1
0
mirror of https://sourceware.org/git/glibc.git synced 2025-07-29 11:41:21 +03:00

Make strtod raise "inexact" exceptions (bug 19380).

The strtod function should raise the "inexact" exception when its
result is inexact, but fails to do so except in the case of underflow
or overflow.  This patch fixes it to do so for all inexact results.

tst-strtod-round is extended to test for this exception; the generator
is fixed to properly mark inexact results as such in the case where
the inexactness is from the mpfr_subnormalize step.

Tested for x86_64, x86 and powerpc.

	[BZ #19380]
	* stdlib/strtod_l.c (round_and_return): Force "inexact" exception
	for inexact results.
	* stdlib/gen-tst-strtod-round.c (string_to_fp): Return indication
	of inexact result where mpfr_subnormalize is the only inexact
	step.
	* stdlib/tst-strtod-round-data.h: Regenerated.
	* stdlib/tst-strtod-round-skeleton.c [!FE_INEXACT] (FE_INEXACT):
	Define to 0.
	(GEN_ONE_TEST): Test inexact exceptions raised are as expected.
This commit is contained in:
Joseph Myers
2016-10-28 00:40:23 +00:00
parent 61668b22f5
commit 4725d33eed
5 changed files with 57 additions and 18 deletions

View File

@ -1,3 +1,16 @@
2016-10-28 Joseph Myers <joseph@codesourcery.com>
[BZ #19380]
* stdlib/strtod_l.c (round_and_return): Force "inexact" exception
for inexact results.
* stdlib/gen-tst-strtod-round.c (string_to_fp): Return indication
of inexact result where mpfr_subnormalize is the only inexact
step.
* stdlib/tst-strtod-round-data.h: Regenerated.
* stdlib/tst-strtod-round-skeleton.c [!FE_INEXACT] (FE_INEXACT):
Define to 0.
(GEN_ONE_TEST): Test inexact exceptions raised are as expected.
2016-10-27 David S. Miller <davem@davemloft.net> 2016-10-27 David S. Miller <davem@davemloft.net>
* sysdeps/unix/sysv/linux/sparc/sys/user.h: Include stddef.h * sysdeps/unix/sysv/linux/sparc/sys/user.h: Include stddef.h

View File

@ -50,12 +50,12 @@ string_to_fp (mpfr_t f, const char *s, mpfr_rnd_t rnd)
mpfr_init2 (f2, 100000); mpfr_init2 (f2, 100000);
int r0 = mpfr_strtofr (f2, s, NULL, 0, rnd); int r0 = mpfr_strtofr (f2, s, NULL, 0, rnd);
int r = mpfr_set (f, f2, rnd); int r = mpfr_set (f, f2, rnd);
mpfr_subnormalize (f, r, rnd); r |= mpfr_subnormalize (f, r, rnd);
mpfr_clear (f2); mpfr_clear (f2);
return r0 | r; return r0 | r;
#else #else
int r = mpfr_strtofr (f, s, NULL, 0, rnd); int r = mpfr_strtofr (f, s, NULL, 0, rnd);
mpfr_subnormalize (f, r, rnd); r |= mpfr_subnormalize (f, r, rnd);
return r; return r;
#endif #endif
} }

View File

@ -294,11 +294,14 @@ round_and_return (mp_limb_t *retval, intmax_t exponent, int negative,
if (exponent > MAX_EXP) if (exponent > MAX_EXP)
goto overflow; goto overflow;
bool half_bit = (round_limb & (((mp_limb_t) 1) << round_bit)) != 0;
bool more_bits_nonzero
= (more_bits
|| (round_limb & ((((mp_limb_t) 1) << round_bit) - 1)) != 0);
if (round_away (negative, if (round_away (negative,
(retval[0] & 1) != 0, (retval[0] & 1) != 0,
(round_limb & (((mp_limb_t) 1) << round_bit)) != 0, half_bit,
(more_bits more_bits_nonzero,
|| (round_limb & ((((mp_limb_t) 1) << round_bit) - 1)) != 0),
mode)) mode))
{ {
mp_limb_t cy = __mpn_add_1 (retval, retval, RETURN_LIMB_SIZE, 1); mp_limb_t cy = __mpn_add_1 (retval, retval, RETURN_LIMB_SIZE, 1);
@ -325,6 +328,11 @@ round_and_return (mp_limb_t *retval, intmax_t exponent, int negative,
overflow: overflow:
return overflow_value (negative); return overflow_value (negative);
if (half_bit || more_bits_nonzero)
{
FLOAT force_inexact = (FLOAT) 1 + MIN_VALUE;
math_force_eval (force_inexact);
}
return MPN2FLOAT (retval, exponent, negative); return MPN2FLOAT (retval, exponent, negative);
} }

View File

@ -809,7 +809,7 @@ static const struct test tests[] = {
TEST ("0.0000000000000000000000000000000000000000000021019476964872" TEST ("0.0000000000000000000000000000000000000000000021019476964872"
"256063855943749348741969203929128147736576356024258346866240" "256063855943749348741969203929128147736576356024258346866240"
"28790902229957282543182373046875", "28790902229957282543182373046875",
true, false,
0x8p-152, 0x8p-152,
0x1p-148, 0x1p-148,
0x8p-152, 0x8p-152,
@ -3454,7 +3454,7 @@ static const struct test tests[] = {
0xcp-152), 0xcp-152),
TEST ("2.1019476964872256063855943749348741969203929128147736576356" TEST ("2.1019476964872256063855943749348741969203929128147736576356"
"02425834686624028790902229957282543182373046875e-45", "02425834686624028790902229957282543182373046875e-45",
true, false,
0x8p-152, 0x8p-152,
0x1p-148, 0x1p-148,
0x8p-152, 0x8p-152,
@ -3550,7 +3550,7 @@ static const struct test tests[] = {
-0xb.fffffffffffffffffffffffffff8p-152), -0xb.fffffffffffffffffffffffffff8p-152),
TEST ("-2.101947696487225606385594374934874196920392912814773657635" TEST ("-2.101947696487225606385594374934874196920392912814773657635"
"602425834686624028790902229957282543182373046875e-45", "602425834686624028790902229957282543182373046875e-45",
true, false,
-0x1p-148, -0x1p-148,
-0x1p-148, -0x1p-148,
-0x8p-152, -0x8p-152,
@ -3646,7 +3646,7 @@ static const struct test tests[] = {
0x1.4p-148), 0x1.4p-148),
TEST ("3.5032461608120426773093239582247903282006548546912894293926" TEST ("3.5032461608120426773093239582247903282006548546912894293926"
"70709724477706714651503716595470905303955078125e-45", "70709724477706714651503716595470905303955078125e-45",
true, false,
0x1p-148, 0x1p-148,
0x1p-148, 0x1p-148,
0x1p-148, 0x1p-148,
@ -3742,7 +3742,7 @@ static const struct test tests[] = {
-0x1.3fffffffffffffffffffffffffffp-148), -0x1.3fffffffffffffffffffffffffffp-148),
TEST ("-3.503246160812042677309323958224790328200654854691289429392" TEST ("-3.503246160812042677309323958224790328200654854691289429392"
"670709724477706714651503716595470905303955078125e-45", "670709724477706714651503716595470905303955078125e-45",
true, false,
-0x1.8p-148, -0x1.8p-148,
-0x1p-148, -0x1p-148,
-0x1p-148, -0x1p-148,
@ -3865,7 +3865,7 @@ static const struct test tests[] = {
0x0p+0, 0x0p+0,
0x0p+0, 0x0p+0,
0x8p-152, 0x8p-152,
true, false,
0x4p-1076, 0x4p-1076,
0x8p-1076, 0x8p-1076,
0x4p-1076, 0x4p-1076,
@ -3880,7 +3880,7 @@ static const struct test tests[] = {
0x6p-1076, 0x6p-1076,
0x6p-1076, 0x6p-1076,
0x6p-1076, 0x6p-1076,
true, false,
0x4p-1076, 0x4p-1076,
0x8p-1076, 0x8p-1076,
0x4p-1076, 0x4p-1076,
@ -3994,7 +3994,7 @@ static const struct test tests[] = {
-0x0p+0, -0x0p+0,
-0x0p+0, -0x0p+0,
-0x0p+0, -0x0p+0,
true, false,
-0x8p-1076, -0x8p-1076,
-0x8p-1076, -0x8p-1076,
-0x4p-1076, -0x4p-1076,
@ -4009,7 +4009,7 @@ static const struct test tests[] = {
-0x6p-1076, -0x6p-1076,
-0x6p-1076, -0x6p-1076,
-0x6p-1076, -0x6p-1076,
true, false,
-0x8p-1076, -0x8p-1076,
-0x8p-1076, -0x8p-1076,
-0x4p-1076, -0x4p-1076,
@ -4486,7 +4486,7 @@ static const struct test tests[] = {
0x0p+0, 0x0p+0,
0x0p+0, 0x0p+0,
0x4p-1076, 0x4p-1076,
true, false,
0x8p-16448, 0x8p-16448,
0x1p-16444, 0x1p-16444,
0x8p-16448, 0x8p-16448,
@ -5152,7 +5152,7 @@ static const struct test tests[] = {
-0x0p+0, -0x0p+0,
-0x0p+0, -0x0p+0,
-0x0p+0, -0x0p+0,
true, false,
-0x1p-16444, -0x1p-16444,
-0x1p-16444, -0x1p-16444,
-0x8p-16448, -0x8p-16448,
@ -5818,7 +5818,7 @@ static const struct test tests[] = {
0x0p+0, 0x0p+0,
0x0p+0, 0x0p+0,
0x4p-1076, 0x4p-1076,
true, false,
0x8p-16448, 0x8p-16448,
0x1p-16444, 0x1p-16444,
0x8p-16448, 0x8p-16448,
@ -6484,7 +6484,7 @@ static const struct test tests[] = {
-0x0p+0, -0x0p+0,
-0x0p+0, -0x0p+0,
-0x0p+0, -0x0p+0,
true, false,
-0x1p-16444, -0x1p-16444,
-0x1p-16444, -0x1p-16444,
-0x8p-16448, -0x8p-16448,

View File

@ -157,8 +157,13 @@ struct test {
#define STR(x) STRX (x) #define STR(x) STRX (x)
#define FNPFXS STR (FNPFX) #define FNPFXS STR (FNPFX)
#ifndef FE_INEXACT
# define FE_INEXACT 0
#endif
#define GEN_ONE_TEST(FSUF, FTYPE, FTOSTR, LSUF, CSUF) \ #define GEN_ONE_TEST(FSUF, FTYPE, FTOSTR, LSUF, CSUF) \
{ \ { \
feclearexcept (FE_INEXACT); \
FTYPE f = STRTO (FSUF) (s, NULL); \ FTYPE f = STRTO (FSUF) (s, NULL); \
if (f != expected->FSUF \ if (f != expected->FSUF \
|| (copysign ## CSUF) (1.0 ## LSUF, f) \ || (copysign ## CSUF) (1.0 ## LSUF, f) \
@ -175,6 +180,19 @@ struct test {
else \ else \
printf ("ignoring this inexact result\n"); \ printf ("ignoring this inexact result\n"); \
} \ } \
else if (FE_INEXACT != 0) \
{ \
bool inexact_raised = fetestexcept (FE_INEXACT) != 0; \
if (inexact_raised != !exact->FSUF) \
{ \
printf (FNPFXS "to" #FSUF " (" STRM ") inexact %d " \
"not %d\n", s, inexact_raised, !exact->FSUF); \
if (EXCEPTION_TESTS (FTYPE)) \
result = 1; \
else \
printf ("ignoring this exception error\n"); \
} \
} \
} }
static int static int