public inbox for libc-hacker@sourceware.org
 help / color / mirror / Atom feed
From: Jakub Jelinek <jakub@redhat.com>
To: Ulrich Drepper <drepper@redhat.com>, Steven Munroe <munroesj@us.ibm.com>
Cc: Glibc hackers <libc-hacker@sources.redhat.com>
Subject: [PATCH] Fix *printf %La with IBM long double format
Date: Mon, 04 Jun 2007 13:00:00 -0000	[thread overview]
Message-ID: <20070604130209.GM3081@sunsite.mff.cuni.cz> (raw)

Hi!

As the attached testcase shows, printf_fphex for ldbl-128ibm
has a bunch of issues when the lower double is denormal or has exponent 1.
E.g. the implicit mantissa bit needs to be also set for exponent 1,
the difference between exponents might be smaller than 53 (when the
smaller double is denormal and the bigger double has exponent less than
53, etc.

I've also included the unrelated workaround for test-misc.c failures
- the tests from 2007-05-03 aren't really testable on ppc/ppc64.

2007-06-04  Jakub Jelinek  <jakub@redhat.com>

	* sysdeps/ieee754/ldbl-128ibm/printf_fphex.c
	(PRINT_FPHEX_LONG_DOUBLE): Fix printing numbers where lower double
	is non-zero, but smaller than 2 * __DBL_MIN__.
	* stdio-common/tst-sprintf2.c: New test.
	* stdio-common/Makefile (tests): Add tst-sprintf2.

	* math/test-misc.c (main): Don't run last batch of tests with
	IBM long double format.

--- libc/sysdeps/ieee754/ldbl-128ibm/printf_fphex.c.jj	2006-01-28 01:07:25.000000000 +0100
+++ libc/sysdeps/ieee754/ldbl-128ibm/printf_fphex.c	2007-06-04 14:02:12.000000000 +0200
@@ -1,5 +1,5 @@
 /* Print floating point number in hexadecimal notation according to ISO C99.
-   Copyright (C) 1997,1998,1999,2000,2001,2002,2004,2006
+   Copyright (C) 1997,1998,1999,2000,2001,2002,2004,2006,2007
 	Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
@@ -35,21 +35,24 @@ do {									      \
 									      \
       lo = ((long long)eldbl.ieee.mantissa2 << 32) | eldbl.ieee.mantissa3;    \
       hi = ((long long)eldbl.ieee.mantissa0 << 32) | eldbl.ieee.mantissa1;    \
-   /* If the lower double is not a denomal or zero then set the hidden	      \
-      53rd bit.  */							      \
-      if (eldbl.ieee.exponent2 > 0x001)					      \
-	{								      \
-	  lo |= (1ULL << 52);						      \
-	  lo = lo << 7; /* pre-shift lo to match ieee854.  */		      \
-	  /* The lower double is normalized separately from the upper.  We    \
-	     may need to adjust the lower manitissa to reflect this.  */      \
-	  ediff = eldbl.ieee.exponent - eldbl.ieee.exponent2;		      \
-	  if (ediff > 53)						      \
-	    lo = lo >> (ediff-53);					      \
-	}								      \
-  									      \
-      if ((eldbl.ieee.negative != eldbl.ieee.negative2)			      \
-	  && ((eldbl.ieee.exponent2 != 0) && (lo != 0L)))		      \
+      lo <<= 7; /* pre-shift lo to match ieee854.  */			      \
+      /* If the lower double is not a denomal or zero then set the hidden     \
+	 53rd bit.  */							      \
+      if (eldbl.ieee.exponent2 != 0)					      \
+	lo |= (1ULL << (52 + 7));					      \
+      else								      \
+	lo <<= 1;							      \
+      /* The lower double is normalized separately from the upper.  We	      \
+	 may need to adjust the lower manitissa to reflect this.  */	      \
+      ediff = eldbl.ieee.exponent - eldbl.ieee.exponent2;		      \
+      if (ediff > 53 + 63)						      \
+	lo = 0;								      \
+      else if (ediff > 53)						      \
+	lo = lo >> (ediff - 53);					      \
+      else if (eldbl.ieee.exponent2 == 0 && ediff < 53)			      \
+	lo = lo << (53 - ediff);					      \
+      if (eldbl.ieee.negative != eldbl.ieee.negative2			      \
+	  && (eldbl.ieee.exponent2 != 0 || lo != 0L))			      \
 	{								      \
 	  lo = (1ULL << 60) - lo;					      \
 	  if (hi == 0L)							      \
--- libc/stdio-common/Makefile.jj	2007-03-19 17:43:12.000000000 +0100
+++ libc/stdio-common/Makefile	2007-06-04 14:05:02.000000000 +0200
@@ -54,7 +54,7 @@ tests := tstscanf test_rdwr test-popen t
 	 tst-swprintf tst-fseek tst-fmemopen test-vfprintf tst-gets \
 	 tst-perror tst-sprintf tst-rndseek tst-fdopen tst-fphex bug14 bug15 \
 	 tst-popen tst-unlockedio tst-fmemopen2 tst-put-error tst-fgets \
-	 tst-fwrite bug16 bug17 tst-swscanf
+	 tst-fwrite bug16 bug17 tst-swscanf tst-sprintf2
 
 test-srcs = tst-unbputc tst-printf
 
--- libc/stdio-common/tst-sprintf2.c.jj	2007-06-04 14:03:18.000000000 +0200
+++ libc/stdio-common/tst-sprintf2.c	2007-06-04 14:04:35.000000000 +0200
@@ -0,0 +1,59 @@
+#include <float.h>
+#include <math.h>
+#include <stdio.h>
+
+int
+main (void)
+{
+  volatile union { long double l; long long x[2]; } u;
+  char buf[64];
+  int result = 0;
+
+#define TEST(val) \
+  do									   \
+    {									   \
+      u.l = (val);							   \
+      snprintf (buf, sizeof buf, "%LaL", u.l);				   \
+      if (strcmp (buf, #val) != 0)					   \
+	{								   \
+	  printf ("Error on line %d: %s != %s\n", __LINE__, buf, #val);	   \
+	  result = 1;							   \
+	}								   \
+      /* printf ("%s %La %016Lx %016Lx\n", #val, u.l, u.x[0], u.x[1]); */  \
+    }									   \
+  while (0)
+
+#if LDBL_MANT_DIG >= 106
+# if LDBL_MANT_DIG == 106
+  TEST (0x0.ffffffffffffp-1022L);
+  TEST (0x0.ffffffffffff1p-1022L);
+  TEST (0x0.fffffffffffffp-1022L);
+# endif
+  TEST (0x1p-1022L);
+  TEST (0x1.0000000000001p-1022L);
+  TEST (0x1.00000000001e7p-1022L);
+  TEST (0x1.fffffffffffffp-1022L);
+  TEST (0x1p-1021L);
+  TEST (0x1.00000000000008p-1021L);
+  TEST (0x1.0000000000001p-1021L);
+  TEST (0x1.00000000000018p-1021L);
+  TEST (0x1.0000000000000f8p-1017L);
+  TEST (0x1.0000000000001p-1017L);
+  TEST (0x1.000000000000108p-1017L);
+  TEST (0x1.000000000000dcf8p-1013L);
+  TEST (0x1.000000000000ddp-1013L);
+  TEST (0x1.000000000000dd08p-1013L);
+  TEST (0x1.ffffffffffffffffffffffffffp-1L);
+  TEST (0x1.ffffffffffffffffffffffffff8p-1L);
+  TEST (0x1p+0L);
+  TEST (0x1.000000000000000000000000008p+0L);
+  TEST (0x1.00000000000000000000000001p+0L);
+  TEST (0x1.000000000000000000000000018p+0L);
+  TEST (0x1.23456789abcdef123456789abc8p+0L);
+  TEST (0x1.23456789abcde7123456789abc8p+0L);
+  TEST (0x1.23456789abcdef123456789abc8p+64L);
+  TEST (0x1.23456789abcde7123456789abc8p+64L);
+  TEST (0x1.123456789abcdef123456789p-969L);
+#endif
+  return result;
+}
--- libc/math/test-misc.c.jj	2007-05-24 16:41:05.000000000 +0200
+++ libc/math/test-misc.c	2007-06-01 18:28:29.000000000 +0200
@@ -1235,7 +1235,12 @@ main (void)
     }
 #endif
 
-#if !defined NO_LONG_DOUBLE && LDBL_MANT_DIG >= DBL_MANT_DIG + 4
+/* Skip testing IBM long double format, for 2 reasons:
+   1) it only supports FE_TONEAREST
+   2) nextafter (0.0, 1.0) == nextafterl (0.0L, 1.0L), so
+      nextafter (0.0, 1.0) / 16.0L will be 0.0L.  */
+#if !defined NO_LONG_DOUBLE && LDBL_MANT_DIG >= DBL_MANT_DIG + 4 \
+    && LDBL_MANT_DIG != 106
   int oldmode = fegetround ();
   int j;
   for (j = 0; j < 4; j++)

	Jakub

             reply	other threads:[~2007-06-04 13:00 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-06-04 13:00 Jakub Jelinek [this message]
2007-06-06 13:28 ` Steven Munroe

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=20070604130209.GM3081@sunsite.mff.cuni.cz \
    --to=jakub@redhat.com \
    --cc=drepper@redhat.com \
    --cc=libc-hacker@sources.redhat.com \
    --cc=munroesj@us.ibm.com \
    /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).