|
|
/**************************************************************************/ /*** SCICALC Scientific Calculator for Windows 3.00.12 ***/ /*** By Kraig Brockschmidt, Microsoft Co-op, Contractor, 1988-1989 ***/ /*** (c)1989 Microsoft Corporation. All Rights Reserved. ***/ /*** ***/ /*** scifunc.c ***/ /*** ***/ /*** Functions contained: ***/ /*** SciCalcFunctions--do sin, cos, tan, com, log, ln, rec, fac, etc.***/ /*** DisplayError--Error display driver. ***/ /*** ***/ /*** Functions called: ***/ /*** SciCalcFunctions call DisplayError. ***/ /*** ***/ /*** Last modification. Fri 05-Jan-1990. ***/ /*** ***/ /*** -by- Amit Chatterjee. [amitc] 05-Jan-1990. ***/ /*** Calc did not have a floating point exception signal handler. This ***/ /*** would cause CALC to be forced to exit on a FP exception as that's ***/ /*** the default. ***/ /*** The signal handler is defined in here, in SCIMAIN.C we hook the ***/ /*** the signal. ***/ /*** ***/ /*** -by- Amit Chatterjee. [amitc] 14-Dec-1989 ***/ /*** The REC function will not depend on the bInv flag. It used to ret ***/ /*** a random number when the bInv flag was set. ***/ /*** ***/ /*** -by- Amit Chatterjee. [amitc] 08-Dec-1989 ***/ /*** Did a minor bug fix. The EnableToggles routine now sets the focus ***/ /*** back to the main window before disabling HEX,DEC etc.. Without this***/ /*** the window with the focus would get disable and cause MOVE to not ***/ /*** work right. ***/ /*** ***/ /**************************************************************************/
#include "scicalc.h"
//#include "float.h"
extern HNUMOBJ ghnoLastNum; extern BOOL bError; extern TCHAR *rgpsz[CSTRINGS]; INT gnPendingError ;
/* Routines for more complex mathematical functions/error checking. */
VOID APIENTRY SciCalcFunctions (PHNUMOBJ phnoNum, DWORD wOp) { try { switch (wOp) { case IDC_CHOP: if (bInv) { // fractional portion
fracrat( phnoNum ); } else { // integer portion
intrat( phnoNum ); } return;
/* Return complement. */ case IDC_COM: NumObjNot( phnoNum ); return;
case IDC_PERCENT: { DECLARE_HNUMOBJ( hno ); DECLARE_HNUMOBJ( hno100 );
try { NumObjAssign( &hno, ghnoLastNum ); NumObjSetIntValue( &hno100, 100 );
divrat( &hno, hno100 );
NumObjDestroy( &hno100 );
mulrat( phnoNum, hno );
NumObjDestroy( &hno ); } catch ( DWORD nErrCode ) { if ( hno != NULL ) NumObjDestroy( &hno ); if ( hno100 != NULL ) NumObjDestroy( &hno100 ); throw nErrCode; } return; }
case IDC_SIN: /* Sine; normal, hyperbolic, arc, and archyperbolic */ if (F_INTMATH()) { MessageBeep(0); return; }
if(bInv) { if (bHyp) { asinhrat( phnoNum ); } else { asinanglerat( phnoNum, nDecMode ); } } else { if (bHyp) { // hyperbolic sine
sinhrat( phnoNum ); } else { NumObjSin( phnoNum ); } } return;
case IDC_COS: /* Cosine, follows convention of sine function. */ if (F_INTMATH()) { MessageBeep(0); return; }
if(bInv) { if (bHyp) { acoshrat( phnoNum ); } else { acosanglerat( phnoNum, nDecMode ); } } else { if (bHyp) coshrat( phnoNum ); else { // cos()
NumObjCos( phnoNum ); } } return;
case IDC_TAN: /* Same as sine and cosine. */ if (F_INTMATH()) { MessageBeep(0); return; }
if(bInv) { if (bHyp) { atanhrat( phnoNum ); } else { atananglerat( phnoNum, nDecMode ); } } else { if (bHyp) tanhrat( phnoNum ); else { // Get the answer
NumObjTan( phnoNum ); } } return;
case IDC_REC: /* Reciprocal. */ NumObjInvert( phnoNum ); return;
case IDC_SQR: /* Square and square root. */ case IDC_SQRT: if(bInv || nCalc) { rootrat( phnoNum, HNO_TWO ); } else { ratpowlong( phnoNum, 2 ); } return;
case IDC_CUB: /* Cubing and cube root functions. */ if(bInv) { DECLARE_HNUMOBJ( hno );
// REVIEW: if constants like 3 are going to be used repeatedly, it will be
// much quicker to define them once and then keep around the definition.
try { NumObjAssign( &hno, HNO_ONE ); addrat( &hno, HNO_TWO );
rootrat( phnoNum, hno );
NumObjDestroy( &hno ); } catch ( DWORD nErrCode ) { if ( hno != NULL ) NumObjDestroy( &hno );
throw nErrCode; } } else { /* Cube it, you dig? */ ratpowlong( phnoNum, 3 ); } return;
case IDC_LOG: /* Functions for common and natural log. */ case IDC_LN: if(bInv) { /* Check maximum for exponentiation for 10� and e�. */ if (wOp==IDC_LOG) /* Do exponentiation. */ NumObjAntiLog10( phnoNum ); // 10�.
else exprat( phnoNum ); // e�.
} else { // ratpak checks for valid range and throws error code if needed
if (wOp==IDC_LOG) log10rat( phnoNum ); else lograt( phnoNum );
// REVIEW: Is conversion of epsilon still needed?
NumObjCvtEpsilonToZero( phnoNum ); } return;
case IDC_FAC: /* Calculate factorial. Inverse is ineffective. */ factrat( phnoNum ); return;
case IDC_DMS: { if (F_INTMATH()) { MessageBeep(0); } else { DECLARE_HNUMOBJ(hnoMin); DECLARE_HNUMOBJ(hnoSec); DECLARE_HNUMOBJ(hnoShft);
try { NumObjSetIntValue( &hnoShft, bInv ? 100 : 60 );
NumObjAssign( &hnoMin, *phnoNum ); intrat( phnoNum );
subrat( &hnoMin, *phnoNum ); mulrat( &hnoMin, hnoShft ); NumObjAssign( &hnoSec, hnoMin ); intrat( &hnoMin );
subrat( &hnoSec, hnoMin ); mulrat( &hnoSec, hnoShft );
//
// *phnoNum == degrees, hnoMin == minutes, hnoSec == seconds
//
NumObjSetIntValue( &hnoShft, bInv ? 60 : 100 ); divrat( &hnoSec, hnoShft ); addrat( &hnoMin, hnoSec );
divrat( &hnoMin, hnoShft ); addrat( phnoNum, hnoMin );
NumObjDestroy( &hnoShft ); NumObjDestroy( &hnoMin ); NumObjDestroy( &hnoSec ); } catch ( DWORD nErrCode ) { if ( hnoShft != NULL ) NumObjDestroy( &hnoShft ); if ( hnoMin != NULL ) NumObjDestroy( &hnoMin ); if ( hnoSec != NULL ) NumObjDestroy( &hnoSec ); throw nErrCode; } } return; } } // end switch( nOp )
} catch( DWORD nErrCode ) { DisplayError( nErrCode ); }
return; }
/* Routine to display error messages and set bError flag. Errors are */ /* called with DisplayError (n), where n is a INT between 0 and 5. */
VOID APIENTRY DisplayError (INT nError) { SetDisplayText(g_hwndDlg, rgpsz[IDS_ERRORS+nError]); bError=TRUE; /* Set error flag. Only cleared with CLEAR or CENTR. */ /* save the pending error */ gnPendingError = nError ; return; }
|