[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