[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...



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);	      \