OSDN Git Service

stdio: Fix printing 0.0
authorBernhard Reutner-Fischer <rep.dot.nop@gmail.com>
Mon, 15 Dec 2014 15:13:01 +0000 (16:13 +0100)
committerBernhard Reutner-Fischer <rep.dot.nop@gmail.com>
Mon, 15 Dec 2014 16:27:49 +0000 (17:27 +0100)
We were relying on FE_DIVBYZERO being turned off when printing
"%f", +-.0
Avoid the whole issue by looking at the sign-bit (in a rough
approximation).

Note that we do not handle gracefully:
  printf ("\n%llf\n", -0.0);
  printf ("\n%llf\n",  0.0);
nor %Lf for both when NOT cast to long double. Avoiding an FPE due to
broken numbers like these does not make sense to me.

Signed-off-by: Bernhard Reutner-Fischer <rep.dot.nop@gmail.com>
libc/stdio/_fpmaxtostr.c

index f7ea792..3580584 100644 (file)
  */
 #define isnan(x)             ((x) != (x))
 
-/* Without seminumerical functions to examine the sign bit, this is
- * about the best we can do to test for '-0'.
- */
-#define zeroisnegative(x)    ((1./(x)) < 0)
-
 /*****************************************************************************/
 /* Don't change anything that follows peroid!!!  ;-)                         */
 /*****************************************************************************/
@@ -262,7 +257,13 @@ ssize_t _fpmaxtostr(FILE * fp, __fpmax_t x, struct printf_info *info,
 
        if (x == 0) {                           /* Handle 0 now to avoid false positive. */
 #ifdef __UCLIBC_HAVE_SIGNED_ZERO__
-               if (zeroisnegative(x)) { /* Handle 'signed' zero. */
+               union {
+                       double x;
+                       struct {
+                               unsigned int l1, l2;
+                       } i;
+               } u = {x};
+               if (u.i.l1 ^ u.i.l2) { /* Handle 'signed' zero. */
                        *sign_str = '-';
                }
 #endif /* __UCLIBC_HAVE_SIGNED_ZERO__ */