Commit: 797fa116fdd6d1a0f3e2761834820857ff7a9af7
Author: Martijn Berger
Date:   Fri Feb 13 14:29:06 2015 +1100
Branches: master
https://developer.blender.org/rB797fa116fdd6d1a0f3e2761834820857ff7a9af7

mathutils: __hash__ for mathutils types

This gives the same result as converting to a tuple and hashing.

===================================================================

M       source/blender/python/mathutils/mathutils.c
M       source/blender/python/mathutils/mathutils.h
M       source/blender/python/mathutils/mathutils_Color.c
M       source/blender/python/mathutils/mathutils_Euler.c
M       source/blender/python/mathutils/mathutils_Matrix.c
M       source/blender/python/mathutils/mathutils_Quaternion.c
M       source/blender/python/mathutils/mathutils_Vector.c

===================================================================

diff --git a/source/blender/python/mathutils/mathutils.c 
b/source/blender/python/mathutils/mathutils.c
index ca20f83..6dbc601 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)
 {
diff --git a/source/blender/python/mathutils/mathutils.h 
b/source/blender/python/mathutils/mathutils.h
index 296b8cf..75bc55e 100644
--- a/source/blender/python/mathutils/mathutils.h
+++ b/source/blender/python/mathutils/mathutils.h
@@ -118,6 +118,8 @@ int mathutils_array_parse_alloc(float **array, int 
array_min, PyObject *value, c
 int mathutils_array_parse_alloc_v(float **array, int array_dim, PyObject 
*value, const char *error_prefix);
 int mathutils_any_to_rotmat(float rmat[3][3], PyObject *value, const char 
*error_prefix);
 
+Py_hash_t mathutils_array_hash(const float *float_array, size_t array_len);
+
 /* zero remaining unused elements of the array */
 #define MU_ARRAY_ZERO      (1 << 30)
 /* ignore larger py sequences than requested (just use first elements),
diff --git a/source/blender/python/mathutils/mathutils_Color.c 
b/source/blender/python/mathutils/mathutils_Color.c
index ce59099..235403b 100644
--- a/source/blender/python/mathutils/mathutils_Color.c
+++ b/source/blender/python/mathutils/mathutils_Color.c
@@ -192,6 +192,14 @@ static PyObject *Color_richcmpr(PyObject *a, PyObject *b, 
int op)
        return Py_INCREF_RET(res);
 }
 
+static Py_hash_t Color_hash(ColorObject *self)
+{
+       if (BaseMath_ReadCallback(self) == -1)
+               return -1;
+
+       return mathutils_array_hash(self->col, COLOR_SIZE);
+}
+
 /* ---------------------SEQUENCE PROTOCOLS------------------------ */
 /* ----------------------------len(object)------------------------ */
 /* sequence length */
@@ -832,7 +840,7 @@ PyTypeObject color_Type = {
        &Color_NumMethods,              /* tp_as_number */
        &Color_SeqMethods,              /* tp_as_sequence */
        &Color_AsMapping,               /* tp_as_mapping */
-       NULL,                           /* tp_hash */
+       (hashfunc)Color_hash,           /* tp_hash */
        NULL,                           /* tp_call */
 #ifndef MATH_STANDALONE
        (reprfunc) Color_str,           /* tp_str */
diff --git a/source/blender/python/mathutils/mathutils_Euler.c 
b/source/blender/python/mathutils/mathutils_Euler.c
index edb4af0..ed11120 100644
--- a/source/blender/python/mathutils/mathutils_Euler.c
+++ b/source/blender/python/mathutils/mathutils_Euler.c
@@ -386,6 +386,14 @@ static PyObject *Euler_richcmpr(PyObject *a, PyObject *b, 
int op)
        return Py_INCREF_RET(res);
 }
 
+static Py_hash_t Euler_hash(EulerObject *self)
+{
+       if (BaseMath_ReadCallback(self) == -1)
+               return -1;
+
+       return mathutils_array_hash(self->eul, EULER_SIZE);
+}
+
 /* ---------------------SEQUENCE PROTOCOLS------------------------ */
 /* ----------------------------len(object)------------------------ */
 /* sequence length */
@@ -680,7 +688,7 @@ PyTypeObject euler_Type = {
        NULL,                           /* tp_as_number */
        &Euler_SeqMethods,              /* tp_as_sequence */
        &Euler_AsMapping,               /* tp_as_mapping */
-       NULL,                           /* tp_hash */
+       (hashfunc)Euler_hash,           /* tp_hash */
        NULL,                           /* tp_call */
 #ifndef MATH_STANDALONE
        (reprfunc) Euler_str,           /* tp_str */
diff --git a/source/blender/python/mathutils/mathutils_Matrix.c 
b/source/blender/python/mathutils/mathutils_Matrix.c
index 95b5325..e03fec5 100644
--- a/source/blender/python/mathutils/mathutils_Matrix.c
+++ b/source/blender/python/mathutils/mathutils_Matrix.c
@@ -895,6 +895,19 @@ static void matrix_copy(MatrixObject *mat_dst, const 
MatrixObject *mat_src)
        memcpy(mat_dst->matrix, mat_src->matrix, sizeof(float) * 
(mat_dst->num_col * mat_dst->num_row));
 }
 
+/* transposes memory layout, rol/col's don't have to match */
+static void matrix_transpose_internal(float mat_dst_fl[], const MatrixObject 
*mat_src)
+{
+       unsigned short col, row;
+       unsigned int i = 0;
+
+       for (row = 0; row < mat_src->num_row; row++) {
+               for (col = 0; col < mat_src->num_col; col++) {
+                       mat_dst_fl[i++] = MATRIX_ITEM(mat_src, row, col);
+               }
+       }
+}
+
 /* assumes rowsize == colsize is checked and the read callback has run */
 static float matrix_determinant_internal(const MatrixObject *self)
 {
@@ -2037,6 +2050,18 @@ static PyObject *Matrix_richcmpr(PyObject *a, PyObject 
*b, int op)
        return Py_INCREF_RET(res);
 }
 
+static Py_hash_t Matrix_hash(MatrixObject *self)
+{
+       float mat[SQUARE(MATRIX_MAX_DIM)];
+
+       if (BaseMath_ReadCallback(self) == -1)
+               return -1;
+
+       matrix_transpose_internal(mat, self);
+
+       return mathutils_array_hash(mat, self->num_row * self->num_col);
+}
+
 /*---------------------SEQUENCE PROTOCOLS------------------------
  * ----------------------------len(object)------------------------
  * sequence length */
@@ -2739,7 +2764,7 @@ PyTypeObject matrix_Type = {
        &Matrix_NumMethods,                 /*tp_as_number*/
        &Matrix_SeqMethods,                 /*tp_as_sequence*/
        &Matrix_AsMapping,                  /*tp_as_mapping*/
-       NULL,                               /*tp_hash*/
+       (hashfunc)Matrix_hash,              /*tp_hash*/
        NULL,                               /*tp_call*/
 #ifndef MATH_STANDALONE
        (reprfunc) Matrix_str,              /*tp_str*/
diff --git a/source/blender/python/mathutils/mathutils_Quaternion.c 
b/source/blender/python/mathutils/mathutils_Quaternion.c
index 42be316..f9272bd 100644
--- a/source/blender/python/mathutils/mathutils_Quaternion.c
+++ b/source/blender/python/mathutils/mathutils_Quaternion.c
@@ -575,6 +575,14 @@ static PyObject *Quaternion_richcmpr(PyObject *a, PyObject 
*b, int op)
        return Py_INCREF_RET(res);
 }
 
+static Py_hash_t Quaternion_hash(QuaternionObject *self)
+{
+       if (BaseMath_ReadCallback(self) == -1)
+               return -1;
+
+       return mathutils_array_hash(self->quat, QUAT_SIZE);
+}
+
 /* ---------------------SEQUENCE PROTOCOLS------------------------ */
 /* ----------------------------len(object)------------------------ */
 /* sequence length */
@@ -1266,7 +1274,7 @@ PyTypeObject quaternion_Type = {
        &Quaternion_NumMethods,             /* tp_as_number */
        &Quaternion_SeqMethods,             /* tp_as_sequence */
        &Quaternion_AsMapping,              /* tp_as_mapping */
-       NULL,                               /* tp_hash */
+       (hashfunc)Quaternion_hash,          /* tp_hash */
        NULL,                               /* tp_call */
 #ifndef MATH_STANDALONE
        (reprfunc) Quaternion_str,          /* tp_str */
diff --git a/source/blender/python/mathutils/mathutils_Vector.c 
b/source/blender/python/mathutils/mathutils_Vector.c
index 091412b..b15eb06 100644
--- a/source/blender/python/mathutils/mathutils_Vector.c
+++ b/source/blender/python/mathutils/mathutils_Vector.c
@@ -2062,6 +2062,14 @@ static PyObject *Vector_richcmpr(PyObject *objectA, 
PyObject *objectB, int compa
        }
 }
 
+static Py_hash_t Vector_hash(VectorObject *self)
+{
+       if (BaseMath_ReadCallback(self) == -1)
+               return -1;
+
+       return mathutils_array_hash(self->vec, self->size);
+}
+
 /*-----------------PROTCOL DECLARATIONS--------------------------*/
 static PySequenceMethods Vector_SeqMethods = {
        (lenfunc) Vector_len,               /* sq_length */
@@ -2935,7 +2943,7 @@ PyTypeObject vector_Type = {
 
        /* More standard operations (here for binary compatibility) */
 
-       NULL,                       /* hashfunc tp_hash; */
+       (hashfunc)Vector_hash,      /* hashfunc tp_hash; */
        NULL,                       /* ternaryfunc tp_call; */
 #ifndef MATH_STANDALONE
        (reprfunc)Vector_str,       /* reprfunc tp_str; */

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
http://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to