Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/python/mathutils')
-rw-r--r--source/blender/python/mathutils/mathutils_Matrix.c195
-rw-r--r--source/blender/python/mathutils/mathutils_Quaternion.c150
-rw-r--r--source/blender/python/mathutils/mathutils_Vector.c182
3 files changed, 439 insertions, 88 deletions
diff --git a/source/blender/python/mathutils/mathutils_Matrix.c b/source/blender/python/mathutils/mathutils_Matrix.c
index 70c400f99b8..3bd40cca5c6 100644
--- a/source/blender/python/mathutils/mathutils_Matrix.c
+++ b/source/blender/python/mathutils/mathutils_Matrix.c
@@ -2321,7 +2321,7 @@ static PyObject *Matrix_sub(PyObject *m1, PyObject *m2)
return Matrix_CreatePyObject(mat, mat1->num_col, mat1->num_row, Py_TYPE(mat1));
}
/*------------------------obj * obj------------------------------
- * multiplication */
+ * element-wise multiplication */
static PyObject *matrix_mul_float(MatrixObject *mat, const float scalar)
{
float tmat[MATRIX_MAX_DIM * MATRIX_MAX_DIM];
@@ -2332,7 +2332,6 @@ static PyObject *matrix_mul_float(MatrixObject *mat, const float scalar)
static PyObject *Matrix_mul(PyObject *m1, PyObject *m2)
{
float scalar;
- int vec_size;
MatrixObject *mat1 = NULL, *mat2 = NULL;
@@ -2348,15 +2347,124 @@ static PyObject *Matrix_mul(PyObject *m1, PyObject *m2)
}
if (mat1 && mat2) {
+#ifdef USE_MATHUTILS_ELEM_MUL
/* MATRIX * MATRIX */
float mat[MATRIX_MAX_DIM * MATRIX_MAX_DIM];
+ if ((mat1->num_row != mat2->num_row) || (mat1->num_col != mat2->num_col)) {
+ PyErr_SetString(PyExc_ValueError,
+ "matrix1 * matrix2: matrix1 number of rows/columns "
+ "and the matrix2 number of rows/columns must be the same");
+ return NULL;
+ }
+
+ mul_vn_vnvn(mat, mat1->matrix, mat2->matrix, mat1->num_col * mat1->num_row);
+
+ return Matrix_CreatePyObject(mat, mat2->num_col, mat1->num_row, Py_TYPE(mat1));
+#endif
+ }
+ else if (mat2) {
+ /*FLOAT/INT * MATRIX */
+ if (((scalar = PyFloat_AsDouble(m1)) == -1.0f && PyErr_Occurred()) == 0) {
+ return matrix_mul_float(mat2, scalar);
+ }
+ }
+ else if (mat1) {
+ /* MATRIX * FLOAT/INT */
+ if (((scalar = PyFloat_AsDouble(m2)) == -1.0f && PyErr_Occurred()) == 0) {
+ return matrix_mul_float(mat1, scalar);
+ }
+ }
+
+ PyErr_Format(PyExc_TypeError,
+ "Element-wise multiplication: "
+ "not supported between '%.200s' and '%.200s' types",
+ Py_TYPE(m1)->tp_name, Py_TYPE(m2)->tp_name);
+ return NULL;
+}
+/*------------------------obj *= obj------------------------------
+ * Inplace element-wise multiplication */
+static PyObject *Matrix_imul(PyObject *m1, PyObject *m2)
+{
+ float scalar;
+
+ MatrixObject *mat1 = NULL, *mat2 = NULL;
+
+ if (MatrixObject_Check(m1)) {
+ mat1 = (MatrixObject *)m1;
+ if (BaseMath_ReadCallback(mat1) == -1)
+ return NULL;
+ }
+ if (MatrixObject_Check(m2)) {
+ mat2 = (MatrixObject *)m2;
+ if (BaseMath_ReadCallback(mat2) == -1)
+ return NULL;
+ }
+
+ if (mat1 && mat2) {
+#ifdef USE_MATHUTILS_ELEM_MUL
+ /* MATRIX *= MATRIX */
+ if ((mat1->num_row != mat2->num_row) || (mat1->num_col != mat2->num_col)) {
+ PyErr_SetString(PyExc_ValueError,
+ "matrix1 *= matrix2: matrix1 number of rows/columns "
+ "and the matrix2 number of rows/columns must be the same");
+ return NULL;
+ }
+
+ mul_vn_vn(mat1->matrix, mat2->matrix, mat1->num_col * mat1->num_row);
+#else
+ PyErr_Format(PyExc_TypeError,
+ "Inplace element-wise multiplication: "
+ "not supported between '%.200s' and '%.200s' types",
+ Py_TYPE(m1)->tp_name, Py_TYPE(m2)->tp_name);
+ return NULL;
+#endif
+ }
+ else if (mat1 && (((scalar = PyFloat_AsDouble(m2)) == -1.0f && PyErr_Occurred()) == 0)) {
+ /* MATRIX *= FLOAT/INT */
+ mul_vn_fl(mat1->matrix, mat1->num_row * mat1->num_col, scalar);
+ }
+ else {
+ PyErr_Format(PyExc_TypeError,
+ "Inplace element-wise multiplication: "
+ "not supported between '%.200s' and '%.200s' types",
+ Py_TYPE(m1)->tp_name, Py_TYPE(m2)->tp_name);
+ return NULL;
+ }
+
+ (void)BaseMath_WriteCallback(mat1);
+ Py_INCREF(m1);
+ return m1;
+}
+/*------------------------obj @ obj------------------------------
+ * matrix multiplication */
+static PyObject *Matrix_matmul(PyObject *m1, PyObject *m2)
+{
+ int vec_size;
+
+ MatrixObject *mat1 = NULL, *mat2 = NULL;
+
+ if (MatrixObject_Check(m1)) {
+ mat1 = (MatrixObject *)m1;
+ if (BaseMath_ReadCallback(mat1) == -1)
+ return NULL;
+ }
+ if (MatrixObject_Check(m2)) {
+ mat2 = (MatrixObject *)m2;
+ if (BaseMath_ReadCallback(mat2) == -1)
+ return NULL;
+ }
+
+ if (mat1 && mat2) {
+ /* MATRIX @ MATRIX */
+ float mat[MATRIX_MAX_DIM * MATRIX_MAX_DIM];
+
int col, row, item;
if (mat1->num_col != mat2->num_row) {
PyErr_SetString(PyExc_ValueError,
- "matrix1 * matrix2: matrix1 number of columns "
- "and the matrix2 number of rows must be the same");
+ "matrix1 * matrix2: matrix1 number of columns "
+ "and the matrix2 number of rows must be the same");
return NULL;
}
@@ -2372,14 +2480,8 @@ static PyObject *Matrix_mul(PyObject *m1, PyObject *m2)
return Matrix_CreatePyObject(mat, mat2->num_col, mat1->num_row, Py_TYPE(mat1));
}
- else if (mat2) {
- /*FLOAT/INT * MATRIX */
- if (((scalar = PyFloat_AsDouble(m1)) == -1.0f && PyErr_Occurred()) == 0) {
- return matrix_mul_float(mat2, scalar);
- }
- }
else if (mat1) {
- /* MATRIX * VECTOR */
+ /* MATRIX @ VECTOR */
if (VectorObject_Check(m2)) {
VectorObject *vec2 = (VectorObject *)m2;
float tvec[MATRIX_MAX_DIM];
@@ -2398,20 +2500,69 @@ static PyObject *Matrix_mul(PyObject *m1, PyObject *m2)
return Vector_CreatePyObject(tvec, vec_size, Py_TYPE(m2));
}
- /*FLOAT/INT * MATRIX */
- else if (((scalar = PyFloat_AsDouble(m2)) == -1.0f && PyErr_Occurred()) == 0) {
- return matrix_mul_float(mat1, scalar);
+ }
+
+ 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;
+}
+/*------------------------obj @= obj------------------------------
+ * inplace matrix multiplication */
+static PyObject *Matrix_imatmul(PyObject *m1, PyObject *m2)
+{
+ MatrixObject *mat1 = NULL, *mat2 = NULL;
+
+ if (MatrixObject_Check(m1)) {
+ mat1 = (MatrixObject *)m1;
+ if (BaseMath_ReadCallback(mat1) == -1)
+ return NULL;
+ }
+ if (MatrixObject_Check(m2)) {
+ mat2 = (MatrixObject *)m2;
+ if (BaseMath_ReadCallback(mat2) == -1)
+ return NULL;
+ }
+
+ if (mat1 && mat2) {
+ /* MATRIX @= MATRIX */
+ float mat[MATRIX_MAX_DIM * MATRIX_MAX_DIM];
+ int col, row, item;
+
+ if (mat1->num_col != mat2->num_row) {
+ PyErr_SetString(PyExc_ValueError,
+ "matrix1 * matrix2: matrix1 number of columns "
+ "and the matrix2 number of rows must be the same");
+ return NULL;
}
+
+ for (col = 0; col < mat2->num_col; col++) {
+ for (row = 0; row < mat1->num_row; row++) {
+ double dot = 0.0f;
+ for (item = 0; item < mat1->num_col; item++) {
+ dot += (double)(MATRIX_ITEM(mat1, row, item) * MATRIX_ITEM(mat2, item, col));
+ }
+ /* store in new matrix as overwriting original at this point will cause
+ * subsequent iterations to use incorrect values */
+ mat[(col * mat1->num_row) + row] = (float)dot;
+ }
+ }
+
+ /* copy matrix back */
+ memcpy(mat1->matrix, mat, mat1->num_row * mat1->num_col);
}
else {
- BLI_assert(!"internal error");
+ PyErr_Format(PyExc_TypeError,
+ "Inplace matrix multiplication: "
+ "not supported between '%.200s' and '%.200s' types",
+ Py_TYPE(m1)->tp_name, Py_TYPE(m2)->tp_name);
+ return NULL;
}
- 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;
+ (void)BaseMath_WriteCallback(mat1);
+ Py_INCREF(m1);
+ return m1;
}
/*-----------------PROTOCOL DECLARATIONS--------------------------*/
@@ -2527,7 +2678,7 @@ static PyNumberMethods Matrix_NumMethods = {
NULL, /*nb_float*/
NULL, /* nb_inplace_add */
NULL, /* nb_inplace_subtract */
- NULL, /* nb_inplace_multiply */
+ (binaryfunc) Matrix_imul, /* nb_inplace_multiply */
NULL, /* nb_inplace_remainder */
NULL, /* nb_inplace_power */
NULL, /* nb_inplace_lshift */
@@ -2540,6 +2691,8 @@ static PyNumberMethods Matrix_NumMethods = {
NULL, /* nb_inplace_floor_divide */
NULL, /* nb_inplace_true_divide */
NULL, /* nb_index */
+ (binaryfunc) Matrix_matmul, /* nb_matrix_multiply */
+ (binaryfunc) Matrix_imatmul, /* nb_inplace_matrix_multiply */
};
PyDoc_STRVAR(Matrix_translation_doc,
diff --git a/source/blender/python/mathutils/mathutils_Quaternion.c b/source/blender/python/mathutils/mathutils_Quaternion.c
index 1a6fd0ee86f..bb5983af535 100644
--- a/source/blender/python/mathutils/mathutils_Quaternion.c
+++ b/source/blender/python/mathutils/mathutils_Quaternion.c
@@ -834,7 +834,7 @@ static PyObject *quat_mul_float(QuaternionObject *quat, const float scalar)
* multiplication */
static PyObject *Quaternion_mul(PyObject *q1, PyObject *q2)
{
- float quat[QUAT_SIZE], scalar;
+ float scalar;
QuaternionObject *quat1 = NULL, *quat2 = NULL;
if (QuaternionObject_Check(q1)) {
@@ -848,9 +848,12 @@ static PyObject *Quaternion_mul(PyObject *q1, PyObject *q2)
return NULL;
}
- if (quat1 && quat2) { /* QUAT * QUAT (cross product) */
- mul_qt_qtqt(quat, quat1->quat, quat2->quat);
+ if (quat1 && quat2) { /* QUAT * QUAT (element-wise product) */
+#ifdef USE_MATHUTILS_ELEM_MUL
+ float quat[QUAT_SIZE];
+ mul_vn_vnvn(quat, quat1->quat, quat2->quat, QUAT_SIZE);
return Quaternion_CreatePyObject(quat, Py_TYPE(q1));
+#endif
}
/* the only case this can happen (for a supported type is "FLOAT * QUAT") */
else if (quat2) { /* FLOAT * QUAT */
@@ -858,17 +861,96 @@ static PyObject *Quaternion_mul(PyObject *q1, PyObject *q2)
return quat_mul_float(quat2, scalar);
}
}
+ else if (quat1) { /* QUAT * FLOAT */
+ if ((((scalar = PyFloat_AsDouble(q2)) == -1.0f && PyErr_Occurred()) == 0)) {
+ return quat_mul_float(quat1, scalar);
+ }
+ }
+
+ PyErr_Format(PyExc_TypeError,
+ "Element-wise multiplication: "
+ "not supported between '%.200s' and '%.200s' types",
+ Py_TYPE(q1)->tp_name, Py_TYPE(q2)->tp_name);
+ return NULL;
+}
+/*------------------------obj *= obj------------------------------
+ * inplace multiplication */
+static PyObject *Quaternion_imul(PyObject *q1, PyObject *q2)
+{
+ float scalar;
+ QuaternionObject *quat1 = NULL, *quat2 = NULL;
+
+ if (QuaternionObject_Check(q1)) {
+ quat1 = (QuaternionObject *)q1;
+ if (BaseMath_ReadCallback(quat1) == -1)
+ return NULL;
+ }
+ if (QuaternionObject_Check(q2)) {
+ quat2 = (QuaternionObject *)q2;
+ if (BaseMath_ReadCallback(quat2) == -1)
+ return NULL;
+ }
+
+ if (quat1 && quat2) { /* QUAT *= QUAT (inplace element-wise product) */
+#ifdef USE_MATHUTILS_ELEM_MUL
+ mul_vn_vn(quat1->quat, quat2->quat, QUAT_SIZE);
+#else
+ PyErr_Format(PyExc_TypeError,
+ "Inplace element-wise multiplication: "
+ "not supported between '%.200s' and '%.200s' types",
+ Py_TYPE(q1)->tp_name, Py_TYPE(q2)->tp_name);
+ return NULL;
+#endif
+ }
+ else if (quat1 && (((scalar = PyFloat_AsDouble(q2)) == -1.0f && PyErr_Occurred()) == 0)) {
+ /* QUAT *= FLOAT */
+ mul_qt_fl(quat1->quat, scalar);
+ }
+ else {
+ PyErr_Format(PyExc_TypeError,
+ "Element-wise multiplication: "
+ "not supported between '%.200s' and '%.200s' types",
+ Py_TYPE(q1)->tp_name, Py_TYPE(q2)->tp_name);
+ return NULL;
+ }
+
+ (void)BaseMath_WriteCallback(quat1);
+ Py_INCREF(q1);
+ return q1;
+}
+/*------------------------obj @ obj------------------------------
+ * quaternion multiplication */
+static PyObject *Quaternion_matmul(PyObject *q1, PyObject *q2)
+{
+ float quat[QUAT_SIZE];
+ QuaternionObject *quat1 = NULL, *quat2 = NULL;
+
+ if (QuaternionObject_Check(q1)) {
+ quat1 = (QuaternionObject *)q1;
+ if (BaseMath_ReadCallback(quat1) == -1)
+ return NULL;
+ }
+ if (QuaternionObject_Check(q2)) {
+ quat2 = (QuaternionObject *)q2;
+ if (BaseMath_ReadCallback(quat2) == -1)
+ return NULL;
+ }
+
+ if (quat1 && quat2) { /* QUAT @ QUAT (cross product) */
+ mul_qt_qtqt(quat, quat1->quat, quat2->quat);
+ return Quaternion_CreatePyObject(quat, Py_TYPE(q1));
+ }
else if (quat1) {
- /* QUAT * VEC */
+ /* QUAT @ VEC */
if (VectorObject_Check(q2)) {
VectorObject *vec2 = (VectorObject *)q2;
float tvec[3];
if (vec2->size != 3) {
PyErr_SetString(PyExc_ValueError,
- "Vector multiplication: "
- "only 3D vector rotations (with quats) "
- "currently supported");
+ "Vector multiplication: "
+ "only 3D vector rotations (with quats) "
+ "currently supported");
return NULL;
}
if (BaseMath_ReadCallback(vec2) == -1) {
@@ -880,21 +962,48 @@ static PyObject *Quaternion_mul(PyObject *q1, PyObject *q2)
return Vector_CreatePyObject(tvec, 3, Py_TYPE(vec2));
}
- /* QUAT * FLOAT */
- else if ((((scalar = PyFloat_AsDouble(q2)) == -1.0f && PyErr_Occurred()) == 0)) {
- return quat_mul_float(quat1, scalar);
- }
- }
- else {
- BLI_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);
+ "Quaternion multiplication: "
+ "not supported between '%.200s' and '%.200s' types",
+ Py_TYPE(q1)->tp_name, Py_TYPE(q2)->tp_name);
return NULL;
}
+/*------------------------obj @= obj------------------------------
+ * inplace quaternion multiplication */
+static PyObject *Quaternion_imatmul(PyObject *q1, PyObject *q2)
+{
+ float quat[QUAT_SIZE];
+ QuaternionObject *quat1 = NULL, *quat2 = NULL;
+
+ if (QuaternionObject_Check(q1)) {
+ quat1 = (QuaternionObject *)q1;
+ if (BaseMath_ReadCallback(quat1) == -1)
+ return NULL;
+ }
+ if (QuaternionObject_Check(q2)) {
+ quat2 = (QuaternionObject *)q2;
+ if (BaseMath_ReadCallback(quat2) == -1)
+ return NULL;
+ }
+
+ if (quat1 && quat2) { /* QUAT @ QUAT (cross product) */
+ mul_qt_qtqt(quat, quat1->quat, quat2->quat);
+ copy_qt_qt(quat1->quat, quat);
+ }
+ else {
+ PyErr_Format(PyExc_TypeError,
+ "Inplace quaternion multiplication: "
+ "not supported between '%.200s' and '%.200s' types",
+ Py_TYPE(q1)->tp_name, Py_TYPE(q2)->tp_name);
+ return NULL;
+ }
+
+ (void)BaseMath_WriteCallback(quat1);
+ Py_INCREF(q1);
+ return q1;
+}
/* -obj
* returns the negative of this object*/
@@ -952,7 +1061,7 @@ static PyNumberMethods Quaternion_NumMethods = {
NULL, /*nb_float*/
NULL, /* nb_inplace_add */
NULL, /* nb_inplace_subtract */
- NULL, /* nb_inplace_multiply */
+ (binaryfunc) Quaternion_imul, /* nb_inplace_multiply */
NULL, /* nb_inplace_remainder */
NULL, /* nb_inplace_power */
NULL, /* nb_inplace_lshift */
@@ -965,6 +1074,8 @@ static PyNumberMethods Quaternion_NumMethods = {
NULL, /* nb_inplace_floor_divide */
NULL, /* nb_inplace_true_divide */
NULL, /* nb_index */
+ (binaryfunc) Quaternion_matmul, /* nb_matrix_multiply */
+ (binaryfunc) Quaternion_imatmul, /* nb_inplace_matrix_multiply */
};
PyDoc_STRVAR(Quaternion_axis_doc,
@@ -1100,7 +1211,8 @@ static PyObject *Quaternion_new(PyTypeObject *type, PyObject *args, PyObject *kw
{
PyObject *seq = NULL;
double angle = 0.0f;
- float quat[QUAT_SIZE] = {0.0f, 0.0f, 0.0f, 0.0f};
+ float quat[QUAT_SIZE];
+ unit_qt(quat);
if (kwds && PyDict_Size(kwds)) {
PyErr_SetString(PyExc_TypeError,
diff --git a/source/blender/python/mathutils/mathutils_Vector.c b/source/blender/python/mathutils/mathutils_Vector.c
index a06a63c8067..dc05f463d22 100644
--- a/source/blender/python/mathutils/mathutils_Vector.c
+++ b/source/blender/python/mathutils/mathutils_Vector.c
@@ -1127,23 +1127,17 @@ PyDoc_STRVAR(Vector_project_doc,
static PyObject *Vector_project(VectorObject *self, PyObject *value)
{
const int size = self->size;
- float tvec[MAX_DIMENSIONS];
- float vec[MAX_DIMENSIONS];
+ float *tvec;
double dot = 0.0f, dot2 = 0.0f;
int x;
- if (mathutils_array_parse(tvec, size, size, value, "Vector.project(other), invalid 'other' arg") == -1)
+ if (BaseMath_ReadCallback(self) == -1)
return NULL;
- if (self->size > 4) {
- PyErr_SetString(PyExc_ValueError,
- "Vector must be 2D, 3D or 4D");
+ if (mathutils_array_parse_alloc(&tvec, size, value, "Vector.project(other), invalid 'other' arg") == -1) {
return NULL;
}
- if (BaseMath_ReadCallback(self) == -1)
- return NULL;
-
/* get dot products */
for (x = 0; x < size; x++) {
dot += (double)(self->vec[x] * tvec[x]);
@@ -1152,9 +1146,9 @@ static PyObject *Vector_project(VectorObject *self, PyObject *value)
/* projection */
dot /= dot2;
for (x = 0; x < size; x++) {
- vec[x] = (float)dot * tvec[x];
+ tvec[x] *= (float)dot;
}
- return Vector_CreatePyObject(vec, size, Py_TYPE(self));
+ return Vector_CreatePyObject_alloc(tvec, size, Py_TYPE(self));
}
PyDoc_STRVAR(Vector_lerp_doc,
@@ -1712,12 +1706,25 @@ static PyObject *vector_mul_float(VectorObject *vec, const float scalar)
mul_vn_vn_fl(tvec, vec->vec, vec->size, scalar);
return Vector_CreatePyObject_alloc(tvec, vec->size, Py_TYPE(vec));
}
+#ifdef USE_MATHUTILS_ELEM_MUL
+static PyObject *vector_mul_vec(VectorObject *vec1, VectorObject *vec2)
+{
+ float *tvec = PyMem_Malloc(vec1->size * sizeof(float));
+ if (tvec == NULL) {
+ PyErr_SetString(PyExc_MemoryError,
+ "vec * vec: "
+ "problem allocating pointer space");
+ return NULL;
+ }
+ mul_vn_vnvn(tvec, vec1->vec, vec2->vec, vec1->size);
+ return Vector_CreatePyObject_alloc(tvec, vec1->size, Py_TYPE(vec1));
+}
+#endif
static PyObject *Vector_mul(PyObject *v1, PyObject *v2)
{
VectorObject *vec1 = NULL, *vec2 = NULL;
float scalar;
- int vec_size;
if (VectorObject_Check(v1)) {
vec1 = (VectorObject *)v1;
@@ -1735,6 +1742,7 @@ static PyObject *Vector_mul(PyObject *v1, PyObject *v2)
/* make sure v1 is always the vector */
if (vec1 && vec2) {
+#ifdef USE_MATHUTILS_ELEM_MUL
if (vec1->size != vec2->size) {
PyErr_SetString(PyExc_ValueError,
"Vector multiplication: "
@@ -1742,30 +1750,12 @@ static PyObject *Vector_mul(PyObject *v1, PyObject *v2)
return NULL;
}
- /*dot product*/
- return PyFloat_FromDouble(dot_vn_vn(vec1->vec, vec2->vec, vec1->size));
+ /* element-wise product */
+ return vector_mul_vec(vec1, vec2);
+#endif
}
else if (vec1) {
- if (MatrixObject_Check(v2)) {
- /* VEC * MATRIX */
- float tvec[MAX_DIMENSIONS];
-
- if (BaseMath_ReadCallback((MatrixObject *)v2) == -1)
- return NULL;
- if (row_vector_multiplication(tvec, vec1, (MatrixObject *)v2) == -1) {
- return NULL;
- }
-
- if (((MatrixObject *)v2)->num_row == 4 && vec1->size == 3) {
- vec_size = 3;
- }
- else {
- vec_size = ((MatrixObject *)v2)->num_col;
- }
-
- return Vector_CreatePyObject(tvec, vec_size, Py_TYPE(vec1));
- }
- else if (((scalar = PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred()) == 0) { /* VEC * FLOAT */
+ if (((scalar = PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred()) == 0) { /* VEC * FLOAT */
return vector_mul_float(vec1, scalar);
}
}
@@ -1774,12 +1764,9 @@ static PyObject *Vector_mul(PyObject *v1, PyObject *v2)
return vector_mul_float(vec2, scalar);
}
}
- else {
- BLI_assert(!"internal error");
- }
PyErr_Format(PyExc_TypeError,
- "Vector multiplication: "
+ "Element-wise multiplication: "
"not supported between '%.200s' and '%.200s' types",
Py_TYPE(v1)->tp_name, Py_TYPE(v2)->tp_name);
return NULL;
@@ -1788,32 +1775,129 @@ static PyObject *Vector_mul(PyObject *v1, PyObject *v2)
/* multiplication in-place: obj *= obj */
static PyObject *Vector_imul(PyObject *v1, PyObject *v2)
{
- VectorObject *vec = (VectorObject *)v1;
+ VectorObject *vec1 = NULL, *vec2 = NULL;
float scalar;
- if (BaseMath_ReadCallback_ForWrite(vec) == -1)
+ if (VectorObject_Check(v1)) {
+ vec1 = (VectorObject *)v1;
+ if (BaseMath_ReadCallback(vec1) == -1)
+ return NULL;
+ }
+ if (VectorObject_Check(v2)) {
+ vec2 = (VectorObject *)v2;
+ if (BaseMath_ReadCallback(vec2) == -1)
+ return NULL;
+ }
+
+ if (BaseMath_ReadCallback_ForWrite(vec1) == -1)
return NULL;
/* Intentionally don't support (Quaternion, Matrix) here, uses reverse order instead. */
- /* only support 'vec *= float'
- * vec*=vec result is a float so that wont work */
- if (((scalar = PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred()) == 0) { /* VEC *= FLOAT */
- mul_vn_fl(vec->vec, vec->size, scalar);
+ if (vec1 && vec2) {
+#ifdef USE_MATHUTILS_ELEM_MUL
+ if (vec1->size != vec2->size) {
+ PyErr_SetString(PyExc_ValueError,
+ "Vector multiplication: "
+ "vectors must have the same dimensions for this operation");
+ return NULL;
+ }
+
+ /* element-wise product inplace */
+ mul_vn_vn(vec1->vec, vec2->vec, vec1->size);
+#else
+ PyErr_Format(PyExc_TypeError,
+ "Inplace element-wise multiplication: "
+ "not supported between '%.200s' and '%.200s' types",
+ Py_TYPE(v1)->tp_name, Py_TYPE(v2)->tp_name);
+ return NULL;
+#endif
+ }
+ else if (vec1 && (((scalar = PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred()) == 0)) { /* VEC *= FLOAT */
+ mul_vn_fl(vec1->vec, vec1->size, scalar);
}
else {
PyErr_Format(PyExc_TypeError,
- "Vector multiplication: (%s *= %s) "
- "invalid type for this operation",
- Py_TYPE(v1)->tp_name, Py_TYPE(v2)->tp_name);
+ "Inplace element-wise multiplication: "
+ "not supported between '%.200s' and '%.200s' types",
+ Py_TYPE(v1)->tp_name, Py_TYPE(v2)->tp_name);
return NULL;
}
- (void)BaseMath_WriteCallback(vec);
+ (void)BaseMath_WriteCallback(vec1);
Py_INCREF(v1);
return v1;
}
+static PyObject *Vector_matmul(PyObject *v1, PyObject *v2)
+{
+ VectorObject *vec1 = NULL, *vec2 = NULL;
+ int vec_size;
+
+ if (VectorObject_Check(v1)) {
+ vec1 = (VectorObject *)v1;
+ if (BaseMath_ReadCallback(vec1) == -1)
+ return NULL;
+ }
+ if (VectorObject_Check(v2)) {
+ vec2 = (VectorObject *)v2;
+ if (BaseMath_ReadCallback(vec2) == -1)
+ return NULL;
+ }
+
+
+ /* Intentionally don't support (Quaternion) here, uses reverse order instead. */
+
+ /* make sure v1 is always the vector */
+ if (vec1 && vec2) {
+ if (vec1->size != vec2->size) {
+ PyErr_SetString(PyExc_ValueError,
+ "Vector multiplication: "
+ "vectors must have the same dimensions for this operation");
+ return NULL;
+ }
+
+ /*dot product*/
+ return PyFloat_FromDouble(dot_vn_vn(vec1->vec, vec2->vec, vec1->size));
+ }
+ else if (vec1) {
+ if (MatrixObject_Check(v2)) {
+ /* VEC @ MATRIX */
+ float tvec[MAX_DIMENSIONS];
+
+ if (BaseMath_ReadCallback((MatrixObject *)v2) == -1)
+ return NULL;
+ if (row_vector_multiplication(tvec, vec1, (MatrixObject *)v2) == -1) {
+ return NULL;
+ }
+
+ if (((MatrixObject *)v2)->num_row == 4 && vec1->size == 3) {
+ vec_size = 3;
+ }
+ else {
+ vec_size = ((MatrixObject *)v2)->num_col;
+ }
+
+ return Vector_CreatePyObject(tvec, vec_size, Py_TYPE(vec1));
+ }
+ }
+
+ 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;
+}
+
+static PyObject *Vector_imatmul(PyObject *v1, PyObject *v2)
+{
+ PyErr_Format(PyExc_TypeError,
+ "Inplace vector multiplication: "
+ "not supported between '%.200s' and '%.200s' types",
+ Py_TYPE(v1)->tp_name, Py_TYPE(v2)->tp_name);
+ return NULL;
+}
+
/* divid: obj / obj */
static PyObject *Vector_div(PyObject *v1, PyObject *v2)
{
@@ -2125,6 +2209,8 @@ static PyNumberMethods Vector_NumMethods = {
NULL, /* nb_inplace_floor_divide */
Vector_idiv, /* nb_inplace_true_divide */
NULL, /* nb_index */
+ (binaryfunc) Vector_matmul, /* nb_matrix_multiply */
+ (binaryfunc) Vector_imatmul, /* nb_inplace_matrix_multiply */
};
/*------------------PY_OBECT DEFINITION--------------------------*/