bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: strtod bugs


From: Eric Blake
Subject: Re: strtod bugs
Date: Sun, 30 Mar 2008 16:03:56 -0600
User-agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.12) Gecko/20080213 Thunderbird/2.0.0.12 Mnenhy/0.7.5.666

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

According to Jim Meyering on 3/30/2008 8:49 AM:
|
| In my copy of test-strtod.c, they're all comparing sign bits:
|
|     ASSERT (signbit (result1) != signbit (result2));

The default value of NaN (both sign bit and other bits) are enough of a
portability mess on different hardware that I'm willing to just skip those
tests.  I think a good implementation of strtod should be able to
distinguish between "nan" and "-nan", but as either result will still be
NaN, I'm happy to disable those tests, as in the patch below:

|
| This sort of mix-up is a good argument for not changing
| line numbers when we add the two prefix lines:
|
|     /* -*- buffer-read-only: t -*- vi: set ro: */
|     /* DO NOT EDIT! GENERATED AUTOMATICALLY! */

Ahh.  That makes sense - I was going off the line numbers in gnulib, not
in my bootstrapped copy of coreutils.  Maybe the same bootstrap process
that adds those two lines should add a third line?
#line 1

| When I run the tests on a 32-bit system with ubuntu's
| 2.7-9ubuntu2, I get even more failures:
|
|     PASS: test-string
|     test-strtod.c:285: assertion failed
|     test-strtod.c:371: assertion failed

Parsing "-0" as 0.0 rather than -0.0 - definite bug.  The buildbot is
showing the same failure.  But the buildbot also shows:
checking whether strtod obeys C99... no
              -e 's|@''REPLACE_STRTOD''@|1|g' \

So, just to be clear, are we seeing any platforms that return positive 0
on "-0" but which are not using the replacement function?  However, I
thought strtod.m4 already caught that.

Yet, when I tested the replacement function (in both mingw, where
strtod.m4 selects it, and on cygwin, by using gl_cv_func_strtod_works=no,
but in both cases with gcc -g without optimization), I didn't see this
failure.  I'm wondering if it is a gcc -O2 bug?  I'm not quite sure what
to do here, without access to a machine with those failures.  Can you step
through the replacement function with a debugger?

And just now, I tested cygwin with -O2, and got:

../../m4/tests/test-strtod.c:149: assertion failed
../../m4/tests/test-strtod.c:221: assertion failed

which looks like rounding errors in computing 0.1.  On further thought,
that particular failure is due to x86 registers having more precision than
memory, such that .1 (register) != .1 (memory).  So I've also changed the
test to use .5 instead of .1.

|     test-strtod.c:480: assertion failed

Returning positive zero for negative underflow - glibc bug:
http://sources.redhat.com/bugzilla/show_bug.cgi?id=5995

This is a QoI issue, and not a POSIX-compliance bug, so I'm disabling it
for now.  On the other hand, if this was a case of the replacement
function not returning -0, then it could be the same as the other bugs on
this platform.

|     test-strtod.c:544: assertion failed
|     test-strtod.c:592: assertion failed
|     test-strtod.c:635: assertion failed

disabled per above; sign bits on NaN are quite difficult.

|     test-strtod.c:816: assertion failed

Another case of not returning -0.

|>
|> This shows some different failures, such as on not leaving errno unchanged
|> for "-0".  Also something I should add to strtod.m4.

Well, now that we've straightened out the line number issue, errno is just
fine.  Rather, the problem is that the result has the wrong sign.

- --
Don't work too hard, make some time for fun as well!

Eric Blake             address@hidden
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.8 (Cygwin)
Comment: Public key at home.comcast.net/~ericblake/eblake.gpg
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iEYEARECAAYFAkfwDksACgkQ84KuGfSFAYBOmQCgi4w0SdukTi6p4g3McZBsT/i4
OTcAoKSQ6JOaYf2QcOsaPogj2C9qUb1p
=jUiB
-----END PGP SIGNATURE-----
>From 35029b9098fbe10eeb3ba5833ee5f01b77c5d883 Mon Sep 17 00:00:00 2001
From: Eric Blake <address@hidden>
Date: Sun, 30 Mar 2008 15:57:54 -0600
Subject: [PATCH] More strtod touchups.

* tests/test-strtod.c (main): Ignore tests for signbit on NaN, and
sign of negative underflow, for now.  Use .5, not .1.
* doc/posix-functions/strtod.texi (strtod): Mention these
limitations.
Reported by Jim Meyering.

Signed-off-by: Eric Blake <address@hidden>
---
 ChangeLog                       |    9 +++++++++
 doc/posix-functions/strtod.texi |    7 ++++++-
 tests/test-strtod.c             |   30 ++++++++++++++++++++++++------
 3 files changed, 39 insertions(+), 7 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 5df9267..117ff3d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -19,6 +19,15 @@
 
 2008-03-30  Eric Blake  <address@hidden>
 
+       More strtod touchups.
+       * tests/test-strtod.c (main): Ignore tests for signbit on NaN, and
+       sign of negative underflow, for now.  Use .5, not .1.
+       * doc/posix-functions/strtod.texi (strtod): Mention these
+       limitations.
+       Reported by Jim Meyering.
+
+2008-03-30  Eric Blake  <address@hidden>
+
        strtod touchups.
        * lib/strtod.c (strtod): Avoid compiler warnings.
        Reported by Jim Meyering.
diff --git a/doc/posix-functions/strtod.texi b/doc/posix-functions/strtod.texi
index fecade3..6e137dd 100644
--- a/doc/posix-functions/strtod.texi
+++ b/doc/posix-functions/strtod.texi
@@ -52,7 +52,12 @@ Portability problems not fixed by Gnulib:
 @item
 This function returns a positive value for negative underflow on some
 platforms:
-glibc 2.4, Mingw, Cygwin.
+glibc 2.7, Mingw, Cygwin.
+
address@hidden
+This function cannot distinguish between ``nan'' and ``-nan'' on some
+platforms:
+glibc 2.7.
 
 @item
 This function fails to correctly parse very long strings on some
diff --git a/tests/test-strtod.c b/tests/test-strtod.c
index 59fe7e7..996e3da 100644
--- a/tests/test-strtod.c
+++ b/tests/test-strtod.c
@@ -143,10 +143,10 @@ main ()
   }
   {
     errno = 0;
-    const char input[] = ".1";
+    const char input[] = ".5";
     char *ptr;
     double result = strtod (input, &ptr);
-    ASSERT (result == 0.1);
+    ASSERT (result == 0.5);
     ASSERT (ptr == input + 2);
     ASSERT (errno == 0);
   }
@@ -215,10 +215,10 @@ main ()
   }
   {
     errno = 0;
-    const char input[] = "1e-1";
+    const char input[] = "5e-1";
     char *ptr;
     double result = strtod (input, &ptr);
-    ASSERT (result == 0.1);
+    ASSERT (result == 0.5);
     ASSERT (ptr == input + 4);
     ASSERT (errno == 0);
   }
@@ -443,7 +443,7 @@ main ()
   /* Overflow/underflow.  */
   {
     errno = 0;
-    const char input[] = "1E100000";
+    const char input[] = "1E1000000";
     char *ptr;
     double result = strtod (input, &ptr);
     ASSERT (result == HUGE_VAL);
@@ -452,7 +452,7 @@ main ()
   }
   {
     errno = 0;
-    const char input[] = "-1E100000";
+    const char input[] = "-1E1000000";
     char *ptr;
     double result = strtod (input, &ptr);
     ASSERT (result == -HUGE_VAL);
@@ -475,7 +475,13 @@ main ()
     char *ptr;
     double result = strtod (input, &ptr);
     ASSERT (-FLT_MIN <= result && result <= 0.0);
+#if 0
+    /* FIXME - this is glibc bug 5995; POSIX allows returning positive
+       0 on negative underflow, even though quality of implementation
+       demands preserving the sign.  Disable this test until fixed
+       glibc is more prevalent.  */
     ASSERT (signbit (result) == signbit (-0.0));
+#endif
     ASSERT (ptr == input + 10);
     ASSERT (errno == ERANGE);
   }
@@ -539,7 +545,11 @@ main ()
 #ifdef NAN
     ASSERT (isnan (result1));
     ASSERT (isnan (result2));
+# if 0
+    /* Sign bits of NaN is a portability sticking point, not worth
+       worrying about.  */
     ASSERT (signbit (result1) != signbit (result2));
+# endif
     ASSERT (ptr1 == input + 4);
     ASSERT (ptr2 == input + 4);
     ASSERT (errno == 0);
@@ -587,7 +597,11 @@ main ()
 #ifdef NAN
     ASSERT (isnan (result1));
     ASSERT (isnan (result2));
+# if 0
+    /* Sign bits of NaN is a portability sticking point, not worth
+       worrying about.  */
     ASSERT (signbit (result1) != signbit (result2));
+# endif
     ASSERT (ptr1 == input + 6);
     ASSERT (ptr2 == input + 6);
     ASSERT (errno == 0);
@@ -630,7 +644,11 @@ main ()
 #ifdef NAN
     ASSERT (isnan (result1));
     ASSERT (isnan (result2));
+# if 0
+    /* Sign bits of NaN is a portability sticking point, not worth
+       worrying about.  */
     ASSERT (signbit (result1) != signbit (result2));
+# endif
     ASSERT (ptr1 == input + 7);
     ASSERT (ptr2 == input + 7);
     ASSERT (errno == 0);
-- 
1.5.4


reply via email to

[Prev in Thread] Current Thread [Next in Thread]