[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