e_exp.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. /* @(#)e_exp.c 1.6 04/04/22 */
  2. /*
  3. * ====================================================
  4. * Copyright (C) 2004 by Sun Microsystems, Inc. All rights reserved.
  5. *
  6. * Permission to use, copy, modify, and distribute this
  7. * software is freely granted, provided that this notice
  8. * is preserved.
  9. * ====================================================
  10. */
  11. #include "cdefs-compat.h"
  12. //__FBSDID("$FreeBSD: src/lib/msun/src/e_exp.c,v 1.14 2011/10/21 06:26:38 das Exp $");
  13. /* __ieee754_exp(x)
  14. * Returns the exponential of x.
  15. *
  16. * Method
  17. * 1. Argument reduction:
  18. * Reduce x to an r so that |r| <= 0.5*ln2 ~ 0.34658.
  19. * Given x, find r and integer k such that
  20. *
  21. * x = k*ln2 + r, |r| <= 0.5*ln2.
  22. *
  23. * Here r will be represented as r = hi-lo for better
  24. * accuracy.
  25. *
  26. * 2. Approximation of exp(r) by a special rational function on
  27. * the interval [0,0.34658]:
  28. * Write
  29. * R(r**2) = r*(exp(r)+1)/(exp(r)-1) = 2 + r*r/6 - r**4/360 + ...
  30. * We use a special Remes algorithm on [0,0.34658] to generate
  31. * a polynomial of degree 5 to approximate R. The maximum error
  32. * of this polynomial approximation is bounded by 2**-59. In
  33. * other words,
  34. * R(z) ~ 2.0 + P1*z + P2*z**2 + P3*z**3 + P4*z**4 + P5*z**5
  35. * (where z=r*r, and the values of P1 to P5 are listed below)
  36. * and
  37. * | 5 | -59
  38. * | 2.0+P1*z+...+P5*z - R(z) | <= 2
  39. * | |
  40. * The computation of exp(r) thus becomes
  41. * 2*r
  42. * exp(r) = 1 + -------
  43. * R - r
  44. * r*R1(r)
  45. * = 1 + r + ----------- (for better accuracy)
  46. * 2 - R1(r)
  47. * where
  48. * 2 4 10
  49. * R1(r) = r - (P1*r + P2*r + ... + P5*r ).
  50. *
  51. * 3. Scale back to obtain exp(x):
  52. * From step 1, we have
  53. * exp(x) = 2^k * exp(r)
  54. *
  55. * Special cases:
  56. * exp(INF) is INF, exp(NaN) is NaN;
  57. * exp(-INF) is 0, and
  58. * for finite argument, only exp(0)=1 is exact.
  59. *
  60. * Accuracy:
  61. * according to an error analysis, the error is always less than
  62. * 1 ulp (unit in the last place).
  63. *
  64. * Misc. info.
  65. * For IEEE double
  66. * if x > 7.09782712893383973096e+02 then exp(x) overflow
  67. * if x < -7.45133219101941108420e+02 then exp(x) underflow
  68. *
  69. * Constants:
  70. * The hexadecimal values are the intended ones for the following
  71. * constants. The decimal values may be used, provided that the
  72. * compiler will convert from decimal to binary accurately enough
  73. * to produce the hexadecimal values shown.
  74. */
  75. #include <float.h>
  76. #include <openlibm.h>
  77. #include "math_private.h"
  78. static const double
  79. one = 1.0,
  80. halF[2] = {0.5,-0.5,},
  81. huge = 1.0e+300,
  82. o_threshold= 7.09782712893383973096e+02, /* 0x40862E42, 0xFEFA39EF */
  83. u_threshold= -7.45133219101941108420e+02, /* 0xc0874910, 0xD52D3051 */
  84. ln2HI[2] ={ 6.93147180369123816490e-01, /* 0x3fe62e42, 0xfee00000 */
  85. -6.93147180369123816490e-01,},/* 0xbfe62e42, 0xfee00000 */
  86. ln2LO[2] ={ 1.90821492927058770002e-10, /* 0x3dea39ef, 0x35793c76 */
  87. -1.90821492927058770002e-10,},/* 0xbdea39ef, 0x35793c76 */
  88. invln2 = 1.44269504088896338700e+00, /* 0x3ff71547, 0x652b82fe */
  89. P1 = 1.66666666666666019037e-01, /* 0x3FC55555, 0x5555553E */
  90. P2 = -2.77777777770155933842e-03, /* 0xBF66C16C, 0x16BEBD93 */
  91. P3 = 6.61375632143793436117e-05, /* 0x3F11566A, 0xAF25DE2C */
  92. P4 = -1.65339022054652515390e-06, /* 0xBEBBBD41, 0xC5D26BF1 */
  93. P5 = 4.13813679705723846039e-08; /* 0x3E663769, 0x72BEA4D0 */
  94. static volatile double
  95. twom1000= 9.33263618503218878990e-302; /* 2**-1000=0x01700000,0*/
  96. DLLEXPORT double
  97. __ieee754_exp(double x) /* default IEEE double exp */
  98. {
  99. double y,hi=0.0,lo=0.0,c,t,twopk;
  100. int32_t k=0,xsb;
  101. u_int32_t hx;
  102. GET_HIGH_WORD(hx,x);
  103. xsb = (hx>>31)&1; /* sign bit of x */
  104. hx &= 0x7fffffff; /* high word of |x| */
  105. /* filter out non-finite argument */
  106. if(hx >= 0x40862E42) { /* if |x|>=709.78... */
  107. if(hx>=0x7ff00000) {
  108. u_int32_t lx;
  109. GET_LOW_WORD(lx,x);
  110. if(((hx&0xfffff)|lx)!=0)
  111. return x+x; /* NaN */
  112. else return (xsb==0)? x:0.0; /* exp(+-inf)={inf,0} */
  113. }
  114. if(x > o_threshold) return huge*huge; /* overflow */
  115. if(x < u_threshold) return twom1000*twom1000; /* underflow */
  116. }
  117. /* this implementation gives 2.7182818284590455 for exp(1.0),
  118. which is well within the allowable error. however,
  119. 2.718281828459045 is closer to the true value so we prefer that
  120. answer, given that 1.0 is such an important argument value. */
  121. if (x == 1.0)
  122. return 2.718281828459045235360;
  123. /* argument reduction */
  124. if(hx > 0x3fd62e42) { /* if |x| > 0.5 ln2 */
  125. if(hx < 0x3FF0A2B2) { /* and |x| < 1.5 ln2 */
  126. hi = x-ln2HI[xsb]; lo=ln2LO[xsb]; k = 1-xsb-xsb;
  127. } else {
  128. k = (int)(invln2*x+halF[xsb]);
  129. t = k;
  130. hi = x - t*ln2HI[0]; /* t*ln2HI is exact here */
  131. lo = t*ln2LO[0];
  132. }
  133. STRICT_ASSIGN(double, x, hi - lo);
  134. }
  135. else if(hx < 0x3e300000) { /* when |x|<2**-28 */
  136. if(huge+x>one) return one+x;/* trigger inexact */
  137. }
  138. else k = 0;
  139. /* x is now in primary range */
  140. t = x*x;
  141. if(k >= -1021)
  142. INSERT_WORDS(twopk,0x3ff00000+(k<<20), 0);
  143. else
  144. INSERT_WORDS(twopk,0x3ff00000+((k+1000)<<20), 0);
  145. c = x - t*(P1+t*(P2+t*(P3+t*(P4+t*P5))));
  146. if(k==0) return one-((x*c)/(c-2.0)-x);
  147. else y = one-((lo-(x*c)/(2.0-c))-hi);
  148. if(k >= -1021) {
  149. if (k==1024) return y*2.0*0x1p1023;
  150. return y*twopk;
  151. } else {
  152. return y*twopk*twom1000;
  153. }
  154. }