summary refs log tree commit diff
path: root/stdio-common
diff options
context:
space:
mode:
authorPaul E. Murphy <murphyp@linux.vnet.ibm.com>2016-02-29 13:27:36 -0600
committerPaul E. Murphy <murphyp@linux.vnet.ibm.com>2016-03-31 12:14:33 -0500
commit37a4c70bd4c5c74ac562072e450dc02e8cb4c150 (patch)
treec9a631e747dcb7ca4213c93460d7e45d153a0771 /stdio-common
parent830566307f038387ca0af3fd327706a8d1a2f595 (diff)
downloadglibc-37a4c70bd4c5c74ac562072e450dc02e8cb4c150.tar.gz
glibc-37a4c70bd4c5c74ac562072e450dc02e8cb4c150.tar.xz
glibc-37a4c70bd4c5c74ac562072e450dc02e8cb4c150.zip
Increase internal precision of ldbl-128ibm decimal printf [BZ #19853]
When the signs differ, the precision of the conversion sometimes
drops below 106 bits.  This strategy is identical to the
hexadecimal variant.

I've refactored tst-sprintf3 to enable testing a value with more
than 30 significant digits in order to demonstrate this failure
and its solution.

Additionally, this implicitly fixes a typo in the shift
quantities when subtracting from the high mantissa to compute
the difference.
Diffstat (limited to 'stdio-common')
-rw-r--r--stdio-common/tst-sprintf3.c14
1 files changed, 10 insertions, 4 deletions
diff --git a/stdio-common/tst-sprintf3.c b/stdio-common/tst-sprintf3.c
index cffd1b69d0..dad216b941 100644
--- a/stdio-common/tst-sprintf3.c
+++ b/stdio-common/tst-sprintf3.c
@@ -38,11 +38,11 @@ do_test (void)
 # define COMPARE_LDBL(u, v) ((u).l == (v).l)
 #endif
 
-#define TEST(val) \
+#define TEST_N(val, n) \
   do									   \
     {									   \
       u.l = (val);							   \
-      snprintf (buf, sizeof buf, "%.30LgL", u.l);			   \
+      snprintf (buf, sizeof buf, "%." #n "LgL", u.l);			   \
       if (strcmp (buf, #val) != 0)					   \
 	{								   \
 	  printf ("Error on line %d: %s != %s\n", __LINE__, buf, #val);	   \
@@ -50,19 +50,25 @@ do_test (void)
 	}								   \
       if (sscanf (#val, "%Lg", &v.l) != 1 || !COMPARE_LDBL (u, v))	   \
 	{								   \
-	  printf ("Error sscanf on line %d: %.30Lg != %.30Lg\n", __LINE__, \
-		  u.l, v.l);						   \
+	  printf ("Error sscanf on line %d: %." #n "Lg != %." #n "Lg\n",   \
+		  __LINE__, u.l, v.l);					   \
 	  result = 1;							   \
 	}								   \
       /* printf ("%s %Lg %016Lx %016Lx\n", #val, u.l, u.x[0], u.x[1]); */  \
     }									   \
   while (0)
 
+#define TEST(val) TEST_N (val,30)
+
 #if LDBL_MANT_DIG >= 106
 # if LDBL_MANT_DIG == 106
   TEST (2.22507385850719347803989925739e-308L);
   TEST (2.22507385850719397210554509863e-308L);
   TEST (2.22507385850720088902458687609e-308L);
+
+  /* Verify precision is not lost for long doubles
+     of the form +1.pN,-1.pM.  */
+  TEST_N (3.32306998946228968225951765070082e+35L, 34);
 # endif
   TEST (2.22507385850720138309023271733e-308L);
   TEST (2.22507385850720187715587855858e-308L);