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 pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit