[pypy-commit] pypy improve-rbigint: Make a new normalize method that skips one check and post results 1.3s improvement, mostly on shifts

stian noreply at buildbot.pypy.org
Sat Jul 21 18:41:39 CEST 2012


Author: stian
Branch: improve-rbigint
Changeset: r56350:eaaa4adb6819
Date: 2012-07-06 06:06 +0200
http://bitbucket.org/pypy/pypy/changeset/eaaa4adb6819/

Log:	Make a new normalize method that skips one check and post results
	1.3s improvement, mostly on shifts

diff --git a/pypy/rlib/rbigint.py b/pypy/rlib/rbigint.py
--- a/pypy/rlib/rbigint.py
+++ b/pypy/rlib/rbigint.py
@@ -717,7 +717,7 @@
             
         z.setdigit(oldsize, accum)
 
-        z._normalize()
+        z._positivenormalize()
         return z
     lshift._always_inline_ = True # It's so fast that it's always benefitial.
     
@@ -737,7 +737,7 @@
             accum >>= SHIFT
             
         z.setdigit(oldsize, accum)
-        z._normalize()
+        z._positivenormalize()
         return z
     lqshift._always_inline_ = True # It's so fast that it's always benefitial.
     
@@ -772,7 +772,7 @@
             z.setdigit(i, newdigit)
             i += 1
             j += 1
-        z._normalize()
+        z._positivenormalize()
         return z
     rshift._always_inline_ = True # It's so fast that it's always benefitial.
     
@@ -818,20 +818,34 @@
         return l * self.sign
 
     def _normalize(self):
-        i = _load_unsigned_digit(self.numdigits())
+        i = c = self.numdigits()
         if i == 0:
             self.sign = 0
             self._digits = [NULLDIGIT]
             return
         
-        while i > 1 and self.udigit(i - 1) == 0:
+        while i > 1 and self.digit(i - 1) == 0:
             i -= 1
-        assert i >= 1
-        if i != self.numdigits():
+        assert i > 0
+        if i != c:
             self._digits = self._digits[:i]
-        if self.numdigits() == 1 and self.udigit(0) == 0:
+        if self.numdigits() == 1 and self.digit(0) == 0:
             self.sign = 0
+            
     _normalize._always_inline_ = True
+    
+    def _positivenormalize(self):
+        """ This function assumes numdigits > 0. Good for shifts and such """
+        i = c = self.numdigits()
+        while i > 1 and self.digit(i - 1) == 0:
+            i -= 1
+        assert i > 0
+        if i != c:
+            self._digits = self._digits[:i]
+        if self.numdigits() == 1 and self.digit(0) == 0:
+            self.sign = 0
+    _positivenormalize._always_inline_ = True
+    
     def bit_length(self):
         i = self.numdigits()
         if i == 1 and self.digit(0) == 0:
@@ -953,7 +967,7 @@
         carry >>= SHIFT
         i += 1
     z.setdigit(i, carry)
-    z._normalize()
+    z._positivenormalize()
     return z
 
 def _x_sub(a, b):
@@ -1059,7 +1073,7 @@
                 z.setdigit(pz, z.widedigit(pz) + carry)
             assert (carry >> SHIFT) == 0
             i += 1
-        z._normalize()
+        z._positivenormalize()
         return z
     
     elif digit and digit & (digit - 1) == 0:
@@ -1084,7 +1098,7 @@
             z.setdigit(pz, z.widedigit(pz) + carry)
         assert (carry >> SHIFT) == 0
         i += 1
-    z._normalize()
+    z._positivenormalize()
     return z
 
 
@@ -1190,8 +1204,8 @@
 
     lo = rbigint(n._digits[:size_lo], 1)
     hi = rbigint(n._digits[size_lo:], 1)
-    lo._normalize()
-    hi._normalize()
+    lo._positivenormalize()
+    hi._positivenormalize()
     return hi, lo
 
 def _k_mul(a, b):
@@ -1285,7 +1299,7 @@
     # See the (*) comment after this function.
     _v_iadd(ret, shift, i, t3, t3.numdigits())
 
-    ret._normalize()
+    ret._positivenormalize()
     return ret
 
 """ (*) Why adding t3 can't "run out of room" above.
@@ -1379,7 +1393,7 @@
         bsize -= nbtouse
         nbdone += nbtouse
 
-    ret._normalize()
+    ret._positivenormalize()
     return ret
 
 def _inplace_divrem1(pout, pin, n, size=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
@@ -29,21 +29,21 @@
         Sum: 901.7231250000001
         
         Pypy with improvements:
-        2.867820
-        2.523047
-        3.848003
-        1.682992
-        4.099669
-        9.233212
-        1.622695
-        4.026895
-        4.708891
-        6.542558
-        0.039864
-        3.508814
-        8.225711
-        5.009382
-        Sum:  57.939553
+        2.892875
+        2.263349
+        2.425365
+        1.579653
+        4.005316
+        9.579625
+        1.774452
+        4.021076
+        4.844961
+        6.432300
+        0.038368
+        3.624531
+        8.156838
+        4.990594
+        Sum:  56.629303
 
         A pure python form of those tests where also run
         Improved pypy           | Pypy                  | CPython 2.7.3


More information about the pypy-commit mailing list