Author: stian Branch: improve-rbigint Changeset: r56335:a503b84e2d2f Date: 2012-06-26 00:44 +0200 http://bitbucket.org/pypy/pypy/changeset/a503b84e2d2f/
Log: Fix a test, fix so all tests passes, and some improvements. Minor impact on performance, some become faster, some slower. I'll see how it turns out in a translated version. diff --git a/pypy/rlib/rarithmetic.py b/pypy/rlib/rarithmetic.py --- a/pypy/rlib/rarithmetic.py +++ b/pypy/rlib/rarithmetic.py @@ -115,26 +115,25 @@ n -= 2*LONG_TEST return int(n) -def longlongmask(n): - """ - NOT_RPYTHON - """ - assert isinstance(n, (int, long)) - n = long(n) - n &= LONGLONG_MASK - if n >= LONGLONG_TEST: - n -= 2*LONGLONG_TEST - return r_longlong(n) +if LONG_BIT >= 64: + def longlongmask(n): + assert isinstance(n, (int, long)) + return int(n) +else: + def longlongmask(n): + """ + NOT_RPYTHON + """ + assert isinstance(n, (int, long)) + n = long(n) + n &= LONGLONG_MASK + if n >= LONGLONG_TEST: + n -= 2*LONGLONG_TEST + return r_longlong(n) def longlonglongmask(n): - """ - NOT_RPYTHON - """ - assert isinstance(n, (int, long)) - n = long(n) - n &= LONGLONGLONG_MASK - if n >= LONGLONGLONG_TEST: - n -= 2*LONGLONGLONG_TEST + # Assume longlonglong doesn't overflow. This is perfectly fine for rbigint. + # We deal directly with overflow there anyway. return r_longlonglong(n) def widen(n): diff --git a/pypy/rlib/rbigint.py b/pypy/rlib/rbigint.py --- a/pypy/rlib/rbigint.py +++ b/pypy/rlib/rbigint.py @@ -1,4 +1,4 @@ -from pypy.rlib.rarithmetic import LONG_BIT, intmask, longlongmask, r_uint, r_ulonglong, r_longlonglong +from pypy.rlib.rarithmetic import LONG_BIT, intmask, longlongmask, r_uint, r_int, r_ulonglong, r_longlonglong from pypy.rlib.rarithmetic import ovfcheck, r_longlong, widen, is_valid_int from pypy.rlib.rarithmetic import most_neg_value_of_same_type from pypy.rlib.rfloat import isfinite @@ -55,10 +55,11 @@ def _widen_digit(x): """if not we_are_translated(): assert is_valid_int(x), "widen_digit() takes an int, got a %r" % type(x)""" - return r_longlonglong(x) - """if LONG_BIT < 64: + if SHIFT > 31: + # XXX: Using rffi.cast is probably quicker, but I dunno how to get it working. + return r_longlonglong(x) + else: return r_longlong(x) - return x""" def _store_digit(x): """if not we_are_translated(): @@ -71,14 +72,22 @@ return rffi.cast(rffi.LONGLONG, x) else: raise ValueError("SHIFT too large!") +_store_digit._annspecialcase_ = 'specialize:argtype(0)' def _load_digit(x): - return x - #return rffi.cast(lltype.Signed, x) + if SHIFT < LONG_BIT: # This would be the case for any SHIFT < LONG_BIT + return rffi.cast(lltype.Signed, x) + else: + # x already is a type large enough, just not as fast. + return x def _load_unsigned_digit(x): - return r_ulonglong(x) - #return rffi.cast(lltype.Unsigned, x) + if SHIFT < LONG_BIT: # This would be the case for any SHIFT < LONG_BIT + return rffi.cast(lltype.Unsigned, x) + else: + # This needs a performance test on 32bit + return rffi.cast(rffi.ULONGLONG, x) + #return r_ulonglong(x) NULLDIGIT = _store_digit(0) ONEDIGIT = _store_digit(1) @@ -86,8 +95,7 @@ def _check_digits(l): for x in l: assert type(x) is type(NULLDIGIT) - # XXX: Fix for int128 - # assert intmask(x) & MASK == intmask(x) + assert longlongmask(x) & MASK == longlongmask(x) class Entry(extregistry.ExtRegistryEntry): _about_ = _check_digits @@ -621,7 +629,7 @@ return rbigint(self._digits, abs(self.sign)) def invert(self): #Implement ~x as -(x + 1) - return self.add(rbigint([_store_digit(1)], 1)).neg() + return self.add(ONERBIGINT).neg() def lshift(self, int_other): if int_other < 0: @@ -783,7 +791,7 @@ INTCACHE = {} for x in range(1, CACHE_INTS+1): - numList = [_store_digit(x)] + numList = [_store_digit(_mask_digit(x))] INTCACHE[x] = rbigint(numList, 1) INTCACHE[-x] = rbigint(numList, -1) @@ -811,7 +819,7 @@ def digits_from_nonneg_long(l): digits = [] while True: - digits.append(_store_digit(intmask(l & MASK))) + digits.append(_store_digit(_mask_digit(l & MASK))) l = l >> SHIFT if not l: return digits[:] # to make it non-resizable @@ -894,7 +902,7 @@ # Special casing. if a is b: - return rbigint([NULLDIGIT], 1) + return NULLRBIGINT size_a = a.numdigits() size_b = b.numdigits() @@ -1425,12 +1433,11 @@ d = (r_ulonglong(MASK)+1) // (w1.udigit(size_w-1) + 1) assert d <= MASK # because the first digit of w1 is not zero d = longlongmask(d) - assert d != 0 v = _muladd1(v1, d) w = _muladd1(w1, d) size_v = v.numdigits() size_w = w.numdigits() - assert size_v >= size_w and size_w > 1 # Assert checks by div() + assert size_v >= size_w and size_w >= 1 # (stian: Adding d doesn't necessary mean it will increase by 1), Assert checks by div() size_a = size_v - size_w + 1 a = rbigint([NULLDIGIT] * size_a, 1) diff --git a/pypy/rlib/test/test_rbigint.py b/pypy/rlib/test/test_rbigint.py --- a/pypy/rlib/test/test_rbigint.py +++ b/pypy/rlib/test/test_rbigint.py @@ -3,7 +3,7 @@ import operator, sys, array from random import random, randint, sample from pypy.rlib.rbigint import rbigint, SHIFT, MASK, KARATSUBA_CUTOFF -from pypy.rlib.rbigint import _store_digit +from pypy.rlib.rbigint import _store_digit, _mask_digit from pypy.rlib import rbigint as lobj from pypy.rlib.rarithmetic import r_uint, r_longlong, r_ulonglong, intmask from pypy.rpython.test.test_llinterp import interpret @@ -120,7 +120,7 @@ def bigint(lst, sign): for digit in lst: assert digit & MASK == digit # wrongly written test! - return rbigint(map(_store_digit, lst), sign) + return rbigint(map(_store_digit, map(_mask_digit, lst)), sign) class Test_rbigint(object): 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 @@ -23,17 +23,18 @@ 6.647562 Pypy with improvements: - 2.085952 - 4.318238 - 9.753659 - 1.641015 - 3.983455 - 5.787758 - 7.573468 - 0.042393 - 4.436702 - 9.103529 - 5.036710 + 2.126048 + 4.276203 + 9.662745 + 1.621029 + 3.956685 + 5.752223 + 7.660295 + 0.039137 + 4.437456 + 9.078680 + 4.995520 + """ _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit