Пример #1
0
double
__asinh (double x)
{
    double w;
    int32_t hx, ix;
    GET_HIGH_WORD (hx, x);
    ix = hx & 0x7fffffff;
    if (__glibc_unlikely (ix < 0x3e300000))                  /* |x|<2**-28 */
    {
        if (huge + x > one)
            return x;                       /* return x inexact except 0 */
    }
    if (__glibc_unlikely (ix > 0x41b00000))                  /* |x| > 2**28 */
    {
        if (ix >= 0x7ff00000)
            return x + x;                           /* x is inf or NaN */
        w = __ieee754_log (fabs (x)) + ln2;
    }
    else
    {
        double xa = fabs (x);
        if (ix > 0x40000000)              /* 2**28 > |x| > 2.0 */
        {
            w = __ieee754_log (2.0 * xa + one / (__ieee754_sqrt (xa * xa + one) +
                                                 xa));
        }
        else                      /* 2.0 > |x| > 2**-28 */
        {
            double t = xa * xa;
            w = __log1p (xa + t / (one + __ieee754_sqrt (one + t)));
        }
    }
    return __copysign (w, x);
}
Пример #2
0
double
__ieee754_acosh (double x)
{
  int64_t hx;
  EXTRACT_WORDS64 (hx, x);

  if (hx > INT64_C (0x4000000000000000))
    {
      if (__builtin_expect (hx >= INT64_C (0x41b0000000000000), 0))
	{
	  /* x > 2**28 */
	  if (hx >= INT64_C (0x7ff0000000000000))
	    /* x is inf of NaN */
	    return x + x;
	  else
	    return __ieee754_log (x) + ln2;/* acosh(huge)=log(2x) */
	}

      /* 2**28 > x > 2 */
      double t = x * x;
      return __ieee754_log (2.0 * x - one / (x + __ieee754_sqrt (t - one)));
    }
  else if (__builtin_expect (hx > INT64_C (0x3ff0000000000000), 1))
    {
      /* 1<x<2 */
      double t = x - one;
      return __log1p (t + __ieee754_sqrt (2.0 * t + t * t));
    }
  else if (__builtin_expect (hx == INT64_C (0x3ff0000000000000), 1))
    return 0.0;				/* acosh(1) = 0 */
  else					/* x < 1 */
    return (x - x) / (x - x);
}
Пример #3
0
double
__ieee754_y1(double x)
{
	double z, s,c,ss,cc,u,v,u1,u2,v1,v2,v3,z2,z4;
	int32_t hx,ix,lx;

	EXTRACT_WORDS(hx,lx,x);
	ix = 0x7fffffff&hx;
    /* if Y1(NaN) is NaN, Y1(-inf) is NaN, Y1(inf) is 0 */
	if(__builtin_expect(ix>=0x7ff00000, 0)) return  one/(x+x*x);
	if(__builtin_expect((ix|lx)==0, 0))
		return -HUGE_VAL+x; /* -inf and overflow exception.  */;
	if(__builtin_expect(hx<0, 0)) return zero/(zero*x);
	if(ix >= 0x40000000) {  /* |x| >= 2.0 */
		__sincos (x, &s, &c);
		ss = -s-c;
		cc = s-c;
		if(ix<0x7fe00000) {  /* make sure x+x not overflow */
		    z = __cos(x+x);
		    if ((s*c)>zero) cc = z/ss;
		    else            ss = z/cc;
		}
	/* y1(x) = sqrt(2/(pi*x))*(p1(x)*sin(x0)+q1(x)*cos(x0))
	 * where x0 = x-3pi/4
	 *      Better formula:
	 *              cos(x0) = cos(x)cos(3pi/4)+sin(x)sin(3pi/4)
	 *                      =  1/sqrt(2) * (sin(x) - cos(x))
	 *              sin(x0) = sin(x)cos(3pi/4)-cos(x)sin(3pi/4)
	 *                      = -1/sqrt(2) * (cos(x) + sin(x))
	 * To avoid cancellation, use
	 *              sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x))
	 * to compute the worse one.
	 */
		if(ix>0x48000000) z = (invsqrtpi*ss)/__ieee754_sqrt(x);
		else {
		    u = pone(x); v = qone(x);
		    z = invsqrtpi*(u*ss+v*cc)/__ieee754_sqrt(x);
		}
		return z;
	}
	if(__builtin_expect(ix<=0x3c900000, 0)) {    /* x < 2**-54 */
	    return(-tpi/x);
	}
	z = x*x;
#ifdef DO_NOT_USE_THIS
	u = U0[0]+z*(U0[1]+z*(U0[2]+z*(U0[3]+z*U0[4])));
	v = one+z*(V0[0]+z*(V0[1]+z*(V0[2]+z*(V0[3]+z*V0[4]))));
#else
	u1 = U0[0]+z*U0[1];z2=z*z;
	u2 = U0[2]+z*U0[3];z4=z2*z2;
	u  = u1 + z2*u2 + z4*U0[4];
	v1 = one+z*V0[0];
	v2 = V0[1]+z*V0[2];
	v3 = V0[3]+z*V0[4];
	v = v1 + z2*v2 + z4*v3;
#endif
	return(x*(u/v) + tpi*(__ieee754_j1(x)*__ieee754_log(x)-one/x));
}
Пример #4
0
double
__ieee754_hypot (double x, double y)
{
  x = fabs (x);
  y = fabs (y);

  TEST_INF_NAN (x, y);

  if (y > x)
    {
      double t = x;
      x = y;
      y = t;
    }
  if (y == 0.0)
    return x;
  /* if y is higher enough, y * 2^60 might overflow. The tests if
     y >= 1.7976931348623157e+308/2^60 (two60factor) and uses the
     appropriate check to avoid the overflow exception generation.  */
  if (y > two60factor)
    {
      if ((x / y) > two60)
	return x + y;
    }
  else
    {
      if (x > (y * two60))
	return x + y;
    }
  if (x > two500)
    {
      x *= twoM600;
      y *= twoM600;
      return __ieee754_sqrt (x * x + y * y) / twoM600;
    }
  if (y < twoM500)
    {
      if (y <= pdnum)
	{
	  x *= two1022;
	  y *= two1022;
	  double ret = __ieee754_sqrt (x * x + y * y) / two1022;
	  math_check_force_underflow_nonneg (ret);
	  return ret;
	}
      else
	{
	  x *= two600;
	  y *= two600;
	  return __ieee754_sqrt (x * x + y * y) / two600;
	}
    }
  return __ieee754_sqrt (x * x + y * y);
}
Пример #5
0
double
__ieee754_j0(double x)
{
	double z, s,c,ss,cc,r,u,v,r1,r2,s1,s2,z2,z4;
	int32_t hx,ix;

	GET_HIGH_WORD(hx,x);
	ix = hx&0x7fffffff;
	if(ix>=0x7ff00000) return one/(x*x);
	x = fabs(x);
	if(ix >= 0x40000000) {	/* |x| >= 2.0 */
		__sincos (x, &s, &c);
		ss = s-c;
		cc = s+c;
		if(ix<0x7fe00000) {  /* make sure x+x not overflow */
		    z = -__cos(x+x);
		    if ((s*c)<zero) cc = z/ss;
		    else	    ss = z/cc;
		}
	/*
	 * j0(x) = 1/sqrt(pi) * (P(0,x)*cc - Q(0,x)*ss) / sqrt(x)
	 * y0(x) = 1/sqrt(pi) * (P(0,x)*ss + Q(0,x)*cc) / sqrt(x)
	 */
		if(ix>0x48000000) z = (invsqrtpi*cc)/__ieee754_sqrt(x);
		else {
		    u = pzero(x); v = qzero(x);
		    z = invsqrtpi*(u*cc-v*ss)/__ieee754_sqrt(x);
		}
		return z;
	}
	if(ix<0x3f200000) {	/* |x| < 2**-13 */
	  math_force_eval(huge+x);	/* raise inexact if x != 0 */
	  if(ix<0x3e400000) return one;	/* |x|<2**-27 */
	  else	      return one - 0.25*x*x;
	}
	z = x*x;
#ifdef DO_NOT_USE_THIS
	r =  z*(R02+z*(R03+z*(R04+z*R05)));
	s =  one+z*(S01+z*(S02+z*(S03+z*S04)));
#else
	r1 = z*R[2]; z2=z*z;
	r2 = R[3]+z*R[4]; z4=z2*z2;
	r  = r1 + z2*r2 + z4*R[5];
	s1 = one+z*S[1];
	s2 = S[2]+z*S[3];
	s = s1 + z2*s2 + z4*S[4];
#endif
	if(ix < 0x3FF00000) {	/* |x| < 1.00 */
	    return one + z*(-0.25+(r/s));
	} else {
	    u = 0.5*x;
	    return((one+u)*(one-u)+z*(r/s));
	}
}
Пример #6
0
double
__ieee754_j1(double x)
{
	double z, s,c,ss,cc,r,u,v,y,r1,r2,s1,s2,s3,z2,z4;
	int32_t hx,ix;

	GET_HIGH_WORD(hx,x);
	ix = hx&0x7fffffff;
	if(__builtin_expect(ix>=0x7ff00000, 0)) return one/x;
	y = fabs(x);
	if(ix >= 0x40000000) {	/* |x| >= 2.0 */
		__sincos (y, &s, &c);
		ss = -s-c;
		cc = s-c;
		if(ix<0x7fe00000) {  /* make sure y+y not overflow */
		    z = __cos(y+y);
		    if ((s*c)>zero) cc = z/ss;
		    else	    ss = z/cc;
		}
	/*
	 * j1(x) = 1/sqrt(pi) * (P(1,x)*cc - Q(1,x)*ss) / sqrt(x)
	 * y1(x) = 1/sqrt(pi) * (P(1,x)*ss + Q(1,x)*cc) / sqrt(x)
	 */
		if(ix>0x48000000) z = (invsqrtpi*cc)/__ieee754_sqrt(y);
		else {
		    u = pone(y); v = qone(y);
		    z = invsqrtpi*(u*cc-v*ss)/__ieee754_sqrt(y);
		}
		if(hx<0) return -z;
		else	 return  z;
	}
	if(__builtin_expect(ix<0x3e400000, 0)) {	/* |x|<2**-27 */
	    if(huge+x>one) return 0.5*x;/* inexact if x!=0 necessary */
	}
	z = x*x;
#ifdef DO_NOT_USE_THIS
	r =  z*(r00+z*(r01+z*(r02+z*r03)));
	s =  one+z*(s01+z*(s02+z*(s03+z*(s04+z*s05))));
	r *= x;
#else
	r1 = z*R[0]; z2=z*z;
	r2 = R[1]+z*R[2]; z4=z2*z2;
	r = r1 + z2*r2 + z4*R[3];
	r *= x;
	s1 = one+z*S[1];
	s2 = S[2]+z*S[3];
	s3 = S[4]+z*S[5];
	s = s1 + z2*s2 + z4*s3;
#endif
	return(x*0.5+r/s);
}
Пример #7
0
double
sqrt(double x)		/* wrapper sqrt */
{
#ifdef _IEEE_LIBM
	return __ieee754_sqrt(x);
#else
	double z;
	z = __ieee754_sqrt(x);
	if(/* _LIB_VERSION == _IEEE_ || */ isnan(x)) return z;
	if(x<0.0) {
	    return __kernel_standard(x,x,26); /* sqrt(negative) */
	} else
	    return z;
#endif
}
Пример #8
0
float
__ieee754_hypotf(float x, float y)
{
	double d_x, d_y;
	int32_t ha, hb;

	GET_FLOAT_WORD(ha,x);
	ha &= 0x7fffffff;
	GET_FLOAT_WORD(hb,y);
	hb &= 0x7fffffff;
	if (ha == 0x7f800000 && !issignaling (y))
	  return fabsf(x);
	else if (hb == 0x7f800000 && !issignaling (x))
	  return fabsf(y);
	else if (ha > 0x7f800000 || hb > 0x7f800000)
	  return fabsf(x) * fabsf(y);
	else if (ha == 0)
	  return fabsf(y);
	else if (hb == 0)
	  return fabsf(x);

	d_x = (double) x;
	d_y = (double) y;

	return (float) __ieee754_sqrt(d_x * d_x + d_y * d_y);
}
Пример #9
0
float
__ieee754_hypotf (float x, float y)
{
  TEST_INF_NAN (x, y);

  return __ieee754_sqrt ((double) x * x + (double) y * y);
}
Пример #10
0
/* wrapper sqrt */
double
__sqrt (double x)
{
  if (__builtin_expect (isless (x, 0.0), 0) && _LIB_VERSION != _IEEE_)
    return __kernel_standard (x, x, 26); /* sqrt(negative) */

  return __ieee754_sqrt (x);
}
Пример #11
0
void
Math_sqrt(void *fp)
{
	F_Math_sqrt *f;

	f = fp;

	*f->ret = __ieee754_sqrt(f->x);
}
Пример #12
0
double
__ieee754_acos(double x)
{
	double z,p,q,r,w,s,c,df;
	int32_t hx,ix;
	GET_HIGH_WORD(hx,x);
	ix = hx&0x7fffffff;
	if(ix>=0x3ff00000) {	/* |x| >= 1 */
	    u_int32_t lx;
	    GET_LOW_WORD(lx,x);
	    if(((ix-0x3ff00000)|lx)==0) {	/* |x|==1 */
		if(hx>0) return 0.0;		/* acos(1) = 0  */
		else return pi+2.0*pio2_lo;	/* acos(-1)= pi */
	    }
	    return (x-x)/(x-x);		/* acos(|x|>1) is NaN */
	}
	if(ix<0x3fe00000) {	/* |x| < 0.5 */
	    if(ix<=0x3c600000) return pio2_hi+pio2_lo;/*if|x|<2**-57*/
	    z = x*x;
	    p = z*(pS0+z*(pS1+z*(pS2+z*(pS3+z*(pS4+z*pS5)))));
	    q = one+z*(qS1+z*(qS2+z*(qS3+z*qS4)));
	    r = p/q;
	    return pio2_hi - (x - (pio2_lo-x*r));
	} else  if (hx<0) {		/* x < -0.5 */
	    z = (one+x)*0.5;
	    p = z*(pS0+z*(pS1+z*(pS2+z*(pS3+z*(pS4+z*pS5)))));
	    q = one+z*(qS1+z*(qS2+z*(qS3+z*qS4)));
	    s = __ieee754_sqrt(z);
	    r = p/q;
	    w = r*s-pio2_lo;
	    return pi - 2.0*(s+w);
	} else {			/* x > 0.5 */
	    z = (one-x)*0.5;
	    s = __ieee754_sqrt(z);
	    df = s;
	    SET_LOW_WORD(df,0);
	    c  = (z-df*df)/(s+df);
	    p = z*(pS0+z*(pS1+z*(pS2+z*(pS3+z*(pS4+z*pS5)))));
	    q = one+z*(qS1+z*(qS2+z*(qS3+z*qS4)));
	    r = p/q;
	    w = r*s+c;
	    return 2.0*(df+w);
	}
}
Пример #13
0
    //------------------------------------------------------------------------------
    double Cmath::__ieee754_acosh( double x )
    {
        static const double one	= 1.0;
        static const double ln2	= 6.93147180559945286227e-01;  // 0x3FE62E42, 0xFEFA39EF

        double t;
        Cmp_signed__int32 hx;
        Cmp_unsigned__int32 lx;
        extract_words( hx, lx, x );
        if( hx < 0x3ff00000 )
        {
            // x < 1
            return ( x - x ) / ( x - x );
        }
        else if( hx >= 0x41b00000 )
        {
            // x > 2**28
            if( hx >= 0x7ff00000 )
            {
                // x is inf of NaN
                return x + x;
            }
            else
            {
                return __ieee754_log( x ) + ln2; // acosh(huge)=log(2x)
            }
        }
        else if( ( ( hx - 0x3ff00000 ) | lx ) == 0 )
        {
            return 0.0; // acosh(1) = 0
        }
        else if( hx > 0x40000000 )
        {
            // 2**28 > x > 2
            t = x * x;
            return __ieee754_log( 2.0 * x - one / ( x + __ieee754_sqrt( t - one ) ) );
        }
        else
        {
            // 1<x<2
            t = x - one;
            return log1p( t + __ieee754_sqrt( 2.0 * t + t * t ) );
        }
    }
Пример #14
0
	double asinh(double x)
{
	double t,w;
	int32_t hx,ix;
	GET_HIGH_WORD(hx,x);
	ix = hx&0x7fffffff;
	if(ix>=0x7ff00000) return x+x;	/* x is inf or NaN */
	if(ix< 0x3e300000) {	/* |x|<2**-28 */
	    if(huge+x>one) return x;	/* return x inexact except 0 */
	}
	if(ix>0x41b00000) {	/* |x| > 2**28 */
	    w = __ieee754_log(fabs(x))+ln2;
	} else if (ix>0x40000000) {	/* 2**28 > |x| > 2.0 */
	    t = fabs(x);
	    w = __ieee754_log(2.0*t+one/(__ieee754_sqrt(x*x+one)+t));
	} else {		/* 2.0 > |x| > 2**-28 */
	    t = x*x;
	    w =log1p(fabs(x)+t/(one+__ieee754_sqrt(one+t)));
	}
	if(hx>0) return w; else return -w;
}
Пример #15
0
double
__ieee754_asin(double x)
{
  double t,w,p,q,c,r,s;
  int32_t hx,ix;

  t = 0;
  GET_HIGH_WORD(hx,x);
  ix = hx&0x7fffffff;
  if(ix>= 0x3ff00000) {   /* |x|>= 1 */
      u_int32_t lx;
      GET_LOW_WORD(lx,x);
      if(((ix-0x3ff00000)|lx)==0)
        /* asin(1)=+-pi/2 with inexact */
    return x*pio2_hi+x*pio2_lo;
      return (x-x)/(x-x);   /* asin(|x|>1) is NaN */
  } else if (ix<0x3fe00000) { /* |x|<0.5 */
      if(ix<0x3e400000) {   /* if |x| < 2**-27 */
    if(huge+x>one) return x;/* return x with inexact if x!=0*/
      } else
    t = x*x;
    p = t*(pS0+t*(pS1+t*(pS2+t*(pS3+t*(pS4+t*pS5)))));
    q = one+t*(qS1+t*(qS2+t*(qS3+t*qS4)));
    w = p/q;
    return x+x*w;
  }
  /* 1> |x|>= 0.5 */
  w = one-fabs(x);
  t = w*0.5;
  p = t*(pS0+t*(pS1+t*(pS2+t*(pS3+t*(pS4+t*pS5)))));
  q = one+t*(qS1+t*(qS2+t*(qS3+t*qS4)));
  s = __ieee754_sqrt(t);
  if(ix>=0x3FEF3333) {  /* if |x| > 0.975 */
      w = p/q;
      t = pio2_hi-(2.0*(s+s*w)-pio2_lo);
  } else {
      w  = s;
      SET_LOW_WORD(w,0);
      c  = (t-w*w)/(s+w);
      r  = p/q;
      p  = 2.0*s*r-(pio2_lo-2.0*c);
      q  = pio4_hi-2.0*w;
      t  = pio4_hi-(p-q);
  }
  if(hx>0) return t; else return -t;
}
Пример #16
0
EXPORT(sqInt) primitiveSqrt(void) {
    double rcvr;
    double result;

	rcvr = interpreterProxy->stackFloatValue(0);
	if (interpreterProxy->failed()) {
		return null;
	}
	if (rcvr < 0.0) {
		return interpreterProxy->primitiveFail();
	}
	result = __ieee754_sqrt(rcvr);
	if (isnan(result)) {
		return interpreterProxy->primitiveFail();
	}
	interpreterProxy->pop((interpreterProxy->methodArgumentCount()) + 1);
	interpreterProxy->pushFloat(result);
}
primitiveSqrt(void)
{
	// FloatMathPlugin>>#primitiveSqrt
    double rcvr;
    double result;

	rcvr = stackFloatValue(0);
	if (failed()) {
		return null;
	}
	if (rcvr < 0.0) {
return primitiveFail();
	}
	result = __ieee754_sqrt(rcvr);
	if (isnan(result)) {
		return primitiveFail();
	}
	pop((methodArgumentCount()) + 1);
	pushFloat(result);
}
Пример #18
0
double acosh(double x)
{
	double t;
	int32_t hx;
	u_int32_t lx;
	EXTRACT_WORDS(hx,lx,x);
	if(hx<0x3ff00000) {		/* x < 1 */
	    return (x-x)/(x-x);
	} else if(hx >=0x41b00000) {	/* x > 2**28 */
	    if(hx >=0x7ff00000) {	/* x is inf of NaN */
	        return x+x;
	    } else
		return __ieee754_log(x)+ln2;	/* acosh(huge)=log(2x) */
	} else if(((hx-0x3ff00000)|lx)==0) {
	    return 0.0;			/* acosh(1) = 0 */
	} else if (hx > 0x40000000) {	/* 2**28 > x > 2 */
	    t=x*x;
	    return __ieee754_log(2.0*x-one/(x+__ieee754_sqrt(t-one)));
	} else {			/* 1<x<2 */
	    t = x-one;
	    return log1p(t+sqrt(2.0*t+t*t));
	}
}
Пример #19
0
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 */
	  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;
}
Пример #20
0
// Special "jump island" routines, used to provide a bridge when
// a routine near one end of our oversized code segment has to call
// a routine near the other end.  The need for these rest stops has
// been minimized by trying to arrange our code segment for good
// locality of reference.
double jumpto__ieee754_sqrt(double x) {
	return __ieee754_sqrt(x);
}
Пример #21
0
Err mathlib_sqrt(UInt16 refnum, double x, double *result) {
#pragma unused(refnum)
	*result = __ieee754_sqrt(x);
	return mlErrNone;
}
Пример #22
0
double
__ieee754_j1 (double x)
{
  double z, s, c, ss, cc, r, u, v, y, r1, r2, s1, s2, s3, z2, z4;
  int32_t hx, ix;

  GET_HIGH_WORD (hx, x);
  ix = hx & 0x7fffffff;
  if (__glibc_unlikely (ix >= 0x7ff00000))
    return one / x;
  y = fabs (x);
  if (ix >= 0x40000000)         /* |x| >= 2.0 */
    {
      __sincos (y, &s, &c);
      ss = -s - c;
      cc = s - c;
      if (ix < 0x7fe00000)           /* make sure y+y not overflow */
	{
	  z = __cos (y + y);
	  if ((s * c) > zero)
	    cc = z / ss;
	  else
	    ss = z / cc;
	}
      /*
       * j1(x) = 1/sqrt(pi) * (P(1,x)*cc - Q(1,x)*ss) / sqrt(x)
       * y1(x) = 1/sqrt(pi) * (P(1,x)*ss + Q(1,x)*cc) / sqrt(x)
       */
      if (ix > 0x48000000)
	z = (invsqrtpi * cc) / __ieee754_sqrt (y);
      else
	{
	  u = pone (y); v = qone (y);
	  z = invsqrtpi * (u * cc - v * ss) / __ieee754_sqrt (y);
	}
      if (hx < 0)
	return -z;
      else
	return z;
    }
  if (__glibc_unlikely (ix < 0x3e400000))                  /* |x|<2**-27 */
    {
      if (huge + x > one)                 /* inexact if x!=0 necessary */
	{
	  double ret = 0.5 * x;
	  if (fabs (ret) < DBL_MIN)
	    {
	      double force_underflow = ret * ret;
	      math_force_eval (force_underflow);
	    }
	  return ret;
	}
    }
  z = x * x;
  r1 = z * R[0]; z2 = z * z;
  r2 = R[1] + z * R[2]; z4 = z2 * z2;
  r = r1 + z2 * r2 + z4 * R[3];
  r *= x;
  s1 = one + z * S[1];
  s2 = S[2] + z * S[3];
  s3 = S[4] + z * S[5];
  s = s1 + z2 * s2 + z4 * s3;
  return (x * 0.5 + r / s);
}
Пример #23
0
static double
gamma_positive (double x, int *exp2_adj)
{
  int local_signgam;
  if (x < 0.5)
    {
      *exp2_adj = 0;
      return __ieee754_exp (__ieee754_lgamma_r (x + 1, &local_signgam)) / x;
    }
  else if (x <= 1.5)
    {
      *exp2_adj = 0;
      return __ieee754_exp (__ieee754_lgamma_r (x, &local_signgam));
    }
  else if (x < 6.5)
    {
      /* Adjust into the range for using exp (lgamma).  */
      *exp2_adj = 0;
      double n = __ceil (x - 1.5);
      double x_adj = x - n;
      double eps;
      double prod = __gamma_product (x_adj, 0, n, &eps);
      return (__ieee754_exp (__ieee754_lgamma_r (x_adj, &local_signgam))
	      * prod * (1.0 + eps));
    }
  else
    {
      double eps = 0;
      double x_eps = 0;
      double x_adj = x;
      double prod = 1;
      if (x < 12.0)
	{
	  /* Adjust into the range for applying Stirling's
	     approximation.  */
	  double n = __ceil (12.0 - x);
#if FLT_EVAL_METHOD != 0
	  volatile
#endif
	  double x_tmp = x + n;
	  x_adj = x_tmp;
	  x_eps = (x - (x_adj - n));
	  prod = __gamma_product (x_adj - n, x_eps, n, &eps);
	}
      /* The result is now gamma (X_ADJ + X_EPS) / (PROD * (1 + EPS)).
	 Compute gamma (X_ADJ + X_EPS) using Stirling's approximation,
	 starting by computing pow (X_ADJ, X_ADJ) with a power of 2
	 factored out.  */
      double exp_adj = -eps;
      double x_adj_int = __round (x_adj);
      double x_adj_frac = x_adj - x_adj_int;
      int x_adj_log2;
      double x_adj_mant = __frexp (x_adj, &x_adj_log2);
      if (x_adj_mant < M_SQRT1_2)
	{
	  x_adj_log2--;
	  x_adj_mant *= 2.0;
	}
      *exp2_adj = x_adj_log2 * (int) x_adj_int;
      double ret = (__ieee754_pow (x_adj_mant, x_adj)
		    * __ieee754_exp2 (x_adj_log2 * x_adj_frac)
		    * __ieee754_exp (-x_adj)
		    * __ieee754_sqrt (2 * M_PI / x_adj)
		    / prod);
      exp_adj += x_eps * __ieee754_log (x);
      double bsum = gamma_coeff[NCOEFF - 1];
      double x_adj2 = x_adj * x_adj;
      for (size_t i = 1; i <= NCOEFF - 1; i++)
	bsum = bsum / x_adj2 + gamma_coeff[NCOEFF - 1 - i];
      exp_adj += bsum / x_adj;
      return ret + ret * __expm1 (exp_adj);
    }
}
Пример #24
0
double
__ieee754_y0(double x)
{
	double z, s,c,ss,cc,u,v,z2,z4,z6,u1,u2,u3,v1,v2;
	int32_t hx,ix,lx;

	EXTRACT_WORDS(hx,lx,x);
	ix = 0x7fffffff&hx;
    /* Y0(NaN) is NaN, y0(-inf) is Nan, y0(inf) is 0, y0(0) is -inf.  */
	if(ix>=0x7ff00000) return  one/(x+x*x);
	if((ix|lx)==0) return -HUGE_VAL+x; /* -inf and overflow exception.  */
	if(hx<0) return zero/(zero*x);
	if(ix >= 0x40000000) {  /* |x| >= 2.0 */
	/* y0(x) = sqrt(2/(pi*x))*(p0(x)*sin(x0)+q0(x)*cos(x0))
	 * where x0 = x-pi/4
	 *      Better formula:
	 *              cos(x0) = cos(x)cos(pi/4)+sin(x)sin(pi/4)
	 *                      =  1/sqrt(2) * (sin(x) + cos(x))
	 *              sin(x0) = sin(x)cos(3pi/4)-cos(x)sin(3pi/4)
	 *                      =  1/sqrt(2) * (sin(x) - cos(x))
	 * To avoid cancellation, use
	 *              sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x))
	 * to compute the worse one.
	 */
		__sincos (x, &s, &c);
		ss = s-c;
		cc = s+c;
	/*
	 * j0(x) = 1/sqrt(pi) * (P(0,x)*cc - Q(0,x)*ss) / sqrt(x)
	 * y0(x) = 1/sqrt(pi) * (P(0,x)*ss + Q(0,x)*cc) / sqrt(x)
	 */
		if(ix<0x7fe00000) {  /* make sure x+x not overflow */
		    z = -__cos(x+x);
		    if ((s*c)<zero) cc = z/ss;
		    else            ss = z/cc;
		}
		if(ix>0x48000000) z = (invsqrtpi*ss)/__ieee754_sqrt(x);
		else {
		    u = pzero(x); v = qzero(x);
		    z = invsqrtpi*(u*ss+v*cc)/__ieee754_sqrt(x);
		}
		return z;
	}
	if(ix<=0x3e400000) {	/* x < 2**-27 */
	    return(U[0] + tpi*__ieee754_log(x));
	}
	z = x*x;
#ifdef DO_NOT_USE_THIS
	u = u00+z*(u01+z*(u02+z*(u03+z*(u04+z*(u05+z*u06)))));
	v = one+z*(v01+z*(v02+z*(v03+z*v04)));
#else
	u1 = U[0]+z*U[1]; z2=z*z;
	u2 = U[2]+z*U[3]; z4=z2*z2;
	u3 = U[4]+z*U[5]; z6=z4*z2;
	u = u1 + z2*u2 + z4*u3 + z6*U[6];
	v1 = one+z*V[0];
	v2 = V[1]+z*V[2];
	v = v1 + z2*v2 + z4*V[3];
#endif
	return(u/v + tpi*(__ieee754_j0(x)*__ieee754_log(x)));
}
Пример #25
0
double attribute_hidden __ieee754_hypot(double x, double y)
{
    double a=x,b=y,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(ha > 0x5f300000) {	/* a>2**500 */
        if(ha >= 0x7ff00000) {	/* Inf or NaN */
            u_int32_t low;
            w = a+b;			/* for sNaN */
            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(hb < 0x20b00000) {	/* b < 2**-500 */
        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;
        } 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));
        return t1*w;
    } else return w;
}
Пример #26
0
double
__ieee754_y1 (double x)
{
  double z, s, c, ss, cc, u, v, u1, u2, v1, v2, v3, z2, z4;
  int32_t hx, ix, lx;

  EXTRACT_WORDS (hx, lx, x);
  ix = 0x7fffffff & hx;
  /* if Y1(NaN) is NaN, Y1(-inf) is NaN, Y1(inf) is 0 */
  if (__glibc_unlikely (ix >= 0x7ff00000))
    return one / (x + x * x);
  if (__glibc_unlikely ((ix | lx) == 0))
    return -1 / zero; /* -inf and divide by zero exception.  */
  /* -inf and overflow exception.  */;
  if (__glibc_unlikely (hx < 0))
    return zero / (zero * x);
  if (ix >= 0x40000000)         /* |x| >= 2.0 */
    {
      __sincos (x, &s, &c);
      ss = -s - c;
      cc = s - c;
      if (ix < 0x7fe00000)           /* make sure x+x not overflow */
	{
	  z = __cos (x + x);
	  if ((s * c) > zero)
	    cc = z / ss;
	  else
	    ss = z / cc;
	}
      /* y1(x) = sqrt(2/(pi*x))*(p1(x)*sin(x0)+q1(x)*cos(x0))
       * where x0 = x-3pi/4
       *      Better formula:
       *              cos(x0) = cos(x)cos(3pi/4)+sin(x)sin(3pi/4)
       *                      =  1/sqrt(2) * (sin(x) - cos(x))
       *              sin(x0) = sin(x)cos(3pi/4)-cos(x)sin(3pi/4)
       *                      = -1/sqrt(2) * (cos(x) + sin(x))
       * To avoid cancellation, use
       *              sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x))
       * to compute the worse one.
       */
      if (ix > 0x48000000)
	z = (invsqrtpi * ss) / __ieee754_sqrt (x);
      else
	{
	  u = pone (x); v = qone (x);
	  z = invsqrtpi * (u * ss + v * cc) / __ieee754_sqrt (x);
	}
      return z;
    }
  if (__glibc_unlikely (ix <= 0x3c900000))              /* x < 2**-54 */
    {
      z = -tpi / x;
      if (isinf (z))
	__set_errno (ERANGE);
      return z;
    }
  z = x * x;
  u1 = U0[0] + z * U0[1]; z2 = z * z;
  u2 = U0[2] + z * U0[3]; z4 = z2 * z2;
  u = u1 + z2 * u2 + z4 * U0[4];
  v1 = one + z * V0[0];
  v2 = V0[1] + z * V0[2];
  v3 = V0[3] + z * V0[4];
  v = v1 + z2 * v2 + z4 * v3;
  return (x * (u / v) + tpi * (__ieee754_j1 (x) * __ieee754_log (x) - one / x));
}
Пример #27
0
    //------------------------------------------------------------------------------
    double Cmath::__ieee754_hypot( double x, double y )
    {
        double a = x, b = y, t1, t2, y1, y2, w;
        Cmp_signed__int32 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( ha > 0x5f300000 )
        {
            // a>2**500
            if( ha >= 0x7ff00000 )
            {
                // Inf or NaN
                Cmp_unsigned__int32 low;
                w = a + b; // for sNaN
                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( hb < 0x20b00000 )
        {
            // b < 2**-500
            if( hb <= 0x000fffff )
            {
                // subnormal b or 0
                Cmp_unsigned__int32 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;
            }
            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 )
        {
            Cmp_unsigned__int32 high;
            t1 = 1.0;
            get_high_word( high, t1 );
            set_high_word( t1, high + ( k << 20 ) );
            return t1 * w;
        }
        else
        {
            return w;
        }
    }
Пример #28
0
__complex__ double
__kernel_casinh (__complex__ double x, int adj)
{
  __complex__ double res;
  double rx, ix;
  __complex__ double y;

  /* Avoid cancellation by reducing to the first quadrant.  */
  rx = fabs (__real__ x);
  ix = fabs (__imag__ x);

  if (rx >= 1.0 / DBL_EPSILON || ix >= 1.0 / DBL_EPSILON)
    {
      /* For large x in the first quadrant, x + csqrt (1 + x * x)
	 is sufficiently close to 2 * x to make no significant
	 difference to the result; avoid possible overflow from
	 the squaring and addition.  */
      __real__ y = rx;
      __imag__ y = ix;

      if (adj)
	{
	  double t = __real__ y;
	  __real__ y = __copysign (__imag__ y, __imag__ x);
	  __imag__ y = t;
	}

      res = __clog (y);
      __real__ res += M_LN2;
    }
  else if (rx >= 0.5 && ix < DBL_EPSILON / 8.0)
    {
      double s = __ieee754_hypot (1.0, rx);

      __real__ res = __ieee754_log (rx + s);
      if (adj)
	__imag__ res = __ieee754_atan2 (s, __imag__ x);
      else
	__imag__ res = __ieee754_atan2 (ix, s);
    }
  else if (rx < DBL_EPSILON / 8.0 && ix >= 1.5)
    {
      double s = __ieee754_sqrt ((ix + 1.0) * (ix - 1.0));

      __real__ res = __ieee754_log (ix + s);
      if (adj)
	__imag__ res = __ieee754_atan2 (rx, __copysign (s, __imag__ x));
      else
	__imag__ res = __ieee754_atan2 (s, rx);
    }
  else if (ix > 1.0 && ix < 1.5 && rx < 0.5)
    {
      if (rx < DBL_EPSILON * DBL_EPSILON)
	{
	  double ix2m1 = (ix + 1.0) * (ix - 1.0);
	  double s = __ieee754_sqrt (ix2m1);

	  __real__ res = __log1p (2.0 * (ix2m1 + ix * s)) / 2.0;
	  if (adj)
	    __imag__ res = __ieee754_atan2 (rx, __copysign (s, __imag__ x));
	  else
	    __imag__ res = __ieee754_atan2 (s, rx);
	}
      else
	{
	  double ix2m1 = (ix + 1.0) * (ix - 1.0);
	  double rx2 = rx * rx;
	  double f = rx2 * (2.0 + rx2 + 2.0 * ix * ix);
	  double d = __ieee754_sqrt (ix2m1 * ix2m1 + f);
	  double dp = d + ix2m1;
	  double dm = f / dp;
	  double r1 = __ieee754_sqrt ((dm + rx2) / 2.0);
	  double r2 = rx * ix / r1;

	  __real__ res = __log1p (rx2 + dp + 2.0 * (rx * r1 + ix * r2)) / 2.0;
	  if (adj)
	    __imag__ res = __ieee754_atan2 (rx + r1, __copysign (ix + r2,
								 __imag__ x));
	  else
	    __imag__ res = __ieee754_atan2 (ix + r2, rx + r1);
	}
    }
  else if (ix == 1.0 && rx < 0.5)
    {
      if (rx < DBL_EPSILON / 8.0)
	{
	  __real__ res = __log1p (2.0 * (rx + __ieee754_sqrt (rx))) / 2.0;
	  if (adj)
	    __imag__ res = __ieee754_atan2 (__ieee754_sqrt (rx),
					    __copysign (1.0, __imag__ x));
	  else
	    __imag__ res = __ieee754_atan2 (1.0, __ieee754_sqrt (rx));
	}
      else
	{
	  double d = rx * __ieee754_sqrt (4.0 + rx * rx);
	  double s1 = __ieee754_sqrt ((d + rx * rx) / 2.0);
	  double s2 = __ieee754_sqrt ((d - rx * rx) / 2.0);

	  __real__ res = __log1p (rx * rx + d + 2.0 * (rx * s1 + s2)) / 2.0;
	  if (adj)
	    __imag__ res = __ieee754_atan2 (rx + s1, __copysign (1.0 + s2,
								 __imag__ x));
	  else
	    __imag__ res = __ieee754_atan2 (1.0 + s2, rx + s1);
	}
    }
  else if (ix < 1.0 && rx < 0.5)
    {
      if (ix >= DBL_EPSILON)
	{
	  if (rx < DBL_EPSILON * DBL_EPSILON)
	    {
	      double onemix2 = (1.0 + ix) * (1.0 - ix);
	      double s = __ieee754_sqrt (onemix2);

	      __real__ res = __log1p (2.0 * rx / s) / 2.0;
	      if (adj)
		__imag__ res = __ieee754_atan2 (s, __imag__ x);
	      else
		__imag__ res = __ieee754_atan2 (ix, s);
	    }
	  else
	    {
	      double onemix2 = (1.0 + ix) * (1.0 - ix);
	      double rx2 = rx * rx;
	      double f = rx2 * (2.0 + rx2 + 2.0 * ix * ix);
	      double d = __ieee754_sqrt (onemix2 * onemix2 + f);
	      double dp = d + onemix2;
	      double dm = f / dp;
	      double r1 = __ieee754_sqrt ((dp + rx2) / 2.0);
	      double r2 = rx * ix / r1;

	      __real__ res
		= __log1p (rx2 + dm + 2.0 * (rx * r1 + ix * r2)) / 2.0;
	      if (adj)
		__imag__ res = __ieee754_atan2 (rx + r1,
						__copysign (ix + r2,
							    __imag__ x));
	      else
		__imag__ res = __ieee754_atan2 (ix + r2, rx + r1);
	    }
	}
      else
	{
	  double s = __ieee754_hypot (1.0, rx);

	  __real__ res = __log1p (2.0 * rx * (rx + s)) / 2.0;
	  if (adj)
	    __imag__ res = __ieee754_atan2 (s, __imag__ x);
	  else
	    __imag__ res = __ieee754_atan2 (ix, s);
	}
      math_check_force_underflow_nonneg (__real__ res);
    }
  else
    {
      __real__ y = (rx - ix) * (rx + ix) + 1.0;
      __imag__ y = 2.0 * rx * ix;

      y = __csqrt (y);

      __real__ y += rx;
      __imag__ y += ix;

      if (adj)
	{
	  double t = __real__ y;
	  __real__ y = __copysign (__imag__ y, __imag__ x);
	  __imag__ y = t;
	}

      res = __clog (y);
    }

  /* Give results the correct sign for the original argument.  */
  __real__ res = __copysign (__real__ res, __real__ x);
  __imag__ res = __copysign (__imag__ res, (adj ? 1.0 : __imag__ x));

  return res;
}
Пример #29
0
double sqrt(double x) { return __ieee754_sqrt(x); }
Пример #30
0
__complex__ double
__csqrt (__complex__ double x)
{
  __complex__ double res;
  int rcls = fpclassify (__real__ x);
  int icls = fpclassify (__imag__ x);

  if (__builtin_expect (rcls <= FP_INFINITE || icls <= FP_INFINITE, 0))
    {
      if (icls == FP_INFINITE)
	{
	  __real__ res = HUGE_VAL;
	  __imag__ res = __imag__ x;
	}
      else if (rcls == FP_INFINITE)
	{
	  if (__real__ x < 0.0)
	    {
	      __real__ res = icls == FP_NAN ? __nan ("") : 0;
	      __imag__ res = __copysign (HUGE_VAL, __imag__ x);
	    }
	  else
	    {
	      __real__ res = __real__ x;
	      __imag__ res = (icls == FP_NAN
			      ? __nan ("") : __copysign (0.0, __imag__ x));
	    }
	}
      else
	{
	  __real__ res = __nan ("");
	  __imag__ res = __nan ("");
	}
    }
  else
    {
      if (__builtin_expect (icls == FP_ZERO, 0))
	{
	  if (__real__ x < 0.0)
	    {
	      __real__ res = 0.0;
	      __imag__ res = __copysign (__ieee754_sqrt (-__real__ x),
					 __imag__ x);
	    }
	  else
	    {
	      __real__ res = fabs (__ieee754_sqrt (__real__ x));
	      __imag__ res = __copysign (0.0, __imag__ x);
	    }
	}
      else if (__builtin_expect (rcls == FP_ZERO, 0))
	{
	  double r;
	  if (fabs (__imag__ x) >= 2.0 * DBL_MIN)
	    r = __ieee754_sqrt (0.5 * fabs (__imag__ x));
	  else
	    r = 0.5 * __ieee754_sqrt (2.0 * fabs (__imag__ x));

	  __real__ res = r;
	  __imag__ res = __copysign (r, __imag__ x);
	}
      else
	{
	  double d, r, s;
	  int scale = 0;

	  if (fabs (__real__ x) > DBL_MAX / 4.0)
	    {
	      scale = 1;
	      __real__ x = __scalbn (__real__ x, -2 * scale);
	      __imag__ x = __scalbn (__imag__ x, -2 * scale);
	    }
	  else if (fabs (__imag__ x) > DBL_MAX / 4.0)
	    {
	      scale = 1;
	      if (fabs (__real__ x) >= 4.0 * DBL_MIN)
		__real__ x = __scalbn (__real__ x, -2 * scale);
	      else
		__real__ x = 0.0;
	      __imag__ x = __scalbn (__imag__ x, -2 * scale);
	    }
	  else if (fabs (__real__ x) < DBL_MIN
		   && fabs (__imag__ x) < DBL_MIN)
	    {
	      scale = -(DBL_MANT_DIG / 2);
	      __real__ x = __scalbn (__real__ x, -2 * scale);
	      __imag__ x = __scalbn (__imag__ x, -2 * scale);
	    }

	  d = __ieee754_hypot (__real__ x, __imag__ x);
	  /* Use the identity   2  Re res  Im res = Im x
	     to avoid cancellation error in  d +/- Re x.  */
	  if (__real__ x > 0)
	    {
	      r = __ieee754_sqrt (0.5 * (d + __real__ x));
	      s = 0.5 * (__imag__ x / r);
	    }
	  else
	    {
	      s = __ieee754_sqrt (0.5 * (d - __real__ x));
	      r = fabs (0.5 * (__imag__ x / s));
	    }

	  if (scale)
	    {
	      r = __scalbn (r, scale);
	      s = __scalbn (s, scale);
	    }

	  __real__ res = r;
	  __imag__ res = __copysign (s, __imag__ x);
	}
    }

  return res;
}