windows-nt/Source/XPSP1/NT/shell/osshell/accesory/calc/scifunc.c
2020-09-26 16:20:57 +08:00

345 lines
12 KiB
C
Raw Permalink Blame History

/**************************************************************************/
/*** 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<31> and e<>. */
if (wOp==IDC_LOG) /* Do exponentiation. */
NumObjAntiLog10( phnoNum ); // 10<31>.
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;
}