[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[commits] r6075 - in /branches/libdfp/libc: dfp/ dfp/sysdeps/dfp/ dfp/sysdeps/dfp/stdlib/ dfp/sysdeps/ieee754r/d32/ dfp/sysdeps/powerp...
- To: commits@xxxxxxxxxx
- Subject: [commits] r6075 - in /branches/libdfp/libc: dfp/ dfp/sysdeps/dfp/ dfp/sysdeps/dfp/stdlib/ dfp/sysdeps/ieee754r/d32/ dfp/sysdeps/powerp...
- From: eberlein@xxxxxxxxxx
- Date: Tue, 29 Apr 2008 20:52:24 -0000
Author: eberlein
Date: Tue Apr 29 13:52:23 2008
New Revision: 6075
Log:
2008-04-29 Pete Eberlein <eberlein@xxxxxxxxxx>
* stdio-common/vfprintf.c(process_arg): Replaced occurrences of __printf_dfphex with __printf_dfp
* dfp/sysdeps/powerpc/powerpc32/power6/fpu/Versions: Added 2.7
* dfp/sysdeps/powerpc/powerpc64/power6/fpu/Versions: ditto
* dfp/sysdeps/soft-dfp/Versions: ditto
* dfp/sysdeps/dfp/Versions: ditto
* dfp/Versions: ditto
* dfp/Versions.def: ditto
* dfp/sysdeps/powerpc/numdigits.h(left_justify): New function and helper functions.
* dfp/sysdeps/powerpc/dfpu/numdigits.h: New file.
* dfp/numdigits.h: New file.
* dfp/sysdeps/powerpc/dfpu/fe_decround.c(__init_printf_dfp_getround): New function.
* dfp/sysdeps/dfp/stdlib/strtod32.c: Changed FLOAT_ZERO to 0.DF. Modified fractional digits to keep significant trailing zeroes and properly handle zero with non-zero exponent.
* dfp/sysdeps/dfp/stdlib/strtod64.c: Changed FLOAT_ZERO to 0.DD.
* dfp/sysdeps/dfp/stdlib/strtod128.c: Changed FLOAT_ZERO to 0.DL.
* dfp/sysdeps/dfp/printf_dfphex.c: Deleted.
* dfp/sysdeps/dfp/printf_dfp.c(__printf_dfp): Added callback for fe_dec_getround to facilitate correct rounding. Added %a conversion.
* dfp/sysdeps/dfp/fe_decround.c(__init_printf_dfp_getround): New function.
* dfp/sysdeps/ieee754r/d32/ldexpd32.c: Added numdigits.h implementation with decnumber fallback.
* dfp/sysdeps/ieee754r/d32/frexpd32.c: Modified numdigits.h implementation with decnumber fallback.
* dfp/Makefile: Removed printf_dfphex.
Added:
branches/libdfp/libc/dfp/numdigits.h
branches/libdfp/libc/dfp/sysdeps/powerpc/dfpu/numdigits.h
Removed:
branches/libdfp/libc/dfp/sysdeps/dfp/printf_dfphex.c
Modified:
branches/libdfp/libc/dfp/Makefile
branches/libdfp/libc/dfp/Versions
branches/libdfp/libc/dfp/Versions.def
branches/libdfp/libc/dfp/sysdeps/dfp/Versions
branches/libdfp/libc/dfp/sysdeps/dfp/fe_decround.c
branches/libdfp/libc/dfp/sysdeps/dfp/printf_dfp.c
branches/libdfp/libc/dfp/sysdeps/dfp/stdlib/strtod128.c
branches/libdfp/libc/dfp/sysdeps/dfp/stdlib/strtod32.c
branches/libdfp/libc/dfp/sysdeps/dfp/stdlib/strtod64.c
branches/libdfp/libc/dfp/sysdeps/ieee754r/d32/frexpd32.c
branches/libdfp/libc/dfp/sysdeps/ieee754r/d32/ldexpd32.c
branches/libdfp/libc/dfp/sysdeps/powerpc/dfpu/fe_decround.c
branches/libdfp/libc/dfp/sysdeps/powerpc/numdigits.h
branches/libdfp/libc/dfp/sysdeps/powerpc/powerpc32/power6/fpu/Versions
branches/libdfp/libc/dfp/sysdeps/powerpc/powerpc64/power6/fpu/Versions
branches/libdfp/libc/dfp/sysdeps/soft-dfp/Versions
branches/libdfp/libc/stdio-common/vfprintf.c
Modified: branches/libdfp/libc/dfp/Makefile
==============================================================================
--- branches/libdfp/libc/dfp/Makefile (original)
+++ branches/libdfp/libc/dfp/Makefile Tue Apr 29 13:52:23 2008
@@ -112,7 +112,7 @@
# due to the sysdeps/unix/sysv/linux/Implies sydeps/dfp/Subdirs chain.
routines = $(libdfp-shared:%=libc_%) \
decroundtls strtod32 strtod64 strtod128 \
- wcstod32 wcstod64 wcstod128 printf_dfp printf_dfphex
+ wcstod32 wcstod64 wcstod128 printf_dfp
# Will only apply to those C files being built into libdfp
ifeq ($(subdir), dfp)
Modified: branches/libdfp/libc/dfp/Versions
==============================================================================
--- branches/libdfp/libc/dfp/Versions (original)
+++ branches/libdfp/libc/dfp/Versions Tue Apr 29 13:52:23 2008
@@ -1,5 +1,5 @@
libdfp {
- GLIBC_2.6 {
+ GLIBC_2.7 {
# functions potentially used in other libraries
fe_dec_getround;
fe_dec_setround;
@@ -336,7 +336,7 @@
};
}
libc {
- GLIBC_2.6 {
+ GLIBC_2.7 {
__decrm_location;
strtod32;
strtod64;
Modified: branches/libdfp/libc/dfp/Versions.def
==============================================================================
--- branches/libdfp/libc/dfp/Versions.def (original)
+++ branches/libdfp/libc/dfp/Versions.def Tue Apr 29 13:52:23 2008
@@ -1,5 +1,5 @@
libdfp {
- GLIBC_2.6
+ GLIBC_2.7
}
#libdecnumber {
# GLIBC_2.6
Added: branches/libdfp/libc/dfp/numdigits.h
==============================================================================
--- branches/libdfp/libc/dfp/numdigits.h (added)
+++ branches/libdfp/libc/dfp/numdigits.h Tue Apr 29 13:52:23 2008
@@ -1,0 +1,28 @@
+/* Number of digits functions, generic (use libdecNumber).
+
+ Copyright (C) 2006, 2007, 2008 IBM Corporation.
+ Author(s): Pete Eberlein <eberlein@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 dfp/COPYING.txt for more information. */
+
+
+#ifndef _NUMDIGITS_H
+#define _NUMDIGITS_H 1
+
+#define NUMDIGITS_SUPPORT 0
+
+#endif /* _NUMDIGITS_H */
Modified: branches/libdfp/libc/dfp/sysdeps/dfp/Versions
==============================================================================
--- branches/libdfp/libc/dfp/sysdeps/dfp/Versions (original)
+++ branches/libdfp/libc/dfp/sysdeps/dfp/Versions Tue Apr 29 13:52:23 2008
@@ -1,7 +1,7 @@
libc {
- GLIBC_2.6 {
+ GLIBC_2.7 {
# functions used in other libraries
__printf_dfp;
- __printf_dfphex;
+ __printf_dfp_getround_callback;
};
}
Modified: branches/libdfp/libc/dfp/sysdeps/dfp/fe_decround.c
==============================================================================
--- branches/libdfp/libc/dfp/sysdeps/dfp/fe_decround.c (original)
+++ branches/libdfp/libc/dfp/sysdeps/dfp/fe_decround.c Tue Apr 29 13:52:23 2008
@@ -69,3 +69,13 @@
}
strong_alias(__fe_dec_getround, fe_dec_getround)
+
+
+extern int (*__printf_dfp_getround_callback)(void);
+
+void __attribute__ ((constructor))
+__init_printf_dfp_getround (void)
+{
+ __printf_dfp_getround_callback = &__fe_dec_getround;
+}
+libc_hidden_def (__init_printf_dfp_getround);
Modified: branches/libdfp/libc/dfp/sysdeps/dfp/printf_dfp.c
==============================================================================
--- branches/libdfp/libc/dfp/sysdeps/dfp/printf_dfp.c (original)
+++ branches/libdfp/libc/dfp/sysdeps/dfp/printf_dfp.c Tue Apr 29 13:52:23 2008
@@ -29,6 +29,8 @@
#include <libioP.h>
#include <fmt_dfp.h>
+
+#include <fenv.h>
extern void __get_dpd_digits (int, const void *const *, char*, int*, int*, int*,
int*);
@@ -102,7 +104,10 @@
#define DECIMAL_PRINTF_BUF_SIZE 65 /* ((DECIMAL128_PMAX + 14) * 2) + 1 */
-/* TODO: add wide character support */
+
+/* fe_decround.c will initialize this function pointer to fe_decgetround */
+int (*__printf_dfp_getround_callback)(void) = NULL;
+
int
__printf_dfp (FILE *fp,
@@ -214,7 +219,7 @@
decpt, /* decimal point offset into digits[] */
prec, /* number of digits that follow the decimal point,
or number of significant digits for %g */
- limit, /* maximum offset into digits[], may exceed len */
+ default_prec, /* default precision, if none given */
n; /* current digit offset into digits[] */
digits[0] = '0'; /* need an extra digit for rounding up */
@@ -276,67 +281,118 @@
if (sig == 0) { sig = 1; n--; } /* coefficient is zero */
len = n + sig;
-
+ switch (spec)
+ {
+ 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;
+ }
/* if no precision is specified, use that of the decimal type */
if (prec < 0)
- switch (spec)
- {
- case 'f': prec = (exp < 0) ? -exp : 0; break;
- case 'g': prec = sig; break;
- case 'e': prec = sig-1; break;
+ prec = default_prec;
+ else if (prec < default_prec)
+ /* do rounding if precision is less than the decimal type */
+ {
+ int index, roundmode = 0, 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;
}
- else if (prec < ((spec == 'f') ? -exp : sig-(spec!='g')))
- /* do rounding if precision is less than the decimal type */
- {
- int index;
- index = n + prec;
- if (spec == 'f') index += sig + exp;
- if (spec == 'e') index += 1;
- if (spec == 'g') index += 0;
-
- if (index < len && digits[index] >= '5')
- {
+
+ }
+
+ 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 */
- switch(spec)
- {
- case 'f':
- decpt = n + sig + exp;
- break;
-
- case 'g':
- if (0 >= exp && exp >= -(prec+5) && exp+sig <= prec)
- {
- spec = 'f';
- prec -= exp+sig;
- decpt = n + sig + exp;
- break;
- }
- /* fallthru to 'e' */
- prec--;
-
- case 'e':
- exp += sig-1;
- decpt = n + 1;
- break;
- }
+ 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 */
- /* temporarily disabled until we can figure out the draft
- if (tolower (info->spec) == '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 %g, but only if they are not significant */
- if (tolower (info->spec) == 'g')
+ }
+
+ /* 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--;
@@ -344,7 +400,11 @@
/* digits to the left of the decimal pt. */
- if (n < decpt) width -= decpt - n;
+ if (n < decpt)
+ {
+ width -= decpt - n;
+ if (grouping) width -= (decpt-n)/3;
+ }
else width--; /* zero */
/* digits to the right of the decimal pt. */
@@ -352,7 +412,12 @@
else if (info->alt) width -= 1;
if (spec != 'f')
- width -= 4 + (0!=(exp/1000)) + (0!=(exp/100));
+ {
+ 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--;
@@ -369,7 +434,7 @@
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');
@@ -384,29 +449,40 @@
}
}
}
+ /* print digits */
while (n < len && n < decpt + prec)
{
- if (n == decpt) outchar (wide ? decimalwc : *decimal);
+ if (n == decpt)
+ outchar (wide ? decimalwc : *decimal);
+ else if (grouping && n < decpt && (decpt-n)%3 == 0)
+ outchar (wide ? thousands_sepwc : *thousands_sep);
outchar (digits[n]);
n++;
}
+ /* print trailing zeroes */
while (n < decpt + prec)
{
- if (n == decpt) outchar (wide ? decimalwc : *decimal);
+ if (n == decpt)
+ outchar (wide ? decimalwc : *decimal);
+ else if (grouping && n < decpt && (decpt-n)%3 == 0)
+ outchar (wide ? thousands_sepwc : *thousands_sep);
outchar ('0');
n++;
}
+ /* print decimal point, if needed */
if (n == decpt && info->alt) outchar (wide ? decimalwc : *decimal);
if (spec != 'f')
{
outchar (isupper(info->spec) ? 'E' : 'e');
- if (exp < 0) { outchar ('-'); exp = -exp; } else outchar ('+');
- n = exp;
- if (exp >= 1000) { outchar ('0'+(n/1000)); n%=1000; }
- if (exp >= 100) { outchar ('0'+(n/100)); n%=100; }
- outchar ('0'+(n/10));
+ 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));
}
Modified: branches/libdfp/libc/dfp/sysdeps/dfp/stdlib/strtod128.c
==============================================================================
--- branches/libdfp/libc/dfp/sysdeps/dfp/stdlib/strtod128.c (original)
+++ branches/libdfp/libc/dfp/sysdeps/dfp/stdlib/strtod128.c Tue Apr 29 13:52:23 2008
@@ -24,7 +24,7 @@
#define FLOAT_HUGE_VAL DEC_INFINITY
#define FLT DEC128
#define FLOAT_SIZE 128
-#define FLOAT_ZERO 0.0DL
+#define FLOAT_ZERO 0.DL
#define SET_MANTISSA(x,y)
#endif
Modified: branches/libdfp/libc/dfp/sysdeps/dfp/stdlib/strtod32.c
==============================================================================
--- branches/libdfp/libc/dfp/sysdeps/dfp/stdlib/strtod32.c (original)
+++ branches/libdfp/libc/dfp/sysdeps/dfp/stdlib/strtod32.c Tue Apr 29 13:52:23 2008
@@ -5,6 +5,7 @@
Contributed by IBM Corporation.
Adapted primarily from stdlib/strtod_l.c by Ulrich Drepper <drepper@xxxxxxxxxx>
Author(s): Joseph Kerian <jkerian@xxxxxxxxxx>
+ Pete Eberlein <eberlein@xxxxxxxxxx>
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -42,9 +43,13 @@
# define FLOAT_HUGE_VAL HUGE_VAL_D32
# define FLOAT_SIZE 32
# define FLT DEC32
-# define FLOAT_ZERO 0.0DF
+# define FLOAT_ZERO 0.DF
# define SET_MANTISSA(x,y)
#endif
+
+#define DEC_TYPE FLOAT
+#define _DECIMAL_SIZE FLOAT_SIZE
+#include <numdigits.h>
/* We use this code for the extended locale handling where the
function gets as an additional argument the locale which has to be
@@ -455,7 +460,7 @@
/* We have the number digits in the integer part. Whether these are all or
any is really a fractional digit will be decided later. */
int_no = dig_no;
- lead_zero = int_no == 0 ? -1 : 0;
+ lead_zero = int_no == 0 ? 1 : 0; /* FIXME: Why was this -1 */
/* Read the fractional digits. A special case are the 'american style'
numbers like `16.' i.e. with decimal but without trailing digits. */
@@ -561,16 +566,14 @@
}
- printf("lead_zero=%d dig_no=%d int_no=%d exponent=%d\n",
- lead_zero, dig_no, int_no, exponent);
-
/* We don't want to have to work with trailing zeroes after the radix. */
+#if 0 /* Actually, for DFP, we do. */
if (dig_no > int_no)
{
while (expp[-1] == L_('0'))
{
--expp;
- --exponent;
+ /*--exponent;*/ /* FIXME: This can't be here */
--dig_no;
}
assert (dig_no >= int_no);
@@ -591,7 +594,7 @@
++exponent;
}
while (dig_no > 0 && exponent < 0);
-
+#endif
number_parsed:
/* The whole string is parsed. Store the address of the next character. */
@@ -600,21 +603,20 @@
if (dig_no == 0)
{
- printf("lead_zero=%d dig_no=%d int_no=%d exponent=%d\n",
- lead_zero, dig_no, int_no, exponent);
-
-
- if (exponent != 0)
+ if (exponent == 0)
return negative ? -FLOAT_ZERO : FLOAT_ZERO;
-
+#if NUMDIGITS_SUPPORT==0
d32 += 1;
- while(exponent-- > 0)
+ while(exponent-- > 0) /* FIXME: this doesn't work right for exponent>0 */
d32 *= 10;
while(++exponent < 0)
d32 /= 10;
-
d32 -= d32;
+#else
+ d32 = setexp(d32, exponent);
+#endif
+
return negative ? -d32 : d32;
}
@@ -643,6 +645,7 @@
exponent -= base == 16 ? 4 * lead_zero : lead_zero;
dig_no -= lead_zero;
}
+
/* Now we have the number of digits in total and the integer digits as well
as the exponent and its sign. We can decide whether the read digits are
@@ -718,7 +721,7 @@
/* Read the decimal part as a FLOAT. */
int digcnt = dig_no - int_no;
FLOAT frac = FLOAT_ZERO;
-
+
/* There might be radix characters in
the string. But these all can be ignored because we know the
format of the number is correct and we have an exact number
@@ -731,7 +734,7 @@
startp += decimal_len;
#endif
- do
+ /*do
{
if(base == 10)
frac = frac/10 + *(startp+digcnt-1) - L_('0');
@@ -743,13 +746,30 @@
while (--digcnt > 0);
frac /= 10;
- d32 += frac;
- }
-
+ d32 += frac;*/
+
+ do
+ {
+ if(base == 10)
+ d32 = d32*10 + *startp - L_('0');
+ else
+ d32 = d32*10 + (*startp >= L_('0') &&
+ *startp <= L_('9') ? -L_('0') : 10-L_('a'))
+ + *startp;
+ ++startp;
+ --exponent;
+ }
+ while (--digcnt > 0);
+ }
+
+#if NUMDIGITS_SUPPORT==0
while(exponent-- > 0)
d32 *= 10;
while(++exponent < 0)
d32 /= 10;
+#else
+ d32 = setexp(d32, getexp(d32) + exponent);
+#endif
return negative? -d32:d32;
}
Modified: branches/libdfp/libc/dfp/sysdeps/dfp/stdlib/strtod64.c
==============================================================================
--- branches/libdfp/libc/dfp/sysdeps/dfp/stdlib/strtod64.c (original)
+++ branches/libdfp/libc/dfp/sysdeps/dfp/stdlib/strtod64.c Tue Apr 29 13:52:23 2008
@@ -25,7 +25,7 @@
#define FLOAT_HUGE_VAL DEC_INFINITY
#define FLT DEC64
#define FLOAT_SIZE 64
-#define FLOAT_ZERO 0.0DD
+#define FLOAT_ZERO 0.DD
#define SET_MANTISSA(x,y)
#endif
Modified: branches/libdfp/libc/dfp/sysdeps/ieee754r/d32/frexpd32.c
==============================================================================
--- branches/libdfp/libc/dfp/sysdeps/ieee754r/d32/frexpd32.c (original)
+++ branches/libdfp/libc/dfp/sysdeps/ieee754r/d32/frexpd32.c Tue Apr 29 13:52:23 2008
@@ -38,6 +38,7 @@
DEC_TYPE
INTERNAL_FUNCTION_NAME (DEC_TYPE x, int *y)
{
+#if NUMDIGITS_SUPPORT==1
DEC_TYPE result;
int digits, exponent;
@@ -48,13 +49,10 @@
exponent = getexp(x);
*y = digits + exponent;
- result = x;
- setexp(&result, -digits);
-
- return result;
+ result = setexp(result, -digits);
-/* old decnumber implementation */
-/* decNumber dn_x;
+#else
+ decNumber dn_x;
decContext context;
*y = 0;
@@ -68,8 +66,9 @@
___decContextDefault(&context, DEFAULT_CONTEXT);
FUNC_CONVERT_FROM_DN (&dn_x, &result, &context);
+#endif
- return result;*/
+ return result;
}
weak_alias (INTERNAL_FUNCTION_NAME, EXTERNAL_FUNCTION_NAME)
Modified: branches/libdfp/libc/dfp/sysdeps/ieee754r/d32/ldexpd32.c
==============================================================================
--- branches/libdfp/libc/dfp/sysdeps/ieee754r/d32/ldexpd32.c (original)
+++ branches/libdfp/libc/dfp/sysdeps/ieee754r/d32/ldexpd32.c Tue Apr 29 13:52:23 2008
@@ -32,14 +32,32 @@
#define FUNCTION_NAME ldexp
#include <dfpmacro.h>
+#include <numdigits.h>
DEC_TYPE
IEEE_FUNCTION_NAME (DEC_TYPE x, int y)
{
+ DEC_TYPE result;
+ long newexp;
+
+#if NUMDIGITS_SUPPORT==1
+ newexp = getexp(x) + y + 1;
+ if (newexp > PASTE(DECIMAL,PASTE(_DECIMAL_SIZE,_Emax)))
+ {
+ result = DFP_HUGE_VAL;
+ DFP_EXCEPT (FE_OVERFLOW);
+ }
+ else if (newexp < PASTE(DECIMAL,PASTE(_DECIMAL_SIZE,_Emin)))
+ {
+ result = -DFP_HUGE_VAL;
+ DFP_EXCEPT (FE_OVERFLOW);
+ }
+ else
+ result = setexp(x, newexp);
+
+#else
decContext context;
- DEC_TYPE result;
decNumber dn_x;
- long newexp;
FUNC_CONVERT_TO_DN (&x, &dn_x);
if (___decNumberIsNaN (&dn_x) || ___decNumberIsZero (&dn_x) ||
@@ -62,6 +80,7 @@
if (context.status & DEC_Overflow)
DFP_EXCEPT (FE_OVERFLOW);
+#endif
return result;
}
Modified: branches/libdfp/libc/dfp/sysdeps/powerpc/dfpu/fe_decround.c
==============================================================================
--- branches/libdfp/libc/dfp/sysdeps/powerpc/dfpu/fe_decround.c (original)
+++ branches/libdfp/libc/dfp/sysdeps/powerpc/dfpu/fe_decround.c Tue Apr 29 13:52:23 2008
@@ -122,3 +122,14 @@
}
}
strong_alias(__fe_dec_getround, fe_dec_getround)
+
+
+
+extern int (*__printf_dfp_getround_callback)(void);
+
+void __attribute__ ((constructor))
+__init_printf_dfp_getround (void)
+{
+ __printf_dfp_getround_callback = &__fe_dec_getround;
+}
+libc_hidden_def (__init_printf_dfp_getround);
Added: branches/libdfp/libc/dfp/sysdeps/powerpc/dfpu/numdigits.h
==============================================================================
--- branches/libdfp/libc/dfp/sysdeps/powerpc/dfpu/numdigits.h (added)
+++ branches/libdfp/libc/dfp/sysdeps/powerpc/dfpu/numdigits.h Tue Apr 29 13:52:23 2008
@@ -1,0 +1,173 @@
+/* Number of digits functions, optimized for Power6.
+
+ Copyright (C) 2006, 2007, 2008 IBM Corporation.
+ Author(s): Pete Eberlein <eberlein@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 dfp/COPYING.txt for more information. */
+
+
+#ifndef _NUMDIGITS_H
+#define _NUMDIGITS_H 1
+
+
+#define NUMDIGITS_SUPPORT 1
+
+#include "dpd-private.h"
+
+#if _DECIMAL_SIZE == 32
+// DECIMAL32 gets widened to DECIMAL64, so it ought to use DECIMAL64 bias
+# define DECIMAL_BIAS (101+297)
+#elif _DECIMAL_SIZE == 64
+# define DECIMAL_BIAS 398
+#elif _DECIMAL_SIZE == 128
+# define DECIMAL_BIAS 6176
+#endif
+
+
+static inline int
+getexp (DEC_TYPE x)
+{
+ union {
+ double f;
+ int i[2];
+ } result;
+
+#if _DECIMAL_SIZE == 32
+ asm ("dctdp %0,%1\n\t"
+ "dxex %0,%0\n\t" : "=f"(result.f) : "f"(x));
+#elif _DECIMAL_SIZE == 64
+ asm ("dxex %0,%1" : "=f"(result.f) : "f"(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;
+}
+
+
+static inline DEC_TYPE
+setexp (DEC_TYPE x, int exp)
+{
+#if _DECIMAL_SIZE == 128
+ register DEC_TYPE tmp asm ("fr0") = x;
+#else
+ register DEC_TYPE tmp = x;
+#endif
+ union {
+ int i[2];
+ double f;
+ } e;
+
+ e.i[0] = 0;
+ e.i[1] = exp + DECIMAL_BIAS;
+
+ asm (
+#if _DECIMAL_SIZE == 32
+ "dctdp %0,%0\n\t"
+ "diex %0,%1,%0\n\t"
+ "drsp %0,%0\n\t"
+#elif _DECIMAL_SIZE == 64
+ "diex %0,%1,%0\n\t"
+#elif _DECIMAL_SIZE == 128
+ "diexq %0,%1,%0\n\t"
+#endif
+ : "=f"(tmp) : "f"(e.f), "0"(tmp));
+ return tmp;
+}
+
+
+
+static inline int
+numdigits (DEC_TYPE x)
+{
+#if _DECIMAL_SIZE == 128
+ register DEC_TYPE tmp asm ("fr0") = x;
+#else
+ register DEC_TYPE tmp = x;
+#endif
+ union {
+ int i[2];
+ double f;
+ } a, b, one;
+
+ one.i[0] = 0;
+ one.i[1] = 1;
+
+ asm (
+#if _DECIMAL_SIZE == 32
+ "dctdp %0,%0\n\t"
+#endif
+#if _DECIMAL_SIZE != 128
+ "dxex %1,%0\n\t"
+ "drrnd %0,%4,%0,1\n\t"
+ "dxex %2,%0\n\t"
+#else /* _DECIMAL_SIZE == 128 */
+ "dxexq %1,%0\n\t"
+ "drrndq %0,%4,%0,1\n\t"
+ "dxexq %2,%0\n\t"
+#endif
+ : "=f"(tmp), "=f"(a.f), "=f"(b.f) : "0"(tmp), "f"(one.f));
+// printf("a: %lld b: %lld\n", a.i, b.i);
+ return b.i[1] - a.i[1] + 1;
+}
+
+
+static 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 {
+ int i[2];
+ double f;
+ } d;
+
+ d.i[0] = 0;
+ d.i[1] = 1;
+
+#if _DECIMAL_SIZE == 32
+ asm ("dctdp %0,%0\n\t" : "=f"(tmp) : "0"(tmp));
+#endif
+
+#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));
+
+#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 */
Modified: branches/libdfp/libc/dfp/sysdeps/powerpc/numdigits.h
==============================================================================
--- branches/libdfp/libc/dfp/sysdeps/powerpc/numdigits.h (original)
+++ branches/libdfp/libc/dfp/sysdeps/powerpc/numdigits.h Tue Apr 29 13:52:23 2008
@@ -22,6 +22,16 @@
#ifndef _NUMDIGITS_H
#define _NUMDIGITS_H 1
+
+#define NUMDIGITS_SUPPORT 1
+
+#ifndef DEC_TYPE
+#error DEC_TYPE must be declared
+#endif
+
+#ifndef _DECIMAL_SIZE
+#error _DECIMAL_SIZE must be declared
+#endif
#include "dpd-private.h"
#include <string.h>
@@ -62,44 +72,110 @@
}
-static inline void
-setexp (DEC_TYPE *x, int exp)
+static inline DEC_TYPE
+setexp (DEC_TYPE x, int exp)
{
#if _DECIMAL_SIZE == 32
union ieee754r_Decimal32 d;
- d.sd = *x;
+ d.sd = x;
exp += DECIMAL32_Bias;
d.ieee.bec = exp;
d.ieee.c = lm2lmd_to_c[c_decoder[d.ieee.c].lmd][exp >> DECIMAL32_BEC_bits];
- *x = d.sd;
+ return d.sd;
#elif _DECIMAL_SIZE == 64
union ieee754r_Decimal64 d;
- d.dd = *x;
+ d.dd = x;
exp += DECIMAL64_Bias;
d.ieee.bec = exp;
d.ieee.c = lm2lmd_to_c[c_decoder[d.ieee.c].lmd][exp >> DECIMAL64_BEC_bits];
- *x = d.dd;
+ return d.dd;
#elif _DECIMAL_SIZE == 128
union ieee754r_Decimal128 d;
- d.td = *x;
+ d.td = x;
exp += DECIMAL128_Bias;
d.ieee.bec = exp;
d.ieee.c = lm2lmd_to_c[c_decoder[d.ieee.c].lmd][exp >> DECIMAL128_BEC_bits];
- *x = d.td;
-
-#endif
-
-}
+ return d.td;
+
+#endif
+
+}
+
+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)
+{
+ unsigned int bcd;
+#if _DECIMAL_SIZE == 32
+ union ieee754r_Decimal32 d;
+ d.sd = x;
+ d.ieee.c = lm2lmd_to_c[str[0]-'0'][c_decoder[d.ieee.c].lm_exp];
+
+ d.ieee.cc0 = __dfp_declet_to_dpd(str+1);
+ d.ieee.cc1 = __dfp_declet_to_dpd(str+4);
+
+ return d.sd;
+
+#elif _DECIMAL_SIZE == 64
+ union ieee754r_Decimal64 d;
+ d.dd = x;
+ d.ieee.c = lm2lmd_to_c[str[0]-'0'][c_decoder[d.ieee.c].lm_exp];
+
+ d.ieee.cc0 = __dfp_declet_to_dpd(str+1);
+ /* Packed fields crossing a word boundary require special handling. */
+ bcd = __dfp_declet_to_dpd(str+4);
+ d.ieee.cc1H8 = bcd>>2;
+ d.ieee.cc1L2 = bcd;
+ d.ieee.cc2 = __dfp_declet_to_dpd(str+7);
+ d.ieee.cc3 = __dfp_declet_to_dpd(str+10);
+ d.ieee.cc4 = __dfp_declet_to_dpd(str+13);
+
+ return d.dd;
+
+#elif _DECIMAL_SIZE == 128
+ union ieee754r_Decimal128 d;
+ d.td = x;
+ d.ieee.c = lm2lmd_to_c[str[0]-'0'][c_decoder[d.ieee.c].lm_exp];
+
+ d.ieee.cc0 = __dfp_declet_to_dpd(str+1);
+ /* Packed fields crossing a word boundary require special handling. */
+ bcd = __dfp_declet_to_dpd(str+4);
+ d.ieee.cc1H4 = bcd>>6;
+ d.ieee.cc1L6 = bcd;
+ d.ieee.cc2 = __dfp_declet_to_dpd(str+7);
+ d.ieee.cc3 = __dfp_declet_to_dpd(str+10);
+ bcd = __dfp_declet_to_dpd(str+13);
+ d.ieee.cc4H6 = bcd>>4;
+ d.ieee.cc4L4 = bcd;
+ d.ieee.cc5 = __dfp_declet_to_dpd(str+16);
+ d.ieee.cc6 = __dfp_declet_to_dpd(str+19);
+ bcd = __dfp_declet_to_dpd(str+22);
+ d.ieee.cc7H8 = bcd>>2;
+ d.ieee.cc7L2 = bcd;
+ d.ieee.cc8 = __dfp_declet_to_dpd(str+25);
+ d.ieee.cc9 = __dfp_declet_to_dpd(str+28);
+ d.ieee.cc10 = __dfp_declet_to_dpd(str+31);
+
+ return d.td;
+
+#endif
+}
+
static inline int
numdigits (DEC_TYPE x)
{
- int firstdigit = 0 ;
+ int firstdigit = 0;
#if _DECIMAL_SIZE == 32
char digits[8];
__get_digits_d32(x, digits, NULL, NULL, NULL, NULL);
@@ -115,5 +191,32 @@
return strlen(digits + firstdigit);
}
+static inline DEC_TYPE
+left_justify (DEC_TYPE x)
+{
+ int firstdigit = 0, len;
+#if _DECIMAL_SIZE == 32
+ char digits[8+7];
+ __get_digits_d32(x, digits, NULL, NULL, NULL, NULL);
+#elif _DECIMAL_SIZE == 64
+ char digits[17+16];
+ __get_digits_d64(x, digits, NULL, NULL, NULL, NULL);
+#elif _DECIMAL_SIZE == 128
+ char digits[35+34];
+ __get_digits_d128(x, digits, NULL, NULL, NULL, NULL);
+#endif
+ while (digits[firstdigit] == '0') firstdigit++;
+ len = strlen(digits + firstdigit);
+ if (len)
+ {
+ /* pad the significant digits with enough trailing zeroes */
+ memset(digits + firstdigit + len, '0', firstdigit);
+ x = setdigits(x, digits + firstdigit);
+ x = setexp(x, getexp(x) - firstdigit);
+ }
+
+ return x;
+}
+
#endif /* _NUMDIGITS_H */
Modified: branches/libdfp/libc/dfp/sysdeps/powerpc/powerpc32/power6/fpu/Versions
==============================================================================
--- branches/libdfp/libc/dfp/sysdeps/powerpc/powerpc32/power6/fpu/Versions (original)
+++ branches/libdfp/libc/dfp/sysdeps/powerpc/powerpc32/power6/fpu/Versions Tue Apr 29 13:52:23 2008
@@ -1,5 +1,5 @@
libdfp {
- GLIBC_2.6 {
+ GLIBC_2.7 {
__addsd3; __adddd3; __addtd3;
__subsd3; __subdd3; __subtd3;
__mulsd3; __muldd3; __multd3;
@@ -17,5 +17,6 @@
__floatdisd; __floatdidd; __floatditd;
__floatunssisd; __floatunssidd; __floatunssitd;
__floatunsdisd; __floatunsdidd; __floatunsditd;
+ quantized32; quantized64; quantized128;
}
}
Modified: branches/libdfp/libc/dfp/sysdeps/powerpc/powerpc64/power6/fpu/Versions
==============================================================================
--- branches/libdfp/libc/dfp/sysdeps/powerpc/powerpc64/power6/fpu/Versions (original)
+++ branches/libdfp/libc/dfp/sysdeps/powerpc/powerpc64/power6/fpu/Versions Tue Apr 29 13:52:23 2008
@@ -1,5 +1,5 @@
libdfp {
- GLIBC_2.6 {
+ GLIBC_2.7 {
__addsd3; __adddd3; __addtd3;
__subsd3; __subdd3; __subtd3;
__mulsd3; __muldd3; __multd3;
Modified: branches/libdfp/libc/dfp/sysdeps/soft-dfp/Versions
==============================================================================
--- branches/libdfp/libc/dfp/sysdeps/soft-dfp/Versions (original)
+++ branches/libdfp/libc/dfp/sysdeps/soft-dfp/Versions Tue Apr 29 13:52:23 2008
@@ -1,5 +1,5 @@
libdfp {
- GLIBC_2.6 {
+ GLIBC_2.7 {
__addsd3; __adddd3; __addtd3;
__subsd3; __subdd3; __subtd3;
__mulsd3; __muldd3; __multd3;
Modified: branches/libdfp/libc/stdio-common/vfprintf.c
==============================================================================
--- branches/libdfp/libc/stdio-common/vfprintf.c (original)
+++ branches/libdfp/libc/stdio-common/vfprintf.c Tue Apr 29 13:52:23 2008
@@ -974,7 +974,7 @@
\
IFDEF__STDC_DEC_FP__( \
if (is_decimal) \
- function_done = __printf_dfphex (s, &info, &ptr); \
+ function_done = __printf_dfp (s, &info, &ptr); \
else \
) \
function_done = __printf_fphex (s, &info, &ptr); \
@@ -988,7 +988,7 @@
IFDEF__STDC_DEC_FP__( \
/* FIX ME */ \
if (is_decimal) \
- function_done = __printf_dfphex (s, &fspec->info, &ptr); \
+ function_done = __printf_dfp (s, &fspec->info, &ptr); \
else \
) \
function_done = __printf_fphex (s, &fspec->info, &ptr); \