[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