#include #include #include "scicalc.h" #include "unifunc.h" #include "..\ratpak\debug.h" /**************************************************************************\ * * * * * * * # # ##### * * # # # # # * * # # # # # # # * * # ### ### # # * * # # ### # # # ### # # ### ##### # ### ### ### * * # ## # # # ## # # # # # # ## # # # * * # # # # # # # # # ##### # # ##### # * * # # # # # # # # # # # # # # ## * * # # # # # # # # # ### # # ### ### ## * * * * * * Infinte Precision Production Version * * * \**************************************************************************/ // // RETAIL version of NUMOBJ math that uses Infinite Precision // // History // // 16-Nov-1996 JonPa Wrote it // whenever-97 ToddB Rewrote it using improved ratpak model // /*****************************************************************\ * * Generic Math Package support routines and variables * * History: * 01-Dec-1996 JonPa Wrote them * whenever-97 ToddB Rewrote them * \*****************************************************************/ // // Worker for NumObjRecalcConstants // // Returns the nearest power of two // int QuickLog2( int iNum ) { int iRes = 0; // while first digit is a zero while ( !(iNum & 1) ) { iRes++; iNum >>= 1; } // if our number isn't a perfect square if ( iNum = iNum >> 1 ) { // find the largest digit while ( iNum = iNum >> 1 ) ++iRes; // and then add two iRes += 2; } return iRes; } //////////////////////////////////////////////////////////////////////// // // UpdateMaxIntDigits // // determine the maximum number of digits needed for the current precision, // word size, and base. This number is conservative towards the small side // such that there may be some extra bits left over. The number of extra // bits is returned. For example, base 8 requires 3 bits per digit. A word // size of 32 bits allows for 10 digits with a remainder of two bits. Bases // that require variable numnber of bits (non-power-of-two bases) are approximated // by the next highest power-of-two base (again, to be conservative and gaurentee // there will be no over flow verse the current word size for numbers entered). // Base 10 is a special case and always uses the base 10 precision (nPrecision). void UpdateMaxIntDigits() { extern int gcIntDigits; int iRemainderBits; if ( nRadix == 10 ) { gcIntDigits = nPrecision; iRemainderBits = 0; } else { int log2; log2 = QuickLog2( nRadix ); ASSERT( 0 != log2 ); // same as ASSERT( nRadix != 1 ) gcIntDigits = dwWordBitWidth / log2; iRemainderBits = dwWordBitWidth % log2; } } void BaseOrPrecisionChanged( void ) { extern LONG dwWordBitWidth; extern int gcIntDigits; UpdateMaxIntDigits(); if ( 10 == nRadix ) { // to prevent unwanted rounded digits from showing up in the // gcIntDigits + 1 spot during non-integer mode we don't want // to add the extra 1 that we ortherwise add ChangeConstants( nRadix, gcIntDigits ); } else { ChangeConstants( nRadix, gcIntDigits+1 ); } } /*****************************************************************\ * * Unary functions * * History: * 01-Dec-1996 JonPa Wrote them * whenever-97 ToddB Rewrote them * \*****************************************************************/ void NumObjInvert( PHNUMOBJ phno ) { DECLARE_HNUMOBJ( hno ); NumObjAssign( &hno, HNO_ONE ); divrat( &hno, *phno ); NumObjAssign( phno, hno ); NumObjDestroy( &hno ); } void NumObjAntiLog10( PHNUMOBJ phno ) { DECLARE_HNUMOBJ( hno ); NumObjSetIntValue( &hno, 10 ); powrat( &hno, *phno ); NumObjAssign( phno, hno ); NumObjDestroy( &hno ); } void NumObjNot( PHNUMOBJ phno ) { if ( nRadix == 10 ) { intrat( phno ); addrat( phno, HNO_ONE ); NumObjNegate( phno ); } else { ASSERT( (nHexMode >= 0) && (nHexMode <= 3) ); ASSERT( phno ); ASSERT( *phno ); ASSERT( g_ahnoChopNumbers[ nHexMode ] ); xorrat( phno, g_ahnoChopNumbers[ nHexMode ] ); } } void NumObjSin( PHNUMOBJ phno ) { ASSERT(( nDecMode == ANGLE_DEG ) || ( nDecMode == ANGLE_RAD ) || ( nDecMode == ANGLE_GRAD )); sinanglerat( (PRAT *)phno, nDecMode ); NumObjCvtEpsilonToZero( phno ); } void NumObjCos( PHNUMOBJ phno ) { ASSERT(( nDecMode == ANGLE_DEG ) || ( nDecMode == ANGLE_RAD ) || ( nDecMode == ANGLE_GRAD )); cosanglerat( (PRAT *)phno, nDecMode ); NumObjCvtEpsilonToZero( phno ); } void NumObjTan( PHNUMOBJ phno ) { ASSERT(( nDecMode == ANGLE_DEG ) || ( nDecMode == ANGLE_RAD ) || ( nDecMode == ANGLE_GRAD )); tananglerat( (PRAT *)phno, nDecMode ); NumObjCvtEpsilonToZero( phno ); } /******************************************************************\ * * Number format conversion routines * * History: * 06-Dec-1996 JonPa wrote them \******************************************************************/ void NumObjSetIntValue( PHNUMOBJ phnol, LONG i ) { PRAT pr = NULL; pr = longtorat( i ); NumObjAssign( phnol, (HNUMOBJ)pr ); destroyrat(pr); } void NumObjGetSzValue( LPTSTR *ppszNum, int* pcchNum, HNUMOBJ hnoNum, INT nRadix, NUMOBJ_FMT fmt ) { LPTSTR psz; int cchNum; psz = putrat( &cchNum, &hnoNum, nRadix, fmt ); if (psz != NULL) { if (*ppszNum != NULL) { NumObjFreeMem( *ppszNum ); } *ppszNum = psz; *pcchNum = cchNum; } }