Author: Armin Rigo <[email protected]>
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
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit