예제 #1
0
double
__ieee754_log2(double x)
{
	double f,hfsq,hi,lo,r,val_hi,val_lo,w,y;
	int32_t i,k,hx;
	u_int32_t lx;

	EXTRACT_WORDS(hx,lx,x);

	k=0;
	if (hx < 0x00100000) {			/* x < 2**-1022  */
	    if (((hx&0x7fffffff)|lx)==0)
		return -two54/vzero;		/* log(+-0)=-inf */
	    if (hx<0) return (x-x)/zero;	/* log(-#) = NaN */
	    k -= 54; x *= two54; /* subnormal number, scale up x */
	    GET_HIGH_WORD(hx,x);
	}
	if (hx >= 0x7ff00000) return x+x;
	if (hx == 0x3ff00000 && lx == 0)
	    return zero;			/* log(1) = +0 */
	k += (hx>>20)-1023;
	hx &= 0x000fffff;
	i = (hx+0x95f64)&0x100000;
	SET_HIGH_WORD(x,hx|(i^0x3ff00000));	/* normalize x or x/2 */
	k += (i>>20);
	y = (double)k;
	f = x - 1.0;
	hfsq = 0.5*f*f;
	r = k_log1p(f);

	/*
	 * f-hfsq must (for args near 1) be evaluated in extra precision
	 * to avoid a large cancellation when x is near sqrt(2) or 1/sqrt(2).
	 * This is fairly efficient since f-hfsq only depends on f, so can
	 * be evaluated in parallel with R.  Not combining hfsq with R also
	 * keeps R small (though not as small as a true `lo' term would be),
	 * so that extra precision is not needed for terms involving R.
	 *
	 * Compiler bugs involving extra precision used to break Dekker's
	 * theorem for spitting f-hfsq as hi+lo, unless double_t was used
	 * or the multi-precision calculations were avoided when double_t
	 * has extra precision.  These problems are now automatically
	 * avoided as a side effect of the optimization of combining the
	 * Dekker splitting step with the clear-low-bits step.
	 *
	 * y must (for args near sqrt(2) and 1/sqrt(2)) be added in extra
	 * precision to avoid a very large cancellation when x is very near
	 * these values.  Unlike the above cancellations, this problem is
	 * specific to base 2.  It is strange that adding +-1 is so much
	 * harder than adding +-ln2 or +-log10_2.
	 *
	 * This uses Dekker's theorem to normalize y+val_hi, so the
	 * compiler bugs are back in some configurations, sigh.  And I
	 * don't want to used double_t to avoid them, since that gives a
	 * pessimization and the support for avoiding the pessimization
	 * is not yet available.
	 *
	 * The multi-precision calculations for the multiplications are
	 * routine.
	 */
	hi = f - hfsq;
	SET_LOW_WORD(hi,0);
	lo = (f - hi) - hfsq + r;
	val_hi = hi*ivln2hi;
	val_lo = (lo+hi)*ivln2lo + lo*ivln2hi;

	/* spadd(val_hi, val_lo, y), except for not using double_t: */
	w = y + val_hi;
	val_lo += (y - w) + val_hi;
	val_hi = w;

	return val_lo + val_hi;
}
예제 #2
0
파일: e_hypot.c 프로젝트: kraj/glibc
double
__ieee754_hypot (double x, double y)
{
  double a, b, t1, t2, y1, y2, w;
  int32_t j, k, ha, hb;

  GET_HIGH_WORD (ha, x);
  ha &= 0x7fffffff;
  GET_HIGH_WORD (hb, y);
  hb &= 0x7fffffff;
  if (hb > ha)
    {
      a = y; b = x; j = ha; ha = hb; hb = j;
    }
  else
    {
      a = x; b = y;
    }
  SET_HIGH_WORD (a, ha);        /* a <- |a| */
  SET_HIGH_WORD (b, hb);        /* b <- |b| */
  if ((ha - hb) > 0x3c00000)
    {
      return a + b;
    }                                       /* x/y > 2**60 */
  k = 0;
  if (__glibc_unlikely (ha > 0x5f300000))                  /* a>2**500 */
    {
      if (ha >= 0x7ff00000)             /* Inf or NaN */
	{
	  u_int32_t low;
	  w = a + b;                    /* for sNaN */
	  if (issignaling (a) || issignaling (b))
	    return w;
	  GET_LOW_WORD (low, a);
	  if (((ha & 0xfffff) | low) == 0)
	    w = a;
	  GET_LOW_WORD (low, b);
	  if (((hb ^ 0x7ff00000) | low) == 0)
	    w = b;
	  return w;
	}
      /* scale a and b by 2**-600 */
      ha -= 0x25800000; hb -= 0x25800000;  k += 600;
      SET_HIGH_WORD (a, ha);
      SET_HIGH_WORD (b, hb);
    }
  if (__builtin_expect (hb < 0x23d00000, 0))            /* b < 2**-450 */
    {
      if (hb <= 0x000fffff)             /* subnormal b or 0 */
	{
	  u_int32_t low;
	  GET_LOW_WORD (low, b);
	  if ((hb | low) == 0)
	    return a;
	  t1 = 0;
	  SET_HIGH_WORD (t1, 0x7fd00000);       /* t1=2^1022 */
	  b *= t1;
	  a *= t1;
	  k -= 1022;
	  GET_HIGH_WORD (ha, a);
	  GET_HIGH_WORD (hb, b);
	  if (hb > ha)
	    {
	      t1 = a;
	      a = b;
	      b = t1;
	      j = ha;
	      ha = hb;
	      hb = j;
	    }
	}
      else                      /* scale a and b by 2^600 */
	{
	  ha += 0x25800000;             /* a *= 2^600 */
	  hb += 0x25800000;             /* b *= 2^600 */
	  k -= 600;
	  SET_HIGH_WORD (a, ha);
	  SET_HIGH_WORD (b, hb);
	}
    }
  /* medium size a and b */
  w = a - b;
  if (w > b)
    {
      t1 = 0;
      SET_HIGH_WORD (t1, ha);
      t2 = a - t1;
      w = __ieee754_sqrt (t1 * t1 - (b * (-b) - t2 * (a + t1)));
    }
  else
    {
      a = a + a;
      y1 = 0;
      SET_HIGH_WORD (y1, hb);
      y2 = b - y1;
      t1 = 0;
      SET_HIGH_WORD (t1, ha + 0x00100000);
      t2 = a - t1;
      w = __ieee754_sqrt (t1 * y1 - (w * (-w) - (t1 * y2 + t2 * b)));
    }
  if (k != 0)
    {
      u_int32_t high;
      t1 = 1.0;
      GET_HIGH_WORD (high, t1);
      SET_HIGH_WORD (t1, high + (k << 20));
      w *= t1;
      math_check_force_underflow_nonneg (w);
      return w;
    }
  else
    return w;
}
예제 #3
0
파일: s_ctanh.c 프로젝트: jashank/freebsd
double complex
ctanh(double complex z)
{
	double x, y;
	double t, beta, s, rho, denom;
	uint32_t hx, ix, lx;

	x = creal(z);
	y = cimag(z);

	EXTRACT_WORDS(hx, lx, x);
	ix = hx & 0x7fffffff;

	/*
	 * ctanh(NaN + i 0) = NaN + i 0
	 *
	 * ctanh(NaN + i y) = NaN + i NaN		for y != 0
	 *
	 * The imaginary part has the sign of x*sin(2*y), but there's no
	 * special effort to get this right.
	 *
	 * ctanh(+-Inf +- i Inf) = +-1 +- 0
	 *
	 * ctanh(+-Inf + i y) = +-1 + 0 sin(2y)		for y finite
	 *
	 * The imaginary part of the sign is unspecified.  This special
	 * case is only needed to avoid a spurious invalid exception when
	 * y is infinite.
	 */
	if (ix >= 0x7ff00000) {
		if ((ix & 0xfffff) | lx)	/* x is NaN */
			return (CMPLX(x, (y == 0 ? y : x * y)));
		SET_HIGH_WORD(x, hx - 0x40000000);	/* x = copysign(1, x) */
		return (CMPLX(x, copysign(0, isinf(y) ? y : sin(y) * cos(y))));
	}

	/*
	 * ctanh(x + i NAN) = NaN + i NaN
	 * ctanh(x +- i Inf) = NaN + i NaN
	 */
	if (!isfinite(y))
		return (CMPLX(y - y, y - y));

	/*
	 * ctanh(+-huge + i +-y) ~= +-1 +- i 2sin(2y)/exp(2x), using the
	 * approximation sinh^2(huge) ~= exp(2*huge) / 4.
	 * We use a modified formula to avoid spurious overflow.
	 */
	if (ix >= 0x40360000) {	/* x >= 22 */
		double exp_mx = exp(-fabs(x));
		return (CMPLX(copysign(1, x),
		    4 * sin(y) * cos(y) * exp_mx * exp_mx));
	}

	/* Kahan's algorithm */
	t = tan(y);
	beta = 1.0 + t * t;	/* = 1 / cos^2(y) */
	s = sinh(x);
	rho = sqrt(1 + s * s);	/* = cosh(x) */
	denom = 1 + beta * s * s;
	return (CMPLX((beta * rho * s) / denom, t / denom));
}