diff options
Diffstat (limited to 'sysdeps/ieee754/dbl-64/s_lround.c')
-rw-r--r-- | sysdeps/ieee754/dbl-64/s_lround.c | 28 |
1 files changed, 25 insertions, 3 deletions
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; } |