Author: Armin Rigo <ar...@tunes.org> Branch: Changeset: r67930:196622fea620 Date: 2013-11-10 16:04 +0100 http://bitbucket.org/pypy/pypy/changeset/196622fea620/
Log: Reverse: a way to build rbigint objects from digits given in base 2**n, for any n <= SHIFT. diff --git a/rpython/rlib/rbigint.py b/rpython/rlib/rbigint.py --- a/rpython/rlib/rbigint.py +++ b/rpython/rlib/rbigint.py @@ -943,6 +943,7 @@ return z rshift._always_inline_ = 'try' # It's so fast that it's always benefitial. + @jit.elidable def abs_rshift_and_mask(self, bigshiftcount, mask): assert type(bigshiftcount) is r_ulonglong assert mask >= 0 @@ -958,6 +959,39 @@ lastdigit |= self.digit(wordshift+1) << hishift return lastdigit & mask + @staticmethod + def from_list_n_bits(list, nbits): + if len(list) == 0: + return NULLRBIGINT + + if nbits == SHIFT: + z = rbigint(list, 1) + else: + if not (1 <= nbits < SHIFT): + raise ValueError + + lllength = (r_ulonglong(len(list)) * nbits) // SHIFT + length = intmask(lllength) + 1 + z = rbigint([NULLDIGIT] * length, 1) + + out = 0 + i = 0 + accum = 0 + for input in list: + accum |= (input << i) + original_i = i + i += nbits + if i > SHIFT: + z.setdigit(out, accum) + out += 1 + accum = input >> (SHIFT - original_i) + i -= SHIFT + assert out < length + z.setdigit(out, accum) + + z._normalize() + return z + @jit.elidable def and_(self, other): return _bitwise(self, '&', other) diff --git a/rpython/rlib/test/test_rbigint.py b/rpython/rlib/test/test_rbigint.py --- a/rpython/rlib/test/test_rbigint.py +++ b/rpython/rlib/test/test_rbigint.py @@ -489,6 +489,20 @@ res3 = f1.abs_rshift_and_mask(r_ulonglong(y), mask) assert res3 == (abs(x) >> y) & mask + def test_from_list_n_bits(self): + for x in ([3L ** 30L, 5L ** 20L, 7 ** 300] + + [1L << i for i in range(130)] + + [(1L << i) - 1L for i in range(130)]): + for nbits in range(1, SHIFT+1): + mask = (1 << nbits) - 1 + lst = [] + got = x + while got > 0: + lst.append(int(got & mask)) + got >>= nbits + f1 = rbigint.from_list_n_bits(lst, nbits) + assert f1.tolong() == x + def test_bitwise(self): for x in gen_signs([0, 1, 5, 11, 42, 43, 3 ** 30]): for y in gen_signs([0, 1, 5, 11, 42, 43, 3 ** 30, 3 ** 31]): _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit