Author: stian Branch: improve-rbigint Changeset: r56328:1d2cb7e2302d Date: 2012-06-24 23:38 +0200 http://bitbucket.org/pypy/pypy/changeset/1d2cb7e2302d/
Log: Reduce operations on mod and floordiv (without power of two) = more speed diff --git a/pypy/rlib/rbigint.py b/pypy/rlib/rbigint.py --- a/pypy/rlib/rbigint.py +++ b/pypy/rlib/rbigint.py @@ -161,8 +161,8 @@ # This function is marked as pure, so you must not call it and # then modify the result. if b: - return rbigint([ONEDIGIT], 1) - return rbigint() + return ONERBIGINT + return NULLRBIGINT @staticmethod def fromlong(l): @@ -421,14 +421,18 @@ div = self.rshift(ptwotable[digit]) return div - div, mod = self.divmod(other) + div, mod = _divrem(self, other) + if mod.sign * other.sign == -1: + div = div.sub(ONERBIGINT) return div def div(self, other): return self.floordiv(other) def mod(self, other): - div, mod = self.divmod(other) + div, mod = _divrem(self, other) + if mod.sign * other.sign == -1: + mod = mod.add(other) return mod def divmod(v, w): @@ -451,7 +455,7 @@ div, mod = _divrem(v, w) if mod.sign * w.sign == -1: mod = mod.add(w) - div = div.sub(rbigint([_store_digit(1)], 1)) + div = div.sub(ONERBIGINT) return div, mod def pow(a, b, c=None): @@ -498,13 +502,13 @@ elif size_b == 1 and a.sign == 1: digit = b.digit(0) if digit == 0: - return rbigint([ONEDIGIT], 1) + return ONERBIGINT elif digit == 1: return a elif a.numdigits() == 1: adigit = a.digit(0) if adigit == 1: - return rbigint([ONEDIGIT], 1) + return ONERBIGINT elif adigit & (adigit - 1) == 0: return a.lshift(((digit-1)*(ptwotable[adigit]-1)) + digit-1) @@ -745,6 +749,9 @@ return "<rbigint digits=%s, sign=%s, %s>" % (self._digits, self.sign, self.str()) +ONERBIGINT = rbigint([ONEDIGIT], 1) +NULLRBIGINT = rbigint() + #_________________________________________________________________ # Helper Functions @@ -866,7 +873,7 @@ while i >= 0 and a.digit(i) == b.digit(i): i -= 1 if i < 0: - return rbigint() + return NULLRBIGINT if a.digit(i) < b.digit(i): sign = -1 a, b = b, a @@ -1464,9 +1471,7 @@ (size_a == size_b and a.digit(size_a-1) < b.digit(size_b-1))): # |a| < |b| - z = rbigint() # result is 0 - rem = a - return z, rem + return NULLRBIGINT, a# result is 0 if size_b == 1: z, urem = _divrem1(a, b.digit(0)) rem = rbigint([_store_digit(urem)], int(urem != 0)) diff --git a/pypy/translator/goal/targetbigintbenchmark.py b/pypy/translator/goal/targetbigintbenchmark.py --- a/pypy/translator/goal/targetbigintbenchmark.py +++ b/pypy/translator/goal/targetbigintbenchmark.py @@ -11,6 +11,7 @@ A cutout with some benchmarks. Pypy default: 5.147583 + 5.139127 484.5688 334.611903 8.637287 @@ -22,16 +23,17 @@ 6.647562 Pypy with improvements: - 2.307890 - 9.451896 - 1.122038 - 5.787821 - 9.937016 - 14.927304 - 0.016683 - 12.018289 - 14.261727 - 6.434917 + 2.291724 + 4.616600 + 9.538857 + 1.102726 + 4.820049 + 9.899771 + 14.733251 + 0.016657 + 11.992919 + 14.144412 + 6.404446 """ @@ -44,6 +46,14 @@ print time() - t t = time() + num = rbigint.fromint(100000000) + for n in xrange(80000000): + rbigint.floordiv(num, rbigint.fromint(3)) + + + print time() - t + + t = time() num = rbigint.fromint(10000000) for n in xrange(10000): rbigint.pow(rbigint.fromint(2), num) _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit