diff options
-rw-r--r-- | ChangeLog | 13 | ||||
-rw-r--r-- | stdlib/gen-tst-strtod-round.c | 4 | ||||
-rw-r--r-- | stdlib/strtod_l.c | 14 | ||||
-rw-r--r-- | stdlib/tst-strtod-round-data.h | 26 | ||||
-rw-r--r-- | stdlib/tst-strtod-round-skeleton.c | 18 |
5 files changed, 57 insertions, 18 deletions
@@ -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> * sysdeps/unix/sysv/linux/sparc/sys/user.h: Include stddef.h diff --git a/stdlib/gen-tst-strtod-round.c b/stdlib/gen-tst-strtod-round.c index 1c2823f..8527909 100644 --- a/stdlib/gen-tst-strtod-round.c +++ b/stdlib/gen-tst-strtod-round.c @@ -50,12 +50,12 @@ string_to_fp (mpfr_t f, const char *s, mpfr_rnd_t rnd) mpfr_init2 (f2, 100000); int r0 = mpfr_strtofr (f2, s, NULL, 0, rnd); int r = mpfr_set (f, f2, rnd); - mpfr_subnormalize (f, r, rnd); + r |= mpfr_subnormalize (f, r, rnd); mpfr_clear (f2); return r0 | r; #else int r = mpfr_strtofr (f, s, NULL, 0, rnd); - mpfr_subnormalize (f, r, rnd); + r |= mpfr_subnormalize (f, r, rnd); return r; #endif } diff --git a/stdlib/strtod_l.c b/stdlib/strtod_l.c index 3d66eac..a6c226e 100644 --- a/stdlib/strtod_l.c +++ b/stdlib/strtod_l.c @@ -294,11 +294,14 @@ round_and_return (mp_limb_t *retval, intmax_t exponent, int negative, if (exponent > MAX_EXP) 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, (retval[0] & 1) != 0, - (round_limb & (((mp_limb_t) 1) << round_bit)) != 0, - (more_bits - || (round_limb & ((((mp_limb_t) 1) << round_bit) - 1)) != 0), + half_bit, + more_bits_nonzero, mode)) { 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: 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); } diff --git a/stdlib/tst-strtod-round-data.h b/stdlib/tst-strtod-round-data.h index 1fd3aa8..fc09bc9 100644 --- a/stdlib/tst-strtod-round-data.h +++ b/stdlib/tst-strtod-round-data.h @@ -809,7 +809,7 @@ static const struct test tests[] = { TEST ("0.0000000000000000000000000000000000000000000021019476964872" "256063855943749348741969203929128147736576356024258346866240" "28790902229957282543182373046875", - true, + false, 0x8p-152, 0x1p-148, 0x8p-152, @@ -3454,7 +3454,7 @@ static const struct test tests[] = { 0xcp-152), TEST ("2.1019476964872256063855943749348741969203929128147736576356" "02425834686624028790902229957282543182373046875e-45", - true, + false, 0x8p-152, 0x1p-148, 0x8p-152, @@ -3550,7 +3550,7 @@ static const struct test tests[] = { -0xb.fffffffffffffffffffffffffff8p-152), TEST ("-2.101947696487225606385594374934874196920392912814773657635" "602425834686624028790902229957282543182373046875e-45", - true, + false, -0x1p-148, -0x1p-148, -0x8p-152, @@ -3646,7 +3646,7 @@ static const struct test tests[] = { 0x1.4p-148), TEST ("3.5032461608120426773093239582247903282006548546912894293926" "70709724477706714651503716595470905303955078125e-45", - true, + false, 0x1p-148, 0x1p-148, 0x1p-148, @@ -3742,7 +3742,7 @@ static const struct test tests[] = { -0x1.3fffffffffffffffffffffffffffp-148), TEST ("-3.503246160812042677309323958224790328200654854691289429392" "670709724477706714651503716595470905303955078125e-45", - true, + false, -0x1.8p-148, -0x1p-148, -0x1p-148, @@ -3865,7 +3865,7 @@ static const struct test tests[] = { 0x0p+0, 0x0p+0, 0x8p-152, - true, + false, 0x4p-1076, 0x8p-1076, 0x4p-1076, @@ -3880,7 +3880,7 @@ static const struct test tests[] = { 0x6p-1076, 0x6p-1076, 0x6p-1076, - true, + false, 0x4p-1076, 0x8p-1076, 0x4p-1076, @@ -3994,7 +3994,7 @@ static const struct test tests[] = { -0x0p+0, -0x0p+0, -0x0p+0, - true, + false, -0x8p-1076, -0x8p-1076, -0x4p-1076, @@ -4009,7 +4009,7 @@ static const struct test tests[] = { -0x6p-1076, -0x6p-1076, -0x6p-1076, - true, + false, -0x8p-1076, -0x8p-1076, -0x4p-1076, @@ -4486,7 +4486,7 @@ static const struct test tests[] = { 0x0p+0, 0x0p+0, 0x4p-1076, - true, + false, 0x8p-16448, 0x1p-16444, 0x8p-16448, @@ -5152,7 +5152,7 @@ static const struct test tests[] = { -0x0p+0, -0x0p+0, -0x0p+0, - true, + false, -0x1p-16444, -0x1p-16444, -0x8p-16448, @@ -5818,7 +5818,7 @@ static const struct test tests[] = { 0x0p+0, 0x0p+0, 0x4p-1076, - true, + false, 0x8p-16448, 0x1p-16444, 0x8p-16448, @@ -6484,7 +6484,7 @@ static const struct test tests[] = { -0x0p+0, -0x0p+0, -0x0p+0, - true, + false, -0x1p-16444, -0x1p-16444, -0x8p-16448, diff --git a/stdlib/tst-strtod-round-skeleton.c b/stdlib/tst-strtod-round-skeleton.c index 2e99dbd..89e0987 100644 --- a/stdlib/tst-strtod-round-skeleton.c +++ b/stdlib/tst-strtod-round-skeleton.c @@ -157,8 +157,13 @@ struct test { #define STR(x) STRX (x) #define FNPFXS STR (FNPFX) +#ifndef FE_INEXACT +# define FE_INEXACT 0 +#endif + #define GEN_ONE_TEST(FSUF, FTYPE, FTOSTR, LSUF, CSUF) \ { \ + feclearexcept (FE_INEXACT); \ FTYPE f = STRTO (FSUF) (s, NULL); \ if (f != expected->FSUF \ || (copysign ## CSUF) (1.0 ## LSUF, f) \ @@ -175,6 +180,19 @@ struct test { else \ 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 |