[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/
- To: commits@xxxxxxxxxx
- Subject: [commits] r11029 - in /libdfp/trunk: ./ base-math/ sysdeps/dpd/ sysdeps/powerpc/dfpu/ sysdeps/soft-dfp/dpd/ tests/
- From: ryanarn@xxxxxxxxxx
- Date: Thu, 22 Jul 2010 17:18:46 -0000
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)
- );
- }
-*/
}