don't set errno or return an error when getspnam[_r] finds no entry
[musl] / src / math / exp2.c
index 08c21a6..e14adba 100644 (file)
 
 #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);
 }