Author: Carl Friedrich Bolz <cfb...@gmx.de>
Branch: 
Changeset: r68714:84ab6e698cac
Date: 2014-01-17 13:23 +0100
http://bitbucket.org/pypy/pypy/changeset/84ab6e698cac/

Log:    issue892 testing

        integrate Mario Pernici's patch to speed up the naive multiplication
        algorithm Thanks!

diff --git a/rpython/rlib/rbigint.py b/rpython/rlib/rbigint.py
--- a/rpython/rlib/rbigint.py
+++ b/rpython/rlib/rbigint.py
@@ -1290,26 +1290,58 @@
         # Even if it's not power of two it can still be useful.
         return _muladd1(b, digit)
 
+    # a is not b
+    # use the following identity to reduce the number of operations
+    # a * b = a_0*b_0 + sum_{i=1}^n(a_0*b_i + a_1*b_{i-1}) + a_1*b_n
     z = rbigint([NULLDIGIT] * (size_a + size_b), 1)
-    # gradeschool long mult
     i = UDIGIT_TYPE(0)
-    while i < size_a:
-        carry = 0
-        f = a.widedigit(i)
+    size_a1 = UDIGIT_TYPE(size_a - 1)
+    size_b1 = UDIGIT_TYPE(size_b - 1)
+    while i < size_a1:
+        f0 = a.widedigit(i)
+        f1 = a.widedigit(i + 1)
         pz = i
+        carry = z.widedigit(pz) + b.widedigit(0) * f0
+        z.setdigit(pz, carry)
+        pz += 1
+        carry >>= SHIFT
+        j = UDIGIT_TYPE(0)
+        while j < size_b1:
+            # this operation does not overflow using 
+            # SHIFT = (LONG_BIT // 2) - 1 = B - 1; in fact before it
+            # carry and z.widedigit(pz) are less than 2**(B - 1);
+            # b.widedigit(j + 1) * f0 < (2**(B-1) - 1)**2; so
+            # carry + z.widedigit(pz) + b.widedigit(j + 1) * f0 +
+            # b.widedigit(j) * f1 < 2**(2*B - 1) - 2**B < 2**LONG)BIT - 1
+            carry += z.widedigit(pz) + b.widedigit(j + 1) * f0 + \
+                     b.widedigit(j) * f1
+            z.setdigit(pz, carry)
+            pz += 1
+            carry >>= SHIFT
+            j += 1
+        # carry < 2**(B + 1) - 2
+        carry += z.widedigit(pz) + b.widedigit(size_b1) * f1
+        z.setdigit(pz, carry)
+        pz += 1
+        carry >>= SHIFT
+        # carry < 4
+        if carry:
+            z.setdigit(pz, carry)
+        assert (carry >> SHIFT) == 0
+        i += 2
+    if size_a & 1:
+        pz = size_a1
+        f = a.widedigit(pz)
         pb = 0
+        carry = _widen_digit(0)
         while pb < size_b:
             carry += z.widedigit(pz) + b.widedigit(pb) * f
             pb += 1
             z.setdigit(pz, carry)
             pz += 1
             carry >>= SHIFT
-            assert carry <= MASK
         if carry:
-            assert pz >= 0
             z.setdigit(pz, z.widedigit(pz) + carry)
-        assert (carry >> SHIFT) == 0
-        i += 1
     z._normalize()
     return z
 
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to