about summary refs log tree commit diff
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