about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAndreas Schwab <schwab@linux-m68k.org>2012-04-03 18:38:46 +0200
committerAndreas Schwab <schwab@linux-m68k.org>2012-04-28 22:21:27 +0200
commit7e0d315da842379f077fc61dca72460fb0e9263e (patch)
tree252f9f59a4b17e807b33979c51ecdff86a07720c
parent6d5c57fabd1a97b110b00e59fd52f50ce5bbb1a3 (diff)
downloadglibc-7e0d315da842379f077fc61dca72460fb0e9263e.tar.gz
glibc-7e0d315da842379f077fc61dca72460fb0e9263e.tar.xz
glibc-7e0d315da842379f077fc61dca72460fb0e9263e.zip
Fix formatting of denormal IBM long double numbers
-rw-r--r--ChangeLog7
-rw-r--r--NEWS18
-rw-r--r--stdio-common/Makefile2
-rw-r--r--stdio-common/tst-sprintf3.c90
-rw-r--r--sysdeps/ieee754/ldbl-128ibm/ldbl2mpn.c14
5 files changed, 115 insertions, 16 deletions
diff --git a/ChangeLog b/ChangeLog
index 931510b322..ca38a87eee 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,12 @@
 2012-04-28  Andreas Schwab  <schwab@linux-m68k.org>
 
+	[BZ #13941]
+	* sysdeps/ieee754/ldbl-128ibm/ldbl2mpn.c
+	(__mpn_extract_long_double): Use DBL_MIN_EXP instead of
+	LDBL_MIN_EXP.
+	* stdio-common/Makefile (tests): Add tst-sprintf3.
+	* stdio-common/tst-sprintf3.c: New file.
+
 	* elf/Makefile ($(objpfx)tst-leaks1-mem, $(objpfx)noload-mem)
 	($(objpfx)tst-unused-dep.out): Don't run when cross-compiling.
 
diff --git a/NEWS b/NEWS
index 34cbf2dec0..fa1d45d22f 100644
--- a/NEWS
+++ b/NEWS
@@ -13,15 +13,15 @@ Version 2.16
   2554, 2562, 2563, 2565, 2566, 2576, 2636, 2678, 3335, 3768, 3866, 3868,
   3976, 3992, 4026, 4108, 4596, 4822, 5077, 5461, 5805, 5993, 6471, 6486,
   6578, 6649, 6730, 6770, 6794, 6884, 6890, 6894, 6895, 6907, 6911, 7064,
-  9739, 9902, 10110, 10135, 10140, 10153, 10210, 10254, 10346, 10545,
-  10716, 11174, 11322, 11365, 11451, 11494, 11521, 11959, 12047, 12340,
-  13058, 13525, 13526, 13527, 13528, 13529, 13530, 13531, 13532, 13533,
-  13547, 13551, 13552, 13553, 13555, 13559, 13566, 13583, 13592, 13618,
-  13637, 13656, 13658, 13673, 13691, 13695, 13704, 13705, 13706, 13726,
-  13738, 13739, 13760, 13761, 13786, 13792, 13806, 13824, 13840, 13841,
-  13844, 13846, 13851, 13852, 13854, 13871, 13872, 13873, 13879, 13883,
-  13886, 13892, 13895, 13908, 13910, 13911, 13912, 13913, 13915, 13916,
-  13917, 13918, 13919, 13920, 13921, 13926, 13927, 13928, 13938, 13963,
+  9739, 9902, 10110, 10135, 10140, 10153, 10210, 10254, 10346, 10545, 10716,
+  11174, 11322, 11365, 11451, 11494, 11521, 11959, 12047, 12340, 13058,
+  13525, 13526, 13527, 13528, 13529, 13530, 13531, 13532, 13533, 13547,
+  13551, 13552, 13553, 13555, 13559, 13566, 13583, 13592, 13618, 13637,
+  13656, 13658, 13673, 13691, 13695, 13704, 13705, 13706, 13726, 13738,
+  13739, 13760, 13761, 13786, 13792, 13806, 13824, 13840, 13841, 13844,
+  13846, 13851, 13852, 13854, 13871, 13872, 13873, 13879, 13883, 13886,
+  13892, 13895, 13908, 13910, 13911, 13912, 13913, 13915, 13916, 13917,
+  13918, 13919, 13920, 13921, 13926, 13927, 13928, 13938, 13941, 13963,
   13967, 13970, 13973, 14027
 
 * ISO C11 support:
diff --git a/stdio-common/Makefile b/stdio-common/Makefile
index 8cf6335bb5..7519bc1a24 100644
--- a/stdio-common/Makefile
+++ b/stdio-common/Makefile
@@ -56,7 +56,7 @@ tests := tstscanf test_rdwr test-popen tstgetln test-fseek \
 	 tst-fwrite bug16 bug17 tst-swscanf tst-sprintf2 bug18 bug18a \
 	 bug19 bug19a tst-popen2 scanf13 scanf14 scanf15 bug20 bug21 bug22 \
 	 scanf16 scanf17 tst-setvbuf1 tst-grouping bug23 bug24 \
-	 bug-vfprintf-nargs tst-long-dbl-fphex tst-fphex-wide
+	 bug-vfprintf-nargs tst-long-dbl-fphex tst-fphex-wide tst-sprintf3
 
 test-srcs = tst-unbputc tst-printf
 
diff --git a/stdio-common/tst-sprintf3.c b/stdio-common/tst-sprintf3.c
new file mode 100644
index 0000000000..d56f247310
--- /dev/null
+++ b/stdio-common/tst-sprintf3.c
@@ -0,0 +1,90 @@
+/* Copyright (C) 2012 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* Test bug #13941.  */
+
+#include <float.h>
+#include <math.h>
+#include <stdio.h>
+#include <string.h>
+
+int
+main (void)
+{
+#if LDBL_MANT_DIG >= 106
+  volatile union { long double l; long long x[2]; } u, v;
+  char buf[64];
+#endif
+  int result = 0;
+
+#if LDBL_MANT_DIG == 106 || LDBL_MANT_DIG == 113
+# define COMPARE_LDBL(u, v) \
+  ((u).l == (v).l && (u).x[0] == (v).x[0] && (u).x[1] == (v).x[1])
+#else
+# define COMPARE_LDBL(u, v) ((u).l == (v).l)
+#endif
+
+#define TEST(val) \
+  do									   \
+    {									   \
+      u.l = (val);							   \
+      snprintf (buf, sizeof buf, "%.30LgL", u.l);			   \
+      if (strcmp (buf, #val) != 0)					   \
+	{								   \
+	  printf ("Error on line %d: %s != %s\n", __LINE__, buf, #val);	   \
+	  result = 1;							   \
+	}								   \
+      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);						   \
+	  result = 1;							   \
+	}								   \
+      /* printf ("%s %Lg %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 (2.22507385850719347803989925739e-308L);
+  TEST (2.22507385850719397210554509863e-308L);
+  TEST (2.22507385850720088902458687609e-308L);
+# endif
+  TEST (2.22507385850720138309023271733e-308L);
+  TEST (2.22507385850720187715587855858e-308L);
+  TEST (2.2250738585074419930597574044e-308L);
+  TEST (4.45014771701440227211481959342e-308L);
+  TEST (4.45014771701440276618046543466e-308L);
+  TEST (4.45014771701440375431175711716e-308L);
+  TEST (4.45014771701440474244304879965e-308L);
+  TEST (7.12023634722304600689881138745e-307L);
+  TEST (1.13923781555569064960474854133e-305L);
+  TEST (1.13777777777777776389998996996L);
+  TEST (1.13777777777777765287768750745L);
+  TEST (20988295479420645138.2044444444L);
+  TEST (20988295479420643090.2044444444L);
+  TEST (2.14668699894294423266045294316e-292L);
+# if LDBL_MANT_DIG == 106
+  TEST (-2.35993711055432139266626434123e-292L);
+  TEST (6.26323524637968345414769634658e-302L);
+  TEST (1.49327164802066885331814201989e-308L);
+  TEST (3.71834550652787023640837473722e-308L);
+  TEST (9.51896449671134907001349268087e-306L);
+# endif
+#endif
+  return result;
+}
diff --git a/sysdeps/ieee754/ldbl-128ibm/ldbl2mpn.c b/sysdeps/ieee754/ldbl-128ibm/ldbl2mpn.c
index 3162bbd9a5..83162c5b32 100644
--- a/sysdeps/ieee754/ldbl-128ibm/ldbl2mpn.c
+++ b/sysdeps/ieee754/ldbl-128ibm/ldbl2mpn.c
@@ -1,5 +1,4 @@
-/* Copyright (C) 1995,1996,1997,1998,1999,2002,2003,2006
-	Free Software Foundation, Inc.
+/* Copyright (C) 1995-2012 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -104,7 +103,10 @@ __mpn_extract_long_double (mp_ptr res_ptr, mp_size_t size,
       else
 	{
 	  /* It is a denormal number, meaning it has no implicit leading
-  	     one bit, and its exponent is in fact the format minimum.  */
+	     one bit, and its exponent is in fact the format minimum.  We
+	     use DBL_MIN_EXP instead of LDBL_MIN_EXP below because the
+	     latter describes the properties of both parts together, but
+	     the exponent is computed from the high part only.  */
 	  int cnt;
 
 #if N == 2
@@ -115,7 +117,7 @@ __mpn_extract_long_double (mp_ptr res_ptr, mp_size_t size,
 	      res_ptr[N - 1] = res_ptr[N - 1] << cnt
 			       | (res_ptr[0] >> (BITS_PER_MP_LIMB - cnt));
 	      res_ptr[0] <<= cnt;
-	      *expt = LDBL_MIN_EXP - 1 - cnt;
+	      *expt = DBL_MIN_EXP - 1 - cnt;
 	    }
 	  else
 	    {
@@ -130,7 +132,7 @@ __mpn_extract_long_double (mp_ptr res_ptr, mp_size_t size,
 		  res_ptr[N - 1] = res_ptr[0] >> (NUM_LEADING_ZEROS - cnt);
 		  res_ptr[0] <<= BITS_PER_MP_LIMB - (NUM_LEADING_ZEROS - cnt);
 		}
-	      *expt = LDBL_MIN_EXP - 1
+	      *expt = DBL_MIN_EXP - 1
 		- (BITS_PER_MP_LIMB - NUM_LEADING_ZEROS) - cnt;
 	    }
 #else
@@ -161,7 +163,7 @@ __mpn_extract_long_double (mp_ptr res_ptr, mp_size_t size,
 
 	  for (; k >= 0; k--)
 	    res_ptr[k] = 0;
-	  *expt = LDBL_MIN_EXP - 1 - l * BITS_PER_MP_LIMB - cnt;
+	  *expt = DBL_MIN_EXP - 1 - l * BITS_PER_MP_LIMB - cnt;
 #endif
 	}
     }