[pypy-commit] pypy improve-rbigint: Refactor the benchmark and make stuff unsigned
stian
noreply at buildbot.pypy.org
Sat Jul 21 18:41:32 CEST 2012
Author: stian
Branch: improve-rbigint
Changeset: r56343:ec8a20c4a39e
Date: 2012-07-03 23:53 +0200
http://bitbucket.org/pypy/pypy/changeset/ec8a20c4a39e/
Log: Refactor the benchmark and make stuff unsigned
diff --git a/pypy/rlib/rbigint.py b/pypy/rlib/rbigint.py
--- a/pypy/rlib/rbigint.py
+++ b/pypy/rlib/rbigint.py
@@ -41,8 +41,6 @@
MASK = BASE - 1
FLOAT_MULTIPLIER = float(1 << LONG_BIT) # Because it works.
-CACHE_INTS = 1024 # CPython do 256
-
# Debugging digit array access.
#
# False == no checking at all
@@ -66,9 +64,6 @@
USE_TOOMCOCK = False # WIP
TOOMCOOK_CUTOFF = 3 # Smallest possible cutoff is 3. Ideal is probably around 150+
-# Use N**2 division when number of digits are smaller than this.
-DIV_LIMIT = KARATSUBA_CUTOFF
-
# For exponentiation, use the binary left-to-right algorithm
# unless the exponent contains more than FIVEARY_CUTOFF digits.
# In that case, do 5 bits at a time. The potential drawback is that
@@ -709,7 +704,7 @@
i += 1
j += 1
- z.setdigit(newsize - 1, accum)
+ z.setdigit(abs(newsize - 1), accum)
z._normalize()
return z
@@ -809,18 +804,18 @@
return l * self.sign
def _normalize(self):
- i = self.numdigits()
+ i = _load_unsigned_digit(self.numdigits())
if i == 0:
self.sign = 0
self._digits = [NULLDIGIT]
return
- while i > 1 and self.digit(i - 1) == 0:
+ while i > 1 and self.udigit(i - 1) == 0:
i -= 1
assert i >= 1
if i != self.numdigits():
self._digits = self._digits[:i]
- if self.numdigits() == 1 and self.digit(0) == 0:
+ if self.numdigits() == 1 and self.udigit(0) == 0:
self.sign = 0
def bit_length(self):
@@ -931,19 +926,22 @@
a, b = b, a
size_a, size_b = size_b, size_a
z = rbigint([NULLDIGIT] * (size_a + 1), 1)
- i = 0
+ i = _load_unsigned_digit(0)
carry = UDIGIT_TYPE(0)
while i < size_b:
carry += a.udigit(i) + b.udigit(i)
z.setdigit(i, carry)
carry >>= SHIFT
i += 1
- while i < size_a:
+ if i < size_a:
carry += a.udigit(i)
z.setdigit(i, carry)
- carry >>= SHIFT
i += 1
- z.setdigit(i, carry)
+ while i < size_a:
+ z.setdigit(i, a.udigit(i))
+ i += 1
+ else:
+ z.setdigit(i, carry)
z._normalize()
return z
@@ -977,7 +975,7 @@
z = rbigint([NULLDIGIT] * size_a, sign)
borrow = UDIGIT_TYPE(0)
- i = 0
+ i = _load_unsigned_digit(0)
while i < size_b:
# The following assumes unsigned arithmetic
# works modulo 2**N for some N>SHIFT.
@@ -986,13 +984,15 @@
borrow >>= SHIFT
borrow &= 1 # Keep only one sign bit
i += 1
- while i < size_a:
+ if i < size_a:
borrow = a.udigit(i) - borrow
z.setdigit(i, borrow)
- borrow >>= SHIFT
- borrow &= 1 # Keep only one sign bit
i += 1
- assert borrow == 0
+ assert borrow >> 63 == 0
+
+ while i < size_a:
+ z.setdigit(i, a.udigit(i))
+ i += 1
z._normalize()
return z
@@ -1018,7 +1018,7 @@
# via exploiting that each entry in the multiplication
# pyramid appears twice (except for the size_a squares).
z = rbigint([NULLDIGIT] * (size_a + size_b), 1)
- i = 0
+ i = _load_unsigned_digit(0)
while i < size_a:
f = a.widedigit(i)
pz = i << 1
@@ -1058,7 +1058,7 @@
z = rbigint([NULLDIGIT] * (size_a + size_b), 1)
# gradeschool long mult
- i = 0
+ i = _load_unsigned_digit(0)
while i < size_a:
carry = 0
f = a.widedigit(i)
@@ -1415,7 +1415,7 @@
carry = r_uint(0)
assert m >= n
- i = xofs
+ i = _load_unsigned_digit(xofs)
iend = xofs + n
while i < iend:
carry += x.udigit(i) + y.udigit(i-xofs)
@@ -1442,7 +1442,7 @@
borrow = r_uint(0)
assert m >= n
- i = xofs
+ i = _load_unsigned_digit(xofs)
iend = xofs + n
while i < iend:
borrow = x.udigit(i) - y.udigit(i-xofs) - borrow
@@ -1512,7 +1512,7 @@
""" Unsigned bigint division with remainder -- the algorithm """
size_w = w1.numdigits()
- d = (UDIGIT_TYPE(MASK)+1) // (w1.udigit(size_w-1) + 1)
+ d = (UDIGIT_TYPE(MASK)+1) // (w1.udigit(abs(size_w-1)) + 1)
assert d <= MASK # because the first digit of w1 is not zero
d = longlongmask(d)
v = _muladd1(v1, d)
@@ -1535,9 +1535,9 @@
size_a = size_v - size_w + 1
a = rbigint([NULLDIGIT] * size_a, 1)
- wm1 = w.widedigit(size_w-1)
- wm2 = w.widedigit(size_w-2)
- j = size_v
+ wm1 = w.widedigit(abs(size_w-1))
+ wm2 = w.widedigit(abs(size_w-2))
+ j = _load_unsigned_digit(size_v)
k = size_a - 1
while k >= 0:
if j >= size_v:
@@ -1690,8 +1690,8 @@
def _divrem(a, b):
""" Long division with remainder, top-level routine """
- size_a = a.numdigits()
- size_b = b.numdigits()
+ size_a = _load_unsigned_digit(a.numdigits())
+ size_b = _load_unsigned_digit(b.numdigits())
if b.sign == 0:
raise ZeroDivisionError("long division or modulo by zero")
diff --git a/pypy/translator/c/src/int.h b/pypy/translator/c/src/int.h
--- a/pypy/translator/c/src/int.h
+++ b/pypy/translator/c/src/int.h
@@ -98,7 +98,7 @@
r = Py_ARITHMETIC_RIGHT_SHIFT(PY_LONG_LONG,x, (y))
#define OP_ULLONG_RSHIFT(x,y,r) CHECK_SHIFT_RANGE(y, PYPY_LONGLONG_BIT); \
r = (x) >> (y)
-#define OP_LLLONG_RSHIFT(x,y,r) r = Py_ARITHMETIC_RIGHT_SHIFT(PY_LONG_LONG_LONG,x, (y))
+#define OP_LLLONG_RSHIFT(x,y,r) r = x >> y
#define OP_INT_LSHIFT(x,y,r) CHECK_SHIFT_RANGE(y, PYPY_LONG_BIT); \
r = (x) << (y)
@@ -106,7 +106,7 @@
r = (x) << (y)
#define OP_LLONG_LSHIFT(x,y,r) CHECK_SHIFT_RANGE(y, PYPY_LONGLONG_BIT); \
r = (x) << (y)
-#define OP_LLLONG_LSHIFT(x,y,r) r = (x) << (y)
+#define OP_LLLONG_LSHIFT(x,y,r) r = x << y
#define OP_ULLONG_LSHIFT(x,y,r) CHECK_SHIFT_RANGE(y, PYPY_LONGLONG_BIT); \
r = (x) << (y)
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
@@ -89,16 +89,18 @@
t = time()
num = rbigint.fromint(100000000)
+ V2 = rbigint.fromint(2)
for n in xrange(80000000):
- rbigint.floordiv(num, rbigint.fromint(2))
+ rbigint.floordiv(num, V2)
print time() - t
t = time()
num = rbigint.fromint(100000000)
+ V3 = rbigint.fromint(3)
for n in xrange(80000000):
- rbigint.floordiv(num, rbigint.fromint(3))
+ rbigint.floordiv(num, V3)
print time() - t
@@ -106,7 +108,7 @@
t = time()
num = rbigint.fromint(10000000)
for n in xrange(10000):
- rbigint.pow(rbigint.fromint(2), num)
+ rbigint.pow(V2, num)
print time() - t
@@ -114,15 +116,17 @@
t = time()
num = rbigint.fromint(100000000)
for n in xrange(31):
- rbigint.pow(rbigint.pow(rbigint.fromint(2), rbigint.fromint(n)), num)
+ rbigint.pow(rbigint.pow(V2, rbigint.fromint(n)), num)
print time() - t
t = time()
num = rbigint.pow(rbigint.fromint(10000), rbigint.fromint(2 ** 8))
+ P10_4 = rbigint.fromint(10**4)
+ V100 = rbigint.fromint(100)
for n in xrange(60000):
- rbigint.pow(rbigint.fromint(10**4), num, rbigint.fromint(100))
+ rbigint.pow(P10_4, num, V100)
print time() - t
@@ -138,15 +142,16 @@
t = time()
for n in xrange(10000):
- rbigint.pow(rbigint.fromint(n), rbigint.fromint(10**4))
+ rbigint.pow(rbigint.fromint(n), P10_4)
print time() - t
t = time()
+ V1024 = rbigint.fromint(1024)
for n in xrange(100000):
- rbigint.pow(rbigint.fromint(1024), rbigint.fromint(1024))
+ rbigint.pow(V1024, V1024)
print time() - t
@@ -154,8 +159,9 @@
t = time()
v = rbigint.fromint(2)
+ P62 = rbigint.fromint(2**62)
for n in xrange(50000):
- v = v.mul(rbigint.fromint(2**62))
+ v = v.mul(P62)
print time() - t
More information about the pypy-commit
mailing list