Exemple #1
0
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;
    }
Exemple #2
0
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;