[pypy-svn] r14385 - pypy/dist/pypy/objspace/std

tismer at codespeak.net tismer at codespeak.net
Thu Jul 7 16:11:28 CEST 2005


Author: tismer
Date: Thu Jul  7 16:11:27 2005
New Revision: 14385

Modified:
   pypy/dist/pypy/objspace/std/longobject.py
Log:
implemented hash()

missing: reimplement pow()

problem: certain division errors are a moving target.
solution: single step in parallel with the C implementation (today)

Modified: pypy/dist/pypy/objspace/std/longobject.py
==============================================================================
--- pypy/dist/pypy/objspace/std/longobject.py	(original)
+++ pypy/dist/pypy/objspace/std/longobject.py	Thu Jul  7 16:11:27 2005
@@ -11,7 +11,7 @@
 # for now, we use r_uint as a digit.
 # we may later switch to r_ushort, when it is supported by rtyper etc.
 
-Digit = r_uint # works: r_ushort
+Digit = r_uint # already works: r_ushort
 Twodigits = r_uint
 Stwodigits = int
 
@@ -26,10 +26,28 @@
     Carryadd = Twodigits
 Carrymul = Twodigits
 
-# masks for normal signed integer
-SIGN_BIT = LONG_BIT-1
-SIGN_MASK = r_uint(1) << SIGN_BIT
-NONSIGN_MASK = ~SIGN_MASK
+# Debugging digit array access.
+#
+# 0 == no check at all
+# 1 == check correct type
+# 2 == check for extra (ab)used bits
+CHECK_DIGITS = 1
+
+if CHECK_DIGITS:
+    class DigitArray(list):
+        if CHECK_DIGITS == 1:
+            def __setitem__(self, idx, value):
+                assert type(value) is Digit
+                list.__setitem__(self, idx, value)
+        elif CHECK_DIGITS == 2:
+            def __setitem__(self, idx, value):
+                assert type(value) is Digit
+                assert value <= MASK
+                list.__setitem__(self, idx, value)
+        else:
+            raise Exception, 'CHECK_DIGITS == %d not supported' % CHECK_DIGITS
+else:
+    DigitArray = list
 
 # XXX some operations below return one of their input arguments
 #     without checking that it's really of type long (and not a subclass).
@@ -44,7 +62,7 @@
         W_Object.__init__(w_self, space)
         if isinstance(digits, long):  #YYYYYY
             digits, sign = args_from_long(digits)
-        w_self.digits = digits
+        w_self.digits = DigitArray(digits)
         w_self.sign = sign
         assert len(w_self.digits)
 
@@ -221,10 +239,8 @@
         i -= 1
     return space.newbool(False)
 
-def hash__Long(space,w_value): #YYYYYY
-    ## %reimplement%
-    # real Implementation should be taken from _Py_HashDouble in object.c
-    return space.wrap(hash(w_value.longval()))
+def hash__Long(space, w_value):
+    return space.wrap(_hash(w_value))
 
 # coerce
 def coerce__Long_Long(space, w_long1, w_long2):
@@ -398,7 +414,7 @@
     z = W_LongObject(space, [Digit(0)] * newsize, a.sign)
     # not sure if we will initialize things in the future?
     for i in range(wordshift):
-        z.digits[i] = 0
+        z.digits[i] = Digit(0)
     accum = Twodigits(0)
     i = wordshift
     j = 0
@@ -765,7 +781,7 @@
 
 def _x_divrem(v1, w1):
     size_w = len(w1.digits)
-    d = (MASK+1) // (w1.digits[size_w-1] + 1)
+    d = Digit(Twodigits(MASK+1) // (w1.digits[size_w-1] + 1))
     v = _muladd1(v1, d, Digit(0))
     w = _muladd1(w1, d, Digit(0))
     size_v = len(v.digits)
@@ -1256,3 +1272,21 @@
     if int(x) < 0 and (sign > 0 or (x << 1) != 0):
             raise OverflowError
     return intmask(int(x) * sign)
+
+def _hash(v):
+    # This is designed so that Python ints and longs with the
+    # same value hash to the same value, otherwise comparisons
+    # of mapping keys will turn out weird
+    i = len(v.digits) - 1
+    sign = v.sign
+    x = 0
+    LONG_BIT_SHIFT = LONG_BIT - SHIFT
+    while i >= 0:
+        # Force a native long #-bits (32 or 64) circular shift
+        x = ((x << SHIFT) & ~MASK) | ((x >> LONG_BIT_SHIFT) & MASK)
+        x += v.digits[i]
+        i -= 1
+    x = intmask(x * sign)
+    if x == -1:
+        x = -2
+    return x



More information about the Pypy-commit mailing list