[pypy-commit] pypy improve-rbigint: Revert _tc_mul to the best version and remove check_nonneg (it did't clear when compiling in jit mode)

stian noreply at buildbot.pypy.org
Sat Jul 21 18:42:08 CEST 2012


Author: stian
Branch: improve-rbigint
Changeset: r56374:9bc690be669e
Date: 2012-07-19 05:06 +0200
http://bitbucket.org/pypy/pypy/changeset/9bc690be669e/

Log:	Revert _tc_mul to the best version and remove check_nonneg (it did't
	clear when compiling in jit mode)

diff --git a/pypy/rlib/rbigint.py b/pypy/rlib/rbigint.py
--- a/pypy/rlib/rbigint.py
+++ b/pypy/rlib/rbigint.py
@@ -2,7 +2,7 @@
 from pypy.rlib.rarithmetic import ovfcheck, r_longlong, widen, is_valid_int
 from pypy.rlib.rarithmetic import most_neg_value_of_same_type
 from pypy.rlib.rfloat import isfinite
-from pypy.rlib.debug import make_sure_not_resized, check_regular_int, check_nonneg
+from pypy.rlib.debug import make_sure_not_resized, check_regular_int
 from pypy.rlib.objectmodel import we_are_translated, specialize
 from pypy.rlib import jit
 from pypy.rpython.lltypesystem import lltype, rffi
@@ -116,6 +116,7 @@
             _check_digits(digits)
         make_sure_not_resized(digits)
         self._digits = digits
+        assert size >= 0
         self.size = size or len(digits)
         self.sign = sign
 
@@ -143,7 +144,7 @@
     setdigit._always_inline_ = True
 
     def numdigits(self):
-        return check_nonneg(self.size)
+        return self.size
     numdigits._always_inline_ = True
     
     @staticmethod
@@ -1118,7 +1119,7 @@
     return z
 
 
-def _tcmul_split(n, size):
+def _tcmul_split(n):
     """
     A helper for Karatsuba multiplication (k_mul).
     Takes a bigint "n" and an integer "size" representing the place to
@@ -1127,15 +1128,15 @@
     the return values are >= 0.
     """
     size_n = n.numdigits() // 3
-    size_lo = min(size_n, size)
-    lo = rbigint(n._digits[:size_lo], 1)
-    mid = rbigint(n._digits[size_lo:size_lo * 2], 1)
-    hi = rbigint(n._digits[size_lo *2:], 1)
+    lo = rbigint(n._digits[:size_n], 1)
+    mid = rbigint(n._digits[size_n:size_n * 2], 1)
+    hi = rbigint(n._digits[size_n *2:], 1)
     lo._normalize()
     mid._normalize()
     hi._normalize()
     return hi, mid, lo
 
+THREERBIGINT = rbigint.fromint(3)
 def _tc_mul(a, b):
     """
     Toom Cook
@@ -1144,8 +1145,8 @@
     bsize = b.numdigits()
 
     # Split a & b into hi, mid and lo pieces.
-    shift = (2+bsize) // 3
-    ah, am, al = _tcmul_split(a, shift)
+    shift = bsize // 3
+    ah, am, al = _tcmul_split(a)
     assert ah.sign == 1    # the split isn't degenerate
 
     if a is b:
@@ -1153,58 +1154,54 @@
         bm = am
         bl = al
     else:
-        bh, bm, bl = _tcmul_split(b, shift)
+        bh, bm, bl = _tcmul_split(b)
+        
     # 2. ahl, bhl
-    ahl = _x_add(al, ah)
-    bhl = _x_add(bl, bh)
-    
+    ahl = al.add(ah)
+    bhl = bl.add(bh)
+
     # Points
     v0 = al.mul(bl)
-    vn1 = ahl.sub(am).mul(bhl.sub(bm))
-    
-    ahml = _x_add(ahl, am)
-    bhml = _x_add(bhl, bm)
-    
-    v1 = ahml.mul(bhml)
-    v2 = _x_add(ahml, ah).lshift(1).sub(al).mul(_x_add(bhml, bh).lshift(1).sub(bl))
+    v1 = ahl.add(bm).mul(bhl.add(bm))
+
+    vn1 = ahl.sub(bm).mul(bhl.sub(bm))
+    v2 = al.add(am.lqshift(1)).add(ah.lshift(2)).mul(bl.add(bm.lqshift(1)).add(bh.lqshift(2)))
+
     vinf = ah.mul(bh)
-    
-    t2 = _x_sub(v2, vn1)
-    _inplace_divrem1(t2, t2, 3)
-    tn1 = v1.sub(vn1)
-    _v_rshift(tn1, tn1, tn1.numdigits(), 1)
-    t1 = v1
-    _v_isub(t1, 0, t1.numdigits(), v0, v0.numdigits())
-    _v_isub(t2, 0, t2.numdigits(), t1, t1.numdigits())
+
+    # Construct
+    t1 = v0.mul(THREERBIGINT).add(vn1.lqshift(1)).add(v2)
+    _inplace_divrem1(t1, t1, 6)
+    t1 = t1.sub(vinf.lqshift(1))
+    t2 = v1
+    _v_iadd(t2, 0, t2.numdigits(), vn1, vn1.numdigits())
     _v_rshift(t2, t2, t2.numdigits(), 1)
-    _v_isub(t1, 0, t1.numdigits(), tn1, tn1.numdigits())
-    _v_isub(t1, 0, t1.numdigits(), vinf, vinf.numdigits())
-    
-    t2 = t2.sub(vinf.lshift(1))
-    _v_isub(tn1, 0, tn1.numdigits(), t2, t2.numdigits())
-    
+
+    r1 = v1.sub(t1)
+    r2 = t2
+    _v_isub(r2, 0, r2.numdigits(), v0, v0.numdigits())
+    r2 = r2.sub(vinf)
+    r3 = t1
+    _v_isub(r3, 0, r3.numdigits(), t2, t2.numdigits())
+
     # Now we fit t+ t2 + t4 into the new string.
     # Now we got to add the r1 and r3 in the mid shift.
     # Allocate result space.
     ret = rbigint([NULLDIGIT] * (4 * shift + vinf.numdigits() + 1), 1)  # This is because of the size of vinf
     
     ret._digits[:v0.numdigits()] = v0._digits
-    #print ret.numdigits(), r2.numdigits(), vinf.numdigits(), shift, shift * 5, asize, bsize
-    #print r2.sign >= 0
     assert t2.sign >= 0
-    #print 2*shift + r2.numdigits() < ret.numdigits()
     assert 2*shift + t2.numdigits() < ret.numdigits()
-    ret._digits[shift * 2:shift * 2+t2.numdigits()] = t2._digits
-    #print vinf.sign >= 0
+    ret._digits[shift * 2:shift * 2+r2.numdigits()] = r2._digits
     assert vinf.sign >= 0
-    #print 4*shift + vinf.numdigits() <= ret.numdigits()
     assert 4*shift + vinf.numdigits() <= ret.numdigits()
     ret._digits[shift*4:shift*4+vinf.numdigits()] = vinf._digits
 
 
     i = ret.numdigits() - shift
-    _v_iadd(ret, shift, i, tn1, tn1.numdigits())
-    _v_iadd(ret, shift * 3, i, t1, t1.numdigits())
+    _v_iadd(ret, shift * 3, i, r3, r3.numdigits())
+    _v_iadd(ret, shift, i, r1, r1.numdigits())
+    
 
     ret._normalize()
     return ret
diff --git a/pypy/translator/goal/targetbigintbenchmark.py b/pypy/translator/goal/targetbigintbenchmark.py
--- a/pypy/translator/goal/targetbigintbenchmark.py
+++ b/pypy/translator/goal/targetbigintbenchmark.py
@@ -78,7 +78,7 @@
     sumTime = 0.0
     
     
-    """ t = time()
+    """t = time()
     by = rbigint.fromint(2**62).lshift(1030000)
     for n in xrange(5000):
         by2 = by.lshift(63)


More information about the pypy-commit mailing list