int totalorderl (long double x, long double y) { int16_t expx, expy; uint32_t hx, hy; uint32_t lx, ly; GET_LDOUBLE_WORDS (expx, hx, lx, x); GET_LDOUBLE_WORDS (expy, hy, ly, y); if (LDBL_MIN_EXP == -16382) { /* M68K variant: for the greatest exponent, the high mantissa bit is not significant and both values of it are valid, so set it before comparing. For the Intel variant, only one value of the high mantissa bit is valid for each exponent, so this is not necessary. */ if ((expx & 0x7fff) == 0x7fff) hx |= 0x80000000; if ((expy & 0x7fff) == 0x7fff) hy |= 0x80000000; } #ifdef HIGH_ORDER_BIT_IS_SET_FOR_SNAN # error not implemented #endif uint32_t x_sign = expx >> 15; uint32_t y_sign = expy >> 15; expx ^= x_sign >> 17; hx ^= x_sign; lx ^= x_sign; expy ^= y_sign >> 17; hy ^= y_sign; ly ^= y_sign; return expx < expy || (expx == expy && (hx < hy || (hx == hy && lx <= ly))); }
long double __tanl(long double x) { long double y[2],z=0.0; int32_t n, se, i0, i1; /* High word of x. */ GET_LDOUBLE_WORDS(se,i0,i1,x); /* |x| ~< pi/4 */ se &= 0x7fff; if(se <= 0x3ffe) return __kernel_tanl(x,z,1); /* tan(Inf or NaN) is NaN */ else if (se==0x7fff) { if (i1 == 0 && i0 == 0x80000000) __set_errno (EDOM); return x-x; } /* argument reduction needed */ else { n = __ieee754_rem_pio2l(x,y); return __kernel_tanl(y[0],y[1],1-((n&1)<<1)); /* 1 -- n even -1 -- n odd */ } }
long double __ieee754_gammal_r (long double x, int *signgamp) { /* We don't have a real gamma implementation now. We'll use lgamma and the exp function. But due to the required boundary conditions we must check some values separately. */ u_int32_t es, hx, lx; GET_LDOUBLE_WORDS (es, hx, lx, x); if (((es & 0x7fff) | hx | lx) == 0) { /* Return value for x == 0 is NaN with invalid exception. */ *signgamp = 0; return x / x; } if (es == 0xffffffff && ((hx & 0x7fffffff) | lx) == 0) { /* x == -Inf. According to ISO this is NaN. */ *signgamp = 0; return x - x; } if ((es & 0x7fff) == 0x7fff && ((hx & 0x7fffffff) | lx) != 0) /* NaN, return it. */ return x; if ((es & 0x8000) != 0 && x < 0xffffffff && __rintl (x) == x) { /* Return value for integer x < 0 is NaN with invalid exception. */ *signgamp = 0; return (x - x) / (x - x); } /* XXX FIXME. */ return __ieee754_expl (__ieee754_lgammal_r (x, signgamp)); }
int __isinf_nsl (long double x) { int32_t se,hx,lx; GET_LDOUBLE_WORDS(se,hx,lx,x); return !(((se & 0x7fff) ^ 0x7fff) | lx | (hx & 0x7fffffff)); }
long long int __llrintl (long double x) { int32_t e, s; u_int32_t h, l; long long int result; x = __m81_u(__rintl) (x); GET_LDOUBLE_WORDS (e, h, l, x); s = e; e = (e & 0x7fff) - 0x3fff; if (e < 0) return 0; if (e < 63) { if (e > 31) { l >>= 63 - e; l |= h << (e - 31); h >>= 63 - e; result = ((long long int) h << 32) | l; } else
long double __cosl(long double x) { long double y[2],z=0.0; int32_t n, se, i0, i1; /* High word of x. */ GET_LDOUBLE_WORDS(se,i0,i1,x); /* |x| ~< pi/4 */ se &= 0x7fff; if(se < 0x3ffe || (se == 0x3ffe && i0 <= 0xc90fdaa2)) return __kernel_cosl(x,z); /* cos(Inf or NaN) is NaN */ else if (se==0x7fff) { if (i1 == 0 && i0 == 0x80000000) __set_errno (EDOM); return x-x; } /* argument reduction needed */ else { n = __ieee754_rem_pio2l(x,y); switch(n&3) { case 0: return __kernel_cosl(y[0],y[1]); case 1: return -__kernel_sinl(y[0],y[1],1); case 2: return -__kernel_cosl(y[0],y[1]); default: return __kernel_sinl(y[0],y[1],1); } } }
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; }
long double erfl(long double x) { long double R, S, P, Q, s, y, z, r; int32_t ix, i; uint32_t se, i0, i1; GET_LDOUBLE_WORDS(se, i0, i1, x); ix = se & 0x7fff; if (ix >= 0x7fff) { /* erf(nan)=nan */ i = ((se & 0xffff) >> 15) << 1; return (long double)(1 - i) + 1.0 / x; /* erf(+-inf)=+-1 */ }
void __sincosl (long double x, long double *sinx, long double *cosx) { int32_t se, i0, i1 __attribute__ ((unused)); /* High word of x. */ GET_LDOUBLE_WORDS (se, i0, i1, x); /* |x| ~< pi/4 */ se &= 0x7fff; if (se < 0x3ffe || (se == 0x3ffe && i0 <= 0xc90fdaa2)) { *sinx = __kernel_sinl (x, 0.0, 0); *cosx = __kernel_cosl (x, 0.0); } else if (se == 0x7fff) { /* sin(Inf or NaN) is NaN */ *sinx = *cosx = x - x; if (isinf (x)) __set_errno (EDOM); } else { /* Argument reduction needed. */ long double y[2]; int n; n = __ieee754_rem_pio2l (x, y); switch (n & 3) { case 0: *sinx = __kernel_sinl (y[0], y[1], 1); *cosx = __kernel_cosl (y[0], y[1]); break; case 1: *sinx = __kernel_cosl (y[0], y[1]); *cosx = -__kernel_sinl (y[0], y[1], 1); break; case 2: *sinx = -__kernel_sinl (y[0], y[1], 1); *cosx = -__kernel_cosl (y[0], y[1]); break; default: *sinx = -__kernel_cosl (y[0], y[1]); *cosx = __kernel_sinl (y[0], y[1], 1); break; } } }
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_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; }
int __fpclassifyl (long double x) { u_int32_t ex, hx, lx; int retval = FP_NORMAL; GET_LDOUBLE_WORDS (ex, hx, lx, x); ex &= 0x7fff; if ((ex | hx | lx) == 0) retval = FP_ZERO; else if (ex == 0 && (hx & 0x80000000) == 0) retval = FP_SUBNORMAL; else if (ex == 0x7fff) retval = ((hx & 0x7fffffff) | lx) != 0 ? FP_NAN : FP_INFINITE; return retval; }
long double __frexpl(long double x, int *eptr) { u_int32_t se, hx, ix, lx; GET_LDOUBLE_WORDS(se,hx,lx,x); ix = 0x7fff&se; *eptr = 0; if(ix==0x7fff||((ix|hx|lx)==0)) return x + x; /* 0,inf,nan */ if (ix==0x0000) { /* subnormal */ x *= two65; GET_LDOUBLE_EXP(se,x); ix = se&0x7fff; *eptr = -65; } *eptr += ix-16382; se = (se & 0x8000) | 0x3ffe; SET_LDOUBLE_EXP(x,se); return x; }
long double coshl(long double x) { long double t,w; int32_t ex; u_int32_t mx,lx; /* High word of |x|. */ GET_LDOUBLE_WORDS(ex,mx,lx,x); ex &= 0x7fff; /* x is INF or NaN */ if(ex==0x7fff) return x*x; /* |x| in [0,0.5*ln2], return 1+expm1l(|x|)^2/(2*expl(|x|)) */ if(ex < 0x3ffd || (ex == 0x3ffd && mx < 0xb17217f7u)) { t = expm1l(fabsl(x)); w = one+t; if (ex<0x3fbc) 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 (ex < 0x4003 || (ex == 0x4003 && mx < 0xb0000000u)) { t = expl(fabsl(x)); return half*t+half/t; } /* |x| in [22, ln(maxdouble)] return half*exp(|x|) */ if (ex < 0x400c || (ex == 0x400c && mx < 0xb1700000u)) return half*expl(fabsl(x)); /* |x| in [log(maxdouble), log(2*maxdouble)) */ if (ex == 0x400c && (mx < 0xb174ddc0u || (mx == 0xb174ddc0u && lx < 0x31aec0ebu))) { w = expl(half*fabsl(x)); t = half*w; return t*w; } /* |x| >= log(2*maxdouble), cosh(x) overflow */ return huge*huge; }
int __issignalingl (long double x) { u_int32_t exi, hxi, lxi; GET_LDOUBLE_WORDS (exi, hxi, lxi, x); #ifdef HIGH_ORDER_BIT_IS_SET_FOR_SNAN # error not implemented #else /* 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 ^= 0x40000000; /* If lxi != 0, then set any suitable bit of the significand in hxi. */ hxi |= (lxi | -lxi) >> 31; /* We do not recognize a pseudo NaN as sNaN; they're invalid on 80387 and later. */ /* We have to compare for greater (instead of greater or equal), because x's significand being all-zero designates infinity not NaN. */ return ((exi & 0x7fff) == 0x7fff) && (hxi > 0xc0000000); #endif }
long double __logbl (long double x) { int32_t es, lx, ix; GET_LDOUBLE_WORDS (es, ix, lx, x); es &= 0x7fff; /* exponent */ if ((es | ix | lx) == 0) return -1.0 / fabsl (x); if (es == 0x7fff) return x * x; if (es == 0) /* IEEE 754 logb */ { /* POSIX specifies that denormal number is treated as though it were normalized. */ if (ix == 0) es = -(__builtin_clz (lx) + 32); else es = -__builtin_clz (ix); } return (long double) (es - 16383); }
long double acoshl(long double x) { long double t; uint32_t se,i0,i1; GET_LDOUBLE_WORDS(se, i0, i1, x); if (se < 0x3fff || se & 0x8000) { /* x < 1 */ return (x-x)/(x-x); } else if (se >= 0x401d) { /* x > 2**30 */ if (se >= 0x7fff) /* x is inf or NaN */ return x+x; return logl(x) + ln2; /* acoshl(huge) = logl(2x) */ } else if (((se-0x3fff)|i0|i1) == 0) { return 0.0; /* acosh(1) = 0 */ } else if (se > 0x4000) { /* x > 2 */ t = x*x; return logl(2.0*x - 1.0/(x + sqrtl(t - 1.0))); } /* 1 < x <= 2 */ t = x - 1.0; return log1pl(t + sqrtl(2.0*t + t*t)); }
long double truncl(long double x) { int e, es; uint32_t ix0, ix1; GET_LDOUBLE_WORDS(es,ix0,ix1,x); e = (es&0x7fff) - LDBL_MAX_EXP + 1; if (e < MANH_SIZE - 1) { if (e < 0) { /* raise inexact if x != 0 */ if (huge + x > 0.0) return (zero[(es&0x8000)!=0]); } else { uint64_t m = ((1llu << MANH_SIZE) - 1) >> (e + 1); if (((ix0 & m) | ix1) == 0) return (x); /* x is integral */ if (huge + x > 0.0) { /* raise inexact flag */ ix0 &= ~m; ix1 = 0; } } } else if (e < LDBL_MANT_DIG - 1) {
long double __modfl(long double x, long double *iptr) { int32_t i0,i1,j0; u_int32_t i,se; GET_LDOUBLE_WORDS(se,i0,i1,x); j0 = (se&0x7fff)-0x3fff; /* exponent of x */ if(j0<32) { /* integer part in high x */ if(j0<0) { /* |x|<1 */ SET_LDOUBLE_WORDS(*iptr,se&0x8000,0,0); /* *iptr = +-0 */ return x; } else { i = (0x7fffffff)>>j0; if(((i0&i)|i1)==0) { /* x is integral */ *iptr = x; SET_LDOUBLE_WORDS(x,se&0x8000,0,0); /* return +-0 */ return x; } else { SET_LDOUBLE_WORDS(*iptr,se,i0&(~i),0); return x - *iptr; } } } else if (__builtin_expect(j0>63, 0)) { /* no fraction part */
long double __nextafterl(long double x, long double y) { u_int32_t hx,hy,ix,iy; u_int32_t lx,ly; int32_t esx,esy; GET_LDOUBLE_WORDS(esx,hx,lx,x); GET_LDOUBLE_WORDS(esy,hy,ly,y); ix = esx&0x7fff; /* |x| */ iy = esy&0x7fff; /* |y| */ /* Intel's extended format has the normally implicit 1 explicit present. Sigh! */ 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 */ long double u; SET_LDOUBLE_WORDS(x,esy&0x8000,0,1);/* return +-minsubnormal */ u = math_opt_barrier (x); u = u * u; math_force_eval (u); /* 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 (hx <= 0x80000000) { if (esx == 0) { --hx; } else { esx -= 1; hx = hx - 1; if (esx > 0) hx |= 0x80000000; } } else hx -= 1; } lx -= 1; } else { /* x < y, x += ulp */ lx += 1; if(lx==0) { hx += 1; if (hx==0 || (esx == 0 && hx == 0x80000000)) { esx += 1; hx |= 0x80000000; } } } } else { /* x < 0 */ if(esy>=0||(esx>esy||((esx==esy)&&(hx>hy||((hx==hy)&&(lx>ly)))))){ /* x < y, x -= ulp */ if(lx==0) { if (hx <= 0x80000000 && esx != 0xffff8000) { esx -= 1; hx = hx - 1; if ((esx&0x7fff) > 0) hx |= 0x80000000; } else hx -= 1; } lx -= 1; } else { /* x > y, x += ulp */ lx += 1; if(lx==0) { hx += 1; if (hx==0 || (esx == 0xffff8000 && hx == 0x80000000)) { esx += 1; hx |= 0x80000000; } } } } esy = esx&0x7fff; if(esy==0x7fff) { long double u = x + x; /* overflow */ math_force_eval (u); __set_errno (ERANGE); } if(esy==0) { long double u = x*x; /* underflow */ math_force_eval (u); /* raise underflow flag */ __set_errno (ERANGE); } SET_LDOUBLE_WORDS(x,esx,hx,lx); return x; }
long double __ieee754_gammal_r (long double x, int *signgamp) { u_int32_t es, hx, lx; GET_LDOUBLE_WORDS (es, hx, lx, x); if (__glibc_unlikely (((es & 0x7fff) | hx | lx) == 0)) { /* Return value for x == 0 is Inf with divide by zero exception. */ *signgamp = 0; return 1.0 / x; } if (__glibc_unlikely (es == 0xffffffff && ((hx & 0x7fffffff) | lx) == 0)) { /* x == -Inf. According to ISO this is NaN. */ *signgamp = 0; return x - x; } if (__glibc_unlikely ((es & 0x7fff) == 0x7fff)) { /* Positive infinity (return positive infinity) or NaN (return NaN). */ *signgamp = 0; return x + x; } if (__builtin_expect ((es & 0x8000) != 0, 0) && __rintl (x) == x) { /* Return value for integer x < 0 is NaN with invalid exception. */ *signgamp = 0; return (x - x) / (x - x); } if (x >= 1756.0L) { /* Overflow. */ *signgamp = 0; return LDBL_MAX * LDBL_MAX; } else if (x > 0.0L) { *signgamp = 0; int exp2_adj; long double ret = gammal_positive (x, &exp2_adj); return __scalbnl (ret, exp2_adj); } else if (x >= -LDBL_EPSILON / 4.0L) { *signgamp = 0; return 1.0f / x; } else { long double tx = __truncl (x); *signgamp = (tx == 2.0L * __truncl (tx / 2.0L)) ? -1 : 1; if (x <= -1766.0L) /* Underflow. */ return LDBL_MIN * LDBL_MIN; long double frac = tx - x; if (frac > 0.5L) frac = 1.0L - frac; long double sinpix = (frac <= 0.25L ? __sinl (M_PIl * frac) : __cosl (M_PIl * (0.5L - frac))); int exp2_adj; long double ret = M_PIl / (-x * sinpix * gammal_positive (-x, &exp2_adj)); return __scalbnl (ret, -exp2_adj); } }
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 __roundevenl (long double x) { uint16_t se; uint32_t hx, lx; GET_LDOUBLE_WORDS (se, hx, lx, x); int exponent = se & 0x7fff; if (exponent >= BIAS + MANT_DIG - 1) { /* Integer, infinity or NaN. */ if (exponent == MAX_EXP) /* Infinity or NaN; quiet signaling NaNs. */ return x + x; else return x; } else if (exponent >= BIAS + MANT_DIG - 32) { /* Not necessarily an integer; integer bit is in low word. Locate the bits with exponents 0 and -1. */ int int_pos = (BIAS + MANT_DIG - 1) - exponent; int half_pos = int_pos - 1; uint32_t half_bit = 1U << half_pos; uint32_t int_bit = 1U << int_pos; if ((lx & (int_bit | (half_bit - 1))) != 0) { /* No need to test whether HALF_BIT is set. */ lx += half_bit; if (lx < half_bit) { hx++; if (hx == 0) { hx = 0x80000000; se++; } } } lx &= ~(int_bit - 1); } else if (exponent == BIAS + MANT_DIG - 33) { /* Not necessarily an integer; integer bit is bottom of high word, half bit is top of low word. */ if (((hx & 1) | (lx & 0x7fffffff)) != 0) { lx += 0x80000000; if (lx < 0x80000000) { hx++; if (hx == 0) { hx = 0x80000000; se++; } } } lx = 0; } else if (exponent >= BIAS) { /* At least 1; not necessarily an integer, integer bit and half bit are in the high word. Locate the bits with exponents 0 and -1. */ int int_pos = (BIAS + MANT_DIG - 33) - exponent; int half_pos = int_pos - 1; uint32_t half_bit = 1U << half_pos; uint32_t int_bit = 1U << int_pos; if (((hx & (int_bit | (half_bit - 1))) | lx) != 0) { hx += half_bit; if (hx < half_bit) { hx = 0x80000000; se++; } } hx &= ~(int_bit - 1); lx = 0; } else if (exponent == BIAS - 1 && (hx > 0x80000000 || lx != 0)) { /* Interval (0.5, 1). */ se = (se & 0x8000) | 0x3fff; hx = 0x80000000; lx = 0; } else { /* Rounds to 0. */ se &= 0x8000; hx = 0; lx = 0; } SET_LDOUBLE_WORDS (x, se, hx, lx); return x; }
long double nextafterl(long double x, long double y) { int32_t hx,hy,ix,iy; u_int32_t lx,ly,esx,esy; 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 */ volatile long double u; SET_LDOUBLE_WORDS(x,esy&0x8000,0,1);/* return +-minsubnormal */ u = x; u = u * u; /* raise underflow flag */ return x; } if(esx<0x8000) { /* x > 0 */ if(ix>iy||((ix==iy) && (hx>hy||((hx==hy)&&(lx>ly))))) { /* x > y, x -= ulp */ if(lx==0) { if ((hx&0x7fffffff)==0) esx -= 1; hx = (hx - 1) | (hx & 0x80000000); } lx -= 1; } else { /* x < y, x += ulp */ lx += 1; if(lx==0) { hx = (hx + 1) | (hx & 0x80000000); if ((hx&0x7fffffff)==0) esx += 1; } } } else { /* x < 0 */ if(esy>=0||(ix>iy||((ix==iy)&&(hx>hy||((hx==hy)&&(lx>ly)))))){ /* x < y, x -= ulp */ if(lx==0) { if ((hx&0x7fffffff)==0) esx -= 1; hx = (hx - 1) | (hx & 0x80000000); } lx -= 1; } else { /* x > y, x += ulp */ lx += 1; if(lx==0) { hx = (hx + 1) | (hx & 0x80000000); if ((hx&0x7fffffff)==0) esx += 1; } } } esy = esx&0x7fff; if(esy==0x7fff) return x+x; /* overflow */ if(esy==0) { volatile long double u = x*x; /* underflow */ if(u==x) { SET_LDOUBLE_WORDS(x,esx,hx,lx); return x; } } SET_LDOUBLE_WORDS(x,esx,hx,lx); return x; }
long double __ieee754_hypotl(long double x, long double y) { long double a,b,t1,t2,y1,y2,w; u_int32_t j,k,ea,eb; GET_LDOUBLE_EXP(ea,x); ea &= 0x7fff; GET_LDOUBLE_EXP(eb,y); eb &= 0x7fff; if(eb > ea) {a=y;b=x;j=ea; ea=eb;eb=j;} else {a=x;b=y;} SET_LDOUBLE_EXP(a,ea); /* a <- |a| */ SET_LDOUBLE_EXP(b,eb); /* b <- |b| */ if((ea-eb)>0x46) {return a+b;} /* x/y > 2**70 */ k=0; if(__builtin_expect(ea > 0x5f3f,0)) { /* a>2**8000 */ if(ea == 0x7fff) { /* Inf or NaN */ u_int32_t exp __attribute__ ((unused)); u_int32_t high,low; w = a+b; /* for sNaN */ GET_LDOUBLE_WORDS(exp,high,low,a); if(((high&0x7fffffff)|low)==0) w = a; GET_LDOUBLE_WORDS(exp,high,low,b); if(((eb^0x7fff)|(high&0x7fffffff)|low)==0) w = b; return w; } /* scale a and b by 2**-9600 */ ea -= 0x2580; eb -= 0x2580; k += 9600; SET_LDOUBLE_EXP(a,ea); SET_LDOUBLE_EXP(b,eb); } if(__builtin_expect(eb < 0x20bf, 0)) { /* b < 2**-8000 */ if(eb == 0) { /* subnormal b or 0 */ u_int32_t exp __attribute__ ((unused)); u_int32_t high,low; GET_LDOUBLE_WORDS(exp,high,low,b); if((high|low)==0) return a; SET_LDOUBLE_WORDS(t1, 0x7ffd, 0x80000000, 0); /* t1=2^16382 */ b *= t1; a *= t1; k -= 16382; GET_LDOUBLE_EXP (ea, a); GET_LDOUBLE_EXP (eb, b); if (eb > ea) { t1 = a; a = b; b = t1; j = ea; ea = eb; eb = j; } } else { /* scale a and b by 2^9600 */ ea += 0x2580; /* a *= 2^9600 */ eb += 0x2580; /* b *= 2^9600 */ k -= 9600; SET_LDOUBLE_EXP(a,ea); SET_LDOUBLE_EXP(b,eb); } } /* medium size a and b */ w = a-b; if (w>b) { u_int32_t high; GET_LDOUBLE_MSW(high,a); SET_LDOUBLE_WORDS(t1,ea,high,0); t2 = a-t1; w = __ieee754_sqrtl(t1*t1-(b*(-b)-t2*(a+t1))); } else { u_int32_t high; GET_LDOUBLE_MSW(high,b); a = a+a; SET_LDOUBLE_WORDS(y1,eb,high,0); y2 = b - y1; GET_LDOUBLE_MSW(high,a); SET_LDOUBLE_WORDS(t1,ea+1,high,0); t2 = a - t1; w = __ieee754_sqrtl(t1*y1-(w*(-w)-(t1*y2+t2*b))); } if(k!=0) { u_int32_t exp; t1 = 1.0; GET_LDOUBLE_EXP(exp,t1); SET_LDOUBLE_EXP(t1,exp+k); w *= t1; math_check_force_underflow_nonneg (w); return w; } else return w; }
long double hypotl(long double x, long double y) { long double a,b,t1,t2,yy1,y2,w; u_int32_t j,k,ea,eb; GET_LDOUBLE_EXP(ea,x); ea &= 0x7fff; GET_LDOUBLE_EXP(eb,y); eb &= 0x7fff; if(eb > ea) {a=y;b=x;j=ea; ea=eb;eb=j;} else {a=x;b=y;} SET_LDOUBLE_EXP(a,ea); /* a <- |a| */ SET_LDOUBLE_EXP(b,eb); /* b <- |b| */ if((ea-eb)>0x46) {return a+b;} /* x/y > 2**70 */ k=0; if(ea > 0x5f3f) { /* a>2**8000 */ if(ea == 0x7fff) { /* Inf or NaN */ u_int32_t es,high,low; w = a+b; /* for sNaN */ GET_LDOUBLE_WORDS(es,high,low,a); if(((high&0x7fffffff)|low)==0) w = a; GET_LDOUBLE_WORDS(es,high,low,b); if(((eb^0x7fff)|(high&0x7fffffff)|low)==0) w = b; return w; } /* scale a and b by 2**-9600 */ ea -= 0x2580; eb -= 0x2580; k += 9600; SET_LDOUBLE_EXP(a,ea); SET_LDOUBLE_EXP(b,eb); } if(eb < 0x20bf) { /* b < 2**-8000 */ if(eb == 0) { /* subnormal b or 0 */ u_int32_t es,high,low; GET_LDOUBLE_WORDS(es,high,low,b); if((high|low)==0) return a; SET_LDOUBLE_WORDS(t1, 0x7ffd, 0, 0); /* t1=2^16382 */ b *= t1; a *= t1; k -= 16382; } else { /* scale a and b by 2^9600 */ ea += 0x2580; /* a *= 2^9600 */ eb += 0x2580; /* b *= 2^9600 */ k -= 9600; SET_LDOUBLE_EXP(a,ea); SET_LDOUBLE_EXP(b,eb); } } /* medium size a and b */ w = a-b; if (w>b) { u_int32_t high; GET_LDOUBLE_MSW(high,a); SET_LDOUBLE_WORDS(t1,ea,high,0); t2 = a-t1; w = sqrtl(t1*t1-(b*(-b)-t2*(a+t1))); } else { u_int32_t high; GET_LDOUBLE_MSW(high,b); a = a+a; SET_LDOUBLE_WORDS(yy1,eb,high,0); y2 = b - yy1; GET_LDOUBLE_MSW(high,a); SET_LDOUBLE_WORDS(t1,ea+1,high,0); t2 = a - t1; w = sqrtl(t1*yy1-(w*(-w)-(t1*y2+t2*b))); } if(k!=0) { u_int32_t es; t1 = 1.0; GET_LDOUBLE_EXP(es,t1); SET_LDOUBLE_EXP(t1,es+k); return t1*w; } else return w; }