[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