__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; }
int ilogbq (__float128 x) { int64_t hx,lx; int ix; GET_FLT128_WORDS64(hx,lx,x); hx &= 0x7fffffffffffffffLL; if(hx <= 0x0001000000000000LL) { if((hx|lx)==0) { errno = EDOM; #ifdef USE_FENV_H feraiseexcept (FE_INVALID); #endif return FP_ILOGB0; /* ilogbl(0) = FP_ILOGB0 */ } else /* subnormal x */ if(hx==0) { for (ix = -16431; lx>0; lx<<=1) ix -=1; } else { for (ix = -16382, hx<<=15; hx>0; hx<<=1) ix -=1; } return ix; } else if (hx<0x7fff000000000000LL) return (hx>>48)-0x3fff; else if (FP_ILOGBNAN != INT_MAX) {
int isnanq (const __float128 x) { int64_t hx,lx; GET_FLT128_WORDS64(hx,lx,x); hx &= 0x7fffffffffffffffLL; hx |= (uint64_t)(lx|(-lx))>>63; hx = 0x7fff000000000000LL - hx; return (int)((uint64_t)hx>>63); }
__float128 frexpq (__float128 x, int *eptr) { uint64_t hx, lx, ix; GET_FLT128_WORDS64(hx,lx,x); ix = 0x7fffffffffffffffULL&hx; *eptr = 0; if(ix>=0x7fff000000000000ULL||((ix|lx)==0)) return x; /* 0,inf,nan */ if (ix<0x0001000000000000ULL) { /* subnormal */ x *= two114; GET_FLT128_MSW64(hx,x); ix = hx&0x7fffffffffffffffULL; *eptr = -114; } *eptr += (ix>>48)-16382; hx = (hx&0x8000ffffffffffffULL) | 0x3ffe000000000000ULL; SET_FLT128_MSW64(x,hx); return x; }
__float128 log2q (__float128 x) { __float128 z; __float128 y; int e; int64_t hx, lx; /* Test for domain */ GET_FLT128_WORDS64 (hx, lx, x); if (((hx & 0x7fffffffffffffffLL) | lx) == 0) return (-1.0Q / fabsq (x)); /* log2l(+-0)=-inf */ if (hx < 0) return (x - x) / (x - x); if (hx >= 0x7fff000000000000LL) return (x + x); if (x == 1.0Q) return 0.0Q; /* separate mantissa from exponent */ /* Note, frexp is used so that denormal numbers * will be handled properly. */ x = frexpq (x, &e); /* logarithm using log(x) = z + z**3 P(z)/Q(z), * where z = 2(x-1)/x+1) */ if ((e > 2) || (e < -2)) { if (x < SQRTH) { /* 2( 2x-1 )/( 2x+1 ) */ e -= 1; z = x - 0.5Q; y = 0.5Q * z + 0.5Q; } else { /* 2 (x-1)/(x+1) */ z = x - 0.5Q; z -= 0.5Q; y = 0.5Q * x + 0.5Q; } x = z / y; z = x * x; y = x * (z * neval (z, R, 5) / deval (z, S, 5)); goto done; } /* logarithm using log(1+x) = x - .5x**2 + x**3 P(x)/Q(x) */ if (x < SQRTH) { e -= 1; x = 2.0 * x - 1.0Q; /* 2x - 1 */ } else { x = x - 1.0Q; } z = x * x; y = x * (z * neval (x, P, 12) / deval (x, Q, 11)); y = y - 0.5 * z; done: /* Multiply log of fraction by log2(e) * and base 2 exponent by 1 */ z = y * LOG2EA; z += x * LOG2EA; z += y; z += x; z += e; return (z); }
__float128 remquoq (__float128 x, __float128 y, int *quo) { int64_t hx,hy; uint64_t sx,lx,ly,qs; int cquo; GET_FLT128_WORDS64 (hx, lx, x); GET_FLT128_WORDS64 (hy, ly, y); sx = hx & 0x8000000000000000ULL; qs = sx ^ (hy & 0x8000000000000000ULL); hy &= 0x7fffffffffffffffLL; hx &= 0x7fffffffffffffffLL; /* Purge off exception values. */ if ((hy | ly) == 0) return (x * y) / (x * y); /* y = 0 */ if ((hx >= 0x7fff000000000000LL) /* x not finite */ || ((hy >= 0x7fff000000000000LL) /* y is NaN */ && (((hy - 0x7fff000000000000LL) | ly) != 0))) return (x * y) / (x * y); if (hy <= 0x7ffbffffffffffffLL) x = fmodq (x, 8 * y); /* now x < 8y */ if (((hx - hy) | (lx - ly)) == 0) { *quo = qs ? -1 : 1; return zero * x; } x = fabsq (x); y = fabsq (y); cquo = 0; if (hy <= 0x7ffcffffffffffffLL && x >= 4 * y) { x -= 4 * y; cquo += 4; } if (hy <= 0x7ffdffffffffffffLL && x >= 2 * y) { x -= 2 * y; cquo += 2; } if (hy < 0x0002000000000000LL) { if (x + x > y) { x -= y; ++cquo; if (x + x >= y) { x -= y; ++cquo; } } } else { __float128 y_half = 0.5Q * y; if (x > y_half) { x -= y; ++cquo; if (x >= y_half) { x -= y; ++cquo; } } } *quo = qs ? -cquo : cquo; /* Ensure correct sign of zero result in round-downward mode. */ if (x == 0.0Q) x = 0.0Q; if (sx) x = -x; return x; }