[pypy-commit] pypy default: merge dtype record hash, based on pr#242 (yuyichao)
mattip
noreply at buildbot.pypy.org
Tue Jul 8 05:16:42 CEST 2014
Author: mattip <matti.picus at gmail.com>
Branch:
Changeset: r72380:f20ac16753b6
Date: 2014-07-08 13:15 +1000
http://bitbucket.org/pypy/pypy/changeset/f20ac16753b6/
Log: merge dtype record hash, based on pr#242 (yuyichao)
diff --git a/pypy/module/micronumpy/descriptor.py b/pypy/module/micronumpy/descriptor.py
--- a/pypy/module/micronumpy/descriptor.py
+++ b/pypy/module/micronumpy/descriptor.py
@@ -6,7 +6,7 @@
from pypy.interpreter.typedef import (TypeDef, GetSetProperty,
interp_attrproperty, interp_attrproperty_w)
from rpython.rlib import jit
-from rpython.rlib.objectmodel import specialize
+from rpython.rlib.objectmodel import specialize, compute_hash
from rpython.rlib.rarithmetic import r_longlong, r_ulonglong
from pypy.module.micronumpy import types, boxes, base, support, constants as NPY
from pypy.module.micronumpy.appbridge import get_appbridge_cache
@@ -254,8 +254,38 @@
def descr_ne(self, space, w_other):
return space.wrap(not self.eq(space, w_other))
+ def _compute_hash(self, space, x):
+ from rpython.rlib.rarithmetic import intmask
+ if self.fields is None and self.subdtype is None:
+ endian = self.byteorder
+ if endian == NPY.NATIVE:
+ endian = NPY.NATBYTE
+ flags = 0
+ y = 0x345678
+ y = intmask((1000003 * y) ^ ord(self.kind[0]))
+ y = intmask((1000003 * y) ^ ord(endian[0]))
+ y = intmask((1000003 * y) ^ flags)
+ y = intmask((1000003 * y) ^ self.elsize)
+ if self.is_flexible():
+ y = intmask((1000003 * y) ^ self.alignment)
+ return intmask((1000003 * x) ^ y)
+ if self.fields is not None:
+ for name, (offset, subdtype) in self.fields.iteritems():
+ assert isinstance(subdtype, W_Dtype)
+ y = intmask(1000003 * (0x345678 ^ compute_hash(name)))
+ y = intmask(1000003 * (y ^ compute_hash(offset)))
+ y = intmask(1000003 * (y ^ subdtype._compute_hash(space,
+ 0x345678)))
+ x = intmask(x ^ y)
+ if self.subdtype is not None:
+ for s in self.shape:
+ x = intmask((1000003 * x) ^ compute_hash(s))
+ x = self.base._compute_hash(space, x)
+ return x
+
def descr_hash(self, space):
- return space.hash(self.descr_reduce(space))
+ return space.wrap(self._compute_hash(space, 0x345678))
+
def descr_str(self, space):
if self.fields:
diff --git a/pypy/module/micronumpy/test/test_dtypes.py b/pypy/module/micronumpy/test/test_dtypes.py
--- a/pypy/module/micronumpy/test/test_dtypes.py
+++ b/pypy/module/micronumpy/test/test_dtypes.py
@@ -368,15 +368,30 @@
d5 = numpy.dtype([('f0', 'i4'), ('f1', d2)])
d6 = numpy.dtype([('f0', 'i4'), ('f1', d3)])
import sys
- if '__pypy__' not in sys.builtin_module_names:
- assert hash(d1) == hash(d2)
- assert hash(d1) != hash(d3)
- assert hash(d4) == hash(d5)
- assert hash(d4) != hash(d6)
- else:
- for d in [d1, d2, d3, d4, d5, d6]:
- raises(TypeError, hash, d)
+ assert hash(d1) == hash(d2)
+ assert hash(d1) != hash(d3)
+ assert hash(d4) == hash(d5)
+ assert hash(d4) != hash(d6)
+ def test_record_hash(self):
+ from numpy import dtype
+ # make sure the fields hash return different value
+ # for different order of field in a structure
+
+ # swap names
+ t1 = dtype([('x', '<f4'), ('y', '<i4')])
+ t2 = dtype([('y', '<f4'), ('x', '<i4')])
+ assert hash(t1) != hash(t2)
+
+ # swap types
+ t3 = dtype([('x', '<f4'), ('y', '<i4')])
+ t4 = dtype([('x', '<i4'), ('y', '<f4')])
+ assert hash(t3) != hash(t4)
+
+ # swap offsets
+ t5 = dtype([('x', '<f4'), ('y', '<i4')])
+ t6 = dtype([('y', '<i4'), ('x', '<f4')])
+ assert hash(t5) != hash(t6)
def test_pickle(self):
import numpy as np
from numpypy import array, dtype
diff --git a/pypy/module/test_lib_pypy/numpypy/core/test_numeric.py b/pypy/module/test_lib_pypy/numpypy/core/test_numeric.py
--- a/pypy/module/test_lib_pypy/numpypy/core/test_numeric.py
+++ b/pypy/module/test_lib_pypy/numpypy/core/test_numeric.py
@@ -248,3 +248,5 @@
assert d.shape == (3, 3)
assert d.dtype == dtype('int32')
assert (d == [[1, 0, 0], [0, 1, 0], [0, 0, 1]]).all()
+
+
More information about the pypy-commit
mailing list