[pypy-commit] pypy improve-rbigint: Fix a test, fix so all tests passes, and some improvements.

stian noreply at buildbot.pypy.org
Sat Jul 21 18:41:23 CEST 2012


Author: stian
Branch: improve-rbigint
Changeset: r56335:a503b84e2d2f
Date: 2012-06-26 00:44 +0200
http://bitbucket.org/pypy/pypy/changeset/a503b84e2d2f/

Log:	Fix a test, fix so all tests passes, and some improvements.

	Minor impact on performance, some become faster, some slower. I'll
	see how it turns out in a translated version.

diff --git a/pypy/rlib/rarithmetic.py b/pypy/rlib/rarithmetic.py
--- a/pypy/rlib/rarithmetic.py
+++ b/pypy/rlib/rarithmetic.py
@@ -115,26 +115,25 @@
         n -= 2*LONG_TEST
     return int(n)
 
-def longlongmask(n):
-    """
-    NOT_RPYTHON
-    """
-    assert isinstance(n, (int, long))
-    n = long(n)
-    n &= LONGLONG_MASK
-    if n >= LONGLONG_TEST:
-        n -= 2*LONGLONG_TEST
-    return r_longlong(n)
+if LONG_BIT >= 64:
+    def longlongmask(n):
+        assert isinstance(n, (int, long))
+        return int(n)
+else:
+    def longlongmask(n):
+        """
+        NOT_RPYTHON
+        """
+        assert isinstance(n, (int, long))
+        n = long(n)
+        n &= LONGLONG_MASK
+        if n >= LONGLONG_TEST:
+            n -= 2*LONGLONG_TEST
+        return r_longlong(n)
 
 def longlonglongmask(n):
-    """
-    NOT_RPYTHON
-    """
-    assert isinstance(n, (int, long))
-    n = long(n)
-    n &= LONGLONGLONG_MASK
-    if n >= LONGLONGLONG_TEST:
-        n -= 2*LONGLONGLONG_TEST
+    # Assume longlonglong doesn't overflow. This is perfectly fine for rbigint.
+    # We deal directly with overflow there anyway.
     return r_longlonglong(n)
 
 def widen(n):
diff --git a/pypy/rlib/rbigint.py b/pypy/rlib/rbigint.py
--- a/pypy/rlib/rbigint.py
+++ b/pypy/rlib/rbigint.py
@@ -1,4 +1,4 @@
-from pypy.rlib.rarithmetic import LONG_BIT, intmask, longlongmask, r_uint, r_ulonglong, r_longlonglong
+from pypy.rlib.rarithmetic import LONG_BIT, intmask, longlongmask, r_uint, r_int, r_ulonglong, r_longlonglong
 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
@@ -55,10 +55,11 @@
 def _widen_digit(x):
     """if not we_are_translated():
         assert is_valid_int(x), "widen_digit() takes an int, got a %r" % type(x)"""
-    return r_longlonglong(x)
-    """if LONG_BIT < 64:
+    if SHIFT > 31:
+        # XXX: Using rffi.cast is probably quicker, but I dunno how to get it working.
+        return r_longlonglong(x)
+    else:
         return r_longlong(x)
-    return x"""
 
 def _store_digit(x):
     """if not we_are_translated():
@@ -71,14 +72,22 @@
         return rffi.cast(rffi.LONGLONG, x)
     else:
         raise ValueError("SHIFT too large!")
+_store_digit._annspecialcase_ = 'specialize:argtype(0)'
 
 def _load_digit(x):
-    return x
-    #return rffi.cast(lltype.Signed, x)
+    if SHIFT < LONG_BIT: # This would be the case for any SHIFT < LONG_BIT
+        return rffi.cast(lltype.Signed, x)
+    else:
+        # x already is a type large enough, just not as fast.
+        return x
 
 def _load_unsigned_digit(x):
-    return r_ulonglong(x)
-    #return rffi.cast(lltype.Unsigned, x)
+    if SHIFT < LONG_BIT: # This would be the case for any SHIFT < LONG_BIT
+        return rffi.cast(lltype.Unsigned, x)
+    else:
+        # This needs a performance test on 32bit
+        return rffi.cast(rffi.ULONGLONG, x)
+        #return r_ulonglong(x)
 
 NULLDIGIT = _store_digit(0)
 ONEDIGIT  = _store_digit(1)
@@ -86,8 +95,7 @@
 def _check_digits(l):
     for x in l:
         assert type(x) is type(NULLDIGIT)
-        # XXX: Fix for int128
-        # assert intmask(x) & MASK == intmask(x)
+        assert longlongmask(x) & MASK == longlongmask(x)
             
 class Entry(extregistry.ExtRegistryEntry):
     _about_ = _check_digits
@@ -621,7 +629,7 @@
         return rbigint(self._digits, abs(self.sign))
 
     def invert(self): #Implement ~x as -(x + 1)
-        return self.add(rbigint([_store_digit(1)], 1)).neg()
+        return self.add(ONERBIGINT).neg()
 
     def lshift(self, int_other):
         if int_other < 0:
@@ -783,7 +791,7 @@
 
 INTCACHE = {}
 for x in range(1, CACHE_INTS+1):
-    numList = [_store_digit(x)]
+    numList = [_store_digit(_mask_digit(x))]
     INTCACHE[x] = rbigint(numList, 1)
     INTCACHE[-x] = rbigint(numList, -1)
     
@@ -811,7 +819,7 @@
 def digits_from_nonneg_long(l):
     digits = []
     while True:
-        digits.append(_store_digit(intmask(l & MASK)))
+        digits.append(_store_digit(_mask_digit(l & MASK)))
         l = l >> SHIFT
         if not l:
             return digits[:] # to make it non-resizable
@@ -894,7 +902,7 @@
     
     # Special casing.
     if a is b:
-        return rbigint([NULLDIGIT], 1)
+        return NULLRBIGINT
     
     size_a = a.numdigits()
     size_b = b.numdigits()
@@ -1425,12 +1433,11 @@
     d = (r_ulonglong(MASK)+1) // (w1.udigit(size_w-1) + 1)
     assert d <= MASK    # because the first digit of w1 is not zero
     d = longlongmask(d)
-    assert d != 0
     v = _muladd1(v1, d)
     w = _muladd1(w1, d)
     size_v = v.numdigits()
     size_w = w.numdigits()
-    assert size_v >= size_w and size_w > 1 # Assert checks by div()
+    assert size_v >= size_w and size_w >= 1 # (stian: Adding d doesn't necessary mean it will increase by 1), Assert checks by div()
 
     size_a = size_v - size_w + 1
     a = rbigint([NULLDIGIT] * size_a, 1)
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,7 +3,7 @@
 import operator, sys, array
 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.rbigint import _store_digit, _mask_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
@@ -120,7 +120,7 @@
 def bigint(lst, sign):
     for digit in lst:
         assert digit & MASK == digit    # wrongly written test!
-    return rbigint(map(_store_digit, lst), sign)
+    return rbigint(map(_store_digit, map(_mask_digit, lst)), sign)
 
 
 class Test_rbigint(object):
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
@@ -23,17 +23,18 @@
         6.647562
 
         Pypy with improvements:
-        2.085952
-        4.318238
-        9.753659
-        1.641015
-        3.983455
-        5.787758
-        7.573468
-        0.042393
-        4.436702
-        9.103529
-        5.036710
+        2.126048
+        4.276203
+        9.662745
+        1.621029
+        3.956685
+        5.752223
+        7.660295
+        0.039137
+        4.437456
+        9.078680
+        4.995520
+
 
     """
 


More information about the pypy-commit mailing list