[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