Esempio n. 1
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 (__glibc_likely (isless (x, himark)))
    {
      /* Exceptional cases:  */
      if (__glibc_unlikely (!isgreaterequal (x, lomark)))
	{
	  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;

      if (fabs (x) < DBL_EPSILON / 4.0)
	return 1.0 + x;

      {
	SET_RESTORE_ROUND_NOEX (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;
	/* x2 is an integer multiple of 2^-54; avoid intermediate
	   underflow from the calculation of x22 * x.  */
	unsafe = abs (tval) >= -DBL_MIN_EXP - 56;
	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).  */
      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;
Esempio n. 2
0
double
__ieee754_remainder (double x, double y)
{
  double z, d, xx;
  int4 kx, ky, n, nn, n1, m1, l;
  mynumber u, t, w = { { 0, 0 } }, v = { { 0, 0 } }, ww = { { 0, 0 } }, r;
  u.x = x;
  t.x = y;
  kx = u.i[HIGH_HALF] & 0x7fffffff; /* no sign  for x*/
  t.i[HIGH_HALF] &= 0x7fffffff;   /*no sign for y */
  ky = t.i[HIGH_HALF];
  /*------ |x| < 2^1023  and   2^-970 < |y| < 2^1024 ------------------*/
  if (kx < 0x7fe00000 && ky < 0x7ff00000 && ky >= 0x03500000)
    {
      SET_RESTORE_ROUND_NOEX (FE_TONEAREST);
      if (kx + 0x00100000 < ky)
	return x;
      if ((kx - 0x01500000) < ky)
	{
	  z = x / t.x;
	  v.i[HIGH_HALF] = t.i[HIGH_HALF];
	  d = (z + big.x) - big.x;
	  xx = (x - d * v.x) - d * (t.x - v.x);
	  if (d - z != 0.5 && d - z != -0.5)
	    return (xx != 0) ? xx : ((x > 0) ? ZERO.x : nZERO.x);
	  else
	    {
	      if (fabs (xx) > 0.5 * t.x)
		return (z > d) ? xx - t.x : xx + t.x;
	      else
		return xx;
	    }
	} /*    (kx<(ky+0x01500000))         */
      else
	{
	  r.x = 1.0 / t.x;
	  n = t.i[HIGH_HALF];
	  nn = (n & 0x7ff00000) + 0x01400000;
	  w.i[HIGH_HALF] = n;
	  ww.x = t.x - w.x;
	  l = (kx - nn) & 0xfff00000;
	  n1 = ww.i[HIGH_HALF];
	  m1 = r.i[HIGH_HALF];
	  while (l > 0)
	    {
	      r.i[HIGH_HALF] = m1 - l;
	      z = u.x * r.x;
	      w.i[HIGH_HALF] = n + l;
	      ww.i[HIGH_HALF] = (n1) ? n1 + l : n1;
	      d = (z + big.x) - big.x;
	      u.x = (u.x - d * w.x) - d * ww.x;
	      l = (u.i[HIGH_HALF] & 0x7ff00000) - nn;
	    }
	  r.i[HIGH_HALF] = m1;
	  w.i[HIGH_HALF] = n;
	  ww.i[HIGH_HALF] = n1;
	  z = u.x * r.x;
	  d = (z + big.x) - big.x;
	  u.x = (u.x - d * w.x) - d * ww.x;
	  if (fabs (u.x) < 0.5 * t.x)
	    return (u.x != 0) ? u.x : ((x > 0) ? ZERO.x : nZERO.x);
	  else
	  if (fabs (u.x) > 0.5 * t.x)
	    return (d > z) ? u.x + t.x : u.x - t.x;
	  else
	    {
	      z = u.x / t.x; d = (z + big.x) - big.x;
              return ((u.x - d * w.x) - d * ww.x);
	    }
	}
    } /*   (kx<0x7fe00000&&ky<0x7ff00000&&ky>=0x03500000)     */
  else
    {
      if (kx < 0x7fe00000 && ky < 0x7ff00000 && (ky > 0 || t.i[LOW_HALF] != 0))
	{
	  y = fabs (y) * t128.x;
	  z = __ieee754_remainder (x, y) * t128.x;
	  z = __ieee754_remainder (z, y) * tm128.x;
	  return z;
	}
      else
	{
	  if ((kx & 0x7ff00000) == 0x7fe00000 && ky < 0x7ff00000 &&
              (ky > 0 || t.i[LOW_HALF] != 0))
	    {
	      y = fabs (y);
	      z = 2.0 * __ieee754_remainder (0.5 * x, y);
	      d = fabs (z);
	      if (d <= fabs (d - y))
		return z;
	      else if (d == y)
		return 0.0 * x;
	      else
		return (z > 0) ? z - y : z + y;
	    }
	  else /* if x is too big */
	    {
	      if (ky == 0 && t.i[LOW_HALF] == 0) /* y = 0 */
		return (x * y) / (x * y);
	      else if (kx >= 0x7ff00000         /* x not finite */
		       || (ky > 0x7ff00000      /* y is NaN */
			   || (ky == 0x7ff00000 && t.i[LOW_HALF] != 0)))
		return (x * y) / (x * y);
	      else
		return x;
	    }
	}
    }
}