Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

478 lines
16 KiB

/**************************************************************************/
/*** 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 double fCleanUpMod(double a, double c);
extern double fpNum, fpLastNum, fpTrigType[3];
extern BOOL bInv, bHyp, bError;
extern HWND hgWnd;
extern INT nCalc, nTrig;
extern TCHAR *rgpsz[CSTRINGS];
INT nPendingError ;
/* Routines for more complex mathematical functions/error checking. */
VOID APIENTRY SciCalcFunctions (DWORD wOp)
{
LONG lIndex, lTemp;
double fpSave, fpSec, fpMin, fpSign=1.0, fpTemp, fpX;
if (fpNum < 0.0)
fpSign=-1.0;
switch (wOp)
{
case CHOP:
/* Return either integer or fractional portion of fpNum */
fpTemp=CalcModF(fRoundForDisplay(fpNum), &fpMin);
if (bInv)
fpNum= fCleanUpMod(fabs(fpNum), fpTemp);
else
fpNum=fpMin;
return;
/* Return complement. */
case COM:
if (fabs(fpNum) > TOPLONG)
DisplayError (SCERR_DOMAIN);
else
#if defined(_MIPS_) || defined(_PPC_)
{
//
// Temporary untill the mips compiler correctly supports
// double to unsigned int.
//
DWORD z;
if (fpNum < 0) {
z = FDtoUL(-fpNum);
z = NegateUL(z);
} else {
z = FDtoUL(fpNum);
}
fpNum=(double) ~z;
}
#else
fpNum=(double) ~(LONG) fpNum;
#endif
return;
case PERCENT:
fpNum *=(fpLastNum/100);
return;
case SIN: /* Sine; normal, hyperbolic, arc, and archyperbolic */
if(bInv)
{
if (bHyp)
/* Following is formula for archyperbolic sine. All */
/* real numbers are legal. */
fpNum=log(fpNum+sqrt(1.0+fpNum*fpNum));
else
// asin() return in radians. range -pi/2 to pi/2
fpNum = asin(fpNum) * fpTrigType[nTrig];
}
else
{
if (bHyp)
{
// hyperbolic sin()
fpNum = sinh(fpNum);
}
else
{
// sin()
// special case a few values for the press
double fpPress = fabs(fpNum);
if (nTrig == 0 &&
(fpPress == 180.0 ||
fpPress == 360.0 ||
fpPress == 540.0 ||
fpPress == 720.0))
{
fpNum = 0.0;
return;
}
if (nTrig == 1 &&
(fpPress == PI_VAL ||
fpPress == 2.0 * PI_VAL ||
fpPress == 3.0 * PI_VAL ||
fpPress == 4.0 * PI_VAL))
{
fpNum = 0.0;
return;
}
fpNum = sin(fpNum / fpTrigType[nTrig]);
// Win31 hack because cos(PI/2) doesn't equal 0.0
if (fabs(fpNum) < 1.0e-15)
fpNum = 0.0;
}
}
return;
case COS: /* Cosine, follows convention of sine function. */
if(bInv)
{
if (bHyp)
{
if (fpNum <1.0) /* Valid range for archyperbolic. */
{
DisplayError (SCERR_DOMAIN);
return;
}
/* Following is archyperbolic cosine formula. All */
/* positive values >=1.0 are valid. */
fpNum=log(fpNum+sqrt(-1.0+fpNum*fpNum));
}
else
// acos() return in radians. range -pi/2 to pi/2
fpNum = acos(fpNum) * fpTrigType[nTrig];
}
else
{
if (bHyp)
fpNum = cosh(fpNum);
else
{
// cos()
// special case a few values for the press
double fpPress = fabs(fpNum);
if (nTrig == 0 &&
(fpPress == 90.0 ||
fpPress == 270.0 ||
fpPress == 450.0 ||
fpPress == 630.0))
{
fpNum = 0.0;
return;
}
if (nTrig == 1 &&
(fpPress == 0.5 * PI_VAL ||
fpPress == 1.5 * PI_VAL ||
fpPress == 2.5 * PI_VAL ||
fpPress == 3.5 * PI_VAL))
{
fpNum = 0.0;
return;
}
fpNum = cos(fpNum / fpTrigType[nTrig]);
// Win31 hack because cos(PI/2) doesn't equal 0.0
if (fabs(fpNum) < 1.0e-15)
fpNum = 0.0;
}
}
return;
case TAN: /* Same as sine and cosine. */
if(bInv)
{
if (bHyp)
{
if (fabs(fpNum) >= 1.0)
{
DisplayError (SCERR_DOMAIN);
return;
}
/* Formula for archyperbolic tangent. Valid range is */
/* -1 to +1. */
fpNum=.5*log((1.0+fpNum)/(1.0-fpNum));
}
else
fpNum=atan(fpNum)*fpTrigType[nTrig];
}
else
if (bHyp)
fpNum=tanh(fpNum);
else
{
// tan()
// special case a few values for the press
double fpPress = fabs(fpNum);
if (nTrig == 0 &&
(fpPress == 180.0 ||
fpPress == 360.0 ||
fpPress == 540.0 ||
fpPress == 720.0))
{
fpNum = 0.0;
return;
}
if (nTrig == 1 &&
(fpPress == PI_VAL ||
fpPress == 2.0 * PI_VAL ||
fpPress == 3.0 * PI_VAL ||
fpPress == 4.0 * PI_VAL))
{
fpNum = 0.0;
return;
}
// The conversion from degrees to radians is so
// poor tan(3PI/2) == error but tan(270) != error.
// Special case a few more values...
if (nTrig == 0 &&
(fpPress == 90.0 ||
fpPress == 270.0 ||
fpPress == 450.0 ||
fpPress == 630.0))
{
fpNum = tan(PI_VAL / 2.0);
}
else
{
fpNum = tan(fpNum / fpTrigType[nTrig]);
}
if (fabs(fpNum) > 1e+15)
DisplayError (SCERR_UNDEFINED);
}
return;
case REC: /* Reciprocal. */
if (fpNum==0.0) /* x/0 is illegal. */
DisplayError(SCERR_DIVIDEZERO);
else
fpNum=1/fpNum;
return;
case SQR: /* Square and square root. */
if(bInv || nCalc)
{
if (fpNum < 0.0)
DisplayError(SCERR_UNDEFINED);
else
fpNum=sqrt(fpNum);
}
else
{
/* Check if number is too big. */
if (fabs(fpNum) > 1.0e+154)
DisplayError (SCERR_OVERFLOW);
else
fpNum *=fpNum; /* Square that puppy. */
}
return;
case CUB: /* Cubing and cube root functions. */
if(bInv)
fpNum=fpSign * pow(fabs(fpNum), 1.0/3.0);
else
{
/* Check upper limit. */
if ( fabs(fpNum) > (1.0e+102))
DisplayError (SCERR_OVERFLOW);
else
fpNum = fpNum*fpNum*fpNum; /* Cube it, you dig? */
}
return;
case LOG: /* Functions for common and natural log. */
case LN:
if(bInv)
{
/* Check maximum for exponentiation for 10ü and eü. */
if (wOp==LOG) /* Do exponentiation. */
fpNum=pow(10.0, fpNum); /* 10ü. */
else
fpNum=pow(MATHE, fpNum); /* eü. */
}
else
{
/* Check for illegal logarithm domain. */
if (fpNum<=0.0)
DisplayError(SCERR_UNDEFINED);
else
{
if (wOp==LOG)
fpNum=log10(fpNum);
else
fpNum=log(fpNum);
}
}
return;
case FAC: /* Calculate factorial. Inverse is ineffective. */
/* Check for negative. */
if (fmod(fpNum, 1.0)!=0.0 || fpNum < 0.0)
{
DisplayError (SCERR_DOMAIN);
return;
}
/* Check for maximum limit. */
if (fpNum > 170.0)
DisplayError (SCERR_OVERFLOW);
else
{
lTemp=(LONG) fpNum; /* Convert to a interger number. */
fpNum=1.0;
for (lIndex=2; lIndex<=lTemp; lIndex++)
fpNum *= (double) lIndex;
}
return;
case DMS:
/* Degrees <-> degrees/minutes/seconds conversions. */
fpTemp = CalcModF(fpSign*fpNum, &fpSave);
/* Multiplies fpTemp *100 with bInv TRUE, otherwise *60 */
fpX=60.0+((bInv) ? (40.0) : (0.0));
fpSec = CalcModF((fpTemp*fpX), &fpMin);
if (fpSec > 1.0-(1.0e-11))
{
fpSec=0.0;
fpMin+=1.0;
}
if (bInv)
/* Convert to degrees format. */
fpNum =fpSign*(fpSave + (fpMin/60.0) + (fpSec/36));
else
/* Convert to degree-minutes-seconds format. */
fpNum=fpSign*(fpSave+(fpMin/100.0)+(fpSec*.006));
break;
}
return;
}
/* Routine to display error messages and set bError flag. Errors are */
/* called with DisplayError (n), where n is a INT between 0 and 4. */
VOID APIENTRY DisplayError (INT nError)
{
SetDlgItemText(hgWnd, DISPLAY+nCalc, rgpsz[IDS_ERRORS+nError]);
bError=TRUE; /* Set error flag. Only cleared with CLEAR or CENTR. */
/* save the pending error */
nPendingError = nError ;
/* Don't wanna no o' dem RIP0x0007 thingamabobs. */
if (nCalc==0)
EnableToggles (FALSE);
return;
}
/* Routine to handle general math errors coming from the math library. */
/* Frees app from checking domains on sines, logs, etc. */
INT _CRTAPI1 matherr(x)
struct _exception *x;
{
INT nErr=x->type;
if (nErr==DOMAIN || nErr==OVERFLOW || nErr==UNDERFLOW)
DisplayError (nErr);
else
DisplayError (SCERR_UNDEFINED); /* General error. */
return TRUE;
}
/* Routine to handle floating point exceptions coming from the math library */
VOID FAR cdecl SignalHandler ( iType, iCode)
INT iType, iCode ;
{
if (iCode == FPE_ZERODIVIDE)
{
DisplayError (SCERR_DIVIDEZERO) ;
return ;
}
if (iCode == FPE_OVERFLOW)
{
DisplayError (SCERR_OVERFLOW) ;
return ;
}
if (iCode == FPE_UNDERFLOW)
{
DisplayError (SCERR_UNDERFLOW) ;
return ;
}
DisplayError (SCERR_UNDEFINED) ;
}
VOID APIENTRY EnableToggles(BOOL bEnable)
{
INT nx;
/* first set the focus back to the main window to ensure that we
do not disbale a window with the focus */
SetFocus (hgWnd) ;
for (nx=BIN; nx<=GRAD; nx++)
EnableWindow(GetDlgItem(hgWnd, nx), bEnable);
return;
}