Changeset View
Changeset View
Standalone View
Standalone View
source/blender/python/mathutils/mathutils_Vector.c
| Show First 20 Lines • Show All 1,496 Lines • ▼ Show 20 Lines | static int Vector_ass_slice(VectorObject *self, int begin, int end, PyObject *seq) | ||||
| if (BaseMath_WriteCallback(self) == -1) | if (BaseMath_WriteCallback(self) == -1) | ||||
| return -1; | return -1; | ||||
| return 0; | return 0; | ||||
| } | } | ||||
| /* Numeric Protocols */ | /* Numeric Protocols */ | ||||
| /* addition: obj + obj */ | /* element-wise addition: obj + obj */ | ||||
| static PyObject *Vector_add(PyObject *v1, PyObject *v2) | static PyObject *Vector_add(PyObject *v1, PyObject *v2) | ||||
| { | { | ||||
| VectorObject *vec1 = NULL, *vec2 = NULL; | return mathtutils_generic_elem_op(v1, v2, ADD); | ||||
| float *vec = NULL; | |||||
| if (!VectorObject_Check(v1) || !VectorObject_Check(v2)) { | |||||
| PyErr_Format(PyExc_AttributeError, | |||||
| "Vector addition: (%s + %s) " | |||||
| "invalid type for this operation", | |||||
| Py_TYPE(v1)->tp_name, Py_TYPE(v2)->tp_name); | |||||
| return NULL; | |||||
| } | |||||
| vec1 = (VectorObject *)v1; | |||||
| vec2 = (VectorObject *)v2; | |||||
| if (BaseMath_ReadCallback(vec1) == -1 || BaseMath_ReadCallback(vec2) == -1) | |||||
| return NULL; | |||||
| /*VECTOR + VECTOR*/ | |||||
| if (vec1->size != vec2->size) { | |||||
| PyErr_SetString(PyExc_AttributeError, | |||||
| "Vector addition: " | |||||
| "vectors must have the same dimensions for this operation"); | |||||
| return NULL; | |||||
| } | |||||
| vec = PyMem_Malloc(vec1->size * sizeof(float)); | |||||
| if (vec == NULL) { | |||||
| PyErr_SetString(PyExc_MemoryError, | |||||
| "Vector(): " | |||||
| "problem allocating pointer space"); | |||||
| return NULL; | |||||
| } | } | ||||
| add_vn_vnvn(vec, vec1->vec, vec2->vec, vec1->size); | /* element-wise addition in-place: obj += obj */ | ||||
| return Vector_CreatePyObject_alloc(vec, vec1->size, Py_TYPE(v1)); | |||||
| } | |||||
| /* addition in-place: obj += obj */ | |||||
| static PyObject *Vector_iadd(PyObject *v1, PyObject *v2) | static PyObject *Vector_iadd(PyObject *v1, PyObject *v2) | ||||
| { | { | ||||
| VectorObject *vec1 = NULL, *vec2 = NULL; | return mathtutils_generic_elem_op_inplace(v1, v2, ADD); | ||||
| if (!VectorObject_Check(v1) || !VectorObject_Check(v2)) { | |||||
| PyErr_Format(PyExc_AttributeError, | |||||
| "Vector addition: (%s += %s) " | |||||
| "invalid type for this operation", | |||||
| Py_TYPE(v1)->tp_name, Py_TYPE(v2)->tp_name); | |||||
| return NULL; | |||||
| } | } | ||||
| vec1 = (VectorObject *)v1; | |||||
| vec2 = (VectorObject *)v2; | |||||
| if (vec1->size != vec2->size) { | /* element-wise subtraction: obj - obj */ | ||||
| PyErr_SetString(PyExc_AttributeError, | |||||
| "Vector addition: " | |||||
| "vectors must have the same dimensions for this operation"); | |||||
| return NULL; | |||||
| } | |||||
| if (BaseMath_ReadCallback_ForWrite(vec1) == -1 || BaseMath_ReadCallback(vec2) == -1) | |||||
| return NULL; | |||||
| add_vn_vn(vec1->vec, vec2->vec, vec1->size); | |||||
| (void)BaseMath_WriteCallback(vec1); | |||||
| Py_INCREF(v1); | |||||
| return v1; | |||||
| } | |||||
| /* subtraction: obj - obj */ | |||||
| static PyObject *Vector_sub(PyObject *v1, PyObject *v2) | static PyObject *Vector_sub(PyObject *v1, PyObject *v2) | ||||
| { | { | ||||
| VectorObject *vec1 = NULL, *vec2 = NULL; | return mathtutils_generic_elem_op(v1, v2, SUB); | ||||
| float *vec; | |||||
| if (!VectorObject_Check(v1) || !VectorObject_Check(v2)) { | |||||
| PyErr_Format(PyExc_AttributeError, | |||||
| "Vector subtraction: (%s - %s) " | |||||
| "invalid type for this operation", | |||||
| Py_TYPE(v1)->tp_name, Py_TYPE(v2)->tp_name); | |||||
| return NULL; | |||||
| } | |||||
| vec1 = (VectorObject *)v1; | |||||
| vec2 = (VectorObject *)v2; | |||||
| if (BaseMath_ReadCallback(vec1) == -1 || BaseMath_ReadCallback(vec2) == -1) | |||||
| return NULL; | |||||
| if (vec1->size != vec2->size) { | |||||
| PyErr_SetString(PyExc_AttributeError, | |||||
| "Vector subtraction: " | |||||
| "vectors must have the same dimensions for this operation"); | |||||
| return NULL; | |||||
| } | } | ||||
| vec = PyMem_Malloc(vec1->size * sizeof(float)); | /* element-wise subtraction in-place: obj -= obj */ | ||||
| if (vec == NULL) { | static PyObject *Vector_isub(PyObject *v1, PyObject *v2) | ||||
| PyErr_SetString(PyExc_MemoryError, | { | ||||
| "Vector(): " | return mathtutils_generic_elem_op_inplace(v1, v2, SUB); | ||||
| "problem allocating pointer space"); | |||||
| return NULL; | |||||
| } | } | ||||
| sub_vn_vnvn(vec, vec1->vec, vec2->vec, vec1->size); | /* element-wise multiplication: obj * obj */ | ||||
| static PyObject *Vector_mul(PyObject *v1, PyObject *v2) | |||||
| return Vector_CreatePyObject_alloc(vec, vec1->size, Py_TYPE(v1)); | { | ||||
| return mathtutils_generic_elem_op(v1, v2, MUL); | |||||
| } | } | ||||
| /* subtraction in-place: obj -= obj */ | /* element-wise multiplication in-place: obj *= obj */ | ||||
| static PyObject *Vector_isub(PyObject *v1, PyObject *v2) | static PyObject *Vector_imul(PyObject *v1, PyObject *v2) | ||||
| { | { | ||||
| VectorObject *vec1 = NULL, *vec2 = NULL; | return mathtutils_generic_elem_op_inplace(v1, v2, MUL); | ||||
| if (!VectorObject_Check(v1) || !VectorObject_Check(v2)) { | |||||
| PyErr_Format(PyExc_AttributeError, | |||||
| "Vector subtraction: (%s -= %s) " | |||||
| "invalid type for this operation", | |||||
| Py_TYPE(v1)->tp_name, Py_TYPE(v2)->tp_name); | |||||
| return NULL; | |||||
| } | } | ||||
| vec1 = (VectorObject *)v1; | |||||
| vec2 = (VectorObject *)v2; | |||||
| if (vec1->size != vec2->size) { | /* element-wise divide: obj / obj */ | ||||
| PyErr_SetString(PyExc_AttributeError, | static PyObject *Vector_div(PyObject *v1, PyObject *v2) | ||||
| "Vector subtraction: " | { | ||||
| "vectors must have the same dimensions for this operation"); | return mathtutils_generic_elem_op(v1, v2, DIV); | ||||
| return NULL; | |||||
| } | } | ||||
| if (BaseMath_ReadCallback_ForWrite(vec1) == -1 || BaseMath_ReadCallback(vec2) == -1) | /* element-wise divide in-place: obj /= obj */ | ||||
| return NULL; | static PyObject *Vector_idiv(PyObject *v1, PyObject *v2) | ||||
| { | |||||
| sub_vn_vn(vec1->vec, vec2->vec, vec1->size); | return mathtutils_generic_elem_op_inplace(v1, v2, DIV); | ||||
| (void)BaseMath_WriteCallback(vec1); | |||||
| Py_INCREF(v1); | |||||
| return v1; | |||||
| } | } | ||||
| /*------------------------obj * obj------------------------------ | |||||
| * multiplication */ | |||||
| /** | /** | ||||
| * Column vector multiplication (Matrix * Vector). | * Column vector multiplication (Matrix * Vector). | ||||
| * <pre> | * <pre> | ||||
| * [1][4][7] [a] | * [1][4][7] [a] | ||||
| * [2][5][8] * [b] | * [2][5][8] * [b] | ||||
| * [3][6][9] [c] | * [3][6][9] [c] | ||||
| * </pre> | * </pre> | ||||
| * | * | ||||
| Show All 28 Lines | for (col = 0; col < mat->num_col; col++) { | ||||
| dot += (double)(MATRIX_ITEM(mat, row, col) * vec_cpy[col]); | dot += (double)(MATRIX_ITEM(mat, row, col) * vec_cpy[col]); | ||||
| } | } | ||||
| r_vec[z++] = (float)dot; | r_vec[z++] = (float)dot; | ||||
| } | } | ||||
| return 0; | return 0; | ||||
| } | } | ||||
| static PyObject *vector_mul_float(VectorObject *vec, const float scalar) | /* matrix multiplication: obj @ obj */ | ||||
| { | |||||
| float *tvec = PyMem_Malloc(vec->size * sizeof(float)); | |||||
| if (tvec == NULL) { | |||||
| PyErr_SetString(PyExc_MemoryError, | |||||
| "vec * float: " | |||||
| "problem allocating pointer space"); | |||||
| return NULL; | |||||
| } | |||||
| 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; | |||||
| 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) { | |||||
| #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 */ | |||||
| return vector_mul_vec(vec1, vec2); | |||||
| #endif | |||||
| } | |||||
| else if (vec1) { | |||||
| if (((scalar = PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred()) == 0) { /* VEC * FLOAT */ | |||||
| return vector_mul_float(vec1, scalar); | |||||
| } | |||||
| } | |||||
| else if (vec2) { | |||||
| if (((scalar = PyFloat_AsDouble(v1)) == -1.0f && PyErr_Occurred()) == 0) { /* FLOAT * VEC */ | |||||
| return vector_mul_float(vec2, scalar); | |||||
| } | |||||
| } | |||||
| PyErr_Format(PyExc_TypeError, | |||||
| "Element-wise multiplication: " | |||||
| "not supported between '%.200s' and '%.200s' types", | |||||
| Py_TYPE(v1)->tp_name, Py_TYPE(v2)->tp_name); | |||||
| return NULL; | |||||
| } | |||||
| /* multiplication in-place: obj *= obj */ | |||||
| static PyObject *Vector_imul(PyObject *v1, PyObject *v2) | |||||
| { | |||||
| VectorObject *vec1 = NULL, *vec2 = NULL; | |||||
| float scalar; | |||||
| 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. */ | |||||
| 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, | |||||
| "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(vec1); | |||||
| Py_INCREF(v1); | |||||
| return v1; | |||||
| } | |||||
| static PyObject *Vector_matmul(PyObject *v1, PyObject *v2) | static PyObject *Vector_matmul(PyObject *v1, PyObject *v2) | ||||
| { | { | ||||
| VectorObject *vec1 = NULL, *vec2 = NULL; | VectorObject *vec1 = NULL, *vec2 = NULL; | ||||
| int vec_size; | int vec_size; | ||||
| if (VectorObject_Check(v1)) { | if (VectorObject_Check(v1)) { | ||||
| vec1 = (VectorObject *)v1; | vec1 = (VectorObject *)v1; | ||||
| if (BaseMath_ReadCallback(vec1) == -1) | if (BaseMath_ReadCallback(vec1) == -1) | ||||
| ▲ Show 20 Lines • Show All 44 Lines • ▼ Show 20 Lines | static PyObject *Vector_matmul(PyObject *v1, PyObject *v2) | ||||
| PyErr_Format(PyExc_TypeError, | PyErr_Format(PyExc_TypeError, | ||||
| "Vector multiplication: " | "Vector multiplication: " | ||||
| "not supported between '%.200s' and '%.200s' types", | "not supported between '%.200s' and '%.200s' types", | ||||
| Py_TYPE(v1)->tp_name, Py_TYPE(v2)->tp_name); | Py_TYPE(v1)->tp_name, Py_TYPE(v2)->tp_name); | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| /* matrix multiplication in-place: obj @= obj */ | |||||
| static PyObject *Vector_imatmul(PyObject *v1, PyObject *v2) | static PyObject *Vector_imatmul(PyObject *v1, PyObject *v2) | ||||
| { | { | ||||
| PyErr_Format(PyExc_TypeError, | PyErr_Format(PyExc_TypeError, | ||||
| "Inplace vector multiplication: " | "Inplace vector multiplication: " | ||||
| "not supported between '%.200s' and '%.200s' types", | "not supported between '%.200s' and '%.200s' types", | ||||
| Py_TYPE(v1)->tp_name, Py_TYPE(v2)->tp_name); | Py_TYPE(v1)->tp_name, Py_TYPE(v2)->tp_name); | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| /* divid: obj / obj */ | |||||
| static PyObject *Vector_div(PyObject *v1, PyObject *v2) | |||||
| { | |||||
| float *vec = NULL, scalar; | |||||
| VectorObject *vec1 = NULL; | |||||
| if (!VectorObject_Check(v1)) { /* not a vector */ | |||||
| PyErr_SetString(PyExc_TypeError, | |||||
| "Vector division: " | |||||
| "Vector must be divided by a float"); | |||||
| return NULL; | |||||
| } | |||||
| vec1 = (VectorObject *)v1; /* vector */ | |||||
| if (BaseMath_ReadCallback(vec1) == -1) | |||||
| return NULL; | |||||
| if ((scalar = PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred()) { /* parsed item not a number */ | |||||
| PyErr_SetString(PyExc_TypeError, | |||||
| "Vector division: " | |||||
| "Vector must be divided by a float"); | |||||
| return NULL; | |||||
| } | |||||
| if (scalar == 0.0f) { | |||||
| PyErr_SetString(PyExc_ZeroDivisionError, | |||||
| "Vector division: " | |||||
| "divide by zero error"); | |||||
| return NULL; | |||||
| } | |||||
| vec = PyMem_Malloc(vec1->size * sizeof(float)); | |||||
| if (vec == NULL) { | |||||
| PyErr_SetString(PyExc_MemoryError, | |||||
| "vec / value: " | |||||
| "problem allocating pointer space"); | |||||
| return NULL; | |||||
| } | |||||
| mul_vn_vn_fl(vec, vec1->vec, vec1->size, 1.0f / scalar); | |||||
| return Vector_CreatePyObject_alloc(vec, vec1->size, Py_TYPE(v1)); | |||||
| } | |||||
| /* divide in-place: obj /= obj */ | |||||
| static PyObject *Vector_idiv(PyObject *v1, PyObject *v2) | |||||
| { | |||||
| float scalar; | |||||
| VectorObject *vec1 = (VectorObject *)v1; | |||||
| if (BaseMath_ReadCallback_ForWrite(vec1) == -1) | |||||
| return NULL; | |||||
| if ((scalar = PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred()) { /* parsed item not a number */ | |||||
| PyErr_SetString(PyExc_TypeError, | |||||
| "Vector division: " | |||||
| "Vector must be divided by a float"); | |||||
| return NULL; | |||||
| } | |||||
| if (scalar == 0.0f) { | |||||
| PyErr_SetString(PyExc_ZeroDivisionError, | |||||
| "Vector division: " | |||||
| "divide by zero error"); | |||||
| return NULL; | |||||
| } | |||||
| mul_vn_fl(vec1->vec, vec1->size, 1.0f / scalar); | |||||
| (void)BaseMath_WriteCallback(vec1); | |||||
| Py_INCREF(v1); | |||||
| return v1; | |||||
| } | |||||
| /* -obj | /* -obj | ||||
| * returns the negative of this object*/ | * returns the negative of this object*/ | ||||
| static PyObject *Vector_neg(VectorObject *self) | static PyObject *Vector_neg(VectorObject *self) | ||||
| { | { | ||||
| float *tvec; | float *tvec; | ||||
| if (BaseMath_ReadCallback(self) == -1) | if (BaseMath_ReadCallback(self) == -1) | ||||
| return NULL; | return NULL; | ||||
| ▲ Show 20 Lines • Show All 1,199 Lines • Show Last 20 Lines | |||||