aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog13
-rw-r--r--stdlib/gen-tst-strtod-round.c4
-rw-r--r--stdlib/strtod_l.c14
-rw-r--r--stdlib/tst-strtod-round-data.h26
-rw-r--r--stdlib/tst-strtod-round-skeleton.c18
5 files changed, 57 insertions, 18 deletions
diff --git a/ChangeLog b/ChangeLog
index 8b7b3e43cc..e1f32df616 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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 1c2823f5be..85279090ee 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 3d66eac706..a6c226ee9f 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 1fd3aa87e1..fc09bc9117 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 2e99dbdc21..89e09870ca 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