strtod: work around icc bug
authorEric Blake <eblake@redhat.com>
Fri, 5 Nov 2010 14:30:27 +0000 (08:30 -0600)
committerEric Blake <eblake@redhat.com>
Fri, 5 Nov 2010 14:30:39 +0000 (08:30 -0600)
With optimization, ICC 10.0 mis-compiles 'cond ? -val : val' such
that a val of 0.0 doesn't result in -0.0.

* lib/strtod.c (minus_zero): Define to working value.
(strtod): Use it to avoid icc bug.

Signed-off-by: Eric Blake <eblake@redhat.com>
ChangeLog
lib/strtod.c

index 7af53b8..1711e5b 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,9 @@
 2010-11-05  Eric Blake  <eblake@redhat.com>
 
+       strtod: work around icc bug
+       * lib/strtod.c (minus_zero): Define to working value.
+       (strtod): Use it to avoid icc bug.
+
        copysign: enhance tests
        * modules/copysign-tests (Files): Add minus-zero.h.
        * tests/test-copysign.c (main): Also test zeros.
index 060dffa..cd61add 100644 (file)
@@ -190,6 +190,21 @@ parse_number (const char *nptr,
 
 static double underlying_strtod (const char *, char **);
 
+/* HP cc on HP-UX 10.20 has a bug with the constant expression -0.0.
+   ICC 10.0 has a bug when optimizing the expression -zero.
+   The expression -DBL_MIN * DBL_MIN does not work when cross-compiling
+   to PowerPC on MacOS X 10.5.  */
+#if defined __hpux || defined __sgi || defined __ICC
+static double
+compute_minus_zero (void)
+{
+  return -DBL_MIN * DBL_MIN;
+}
+# define minus_zero compute_minus_zero ()
+#else
+double minus_zero = -0.0;
+#endif
+
 /* Convert NPTR to a double.  If ENDPTR is not NULL, a pointer to the
    character after the last one used in the number is put in *ENDPTR.  */
 double
@@ -320,6 +335,10 @@ strtod (const char *nptr, char **endptr)
 
   if (endptr != NULL)
     *endptr = (char *) s;
+  /* Special case -0.0, since at least ICC miscompiles negation.  We
+     can't use copysign(), as that drags in -lm on some platforms.  */
+  if (!num && negative)
+    return minus_zero;
   return negative ? -num : num;
 }