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.

187 lines
4.5 KiB

  1. /***
  2. *exp.c - exponential
  3. *
  4. * Copyright (c) 1991-2001, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. * Compute exp(x)
  8. *
  9. *Revision History:
  10. * 8-15-91 GDP written
  11. * 12-21-91 GDP support IEEE exceptions
  12. * 02-03-92 GDP added _exphlp for use by exp, sinh, and cosh
  13. * 02-06-95 JWM Mac merge
  14. * 10-07-97 RDL Added IA64.
  15. *
  16. *******************************************************************************/
  17. #include <math.h>
  18. #include <trans.h>
  19. #if defined(_M_IA64)
  20. #pragma function(exp)
  21. #endif
  22. double _exphlp(double, int *);
  23. /*
  24. * Thresholds for over/underflow that results in an adjusted value
  25. * too big/small to be represented as a double.
  26. * OVFX: ln(XMAX * 2^IEEE_ADJ)
  27. * UFLX: ln(XIN * 2^(-IEEE_ADJ)
  28. */
  29. static _dbl const ovfx = {SET_DBL(0x40862e42, 0xfefa39f8)}; /* 709.782712893385 */
  30. static _dbl const uflx = {SET_DBL(0xc086232b, 0xdd7abcda)}; /* -708.396418532265 */
  31. #define OVFX ovfx.dbl
  32. #define UFLX uflx.dbl
  33. static double const EPS = 5.16987882845642297e-26; /* 2^(-53) / 2 */
  34. static double const LN2INV = 1.442695040889634074; /* 1/ln(2) */
  35. static double const C1 = 0.693359375000000000;
  36. static double const C2 = -2.1219444005469058277e-4;
  37. /* constants for the rational approximation */
  38. static double const p0 = 0.249999999999999993e+0;
  39. static double const p1 = 0.694360001511792852e-2;
  40. static double const p2 = 0.165203300268279130e-4;
  41. static double const q0 = 0.500000000000000000e+0;
  42. static double const q1 = 0.555538666969001188e-1;
  43. static double const q2 = 0.495862884905441294e-3;
  44. #define P(z) ( (p2 * (z) + p1) * (z) + p0 )
  45. #define Q(z) ( (q2 * (z) + q1) * (z) + q0 )
  46. /***
  47. *double exp(double x) - exponential
  48. *
  49. *Purpose:
  50. * Compute the exponential of a number.
  51. * The algorithm (reduction / rational approximation) is
  52. * taken from Cody & Waite.
  53. *
  54. *Entry:
  55. *
  56. *Exit:
  57. *
  58. *Exceptions: O, U, P, I
  59. *
  60. *******************************************************************************/
  61. double exp (double x)
  62. {
  63. uintptr_t savedcw;
  64. int newexp;
  65. double result;
  66. /* save user fp control word */
  67. savedcw = _maskfp();
  68. if (IS_D_SPECIAL(x)){
  69. switch (_sptype(x)) {
  70. case T_PINF:
  71. RETURN(savedcw,x);
  72. case T_NINF:
  73. RETURN(savedcw,0.0);
  74. case T_QNAN:
  75. return _handle_qnan1(OP_EXP, x, savedcw);
  76. default: //T_SNAN
  77. return _except1(FP_I, OP_EXP, x, _s2qnan(x), savedcw);
  78. }
  79. }
  80. if (x == 0.0) {
  81. RETURN(savedcw, 1.0);
  82. }
  83. if (x > OVFX) {
  84. // even after scaling the exponent of the result,
  85. // it is still too large.
  86. // Deliver infinity to the trap handler
  87. return _except1(FP_O | FP_P, OP_EXP, x, D_INF, savedcw);
  88. }
  89. if (x < UFLX) {
  90. // even after scaling the exponent of the result,
  91. // it is still too small.
  92. // Deliver 0 to the trap handler
  93. return _except1(FP_U | FP_P, OP_EXP, x, 0.0, savedcw);
  94. }
  95. if (ABS(x) < EPS) {
  96. result = 1.0;
  97. }
  98. else {
  99. result = _exphlp(x, &newexp);
  100. if (newexp > MAXEXP) {
  101. result = _set_exp(result, newexp-IEEE_ADJUST);
  102. return _except1(FP_O | FP_P, OP_EXP, x, result, savedcw);
  103. }
  104. else if (newexp < MINEXP) {
  105. result = _set_exp(result, newexp+IEEE_ADJUST);
  106. return _except1(FP_U | FP_P, OP_EXP, x, result, savedcw);
  107. }
  108. else
  109. result = _set_exp(result, newexp);
  110. }
  111. RETURN_INEXACT1(OP_EXP, x, result, savedcw);
  112. }
  113. /***
  114. *double _exphlp(double x, int * pnewexp) - exp helper routine
  115. *
  116. *Purpose:
  117. * Provide the mantissa and the exponent of e^x
  118. *
  119. *Entry:
  120. * x : a (non special) double precision number
  121. *
  122. *Exit:
  123. * *newexp: the exponent of e^x
  124. * return value: the mantissa m of e^x scaled by a factor
  125. * (the value of this factor has no significance.
  126. * The mantissa can be obtained with _set_exp(m, 0).
  127. *
  128. * _set_exp(m, *pnewexp) may be used for constructing the final
  129. * result, if it is within the representable range.
  130. *
  131. *Exceptions:
  132. * No exceptions are raised by this function
  133. *
  134. *******************************************************************************/
  135. double _exphlp(double x, int * pnewexp)
  136. {
  137. double xn;
  138. double g,z,gpz,qz,rg;
  139. int n;
  140. xn = _frnd(x * LN2INV);
  141. n = (int) xn;
  142. /* assume guard digit is present */
  143. g = (x - xn * C1) - xn * C2;
  144. z = g*g;
  145. gpz = g * P(z);
  146. qz = Q(z);
  147. rg = 0.5 + gpz/(qz-gpz);
  148. n++;
  149. *pnewexp = _get_exp(rg) + n;
  150. return rg;
  151. }