[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[commits] r11029 - in /libdfp/trunk: ./ base-math/ sysdeps/dpd/ sysdeps/powerpc/dfpu/ sysdeps/soft-dfp/dpd/ tests/



Author: ryanarn
Date: Thu Jul 22 10:18:45 2010
New Revision: 11029

Log:
Bugs in printf-dfp led to test-cases and bug fixes in numdigits, left_justify,
getexp, and printf_dfp, and _fe_dec_setround.  This check-in fixes them all.

2010-07-21  Ryan S. Arnold <rsa@xxxxxxxxxx>

	* Makefile.in: Added test-numdigits, test-get_digits, and test-left_justify.
	* base-math/Makefile: Fixed missing truncd* exports which was exposed
	by GCC 4.4.
	* base-math/lttd2.c (lttd3): Renamed lttd3 to lttd2.  Typo.
	* tests/test-get_digits.c: Added test-cases to show previously failing
	numdigits for soft-dfp when coefficient was zero.  It was returning
	'0' intead of '1', which is what hardware DFP returns.
	* tests/test-printf.c: Added test-cases to show failing tests.
	* tests/test-fpclassify.c: (printf_d32s): Changed DENORMAL to
	SUBNORMAL in constant usage.  GCC changed usage.
	* tests/test-numdigits.c: New test.
	* tests/scaffold.c: Updated output formatting of macros to make output
	clearer (columns and test numbering).
	* tests/test-left_justify.c: New test.
	* tests/test-strtod.c: Added test-cases to show failing tests.
	* sysdeps/powerpc/dfpu/numdigits.h (_NUMDIGITS_H): Removed guard to
	allow multiple #includes with different preconditions.
	(numdigits): New implementation which avoids clobbers and avoids
	modifying a parameter.
	(left_justify): New implementation which avoids clobbers and avoids
	modifyinig a parameter.
	(getexp): New implementation which avoids modifying a parameter.
	* sysdeps/powerpc/dfpu/fe_decround.c (__fe_dec_setround): Fixed
	errorneous usage of mtfsfi instruction.  Previous usage resulted in
	the set rounding mode not being permanent.
	* sysdeps/soft-dfp/dpd/numdigits.h (numdigits): Return '1' if
	coefficient is zero, which is what hardware DFP does.
	(__dfp_declet_to_dpd): Moved to ...
	* sysdeps/dpd/dpd-private.h: ... this file.
	* sysdeps/dpd/dpd-private.c: Formatting.
	* printf_dfp.c (printf_dfp): Major fixes to correct a variety of
	printing errors.  It should now fully support %f, %e, %g, and %a in
	the myriad of bizarre combinations.


Added:
    libdfp/trunk/tests/test-get_digits.c
    libdfp/trunk/tests/test-left_justify.c
    libdfp/trunk/tests/test-numdigits.c
Modified:
    libdfp/trunk/ChangeLog
    libdfp/trunk/Makefile.in
    libdfp/trunk/base-math/Makefile
    libdfp/trunk/base-math/lttd2.c
    libdfp/trunk/printf_dfp.c
    libdfp/trunk/sysdeps/dpd/dpd-private.c
    libdfp/trunk/sysdeps/dpd/dpd-private.h
    libdfp/trunk/sysdeps/powerpc/dfpu/fe_decround.c
    libdfp/trunk/sysdeps/powerpc/dfpu/numdigits.h
    libdfp/trunk/sysdeps/soft-dfp/dpd/numdigits.h
    libdfp/trunk/tests/scaffold.c
    libdfp/trunk/tests/test-fpclassify.c
    libdfp/trunk/tests/test-printf.c
    libdfp/trunk/tests/test-strtod.c

Modified: libdfp/trunk/ChangeLog
==============================================================================
--- libdfp/trunk/ChangeLog (original)
+++ libdfp/trunk/ChangeLog Thu Jul 22 10:18:45 2010
@@ -1,3 +1,39 @@
+2010-07-21  Ryan S. Arnold <rsa@xxxxxxxxxx>
+
+	* Makefile.in: Added test-numdigits, test-get_digits, and test-left_justify.
+	* base-math/Makefile: Fixed missing truncd* exports which was exposed
+	by GCC 4.4.
+	* base-math/lttd2.c (lttd3): Renamed lttd3 to lttd2.  Typo.
+	* tests/test-get_digits.c: Added test-cases to show previously failing
+	numdigits for soft-dfp when coefficient was zero.  It was returning
+	'0' intead of '1', which is what hardware DFP returns.
+	* tests/test-printf.c: Added test-cases to show failing tests.
+	* tests/test-fpclassify.c: (printf_d32s): Changed DENORMAL to
+	SUBNORMAL in constant usage.  GCC changed usage.
+	* tests/test-numdigits.c: New test.
+	* tests/scaffold.c: Updated output formatting of macros to make output
+	clearer (columns and test numbering).
+	* tests/test-left_justify.c: New test.
+	* tests/test-strtod.c: Added test-cases to show failing tests.
+	* sysdeps/powerpc/dfpu/numdigits.h (_NUMDIGITS_H): Removed guard to
+	allow multiple #includes with different preconditions.
+	(numdigits): New implementation which avoids clobbers and avoids
+	modifying a parameter.
+	(left_justify): New implementation which avoids clobbers and avoids
+	modifyinig a parameter.
+	(getexp): New implementation which avoids modifying a parameter.
+	* sysdeps/powerpc/dfpu/fe_decround.c (__fe_dec_setround): Fixed
+	errorneous usage of mtfsfi instruction.  Previous usage resulted in
+	the set rounding mode not being permanent.
+	* sysdeps/soft-dfp/dpd/numdigits.h (numdigits): Return '1' if
+	coefficient is zero, which is what hardware DFP does.
+	(__dfp_declet_to_dpd): Moved to ...
+	* sysdeps/dpd/dpd-private.h: ... this file.
+	* sysdeps/dpd/dpd-private.c: Formatting.
+	* printf_dfp.c (printf_dfp): Major fixes to correct a variety of
+	printing errors.  It should now fully support %f, %e, %g, and %a in
+	the myriad of bizarre combinations.
+
 2010-07-06  Ryan S. Arnold <rsa@xxxxxxxxxx>
 
 	* Makefile.in: Added test-strtod testcase.

Modified: libdfp/trunk/Makefile.in
==============================================================================
--- libdfp/trunk/Makefile.in (original)
+++ libdfp/trunk/Makefile.in Thu Jul 22 10:18:45 2010
@@ -250,7 +250,8 @@
 #  calls.
 $(top_builddir)/$(SHARED_REALNAME_LIB): $(top_builddir)/$(dfp_name).map $(dfp_backend)/$(dfp_backend_lib) $(addsuffix .os,$(libdfp_files))
 	@echo +Linking shared object files into $@.
-	$(CC) $(CFLAGS) -shared -Wl,-soname,$(SHARED_SONAME_LIB) -Bsymbolic -Wl,--whole-archive $(dfp_backend)/$(dfp_backend_lib) -Wl,--no-whole-archive -Wl,--version-script,$(dfp_name).map $(wordlist 3,$(words $?),$?) -o $@ -lm
+	$(CC) $(CFLAGS) -shared -Wl,-soname,$(SHARED_SONAME_LIB) -Bsymbolic -Wl,--whole-archive $(dfp_backend)/$(dfp_backend_lib) -Wl,--no-whole-archive -Wl,--version-script,$(dfp_name).map $(addsuffix .os,$(libdfp_files)) -o $@ -lm
+	#$(CC) $(CFLAGS) -shared -Wl,-soname,$(SHARED_SONAME_LIB) -Bsymbolic -Wl,--whole-archive $(dfp_backend)/$(dfp_backend_lib) -Wl,--no-whole-archive -Wl,--version-script,$(dfp_name).map $(wordlist 3,$(words $?),$?) -o $@ -lm
 	@echo
 
 # The LIBDFP version script support is strongly based upon the GLIBC version
@@ -302,7 +303,7 @@
 GLIBC_LIBS := $(glibc_builddir)/libc.so $(glibc_builddir)/math/libm.so $(glibc_builddir)/nptl/libpthread.so
 endif
 
-libdfp_tests = test-printf test-param test-amort test-decode test-quantize test-isnan test-isinf test-isfinite test-fpclassify test-logd test-strtod
+libdfp_tests = test-printf test-param test-amort test-decode test-quantize test-isnan test-isinf test-isfinite test-fpclassify test-logd test-strtod test-numdigits test-left_justify test-get_digits
 
 # Explicitly link against the uninstalled GLIBC and the Libdfp.so.1 we just
 # built.

Modified: libdfp/trunk/base-math/Makefile
==============================================================================
--- libdfp/trunk/base-math/Makefile (original)
+++ libdfp/trunk/base-math/Makefile Thu Jul 22 10:18:45 2010
@@ -17,5 +17,5 @@
 		mulsd3 muldd3 multd3 \
 		nesd2 nedd2 netd2 \
 		subsd3 subdd3 subtd3 \
-		trunctdsd2 truncddsd2 trunctdsd2 \
+		truncddsd2 trunctddd2 trunctdsd2 \
 		unordsd2 unorddd2 unordtd2 \

Modified: libdfp/trunk/base-math/lttd2.c
==============================================================================
--- libdfp/trunk/base-math/lttd2.c (original)
+++ libdfp/trunk/base-math/lttd2.c Thu Jul 22 10:18:45 2010
@@ -25,7 +25,7 @@
 #include <dfpacc.h>
 
 int
-__BACKEND_(lttd3) (_Decimal128 x, _Decimal128 y)
+__BACKEND_(lttd2) (_Decimal128 x, _Decimal128 y)
 {
   return x < y ? -1 : 1;
 }

Modified: libdfp/trunk/printf_dfp.c
==============================================================================
--- libdfp/trunk/printf_dfp.c (original)
+++ libdfp/trunk/printf_dfp.c Thu Jul 22 10:18:45 2010
@@ -1,6 +1,6 @@
 /* Function definition to convert DFP values to strings
 
-   Copyright (C) 2006, 2009 Free Software Foundation, Inc.
+   Copyright (C) 2006, 2009, 2010 Free Software Foundation, Inc.
 
    This file is part of the Decimal Floating Point C Library.
 
@@ -35,12 +35,9 @@
 #include <stdio.h>
 
 #include <string.h>
-//#include <libioP.h>
 #include <stdlib.h>
 #include <ctype.h>
 #include <assert.h>
-
-//#include <fmt_dfp.h>
 
 #include <fenv.h>
 
@@ -49,17 +46,26 @@
 #include <limits.h> /* For CHAR_MAX  */
 #include <stdio.h>
 
-#include "get_digits.h"
-
-//#include "numdigits.h"
-//
-//extern void __get_dpd_digits (int, const void *const *, char*, int*, int*, int*,
-//int*);
-
-
-/* This defines make it possible to use the same code for GNU C library and
-   the GNU I/O library.	 */
-//#define PUT(f, s, n) _IO_sputn (f, s, n)
+#include <get_digits.h>
+#define _DECIMAL_SIZE 128
+#define DEC_TYPE _Decimal128
+#include <numdigits.h>
+#undef _DECIMAL_SIZE
+#undef DEC_TYPE
+#undef ADJUST
+#undef Q
+#undef DECIMAL_BIAS
+#define _DECIMAL_SIZE 64
+#define DEC_TYPE _Decimal64
+#include <numdigits.h>
+#undef _DECIMAL_SIZE
+#undef DEC_TYPE
+#undef ADJUST
+#undef Q
+#undef DECIMAL_BIAS
+#define _DECIMAL_SIZE 32
+#define DEC_TYPE _Decimal32
+#include <numdigits.h>
 
 static int
 wpadn (FILE *fp, wint_t pad, int count)
@@ -138,6 +144,124 @@
     }									      \
   while (0)
 
+#define _OUT(pr) \
+  do \
+    { \
+	int t_pr = 0; \
+    if (pr < 0) \
+      outchar('-');\
+    if (__builtin_abs(pr) > 999)\
+      {\
+        outchar('0' + __builtin_abs(pr) / 1000);\
+	t_pr = (__builtin_abs(pr) % 1000);\
+        outchar('0' + t_pr/100);\
+	t_pr = (__builtin_abs(t_pr) % 100);\
+        outchar('0' + t_pr/10);\
+	t_pr = (__builtin_abs(t_pr) % 10);\
+        outchar('0' + t_pr);\
+      }\
+    else if (__builtin_abs(pr) > 99)\
+      {\
+        outchar('0' + __builtin_abs(pr)/100);\
+	t_pr = (__builtin_abs(pr) % 100);\
+        outchar('0' + t_pr/10);\
+	t_pr = (__builtin_abs(t_pr) % 10);\
+        outchar('0' + t_pr);\
+      }\
+    else if (__builtin_abs(pr) > 9)\
+      {\
+        outchar('0' + __builtin_abs(pr)/10);\
+	t_pr = (__builtin_abs(pr) % 10);\
+        outchar('0' + t_pr);\
+      }\
+    else\
+      {\
+        outchar('0' + __builtin_abs(pr));\
+      }\
+   } while (0)
+
+#define OUT_DIGITS(xp) \
+  do \
+   { \
+      int ia; \
+      outchar('['); \
+      outchar('d'); \
+      outchar('i'); \
+      outchar('g'); \
+      outchar('i'); \
+      outchar('t'); \
+      outchar('s'); \
+      outchar(':'); \
+      for (ia = 0; digits[ia] != '\0'; ia++) \
+	outchar(digits[ia]); \
+      outchar('e'); \
+      _OUT(xp); \
+      outchar(']');\
+   } while (0)
+
+
+#define OUT(pr,val) \
+  do \
+   { \
+      int slen = strlen(pr); \
+      int ia; \
+      outchar('['); \
+      for (ia = 0; ia < slen; ia++) \
+	   outchar(pr[ia]); \
+      outchar(':'); \
+      _OUT(val); \
+      outchar(']');\
+   } while (0)
+
+#define OUT_PREC(pr) \
+  do \
+    { \
+      OUT("prec",pr); \
+    } while (0)
+
+#define OUT_INDEX(idx) \
+  do \
+    { \
+      OUT("index",idx); \
+    } while (0)
+
+#define OUT_DEFAULT_PREC(pr) \
+  do \
+    { \
+      OUT("default_prec",pr); \
+    } while (0)
+
+#define OUT_LEN(ln) \
+  do \
+    { \
+      OUT("len",ln); \
+    } while (0)
+
+#define OUT_SIG(sg) \
+  do \
+    { \
+      OUT("sig",sg); \
+   } while (0)
+
+
+#define OUT_N(na) \
+  do \
+    { \
+      OUT("n",na); \
+   } while (0)
+
+#define OUT_WIDTH(wd) \
+  do \
+    { \
+      OUT("width",wd); \
+   } while (0)
+
+#define OUT_DECPT(dpt) \
+  do \
+    { \
+      OUT("decpt",dpt); \
+   } while (0)
+
 static int pa_d128;
 static int pa_d64;
 static int pa_d32;
@@ -176,30 +300,36 @@
 int
 __dfp_ais (const struct printf_info *info, size_t n __attribute__ ((unused)), int *argtype, int *size)
 {
-  if ((info->user & mod_H) == mod_H)
+  if ((info->user & mod_D) == mod_D)
+    {
+      argtype[0] = pa_d64;
+      size[0] = sizeof (_Decimal64);
+      return 1;
+    }
+  else if ((info->user & mod_DD) == mod_DD)
+    {
+      argtype[0] = pa_d128;
+      size[0] = sizeof (_Decimal128);
+      return 1;
+    }
+  else if ((info->user & mod_H) == mod_H)
     {
       argtype[0] = pa_d32;
       size[0] = sizeof (_Decimal32);
       return 1;
     }
-  else if ((info->user & mod_D) == mod_D)
-    {
-      argtype[0] = pa_d64;
-      size[0] = sizeof (_Decimal64);
-      return 1;
-    }
-  else if ((info->user & mod_DD) == mod_DD)
-    {
-      argtype[0] = pa_d128;
-      size[0] = sizeof (_Decimal128);
-      return 1;
-    }
+
   return 0;
 }
 strong_alias(__dfp_ais, dfp_ais)
 hidden_def(__dfp_ais)
 
-
+#define EXP_BIAS_D128 -6109
+#define EXP_BIAS_D64  -368
+#define EXP_BIAS_D32  -87
+
+/* this includes the max digits in a _Decimal128, plus a bunch of formatting
+ * characters.  */
 #define DECIMAL_PRINTF_BUF_SIZE 65 /* ((DECIMAL128_PMAX + 14) * 2) + 1  */
 
 /* fe_decround.c will initialize this function pointer to fe_decgetround */
@@ -211,11 +341,8 @@
 	      const void *const *args)
 {
 	int wide = info->wide;
-//	wchar_t *wbuffer = NULL;
-//	int buffer_malloced = 0;  /* PRINT macro uses this.  */
 	/* Counter for number of written characters.	*/
 	int done = 0;
-	int len = 0;
 
   /* Locale-dependent representation of decimal point.	*/
 
@@ -235,41 +362,24 @@
 
   const char *grouping;
 
-//  mbstate_t mbstate;
- // memset(&mbstate,0,sizeof(mbstate));
-
 #ifdef OPTION_EGLIBC_LOCALE_CODE
   if (info->extra == 0)
     {
-      //decimal = _NL_CURRENT (LC_NUMERIC, DECIMAL_POINT);
       decimal = nl_langinfo (__DECIMAL_POINT);
-      //decimalwc = _NL_CURRENT_WORD (LC_NUMERIC, _NL_NUMERIC_DECIMAL_POINT_WC);
       decimalwc.mb = nl_langinfo (_NL_NUMERIC_DECIMAL_POINT_WC);
-      //mbrtowc(&decimalwc,decimalmb, CHAR_MAX, NULL);
-      //mbrtowc(&decimalwc,&decimalmb, 1, NULL);
     }
   else
     {
-     // decimal = _NL_CURRENT (LC_MONETARY, MON_DECIMAL_POINT);
       decimal = nl_langinfo (__MON_DECIMAL_POINT);
       if (*decimal == '\0')
-	//decimal = _NL_CURRENT (LC_NUMERIC, DECIMAL_POINT);
 	decimal = nl_langinfo (__DECIMAL_POINT);
-      //decimalwc = _NL_CURRENT_WORD (LC_MONETARY,
-      //			    _NL_MONETARY_DECIMAL_POINT_WC);
+
       decimalwc.mb = nl_langinfo (_NL_MONETARY_DECIMAL_POINT_WC);
-      //mbrtowc(&decimalwc,decimalmb, CHAR_MAX, NULL);
       if (decimalwc.wc == L'\0')
-	{
-	//decimalwc = _NL_CURRENT_WORD (LC_NUMERIC,
-	//			      _NL_NUMERIC_DECIMAL_POINT_WC);
-	  decimalwc.mb = nl_langinfo (_NL_NUMERIC_DECIMAL_POINT_WC);
-	  //mbrtowc(&decimalwc,decimalmb, CHAR_MAX, NULL);
-	}
+	decimalwc.mb = nl_langinfo (_NL_NUMERIC_DECIMAL_POINT_WC);
     }
   /* The decimal point character must not be zero.  */
   assert (*decimal != '\0');
-  //assert (decimalwc != L'\0');
   assert (decimalwc.wc != L'\0');
 #else
   /* Hard-code values from 'C' locale.  */
@@ -283,10 +393,8 @@
   if (info->group)
     {
       if (info->extra == 0)
-	//grouping = _NL_CURRENT (LC_NUMERIC, GROUPING);
 	grouping = nl_langinfo (__GROUPING);
       else
-	//grouping = _NL_CURRENT (LC_MONETARY, MON_GROUPING);
 	grouping = nl_langinfo (__MON_GROUPING);
 
       if (*grouping <= 0 || *grouping == CHAR_MAX)
@@ -300,24 +408,19 @@
 		{
 		  thousands_sepmb = nl_langinfo (_NL_NUMERIC_THOUSANDS_SEP_WC);
 		  mbrtowc(&thousands_sepwc,thousands_sepmb, CHAR_MAX, NULL);
-		  //_NL_CURRENT_WORD (LC_NUMERIC, _NL_NUMERIC_THOUSANDS_SEP_WC);
 		}
 	      else
 		{
 		  thousands_sepmb = nl_langinfo (_NL_MONETARY_THOUSANDS_SEP_WC);
 		  mbrtowc(&thousands_sepwc,thousands_sepmb, CHAR_MAX, NULL);
-		  //_NL_CURRENT_WORD (LC_MONETARY,
-		  //		    _NL_MONETARY_THOUSANDS_SEP_WC);
 		}
 	    }
 	  else
 	    {
 	      if (info->extra == 0)
 		thousands_sep = nl_langinfo (__THOUSANDS_SEP);
-		//thousands_sep = _NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP);
 	      else
 		thousands_sep = nl_langinfo (__MON_THOUSANDS_SEP);
-		//thousands_sep = _NL_CURRENT (LC_MONETARY, MON_THOUSANDS_SEP);
 	    }
 
 	  if ((wide && thousands_sepwc == L'\0')
@@ -337,291 +440,439 @@
   grouping = NULL;
 #endif
 
+  /* Seriously, only touch this code if you MUST.  */
 
 {
-    char digits[DECIMAL_PRINTF_BUF_SIZE];
-    int exp, /* the exponent */
-     is_neg, /* is negative */
-     is_nan, /* is not a number */
-     is_inf, /* is infinite */
-     sig,    /* number of significant digits */
-     decpt,  /* decimal point offset into digits[] */
-     prec,   /* number of digits that follow the decimal point, or number of significant digits for %g */
-     default_prec = 0, /* default precision, if none given */
-     n;      /* current digit offset into digits[] */
-
-     //width,  /* width of the field */
-    int width; /* width of the field */
-    digits[0] = '0'; /* need an extra digit for rounding up */
-
-//    __get_dpd_digits (
-//      (info->is_short) ?        32: /* %H */
-//      (info->is_long_double) ? 128: /* %DD */
-//                                64, /* %D */
-//	args, digits+1, &exp, &is_neg, &is_nan, &is_inf);
-
-    //if (info->is_short)
-    if (info->user & mod_H)
-      __get_digits_d32 (**((_Decimal32**)args[0]), digits+1, &exp, &is_neg,
-			&is_nan, &is_inf);
-    else if (info->user & mod_DD)
-      __get_digits_d128 (**((_Decimal128**)args[0]), digits+1, &exp, &is_neg,
-			 &is_nan, &is_inf);
-    else
-      __get_digits_d64 (**((_Decimal64**)args[0]), digits+1, &exp, &is_neg,
-			&is_nan, &is_inf);
-
-    width = info->width;
-    prec = info->prec;
-    
-    if (is_nan || is_inf) {
+  char digits[DECIMAL_PRINTF_BUF_SIZE];
+  int exp,       /* The exponent. */
+   is_neg,       /* Is negative?  */
+   is_nan,       /* Is not a number?  */
+   is_inf,       /* Is infinite? */
+   decpt = 2,    /* decimal point offset into digits[] */
+   prec,         /* number of digits that follow the decimal point, or number of significant digits for %g */
+   default_prec = 6, /* Default precision, per the C Spec.  */
+   input_prec = 0,   /* Precision of the _Decimal* value.  */
+   mw,           /* Mantissa Width  */
+   n,            /* Current digit offset into digits[] */
+   nd,           /* num_digits before the get_digits call. */
+   width,        /* Width of the field */
+   is_zero = 0;  /* Used in some of the output tests.  */
+
+  digits[0] = '0'; /* need an extra digit for rounding up */
+
+  if (info->user & mod_D)
+    {
+      _Decimal64 d64 = **(_Decimal64**)args[0];
+      if (d64 == 0) is_zero = 1;
+      nd = numdigitsd64(d64);
+      __get_digits_d64 (d64, digits+1, &exp, &is_neg, &is_nan, &is_inf);
+      mw = __DEC64_MANT_DIG__ + 1;
+    }
+  else if (info->user & mod_DD)
+    {
+      _Decimal128 d128 = **(_Decimal128**)args[0];
+      if (d128 == 0) is_zero = 1;
+      nd = numdigitsd128(d128);
+      __get_digits_d128 (d128, digits+1, &exp, &is_neg, &is_nan, &is_inf);
+      mw = __DEC128_MANT_DIG__ + 1;
+    }
+  else
+    {
+       _Decimal32 d32 = **(_Decimal32**)args[0];
+       if (d32 == 0) is_zero = 1;
+       nd = numdigitsd32(d32);
+       __get_digits_d32 (d32, digits+1, &exp, &is_neg, &is_nan, &is_inf);
+       mw = __DEC32_MANT_DIG__ + 1;
+    }
+
+  /* The first digit is always a zero to allow rounding.  */
+  n = 0;
+
+  /* 'n' = position of first non-zero digit in the right-justified mantissa.  */
+  n = mw - nd;
+
+  /* Width and precision can not both be set or the results are undefined per
+   * the C Spec.  */
+  width = info->width;
+
+  /* The user specified precision overrides the input's inherent precision.
+   * This gets complicated quickly.  */
+  prec = info->prec;
+
+  if (is_nan || is_inf)
+    {
       width -= 3;
       /*if (is_nan) is_neg = 0;*/
       if (is_neg || info->showsign || info->space) width--;
-      
+
       if (!info->left && width > 0)
-        PADN (' ', width);
+	PADN (' ', width);
 
       if (is_neg)
-        outchar ('-');
+	outchar ('-');
       else if (info->showsign)
-        outchar ('+');
+	outchar ('+');
       else if (info->space)
-        outchar (' ');
-      
+	outchar (' ');
+
       if (is_nan)
-        if (isupper(info->spec))
-	  { outchar ('N'); outchar ('A'); outchar ('N'); }
-	else
-	  { outchar ('n'); outchar ('a'); outchar ('n'); }
+	{
+	  if (isupper(info->spec))
+	    { outchar ('N'); outchar ('A'); outchar ('N'); }
+	  else
+	    { outchar ('n'); outchar ('a'); outchar ('n'); }
+	}
       else
-        if (isupper(info->spec))
-	  { outchar ('I'); outchar ('N'); outchar ('F'); }
-	else
-	  { outchar ('i'); outchar ('n'); outchar ('f'); }
-	
+	{
+	  if (isupper(info->spec))
+	    { outchar ('I'); outchar ('N'); outchar ('F'); }
+	  else
+	    { outchar ('i'); outchar ('n'); outchar ('f'); }
+	}
       if (info->left && width > 0)
-        PADN (' ', width);
-
-      return 0;
-    }
-    
-   
-    n = 0;
-    while (digits[n] == '0') n++;
-    sig = strlen(digits+n);
-    if (sig == 0) { sig = 1; n--; } /* coefficient is zero */
-    len = n + sig;
-    
-    switch (spec)
+	PADN (' ', width);
+
+	return 0;
+    }
+
+  /* The term "precision" refers to the number of significant digits right of
+   * the decimal place.  Determine the implicit precision of the input value.
+   * There are special rules for each of the supported flags.*/
+  switch (spec)
+    {
+      case 'a':
+	  {
+	    /* This is totally bogus but the DFP spec addition for %a refers to
+	     * all of the significant digits in the precision.  */
+	    if (exp < 0)
+	      {
+		  input_prec = nd;
+	      }
+	    else
+	      {
+	        input_prec = 1;
+	      }
+
+	    /* This same check is done in two different places but it'll only
+	     * effect a single pass through once.  If prec is not set it'll hit
+	     * this instance.  If prec is set it'll hit the next instance.  This
+	     * is because the DFP spec requires this to be run after rounding
+	     * when prec < input_prec.  */
+	    if (prec < 0 || prec >= input_prec)
+	    {
+	      /* Per the DFP specification (s,c,q), c == digits, q = exp, s ==
+	       * is_neg.  */
+	      if (exp >= -(nd+5) && exp <= 0)
+	        {
+	          prec = -exp;
+	          spec = 'f';
+	        }
+	      else
+	        {
+	          prec = nd - 1;
+	          spec = 'e';
+	          input_prec = nd - 1;
+	        }
+	      }
+	    break;
+	  }
+	case 'g':
+	  {
+	    int P = prec;
+
+	    /* When the C specification refers to X as the exponent it means the
+	     * exponent when the input value encoding is normalized to the form
+	     * d.dddd.  This means we have to do that before we can do the goof
+	     * check.
+	     *
+	     * e.g., 123.456E-5
+	     * right-justified -> 00123456E-9
+	     * normalized -> 1.23456E-4
+	     *
+	     * Normalize X to d.ddd... form by taking (exp) + (nd - 1)
+	     *
+	     * X == -4  */
+	    int X = exp + (nd -1);
+
+	    /* The C Specification also indicates how to compute P. */
+	    if (prec < 0)
+	      P = 6;
+	    else if (prec == 0)
+	      P = 1;
+
+	    /* Straight from the specification which assumes X is exponent normalized to
+	     * d.ddd... form.  */
+	    if (X >= -4 && P > X)
+	      {
+		prec = (P - (X + 1));
+		spec = 'f';
+	      }
+	    else
+	      {
+		prec = P - 1;
+		spec = 'e';
+		input_prec = nd - 1;
+	      }
+	  break;
+	  }
+	case 'e':
+	  input_prec = nd - 1;
+	  break;
+	case 'f':
+	  if(exp < 0 && (-exp) > default_prec)
+	    /*  00123456E-7 has an input_prec of 7. */
+	    input_prec = (-exp);
+	  else
+	    /*  01234567E-6 has an input_prec of 6. */
+	    /*  00000190E6 has an input_prec of 6. */
+	    /*  00000123E1 has an input_prec of 6.  */
+	    /*  00000123E0 has an input_prec of 6.  */
+	    input_prec = default_prec;
+	  break;
+    }
+
+  /* The specs 'g' and 'a' may have already modified prec so this won't happen for
+   * those cases.  */
+  if (prec < 0)
+    prec = default_prec;
+
+  /* do rounding if precision is less than the decimal type */
+  if (prec < input_prec)
+    {
+      int index, roundmode = 0;
+      char rounddigit = '4';
+
+      if (spec == 'f')
+	index = n + nd + exp + prec;
+      /* Goofy special case where we round significant digits which aren't
+       * right of the decimal place.  */
+      else if (tolower(info->spec) == 'a')
+	index = n + prec;
+      else
+	index = n + prec + 1;
+
+      /* FIXME: we should check rounding mode for %a */
+      if (__printf_dfp_getround_callback)
+        {
+          roundmode = (*__printf_dfp_getround_callback)();
+
+	  switch (roundmode)
+	    {
+	      case FE_DEC_TONEAREST: rounddigit = '4'; break;
+	      case FE_DEC_TOWARDZERO: rounddigit = '9'; break;
+	      case FE_DEC_UPWARD: rounddigit = (is_neg ? '9' : '0'-1); break;
+	      case FE_DEC_DOWNWARD: rounddigit = (is_neg ? '0'-1 : '9'); break;
+	      case FE_DEC_TONEARESTFROMZERO: rounddigit = '4'; break;
+	      case 5: rounddigit = '4'; break; /* nearest, ties toward zero */
+	      case 6: rounddigit = '0'-1; break; /* away from zero */
+	      case 7: rounddigit = '4'; break; /* round for shorter precision */
+	      default: rounddigit = '4'; break;
+	    }
+	}
+
+      /* If this is true then the requested precision is smaller than the
+      * default and rounding is required.  */
+      if (index < mw && digits[index] > rounddigit)
+	do {
+	  int trailzero = index+1;
+	  if (digits[index] == rounddigit+1)
+	    {
+	      while (trailzero < mw)
+		{
+		  if (digits[trailzero] != '0')
+		    {
+		      trailzero = 0;
+		      break;
+		    }
+		  ++trailzero;
+		}
+	      if (roundmode == FE_DEC_TONEAREST && trailzero &&
+	        (digits[index-1] & 1) == 0) break;
+	      if (roundmode == FE_DEC_UPWARD && !trailzero) break;
+	      if (roundmode == FE_DEC_DOWNWARD && !trailzero) break;
+	      if (roundmode == 5 && trailzero) break;
+	      if (roundmode == 6 && trailzero) break;
+	  }
+
+	while (digits[--index] == '9') digits[index] = '0';
+	  digits[index]++;
+	if (index < n) { n--; }
+      } while (0);
+    } /* Done rounding.  */
+
+  /* If spec == 'a' at this point it means that prec was set by the user
+   * and rounding had to be considered.  The spec now requires that the
+   * 'a' format presentation algorithm be calculated again.  If prec
+   * wasn't set by the user then this was handled earlier and spec has already
+   * been set to either 'e' or 'f'.  */
+  if (spec == 'a')
+    {
+      int old_exp = exp;
+
+      /* The goofy DFP specification requires that we now assume that after
+       * rounding the digits are right justified and truncated and the
+       * algorithm recomputed using the new values for nd and exp, e.g.,
+       *
+       * 00654300E-2 with %.1Hf -> 00000007E3.  */
+
+       exp = nd + exp - prec;
+       nd = prec;
+
+      /* Per the DFP specification (s,c,q), c == digits, q = exp, s ==
+      * is_neg.  */
+      if (exp >= -(nd+5) && exp <= 0)
+	{
+	  prec = -exp;
+	  spec = 'f';
+	}
+      else
+	{
+	  prec = nd - 1;
+	  if (prec < 0) prec = 0;
+	  spec = 'e';
+	  input_prec = nd - 1;
+	  /* Return exp to the original value because the 'e' case below will
+	   * recompute it.  */
+	  exp = old_exp;
+	}
+	/* spec will have been changed to 'e' or 'f' at this point, so determine
+	* the decimal point now.  */
+    }
+
+  /* Calculate decimal point, adjust prec and exp if necessary.
+   * By this point everything should be represented as either %e or %f.  */
+  if (spec == 'f')
+    {
+      if (exp < 0)
+	decpt = exp + nd + n;
+      else if (is_zero)
+	decpt = n + 1;
+      else
+	decpt = n + nd + exp;
+    }
+  else if (spec == 'e')
+    {
+      decpt = n + 1;
+      exp = mw + exp - decpt;
+    }
+
+  /* Remove trailing zeroes for %g */
+  if (tolower(info->spec) == 'g' && !info->alt)
+    {
+      while (prec > 0 && decpt+prec > mw) prec--;
+      while (prec > 0 && digits[decpt+prec-1] == '0') prec--;
+    }
+
+  /* Remove trailing zeroes for %a, but only if they are not significant.  */
+  if (tolower(info->spec) == 'a')
+    {
+      while (prec > 0 && decpt+prec > mw) prec--;
+      while (prec > 0 && decpt+prec > n+nd && digits[decpt+prec-1] == '0') prec--;
+    }
+
+  /* Digits to the left of the decimal pt. */
+  if (n < decpt)
+    {
+      width -= decpt - n;
+      if (grouping) width -= (decpt-n)/3;
+    }
+  else width--;  /* none to the left of the decimal point */
+
+  /* Digits to the right of the decimal pt. */
+  if (prec > 0) width -= 1 + prec;
+  else if (info->alt) width -= 1;
+
+  if (spec != 'f')
+    {
+      width -= 3;
+      if (0!=(exp/10) || spec!='a') --width;
+      if (0!=(exp/100)) --width;
+      if (0!=(exp/1000)) --width;
+    }
+
+  if (is_neg || info->showsign || info->space) width--;
+
+  if (!info->left && info->pad != '0' && width > 0)
+    PADN (info->pad, width);
+
+  if (is_neg)
+    outchar ('-');
+  else if (info->showsign)
+    outchar ('+');
+  else if (info->space)
+    outchar (' ');
+
+  if (!info->left && info->pad == '0' && width > 0)
+    PADN ('0', width);
+
+  /* Print zero, decimal point and leading zeroes if needed */
+  if (decpt <= n)
+    {
+      n = decpt;
+      outchar ('0');
+      if (n < 0)
+	{
+	  outchar (wide ? decimalwc.wc : *decimal);
+	  while (n < 0 && n < decpt + prec)
+	    {
+	      outchar ('0');
+	      n++;
+	    }
+	}
+    }
+
+  /* Print the digits.  If decpt exceeds mw then we know that
+   * they're simply trailing zeros and we don't need to display them.  */
+  while (n < mw && n < decpt + prec)
+    {
+      if (n == decpt)
       {
-        case 'a': /* fall thru */
-	case 'g': default_prec = sig; break;
-	case 'f': default_prec = (exp < 0) ? -exp : 0; break;
-        case 'e': default_prec = sig-1; break;
+	outchar (wide ? decimalwc.wc : *decimal);
       }
-    
-    /* if no precision is specified, use that of the decimal type */
-    if (prec < 0)
-      prec = default_prec;
-    else if (prec < default_prec)
-    /* do rounding if precision is less than the decimal type */
-      {
-        int index, roundmode = 0;
-	//int do_round = 0;
-	char rounddigit = '4';
-	
-        index = n + prec + sig - default_prec;
-
-        /* FIXME: we should check rounding mode for %a */
-	if (__printf_dfp_getround_callback) {
-	  roundmode = (*__printf_dfp_getround_callback)();
-	
-/*	outchar('[');
-	outchar('r');
-	outchar('o');
-	outchar('u');
-	outchar('n');
-	outchar('d');
-	outchar('m');
-	outchar('o');
-	outchar('d');
-	outchar('e');
-	outchar('=');
-	outchar('0'+roundmode);
-	outchar(']');*/
-	
-	switch (roundmode) {
-	  case FE_DEC_TONEAREST: rounddigit = '4'; break;
-	  case FE_DEC_TOWARDZERO: rounddigit = '9'; break;
-	  case FE_DEC_UPWARD: rounddigit = is_neg ? '9' : '0'-1; break;
-	  case FE_DEC_DOWNWARD: rounddigit = is_neg ? '0'-1 : '9'; break;
-	  case FE_DEC_TONEARESTFROMZERO: rounddigit = '4'; break;
-	  case 5: rounddigit = '4'; break; /* nearest, ties toward zero */
-	  case 6: rounddigit = '0'-1; break; /* away from zero */
-	  case 7: rounddigit = '4'; break; /* round for shorter precision */
-	  default: rounddigit = '4'; break;
-	}
-	
-	}
-	
-        if (index < len && digits[index] > rounddigit)
-          do { 
-	    int trailzero = index+1;
-	    if (digits[index] == rounddigit+1)
-	      {
-	        while (trailzero < len)
-	          {
-	            if (digits[trailzero] != '0')
-		      {
-		        trailzero = 0;
-		        break;
-		      }
-		    ++trailzero;
-		  }
-		if (roundmode == FE_DEC_TONEAREST && trailzero &&
-		  (digits[index-1] & 1) == 0) break;
-		if (roundmode == FE_DEC_UPWARD && !trailzero) break;
-		if (roundmode == FE_DEC_DOWNWARD && !trailzero) break;
-		if (roundmode == 5 && trailzero) break;
-		if (roundmode == 6 && trailzero) break;
-	      }
-	  
-            while (digits[--index] == '9') digits[index] = '0';
-            digits[index]++;
-            if (index < n) { n--; sig++; }
-          } while (0);
-      }
-    
-    /* calculate decimal point, adjust prec and exp if necessary */
-    if (spec == 'f')
-      {
-	decpt = n + sig + exp;
-      }
-    else if (spec == 'a' && -(prec+5) <= exp && exp <= 0 && exp+sig <= prec)
-      {
-	spec = 'f';
-	prec -= exp+sig;
-	decpt = n + sig + exp;
-      }
-    else if (spec == 'g' && -4 < exp+sig && exp+sig <= prec)
-      {
-	spec = 'f';
-	prec -= exp+sig;
-	decpt = n + sig + exp;
-      }
-    else
-      {
-        if (spec != 'e') prec--;
-	exp += sig-1;
-	decpt = n + 1;
-      }
-
-    /* remove trailing zeroes for %g */
-    if (tolower(info->spec) == 'g')
-      {
-        while (prec > 0 && decpt+prec > len) prec--;
-	while (prec > 0 && digits[decpt+prec-1] == '0') prec--;
-      }
-
-    /* remove trailing zeroes for %a, but only if they are not significant */
-    if (tolower(info->spec) == 'a')
-      {
-        while (prec > 0 && decpt+prec > len) prec--;
-	while (prec > 0 && decpt+prec > n+sig && digits[decpt+prec-1] == '0') prec--;
-      }
-      
-
-    /* digits to the left of the decimal pt. */
-    if (n < decpt)
-      { 
-        width -= decpt - n;
-	if (grouping) width -= (decpt-n)/3;
-      }
-    else width--;  /* zero */
-  
-    /* digits to the right of the decimal pt. */
-    if (prec > 0) width -= 1 + prec;
-    else if (info->alt) width -= 1;
-  
-    if (spec != 'f')
-      {
-        width -= 3;
-	if (0!=(exp/10) || spec!='a') --width;
-	if (0!=(exp/100)) --width;
-	if (0!=(exp/1000)) --width;
-      }
-  
-    if (is_neg || info->showsign || info->space) width--;
-
-    if (!info->left && info->pad != '0' && width > 0)
-      PADN (info->pad, width);
-
-    if (is_neg)
-      outchar ('-');
-    else if (info->showsign)
-      outchar ('+');
-    else if (info->space)
-      outchar (' ');
-
-    if (!info->left && info->pad == '0' && width > 0)
-      PADN ('0', width);
-
-  /* print zero, decimal point and leading zeroes if needed */
-  if (decpt <= n)
-    {
-      outchar ('0');
-      n = decpt;
-      if (n < 0)
-        {
-          outchar (wide ? decimalwc.wc : *decimal);
-          while (n < 0 && n < decpt + prec)
-	    {
-              outchar ('0');
-              n++;
-            }
-        }
-    }
-  /* print digits */
-  while (n < len && n < decpt + prec)
-    {
-      if (n == decpt) 
-        outchar (wide ? decimalwc.wc : *decimal);
       else if (grouping && n < decpt && (decpt-n)%3 == 0)
-        outchar (wide ? thousands_sepwc : *thousands_sep);
+	outchar (wide ? thousands_sepwc : *thousands_sep);
       outchar (digits[n]);
       n++;
     }
+
   /* print trailing zeroes */
   while (n < decpt + prec)
     {
-      if (n == decpt) 
-        outchar (wide ? decimalwc.wc : *decimal);
+      if (n == decpt)
+	outchar (wide ? decimalwc.wc : *decimal);
       else if (grouping && n < decpt && (decpt-n)%3 == 0)
-        outchar (wide ? thousands_sepwc : *thousands_sep);
+	outchar (wide ? thousands_sepwc : *thousands_sep);
       outchar ('0');
       n++;
     }
+
   /* print decimal point, if needed */
   if (n == decpt && info->alt) outchar (wide ? decimalwc.wc : *decimal);
-  
-  
-  if (spec != 'f')
-   {
-     outchar (isupper(info->spec) ? 'E' : 'e');
-     if (exp < 0) 
-       { outchar ('-'); n = -exp; }
-     else
-       { outchar ('+'); n = exp; }
-     if (n >= 1000) outchar ('0'+((n/1000)%10)); 
-     if (n >= 100) outchar ('0'+((n/100)%10));
-     if (n >= 10 || spec!='a') outchar ('0'+((n/10)%10));
-     outchar ('0'+(n%10));
- 
-   }
+
+  /* The C spec says that for %e, if the value is zero the exponent is zero.
+   * This isn't true for the DFP spec for %a so make sure to check info->spec
+   * and not spec since it could have promoted 'a' to 'e'.  */
+  if(spec == 'e' && (tolower(info->spec) != 'a' && is_zero))
+    exp = 0;
+
+  /* Don't display the exponent part for 'f' because it is never used and don't
+   * do it for 'g' if the value is zero.  */
+  if (spec != 'f' && !((tolower(info->spec) == 'g') && is_zero))
+    {
+      outchar (isupper(info->spec) ? 'E' : 'e');
+      if (exp < 0)
+	{ outchar ('-'); n = -exp; }
+      else
+	{ outchar ('+'); n = exp; }
+      if (n >= 1000) outchar ('0'+((n/1000)%10));
+      if (n >= 100) outchar ('0'+((n/100)%10));
+      if (n >= 10 || (tolower(info->spec) != 'a')) outchar ('0'+((n/10)%10));
+      outchar ('0'+(n%10));
+    }
+
   if (info->left && width > 0)
     PADN (info->pad, width);
-} 
+} /* Done output block.  */
 
    return 0;
 }

Modified: libdfp/trunk/sysdeps/dpd/dpd-private.c
==============================================================================
--- libdfp/trunk/sysdeps/dpd/dpd-private.c (original)
+++ libdfp/trunk/sysdeps/dpd/dpd-private.c Thu Jul 22 10:18:45 2010
@@ -737,10 +737,10 @@
   if (exp_p) *exp_p = exp;
   if (nan_p) *nan_p = c_f.is_nan;
   if (inf_p) *inf_p = c_f.is_inf;
-  
+
 }
 
-void 
+void
 __get_digits_d32 (_Decimal32 x, char *str, int *exp_p, int *sign_p, 
 		  int *nan_p, int *inf_p)
 {
@@ -761,7 +761,6 @@
   if (exp_p) *exp_p = exp;
   if (nan_p) *nan_p = c_f.is_nan;
   if (inf_p) *inf_p = c_f.is_inf;
-  
 }
 
 void 
@@ -789,7 +788,7 @@
   if (exp_p) *exp_p = exp;
   if (nan_p) *nan_p = c_f.is_nan;
   if (inf_p) *inf_p = c_f.is_inf;
-  
+
 }
 
 void 

Modified: libdfp/trunk/sysdeps/dpd/dpd-private.h
==============================================================================
--- libdfp/trunk/sysdeps/dpd/dpd-private.h (original)
+++ libdfp/trunk/sysdeps/dpd/dpd-private.h Thu Jul 22 10:18:45 2010
@@ -1,11 +1,12 @@
 /* Data types for DPD format output.
 
    Copyright (C) 2006, 2007 IBM Corporation.
-   Copyright (C) 2007, 2009 Free Software Foundation, Inc.
+   Copyright (C) 2007, 2009, 2010 Free Software Foundation, Inc.
 
    This file is part of the Decimal Floating Point C Library.
 
    Author(s): Steve Munroe <sjmunroe@xxxxxxxxxx>
+              Ryan S. Arnold  <rsa@xxxxxxxxxx>
 
    The Decimal Floating Point C Library is free software; you can
    redistribute it and/or modify it under the terms of the GNU Lesser
@@ -306,4 +307,12 @@
 extern const const short int	dpd_to_bcd[1024];
 extern const short int	bcd_to_dpd[2464];
 
+static inline unsigned int
+__dfp_declet_to_dpd(char *str)
+{
+  return bcd_to_dpd[(str[0]<<8) + (str[1]<<4) + str[2] - '0'*0x111];
+}
+
+
+
 #endif /* _DPD_PRIVATE */

Modified: libdfp/trunk/sysdeps/powerpc/dfpu/fe_decround.c
==============================================================================
--- libdfp/trunk/sysdeps/powerpc/dfpu/fe_decround.c (original)
+++ libdfp/trunk/sysdeps/powerpc/dfpu/fe_decround.c Thu Jul 22 10:18:45 2010
@@ -1,7 +1,7 @@
 /* Decimal Float fe_dec_getround and fe_dec_setround definitions.
 
    Copyright (C) 2006 IBM Corporation.
-   Copyright (C) 2007, 2009 Free Software Foundation, Inc.
+   Copyright (C) 2007, 2009, 2010 Free Software Foundation, Inc.
 
    This file is part of the Decimal Floating Point C Library.
 
@@ -26,6 +26,8 @@
 
 #include <fenv.h>
 #include <dfpfenv_private.h>
+
+#include <stdio.h>
 
 int __fe_dec_setround(int rounding_direction)
 {
@@ -72,28 +74,28 @@
   switch(rounding_direction)
     {
       case FE_DEC_TONEAREST:
-	asm ("mtfsfi 7, 0, 1\n");
+	asm ("mtfsfi 7, 0\n");
 	break;
       case FE_DEC_TOWARDZERO:
-	asm ("mtfsfi 7, 1, 1\n");
+	asm ("mtfsfi 7, 1\n");
 	break;
       case FE_DEC_UPWARD:
-	asm ("mtfsfi 7, 2, 1\n");
+	asm ("mtfsfi 7, 2\n");
 	break;
       case FE_DEC_DOWNWARD:
-	asm ("mtfsfi 7, 3, 1\n");
+	asm ("mtfsfi 7, 3\n");
 	break;
       case FE_DEC_TONEARESTFROMZERO:
-	asm ("mtfsfi 7, 4, 1\n");
+	asm ("mtfsfi 7, 4\n");
 	break;
       case 5: /* Allow covert setting of this rounding mode.  */
-	asm ("mtfsfi 7, 5, 1\n");
+	asm ("mtfsfi 7, 5\n");
 	break;
       case 6: /* Allow covert setting of this rounding mode.  */
-	asm ("mtfsfi 7, 6, 1\n");
+	asm ("mtfsfi 7, 6\n");
 	break;
       case 7: /* Allow covert setting of this rounding mode.  */
-	asm ("mtfsfi 7, 7, 1\n");
+	asm ("mtfsfi 7, 7\n");
 	break;
       default:
 	return 1;

Modified: libdfp/trunk/sysdeps/powerpc/dfpu/numdigits.h
==============================================================================
--- libdfp/trunk/sysdeps/powerpc/dfpu/numdigits.h (original)
+++ libdfp/trunk/sysdeps/powerpc/dfpu/numdigits.h Thu Jul 22 10:18:45 2010
@@ -1,11 +1,13 @@
 /* Number of digits functions, optimized for Power6.
 
    Copyright (C) 2006, 2007, 2008 IBM Corporation.
-   Copyright (C) 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+   Copyright (C) 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 
    This file is part of the Decimal Floating Point C Library.
 
    Author(s): Pete Eberlein <eberlein@xxxxxxxxxx>
+              Michael Meissner <meissner@xxxxxxxxxxxxxxxxxx>
+              Peter Bergner <bergner@xxxxxxxxxxxxxxxxxx>
 
    The Decimal Floating Point C Library is free software; you can
    redistribute it and/or modify it under the terms of the GNU Lesser
@@ -23,10 +25,9 @@
 
    Please see dfp/COPYING.txt for more information.  */
 
-
-#ifndef _NUMDIGITS_H
-#define _NUMDIGITS_H 1
-
+/* Allow this to be included more than once so don't guard it. */
+//#ifndef _NUMDIGITS_H
+//#define _NUMDIGITS_H 1
 
 #define NUMDIGITS_SUPPORT 1
 
@@ -61,23 +62,20 @@
 static inline int
 FUNC_D (getexp) (DEC_TYPE x)
 {
-  union {
-    double f;
-    int i[2];
-  } result;
-
+  double f;
+  int i;
 #if _DECIMAL_SIZE == 32
   asm ("dctdp %0,%1\n\t"
-       "dxex %0,%0\n\t" : "=f"(result.f) : "f"(x));
+       "dxex %0,%0\n\t" : "=d"(f) : "f"(x));
 #elif _DECIMAL_SIZE == 64
-  asm ("dxex %0,%1" : "=f"(result.f) : "f"(x));
+  asm ("dxex %0,%1" : "=d"(f) : "d"(x));
 #elif _DECIMAL_SIZE == 128
   /* dec quad needs to be in an even-odd fr pair */
   register DEC_TYPE tmp asm ("fr0") = x;
-  asm ("dxexq %0,%1" : "=f"(result.f) : "f"(tmp));
-#endif
-
-  return result.i[1] - DECIMAL_BIAS;
+  asm ("dxexq %0,%1" : "=d"(f) : "d"(tmp));
+#endif
+  asm ("stfiwx %1,%y0" : "=Z"(i) : "d"(f));
+  return i - DECIMAL_BIAS;
 }
 
 #ifndef PASTE
@@ -85,14 +83,8 @@
 # define PASTE2(x,y) x##y
 #endif
 
-#ifndef FUNC_D
-# define FUNC_D(x)		PASTE(x,PASTE(d,_DECIMAL_SIZE))
-#endif
-
-#define SETEXP	PASTE(setexp,PASTE(d,_DECIMAL_SIZE))
-
 static inline DEC_TYPE
-SETEXP (DEC_TYPE x, int exp)
+FUNC_D (setexp) (DEC_TYPE x, int exp)
 {
 #if _DECIMAL_SIZE == 128
   register DEC_TYPE tmp asm ("fr0") = x;
@@ -121,93 +113,97 @@
   return tmp;
 }
 
-
-
 static inline int
 FUNC_D (numdigits) (DEC_TYPE x)
 {
-#if _DECIMAL_SIZE == 128
-  register DEC_TYPE tmp asm ("fr0") = x;
+#if _DECIMAL_SIZE == 32
+  register _Decimal64 tmp = x;
 #else
   register DEC_TYPE tmp = x;
 #endif
-  union {
-    int i[2];
-#if _DECIMAL_SIZE == 128
-    _Decimal128 f;
-#else
-    _Decimal64 f; /* promote _Decimal32 -> _Decimal64  */
-#endif
-  } a, b, one;
-  
-  one.i[0] = 0;
-  one.i[1] = 1;
-  
-  asm (
-#if _DECIMAL_SIZE == 32
-    "dctdp %2,%2\n\t"
-#endif
-#if _DECIMAL_SIZE != 128
-    "dxex %0,%2\n\t"
-    "drrnd %1,%3,%2,1\n\t"
-    "dxex %1,%1\n\t"
-#else /* _DECIMAL_SIZE == 128 */
-    "dxexq %0,%2\n\t"
-    "drrndq %1,%3,%2,1\n\t"
-    "dxexq %1,%1\n\t"
-#endif
-   : "+f"(a.f), "+f"(b.f) : "f"(tmp), "f"(one.f));
-//  printf("a: %lld  b: %lld\n", a.i, b.i);
-  return b.i[1] - a.i[1] + 1;
-}
-
-
-static inline DEC_TYPE
-left_justify (DEC_TYPE x)
-{
-#if _DECIMAL_SIZE == 128
-  register DEC_TYPE tmp asm ("fr0") = x, rnd asm ("fr2");
-#else
-  register DEC_TYPE tmp = x, rnd;
-#endif
-  union {
+  double f1, f2;
+  DEC_TYPE f3;
+  int i1, i2;
+  static union
+  {
     int i[2];
     double f;
-  } d;
-/* Should double f; be replaced with the following for left_justify as well?  */
-//#if _DECIMAL_SIZE == 128
-//    _Decimal128 f;
-//#else
-//    _Decimal64 f; /* promote _Decimal32 -> _Decimal64  */
-//#endif
-
-  d.i[0] = 0;
-  d.i[1] = 1;
-
-#if _DECIMAL_SIZE == 32
-  asm ("dctdp %0,%0\n\t" : "=f"(tmp) : "0"(tmp));
-#endif  
-
+  } u = { { 0, 1 } };
+  asm (
 #if _DECIMAL_SIZE != 128
-  asm ("drrnd %0,%1,%2,1" : "=f"(rnd) : "f"(d.f), "f"(tmp));
-  asm ("dxex %0,%1\n\t" : "=f"(d.f) : "f"(rnd));
-  d.i[1] -= (_DECIMAL_SIZE==32) ? 6 : 15;
-  asm ("diex %0,%1,%0\n\t" : "=f"(rnd) : "f"(d.f), "0"(rnd));
-  asm ("dqua %0,%0,%2,1\n\t" : "=f"(rnd) : "0"(rnd), "f"(tmp));
-
+    "dxex %2,%5\n\t"
+    "drrnd %4,%6,%5,1\n\t"
+    "dxex %3,%4\n\t"
 #else /* _DECIMAL_SIZE == 128 */
-  asm ("drrndq %0,%1,%2,1" : "=f"(rnd) : "f"(d.f), "f"(tmp));
-  asm ("dxexq %0,%1\n\t" : "=f"(d.f) : "f"(rnd));
-  d.i[1] -= 33;
-  asm ("diexq %0,%1,%0\n\t" : "=f"(rnd) : "f"(d.f), "0"(rnd));
-  asm ("dquaq %0,%0,%2,1\n\t" : "=f"(rnd) : "0"(rnd), "f"(tmp));
-#endif
-
-#if _DECIMAL_SIZE == 32
-  asm ("drsp %0,%0\n\t" : "=f"(rnd) : "0"(rnd));
-#endif  
-  return rnd;
-}
-
-
-#endif /* _NUMDIGITS_H */
+    "dxexq %2,%5\n\t"
+    "drrndq %4,%6,%5,1\n\t"
+    "dxexq %3,%4\n\t"
+#endif
+    "stfiwx %2,%y0\n\t"
+    "stfiwx %3,%y1\n\t"
+    : "=Z"(i1), "=Z"(i2), "=&d"(f1), "=&d"(f2), "=&d"(f3)
+    : "d"(tmp), "d"(u.f));
+  return i2 - i1 + 1;
+}
+
+static inline DEC_TYPE
+FUNC_D (left_justify) (DEC_TYPE x)
+{
+#if _DECIMAL_SIZE == 32
+  register _Decimal64 tmp = x;
+  register _Decimal64 rnd;
+#else
+  register DEC_TYPE tmp = x;
+  register DEC_TYPE rnd;
+#endif
+  double tmp2;
+  union int_dbl
+  {
+    int i[2];
+    double f;
+  };
+  static union int_dbl d = { { 0, 1 } };
+#if _DECIMAL_SIZE==32
+# define ADJUST 6
+#elif _DECIMAL_SIZE==64
+# define ADJUST 15
+#elif _DECIMAL_SIZE==128
+# define ADJUST 33
+#else
+# error "Unknown decimal size"
+#endif
+
+#ifdef __VSX__
+  static vector int vsx_adjust = { 0, ADJUST, 0, 0 };
+  register vector int tmp3;
+#else
+  union int_dbl d2;
+#endif
+
+#if _DECIMAL_SIZE != 128
+# define Q ""
+#else
+# define Q "q"
+#endif
+
+  asm ("drrnd" Q " %0,%1,%2,1" : "=d"(rnd) : "d"(d.f), "d"(tmp));
+  asm ("dxex" Q " %0,%1\n\t" : "=d"(tmp2) : "d"(rnd));
+
+#ifdef __VSX__
+  asm ("xxlxor %x0,%x1,%x1" : "=v"(tmp3) : "d"(tmp2));
+  asm ("vsubuwm %0,%1,%2" : "=v"(tmp3) : "v"(tmp3), "v"(vsx_adjust));
+  asm ("xxlxor %x0,%x1,%x1" : "=d"(tmp2) : "v"(tmp3));
+#else
+  d2.f = tmp2;
+  d2.i[1] -= ADJUST;
+  tmp2 = d2.f;
+#endif
+  asm ("diex" Q " %0,%1,%0\n\t" : "=d"(rnd) : "d"(tmp2), "0"(rnd));
+  asm ("dqua" Q " %0,%0,%2,1\n\t" : "=d"(rnd) : "0"(rnd), "d"(tmp));
+
+ /* cast is necessary if input is _Decimal32 in order to convert it from
+  * _Decima64 back to _Decimal32 since the calculation is done in _Decimal64.  */
+  return (DEC_TYPE)rnd;
+}
+
+//#endif /* _NUMDIGITS_H */

Modified: libdfp/trunk/sysdeps/soft-dfp/dpd/numdigits.h
==============================================================================
--- libdfp/trunk/sysdeps/soft-dfp/dpd/numdigits.h (original)
+++ libdfp/trunk/sysdeps/soft-dfp/dpd/numdigits.h Thu Jul 22 10:18:45 2010
@@ -1,7 +1,7 @@
 /* Number of digits functions.
 
    Copyright (C) 2006, 2007, 2008 IBM Corporation.
-   Copyright (C) 2007, 2008, 2009 Free Software Foundation, Inc.
+   Copyright (C) 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 
    This file is part of the Decimal Floating Point C Library.
 
@@ -24,8 +24,8 @@
    Please see dfp/COPYING.txt for more information.  */
 
 
-#ifndef _NUMDIGITS_H
-#define _NUMDIGITS_H 1
+//#ifndef _NUMDIGITS_H
+//#define _NUMDIGITS_H 1
 
 #define NUMDIGITS_SUPPORT 1
 
@@ -39,7 +39,7 @@
 
 #include "dpd-private.h"
 #include <string.h>
-#include "get_digits.h"
+#include <get_digits.h>
 
 #ifndef PASTE
 # define PASTE(x,y) PASTE2(x,y)
@@ -117,14 +117,8 @@
 
 }
 
-static inline unsigned int
-__dfp_declet_to_dpd(char *str) 
-{
-  return bcd_to_dpd[(str[0]<<8) + (str[1]<<4) + str[2] - '0'*0x111];
-}
-
 static inline DEC_TYPE
-setdigits (DEC_TYPE x, char *str)
+FUNC_D (setdigits) (DEC_TYPE x, char *str)
 {
 #if _DECIMAL_SIZE == 32
   union ieee754r_Decimal32 d;
@@ -187,6 +181,7 @@
 FUNC_D (numdigits) (DEC_TYPE x)
 {
   int firstdigit = 0;
+  int len = 0;
 #if _DECIMAL_SIZE == 32
   char digits[8];
   __get_digits_d32(x, digits, NULL, NULL, NULL, NULL);
@@ -199,11 +194,14 @@
 #endif
   while (digits[firstdigit] == '0') firstdigit++;
 
-  return strlen(digits + firstdigit);
+  len = strlen(digits + firstdigit);
+  /* Hardware DFP always returns 1 digit if the mantissa is zero.  We should
+   * do the same.  */
+  return (len == 0 ? 1 : len);
 }
 
 static inline DEC_TYPE
-left_justify (DEC_TYPE x)
+FUNC_D (left_justify) (DEC_TYPE x)
 {
   int firstdigit = 0, len;
 #if _DECIMAL_SIZE == 32
@@ -222,12 +220,11 @@
     {
       /* pad the significant digits with enough trailing zeroes */
       memset(digits + firstdigit + len, '0', firstdigit);
-      x = setdigits(x, digits + firstdigit);
+      x = FUNC_D (setdigits) (x, digits + firstdigit);
       x = FUNC_D(setexp) (x, FUNC_D (getexp) (x) - firstdigit);
     }
 
   return x;
 }
 
-
-#endif /* _NUMDIGITS_H */
+//#endif /* _NUMDIGITS_H */

Modified: libdfp/trunk/tests/scaffold.c
==============================================================================
--- libdfp/trunk/tests/scaffold.c (original)
+++ libdfp/trunk/tests/scaffold.c Thu Jul 22 10:18:45 2010
@@ -27,6 +27,7 @@
 #include "decode.h"
 
 static int fail = 0;
+static int testnum = 0;
 
 /* String compare macros  */
 #ifndef _SC
@@ -38,11 +39,12 @@
  * a variable and want _SC_P to output it.  The name stands for Compare with
  * Position.  */
 #define _SC_P(f,l,x,y) do { \
+  ++testnum; \
   if(strcmp(x,y)) { \
-    fprintf(stderr, "Error: Expected: \"%s\" - Result: \"%s\" in: %s:%d.\n", x,y,f,l); \
+    fprintf(stderr, "%-3d Error:   Expected: \"%s\"\n             Result:   \"%s\"\n    in: %s:%d.\n\n", testnum,x,y,f,l); \
     ++fail; \
   } else { \
-    fprintf(stdout, "Success: Expected: \"%s\" - Result: \"%s\" in: %s:%d.\n", x,y,f,l); \
+    fprintf(stdout, "%-3d Success: Expected: \"%s\"\n             Result:   \"%s\"\n    in: %s:%d.\n\n", testnum,x,y,f,l); \
   } \
 } while (0)
 
@@ -87,16 +89,17 @@
 #ifndef _VC
 /* _VC_P == Value Compare with Position  */
 #define _VC_P(f,l,x,y,fmt) do { \
+  ++testnum; \
   memset(bufx,'\0',CHAR_MAX); \
   memset(bufy,'\0',CHAR_MAX); \
   /* Invokes printf dfp.  */  \
   sprintf(bufx, fmt, x); \
   sprintf(bufy, fmt, y); \
   if(x!=y) { \
-    fprintf(stderr, "Error: Expected: \"%s\" - Result: \"%s\" in: %s:%d.\n", bufx,bufy,f,l); \
+    fprintf(stderr, "%-3d Error:   Expected: \"%s\"\n             Result:   \"%s\"\n    in: %s:%d.\n\n", testnum,bufx,bufy,f,l); \
     ++fail; \
   } else { \
-    fprintf(stdout, "Success: Expected: \"%s\" - Result: \"%s\" in: %s:%d.\n", bufx,bufy,f,l); \
+    fprintf(stdout, "%-3d Success: Expected: \"%s\"\n             Result:   \"%s\"\n    in: %s:%d.\n\n", testnum,bufx,bufy,f,l); \
   } \
 } while (0)
 
@@ -131,16 +134,17 @@
 #ifndef _QC
 /* _QC_P == Quantize Compare with Position  */
 #define _QC_P(f,l,x,y,fmt,type) do { \
+  ++testnum; \
   memset(bufx,'\0',CHAR_MAX); \
   memset(bufy,'\0',CHAR_MAX); \
   /* Invokes printf dfp.  */  \
   sprintf(bufx, fmt, x); \
   sprintf(bufy, fmt, y); \
   if(x!=y) { \
-    fprintf(stderr, "Error: Expected: \"%s\" - Result: \"%s\" in: %s:%d.\n", bufx,bufy,f,l); \
+    fprintf(stderr, "%-3d Error:   Expected: \"%s\"\n             Result:    \"%s\"\n    in: %s:%d.\n\n", testnum, bufx,bufy,f,l); \
     ++fail; \
   } else { \
-    fprintf(stdout, "Success: Expected: \"%s\" - Result: \"%s\" in: %s:%d.\n", bufx,bufy,f,l); \
+    fprintf(stdout, "%-3d Success: Expected: \"%s\"\n             Result:    \"%s\"\n    in: %s:%d.\n\n", testnum, bufx,bufy,f,l); \
   } \
 } while (0)
 

Modified: libdfp/trunk/tests/test-fpclassify.c
==============================================================================
--- libdfp/trunk/tests/test-fpclassify.c (original)
+++ libdfp/trunk/tests/test-fpclassify.c Thu Jul 22 10:18:45 2010
@@ -50,7 +50,7 @@
   {__LINE__, 0.0DL, FP_ZERO, "%d"},
   {__LINE__, 2.3DL, FP_NORMAL, "%d"},
   {__LINE__, -2.3DL, FP_NORMAL, "%d"},
-  {__LINE__, __DEC128_DEN__, FP_SUBNORMAL, "%d"}, /* Subnormal  */
+  {__LINE__, __DEC128_SUBNORMAL_MIN__, FP_SUBNORMAL, "%d"}, /* Subnormal  */
   {__LINE__, 0.000000000000000000000000000000001E-6143DL, FP_SUBNORMAL, "%d"},
   {__LINE__, __DEC128_MIN__, FP_NORMAL, "%d"},
   {0,0,0,0 }
@@ -71,7 +71,7 @@
   {__LINE__, 0.0DD, FP_ZERO, "%d"},
   {__LINE__, 2.3DD, FP_NORMAL, "%d"},
   {__LINE__, -2.3DD, FP_NORMAL, "%d"},
-  {__LINE__, __DEC64_DEN__, FP_SUBNORMAL, "%d"}, /* Subnormal  */
+  {__LINE__, __DEC64_SUBNORMAL_MIN__, FP_SUBNORMAL, "%d"}, /* Subnormal  */
   {__LINE__, 0.000000000000001E-383DD, FP_SUBNORMAL, "%d"},
   {__LINE__, __DEC64_MIN__, FP_NORMAL, "%d"},
   {0,0,0,0 }
@@ -92,7 +92,7 @@
   {__LINE__, 0.0DF, FP_ZERO, "%d"},
   {__LINE__, 2.3DF, FP_NORMAL, "%d"},
   {__LINE__, -2.3DF, FP_NORMAL, "%d"},
-  {__LINE__, __DEC32_DEN__, FP_SUBNORMAL, "%d"}, /* Subnormal  */
+  {__LINE__, __DEC32_SUBNORMAL_MIN__, FP_SUBNORMAL, "%d"}, /* Subnormal  */
   {__LINE__, 0.000001E-95DF, FP_SUBNORMAL, "%d"},
   {__LINE__, __DEC32_MIN__, FP_NORMAL, "%d"},
   {0,0,0,0 }

Added: libdfp/trunk/tests/test-get_digits.c
==============================================================================
--- libdfp/trunk/tests/test-get_digits.c (added)
+++ libdfp/trunk/tests/test-get_digits.c Thu Jul 22 10:18:45 2010
@@ -1,0 +1,116 @@
+/* Test the internal facility to get_digits_d{32|64|128].
+
+   Copyright (C) 2010 Free Software Foundation, Inc.
+
+   This file is part of the Decimal Floating Point C Library.
+
+   Author(s): Ryan S. Arnold <rsa@xxxxxxxxxx>
+
+   The Decimal Floating Point C Library is free software; you can
+   redistribute it and/or modify it under the terms of the GNU Lesser
+   General Public License version 2.1.
+
+   The Decimal Floating Point 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 version 2.1 for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License version 2.1 along with the Decimal Floating Point C Library;
+   if not, write to the Free Software Foundation, Inc., 59 Temple Place,
+   Suite 330, Boston, MA 02111-1307 USA.
+
+   Please see libdfp/COPYING.txt for more information.  */
+
+#ifndef __STDC_WANT_DEC_FP__
+#define __STDC_WANT_DEC_FP__ 1
+#endif
+
+#include <fenv.h>
+#include <float.h>
+#include <dfp.h>
+#include <stdio.h>
+#include <wchar.h> /* This should pick up the libdfp wchar in dfp/wchar.h.  */
+
+#include "scaffold.c"
+
+#include <get_digits.h>
+
+/* We're going to be comparing fields so we need to extract the data.  This is a
+ *  * sneaky way to get around the fact that get_digits_d* isn't exported from
+ *   * libdfp.  */
+#include "../sysdeps/dpd/dpd-private.c"
+
+#define DECIMAL_PRINTF_BUF_SIZE 65 /* ((DECIMAL128_PMAX + 14) * 2) + 1 */
+
+/* This may be useful for debugging.  */
+#define OUT_DIGITS() \
+  do \
+    { \
+      int i; \
+      if(is_neg) \
+	digits[0] = '-'; \
+      else \
+	digits[0] = '+'; \
+      i = 1; \
+      while (digits[i] != '\0') \
+        i++; \
+      digits[i++] = 'e'; \
+      if (exp < 0) \
+	  digits[i++] = '-'; \
+      else \
+	digits[i++] = '+'; \
+      if (__builtin_abs(exp) >= 1000) \
+	      digits[i++] = '0'+((__builtin_abs(exp)/1000)%10); \
+      if (__builtin_abs(exp) >= 100) \
+	      digits[i++] = '0'+((__builtin_abs(exp)/100)%10); \
+      if (__builtin_abs(exp) >= 10) \
+	      digits[i++] = '0'+((__builtin_abs(exp)/10)%10); \
+      digits[i++] = '0'+(__builtin_abs(exp)%10); \
+      digits[i] = '\0'; \
+    } while(0);
+
+#include "decode.h"
+
+/* Inspired by GLIBC stdio-common/tfformat.c  */
+typedef struct{
+  int line;
+  _Decimal32 d;
+  const char *expect;
+  const char *format;
+} d32_type;
+
+d32_type printf_d32s[] =
+{
+
+  {__LINE__, 0.00000E-101DF, "+0000000e-101", "%Ha"},
+  {__LINE__, 0e10DF, "+0000000e+10", "%Ha"},
+  {__LINE__, 0e-6DF, "+0000000e-6", "%Ha"},
+  {__LINE__, 0.00000E-95DF, "+0000000e-100", "%Ha"},
+  {0,0,0,0 }
+};
+
+int main (void)
+{
+  d32_type *d32ptr;
+
+  char digits[DECIMAL_PRINTF_BUF_SIZE];
+  int exp, /* the exponent */
+   is_neg, /* is negative */
+   is_nan, /* is not a number */
+   is_inf; /* is infinite */
+
+  for (d32ptr = printf_d32s; d32ptr->line; d32ptr++)
+    {
+      fprintf(stdout,"__get_digits_d32(%HeDF) in: %s:%d\n", d32ptr->d,__FILE__,__LINE__-1);
+      memset(&digits[0],'\0',DECIMAL_PRINTF_BUF_SIZE);
+      __get_digits_d32 (d32ptr->d, digits+1, &exp, &is_neg, &is_nan, &is_inf);
+      OUT_DIGITS();
+      _SC_P(__FILE__,d32ptr->line, d32ptr->expect,&digits[0]);
+    }
+
+  _REPORT();
+
+  /* fail comes from scaffold.c  */
+  return fail;
+}

Added: libdfp/trunk/tests/test-left_justify.c
==============================================================================
--- libdfp/trunk/tests/test-left_justify.c (added)
+++ libdfp/trunk/tests/test-left_justify.c Thu Jul 22 10:18:45 2010
@@ -1,0 +1,222 @@
+/* Unit test the internal left_justifyd[32|64|128]() functions.
+
+   Copyright (C) 2010 Free Software Foundation, Inc.
+
+   This file is part of the Decimal Floating Point C Library.
+
+   Author(s): Ryan S. Arnold <rsa@xxxxxxxxxx>
+
+   The Decimal Floating Point C Library is free software; you can
+   redistribute it and/or modify it under the terms of the GNU Lesser
+   General Public License version 2.1.
+
+   The Decimal Floating Point 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 version 2.1 for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License version 2.1 along with the Decimal Floating Point C Library;
+   if not, write to the Free Software Foundation, Inc., 59 Temple Place,
+   Suite 330, Boston, MA 02111-1307 USA.
+
+   Please see libdfp/COPYING.txt for more information.  */
+
+#ifndef __STDC_WANT_DEC_FP__
+#define __STDC_WANT_DEC_FP__
+#endif
+
+#include <float.h> /* DEC_NAN definition.  */
+#include <dfp.h>
+#include <stdio.h>
+#include <math.h>
+
+#include <get_digits.h>
+#define _DECIMAL_SIZE 32
+#define DEC_TYPE _Decimal32
+#include <numdigits.h>
+#undef _DECIMAL_SIZE
+#undef DEC_TYPE
+#undef ADJUST
+#undef Q
+#undef DECIMAL_BIAS
+#define _DECIMAL_SIZE 64
+#define DEC_TYPE _Decimal64
+#include <numdigits.h>
+#undef _DECIMAL_SIZE
+#undef DEC_TYPE
+#undef ADJUST
+#undef Q
+#undef DECIMAL_BIAS
+#define _DECIMAL_SIZE 128
+#define DEC_TYPE _Decimal128
+#include <numdigits.h>
+
+#include "scaffold.c" /* Pick up the _SC_P(x,y,fmt) macro.  */
+
+/* We're going to be comparing fields so we need to extract the data.  This is a
+ * sneaky way to get around the fact that get_digits_d* isn't exported from
+ * libdfp.  */
+#include "../sysdeps/dpd/dpd-private.c"
+
+/* Inspired by GLIBC stdio-common/tfformat.c  */
+typedef struct{
+  int line;
+  _Decimal32 d;
+  const char *expect;
+  const char *format;
+} d32_type;
+
+d32_type printf_d32s[] =
+{
+  {__LINE__, 0.0004E-4DF, "+4000000e-14", "%s"},
+  {__LINE__, 0.0004E-0DF, "+4000000e-10", "%s"},
+  {__LINE__, 0.0004E-2DF, "+4000000e-12", "%s"},
+  {__LINE__, 1.0E+2DF, "+1000000e-4", "%s"},
+  {__LINE__, 0.9999999E-91DF, "+9999999e-98", "%s"},
+
+  {__LINE__, 0.9999999E-92DF, "+9999999e-99", "%s"},
+  {__LINE__, 0.9999999E-93DF, "+9999999e-100", "%s"},
+  {__LINE__, 0.9999999E-94DF, "+9999999e-101", "%s"},
+  /* Notice 1000000e-101 is the answer.  */
+  {__LINE__, 0.9999999E-95DF, "+1000000e-101", "%s"},
+  {__LINE__, 0.0000010E-95DF, "+0000001e-101", "%s"},
+
+  {__LINE__, 0.0000100E-95DF, "+0000010e-101", "%s"},
+  {__LINE__, 0.0001000E-95DF, "+0000100e-101", "%s"},
+  {__LINE__, 0.0010000E-95DF, "+0001000e-101", "%s"},
+  {__LINE__, 0.0100000E-95DF, "+0010000e-101", "%s"},
+  {__LINE__, 0.1000000E-95DF, "+0100000e-101", "%s"},
+
+  {__LINE__, 1.0000000E-95DF, "+1000000e-101", "%s"},
+  {__LINE__, 10.0000000E-95DF, "+1000000e-100", "%s"},
+  /* Notice 1000000e-101 is the answer.  */
+  {__LINE__, 10.0000000E-96DF,"+1000000e-101", "%s"},
+  {0,0,0,0 }
+};
+
+/* Inspired by GLIBC stdio-common/tfformat.c  */
+typedef struct{
+  int line;
+  _Decimal64 d;
+  const char *expect;
+  const char *format;
+} d64_type;
+
+d64_type printf_d64s[] =
+{
+  {__LINE__, 1.0E+2DD, "+1000000000000000e-13", "%s"},
+  {__LINE__, 123456789.123456E+300DD, "+1234567891234560e+293", "%s"},
+  {__LINE__, 2.0E-2DD, "+2000000000000000e-17", "%s"},
+  {__LINE__, -2.0E-2DD, "-2000000000000000e-17", "%s"},
+  {__LINE__, 0.0000000000000001E-365DD, "+1000000000000000e-396", "%s"},
+  {__LINE__, 0.0000000000000001E-366DD, "+1000000000000000e-397", "%s"},
+  /* The minimum exponent we can left-justify if the mantissa is full.  */
+  {__LINE__, 0.0000000000000001E-367DD, "+1000000000000000e-398", "%s"},
+  /* Notice the 15 digit mantissa.  */
+  {__LINE__, 0.000000000000001E-368DD, "+1000000000000000e-398", "%s"},
+  /* Notice the 14 digit mantissa.  */
+  {__LINE__, 0.00000000000001E-369DD, "+1000000000000000e-398", "%s"},
+  /* Notice the 1 digit mantissa.  */
+  {__LINE__, 0.1E-382DD, "+1000000000000000e-398", "%s"},
+  /* Notice the 1 digit mantissa.  */
+  {__LINE__, 1.E-383DD, "+1000000000000000e-398", "%s"},
+  {0,0,0,0 }
+};
+
+/* Inspired by GLIBC stdio-common/tfformat.c  */
+typedef struct{
+  int line;
+  _Decimal128 d;
+  const char *expect;
+  const char *format;
+} d128_type;
+
+d128_type printf_d128s[] =
+{
+  {__LINE__, 1.0E+2DL, "+1000000000000000000000000000000000e-31", "%s"},
+  {__LINE__, 123456789.123456E+300DL, "+1234567891234560000000000000000000e+275", "%s"},
+  {__LINE__, 2.0E-2DL, "+2000000000000000000000000000000000e-35", "%s"},
+  {__LINE__, -2.0E-2DL, "-2000000000000000000000000000000000e-35", "%s"},
+  {__LINE__, 0.0000000000000001E-365DL, "+1000000000000000000000000000000000e-414", "%s"},
+  {__LINE__, 0.0000000000000001E-366DL, "+1000000000000000000000000000000000e-415", "%s"},
+  {__LINE__, 0.0000000000000001E-367DL, "+1000000000000000000000000000000000e-416", "%s"},
+  {0,0,0,0 }
+};
+
+
+#define DECIMAL_PRINTF_BUF_SIZE 65 /* ((DECIMAL128_PMAX + 14) * 2) + 1 */
+
+#define OUT_DIGITS() \
+  do \
+    { \
+      int i; \
+      if(is_neg) \
+	digits[0] = '-'; \
+      else \
+	digits[0] = '+'; \
+      i = 1; \
+      while (digits[i] != '\0') \
+        i++; \
+      digits[i++] = 'e'; \
+      if (exp < 0) \
+	  digits[i++] = '-'; \
+      else \
+	digits[i++] = '+'; \
+      if (__builtin_abs(exp) >= 1000) \
+	      digits[i++] = '0'+((__builtin_abs(exp)/1000)%10); \
+      if (__builtin_abs(exp) >= 100) \
+	      digits[i++] = '0'+((__builtin_abs(exp)/100)%10); \
+      if (__builtin_abs(exp) >= 10) \
+	      digits[i++] = '0'+((__builtin_abs(exp)/10)%10); \
+      digits[i++] = '0'+(__builtin_abs(exp)%10); \
+      digits[i] = '\0'; \
+    } while(0);
+
+
+int main (void)
+{
+  d32_type *d32ptr;
+  d64_type *d64ptr;
+  d128_type *d128ptr;
+
+  char digits[DECIMAL_PRINTF_BUF_SIZE];
+  int exp, /* the exponent */
+   is_neg, /* is negative */
+   is_nan, /* is not a number */
+   is_inf; /* is infinite */
+
+  for (d32ptr = printf_d32s; d32ptr->line; d32ptr++)
+    {
+      _Decimal32 d32 = left_justifyd32(d32ptr->d);
+      __get_digits_d32 (d32, digits+1, &exp, &is_neg, &is_nan, &is_inf);
+      OUT_DIGITS();
+      fprintf(stdout,"left_justifyd32(%HeDF) in: %s:%d\n", d32ptr->d,__FILE__,__LINE__-1);
+      _SC_P(__FILE__,d32ptr->line, d32ptr->expect,&digits[0]);
+    }
+
+  for (d64ptr = printf_d64s; d64ptr->line; d64ptr++)
+    {
+      _Decimal64 d64 = left_justifyd64(d64ptr->d);
+      __get_digits_d64 (d64, digits+1, &exp, &is_neg, &is_nan, &is_inf);
+      OUT_DIGITS();
+      fprintf(stdout,"left_justifyd64(%DeDD) in: %s:%d\n", d64ptr->d,__FILE__,__LINE__-1);
+      _SC_P(__FILE__,d64ptr->line, d64ptr->expect,&digits[0]);
+    }
+
+  for (d128ptr = printf_d128s; d128ptr->line; d128ptr++)
+    {
+      _Decimal128 d128 = left_justifyd128(d128ptr->d);
+      __get_digits_d128 (d128, digits+1, &exp, &is_neg, &is_nan, &is_inf);
+      OUT_DIGITS();
+      fprintf(stdout,"left_justifyd128(%DDeDL) in: %s:%d\n", d128ptr->d,__FILE__,__LINE__-1);
+      _SC_P(__FILE__,d128ptr->line, d128ptr->expect,&digits[0]);
+    }
+
+  _REPORT();
+
+  /* fail comes from scaffold.c  */
+  return fail;
+}
+
+

Added: libdfp/trunk/tests/test-numdigits.c
==============================================================================
--- libdfp/trunk/tests/test-numdigits.c (added)
+++ libdfp/trunk/tests/test-numdigits.c Thu Jul 22 10:18:45 2010
@@ -1,0 +1,185 @@
+/* Unit test the internal numdigitsd[32|64|128]() functions.
+
+   Copyright (C) 2010 Free Software Foundation, Inc.
+
+   This file is part of the Decimal Floating Point C Library.
+
+   Author(s): Ryan S. Arnold <rsa@xxxxxxxxxx>
+
+   The Decimal Floating Point C Library is free software; you can
+   redistribute it and/or modify it under the terms of the GNU Lesser
+   General Public License version 2.1.
+
+   The Decimal Floating Point 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 version 2.1 for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License version 2.1 along with the Decimal Floating Point C Library;
+   if not, write to the Free Software Foundation, Inc., 59 Temple Place,
+   Suite 330, Boston, MA 02111-1307 USA.
+
+   Please see libdfp/COPYING.txt for more information.  */
+
+#ifndef __STDC_WANT_DEC_FP__
+#define __STDC_WANT_DEC_FP__
+#endif
+
+#include <float.h> /* DEC_NAN definition.  */
+#include <dfp.h>
+#include <stdio.h>
+#include <math.h>
+
+#include <get_digits.h>
+#define _DECIMAL_SIZE 32
+#define DEC_TYPE _Decimal32
+#include <numdigits.h>
+#undef _DECIMAL_SIZE
+#undef DEC_TYPE
+#undef ADJUST
+#undef Q
+#undef DECIMAL_BIAS
+#define _DECIMAL_SIZE 64
+#define DEC_TYPE _Decimal64
+#include <numdigits.h>
+#undef _DECIMAL_SIZE
+#undef DEC_TYPE
+#undef ADJUST
+#undef Q
+#undef DECIMAL_BIAS
+#define _DECIMAL_SIZE 128
+#define DEC_TYPE _Decimal128
+#include <numdigits.h>
+
+#define _WANT_VC 1 /* Pick up the _VC_P(x,y,fmt) macro.  */
+#include "scaffold.c" /* Pick up the _VC_P(x,y,fmt) macro.  */
+
+/* We're going to be comparing fields so we need to extract the data.  This is a
+ * sneaky way to get around the fact that get_digits_d* isn't exported from
+ * libdfp.  */
+#include "../sysdeps/dpd/dpd-private.c"
+
+/* Inspired by GLIBC stdio-common/tfformat.c  */
+typedef struct{
+  int line;
+  _Decimal128 x;  /* Value to test  */
+  int e;  /* Result should be this.  */
+  const char *format; /* printf %d */
+} d128_type;
+
+d128_type printf_d128s[] =
+{
+  {__LINE__, 0.02E-2DL, 1,  "%d"},
+  {__LINE__, 0.0200E-2DL, 3,  "%d"},
+  {__LINE__, 1.0E-2DL, 2,  "%d"},
+  {__LINE__, 0.0000345E-2DL, 3,  "%d"},
+  {__LINE__, 0.0000345E-10DL, 3,  "%d"},
+  {__LINE__, 123456.0E-2DL, 7,  "%d"},
+  {__LINE__, 123456.000E-2DL, 9,  "%d"},
+  {__LINE__, 123456.000E-4DL, 9,  "%d"},
+  {__LINE__, 123456.000E-6DL, 9,  "%d"},
+  {__LINE__, 123456.00000000000000E-18DL, 20,  "%d"},
+  {__LINE__, 123.456E-6DL, 6, "%d"},
+  {0,0,0,0 }
+};
+
+typedef struct{
+  int line;
+  _Decimal64 x;  /* Value to test  */
+  int e;  /* Result should be this.  */
+  const char *format; /* printf %d */
+} d64_type;
+
+d64_type printf_d64s[] =
+{
+  {__LINE__, 0.02E-2DD, 1,  "%d"},
+  {__LINE__, 0.0200E-2DD, 3,  "%d"},
+  {__LINE__, 1.0E-2DD, 2,  "%d"},
+  {__LINE__, 0.0000345E-2DD, 3,  "%d"},
+  {__LINE__, 0.0000345E-10DD, 3,  "%d"},
+  {__LINE__, 123456.0E-2DD, 7,  "%d"},
+  {__LINE__, 123456.000E-2DD, 9,  "%d"},
+  {__LINE__, 123456.000E-4DD, 9,  "%d"},
+  {__LINE__, 123456.000E-6DD, 9,  "%d"},
+  /* can't exceed __DEC64_MANT_DIG__  */
+  {__LINE__, 123456.00000000000000E-18DD, 16,  "%d"},
+  {0,0,0,0 }
+};
+
+typedef struct{
+  int line;
+  _Decimal32 x;  /* Value to test  */
+  int e;  /* Result should be this.  */
+  const char *format; /* printf %d */
+} d32_type;
+
+d32_type printf_d32s[] =
+{
+  {__LINE__, 0.02E-2DF, 1,  "%d"},
+  {__LINE__, 0.0200E-2DF, 3,  "%d"},
+  {__LINE__, 1.0E-2DF, 2,  "%d"},
+  {__LINE__, 0.0000345E-2DF, 3,  "%d"},
+  {__LINE__, 0.0000345E-10DF, 3,  "%d"},
+  {__LINE__, 123456.0E-2DF, 7,  "%d"},
+  {__LINE__, 123456.000E-2DF, 7,  "%d"}, /* can't exceed __DEC32_MANT_DIG__  */
+  {__LINE__, 123456.000E-4DF, 7,  "%d"}, /* can't exceed __DEC32_MANT_DIG__  */
+  {__LINE__, 123456.000E-6DF, 7,  "%d"}, /* can't exceed __DEC32_MANT_DIG__  */
+  /* can't exceed __DEC32_MANT_DIG__  */
+  {__LINE__, 123456.00000000000000E-18DD, 7,  "%d"},
+
+   /* Problem numbers.  These should all return '1'.  At some point they were
+    * returning '0' for soft-dfp and '1' for hard-dfp.  */
+  {__LINE__, 0.00000E-101DF, 1,  "%d"},
+  {__LINE__, 0.00000E-97DF, 1, "%d"},
+  {__LINE__, 0.00000E-96DF, 1, "%d"},
+  {__LINE__, 0.00000E-95DF, 1, "%d"},
+  {__LINE__, 0e10DF, 1, "%d"},
+  {__LINE__, 0.0e10DF, 1, "%d"},
+  {__LINE__, 0.0e-09DF, 1, "%d"},
+  {__LINE__, 0e-6DF,1, "%d"},
+  {__LINE__, 0e-7DF, 1, "%d"},
+  {__LINE__, 0.e-10DF, 1, "%d"},
+  {__LINE__, 0.e-10DF, 1, "%d"},
+  {__LINE__, 0.e-10DF, 1, "%d"},
+  {__LINE__, 0e2DF, 1, "%d"},
+  {__LINE__, 0.0e2DF, 1, "%d"},
+  {__LINE__, 0.0e10DF, 1, "%d"},
+
+  {0,0,0,0 }
+};
+
+int main (void)
+{
+  d128_type *d128ptr;
+  d64_type *d64ptr;
+  d32_type *d32ptr;
+
+  for (d128ptr = printf_d128s; d128ptr->line; d128ptr++)
+    {
+      int retval = numdigitsd128(d128ptr->x);
+      fprintf(stdout,"numdigitsd128(%DDfDL) in: %s:%d\n", d128ptr->x,__FILE__,__LINE__-1);
+      _VC_P(__FILE__,d128ptr->line, d128ptr->e,retval,d128ptr->format);
+    }
+
+  for (d64ptr = printf_d64s; d64ptr->line; d64ptr++)
+    {
+      int retval = numdigitsd64(d64ptr->x);
+      fprintf(stdout,"numdigitsd64(%DfDD) in: %s:%d\n", d64ptr->x,__FILE__,__LINE__-1);
+      _VC_P(__FILE__,d64ptr->line, d64ptr->e,retval,d64ptr->format);
+    }
+
+  for (d32ptr = printf_d32s; d32ptr->line; d32ptr++)
+    {
+      int retval = numdigitsd32(d32ptr->x);
+      fprintf(stdout,"numdigitsd32(%HfDF) in: %s:%d\n", d32ptr->x,__FILE__,__LINE__-1);
+      _VC_P(__FILE__,d32ptr->line, d32ptr->e,retval,d32ptr->format);
+    }
+
+  _REPORT();
+
+  /* fail comes from scaffold.c  */
+  return fail;
+}
+
+

Modified: libdfp/trunk/tests/test-printf.c
==============================================================================
--- libdfp/trunk/tests/test-printf.c (original)
+++ libdfp/trunk/tests/test-printf.c Thu Jul 22 10:18:45 2010
@@ -23,9 +23,10 @@
    Please see libdfp/COPYING.txt for more information.  */
 
 #ifndef __STDC_WANT_DEC_FP__
-#define __STDC_WANT_DEC_FP__
+#define __STDC_WANT_DEC_FP__ 1
 #endif
 
+#include <fenv.h>
 #include <float.h>
 #include <dfp.h>
 #include <stdio.h>
@@ -34,7 +35,455 @@
 #define _WANT_PC 1 /* Pick up the _PC(x,y,...) macro.  */
 #include "scaffold.c"
 
+#include "decode.h"
+
 /* Inspired by GLIBC stdio-common/tfformat.c  */
+typedef struct{
+  int line;
+  _Decimal32 d;
+  const char *expect;
+  const char *format;
+} d32_type;
+
+d32_type printf_d32s[] =
+{
+  /* Default precision.  */
+  {__LINE__, 0.0004E-4DF, "0.00000004", "%.8Hf"},
+  {__LINE__, 123.456E-6DF, "0.000123", "%Hf"},
+  {__LINE__, 123.456E-6DF, "1.234560e-04", "%He"},
+  {__LINE__, 12.0E-15DF, "0.000000", "%Hf"},
+  {__LINE__, 12.0E-5DF, "0.000120", "%Hf"},
+  {__LINE__, 12.0E-15DF, "1.2e-14", "%Hg"},
+  {__LINE__, 0.E+0DF, "0.000000", "%Hf"},
+  {__LINE__, 1.E+2DF, "100.000000", "%Hf"},
+  {__LINE__, 12.0E+3DF, "1.200000e+04", "%He"},
+  {__LINE__, 12.000E+3DF, "1.200000e+04", "%He"},
+  {__LINE__, 12.0E+3DF, "12000.000000", "%Hf"},
+  {__LINE__, 1900000.E+2DF, "190000000.000000", "%Hf"},
+  {__LINE__, 1900000.E+2DF, "190000000", "%.Hf"},
+  {__LINE__, 19.E+2DF, "1900.000000", "%Hf"},
+  /* Default precision.  */
+  {__LINE__, 1.0E+2DF, "100.000000", "%Hf"},
+  /* Default precision.  */
+  {__LINE__, 1.00E+2DF, "100.000000", "%Hf"},
+  {__LINE__, 23456.0E-3DF, "2.35e+01", "%.2He"},
+  {__LINE__, 23456.0E-3DF, "23.46", "%.2Hf"},
+  {__LINE__, 23456.E-3DF, "23.46", "%.2Hf"},
+  {__LINE__, 1234567.E0DF, "1234567.00", "%.2Hf"},
+  {__LINE__, 1234567.E0DF, "1234567.000000", "%Hf"},
+  /* Precision of '3'.  */
+  {__LINE__, 123.456E+0DF, "123.456000", "%Hf"},
+  {__LINE__, 123.456E+0DF, "123.456", "%.3Hf"},
+  /* Implict precision of '1' since there is one explicit zero in the mantissa
+   * right of the decimal place after it is adjusted for the exponent.  */
+  {__LINE__, 1.000E+2DF, "100.000000", "%Hf"},
+  /* Implict precision of '1' since there is one explicit zero in the mantissa
+   * right of the decimal place after it is adjusted for the exponent.  */
+  {__LINE__, 100.0E+0DF, "100.000000", "%Hf"},
+  /* Implict precision of '1' since there is one explicit zero in the mantissa
+   * right of the decimal place after it is adjusted for the exponent.  */
+  {__LINE__, 0.0001000E+6DF, "100.000000", "%Hf"},
+  /* Implict precision of '4' since there is one explicit zero in the mantissa
+   * right of the decimal place after it is adjusted for the exponent.  */
+  {__LINE__, 1.000000E+2DF, "100.000000", "%Hf"},
+  /* Because of the 'e' output precision is '5'.  */
+  {__LINE__, 123.456E+0DF, "1.234560e+02", "%He"},
+  {__LINE__, 123.456E+0DF, "1.23456e+02", "%.5He"},
+  {__LINE__, 123.456E+0DF, "1.234560E+02", "%HE"},
+  {__LINE__, 19000E+15DF, "19000000000000000000.000000", "%Hf"},
+  {__LINE__, 190001E+45DF, "190001000000000000000000000000000000000000000000000.000000", "%Hf"},
+  {__LINE__, -123.456E+0DF, "-1.234560e+02", "%He"},
+  /* Encoded as 1234567E1, prec 5*/
+  {__LINE__, 12.34567E+6DF, "12345670.000000", "%Hf"},
+
+  {__LINE__, 123.456E-5DF, "1.234560e-03", "%He"},
+  {__LINE__, 123.456E-5DF, "0.001235", "%Hf"},
+  {__LINE__, 123.456E-5DF, "0.00123456", "%Hg"},
+
+  {__LINE__, 123.456E-6DF, "1.234560e-04", "%He"},
+  {__LINE__, 123.456E-6DF, "0.000123", "%Hf"},
+  {__LINE__, 123.456E-6DF, "0.000123456", "%Hg"},
+
+  {__LINE__, 123.456E-7DF, "1.234560e-05", "%He"},
+  {__LINE__, 123.456E-7DF, "0.000012", "%Hf"},
+  {__LINE__, 123.456E-7DF, "1.23456e-05", "%Hg"},
+  {__LINE__, 123.456E-7DF, "1.235e-05", "%.4Hg"},
+  {__LINE__, 123.456E-9DF, "1.234560e-07", "%He"},
+
+  {__LINE__, 6.5DF, "6.5e+00", "%.1He"},
+  {__LINE__, 6.5DF, "6e+00", "%.0He"},
+  {__LINE__, 6.6DF, "7e+00", "%.0He"},
+
+  {__LINE__, 123.456E-9DF, "1.23456e-7", "%Ha"},
+  {__LINE__, 0.00000E-101DF, "0.000000e+00", "%He"},
+
+
+  {__LINE__, 0.0e10DF, "0.000000e+00", "%He"},
+  {__LINE__, 0.0e10DF, "0.000000", "%Hf"},
+
+  {__LINE__, 0.0e10DF, "0", "%Hg"},
+  /* For 'g' when '#' is present the spec says that trailing zeros are NOT
+   * removed.  And YES, this SHOULD be five trailing zeros because this falls
+   * into the category where 'g' is converted to 'e' and precision equals P - 1.
+   * Additionally, the C-spec indicates that.  This is congruent with how this
+   * works for binary float.  */
+  {__LINE__, 0.0e10DF, "0.00000", "%#Hg"},
+  {__LINE__, 0.0e10DF, "0", "%.4Hg"},
+
+  /* (1,0,-1)  */
+  {__LINE__, 0.0DF, "0.0", "%Ha"},
+  /* (1,0,0)  */
+  {__LINE__, 0e0DF, "0", "%Ha"},
+
+  /* (1,0,0)  */
+  {__LINE__, -0e0DF, "-0", "%Ha"},
+  /* (-1,0,-1)  */
+  {__LINE__, -0.0DF, "-0.0", "%Ha"},
+
+  /* ( 1, 123, 0)  */
+  {__LINE__, 123.DF, "123", "%Ha"},
+
+  /* (-1, 123, 0) -123  */
+  {__LINE__, -123.DF, "-123", "%Ha"},
+
+  /* ( 1, 123, -2) 1.23  */
+  {__LINE__, 1.23DF, "1.23", "%Ha"},
+  {__LINE__, 123E-2DF, "1.23", "%Ha"},
+  {__LINE__, 0.123E1DF, "1.23", "%Ha"},
+
+  /* ( 1, 123, 1) 1.23e+3  */
+  {__LINE__, 123e1DF, "1.23e+3", "%Ha"},
+
+  /* ( 1, 1230, 0) 1230  */
+  {__LINE__, 123.0e1DF, "1230", "%Ha"},
+
+  /* (-1, 123, 1) -1.23e+3  */
+  {__LINE__, -123e1DF, "-1.23e+3", "%Ha"},
+
+  /* ( 1, 123, -8) 0.00000123  */
+  {__LINE__, 123e-8DF, "0.00000123", "%Ha"},
+  {__LINE__, 123.e-8DF, "0.00000123", "%Ha"},
+
+  /* ( 1, 123, -9) 1.23e-7  */
+  {__LINE__, 123e-9DF, "1.23e-7", "%Ha"},
+  {__LINE__, 123.e-9DF, "1.23e-7", "%Ha"},
+
+  /* Can't represent the following in _Decimal32  */
+  /* ( 1, 1234567890123456, 0) 1234567890123456  */
+  /* ( 1, 1234567890123456, 1) 1.234567890123456e+16  */
+  /* ( 1, 1234567890123456, -1) 123456789012345.6  */
+  /* ( 1, 1234567890123456, -21) 0.000001234567890123456  */
+  /* ( 1, 1234567890123456, -22) 1.234567890123456e-7  */
+
+  /* ( 1, 0, 0) 0  */
+  {__LINE__, 0e0DF, "0", "%Ha"},
+  {__LINE__, 0.DF, "0", "%Ha"},
+  {__LINE__, 0.e0DF, "0", "%Ha"},
+
+  /* (-1, 0, 0) -0  */
+  {__LINE__, -0e0DF, "-0", "%Ha"},
+  {__LINE__, -0.DF, "-0", "%Ha"},
+  {__LINE__, -0.e0DF, "-0", "%Ha"},
+
+
+  /* ( 1, 5, -6) 0.000005  */
+  {__LINE__, 5e-6DF, "0.000005", "%Ha"},
+
+  /* ( 1, 50, -7) 0.0000050  */
+  {__LINE__, 50e-7DF, "0.0000050", "%Ha"},
+
+  /* ( 1, 5, -7) 5e-7  */
+  {__LINE__, 5e-7DF, "5e-7", "%Ha"},
+
+  /* Yes, goofy, but it is encoded 00000000e0.  */
+  {__LINE__, 0.00e2DF, "0", "%Ha"},
+
+  /* Yes, goofy, but it is encoded 00000000e0.  */
+  {__LINE__, 0.00e2DF, "0", "%.2Ha"},
+
+  /* Notice the '#'.  The DFP spec doesn't speak about this and doesn't indicate
+   * that this is supposed to work like it does for 'g' so we still expect to
+   * see trailing zeros removed and no exponent.  */
+  {__LINE__, 0.00e2DF, "0.", "%#Ha"},
+
+  /* ( 1, 5, -7)  */
+  {__LINE__, 5e-7DF, "5.e-7", "%#Ha"},
+
+  {__LINE__, 6543.E-11DF, "6.543e-8", "%Ha"},
+
+  /* Continued DPF spec examples.  */
+  {__LINE__, 6543.00DF, "6543.00", "%Ha"},
+  {__LINE__, 6543.00DF, "6543.00", "%.6Ha"},
+  {__LINE__, 6543.00DF, "6543.0", "%.5Ha"},
+  {__LINE__, 6543.00DF, "6543", "%.4Ha"},
+  {__LINE__, 6543.00DF, "6.54e+3", "%.3Ha"},
+  {__LINE__, 6543.00DF, "6.5e+3", "%.2Ha"},
+  {__LINE__, 6543.00DF, "7e+3", "%.1Ha"},
+  {__LINE__, 6543.00DF, "7E+3", "%.1HA"},
+
+  {__LINE__, 6543.00DF, " 6543.00", "%8Ha"},
+  /* The following have shown inconsistent results between soft-dfp and
+   * hard-dfp.  */
+
+  /* In reality this exceeds the ability of _Decimal32 to represent the exponent
+   * so while it SHOULD be 0e-106 it really ends up being encoded as 0e-101
+   * because that is the min exponent.  */
+  {__LINE__, 0.00000E-101DF, "0e-101", "%Ha"},
+  /* Likewise, this still exceeds.  */
+  {__LINE__, 0.00000E-97DF, "0e-101", "%Ha"},
+
+  /* As shown, this is 0e-101 for real.  */
+  {__LINE__, 0.00000E-96DF, "0e-101", "%Ha"},
+
+  {__LINE__, 0.00000E-95DF, "0e-100", "%Ha"},
+
+  {__LINE__, 0e10DF, "0e+10", "%Ha"},
+
+  {__LINE__, 0.0e10DF, "0e+9", "%.1Ha"},
+
+  {__LINE__, 0.0e-09DF, "0e-10", "%.0Ha"},
+
+  /* ( 1, 0, -6) 0.000000  */
+  {__LINE__, 0e-6DF, "0.000000", "%Ha"},
+
+  /* ( 1, 0, -7) 0e-7  */
+  {__LINE__, 0e-7DF, "0e-7", "%Ha"},
+  {__LINE__, 0.e-10DF, "0e-10", "%.1Ha"},
+  {__LINE__, 0.e-10DF, "0e-10", "%.3Ha"},
+
+  {__LINE__, 0.e-10DF, "0e-10", "%.4Ha"},
+
+  /* ( 1, 0, 2) 0e+2 encoded as 00000000e2.  */
+  {__LINE__, 0e2DF, "0e+2", "%Ha"},
+
+  /* Yes, goofy, but it is encoded 00000000e1.  */
+  {__LINE__, 0.0e2DF, "0e+1", "%Ha"},
+  {__LINE__, 0.0e10DF, "0e+9", "%Ha"},
+
+  {0,0,0,0 }
+};
+
+typedef struct{
+  int line;
+  _Decimal64 d;
+  const char *expect;
+  const char *format;
+} d64_type;
+
+d64_type printf_d64s[] =
+{
+  /* Default precision.  */
+  {__LINE__, 123.456E-6DD, "0.000123", "%Df"},
+  {__LINE__, 123.456E-6DD, "1.234560e-04", "%De"},
+  {__LINE__, 12.0E-15DD, "0.000000", "%Df"},
+  {__LINE__, 12.0E-5DD, "0.000120", "%Df"},
+  {__LINE__, 12.0E-15DD, "1.2e-14", "%Dg"},
+  {__LINE__, 0.E+0DD, "0.000000", "%Df"},
+  {__LINE__, 1.E+2DD, "100.000000", "%Df"},
+  {__LINE__, 12.0E+3DD, "1.200000e+04", "%De"},
+  {__LINE__, 12.000E+3DD, "1.200000e+04", "%De"},
+  {__LINE__, 12.0E+3DD, "12000.000000", "%Df"},
+  {__LINE__, 1900000.E+2DD, "190000000.000000", "%Df"},
+  {__LINE__, 1900000.E+2DD, "190000000", "%.Df"},
+  {__LINE__, 19.E+2DD, "1900.000000", "%Df"},
+  /* Default precision.  */
+  {__LINE__, 1.0E+2DD, "100.000000", "%Df"},
+  /* Default precision.  */
+  {__LINE__, 1.00E+2DD, "100.000000", "%Df"},
+  {__LINE__, 23456.0E-3DD, "2.35e+01", "%.2De"},
+  {__LINE__, 23456.0E-3DD, "23.46", "%.2Df"},
+  {__LINE__, 23456.E-3DD, "23.46", "%.2Df"},
+  {__LINE__, 1234567.E0DD, "1234567.00", "%.2Df"},
+  {__LINE__, 1234567.E0DD, "1234567.000000", "%Df"},
+  /* Precision of '3'.  */
+  {__LINE__, 123.456E+0DD, "123.456000", "%Df"},
+  {__LINE__, 123.456E+0DD, "123.456", "%.3Df"},
+  /* Implict precision of '1' since there is one explicit zero in the mantissa
+   * right of the decimal place after it is adjusted for the exponent.  */
+  {__LINE__, 1.000E+2DD, "100.000000", "%Df"},
+  /* Implict precision of '1' since there is one explicit zero in the mantissa
+   * right of the decimal place after it is adjusted for the exponent.  */
+  {__LINE__, 100.0E+0DD, "100.000000", "%Df"},
+  /* Implict precision of '1' since there is one explicit zero in the mantissa
+   * right of the decimal place after it is adjusted for the exponent.  */
+  {__LINE__, 0.0001000E+6DD, "100.000000", "%Df"},
+  /* Implict precision of '4' since there is one explicit zero in the mantissa
+   * right of the decimal place after it is adjusted for the exponent.  */
+  {__LINE__, 1.000000E+2DD, "100.000000", "%Df"},
+  /* Because of the 'e' output precision is '5'.  */
+  {__LINE__, 123.456E+0DD, "1.234560e+02", "%De"},
+  {__LINE__, 123.456E+0DD, "1.23456e+02", "%.5De"},
+  {__LINE__, 123.456E+0DD, "1.234560E+02", "%DE"},
+  {__LINE__, 19000E+15DD, "19000000000000000000.000000", "%Df"},
+  {__LINE__, 190001E+45DD, "190001000000000000000000000000000000000000000000000.000000", "%Df"},
+  {__LINE__, -123.456E+0DD, "-1.234560e+02", "%De"},
+  /* Encoded as 1234567E1, prec 5*/
+  {__LINE__, 12.34567E+6DD, "12345670.000000", "%Df"},
+
+  {__LINE__, 123.456E-5DD, "1.234560e-03", "%De"},
+  {__LINE__, 123.456E-5DD, "0.001235", "%Df"},
+  {__LINE__, 123.456E-5DD, "0.00123456", "%Dg"},
+
+  {__LINE__, 123.456E-6DD, "1.234560e-04", "%De"},
+  {__LINE__, 123.456E-6DD, "0.000123", "%Df"},
+  {__LINE__, 123.456E-6DD, "0.000123456", "%Dg"},
+
+  {__LINE__, 123.456E-7DD, "1.234560e-05", "%De"},
+  {__LINE__, 123.456E-7DD, "0.000012", "%Df"},
+  {__LINE__, 123.456E-7DD, "1.23456e-05", "%Dg"},
+  {__LINE__, 123.456E-7DD, "1.235e-05", "%.4Dg"},
+  {__LINE__, 123.456E-9DD, "1.234560e-07", "%De"},
+
+  {__LINE__, 6.5DD, "6.5e+00", "%.1De"},
+  {__LINE__, 6.5DD, "6e+00", "%.0De"},
+  {__LINE__, 6.6DD, "7e+00", "%.0De"},
+
+  {__LINE__, 123.456E-9DD, "1.23456e-7", "%Da"},
+  {__LINE__, 0.00000E-101DD, "0.000000e+00", "%De"},
+
+  {__LINE__, 0.e-101DD, "0e-101", "%Da"},
+
+  /* This returns 0e-106 because the zeros are significant.  */
+  {__LINE__, 0.00000E-101DD, "0e-106", "%Da"},
+
+  {__LINE__, 0.0e10DD, "0.000000e+00", "%De"},
+  {__LINE__, 0.0e10DD, "0.000000", "%Df"},
+
+  {__LINE__, 0.0e10DD, "0", "%Dg"},
+  /* For 'g' when '#' is present the spec says that trailing zeros are NOT
+   * removed.  And YES, this SHOULD be five trailing zeros because this falls
+   * into the category where 'g' is converted to 'e' and precision equals P - 1.
+   * Additionally, the C-spec indicates that.  This is congruent with how this
+   * works for binary float.  */
+  {__LINE__, 0.0e10DD, "0.00000", "%#Dg"},
+  {__LINE__, 0.0e10DD, "0", "%.4Dg"},
+
+  /* (1,0,-1)  */
+  {__LINE__, 0.0DD, "0.0", "%Da"},
+  {__LINE__, 0e10DD, "0e+10", "%Da"},
+
+  {__LINE__, 0.0e10DD, "0e+9", "%.1Da"},
+  {__LINE__, 0.0e-09DD, "0e-10", "%.0Da"},
+  /* (1,0,0)  */
+  {__LINE__, 0e0DD, "0", "%Da"},
+
+  /* (1,0,0)  */
+  {__LINE__, -0e0DD, "-0", "%Da"},
+  /* (-1,0,-1)  */
+  {__LINE__, -0.0DD, "-0.0", "%Da"},
+
+  /* ( 1, 123, 0)  */
+  {__LINE__, 123.DD, "123", "%Da"},
+
+  /* (-1, 123, 0) -123  */
+  {__LINE__, -123.DD, "-123", "%Da"},
+
+  /* ( 1, 123, -2) 1.23  */
+  {__LINE__, 1.23DD, "1.23", "%Da"},
+  {__LINE__, 123E-2DD, "1.23", "%Da"},
+  {__LINE__, 0.123E1DD, "1.23", "%Da"},
+
+  /* ( 1, 123, 1) 1.23e+3  */
+  {__LINE__, 123e1DD, "1.23e+3", "%Da"},
+
+  /* ( 1, 1230, 0) 1230  */
+  {__LINE__, 123.0e1DD, "1230", "%Da"},
+
+  /* (-1, 123, 1) -1.23e+3  */
+  {__LINE__, -123e1DD, "-1.23e+3", "%Da"},
+
+  /* ( 1, 123, -8) 0.00000123  */
+  {__LINE__, 123e-8DD, "0.00000123", "%Da"},
+  {__LINE__, 123.e-8DD, "0.00000123", "%Da"},
+
+  /* ( 1, 123, -9) 1.23e-7  */
+  {__LINE__, 123e-9DD, "1.23e-7", "%Da"},
+  {__LINE__, 123.e-9DD, "1.23e-7", "%Da"},
+
+  /* Can represent the following in _Decimal64  */
+  /* ( 1, 1234567890123456, 0) 1234567890123456  */
+  {__LINE__, 1234567890123456e0DD, "1234567890123456", "%Da"},
+
+  /* ( 1, 1234567890123456, 1) 1.234567890123456e+16  */
+  {__LINE__, 1234567890123456e1DD, "1.234567890123456e+16", "%Da"},
+
+  /* ( 1, 1234567890123456, -1) 123456789012345.6  */
+  {__LINE__, 1234567890123456e-1DD, "123456789012345.6", "%Da"},
+
+  /* ( 1, 1234567890123456, -21)    0.000001234567890123456  */
+  {__LINE__, 1234567890123456e-21DD, "0.000001234567890123456", "%Da"},
+
+  /* ( 1, 1234567890123456, -22)    1.234567890123456e-7  */
+  {__LINE__, 1234567890123456e-22DD, "1.234567890123456e-7", "%Da"},
+
+  /* ( 1, 0, 0) 0  */
+  {__LINE__, 0e0DD, "0", "%Da"},
+  {__LINE__, 0.DD, "0", "%Da"},
+  {__LINE__, 0.e0DD, "0", "%Da"},
+
+  /* (-1, 0, 0) -0  */
+  {__LINE__, -0e0DD, "-0", "%Da"},
+  {__LINE__, -0.DD, "-0", "%Da"},
+  {__LINE__, -0.e0DD, "-0", "%Da"},
+
+  /* ( 1, 0, -6) 0.000000  */
+  {__LINE__, 0e-6DD, "0.000000", "%Da"},
+
+  /* ( 1, 0, -7) 0e-7  */
+  {__LINE__, 0e-7DD, "0e-7", "%Da"},
+  {__LINE__, 0.e-10DD, "0e-10", "%.1Da"},
+  {__LINE__, 0.e-10DD, "0e-10", "%.3Da"},
+  {__LINE__, 0.e-10DD, "0e-10", "%.4Da"},
+
+
+  /* ( 1, 5, -6) 0.000005  */
+  {__LINE__, 5e-6DD, "0.000005", "%Da"},
+
+  /* ( 1, 50, -7) 0.0000050  */
+  {__LINE__, 50e-7DD, "0.0000050", "%Da"},
+
+  /* ( 1, 5, -7) 5e-7  */
+  {__LINE__, 5e-7DD, "5e-7", "%Da"},
+
+  /* ( 1, 0, 2) 0e+2 encoded as 00000000e2.  */
+  {__LINE__, 0e2DD, "0e+2", "%Da"},
+
+  /* Yes, goofy, but it is encoded 00000000e1.  */
+  {__LINE__, 0.0e2DD, "0e+1", "%Da"},
+
+  {__LINE__, 0.0e10DD, "0e+9", "%Da"},
+
+  /* Yes, goofy, but it is encoded 00000000e0.  */
+  {__LINE__, 0.00e2DD, "0", "%Da"},
+
+  /* Yes, goofy, but it is encoded 00000000e0.  */
+  {__LINE__, 0.00e2DD, "0", "%.2Da"},
+
+  /* Notice the '#'.  The DDP spec doesn't speak about this and doesn't indicate
+   * that this is supposed to work like it does for 'g' so we still expect to
+   * see trailing zeros removed and no exponent.  */
+  {__LINE__, 0.00e2DD, "0.", "%#Da"},
+
+  /* ( 1, 5, -7)  */
+  {__LINE__, 5e-7DD, "5.e-7", "%#Da"},
+
+  {__LINE__, 6543.E-11DD, "6.543e-8", "%Da"},
+
+  /* Continued DPF spec examples.  */
+  {__LINE__, 6543.00DD, "6543.00", "%Da"},
+  {__LINE__, 6543.00DD, "6543.00", "%.6Da"},
+  {__LINE__, 6543.00DD, "6543.0", "%.5Da"},
+  {__LINE__, 6543.00DD, "6543", "%.4Da"},
+  {__LINE__, 6543.00DD, "6.54e+3", "%.3Da"},
+  {__LINE__, 6543.00DD, "6.5e+3", "%.2Da"},
+  {__LINE__, 6543.00DD, "7e+3", "%.1Da"},
+  {__LINE__, 6543.00DD, "7E+3", "%.1DA"},
+
+  {__LINE__, 6543.00DD, " 6543.00", "%8Da"},
+
+  {0,0,0,0 }
+};
+
 typedef struct{
   int line;
   _Decimal128 d;
@@ -44,25 +493,237 @@
 
 d128_type printf_d128s[] =
 {
-  {__LINE__, 0.000033333DL, "0.000033333", "%DDf"},
-  /* Three digits of precision right of the decimal place.  */
-  {__LINE__, 231.2315DL, "231.232", "%.3DDf"},
-  /* Four digits of precision right of the decimal place.  */
-  {__LINE__, 231.2315DL, "231.2315", "%.4DDf"},
-  /* Space padded to 12,  Right justified.  */
-  {__LINE__, 231.2315DL, "     231.232", "%12.3DDf"},
-  /* Left justified, Space padded to 12.  */
-  {__LINE__, 231.2315DL, "231.232     ", "%-12.3DDf"},
+  /* Default precision.  */
+  {__LINE__, 123.456E-6DL, "0.000123", "%DDf"},
+  {__LINE__, 123.456E-6DL, "1.234560e-04", "%DDe"},
+  {__LINE__, 12.0E-15DL, "0.000000", "%DDf"},
+  {__LINE__, 12.0E-5DL, "0.000120", "%DDf"},
+  {__LINE__, 12.0E-15DL, "1.2e-14", "%DDg"},
+  {__LINE__, 0.E+0DL, "0.000000", "%DDf"},
+  {__LINE__, 1.E+2DL, "100.000000", "%DDf"},
+  {__LINE__, 12.0E+3DL, "1.200000e+04", "%DDe"},
+  {__LINE__, 12.000E+3DL, "1.200000e+04", "%DDe"},
+  {__LINE__, 12.0E+3DL, "12000.000000", "%DDf"},
+  {__LINE__, 1900000.E+2DL, "190000000.000000", "%DDf"},
+  {__LINE__, 1900000.E+2DL, "190000000", "%.DDf"},
+  {__LINE__, 19.E+2DL, "1900.000000", "%DDf"},
+  /* Default precision.  */
+  {__LINE__, 1.0E+2DL, "100.000000", "%DDf"},
+  /* Default precision.  */
+  {__LINE__, 1.00E+2DL, "100.000000", "%DDf"},
+  {__LINE__, 23456.0E-3DL, "2.35e+01", "%.2DDe"},
+  {__LINE__, 23456.0E-3DL, "23.46", "%.2DDf"},
+  {__LINE__, 23456.E-3DL, "23.46", "%.2DDf"},
+  {__LINE__, 1234567.E0DL, "1234567.00", "%.2DDf"},
+  {__LINE__, 1234567.E0DL, "1234567.000000", "%DDf"},
+  /* Precision of '3'.  */
+  {__LINE__, 123.456E+0DL, "123.456000", "%DDf"},
+  {__LINE__, 123.456E+0DL, "123.456", "%.3DDf"},
+  /* Implict precision of '1' since there is one explicit zero in the mantissa
+   * right of the decimal place after it is adjusted for the exponent.  */
+  {__LINE__, 1.000E+2DL, "100.000000", "%DDf"},
+  /* Implict precision of '1' since there is one explicit zero in the mantissa
+   * right of the decimal place after it is adjusted for the exponent.  */
+  {__LINE__, 100.0E+0DL, "100.000000", "%DDf"},
+  /* Implict precision of '1' since there is one explicit zero in the mantissa
+   * right of the decimal place after it is adjusted for the exponent.  */
+  {__LINE__, 0.0001000E+6DL, "100.000000", "%DDf"},
+  /* Implict precision of '4' since there is one explicit zero in the mantissa
+   * right of the decimal place after it is adjusted for the exponent.  */
+  {__LINE__, 1.000000E+2DL, "100.000000", "%DDf"},
+  /* Because of the 'e' output precision is '5'.  */
+  {__LINE__, 123.456E+0DL, "1.234560e+02", "%DDe"},
+  {__LINE__, 123.456E+0DL, "1.23456e+02", "%.5DDe"},
+  {__LINE__, 123.456E+0DL, "1.234560E+02", "%DDE"},
+  {__LINE__, 19000E+15DL, "19000000000000000000.000000", "%DDf"},
+  {__LINE__, 190001E+45DL, "190001000000000000000000000000000000000000000000000.000000", "%DDf"},
+  {__LINE__, -123.456E+0DL, "-1.234560e+02", "%DDe"},
+  /* Encoded as 1234567E1, prec 5*/
+  {__LINE__, 12.34567E+6DL, "12345670.000000", "%DDf"},
+
+  {__LINE__, 123.456E-5DL, "1.234560e-03", "%DDe"},
+  {__LINE__, 123.456E-5DL, "0.001235", "%DDf"},
+  {__LINE__, 123.456E-5DL, "0.00123456", "%DDg"},
+
+  {__LINE__, 123.456E-6DL, "1.234560e-04", "%DDe"},
+  {__LINE__, 123.456E-6DL, "0.000123", "%DDf"},
+  {__LINE__, 123.456E-6DL, "0.000123456", "%DDg"},
+
+  {__LINE__, 123.456E-7DL, "1.234560e-05", "%DDe"},
+  {__LINE__, 123.456E-7DL, "0.000012", "%DDf"},
+  {__LINE__, 123.456E-7DL, "1.23456e-05", "%DDg"},
+  {__LINE__, 123.456E-7DL, "1.235e-05", "%.4DDg"},
+  {__LINE__, 123.456E-9DL, "1.234560e-07", "%DDe"},
+
+  {__LINE__, 6.5DL, "6.5e+00", "%.1DDe"},
+  {__LINE__, 6.5DL, "6e+00", "%.0DDe"},
+  {__LINE__, 6.6DL, "7e+00", "%.0DDe"},
+
+  {__LINE__, 123.456E-9DL, "1.23456e-7", "%DDa"},
+  {__LINE__, 0.00000E-101DL, "0.000000e+00", "%DDe"},
+
+  {__LINE__, 0.e-101DL, "0e-101", "%DDa"},
+
+  /* This returns 0e-106 because the zeros are significant.  */
+  {__LINE__, 0.00000E-101DL, "0e-106", "%DDa"},
+
+  {__LINE__, 0.0e10DL, "0.000000e+00", "%DDe"},
+  {__LINE__, 0.0e10DL, "0.000000", "%DDf"},
+
+  {__LINE__, 0.0e10DL, "0", "%DDg"},
+  /* For 'g' when '#' is present the spec says that trailing zeros are NOT
+   * removed.  And YES, this SHOULD be five trailing zeros because this falls
+   * into the category where 'g' is converted to 'e' and precision equals P - 1.
+   * Additionally, the C-spec indicates that.  This is congruent with how this
+   * works for binary float.  */
+  {__LINE__, 0.0e10DL, "0.00000", "%#DDg"},
+  {__LINE__, 0.0e10DL, "0", "%.4DDg"},
+
+  /* (1,0,-1)  */
+  {__LINE__, 0.0DL, "0.0", "%DDa"},
+  {__LINE__, 0e10DL, "0e+10", "%DDa"},
+
+  {__LINE__, 0.0e10DL, "0e+9", "%.1DDa"},
+  {__LINE__, 0.0e-09DL, "0e-10", "%.0DDa"},
+  /* (1,0,0)  */
+  {__LINE__, 0e0DL, "0", "%DDa"},
+
+  /* (1,0,0)  */
+  {__LINE__, -0e0DL, "-0", "%DDa"},
+  /* (-1,0,-1)  */
+  {__LINE__, -0.0DL, "-0.0", "%DDa"},
+
+  /* ( 1, 123, 0)  */
+  {__LINE__, 123.DL, "123", "%DDa"},
+
+  /* (-1, 123, 0) -123  */
+  {__LINE__, -123.DL, "-123", "%DDa"},
+
+  /* ( 1, 123, -2) 1.23  */
+  {__LINE__, 1.23DL, "1.23", "%DDa"},
+  {__LINE__, 123E-2DL, "1.23", "%DDa"},
+  {__LINE__, 0.123E1DL, "1.23", "%DDa"},
+
+  /* ( 1, 123, 1) 1.23e+3  */
+  {__LINE__, 123e1DL, "1.23e+3", "%DDa"},
+
+  /* ( 1, 1230, 0) 1230  */
+  {__LINE__, 123.0e1DL, "1230", "%DDa"},
+
+  /* (-1, 123, 1) -1.23e+3  */
+  {__LINE__, -123e1DL, "-1.23e+3", "%DDa"},
+
+  /* ( 1, 123, -8) 0.00000123  */
+  {__LINE__, 123e-8DL, "0.00000123", "%DDa"},
+  {__LINE__, 123.e-8DL, "0.00000123", "%DDa"},
+
+  /* ( 1, 123, -9) 1.23e-7  */
+  {__LINE__, 123e-9DL, "1.23e-7", "%DDa"},
+  {__LINE__, 123.e-9DL, "1.23e-7", "%DDa"},
+
+  /* Can represent the following in _Decimal128  */
+  /* ( 1, 1234567890123456, 0) 1234567890123456  */
+  {__LINE__, 1234567890123456e0DL, "1234567890123456", "%DDa"},
+
+  /* ( 1, 1234567890123456, 1) 1.234567890123456e+16  */
+  {__LINE__, 1234567890123456e1DL, "1.234567890123456e+16", "%DDa"},
+
+  /* ( 1, 1234567890123456, -1) 123456789012345.6  */
+  {__LINE__, 1234567890123456e-1DL, "123456789012345.6", "%DDa"},
+
+  /* ( 1, 1234567890123456, -21)    0.000001234567890123456  */
+  {__LINE__, 1234567890123456e-21DL, "0.000001234567890123456", "%DDa"},
+
+  /* ( 1, 1234567890123456, -22)    1.234567890123456e-7  */
+  {__LINE__, 1234567890123456e-22DL, "1.234567890123456e-7", "%DDa"},
+
+  /* ( 1, 0, 0) 0  */
+  {__LINE__, 0e0DL, "0", "%DDa"},
+  {__LINE__, 0.DL, "0", "%DDa"},
+  {__LINE__, 0.e0DL, "0", "%DDa"},
+
+  /* (-1, 0, 0) -0  */
+  {__LINE__, -0e0DL, "-0", "%DDa"},
+  {__LINE__, -0.DL, "-0", "%DDa"},
+  {__LINE__, -0.e0DL, "-0", "%DDa"},
+
+  /* ( 1, 0, -6) 0.000000  */
+  {__LINE__, 0e-6DL, "0.000000", "%DDa"},
+
+  /* ( 1, 0, -7) 0e-7  */
+  {__LINE__, 0e-7DL, "0e-7", "%DDa"},
+  {__LINE__, 0.e-10DL, "0e-10", "%.1DDa"},
+  {__LINE__, 0.e-10DL, "0e-10", "%.3DDa"},
+  {__LINE__, 0.e-10DL, "0e-10", "%.4DDa"},
+
+
+  /* ( 1, 5, -6) 0.000005  */
+  {__LINE__, 5e-6DL, "0.000005", "%DDa"},
+
+  /* ( 1, 50, -7) 0.0000050  */
+  {__LINE__, 50e-7DL, "0.0000050", "%DDa"},
+
+  /* ( 1, 5, -7) 5e-7  */
+  {__LINE__, 5e-7DL, "5e-7", "%DDa"},
+
+  /* ( 1, 0, 2) 0e+2 encoded as 00000000e2.  */
+  {__LINE__, 0e2DL, "0e+2", "%DDa"},
+
+  /* Yes, goofy, but it is encoded 00000000e1.  */
+  {__LINE__, 0.0e2DL, "0e+1", "%DDa"},
+
+  {__LINE__, 0.0e10DL, "0e+9", "%DDa"},
+
+  /* Yes, goofy, but it is encoded 00000000e0.  */
+  {__LINE__, 0.00e2DL, "0", "%DDa"},
+
+  /* Yes, goofy, but it is encoded 00000000e0.  */
+  {__LINE__, 0.00e2DL, "0", "%.2DDa"},
+
+  /* Notice the '#'.  The DLP spec doesn't speak about this and doesn't indicate
+   * that this is supposed to work like it does for 'g' so we still expect to
+   * see trailing zeros removed and no exponent.  */
+  {__LINE__, 0.00e2DL, "0.", "%#DDa"},
+
+  /* ( 1, 5, -7)  */
+  {__LINE__, 5e-7DL, "5.e-7", "%#DDa"},
+
+  {__LINE__, 6543.E-11DL, "6.543e-8", "%DDa"},
+
+  /* Continued DPF spec examples.  */
+  {__LINE__, 6543.00DL, "6543.00", "%DDa"},
+  {__LINE__, 6543.00DL, "6543.00", "%.6DDa"},
+  {__LINE__, 6543.00DL, "6543.0", "%.5DDa"},
+  {__LINE__, 6543.00DL, "6543", "%.4DDa"},
+  {__LINE__, 6543.00DL, "6.54e+3", "%.3DDa"},
+  {__LINE__, 6543.00DL, "6.5e+3", "%.2DDa"},
+  {__LINE__, 6543.00DL, "7e+3", "%.1DDa"},
+  {__LINE__, 6543.00DL, "7E+3", "%.1DDA"},
+
+  {__LINE__, 6543.00DL, " 6543.00", "%8DDa"},
+
   {0,0,0,0 }
 };
 
 int main (void)
 {
-  d128_type *dptr;
-
-  for (dptr = printf_d128s; dptr->line; dptr++)
+  d32_type *d32ptr;
+  d64_type *d64ptr;
+  d128_type *d128ptr;
+
+  for (d32ptr = printf_d32s; d32ptr->line; d32ptr++)
     {
-      _PC_P(__FILE__,dptr->line, dptr->expect,dptr->format,dptr->d);
+      _PC_P(__FILE__,d32ptr->line, d32ptr->expect,d32ptr->format,d32ptr->d);
+    }
+
+  for (d64ptr = printf_d64s; d64ptr->line; d64ptr++)
+    {
+      _PC_P(__FILE__,d64ptr->line, d64ptr->expect,d64ptr->format,d64ptr->d);
+    }
+
+  for (d128ptr = printf_d128s; d128ptr->line; d128ptr++)
+    {
+      _PC_P(__FILE__,d128ptr->line, d128ptr->expect,d128ptr->format,d128ptr->d);
     }
 
   _REPORT();

Modified: libdfp/trunk/tests/test-strtod.c
==============================================================================
--- libdfp/trunk/tests/test-strtod.c (original)
+++ libdfp/trunk/tests/test-strtod.c Thu Jul 22 10:18:45 2010
@@ -31,12 +31,22 @@
   {__LINE__, "-0.0001", -0.0001DF, -0.0001DD, -0.0001DL },
   {__LINE__, "inf", DEC_INFINITY, DEC_INFINITY, DEC_INFINITY },
   {__LINE__, "INFINITY", DEC_INFINITY, DEC_INFINITY, DEC_INFINITY },
+  {__LINE__, "0.0E+100", DEC_INFINITY, 0.0DD, 0.0DL },
+  {__LINE__, "0.01", 0.01DF, 0.01DD, 0.01DL },
+  {__LINE__, "0.1", 0.1DF, 0.1DD, 0.1DL },
+  {__LINE__, "0.11", 0.11DF, 0.11DD, 0.11DL },
+  {__LINE__, "0.21", 0.21DF, 0.21DD, 0.21DL },
+  {__LINE__, "1.23456789E-7", 0.0DF, 0.0DD, 0.0DL },
   {__LINE__, "19e9", 19000000000.0DF, 19000000000.0DD, 19000000000.0DL },
-  {__LINE__, "1234.5678910111213e-5",0.01234DF ,0.01234DD ,0.01234DL },
+  {__LINE__, "1234.5678910111213e-5", 0.01234DF ,0.01234DD ,0.01234DL },
+  {__LINE__, "3.14", 3.140000DF, 3.140000DD, 3.140000DL },
+  {__LINE__, "3.14e-2", 0.031400DF, 0.031400DD, 0.031400DL },
   {0,0,0,0,0 }
 };
 
-const char DECLET_DEC_NAN[] = "-0,000,000,000,000,010E-1";
+const char DECLET32_NAN[] = "+0,000,000E-101";
+const char DECLET64_NAN[] = "+0,000,000,000,000,000E-398";
+const char DECLET128_NAN[] = "+0,000,000,000,000,000,000,000,000,000,000,000E-6176";
 
 /* Inspired by GLIBC stdio-common/tfformat.c  */
 typedef struct{
@@ -49,18 +59,28 @@
 
 d_nan_type strtods_nan[] =
 {
-  /* DEC_NAN is +0,000,000,000,000,000E-398 so test against that
+  /* Compare against the decoded declet for each representation of DEC_NAN since
    * since you can't compare DEC_NAN to DEC_NAN.  */
-  {__LINE__, "NaN", DECLET_DEC_NAN, DECLET_DEC_NAN, DECLET_DEC_NAN},
+  {__LINE__, "NaN", DECLET32_NAN, DECLET64_NAN, DECLET128_NAN},
   {0,0,0,0,0 }
 };
 
+#include "decode.h"
+
 int main(void) {
+
   d_type *dptr;
+
   for (dptr = strtods; dptr->line; dptr++)
     {
+
+      fprintf(stderr, "  strtod32(\"%s\",NULL) == %Hf\n  ", dptr->input, strtod32(dptr->input, NULL));
       _VC_P(__FILE__,dptr->line,dptr->d32,strtod32(dptr->input,NULL), "%Hf");
+
+      fprintf(stderr, "  strtod64(\"%s\",NULL) == %Df\n  ", dptr->input, strtod64(dptr->input, NULL));
       _VC_P(__FILE__,dptr->line,dptr->d64, strtod64(dptr->input,NULL), "%Df");
+
+      fprintf(stderr, "  strtod128(\"%s\",NULL) == %DDf\n  ", dptr->input, strtod128(dptr->input, NULL));
       _VC_P(__FILE__,dptr->line,dptr->d128, strtod128(dptr->input,NULL), "%DDf");
     }
 
@@ -76,18 +96,4 @@
 
   /* fail comes from scaffold.c  */
   return fail;
-/*
-
-	char *testcases[] = { "12.04","1234.5678910111213e-5", "1.0", "1", "19","19E2","-0.0001","-5","NaN", "INF", "0", "0.0"};
-	int i,numCases=12;
-
-	for(i=0; i< numCases; i++) {
-		printf("in: %s\n",testcases[i]);
-		printf("  out32: %Hf\n  out64: %Df\n  out128: %DDf\n",
-				strtod32(testcases[i],NULL),
-				strtod64(testcases[i],NULL),
-				strtod128(testcases[i],NULL)
-				);
-	}
-*/
 }