public inbox for libc-alpha@sourceware.org
 help / color / mirror / Atom feed
From: Joseph Myers <joseph@codesourcery.com>
To: <libc-alpha@sourceware.org>
Subject: Make strtod raise "inexact" exceptions (bug 19380) [committed]
Date: Fri, 28 Oct 2016 00:41:00 -0000	[thread overview]
Message-ID: <alpine.DEB.2.20.1610280041010.22353@digraph.polyomino.org.uk> (raw)

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.  Committed.

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.

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

-- 
Joseph S. Myers
joseph@codesourcery.com

                 reply	other threads:[~2016-10-28  0:41 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=alpine.DEB.2.20.1610280041010.22353@digraph.polyomino.org.uk \
    --to=joseph@codesourcery.com \
    --cc=libc-alpha@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).