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. */ int64_t hx; u_int64_t lx; GET_LDOUBLE_WORDS64 (hx, lx, x); if (((hx | lx) & 0x7fffffffffffffffLL) == 0) { /* Return value for x == 0 is Inf with divide by zero exception. */ *signgamp = 0; return 1.0 / x; } if (hx < 0 && (u_int64_t) hx < 0xfff0000000000000ULL && __rintl (x) == x) { /* Return value for integer x < 0 is NaN with invalid exception. */ *signgamp = 0; return (x - x) / (x - x); } if (hx == 0xfff0000000000000ULL) { /* x == -Inf. According to ISO this is NaN. */ *signgamp = 0; return x - x; } /* XXX FIXME. */ return __ieee754_expl (__ieee754_lgammal_r (x, signgamp)); }
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)); }
invalid_fn (long double x, long double fn) { if (__rintl (fn) != fn) { feraiseexcept (FE_INVALID); return __nan (""); } else if (fn > 65000.0L) return __scalbnl (x, 65000); else return __scalbnl (x,-65000); }
long double __ieee754_gammal_r (long double x, int *signgamp) { int64_t hx; u_int64_t lx; long double ret; GET_LDOUBLE_WORDS64 (hx, lx, x); if (((hx & 0x7fffffffffffffffLL) | lx) == 0) { /* Return value for x == 0 is Inf with divide by zero exception. */ *signgamp = 0; return 1.0 / x; } if (hx < 0 && (u_int64_t) hx < 0xffff000000000000ULL && __rintl (x) == x) { /* Return value for integer x < 0 is NaN with invalid exception. */ *signgamp = 0; return (x - x) / (x - x); } if (hx == 0xffff000000000000ULL && lx == 0) { /* x == -Inf. According to ISO this is NaN. */ *signgamp = 0; return x - x; } if ((hx & 0x7fff000000000000ULL) == 0x7fff000000000000ULL) { /* Positive infinity (return positive infinity) or NaN (return NaN). */ *signgamp = 0; return x + x; } if (x >= 1756.0L) { /* Overflow. */ *signgamp = 0; return LDBL_MAX * LDBL_MAX; } else { SET_RESTORE_ROUNDL (FE_TONEAREST); if (x > 0.0L) { *signgamp = 0; int exp2_adj; ret = gammal_positive (x, &exp2_adj); ret = __scalbnl (ret, exp2_adj); } else if (x >= -LDBL_EPSILON / 4.0L) { *signgamp = 0; ret = 1.0L / x; } else { long double tx = __truncl (x); *signgamp = (tx == 2.0L * __truncl (tx / 2.0L)) ? -1 : 1; if (x <= -1775.0L) /* Underflow. */ ret = LDBL_MIN * LDBL_MIN; else { 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; ret = M_PIl / (-x * sinpix * gammal_positive (-x, &exp2_adj)); ret = __scalbnl (ret, -exp2_adj); } } } if (isinf (ret) && x != 0) { if (*signgamp < 0) return -(-__copysignl (LDBL_MAX, ret) * LDBL_MAX); else return __copysignl (LDBL_MAX, ret) * LDBL_MAX; } else if (ret == 0) { if (*signgamp < 0) return -(-__copysignl (LDBL_MIN, ret) * LDBL_MIN); else return __copysignl (LDBL_MIN, ret) * LDBL_MIN; } else return ret; }
long double __kernel_standard_l (long double x, long double y, int type) { double dx, dy; struct exception exc; if (isfinite (x)) { long double ax = fabsl (x); if (ax > DBL_MAX) dx = __copysignl (DBL_MAX, x); else if (ax > 0 && ax < DBL_MIN) dx = __copysignl (DBL_MIN, x); else dx = x; } else dx = x; if (isfinite (y)) { long double ay = fabsl (y); if (ay > DBL_MAX) dy = __copysignl (DBL_MAX, y); else if (ay > 0 && ay < DBL_MIN) dy = __copysignl (DBL_MIN, y); else dy = y; } else dy = y; switch (type) { case 221: /* powl (x, y) overflow. */ exc.arg1 = dx; exc.arg2 = dy; exc.type = OVERFLOW; exc.name = "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 = "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 __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 __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); } }