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

Reply via email to