Author: mattip <matti.pi...@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() + + _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit