diff options
author | Campbell Barton <ideasman42@gmail.com> | 2015-02-15 02:46:14 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2015-02-15 06:02:08 +0300 |
commit | fa2f7c69acc55fd1fe3db0610ad319d08d77d79e (patch) | |
tree | 004780e19ea70ec8ee5eb6b26cde8ace90558a70 /source/blender/python/mathutils/mathutils.c | |
parent | a9d979c8ef2b6de25c1953da341dd5e207416540 (diff) |
mathutils: Implement __hash__() functions
- all mathutils types
- only works on frozen data (so vectors can be used in sets/dict keys)
- uses same method as CPython, (matches hashing a tuple)
D1104 by @juicyfruit with own modifications
Diffstat (limited to 'source/blender/python/mathutils/mathutils.c')
-rw-r--r-- | source/blender/python/mathutils/mathutils.c | 38 |
1 files changed, 38 insertions, 0 deletions
diff --git a/source/blender/python/mathutils/mathutils.c b/source/blender/python/mathutils/mathutils.c index 28b2d26d3fd..7b51b08451b 100644 --- a/source/blender/python/mathutils/mathutils.c +++ b/source/blender/python/mathutils/mathutils.c @@ -79,6 +79,37 @@ static int mathutils_array_parse_fast(float *array, return size; } +/** + * helper function that returns a Python ``__hash__``. + * + * \note consistent with the equivalent tuple of floats (CPython's 'tuplehash') + */ +Py_hash_t mathutils_array_hash(const float *array, size_t array_len) +{ + int i; + Py_uhash_t x; /* Unsigned for defined overflow behavior. */ + Py_hash_t y; + Py_uhash_t mult; + Py_ssize_t len; + + mult = _PyHASH_MULTIPLIER; + len = array_len; + x = 0x345678UL; + i = 0; + while (--len >= 0) { + y = _Py_HashDouble((double)(array[i++])); + if (y == -1) + return -1; + x = (x ^ y) * mult; + /* the cast might truncate len; that doesn't change hash stability */ + mult += (Py_hash_t)(82520UL + len + len); + } + x += 97531UL; + if (x == (Py_uhash_t)-1) + x = -2; + return x; +} + /* helper functionm returns length of the 'value', -1 on error */ int mathutils_array_parse(float *array, int array_min, int array_max, PyObject *value, const char *error_prefix) { @@ -459,6 +490,13 @@ void _BaseMathObject_RaiseFrozenExc(const BaseMathObject *self) Py_TYPE(self)->tp_name); } +void _BaseMathObject_RaiseNotFrozenExc(const BaseMathObject *self) +{ + PyErr_Format(PyExc_TypeError, + "%s is not frozen (mutable), call freeze first", + Py_TYPE(self)->tp_name); +} + /* BaseMathObject generic functions for all mathutils types */ char BaseMathObject_owner_doc[] = "The item this is wrapping or None (read-only)."; PyObject *BaseMathObject_owner_get(BaseMathObject *self, void *UNUSED(closure)) |