[pypy-commit] pypy improve-rbigint: Reduce operations on mod and floordiv (without power of two) = more speed
stian
noreply at buildbot.pypy.org
Sat Jul 21 18:41:15 CEST 2012
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)
More information about the pypy-commit
mailing list