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); }
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); }
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)); }
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); }
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)); } }
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); }
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 }
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); }
float __ieee754_hypotf (float x, float y) { TEST_INF_NAN (x, y); return __ieee754_sqrt ((double) x * x + (double) y * y); }
/* 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); }
void Math_sqrt(void *fp) { F_Math_sqrt *f; f = fp; *f->ret = __ieee754_sqrt(f->x); }
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); } }
//------------------------------------------------------------------------------ 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 ) ); } }
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; }
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; }
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); }
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)); } }
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; }
// 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); }
Err mathlib_sqrt(UInt16 refnum, double x, double *result) { #pragma unused(refnum) *result = __ieee754_sqrt(x); return mlErrNone; }
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); }
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); } }
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))); }
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; }
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)); }
//------------------------------------------------------------------------------ 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; } }
__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; }
double sqrt(double x) { return __ieee754_sqrt(x); }
__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; }