[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