From 41bf21a1e72c907b1a065727c3b5da43821ca6b0 Mon Sep 17 00:00:00 2001 From: Joseph Myers Date: Wed, 28 Mar 2012 09:32:12 +0000 Subject: [PATCH] Avoid overflows from long double functions using __kernel_standard. --- ChangeLog | 63 +++++++++++++++++++++++++++++++++++++++ NEWS | 5 ++-- math/libm-test.inc | 42 +++++++++++++++++++++++--- math/w_acoshl.c | 2 +- math/w_acosl.c | 2 +- math/w_asinl.c | 2 +- math/w_atan2l.c | 4 +-- math/w_atanhl.c | 8 ++--- math/w_coshl.c | 2 +- math/w_exp10l.c | 4 +-- math/w_exp2l.c | 2 +- math/w_fmodl.c | 4 +-- math/w_hypotl.c | 2 +- math/w_j0l.c | 8 ++--- math/w_j1l.c | 8 ++--- math/w_jnl.c | 8 ++--- math/w_lgammal.c | 8 ++--- math/w_log10l.c | 4 +-- math/w_log2l.c | 4 +-- math/w_logl.c | 4 +-- math/w_powl.c | 16 +++++----- math/w_remainderl.c | 4 +-- math/w_scalbl.c | 6 ++-- math/w_sinhl.c | 2 +- math/w_sqrtl.c | 2 +- math/w_tgammal.c | 6 ++-- sysdeps/generic/math_private.h | 1 + sysdeps/ieee754/k_standard.c | 32 ++++++++++++++++++++ sysdeps/ieee754/ldbl-128/w_expl.c | 4 +-- sysdeps/ieee754/ldbl-96/w_expl.c | 4 +-- 30 files changed, 197 insertions(+), 66 deletions(-) diff --git a/ChangeLog b/ChangeLog index ad72281..2d4beb4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,66 @@ +2012-03-28 Joseph Myers + + [BZ #13879] + [BZ #13910] + [BZ #13911] + [BZ #13912] + [BZ #13913] + [BZ #13915] + [BZ #13916] + [BZ #13917] + [BZ #13918] + [BZ #13919] + [BZ #13920] + [BZ #13921] + * sysdeps/generic/math_private.h (__kernel_standard_l): Declare. + * sysdeps/ieee754/k_standard.c: Include . + (__kernel_standard_l): New function. + * math/w_acoshl.c (__acoshl): Use __kernel_standard_l instead of + __kernel_standard. + * math/w_acosl.c (__acosl): Likewise. + * math/w_asinl.c (__asinl): Likewise. + * math/w_atan2l.c (__atan2l): Likewise. + * math/w_atanhl.c (__atanhl): Likewise. + * math/w_coshl.c (__coshl): Likewise. + * math/w_exp10l.c (__exp10l): Likewise. + * math/w_exp2l.c (__exp2l): Likewise. + * math/w_fmodl.c (__fmodl): Likewise. + * math/w_hypotl.c (__hypotl): Likewise. + * math/w_j0l.c (__j0l, __y0l): Likewise. + * math/w_j1l.c (__j1l, __y1l): Likewise. + * math/w_jnl.c (__jnl, __ynl): Likewise. + * math/w_lgammal.c (__lgammal): Likewise. + * math/w_log10l.c (__log10l): Likewise. + * math/w_log2l.c (__log2l): Likewise. + * math/w_logl.c (__logl): Likewise. + * math/w_powl.c (__powl): Likewise. + * math/w_remainderl.c (__remainderl): Likewise. + * math/w_scalbl.c (sysv_scalbl): Likewise. + * math/w_sinhl.c (__sinhl): Likewise. + * math/w_sqrtl.c (__sqrtl): Likewise. + * math/w_tgammal.c (__tgammal): Likewise. + * sysdeps/ieee754/ldbl-128/w_expl.c (__expl): Likewise. + * sysdeps/ieee754/ldbl-96/w_expl.c (__expl): Likewise. + * math/libm-test.inc (acos_test): Add more tests. + (acosh_test): Likewise. + (asin_test): Likewise. + (atanh_test): Likewise. + (exp_test): Likewise. + (exp10_test): Likewise. + (exp2_test): Likewise. + (expm1_test): Likewise. + (lgamma_test): Likewise. + (log_test): Likewise. + (log10_test): Likewise. + (log1p_test): Likewise. + (log2_test): Likewise. + (pow_test): Do not allow some spurious overflow exceptions. + (sqrt_test): Add more tests. + (tgamma_test): Likewise. + (y0_test): Likewise. + (y1_test): Likewise. + (yn_test): Likewise. + 2012-03-27 Anton Blanchard * sysdeps/unix/sysv/linux/powerpc/bits/mman.h: Define MAP_STACK and diff --git a/NEWS b/NEWS index e54abbe..ea7a178 100644 --- a/NEWS +++ b/NEWS @@ -16,8 +16,9 @@ Version 2.16 13525, 13526, 13527, 13528, 13529, 13530, 13531, 13532, 13533, 13547, 13551, 13552, 13553, 13555, 13559, 13566, 13583, 13618, 13637, 13656, 13658, 13673, 13695, 13704, 13706, 13726, 13738, 13786, 13792, 13806, - 13824, 13840, 13841, 13844, 13846, 13851, 13852, 13854, 13871, 13883, - 13892 + 13824, 13840, 13841, 13844, 13846, 13851, 13852, 13854, 13871, 13879, + 13883, 13892, 13910, 13911, 13912, 13913, 13915, 13916, 13917, 13918, + 13919, 13920, 13921 * ISO C11 support: diff --git a/math/libm-test.inc b/math/libm-test.inc index 3851855..68f6ef2 100644 --- a/math/libm-test.inc +++ b/math/libm-test.inc @@ -746,6 +746,8 @@ acos_test (void) /* |x| > 1: */ TEST_f_f (acos, 1.125L, nan_value, INVALID_EXCEPTION); TEST_f_f (acos, -1.125L, nan_value, INVALID_EXCEPTION); + TEST_f_f (acos, max_value, nan_value, INVALID_EXCEPTION); + TEST_f_f (acos, -max_value, nan_value, INVALID_EXCEPTION); TEST_f_f (acos, 0, M_PI_2l); TEST_f_f (acos, minus_zero, M_PI_2l); @@ -775,6 +777,7 @@ acosh_test (void) /* x < 1: */ TEST_f_f (acosh, -1.125L, nan_value, INVALID_EXCEPTION); + TEST_f_f (acosh, -max_value, nan_value, INVALID_EXCEPTION); TEST_f_f (acosh, 1, 0); TEST_f_f (acosh, 7, 2.63391579384963341725009269461593689L); @@ -800,6 +803,8 @@ asin_test (void) /* asin x == NaN plus invalid exception for |x| > 1. */ TEST_f_f (asin, 1.125L, nan_value, INVALID_EXCEPTION); TEST_f_f (asin, -1.125L, nan_value, INVALID_EXCEPTION); + TEST_f_f (asin, max_value, nan_value, INVALID_EXCEPTION); + TEST_f_f (asin, -max_value, nan_value, INVALID_EXCEPTION); TEST_f_f (asin, 0, 0); TEST_f_f (asin, minus_zero, minus_zero); @@ -885,6 +890,8 @@ atanh_test (void) /* atanh (x) == NaN plus invalid exception if |x| > 1. */ TEST_f_f (atanh, 1.125L, nan_value, INVALID_EXCEPTION); TEST_f_f (atanh, -1.125L, nan_value, INVALID_EXCEPTION); + TEST_f_f (atanh, max_value, nan_value, INVALID_EXCEPTION); + TEST_f_f (atanh, -max_value, nan_value, INVALID_EXCEPTION); TEST_f_f (atanh, 0.75L, 0.972955074527656652552676371721589865L); @@ -2994,6 +3001,11 @@ exp_test (void) TEST_f_f (exp, 1000.0L, 0.197007111401704699388887935224332313e435L); #endif + /* Bug 13922: OVERFLOW exception may be missing. */ + TEST_f_f (exp, max_value, plus_infty, OVERFLOW_EXCEPTION_OK); + /* Bug 13705: spurious OVERFLOW exception may be present. */ + TEST_f_f (exp, -max_value, 0, OVERFLOW_EXCEPTION_OK); + END (exp); } @@ -3127,6 +3139,11 @@ exp10_test (void) TEST_f_f (exp10, -1, 0.1L); TEST_f_f (exp10, 1e6, plus_infty, OVERFLOW_EXCEPTION); TEST_f_f (exp10, -1e6, 0); +#ifndef TEST_LDOUBLE /* Bug 13914: spurious exceptions. */ + TEST_f_f (exp10, max_value, plus_infty, OVERFLOW_EXCEPTION); + /* Bug 13924: spurious OVERFLOW exception may be present. */ + TEST_f_f (exp10, -max_value, 0, OVERFLOW_EXCEPTION_OK); +#endif TEST_f_f (exp10, 0.75L, 5.62341325190349080394951039776481231L); END (exp10); @@ -3154,6 +3171,8 @@ exp2_test (void) TEST_f_f (exp2, -1, 0.5); TEST_f_f (exp2, 1e6, plus_infty, OVERFLOW_EXCEPTION); TEST_f_f (exp2, -1e6, 0); + TEST_f_f (exp2, max_value, plus_infty, OVERFLOW_EXCEPTION); + TEST_f_f (exp2, -max_value, 0); TEST_f_f (exp2, 0.75L, 1.68179283050742908606225095246642979L); TEST_f_f (exp2, 100.5, 1.792728671193156477399422023278661496394e+30L); @@ -3206,6 +3225,11 @@ expm1_test (void) /* Bug 13787: OVERFLOW exception may be missing. */ TEST_f_f (expm1, 100000.0, plus_infty, OVERFLOW_EXCEPTION_OK); check_int ("errno for expm1(large) == ERANGE", errno, ERANGE, 0, 0, 0); + /* Bug 13787: OVERFLOW exception may be missing. */ + TEST_f_f (expm1, max_value, plus_infty, OVERFLOW_EXCEPTION_OK); +#ifndef TEST_LDOUBLE /* Bug 13923. */ + TEST_f_f (expm1, -max_value, -1); +#endif END (expm1); } @@ -3968,6 +3992,8 @@ lgamma_test (void) TEST_f_f (lgamma, -3, plus_infty, DIVIDE_BY_ZERO_EXCEPTION); check_int ("errno for lgamma(-integer) == ERANGE", errno, ERANGE, 0, 0, 0); TEST_f_f (lgamma, minus_infty, plus_infty); + TEST_f_f (lgamma, -max_value, plus_infty, DIVIDE_BY_ZERO_EXCEPTION); + TEST_f_f (lgamma, max_value, plus_infty, OVERFLOW_EXCEPTION); TEST_f_f1 (lgamma, 1, 0, 1); @@ -4869,6 +4895,7 @@ log_test (void) TEST_f_f (log, 1, 0); TEST_f_f (log, -1, nan_value, INVALID_EXCEPTION); + TEST_f_f (log, -max_value, nan_value, INVALID_EXCEPTION); TEST_f_f (log, minus_infty, nan_value, INVALID_EXCEPTION); TEST_f_f (log, plus_infty, plus_infty); TEST_f_f (log, nan_value, nan_value); @@ -4901,6 +4928,7 @@ log10_test (void) /* log10 (x) == NaN plus invalid exception if x < 0. */ TEST_f_f (log10, -1, nan_value, INVALID_EXCEPTION); + TEST_f_f (log10, -max_value, nan_value, INVALID_EXCEPTION); TEST_f_f (log10, minus_infty, nan_value, INVALID_EXCEPTION); TEST_f_f (log10, plus_infty, plus_infty); @@ -4933,6 +4961,7 @@ log1p_test (void) TEST_f_f (log1p, -1, minus_infty, DIVIDE_BY_ZERO_EXCEPTION); TEST_f_f (log1p, -2, nan_value, INVALID_EXCEPTION); + TEST_f_f (log1p, -max_value, nan_value, INVALID_EXCEPTION); TEST_f_f (log1p, minus_infty, nan_value, INVALID_EXCEPTION); TEST_f_f (log1p, plus_infty, plus_infty); @@ -4964,6 +4993,7 @@ log2_test (void) TEST_f_f (log2, 1, 0); TEST_f_f (log2, -1, nan_value, INVALID_EXCEPTION); + TEST_f_f (log2, -max_value, nan_value, INVALID_EXCEPTION); TEST_f_f (log2, minus_infty, nan_value, INVALID_EXCEPTION); TEST_f_f (log2, plus_infty, plus_infty); @@ -5572,8 +5602,7 @@ pow_test (void) TEST_ff_f (pow, 0, -0x1p127, plus_infty, DIVIDE_BY_ZERO_EXCEPTION); check_int ("errno for pow(0,-num) == ERANGE", errno, ERANGE, 0, 0, 0); errno = 0; - /* Bug 13879: spurious OVERFLOW exception may be present. */ - TEST_ff_f (pow, 0, -max_value, plus_infty, DIVIDE_BY_ZERO_EXCEPTION|OVERFLOW_EXCEPTION_OK); + TEST_ff_f (pow, 0, -max_value, plus_infty, DIVIDE_BY_ZERO_EXCEPTION); check_int ("errno for pow(0,-num) == ERANGE", errno, ERANGE, 0, 0, 0); errno = 0; TEST_ff_f (pow, minus_zero, -2, plus_infty, DIVIDE_BY_ZERO_EXCEPTION); @@ -5588,8 +5617,7 @@ pow_test (void) TEST_ff_f (pow, minus_zero, -0x1p127, plus_infty, DIVIDE_BY_ZERO_EXCEPTION); check_int ("errno for pow(-0,-num) == ERANGE", errno, ERANGE, 0, 0, 0); errno = 0; - /* Bug 13879: spurious OVERFLOW exception may be present. */ - TEST_ff_f (pow, minus_zero, -max_value, plus_infty, DIVIDE_BY_ZERO_EXCEPTION|OVERFLOW_EXCEPTION_OK); + TEST_ff_f (pow, minus_zero, -max_value, plus_infty, DIVIDE_BY_ZERO_EXCEPTION); check_int ("errno for pow(-0,-num) == ERANGE", errno, ERANGE, 0, 0, 0); TEST_ff_f (pow, 0x1p72L, 0x1p72L, plus_infty, OVERFLOW_EXCEPTION); @@ -7083,6 +7111,7 @@ sqrt_test (void) /* sqrt (x) == NaN plus invalid exception for x < 0. */ TEST_f_f (sqrt, -1, nan_value, INVALID_EXCEPTION); + TEST_f_f (sqrt, -max_value, nan_value, INVALID_EXCEPTION); TEST_f_f (sqrt, minus_infty, nan_value, INVALID_EXCEPTION); TEST_f_f (sqrt, nan_value, nan_value); @@ -7321,10 +7350,12 @@ tgamma_test (void) START (tgamma); TEST_f_f (tgamma, plus_infty, plus_infty); + TEST_f_f (tgamma, max_value, plus_infty, OVERFLOW_EXCEPTION); TEST_f_f (tgamma, 0, plus_infty, DIVIDE_BY_ZERO_EXCEPTION); TEST_f_f (tgamma, minus_zero, minus_infty, DIVIDE_BY_ZERO_EXCEPTION); /* tgamma (x) == NaN plus invalid exception for integer x <= 0. */ TEST_f_f (tgamma, -2, nan_value, INVALID_EXCEPTION); + TEST_f_f (tgamma, -max_value, nan_value, INVALID_EXCEPTION); TEST_f_f (tgamma, minus_infty, nan_value, INVALID_EXCEPTION); TEST_f_f (tgamma, nan_value, nan_value); @@ -7468,6 +7499,7 @@ y0_test (void) START (y0); TEST_f_f (y0, -1.0, minus_infty, INVALID_EXCEPTION); + TEST_f_f (y0, -max_value, minus_infty, INVALID_EXCEPTION); TEST_f_f (y0, 0.0, minus_infty); TEST_f_f (y0, nan_value, nan_value); TEST_f_f (y0, plus_infty, 0); @@ -7508,6 +7540,7 @@ y1_test (void) START (y1); TEST_f_f (y1, -1.0, minus_infty, INVALID_EXCEPTION); + TEST_f_f (y1, -max_value, minus_infty, INVALID_EXCEPTION); TEST_f_f (y1, 0.0, minus_infty); TEST_f_f (y1, plus_infty, 0); TEST_f_f (y1, nan_value, nan_value); @@ -7549,6 +7582,7 @@ yn_test (void) /* yn (0, x) == y0 (x) */ TEST_ff_f (yn, 0, -1.0, minus_infty, INVALID_EXCEPTION); + TEST_ff_f (yn, 0, -max_value, minus_infty, INVALID_EXCEPTION); TEST_ff_f (yn, 0, 0.0, minus_infty); TEST_ff_f (yn, 0, nan_value, nan_value); TEST_ff_f (yn, 0, plus_infty, 0); diff --git a/math/w_acoshl.c b/math/w_acoshl.c index cc823b8..def7be4 100644 --- a/math/w_acoshl.c +++ b/math/w_acoshl.c @@ -26,7 +26,7 @@ __acoshl (long double x) { if (__builtin_expect (isless (x, 1.0L), 0) && _LIB_VERSION != _IEEE_) /* acosh(x<1) */ - return __kernel_standard (x, x, 229); + return __kernel_standard_l (x, x, 229); return __ieee754_acoshl (x); } diff --git a/math/w_acosl.c b/math/w_acosl.c index 05023b4..394fce1 100644 --- a/math/w_acosl.c +++ b/math/w_acosl.c @@ -30,7 +30,7 @@ __acosl (long double x) { /* acos(|x|>1) */ feraiseexcept (FE_INVALID); - return __kernel_standard (x, x, 201); + return __kernel_standard_l (x, x, 201); } return __ieee754_acosl (x); diff --git a/math/w_asinl.c b/math/w_asinl.c index e4036d8..e56e2e5 100644 --- a/math/w_asinl.c +++ b/math/w_asinl.c @@ -30,7 +30,7 @@ __asinl (long double x) { /* asin(|x|>1) */ feraiseexcept (FE_INVALID); - return __kernel_standard (x, x, 202); + return __kernel_standard_l (x, x, 202); } return __ieee754_asinl (x); diff --git a/math/w_atan2l.c b/math/w_atan2l.c index 8554376..30f9512 100644 --- a/math/w_atan2l.c +++ b/math/w_atan2l.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2011 Free Software Foundation, Inc. +/* Copyright (C) 2011-2012 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 2011. @@ -28,7 +28,7 @@ long double __atan2l (long double y, long double x) { if (__builtin_expect (x == 0.0L && y == 0.0L, 0) && _LIB_VERSION == _SVID_) - return __kernel_standard (y, x, 203); /* atan2(+-0,+-0) */ + return __kernel_standard_l (y, x, 203); /* atan2(+-0,+-0) */ return __ieee754_atan2l (y, x); } diff --git a/math/w_atanhl.c b/math/w_atanhl.c index 319535d..6b00bbb 100644 --- a/math/w_atanhl.c +++ b/math/w_atanhl.c @@ -26,10 +26,10 @@ __atanhl (long double x) { if (__builtin_expect (isgreaterequal (fabsl (x), 1.0L), 0) && _LIB_VERSION != _IEEE_) - return __kernel_standard (x, x, - fabsl (x) > 1.0L - ? 230 /* atanh(|x|>1) */ - : 231); /* atanh(|x|==1) */ + return __kernel_standard_l (x, x, + fabsl (x) > 1.0L + ? 230 /* atanh(|x|>1) */ + : 231); /* atanh(|x|==1) */ return __ieee754_atanhl (x); } diff --git a/math/w_coshl.c b/math/w_coshl.c index abca8b0..9c638e9 100644 --- a/math/w_coshl.c +++ b/math/w_coshl.c @@ -28,7 +28,7 @@ __coshl (long double x) long double z = __ieee754_coshl (x); if (__builtin_expect (!__finitel (z), 0) && __finitel (x) && _LIB_VERSION != _IEEE_) - return __kernel_standard (x, x, 205); /* cosh overflow */ + return __kernel_standard_l (x, x, 205); /* cosh overflow */ return z; } diff --git a/math/w_exp10l.c b/math/w_exp10l.c index bea6a1e..7f426ea 100644 --- a/math/w_exp10l.c +++ b/math/w_exp10l.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2011 Free Software Foundation, Inc. +/* Copyright (C) 2011-2012 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 2011. @@ -31,7 +31,7 @@ __exp10l (long double x) if (__builtin_expect (!__finitel (z), 0) && __finitel (x) && _LIB_VERSION != _IEEE_) /* exp10l overflow (246) if x > 0, underflow (247) if x < 0. */ - return __kernel_standard (x, x, 246 + !!__signbitl (x)); + return __kernel_standard_l (x, x, 246 + !!__signbitl (x)); return z; } diff --git a/math/w_exp2l.c b/math/w_exp2l.c index f05a8fe..7f06805 100644 --- a/math/w_exp2l.c +++ b/math/w_exp2l.c @@ -12,7 +12,7 @@ __exp2l (long double x) if (__builtin_expect (!__finitel (z), 0) && __finitel (x) && _LIB_VERSION != _IEEE_) /* exp2 overflow: 244, exp2 underflow: 245 */ - return __kernel_standard (x, x, 244 + !!__signbitl (x)); + return __kernel_standard_l (x, x, 244 + !!__signbitl (x)); return z; } diff --git a/math/w_fmodl.c b/math/w_fmodl.c index b088cc3..f508a1f 100644 --- a/math/w_fmodl.c +++ b/math/w_fmodl.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2011 Free Software Foundation, Inc. +/* Copyright (C) 2011-2012 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 2011. @@ -26,7 +26,7 @@ __fmodl (long double x, long double y) if (__builtin_expect (__isinf_nsl (x) || y == 0.0L, 0) && _LIB_VERSION != _IEEE_ && !__isnanl (y) && !__isnanl (x)) /* fmod(+-Inf,y) or fmod(x,0) */ - return __kernel_standard (x, y, 227); + return __kernel_standard_l (x, y, 227); return __ieee754_fmodl (x, y); } diff --git a/math/w_hypotl.c b/math/w_hypotl.c index 522eb63..2e942ca 100644 --- a/math/w_hypotl.c +++ b/math/w_hypotl.c @@ -29,7 +29,7 @@ __hypotl(long double x, long double y) z = __ieee754_hypotl(x,y); if(__builtin_expect(!__finitel(z), 0) && __finitel(x) && __finitel(y) && _LIB_VERSION != _IEEE_) - return __kernel_standard(x, y, 204); /* hypot overflow */ + return __kernel_standard_l(x, y, 204); /* hypot overflow */ return z; } diff --git a/math/w_j0l.c b/math/w_j0l.c index 54c9c89..1532d2e 100644 --- a/math/w_j0l.c +++ b/math/w_j0l.c @@ -28,7 +28,7 @@ __j0l (long double x) if (__builtin_expect (isgreater (fabsl (x), X_TLOSS), 0) && _LIB_VERSION != _IEEE_ && _LIB_VERSION != _POSIX_) /* j0(|x|>X_TLOSS) */ - return __kernel_standard (x, x, 234); + return __kernel_standard_l (x, x, 234); return __ieee754_j0l (x); } @@ -46,14 +46,14 @@ __y0l (long double x) { /* d = zero/(x-x) */ feraiseexcept (FE_INVALID); - return __kernel_standard (x, x, 209); + return __kernel_standard_l (x, x, 209); } else if (x == 0.0L) /* d = -one/(x-x) */ - return __kernel_standard (x, x, 208); + return __kernel_standard_l (x, x, 208); else if (_LIB_VERSION != _POSIX_) /* y0(x>X_TLOSS) */ - return __kernel_standard (x, x, 235); + return __kernel_standard_l (x, x, 235); } return __ieee754_y0l (x); diff --git a/math/w_j1l.c b/math/w_j1l.c index 208377e..0b01360 100644 --- a/math/w_j1l.c +++ b/math/w_j1l.c @@ -28,7 +28,7 @@ __j1l (long double x) if (__builtin_expect (isgreater (fabsl (x), X_TLOSS), 0) && _LIB_VERSION != _IEEE_ && _LIB_VERSION != _POSIX_) /* j1(|x|>X_TLOSS) */ - return __kernel_standard (x, x, 236); + return __kernel_standard_l (x, x, 236); return __ieee754_j1l (x); } @@ -46,14 +46,14 @@ __y1l (long double x) { /* d = zero/(x-x) */ feraiseexcept (FE_INVALID); - return __kernel_standard (x, x, 211); + return __kernel_standard_l (x, x, 211); } else if (x == 0.0L) /* d = -one/(x-x) */ - return __kernel_standard (x, x, 210); + return __kernel_standard_l (x, x, 210); else if (_LIB_VERSION != _POSIX_) /* y1(x>X_TLOSS) */ - return __kernel_standard (x, x, 237); + return __kernel_standard_l (x, x, 237); } return __ieee754_y1l (x); diff --git a/math/w_jnl.c b/math/w_jnl.c index 2028d48..0263147 100644 --- a/math/w_jnl.c +++ b/math/w_jnl.c @@ -59,7 +59,7 @@ long double __jnl(int n, long double x) /* wrapper jnl */ || __isnanl(x)) return z; if(fabsl(x)>X_TLOSS) { - return __kernel_standard((double)n,x,238); /* jn(|x|>X_TLOSS,n) */ + return __kernel_standard_l((double)n,x,238); /* jn(|x|>X_TLOSS,n) */ } else return z; #endif @@ -77,13 +77,13 @@ long double __ynl(int n, long double x) /* wrapper ynl */ if(x <= 0.0){ if(x==0.0) /* d= -one/(x-x); */ - return __kernel_standard((double)n,x,212); + return __kernel_standard_l((double)n,x,212); else /* d = zero/(x-x); */ - return __kernel_standard((double)n,x,213); + return __kernel_standard_l((double)n,x,213); } if(x>X_TLOSS && _LIB_VERSION != _POSIX_) { - return __kernel_standard((double)n,x,239); /* yn(x>X_TLOSS,n) */ + return __kernel_standard_l((double)n,x,239); /* yn(x>X_TLOSS,n) */ } else return z; #endif diff --git a/math/w_lgammal.c b/math/w_lgammal.c index 7df38e7..1dc7e58 100644 --- a/math/w_lgammal.c +++ b/math/w_lgammal.c @@ -35,10 +35,10 @@ __lgammal(long double x) : &local_signgam); if(__builtin_expect(!__finitel(y), 0) && __finitel(x) && _LIB_VERSION != _IEEE_) - return __kernel_standard(x, x, - __floorl(x)==x&&x<=0.0L - ? 215 /* lgamma pole */ - : 214); /* lgamma overflow */ + return __kernel_standard_l(x, x, + __floorl(x)==x&&x<=0.0L + ? 215 /* lgamma pole */ + : 214); /* lgamma overflow */ return y; } diff --git a/math/w_log10l.c b/math/w_log10l.c index 0e5a137..3371b7b 100644 --- a/math/w_log10l.c +++ b/math/w_log10l.c @@ -30,12 +30,12 @@ __log10l (long double x) if (x == 0.0L) { feraiseexcept (FE_DIVBYZERO); - return __kernel_standard (x, x, 218); /* log10(0) */ + return __kernel_standard_l (x, x, 218); /* log10(0) */ } else { feraiseexcept (FE_INVALID); - return __kernel_standard (x, x, 219); /* log10(x<0) */ + return __kernel_standard_l (x, x, 219); /* log10(x<0) */ } } diff --git a/math/w_log2l.c b/math/w_log2l.c index eed04ff6c..1400c93 100644 --- a/math/w_log2l.c +++ b/math/w_log2l.c @@ -30,12 +30,12 @@ __log2l (long double x) if (x == 0.0L) { feraiseexcept (FE_DIVBYZERO); - return __kernel_standard (x, x, 248); /* log2(0) */ + return __kernel_standard_l (x, x, 248); /* log2(0) */ } else { feraiseexcept (FE_INVALID); - return __kernel_standard (x, x, 249); /* log2(x<0) */ + return __kernel_standard_l (x, x, 249); /* log2(x<0) */ } } diff --git a/math/w_logl.c b/math/w_logl.c index 593b37d..9ea4ff7 100644 --- a/math/w_logl.c +++ b/math/w_logl.c @@ -30,12 +30,12 @@ __logl (long double x) if (x == 0.0L) { feraiseexcept (FE_DIVBYZERO); - return __kernel_standard (x, x, 216); /* log(0) */ + return __kernel_standard_l (x, x, 216); /* log(0) */ } else { feraiseexcept (FE_INVALID); - return __kernel_standard (x, x, 217); /* log(x<0) */ + return __kernel_standard_l (x, x, 217); /* log(x<0) */ } } diff --git a/math/w_powl.c b/math/w_powl.c index 5bb8597..3786388 100644 --- a/math/w_powl.c +++ b/math/w_powl.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2011 Free Software Foundation, Inc. +/* Copyright (C) 2011-2012 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 2011. @@ -33,25 +33,25 @@ __powl (long double x, long double y) { if (y == 0.0L) /* pow(NaN,0.0) */ - return __kernel_standard (x, y, 242); + return __kernel_standard_l (x, y, 242); } else if (__finitel (x) && __finitel (y)) { if (__isnanl (z)) /* pow neg**non-int */ - return __kernel_standard (x, y, 224); + return __kernel_standard_l (x, y, 224); else if (x == 0.0L && y < 0.0L) { if (signbit (x) && signbit (z)) /* pow(-0.0,negative) */ - return __kernel_standard (x, y, 223); + return __kernel_standard_l (x, y, 223); else /* pow(+0.0,negative) */ - return __kernel_standard (x, y, 243); + return __kernel_standard_l (x, y, 243); } else /* pow overflow */ - return __kernel_standard (x, y, 221); + return __kernel_standard_l (x, y, 221); } } } @@ -62,11 +62,11 @@ __powl (long double x, long double y) { if (y == 0.0L) /* pow(0.0,0.0) */ - return __kernel_standard (x, y, 220); + return __kernel_standard_l (x, y, 220); } else /* pow underflow */ - return __kernel_standard (x, y, 222); + return __kernel_standard_l (x, y, 222); } return z; diff --git a/math/w_remainderl.c b/math/w_remainderl.c index 3f67b58..a21065c 100644 --- a/math/w_remainderl.c +++ b/math/w_remainderl.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2011 Free Software Foundation, Inc. +/* Copyright (C) 2011-2012 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 2011. @@ -27,7 +27,7 @@ __remainderl (long double x, long double y) if (((__builtin_expect (y == 0.0L, 0) && ! __isnanl (x)) || (__builtin_expect (__isinf_nsl (x), 0) && ! __isnanl (y))) && _LIB_VERSION != _IEEE_) - return __kernel_standard (x, y, 228); /* remainder domain */ + return __kernel_standard_l (x, y, 228); /* remainder domain */ return __ieee754_remainderl (x, y); } diff --git a/math/w_scalbl.c b/math/w_scalbl.c index b3584de..1181874 100644 --- a/math/w_scalbl.c +++ b/math/w_scalbl.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2011 Free Software Foundation, Inc. +/* Copyright (C) 2011-2012 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 2011. @@ -30,12 +30,12 @@ sysv_scalbl (long double x, long double fn) if (__builtin_expect (__isinfl (z), 0)) { if (__finitel (x)) - return __kernel_standard (x, fn, 232); /* scalb overflow */ + return __kernel_standard_l (x, fn, 232); /* scalb overflow */ else __set_errno (ERANGE); } else if (__builtin_expect (z == 0.0L, 0) && z != x) - return __kernel_standard (x, fn, 233); /* scalb underflow */ + return __kernel_standard_l (x, fn, 233); /* scalb underflow */ return z; } diff --git a/math/w_sinhl.c b/math/w_sinhl.c index 5e65cf9..f801b4d 100644 --- a/math/w_sinhl.c +++ b/math/w_sinhl.c @@ -27,7 +27,7 @@ __sinhl (long double x) long double z = __ieee754_sinhl (x); if (__builtin_expect (!__finitel (z), 0) && __finitel (x) && _LIB_VERSION != _IEEE_) - return __kernel_standard (x, x, 225); /* sinh overflow */ + return __kernel_standard_l (x, x, 225); /* sinh overflow */ return z; } diff --git a/math/w_sqrtl.c b/math/w_sqrtl.c index 2a4a048..74529f9 100644 --- a/math/w_sqrtl.c +++ b/math/w_sqrtl.c @@ -25,7 +25,7 @@ long double __sqrtl (long double x) { if (__builtin_expect (isless (x, 0.0L), 0) && _LIB_VERSION != _IEEE_) - return __kernel_standard (x, x, 226); /* sqrt(negative) */ + return __kernel_standard_l (x, x, 226); /* sqrt(negative) */ return __ieee754_sqrtl (x); } diff --git a/math/w_tgammal.c b/math/w_tgammal.c index 6910f92..86adab2 100644 --- a/math/w_tgammal.c +++ b/math/w_tgammal.c @@ -30,11 +30,11 @@ __tgammal(long double x) if(__builtin_expect(!__finitel(y), 0) && __finitel(x) && _LIB_VERSION != _IEEE_) { if(x==0.0) - return __kernel_standard(x,x,250); /* tgamma pole */ + return __kernel_standard_l(x,x,250); /* tgamma pole */ else if(__floorl(x)==x&&x<0.0L) - return __kernel_standard(x,x,241); /* tgamma domain */ + return __kernel_standard_l(x,x,241); /* tgamma domain */ else - return __kernel_standard(x,x,240); /* tgamma overflow */ + return __kernel_standard_l(x,x,240); /* tgamma overflow */ } return local_signgam < 0 ? - y : y; } diff --git a/sysdeps/generic/math_private.h b/sysdeps/generic/math_private.h index 813ad93..e217224 100644 --- a/sysdeps/generic/math_private.h +++ b/sysdeps/generic/math_private.h @@ -217,6 +217,7 @@ extern double __ieee754_scalb (double,double); /* fdlibm kernel function */ extern double __kernel_standard (double,double,int); extern float __kernel_standard_f (float,float,int); +extern long double __kernel_standard_l (long double,long double,int); extern double __kernel_sin (double,double,int); extern double __kernel_cos (double,double); extern double __kernel_tan (double,double,int); diff --git a/sysdeps/ieee754/k_standard.c b/sysdeps/ieee754/k_standard.c index 5d84543..c3326d9 100644 --- a/sysdeps/ieee754/k_standard.c +++ b/sysdeps/ieee754/k_standard.c @@ -16,6 +16,7 @@ static char rcsid[] = "$NetBSD: k_standard.c,v 1.6 1995/05/10 20:46:35 jtc Exp $ #include #include +#include #include #include @@ -998,3 +999,34 @@ __kernel_standard_f(float x, float y, int type) { return __kernel_standard(x, y, type); } + +long double +__kernel_standard_l (long double x, long double y, int type) +{ + double dx, dy; + 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; + return __kernel_standard (dx, dy, type); +} diff --git a/sysdeps/ieee754/ldbl-128/w_expl.c b/sysdeps/ieee754/ldbl-128/w_expl.c index f4deda8..10193be 100644 --- a/sysdeps/ieee754/ldbl-128/w_expl.c +++ b/sysdeps/ieee754/ldbl-128/w_expl.c @@ -39,9 +39,9 @@ long double __expl(long double x) /* wrapper exp */ if(_LIB_VERSION == _IEEE_) return z; if(__finitel(x)) { if(x>o_threshold) - return __kernel_standard(x,x,206); /* exp overflow */ + return __kernel_standard_l(x,x,206); /* exp overflow */ else if(x