Fix lrint, llrint missing exceptions close to overflow threshold (bug 19094).

The dbl-64, ldbl-96 and ldbl-128 implementations of lrint and llrint
fail to produce "invalid" exceptions in cases where the rounded result
overflows the target type, but truncating the floating-point argument
to the next integer towards zero does not overflow it (so in
particular casts do not produce such exceptions).  (This issue cannot
arise for float, or for double with 64-bit target type, or for ldbl-96
with 64-bit target type and negative arguments, because of
insufficient precision in the floating-point type for arguments with
the relevant property to exist.  It also obviously cannot arise in
FE_TOWARDZERO mode.)

This patch fixes these problems by inserting checks for the special
cases that can occur in each implementation, and explicitly raising
FE_INVALID (and avoiding the cast if it might raise spurious
FE_INEXACT, while raising FE_INEXACT explicitly in the cases where it
is needed; unlike lround and llround, FE_INEXACT is required, not
optional, for these functions for a within-range inexact result).

The fixes are conditional on FE_INVALID or FE_INEXACT being defined.
If any future architecture supports one but not both of those
exceptions, the code will fail to compile and need fixing to handle
that case (this seemed better than conditioning on both macros being
defined, resulting in code that would compile but quietly miss
exceptions on such a system).

Tested for x86_64, x86 and mips64.  Tested the ldbl-96 changes (only
relevant for ia64, it appears) on x86_64 by removing the x86_64
versions of lrintl / llrintl.

	[BZ #19094]
	* sysdeps/ieee754/dbl-64/s_lrint.c: Include <fenv.h> and
	<limits.h>.
	(__lrint) [FE_INVALID || FE_INEXACT]: Force FE_INVALID exception
	when result overflows but exception would not result from cast.
	* sysdeps/ieee754/ldbl-128/s_llrintl.c: Include <fenv.h> and
	<limits.h>.
	(__llrintl) [FE_INVALID || FE_INEXACT]: Force FE_INVALID exception
	when result overflows but exception would not result from cast.
	* sysdeps/ieee754/ldbl-128/s_lrintl.c: Include <fenv.h> and
	<limits.h>.
	(__lrintl) [FE_INVALID || FE_INEXACT]: Force FE_INVALID exception
	when result overflows but exception would not result from cast.
	* sysdeps/ieee754/ldbl-96/s_llrintl.c: Include <fenv.h> and
	<limits.h>.
	(__llrintl) [FE_INVALID || FE_INEXACT]: Force FE_INVALID exception
	when result overflows but exception would not result from cast.
	* sysdeps/ieee754/ldbl-96/s_lrintl.c: Include <fenv.h> and
	<limits.h>.
	(__lrintl) [FE_INVALID || FE_INEXACT]: Force FE_INVALID exception
	when result overflows but exception would not result from cast.
	* math/libm-test.inc (lrint_test_data): Add more tests.
	(llrint_test_data): Likewise.
This commit is contained in:
Joseph Myers 2015-10-08 22:17:45 +00:00
parent 240634ec35
commit d0d286d32d
8 changed files with 422 additions and 23 deletions

View File

@ -1,3 +1,29 @@
2015-10-08 Joseph Myers <joseph@codesourcery.com>
[BZ #19094]
* sysdeps/ieee754/dbl-64/s_lrint.c: Include <fenv.h> and
<limits.h>.
(__lrint) [FE_INVALID || FE_INEXACT]: Force FE_INVALID exception
when result overflows but exception would not result from cast.
* sysdeps/ieee754/ldbl-128/s_llrintl.c: Include <fenv.h> and
<limits.h>.
(__llrintl) [FE_INVALID || FE_INEXACT]: Force FE_INVALID exception
when result overflows but exception would not result from cast.
* sysdeps/ieee754/ldbl-128/s_lrintl.c: Include <fenv.h> and
<limits.h>.
(__lrintl) [FE_INVALID || FE_INEXACT]: Force FE_INVALID exception
when result overflows but exception would not result from cast.
* sysdeps/ieee754/ldbl-96/s_llrintl.c: Include <fenv.h> and
<limits.h>.
(__llrintl) [FE_INVALID || FE_INEXACT]: Force FE_INVALID exception
when result overflows but exception would not result from cast.
* sysdeps/ieee754/ldbl-96/s_lrintl.c: Include <fenv.h> and
<limits.h>.
(__lrintl) [FE_INVALID || FE_INEXACT]: Force FE_INVALID exception
when result overflows but exception would not result from cast.
* math/libm-test.inc (lrint_test_data): Add more tests.
(llrint_test_data): Likewise.
2015-10-08 Roland McGrath <roland@hack.frob.com> 2015-10-08 Roland McGrath <roland@hack.frob.com>
[BZ #18872] [BZ #18872]

2
NEWS
View File

@ -19,7 +19,7 @@ Version 2.23
18875, 18887, 18921, 18951, 18952, 18956, 18961, 18966, 18967, 18969, 18875, 18887, 18921, 18951, 18952, 18956, 18961, 18966, 18967, 18969,
18970, 18977, 18980, 18981, 18985, 19003, 19012, 19016, 19018, 19032, 18970, 18977, 18980, 18981, 18985, 19003, 19012, 19016, 19018, 19032,
19046, 19049, 19050, 19059, 19071, 19076, 19077, 19078, 19079, 19085, 19046, 19049, 19050, 19059, 19071, 19076, 19077, 19078, 19079, 19085,
19086, 19088. 19086, 19088, 19094.
* The obsolete header <regexp.h> has been removed. Programs that require * The obsolete header <regexp.h> has been removed. Programs that require
this header must be updated to use <regex.h> instead. this header must be updated to use <regex.h> instead.

View File

@ -7808,6 +7808,155 @@ static const struct test_f_l_data lrint_test_data[] =
#endif #endif
TEST_f_l (lrint, -0x1p64, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION), TEST_f_l (lrint, -0x1p64, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION),
TEST_f_l (lrint, -0x1p65, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION), TEST_f_l (lrint, -0x1p65, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION),
TEST_f_l (lrint, 0x7fffff80p0, 0x7fffff80LL, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
#ifndef TEST_FLOAT
TEST_f_l (lrint, 0x7fffffffp0, 0x7fffffffLL, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
# if LONG_MAX > 0x7fffffff
TEST_f_l (lrint, 0x7fffffff.4p0, 0x7fffffffLL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, 0x7fffffffLL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, 0x7fffffffLL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, 0x80000000LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_f_l (lrint, 0x7fffffff.7ffffcp0, 0x7fffffffLL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, 0x7fffffffLL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, 0x7fffffffLL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, 0x80000000LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_f_l (lrint, 0x7fffffff.8p0, 0x7fffffffLL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, 0x80000000LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, 0x7fffffffLL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, 0x80000000LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_f_l (lrint, 0x7fffffff.cp0, 0x7fffffffLL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, 0x80000000LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, 0x7fffffffLL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, 0x80000000LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED),
# else
TEST_f_l (lrint, 0x7fffffff.4p0, 0x7fffffffLL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, 0x7fffffffLL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, 0x7fffffffLL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION),
TEST_f_l (lrint, 0x7fffffff.7ffffcp0, 0x7fffffffLL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, 0x7fffffffLL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, 0x7fffffffLL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION),
TEST_f_l (lrint, 0x7fffffff.8p0, 0x7fffffffLL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION, 0x7fffffffLL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION),
TEST_f_l (lrint, 0x7fffffff.cp0, 0x7fffffffLL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION, 0x7fffffffLL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION),
# endif
#endif
#if LONG_MAX > 0x7fffffff
# if defined TEST_LDOUBLE && LDBL_MANT_DIG >= 64
TEST_f_l (lrint, 0x7fffffff.7fffffff8p0L, 0x7fffffffLL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, 0x7fffffffLL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, 0x7fffffffLL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, 0x80000000LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED),
# endif
# if defined TEST_LDOUBLE && LDBL_MANT_DIG >= 106
TEST_f_l (lrint, 0x7fffffff.7fffffffffffffffffep0L, 0x7fffffffLL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, 0x7fffffffLL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, 0x7fffffffLL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, 0x80000000LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED),
# endif
# if defined TEST_LDOUBLE && LDBL_MANT_DIG >= 113
TEST_f_l (lrint, 0x7fffffff.7fffffffffffffffffffcp0L, 0x7fffffffLL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, 0x7fffffffLL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, 0x7fffffffLL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, 0x80000000LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED),
# endif
#else
# if defined TEST_LDOUBLE && LDBL_MANT_DIG >= 64
TEST_f_l (lrint, 0x7fffffff.7fffffff8p0L, 0x7fffffffLL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, 0x7fffffffLL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, 0x7fffffffLL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION),
# endif
# if defined TEST_LDOUBLE && LDBL_MANT_DIG >= 106
TEST_f_l (lrint, 0x7fffffff.7fffffffffffffffffep0L, 0x7fffffffLL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, 0x7fffffffLL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, 0x7fffffffLL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION),
# endif
# if defined TEST_LDOUBLE && LDBL_MANT_DIG >= 113
TEST_f_l (lrint, 0x7fffffff.7fffffffffffffffffffcp0L, 0x7fffffffLL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, 0x7fffffffLL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, 0x7fffffffLL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION),
# endif
#endif
#ifndef TEST_FLOAT
# if LONG_MAX > 0x7fffffff
TEST_f_l (lrint, -0x80000000.4p0, -0x80000001LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, -0x80000000LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, -0x80000000LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, -0x80000000LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_f_l (lrint, -0x80000000.7ffff8p0, -0x80000001LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, -0x80000000LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, -0x80000000LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, -0x80000000LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_f_l (lrint, -0x80000000.8p0, -0x80000001LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, -0x80000000LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, -0x80000000LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, -0x80000000LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_f_l (lrint, -0x80000000.cp0, -0x80000001LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, -0x80000001LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, -0x80000000LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, -0x80000000LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_f_l (lrint, -0x80000001p0, -0x80000001LL, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
# else
TEST_f_l (lrint, -0x80000000.4p0, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION, -0x80000000LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, -0x80000000LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, -0x80000000LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_f_l (lrint, -0x80000000.7ffff8p0, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION, -0x80000000LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, -0x80000000LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, -0x80000000LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_f_l (lrint, -0x80000000.8p0, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION, -0x80000000LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, -0x80000000LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, -0x80000000LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_f_l (lrint, -0x80000000.cp0, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION, -0x80000000LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, -0x80000000LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_f_l (lrint, -0x80000001p0, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION),
# endif
#endif
#if LONG_MAX > 0x7fffffff
TEST_f_l (lrint, -0x80000100p0, -0x80000100LL, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
#else
TEST_f_l (lrint, -0x80000100p0, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION),
#endif
#if LONG_MAX > 0x7fffffff
# if defined TEST_LDOUBLE && LDBL_MANT_DIG >= 64
TEST_f_l (lrint, -0x80000000.7fffffffp0L, -0x80000001LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, -0x80000000LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, -0x80000000LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, -0x80000000LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED),
# endif
# if defined TEST_LDOUBLE && LDBL_MANT_DIG >= 106
TEST_f_l (lrint, -0x80000000.7fffffffffffffffffcp0L, -0x80000001LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, -0x80000000LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, -0x80000000LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, -0x80000000LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED),
# endif
# if defined TEST_LDOUBLE && LDBL_MANT_DIG >= 113
TEST_f_l (lrint, -0x80000000.7fffffffffffffffffff8p0L, -0x80000001LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, -0x80000000LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, -0x80000000LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, -0x80000000LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED),
# endif
#else
# if defined TEST_LDOUBLE && LDBL_MANT_DIG >= 64
TEST_f_l (lrint, -0x80000000.7fffffffp0L, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION, -0x80000000LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, -0x80000000LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, -0x80000000LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED),
# endif
# if defined TEST_LDOUBLE && LDBL_MANT_DIG >= 106
TEST_f_l (lrint, -0x80000000.7fffffffffffffffffcp0L, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION, -0x80000000LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, -0x80000000LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, -0x80000000LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED),
# endif
# if defined TEST_LDOUBLE && LDBL_MANT_DIG >= 113
TEST_f_l (lrint, -0x80000000.7fffffffffffffffffff8p0L, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION, -0x80000000LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, -0x80000000LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, -0x80000000LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED),
# endif
#endif
#if LONG_MAX > 0x7fffffff
TEST_f_l (lrint, 0x7fffff8000000000p0, 0x7fffff8000000000LL, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
#else
TEST_f_l (lrint, 0x7fffff8000000000p0, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION),
#endif
#ifndef TEST_FLOAT
# if LONG_MAX > 0x7fffffff
TEST_f_l (lrint, 0x7ffffffffffffc00p0, 0x7ffffffffffffc00LL, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
# else
TEST_f_l (lrint, 0x7ffffffffffffc00p0, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION),
# endif
#endif
#ifdef TEST_LDOUBLE
# if LONG_MAX > 0x7fffffff
TEST_f_l (lrint, 0x7fffffffffffffffp0L, 0x7fffffffffffffffLL, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_f_l (lrint, 0x7fffffffffffffff.8p0L, 0x7fffffffffffffffLL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION, 0x7fffffffffffffffLL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION),
# else
TEST_f_l (lrint, 0x7fffffffffffffffp0L, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION),
TEST_f_l (lrint, 0x7fffffffffffffff.8p0L, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION),
# endif
# if LDBL_MANT_DIG > 64
# if LONG_MAX > 0x7fffffff
TEST_f_l (lrint, 0x7fffffffffffffff.4p0L, 0x7fffffffffffffffLL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, 0x7fffffffffffffffLL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, 0x7fffffffffffffffLL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION),
TEST_f_l (lrint, 0x7fffffffffffffff.cp0L, 0x7fffffffffffffffLL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION, 0x7fffffffffffffffLL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION),
# else
TEST_f_l (lrint, 0x7fffffffffffffff.4p0L, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION),
TEST_f_l (lrint, 0x7fffffffffffffff.cp0L, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION),
# endif
# endif
# if LONG_MAX > 0x7fffffff
# if LDBL_MANT_DIG >= 106
TEST_f_l (lrint, 0x7fffffffffffffff.7fffffffffep0L, 0x7fffffffffffffffLL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, 0x7fffffffffffffffLL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, 0x7fffffffffffffffLL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION),
# endif
# if LDBL_MANT_DIG >= 113
TEST_f_l (lrint, 0x7fffffffffffffff.7fffffffffffcp0L, 0x7fffffffffffffffLL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, 0x7fffffffffffffffLL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, 0x7fffffffffffffffLL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION),
# endif
# else
# if LDBL_MANT_DIG >= 106
TEST_f_l (lrint, 0x7fffffffffffffff.7fffffffffep0L, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION),
# endif
# if LDBL_MANT_DIG >= 113
TEST_f_l (lrint, 0x7fffffffffffffff.7fffffffffffcp0L, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION),
# endif
# endif
#endif
#ifdef TEST_LDOUBLE
TEST_f_l (lrint, -0x8000000000000001p0L, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION),
#endif
#if defined TEST_LDOUBLE && LDBL_MANT_DIG >= 106
# if LONG_MAX > 0x7fffffff
TEST_f_l (lrint, -0x8000000000000000.4p0L, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION, LLONG_MIN, INEXACT_EXCEPTION|ERRNO_UNCHANGED, LLONG_MIN, INEXACT_EXCEPTION|ERRNO_UNCHANGED, LLONG_MIN, INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_f_l (lrint, -0x8000000000000000.7fffffffffcp0L, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION, LLONG_MIN, INEXACT_EXCEPTION|ERRNO_UNCHANGED, LLONG_MIN, INEXACT_EXCEPTION|ERRNO_UNCHANGED, LLONG_MIN, INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_f_l (lrint, -0x8000000000000000.8p0L, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION, LLONG_MIN, INEXACT_EXCEPTION|ERRNO_UNCHANGED, LLONG_MIN, INEXACT_EXCEPTION|ERRNO_UNCHANGED, LLONG_MIN, INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_f_l (lrint, -0x8000000000000000.cp0L, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION, LLONG_MIN, INEXACT_EXCEPTION|ERRNO_UNCHANGED, LLONG_MIN, INEXACT_EXCEPTION|ERRNO_UNCHANGED),
# else
TEST_f_l (lrint, -0x8000000000000000.4p0L, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION),
TEST_f_l (lrint, -0x8000000000000000.7fffffffffcp0L, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION),
TEST_f_l (lrint, -0x8000000000000000.8p0L, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION),
TEST_f_l (lrint, -0x8000000000000000.cp0L, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION),
# endif
#endif
TEST_f_l (lrint, -0x8000010000000000p0, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION),
#ifndef TEST_FLOAT
TEST_f_l (lrint, -0x8000000000000800p0, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION),
#endif
#if defined TEST_LDOUBLE && LDBL_MANT_DIG >= 113
# if LONG_MAX > 0x7fffffff
TEST_f_l (lrint, -0x8000000000000000.7fffffffffff8p0L, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION, LLONG_MIN, INEXACT_EXCEPTION|ERRNO_UNCHANGED, LLONG_MIN, INEXACT_EXCEPTION|ERRNO_UNCHANGED, LLONG_MIN, INEXACT_EXCEPTION|ERRNO_UNCHANGED),
# else
TEST_f_l (lrint, -0x8000000000000000.7fffffffffff8p0L, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION),
# endif
#endif
TEST_f_l (lrint, 0.0, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), TEST_f_l (lrint, 0.0, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_f_l (lrint, minus_zero, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), TEST_f_l (lrint, minus_zero, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_f_l (lrint, min_value, 0, INEXACT_EXCEPTION|ERRNO_UNCHANGED, 0, INEXACT_EXCEPTION|ERRNO_UNCHANGED, 0, INEXACT_EXCEPTION|ERRNO_UNCHANGED, 1, INEXACT_EXCEPTION|ERRNO_UNCHANGED), TEST_f_l (lrint, min_value, 0, INEXACT_EXCEPTION|ERRNO_UNCHANGED, 0, INEXACT_EXCEPTION|ERRNO_UNCHANGED, 0, INEXACT_EXCEPTION|ERRNO_UNCHANGED, 1, INEXACT_EXCEPTION|ERRNO_UNCHANGED),
@ -7975,6 +8124,74 @@ static const struct test_f_L_data llrint_test_data[] =
TEST_f_L (llrint, -0x1p63, LLONG_MIN, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), TEST_f_L (llrint, -0x1p63, LLONG_MIN, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_f_L (llrint, -0x1p64, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION), TEST_f_L (llrint, -0x1p64, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION),
TEST_f_L (llrint, -0x1p65, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION), TEST_f_L (llrint, -0x1p65, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION),
TEST_f_L (llrint, 0x7fffff80p0, 0x7fffff80LL, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
#ifndef TEST_FLOAT
TEST_f_L (llrint, 0x7fffffffp0, 0x7fffffffLL, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_f_L (llrint, 0x7fffffff.4p0, 0x7fffffffLL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, 0x7fffffffLL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, 0x7fffffffLL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, 0x80000000LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_f_L (llrint, 0x7fffffff.7ffffcp0, 0x7fffffffLL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, 0x7fffffffLL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, 0x7fffffffLL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, 0x80000000LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_f_L (llrint, 0x7fffffff.8p0, 0x7fffffffLL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, 0x80000000LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, 0x7fffffffLL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, 0x80000000LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_f_L (llrint, 0x7fffffff.cp0, 0x7fffffffLL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, 0x80000000LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, 0x7fffffffLL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, 0x80000000LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED),
#endif
#if defined TEST_LDOUBLE && LDBL_MANT_DIG >= 64
TEST_f_L (llrint, 0x7fffffff.7fffffff8p0L, 0x7fffffffLL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, 0x7fffffffLL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, 0x7fffffffLL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, 0x80000000LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED),
#endif
#if defined TEST_LDOUBLE && LDBL_MANT_DIG >= 106
TEST_f_L (llrint, 0x7fffffff.7fffffffffffffffffep0L, 0x7fffffffLL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, 0x7fffffffLL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, 0x7fffffffLL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, 0x80000000LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED),
#endif
#if defined TEST_LDOUBLE && LDBL_MANT_DIG >= 113
TEST_f_L (llrint, 0x7fffffff.7fffffffffffffffffffcp0L, 0x7fffffffLL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, 0x7fffffffLL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, 0x7fffffffLL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, 0x80000000LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED),
#endif
#ifndef TEST_FLOAT
TEST_f_L (llrint, -0x80000000.4p0, -0x80000001LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, -0x80000000LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, -0x80000000LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, -0x80000000LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_f_L (llrint, -0x80000000.7ffff8p0, -0x80000001LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, -0x80000000LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, -0x80000000LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, -0x80000000LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_f_L (llrint, -0x80000000.8p0, -0x80000001LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, -0x80000000LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, -0x80000000LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, -0x80000000LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_f_L (llrint, -0x80000000.cp0, -0x80000001LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, -0x80000001LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, -0x80000000LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, -0x80000000LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_f_L (llrint, -0x80000001p0, -0x80000001LL, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
#endif
TEST_f_L (llrint, -0x80000100p0, -0x80000100LL, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
#if defined TEST_LDOUBLE && LDBL_MANT_DIG >= 64
TEST_f_L (llrint, -0x80000000.7fffffffp0L, -0x80000001LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, -0x80000000LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, -0x80000000LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, -0x80000000LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED),
#endif
#if defined TEST_LDOUBLE && LDBL_MANT_DIG >= 106
TEST_f_L (llrint, -0x80000000.7fffffffffffffffffcp0L, -0x80000001LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, -0x80000000LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, -0x80000000LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, -0x80000000LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED),
#endif
#if defined TEST_LDOUBLE && LDBL_MANT_DIG >= 113
TEST_f_L (llrint, -0x80000000.7fffffffffffffffffff8p0L, -0x80000001LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, -0x80000000LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, -0x80000000LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, -0x80000000LL, INEXACT_EXCEPTION|ERRNO_UNCHANGED),
#endif
TEST_f_L (llrint, 0x7fffff8000000000p0, 0x7fffff8000000000LL, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
#ifndef TEST_FLOAT
TEST_f_L (llrint, 0x7ffffffffffffc00p0, 0x7ffffffffffffc00LL, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
#endif
#ifdef TEST_LDOUBLE
TEST_f_L (llrint, 0x7fffffffffffffffp0L, 0x7fffffffffffffffLL, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_f_L (llrint, 0x7fffffffffffffff.8p0L, 0x7fffffffffffffffLL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION, 0x7fffffffffffffffLL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION),
# if LDBL_MANT_DIG > 64
TEST_f_L (llrint, 0x7fffffffffffffff.4p0L, 0x7fffffffffffffffLL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, 0x7fffffffffffffffLL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, 0x7fffffffffffffffLL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION),
TEST_f_L (llrint, 0x7fffffffffffffff.cp0L, 0x7fffffffffffffffLL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION, 0x7fffffffffffffffLL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION),
# endif
# if LDBL_MANT_DIG >= 106
TEST_f_L (llrint, 0x7fffffffffffffff.7fffffffffep0L, 0x7fffffffffffffffLL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, 0x7fffffffffffffffLL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, 0x7fffffffffffffffLL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION),
# endif
# if LDBL_MANT_DIG >= 113
TEST_f_L (llrint, 0x7fffffffffffffff.7fffffffffffcp0L, 0x7fffffffffffffffLL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, 0x7fffffffffffffffLL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, 0x7fffffffffffffffLL, INEXACT_EXCEPTION|ERRNO_UNCHANGED, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION),
# endif
#endif
#ifdef TEST_LDOUBLE
TEST_f_L (llrint, -0x8000000000000001p0L, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION),
#endif
#if defined TEST_LDOUBLE && LDBL_MANT_DIG >= 106
TEST_f_L (llrint, -0x8000000000000000.4p0L, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION, LLONG_MIN, INEXACT_EXCEPTION|ERRNO_UNCHANGED, LLONG_MIN, INEXACT_EXCEPTION|ERRNO_UNCHANGED, LLONG_MIN, INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_f_L (llrint, -0x8000000000000000.7fffffffffcp0L, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION, LLONG_MIN, INEXACT_EXCEPTION|ERRNO_UNCHANGED, LLONG_MIN, INEXACT_EXCEPTION|ERRNO_UNCHANGED, LLONG_MIN, INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_f_L (llrint, -0x8000000000000000.8p0L, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION, LLONG_MIN, INEXACT_EXCEPTION|ERRNO_UNCHANGED, LLONG_MIN, INEXACT_EXCEPTION|ERRNO_UNCHANGED, LLONG_MIN, INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_f_L (llrint, -0x8000000000000000.cp0L, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION, LLONG_MIN, INEXACT_EXCEPTION|ERRNO_UNCHANGED, LLONG_MIN, INEXACT_EXCEPTION|ERRNO_UNCHANGED),
#endif
TEST_f_L (llrint, -0x8000010000000000p0, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION),
#ifndef TEST_FLOAT
TEST_f_L (llrint, -0x8000000000000800p0, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION),
#endif
#if defined TEST_LDOUBLE && LDBL_MANT_DIG >= 113
TEST_f_L (llrint, -0x8000000000000000.7fffffffffff8p0L, IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION, LLONG_MIN, INEXACT_EXCEPTION|ERRNO_UNCHANGED, LLONG_MIN, INEXACT_EXCEPTION|ERRNO_UNCHANGED, LLONG_MIN, INEXACT_EXCEPTION|ERRNO_UNCHANGED),
#endif
TEST_f_L (llrint, 0.0, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), TEST_f_L (llrint, 0.0, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_f_L (llrint, minus_zero, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), TEST_f_L (llrint, minus_zero, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
TEST_f_L (llrint, min_value, 0, INEXACT_EXCEPTION|ERRNO_UNCHANGED, 0, INEXACT_EXCEPTION|ERRNO_UNCHANGED, 0, INEXACT_EXCEPTION|ERRNO_UNCHANGED, 1, INEXACT_EXCEPTION|ERRNO_UNCHANGED), TEST_f_L (llrint, min_value, 0, INEXACT_EXCEPTION|ERRNO_UNCHANGED, 0, INEXACT_EXCEPTION|ERRNO_UNCHANGED, 0, INEXACT_EXCEPTION|ERRNO_UNCHANGED, 1, INEXACT_EXCEPTION|ERRNO_UNCHANGED),

View File

@ -18,6 +18,8 @@
License along with the GNU C Library; if not, see License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */ <http://www.gnu.org/licenses/>. */
#include <fenv.h>
#include <limits.h>
#include <math.h> #include <math.h>
#include <math_private.h> #include <math_private.h>
@ -62,8 +64,22 @@ __lrint (double x)
result = ((long int) i0 << (j0 - 20)) | (i1 << (j0 - 52)); result = ((long int) i0 << (j0 - 20)) | (i1 << (j0 - 52));
else else
{ {
#if defined FE_INVALID || defined FE_INEXACT
/* X < LONG_MAX + 1 implied by J0 < 31. */
if (sizeof (long int) == 4
&& x > (double) LONG_MAX)
{
/* In the event of overflow we must raise the "invalid"
exception, but not "inexact". */
t = __nearbyint (x);
feraiseexcept (t == LONG_MAX ? FE_INEXACT : FE_INVALID);
}
else
#endif
{
w = math_narrow_eval (two52[sx] + x); w = math_narrow_eval (two52[sx] + x);
t = w - two52[sx]; t = w - two52[sx];
}
EXTRACT_WORDS (i0, i1, t); EXTRACT_WORDS (i0, i1, t);
j0 = ((i0 >> 20) & 0x7ff) - 0x3ff; j0 = ((i0 >> 20) & 0x7ff) - 0x3ff;
i0 &= 0xfffff; i0 &= 0xfffff;
@ -77,8 +93,21 @@ __lrint (double x)
} }
else else
{ {
/* The number is too large. It is left implementation defined /* The number is too large. Unless it rounds to LONG_MIN,
what happens. */ FE_INVALID must be raised and the return value is
unspecified. */
#if defined FE_INVALID || defined FE_INEXACT
if (sizeof (long int) == 4
&& x < (double) LONG_MIN
&& x > (double) LONG_MIN - 1.0)
{
/* If truncation produces LONG_MIN, the cast will not raise
the exception, but may raise "inexact". */
t = __nearbyint (x);
feraiseexcept (t == LONG_MIN ? FE_INEXACT : FE_INVALID);
return LONG_MIN;
}
#endif
return (long int) x; return (long int) x;
} }

View File

@ -19,6 +19,8 @@
License along with the GNU C Library; if not, see License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */ <http://www.gnu.org/licenses/>. */
#include <fenv.h>
#include <limits.h>
#include <math.h> #include <math.h>
#include <math_private.h> #include <math_private.h>
@ -47,8 +49,21 @@ __llrintl (long double x)
if (j0 < (int32_t) (8 * sizeof (long long int)) - 1) if (j0 < (int32_t) (8 * sizeof (long long int)) - 1)
{ {
#if defined FE_INVALID || defined FE_INEXACT
/* X < LLONG_MAX + 1 implied by J0 < 63. */
if (x > (long double) LLONG_MAX)
{
/* In the event of overflow we must raise the "invalid"
exception, but not "inexact". */
t = __nearbyintl (x);
feraiseexcept (t == LLONG_MAX ? FE_INEXACT : FE_INVALID);
}
else
#endif
{
w = two112[sx] + x; w = two112[sx] + x;
t = w - two112[sx]; t = w - two112[sx];
}
GET_LDOUBLE_WORDS64 (i0, i1, t); GET_LDOUBLE_WORDS64 (i0, i1, t);
j0 = ((i0 >> 48) & 0x7fff) - 0x3fff; j0 = ((i0 >> 48) & 0x7fff) - 0x3fff;
i0 &= 0x0000ffffffffffffLL; i0 &= 0x0000ffffffffffffLL;
@ -63,8 +78,20 @@ __llrintl (long double x)
} }
else else
{ {
/* The number is too large. It is left implementation defined /* The number is too large. Unless it rounds to LLONG_MIN,
what happens. */ FE_INVALID must be raised and the return value is
unspecified. */
#if defined FE_INVALID || defined FE_INEXACT
if (x < (long double) LLONG_MIN
&& x > (long double) LLONG_MIN - 1.0L)
{
/* If truncation produces LLONG_MIN, the cast will not raise
the exception, but may raise "inexact". */
t = __nearbyintl (x);
feraiseexcept (t == LLONG_MIN ? FE_INEXACT : FE_INVALID);
return LLONG_MIN;
}
#endif
return (long long int) x; return (long long int) x;
} }

View File

@ -19,6 +19,8 @@
License along with the GNU C Library; if not, see License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */ <http://www.gnu.org/licenses/>. */
#include <fenv.h>
#include <limits.h>
#include <math.h> #include <math.h>
#include <math_private.h> #include <math_private.h>
@ -49,8 +51,22 @@ __lrintl (long double x)
{ {
if (j0 < 48) if (j0 < 48)
{ {
#if defined FE_INVALID || defined FE_INEXACT
/* X < LONG_MAX + 1 implied by J0 < 31. */
if (sizeof (long int) == 4
&& x > (long double) LONG_MAX)
{
/* In the event of overflow we must raise the "invalid"
exception, but not "inexact". */
t = __nearbyintl (x);
feraiseexcept (t == LONG_MAX ? FE_INEXACT : FE_INVALID);
}
else
#endif
{
w = two112[sx] + x; w = two112[sx] + x;
t = w - two112[sx]; t = w - two112[sx];
}
GET_LDOUBLE_WORDS64 (i0, i1, t); GET_LDOUBLE_WORDS64 (i0, i1, t);
j0 = ((i0 >> 48) & 0x7fff) - 0x3fff; j0 = ((i0 >> 48) & 0x7fff) - 0x3fff;
i0 &= 0x0000ffffffffffffLL; i0 &= 0x0000ffffffffffffLL;
@ -62,8 +78,22 @@ __lrintl (long double x)
result = ((long int) i0 << (j0 - 48)) | (i1 << (j0 - 112)); result = ((long int) i0 << (j0 - 48)) | (i1 << (j0 - 112));
else else
{ {
#if defined FE_INVALID || defined FE_INEXACT
/* X < LONG_MAX + 1 implied by J0 < 63. */
if (sizeof (long int) == 8
&& x > (long double) LONG_MAX)
{
/* In the event of overflow we must raise the "invalid"
exception, but not "inexact". */
t = __nearbyintl (x);
feraiseexcept (t == LONG_MAX ? FE_INEXACT : FE_INVALID);
}
else
#endif
{
w = two112[sx] + x; w = two112[sx] + x;
t = w - two112[sx]; t = w - two112[sx];
}
GET_LDOUBLE_WORDS64 (i0, i1, t); GET_LDOUBLE_WORDS64 (i0, i1, t);
j0 = ((i0 >> 48) & 0x7fff) - 0x3fff; j0 = ((i0 >> 48) & 0x7fff) - 0x3fff;
i0 &= 0x0000ffffffffffffLL; i0 &= 0x0000ffffffffffffLL;
@ -77,8 +107,20 @@ __lrintl (long double x)
} }
else else
{ {
/* The number is too large. It is left implementation defined /* The number is too large. Unless it rounds to LONG_MIN,
what happens. */ FE_INVALID must be raised and the return value is
unspecified. */
#if defined FE_INVALID || defined FE_INEXACT
if (x < (long double) LONG_MIN
&& x > (long double) LONG_MIN - 1.0L)
{
/* If truncation produces LONG_MIN, the cast will not raise
the exception, but may raise "inexact". */
t = __nearbyintl (x);
feraiseexcept (t == LONG_MIN ? FE_INEXACT : FE_INVALID);
return LONG_MIN;
}
#endif
return (long int) x; return (long int) x;
} }

View File

@ -18,6 +18,8 @@
License along with the GNU C Library; if not, see License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */ <http://www.gnu.org/licenses/>. */
#include <fenv.h>
#include <limits.h>
#include <math.h> #include <math.h>
#include <math_private.h> #include <math_private.h>
@ -50,8 +52,21 @@ __llrintl (long double x)
result = (((long long int) i0 << 32) | i1) << (j0 - 63); result = (((long long int) i0 << 32) | i1) << (j0 - 63);
else else
{ {
#if defined FE_INVALID || defined FE_INEXACT
/* X < LLONG_MAX + 1 implied by J0 < 63. */
if (x > (long double) LLONG_MAX)
{
/* In the event of overflow we must raise the "invalid"
exception, but not "inexact". */
t = __nearbyintl (x);
feraiseexcept (t == LLONG_MAX ? FE_INEXACT : FE_INVALID);
}
else
#endif
{
w = two63[sx] + x; w = two63[sx] + x;
t = w - two63[sx]; t = w - two63[sx];
}
GET_LDOUBLE_WORDS (se, i0, i1, t); GET_LDOUBLE_WORDS (se, i0, i1, t);
j0 = (se & 0x7fff) - 0x3fff; j0 = (se & 0x7fff) - 0x3fff;

View File

@ -18,6 +18,8 @@
License along with the GNU C Library; if not, see License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */ <http://www.gnu.org/licenses/>. */
#include <fenv.h>
#include <limits.h>
#include <math.h> #include <math.h>
#include <math_private.h> #include <math_private.h>
@ -46,8 +48,22 @@ __lrintl (long double x)
if (j0 < 31) if (j0 < 31)
{ {
#if defined FE_INVALID || defined FE_INEXACT
/* X < LONG_MAX + 1 implied by J0 < 31. */
if (sizeof (long int) == 4
&& x > (long double) LONG_MAX)
{
/* In the event of overflow we must raise the "invalid"
exception, but not "inexact". */
t = __nearbyintl (x);
feraiseexcept (t == LONG_MAX ? FE_INEXACT : FE_INVALID);
}
else
#endif
{
w = two63[sx] + x; w = two63[sx] + x;
t = w - two63[sx]; t = w - two63[sx];
}
GET_LDOUBLE_WORDS (se, i0, i1, t); GET_LDOUBLE_WORDS (se, i0, i1, t);
j0 = (se & 0x7fff) - 0x3fff; j0 = (se & 0x7fff) - 0x3fff;
@ -59,8 +75,22 @@ __lrintl (long double x)
result = ((long int) i0 << (j0 - 31)) | (i1 << (j0 - 63)); result = ((long int) i0 << (j0 - 31)) | (i1 << (j0 - 63));
else else
{ {
#if defined FE_INVALID || defined FE_INEXACT
/* X < LONG_MAX + 1 implied by J0 < 63. */
if (sizeof (long int) == 8
&& x > (long double) LONG_MAX)
{
/* In the event of overflow we must raise the "invalid"
exception, but not "inexact". */
t = __nearbyintl (x);
feraiseexcept (t == LONG_MAX ? FE_INEXACT : FE_INVALID);
}
else
#endif
{
w = two63[sx] + x; w = two63[sx] + x;
t = w - two63[sx]; t = w - two63[sx];
}
GET_LDOUBLE_WORDS (se, i0, i1, t); GET_LDOUBLE_WORDS (se, i0, i1, t);
j0 = (se & 0x7fff) - 0x3fff; j0 = (se & 0x7fff) - 0x3fff;
@ -72,8 +102,21 @@ __lrintl (long double x)
} }
else else
{ {
/* The number is too large. It is left implementation defined /* The number is too large. Unless it rounds to LONG_MIN,
what happens. */ FE_INVALID must be raised and the return value is
unspecified. */
#if defined FE_INVALID || defined FE_INEXACT
if (sizeof (long int) == 4
&& x < (long double) LONG_MIN
&& x > (long double) LONG_MIN - 1.0L)
{
/* If truncation produces LONG_MIN, the cast will not raise
the exception, but may raise "inexact". */
t = __nearbyintl (x);
feraiseexcept (t == LONG_MIN ? FE_INEXACT : FE_INVALID);
return LONG_MIN;
}
#endif
return (long int) x; return (long int) x;
} }