]> sourceware.org Git - glibc.git/commitdiff
Make strtod raise "inexact" exceptions (bug 19380).
authorJoseph Myers <joseph@codesourcery.com>
Fri, 28 Oct 2016 00:40:23 +0000 (00:40 +0000)
committerJoseph Myers <joseph@codesourcery.com>
Fri, 28 Oct 2016 00:40:23 +0000 (00:40 +0000)
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.

ChangeLog
stdlib/gen-tst-strtod-round.c
stdlib/strtod_l.c
stdlib/tst-strtod-round-data.h
stdlib/tst-strtod-round-skeleton.c

index 8b7b3e43cc494bdf9a267e57416ee7018d294e9f..e1f32df616c0c32e7939bf8ab6a496e0e91719e7 100644 (file)
--- 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
index 1c2823f5beecb37c11feeb02a55f5c6cfbdda250..85279090ee629891cb2e130e1eb5f7e67932a619 100644 (file)
@@ -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
 }
index 3d66eac70682c430d211109cbe51cc9a622d4ad9..a6c226ee9f9e0d9fe4c1786abfb032d251bce7eb 100644 (file)
@@ -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);
 }
 
index 1fd3aa87e1adc6421451522661746f66af1d070d..fc09bc91175c315c39a6fd3b9d811b26d9df2f78 100644 (file)
@@ -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,
index 2e99dbdc21542b0831b6ab6c9b1cf73dff1106a9..89e09870ca92a0ec21902d386eb72a7d5aa25991 100644 (file)
@@ -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
This page took 0.167804 seconds and 5 git commands to generate.