double __ieee754_exp10 (double arg) { int32_t lx; double arg_high, arg_low; double exp_high, exp_low; if (!isfinite (arg)) return __ieee754_exp (arg); if (arg < DBL_MIN_10_EXP - DBL_DIG - 10) return DBL_MIN * DBL_MIN; else if (arg > DBL_MAX_10_EXP + 1) return DBL_MAX * DBL_MAX; else if (fabs (arg) < 0x1p-56) return 1.0; GET_LOW_WORD (lx, arg); lx &= 0xf8000000; arg_high = arg; SET_LOW_WORD (arg_high, lx); arg_low = arg - arg_high; exp_high = arg_high * log10_high; exp_low = arg_high * log10_low + arg_low * M_LN10; return __ieee754_exp (exp_high) * __ieee754_exp (exp_low); }
int __ieee754_ilogb (double x) { int32_t hx, lx, ix; GET_HIGH_WORD (hx, x); hx &= 0x7fffffff; if (hx < 0x00100000) { GET_LOW_WORD (lx, x); if ((hx | lx) == 0) return FP_ILOGB0; /* ilogb(0) = FP_ILOGB0 */ else /* subnormal x */ if (hx == 0) { for (ix = -1043; lx > 0; lx <<= 1) ix -= 1; } else { for (ix = -1022, hx <<= 11; hx > 0; hx <<= 1) ix -= 1; } return ix; } else if (hx < 0x7ff00000) return (hx >> 20) - 1023; else if (FP_ILOGBNAN != INT_MAX)
double atan(double x) { double w,s1,s2,z; int32_t ix,hx,id; GET_HIGH_WORD(hx, x); ix = hx & 0x7fffffff; if (ix >= 0x44100000) { /* if |x| >= 2^66 */ uint32_t low; GET_LOW_WORD(low, x); if (ix > 0x7ff00000 || (ix == 0x7ff00000 && low != 0)) /* NaN */ return x+x; if (hx > 0) return atanhi[3] + *(volatile double *)&atanlo[3]; else return -atanhi[3] - *(volatile double *)&atanlo[3]; } if (ix < 0x3fdc0000) { /* |x| < 0.4375 */ if (ix < 0x3e400000) { /* |x| < 2^-27 */ /* raise inexact */ if (huge+x > 1.0) return x; } id = -1; } else { x = fabs(x); if (ix < 0x3ff30000) { /* |x| < 1.1875 */ if (ix < 0x3fe60000) { /* 7/16 <= |x| < 11/16 */ id = 0; x = (2.0*x-1.0)/(2.0+x); } else { /* 11/16 <= |x| < 19/16 */ id = 1; x = (x-1.0)/(x+1.0); } } else { if (ix < 0x40038000) { /* |x| < 2.4375 */ id = 2; x = (x-1.5)/(1.0+1.5*x); } else { /* 2.4375 <= |x| < 2^66 */ id = 3; x = -1.0/x; } } } /* end of argument reduction */ z = x*x; w = z*z; /* break sum from i=0 to 10 aT[i]z**(i+1) into odd and even poly */ s1 = z*(aT[0]+w*(aT[2]+w*(aT[4]+w*(aT[6]+w*(aT[8]+w*aT[10]))))); s2 = w*(aT[1]+w*(aT[3]+w*(aT[5]+w*(aT[7]+w*aT[9])))); if (id < 0) return x - x*(s1+s2); z = atanhi[id] - (x*(s1+s2) - atanlo[id] - x); return hx < 0 ? -z : z; }
double acos(double x) { double z, p, q, r, w, s, c, df; s32_t hx, ix; GET_HIGH_WORD(hx,x); ix = hx & 0x7fffffff; if (ix >= 0x3ff00000) { u32_t lx; GET_LOW_WORD(lx,x); if (((ix - 0x3ff00000) | lx) == 0) { if (hx > 0) return 0.0; else return pi + 2.0 * pio2_lo; } return (x - x) / (x - x); } if (ix < 0x3fe00000) { if (ix <= 0x3c600000) return pio2_hi + pio2_lo; 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) { 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 = sqrt(z); r = p / q; w = r * s - pio2_lo; return pi - 2.0 * (s + w); } else { z = (one - x) * 0.5; s = 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 __ieee754_cosh (double x) { double t, w; int32_t ix; u_int32_t lx; /* High word of |x|. */ GET_HIGH_WORD (ix, x); ix &= 0x7fffffff; /* |x| in [0,22] */ if (ix < 0x40360000) { /* |x| in [0,0.5*ln2], return 1+expm1(|x|)^2/(2*exp(|x|)) */ if (ix < 0x3fd62e43) { if (ix < 0x3c800000) return one; /* cosh(tiny) = 1 */ t = __expm1 (fabs (x)); w = one + t; return one + (t * t) / (w + w); } /* |x| in [0.5*ln2,22], return (exp(|x|)+1/exp(|x|)/2; */ 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] */ GET_LOW_WORD (lx, x); if (ix < 0x408633ce || ((ix == 0x408633ce) && (lx <= (u_int32_t) 0x8fb9f87d))) { w = __ieee754_exp (half * fabs (x)); t = half * w; return t * w; } /* x is INF or NaN */ if (ix >= 0x7ff00000) return x * x; /* |x| > overflowthresold, cosh(x) overflow */ return huge * huge; }
double cbrt(double x) { int32_t hx; double r,s,t=0.0,w; u_int32_t sign; u_int32_t high,low; GET_HIGH_WORD(hx,x); sign=hx&0x80000000; /* sign= sign(x) */ hx ^=sign; if(hx>=0x7ff00000) return(x+x); /* cbrt(NaN,INF) is itself */ GET_LOW_WORD(low,x); if((hx|low)==0) return(x); /* cbrt(0) is itself */ SET_HIGH_WORD(x,hx); /* x <- |x| */ /* rough cbrt to 5 bits */ if(hx<0x00100000) /* subnormal number */ {SET_HIGH_WORD(t,0x43500000); /* set t= 2**54 */ t*=x; GET_HIGH_WORD(high,t); SET_HIGH_WORD(t,high/3+B2); } else SET_HIGH_WORD(t,hx/3+B1); /* new cbrt to 23 bits, may be implemented in single precision */ r=t*t/x; s=C+r*t; t*=G+F/(s+E+D/s); /* chopped to 20 bits and make it larger than cbrt(x) */ GET_HIGH_WORD(high,t); INSERT_WORDS(t,high+0x00000001,0); /* one step newton iteration to 53 bits with error less than 0.667 ulps */ s=t*t; /* t*t is exact */ r=x/s; w=t+t; r=(r-t)/(w+r); /* r-s is exact */ t=t+t*r; /* retore the sign bit */ GET_HIGH_WORD(high,t); SET_HIGH_WORD(t,high|sign); return(t); }
double asin(double x) { double t=0.0,w,p,q,c,r,s; int32_t hx,ix; GET_HIGH_WORD(hx, x); ix = hx & 0x7fffffff; if (ix >= 0x3ff00000) { /* |x|>= 1 */ uint32_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 < 0x3e500000) { /* if |x| < 2**-26 */ if (huge+x > 1.0) return x; /* return x with inexact if x!=0*/ } t = x*x; p = t*(pS0+t*(pS1+t*(pS2+t*(pS3+t*(pS4+t*pS5))))); q = 1.0+t*(qS1+t*(qS2+t*(qS3+t*qS4))); w = p/q; return x + x*w; } /* 1 > |x| >= 0.5 */ w = 1.0 - fabs(x); t = w*0.5; p = t*(pS0+t*(pS1+t*(pS2+t*(pS3+t*(pS4+t*pS5))))); q = 1.0+t*(qS1+t*(qS2+t*(qS3+t*qS4))); s = 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; return -t; }
static double sin_pi(double x) { double y,z; int n,ix; GET_HIGH_WORD(ix, x); ix &= 0x7fffffff; if (ix < 0x3fd00000) return __sin(pi*x, 0.0, 0); y = -x; /* negative x is assumed */ /* * argument reduction, make sure inexact flag not raised if input * is an integer */ z = floor(y); if (z != y) { /* inexact anyway */ y *= 0.5; y = 2.0*(y - floor(y)); /* y = |x| mod 2.0 */ n = (int)(y*4.0); } else { if (ix >= 0x43400000) { y = 0.0; /* y must be even */ n = 0; } else { if (ix < 0x43300000) z = y + two52; /* exact */ GET_LOW_WORD(n, z); n &= 1; y = n; n <<= 2; } } switch (n) { case 0: y = __sin(pi*y, 0.0, 0); break; case 1: case 2: y = __cos(pi*(0.5-y), 0.0); break; case 3: case 4: y = __sin(pi*(1.0-y), 0.0, 0); break; case 5: case 6: y = -__cos(pi*(y-1.5), 0.0); break; default: y = __sin(pi*(y-2.0), 0.0, 0); break; } return -y; }
double expm1(double x) { double y,hi,lo,c,t,e,hxs,hfx,r1,twopk; int32_t k,xsb; uint32_t hx; GET_HIGH_WORD(hx,x); xsb = hx&0x80000000; /* sign bit of 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; } STRICT_ASSIGN(double, x, hi - lo); c = (hi-x)-lo; } else if(hx < 0x3c900000) { /* when |x|<2**-54, return 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 */ uint32_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 = 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 = 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); } }
int ilogb(double x) { int32_t hx,lx,ix; GET_HIGH_WORD(hx,x); hx &= 0x7fffffff; if(hx<0x00100000) { GET_LOW_WORD(lx,x); if((hx|lx)==0) return 0x80000001; /* ilogb(0) = 0x80000001 */ else /* subnormal x */ if(hx==0) { for (ix = -1043; lx>0; lx<<=1) ix -=1; } else { for (ix = -1022,hx<<=11; hx>0; hx<<=1) ix -=1; } return ix; } else if (hx<0x7ff00000) return (hx>>20)-1023; else return 0x7fffffff;
double cosh(double x) { double t, w; s32_t ix; u32_t lx; GET_HIGH_WORD(ix,x); ix &= 0x7fffffff; if (ix >= 0x7ff00000) return x * x; if (ix < 0x3fd62e43) { t = expm1(fabs(x)); w = one + t; if (ix < 0x3c800000) return w; return one + (t * t) / (w + w); } if (ix < 0x40360000) { t = exp(fabs(x)); return half * t + half / t; } if (ix < 0x40862E42) return half * exp(fabs(x)); GET_LOW_WORD(lx,x); if (ix < 0x408633CE || ((ix == 0x408633ce) && (lx <= (u32_t) 0x8fb9f87d))) { w = exp(half * fabs(x)); t = half * w; return t * w; } return huge * huge; }
double __ieee754_sinh(double x) { double t,w,h; int32_t ix,jx; uint32_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<=(uint32_t)0x8fb9f87d))) { w = __ieee754_exp(0.5*fabs(x)); t = h*w; return t*w; } /* |x| > overflowthresold, sinh(x) overflow */ return x*shuge; }
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))); }
/* * 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 __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 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_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 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 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; }