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 _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit