[pypy-svn] pypy default: Refactor rbigint to use the proper types more explicitly:

arigo commits-noreply at bitbucket.org
Sun Feb 6 13:48:00 CET 2011


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r41647:04682c4565b6
Date: 2011-02-06 12:21 +0100
http://bitbucket.org/pypy/pypy/changeset/04682c4565b6/

Log:	Refactor rbigint to use the proper types more explicitly:

	* the digits are now a list of rffi.INT, so that they are 32-bits
	even on 64-bit machines

	* to read a digit out of the list, there are now three functions:
	digit() which returns an int, udigit() which returns an unsigned
	int, and widedigit() which returns a longlong. Trying to use
	carefully the right one at each place...

diff --git a/pypy/rlib/test/test_rbigint.py b/pypy/rlib/test/test_rbigint.py
--- a/pypy/rlib/test/test_rbigint.py
+++ b/pypy/rlib/test/test_rbigint.py
@@ -3,6 +3,7 @@
 import operator, sys
 from random import random, randint, sample
 from pypy.rlib.rbigint import rbigint, SHIFT, MASK, KARATSUBA_CUTOFF
+from pypy.rlib.rbigint import _store_digit
 from pypy.rlib import rbigint as lobj
 from pypy.rlib.rarithmetic import r_uint, r_longlong, r_ulonglong, intmask
 from pypy.rpython.test.test_llinterp import interpret
@@ -17,7 +18,15 @@
                     r1 = getattr(rl_op1, op)(rl_op2)
                     r2 = getattr(operator, op)(op1, op2)
                     assert r1.tolong() == r2
-            
+
+    def test_str(self):
+        for i in range(100):
+            n = 3 ** i
+            r1 = rbigint.fromlong(n)
+            assert r1.str() == str(n)
+            r2 = rbigint.fromlong(-n)
+            assert r2.str() == str(-n)
+
     def test_floordiv(self):
         for op1 in [-12, -2, -1, 1, 2, 50]:
             for op2 in [-4, -2, -1, 1, 2, 8]:
@@ -67,47 +76,52 @@
             yield s
             yield -s
 
+def bigint(lst, sign):
+    for digit in lst:
+        assert digit & MASK == digit    # wrongly written test!
+    return rbigint(map(_store_digit, lst), sign)
+
 
 class Test_rbigint(object):
 
     def test_args_from_long(self):
         BASE = 1 << SHIFT
-        assert rbigint.fromlong(0).eq(rbigint([0], 0))
-        assert rbigint.fromlong(17).eq(rbigint([17], 1))
-        assert rbigint.fromlong(BASE-1).eq(rbigint([intmask(BASE-1)], 1))
-        assert rbigint.fromlong(BASE).eq(rbigint([0, 1], 1))
-        assert rbigint.fromlong(BASE**2).eq(rbigint([0, 0, 1], 1))
-        assert rbigint.fromlong(-17).eq(rbigint([17], -1))
-        assert rbigint.fromlong(-(BASE-1)).eq(rbigint([intmask(BASE-1)], -1))
-        assert rbigint.fromlong(-BASE).eq(rbigint([0, 1], -1))
-        assert rbigint.fromlong(-(BASE**2)).eq(rbigint([0, 0, 1], -1))
+        assert rbigint.fromlong(0).eq(bigint([0], 0))
+        assert rbigint.fromlong(17).eq(bigint([17], 1))
+        assert rbigint.fromlong(BASE-1).eq(bigint([intmask(BASE-1)], 1))
+        assert rbigint.fromlong(BASE).eq(bigint([0, 1], 1))
+        assert rbigint.fromlong(BASE**2).eq(bigint([0, 0, 1], 1))
+        assert rbigint.fromlong(-17).eq(bigint([17], -1))
+        assert rbigint.fromlong(-(BASE-1)).eq(bigint([intmask(BASE-1)], -1))
+        assert rbigint.fromlong(-BASE).eq(bigint([0, 1], -1))
+        assert rbigint.fromlong(-(BASE**2)).eq(bigint([0, 0, 1], -1))
 #        assert rbigint.fromlong(-sys.maxint-1).eq(
 #            rbigint.digits_for_most_neg_long(-sys.maxint-1), -1)
 
     def test_args_from_int(self):
         BASE = 1 << SHIFT
         MAX = int(BASE-1)
-        assert rbigint.fromrarith_int(0).eq(rbigint([0], 0))
-        assert rbigint.fromrarith_int(17).eq(rbigint([17], 1))
-        assert rbigint.fromrarith_int(MAX).eq(rbigint([MAX], 1))
-        assert rbigint.fromrarith_int(r_longlong(BASE)).eq(rbigint([0, 1], 1))
+        assert rbigint.fromrarith_int(0).eq(bigint([0], 0))
+        assert rbigint.fromrarith_int(17).eq(bigint([17], 1))
+        assert rbigint.fromrarith_int(MAX).eq(bigint([MAX], 1))
+        assert rbigint.fromrarith_int(r_longlong(BASE)).eq(bigint([0, 1], 1))
         assert rbigint.fromrarith_int(r_longlong(BASE**2)).eq(
-            rbigint([0, 0, 1], 1))
-        assert rbigint.fromrarith_int(-17).eq(rbigint([17], -1))
-        assert rbigint.fromrarith_int(-MAX).eq(rbigint([MAX], -1))
-        assert rbigint.fromrarith_int(-MAX-1).eq(rbigint([0, 1], -1))
+            bigint([0, 0, 1], 1))
+        assert rbigint.fromrarith_int(-17).eq(bigint([17], -1))
+        assert rbigint.fromrarith_int(-MAX).eq(bigint([MAX], -1))
+        assert rbigint.fromrarith_int(-MAX-1).eq(bigint([0, 1], -1))
         assert rbigint.fromrarith_int(r_longlong(-(BASE**2))).eq(
-            rbigint([0, 0, 1], -1))
+            bigint([0, 0, 1], -1))
 #        assert rbigint.fromrarith_int(-sys.maxint-1).eq((
 #            rbigint.digits_for_most_neg_long(-sys.maxint-1), -1)
 
     def test_args_from_uint(self):
         BASE = 1 << SHIFT
-        assert rbigint.fromrarith_int(r_uint(0)).eq(rbigint([0], 0))
-        assert rbigint.fromrarith_int(r_uint(17)).eq(rbigint([17], 1))
-        assert rbigint.fromrarith_int(r_uint(BASE-1)).eq(rbigint([intmask(BASE-1)], 1))
-        assert rbigint.fromrarith_int(r_uint(BASE)).eq(rbigint([0, 1], 1))
-        #assert rbigint.fromrarith_int(r_uint(BASE**2)).eq(rbigint([0], 0))
+        assert rbigint.fromrarith_int(r_uint(0)).eq(bigint([0], 0))
+        assert rbigint.fromrarith_int(r_uint(17)).eq(bigint([17], 1))
+        assert rbigint.fromrarith_int(r_uint(BASE-1)).eq(bigint([intmask(BASE-1)], 1))
+        assert rbigint.fromrarith_int(r_uint(BASE)).eq(bigint([0, 1], 1))
+        #assert rbigint.fromrarith_int(r_uint(BASE**2)).eq(bigint([0], 0))
         assert rbigint.fromrarith_int(r_uint(sys.maxint)).eq(
             rbigint.fromint(sys.maxint))
         assert rbigint.fromrarith_int(r_uint(sys.maxint+1)).eq(
@@ -175,7 +189,7 @@
         x = x ** 100
         f1 = rbigint.fromlong(x)
         assert raises(OverflowError, f1.tofloat)
-        f2 = rbigint([0, 2097152], 1)
+        f2 = rbigint.fromlong(2097152 << SHIFT)
         d = f2.tofloat()
         assert d == float(2097152 << SHIFT)
 
@@ -290,12 +304,30 @@
         f3 = rbigint.fromlong(z)
         v = f1.pow(f2, f3)
         assert v.tolong() == pow(x, y, z)
+        f3n = f3.neg()
+        v = f1.pow(f2, f3n)
+        assert v.tolong() == pow(x, y, -z)
+        #
         f1, f2, f3 = [rbigint.fromlong(i)
                       for i in (10L, -1L, 42L)]
         py.test.raises(TypeError, f1.pow, f2, f3)
         f1, f2, f3 = [rbigint.fromlong(i)
                       for i in (10L, 5L, 0L)]
         py.test.raises(ValueError, f1.pow, f2, f3)
+        #
+        MAX = 1E40
+        x = long(random() * MAX) + 1
+        y = long(random() * MAX) + 1
+        z = long(random() * MAX) + 1
+        f1 = rbigint.fromlong(x)
+        f2 = rbigint.fromlong(y)
+        f3 = rbigint.fromlong(z)
+        print f1
+        print f2
+        print f3
+        v = f1.pow(f2, f3)
+        print '--->', v
+        assert v.tolong() == pow(x, y, z)
 
     def test_pow_lln(self):
         x = 10L
@@ -306,10 +338,10 @@
         assert v.tolong() == x ** y
 
     def test_normalize(self):
-        f1 = rbigint([1, 0], 1)
+        f1 = bigint([1, 0], 1)
         f1._normalize()
-        assert len(f1.digits) == 1
-        f0 = rbigint([0], 0)
+        assert len(f1._digits) == 1
+        f0 = bigint([0], 0)
         assert f1.sub(f1).eq(f0)
 
     def test_invert(self):
@@ -394,11 +426,13 @@
     def test__inplace_divrem1(self):
         # signs are not handled in the helpers!
         for x, y in [(1238585838347L, 3), (1234123412311231L, 1231231), (99, 100)]:
+            if y > MASK:
+                continue
             f1 = rbigint.fromlong(x)
             f2 = y
             remainder = lobj._inplace_divrem1(f1, f1, f2)
             assert (f1.tolong(), remainder) == divmod(x, y)
-        out = rbigint([99, 99], 1)
+        out = bigint([99, 99], 1)
         remainder = lobj._inplace_divrem1(out, out, 100)
 
     def test__divrem1(self):
@@ -447,16 +481,16 @@
 
     # testing Karatsuba stuff
     def test__v_iadd(self):
-        f1 = rbigint([lobj.MASK] * 10, 1)
-        f2 = rbigint([1], 1)
-        carry = lobj._v_iadd(f1, 1, len(f1.digits)-1, f2, 1)
+        f1 = bigint([lobj.MASK] * 10, 1)
+        f2 = bigint([1], 1)
+        carry = lobj._v_iadd(f1, 1, len(f1._digits)-1, f2, 1)
         assert carry == 1
         assert f1.tolong() == lobj.MASK
 
     def test__v_isub(self):
-        f1 = rbigint([lobj.MASK] + [0] * 9 + [1], 1)
-        f2 = rbigint([1], 1)
-        borrow = lobj._v_isub(f1, 1, len(f1.digits)-1, f2, 1)
+        f1 = bigint([lobj.MASK] + [0] * 9 + [1], 1)
+        f2 = bigint([1], 1)
+        borrow = lobj._v_isub(f1, 1, len(f1._digits)-1, f2, 1)
         assert borrow == 0
         assert f1.tolong() == (1 << lobj.SHIFT) ** 10 - 1
 
@@ -464,23 +498,23 @@
         split = 5
         diglo = [0] * split
         dighi = [lobj.MASK] * split
-        f1 = rbigint(diglo + dighi, 1)
+        f1 = bigint(diglo + dighi, 1)
         hi, lo = lobj._kmul_split(f1, split)
-        assert lo.digits == [0]
-        assert hi.digits == dighi
+        assert lo._digits == [_store_digit(0)]
+        assert hi._digits == map(_store_digit, dighi)
 
     def test__k_mul(self):
         digs = KARATSUBA_CUTOFF * 5
-        f1 = rbigint([lobj.MASK] * digs, 1)
-        f2 = lobj._x_add(f1,rbigint([1], 1))
+        f1 = bigint([lobj.MASK] * digs, 1)
+        f2 = lobj._x_add(f1, bigint([1], 1))
         ret = lobj._k_mul(f1, f2)
         assert ret.tolong() == f1.tolong() * f2.tolong()
 
     def test__k_lopsided_mul(self):
         digs_a = KARATSUBA_CUTOFF + 3
         digs_b = 3 * digs_a
-        f1 = rbigint([lobj.MASK] * digs_a, 1)
-        f2 = rbigint([lobj.MASK] * digs_b, 1)
+        f1 = bigint([lobj.MASK] * digs_a, 1)
+        f2 = bigint([lobj.MASK] * digs_b, 1)
         ret = lobj._k_lopsided_mul(f1, f2)
         assert ret.tolong() == f1.tolong() * f2.tolong()
 
@@ -547,7 +581,9 @@
 class TestTranslatable(object):
     def test_square(self):
         def test():
-            x = rbigint([1410065408, 4], 1)
+            xlo = rbigint.fromint(1410065408)
+            xhi = rbigint.fromint(4)
+            x = xlo.or_(xhi.lshift(31))
             y = x.mul(x)
             return y.str()
         res = interpret(test, [])

diff --git a/pypy/rlib/rbigint.py b/pypy/rlib/rbigint.py
--- a/pypy/rlib/rbigint.py
+++ b/pypy/rlib/rbigint.py
@@ -3,6 +3,8 @@
 from pypy.rlib.rarithmetic import most_neg_value_of_same_type
 from pypy.rlib.debug import make_sure_not_resized, check_regular_int
 from pypy.rlib.objectmodel import we_are_translated
+from pypy.rpython.lltypesystem import lltype, rffi
+from pypy.rpython import extregistry
 
 import math, sys
 
@@ -39,36 +41,84 @@
 FIVEARY_CUTOFF = 8
 
 
-def mask_digit(x):
+def _mask_digit(x):
+    if not we_are_translated():
+        assert type(x) is not long, "overflow occurred!"
     return intmask(x & MASK)
-mask_digit._annspecialcase_ = 'specialize:argtype(0)'
+_mask_digit._annspecialcase_ = 'specialize:argtype(0)'
 
-def widen_digit(x):
+def _widen_digit(x):
+    if not we_are_translated():
+        assert type(x) is int, "widen_digit() takes an int, got a %r" % type(x)
     if SHIFT <= 15:
         return int(x)
     return r_longlong(x)
 
+def _store_digit(x):
+    if not we_are_translated():
+        assert type(x) is int, "store_digit() takes an int, got a %r" % type(x)
+    if SHIFT <= 15:
+        return rffi.cast(rffi.SHORT, x)
+    elif SHIFT <= 31:
+        return rffi.cast(rffi.INT, x)
+    else:
+        raise ValueError("SHIFT too large!")
+
+def _load_digit(x):
+    return rffi.cast(lltype.Signed, x)
+
+def _load_unsigned_digit(x):
+    return rffi.cast(lltype.Unsigned, x)
+
+NULLDIGIT = _store_digit(0)
+
+def _check_digits(l):
+    for x in l:
+        assert type(x) is type(NULLDIGIT)
+        assert intmask(x) & MASK == intmask(x)
+class Entry(extregistry.ExtRegistryEntry):
+    _about_ = _check_digits
+    def compute_result_annotation(self, s_list):
+        from pypy.annotation import model as annmodel
+        assert isinstance(s_list, annmodel.SomeList)
+        s_DIGIT = self.bookkeeper.valueoftype(type(NULLDIGIT))
+        assert s_DIGIT.contains(s_list.listdef.listitem.s_value)
+    def specialize_call(self, hop):
+        pass
+
 
 class rbigint(object):
     """This is a reimplementation of longs using a list of digits."""
-    # XXX relace the list of ints with a list of rffi.INTs, maybe
-    
-    def __init__(self, digits=None, sign=0):
-        if digits is None or len(digits) == 0:
-            digits = [0]
+
+    def __init__(self, digits=[], sign=0):
+        if len(digits) == 0:
+            digits = [NULLDIGIT]
+        _check_digits(digits)
         make_sure_not_resized(digits)
-        self.digits = digits
+        self._digits = digits
         self.sign = sign
 
-    def _digit(self, x):
-        return widen_digit(self.digits[x])
-    def _setdigit(self, x, val):
-        val = mask_digit(val)
+    def digit(self, x):
+        """Return the x'th digit, as an int."""
+        return _load_digit(self._digits[x])
+
+    def widedigit(self, x):
+        """Return the x'th digit, as a long long int if needed
+        to have enough room to contain two digits."""
+        return _widen_digit(_load_digit(self._digits[x]))
+
+    def udigit(self, x):
+        """Return the x'th digit, as an unsigned int."""
+        return _load_unsigned_digit(self._digits[x])
+
+    def setdigit(self, x, val):
+        val = _mask_digit(val)
         assert val >= 0
-        self.digits[x] = int(val)
-    _setdigit._annspecialcase_ = 'specialize:argtype(2)'
-    def _numdigits(self):
-        return len(self.digits)
+        self._digits[x] = _store_digit(val)
+    setdigit._annspecialcase_ = 'specialize:argtype(2)'
+
+    def numdigits(self):
+        return len(self._digits)
 
     def fromint(intval):
         check_regular_int(intval)
@@ -89,11 +139,11 @@
         while t:
             ndigits += 1
             t >>= SHIFT
-        v = rbigint([0] * ndigits, sign)
+        v = rbigint([NULLDIGIT] * ndigits, sign)
         t = ival
         p = 0
         while t:
-            v._setdigit(p, t)
+            v.setdigit(p, t)
             t >>= SHIFT
             p += 1
         return v
@@ -121,11 +171,11 @@
         if expo <= 0:
             return rbigint()
         ndig = (expo-1) // SHIFT + 1 # Number of 'digits' in result
-        v = rbigint([0] * ndig, 1)
+        v = rbigint([NULLDIGIT] * ndig, 1)
         frac = math.ldexp(frac, (expo-1) % SHIFT + 1)
         for i in range(ndig-1, -1, -1):
-            bits = mask_digit(int(frac))
-            v._setdigit(i, bits)
+            bits = int(frac)
+            v.setdigit(i, bits)
             frac -= float(bits)
             frac = math.ldexp(frac, SHIFT)
         if neg:
@@ -170,10 +220,10 @@
 
     def _touint_helper(self):
         x = r_uint(0)
-        i = self._numdigits() - 1
+        i = self.numdigits() - 1
         while i >= 0:
             prev = x
-            x = r_uint((x << SHIFT) + self.digits[i])
+            x = (x << SHIFT) + self.udigit(i)
             if (x >> SHIFT) != prev:
                 raise OverflowError(
                         "long int too large to convert to unsigned int")
@@ -195,26 +245,6 @@
     def tofloat(self):
         return _AsDouble(self)
 
-    def _count_bits(self):
-        # return the number of bits in the digits
-        if self.sign == 0:
-            return 0
-        p = self._numdigits() - 1
-        bits = SHIFT * p
-        digit = self.digits[p]
-        while digit:
-            digit >>= 1
-            bits += 1
-        return bits
-
-    def is_odd(self):
-        # Note: this is a tiny optimization.
-        # Instead of implementing a general "get_bit" operation,
-        # which would be expensive for negative numbers,
-        # get_odd has the nice feature that it is always correct,
-        # no matter what the sign is (two's complement)
-        return self.digits[0] & 1
-
     def format(self, digits, prefix='', suffix=''):
         # 'digits' is a string whose length is the base to use,
         # and where each character is the corresponding digit.
@@ -228,12 +258,12 @@
 
     def eq(self, other):
         if (self.sign != other.sign or
-            self._numdigits() != other._numdigits()):
+            self.numdigits() != other.numdigits()):
             return False
         i = 0
-        ld = self._numdigits()
+        ld = self.numdigits()
         while i < ld:
-            if self.digits[i] != other.digits[i]:
+            if self.digit(i) != other.digit(i):
                 return False
             i += 1
         return True
@@ -246,8 +276,8 @@
             return False
         if self.sign < other.sign:
             return True
-        ld1 = self._numdigits()
-        ld2 = other._numdigits()
+        ld1 = self.numdigits()
+        ld2 = other.numdigits()
         if ld1 > ld2:
             if other.sign > 0:
                 return False
@@ -260,8 +290,8 @@
                 return False
         i = ld1 - 1
         while i >= 0:
-            d1 = self.digits[i]
-            d2 = other.digits[i]
+            d1 = self.digit(i)
+            d2 = other.digit(i)
             if d1 < d2:
                 if other.sign > 0:
                     return True
@@ -303,7 +333,7 @@
         if other.sign == 0:
             return self
         if self.sign == 0:
-            return rbigint(other.digits[:], -other.sign)
+            return rbigint(other._digits[:], -other.sign)
         if self.sign == other.sign:
             result = _x_sub(self, other)
         else:
@@ -355,7 +385,7 @@
         div, mod = _divrem(v, w)
         if mod.sign * w.sign == -1:
             mod = mod.add(w)
-            div = div.sub(rbigint([1], 1))
+            div = div.sub(rbigint([_store_digit(1)], 1))
         return div, mod
 
     def pow(a, b, c=None):
@@ -382,11 +412,11 @@
             #     modulus = -modulus
             if c.sign < 0:
                 negativeOutput = True
-                c = rbigint(c.digits, -c.sign)
+                c = c.neg()
 
             # if modulus == 1:
             #     return 0
-            if c._numdigits() == 1 and c.digits[0] == 1:
+            if c.numdigits() == 1 and c.digit(0) == 1:
                 return rbigint()
 
             # if base < 0:
@@ -399,16 +429,16 @@
         # At this point a, b, and c are guaranteed non-negative UNLESS
         # c is NULL, in which case a may be negative. */
 
-        z = rbigint([1], 1)
+        z = rbigint([_store_digit(1)], 1)
 
         # python adaptation: moved macros REDUCE(X) and MULT(X, Y, result)
         # into helper function result = _help_mult(x, y, c)
-        if b._numdigits() <= FIVEARY_CUTOFF:
+        if b.numdigits() <= FIVEARY_CUTOFF:
             # Left-to-right binary exponentiation (HAC Algorithm 14.79)
             # http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf
-            i = b._numdigits() - 1
+            i = b.numdigits() - 1
             while i >= 0:
-                bi = b.digits[i]
+                bi = b.digit(i)
                 j = 1 << (SHIFT-1)
                 while j != 0:
                     z = _help_mult(z, z, c)
@@ -418,14 +448,15 @@
                 i -= 1
         else:
             # Left-to-right 5-ary exponentiation (HAC Algorithm 14.82)
+            # This is only useful in the case where c != None.
             # z still holds 1L
             table = [z] * 32
-            table[0] = z;
+            table[0] = z
             for i in range(1, 32):
                 table[i] = _help_mult(table[i-1], a, c)
-            i = b._numdigits() - 1
+            i = b.numdigits() - 1
             while i >= 0:
-                bi = b.digits[i]
+                bi = b.digit(i)
                 j = SHIFT - 5
                 while j >= 0:
                     index = (bi >> j) & 0x1f
@@ -441,13 +472,13 @@
         return z
 
     def neg(self):
-        return rbigint(self.digits, -self.sign)
+        return rbigint(self._digits, -self.sign)
 
     def abs(self):
-        return rbigint(self.digits, abs(self.sign))
+        return rbigint(self._digits, abs(self.sign))
 
     def invert(self): #Implement ~x as -(x + 1)
-        return self.add(rbigint([1], 1)).neg()
+        return self.add(rbigint([_store_digit(1)], 1)).neg()
 
     def lshift(self, int_other):
         if int_other < 0:
@@ -459,22 +490,22 @@
         wordshift = int_other // SHIFT
         remshift  = int_other - wordshift * SHIFT
 
-        oldsize = self._numdigits()
+        oldsize = self.numdigits()
         newsize = oldsize + wordshift
         if remshift:
             newsize += 1
-        z = rbigint([0] * newsize, self.sign)
-        accum = 0
+        z = rbigint([NULLDIGIT] * newsize, self.sign)
+        accum = _widen_digit(0)
         i = wordshift
         j = 0
         while j < oldsize:
-            accum |= self._digit(j) << remshift
-            z._setdigit(i, accum)
+            accum |= self.widedigit(j) << remshift
+            z.setdigit(i, accum)
             accum >>= SHIFT
             i += 1
             j += 1
         if remshift:
-            z._setdigit(newsize - 1, accum)
+            z.setdigit(newsize - 1, accum)
         else:
             assert not accum
         z._normalize()
@@ -491,21 +522,22 @@
             return a2.invert()
 
         wordshift = int_other // SHIFT
-        newsize = self._numdigits() - wordshift
+        newsize = self.numdigits() - wordshift
         if newsize <= 0:
             return rbigint()
 
         loshift = int_other % SHIFT
         hishift = SHIFT - loshift
-        lomask = (1 << hishift) - 1
+        lomask = intmask((r_uint(1) << hishift) - 1)
         himask = MASK ^ lomask
-        z = rbigint([0] * newsize, self.sign)
+        z = rbigint([NULLDIGIT] * newsize, self.sign)
         i = 0
         j = wordshift
         while i < newsize:
-            z.digits[i] = (self.digits[j] >> loshift) & lomask
+            newdigit = (self.digit(j) >> loshift) & lomask
             if i+1 < newsize:
-                z.digits[i] |= (self.digits[j+1] << hishift) & himask
+                newdigit |= intmask(self.digit(j+1) << hishift) & himask
+            z.setdigit(i, newdigit)
             i += 1
             j += 1
         z._normalize()
@@ -538,34 +570,35 @@
             ret /= math.log(base)
         return ret
 
-    def tolong(self): #YYYYYY
-        l = 0
-        digits = list(self.digits)
+    def tolong(self):
+        "NOT_RPYTHON"
+        l = 0L
+        digits = list(self._digits)
         digits.reverse()
         for d in digits:
             l = l << SHIFT
-            l += long(d)
+            l += intmask(d)
         return l * self.sign
 
     def _normalize(self):
-        if self._numdigits() == 0:
+        if self.numdigits() == 0:
             self.sign = 0
-            self.digits = [0]
+            self._digits = [NULLDIGIT]
             return
-        i = self._numdigits()
-        while i > 1 and self.digits[i - 1] == 0:
+        i = self.numdigits()
+        while i > 1 and self.digit(i - 1) == 0:
             i -= 1
         assert i >= 1
-        if i != self._numdigits():
-            self.digits = self.digits[:i]
-        if self._numdigits() == 1 and self.digits[0] == 0:
+        if i != self.numdigits():
+            self._digits = self._digits[:i]
+        if self.numdigits() == 1 and self.digit(0) == 0:
             self.sign = 0
 
     def bit_length(self):
-        i = self._numdigits()
-        if i == 1 and self.digits[0] == 0:
+        i = self.numdigits()
+        if i == 1 and self.digit(0) == 0:
             return 0
-        msd = self.digits[i - 1]
+        msd = self.digit(i - 1)
         msd_bits = 0
         while msd >= 32:
             msd_bits += 6
@@ -580,7 +613,8 @@
         return bits
 
     def __repr__(self):
-        return "<rbigint digits=%s, sign=%s, %s>" % (self.digits, self.sign, self.str())
+        return "<rbigint digits=%s, sign=%s, %s>" % (self._digits,
+                                                     self.sign, self.str())
 
 #_________________________________________________________________
 
@@ -605,7 +639,7 @@
 def digits_from_nonneg_long(l):
     digits = []
     while True:
-        digits.append(mask_digit(l))
+        digits.append(_store_digit(intmask(l & MASK)))
         l = l >> SHIFT
         if not l:
             return digits[:] # to make it non-resizable
@@ -615,15 +649,15 @@
     # This helper only works if 'l' is the most negative integer of its
     # type, which in base 2 looks like: 1000000..0000
     digits = []
-    while (mask_digit(l)) == 0:
-        digits.append(0)
+    while _mask_digit(l) == 0:
+        digits.append(NULLDIGIT)
         l = l >> SHIFT
     # now 'l' looks like: ...111100000
     # turn it into:       ...000100000
     # to drop the extra unwanted 1's introduced by the signed right shift
     l = -intmask(l)
-    assert l >= 0
-    digits.append(l)
+    assert l & MASK == l
+    digits.append(_store_digit(l))
     return digits[:] # to make it non-resizable
 digits_for_most_neg_long._annspecialcase_ = "specialize:argtype(0)"
 
@@ -631,7 +665,7 @@
     if x > 0:
         return digits_from_nonneg_long(x), 1
     elif x == 0:
-        return [0], 0
+        return [NULLDIGIT], 0
     elif x != most_neg_value_of_same_type(x):
         # normal case
         return digits_from_nonneg_long(-x), -1
@@ -650,42 +684,42 @@
     "NOT_RPYTHON"
     if x >= 0:
         if x == 0:
-            return [0], 0
+            return [NULLDIGIT], 0
         else:
             return digits_from_nonneg_long(x), 1
     else:
-        return digits_from_nonneg_long(-long(x)), -1
+        return digits_from_nonneg_long(-x), -1
 
 def _x_add(a, b):
     """ Add the absolute values of two bigint integers. """
-    size_a = a._numdigits()
-    size_b = b._numdigits()
+    size_a = a.numdigits()
+    size_b = b.numdigits()
 
     # Ensure a is the larger of the two:
     if size_a < size_b:
         a, b = b, a
         size_a, size_b = size_b, size_a
-    z = rbigint([0] * (a._numdigits() + 1), 1)
+    z = rbigint([NULLDIGIT] * (a.numdigits() + 1), 1)
     i = 0
-    carry = 0
+    carry = r_uint(0)
     while i < size_b:
-        carry += a._digit(i) + b._digit(i)
-        z._setdigit(i, carry)
+        carry += a.udigit(i) + b.udigit(i)
+        z.setdigit(i, carry)
         carry >>= SHIFT
         i += 1
     while i < size_a:
-        carry += a._digit(i)
-        z._setdigit(i, carry)
+        carry += a.udigit(i)
+        z.setdigit(i, carry)
         carry >>= SHIFT
         i += 1
-    z._setdigit(i, carry)
+    z.setdigit(i, carry)
     z._normalize()
     return z
 
 def _x_sub(a, b):
     """ Subtract the absolute values of two integers. """
-    size_a = a._numdigits()
-    size_b = b._numdigits()
+    size_a = a.numdigits()
+    size_b = b.numdigits()
     sign = 1
 
     # Ensure a is the larger of the two:
@@ -696,34 +730,32 @@
     elif size_a == size_b:
         # Find highest digit where a and b differ:
         i = size_a - 1
-        while i >= 0 and a.digits[i] == b.digits[i]:
+        while i >= 0 and a.digit(i) == b.digit(i):
             i -= 1
         if i < 0:
-            return rbigint([0], 0)
-        if a.digits[i] < b.digits[i]:
+            return rbigint()
+        if a.digit(i) < b.digit(i):
             sign = -1
             a, b = b, a
         size_a = size_b = i+1
-    borrow = 0
-    z = rbigint([0] * size_a, 1)
+    z = rbigint([NULLDIGIT] * size_a, sign)
+    borrow = r_uint(0)
     i = 0
     while i < size_b:
         # The following assumes unsigned arithmetic
         # works modulo 2**N for some N>SHIFT.
-        borrow = a._digit(i) - b._digit(i) - borrow
-        z._setdigit(i, borrow)
+        borrow = a.udigit(i) - b.udigit(i) - borrow
+        z.setdigit(i, borrow)
         borrow >>= SHIFT
         borrow &= 1 # Keep only one sign bit
         i += 1
     while i < size_a:
-        borrow = a._digit(i) - borrow
-        z._setdigit(i, borrow)
+        borrow = a.udigit(i) - borrow
+        z.setdigit(i, borrow)
         borrow >>= SHIFT
         borrow &= 1 # Keep only one sign bit
         i += 1
     assert borrow == 0
-    if sign < 0:
-        z.sign = -1
     z._normalize()
     return z
 
@@ -734,9 +766,9 @@
     Returns the absolute value of the product, or None if error.
     """
 
-    size_a = a._numdigits()
-    size_b = b._numdigits()
-    z = rbigint([0] * (size_a + size_b), 1)
+    size_a = a.numdigits()
+    size_b = b.numdigits()
+    z = rbigint([NULLDIGIT] * (size_a + size_b), 1)
     if a is b:
         # Efficient squaring per HAC, Algorithm 14.16:
         # http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf
@@ -745,13 +777,13 @@
         # pyramid appears twice (except for the size_a squares).
         i = 0
         while i < size_a:
-            f = a._digit(i)
+            f = a.widedigit(i)
             pz = i << 1
             pa = i + 1
             paend = size_a
 
-            carry = z._digit(pz) + f * f
-            z._setdigit(pz, carry)
+            carry = z.widedigit(pz) + f * f
+            z.setdigit(pz, carry)
             pz += 1
             carry >>= SHIFT
             assert carry <= MASK
@@ -760,19 +792,19 @@
             # pyramid it appears.  Same as adding f<<1 once.
             f <<= 1
             while pa < paend:
-                carry += z._digit(pz) + a._digit(pa) * f
+                carry += z.widedigit(pz) + a.widedigit(pa) * f
                 pa += 1
-                z._setdigit(pz, carry)
+                z.setdigit(pz, carry)
                 pz += 1
                 carry >>= SHIFT
-                assert carry <= (widen_digit(MASK) << 1)
+                assert carry <= (_widen_digit(MASK) << 1)
             if carry:
-                carry += z._digit(pz)
-                z._setdigit(pz, carry)
+                carry += z.widedigit(pz)
+                z.setdigit(pz, carry)
                 pz += 1
                 carry >>= SHIFT
             if carry:
-                z._setdigit(pz, z._digit(pz) + carry)
+                z.setdigit(pz, z.widedigit(pz) + carry)
             assert (carry >> SHIFT) == 0
             i += 1
     else:
@@ -780,19 +812,19 @@
         i = 0
         while i < size_a:
             carry = 0
-            f = a._digit(i)
+            f = a.widedigit(i)
             pz = i
             pb = 0
             pbend = size_b
             while pb < pbend:
-                carry += z._digit(pz) + b._digit(pb) * f
+                carry += z.widedigit(pz) + b.widedigit(pb) * f
                 pb += 1
-                z._setdigit(pz, carry)
+                z.setdigit(pz, carry)
                 pz += 1
                 carry >>= SHIFT
                 assert carry <= MASK
             if carry:
-                z._setdigit(pz, z._digit(pz) + carry)
+                z.setdigit(pz, z.widedigit(pz) + carry)
             assert (carry >> SHIFT) == 0
             i += 1
     z._normalize()
@@ -807,11 +839,11 @@
     viewing the shift as being by digits.  The sign bit is ignored, and
     the return values are >= 0.
     """
-    size_n = n._numdigits()
+    size_n = n.numdigits()
     size_lo = min(size_n, size)
 
-    lo = rbigint(n.digits[:size_lo], 1)
-    hi = rbigint(n.digits[size_lo:], 1)
+    lo = rbigint(n._digits[:size_lo], 1)
+    hi = rbigint(n._digits[size_lo:], 1)
     lo._normalize()
     hi._normalize()
     return hi, lo
@@ -822,8 +854,8 @@
     absolute value of the product (or raises if error).
     See Knuth Vol. 2 Chapter 4.3.3 (Pp. 294-295).
     """
-    asize = a._numdigits()
-    bsize = b._numdigits()
+    asize = a.numdigits()
+    bsize = b.numdigits()
     # (ah*X+al)(bh*X+bl) = ah*bh*X*X + (ah*bl + al*bh)*X + al*bl
     # Let k = (ah+al)*(bh+bl) = ah*bl + al*bh  + ah*bh + al*bl
     # Then the original product is
@@ -843,7 +875,7 @@
         i = KARATSUBA_CUTOFF
     if asize <= i:
         if a.sign == 0:
-            return rbigint([0], 0)
+            return rbigint()     # zero
         else:
             return _x_mul(a, b)
 
@@ -882,13 +914,13 @@
     #    at shift.
 
     # 1. Allocate result space.
-    ret = rbigint([0] * (asize + bsize), 1)
+    ret = rbigint([NULLDIGIT] * (asize + bsize), 1)
 
     # 2. t1 <- ah*bh, and copy into high digits of result.
     t1 = _k_mul(ah, bh)
     assert t1.sign >= 0
-    assert 2*shift + t1._numdigits() <= ret._numdigits()
-    ret.digits[2*shift : 2*shift + t1._numdigits()] = t1.digits
+    assert 2*shift + t1.numdigits() <= ret.numdigits()
+    ret._digits[2*shift : 2*shift + t1.numdigits()] = t1._digits
 
     # Zero-out the digits higher than the ah*bh copy. */
     ## ignored, assuming that we initialize to zero
@@ -900,8 +932,8 @@
     # 3. t2 <- al*bl, and copy into the low digits.
     t2 = _k_mul(al, bl)
     assert t2.sign >= 0
-    assert t2._numdigits() <= 2*shift # no overlap with high digits
-    ret.digits[:t2._numdigits()] = t2.digits
+    assert t2.numdigits() <= 2*shift # no overlap with high digits
+    ret._digits[:t2.numdigits()] = t2._digits
 
     # Zero out remaining digits.
     ## ignored, assuming that we initialize to zero
@@ -911,9 +943,9 @@
 
     # 4 & 5. Subtract ah*bh (t1) and al*bl (t2).  We do al*bl first
     # because it's fresher in cache.
-    i = ret._numdigits() - shift  # # digits after shift
-    _v_isub(ret, shift, i, t2, t2._numdigits())
-    _v_isub(ret, shift, i, t1, t1._numdigits())
+    i = ret.numdigits() - shift  # # digits after shift
+    _v_isub(ret, shift, i, t2, t2.numdigits())
+    _v_isub(ret, shift, i, t1, t1.numdigits())
     del t1, t2
 
     # 6. t3 <- (ah+al)(bh+bl), and add into result.
@@ -932,7 +964,7 @@
 
     # Add t3.  It's not obvious why we can't run out of room here.
     # See the (*) comment after this function.
-    _v_iadd(ret, shift, i, t3, t3._numdigits())
+    _v_iadd(ret, shift, i, t3, t3.numdigits())
     del t3
 
     ret._normalize()
@@ -993,20 +1025,20 @@
     at a time, then move on, never bactracking except for the helpful
     single-width slice overlap between successive partial sums).
     """
-    asize = a._numdigits()
-    bsize = b._numdigits()
+    asize = a.numdigits()
+    bsize = b.numdigits()
     # nbdone is # of b digits already multiplied
 
     assert asize > KARATSUBA_CUTOFF
     assert 2 * asize <= bsize
 
     # Allocate result space, and zero it out.
-    ret = rbigint([0] * (asize + bsize), 1)
+    ret = rbigint([NULLDIGIT] * (asize + bsize), 1)
 
     # Successive slices of b are copied into bslice.
     #bslice = rbigint([0] * asize, 1)
     # XXX we cannot pre-allocate, see comments below!
-    bslice = rbigint([0], 1)
+    bslice = rbigint([NULLDIGIT], 1)
 
     nbdone = 0;
     while bsize > 0:
@@ -1018,12 +1050,12 @@
         # XXX: this would be more efficient if we adopted CPython's
         # way to store the size, instead of resizing the list!
         # XXX change the implementation, encoding length via the sign.
-        bslice.digits = b.digits[nbdone : nbdone + nbtouse]
+        bslice._digits = b._digits[nbdone : nbdone + nbtouse]
         product = _k_mul(a, bslice)
 
         # Add into result.
-        _v_iadd(ret, nbdone, ret._numdigits() - nbdone,
-                 product, product._numdigits())
+        _v_iadd(ret, nbdone, ret.numdigits() - nbdone,
+                 product, product.numdigits())
         del product
 
         bsize -= nbtouse
@@ -1038,18 +1070,18 @@
     Divide bigint pin by non-zero digit n, storing quotient
     in pout, and returning the remainder. It's OK for pin == pout on entry.
     """
-    rem = widen_digit(0)
+    rem = _widen_digit(0)
     assert n > 0 and n <= MASK
     if not size:
-        size = pin._numdigits()
+        size = pin.numdigits()
     size -= 1
     while size >= 0:
-        rem = (rem << SHIFT) + pin._digit(size)
+        rem = (rem << SHIFT) + pin.widedigit(size)
         hi = rem // n
-        pout._setdigit(size, hi)
+        pout.setdigit(size, hi)
         rem -= hi * n
         size -= 1
-    return mask_digit(rem)
+    return _mask_digit(rem)
 
 def _divrem1(a, n):
     """
@@ -1058,8 +1090,8 @@
     The sign of a is ignored; n should not be zero.
     """
     assert n > 0 and n <= MASK
-    size = a._numdigits()
-    z = rbigint([0] * size, 1)
+    size = a.numdigits()
+    z = rbigint([NULLDIGIT] * size, 1)
     rem = _inplace_divrem1(z, a, n)
     z._normalize()
     return z, rem
@@ -1071,21 +1103,21 @@
     x[m-1], and the remaining carry (0 or 1) is returned.
     Python adaptation: x is addressed relative to xofs!
     """
-    carry = 0;
+    carry = r_uint(0)
 
     assert m >= n
     i = xofs
     iend = xofs + n
     while i < iend:
-        carry += x._digit(i) + y._digit(i-xofs)
-        x._setdigit(i, carry)
+        carry += x.udigit(i) + y.udigit(i-xofs)
+        x.setdigit(i, carry)
         carry >>= SHIFT
         assert (carry & 1) == carry
         i += 1
     iend = xofs + m
     while carry and i < iend:
-        carry += x._digit(i)
-        x._setdigit(i, carry)
+        carry += x.udigit(i)
+        x.setdigit(i, carry)
         carry >>= SHIFT
         assert (carry & 1) == carry
         i += 1
@@ -1098,57 +1130,59 @@
     far as x[m-1], and the remaining borrow (0 or 1) is returned.
     Python adaptation: x is addressed relative to xofs!
     """
-    borrow = 0
+    borrow = r_uint(0)
 
     assert m >= n
     i = xofs
     iend = xofs + n
     while i < iend:
-        borrow = x._digit(i) - y._digit(i-xofs) - borrow
-        x._setdigit(i, borrow)
+        borrow = x.udigit(i) - y.udigit(i-xofs) - borrow
+        x.setdigit(i, borrow)
         borrow >>= SHIFT
         borrow &= 1    # keep only 1 sign bit
         i += 1
     iend = xofs + m
     while borrow and i < iend:
-        borrow = x._digit(i) - borrow
-        x._setdigit(i, borrow)
+        borrow = x.udigit(i) - borrow
+        x.setdigit(i, borrow)
         borrow >>= SHIFT
         borrow &= 1
         i += 1
     return borrow
 
 
-def _muladd1(a, n, extra=widen_digit(0)):
+def _muladd1(a, n, extra=0):
     """Multiply by a single digit and add a single digit, ignoring the sign.
     """
-    size_a = a._numdigits()
-    z = rbigint([0] * (size_a+1), 1)
-    carry = extra
-    assert carry & MASK == carry
+    size_a = a.numdigits()
+    z = rbigint([NULLDIGIT] * (size_a+1), 1)
+    assert extra & MASK == extra
+    carry = _widen_digit(extra)
     i = 0
     while i < size_a:
-        carry += a._digit(i) * n
-        z._setdigit(i, carry)
+        carry += a.widedigit(i) * n
+        z.setdigit(i, carry)
         carry >>= SHIFT
         i += 1
-    z._setdigit(i, carry)
+    z.setdigit(i, carry)
     z._normalize()
     return z
 
 
 def _x_divrem(v1, w1):
     """ Unsigned bigint division with remainder -- the algorithm """
-    size_w = w1._numdigits()
-    d = (widen_digit(MASK)+1) // (w1._digit(size_w-1) + 1)
+    size_w = w1.numdigits()
+    d = (r_uint(MASK)+1) // (w1.udigit(size_w-1) + 1)
+    assert d <= MASK    # because the first digit of w1 is not zero
+    d = intmask(d)
     v = _muladd1(v1, d)
     w = _muladd1(w1, d)
-    size_v = v._numdigits()
-    size_w = w._numdigits()
+    size_v = v.numdigits()
+    size_w = w.numdigits()
     assert size_v >= size_w and size_w > 1 # Assert checks by div()
 
     size_a = size_v - size_w + 1
-    a = rbigint([0] * size_a, 1)
+    a = rbigint([NULLDIGIT] * size_a, 1)
 
     j = size_v
     k = size_a - 1
@@ -1156,50 +1190,50 @@
         if j >= size_v:
             vj = 0
         else:
-            vj = v._digit(j)
+            vj = v.widedigit(j)
         carry = 0
 
-        if vj == w._digit(size_w-1):
+        if vj == w.widedigit(size_w-1):
             q = MASK
         else:
-            q = ((vj << SHIFT) + v._digit(j-1)) // w._digit(size_w-1)
+            q = ((vj << SHIFT) + v.widedigit(j-1)) // w.widedigit(size_w-1)
 
-        while (w._digit(size_w-2) * q >
+        while (w.widedigit(size_w-2) * q >
                 ((
                     (vj << SHIFT)
-                    + v._digit(j-1)
-                    - q * w._digit(size_w-1)
+                    + v.widedigit(j-1)
+                    - q * w.widedigit(size_w-1)
                                 ) << SHIFT)
-                + v._digit(j-2)):
+                + v.widedigit(j-2)):
             q -= 1
         i = 0
         while i < size_w and i+k < size_v:
-            z = w._digit(i) * q
+            z = w.widedigit(i) * q
             zz = z >> SHIFT
-            carry += v._digit(i+k) - z + (zz << SHIFT)
-            v._setdigit(i+k, carry)
+            carry += v.widedigit(i+k) - z + (zz << SHIFT)
+            v.setdigit(i+k, carry)
             carry >>= SHIFT
             carry -= zz
             i += 1
 
         if i+k < size_v:
-            carry += v._digit(i+k)
-            v._setdigit(i+k, 0)
+            carry += v.widedigit(i+k)
+            v.setdigit(i+k, 0)
 
         if carry == 0:
-            a._setdigit(k, q)
+            a.setdigit(k, q)
             assert not q >> SHIFT
         else:
             assert carry == -1
             q -= 1
-            a._setdigit(k, q)
+            a.setdigit(k, q)
             assert not q >> SHIFT
 
             carry = 0
             i = 0
             while i < size_w and i+k < size_v:
-                carry += v._digit(i+k) + w._digit(i)
-                v._setdigit(i+k, carry)
+                carry += v.udigit(i+k) + w.udigit(i)
+                v.setdigit(i+k, carry)
                 carry >>= SHIFT
                 i += 1
         j -= 1
@@ -1212,22 +1246,22 @@
 
 def _divrem(a, b):
     """ Long division with remainder, top-level routine """
-    size_a = a._numdigits()
-    size_b = b._numdigits()
+    size_a = a.numdigits()
+    size_b = b.numdigits()
 
     if b.sign == 0:
         raise ZeroDivisionError("long division or modulo by zero")
 
     if (size_a < size_b or
         (size_a == size_b and
-         a.digits[size_a-1] < b.digits[size_b-1])):
+         a.digit(size_a-1) < b.digit(size_b-1))):
         # |a| < |b|
-        z = rbigint([0], 0)
+        z = rbigint()   # result is 0
         rem = a
         return z, rem
     if size_b == 1:
-        z, urem = _divrem1(a, b._digit(0))
-        rem = rbigint([urem], int(urem != 0))
+        z, urem = _divrem1(a, b.digit(0))
+        rem = rbigint([_store_digit(urem)], int(urem != 0))
     else:
         z, rem = _x_divrem(a, b)
     # Set the signs.
@@ -1257,14 +1291,14 @@
     NBITS_WANTED = 57
     if v.sign == 0:
         return 0.0, 0
-    i = v._numdigits() - 1
+    i = v.numdigits() - 1
     sign = v.sign
-    x = float(v.digits[i])
+    x = float(v.digit(i))
     nbitsneeded = NBITS_WANTED - 1
     # Invariant:  i Python digits remain unaccounted for.
     while i > 0 and nbitsneeded > 0:
         i -= 1
-        x = x * FLOAT_MULTIPLIER + float(v.digits[i])
+        x = x * FLOAT_MULTIPLIER + float(v.digit(i))
         nbitsneeded -= SHIFT
     # There are i digits we didn't shift in.  Pretending they're all
     # zeroes, the true value is x * 2**(i*SHIFT).
@@ -1385,7 +1419,7 @@
     Convert a bigint object to a string, using a given conversion base.
     Return a string object.
     """
-    size_a = a._numdigits()
+    size_a = a.numdigits()
 
     base = len(digits)
     assert base >= 2 and base <= 36
@@ -1421,11 +1455,11 @@
             basebits += 1
 
         for i in range(size_a):
-            accum |= a._digit(i) << accumbits
+            accum |= a.widedigit(i) << accumbits
             accumbits += SHIFT
             assert accumbits >= basebits
             while 1:
-                cdigit = accum & (base - 1)
+                cdigit = intmask(accum & (base - 1))
                 p -= 1
                 assert p >= 0
                 s[p] = digits[cdigit]
@@ -1444,7 +1478,7 @@
         size = size_a
         pin = a # just for similarity to C source which uses the array
         # powbase <- largest power of base that fits in a digit.
-        powbase = widen_digit(base)  # powbase == base ** power
+        powbase = _widen_digit(base)  # powbase == base ** power
         power = 1
         while 1:
             newpow = powbase * base
@@ -1454,14 +1488,14 @@
             power += 1
 
         # Get a scratch area for repeated division.
-        scratch = rbigint([0] * size, 1)
+        scratch = rbigint([NULLDIGIT] * size, 1)
 
         # Repeatedly divide by powbase.
         while 1:
             ntostore = power
             rem = _inplace_divrem1(scratch, pin, powbase, size)
             pin = scratch  # no need to use a again
-            if pin.digits[size - 1] == 0:
+            if pin.digit(size - 1) == 0:
                 size -= 1
 
             # Break rem into digits.
@@ -1538,8 +1572,8 @@
     # iff one of these cases applies, and mask will be non-0 for operands
     # whose length should be ignored.
 
-    size_a = a._numdigits()
-    size_b = b._numdigits()
+    size_a = a.numdigits()
+    size_b = b.numdigits()
     if op == '&':
         if maska:
             size_z = size_b
@@ -1551,23 +1585,23 @@
     else:
         size_z = max(size_a, size_b)
 
-    z = rbigint([0] * size_z, 1)
+    z = rbigint([NULLDIGIT] * size_z, 1)
 
     for i in range(size_z):
         if i < size_a:
-            diga = a.digits[i] ^ maska
+            diga = a.digit(i) ^ maska
         else:
             diga = maska
         if i < size_b:
-            digb = b.digits[i] ^ maskb
+            digb = b.digit(i) ^ maskb
         else:
             digb = maskb
         if op == '&':
-            z.digits[i] = diga & digb
+            z.setdigit(i, diga & digb)
         elif op == '|':
-            z.digits[i] = diga | digb
+            z.setdigit(i, diga | digb)
         elif op == '^':
-            z.digits[i] = diga ^ digb
+            z.setdigit(i, diga ^ digb)
 
     z._normalize()
     if negz == 0:
@@ -1599,10 +1633,10 @@
 
 def _AsULonglong_ignore_sign(v):
     x = r_ulonglong(0)
-    i = v._numdigits() - 1
+    i = v.numdigits() - 1
     while i >= 0:
         prev = x
-        x = (x << SHIFT) + v._digit(i)
+        x = (x << SHIFT) + v.widedigit(i)
         if (x >> SHIFT) != prev:
                 raise OverflowError(
                     "long int too large to convert to unsigned long long int")
@@ -1612,10 +1646,9 @@
 def make_unsigned_mask_conversion(T):
     def _As_unsigned_mask(v):
         x = T(0)
-        i = v._numdigits() - 1
+        i = v.numdigits() - 1
         while i >= 0:
-            prev = x
-            x = (x << SHIFT) + T(v._digit(i))
+            x = (x << SHIFT) + T(v.digit(i))
             i -= 1
         if v.sign < 0:
             x = -x
@@ -1632,18 +1665,18 @@
     # to please decimal.py, we return a hash that satisfies
     # hash(x) == hash(x % ULONG_MAX).  In particular, this
     # implies that hash(x) == hash(x % (2**64-1)).
-    i = v._numdigits() - 1
+    i = v.numdigits() - 1
     sign = v.sign
     x = r_uint(0)
     LONG_BIT_SHIFT = LONG_BIT - SHIFT
     while i >= 0:
         # Force a native long #-bits (32 or 64) circular shift
         x = (x << SHIFT) | (x >> LONG_BIT_SHIFT)
-        x += r_uint(v.digits[i])
+        x += v.udigit(i)
         # If the addition above overflowed we compensate by
         # incrementing.  This preserves the value modulo
         # ULONG_MAX.
-        if x < r_uint(v.digits[i]):
+        if x < v.udigit(i):
             x += 1
         i -= 1
     x = intmask(x * sign)


More information about the Pypy-commit mailing list