[pypy-svn] pypy jit-longlong: Merge default.

arigo commits-noreply at bitbucket.org
Wed Jan 26 15:29:55 CET 2011


Author: Armin Rigo <arigo at tunes.org>
Branch: jit-longlong
Changeset: r41353:0bb5e9dc6629
Date: 2011-01-26 15:27 +0100
http://bitbucket.org/pypy/pypy/changeset/0bb5e9dc6629/

Log:	Merge default.

diff --git a/pypy/jit/metainterp/history.py b/pypy/jit/metainterp/history.py
--- a/pypy/jit/metainterp/history.py
+++ b/pypy/jit/metainterp/history.py
@@ -29,7 +29,8 @@
         if TYPE in (lltype.Float, lltype.SingleFloat):
             raise NotImplementedError("type %s not supported" % TYPE)
         # XXX fix this for oo...
-        if rffi.sizeof(TYPE) > rffi.sizeof(lltype.Signed):
+        if (TYPE != llmemory.Address and
+            rffi.sizeof(TYPE) > rffi.sizeof(lltype.Signed)):
             if supports_longlong:
                 assert rffi.sizeof(TYPE) == 8
                 return 'float'

diff --git a/pypy/rlib/test/test_rarithmetic.py b/pypy/rlib/test/test_rarithmetic.py
--- a/pypy/rlib/test/test_rarithmetic.py
+++ b/pypy/rlib/test/test_rarithmetic.py
@@ -343,21 +343,26 @@
         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):
+    def test_formatd_huge(self):
+        def f(x):
+            return formatd(x, 'f', 1234, 0)
+        res = self.ll_to_string(self.interpret(f, [1.0]))
+        assert res == '1.' + 1234 * '0'
+
+    def test_formatd_F(self):
         from pypy.translator.c.test.test_genc import compile
-        from pypy.rlib.rarithmetic import formatd_overflow
+        from pypy.rlib.rarithmetic import formatd
 
         def func(x):
             # Test the %F format, which is not supported by
             # the Microsoft's msvcrt library.
-            return formatd_overflow(x, 'F', 4)
+            return formatd(x, 'F', 4)
 
         f = compile(func, [float])
         assert f(10/3.0) == '3.3333'
@@ -377,6 +382,18 @@
         res = self.interpret(f, [1])
         assert res == 1e-100
 
+    def test_string_to_float(self):
+        from pypy.rlib.rarithmetic import rstring_to_float
+        def func(x):
+            if x == 0:
+                s = '1e23'
+            else:
+                s = '-1e23'
+            return rstring_to_float(s)
+
+        assert self.interpret(func, [0]) == 1e23
+        assert self.interpret(func, [1]) == -1e23
+
     def test_compare_singlefloat_crashes(self):
         from pypy.rlib.rarithmetic import r_singlefloat
         from pypy.rpython.error import MissingRTypeOperation
@@ -391,7 +408,17 @@
     pass
 
 class TestOOtype(BaseTestRarithmetic, OORtypeMixin):
-    pass
+    def test_formatd(self):
+        skip('formatd is broken on ootype')
+
+    def test_formatd_repr(self):
+        skip('formatd is broken on ootype')
+
+    def test_formatd_huge(self):
+        skip('formatd is broken on ootype')
+
+    def test_string_to_float(self):
+        skip('string_to_float is broken on ootype')
 
 def test_isinf():
     assert isinf(INFINITY)

diff --git a/pypy/rlib/rarithmetic.py b/pypy/rlib/rarithmetic.py
--- a/pypy/rlib/rarithmetic.py
+++ b/pypy/rlib/rarithmetic.py
@@ -37,6 +37,8 @@
 from pypy.rpython import extregistry
 from pypy.rlib import objectmodel
 
+USE_SHORT_FLOAT_REPR = True # XXX make it a translation option?
+
 # set up of machine internals
 _bits = 0
 _itest = 1
@@ -549,8 +551,19 @@
     r_int64 = int
 
 
+def rstring_to_float(s):
+    if USE_SHORT_FLOAT_REPR:
+        from pypy.rlib.rdtoa import strtod
+        return strtod(s)
+
+    sign, before_point, after_point, exponent = break_up_float(s)
+
+    if not before_point and not after_point:
+        raise ValueError
+
+    return parts_to_float(sign, before_point, after_point, exponent)
+
 # float as string  -> sign, beforept, afterpt, exponent
-
 def break_up_float(s):
     i = 0
 
@@ -605,6 +618,7 @@
 # string -> float helper
 
 def parts_to_float(sign, beforept, afterpt, exponent):
+    "NOT_RPYTHON"
     if not exponent:
         exponent = '0'
     return float("%s%s.%se%s" % (sign, beforept, afterpt, exponent))
@@ -649,23 +663,13 @@
         s = s[:-2]
 
     return s
+
 def formatd(x, code, precision, flags=0):
-    return _formatd(x, code, precision, flags)
-
-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)
+    if USE_SHORT_FLOAT_REPR:
+        from pypy.rlib.rdtoa import dtoa_formatd
+        return dtoa_formatd(x, code, precision, flags)
+    else:
+        return _formatd(x, code, precision, flags)
 
 def double_to_string(value, tp, precision, flags):
     if isnan(value):
@@ -674,7 +678,7 @@
         special = DIST_INFINITY
     else:
         special = DIST_FINITE
-    result = formatd_overflow(value, tp, precision)
+    result = formatd(value, tp, precision, flags)
     return result, special
 
 # the 'float' C type

diff --git a/pypy/objspace/std/strutil.py b/pypy/objspace/std/strutil.py
--- a/pypy/objspace/std/strutil.py
+++ b/pypy/objspace/std/strutil.py
@@ -2,8 +2,7 @@
 Pure Python implementation of string utilities.
 """
 
-from pypy.rlib.rarithmetic import ovfcheck, break_up_float, parts_to_float,\
-     INFINITY, NAN
+from pypy.rlib.rarithmetic import ovfcheck, rstring_to_float, INFINITY, NAN
 from pypy.rlib.rbigint import rbigint, parse_digit_string
 from pypy.interpreter.error import OperationError
 import math
@@ -179,93 +178,7 @@
     elif low == "nan" or low == "-nan" or low == "+nan":
         return NAN
 
-    # 1) parse the string into pieces.
     try:
-        sign, before_point, after_point, exponent = break_up_float(s)
+        return rstring_to_float(s)
     except ValueError:
         raise ParseStringError("invalid literal for float()")
-    
-    digits = before_point + after_point
-    if not digits:
-        raise ParseStringError("invalid literal for float()")
-
-    # 2) pre-calculate digit exponent dexp.
-    dexp = len(before_point)
-
-    # 3) truncate and adjust dexp.
-    p = 0
-    plim = dexp + len(after_point)
-    while p < plim and digits[p] == '0':
-        p += 1
-        dexp -= 1
-    digits = digits[p : p + MANTISSA_DIGITS]
-    p = len(digits) - 1
-    while p >= 0 and digits[p] == '0':
-        p -= 1
-    dexp -= p + 1
-    p += 1
-    assert p >= 0
-    digits = digits[:p]
-    if len(digits) == 0:
-        digits = '0'
-
-    # 4) compute the exponent and truncate to +-400
-    if not exponent:
-        exponent = '0'
-    long_exponent = rbigint.fromdecimalstr(exponent)
-    long_exponent = long_exponent.add(rbigint.fromint(dexp))
-    try:
-        e = long_exponent.toint()
-    except OverflowError:
-        # XXX poking at internals
-        e = long_exponent.sign * 400
-    else:
-        if e >= 400:
-            e = 400
-        elif e <= -400:
-            e = -400
-
-    # 5) compute the value using long math and proper rounding.
-    b_digits = rbigint.fromdecimalstr(digits)
-    b_10 = rbigint.fromint(10)
-    b_1 = rbigint.fromint(1)
-    if e >= 0:
-        bits = 0
-        b_power_of_ten = b_10.pow(rbigint.fromint(e))
-        b_mantissa = b_digits.mul(b_power_of_ten)
-    else:
-        # compute a sufficiently large scale
-        prec = MANTISSA_DIGITS * 2 + 22 # 128, maybe
-        bits = - (int(math.ceil(-e / math.log10(2.0) - 1e-10)) + prec)
-        b_scale = b_1.lshift(-bits)
-        b_power_of_ten = b_10.pow(rbigint.fromint(-e))
-        b_mantissa = b_digits.mul(b_scale).div(b_power_of_ten)
-
-    # we now have a fairly large mantissa.
-    # Shift it and round the last bit.
-
-    # first estimate the bits and do a big shift
-    mbits = b_mantissa._count_bits()
-    needed = MANTISSA_BITS
-    if mbits > needed:
-        if mbits > needed+1:
-            shifted = mbits - (needed+1)
-            b_mantissa = b_mantissa.rshift(shifted)
-            bits += shifted
-        # do the rounding
-        bits += 1
-        round = b_mantissa.is_odd()
-        b_mantissa = b_mantissa.rshift(1).add(rbigint.fromint(round))
-
-    try:
-        r = math.ldexp(b_mantissa.tofloat(), bits)
-        # XXX I guess we do not check for overflow in ldexp as we agreed to!
-        if r == 2*r and r != 0.0:
-            raise OverflowError
-    except OverflowError:
-        r = INFINITY
-
-    if sign == '-':
-        r = -r
-
-    return r

diff --git a/pypy/jit/codewriter/test/test_longlong.py b/pypy/jit/codewriter/test/test_longlong.py
--- a/pypy/jit/codewriter/test/test_longlong.py
+++ b/pypy/jit/codewriter/test/test_longlong.py
@@ -16,7 +16,7 @@
 class FakeBuiltinCallControl:
     def guess_call_kind(self, op):
         return 'builtin'
-    def getcalldescr(self, op, oopspecindex=None):
+    def getcalldescr(self, op, oopspecindex=None, extraeffect=None):
         assert oopspecindex is not None    # in this test
         return 'calldescr-%d' % oopspecindex
     def calldescr_canraise(self, calldescr):

diff --git a/pypy/jit/codewriter/jtransform.py b/pypy/jit/codewriter/jtransform.py
--- a/pypy/jit/codewriter/jtransform.py
+++ b/pypy/jit/codewriter/jtransform.py
@@ -1275,9 +1275,10 @@
     # Strings and Unicodes.
 
     def _handle_oopspec_call(self, op, args, oopspecindex, extraeffect=None):
-        calldescr = self.callcontrol.getcalldescr(op, oopspecindex)
+        calldescr = self.callcontrol.getcalldescr(op, oopspecindex,
+                                                  extraeffect)
         if extraeffect is not None:
-            calldescr.get_extra_info().extraeffect = extraeffect
+            assert calldescr.get_extra_info().extraeffect == extraeffect
         if isinstance(op.args[0].value, str):
             pass  # for tests only
         else:


diff --git a/pypy/translator/c/test/test_dtoa.py b/pypy/translator/c/test/test_dtoa.py
deleted file mode 100644
--- a/pypy/translator/c/test/test_dtoa.py
+++ /dev/null
@@ -1,92 +0,0 @@
-from __future__ import with_statement
-from pypy.translator.tool.cbuild import ExternalCompilationInfo
-from pypy.tool.autopath import pypydir
-from pypy.rpython.lltypesystem import lltype, rffi
-from pypy.rlib.rstring import StringBuilder
-import py
-
-includes = []
-libraries = []
-
-cdir = py.path.local(pypydir) / 'translator' / 'c'
-files = [cdir / 'src' / 'dtoa.c']
-include_dirs = [cdir]
-
-eci = ExternalCompilationInfo(
-    include_dirs = include_dirs,
-    libraries = libraries,
-    separate_module_files = files,
-    separate_module_sources = ['''
-        #include <stdlib.h>
-        #include <assert.h>
-        #define WITH_PYMALLOC
-        #include "src/obmalloc.c"
-    '''],
-    export_symbols = ['_Py_dg_strtod',
-                      '_Py_dg_dtoa',
-                      '_Py_dg_freedtoa',
-                      ],
-)
-
-dg_strtod = rffi.llexternal(
-    '_Py_dg_strtod', [rffi.CCHARP, rffi.CCHARPP], rffi.DOUBLE,
-    compilation_info=eci)
-
-dg_dtoa = rffi.llexternal(
-    '_Py_dg_dtoa', [rffi.DOUBLE, rffi.INT, rffi.INT,
-                    rffi.INTP, rffi.INTP, rffi.CCHARPP], rffi.CCHARP,
-    compilation_info=eci)
-
-dg_freedtoa = rffi.llexternal(
-    '_Py_dg_freedtoa', [rffi.CCHARP], lltype.Void,
-    compilation_info=eci)
-
-def strtod(input):
-    with lltype.scoped_alloc(rffi.CCHARPP.TO, 1) as end_ptr:
-        with rffi.scoped_str2charp(input) as ll_input:
-            result = dg_strtod(ll_input, end_ptr)
-            if end_ptr[0] and ord(end_ptr[0][0]):
-                offset = (rffi.cast(rffi.LONG, end_ptr[0]) -
-                          rffi.cast(rffi.LONG, ll_input))
-                raise ValueError("invalid input at position %d" % (offset,))
-            return result
-
-def dtoa(value, mode=0, precision=0):
-    builder = StringBuilder(20)
-    with lltype.scoped_alloc(rffi.INTP.TO, 1) as decpt_ptr:
-        with lltype.scoped_alloc(rffi.INTP.TO, 1) as sign_ptr:
-            with lltype.scoped_alloc(rffi.CCHARPP.TO, 1) as end_ptr:
-                output_ptr = dg_dtoa(value, mode, precision,
-                                     decpt_ptr, sign_ptr, end_ptr)
-                try:
-                    buflen = (rffi.cast(rffi.LONG, end_ptr[0]) -
-                              rffi.cast(rffi.LONG, output_ptr))
-                    intpart = rffi.cast(lltype.Signed, decpt_ptr[0])
-                    if intpart <= buflen:
-                        builder.append(rffi.charpsize2str(output_ptr, intpart))
-                    else:
-                        builder.append(rffi.charpsize2str(output_ptr, buflen))
-                        while buflen < intpart:
-                            builder.append('0')
-                            intpart -= 1
-                    builder.append('.')
-                    fracpart = buflen - intpart
-                    if fracpart > 0:
-                        ptr = rffi.ptradd(output_ptr, intpart)
-                        builder.append(rffi.charpsize2str(ptr, fracpart))
-                finally:
-                    dg_freedtoa(output_ptr)
-    return builder.build()
-
-def test_strtod():
-    assert strtod("12345") == 12345.0
-    assert strtod("1.1") == 1.1
-    assert strtod("3.47") == 3.47
-    raises(ValueError, strtod, "123A")
-
-def test_dtoa():
-    assert dtoa(3.47) == "3.47"
-    assert dtoa(1.1) == "1.1"
-    assert dtoa(12.3577) == "12.3577"
-    assert dtoa(10) == "10."
-    assert dtoa(1e100) == "1" + "0" * 100 + "."


More information about the Pypy-commit mailing list