[pypy-svn] r79964 - in pypy/branch/fast-forward/pypy: objspace/std rlib rlib/test rpython/lltypesystem rpython/module rpython/module/test translator/c/src translator/c/test

afa at codespeak.net afa at codespeak.net
Sat Dec 11 00:34:43 CET 2010


Author: afa
Date: Sat Dec 11 00:34:40 2010
New Revision: 79964

Modified:
   pypy/branch/fast-forward/pypy/objspace/std/complexobject.py
   pypy/branch/fast-forward/pypy/objspace/std/floatobject.py
   pypy/branch/fast-forward/pypy/rlib/rarithmetic.py
   pypy/branch/fast-forward/pypy/rlib/rmarshal.py
   pypy/branch/fast-forward/pypy/rlib/test/test_rarithmetic.py
   pypy/branch/fast-forward/pypy/rlib/test/test_rmarshal.py
   pypy/branch/fast-forward/pypy/rpython/lltypesystem/ll_str.py
   pypy/branch/fast-forward/pypy/rpython/module/ll_strtod.py
   pypy/branch/fast-forward/pypy/rpython/module/test/test_ll_strtod.py
   pypy/branch/fast-forward/pypy/translator/c/src/ll_strtod.h
   pypy/branch/fast-forward/pypy/translator/c/test/test_extfunc.py
   pypy/branch/fast-forward/pypy/translator/c/test/test_standalone.py
Log:
Refactor formatd() to not take a printf-like format,
but several arguments instead.
This prepares for the inclusion of the dtoa functions.


Modified: pypy/branch/fast-forward/pypy/objspace/std/complexobject.py
==============================================================================
--- pypy/branch/fast-forward/pypy/objspace/std/complexobject.py	(original)
+++ pypy/branch/fast-forward/pypy/objspace/std/complexobject.py	Sat Dec 11 00:34:40 2010
@@ -3,7 +3,8 @@
 from pypy.objspace.std.model import registerimplementation, W_Object
 from pypy.objspace.std.register_all import register_all
 from pypy.objspace.std.floatobject import W_FloatObject, _hash_float
-from pypy.rlib.rarithmetic import formatd, isinf, isnan, copysign
+from pypy.rlib.rarithmetic import (
+    formatd, DTSF_STR_PRECISION, isinf, isnan, copysign)
 
 import math
 
@@ -255,7 +256,7 @@
     #w_imag = space.call_function(space.w_float,space.wrap(-w_self.imagval))
     return space.newcomplex(w_self.realval,-w_self.imagval)
 
-def format_float(x, format):
+def format_float(x, code, precision):
     # like float2string, except that the ".0" is not necessary
     if isinf(x):
         if x > 0.0:
@@ -265,12 +266,12 @@
     elif isnan(x):
         return "nan"
     else:
-        return formatd(format, x)
+        return formatd(x, code, precision)
 
 def repr_format(x):
-    return format_float(x, "%.17g")
+    return format_float(x, 'r', 0)
 def str_format(x):
-    return format_float(x, "%.12g")
+    return format_float(x, 'g', DTSF_STR_PRECISION)
 
 def repr__Complex(space, w_complex):
     if w_complex.realval == 0 and copysign(1., w_complex.realval) == 1.:

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	Sat Dec 11 00:34:40 2010
@@ -9,7 +9,8 @@
 from pypy.objspace.std.noneobject import W_NoneObject
 from pypy.objspace.std.longobject import W_LongObject
 from pypy.rlib.rarithmetic import ovfcheck_float_to_int, intmask, isinf, isnan
-from pypy.rlib.rarithmetic import formatd, LONG_BIT, INFINITY, copysign
+from pypy.rlib.rarithmetic import (LONG_BIT, INFINITY, copysign,
+    formatd, DTSF_ADD_DOT_0, DTSF_STR_PRECISION)
 from pypy.rlib.rbigint import rbigint
 from pypy.rlib.objectmodel import we_are_translated
 from pypy.rlib import rfloat
@@ -130,7 +131,7 @@
     else:
         return space.wrap("0x%sp%s%d" % (s, sign, exp))
 
-def float2string(space, w_float, format):
+def float2string(space, w_float, code, precision):
     x = w_float.floatval
     # we special-case explicitly inf and nan here
     if isinf(x):
@@ -141,23 +142,14 @@
     elif isnan(x):
         s = "nan"
     else:
-        s = formatd(format, x)
-        # We want float numbers to be recognizable as such,
-        # i.e., they should contain a decimal point or an exponent.
-        # However, %g may print the number as an integer;
-        # in such cases, we append ".0" to the string.
-        for c in s:
-            if c in '.eE':
-                break
-        else:
-            s += '.0'
+        s = formatd(x, code, precision, DTSF_ADD_DOT_0)
     return space.wrap(s)
 
 def repr__Float(space, w_float):
-    return float2string(space, w_float, "%.17g")
+    return float2string(space, w_float, 'r', 0)
 
 def str__Float(space, w_float):
-    return float2string(space, w_float, "%.12g")
+    return float2string(space, w_float, 'g', DTSF_STR_PRECISION)
 
 def format__Float_ANY(space, w_float, w_spec):
     return newformat.run_formatter(space, w_spec, "format_float", w_float)

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	Sat Dec 11 00:34:40 2010
@@ -555,35 +555,60 @@
 
 # float -> string
 
-formatd_max_length = 120
+DTSF_STR_PRECISION = 12
 
-def formatd(fmt, x):
-    return fmt % (x,)
+DTSF_SIGN      = 0x1
+DTSF_ADD_DOT_0 = 0x2
+DTSF_ALT       = 0x4
 
-def formatd_overflow(alt, prec, kind, x):
-    # msvcrt does not support the %F format.
-    # OTOH %F and %f only differ for 'inf' or 'nan' numbers
-    # which are already handled elsewhere
-    if kind == 'F':
-        kind = 'f'
+DIST_FINITE   = 1
+DIST_NAN      = 2
+DIST_INFINITY = 3
 
-    if ((kind in 'gG' and formatd_max_length <= 10+prec) or
-        (kind in 'fF' and formatd_max_length <= 53+prec)):
-        raise OverflowError("formatted float is too long (precision too large?)")
-    if alt:
+formatd_ADD_DOT_0 = 0x1
+
+def formatd(x, code, precision, flags=0):
+    "NOT_RPYTHON"
+    if flags & DTSF_ALT:
         alt = '#'
     else:
         alt = ''
 
-    fmt = "%%%s.%d%s" % (alt, prec, kind)
+    if code == 'r':
+        fmt = "%r"
+    else:
+        fmt = "%%%s.%d%s" % (alt, precision, code)
+    s = fmt % (x,)
 
-    return formatd(fmt, x)
+    if flags & formatd_ADD_DOT_0:
+        # We want float numbers to be recognizable as such,
+        # i.e., they should contain a decimal point or an exponent.
+        # However, %g may print the number as an integer;
+        # in such cases, we append ".0" to the string.
+        for c in s:
+            if c in '.eE':
+                break
+        else:
+            s += '.0'
+    elif code == 'r' and s.endswith('.0'):
+        s = s[:-2]
 
-DTSF_ADD_DOT_0 = 1
+    return s
 
-DIST_FINITE = 1
-DIST_NAN = 2
-DIST_INFINITY = 3
+formatd_max_length = 120
+
+def formatd_overflow(x, kind, precision, flags=0):
+    # msvcrt does not support the %F format.
+    # OTOH %F and %f only differ for 'inf' or 'nan' numbers
+    # which are already handled elsewhere
+    if kind == 'F':
+        kind = 'f'
+
+    if ((kind in 'gG' and formatd_max_length < 10+precision) or
+        (kind in 'fF' and formatd_max_length < 53+precision)):
+        raise OverflowError("formatted float is too long (precision too large?)")
+
+    return formatd(x, kind, precision, flags)
 
 def double_to_string(value, tp, precision, flags):
     if isnan(value):
@@ -592,7 +617,7 @@
         special = DIST_INFINITY
     else:
         special = DIST_FINITE
-    result = formatd_overflow(False, precision, tp, value)
+    result = formatd_overflow(value, tp, precision)
     return result, special
 
 # the 'float' C type

Modified: pypy/branch/fast-forward/pypy/rlib/rmarshal.py
==============================================================================
--- pypy/branch/fast-forward/pypy/rlib/rmarshal.py	(original)
+++ pypy/branch/fast-forward/pypy/rlib/rmarshal.py	Sat Dec 11 00:34:40 2010
@@ -195,7 +195,7 @@
 
 def dump_float(buf, x):
     buf.append(TYPE_FLOAT)
-    s = formatd("%.17g", x)
+    s = formatd(x, 'g', 17)
     buf.append(chr(len(s)))
     buf += s
 add_dumper(annmodel.SomeFloat(), dump_float)

Modified: pypy/branch/fast-forward/pypy/rlib/test/test_rarithmetic.py
==============================================================================
--- pypy/branch/fast-forward/pypy/rlib/test/test_rarithmetic.py	(original)
+++ pypy/branch/fast-forward/pypy/rlib/test/test_rarithmetic.py	Sat Dec 11 00:34:40 2010
@@ -338,10 +338,18 @@
     def test_formatd(self):
         from pypy.rlib.rarithmetic import formatd
         def f(x):
-            return formatd('%.2f', x)
+            return formatd(x, 'f', 2, 0)
         res = self.ll_to_string(self.interpret(f, [10/3.0]))
         assert res == '3.33'
 
+    def test_formatd_repr(self):
+        py.test.skip('WIP: Need full dtoa support to run this test')
+        from pypy.rlib.rarithmetic import formatd
+        def f(x):
+            return formatd(x, 'r', 0, 0)
+        res = self.ll_to_string(self.interpret(f, [1.1]))
+        assert res == '1.1'
+
     def test_formatd_overflow(self):
         from pypy.translator.c.test.test_genc import compile
         from pypy.rlib.rarithmetic import formatd_overflow
@@ -349,7 +357,7 @@
         def func(x):
             # Test the %F format, which is not supported by
             # the Microsoft's msvcrt library.
-            return formatd_overflow(0, 4, 'F', x)
+            return formatd_overflow(x, 'F', 4)
 
         f = compile(func, [float])
         assert f(10/3.0) == '3.3333'

Modified: pypy/branch/fast-forward/pypy/rlib/test/test_rmarshal.py
==============================================================================
--- pypy/branch/fast-forward/pypy/rlib/test/test_rmarshal.py	(original)
+++ pypy/branch/fast-forward/pypy/rlib/test/test_rmarshal.py	Sat Dec 11 00:34:40 2010
@@ -147,7 +147,7 @@
     def f():
         result = ''
         for num, string, fval in unmarshaller(buf):
-            result += '%d=%s/%s;' % (num, string, formatd('%.17g', fval))
+            result += '%d=%s/%s;' % (num, string, formatd(fval, 'g', 17))
         return result
     res = interpret(f, [])
     res = ''.join(res.chars)

Modified: pypy/branch/fast-forward/pypy/rpython/lltypesystem/ll_str.py
==============================================================================
--- pypy/branch/fast-forward/pypy/rpython/lltypesystem/ll_str.py	(original)
+++ pypy/branch/fast-forward/pypy/rpython/lltypesystem/ll_str.py	Sat Dec 11 00:34:40 2010
@@ -126,5 +126,5 @@
 ll_int2oct._pure_function_ = True
 
 def ll_float_str(repr, f):
-    return llstr(formatd("%f", f))
+    return llstr(formatd(f, 'f', 6))
 ll_float_str._pure_function_ = True

Modified: pypy/branch/fast-forward/pypy/rpython/module/ll_strtod.py
==============================================================================
--- pypy/branch/fast-forward/pypy/rpython/module/ll_strtod.py	(original)
+++ pypy/branch/fast-forward/pypy/rpython/module/ll_strtod.py	Sat Dec 11 00:34:40 2010
@@ -24,17 +24,20 @@
     @registering(rarithmetic.formatd)
     def register_formatd(self):
         ll_strtod = self.llexternal('LL_strtod_formatd',
-                                    [rffi.CCHARP, rffi.DOUBLE], rffi.CCHARP,
+                                    [rffi.DOUBLE, rffi.CHAR, rffi.INT], rffi.CCHARP,
                                     sandboxsafe=True, threadsafe=False)
         
-        def llimpl(fmt, x):
-            res = ll_strtod(fmt, x)
+        def llimpl(x, code, precision, flags):
+            if code == 'r':
+                code = 'g'
+                precision = 17
+            res = ll_strtod(x, code, precision)
             return rffi.charp2str(res)
 
-        def oofakeimpl(fmt, x):
-            return ootype.oostring(rarithmetic.formatd(fmt._str, x), -1)
+        def oofakeimpl(x, code, precision, flags):
+            return ootype.oostring(rarithmetic.formatd(x, code, precision, flags), -1)
 
-        return extdef([str, float], str, 'll_strtod.ll_strtod_formatd',
+        return extdef([float, lltype.Char, int, int], str, 'll_strtod.ll_strtod_formatd',
                       llimpl=llimpl, oofakeimpl=oofakeimpl,
                       sandboxsafe=True)
 

Modified: pypy/branch/fast-forward/pypy/rpython/module/test/test_ll_strtod.py
==============================================================================
--- pypy/branch/fast-forward/pypy/rpython/module/test/test_ll_strtod.py	(original)
+++ pypy/branch/fast-forward/pypy/rpython/module/test/test_ll_strtod.py	Sat Dec 11 00:34:40 2010
@@ -6,7 +6,7 @@
 class BaseTestStrtod(BaseRtypingTest):    
     def test_formatd(self):
         def f(y):
-            return rarithmetic.formatd("%.2f", y)
+            return rarithmetic.formatd(y, 'f', 2)
 
         assert self.ll_to_string(self.interpret(f, [3.0])) == f(3.0)
 

Modified: pypy/branch/fast-forward/pypy/translator/c/src/ll_strtod.h
==============================================================================
--- pypy/branch/fast-forward/pypy/translator/c/src/ll_strtod.h	(original)
+++ pypy/branch/fast-forward/pypy/translator/c/src/ll_strtod.h	Sat Dec 11 00:34:40 2010
@@ -13,7 +13,7 @@
 
 double LL_strtod_parts_to_float(char *sign, char *beforept,
 				char *afterpt, char *exponent);
-char *LL_strtod_formatd(char *fmt, double x);
+char *LL_strtod_formatd(double x, char code, int precision);
 
 
 /* implementations */
@@ -86,9 +86,16 @@
 #define snprintf _snprintf
 #endif
 
-char* LL_strtod_formatd(char *fmt, double x) {
+char* LL_strtod_formatd(double x, char code, int precision) {
 	int res;
-	res = snprintf(buffer, buflen, fmt, x);
+	const char* fmt;
+        if (code == 'f') fmt = "%.*f";
+        else if (code == 'g') fmt = "%.*g";
+        else {
+            strcpy(buffer, "??.?"); /* should not occur */
+            return buffer;
+        }
+	res = snprintf(buffer, buflen, fmt, precision, x);
 	if (res <= 0 || res >= buflen) {
 		strcpy(buffer, "??.?"); /* should not occur */
 	} else {

Modified: pypy/branch/fast-forward/pypy/translator/c/test/test_extfunc.py
==============================================================================
--- pypy/branch/fast-forward/pypy/translator/c/test/test_extfunc.py	(original)
+++ pypy/branch/fast-forward/pypy/translator/c/test/test_extfunc.py	Sat Dec 11 00:34:40 2010
@@ -283,7 +283,7 @@
 def test_rarith_formatd():
     from pypy.rlib.rarithmetic import formatd
     def fn(x):
-        return formatd("%.2f", x)
+        return formatd(x, 'f', 2, 0)
 
     f = compile(fn, [float])
 

Modified: pypy/branch/fast-forward/pypy/translator/c/test/test_standalone.py
==============================================================================
--- pypy/branch/fast-forward/pypy/translator/c/test/test_standalone.py	(original)
+++ pypy/branch/fast-forward/pypy/translator/c/test/test_standalone.py	Sat Dec 11 00:34:40 2010
@@ -239,7 +239,7 @@
         fname2 = dirname.join("test_genc.c")
         fname2.write("""
         void f() {
-            LL_strtod_formatd("%5f", 12.3);
+            LL_strtod_formatd(12.3, 'f', 5);
         }""")
 
         files = [fname, fname2]



More information about the Pypy-commit mailing list