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.

465 lines
9.6 KiB

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