[pypy-svn] r75707 - in pypy/branch/fast-forward/pypy: objspace/std objspace/std/test rlib

benjamin at codespeak.net benjamin at codespeak.net
Thu Jul 1 00:14:49 CEST 2010


Author: benjamin
Date: Thu Jul  1 00:14:47 2010
New Revision: 75707

Modified:
   pypy/branch/fast-forward/pypy/objspace/std/floatobject.py
   pypy/branch/fast-forward/pypy/objspace/std/newformat.py
   pypy/branch/fast-forward/pypy/objspace/std/test/test_newformat.py
   pypy/branch/fast-forward/pypy/rlib/rarithmetic.py
Log:
cobble some code together for float formatting

Modified: pypy/branch/fast-forward/pypy/objspace/std/floatobject.py
==============================================================================
--- pypy/branch/fast-forward/pypy/objspace/std/floatobject.py	(original)
+++ pypy/branch/fast-forward/pypy/objspace/std/floatobject.py	Thu Jul  1 00:14:47 2010
@@ -1,7 +1,7 @@
 import operator, new
 from pypy.interpreter import gateway
 from pypy.interpreter.error import OperationError
-from pypy.objspace.std import model
+from pypy.objspace.std import model, newformat
 from pypy.objspace.std.multimethod import FailedToImplementArgs
 from pypy.objspace.std.model import registerimplementation, W_Object
 from pypy.objspace.std.register_all import register_all
@@ -106,6 +106,9 @@
 def str__Float(space, w_float):
     return float2string(space, w_float, "%.12g")
 
+def format__Float_ANY(space, w_float, w_spec):
+    return newformat.get_formatter(space, w_spec).format_float(w_float)
+
 # ____________________________________________________________
 # A mess to handle all cases of float comparison without relying
 # on delegation, which can unfortunately loose precision when

Modified: pypy/branch/fast-forward/pypy/objspace/std/newformat.py
==============================================================================
--- pypy/branch/fast-forward/pypy/objspace/std/newformat.py	(original)
+++ pypy/branch/fast-forward/pypy/objspace/std/newformat.py	Thu Jul  1 00:14:47 2010
@@ -419,15 +419,15 @@
         self._calc_padding(string, length)
         return space.wrap(self._pad(string))
 
-    def _get_locale(self, locale_kind):
+    def _get_locale(self, tp):
         space = self.space
-        if locale_kind == CURRENT_LOCALE:
+        if tp == "n":
             dec, thousands, grouping = rlocale.numeric_formatting()
-        elif locale_kind == DEFAULT_LOCALE:
+        elif self._thousands_sep:
             dec = "."
             thousands = ","
             grouping = "\3\0"
-        elif locale_kind == NO_LOCALE:
+        else:
             dec = "."
             thousands = ""
             grouping = "\256"
@@ -445,7 +445,7 @@
         spec.n_digits = n_number - n_remainder - has_dec
         spec.n_prefix = n_prefix
         spec.n_lpadding = 0
-        spec.n_decimal = 1 if has_dec else 0
+        spec.n_decimal = int(has_dec)
         spec.n_remainder = n_remainder
         spec.n_spadding = 0
         spec.n_rpadding = 0
@@ -548,7 +548,7 @@
 
 
     def _fill_number(self, spec, num, to_digits, n_digits, to_prefix, fill_char,
-                     upper):
+                     to_remainder, upper):
         out = self._builder()
         if spec.n_lpadding:
             out.append_multiple_char(fill_char, spec.n_lpadding)
@@ -563,16 +563,16 @@
             out.append_multiple_char(fill_char, spec.n_spadding)
         if spec.n_digits != 0:
             if self._loc_thousands:
-                num = self._grouped_digits
+                digits = self._grouped_digits
             else:
-                num = num[to_digits:]
+                digits = num[to_digits:to_digits + spec.n_digits]
             if upper:
-                num = self._upcase_string(num)
-            out.append(num)
+                digits = self._upcase_string(digits)
+            out.append(digits)
         if spec.n_decimal:
             out.append(".")
         if spec.n_remainder:
-            out.append(num[0])
+            out.append(num[to_remainder:])
         if spec.n_rpadding:
             out.append_multiple_char(fill_char, spec.n_rpadding)
         return self.space.wrap(out.build())
@@ -598,6 +598,7 @@
                 result = chr(value)
             n_digits = 1
             n_remainder = 1
+            to_remainder = 0
             n_prefix = 0
             to_prefix = 0
             to_numeric = 0
@@ -628,20 +629,15 @@
                 to_prefix += 1
             n_digits = len(result) - skip_leading
             n_remainder = 0
+            to_remainder = 0
             to_numeric = skip_leading
-        if tp == "n":
-            locale_kind = CURRENT_LOCALE
-        elif self._thousands_sep:
-            locale_kind = DEFAULT_LOCALE
-        else:
-            locale_kind = NO_LOCALE
-        self._get_locale(locale_kind)
+        self._get_locale(tp)
         spec = self._calc_num_width(n_prefix, sign_char, to_numeric, n_digits,
                                     n_remainder, False, result)
         fill = " " if self._fill_char == "\0" else self._fill_char
         upper = self._type == "X"
         return self._fill_number(spec, result, to_numeric, n_digits, to_prefix,
-                                 fill, upper)
+                                 fill, to_remainder, upper)
 
     def _long_to_base(self, base, value):
         prefix = ""
@@ -718,24 +714,63 @@
               tp == "G" or
               tp == "%"):
             w_float = space.float(w_num)
-            self._format_float(w_float)
+            return self._format_float(w_float)
         else:
             self._unknown_presentation("int" if kind == INT_KIND else "long")
 
+    def _parse_number(self, s, i):
+        length = len(s)
+        while i < length and "0" <= s[i] <= "9":
+            i += 1
+        rest = i
+        dec_point = i < length and s[i] == "."
+        if dec_point:
+            rest += 1
+        return dec_point, rest
+
     def _format_float(self, w_float):
         space = self.space
+        flags = 0
+        default_precision = 6
         if self._alternate:
             msg = "alternate form not allowed in float formats"
             raise OperationError(space.w_ValueError, space.wrap(msg))
         tp = self._type
         if tp == "\0":
             tp = "g"
+            default_prec = 12
+            flags |= rarithmetic.DTSF_ADD_DOT_0
+        elif tp == "n":
+            tp = "g"
         value = space.float_w(w_float)
         if tp == "%":
             tp = "f"
             value *= 100
+            add_pct = True
+        else:
+            add_pct = False
         if self._precision == -1:
-            self._precision = 6
+            self._precision = default_precision
+        result, special = rarithmetic.double_to_string(value, tp,
+                                                       self._precision, flags)
+        if add_pct:
+            result += "%"
+        n_digits = len(result)
+        if result[0] == "-":
+            sign = "-"
+            to_number = 1
+            n_digits -= 1
+        else:
+            sign = "\0"
+            to_number = 0
+        have_dec_point, to_remainder = self._parse_number(result, to_number)
+        n_remainder = len(result) - to_remainder
+        self._get_locale(tp)
+        spec = self._calc_num_width(0, sign, to_number, n_digits,
+                                    n_remainder, have_dec_point, result)
+        fill = " " if self._fill_char == "\0" else self._fill_char
+        return self._fill_number(spec, result, to_number, None, 0, fill,
+                                 to_remainder, False)
 
     def format_float(self, w_float):
         space = self.space

Modified: pypy/branch/fast-forward/pypy/objspace/std/test/test_newformat.py
==============================================================================
--- pypy/branch/fast-forward/pypy/objspace/std/test/test_newformat.py	(original)
+++ pypy/branch/fast-forward/pypy/objspace/std/test/test_newformat.py	Thu Jul  1 00:14:47 2010
@@ -215,3 +215,15 @@
 
     def setup_class(cls):
         cls.w_i = cls.space.w_long
+
+
+class AppTestFloatFormatting:
+
+    def test_alternate(self):
+        raises(ValueError, format, 1.0, "#")
+
+    def test_simple(self):
+        assert format(0.0, "f") == "0.000000"
+
+    def test_sign(self):
+        assert format(-1.23, "1") == "-1.23"

Modified: pypy/branch/fast-forward/pypy/rlib/rarithmetic.py
==============================================================================
--- pypy/branch/fast-forward/pypy/rlib/rarithmetic.py	(original)
+++ pypy/branch/fast-forward/pypy/rlib/rarithmetic.py	Thu Jul  1 00:14:47 2010
@@ -465,6 +465,22 @@
 
     return formatd(fmt, x)
 
+DTSF_ADD_DOT_0 = 1
+
+DIST_FINITE = 1
+DIST_NAN = 2
+DIST_INFINITY = 3
+
+def double_to_string(value, tp, precision, flags):
+    if isnan(value):
+        special = DIST_NAN
+    elif isinf(value):
+        special = DIST_INFINITY
+    else:
+        special = DIST_FINITE
+    result = formatd_overflow(False, precision, tp, value)
+    return result, special
+
 # the 'float' C type
 
 class r_singlefloat(object):



More information about the Pypy-commit mailing list