OLD | NEW |
(Empty) | |
| 1 /* origin: FreeBSD /usr/src/lib/msun/src/e_expf.c */ |
| 2 /* |
| 3 * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. |
| 4 */ |
| 5 /* |
| 6 * ==================================================== |
| 7 * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. |
| 8 * |
| 9 * Developed at SunPro, a Sun Microsystems, Inc. business. |
| 10 * Permission to use, copy, modify, and distribute this |
| 11 * software is freely granted, provided that this notice |
| 12 * is preserved. |
| 13 * ==================================================== |
| 14 */ |
| 15 |
| 16 #include "libm.h" |
| 17 |
| 18 static const float |
| 19 half[2] = {0.5,-0.5}, |
| 20 ln2hi = 6.9314575195e-1f, /* 0x3f317200 */ |
| 21 ln2lo = 1.4286067653e-6f, /* 0x35bfbe8e */ |
| 22 invln2 = 1.4426950216e+0f, /* 0x3fb8aa3b */ |
| 23 /* |
| 24 * Domain [-0.34568, 0.34568], range ~[-4.278e-9, 4.447e-9]: |
| 25 * |x*(exp(x)+1)/(exp(x)-1) - p(x)| < 2**-27.74 |
| 26 */ |
| 27 P1 = 1.6666625440e-1f, /* 0xaaaa8f.0p-26 */ |
| 28 P2 = -2.7667332906e-3f; /* -0xb55215.0p-32 */ |
| 29 |
| 30 float expf(float x) |
| 31 { |
| 32 float_t hi, lo, c, xx, y; |
| 33 int k, sign; |
| 34 uint32_t hx; |
| 35 |
| 36 GET_FLOAT_WORD(hx, x); |
| 37 sign = hx >> 31; /* sign bit of x */ |
| 38 hx &= 0x7fffffff; /* high word of |x| */ |
| 39 |
| 40 /* special cases */ |
| 41 if (hx >= 0x42aeac50) { /* if |x| >= -87.33655f or NaN */ |
| 42 if (hx >= 0x42b17218 && !sign) { /* x >= 88.722839f */ |
| 43 /* overflow */ |
| 44 x *= 0x1p127f; |
| 45 return x; |
| 46 } |
| 47 if (sign) { |
| 48 /* underflow */ |
| 49 FORCE_EVAL(-0x1p-149f/x); |
| 50 if (hx >= 0x42cff1b5) /* x <= -103.972084f */ |
| 51 return 0; |
| 52 } |
| 53 } |
| 54 |
| 55 /* argument reduction */ |
| 56 if (hx > 0x3eb17218) { /* if |x| > 0.5 ln2 */ |
| 57 if (hx > 0x3f851592) /* if |x| > 1.5 ln2 */ |
| 58 k = invln2*x + half[sign]; |
| 59 else |
| 60 k = 1 - sign - sign; |
| 61 hi = x - k*ln2hi; /* k*ln2hi is exact here */ |
| 62 lo = k*ln2lo; |
| 63 x = hi - lo; |
| 64 } else if (hx > 0x39000000) { /* |x| > 2**-14 */ |
| 65 k = 0; |
| 66 hi = x; |
| 67 lo = 0; |
| 68 } else { |
| 69 /* raise inexact */ |
| 70 FORCE_EVAL(0x1p127f + x); |
| 71 return 1 + x; |
| 72 } |
| 73 |
| 74 /* x is now in primary range */ |
| 75 xx = x*x; |
| 76 c = x - xx*(P1+xx*P2); |
| 77 y = 1 + (x*c/(2-c) - lo + hi); |
| 78 if (k == 0) |
| 79 return y; |
| 80 return scalbnf(y, k); |
| 81 } |
OLD | NEW |