double __ieee754_sqrt (double x) { #include "uroot.h" static const double rt0 = 9.99999999859990725855365213134618E-01, rt1 = 4.99999999495955425917856814202739E-01, rt2 = 3.75017500867345182581453026130850E-01, rt3 = 3.12523626554518656309172508769531E-01; static const double big = 134217728.0; double y, t, del, res, res1, hy, z, zz, p, hx, tx, ty, s; mynumber a, c = { { 0, 0 } }; int4 k; a.x = x; k = a.i[HIGH_HALF]; a.i[HIGH_HALF] = (k & 0x001fffff) | 0x3fe00000; t = inroot[(k & 0x001fffff) >> 14]; s = a.x; /*----------------- 2^-1022 <= | x |< 2^1024 -----------------*/ if (k > 0x000fffff && k < 0x7ff00000) { int rm = __fegetround (); fenv_t env; libc_feholdexcept_setround (&env, FE_TONEAREST); double ret; y = 1.0 - t * (t * s); t = t * (rt0 + y * (rt1 + y * (rt2 + y * rt3))); c.i[HIGH_HALF] = 0x20000000 + ((k & 0x7fe00000) >> 1); y = t * s; hy = (y + big) - big; del = 0.5 * t * ((s - hy * hy) - (y - hy) * (y + hy)); res = y + del; if (res == (res + 1.002 * ((y - res) + del))) ret = res * c.x; else { res1 = res + 1.5 * ((y - res) + del); EMULV (res, res1, z, zz, p, hx, tx, hy, ty); /* (z+zz)=res*res1 */ res = ((((z - s) + zz) < 0) ? max (res, res1) : min (res, res1)); ret = res * c.x; } math_force_eval (ret); libc_fesetenv (&env); double dret = x / ret; if (dret != ret) { double force_inexact = 1.0 / 3.0; math_force_eval (force_inexact); /* The square root is inexact, ret is the round-to-nearest value which may need adjusting for other rounding modes. */ switch (rm) { #ifdef FE_UPWARD case FE_UPWARD: if (dret > ret) ret = (res + 0x1p-1022) * c.x; break; #endif #ifdef FE_DOWNWARD case FE_DOWNWARD: #endif #ifdef FE_TOWARDZERO case FE_TOWARDZERO: #endif #if defined FE_DOWNWARD || defined FE_TOWARDZERO if (dret < ret) ret = (res - 0x1p-1022) * c.x; break; #endif default: break; } } /* Otherwise (x / ret == ret), either the square root was exact or the division was inexact. */ return ret; }
double __ieee754_exp2 (double x) { static const double himark = (double) DBL_MAX_EXP; static const double lomark = (double) (DBL_MIN_EXP - DBL_MANT_DIG - 1); /* Check for usual case. */ if (__builtin_expect (isless (x, himark), 1)) { /* Exceptional cases: */ if (__builtin_expect (! isgreaterequal (x, lomark), 0)) { if (__isinf (x)) /* e^-inf == 0, with no error. */ return 0; else /* Underflow */ return TWOM1000 * TWOM1000; } static const double THREEp42 = 13194139533312.0; int tval, unsafe; double rx, x22, result; union ieee754_double ex2_u, scale_u; fenv_t oldenv; libc_feholdexcept_setround (&oldenv, FE_TONEAREST); /* 1. Argument reduction. Choose integers ex, -256 <= t < 256, and some real -1/1024 <= x1 <= 1024 so that x = ex + t/512 + x1. First, calculate rx = ex + t/512. */ rx = x + THREEp42; rx -= THREEp42; x -= rx; /* Compute x=x1. */ /* Compute tval = (ex*512 + t)+256. Now, t = (tval mod 512)-256 and ex=tval/512 [that's mod, NOT %; and /-round-to-nearest not the usual c integer /]. */ tval = (int) (rx * 512.0 + 256.0); /* 2. Adjust for accurate table entry. Find e so that x = ex + t/512 + e + x2 where -1e6 < e < 1e6, and (double)(2^(t/512+e)) is accurate to one part in 2^-64. */ /* 'tval & 511' is the same as 'tval%512' except that it's always positive. Compute x = x2. */ x -= exp2_deltatable[tval & 511]; /* 3. Compute ex2 = 2^(t/512+e+ex). */ ex2_u.d = exp2_accuratetable[tval & 511]; tval >>= 9; unsafe = abs(tval) >= -DBL_MIN_EXP - 1; ex2_u.ieee.exponent += tval >> unsafe; scale_u.d = 1.0; scale_u.ieee.exponent += tval - (tval >> unsafe); /* 4. Approximate 2^x2 - 1, using a fourth-degree polynomial, with maximum error in [-2^-10-2^-30,2^-10+2^-30] less than 10^-19. */ x22 = (((.0096181293647031180 * x + .055504110254308625) * x + .240226506959100583) * x + .69314718055994495) * ex2_u.d; math_opt_barrier (x22); /* 5. Return (2^x2-1) * 2^(t/512+e+ex) + 2^(t/512+e+ex). */ libc_fesetenv (&oldenv); result = x22 * x + ex2_u.d; if (!unsafe) return result; else return result * scale_u.d; } else /* Return x, if x is a NaN or Inf; or overflow, otherwise. */ return TWO1023*x;