Author: Armin Rigo <ar...@tunes.org> Branch: Changeset: r67928:6eaf1ec3939a Date: 2013-11-10 14:33 +0100 http://bitbucket.org/pypy/pypy/changeset/6eaf1ec3939a/
Log: Add a function to extract a (small) number of bits from a bigint. 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,21 @@ return z rshift._always_inline_ = 'try' # It's so fast that it's always benefitial. + def abs_rshift_and_mask(self, bigshiftcount, mask): + assert type(bigshiftcount) is r_ulonglong + assert mask >= 0 + wordshift = bigshiftcount / SHIFT + numdigits = self.numdigits() + if wordshift >= numdigits: + return 0 + wordshift = intmask(wordshift) + loshift = intmask(intmask(bigshiftcount) - intmask(wordshift * SHIFT)) + lastdigit = self.digit(wordshift) >> loshift + if mask > (MASK >> loshift) and wordshift + 1 < numdigits: + hishift = SHIFT - loshift + lastdigit |= self.digit(wordshift+1) << hishift + return lastdigit & mask + @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 @@ -475,6 +475,7 @@ def test_shift(self): negative = -23 + masks_list = [int((1 << i) - 1) for i in range(1, r_uint.BITS-1)] for x in gen_signs([3L ** 30L, 5L ** 20L, 7 ** 300, 0L, 1L]): f1 = rbigint.fromlong(x) py.test.raises(ValueError, f1.lshift, negative) @@ -484,7 +485,10 @@ res2 = f1.rshift(int(y)).tolong() assert res1 == x << y assert res2 == x >> y - + for mask in masks_list: + res3 = f1.abs_rshift_and_mask(r_ulonglong(y), mask) + assert res3 == (abs(x) >> y) & mask + 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