diff options
author | Campbell Barton <ideasman42@gmail.com> | 2011-01-09 12:16:04 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2011-01-09 12:16:04 +0300 |
commit | d31ebbe66681cda8e94c6593e4b40c4b4df5809c (patch) | |
tree | dbfe940f8cbde15efa5545a21d33c0dbeae91516 /source | |
parent | ca89269c227607923bcfd8c137c552bdb0c37c16 (diff) |
cleanup for mathutils multiplication functions, a little faster in some cases, raise more informative exceptions.
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/blenlib/BLI_math_vector.h | 2 | ||||
-rw-r--r-- | source/blender/blenlib/intern/math_vector.c | 18 | ||||
-rw-r--r-- | source/blender/python/generic/mathutils_matrix.c | 102 | ||||
-rw-r--r-- | source/blender/python/generic/mathutils_quat.c | 42 | ||||
-rw-r--r-- | source/blender/python/generic/mathutils_vector.c | 86 |
5 files changed, 126 insertions, 124 deletions
diff --git a/source/blender/blenlib/BLI_math_vector.h b/source/blender/blenlib/BLI_math_vector.h index 5f6251bf382..43cf612c33c 100644 --- a/source/blender/blenlib/BLI_math_vector.h +++ b/source/blender/blenlib/BLI_math_vector.h @@ -175,6 +175,8 @@ void range_vni(int *array, const int size, const int start); void mul_vn_fl(float *array, const int size, const float f); void mul_vn_vn_fl(float *array_tar, const float *array_src, const int size, const float f); void add_vn_vn(float *array_tar, const float *array_src, const int size); +void add_vn_vnvn(float *array_tar, const float *array_src_a, const float *array_src_b, const int size); +void sub_vn_vnvn(float *array_tar, const float *array_src_a, const float *array_src_b, const int size); void fill_vni(int *array_tar, const int size, const int val); void fill_vn(float *array_tar, const int size, const float val); diff --git a/source/blender/blenlib/intern/math_vector.c b/source/blender/blenlib/intern/math_vector.c index 2ff1e948317..539d3fb97f6 100644 --- a/source/blender/blenlib/intern/math_vector.c +++ b/source/blender/blenlib/intern/math_vector.c @@ -398,6 +398,24 @@ void add_vn_vn(float *array_tar, const float *array_src, const int size) while(i--) { *(tar--) += *(src--); } } +void add_vn_vnvn(float *array_tar, const float *array_src_a, const float *array_src_b, const int size) +{ + float *tar= array_tar + (size-1); + const float *src_a= array_src_a + (size-1); + const float *src_b= array_src_b + (size-1); + int i= size; + while(i--) { *(tar--) = *(src_a--) + *(src_b--); } +} + +void sub_vn_vnvn(float *array_tar, const float *array_src_a, const float *array_src_b, const int size) +{ + float *tar= array_tar + (size-1); + const float *src_a= array_src_a + (size-1); + const float *src_b= array_src_b + (size-1); + int i= size; + while(i--) { *(tar--) = *(src_a--) - *(src_b--); } +} + void fill_vni(int *array_tar, const int size, const int val) { int *tar= array_tar + (size-1); diff --git a/source/blender/python/generic/mathutils_matrix.c b/source/blender/python/generic/mathutils_matrix.c index b67d4c54a7d..df176d4f18d 100644 --- a/source/blender/python/generic/mathutils_matrix.c +++ b/source/blender/python/generic/mathutils_matrix.c @@ -1498,9 +1498,7 @@ static int Matrix_ass_slice(MatrixObject * self, int begin, int end, PyObject * ------------------------obj + obj------------------------------*/ static PyObject *Matrix_add(PyObject * m1, PyObject * m2) { - int x, y; - float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}; + float mat[16]; MatrixObject *mat1 = NULL, *mat2 = NULL; mat1 = (MatrixObject*)m1; @@ -1519,21 +1517,15 @@ static PyObject *Matrix_add(PyObject * m1, PyObject * m2) return NULL; } - for(x = 0; x < mat1->rowSize; x++) { - for(y = 0; y < mat1->colSize; y++) { - mat[((x * mat1->colSize) + y)] = mat1->matrix[x][y] + mat2->matrix[x][y]; - } - } + add_vn_vnvn(mat, mat1->contigPtr, mat2->contigPtr, mat1->rowSize * mat1->colSize); - return newMatrixObject(mat, mat1->rowSize, mat1->colSize, Py_NEW, NULL); + return newMatrixObject(mat, mat1->rowSize, mat1->colSize, Py_NEW, Py_TYPE(mat1)); } /*------------------------obj - obj------------------------------ subtraction*/ static PyObject *Matrix_sub(PyObject * m1, PyObject * m2) { - int x, y; - float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}; + float mat[16]; MatrixObject *mat1 = NULL, *mat2 = NULL; mat1 = (MatrixObject*)m1; @@ -1552,23 +1544,23 @@ static PyObject *Matrix_sub(PyObject * m1, PyObject * m2) return NULL; } - for(x = 0; x < mat1->rowSize; x++) { - for(y = 0; y < mat1->colSize; y++) { - mat[((x * mat1->colSize) + y)] = mat1->matrix[x][y] - mat2->matrix[x][y]; - } - } + sub_vn_vnvn(mat, mat1->contigPtr, mat2->contigPtr, mat1->rowSize * mat1->colSize); - return newMatrixObject(mat, mat1->rowSize, mat1->colSize, Py_NEW, NULL); + return newMatrixObject(mat, mat1->rowSize, mat1->colSize, Py_NEW, Py_TYPE(mat1)); } /*------------------------obj * obj------------------------------ mulplication*/ +static PyObject *matrix_mul_float(MatrixObject *mat, const float scalar) +{ + float tmat[16]; + mul_vn_vn_fl(tmat, mat->contigPtr, mat->rowSize * mat->colSize, scalar); + return newMatrixObject(tmat, mat->rowSize, mat->colSize, Py_NEW, Py_TYPE(mat)); +} + static PyObject *Matrix_mul(PyObject * m1, PyObject * m2) { - int x, y, z; float scalar; - float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}; - double dot = 0.0f; + MatrixObject *mat1 = NULL, *mat2 = NULL; if(MatrixObject_Check(m1)) { @@ -1587,54 +1579,42 @@ static PyObject *Matrix_mul(PyObject * m1, PyObject * m2) PyErr_SetString(PyExc_AttributeError,"Matrix multiplication: matrix A rowsize must equal matrix B colsize"); return NULL; } - for(x = 0; x < mat2->rowSize; x++) { - for(y = 0; y < mat1->colSize; y++) { - for(z = 0; z < mat1->rowSize; z++) { - dot += (mat1->matrix[z][y] * mat2->matrix[x][z]); - } - mat[((x * mat1->colSize) + y)] = (float)dot; - dot = 0.0f; - } - } - - return newMatrixObject(mat, mat2->rowSize, mat1->colSize, Py_NEW, Py_TYPE(mat1)); - } - - if(mat1==NULL){ - scalar=PyFloat_AsDouble(m1); // may not be a float - if ((scalar == -1.0 && PyErr_Occurred())==0) { /*FLOAT/INT * MATRIX, this line annoys theeth, lets see if he finds it */ + else { + float mat[16]= {0.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f}; + double dot = 0.0f; + int x, y, z; + for(x = 0; x < mat2->rowSize; x++) { - for(y = 0; y < mat2->colSize; y++) { - mat[((x * mat2->colSize) + y)] = scalar * mat2->matrix[x][y]; + for(y = 0; y < mat1->colSize; y++) { + for(z = 0; z < mat1->rowSize; z++) { + dot += (mat1->matrix[z][y] * mat2->matrix[x][z]); + } + mat[((x * mat1->colSize) + y)] = (float)dot; + dot = 0.0f; } } - return newMatrixObject(mat, mat2->rowSize, mat2->colSize, Py_NEW, Py_TYPE(mat2)); + + return newMatrixObject(mat, mat2->rowSize, mat1->colSize, Py_NEW, Py_TYPE(mat1)); } - - PyErr_SetString(PyExc_TypeError, "Matrix multiplication: arguments not acceptable for this operation"); - return NULL; } - else /* if(mat1) { */ { - if(VectorObject_Check(m2)) { /* MATRIX*VECTOR */ - PyErr_SetString(PyExc_TypeError, "Matrix multiplication: Only 'vec * matrix' is supported, not the reverse"); - return NULL; + else if(mat2) { + if (((scalar= PyFloat_AsDouble(m1)) == -1.0 && PyErr_Occurred())==0) { /*FLOAT/INT * MATRIX */ + return matrix_mul_float(mat2, scalar); } - else { - scalar= PyFloat_AsDouble(m2); - if ((scalar == -1.0 && PyErr_Occurred())==0) { /* MATRIX*FLOAT/INT */ - for(x = 0; x < mat1->rowSize; x++) { - for(y = 0; y < mat1->colSize; y++) { - mat[((x * mat1->colSize) + y)] = scalar * mat1->matrix[x][y]; - } - } - return newMatrixObject(mat, mat1->rowSize, mat1->colSize, Py_NEW, Py_TYPE(mat1)); - } + } + else if(mat1) { + if (((scalar= PyFloat_AsDouble(m2)) == -1.0 && PyErr_Occurred())==0) { /*FLOAT/INT * MATRIX */ + return matrix_mul_float(mat1, scalar); } - PyErr_SetString(PyExc_TypeError, "Matrix multiplication: arguments not acceptable for this operation"); - return NULL; + } + else { + BKE_assert(!"internal error"); } - PyErr_SetString(PyExc_TypeError, "Matrix multiplication: arguments not acceptable for this operation"); + PyErr_Format(PyExc_TypeError, "Matrix multiplication: not supported between '%.200s' and '%.200s' types", Py_TYPE(m1)->tp_name, Py_TYPE(m2)->tp_name); return NULL; } static PyObject* Matrix_inv(MatrixObject *self) diff --git a/source/blender/python/generic/mathutils_quat.c b/source/blender/python/generic/mathutils_quat.c index 36fb0ad66bd..1de249205b2 100644 --- a/source/blender/python/generic/mathutils_quat.c +++ b/source/blender/python/generic/mathutils_quat.c @@ -641,6 +641,15 @@ static PyObject *Quaternion_sub(PyObject * q1, PyObject * q2) return newQuaternionObject(quat, Py_NEW, Py_TYPE(q1)); } + +static PyObject *quat_mul_float(QuaternionObject *quat, const float scalar) +{ + float tquat[4]; + copy_qt_qt(tquat, quat->quat); + mul_qt_fl(tquat, scalar); + return newQuaternionObject(tquat, Py_NEW, Py_TYPE(quat)); +} + //------------------------obj * obj------------------------------ //mulplication static PyObject *Quaternion_mul(PyObject * q1, PyObject * q2) @@ -663,33 +672,22 @@ static PyObject *Quaternion_mul(PyObject * q1, PyObject * q2) mul_qt_qtqt(quat, quat1->quat, quat2->quat); return newQuaternionObject(quat, Py_NEW, Py_TYPE(q1)); } - /* the only case this can happen (for a supported type is "FLOAT*QUAT" ) */ - if(!QuaternionObject_Check(q1)) { - scalar= PyFloat_AsDouble(q1); - if ((scalar == -1.0 && PyErr_Occurred())==0) { /* FLOAT*QUAT */ - QUATCOPY(quat, quat2->quat); - mul_qt_fl(quat, scalar); - return newQuaternionObject(quat, Py_NEW, Py_TYPE(q2)); + else if(quat2) { /* FLOAT*QUAT */ + if(((scalar= PyFloat_AsDouble(q1)) == -1.0 && PyErr_Occurred())==0) { + return quat_mul_float(quat2, scalar); } - PyErr_SetString(PyExc_TypeError, "Quaternion multiplication: val * quat, val is not an acceptable type"); - return NULL; } - else { /* QUAT*SOMETHING */ - if(VectorObject_Check(q2)){ /* QUAT*VEC */ - PyErr_SetString(PyExc_TypeError, "Quaternion multiplication: Only 'vector * quaternion' is supported, not the reverse"); - return NULL; - } - - scalar= PyFloat_AsDouble(q2); - if ((scalar == -1.0 && PyErr_Occurred())==0) { /* QUAT*FLOAT */ - QUATCOPY(quat, quat1->quat); - mul_qt_fl(quat, scalar); - return newQuaternionObject(quat, Py_NEW, Py_TYPE(q1)); + else if (quat1) { /* QUAT*FLOAT */ + if((((scalar= PyFloat_AsDouble(q2)) == -1.0 && PyErr_Occurred())==0)) { + return quat_mul_float(quat1, scalar); } } - - PyErr_SetString(PyExc_TypeError, "Quaternion multiplication: arguments not acceptable for this operation"); + else { + BKE_assert(!"internal error"); + } + + PyErr_Format(PyExc_TypeError, "Quaternion multiplication: not supported between '%.200s' and '%.200s' types", Py_TYPE(q1)->tp_name, Py_TYPE(q2)->tp_name); return NULL; } diff --git a/source/blender/python/generic/mathutils_vector.c b/source/blender/python/generic/mathutils_vector.c index 3d80f6bade4..2208046e6c0 100644 --- a/source/blender/python/generic/mathutils_vector.c +++ b/source/blender/python/generic/mathutils_vector.c @@ -1047,6 +1047,17 @@ static int column_vector_multiplication(float *rvec, VectorObject* vec, MatrixOb return 0; } +static PyObject *vector_mul_float(VectorObject *vec, const float scalar) +{ + float tvec[MAX_DIMENSIONS]; + int i; + + for(i = 0; i < vec->size; i++) { + tvec[i] = vec->vec[i] * scalar; + } + return newVectorObject(tvec, vec->size, Py_NEW, Py_TYPE(vec)); +} + static PyObject *Vector_mul(PyObject * v1, PyObject * v2) { VectorObject *vec1 = NULL, *vec2 = NULL; @@ -1080,55 +1091,48 @@ static PyObject *Vector_mul(PyObject * v1, PyObject * v2) } return PyFloat_FromDouble(dot); } - - /* swap so vec1 is always the vector */ - /* note: it would seem from this code that the matrix multiplication below - * is communicative. however the matrix class will always handle the - * (matrix * vector) case so we can ignore it here. - * This is NOT so for Quaternions: TODO, check if communicative (vec * quat) is correct */ - if (vec2) { - vec1= vec2; - v2= v1; - } + else if (vec1) { + if (MatrixObject_Check(v2)) { + /* VEC * MATRIX */ + float tvec[MAX_DIMENSIONS]; + if(!BaseMath_ReadCallback((MatrixObject *)v2)) + return NULL; + if(column_vector_multiplication(tvec, vec1, (MatrixObject*)v2) == -1) { + return NULL; + } - if (MatrixObject_Check(v2)) { - /* VEC * MATRIX */ - float tvec[MAX_DIMENSIONS]; - if(!BaseMath_ReadCallback((MatrixObject *)v2)) - return NULL; - if(column_vector_multiplication(tvec, vec1, (MatrixObject*)v2) == -1) { - return NULL; + return newVectorObject(tvec, vec1->size, Py_NEW, Py_TYPE(vec1)); } + else if (QuaternionObject_Check(v2)) { + /* VEC * QUAT */ + QuaternionObject *quat2 = (QuaternionObject*)v2; + float tvec[3]; - return newVectorObject(tvec, vec1->size, Py_NEW, Py_TYPE(vec1)); - } else if (QuaternionObject_Check(v2)) { - /* VEC * QUAT */ - QuaternionObject *quat2 = (QuaternionObject*)v2; - float tvec[3]; - - if(vec1->size != 3) { - PyErr_SetString(PyExc_TypeError, "Vector multiplication: only 3D vector rotations (with quats) currently supported"); - return NULL; + if(vec1->size != 3) { + PyErr_SetString(PyExc_TypeError, "Vector multiplication: only 3D vector rotations (with quats) currently supported"); + return NULL; + } + if(!BaseMath_ReadCallback(quat2)) { + return NULL; + } + copy_v3_v3(tvec, vec1->vec); + mul_qt_v3(quat2->quat, tvec); + return newVectorObject(tvec, 3, Py_NEW, Py_TYPE(vec1)); } - if(!BaseMath_ReadCallback(quat2)) { - return NULL; + else if (((scalar= PyFloat_AsDouble(v2)) == -1.0 && PyErr_Occurred())==0) { /* VEC*FLOAT */ + return vector_mul_float(vec1, scalar); } - copy_v3_v3(tvec, vec1->vec); - mul_qt_v3(quat2->quat, tvec); - return newVectorObject(tvec, 3, Py_NEW, Py_TYPE(vec1)); } - else if (((scalar= PyFloat_AsDouble(v2)) == -1.0 && PyErr_Occurred())==0) { /* VEC*FLOAT */ - int i; - float vec[MAX_DIMENSIONS]; - - for(i = 0; i < vec1->size; i++) { - vec[i] = vec1->vec[i] * scalar; + else if (vec2) { + if (((scalar= PyFloat_AsDouble(v1)) == -1.0 && PyErr_Occurred())==0) { /* VEC*FLOAT */ + return vector_mul_float(vec2, scalar); } - return newVectorObject(vec, vec1->size, Py_NEW, Py_TYPE(vec1)); - } - - PyErr_SetString(PyExc_TypeError, "Vector multiplication: arguments not acceptable for this operation"); + else { + BKE_assert(!"internal error"); + } + + PyErr_Format(PyExc_TypeError, "Vector multiplication: not supported between '%.200s' and '%.200s' types", Py_TYPE(v1)->tp_name, Py_TYPE(v2)->tp_name); return NULL; } |