[pypy-commit] pypy improve-rbigint: Revert changes to rshift, and change a test so it fails, and fix it. All tests should now pass

Stian Andreassen noreply at buildbot.pypy.org
Thu Aug 23 06:16:21 CEST 2012


Author: Stian Andreassen
Branch: improve-rbigint
Changeset: r56815:31d713444087
Date: 2012-08-23 06:15 +0200
http://bitbucket.org/pypy/pypy/changeset/31d713444087/

Log:	Revert changes to rshift, and change a test so it fails, and fix it.
	All tests should now pass

diff --git a/pypy/rlib/rbigint.py b/pypy/rlib/rbigint.py
--- a/pypy/rlib/rbigint.py
+++ b/pypy/rlib/rbigint.py
@@ -21,7 +21,6 @@
 #SHIFT = (LONG_BIT // 2) - 1
 if SUPPORT_INT128:
     SHIFT = 63
-    BASE = long(1 << SHIFT)
     UDIGIT_TYPE = r_ulonglong
     if LONG_BIT >= 64:
         UDIGIT_MASK = intmask
@@ -36,14 +35,13 @@
         UNSIGNED_TYPE = rffi.ULONGLONG
 else:
     SHIFT = 31
-    BASE = int(1 << SHIFT)
     UDIGIT_TYPE = r_uint
     UDIGIT_MASK = intmask
     STORE_TYPE = lltype.Signed
     UNSIGNED_TYPE = lltype.Unsigned
     LONG_TYPE = rffi.LONGLONG
 
-MASK = BASE - 1
+MASK = int((1 << SHIFT) - 1)
 FLOAT_MULTIPLIER = float(1 << SHIFT)
 
 # Debugging digit array access.
@@ -762,27 +760,24 @@
         elif int_other == 0:
             return self
         if self.sign == -1 and not dont_invert:
-            a1 = self.invert()
-            a2 = a1.rshift(int_other)
-            return a2.invert()
+            a = self.invert().rshift(int_other)
+            return a.invert()
 
-        wordshift = int_other // SHIFT
+        wordshift = int_other / SHIFT
         newsize = self.numdigits() - wordshift
         if newsize <= 0:
             return NULLRBIGINT
 
         loshift = int_other % SHIFT
         hishift = SHIFT - loshift
-        # Not 100% sure here, but the reason why it won't be a problem is because
-        # int is max 63bit, same as our SHIFT now.
-        #lomask = UDIGIT_MASK((UDIGIT_TYPE(1) << hishift) - 1)
-        #himask = MASK ^ lomask
+        lomask = (1 << hishift) - 1
+        himask = MASK ^ lomask
         z = rbigint([NULLDIGIT] * newsize, self.sign, newsize)
         i = 0
         while i < newsize:
-            newdigit = (self.udigit(wordshift) >> loshift) #& lomask
+            newdigit = (self.digit(wordshift) >> loshift) & lomask
             if i+1 < newsize:
-                newdigit += (self.udigit(wordshift+1) << hishift) #& himask
+                newdigit |= (self.digit(wordshift+1) << hishift) & himask
             z.setdigit(i, newdigit)
             i += 1
             wordshift += 1
@@ -1408,7 +1403,6 @@
     if not size:
         size = pin.numdigits()
     size -= 1
-    
     while size >= 0:
         rem = (rem << SHIFT) | pin.widedigit(size)
         hi = rem // n
@@ -1438,7 +1432,7 @@
     x[m-1], and the remaining carry (0 or 1) is returned.
     Python adaptation: x is addressed relative to xofs!
     """
-    carry = r_uint(0)
+    carry = UDIGIT_TYPE(0)
 
     assert m >= n
     i = _load_unsigned_digit(xofs)
@@ -1463,7 +1457,7 @@
     far as x[m-1], and the remaining borrow (0 or 1) is returned.
     Python adaptation: x is addressed relative to xofs!
     """
-    borrow = r_uint(0)
+    borrow = UDIGIT_TYPE(0)
 
     assert m >= n
     i = _load_unsigned_digit(xofs)
@@ -1559,13 +1553,17 @@
     """ Now v->ob_digit[size_v-1] < w->ob_digit[size_w-1], so quotient has
         at most (and usually exactly) k = size_v - size_w digits. """
     k = size_v - size_w
+    if k == 0:
+        return NULLRBIGINT, v1
+    
     assert k > 0
     a = rbigint([NULLDIGIT] * k, 1, k)
     
-    wm1 = w.digit(abs(size_w-1))
+    wm1 = w.widedigit(abs(size_w-1))
     wm2 = w.widedigit(abs(size_w-2))
 
-    j = size_v
+    j = size_v - 1
+    k -= 1
     while k >= 0:
         assert j >= 0
         """ inner loop: divide vk[0:size_w+1] by w0[0:size_w], giving
@@ -1575,17 +1573,15 @@
         if j >= size_v:
             vtop = 0
         else:
-            vtop = v.digit(j)
+            vtop = v.widedigit(j)
         assert vtop <= wm1
         vv = (vtop << SHIFT) | v.widedigit(abs(j-1))
-        q = UDIGIT_MASK(vv / wm1)
+        q = vv / wm1
         r = vv - wm1 * q
         while wm2 * q > ((r << SHIFT) | v.widedigit(abs(j-2))):
             q -= 1
             r += wm1
-            if r > MASK:
-                break
-                
+            
         assert q < MASK
         
         # subtract q*w0[0:size_w] from vk[0:size_w+1]
@@ -1609,9 +1605,10 @@
             q -= 1
             
         # store quotient digit
+        a.setdigit(k, q)
         k -= 1
         j -= 1
-        a.setdigit(k, q)
+        
         
     carry = _v_rshift(w, v, size_w, d)
     assert carry == 0
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
@@ -547,7 +547,7 @@
         Rx = 1 << 130
         Rx2 = 1 << 150
         Ry = 1 << 127
-        Ry2 = 1<< 130
+        Ry2 = 1<< 150
         for i in range(10):
             x = long(randint(Rx, Rx2))
             y = long(randint(Ry, Ry2))


More information about the pypy-commit mailing list