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.

474 lines
8.9 KiB

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. ieeemisc.c
  5. Abstract:
  6. IEEE miscellaneous recommended functions
  7. Author:
  8. Revision History:
  9. 29-sept-1999 ATM Shafiqul Khalid [askhalid] copied from rtl library.
  10. --*/
  11. #include <trans.h>
  12. #include <math.h>
  13. #include <float.h>
  14. /***
  15. * _copysign - copy sign
  16. *
  17. *Purpose:
  18. * copysign(x,y) returns x with the sign of y. Hence, abs(x) := copysign
  19. * even if x is NaN [IEEE std 854-1987 Appendix]
  20. *
  21. *
  22. *Entry:
  23. *
  24. *Exit:
  25. *
  26. *Exceptions:
  27. * No exceptions, even if one of the arguments is NaN.
  28. *
  29. * (Currently the i386 compiler returns doubles on the fp stack
  30. * so the fld instruction at the end will cause an invalid operation
  31. * if x is NaN. However this compiler calling convention will change
  32. * soon)
  33. *
  34. *******************************************************************************/
  35. double _copysign (double x, double y)
  36. {
  37. double retval;
  38. *D_LO(retval) = *D_LO(x);
  39. *D_HI(retval) = *D_HI(x) & ~(1<<31) |
  40. *D_HI(y) & (1<<31) ;
  41. return retval;
  42. }
  43. /***
  44. * _chgsign - change sign
  45. *
  46. *Purpose:
  47. * x is copied with its sign reversed, not 0-x; the distinction is germane
  48. * when x is +0, -0, or NaN
  49. *
  50. *Entry:
  51. *
  52. *Exit:
  53. *
  54. *Exceptions:
  55. * No exceptions, even if x is NaN.
  56. *
  57. * (Currently the i386 compiler returns doubles on the fp stack
  58. * so the fld instruction at the end will cause an invalid operation
  59. * if x is NaN. However this compiler calling convention will change
  60. * soon)
  61. *
  62. *******************************************************************************/
  63. double _chgsign (double x)
  64. {
  65. double retval;
  66. *D_LO(retval) = *D_LO(x);
  67. *D_HI(retval) = *D_HI(x) & ~(1 << 31) |
  68. ~*D_HI(x) & (1<<31);
  69. return retval;
  70. }
  71. /***
  72. * _scalb - scale by power of 2
  73. *
  74. *Purpose:
  75. * _scalb(x,n) returns x * 2^n for integral values of n without
  76. * computing 2^n
  77. * Special case:
  78. * If x is infinity or zero, _scaleb returns x
  79. *
  80. *
  81. *Entry:
  82. * double x
  83. * int n
  84. *
  85. *Exit:
  86. *
  87. *Exceptions:
  88. * Invalid operation, Overflow, Underflow
  89. *
  90. *******************************************************************************/
  91. double _scalb(double x, long n)
  92. {
  93. //
  94. // It turns out that our implementation of ldexp matces the IEEE
  95. // description of _scalb. The only problem with calling ldexp
  96. // is that if an exception occurs, the operation code reported
  97. // to the handler will be the one that corresponds to ldexp
  98. // (i.e., we do not define a new operation code for _scalb
  99. //
  100. return ldexp(x,n);
  101. }
  102. /***
  103. * _logb - extract exponent
  104. *
  105. *Purpose:
  106. * _logb(x) returns the unbiased exponent of x, a signed integer in the
  107. * format of x, except that logb(NaN) is a NaN, logb(+INF) is +INF,and
  108. * logb(0) is is -INF and signals the division by zero exception.
  109. * For x positive and finite, 1<= abs(scalb(x, -logb(x))) < 2
  110. *
  111. *
  112. *Entry:
  113. * double x
  114. * int n
  115. *
  116. *Exit:
  117. *
  118. *Exceptions:
  119. * Invalid operation, Division by zero
  120. *
  121. *******************************************************************************/
  122. double _logb(double x)
  123. {
  124. unsigned int savedcw;
  125. int exp;
  126. double retval;
  127. /* save user fp control word */
  128. savedcw = _maskfp();
  129. /* check for infinity or NAN */
  130. if (IS_D_SPECIAL(x)){
  131. switch (_sptype(x)) {
  132. case T_PINF:
  133. case T_NINF:
  134. RETURN(savedcw, x);
  135. case T_QNAN:
  136. return _handle_qnan1(OP_LOGB, x, savedcw);
  137. default: //T_SNAN
  138. return _except1(FP_I, OP_LOGB, x, _s2qnan(x), savedcw);
  139. }
  140. }
  141. if (x == 0) {
  142. return _except1(FP_Z, OP_LOGB, x, -D_INF, savedcw);
  143. }
  144. (void) _decomp(x, &exp);
  145. //
  146. // x == man * 2^exp, where .5 <= man < 1. According to the spec
  147. // of this function, we should compute the exponent so that
  148. // 1<=man<2, i.e., we should decrement the computed exp by one
  149. //
  150. retval = (double) (exp - 1);
  151. RETURN(savedcw, retval);
  152. }
  153. /***
  154. * _nextafter - next representable neighbor
  155. *
  156. *Purpose:
  157. * _nextafter(x,y) returns the next representable neighbor of x in
  158. * the direction toward y. The following special cases arise: if
  159. * x=y, then the result is x without any exception being signaled;
  160. * otherwise, if either x or y is a quiet NaN, then the result is
  161. * one or the other of the input NaNs. Overflow is sibnaled when x
  162. * is finite but nextafter(x,y) is infinite; underflow is signaled
  163. * when nextafter(x,y) lies strictly between -2^Emin, 2^Emin; in
  164. * both cases, inexact is signaled.
  165. *
  166. *
  167. *Entry:
  168. *
  169. *Exit:
  170. *
  171. *Exceptions:
  172. * O, U, I, P
  173. *
  174. *******************************************************************************/
  175. double _nextafter(double x, double y)
  176. {
  177. unsigned int savedcw;
  178. double result;
  179. /* save user fp control word */
  180. savedcw = _maskfp();
  181. /* check for infinity or NAN */
  182. if (IS_D_SPECIAL(x) || IS_D_SPECIAL(y)){
  183. if (IS_D_SNAN(x) || IS_D_SNAN(y)){
  184. return _except2(FP_I,OP_NEXTAFTER,x,y,_d_snan2(x,y),savedcw);
  185. }
  186. if (IS_D_QNAN(x) || IS_D_QNAN(y)){
  187. return _handle_qnan2(OP_NEXTAFTER,x,y,savedcw);
  188. }
  189. //
  190. // infinite arguments are not treated as special cases
  191. //
  192. }
  193. if (y == x) {
  194. //
  195. // no exceptions are raised in this case
  196. //
  197. RETURN(savedcw, x);
  198. }
  199. if (x == 0) {
  200. *D_LO(result) = 1;
  201. if (y > x) {
  202. *D_HI(result) = 0;
  203. }
  204. else {
  205. //
  206. // result should be negative
  207. //
  208. *D_HI(result) = (unsigned long)(1<<31);
  209. }
  210. }
  211. //
  212. // At this point x!=y, and x!=0. x can be treated as a 64bit
  213. // integer in sign/magnitude representation. To get the next
  214. // representable neighbor we add or subtract one from this
  215. // integer. (Note that for boundary cases like x==INF, need to
  216. // add one will never occur --this would mean that y should
  217. // be greater than INF, which is impossible)
  218. //
  219. if (x > 0 && y < x ||
  220. x < 0 && y > x) {
  221. //
  222. // decrease value by one
  223. //
  224. *D_LO(result) = *D_LO(x) - 1;
  225. *D_HI(result) = *D_HI(x);
  226. if (*D_LO(x) == 0) {
  227. //
  228. // a borrow should propagate to the high order dword
  229. //
  230. (*D_HI(result)) --;
  231. }
  232. }
  233. else if (x > 0 && y > x ||
  234. x < 0 && y < x) {
  235. //
  236. // increase value by one
  237. //
  238. *D_LO(result) = *D_LO(x) + 1;
  239. *D_HI(result) = *D_HI(x);
  240. if (*D_LO(result) == 0) {
  241. //
  242. // a carry should propagate to the high order dword
  243. //
  244. (*D_HI(result)) ++;
  245. }
  246. }
  247. //
  248. // check if an exception should be raised
  249. //
  250. if ( IS_D_DENORM(result) ) {
  251. //
  252. // should signal underflow and inexact
  253. // and provide a properly scaled value
  254. //
  255. double mant;
  256. int exp;
  257. mant = _decomp(result, &exp);
  258. result = _set_exp(mant, exp+IEEE_ADJUST);
  259. return _except2(FP_U|FP_P,OP_NEXTAFTER,x,y,result,savedcw);
  260. }
  261. if ( IS_D_INF(result) || IS_D_MINF(result) ) {
  262. //
  263. // should signal overflow and inexact
  264. // and provide a properly scaled value
  265. //
  266. double mant;
  267. int exp;
  268. mant = _decomp(result, &exp);
  269. result = _set_exp(mant, exp-IEEE_ADJUST);
  270. return _except2(FP_O|FP_P,OP_NEXTAFTER,x,y,result,savedcw);
  271. }
  272. RETURN(savedcw, result);
  273. }
  274. /***
  275. * _finite -
  276. *
  277. *Purpose:
  278. * finite(x) returns the value TRUE if -INF < x < +INF and returns
  279. * false otherwise [IEEE std]
  280. *
  281. *Entry:
  282. *
  283. *Exit:
  284. *
  285. *Exceptions:
  286. *
  287. * This routine is treated as a nonarithmetic operation, therefore
  288. * it does not signal any floating point exceptions
  289. *
  290. *******************************************************************************/
  291. int _finite(double x)
  292. {
  293. if (IS_D_SPECIAL(x)) {
  294. //
  295. // x is INF or NaN
  296. //
  297. return 0;
  298. }
  299. return 1;
  300. }
  301. /***
  302. * _isnan -
  303. *
  304. *Purpose:
  305. * isnan(x) returns the value TRUE if x is a NaN, and returns FALSE
  306. * otherwise.
  307. *
  308. *
  309. *Entry:
  310. *
  311. *Exit:
  312. *
  313. *Exceptions:
  314. *
  315. * This routine is treated as a nonarithmetic operation, therefore
  316. * it does not signal any floating point exceptions
  317. *
  318. *******************************************************************************/
  319. int _isnan(double x)
  320. {
  321. if (IS_D_SNAN(x) || IS_D_QNAN(x)) {
  322. return 1;
  323. }
  324. return 0;
  325. }
  326. /***
  327. *double _fpclass(double x) - floating point class
  328. *
  329. *Purpose:
  330. * Compute the floating point class of a number, according
  331. * to the recommendations of the IEEE std. 754
  332. *
  333. *Entry:
  334. *
  335. *Exit:
  336. *
  337. *Exceptions:
  338. * This function is never exceptional, even when the argument is SNAN
  339. *
  340. *******************************************************************************/
  341. int _fpclass(double x)
  342. {
  343. int sign;
  344. if (IS_D_SPECIAL(x)){
  345. switch (_sptype(x)) {
  346. case T_PINF:
  347. return _FPCLASS_PINF;
  348. case T_NINF:
  349. return _FPCLASS_NINF;
  350. case T_QNAN:
  351. return _FPCLASS_QNAN;
  352. default: //T_SNAN
  353. return _FPCLASS_SNAN;
  354. }
  355. }
  356. sign = (*D_EXP(x)) & 0x8000;
  357. if (IS_D_DENORM(x))
  358. return sign? _FPCLASS_ND : _FPCLASS_PD;
  359. if (x == 0.0)
  360. return sign? _FPCLASS_NZ : _FPCLASS_PZ;
  361. return sign? _FPCLASS_NN : _FPCLASS_PN;
  362. }