Source code of Windows XP (NT5)
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.

344 lines
12 KiB

  1. /**************************************************************************/
  2. /*** SCICALC Scientific Calculator for Windows 3.00.12 ***/
  3. /*** By Kraig Brockschmidt, Microsoft Co-op, Contractor, 1988-1989 ***/
  4. /*** (c)1989 Microsoft Corporation. All Rights Reserved. ***/
  5. /*** ***/
  6. /*** scifunc.c ***/
  7. /*** ***/
  8. /*** Functions contained: ***/
  9. /*** SciCalcFunctions--do sin, cos, tan, com, log, ln, rec, fac, etc.***/
  10. /*** DisplayError--Error display driver. ***/
  11. /*** ***/
  12. /*** Functions called: ***/
  13. /*** SciCalcFunctions call DisplayError. ***/
  14. /*** ***/
  15. /*** Last modification. Fri 05-Jan-1990. ***/
  16. /*** ***/
  17. /*** -by- Amit Chatterjee. [amitc] 05-Jan-1990. ***/
  18. /*** Calc did not have a floating point exception signal handler. This ***/
  19. /*** would cause CALC to be forced to exit on a FP exception as that's ***/
  20. /*** the default. ***/
  21. /*** The signal handler is defined in here, in SCIMAIN.C we hook the ***/
  22. /*** the signal. ***/
  23. /*** ***/
  24. /*** -by- Amit Chatterjee. [amitc] 14-Dec-1989 ***/
  25. /*** The REC function will not depend on the bInv flag. It used to ret ***/
  26. /*** a random number when the bInv flag was set. ***/
  27. /*** ***/
  28. /*** -by- Amit Chatterjee. [amitc] 08-Dec-1989 ***/
  29. /*** Did a minor bug fix. The EnableToggles routine now sets the focus ***/
  30. /*** back to the main window before disabling HEX,DEC etc.. Without this***/
  31. /*** the window with the focus would get disable and cause MOVE to not ***/
  32. /*** work right. ***/
  33. /*** ***/
  34. /**************************************************************************/
  35. #include "scicalc.h"
  36. //#include "float.h"
  37. extern HNUMOBJ ghnoLastNum;
  38. extern BOOL bError;
  39. extern TCHAR *rgpsz[CSTRINGS];
  40. INT gnPendingError ;
  41. /* Routines for more complex mathematical functions/error checking. */
  42. VOID APIENTRY SciCalcFunctions (PHNUMOBJ phnoNum, DWORD wOp)
  43. {
  44. try
  45. {
  46. switch (wOp)
  47. {
  48. case IDC_CHOP:
  49. if (bInv)
  50. {
  51. // fractional portion
  52. fracrat( phnoNum );
  53. }
  54. else
  55. {
  56. // integer portion
  57. intrat( phnoNum );
  58. }
  59. return;
  60. /* Return complement. */
  61. case IDC_COM:
  62. NumObjNot( phnoNum );
  63. return;
  64. case IDC_PERCENT:
  65. {
  66. DECLARE_HNUMOBJ( hno );
  67. DECLARE_HNUMOBJ( hno100 );
  68. try
  69. {
  70. NumObjAssign( &hno, ghnoLastNum );
  71. NumObjSetIntValue( &hno100, 100 );
  72. divrat( &hno, hno100 );
  73. NumObjDestroy( &hno100 );
  74. mulrat( phnoNum, hno );
  75. NumObjDestroy( &hno );
  76. }
  77. catch ( DWORD nErrCode )
  78. {
  79. if ( hno != NULL )
  80. NumObjDestroy( &hno );
  81. if ( hno100 != NULL )
  82. NumObjDestroy( &hno100 );
  83. throw nErrCode;
  84. }
  85. return;
  86. }
  87. case IDC_SIN: /* Sine; normal, hyperbolic, arc, and archyperbolic */
  88. if (F_INTMATH())
  89. {
  90. MessageBeep(0);
  91. return;
  92. }
  93. if(bInv)
  94. {
  95. if (bHyp)
  96. {
  97. asinhrat( phnoNum );
  98. }
  99. else
  100. {
  101. asinanglerat( phnoNum, nDecMode );
  102. }
  103. }
  104. else
  105. {
  106. if (bHyp)
  107. {
  108. // hyperbolic sine
  109. sinhrat( phnoNum );
  110. }
  111. else
  112. {
  113. NumObjSin( phnoNum );
  114. }
  115. }
  116. return;
  117. case IDC_COS: /* Cosine, follows convention of sine function. */
  118. if (F_INTMATH())
  119. {
  120. MessageBeep(0);
  121. return;
  122. }
  123. if(bInv)
  124. {
  125. if (bHyp)
  126. {
  127. acoshrat( phnoNum );
  128. }
  129. else
  130. {
  131. acosanglerat( phnoNum, nDecMode );
  132. }
  133. }
  134. else
  135. {
  136. if (bHyp)
  137. coshrat( phnoNum );
  138. else
  139. {
  140. // cos()
  141. NumObjCos( phnoNum );
  142. }
  143. }
  144. return;
  145. case IDC_TAN: /* Same as sine and cosine. */
  146. if (F_INTMATH())
  147. {
  148. MessageBeep(0);
  149. return;
  150. }
  151. if(bInv)
  152. {
  153. if (bHyp)
  154. {
  155. atanhrat( phnoNum );
  156. }
  157. else
  158. {
  159. atananglerat( phnoNum, nDecMode );
  160. }
  161. }
  162. else
  163. {
  164. if (bHyp)
  165. tanhrat( phnoNum );
  166. else
  167. {
  168. // Get the answer
  169. NumObjTan( phnoNum );
  170. }
  171. }
  172. return;
  173. case IDC_REC: /* Reciprocal. */
  174. NumObjInvert( phnoNum );
  175. return;
  176. case IDC_SQR: /* Square and square root. */
  177. case IDC_SQRT:
  178. if(bInv || nCalc)
  179. {
  180. rootrat( phnoNum, HNO_TWO );
  181. }
  182. else
  183. {
  184. ratpowlong( phnoNum, 2 );
  185. }
  186. return;
  187. case IDC_CUB: /* Cubing and cube root functions. */
  188. if(bInv) {
  189. DECLARE_HNUMOBJ( hno );
  190. // REVIEW: if constants like 3 are going to be used repeatedly, it will be
  191. // much quicker to define them once and then keep around the definition.
  192. try
  193. {
  194. NumObjAssign( &hno, HNO_ONE );
  195. addrat( &hno, HNO_TWO );
  196. rootrat( phnoNum, hno );
  197. NumObjDestroy( &hno );
  198. }
  199. catch ( DWORD nErrCode )
  200. {
  201. if ( hno != NULL )
  202. NumObjDestroy( &hno );
  203. throw nErrCode;
  204. }
  205. }
  206. else {
  207. /* Cube it, you dig? */
  208. ratpowlong( phnoNum, 3 );
  209. }
  210. return;
  211. case IDC_LOG: /* Functions for common and natural log. */
  212. case IDC_LN:
  213. if(bInv)
  214. {
  215. /* Check maximum for exponentiation for 10� and e�. */
  216. if (wOp==IDC_LOG) /* Do exponentiation. */
  217. NumObjAntiLog10( phnoNum ); // 10�.
  218. else
  219. exprat( phnoNum ); // e�.
  220. }
  221. else
  222. {
  223. // ratpak checks for valid range and throws error code if needed
  224. if (wOp==IDC_LOG)
  225. log10rat( phnoNum );
  226. else
  227. lograt( phnoNum );
  228. // REVIEW: Is conversion of epsilon still needed?
  229. NumObjCvtEpsilonToZero( phnoNum );
  230. }
  231. return;
  232. case IDC_FAC: /* Calculate factorial. Inverse is ineffective. */
  233. factrat( phnoNum );
  234. return;
  235. case IDC_DMS:
  236. {
  237. if (F_INTMATH())
  238. {
  239. MessageBeep(0);
  240. }
  241. else
  242. {
  243. DECLARE_HNUMOBJ(hnoMin);
  244. DECLARE_HNUMOBJ(hnoSec);
  245. DECLARE_HNUMOBJ(hnoShft);
  246. try
  247. {
  248. NumObjSetIntValue( &hnoShft, bInv ? 100 : 60 );
  249. NumObjAssign( &hnoMin, *phnoNum );
  250. intrat( phnoNum );
  251. subrat( &hnoMin, *phnoNum );
  252. mulrat( &hnoMin, hnoShft );
  253. NumObjAssign( &hnoSec, hnoMin );
  254. intrat( &hnoMin );
  255. subrat( &hnoSec, hnoMin );
  256. mulrat( &hnoSec, hnoShft );
  257. //
  258. // *phnoNum == degrees, hnoMin == minutes, hnoSec == seconds
  259. //
  260. NumObjSetIntValue( &hnoShft, bInv ? 60 : 100 );
  261. divrat( &hnoSec, hnoShft );
  262. addrat( &hnoMin, hnoSec );
  263. divrat( &hnoMin, hnoShft );
  264. addrat( phnoNum, hnoMin );
  265. NumObjDestroy( &hnoShft );
  266. NumObjDestroy( &hnoMin );
  267. NumObjDestroy( &hnoSec );
  268. }
  269. catch ( DWORD nErrCode )
  270. {
  271. if ( hnoShft != NULL )
  272. NumObjDestroy( &hnoShft );
  273. if ( hnoMin != NULL )
  274. NumObjDestroy( &hnoMin );
  275. if ( hnoSec != NULL )
  276. NumObjDestroy( &hnoSec );
  277. throw nErrCode;
  278. }
  279. }
  280. return;
  281. }
  282. } // end switch( nOp )
  283. }
  284. catch( DWORD nErrCode )
  285. {
  286. DisplayError( nErrCode );
  287. }
  288. return;
  289. }
  290. /* Routine to display error messages and set bError flag. Errors are */
  291. /* called with DisplayError (n), where n is a INT between 0 and 5. */
  292. VOID APIENTRY DisplayError (INT nError)
  293. {
  294. SetDisplayText(g_hwndDlg, rgpsz[IDS_ERRORS+nError]);
  295. bError=TRUE; /* Set error flag. Only cleared with CLEAR or CENTR. */
  296. /* save the pending error */
  297. gnPendingError = nError ;
  298. return;
  299. }