[pypy-commit] pypy improve-rbigint: More optimalization and a bug fix.

stian noreply at buildbot.pypy.org
Sat Jul 21 18:40:57 CEST 2012


Author: stian
Branch: improve-rbigint
Changeset: r56312:0b802b5f307e
Date: 2012-06-22 02:16 +0200
http://bitbucket.org/pypy/pypy/changeset/0b802b5f307e/

Log:	More optimalization and a bug fix.

	Revert _normalize() it causes a test to fail when _x_sub is special
	cased. Add special cases to _x_add, _x_sub Add a lqshift function
	for those more constant shifts. It's slightly quicker.

	Add operations benchmarked to 4% improvement in general.

diff --git a/pypy/rlib/rbigint.py b/pypy/rlib/rbigint.py
--- a/pypy/rlib/rbigint.py
+++ b/pypy/rlib/rbigint.py
@@ -561,6 +561,26 @@
         z._normalize()
         return z
 
+    def lqshift(self, int_other):
+        " A quicker one with much less checks, int_other is valid and for the most part constant."
+        if int_other == 0:
+            return self
+
+        oldsize = self.numdigits()
+        newsize = oldsize + 1
+
+        z = rbigint([NULLDIGIT] * newsize, self.sign)
+        accum = _widen_digit(0)
+
+        for i in range(oldsize):
+            accum += self.widedigit(i) << int_other
+            z.setdigit(i, accum)
+            accum >>= SHIFT
+            
+        z.setdigit(newsize - 1, accum)
+        z._normalize()
+        return z
+    
     def rshift(self, int_other, dont_invert=False):
         if int_other < 0:
             raise ValueError("negative shift count")
@@ -642,8 +662,8 @@
         assert i >= 1
         if i != self.numdigits():
             self._digits = self._digits[:i]
-            if self.numdigits() == 1 and self.digit(0) == 0:
-                self.sign = 0
+        if self.numdigits() == 1 and self.digit(0) == 0:
+            self.sign = 0
 
     def bit_length(self):
         i = self.numdigits()
@@ -743,7 +763,15 @@
 
 def _x_add(a, b):
     """ Add the absolute values of two bigint integers. """
+    
     size_a = a.numdigits()
+    
+    # Special casing. This is good, sometimes.
+    # The sweetspot is hard to find. But it's someplace between 60 and 70.
+    if size_a < 65 and a is b:
+        return a.lqshift(1)
+    
+    
     size_b = b.numdigits()
 
     # Ensure a is the larger of the two:
@@ -769,6 +797,11 @@
 
 def _x_sub(a, b):
     """ Subtract the absolute values of two integers. """
+    
+    # Special casing.
+    if a is b:
+        return rbigint([NULLDIGIT], 1)
+    
     size_a = a.numdigits()
     size_b = b.numdigits()
     sign = 1
@@ -870,11 +903,11 @@
         # Special case.
         digit = a.digit(0)
         if digit == 0:
-            return rbigint(a._digits[:], 1)
+            return rbigint([NULLDIGIT], 1)
         elif digit == 1:
             return rbigint(b._digits[:], 1)
         elif digit & (digit - 1) == 0:
-            return b.lshift(ptwotable[digit])
+            return b.lqshift(ptwotable[digit])
     
     z = rbigint([NULLDIGIT] * (size_a + size_b), 1)
     # gradeschool long mult


More information about the pypy-commit mailing list