// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. //----------------------------------------------------------------------------- // Package Title ratpak // File transh.c // Copyright (C) 1995-96 Microsoft // Date 01-16-95 // // // Description // // Contains hyperbolic sin, cos, and tan for rationals. // // //----------------------------------------------------------------------------- #include "pch.h" #include "ratpak.h" bool IsValidForHypFunc(PRAT px, int32_t precision) { PRAT ptmp = nullptr; bool bRet = true; DUPRAT(ptmp,rat_min_exp); divrat(&ptmp, rat_ten, precision); if ( rat_lt( px, ptmp, precision) ) { bRet = false; } destroyrat( ptmp ); return bRet; } //----------------------------------------------------------------------------- // // FUNCTION: sinhrat, _sinhrat // // ARGUMENTS: x PRAT representation of number to take the sine hyperbolic // of // RETURN: sinh of x in PRAT form. // // EXPLANATION: This uses Taylor series // // n // ___ 2j+1 // \ ] X // \ --------- // / (2j+1)! // /__] // j=0 // or, // n // ___ 2 // \ ] X // \ thisterm ; where thisterm = thisterm * --------- // / j j+1 j (2j)*(2j+1) // /__] // j=0 // // thisterm = X ; and stop when thisterm < precision used. // 0 n // // if x is bigger than 1.0 (e^x-e^-x)/2 is used. // //----------------------------------------------------------------------------- void _sinhrat( PRAT *px, int32_t precision) { if ( !IsValidForHypFunc(*px, precision)) { // Don't attempt exp of anything large or small throw( CALC_E_DOMAIN ); } CREATETAYLOR(); DUPRAT(pret,*px); DUPRAT(thisterm,pret); DUPNUM(n2,num_one); do { NEXTTERM(xx,INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision); } while ( !SMALL_ENOUGH_RAT( thisterm, precision) ); DESTROYTAYLOR(); } void sinhrat( PRAT *px, uint32_t radix, int32_t precision) { PRAT tmpx= nullptr; if ( rat_ge( *px, rat_one, precision) ) { DUPRAT(tmpx,*px); exprat(px, radix, precision); tmpx->pp->sign *= -1; exprat(&tmpx, radix, precision); subrat( px, tmpx, precision); divrat( px, rat_two, precision); destroyrat( tmpx ); } else { _sinhrat( px, precision); } } //----------------------------------------------------------------------------- // // FUNCTION: coshrat // // ARGUMENTS: x PRAT representation of number to take the cosine // hyperbolic of // // RETURN: cosh of x in PRAT form. // // EXPLANATION: This uses Taylor series // // n // ___ 2j // \ ] X // \ --------- // / (2j)! // /__] // j=0 // or, // n // ___ 2 // \ ] X // \ thisterm ; where thisterm = thisterm * --------- // / j j+1 j (2j)*(2j+1) // /__] // j=0 // // thisterm = 1 ; and stop when thisterm < precision used. // 0 n // // if x is bigger than 1.0 (e^x+e^-x)/2 is used. // //----------------------------------------------------------------------------- void _coshrat( PRAT *px, uint32_t radix, int32_t precision) { if ( !IsValidForHypFunc(*px, precision)) { // Don't attempt exp of anything large or small throw( CALC_E_DOMAIN ); } CREATETAYLOR(); pret->pp=longtonum( 1L, radix); pret->pq=longtonum( 1L, radix); DUPRAT(thisterm,pret) n2=longtonum(0L, radix); do { NEXTTERM(xx,INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision); } while ( !SMALL_ENOUGH_RAT( thisterm, precision) ); DESTROYTAYLOR(); } void coshrat( PRAT *px, uint32_t radix, int32_t precision) { PRAT tmpx= nullptr; (*px)->pp->sign = 1; (*px)->pq->sign = 1; if ( rat_ge( *px, rat_one, precision) ) { DUPRAT(tmpx,*px); exprat(px, radix, precision); tmpx->pp->sign *= -1; exprat(&tmpx, radix, precision); addrat( px, tmpx, precision); divrat( px, rat_two, precision); destroyrat( tmpx ); } else { _coshrat( px, radix, precision); } // Since *px might be epsilon below 1 due to TRIMIT // we need this trick here. if ( rat_lt(*px, rat_one, precision) ) { DUPRAT(*px,rat_one); } } //----------------------------------------------------------------------------- // // FUNCTION: tanhrat // // ARGUMENTS: x PRAT representation of number to take the tangent // hyperbolic of // // RETURN: tanh of x in PRAT form. // // EXPLANATION: This uses sinhrat and coshrat // //----------------------------------------------------------------------------- void tanhrat( PRAT *px, uint32_t radix, int32_t precision) { PRAT ptmp= nullptr; DUPRAT(ptmp,*px); sinhrat(px, radix, precision); coshrat(&ptmp, radix, precision); mulnumx(&((*px)->pp),ptmp->pq); mulnumx(&((*px)->pq),ptmp->pp); destroyrat(ptmp); }