[pypy-svn] r14323 - in pypy/dist/pypy/objspace/std: . test

tismer at codespeak.net tismer at codespeak.net
Wed Jul 6 00:40:41 CEST 2005


Author: tismer
Date: Wed Jul  6 00:40:40 2005
New Revision: 14323

Modified:
   pypy/dist/pypy/objspace/std/longobject.py
   pypy/dist/pypy/objspace/std/test/test_longobject.py
Log:
quite a lot more is implemented,
basically hash and pow are missing.
remaining problem:
there is still a special case where we overflow.
the intermediate "q" has one bit more.
See the comments in longintrepr.h; I fear we finally
need tobite and use 15 b

Modified: pypy/dist/pypy/objspace/std/longobject.py
==============================================================================
--- pypy/dist/pypy/objspace/std/longobject.py	(original)
+++ pypy/dist/pypy/objspace/std/longobject.py	Wed Jul  6 00:40:40 2005
@@ -435,31 +435,20 @@
     w_result._normalize()
     return w_result
 
-def and__Long_Long(space, w_long1, w_long2): #YYYYYY
-    a = w_long1.longval()
-    b = w_long2.longval()
-    res = a & b
-    return W_LongObject(space, *args_from_long(res))
-
-def xor__Long_Long(space, w_long1, w_long2): #YYYYYY
-    a = w_long1.longval()
-    b = w_long2.longval()
-    res = a ^ b
-    return W_LongObject(space, *args_from_long(res))
-
-def or__Long_Long(space, w_long1, w_long2): #YYYYYY
-    a = w_long1.longval()
-    b = w_long2.longval()
-    res = a | b
-    return W_LongObject(space, *args_from_long(res))
-
-def oct__Long(space, w_long1): #YYYYYY
-    x = w_long1.longval()
-    return space.wrap(oct(x))
-
-def hex__Long(space, w_long1): #YYYYYY
-    x = w_long1.longval()
-    return space.wrap(hex(x))
+def and__Long_Long(space, w_long1, w_long2):
+    return _bitwise(w_long1, '&', w_long2)
+
+def xor__Long_Long(space, w_long1, w_long2):
+    return _bitwise(w_long1, '^', w_long2)
+
+def or__Long_Long(space, w_long1, w_long2):
+    return _bitwise(w_long1, '|', w_long2)
+
+def oct__Long(space, w_long1):
+    return space.wrap(_format(w_long1, 8, True))
+
+def hex__Long(space, w_long1):
+    return space.wrap(_format(w_long1, 16, True))
 
 def getnewargs__Long(space, w_long1):
     return space.newtuple([W_LongObject(space, w_long1.digits, w_long1.sign)])
@@ -794,7 +783,6 @@
                                 ) << SHORT_BIT)
                 + v._getshort(j-2)):
             q -= 1
-            print '***', q##!!
         i = 0
         while i < size_w and i+k < size_v:
             z = w._getshort(i) * q
@@ -1015,7 +1003,7 @@
 
     assert base >= 2 and base <= 36
 
-    sign = chr(0)
+    sign = False
 
     # Compute a rough upper bound for the length of the string
     i = base
@@ -1030,7 +1018,7 @@
         p -= 1
         s[p] = 'L'
     if a.sign < 0:
-        sign = '-'
+        sign = True
 
     if a.sign == 0:
         p -= 1
@@ -1137,7 +1125,7 @@
             s[p] = chr(ord('0') + base // 10)
     if sign:
         p -= 1
-        s[p] = sign
+        s[p] = '-'
 
     if p == 0:
         return ''.join(s)
@@ -1145,3 +1133,83 @@
         return ''.join(s[p:])
 
 
+def _bitwise(a, op, n): # '&', '|', '^'
+    """ Bitwise and/xor/or operations """
+
+    if a.sign < 0:
+        a = invert__Long(a.space, a)
+        maska = r_uint(SHORT_MASK)
+    else:
+        maska = r_uint(0)
+    if b.sign < 0:
+        b = invert__Long(b.space, b)
+        maskb = r_uint(SHORT_MASK)
+    else:
+        maskb = r_uint(0)
+
+    negz = 0
+    if op == '^':
+        if maska != maskb:
+            maska ^= SHORT_MASK
+            negz = -1
+    elif op == '&':
+        if maska and maskb:
+            op = '|'
+            maska ^= SHORT_MASK
+            maskb ^= SHORT_MASK
+            negz = -1
+    elif op == '|':
+        if maska or maskb:
+            op = '&'
+            maska ^= SHORT_MASK
+            maskb ^= SHORT_MASK
+            negz = -1
+
+    # JRH: The original logic here was to allocate the result value (z)
+    # as the longer of the two operands.  However, there are some cases
+    # where the result is guaranteed to be shorter than that: AND of two
+    # positives, OR of two negatives: use the shorter number.  AND with
+    # mixed signs: use the positive number.  OR with mixed signs: use the
+    # negative number.  After the transformations above, op will be '&'
+    # iff one of these cases applies, and mask will be non-0 for operands
+    # whose length should be ignored.
+
+    size_a = len(a.digits) * 2
+    if a._getshort(size_a - 1) == 0:
+        size_a -= 1
+    if b._getshort(size_b - 1) == 0:
+        size_b -= 1
+    if op == '&':
+        if maska:
+            size_z = size_b
+        else:
+            if maskb:
+                size_z = size_a
+            else:
+                size_z = min(size_a, size_b)
+    else:
+        size_z = max(size_a, size_b)
+
+    digitpairs = (size_z + 1) // 2
+    z = W_LongObject(a.space, [r_uint(0)] * digitpairs, 1)
+
+    for i in range(size_z):
+        if i < size_a:
+            diga = a._getshort(i) ^ maska
+        else:
+            diga = maska
+        if i < size_b:
+            digb = b._getshort(i) ^ maskb
+        else:
+            digb = maskb
+        if op == '&':
+            z._setshort(i, diga & digb)
+        elif op == '|':
+            z._setshort(i, diga | digb)
+        elif op == '^':
+            z._setshort(i, diga ^ digb)
+
+    z_normalize()
+    if negz == 0:
+        return z
+    return invert__Long(z)

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	Wed Jul  6 00:40:40 2005
@@ -161,7 +161,7 @@
 
     def test_conversions(self):
         space = self.space
-        for v in (0,1,-1,sys.maxint,-sys.maxint-1):
+        for v in (0, 1, -1, sys.maxint, -sys.maxint-1):
             assert lobj.W_LongObject(self.space, *lobj.args_from_long(v)).longval() == v
             w_v = space.newint(v)
             for w_lv in (lobj.long__Int(space, w_v), lobj.delegate_Int2Long(w_v)):
@@ -319,9 +319,15 @@
             for y in [-105566530L, -1L, 1L, 1034522340L]:
                 print "checking division for %s, %s" % (x, y)
                 check_division(x, y)
-            raises(ZeroDivisionError, "x // 0L")
-
-    def test_str(self):
-        assert str(-123456789L) == "-123456789"
-        assert str(123456789L) == "123456789"
-        
+        # special case from python tests:
+        x = 16565645174462751485571442763871865344588923363439663038777355323778298703228675004033774331442052275771343018700586987657790981527457655176938756028872904152013524821759375058141439
+        y = 10953035502453784575
+        print "special case"
+        check_division(x, y)
+        raises(ZeroDivisionError, "x // 0L")
+
+    def test_format(self):
+        assert repr(12345678901234567890) == '12345678901234567890L'
+        assert str(12345678901234567890) == '12345678901234567890'
+        assert hex(0x1234567890ABCDEFL) == '0x1234567890ABCDEFL'
+        assert oct(01234567012345670L) == '01234567012345670L'



More information about the Pypy-commit mailing list