X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=src%2Fmath%2Fexp2.c;h=e14adba530e49d25849107a75952d7776402319b;hb=9db81b862d95326d43af7c7fae9078ad9ff5bd6f;hp=08c21a66a79c701193ee645415ac6c2b4af18626;hpb=9e2a895aaaa4a3985e94ae4f3e24c1af65f9bb34;p=musl diff --git a/src/math/exp2.c b/src/math/exp2.c index 08c21a66..e14adba5 100644 --- a/src/math/exp2.c +++ b/src/math/exp2.c @@ -27,11 +27,9 @@ #include "libm.h" -#define TBLBITS 8 -#define TBLSIZE (1 << TBLBITS) +#define TBLSIZE 256 static const double -huge = 0x1p1000, redux = 0x1.8p52 / TBLSIZE, P1 = 0x1.62e42fefa39efp-1, P2 = 0x1.ebfbdff82c575p-3, @@ -39,8 +37,6 @@ P3 = 0x1.c6b08d704a0a6p-5, P4 = 0x1.3b2ab88f70400p-7, P5 = 0x1.5d88003875c74p-10; -static const volatile double twom1000 = 0x1p-1000; - static const double tbl[TBLSIZE * 2] = { /* exp2(z + eps) eps */ 0x1.6a09e667f3d5dp-1, 0x1.9880p-44, @@ -309,7 +305,7 @@ static const double tbl[TBLSIZE * 2] = { * Method: (accurate tables) * * Reduce x: - * x = 2**k + y, for integer k and |y| <= 1/2. + * x = k + y, for integer k and |y| <= 1/2. * Thus we have exp2(x) = 2**k * exp2(y). * * Reduce y: @@ -334,51 +330,46 @@ static const double tbl[TBLSIZE * 2] = { */ double exp2(double x) { - double r, t, twopk, twopkp1000, z; - uint32_t hx, ix, lx, i0; - int k; + double_t r, t, z; + uint32_t ix, i0; + union {double f; uint64_t i;} u = {x}; + union {uint32_t u; int32_t i;} k; /* Filter out exceptional cases. */ - GET_HIGH_WORD(hx, x); - ix = hx & 0x7fffffff; - if (ix >= 0x40900000) { /* |x| >= 1024 */ - if (ix >= 0x7ff00000) { - GET_LOW_WORD(lx, x); - if (((ix & 0xfffff) | lx) != 0 || (hx & 0x80000000) == 0) - return x + x; /* x is NaN or +Inf */ - else - return 0.0; /* x is -Inf */ + ix = u.i>>32 & 0x7fffffff; + if (ix >= 0x408ff000) { /* |x| >= 1022 or nan */ + if (ix >= 0x40900000 && u.i>>63 == 0) { /* x >= 1024 or nan */ + /* overflow */ + x *= 0x1p1023; + return x; + } + if (ix >= 0x7ff00000) /* -inf or -nan */ + return -1/x; + if (u.i>>63) { /* x <= -1022 */ + /* underflow */ + if (x <= -1075 || x - 0x1p52 + 0x1p52 != x) + FORCE_EVAL((float)(-0x1p-149/x)); + if (x <= -1075) + return 0; } - if (x >= 0x1.0p10) - return huge * huge; /* overflow */ - if (x <= -0x1.0ccp10) - return twom1000 * twom1000; /* underflow */ } else if (ix < 0x3c900000) { /* |x| < 0x1p-54 */ return 1.0 + x; } /* Reduce x, computing z, i0, and k. */ - STRICT_ASSIGN(double, t, x + redux); - GET_LOW_WORD(i0, t); + u.f = x + redux; + i0 = u.i; i0 += TBLSIZE / 2; - k = (i0 >> TBLBITS) << 20; - i0 = (i0 & (TBLSIZE - 1)) << 1; - t -= redux; - z = x - t; + k.u = i0 / TBLSIZE * TBLSIZE; + k.i /= TBLSIZE; + i0 %= TBLSIZE; + u.f -= redux; + z = x - u.f; /* Compute r = exp2(y) = exp2t[i0] * p(z - eps[i]). */ - t = tbl[i0]; /* exp2t[i0] */ - z -= tbl[i0 + 1]; /* eps[i0] */ - if (k >= -1021 << 20) - INSERT_WORDS(twopk, 0x3ff00000 + k, 0); - else - INSERT_WORDS(twopkp1000, 0x3ff00000 + k + (1000 << 20), 0); + t = tbl[2*i0]; /* exp2t[i0] */ + z -= tbl[2*i0 + 1]; /* eps[i0] */ r = t + t * z * (P1 + z * (P2 + z * (P3 + z * (P4 + z * P5)))); - /* Scale by 2**(k>>20). */ - if (k < -1021 << 20) - return r * twopkp1000 * twom1000; - if (k == 1024 << 20) - return r * 2.0 * 0x1p1023; - return r * twopk; + return scalbn(r, k.i); }