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

Reply via email to