float __ieee754_atanhf (float x) { float xa = fabsf (x); float t; if (isless (xa, 0.5f)) { if (__glibc_unlikely (xa < 0x1.0p-28f)) { math_force_eval (huge + x); if (fabsf (x) < FLT_MIN) { float force_underflow = x * x; math_force_eval (force_underflow); } return x; } t = xa + xa; t = 0.5f * __log1pf (t + t * xa / (1.0f - xa)); } else if (__glibc_likely (isless (xa, 1.0f))) t = 0.5f * __log1pf ((xa + xa) / (1.0f - xa)); else { if (isgreater (xa, 1.0f)) return (x - x) / (x - x); return x / 0.0f; } return __copysignf (t, x); }
double __nexttoward(double x, long double y) { int32_t hx,ix,iy; u_int32_t lx,hy,ly,esy; EXTRACT_WORDS(hx,lx,x); GET_LDOUBLE_WORDS(esy,hy,ly,y); ix = hx&0x7fffffff; /* |x| */ iy = esy&0x7fff; /* |y| */ /* Intel's extended format has the normally implicit 1 explicit present. Sigh! */ if(((ix>=0x7ff00000)&&((ix-0x7ff00000)|lx)!=0) || /* x is nan */ ((iy>=0x7fff)&&((hy&0x7fffffff)|ly)!=0)) /* y is nan */ return x+y; if((long double) x==y) return y; /* x=y, return y */ if((ix|lx)==0) { /* x == 0 */ double u; INSERT_WORDS(x,(esy&0x8000)<<16,1); /* return +-minsub */ u = math_opt_barrier (x); u = u * u; math_force_eval (u); /* raise underflow flag */ return x; } if(hx>=0) { /* x > 0 */ if (x > y) { /* x -= ulp */ if(lx==0) hx -= 1; lx -= 1; } else { /* x < y, x += ulp */ lx += 1; if(lx==0) hx += 1; } } else { /* x < 0 */ if (x < y) { /* x -= ulp */ if(lx==0) hx -= 1; lx -= 1; } else { /* x > y, x += ulp */ lx += 1; if(lx==0) hx += 1; } } hy = hx&0x7ff00000; if(hy>=0x7ff00000) { double u = x+x; /* overflow */ math_force_eval (u); } if(hy<0x00100000) { double u = x*x; /* underflow */ math_force_eval (u); /* raise underflow flag */ } INSERT_WORDS(x,hx,lx); return x; }
__float128 nextafterq (__float128 x, __float128 y) { int64_t hx,hy,ix,iy; uint64_t lx,ly; GET_FLT128_WORDS64(hx,lx,x); GET_FLT128_WORDS64(hy,ly,y); ix = hx&0x7fffffffffffffffLL; /* |x| */ iy = hy&0x7fffffffffffffffLL; /* |y| */ if(((ix>=0x7fff000000000000LL)&&((ix-0x7fff000000000000LL)|lx)!=0) || /* x is nan */ ((iy>=0x7fff000000000000LL)&&((iy-0x7fff000000000000LL)|ly)!=0)) /* y is nan */ return x+y; if(x==y) return y; /* x=y, return y */ if((ix|lx)==0) { /* x == 0 */ SET_FLT128_WORDS64(x,hy&0x8000000000000000ULL,1);/* return +-minsubnormal */ /* here we should raise an underflow flag */ return x; } if(hx>=0) { /* x > 0 */ if(hx>hy||((hx==hy)&&(lx>ly))) { /* x > y, x -= ulp */ if(lx==0) hx--; lx--; } else { /* x < y, x += ulp */ lx++; if(lx==0) hx++; } } else { /* x < 0 */ if(hy>=0||hx>hy||((hx==hy)&&(lx>ly))){/* x < y, x -= ulp */ if(lx==0) hx--; lx--; } else { /* x > y, x += ulp */ lx++; if(lx==0) hx++; } } hy = hx&0x7fff000000000000LL; if(hy==0x7fff000000000000LL) { __float128 u = x + x; /* overflow */ math_force_eval (u); errno = ERANGE; } if(hy==0) { __float128 u = x*x; /* underflow */ math_force_eval (u); /* raise underflow flag */ errno = ERANGE; } SET_FLT128_WORDS64(x,hx,lx); return x; }
long double __nextafterl(long double x, long double y) { int64_t hx,hy,ix,iy; u_int64_t lx,ly; GET_LDOUBLE_WORDS64(hx,lx,x); GET_LDOUBLE_WORDS64(hy,ly,y); ix = hx&0x7fffffffffffffffLL; /* |x| */ iy = hy&0x7fffffffffffffffLL; /* |y| */ if(((ix>=0x7fff000000000000LL)&&((ix-0x7fff000000000000LL)|lx)!=0) || /* x is nan */ ((iy>=0x7fff000000000000LL)&&((iy-0x7fff000000000000LL)|ly)!=0)) /* y is nan */ return x+y; if(x==y) return y; /* x=y, return y */ if((ix|lx)==0) { /* x == 0 */ long double u; SET_LDOUBLE_WORDS64(x,hy&0x8000000000000000ULL,1);/* return +-minsubnormal */ u = math_opt_barrier (x); u = u * u; math_force_eval (u); /* raise underflow flag */ return x; } if(hx>=0) { /* x > 0 */ if(hx>hy||((hx==hy)&&(lx>ly))) { /* x > y, x -= ulp */ if(lx==0) hx--; lx--; } else { /* x < y, x += ulp */ lx++; if(lx==0) hx++; } } else { /* x < 0 */ if(hy>=0||hx>hy||((hx==hy)&&(lx>ly))){/* x < y, x -= ulp */ if(lx==0) hx--; lx--; } else { /* x > y, x += ulp */ lx++; if(lx==0) hx++; } } hy = hx&0x7fff000000000000LL; if(hy==0x7fff000000000000LL) { long double u = x + x; /* overflow */ math_force_eval (u); } if(hy==0) { long double u = x*x; /* underflow */ math_force_eval (u); /* raise underflow flag */ } SET_LDOUBLE_WORDS64(x,hx,lx); return x; }
float __nexttowardf(float x, long double y) { int32_t hx,ix,iy; uint32_t hy,ly,esy; GET_FLOAT_WORD(hx,x); GET_LDOUBLE_WORDS(esy,hy,ly,y); ix = hx&0x7fffffff; /* |x| */ iy = esy&0x7fff; /* |y| */ if((ix>0x7f800000) || /* x is nan */ (iy>=0x7fff&&((hy|ly)!=0))) /* y is nan */ return x+y; if((long double) x==y) return y; /* x=y, return y */ if(ix==0) { /* x == 0 */ float u; SET_FLOAT_WORD(x,((esy&0x8000)<<16)|1);/* return +-minsub*/ u = math_opt_barrier (x); u = u * u; math_force_eval (u); /* raise underflow flag */ return x; } if(hx>=0) { /* x > 0 */ if(x > y) { /* x -= ulp */ hx -= 1; } else { /* x < y, x += ulp */ hx += 1; } } else { /* x < 0 */ if(x < y) { /* x -= ulp */ hx -= 1; } else { /* x > y, x += ulp */ hx += 1; } } hy = hx&0x7f800000; if(hy>=0x7f800000) { float u = x+x; /* overflow */ math_force_eval (u); __set_errno (ERANGE); } if(hy<0x00800000) { float u = x*x; /* underflow */ math_force_eval (u); /* raise underflow flag */ __set_errno (ERANGE); } SET_FLOAT_WORD(x,hx); return x; }
long double __ieee754_atanhl(long double x) { long double t; u_int32_t jx, ix; ieee854_long_double_shape_type u; u.value = x; jx = u.parts32.w0; ix = jx & 0x7fffffff; u.parts32.w0 = ix; if (ix >= 0x3fff0000) /* |x| >= 1.0 or infinity or NaN */ { if (u.value == one) return x/zero; else return (x-x)/(x-x); } if(ix<0x3fc60000 && (huge+x)>zero) /* x < 2^-57 */ { if (fabsl (x) < LDBL_MIN) { long double force_underflow = x * x; math_force_eval (force_underflow); } return x; } if(ix<0x3ffe0000) { /* x < 0.5 */ t = u.value+u.value; t = 0.5*__log1pl(t+t*u.value/(one-u.value)); } else t = 0.5*__log1pl((u.value+u.value)/(one-u.value)); if(jx & 0x80000000) return -t; else return t; }
float __ieee754_atanhf (float x) { float xa = fabsf (x); float t; if (isless (xa, 0.5f)) { if (__builtin_expect (xa < 0x1.0p-28f, 0)) { math_force_eval (huge + x); return x; } t = xa + xa; t = 0.5f * __log1pf (t + t * xa / (1.0f - xa)); } else if (__builtin_expect (isless (xa, 1.0f), 1)) t = 0.5f * __log1pf ((xa + xa) / (1.0f - xa)); else { if (isgreater (xa, 1.0f)) return (x - x) / (x - x); return x / 0.0f; } return __copysignf (t, x); }
double __nexttoward(double x, long double y) { int32_t hx,ix; int64_t hy,iy; uint32_t lx; double yhi; EXTRACT_WORDS(hx,lx,x); yhi = ldbl_high (y); EXTRACT_WORDS64(hy,yhi); ix = hx&0x7fffffff; /* |x| */ iy = hy&0x7fffffffffffffffLL; /* |y| */ if(((ix>=0x7ff00000)&&((ix-0x7ff00000)|lx)!=0) || /* x is nan */ iy>0x7ff0000000000000LL) /* y is nan */ return x+y; if((long double) x==y) return y; /* x=y, return y */ if((ix|lx)==0) { /* x == 0 */ double u; INSERT_WORDS(x,(uint32_t)((hy>>32)&0x80000000),1);/* return +-minsub */ u = math_opt_barrier (x); u = u * u; math_force_eval (u); /* raise underflow flag */ return x; }
double __ieee754_atanh (double x) { double xa = fabs (x); double t; if (isless (xa, 0.5)) { if (__glibc_unlikely (xa < 0x1.0p-28)) { math_force_eval (huge + x); math_check_force_underflow (x); return x; } t = xa + xa; t = 0.5 * __log1p (t + t * xa / (1.0 - xa)); } else if (__glibc_likely (isless (xa, 1.0))) t = 0.5 * __log1p ((xa + xa) / (1.0 - xa)); else { if (isgreater (xa, 1.0)) return (x - x) / (x - x); return x / 0.0; } return __copysign (t, x); }
double __ieee754_atanh (double x) { double xa = fabs (x); double t; if (isless (xa, 0.5)) { if (__builtin_expect (xa < 0x1.0p-28, 0)) { math_force_eval (huge + x); return x; } t = xa + xa; t = 0.5 * __log1p (t + t * xa / (1.0 - xa)); } else if (__builtin_expect (isless (xa, 1.0), 1)) t = 0.5 * __log1p ((xa + xa) / (1.0 - xa)); else { if (isgreater (xa, 1.0)) return (x - x) / (x - x); return x / 0.0; } return __copysign (t, x); }
float __fmaf (float x, float y, float z) { fenv_t env; /* Multiplication is always exact. */ double temp = (double) x * (double) y; /* Ensure correct sign of an exact zero result by performing the addition in the original rounding mode in that case. */ if (temp == -z) return (float) temp + z; union ieee754_double u; libc_feholdexcept_setround (&env, FE_TOWARDZERO); /* Perform addition with round to odd. */ u.d = temp + (double) z; /* Ensure the addition is not scheduled after fetestexcept call. */ math_force_eval (u.d); /* Reset rounding mode and test for inexact simultaneously. */ int j = libc_feupdateenv_test (&env, FE_INEXACT) != 0; if ((u.ieee.mantissa1 & 1) == 0 && u.ieee.exponent != 0x7ff) u.ieee.mantissa1 |= j; /* And finally truncation with round to nearest. */ return (float) u.d; }
float __nexttowardf(float x, long double y) { int32_t hx,ix; int64_t hy,iy; double yhi; GET_FLOAT_WORD(hx,x); yhi = ldbl_high (y); EXTRACT_WORDS64 (hy, yhi); ix = hx&0x7fffffff; /* |x| */ iy = hy&0x7fffffffffffffffLL; /* |y| */ if((ix>0x7f800000) || /* x is nan */ (iy>0x7ff0000000000000LL)) /* y is nan */ return x+y; if((long double) x==y) return y; /* x=y, return y */ if(ix==0) { /* x == 0 */ float u; SET_FLOAT_WORD(x,(u_int32_t)((hy>>32)&0x80000000)|1);/* return +-minsub*/ u = math_opt_barrier (x); u = u * u; math_force_eval (u); /* raise underflow flag */ return x; }
float __nldbl_nexttowardf(float x, double y) { int32_t hx,hy,ix,iy; u_int32_t ly; GET_FLOAT_WORD(hx,x); EXTRACT_WORDS(hy,ly,y); ix = hx&0x7fffffff; /* |x| */ iy = hy&0x7fffffff; /* |y| */ if((ix>0x7f800000) || /* x is nan */ ((iy>=0x7ff00000)&&((iy-0x7ff00000)|ly)!=0)) /* y is nan */ return x+y; if((double) x==y) return y; /* x=y, return y */ if(ix==0) { /* x == 0 */ float u; SET_FLOAT_WORD(x,(u_int32_t)(hy&0x80000000)|1);/* return +-minsub*/ u = math_opt_barrier (x); u = u * u; math_force_eval (u); /* raise underflow flag */ return x; } if(hx>=0) { /* x > 0 */ if(x > y) /* x -= ulp */ hx -= 1; else /* x < y, x += ulp */ hx += 1; } else { /* x < 0 */ if(x < y) /* x -= ulp */ hx -= 1; else /* x > y, x += ulp */ hx += 1; } hy = hx&0x7f800000; if(hy>=0x7f800000) { float u = x+x; /* overflow */ math_force_eval (u); __set_errno (ERANGE); } if(hy<0x00800000) { float u = x*x; /* underflow */ math_force_eval (u); /* raise underflow flag */ __set_errno (ERANGE); } SET_FLOAT_WORD(x,hx); return x; }
float __nextafterf(float x, float y) { int32_t hx,hy,ix,iy; GET_FLOAT_WORD(hx,x); GET_FLOAT_WORD(hy,y); ix = hx&0x7fffffff; /* |x| */ iy = hy&0x7fffffff; /* |y| */ if((ix>0x7f800000) || /* x is nan */ (iy>0x7f800000)) /* y is nan */ return x+y; if(x==y) return y; /* x=y, return y */ if(ix==0) { /* x == 0 */ float u; SET_FLOAT_WORD(x,(hy&0x80000000)|1);/* return +-minsubnormal */ u = math_opt_barrier (x); u = u*u; math_force_eval (u); /* raise underflow flag */ return x; } if(hx>=0) { /* x > 0 */ if(hx>hy) { /* x > y, x -= ulp */ hx -= 1; } else { /* x < y, x += ulp */ hx += 1; } } else { /* x < 0 */ if(hy>=0||hx>hy){ /* x < y, x -= ulp */ hx -= 1; } else { /* x > y, x += ulp */ hx += 1; } } hy = hx&0x7f800000; if(hy>=0x7f800000) { float u = x+x; /* overflow */ math_force_eval (u); } if(hy<0x00800000) { float u = x*x; /* underflow */ math_force_eval (u); /* raise underflow flag */ } SET_FLOAT_WORD(x,hx); return x; }
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)); } }
float nextafterf(float x, float y) { int32_t hx, hy, ix, iy; GET_FLOAT_WORD(hx, x); GET_FLOAT_WORD(hy, y); ix = hx & 0x7fffffff; /* |x| */ iy = hy & 0x7fffffff; /* |y| */ /* x is nan or y is nan? */ if ((ix > 0x7f800000) || (iy > 0x7f800000)) return x + y; if (x == y) return y; if (ix == 0) { /* x == 0? */ /* glibc 2.4 does not seem to set underflow? */ /* float u; */ /* return +-minsubnormal */ SET_FLOAT_WORD(x, (hy & 0x80000000) | 1); /* u = x * x; raise underflow flag */ /* math_force_eval(u); */ return x; } if (hx >= 0) { /* x > 0 */ if (hx > hy) { /* x > y: x -= ulp */ hx -= 1; } else { /* x < y: x += ulp */ hx += 1; } } else { /* x < 0 */ if (hy >= 0 || hx > hy) { /* x < y: x -= ulp */ hx -= 1; } else { /* x > y: x += ulp */ hx += 1; } } hy = hx & 0x7f800000; if (hy >= 0x7f800000) { x = x + x; /* overflow */ return x; /* overflow */ } if (hy < 0x00800000) { float u = x * x; /* underflow */ math_force_eval(u); /* raise underflow flag */ } SET_FLOAT_WORD(x, hx); return x; }
double __tanh (double x) { double t, z; int32_t jx, ix, lx; /* High word of |x|. */ EXTRACT_WORDS (jx, lx, x); ix = jx & 0x7fffffff; /* x is INF or NaN */ if (ix >= 0x7ff00000) { if (jx >= 0) return one / x + one; /* tanh(+-inf)=+-1 */ else return one / x - one; /* tanh(NaN) = NaN */ } /* |x| < 22 */ if (ix < 0x40360000) /* |x|<22 */ { if ((ix | lx) == 0) return x; /* x == +-0 */ if (ix < 0x3c800000) /* |x|<2**-55 */ { if (fabs (x) < DBL_MIN) { double force_underflow = x * x; math_force_eval (force_underflow); } return x * (one + x); /* tanh(small) = small */ } if (ix >= 0x3ff00000) /* |x|>=1 */ { t = __expm1 (two * fabs (x)); z = one - two / (t + two); } else { t = __expm1 (-two * fabs (x)); z = -t / (t + two); } /* |x| > 22, return +-1 */ } else { z = one - tiny; /* raised inexact flag */ } return (jx >= 0) ? z : -z; }
long double __kernel_sinl(long double x, long double y, int iy) { long double absx, h, l, z, sin_l, cos_l_m1; int index; absx = fabsl (x); if (absx < 0.1484375L) { /* Argument is small enough to approximate it by a Chebyshev polynomial of degree 17. */ if (absx < 0x1p-33L) { if (fabsl (x) < LDBL_MIN) { long double force_underflow = x * x; math_force_eval (force_underflow); } if (!((int)x)) return x; /* generate inexact */ } z = x * x; return x + (x * (z*(SIN1+z*(SIN2+z*(SIN3+z*(SIN4+ z*(SIN5+z*(SIN6+z*(SIN7+z*SIN8))))))))); } else { /* So that we don't have to use too large polynomial, we find l and h such that x = l + h, where fabsl(l) <= 1.0/256 with 83 possible values for h. We look up cosl(h) and sinl(h) in pre-computed tables, compute cosl(l) and sinl(l) using a Chebyshev polynomial of degree 10(11) and compute sinl(h+l) = sinl(h)cosl(l) + cosl(h)sinl(l). */ index = (int) (128 * (absx - (0.1484375L - 1.0L / 256.0L))); h = 0.1484375L + index / 128.0; index *= 4; if (iy) l = (x < 0 ? -y : y) - (h - absx); else l = absx - h; z = l * l; sin_l = l*(ONE+z*(SSIN1+z*(SSIN2+z*(SSIN3+z*(SSIN4+z*SSIN5))))); cos_l_m1 = z*(SCOS1+z*(SCOS2+z*(SCOS3+z*(SCOS4+z*SCOS5)))); z = __sincosl_table [index + SINCOSL_SIN_HI] + (__sincosl_table [index + SINCOSL_SIN_LO] + (__sincosl_table [index + SINCOSL_SIN_HI] * cos_l_m1) + (__sincosl_table [index + SINCOSL_COS_HI] * sin_l)); return (x < 0) ? -z : z; } }
float __atanf(float x) { float w,s1,s2,z; int32_t ix,hx,id; GET_FLOAT_WORD(hx,x); ix = hx&0x7fffffff; if(ix>=0x50800000) { /* if |x| >= 2^34 */ if(ix>0x7f800000) return x+x; /* NaN */ if(hx>0) return atanhi[3]+atanlo[3]; else return -atanhi[3]-atanlo[3]; } if (ix < 0x3ee00000) { /* |x| < 0.4375 */ if (ix < 0x31000000) { /* |x| < 2^-29 */ if (fabsf (x) < FLT_MIN) { float force_underflow = x * x; math_force_eval (force_underflow); } if(huge+x>one) return x; /* raise inexact */ } id = -1; } else { x = fabsf(x); if (ix < 0x3f980000) { /* |x| < 1.1875 */ if (ix < 0x3f300000) { /* 7/16 <=|x|<11/16 */ id = 0; x = ((float)2.0*x-one)/((float)2.0+x); } else { /* 11/16<=|x|< 19/16 */ id = 1; x = (x-one)/(x+one); } } else { if (ix < 0x401c0000) { /* |x| < 2.4375 */ id = 2; x = (x-(float)1.5)/(one+(float)1.5*x); } else { /* 2.4375 <= |x| < 2^66 */ id = 3; x = -(float)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); else { z = atanhi[id] - ((x*(s1+s2) - atanlo[id]) - x); return (hx<0)? -z:z; } }
long double __ieee754_sinhl(long double x) { long double t,w,h; u_int32_t jx,ix,i0,i1; /* Words of |x|. */ GET_LDOUBLE_WORDS(jx,i0,i1,x); ix = jx&0x7fff; /* x is INF or NaN */ if(__builtin_expect(ix==0x7fff, 0)) return x+x; h = 0.5; if (jx & 0x8000) h = -h; /* |x| in [0,25], return sign(x)*0.5*(E+E/(E+1))) */ if (ix < 0x4003 || (ix == 0x4003 && i0 <= 0xc8000000)) { /* |x|<25 */ if (ix<0x3fdf) { /* |x|<2**-32 */ if (fabsl (x) < LDBL_MIN) { long double force_underflow = x * x; math_force_eval (force_underflow); } if(shuge+x>one) return x;/* sinh(tiny) = tiny with inexact */ } t = __expm1l(fabsl(x)); if(ix<0x3fff) return h*(2.0*t-t*t/(t+one)); return h*(t+t/(t+one)); } /* |x| in [25, log(maxdouble)] return 0.5*exp(|x|) */ if (ix < 0x400c || (ix == 0x400c && i0 < 0xb17217f7)) return h*__ieee754_expl(fabsl(x)); /* |x| in [log(maxdouble), overflowthreshold] */ if (ix<0x400c || (ix == 0x400c && (i0 < 0xb174ddc0 || (i0 == 0xb174ddc0 && i1 <= 0x31aec0ea)))) { w = __ieee754_expl(0.5*fabsl(x)); t = h*w; return t*w; } /* |x| > overflowthreshold, sinhl(x) overflow */ return x*shuge; }
float __ieee754_j0f(float x) { float z, s,c,ss,cc,r,u,v; int32_t hx,ix; GET_FLOAT_WORD(hx,x); ix = hx&0x7fffffff; if(ix>=0x7f800000) return one/(x*x); x = fabsf(x); if(ix >= 0x40000000) { /* |x| >= 2.0 */ __sincosf (x, &s, &c); ss = s-c; cc = s+c; if(ix<0x7f000000) { /* make sure x+x not overflow */ z = -__cosf(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_sqrtf(x); else { u = pzerof(x); v = qzerof(x); z = invsqrtpi*(u*cc-v*ss)/__ieee754_sqrtf(x); } return z; } if(ix<0x39000000) { /* |x| < 2**-13 */ math_force_eval(huge+x); /* raise inexact if x != 0 */ if(ix<0x32000000) return one; /* |x|<2**-27 */ else return one - (float)0.25*x*x; } z = x*x; r = z*(R02+z*(R03+z*(R04+z*R05))); s = one+z*(S01+z*(S02+z*(S03+z*S04))); if(ix < 0x3F800000) { /* |x| < 1.00 */ return one + z*((float)-0.25+(r/s)); } else { u = (float)0.5*x; return((one+u)*(one-u)+z*(r/s)); } }
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 (fabs (x) < DBL_MIN) { double force_underflow = x * x; math_force_eval (force_underflow); } 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 __fma (double x, double y, double z) { union ieee754_double u, v, w; int adjust = 0; u.d = x; v.d = y; w.d = z; if (__builtin_expect (u.ieee.exponent + v.ieee.exponent >= 0x7ff + IEEE754_DOUBLE_BIAS - DBL_MANT_DIG, 0) || __builtin_expect (u.ieee.exponent >= 0x7ff - DBL_MANT_DIG, 0) || __builtin_expect (v.ieee.exponent >= 0x7ff - DBL_MANT_DIG, 0) || __builtin_expect (w.ieee.exponent >= 0x7ff - DBL_MANT_DIG, 0) || __builtin_expect (u.ieee.exponent + v.ieee.exponent <= IEEE754_DOUBLE_BIAS + DBL_MANT_DIG, 0)) { /* If z is Inf, but x and y are finite, the result should be z rather than NaN. */ if (w.ieee.exponent == 0x7ff && u.ieee.exponent != 0x7ff && v.ieee.exponent != 0x7ff) return (z + x) + y; /* If z is zero and x are y are nonzero, compute the result as x * y to avoid the wrong sign of a zero result if x * y underflows to 0. */ if (z == 0 && x != 0 && y != 0) return x * y; /* If x or y or z is Inf/NaN, or if x * y is zero, compute as x * y + z. */ if (u.ieee.exponent == 0x7ff || v.ieee.exponent == 0x7ff || w.ieee.exponent == 0x7ff || x == 0 || y == 0) return x * y + z; /* If fma will certainly overflow, compute as x * y. */ if (u.ieee.exponent + v.ieee.exponent > 0x7ff + IEEE754_DOUBLE_BIAS) return x * y; /* If x * y is less than 1/4 of DBL_DENORM_MIN, neither the result nor whether there is underflow depends on its exact value, only on its sign. */ if (u.ieee.exponent + v.ieee.exponent < IEEE754_DOUBLE_BIAS - DBL_MANT_DIG - 2) { int neg = u.ieee.negative ^ v.ieee.negative; double tiny = neg ? -0x1p-1074 : 0x1p-1074; if (w.ieee.exponent >= 3) return tiny + z; /* Scaling up, adding TINY and scaling down produces the correct result, because in round-to-nearest mode adding TINY has no effect and in other modes double rounding is harmless. But it may not produce required underflow exceptions. */ v.d = z * 0x1p54 + tiny; if (TININESS_AFTER_ROUNDING ? v.ieee.exponent < 55 : (w.ieee.exponent == 0 || (w.ieee.exponent == 1 && w.ieee.negative != neg && w.ieee.mantissa1 == 0 && w.ieee.mantissa0 == 0))) { volatile double force_underflow = x * y; (void) force_underflow; } return v.d * 0x1p-54; } if (u.ieee.exponent + v.ieee.exponent >= 0x7ff + IEEE754_DOUBLE_BIAS - DBL_MANT_DIG) { /* Compute 1p-53 times smaller result and multiply at the end. */ if (u.ieee.exponent > v.ieee.exponent) u.ieee.exponent -= DBL_MANT_DIG; else v.ieee.exponent -= DBL_MANT_DIG; /* If x + y exponent is very large and z exponent is very small, it doesn't matter if we don't adjust it. */ if (w.ieee.exponent > DBL_MANT_DIG) w.ieee.exponent -= DBL_MANT_DIG; adjust = 1; } else if (w.ieee.exponent >= 0x7ff - DBL_MANT_DIG) { /* Similarly. If z exponent is very large and x and y exponents are very small, adjust them up to avoid spurious underflows, rather than down. */ if (u.ieee.exponent + v.ieee.exponent <= IEEE754_DOUBLE_BIAS + DBL_MANT_DIG) { if (u.ieee.exponent > v.ieee.exponent) u.ieee.exponent += 2 * DBL_MANT_DIG + 2; else v.ieee.exponent += 2 * DBL_MANT_DIG + 2; } else if (u.ieee.exponent > v.ieee.exponent) { if (u.ieee.exponent > DBL_MANT_DIG) u.ieee.exponent -= DBL_MANT_DIG; } else if (v.ieee.exponent > DBL_MANT_DIG) v.ieee.exponent -= DBL_MANT_DIG; w.ieee.exponent -= DBL_MANT_DIG; adjust = 1; } else if (u.ieee.exponent >= 0x7ff - DBL_MANT_DIG) { u.ieee.exponent -= DBL_MANT_DIG; if (v.ieee.exponent) v.ieee.exponent += DBL_MANT_DIG; else v.d *= 0x1p53; } else if (v.ieee.exponent >= 0x7ff - DBL_MANT_DIG) { v.ieee.exponent -= DBL_MANT_DIG; if (u.ieee.exponent) u.ieee.exponent += DBL_MANT_DIG; else u.d *= 0x1p53; } else /* if (u.ieee.exponent + v.ieee.exponent <= IEEE754_DOUBLE_BIAS + DBL_MANT_DIG) */ { if (u.ieee.exponent > v.ieee.exponent) u.ieee.exponent += 2 * DBL_MANT_DIG + 2; else v.ieee.exponent += 2 * DBL_MANT_DIG + 2; if (w.ieee.exponent <= 4 * DBL_MANT_DIG + 6) { if (w.ieee.exponent) w.ieee.exponent += 2 * DBL_MANT_DIG + 2; else w.d *= 0x1p108; adjust = -1; } /* Otherwise x * y should just affect inexact and nothing else. */ } x = u.d; y = v.d; z = w.d; } /* Ensure correct sign of exact 0 + 0. */ if (__glibc_unlikely ((x == 0 || y == 0) && z == 0)) return x * y + z; fenv_t env; libc_feholdexcept_setround (&env, FE_TONEAREST); /* Multiplication m1 + m2 = x * y using Dekker's algorithm. */ #define C ((1 << (DBL_MANT_DIG + 1) / 2) + 1) double x1 = x * C; double y1 = y * C; double m1 = x * y; x1 = (x - x1) + x1; y1 = (y - y1) + y1; double x2 = x - x1; double y2 = y - y1; double m2 = (((x1 * y1 - m1) + x1 * y2) + x2 * y1) + x2 * y2; /* Addition a1 + a2 = z + m1 using Knuth's algorithm. */ double a1 = z + m1; double t1 = a1 - z; double t2 = a1 - t1; t1 = m1 - t1; t2 = z - t2; double a2 = t1 + t2; /* Ensure the arithmetic is not scheduled after feclearexcept call. */ math_force_eval (m2); math_force_eval (a2); feclearexcept (FE_INEXACT); /* If the result is an exact zero, ensure it has the correct sign. */ if (a1 == 0 && m2 == 0) { libc_feupdateenv (&env); /* Ensure that round-to-nearest value of z + m1 is not reused. */ z = math_opt_barrier (z); return z + m1; } libc_fesetround (FE_TOWARDZERO); /* Perform m2 + a2 addition with round to odd. */ u.d = a2 + m2; if (__glibc_unlikely (adjust < 0)) { if ((u.ieee.mantissa1 & 1) == 0) u.ieee.mantissa1 |= libc_fetestexcept (FE_INEXACT) != 0; v.d = a1 + u.d; /* Ensure the addition is not scheduled after fetestexcept call. */ math_force_eval (v.d); } /* Reset rounding mode and test for inexact simultaneously. */ int j = libc_feupdateenv_test (&env, FE_INEXACT) != 0; if (__glibc_likely (adjust == 0)) { if ((u.ieee.mantissa1 & 1) == 0 && u.ieee.exponent != 0x7ff) u.ieee.mantissa1 |= j; /* Result is a1 + u.d. */ return a1 + u.d; } else if (__glibc_likely (adjust > 0)) { if ((u.ieee.mantissa1 & 1) == 0 && u.ieee.exponent != 0x7ff) u.ieee.mantissa1 |= j; /* Result is a1 + u.d, scaled up. */ return (a1 + u.d) * 0x1p53; } else { /* If a1 + u.d is exact, the only rounding happens during scaling down. */ if (j == 0) return v.d * 0x1p-108; /* If result rounded to zero is not subnormal, no double rounding will occur. */ if (v.ieee.exponent > 108) return (a1 + u.d) * 0x1p-108; /* If v.d * 0x1p-108 with round to zero is a subnormal above or equal to DBL_MIN / 2, then v.d * 0x1p-108 shifts mantissa down just by 1 bit, which means v.ieee.mantissa1 |= j would change the round bit, not sticky or guard bit. v.d * 0x1p-108 never normalizes by shifting up, so round bit plus sticky bit should be already enough for proper rounding. */ if (v.ieee.exponent == 108) { /* If the exponent would be in the normal range when rounding to normal precision with unbounded exponent range, the exact result is known and spurious underflows must be avoided on systems detecting tininess after rounding. */ if (TININESS_AFTER_ROUNDING) { w.d = a1 + u.d; if (w.ieee.exponent == 109) return w.d * 0x1p-108; } /* v.ieee.mantissa1 & 2 is LSB bit of the result before rounding, v.ieee.mantissa1 & 1 is the round bit and j is our sticky bit. */ w.d = 0.0; w.ieee.mantissa1 = ((v.ieee.mantissa1 & 3) << 1) | j; w.ieee.negative = v.ieee.negative; v.ieee.mantissa1 &= ~3U; v.d *= 0x1p-108; w.d *= 0x1p-2; return v.d + w.d; } v.ieee.mantissa1 |= j; return v.d * 0x1p-108; } }
long double __nextafterl(long double x, long double y) { int32_t ix,iy,esx,esy; uint32_t hx,hy,lx,ly; GET_LDOUBLE_WORDS(esx,hx,lx,x); GET_LDOUBLE_WORDS(esy,hy,ly,y); ix = esx&0x7fff; /* |x| */ iy = esy&0x7fff; /* |y| */ if(((ix==0x7fff)&&((hx&0x7fffffff)|lx)!=0) || /* x is nan */ ((iy==0x7fff)&&((hy&0x7fffffff)|ly)!=0)) /* y is nan */ return x+y; if(x==y) return y; /* x=y, return y */ if((ix|hx|lx)==0) { /* x == 0 */ SET_LDOUBLE_WORDS(x,esy&0x8000,0,1);/* return +-minsubnormal */ y = x*x; math_force_eval (y); /* raise underflow flag */ return x; } if(esx>=0) { /* x > 0 */ if(esx>esy||((esx==esy) && (hx>hy||((hx==hy)&&(lx>ly))))) { /* x > y, x -= ulp */ if(lx==0) { if (ix != 0 && hx == 0x80000000) hx = 0; if (hx==0) esx -= 1; hx -= 1; } lx -= 1; } else { /* x < y, x += ulp */ lx += 1; if(lx==0) { hx += 1; if (hx==0) { hx = 0x80000000; esx += 1; } } } } else { /* x < 0 */ if(esy>=0||esx>esy||((esx==esy) && (hx>hy||((hx==hy)&&(lx>ly))))){ /* x < y, x -= ulp */ if(lx==0) { if (ix != 0 && hx == 0x80000000) hx = 0; if (hx==0) esx -= 1; hx -= 1; } lx -= 1; } else { /* x > y, x += ulp */ lx += 1; if(lx==0) { hx += 1; if (hx==0) { hx = 0x80000000; esx += 1; } } } } esy = esx&0x7fff; if(esy==0x7fff) { long double u = x + x; /* overflow */ math_force_eval (u); __set_errno (ERANGE); } if(esy==0 && (hx & 0x80000000) == 0) { /* underflow */ y = x*x; math_force_eval (y); /* raise underflow flag */ __set_errno (ERANGE); } SET_LDOUBLE_WORDS(x,esx,hx,lx); return x; }
long double __ieee754_asinl (long double x) { long double t, w, p, q, c, r, s; int32_t ix, sign, flag; ieee854_long_double_shape_type u; flag = 0; u.value = x; sign = u.parts32.w0; ix = sign & 0x7fffffff; u.parts32.w0 = ix; /* |x| */ if (ix >= 0x3fff0000) /* |x|>= 1 */ { if (ix == 0x3fff0000 && (u.parts32.w1 | u.parts32.w2 | u.parts32.w3) == 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 < 0x3ffe0000) /* |x| < 0.5 */ { if (ix < 0x3fc60000) /* |x| < 2**-57 */ { if (fabsl (x) < LDBL_MIN) { long double force_underflow = x * x; math_force_eval (force_underflow); } if (huge + x > one) return x; /* return x with inexact if x!=0 */ } else { t = x * x; /* Mark to use pS, qS later on. */ flag = 1; } } else if (ix < 0x3ffe4000) /* 0.625 */ { t = u.value - 0.5625; p = ((((((((((rS10 * t + rS9) * t + rS8) * t + rS7) * t + rS6) * t + rS5) * t + rS4) * t + rS3) * t + rS2) * t + rS1) * t + rS0) * t; q = ((((((((( t + sS9) * t + sS8) * t + sS7) * t + sS6) * t + sS5) * t + sS4) * t + sS3) * t + sS2) * t + sS1) * t + sS0; t = asinr5625 + p / q; if ((sign & 0x80000000) == 0) return t; else return -t; } else { /* 1 > |x| >= 0.625 */ w = one - u.value; t = w * 0.5; } p = (((((((((pS9 * t + pS8) * t + pS7) * t + pS6) * t + pS5) * t + pS4) * t + pS3) * t + pS2) * t + pS1) * t + pS0) * t; q = (((((((( t + qS8) * t + qS7) * t + qS6) * t + qS5) * t + qS4) * t + qS3) * t + qS2) * t + qS1) * t + qS0; if (flag) /* 2^-57 < |x| < 0.5 */ { w = p / q; return x + x * w; } s = __ieee754_sqrtl (t); if (ix >= 0x3ffef333) /* |x| > 0.975 */ { w = p / q; t = pio2_hi - (2.0 * (s + s * w) - pio2_lo); } else { u.value = s; u.parts32.w3 = 0; u.parts32.w2 = 0; w = u.value; 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 ((sign & 0x80000000) == 0) return t; else return -t; }
__complex__ float __clog10f (__complex__ float x) { __complex__ float result; int rcls = fpclassify (__real__ x); int icls = fpclassify (__imag__ x); if (__glibc_unlikely (rcls == FP_ZERO && icls == FP_ZERO)) { /* Real and imaginary part are 0.0. */ __imag__ result = signbit (__real__ x) ? M_PI_LOG10Ef : 0.0; __imag__ result = __copysignf (__imag__ result, __imag__ x); /* Yes, the following line raises an exception. */ __real__ result = -1.0 / fabsf (__real__ x); } else if (__glibc_likely (rcls != FP_NAN && icls != FP_NAN)) { /* Neither real nor imaginary part is NaN. */ float absx = fabsf (__real__ x), absy = fabsf (__imag__ x); int scale = 0; if (absx < absy) { float t = absx; absx = absy; absy = t; } if (absx > FLT_MAX / 2.0f) { scale = -1; absx = __scalbnf (absx, scale); absy = (absy >= FLT_MIN * 2.0f ? __scalbnf (absy, scale) : 0.0f); } else if (absx < FLT_MIN && absy < FLT_MIN) { scale = FLT_MANT_DIG; absx = __scalbnf (absx, scale); absy = __scalbnf (absy, scale); } if (absx == 1.0f && scale == 0) { float absy2 = absy * absy; if (absy2 <= FLT_MIN * 2.0f * (float) M_LN10) { float force_underflow = absy2 * absy2; __real__ result = absy2 * ((float) M_LOG10E / 2.0f); math_force_eval (force_underflow); } else __real__ result = __log1pf (absy2) * ((float) M_LOG10E / 2.0f); } else if (absx > 1.0f && absx < 2.0f && absy < 1.0f && scale == 0) { float d2m1 = (absx - 1.0f) * (absx + 1.0f); if (absy >= FLT_EPSILON) d2m1 += absy * absy; __real__ result = __log1pf (d2m1) * ((float) M_LOG10E / 2.0f); } else if (absx < 1.0f && absx >= 0.75f && absy < FLT_EPSILON / 2.0f && scale == 0) { float d2m1 = (absx - 1.0f) * (absx + 1.0f); __real__ result = __log1pf (d2m1) * ((float) M_LOG10E / 2.0f); } else if (absx < 1.0f && (absx >= 0.75f || absy >= 0.5f) && scale == 0) { float d2m1 = __x2y2m1f (absx, absy); __real__ result = __log1pf (d2m1) * ((float) M_LOG10E / 2.0f); } else { float d = __ieee754_hypotf (absx, absy); __real__ result = __ieee754_log10f (d) - scale * M_LOG10_2f; } __imag__ result = M_LOG10E * __ieee754_atan2f (__imag__ x, __real__ x); } else { __imag__ result = __nanf (""); if (rcls == FP_INFINITE || icls == FP_INFINITE) /* Real or imaginary part is infinite. */ __real__ result = HUGE_VALF; else __real__ result = __nanf (""); } return result; }
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); }
npy_longdouble _nextl(npy_longdouble x, int p) { npy_int64 hx,ihx,ilx; npy_uint64 lx; GET_LDOUBLE_WORDS64(hx, lx, x); ihx = hx & 0x7fffffffffffffffLL; /* |hx| */ ilx = lx & 0x7fffffffffffffffLL; /* |lx| */ if(((ihx & 0x7ff0000000000000LL)==0x7ff0000000000000LL)&& ((ihx & 0x000fffffffffffffLL)!=0)) { return x; /* signal the nan */ } if(ihx == 0 && ilx == 0) { /* x == 0 */ npy_longdouble u; SET_LDOUBLE_WORDS64(x, p, 0ULL);/* return +-minsubnormal */ u = x * x; if (u == x) { return u; } else { return x; /* raise underflow flag */ } } npy_longdouble u; if(p < 0) { /* p < 0, x -= ulp */ if((hx==0xffefffffffffffffLL)&&(lx==0xfc8ffffffffffffeLL)) return x+x; /* overflow, return -inf */ if (hx >= 0x7ff0000000000000LL) { SET_LDOUBLE_WORDS64(u,0x7fefffffffffffffLL,0x7c8ffffffffffffeLL); return u; } if(ihx <= 0x0360000000000000LL) { /* x <= LDBL_MIN */ u = math_opt_barrier (x); x -= LDBL_TRUE_MIN; if (ihx < 0x0360000000000000LL || (hx > 0 && (npy_int64) lx <= 0) || (hx < 0 && (npy_int64) lx > 1)) { u = u * u; math_force_eval (u); /* raise underflow flag */ } return x; } if (ihx < 0x06a0000000000000LL) { /* ulp will denormal */ SET_LDOUBLE_WORDS64(u,(hx&0x7ff0000000000000LL),0ULL); u *= 0x1.0000000000000p-105L; } else SET_LDOUBLE_WORDS64(u,(hx&0x7ff0000000000000LL)-0x0690000000000000LL,0ULL); return x - u; } else { /* p >= 0, x += ulp */ if((hx==0x7fefffffffffffffLL)&&(lx==0x7c8ffffffffffffeLL)) return x+x; /* overflow, return +inf */ if ((npy_uint64) hx >= 0xfff0000000000000ULL) { SET_LDOUBLE_WORDS64(u,0xffefffffffffffffLL,0xfc8ffffffffffffeLL); return u; } if(ihx <= 0x0360000000000000LL) { /* x <= LDBL_MIN */ u = math_opt_barrier (x); x += LDBL_TRUE_MIN; if (ihx < 0x0360000000000000LL || (hx > 0 && (npy_int64) lx < 0 && lx != 0x8000000000000001LL) || (hx < 0 && (npy_int64) lx >= 0)) { u = u * u; math_force_eval (u); /* raise underflow flag */ } if (x == 0.0L) /* handle negative LDBL_TRUE_MIN case */ x = -0.0L; return x; } if (ihx < 0x06a0000000000000LL) { /* ulp will denormal */ SET_LDOUBLE_WORDS64(u,(hx&0x7ff0000000000000LL),0ULL); u *= 0x1.0000000000000p-105L; } else SET_LDOUBLE_WORDS64(u,(hx&0x7ff0000000000000LL)-0x0690000000000000LL,0ULL); return x + u; } }
long double __kernel_standard_l (long double x, long double y, int type) { double dx, dy; struct exception exc; fenv_t env; feholdexcept (&env); dx = x; dy = y; math_force_eval (dx); math_force_eval (dy); fesetenv (&env); switch (type) { case 221: /* powl (x, y) overflow. */ exc.arg1 = dx; exc.arg2 = dy; exc.type = OVERFLOW; exc.name = (char *) "powl"; if (_LIB_VERSION == _SVID_) { exc.retval = HUGE; y *= 0.5; if (x < zero && __rintl (y) != y) exc.retval = -HUGE; } else { exc.retval = HUGE_VAL; y *= 0.5; if (x < zero && __rintl (y) != y) exc.retval = -HUGE_VAL; } if (_LIB_VERSION == _POSIX_) __set_errno (ERANGE); else if (!matherr (&exc)) __set_errno (ERANGE); return exc.retval; case 222: /* powl (x, y) underflow. */ exc.arg1 = dx; exc.arg2 = dy; exc.type = UNDERFLOW; exc.name = (char *) "powl"; exc.retval = zero; y *= 0.5; if (x < zero && __rintl (y) != y) exc.retval = -zero; if (_LIB_VERSION == _POSIX_) __set_errno (ERANGE); else if (!matherr (&exc)) __set_errno (ERANGE); return exc.retval; default: return __kernel_standard (dx, dy, type); } }
long double __nearbyintl (long double x) { fenv_t env; static const long double TWO52 = 4503599627370496.0L; union ibm_extended_long_double u; u.d = x; if (fabs (u.dd[0]) < TWO52) { double high = u.dd[0]; feholdexcept (&env); if (high > 0.0) { high += TWO52; high -= TWO52; if (high == -0.0) high = 0.0; } else if (high < 0.0) { high -= TWO52; high += TWO52; if (high == 0.0) high = -0.0; } u.dd[0] = high; u.dd[1] = 0.0; math_force_eval (u.dd[0]); math_force_eval (u.dd[1]); fesetenv (&env); } else if (fabs (u.dd[1]) < TWO52 && u.dd[1] != 0.0) { double high, low, tau; /* In this case we have to round the low double and handle any adjustment to the high double that may be caused by rounding (up). This is complicated by the fact that the high double may already be rounded and the low double may have the opposite sign to compensate. */ feholdexcept (&env); if (u.dd[0] > 0.0) { if (u.dd[1] > 0.0) { /* If the high/low doubles are the same sign then simply round the low double. */ high = u.dd[0]; low = u.dd[1]; } else if (u.dd[1] < 0.0) { /* Else the high double is pre rounded and we need to adjust for that. */ tau = __nextafter (u.dd[0], 0.0); tau = (u.dd[0] - tau) * 2.0; high = u.dd[0] - tau; low = u.dd[1] + tau; } low += TWO52; low -= TWO52; } else if (u.dd[0] < 0.0) { if (u.dd[1] < 0.0) { /* If the high/low doubles are the same sign then simply round the low double. */ high = u.dd[0]; low = u.dd[1]; } else if (u.dd[1] > 0.0) { /* Else the high double is pre rounded and we need to adjust for that. */ tau = __nextafter (u.dd[0], 0.0); tau = (u.dd[0] - tau) * 2.0; high = u.dd[0] - tau; low = u.dd[1] + tau; } low = TWO52 - low; low = -(low - TWO52); } u.dd[0] = high + low; u.dd[1] = high - u.dd[0] + low; math_force_eval (u.dd[0]); math_force_eval (u.dd[1]); fesetenv (&env); } return u.d; }