[pypy-commit] pypy default: cpython issue1811: improve truediv accuracy on larger ints

pjenvey noreply at buildbot.pypy.org
Wed Mar 5 03:44:54 CET 2014


Author: Philip Jenvey <pjenvey at underboss.org>
Branch: 
Changeset: r69697:339ee58d7163
Date: 2014-03-04 18:42 -0800
http://bitbucket.org/pypy/pypy/changeset/339ee58d7163/

Log:	cpython issue1811: improve truediv accuracy on larger ints

diff --git a/pypy/objspace/std/intobject.py b/pypy/objspace/std/intobject.py
--- a/pypy/objspace/std/intobject.py
+++ b/pypy/objspace/std/intobject.py
@@ -13,6 +13,7 @@
 from rpython.rlib.rarithmetic import (
     LONG_BIT, is_valid_int, ovfcheck, r_longlong, r_uint, string_to_int)
 from rpython.rlib.rbigint import rbigint
+from rpython.rlib.rfloat import DBL_MANT_DIG
 from rpython.rlib.rstring import (
     InvalidBaseError, ParseStringError, ParseStringOverflowError)
 from rpython.tool.sourcetools import func_renamer, func_with_new_name
@@ -163,10 +164,18 @@
 
 
 def _truediv(space, x, y):
+    if not y:
+        raise oefmt(space.w_ZeroDivisionError, "division by zero")
+
+    if (DBL_MANT_DIG < LONG_BIT and
+        (r_uint(abs(x)) >> DBL_MANT_DIG or r_uint(abs(y)) >> DBL_MANT_DIG)):
+        # large x or y, use long arithmetic
+        raise OverflowError
+
+    # both ints can be exactly represented as doubles, do a
+    # floating-point division
     a = float(x)
     b = float(y)
-    if b == 0.0:
-        raise oefmt(space.w_ZeroDivisionError, "division by zero")
     return space.wrap(a / b)
 
 
@@ -589,7 +598,7 @@
 
     descr_floordiv, descr_rfloordiv = _make_descr_binop(_floordiv)
     descr_div, descr_rdiv = _make_descr_binop(_div)
-    descr_truediv, descr_rtruediv = _make_descr_binop(_truediv, ovf=False)
+    descr_truediv, descr_rtruediv = _make_descr_binop(_truediv)
     descr_mod, descr_rmod = _make_descr_binop(_mod)
     descr_divmod, descr_rdivmod = _make_descr_binop(
         _divmod, ovf2small=_divmod_ovf2small)
diff --git a/pypy/objspace/std/test/test_intobject.py b/pypy/objspace/std/test/test_intobject.py
--- a/pypy/objspace/std/test/test_intobject.py
+++ b/pypy/objspace/std/test/test_intobject.py
@@ -563,6 +563,25 @@
         base = MyInt(24)
         assert int('10', base) == 24
 
+    def test_truediv(self):
+        import operator
+        x = 1000000
+        a = x / 2
+        assert a == 500000
+        a = operator.truediv(x, 2)
+        assert a == 500000.0
+
+        x = 63050394783186940
+        a = x / 7
+        assert a == 9007199254740991
+        a = operator.truediv(x, 7)
+        assert a == 9007199254740991.0
+        exec("from __future__ import division; "
+             "a = x / 7; b = operator.truediv(x, 7)")
+        assert a == 9007199254740991.0
+        assert b == 9007199254740991.0
+
+
 class AppTestIntShortcut(AppTestInt):
     spaceconfig = {"objspace.std.intshortcut": True}
 


More information about the pypy-commit mailing list