[pypy-svn] r10808 - in pypy/dist/pypy/objspace/std: . test
cfbolz at codespeak.net
cfbolz at codespeak.net
Mon Apr 18 02:12:42 CEST 2005
Author: cfbolz
Date: Mon Apr 18 02:12:42 2005
New Revision: 10808
Modified:
pypy/dist/pypy/objspace/std/longobject.py
pypy/dist/pypy/objspace/std/test/test_longobject.py
Log:
Added invert, lshift, rshift to longs.
Modified: pypy/dist/pypy/objspace/std/longobject.py
==============================================================================
--- pypy/dist/pypy/objspace/std/longobject.py (original)
+++ pypy/dist/pypy/objspace/std/longobject.py Mon Apr 18 02:12:42 2005
@@ -170,7 +170,7 @@
i += 1
return space.newbool(True)
-def lt__Long_Long(space, w_long1, w_long2): #YYYYYY
+def lt__Long_Long(space, w_long1, w_long2):
if w_long1.sign > w_long2.sign:
return space.newbool(False)
if w_long1.sign < w_long2.sign:
@@ -257,7 +257,7 @@
raise OperationError(space.w_ZeroDivisionError,
space.wrap("long division"))
z = x / y
- return space.newfloat(float(z))
+ return space.newfloat(z)
def floordiv__Long_Long(space, w_long1, w_long2): #YYYYYY
x = w_long1.longval()
@@ -375,31 +375,83 @@
def nonzero__Long(space, w_long):
return space.newbool(w_long.sign != 0)
-def invert__Long(space, w_long): #YYYYYY
- z = ~w_long.longval()
- return W_LongObject(space, *args_from_long(z))
+def invert__Long(space, w_long): #Implement ~x as -(x + 1)
+ w_lpp = add__Long_Long(space, w_long, W_LongObject(space, [r_uint(1)], 1))
+ return neg__Long(space, w_lpp)
-def lshift__Long_Long(space, w_long1, w_long2): #YYYYYY
- a = w_long1.longval()
- b = w_long2.longval()
- if b < 0:
+def lshift__Long_Long(space, w_long1, w_long2):
+ if w_long2.sign < 0:
raise OperationError(space.w_ValueError,
space.wrap("negative shift count"))
+ elif w_long2.sign == 0:
+ return w_long1
try:
- res = a << b
+ b = int_w__Long(space, w_long2)
except OverflowError: # b too big
raise OperationError(space.w_OverflowError,
space.wrap("shift count too large"))
- return W_LongObject(space, *args_from_long(res))
+ wordshift = b // LONG_BIT
+ remshift = r_uint(b) % LONG_BIT
+ oldsize = len(w_long1.digits)
+ newsize = oldsize + wordshift
+ if remshift != 0:
+ newsize += 1
+ w_result = W_LongObject(space, [r_uint(0)] * newsize, w_long1.sign)
+ rightshift = LONG_BIT - remshift
+ LOWER_MASK = (r_uint(1) << r_uint(rightshift)) - 1
+ UPPER_MASK = ~LOWER_MASK
+ accum = r_uint(0)
+ i = wordshift
+ j = 0
+ while j < oldsize:
+ digit = w_long1.digits[j]
+ w_result.digits[i] = (accum | (digit << remshift))
+ accum = (digit & UPPER_MASK) >> rightshift
+ i += 1
+ j += 1
+ if remshift:
+ w_result.digits[i] = accum
+ else:
+ assert not accum
+ w_result._normalize()
+ return w_result
def rshift__Long_Long(space, w_long1, w_long2): #YYYYYY
- a = w_long1.longval()
- b = w_long2.longval()
- if b < 0:
+ if w_long2.sign < 0:
raise OperationError(space.w_ValueError,
space.wrap("negative shift count"))
- res = a >> b
- return W_LongObject(space, *args_from_long(res))
+ elif w_long2.sign == 0:
+ return w_long1
+ if w_long1.sign == -1:
+ w_a1 = invert__Long(space, w_long1)
+ w_a2 = rshift__Long_Long(space, w_a1, w_long2)
+ return invert__Long(space, w_a2)
+ try:
+ b = int_w__Long(space, w_long2)
+ except OverflowError: # b too big # XXX maybe just return 0L instead?
+ raise OperationError(space.w_OverflowError,
+ space.wrap("shift count too large"))
+ wordshift = b // LONG_BIT
+ remshift = r_uint(b) % LONG_BIT
+ oldsize = len(w_long1.digits)
+ newsize = oldsize - wordshift
+ if newsize <= 0:
+ return W_LongObject(space, [r_uint(0)], 0)
+ w_result = W_LongObject(space, [r_uint(0)] * newsize, 1)
+ leftshift = LONG_BIT - remshift
+ LOWER_MASK = (r_uint(1) << r_uint(remshift)) - 1
+ UPPER_MASK = ~LOWER_MASK
+ accum = r_uint(0)
+ i = newsize - 1
+ j = oldsize - 1
+ while j >= 0:
+ digit = w_long1.digits[j]
+ w_result.digits[i] = (accum | (digit >> remshift))
+ accum = (digit & LOWER_MASK) << leftshift
+ i -= 1
+ j -= 1
+ w_result._normalize()
+ return w_result
def and__Long_Long(space, w_long1, w_long2): #YYYYYY
a = w_long1.longval()
Modified: pypy/dist/pypy/objspace/std/test/test_longobject.py
==============================================================================
--- pypy/dist/pypy/objspace/std/test/test_longobject.py (original)
+++ pypy/dist/pypy/objspace/std/test/test_longobject.py Mon Apr 18 02:12:42 2005
@@ -7,6 +7,15 @@
objspacename = 'std'
+def gen_signs(l):
+ for s in l:
+ if s == 0:
+ yield s
+ else:
+ yield s
+ yield -s
+
+
class TestW_LongObject:
def test_add(self):
@@ -54,13 +63,6 @@
assert not self.space.is_true(lobj.eq__Long_Long(self.space, f1, f3))
def test_lt(self):
- def gen_signs(l):
- for s in l:
- if s == 0:
- yield s
- else:
- yield s
- yield -s
val = [0, 0x111111111111, 0x111111111112, 0x111111111112FFFF]
for x in gen_signs(val):
for y in gen_signs(val):
@@ -159,6 +161,39 @@
assert self.space.is_true(
self.space.eq(lobj.sub__Long_Long(self.space, f1, f1), f0))
+ def test_invert(self):
+ x = 3 ** 40
+ f1 = lobj.W_LongObject(self.space, *lobj.args_from_long(x))
+ f2 = lobj.W_LongObject(self.space, *lobj.args_from_long(-x))
+ r1 = lobj.invert__Long(self.space, f1)
+ r2 = lobj.invert__Long(self.space, f2)
+ assert r1.longval() == -(x + 1)
+ assert r2.longval() == -(-x + 1)
+
+ def test_shift(self):
+ negative = lobj.W_LongObject(self.space, *lobj.args_from_long(-23))
+ big = lobj.W_LongObject(self.space, *lobj.args_from_long(2L ** 100L))
+ for x in gen_signs([3L ** 30L, 5L ** 20L, 7 ** 300, 0L, 1L]):
+ f1 = lobj.W_LongObject(self.space, *lobj.args_from_long(x))
+ self.space.raises_w(self.space.w_ValueError,
+ lobj.lshift__Long_Long, self.space, f1,
+ negative)
+ self.space.raises_w(self.space.w_ValueError,
+ lobj.rshift__Long_Long, self.space, f1,
+ negative)
+ self.space.raises_w(self.space.w_OverflowError,
+ lobj.lshift__Long_Long, self.space, f1,
+ big)
+ self.space.raises_w(self.space.w_OverflowError,
+ lobj.rshift__Long_Long, self.space, f1,
+ big)
+ for y in [0L, 1L, 2304L, 11233L, 3 ** 9]:
+ f2 = lobj.W_LongObject(self.space, *lobj.args_from_long(y))
+ res1 = lobj.lshift__Long_Long(self.space, f1, f2).longval()
+ res2 = lobj.rshift__Long_Long(self.space, f1, f2).longval()
+ assert res1 == x << y
+ assert res2 == x >> y
+
class AppTestLong:
def test_add(self):
assert int(123L + 12443L) == 123 + 12443
@@ -180,3 +215,4 @@
def test_pow(self):
assert pow(0L, 0L, 1L) == 0L
+
More information about the Pypy-commit
mailing list