diff options
-rw-r--r-- | ChangeLog | 30 | ||||
-rw-r--r-- | NEWS | 2 | ||||
-rw-r--r-- | math/libm-test.inc | 185 | ||||
-rw-r--r-- | sysdeps/ieee754/dbl-64/s_lround.c | 28 | ||||
-rw-r--r-- | sysdeps/ieee754/dbl-64/wordsize-64/s_lround.c | 24 | ||||
-rw-r--r-- | sysdeps/ieee754/ldbl-128/s_llroundl.c | 25 | ||||
-rw-r--r-- | sysdeps/ieee754/ldbl-128/s_lroundl.c | 32 | ||||
-rw-r--r-- | sysdeps/ieee754/ldbl-96/s_llroundl.c | 11 | ||||
-rw-r--r-- | sysdeps/ieee754/ldbl-96/s_lroundl.c | 35 |
9 files changed, 358 insertions, 14 deletions
diff --git a/ChangeLog b/ChangeLog index 58069c75a2..821168246e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,33 @@ +2015-10-07 Joseph Myers <joseph@codesourcery.com> + + [BZ #19088] + * sysdeps/ieee754/dbl-64/s_lround.c: Include <fenv.h> and + <limits.h>. + (__lround) [FE_INVALID]: Force FE_INVALID exception when result + overflows but exception would not result from cast. + * sysdeps/ieee754/dbl-64/wordsize-64/s_lround.c: Include <fenv.h> + and <limits.h>. + (__lround) [FE_INVALID]: Force FE_INVALID exception when result + overflows but exception would not result from cast. + * sysdeps/ieee754/ldbl-128/s_llroundl.c: Include <fenv.h> and + <limits.h>. + (__llroundl) [FE_INVALID]: Force FE_INVALID exception when result + overflows but exception would not result from cast. + * sysdeps/ieee754/ldbl-128/s_lroundl.c: Include <fenv.h> and + <limits.h>. + (__lroundl) [FE_INVALID]: Force FE_INVALID exception when result + overflows but exception would not result from cast. + * sysdeps/ieee754/ldbl-96/s_llroundl.c: Include <fenv.h> and + <limits.h>. + (__llroundl) [FE_INVALID]: Force FE_INVALID exception when result + overflows but exception would not result from cast. + * sysdeps/ieee754/ldbl-96/s_lroundl.c: Include <fenv.h> and + <limits.h>. + (__lroundl) [FE_INVALID]: Force FE_INVALID exception when result + overflows but exception would not result from cast. + * math/libm-test.inc (lround_test_data): Add more tests. + (llround_test_data): Likewise. + 2015-10-07 Steve Ellcey <sellcey@imgtec.com> * timezone/Makefile (CFLAGS-zic.c): Add -Wno-unused-variable. diff --git a/NEWS b/NEWS index 30284ba6a3..a3adcfdff8 100644 --- a/NEWS +++ b/NEWS @@ -18,7 +18,7 @@ Version 2.23 18820, 18823, 18824, 18825, 18857, 18863, 18870, 18872, 18873, 18875, 18887, 18921, 18951, 18952, 18956, 18961, 18966, 18967, 18969, 18970, 18977, 18980, 18981, 18985, 19003, 19012, 19016, 19018, 19032, 19046, - 19049, 19050, 19059, 19071, 19076, 19077, 19078, 19079, 19085. + 19049, 19050, 19059, 19071, 19076, 19077, 19078, 19079, 19085, 19088. * The obsolete header <regexp.h> has been removed. Programs that require this header must be updated to use <regex.h> instead. diff --git a/math/libm-test.inc b/math/libm-test.inc index 54f62f8a32..fe74e28e34 100644 --- a/math/libm-test.inc +++ b/math/libm-test.inc @@ -8282,6 +8282,123 @@ static const struct test_f_l_data lround_test_data[] = #endif TEST_f_l (lround, -0x1p64, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION), TEST_f_l (lround, -0x1p65, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION), + TEST_f_l (lround, 0x7fffff80p0, 0x7fffff80LL, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), +#ifndef TEST_FLOAT + TEST_f_l (lround, 0x7fffffffp0, 0x7fffffffLL, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), + TEST_f_l (lround, 0x7fffffff.4p0, 0x7fffffffLL, ERRNO_UNCHANGED), + TEST_f_l (lround, 0x7fffffff.7ffffcp0, 0x7fffffffLL, ERRNO_UNCHANGED), +# if LONG_MAX > 0x7fffffff + TEST_f_l (lround, 0x7fffffff.8p0, 0x80000000LL, ERRNO_UNCHANGED), + TEST_f_l (lround, 0x7fffffff.cp0, 0x80000000LL, ERRNO_UNCHANGED), +# else + TEST_f_l (lround, 0x7fffffff.8p0, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION), + TEST_f_l (lround, 0x7fffffff.cp0, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION), +# endif +#endif +#if defined TEST_LDOUBLE && LDBL_MANT_DIG >= 64 + TEST_f_l (lround, 0x7fffffff.7fffffff8p0L, 0x7fffffffLL, ERRNO_UNCHANGED), +#endif +#if defined TEST_LDOUBLE && LDBL_MANT_DIG >= 106 + TEST_f_l (lround, 0x7fffffff.7fffffffffffffffffep0L, 0x7fffffffLL, ERRNO_UNCHANGED), +#endif +#if defined TEST_LDOUBLE && LDBL_MANT_DIG >= 113 + TEST_f_l (lround, 0x7fffffff.7fffffffffffffffffffcp0L, 0x7fffffffLL, ERRNO_UNCHANGED), +#endif +#ifndef TEST_FLOAT + TEST_f_l (lround, -0x80000000.4p0, -0x80000000LL, ERRNO_UNCHANGED), + TEST_f_l (lround, -0x80000000.7ffff8p0, -0x80000000LL, ERRNO_UNCHANGED), +# if LONG_MAX > 0x7fffffff + TEST_f_l (lround, -0x80000000.8p0, -0x80000001LL, ERRNO_UNCHANGED), + TEST_f_l (lround, -0x80000000.cp0, -0x80000001LL, ERRNO_UNCHANGED), + TEST_f_l (lround, -0x80000001p0, -0x80000001LL, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), +# else + TEST_f_l (lround, -0x80000000.8p0, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION), + TEST_f_l (lround, -0x80000000.cp0, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION), + TEST_f_l (lround, -0x80000001p0, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION), +# endif +#endif +#if LONG_MAX > 0x7fffffff + TEST_f_l (lround, -0x80000100p0, -0x80000100LL, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), +#else + TEST_f_l (lround, -0x80000100p0, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION), +#endif +#if defined TEST_LDOUBLE && LDBL_MANT_DIG >= 64 + TEST_f_l (lround, -0x80000000.7fffffffp0L, -0x80000000LL, ERRNO_UNCHANGED), +#endif +#if defined TEST_LDOUBLE && LDBL_MANT_DIG >= 106 + TEST_f_l (lround, -0x80000000.7fffffffffffffffffcp0L, -0x80000000LL, ERRNO_UNCHANGED), +#endif +#if defined TEST_LDOUBLE && LDBL_MANT_DIG >= 113 + TEST_f_l (lround, -0x80000000.7fffffffffffffffffff8p0L, -0x80000000LL, ERRNO_UNCHANGED), +#endif +#if LONG_MAX > 0x7fffffff + TEST_f_l (lround, 0x7fffff8000000000p0, 0x7fffff8000000000LL, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), +#else + TEST_f_l (lround, 0x7fffff8000000000p0, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION), +#endif +#ifndef TEST_FLOAT +# if LONG_MAX > 0x7fffffff + TEST_f_l (lround, 0x7ffffffffffffc00p0, 0x7ffffffffffffc00LL, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), +# else + TEST_f_l (lround, 0x7ffffffffffffc00p0, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION), +# endif +#endif +#ifdef TEST_LDOUBLE +# if LONG_MAX > 0x7fffffff + TEST_f_l (lround, 0x7fffffffffffffffp0L, 0x7fffffffffffffffLL, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), +# else + TEST_f_l (lround, 0x7fffffffffffffffp0L, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION), +# endif + TEST_f_l (lround, 0x7fffffffffffffff.8p0L, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION), +# if LDBL_MANT_DIG > 64 +# if LONG_MAX > 0x7fffffff + TEST_f_l (lround, 0x7fffffffffffffff.4p0L, 0x7fffffffffffffffLL, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), +# else + TEST_f_l (lround, 0x7fffffffffffffff.4p0L, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION), +# endif + TEST_f_l (lround, 0x7fffffffffffffff.cp0L, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION), +# endif +# if LONG_MAX > 0x7fffffff +# if LDBL_MANT_DIG >= 106 + TEST_f_l (lround, 0x7fffffffffffffff.7fffffffffep0L, 0x7fffffffffffffffLL, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), +# endif +# if LDBL_MANT_DIG >= 113 + TEST_f_l (lround, 0x7fffffffffffffff.7fffffffffffcp0L, 0x7fffffffffffffffLL, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), +# endif +# else +# if LDBL_MANT_DIG >= 106 + TEST_f_l (lround, 0x7fffffffffffffff.7fffffffffep0L, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION), +# endif +# if LDBL_MANT_DIG >= 113 + TEST_f_l (lround, 0x7fffffffffffffff.7fffffffffffcp0L, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION), +# endif +# endif +#endif +#ifdef TEST_LDOUBLE + TEST_f_l (lround, -0x8000000000000001p0L, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION), +#endif +#if defined TEST_LDOUBLE && LDBL_MANT_DIG >= 106 +# if LONG_MAX > 0x7fffffff + TEST_f_l (lround, -0x8000000000000000.4p0L, LLONG_MIN, ERRNO_UNCHANGED), + TEST_f_l (lround, -0x8000000000000000.7fffffffffcp0L, LLONG_MIN, ERRNO_UNCHANGED), +# else + TEST_f_l (lround, -0x8000000000000000.4p0L, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION), + TEST_f_l (lround, -0x8000000000000000.7fffffffffcp0L, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION), +# endif + TEST_f_l (lround, -0x8000000000000000.8p0L, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION), + TEST_f_l (lround, -0x8000000000000000.cp0L, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION), +#endif + TEST_f_l (lround, -0x8000010000000000p0, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION), +#ifndef TEST_FLOAT + TEST_f_l (lround, -0x8000000000000800p0, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION), +#endif +#if defined TEST_LDOUBLE && LDBL_MANT_DIG >= 113 +# if LONG_MAX > 0x7fffffff + TEST_f_l (lround, -0x8000000000000000.7fffffffffff8p0L, LLONG_MIN, ERRNO_UNCHANGED), +# else + TEST_f_l (lround, -0x8000000000000000.7fffffffffff8p0L, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION), +# endif +#endif TEST_f_l (lround, 0, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), TEST_f_l (lround, minus_zero, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), TEST_f_l (lround, min_value, 0.0, ERRNO_UNCHANGED), @@ -8492,6 +8609,74 @@ static const struct test_f_L_data llround_test_data[] = TEST_f_L (llround, -0x1p63, LLONG_MIN, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), TEST_f_L (llround, -0x1p64, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION), TEST_f_L (llround, -0x1p65, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION), + TEST_f_L (llround, 0x7fffff80p0, 0x7fffff80LL, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), +#ifndef TEST_FLOAT + TEST_f_L (llround, 0x7fffffffp0, 0x7fffffffLL, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), + TEST_f_L (llround, 0x7fffffff.4p0, 0x7fffffffLL, ERRNO_UNCHANGED), + TEST_f_L (llround, 0x7fffffff.7ffffcp0, 0x7fffffffLL, ERRNO_UNCHANGED), + TEST_f_L (llround, 0x7fffffff.8p0, 0x80000000LL, ERRNO_UNCHANGED), + TEST_f_L (llround, 0x7fffffff.cp0, 0x80000000LL, ERRNO_UNCHANGED), +#endif +#if defined TEST_LDOUBLE && LDBL_MANT_DIG >= 64 + TEST_f_L (llround, 0x7fffffff.7fffffff8p0L, 0x7fffffffLL, ERRNO_UNCHANGED), +#endif +#if defined TEST_LDOUBLE && LDBL_MANT_DIG >= 106 + TEST_f_L (llround, 0x7fffffff.7fffffffffffffffffep0L, 0x7fffffffLL, ERRNO_UNCHANGED), +#endif +#if defined TEST_LDOUBLE && LDBL_MANT_DIG >= 113 + TEST_f_L (llround, 0x7fffffff.7fffffffffffffffffffcp0L, 0x7fffffffLL, ERRNO_UNCHANGED), +#endif +#ifndef TEST_FLOAT + TEST_f_L (llround, -0x80000000.4p0, -0x80000000LL, ERRNO_UNCHANGED), + TEST_f_L (llround, -0x80000000.7ffff8p0, -0x80000000LL, ERRNO_UNCHANGED), + TEST_f_L (llround, -0x80000000.8p0, -0x80000001LL, ERRNO_UNCHANGED), + TEST_f_L (llround, -0x80000000.cp0, -0x80000001LL, ERRNO_UNCHANGED), + TEST_f_L (llround, -0x80000001p0, -0x80000001LL, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), +#endif + TEST_f_L (llround, -0x80000100p0, -0x80000100LL, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), +#if defined TEST_LDOUBLE && LDBL_MANT_DIG >= 64 + TEST_f_L (llround, -0x80000000.7fffffffp0L, -0x80000000LL, ERRNO_UNCHANGED), +#endif +#if defined TEST_LDOUBLE && LDBL_MANT_DIG >= 106 + TEST_f_L (llround, -0x80000000.7fffffffffffffffffcp0L, -0x80000000LL, ERRNO_UNCHANGED), +#endif +#if defined TEST_LDOUBLE && LDBL_MANT_DIG >= 113 + TEST_f_L (llround, -0x80000000.7fffffffffffffffffff8p0L, -0x80000000LL, ERRNO_UNCHANGED), +#endif + TEST_f_L (llround, 0x7fffff8000000000p0, 0x7fffff8000000000LL, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), +#ifndef TEST_FLOAT + TEST_f_L (llround, 0x7ffffffffffffc00p0, 0x7ffffffffffffc00LL, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), +#endif +#ifdef TEST_LDOUBLE + TEST_f_L (llround, 0x7fffffffffffffffp0L, 0x7fffffffffffffffLL, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), + TEST_f_L (llround, 0x7fffffffffffffff.8p0L, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION), +# if LDBL_MANT_DIG > 64 + TEST_f_L (llround, 0x7fffffffffffffff.4p0L, 0x7fffffffffffffffLL, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), + TEST_f_L (llround, 0x7fffffffffffffff.cp0L, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION), +# endif +# if LDBL_MANT_DIG >= 106 + TEST_f_L (llround, 0x7fffffffffffffff.7fffffffffep0L, 0x7fffffffffffffffLL, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), +# endif +# if LDBL_MANT_DIG >= 113 + TEST_f_L (llround, 0x7fffffffffffffff.7fffffffffffcp0L, 0x7fffffffffffffffLL, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), +# endif +#endif +#ifdef TEST_LDOUBLE + TEST_f_L (llround, -0x8000000000000001p0L, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION), +#endif +#if defined TEST_LDOUBLE && LDBL_MANT_DIG >= 106 + TEST_f_L (llround, -0x8000000000000000.4p0L, LLONG_MIN, ERRNO_UNCHANGED), + TEST_f_L (llround, -0x8000000000000000.7fffffffffcp0L, LLONG_MIN, ERRNO_UNCHANGED), + TEST_f_L (llround, -0x8000000000000000.8p0L, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION), + TEST_f_L (llround, -0x8000000000000000.cp0L, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION), +#endif + TEST_f_L (llround, -0x8000010000000000p0, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION), +#ifndef TEST_FLOAT + TEST_f_L (llround, -0x8000000000000800p0, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION), +#endif +#if defined TEST_LDOUBLE && LDBL_MANT_DIG >= 113 + TEST_f_L (llround, -0x8000000000000000.7fffffffffff8p0L, LLONG_MIN, ERRNO_UNCHANGED), +#endif TEST_f_L (llround, 0, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), TEST_f_L (llround, minus_zero, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), TEST_f_L (llround, min_value, 0.0, ERRNO_UNCHANGED), diff --git a/sysdeps/ieee754/dbl-64/s_lround.c b/sysdeps/ieee754/dbl-64/s_lround.c index bdc838a676..91b17b0de9 100644 --- a/sysdeps/ieee754/dbl-64/s_lround.c +++ b/sysdeps/ieee754/dbl-64/s_lround.c @@ -17,6 +17,8 @@ License along with the GNU C Library; if not, see <http://www.gnu.org/licenses/>. */ +#include <fenv.h> +#include <limits.h> #include <math.h> #include <math_private.h> @@ -60,13 +62,33 @@ __lround (double x) if (j0 == 20) result = (long int) i0; else - result = ((long int) i0 << (j0 - 20)) | (j >> (52 - j0)); + { + result = ((long int) i0 << (j0 - 20)) | (j >> (52 - j0)); +#ifdef FE_INVALID + if (sizeof (long int) == 4 + && sign == 1 + && result == LONG_MIN) + /* Rounding brought the value out of range. */ + feraiseexcept (FE_INVALID); +#endif + } } } else { - /* The number is too large. It is left implementation defined - what happens. */ + /* The number is too large. Unless it rounds to LONG_MIN, + FE_INVALID must be raised and the return value is + unspecified. */ +#ifdef FE_INVALID + if (sizeof (long int) == 4 + && x <= (double) LONG_MIN - 0.5) + { + /* If truncation produces LONG_MIN, the cast will not raise + the exception, but may raise "inexact". */ + feraiseexcept (FE_INVALID); + return LONG_MIN; + } +#endif return (long int) x; } diff --git a/sysdeps/ieee754/dbl-64/wordsize-64/s_lround.c b/sysdeps/ieee754/dbl-64/wordsize-64/s_lround.c index 390e733ffd..bbc0628c04 100644 --- a/sysdeps/ieee754/dbl-64/wordsize-64/s_lround.c +++ b/sysdeps/ieee754/dbl-64/wordsize-64/s_lround.c @@ -16,6 +16,8 @@ License along with the GNU C Library; if not, see <http://www.gnu.org/licenses/>. */ +#include <fenv.h> +#include <limits.h> #include <math.h> #include <math_private.h> @@ -48,12 +50,30 @@ __lround (double x) i0 += UINT64_C(0x8000000000000) >> j0; result = i0 >> (52 - j0); +#ifdef FE_INVALID + if (sizeof (long int) == 4 + && sign == 1 + && result == LONG_MIN) + /* Rounding brought the value out of range. */ + feraiseexcept (FE_INVALID); +#endif } } else { - /* The number is too large. It is left implementation defined - what happens. */ + /* The number is too large. Unless it rounds to LONG_MIN, + FE_INVALID must be raised and the return value is + unspecified. */ +#ifdef FE_INVALID + if (sizeof (long int) == 4 + && x <= (double) LONG_MIN - 0.5) + { + /* If truncation produces LONG_MIN, the cast will not raise + the exception, but may raise "inexact". */ + feraiseexcept (FE_INVALID); + return LONG_MIN; + } +#endif return (long int) x; } diff --git a/sysdeps/ieee754/ldbl-128/s_llroundl.c b/sysdeps/ieee754/ldbl-128/s_llroundl.c index 4adc50eaa4..235a433dbe 100644 --- a/sysdeps/ieee754/ldbl-128/s_llroundl.c +++ b/sysdeps/ieee754/ldbl-128/s_llroundl.c @@ -18,6 +18,8 @@ License along with the GNU C Library; if not, see <http://www.gnu.org/licenses/>. */ +#include <fenv.h> +#include <limits.h> #include <math.h> #include <math_private.h> @@ -60,13 +62,30 @@ __llroundl (long double x) if (j0 == 48) result = (long long int) i0; else - result = ((long long int) i0 << (j0 - 48)) | (j >> (112 - j0)); + { + result = ((long long int) i0 << (j0 - 48)) | (j >> (112 - j0)); +#ifdef FE_INVALID + if (sign == 1 && result == LLONG_MIN) + /* Rounding brought the value out of range. */ + feraiseexcept (FE_INVALID); +#endif + } } } else { - /* The number is too large. It is left implementation defined - what happens. */ + /* The number is too large. Unless it rounds to LLONG_MIN, + FE_INVALID must be raised and the return value is + unspecified. */ +#ifdef FE_INVALID + if (x <= (long double) LLONG_MIN - 0.5L) + { + /* If truncation produces LLONG_MIN, the cast will not raise + the exception, but may raise "inexact". */ + feraiseexcept (FE_INVALID); + return LLONG_MIN; + } +#endif return (long long int) x; } diff --git a/sysdeps/ieee754/ldbl-128/s_lroundl.c b/sysdeps/ieee754/ldbl-128/s_lroundl.c index 64b285e291..3c6d26abe1 100644 --- a/sysdeps/ieee754/ldbl-128/s_lroundl.c +++ b/sysdeps/ieee754/ldbl-128/s_lroundl.c @@ -18,6 +18,8 @@ License along with the GNU C Library; if not, see <http://www.gnu.org/licenses/>. */ +#include <fenv.h> +#include <limits.h> #include <math.h> #include <math_private.h> @@ -47,6 +49,13 @@ __lroundl (long double x) { i0 += 0x0000800000000000LL >> j0; result = i0 >> (48 - j0); +#ifdef FE_INVALID + if (sizeof (long int) == 4 + && sign == 1 + && result == LONG_MIN) + /* Rounding brought the value out of range. */ + feraiseexcept (FE_INVALID); +#endif } } else if (j0 >= 112) @@ -60,11 +69,32 @@ __lroundl (long double x) if (j0 == 48) result = (long int) i0; else - result = ((long int) i0 << (j0 - 48)) | (j >> (112 - j0)); + { + result = ((long int) i0 << (j0 - 48)) | (j >> (112 - j0)); +#ifdef FE_INVALID + if (sizeof (long int) == 8 + && sign == 1 + && result == LONG_MIN) + /* Rounding brought the value out of range. */ + feraiseexcept (FE_INVALID); +#endif + } } } else { + /* The number is too large. Unless it rounds to LONG_MIN, + FE_INVALID must be raised and the return value is + unspecified. */ +#ifdef FE_INVALID + if (x <= (long double) LONG_MIN - 0.5L) + { + /* If truncation produces LONG_MIN, the cast will not raise + the exception, but may raise "inexact". */ + feraiseexcept (FE_INVALID); + return LONG_MIN; + } +#endif /* The number is too large. It is left implementation defined what happens. */ return (long int) x; diff --git a/sysdeps/ieee754/ldbl-96/s_llroundl.c b/sysdeps/ieee754/ldbl-96/s_llroundl.c index 8381649269..17a3ccac08 100644 --- a/sysdeps/ieee754/ldbl-96/s_llroundl.c +++ b/sysdeps/ieee754/ldbl-96/s_llroundl.c @@ -17,6 +17,8 @@ License along with the GNU C Library; if not, see <http://www.gnu.org/licenses/>. */ +#include <fenv.h> +#include <limits.h> #include <math.h> #include <math_private.h> @@ -64,7 +66,14 @@ __llroundl (long double x) ++result; if (j0 > 31) - result = (result << (j0 - 31)) | (j >> (63 - j0)); + { + result = (result << (j0 - 31)) | (j >> (63 - j0)); +#ifdef FE_INVALID + if (sign == 1 && result == LLONG_MIN) + /* Rounding brought the value out of range. */ + feraiseexcept (FE_INVALID); +#endif + } } } else diff --git a/sysdeps/ieee754/ldbl-96/s_lroundl.c b/sysdeps/ieee754/ldbl-96/s_lroundl.c index 7a59835783..6bfc2560c3 100644 --- a/sysdeps/ieee754/ldbl-96/s_lroundl.c +++ b/sysdeps/ieee754/ldbl-96/s_lroundl.c @@ -17,6 +17,8 @@ License along with the GNU C Library; if not, see <http://www.gnu.org/licenses/>. */ +#include <fenv.h> +#include <limits.h> #include <math.h> #include <math_private.h> @@ -49,6 +51,13 @@ __lroundl (long double x) } result = j >> (31 - j0); +#ifdef FE_INVALID + if (sizeof (long int) == 4 + && sign == 1 + && result == LONG_MIN) + /* Rounding brought the value out of range. */ + feraiseexcept (FE_INVALID); +#endif } } else if (j0 < (int32_t) (8 * sizeof (long int)) - 1) @@ -66,13 +75,33 @@ __lroundl (long double x) if (j0 == 31) result = ures; else - result = (ures << (j0 - 31)) | (j >> (63 - j0)); + { + result = (ures << (j0 - 31)) | (j >> (63 - j0)); +#ifdef FE_INVALID + if (sizeof (long int) == 8 + && sign == 1 + && result == LONG_MIN) + /* Rounding brought the value out of range. */ + feraiseexcept (FE_INVALID); +#endif + } } } else { - /* The number is too large. It is left implementation defined - what happens. */ + /* The number is too large. Unless it rounds to LONG_MIN, + FE_INVALID must be raised and the return value is + unspecified. */ +#ifdef FE_INVALID + if (sizeof (long int) == 4 + && x <= (long double) LONG_MIN - 0.5L) + { + /* If truncation produces LONG_MIN, the cast will not raise + the exception, but may raise "inexact". */ + feraiseexcept (FE_INVALID); + return LONG_MIN; + } +#endif return (long int) x; } |