double sinh(double x) { double t, h; int32_t ix, jx; /* High word of |x|. */ GET_HIGH_WORD(jx, x); ix = jx & 0x7fffffff; /* x is INF or NaN */ if (ix >= 0x7ff00000) return x + x; h = 0.5; if (jx < 0) h = -h; /* |x| in [0,22], return sign(x)*0.5*(E+E/(E+1))) */ if (ix < 0x40360000) { /* |x|<22 */ if (ix < 0x3e300000) /* |x|<2**-28 */ /* raise inexact, return x */ if (huge+x > 1.0) return x; t = expm1(fabs(x)); if (ix < 0x3ff00000) return h*(2.0*t - t*t/(t+1.0)); return h*(t + t/(t+1.0)); } /* |x| in [22, log(maxdouble)] return 0.5*exp(|x|) */ if (ix < 0x40862E42) return h*exp(fabs(x)); /* |x| in [log(maxdouble), overflowthresold] */ if (ix <= 0x408633CE) return h * 2.0 * __expo2(fabs(x)); /* h is for sign only */ /* |x| > overflowthresold, sinh(x) overflow */ return x*huge; }
double sinh(double x) { double t,w,h; int32_t ix,jx; u_int32_t lx; /* High word of |x|. */ GET_HIGH_WORD(jx,x); ix = jx&0x7fffffff; /* x is INF or NaN */ if(ix>=0x7ff00000) return x+x; h = 0.5; if (jx<0) h = -h; /* |x| in [0,22], return sign(x)*0.5*(E+E/(E+1))) */ if (ix < 0x40360000) { /* |x|<22 */ if (ix<0x3e300000) /* |x|<2**-28 */ if(shuge+x>one) return x;/* sinh(tiny) = tiny with inexact */ t = expm1(fabs(x)); if(ix<0x3ff00000) return h*(2.0*t-t*t/(t+one)); return h*(t+t/(t+one)); } /* |x| in [22, log(maxdouble)] return 0.5*exp(|x|) */ if (ix < 0x40862E42) return h*__ieee754_exp(fabs(x)); /* |x| in [log(maxdouble), overflowthresold] */ GET_LOW_WORD(lx,x); if (ix<0x408633CE || ((ix==0x408633ce)&&(lx<=(u_int32_t)0x8fb9f87d))) { w = __ieee754_exp(0.5*fabs(x)); t = h*w; return t*w; } /* |x| > overflowthresold, sinh(x) overflow */ return x*shuge; }
double cosh(double x) { double t, w; int32_t ix; GET_HIGH_WORD(ix, x); ix &= 0x7fffffff; /* x is INF or NaN */ if (ix >= 0x7ff00000) return x*x; /* |x| in [0,0.5*ln2], return 1+expm1(|x|)^2/(2*exp(|x|)) */ if (ix < 0x3fd62e43) { t = expm1(fabs(x)); w = 1.0+t; if (ix < 0x3c800000) return w; /* cosh(tiny) = 1 */ return 1.0 + (t*t)/(w+w); } /* |x| in [0.5*ln2,22], return (exp(|x|)+1/exp(|x|))/2; */ if (ix < 0x40360000) { t = exp(fabs(x)); return 0.5*t + 0.5/t; } /* |x| in [22, log(maxdouble)] return 0.5*exp(|x|) */ if (ix < 0x40862E42) return 0.5*exp(fabs(x)); /* |x| in [log(maxdouble), overflowthresold] */ if (ix <= 0x408633CE) return __expo2(fabs(x)); /* |x| > overflowthresold, cosh(x) overflow */ return huge*huge; }
double tan(double x) { double y[2],z=0.0; int32_t n, ix; /* High word of x. */ GET_HIGH_WORD(ix,x); /* |x| ~< pi/4 */ ix &= 0x7fffffff; if(ix <= 0x3fe921fb) return __kernel_tan(x,z,1); /* tan(Inf or NaN) is NaN */ else if (ix>=0x7ff00000) return x-x; /* NaN */ /* argument reduction needed */ else { n = __libm_rem_pio2(x,y); return __kernel_tan(y[0],y[1],1-((n&1)<<1)); /* 1 -- n even -1 -- n odd */ } }
double __ieee754_cosh(double x) { double t,w; int32_t ix; /* High word of |x|. */ GET_HIGH_WORD(ix,x); ix &= 0x7fffffff; /* x is INF or NaN */ if(ix>=0x7ff00000) return x*x; /* |x| in [0,0.5*ln2], return 1+expm1(|x|)^2/(2*exp(|x|)) */ if(ix<0x3fd62e43) { t = expm1(fabs(x)); w = one+t; if (ix<0x3c800000) return w; /* cosh(tiny) = 1 */ return one+(t*t)/(w+w); } /* |x| in [0.5*ln2,22], return (exp(|x|)+1/exp(|x|)/2; */ if (ix < 0x40360000) { t = __ieee754_exp(fabs(x)); return half*t+half/t; } /* |x| in [22, log(maxdouble)] return half*exp(|x|) */ if (ix < 0x40862E42) return half*__ieee754_exp(fabs(x)); /* |x| in [log(maxdouble), overflowthresold] */ if (ix<=0x408633CE) return __ldexp_exp(fabs(x), -1); /* |x| > overflowthresold, cosh(x) overflow */ return huge*huge; }
double tanh(double x) { double t, z; s32_t jx, ix; GET_HIGH_WORD(jx,x); ix = jx & 0x7fffffff; if (ix >= 0x7ff00000) { if (jx >= 0) return one / x + one; else return one / x - one; } if (ix < 0x40360000) { if (ix < 0x3c800000) return x * (one + x); if (ix >= 0x3ff00000) { t = expm1(two * fabs(x)); z = one - two / (t + two); } else { t = expm1(-two * fabs(x)); z = -t / (t + two); } } else { z = one - tiny; } return (jx >= 0) ? z : -z; }
/* * exp2(x): compute the base 2 exponential of x * * Accuracy: Peak error < 0.503 ulp for normalized results. * * Method: (accurate tables) * * Reduce x: * x = 2**k + y, for integer k and |y| <= 1/2. * Thus we have exp2(x) = 2**k * exp2(y). * * Reduce y: * y = i/TBLSIZE + z - eps[i] for integer i near y * TBLSIZE. * Thus we have exp2(y) = exp2(i/TBLSIZE) * exp2(z - eps[i]), * with |z - eps[i]| <= 2**-9 + 2**-39 for the table used. * * We compute exp2(i/TBLSIZE) via table lookup and exp2(z - eps[i]) via * a degree-5 minimax polynomial with maximum error under 1.3 * 2**-61. * The values in exp2t[] and eps[] are chosen such that * exp2t[i] = exp2(i/TBLSIZE + eps[i]), and eps[i] is a small offset such * that exp2t[i] is accurate to 2**-64. * * Note that the range of i is +-TBLSIZE/2, so we actually index the tables * by i0 = i + TBLSIZE/2. For cache efficiency, exp2t[] and eps[] are * virtual tables, interleaved in the real table tbl[]. * * This method is due to Gal, with many details due to Gal and Bachelis: * * Gal, S. and Bachelis, B. An Accurate Elementary Mathematical Library * for the IEEE Floating Point Standard. TOMS 17(1), 26-46 (1991). */ double exp2(double x) { double r, t, z; uint32_t hx, ix, i0; union {uint32_t u; int32_t i;} k; /* Filter out exceptional cases. */ GET_HIGH_WORD(hx, x); ix = hx & 0x7fffffff; if (ix >= 0x40900000) { /* |x| >= 1024 */ if (ix >= 0x7ff00000) { GET_LOW_WORD(ix, x); if (hx == 0xfff00000 && ix == 0) /* -inf */ return 0; return x; } if (x >= 1024) { STRICT_ASSIGN(double, x, x * 0x1p1023); return x; } if (x <= -1075) { STRICT_ASSIGN(double, x, 0x1p-1000*0x1p-1000); return x; }
double __asinh(double x) { double w; int32_t hx,ix; GET_HIGH_WORD(hx,x); ix = hx&0x7fffffff; if(__builtin_expect(ix< 0x3e300000, 0)) { /* |x|<2**-28 */ if(huge+x>one) return x; /* return x inexact except 0 */ } if(__builtin_expect(ix>0x41b00000, 0)) { /* |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 attribute_hidden __kernel_cos(double x, double y) { double a,hz,z,r,qx; int32_t ix; GET_HIGH_WORD(ix,x); ix &= 0x7fffffff; /* ix = |x|'s high word*/ if(ix<0x3e400000) { /* if x < 2**27 */ if(((int)x)==0) return one; /* generate inexact */ } z = x*x; r = z*(C1+z*(C2+z*(C3+z*(C4+z*(C5+z*C6))))); if(ix < 0x3FD33333) /* if |x| < 0.3 */ return one - (0.5*z - (z*r - x*y)); else { if(ix > 0x3fe90000) { /* x > 0.78125 */ qx = 0.28125; } else { INSERT_WORDS(qx,ix-0x00200000,0); /* x/4 */ } hz = 0.5*z-qx; a = one-qx; return a - (hz - (z*r-x*y)); } }
int __issignaling (double x) { #ifdef HIGH_ORDER_BIT_IS_SET_FOR_SNAN u_int32_t hxi; GET_HIGH_WORD (hxi, x); /* We only have to care about the high-order bit of x's significand, because having it set (sNaN) already makes the significand different from that used to designate infinity. */ return (hxi & 0x7ff80000) == 0x7ff80000; #else u_int32_t hxi, lxi; EXTRACT_WORDS (hxi, lxi, x); /* To keep the following comparison simple, toggle the quiet/signaling bit, so that it is set for sNaNs. This is inverse to IEEE 754-2008 (as well as common practice for IEEE 754-1985). */ hxi ^= 0x00080000; /* If lxi != 0, then set any suitable bit of the significand in hxi. */ hxi |= (lxi | -lxi) >> 31; /* We have to compare for greater (instead of greater or equal), because x's significand being all-zero designates infinity not NaN. */ return (hxi & 0x7fffffff) > 0x7ff80000; #endif }
double __kernel_tan(double x, double y, int iy) { double z,r,v,w,s; int32_t ix,hx; GET_HIGH_WORD(hx,x); ix = hx&0x7fffffff; /* high word of |x| */ if(ix<0x3e300000) /* x < 2**-28 */ {if((int)x==0) { /* generate inexact */ u_int32_t low; GET_LOW_WORD(low,x); if(((ix|low)|(iy+1))==0) return one/fabs(x); else return (iy==1)? x: -one/x; } } if(ix>=0x3FE59428) { /* |x|>=0.6744 */ if(hx<0) {x = -x; y = -y;} z = pio4-x; w = pio4lo-y; x = z+w; y = 0.0; } z = x*x; w = z*z; /* Break x^5*(T[1]+x^2*T[2]+...) into * x^5(T[1]+x^4*T[3]+...+x^20*T[11]) + * x^5(x^2*(T[2]+x^4*T[4]+...+x^22*[T12])) */ r = T[1]+w*(T[3]+w*(T[5]+w*(T[7]+w*(T[9]+w*T[11])))); v = z*(T[2]+w*(T[4]+w*(T[6]+w*(T[8]+w*(T[10]+w*T[12]))))); s = z*x; r = y + z*(s*(r+v)+y); r += T[0]*s; w = x+r; if(ix>=0x3FE59428) { v = (double)iy; return (double)(1-((hx>>30)&2))*(v-2.0*(x-(w*w/(w+v)-r))); }
long double hypotl(long double x, long double y) { long double a=x,b=y,t1,t2,y1,y2,w; int32_t j,k,ha,hb; GET_HIGH_WORD(ha,x); ha &= 0x7fff; GET_HIGH_WORD(hb,y); hb &= 0x7fff; if(hb > ha) {a=y;b=x;j=ha; ha=hb;hb=j;} else {a=x;b=y;} a = fabsl(a); b = fabsl(b); if((ha-hb)>DESW(MANT_DIG+7)) {return a+b;} /* x/y > 2**(MANT_DIG+7) */ k=0; if(ha > ESW(MAX_EXP/2-12)) { /* a>2**(MAX_EXP/2-12) */ if(ha >= ESW(MAX_EXP)) { /* Inf or NaN */ man_t manh, manl; /* Use original arg order iff result is NaN; quieten sNaNs. */ w = fabsl(x+0.0)-fabsl(y+0.0); GET_LDBL_MAN(manh,manl,a); if (manh == LDBL_NBIT && manl == 0) w = a; GET_LDBL_MAN(manh,manl,b); if (hb >= ESW(MAX_EXP) && manh == LDBL_NBIT && manl == 0) w = b; return w; } /* scale a and b by 2**-(MAX_EXP/2+88) */ ha -= DESW(MAX_EXP/2+88); hb -= DESW(MAX_EXP/2+88); k += MAX_EXP/2+88; SET_HIGH_WORD(a,ha); SET_HIGH_WORD(b,hb); } if(hb < ESW(-(MAX_EXP/2-12))) { /* b < 2**-(MAX_EXP/2-12) */ if(hb <= 0) { /* subnormal b or 0 */ man_t manh, manl; GET_LDBL_MAN(manh,manl,b); if((manh|manl)==0) return a; t1=0; SET_HIGH_WORD(t1,ESW(MAX_EXP-2)); /* t1=2^(MAX_EXP-2) */ b *= t1; a *= t1; k -= MAX_EXP-2; } else { /* scale a and b by 2^(MAX_EXP/2+88) */ ha += DESW(MAX_EXP/2+88); hb += DESW(MAX_EXP/2+88); k -= MAX_EXP/2+88; SET_HIGH_WORD(a,ha); SET_HIGH_WORD(b,hb); } } /* medium size a and b */ w = a-b; if (w>b) { t1 = a; union IEEEl2bits uv; uv.e = t1; uv.bits.manl = 0; t1 = uv.e; t2 = a-t1; w = sqrtl(t1*t1-(b*(-b)-t2*(a+t1))); } else { a = a+a; y1 = b; union IEEEl2bits uv; uv.e = y1; uv.bits.manl = 0; y1 = uv.e; y2 = b - y1; t1 = a; uv.e = t1; uv.bits.manl = 0; t1 = uv.e; t2 = a - t1; w = sqrtl(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+DESW(k)); return t1*w; } else return w; }
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; }
double log2(double x) { double f,hfsq,hi,lo,r,val_hi,val_lo,w,y; int32_t i,k,hx; uint32_t lx; EXTRACT_WORDS(hx, lx, x); k = 0; if (hx < 0x00100000) { /* x < 2**-1022 */ if (((hx&0x7fffffff)|lx) == 0) return -two54/0.0; /* log(+-0)=-inf */ if (hx < 0) return (x-x)/0.0; /* log(-#) = NaN */ /* subnormal number, scale up x */ k -= 54; x *= two54; GET_HIGH_WORD(hx, x); } if (hx >= 0x7ff00000) return x+x; if (hx == 0x3ff00000 && lx == 0) return 0.0; /* 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 = __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; }
double pow (double x, double y) { double d, k, t, r = 1.0; int n, sign, exponent_is_even_int = 0; __uint32_t px; GET_HIGH_WORD (px, x); k = modf (y, &d); if (k == 0.0) { /* Exponent y is an integer. */ if (modf (ldexp (y, -1), &t)) { /* y is odd. */ exponent_is_even_int = 0; } else { /* y is even. */ exponent_is_even_int = 1; } } if (x == 0.0 && y <= 0.0) { errno = EDOM; } else if ((t = y * log (fabs (x))) >= BIGX) { errno = ERANGE; if (px & 0x80000000) { /* x is negative. */ if (k) { /* y is not an integer. */ errno = EDOM; x = 0.0; } else if (exponent_is_even_int) x = z_infinity.d; else x = -z_infinity.d; } else { x = z_infinity.d; } } else if (t < SMALLX) { errno = ERANGE; x = 0.0; } else { if ( !k && fabs(d) <= 32767 ) { n = (int) d; if ((sign = (n < 0))) n = -n; while ( n > 0 ) { if ((unsigned int) n % 2) r *= x; x *= x; n = (unsigned int) n / 2; } if (sign) r = 1.0 / r; return r; } else { if ( px & 0x80000000 ) { /* x is negative. */ if ( k ) { /* y is not an integer. */ errno = EDOM; return 0.0; } } x = exp (t); if (!exponent_is_even_int) { if (px & 0x80000000) { /* y is an odd integer, and x is negative, so the result is negative. */ GET_HIGH_WORD (px, x); px |= 0x80000000; SET_HIGH_WORD (x, px); } } } } return x; }
int __finite(double x) { int32_t hx; GET_HIGH_WORD(hx,x); return (int)((u_int32_t)((hx&0x7fffffff)-0x7ff00000)>>31); }
double pow (double x, double y) { double d, t, r = 1.0; int n, k, sign = 0; __uint32_t px; GET_HIGH_WORD (px, x); k = modf (y, &d); if (k == 0.0) { if (modf (ldexp (y, -1), &t)) sign = 0; else sign = 1; } if (x == 0.0 && y <= 0.0) errno = EDOM; else if ((t = y * log (fabs (x))) >= BIGX) { errno = ERANGE; if (px & 0x80000000) { if (!k) { errno = EDOM; x = 0.0; } else if (sign) x = -z_infinity.d; else x = z_infinity.d; } else x = z_infinity.d; } else if (t < SMALLX) { errno = ERANGE; x = 0.0; } else { if ( k && fabs(d) <= 32767 ) { n = (int) d; if (sign = (n < 0)) n = -n; while ( n > 0 ) { if ((unsigned int) n % 2) r *= x; x *= x; n = (unsigned int) n / 2; } if (sign) r = 1.0 / r; return r; } else { if ( px & 0x80000000 ) { if ( !k ) { errno = EDOM; return 0.0; } } x = exp (t); /* // The usage of sign over here is incorrect. if ( sign ) { px ^= 0x80000000; SET_HIGH_WORD (x, px); } */ } } return x; }
double expm1(double x) { double y, hi, lo, c=0, t, e, hxs, hfx, r1; s32_t k, xsb; u32_t hx; GET_HIGH_WORD(hx,x); xsb = hx & 0x80000000; if (xsb == 0) y = x; else y = -x; hx &= 0x7fffffff; if (hx >= 0x4043687A) { if (hx >= 0x40862E42) { if (hx >= 0x7ff00000) { u32_t low; GET_LOW_WORD(low,x); if (((hx & 0xfffff) | low) != 0) return x + x; else return (xsb == 0) ? x : -1.0; } if (x > o_threshold) return huge * huge; } if (xsb != 0) { if (x + tiny < 0.0) return tiny - one; } } if (hx > 0x3fd62e42) { if (hx < 0x3FF0A2B2) { if (xsb == 0) { hi = x - ln2_hi; lo = ln2_lo; k = 1; } else { hi = x + ln2_hi; lo = -ln2_lo; k = -1; } } else { k = invln2 * x + ((xsb == 0) ? 0.5 : -0.5); t = k; hi = x - t * ln2_hi; lo = t * ln2_lo; } x = hi - lo; c = (hi - x) - lo; } else if (hx < 0x3c900000) { t = huge + x; return x - (t - (huge + x)); } else k = 0; hfx = 0.5 * x; hxs = x * hfx; r1 = one + hxs * (Q1 + hxs * (Q2 + hxs * (Q3 + hxs * (Q4 + hxs * Q5)))); t = 3.0 - r1 * hfx; e = hxs * ((r1 - t) / (6.0 - x * t)); if (k == 0) return x - (x * e - hxs); else { e = (x * (e - c) - c); e -= hxs; if (k == -1) return 0.5 * (x - e) - 0.5; if (k == 1) { if (x < -0.25) return -2.0 * (e - (x + 0.5)); else return one + 2.0 * (x - e); } if (k <= -2 || k > 56) { u32_t high; y = one - (e - x); GET_HIGH_WORD(high,y); SET_HIGH_WORD(y,high+(k<<20)); return y - one; } t = one; if (k < 20) { u32_t high; SET_HIGH_WORD(t,0x3ff00000 - (0x200000>>k)); y = t - (e - x); GET_HIGH_WORD(high,y); SET_HIGH_WORD(y,high+(k<<20)); } else {
double __ieee754_log(double x) { double hfsq,f,s,z,R,w,t1,t2,dk; int32_t k,hx,i,j; uint32_t lx; EXTRACT_WORDS(hx,lx,x); k=0; if (hx < 0x00100000) { /* x < 2**-1022 */ if (((hx&0x7fffffff)|lx)==0) return -two54/zero; /* 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; 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); f = x-1.0; if((0x000fffff&(2+hx))<3) { /* |f| < 2**-20 */ if(f==zero) { if(k==0) return zero; else { dk=(double)k; return dk*ln2_hi+dk*ln2_lo; } } R = f*f*(0.5-0.33333333333333333*f); if(k==0) return f-R; else { dk=(double)k; return dk*ln2_hi-((R-dk*ln2_lo)-f); } } s = f/(2.0+f); dk = (double)k; z = s*s; i = hx-0x6147a; w = z*z; j = 0x6b851-hx; t1= w*(Lg2+w*(Lg4+w*Lg6)); t2= z*(Lg1+w*(Lg3+w*(Lg5+w*Lg7))); i |= j; R = t2+t1; if(i>0) { hfsq=0.5*f*f; if(k==0) return f-(hfsq-s*(hfsq+R)); else return dk*ln2_hi-((hfsq-(s*(hfsq+R)+dk*ln2_lo))-f); } else { if(k==0) return f-s*(f-R); else return dk*ln2_hi-((s*(f-R)-dk*ln2_lo)-f); } }
double cbrt(double x) { int32_t hx; union { double value; u_int64_t bits; } u; double r,s,t=0.0,w; u_int32_t sign; u_int32_t high,low; EXTRACT_WORDS(hx,low,x); sign=hx&0x80000000; /* sign= sign(x) */ hx ^=sign; if(hx>=0x7ff00000) return(x+x); /* cbrt(NaN,INF) is itself */ /* * Rough cbrt to 5 bits: * cbrt(2**e*(1+m) ~= 2**(e/3)*(1+(e%3+m)/3) * where e is integral and >= 0, m is real and in [0, 1), and "/" and * "%" are integer division and modulus with rounding towards minus * infinity. The RHS is always >= the LHS and has a maximum relative * error of about 1 in 16. Adding a bias of -0.03306235651 to the * (e%3+m)/3 term reduces the error to about 1 in 32. With the IEEE * floating point representation, for finite positive normal values, * ordinary integer divison of the value in bits magically gives * almost exactly the RHS of the above provided we first subtract the * exponent bias (1023 for doubles) and later add it back. We do the * subtraction virtually to keep e >= 0 so that ordinary integer * division rounds towards minus infinity; this is also efficient. */ if(hx<0x00100000) { /* zero or subnormal? */ if((hx|low)==0) return(x); /* cbrt(0) is itself */ SET_HIGH_WORD(t,0x43500000); /* set t= 2**54 */ t*=x; GET_HIGH_WORD(high,t); INSERT_WORDS(t,sign|((high&0x7fffffff)/3+B2),0); } else INSERT_WORDS(t,sign|(hx/3+B1),0); /* * New cbrt to 23 bits: * cbrt(x) = t*cbrt(x/t**3) ~= t*P(t**3/x) * where P(r) is a polynomial of degree 4 that approximates 1/cbrt(r) * to within 2**-23.5 when |r - 1| < 1/10. The rough approximation * has produced t such than |t/cbrt(x) - 1| ~< 1/32, and cubing this * gives us bounds for r = t**3/x. * * Try to optimize for parallel evaluation as in k_tanf.c. */ r=(t*t)*(t/x); t=t*((P0+r*(P1+r*P2))+((r*r)*r)*(P3+r*P4)); /* * Round t away from zero to 23 bits (sloppily except for ensuring that * the result is larger in magnitude than cbrt(x) but not much more than * 2 23-bit ulps larger). With rounding towards zero, the error bound * would be ~5/6 instead of ~4/6. With a maximum error of 2 23-bit ulps * in the rounded t, the infinite-precision error in the Newton * approximation barely affects third digit in the final error * 0.667; the error in the rounded t can be up to about 3 23-bit ulps * before the final error is larger than 0.667 ulps. */ u.value=t; u.bits=(u.bits+0x80000000)&0xffffffffc0000000ULL; t=u.value; /* one step Newton iteration to 53 bits with error < 0.667 ulps */ s=t*t; /* t*t is exact */ r=x/s; /* error <= 0.5 ulps; |r| < |t| */ w=t+t; /* t+t is exact */ r=(r-t)/(w+r); /* r-t is exact; w+r ~= 3*t */ t=t+t*r; /* error <= 0.5 + 0.5/3 + epsilon */ return(t); }
double expm1(double x) { double y,hi,lo,c,t,e,hxs,hfx,r1; int32_t k,xsb; uint32_t hx; c = 0; GET_HIGH_WORD(hx,x); xsb = hx&0x80000000; /* sign bit of x */ if(xsb==0) y=x; else y= -x; /* y = |x| */ hx &= 0x7fffffff; /* high word of |x| */ /* filter out huge and non-finite argument */ if(hx >= 0x4043687A) { /* if |x|>=56*ln2 */ if(hx >= 0x40862E42) { /* if |x|>=709.78... */ if(hx>=0x7ff00000) { uint32_t low; GET_LOW_WORD(low,x); if(((hx&0xfffff)|low)!=0) return x+x; /* NaN */ else return (xsb==0)? x:-1.0;/* exp(+-inf)={inf,-1} */ } if(x > o_threshold) return huge*huge; /* overflow */ } if(xsb!=0) { /* x < -56*ln2, return -1.0 with inexact */ if(x+tiny<0.0) /* raise inexact */ return tiny-one; /* return -1 */ } } /* argument reduction */ if(hx > 0x3fd62e42) { /* if |x| > 0.5 ln2 */ if(hx < 0x3FF0A2B2) { /* and |x| < 1.5 ln2 */ if(xsb==0) {hi = x - ln2_hi; lo = ln2_lo; k = 1;} else {hi = x + ln2_hi; lo = -ln2_lo; k = -1;} } else { k = invln2*x+((xsb==0)?0.5:-0.5); t = k; hi = x - t*ln2_hi; /* t*ln2_hi is exact here */ lo = t*ln2_lo; } x = hi - lo; c = (hi-x)-lo; } else if(hx < 0x3c900000) { /* when |x|<2**-54, return x */ t = huge+x; /* return x with inexact flags when x!=0 */ return x - (t-(huge+x)); } else k = 0; /* x is now in primary range */ hfx = 0.5*x; hxs = x*hfx; r1 = one+hxs*(Q1+hxs*(Q2+hxs*(Q3+hxs*(Q4+hxs*Q5)))); t = 3.0-r1*hfx; e = hxs*((r1-t)/(6.0 - x*t)); if(k==0) return x - (x*e-hxs); /* c is 0 */ else { e = (x*(e-c)-c); e -= hxs; if(k== -1) return 0.5*(x-e)-0.5; if(k==1) { if(x < -0.25) return -2.0*(e-(x+0.5)); else return one+2.0*(x-e); } if (k <= -2 || k>56) { /* suffice to return exp(x)-1 */ uint32_t high; y = one-(e-x); GET_HIGH_WORD(high,y); SET_HIGH_WORD(y,high+(k<<20)); /* add k to y's exponent */ return y-one; } t = one; if(k<20) { uint32_t high; SET_HIGH_WORD(t,0x3ff00000 - (0x200000>>k)); /* t=1-2^-k */ y = t-(e-x); GET_HIGH_WORD(high,y); SET_HIGH_WORD(y,high+(k<<20)); /* add k to y's exponent */ } else {
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) / sqrt (y); else { u = pone (y); v = qone (y); z = invsqrtpi * (u * cc - v * ss) / 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 = math_narrow_eval (0.5 * x); math_check_force_underflow (ret); if (ret == 0 && x != 0) __set_errno (ERANGE); 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); }
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; 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]; 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_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; } a = fabs(a); b = fabs(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 */ uint32_t low; /* Use original arg order iff result is NaN; quieten sNaNs. */ w = fabs(x + 0.0) - fabs(y + 0.0); 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 */ uint32_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 = 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 = sqrt(t1*y1 - (w*(-w) - (t1*y2 + t2*b))); } if (k != 0) { uint32_t high; t1 = 1.0; GET_HIGH_WORD(high, t1); SET_HIGH_WORD(t1, high + (k << 20)); return t1*w; } else return w; }
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; }