[pypy-commit] pypy default: Optimized eq- and hash-method in SmallTupleObject

l.diekmann noreply at buildbot.pypy.org
Wed May 25 16:47:46 CEST 2011


Author: Lukas Diekmann <lukas.diekmann at uni-duesseldorf.de>
Branch: 
Changeset: r44438:b16b79d718eb
Date: 2011-04-06 11:47 +0200
http://bitbucket.org/pypy/pypy/changeset/b16b79d718eb/

Log:	Optimized eq- and hash-method in SmallTupleObject

diff --git a/pypy/objspace/std/smalltupleobject.py b/pypy/objspace/std/smalltupleobject.py
--- a/pypy/objspace/std/smalltupleobject.py
+++ b/pypy/objspace/std/smalltupleobject.py
@@ -20,6 +20,15 @@
     def length(self):
         raise NotImplementedError
 
+    def getitem(self, index):
+        raise NotImplementedError
+
+    def hash(self):
+        raise NotImplementedError
+
+    def eq(self, w_other):
+        raise NotImplementedError
+
 def make_specialized_class(n):
     iter_n = unrolling_iterable(range(n))
     class cls(W_SmallTupleObject):
@@ -44,6 +53,29 @@
                     return getattr(self,'w_value%s' % i)
             raise IndexError
 
+        def eq(self, space, w_other):
+            if self.length() != w_other.length():
+                return space.w_False
+            for i in iter_n:
+                item1 = self.getitem(i)
+                item2 = w_other.getitem(i)
+                if not space.eq_w(item1, item2):
+                    return space.w_False
+            return space.w_True
+
+        def hash(self, space):
+            mult = 1000003
+            x = 0x345678
+            z = self.length()
+            for i in iter_n:
+                w_item = self.getitem(i)
+                y = space.int_w(space.hash(w_item))
+                x = (x ^ y) * mult
+                z -= 1
+                mult += 82520 + z + z
+            x += 97531
+            return space.wrap(intmask(x))
+
     cls.__name__ = "W_SmallTupleObject%s" % n
     return cls
 
@@ -102,27 +134,10 @@
     return mul_smalltuple_times(space, w_tuple, w_times)
 
 def eq__SmallTuple_SmallTuple(space, w_tuple1, w_tuple2):
-    if w_tuple1.length() != w_tuple2.length():
-        return space.w_False
-    for i in range(w_tuple1.length()):
-        item1 = w_tuple1.getitem(i)
-        item2 = w_tuple2.getitem(i)
-        if not space.eq_w(item1, item2):
-            return space.w_False
-    return space.w_True
+    return w_tuple1.eq(space, w_tuple2)
 
 def hash__SmallTuple(space, w_tuple):
-    # this is the CPython 2.4 algorithm (changed from 2.3)
-    mult = 1000003
-    x = 0x345678
-    z = w_tuple.length()
-    for w_item in w_tuple.tolist():     #XXX: remove list and run through items directly, later
-        y = space.int_w(space.hash(w_item))
-        x = (x ^ y) * mult
-        z -= 1
-        mult += 82520 + z + z
-    x += 97531
-    return space.wrap(intmask(x))
+    return w_tuple.hash(space)
 
 from pypy.objspace.std import tupletype
 register_all(vars(), tupletype)
diff --git a/pypy/objspace/std/test/test_smalltupleobject.py b/pypy/objspace/std/test/test_smalltupleobject.py
--- a/pypy/objspace/std/test/test_smalltupleobject.py
+++ b/pypy/objspace/std/test/test_smalltupleobject.py
@@ -44,11 +44,17 @@
         b = (1,2,3)
         assert a == b
 
+        c = (1,3,2)
+        assert a != c
+
     def test_hash(self):
         a = (1,2,3)
         b = (1,2,3)
         assert hash(a) == hash(b)
 
+        c = (1,3,2)
+        assert hash(a) != hash(c)
+
 class TestW_SmallTupleObject():
 
     def setup_class(cls):


More information about the pypy-commit mailing list