Author: stian
Branch:
Changeset: r92789:d420391a020a
Date: 2017-10-18 17:48 +0200
http://bitbucket.org/pypy/pypy/changeset/d420391a020a/
Log: Add missing int_floordiv, int_divmod. Improves pidigits by about 5%
diff --git a/pypy/objspace/std/longobject.py b/pypy/objspace/std/longobject.py
--- a/pypy/objspace/std/longobject.py
+++ b/pypy/objspace/std/longobject.py
@@ -491,17 +491,18 @@
"long division or modulo by zero")
return newlong(space, z)
- def _floordiv(self, space, w_other):
+ def _int_floordiv(self, space, w_other):
try:
- z = self.num.floordiv(w_other.asbigint())
+ z = self.num.int_floordiv(w_other)
except ZeroDivisionError:
raise oefmt(space.w_ZeroDivisionError,
"long division or modulo by zero")
return newlong(space, z)
- descr_floordiv, descr_rfloordiv = _make_descr_binop(_floordiv)
+ descr_floordiv, descr_rfloordiv = _make_descr_binop(_floordiv,
_int_floordiv)
_div = func_with_new_name(_floordiv, '_div')
- descr_div, descr_rdiv = _make_descr_binop(_div)
+ _int_div = func_with_new_name(_int_floordiv, '_int_div')
+ descr_div, descr_rdiv = _make_descr_binop(_div, _int_div)
def _mod(self, space, w_other):
try:
@@ -527,7 +528,16 @@
raise oefmt(space.w_ZeroDivisionError,
"long division or modulo by zero")
return space.newtuple([newlong(space, div), newlong(space, mod)])
- descr_divmod, descr_rdivmod = _make_descr_binop(_divmod)
+
+ def _int_divmod(self, space, w_other):
+ try:
+ div, mod = self.num.int_divmod(w_other)
+ except ZeroDivisionError:
+ raise oefmt(space.w_ZeroDivisionError,
+ "long division or modulo by zero")
+ return space.newtuple([newlong(space, div), newlong(space, mod)])
+
+ descr_divmod, descr_rdivmod = _make_descr_binop(_divmod, _int_divmod)
def newlong(space, bigint):
diff --git a/pypy/objspace/std/test/test_longobject.py
b/pypy/objspace/std/test/test_longobject.py
--- a/pypy/objspace/std/test/test_longobject.py
+++ b/pypy/objspace/std/test/test_longobject.py
@@ -70,6 +70,17 @@
a = x // 10000000L
assert a == 3L
+ def test_int_floordiv(self):
+ x = 3000L
+ a = x // 1000
+ assert a == 3L
+
+ x = 3000L
+ a = x // -1000
+ assert a == -3L
+
+
+
def test_numerator_denominator(self):
assert (1L).numerator == 1L
assert (1L).denominator == 1L
@@ -208,6 +219,11 @@
check_division(x, y)
raises(ZeroDivisionError, "x // 0L")
+ def test_int_divmod(self):
+ q, r = divmod(100L, 11)
+ assert q == 9L
+ assert r == 1L
+
def test_format(self):
assert repr(12345678901234567890) == '12345678901234567890L'
assert str(12345678901234567890) == '12345678901234567890'
@@ -386,3 +402,4 @@
n = "a" * size
expected = (2 << (size * 4)) // 3
assert long(n, 16) == expected
+
diff --git a/rpython/rlib/rbigint.py b/rpython/rlib/rbigint.py
--- a/rpython/rlib/rbigint.py
+++ b/rpython/rlib/rbigint.py
@@ -781,7 +781,34 @@
def div(self, other):
return self.floordiv(other)
-
+
+ @jit.elidable
+ def int_floordiv(self, b):
+ if not int_in_valid_range(b):
+ # Fallback to long.
+ return self.mul(rbigint.fromint(b))
+
+ digit = abs(b)
+ assert digit > 0
+
+ if self.sign == 1 and b > 0:
+ if digit == 1:
+ return self
+ """elif digit & (digit - 1) == 0:
+ return self.rshift(ptwotable[digit])
+ """
+ div, mod = _divrem1(self, digit)
+
+ if mod != 0 and self.sign * (-1 if b < 0 else 1) == -1:
+ if div.sign == 0:
+ return ONENEGATIVERBIGINT
+ div = div.int_add(1)
+ div.sign = self.sign * (-1 if b < 0 else 1)
+ return div
+
+ def int_div(self, other):
+ return self.int_floordiv(other)
+
@jit.elidable
def mod(self, other):
if self.sign == 0:
@@ -888,6 +915,30 @@
return div, mod
@jit.elidable
+ def int_divmod(v, w):
+ """ Divmod with int """
+
+ if w == 0:
+ raise ZeroDivisionError("long division or modulo by zero")
+
+ wsign = (-1 if w < 0 else 1)
+ if not int_in_valid_range(w) or v.sign != wsign:
+ # Divrem1 doesn't deal with the sign difference. Instead of having
yet another copy,
+ # Just fallback.
+ return v.divmod(rbigint.fromint(w))
+
+ digit = abs(w)
+ assert digit > 0
+
+ div, mod = _divrem1(v, digit)
+ mod = rbigint.fromint(mod)
+
+ mod.sign = wsign
+ div.sign = v.sign * wsign
+
+ return div, mod
+
+ @jit.elidable
def pow(a, b, c=None):
negativeOutput = False # if x<0 return negative output
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit