//----------------------------------------------------------------------------- // Package Title ratpak // File transh.c // Author Timothy David Corrie Jr. (timc@microsoft.com) // Copyright (C) 1995-96 Microsoft // Date 01-16-95 // // // Description // // Contains hyperbolic sin, cos, and tan for rationals. // // //----------------------------------------------------------------------------- #include #include #include #if defined( DOS ) #include #else #include #endif #include //----------------------------------------------------------------------------- // // 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 ) { CREATETAYLOR(); DUPRAT(pret,*px); DUPRAT(thisterm,pret); DUPNUM(n2,num_one); do { NEXTTERM(xx,INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2)); } while ( !SMALL_ENOUGH_RAT( thisterm ) ); DESTROYTAYLOR(); } void sinhrat( PRAT *px ) { PRAT pret=NULL; PRAT tmpx=NULL; if ( rat_ge( *px, rat_one ) ) { DUPRAT(tmpx,*px); exprat(px); tmpx->pp->sign *= -1; exprat(&tmpx); subrat( px, tmpx ); divrat( px, rat_two ); destroyrat( tmpx ); } else { _sinhrat( px ); } } //----------------------------------------------------------------------------- // // 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 ) { CREATETAYLOR(); pret->pp=longtonum( 1L, nRadix ); pret->pq=longtonum( 1L, nRadix ); DUPRAT(thisterm,pret) n2=longtonum(0L, nRadix); do { NEXTTERM(xx,INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2)); } while ( !SMALL_ENOUGH_RAT( thisterm ) ); DESTROYTAYLOR(); } void coshrat( PRAT *px ) { PRAT tmpx=NULL; (*px)->pp->sign = 1; (*px)->pq->sign = 1; if ( rat_ge( *px, rat_one ) ) { DUPRAT(tmpx,*px); exprat(px); tmpx->pp->sign *= -1; exprat(&tmpx); addrat( px, tmpx ); divrat( px, rat_two ); destroyrat( tmpx ); } else { _coshrat( px ); } // Since *px might be epsilon below 1 due to TRIMIT // we need this trick here. if ( rat_lt(*px,rat_one) ) { 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 ) { PRAT ptmp=NULL; DUPRAT(ptmp,*px); sinhrat(px); coshrat(&ptmp); mulnumx(&((*px)->pp),ptmp->pq); mulnumx(&((*px)->pq),ptmp->pp); destroyrat(ptmp); }