Blender  V3.3
mathutils_Matrix.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
7 #include <Python.h>
8 
9 #include "mathutils.h"
10 
11 #include "BLI_math.h"
12 #include "BLI_utildefines.h"
13 
14 #include "../generic/py_capi_utils.h"
15 #include "../generic/python_utildefines.h"
16 
17 #ifndef MATH_STANDALONE
18 # include "BLI_dynstr.h"
19 # include "BLI_string.h"
20 #endif
21 
22 typedef enum eMatrixAccess_t {
26 
27 static PyObject *Matrix_copy_notest(MatrixObject *self, const float *matrix);
28 static PyObject *Matrix_copy(MatrixObject *self);
29 static PyObject *Matrix_deepcopy(MatrixObject *self, PyObject *args);
30 static int Matrix_ass_slice(MatrixObject *self, int begin, int end, PyObject *value);
31 static PyObject *matrix__apply_to_copy(PyObject *(*matrix_func)(MatrixObject *),
32  MatrixObject *self);
33 static PyObject *MatrixAccess_CreatePyObject(MatrixObject *matrix, const eMatrixAccess_t type);
34 
35 /* -------------------------------------------------------------------- */
39 static int matrix_row_vector_check(MatrixObject *mat, VectorObject *vec, int row)
40 {
41  if ((vec->vec_num != mat->col_num) || (row >= mat->row_num)) {
42  PyErr_SetString(PyExc_AttributeError,
43  "Matrix(): "
44  "owner matrix has been resized since this row vector was created");
45  return 0;
46  }
47 
48  return 1;
49 }
50 
52 {
53  if ((vec->vec_num != mat->row_num) || (col >= mat->col_num)) {
54  PyErr_SetString(PyExc_AttributeError,
55  "Matrix(): "
56  "owner matrix has been resized since this column vector was created");
57  return 0;
58  }
59 
60  return 1;
61 }
62 
64 static void matrix_3x3_as_4x4(float mat[16])
65 {
66  mat[10] = mat[8];
67  mat[9] = mat[7];
68  mat[8] = mat[6];
69  mat[7] = 0.0f;
70  mat[6] = mat[5];
71  mat[5] = mat[4];
72  mat[4] = mat[3];
73  mat[3] = 0.0f;
74 }
75 
76 void matrix_as_3x3(float mat[3][3], MatrixObject *self)
77 {
78  copy_v3_v3(mat[0], MATRIX_COL_PTR(self, 0));
79  copy_v3_v3(mat[1], MATRIX_COL_PTR(self, 1));
80  copy_v3_v3(mat[2], MATRIX_COL_PTR(self, 2));
81 }
82 
83 static void matrix_copy(MatrixObject *mat_dst, const MatrixObject *mat_src)
84 {
85  BLI_assert((mat_dst->col_num == mat_src->col_num) && (mat_dst->row_num == mat_src->row_num));
86  BLI_assert(mat_dst != mat_src);
87 
88  memcpy(mat_dst->matrix, mat_src->matrix, sizeof(float) * (mat_dst->col_num * mat_dst->row_num));
89 }
90 
92 {
93  const int mat_size = sizeof(float) * (self->col_num * self->row_num);
94  memset(self->matrix, 0x0, mat_size);
95  const int col_row_max = min_ii(self->col_num, self->row_num);
96  const int row_num = self->row_num;
97  for (int col = 0; col < col_row_max; col++) {
98  self->matrix[(col * row_num) + col] = 1.0f;
99  }
100 }
101 
103 static void matrix_transpose_internal(float mat_dst_fl[], const MatrixObject *mat_src)
104 {
105  ushort col, row;
106  uint i = 0;
107 
108  for (row = 0; row < mat_src->row_num; row++) {
109  for (col = 0; col < mat_src->col_num; col++) {
110  mat_dst_fl[i++] = MATRIX_ITEM(mat_src, row, col);
111  }
112  }
113 }
114 
116 static float matrix_determinant_internal(const MatrixObject *self)
117 {
118  if (self->col_num == 2) {
119  return determinant_m2(MATRIX_ITEM(self, 0, 0),
120  MATRIX_ITEM(self, 0, 1),
121  MATRIX_ITEM(self, 1, 0),
122  MATRIX_ITEM(self, 1, 1));
123  }
124  if (self->col_num == 3) {
125  return determinant_m3(MATRIX_ITEM(self, 0, 0),
126  MATRIX_ITEM(self, 0, 1),
127  MATRIX_ITEM(self, 0, 2),
128  MATRIX_ITEM(self, 1, 0),
129  MATRIX_ITEM(self, 1, 1),
130  MATRIX_ITEM(self, 1, 2),
131  MATRIX_ITEM(self, 2, 0),
132  MATRIX_ITEM(self, 2, 1),
133  MATRIX_ITEM(self, 2, 2));
134  }
135 
136  return determinant_m4((const float(*)[4])self->matrix);
137 }
138 
139 static void adjoint_matrix_n(float *mat_dst, const float *mat_src, const ushort dim)
140 {
141  /* calculate the classical adjoint */
142  switch (dim) {
143  case 2: {
144  adjoint_m2_m2((float(*)[2])mat_dst, (const float(*)[2])mat_src);
145  break;
146  }
147  case 3: {
148  adjoint_m3_m3((float(*)[3])mat_dst, (const float(*)[3])mat_src);
149  break;
150  }
151  case 4: {
152  adjoint_m4_m4((float(*)[4])mat_dst, (const float(*)[4])mat_src);
153  break;
154  }
155  default:
157  break;
158  }
159 }
160 
161 static void matrix_invert_with_det_n_internal(float *mat_dst,
162  const float *mat_src,
163  const float det,
164  const ushort dim)
165 {
166  float mat[MATRIX_MAX_DIM * MATRIX_MAX_DIM];
167  ushort i, j, k;
168 
169  BLI_assert(det != 0.0f);
170 
171  adjoint_matrix_n(mat, mat_src, dim);
172 
173  /* divide by determinant & set values */
174  k = 0;
175  for (i = 0; i < dim; i++) { /* col_num */
176  for (j = 0; j < dim; j++) { /* row_num */
177  mat_dst[MATRIX_ITEM_INDEX_NUMROW(dim, j, i)] = mat[k++] / det;
178  }
179  }
180 }
181 
185 static bool matrix_invert_internal(const MatrixObject *self, float *r_mat)
186 {
187  float det;
188  BLI_assert(self->col_num == self->row_num);
189  det = matrix_determinant_internal(self);
190 
191  if (det != 0.0f) {
192  matrix_invert_with_det_n_internal(r_mat, self->matrix, det, self->col_num);
193  return true;
194  }
195 
196  return false;
197 }
198 
203 static void matrix_invert_safe_internal(const MatrixObject *self, float *r_mat)
204 {
205  float det;
206  float *in_mat = self->matrix;
207  BLI_assert(self->col_num == self->row_num);
208  det = matrix_determinant_internal(self);
209 
210  if (det == 0.0f) {
211  const float eps = PSEUDOINVERSE_EPSILON;
212 
213  /* We will copy self->matrix into r_mat (if needed),
214  * and modify it in place to add diagonal epsilon. */
215  in_mat = r_mat;
216 
217  switch (self->col_num) {
218  case 2: {
219  float(*mat)[2] = (float(*)[2])in_mat;
220 
221  if (in_mat != self->matrix) {
222  copy_m2_m2(mat, (const float(*)[2])self->matrix);
223  }
224  mat[0][0] += eps;
225  mat[1][1] += eps;
226 
227  if (UNLIKELY((det = determinant_m2(mat[0][0], mat[0][1], mat[1][0], mat[1][1])) == 0.0f)) {
228  unit_m2(mat);
229  det = 1.0f;
230  }
231  break;
232  }
233  case 3: {
234  float(*mat)[3] = (float(*)[3])in_mat;
235 
236  if (in_mat != self->matrix) {
237  copy_m3_m3(mat, (const float(*)[3])self->matrix);
238  }
239  mat[0][0] += eps;
240  mat[1][1] += eps;
241  mat[2][2] += eps;
242 
243  if (UNLIKELY((det = determinant_m3_array(mat)) == 0.0f)) {
244  unit_m3(mat);
245  det = 1.0f;
246  }
247  break;
248  }
249  case 4: {
250  float(*mat)[4] = (float(*)[4])in_mat;
251 
252  if (in_mat != self->matrix) {
253  copy_m4_m4(mat, (const float(*)[4])self->matrix);
254  }
255  mat[0][0] += eps;
256  mat[1][1] += eps;
257  mat[2][2] += eps;
258  mat[3][3] += eps;
259 
260  if (UNLIKELY(det = determinant_m4(mat)) == 0.0f) {
261  unit_m4(mat);
262  det = 1.0f;
263  }
264  break;
265  }
266  default:
268  }
269  }
270 
271  matrix_invert_with_det_n_internal(r_mat, in_mat, det, self->col_num);
272 }
273 
274 static PyObject *matrix__apply_to_copy(PyObject *(*matrix_func)(MatrixObject *),
275  MatrixObject *self)
276 {
277  PyObject *ret = Matrix_copy(self);
278  if (ret) {
279  PyObject *ret_dummy = matrix_func((MatrixObject *)ret);
280  if (ret_dummy) {
281  Py_DECREF(ret_dummy);
282  return ret;
283  }
284  /* error */
285  Py_DECREF(ret);
286  return NULL;
287  }
288 
289  /* copy may fail if the read callback errors out */
290  return NULL;
291 }
292 
294 {
295  for (int row = 0; row < self->row_num; row++) {
296  for (int col = 0; col < self->col_num; col++) {
297  if (MATRIX_ITEM(self, row, col) != ((row != col) ? 0.0f : 1.0f)) {
298  return false;
299  }
300  }
301  }
302  return true;
303 }
304 
307 /* -------------------------------------------------------------------- */
313 
315 {
316  MatrixObject *self = (MatrixObject *)bmo->cb_user;
317  return BaseMath_ReadCallback(self);
318 }
319 
320 static int mathutils_matrix_row_get(BaseMathObject *bmo, int row)
321 {
322  MatrixObject *self = (MatrixObject *)bmo->cb_user;
323  int col;
324 
325  if (BaseMath_ReadCallback(self) == -1) {
326  return -1;
327  }
328  if (!matrix_row_vector_check(self, (VectorObject *)bmo, row)) {
329  return -1;
330  }
331 
332  for (col = 0; col < self->col_num; col++) {
333  bmo->data[col] = MATRIX_ITEM(self, row, col);
334  }
335 
336  return 0;
337 }
338 
339 static int mathutils_matrix_row_set(BaseMathObject *bmo, int row)
340 {
341  MatrixObject *self = (MatrixObject *)bmo->cb_user;
342  int col;
343 
344  if (BaseMath_ReadCallback_ForWrite(self) == -1) {
345  return -1;
346  }
347  if (!matrix_row_vector_check(self, (VectorObject *)bmo, row)) {
348  return -1;
349  }
350 
351  for (col = 0; col < self->col_num; col++) {
352  MATRIX_ITEM(self, row, col) = bmo->data[col];
353  }
354 
356  return 0;
357 }
358 
359 static int mathutils_matrix_row_get_index(BaseMathObject *bmo, int row, int col)
360 {
361  MatrixObject *self = (MatrixObject *)bmo->cb_user;
362 
363  if (BaseMath_ReadCallback(self) == -1) {
364  return -1;
365  }
366  if (!matrix_row_vector_check(self, (VectorObject *)bmo, row)) {
367  return -1;
368  }
369 
370  bmo->data[col] = MATRIX_ITEM(self, row, col);
371  return 0;
372 }
373 
374 static int mathutils_matrix_row_set_index(BaseMathObject *bmo, int row, int col)
375 {
376  MatrixObject *self = (MatrixObject *)bmo->cb_user;
377 
378  if (BaseMath_ReadCallback_ForWrite(self) == -1) {
379  return -1;
380  }
381  if (!matrix_row_vector_check(self, (VectorObject *)bmo, row)) {
382  return -1;
383  }
384 
385  MATRIX_ITEM(self, row, col) = bmo->data[col];
386 
388  return 0;
389 }
390 
397 };
398 
401 /* -------------------------------------------------------------------- */
407 
409 {
410  MatrixObject *self = (MatrixObject *)bmo->cb_user;
411  return BaseMath_ReadCallback(self);
412 }
413 
415 {
416  MatrixObject *self = (MatrixObject *)bmo->cb_user;
417  int row_num;
418  int row;
419 
420  if (BaseMath_ReadCallback(self) == -1) {
421  return -1;
422  }
423  if (!matrix_col_vector_check(self, (VectorObject *)bmo, col)) {
424  return -1;
425  }
426 
427  /* for 'translation' `vec_num` will always be '3' even on 4x4 vec */
428  row_num = min_ii(self->row_num, ((const VectorObject *)bmo)->vec_num);
429 
430  for (row = 0; row < row_num; row++) {
431  bmo->data[row] = MATRIX_ITEM(self, row, col);
432  }
433 
434  return 0;
435 }
436 
438 {
439  MatrixObject *self = (MatrixObject *)bmo->cb_user;
440  int row_num;
441  int row;
442 
443  if (BaseMath_ReadCallback_ForWrite(self) == -1) {
444  return -1;
445  }
446  if (!matrix_col_vector_check(self, (VectorObject *)bmo, col)) {
447  return -1;
448  }
449 
450  /* for 'translation' `vec_num` will always be '3' even on 4x4 vec */
451  row_num = min_ii(self->row_num, ((const VectorObject *)bmo)->vec_num);
452 
453  for (row = 0; row < row_num; row++) {
454  MATRIX_ITEM(self, row, col) = bmo->data[row];
455  }
456 
458  return 0;
459 }
460 
461 static int mathutils_matrix_col_get_index(BaseMathObject *bmo, int col, int row)
462 {
463  MatrixObject *self = (MatrixObject *)bmo->cb_user;
464 
465  if (BaseMath_ReadCallback(self) == -1) {
466  return -1;
467  }
468  if (!matrix_col_vector_check(self, (VectorObject *)bmo, col)) {
469  return -1;
470  }
471 
472  bmo->data[row] = MATRIX_ITEM(self, row, col);
473  return 0;
474 }
475 
476 static int mathutils_matrix_col_set_index(BaseMathObject *bmo, int col, int row)
477 {
478  MatrixObject *self = (MatrixObject *)bmo->cb_user;
479 
480  if (BaseMath_ReadCallback_ForWrite(self) == -1) {
481  return -1;
482  }
483  if (!matrix_col_vector_check(self, (VectorObject *)bmo, col)) {
484  return -1;
485  }
486 
487  MATRIX_ITEM(self, row, col) = bmo->data[row];
488 
490  return 0;
491 }
492 
499 };
500 
503 /* -------------------------------------------------------------------- */
511 
513 {
514  MatrixObject *self = (MatrixObject *)bmo->cb_user;
515  return BaseMath_ReadCallback(self);
516 }
517 
519 {
520  MatrixObject *self = (MatrixObject *)bmo->cb_user;
521  int row;
522 
523  if (BaseMath_ReadCallback(self) == -1) {
524  return -1;
525  }
526 
527  for (row = 0; row < 3; row++) {
528  bmo->data[row] = MATRIX_ITEM(self, row, col);
529  }
530 
531  return 0;
532 }
533 
535 {
536  MatrixObject *self = (MatrixObject *)bmo->cb_user;
537  int row;
538 
539  if (BaseMath_ReadCallback_ForWrite(self) == -1) {
540  return -1;
541  }
542 
543  for (row = 0; row < 3; row++) {
544  MATRIX_ITEM(self, row, col) = bmo->data[row];
545  }
546 
548  return 0;
549 }
550 
552 {
553  MatrixObject *self = (MatrixObject *)bmo->cb_user;
554 
555  if (BaseMath_ReadCallback(self) == -1) {
556  return -1;
557  }
558 
559  bmo->data[row] = MATRIX_ITEM(self, row, col);
560  return 0;
561 }
562 
564 {
565  MatrixObject *self = (MatrixObject *)bmo->cb_user;
566 
567  if (BaseMath_ReadCallback_ForWrite(self) == -1) {
568  return -1;
569  }
570 
571  MATRIX_ITEM(self, row, col) = bmo->data[row];
572 
574  return 0;
575 }
576 
583 };
584 
587 /* -------------------------------------------------------------------- */
591 static PyObject *Matrix_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
592 {
593  if (kwds && PyDict_Size(kwds)) {
594  PyErr_SetString(PyExc_TypeError,
595  "Matrix(): "
596  "takes no keyword args");
597  return NULL;
598  }
599 
600  switch (PyTuple_GET_SIZE(args)) {
601  case 0:
602  return Matrix_CreatePyObject(NULL, 4, 4, type);
603  case 1: {
604  PyObject *arg = PyTuple_GET_ITEM(args, 0);
605 
606  /* Input is now as a sequence of rows so length of sequence
607  * is the number of rows */
608  /* -1 is an error, size checks will account for this */
609  const ushort row_num = PySequence_Size(arg);
610 
611  if (row_num >= 2 && row_num <= 4) {
612  PyObject *item = PySequence_GetItem(arg, 0);
613  /* Since each item is a row, number of items is the
614  * same as the number of columns */
615  const ushort col_num = PySequence_Size(item);
616  Py_XDECREF(item);
617 
618  if (col_num >= 2 && col_num <= 4) {
619  /* Sane row & col size, new matrix and assign as slice. */
620  PyObject *matrix = Matrix_CreatePyObject(NULL, col_num, row_num, type);
621  if (Matrix_ass_slice((MatrixObject *)matrix, 0, INT_MAX, arg) == 0) {
622  return matrix;
623  }
624  /* matrix ok, slice assignment not */
625  Py_DECREF(matrix);
626  }
627  }
628  break;
629  }
630  }
631 
632  /* will overwrite error */
633  PyErr_SetString(PyExc_TypeError,
634  "Matrix(): "
635  "expects no args or a single arg containing 2-4 numeric sequences");
636  return NULL;
637 }
638 
641 /* -------------------------------------------------------------------- */
646 PyDoc_STRVAR(C_Matrix_Identity_doc,
647  ".. classmethod:: Identity(size)\n"
648  "\n"
649  " Create an identity matrix.\n"
650  "\n"
651  " :arg size: The size of the identity matrix to construct [2, 4].\n"
652  " :type size: int\n"
653  " :return: A new identity matrix.\n"
654  " :rtype: :class:`Matrix`\n");
655 static PyObject *C_Matrix_Identity(PyObject *cls, PyObject *args)
656 {
657  int matSize;
658 
659  if (!PyArg_ParseTuple(args, "i:Matrix.Identity", &matSize)) {
660  return NULL;
661  }
662 
663  if (matSize < 2 || matSize > 4) {
664  PyErr_SetString(PyExc_RuntimeError,
665  "Matrix.Identity(): "
666  "size must be between 2 and 4");
667  return NULL;
668  }
669 
670  return Matrix_CreatePyObject(NULL, matSize, matSize, (PyTypeObject *)cls);
671 }
672 
674 PyDoc_STRVAR(C_Matrix_Rotation_doc,
675  ".. classmethod:: Rotation(angle, size, axis)\n"
676  "\n"
677  " Create a matrix representing a rotation.\n"
678  "\n"
679  " :arg angle: The angle of rotation desired, in radians.\n"
680  " :type angle: float\n"
681  " :arg size: The size of the rotation matrix to construct [2, 4].\n"
682  " :type size: int\n"
683  " :arg axis: a string in ['X', 'Y', 'Z'] or a 3D Vector Object\n"
684  " (optional when size is 2).\n"
685  " :type axis: string or :class:`Vector`\n"
686  " :return: A new rotation matrix.\n"
687  " :rtype: :class:`Matrix`\n");
688 static PyObject *C_Matrix_Rotation(PyObject *cls, PyObject *args)
689 {
690  PyObject *vec = NULL;
691  const char *axis = NULL;
692  int matSize;
693  double angle; /* Use double because of precision problems at high values. */
694  float mat[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
695 
696  if (!PyArg_ParseTuple(args, "di|O:Matrix.Rotation", &angle, &matSize, &vec)) {
697  return NULL;
698  }
699 
700  if (vec && PyUnicode_Check(vec)) {
701  axis = PyUnicode_AsUTF8((PyObject *)vec);
702  if (axis == NULL || axis[0] == '\0' || axis[1] != '\0' || axis[0] < 'X' || axis[0] > 'Z') {
703  PyErr_SetString(PyExc_ValueError,
704  "Matrix.Rotation(): "
705  "3rd argument axis value must be a 3D vector "
706  "or a string in 'X', 'Y', 'Z'");
707  return NULL;
708  }
709 
710  /* use the string */
711  vec = NULL;
712  }
713 
715 
716  if (!ELEM(matSize, 2, 3, 4)) {
717  PyErr_SetString(PyExc_ValueError,
718  "Matrix.Rotation(): "
719  "can only return a 2x2 3x3 or 4x4 matrix");
720  return NULL;
721  }
722  if (matSize == 2 && (vec != NULL)) {
723  PyErr_SetString(PyExc_ValueError,
724  "Matrix.Rotation(): "
725  "cannot create a 2x2 rotation matrix around arbitrary axis");
726  return NULL;
727  }
728  if ((ELEM(matSize, 3, 4)) && (axis == NULL) && (vec == NULL)) {
729  PyErr_SetString(PyExc_ValueError,
730  "Matrix.Rotation(): "
731  "axis of rotation for 3d and 4d matrices is required");
732  return NULL;
733  }
734 
735  /* check for valid vector/axis above */
736  if (vec) {
737  float tvec[3];
738 
740  tvec, 3, 3, vec, "Matrix.Rotation(angle, size, axis), invalid 'axis' arg") == -1) {
741  return NULL;
742  }
743 
744  axis_angle_to_mat3((float(*)[3])mat, tvec, angle);
745  }
746  else if (matSize == 2) {
747  angle_to_mat2((float(*)[2])mat, angle);
748  }
749  else {
750  /* valid axis checked above */
751  axis_angle_to_mat3_single((float(*)[3])mat, axis[0], angle);
752  }
753 
754  if (matSize == 4) {
755  matrix_3x3_as_4x4(mat);
756  }
757  /* pass to matrix creation */
758  return Matrix_CreatePyObject(mat, matSize, matSize, (PyTypeObject *)cls);
759 }
760 
762 PyDoc_STRVAR(C_Matrix_Translation_doc,
763  ".. classmethod:: Translation(vector)\n"
764  "\n"
765  " Create a matrix representing a translation.\n"
766  "\n"
767  " :arg vector: The translation vector.\n"
768  " :type vector: :class:`Vector`\n"
769  " :return: An identity matrix with a translation.\n"
770  " :rtype: :class:`Matrix`\n");
771 static PyObject *C_Matrix_Translation(PyObject *cls, PyObject *value)
772 {
773  float mat[4][4];
774 
775  unit_m4(mat);
776 
778  mat[3], 3, 4, value, "mathutils.Matrix.Translation(vector), invalid vector arg") == -1) {
779  return NULL;
780  }
781 
782  return Matrix_CreatePyObject(&mat[0][0], 4, 4, (PyTypeObject *)cls);
783 }
784 
785 PyDoc_STRVAR(C_Matrix_Diagonal_doc,
786  ".. classmethod:: Diagonal(vector)\n"
787  "\n"
788  " Create a diagonal (scaling) matrix using the values from the vector.\n"
789  "\n"
790  " :arg vector: The vector of values for the diagonal.\n"
791  " :type vector: :class:`Vector`\n"
792  " :return: A diagonal matrix.\n"
793  " :rtype: :class:`Matrix`\n");
795 static PyObject *C_Matrix_Diagonal(PyObject *cls, PyObject *value)
796 {
797  float mat[16] = {0.0f};
798  float vec[4];
799 
801  vec, 2, 4, value, "mathutils.Matrix.Diagonal(vector), invalid vector arg");
802 
803  if (size == -1) {
804  return NULL;
805  }
806 
807  for (int i = 0; i < size; i++) {
808  mat[size * i + i] = vec[i];
809  }
810 
811  return Matrix_CreatePyObject(mat, size, size, (PyTypeObject *)cls);
812 }
813 
815 PyDoc_STRVAR(C_Matrix_Scale_doc,
816  ".. classmethod:: Scale(factor, size, axis)\n"
817  "\n"
818  " Create a matrix representing a scaling.\n"
819  "\n"
820  " :arg factor: The factor of scaling to apply.\n"
821  " :type factor: float\n"
822  " :arg size: The size of the scale matrix to construct [2, 4].\n"
823  " :type size: int\n"
824  " :arg axis: Direction to influence scale. (optional).\n"
825  " :type axis: :class:`Vector`\n"
826  " :return: A new scale matrix.\n"
827  " :rtype: :class:`Matrix`\n");
828 static PyObject *C_Matrix_Scale(PyObject *cls, PyObject *args)
829 {
830  PyObject *vec = NULL;
831  int vec_num;
832  float tvec[3];
833  float factor;
834  int matSize;
835  float mat[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
836 
837  if (!PyArg_ParseTuple(args, "fi|O:Matrix.Scale", &factor, &matSize, &vec)) {
838  return NULL;
839  }
840  if (!ELEM(matSize, 2, 3, 4)) {
841  PyErr_SetString(PyExc_ValueError,
842  "Matrix.Scale(): "
843  "can only return a 2x2 3x3 or 4x4 matrix");
844  return NULL;
845  }
846  if (vec) {
847  vec_num = (matSize == 2 ? 2 : 3);
849  tvec, vec_num, vec_num, vec, "Matrix.Scale(factor, size, axis), invalid 'axis' arg") ==
850  -1) {
851  return NULL;
852  }
853  }
854  if (vec == NULL) { /* scaling along axis */
855  if (matSize == 2) {
856  mat[0] = factor;
857  mat[3] = factor;
858  }
859  else {
860  mat[0] = factor;
861  mat[4] = factor;
862  mat[8] = factor;
863  }
864  }
865  else {
866  /* scaling in arbitrary direction
867  * normalize arbitrary axis */
868  float norm = 0.0f;
869  int x;
870  for (x = 0; x < vec_num; x++) {
871  norm += tvec[x] * tvec[x];
872  }
873  norm = sqrtf(norm);
874  for (x = 0; x < vec_num; x++) {
875  tvec[x] /= norm;
876  }
877  if (matSize == 2) {
878  mat[0] = 1 + ((factor - 1) * (tvec[0] * tvec[0]));
879  mat[1] = ((factor - 1) * (tvec[0] * tvec[1]));
880  mat[2] = ((factor - 1) * (tvec[0] * tvec[1]));
881  mat[3] = 1 + ((factor - 1) * (tvec[1] * tvec[1]));
882  }
883  else {
884  mat[0] = 1 + ((factor - 1) * (tvec[0] * tvec[0]));
885  mat[1] = ((factor - 1) * (tvec[0] * tvec[1]));
886  mat[2] = ((factor - 1) * (tvec[0] * tvec[2]));
887  mat[3] = ((factor - 1) * (tvec[0] * tvec[1]));
888  mat[4] = 1 + ((factor - 1) * (tvec[1] * tvec[1]));
889  mat[5] = ((factor - 1) * (tvec[1] * tvec[2]));
890  mat[6] = ((factor - 1) * (tvec[0] * tvec[2]));
891  mat[7] = ((factor - 1) * (tvec[1] * tvec[2]));
892  mat[8] = 1 + ((factor - 1) * (tvec[2] * tvec[2]));
893  }
894  }
895  if (matSize == 4) {
896  matrix_3x3_as_4x4(mat);
897  }
898  /* pass to matrix creation */
899  return Matrix_CreatePyObject(mat, matSize, matSize, (PyTypeObject *)cls);
900 }
902 PyDoc_STRVAR(C_Matrix_OrthoProjection_doc,
903  ".. classmethod:: OrthoProjection(axis, size)\n"
904  "\n"
905  " Create a matrix to represent an orthographic projection.\n"
906  "\n"
907  " :arg axis: Can be any of the following: ['X', 'Y', 'XY', 'XZ', 'YZ'],\n"
908  " where a single axis is for a 2D matrix.\n"
909  " Or a vector for an arbitrary axis\n"
910  " :type axis: string or :class:`Vector`\n"
911  " :arg size: The size of the projection matrix to construct [2, 4].\n"
912  " :type size: int\n"
913  " :return: A new projection matrix.\n"
914  " :rtype: :class:`Matrix`\n");
915 static PyObject *C_Matrix_OrthoProjection(PyObject *cls, PyObject *args)
916 {
917  PyObject *axis;
918 
919  int matSize, x;
920  float norm = 0.0f;
921  float mat[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
922 
923  if (!PyArg_ParseTuple(args, "Oi:Matrix.OrthoProjection", &axis, &matSize)) {
924  return NULL;
925  }
926  if (!ELEM(matSize, 2, 3, 4)) {
927  PyErr_SetString(PyExc_ValueError,
928  "Matrix.OrthoProjection(): "
929  "can only return a 2x2 3x3 or 4x4 matrix");
930  return NULL;
931  }
932 
933  if (PyUnicode_Check(axis)) { /* ortho projection onto cardinal plane */
934  Py_ssize_t plane_len;
935  const char *plane = PyUnicode_AsUTF8AndSize(axis, &plane_len);
936  if (matSize == 2) {
937  if (plane_len == 1 && plane[0] == 'X') {
938  mat[0] = 1.0f;
939  }
940  else if (plane_len == 1 && plane[0] == 'Y') {
941  mat[3] = 1.0f;
942  }
943  else {
944  PyErr_Format(PyExc_ValueError,
945  "Matrix.OrthoProjection(): "
946  "unknown plane, expected: X, Y, not '%.200s'",
947  plane);
948  return NULL;
949  }
950  }
951  else {
952  if (plane_len == 2 && plane[0] == 'X' && plane[1] == 'Y') {
953  mat[0] = 1.0f;
954  mat[4] = 1.0f;
955  }
956  else if (plane_len == 2 && plane[0] == 'X' && plane[1] == 'Z') {
957  mat[0] = 1.0f;
958  mat[8] = 1.0f;
959  }
960  else if (plane_len == 2 && plane[0] == 'Y' && plane[1] == 'Z') {
961  mat[4] = 1.0f;
962  mat[8] = 1.0f;
963  }
964  else {
965  PyErr_Format(PyExc_ValueError,
966  "Matrix.OrthoProjection(): "
967  "unknown plane, expected: XY, XZ, YZ, not '%.200s'",
968  plane);
969  return NULL;
970  }
971  }
972  }
973  else {
974  /* arbitrary plane */
975 
976  const int vec_num = (matSize == 2 ? 2 : 3);
977  float tvec[4];
978 
979  if (mathutils_array_parse(tvec,
980  vec_num,
981  vec_num,
982  axis,
983  "Matrix.OrthoProjection(axis, size), invalid 'axis' arg") == -1) {
984  return NULL;
985  }
986 
987  /* normalize arbitrary axis */
988  for (x = 0; x < vec_num; x++) {
989  norm += tvec[x] * tvec[x];
990  }
991  norm = sqrtf(norm);
992  for (x = 0; x < vec_num; x++) {
993  tvec[x] /= norm;
994  }
995  if (matSize == 2) {
996  mat[0] = 1 - (tvec[0] * tvec[0]);
997  mat[1] = -(tvec[0] * tvec[1]);
998  mat[2] = -(tvec[0] * tvec[1]);
999  mat[3] = 1 - (tvec[1] * tvec[1]);
1000  }
1001  else if (matSize > 2) {
1002  mat[0] = 1 - (tvec[0] * tvec[0]);
1003  mat[1] = -(tvec[0] * tvec[1]);
1004  mat[2] = -(tvec[0] * tvec[2]);
1005  mat[3] = -(tvec[0] * tvec[1]);
1006  mat[4] = 1 - (tvec[1] * tvec[1]);
1007  mat[5] = -(tvec[1] * tvec[2]);
1008  mat[6] = -(tvec[0] * tvec[2]);
1009  mat[7] = -(tvec[1] * tvec[2]);
1010  mat[8] = 1 - (tvec[2] * tvec[2]);
1011  }
1012  }
1013  if (matSize == 4) {
1014  matrix_3x3_as_4x4(mat);
1015  }
1016  /* pass to matrix creation */
1017  return Matrix_CreatePyObject(mat, matSize, matSize, (PyTypeObject *)cls);
1018 }
1019 
1021 PyDoc_STRVAR(C_Matrix_Shear_doc,
1022  ".. classmethod:: Shear(plane, size, factor)\n"
1023  "\n"
1024  " Create a matrix to represent an shear transformation.\n"
1025  "\n"
1026  " :arg plane: Can be any of the following: ['X', 'Y', 'XY', 'XZ', 'YZ'],\n"
1027  " where a single axis is for a 2D matrix only.\n"
1028  " :type plane: string\n"
1029  " :arg size: The size of the shear matrix to construct [2, 4].\n"
1030  " :type size: int\n"
1031  " :arg factor: The factor of shear to apply. For a 3 or 4 *size* matrix\n"
1032  " pass a pair of floats corresponding with the *plane* axis.\n"
1033  " :type factor: float or float pair\n"
1034  " :return: A new shear matrix.\n"
1035  " :rtype: :class:`Matrix`\n");
1036 static PyObject *C_Matrix_Shear(PyObject *cls, PyObject *args)
1037 {
1038  int matSize;
1039  const char *plane;
1040  PyObject *fac;
1041  float mat[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
1042 
1043  if (!PyArg_ParseTuple(args, "siO:Matrix.Shear", &plane, &matSize, &fac)) {
1044  return NULL;
1045  }
1046  if (!ELEM(matSize, 2, 3, 4)) {
1047  PyErr_SetString(PyExc_ValueError,
1048  "Matrix.Shear(): "
1049  "can only return a 2x2 3x3 or 4x4 matrix");
1050  return NULL;
1051  }
1052 
1053  if (matSize == 2) {
1054  float const factor = PyFloat_AsDouble(fac);
1055 
1056  if (factor == -1.0f && PyErr_Occurred()) {
1057  PyErr_SetString(PyExc_TypeError,
1058  "Matrix.Shear(): "
1059  "the factor to be a float");
1060  return NULL;
1061  }
1062 
1063  /* unit */
1064  mat[0] = 1.0f;
1065  mat[3] = 1.0f;
1066 
1067  if (STREQ(plane, "X")) {
1068  mat[2] = factor;
1069  }
1070  else if (STREQ(plane, "Y")) {
1071  mat[1] = factor;
1072  }
1073  else {
1074  PyErr_SetString(PyExc_ValueError,
1075  "Matrix.Shear(): "
1076  "expected: X, Y or wrong matrix size for shearing plane");
1077  return NULL;
1078  }
1079  }
1080  else {
1081  /* 3 or 4, apply as 3x3, resize later if needed */
1082  float factor[2];
1083 
1084  if (mathutils_array_parse(factor, 2, 2, fac, "Matrix.Shear()") == -1) {
1085  return NULL;
1086  }
1087 
1088  /* unit */
1089  mat[0] = 1.0f;
1090  mat[4] = 1.0f;
1091  mat[8] = 1.0f;
1092 
1093  if (STREQ(plane, "XY")) {
1094  mat[6] = factor[0];
1095  mat[7] = factor[1];
1096  }
1097  else if (STREQ(plane, "XZ")) {
1098  mat[3] = factor[0];
1099  mat[5] = factor[1];
1100  }
1101  else if (STREQ(plane, "YZ")) {
1102  mat[1] = factor[0];
1103  mat[2] = factor[1];
1104  }
1105  else {
1106  PyErr_SetString(PyExc_ValueError,
1107  "Matrix.Shear(): "
1108  "expected: X, Y, XY, XZ, YZ");
1109  return NULL;
1110  }
1111  }
1112 
1113  if (matSize == 4) {
1114  matrix_3x3_as_4x4(mat);
1115  }
1116  /* pass to matrix creation */
1117  return Matrix_CreatePyObject(mat, matSize, matSize, (PyTypeObject *)cls);
1118 }
1119 
1121  C_Matrix_LocRotScale_doc,
1122  ".. classmethod:: LocRotScale(location, rotation, scale)\n"
1123  "\n"
1124  " Create a matrix combining translation, rotation and scale,\n"
1125  " acting as the inverse of the decompose() method.\n"
1126  "\n"
1127  " Any of the inputs may be replaced with None if not needed.\n"
1128  "\n"
1129  " :arg location: The translation component.\n"
1130  " :type location: :class:`Vector` or None\n"
1131  " :arg rotation: The rotation component.\n"
1132  " :type rotation: 3x3 :class:`Matrix`, :class:`Quaternion`, :class:`Euler` or None\n"
1133  " :arg scale: The scale component.\n"
1134  " :type scale: :class:`Vector` or None\n"
1135  " :return: Combined transformation matrix. \n"
1136  " :rtype: 4x4 :class:`Matrix`\n");
1137 static PyObject *C_Matrix_LocRotScale(PyObject *cls, PyObject *args)
1138 {
1139  PyObject *loc_obj, *rot_obj, *scale_obj;
1140  float mat[4][4], loc[3];
1141 
1142  if (!PyArg_ParseTuple(args, "OOO:Matrix.LocRotScale", &loc_obj, &rot_obj, &scale_obj)) {
1143  return NULL;
1144  }
1145 
1146  /* Decode location. */
1147  if (loc_obj == Py_None) {
1148  zero_v3(loc);
1149  }
1150  else if (mathutils_array_parse(
1151  loc, 3, 3, loc_obj, "Matrix.LocRotScale(), invalid location argument") == -1) {
1152  return NULL;
1153  }
1154 
1155  /* Decode rotation. */
1156  if (rot_obj == Py_None) {
1157  unit_m4(mat);
1158  }
1159  else if (QuaternionObject_Check(rot_obj)) {
1160  QuaternionObject *quat_obj = (QuaternionObject *)rot_obj;
1161 
1162  if (BaseMath_ReadCallback(quat_obj) == -1) {
1163  return NULL;
1164  }
1165 
1166  quat_to_mat4(mat, quat_obj->quat);
1167  }
1168  else if (EulerObject_Check(rot_obj)) {
1169  EulerObject *eul_obj = (EulerObject *)rot_obj;
1170 
1171  if (BaseMath_ReadCallback(eul_obj) == -1) {
1172  return NULL;
1173  }
1174 
1175  eulO_to_mat4(mat, eul_obj->eul, eul_obj->order);
1176  }
1177  else if (MatrixObject_Check(rot_obj)) {
1178  MatrixObject *mat_obj = (MatrixObject *)rot_obj;
1179 
1180  if (BaseMath_ReadCallback(mat_obj) == -1) {
1181  return NULL;
1182  }
1183 
1184  if (mat_obj->col_num == 3 && mat_obj->row_num == 3) {
1185  copy_m4_m3(mat, (const float(*)[3])mat_obj->matrix);
1186  }
1187  else {
1188  PyErr_SetString(PyExc_ValueError,
1189  "Matrix.LocRotScale(): "
1190  "inappropriate rotation matrix size - expects 3x3 matrix");
1191  return NULL;
1192  }
1193  }
1194  else {
1195  PyErr_SetString(PyExc_ValueError,
1196  "Matrix.LocRotScale(): "
1197  "rotation argument must be Matrix, Quaternion, Euler or None");
1198  return NULL;
1199  }
1200 
1201  /* Decode scale. */
1202  if (scale_obj != Py_None) {
1203  float scale[3];
1204 
1206  scale, 3, 3, scale_obj, "Matrix.LocRotScale(), invalid scale argument") == -1) {
1207  return NULL;
1208  }
1209 
1210  rescale_m4(mat, scale);
1211  }
1212 
1213  copy_v3_v3(mat[3], loc);
1214 
1215  return Matrix_CreatePyObject(&mat[0][0], 4, 4, (PyTypeObject *)cls);
1216 }
1217 
1220 /* -------------------------------------------------------------------- */
1224 PyDoc_STRVAR(Matrix_to_quaternion_doc,
1225  ".. method:: to_quaternion()\n"
1226  "\n"
1227  " Return a quaternion representation of the rotation matrix.\n"
1228  "\n"
1229  " :return: Quaternion representation of the rotation matrix.\n"
1230  " :rtype: :class:`Quaternion`\n");
1231 static PyObject *Matrix_to_quaternion(MatrixObject *self)
1232 {
1233  float quat[4];
1234 
1235  if (BaseMath_ReadCallback(self) == -1) {
1236  return NULL;
1237  }
1238 
1239  /* must be 3-4 cols, 3-4 rows, square matrix */
1240  if ((self->row_num < 3) || (self->col_num < 3) || (self->row_num != self->col_num)) {
1241  PyErr_SetString(PyExc_ValueError,
1242  "Matrix.to_quat(): "
1243  "inappropriate matrix size - expects 3x3 or 4x4 matrix");
1244  return NULL;
1245  }
1246  float mat3[3][3];
1247  if (self->row_num == 3) {
1248  copy_m3_m3(mat3, (const float(*)[3])self->matrix);
1249  }
1250  else {
1251  copy_m3_m4(mat3, (const float(*)[4])self->matrix);
1252  }
1253  normalize_m3(mat3);
1254  if (is_negative_m3(mat3)) {
1255  /* Without this, the results are invalid, see: T94231. */
1256  negate_m3(mat3);
1257  }
1258  mat3_normalized_to_quat(quat, mat3);
1259  return Quaternion_CreatePyObject(quat, NULL);
1260 }
1261 
1264 /* -------------------------------------------------------------------- */
1268 PyDoc_STRVAR(Matrix_to_euler_doc,
1269  ".. method:: to_euler(order, euler_compat)\n"
1270  "\n"
1271  " Return an Euler representation of the rotation matrix\n"
1272  " (3x3 or 4x4 matrix only).\n"
1273  "\n"
1274  " :arg order: Optional rotation order argument in\n"
1275  " ['XYZ', 'XZY', 'YXZ', 'YZX', 'ZXY', 'ZYX'].\n"
1276  " :type order: string\n"
1277  " :arg euler_compat: Optional euler argument the new euler will be made\n"
1278  " compatible with (no axis flipping between them).\n"
1279  " Useful for converting a series of matrices to animation curves.\n"
1280  " :type euler_compat: :class:`Euler`\n"
1281  " :return: Euler representation of the matrix.\n"
1282  " :rtype: :class:`Euler`\n");
1283 static PyObject *Matrix_to_euler(MatrixObject *self, PyObject *args)
1284 {
1285  const char *order_str = NULL;
1286  short order = EULER_ORDER_XYZ;
1287  float eul[3], eul_compatf[3];
1288  EulerObject *eul_compat = NULL;
1289 
1290  float mat[3][3];
1291 
1292  if (BaseMath_ReadCallback(self) == -1) {
1293  return NULL;
1294  }
1295 
1296  if (!PyArg_ParseTuple(args, "|sO!:to_euler", &order_str, &euler_Type, &eul_compat)) {
1297  return NULL;
1298  }
1299 
1300  if (eul_compat) {
1301  if (BaseMath_ReadCallback(eul_compat) == -1) {
1302  return NULL;
1303  }
1304 
1305  copy_v3_v3(eul_compatf, eul_compat->eul);
1306  }
1307 
1308  /* Must be 3-4 cols, 3-4 rows, square matrix. */
1309  if (self->row_num == 3 && self->col_num == 3) {
1310  copy_m3_m3(mat, (const float(*)[3])self->matrix);
1311  }
1312  else if (self->row_num == 4 && self->col_num == 4) {
1313  copy_m3_m4(mat, (const float(*)[4])self->matrix);
1314  }
1315  else {
1316  PyErr_SetString(PyExc_ValueError,
1317  "Matrix.to_euler(): "
1318  "inappropriate matrix size - expects 3x3 or 4x4 matrix");
1319  return NULL;
1320  }
1321 
1322  if (order_str) {
1323  order = euler_order_from_string(order_str, "Matrix.to_euler()");
1324 
1325  if (order == -1) {
1326  return NULL;
1327  }
1328  }
1329 
1330  normalize_m3(mat);
1331 
1332  if (eul_compat) {
1333  if (order == 1) {
1334  mat3_normalized_to_compatible_eul(eul, eul_compatf, mat);
1335  }
1336  else {
1337  mat3_normalized_to_compatible_eulO(eul, eul_compatf, order, mat);
1338  }
1339  }
1340  else {
1341  if (order == 1) {
1342  mat3_normalized_to_eul(eul, mat);
1343  }
1344  else {
1345  mat3_normalized_to_eulO(eul, order, mat);
1346  }
1347  }
1348 
1349  return Euler_CreatePyObject(eul, order, NULL);
1350 }
1351 
1354 /* -------------------------------------------------------------------- */
1358 PyDoc_STRVAR(Matrix_resize_4x4_doc,
1359  ".. method:: resize_4x4()\n"
1360  "\n"
1361  " Resize the matrix to 4x4.\n");
1362 static PyObject *Matrix_resize_4x4(MatrixObject *self)
1363 {
1364  float mat[4][4];
1365  int col;
1366 
1367  if (self->flag & BASE_MATH_FLAG_IS_WRAP) {
1368  PyErr_SetString(PyExc_ValueError,
1369  "Matrix.resize_4x4(): "
1370  "cannot resize wrapped data - make a copy and resize that");
1371  return NULL;
1372  }
1373  if (self->cb_user) {
1374  PyErr_SetString(PyExc_ValueError,
1375  "Matrix.resize_4x4(): "
1376  "cannot resize owned data - make a copy and resize that");
1377  return NULL;
1378  }
1379 
1380  self->matrix = PyMem_Realloc(self->matrix, (sizeof(float) * (MATRIX_MAX_DIM * MATRIX_MAX_DIM)));
1381  if (self->matrix == NULL) {
1382  PyErr_SetString(PyExc_MemoryError,
1383  "Matrix.resize_4x4(): "
1384  "problem allocating pointer space");
1385  return NULL;
1386  }
1387 
1388  unit_m4(mat);
1389 
1390  for (col = 0; col < self->col_num; col++) {
1391  memcpy(mat[col], MATRIX_COL_PTR(self, col), self->row_num * sizeof(float));
1392  }
1393 
1394  copy_m4_m4((float(*)[4])self->matrix, (const float(*)[4])mat);
1395 
1396  self->col_num = 4;
1397  self->row_num = 4;
1398 
1399  Py_RETURN_NONE;
1400 }
1401 
1404 /* -------------------------------------------------------------------- */
1408 static PyObject *Matrix_to_NxN(MatrixObject *self, const int col_num, const int row_num)
1409 {
1410  const int mat_size = sizeof(float) * (col_num * row_num);
1412  PyMem_Malloc(mat_size), col_num, row_num, Py_TYPE(self));
1413 
1414  if ((self->row_num == row_num) && (self->col_num == col_num)) {
1415  memcpy(pymat->matrix, self->matrix, mat_size);
1416  }
1417  else {
1418  if ((self->col_num < col_num) || (self->row_num < row_num)) {
1419  matrix_unit_internal(pymat);
1420  }
1421  const int col_len_src = min_ii(col_num, self->col_num);
1422  const int row_len_src = min_ii(row_num, self->row_num);
1423  for (int col = 0; col < col_len_src; col++) {
1424  memcpy(
1425  &pymat->matrix[col * row_num], MATRIX_COL_PTR(self, col), sizeof(float) * row_len_src);
1426  }
1427  }
1428  return (PyObject *)pymat;
1429 }
1430 
1431 PyDoc_STRVAR(Matrix_to_2x2_doc,
1432  ".. method:: to_2x2()\n"
1433  "\n"
1434  " Return a 2x2 copy of this matrix.\n"
1435  "\n"
1436  " :return: a new matrix.\n"
1437  " :rtype: :class:`Matrix`\n");
1438 static PyObject *Matrix_to_2x2(MatrixObject *self)
1439 {
1440  if (BaseMath_ReadCallback(self) == -1) {
1441  return NULL;
1442  }
1443  return Matrix_to_NxN(self, 2, 2);
1444 }
1445 
1446 PyDoc_STRVAR(Matrix_to_3x3_doc,
1447  ".. method:: to_3x3()\n"
1448  "\n"
1449  " Return a 3x3 copy of this matrix.\n"
1450  "\n"
1451  " :return: a new matrix.\n"
1452  " :rtype: :class:`Matrix`\n");
1453 static PyObject *Matrix_to_3x3(MatrixObject *self)
1454 {
1455  if (BaseMath_ReadCallback(self) == -1) {
1456  return NULL;
1457  }
1458  return Matrix_to_NxN(self, 3, 3);
1459 }
1460 
1461 PyDoc_STRVAR(Matrix_to_4x4_doc,
1462  ".. method:: to_4x4()\n"
1463  "\n"
1464  " Return a 4x4 copy of this matrix.\n"
1465  "\n"
1466  " :return: a new matrix.\n"
1467  " :rtype: :class:`Matrix`\n");
1468 static PyObject *Matrix_to_4x4(MatrixObject *self)
1469 {
1470 
1471  if (BaseMath_ReadCallback(self) == -1) {
1472  return NULL;
1473  }
1474  return Matrix_to_NxN(self, 4, 4);
1475 }
1476 
1479 /* -------------------------------------------------------------------- */
1483 PyDoc_STRVAR(Matrix_to_translation_doc,
1484  ".. method:: to_translation()\n"
1485  "\n"
1486  " Return the translation part of a 4 row matrix.\n"
1487  "\n"
1488  " :return: Return the translation of a matrix.\n"
1489  " :rtype: :class:`Vector`\n");
1490 static PyObject *Matrix_to_translation(MatrixObject *self)
1491 {
1492  if (BaseMath_ReadCallback(self) == -1) {
1493  return NULL;
1494  }
1495 
1496  if ((self->row_num < 3) || self->col_num < 4) {
1497  PyErr_SetString(PyExc_ValueError,
1498  "Matrix.to_translation(): "
1499  "inappropriate matrix size");
1500  return NULL;
1501  }
1502 
1503  return Vector_CreatePyObject(MATRIX_COL_PTR(self, 3), 3, NULL);
1504 }
1505 
1506 PyDoc_STRVAR(Matrix_to_scale_doc,
1507  ".. method:: to_scale()\n"
1508  "\n"
1509  " Return the scale part of a 3x3 or 4x4 matrix.\n"
1510  "\n"
1511  " :return: Return the scale of a matrix.\n"
1512  " :rtype: :class:`Vector`\n"
1513  "\n"
1514  " .. note:: This method does not return a negative scale on any axis because it is "
1515  "not possible to obtain this data from the matrix alone.\n");
1516 static PyObject *Matrix_to_scale(MatrixObject *self)
1517 {
1518  float rot[3][3];
1519  float mat[3][3];
1520  float size[3];
1521 
1522  if (BaseMath_ReadCallback(self) == -1) {
1523  return NULL;
1524  }
1525 
1526  /* Must be 3-4 cols, 3-4 rows, square matrix. */
1527  if ((self->row_num < 3) || (self->col_num < 3)) {
1528  PyErr_SetString(PyExc_ValueError,
1529  "Matrix.to_scale(): "
1530  "inappropriate matrix size, 3x3 minimum size");
1531  return NULL;
1532  }
1533 
1534  matrix_as_3x3(mat, self);
1535 
1536  /* compatible mat4_to_loc_rot_size */
1537  mat3_to_rot_size(rot, size, mat);
1538 
1539  return Vector_CreatePyObject(size, 3, NULL);
1540 }
1541 
1544 /* -------------------------------------------------------------------- */
1549 static bool matrix_invert_is_compat(const MatrixObject *self)
1550 {
1551  if (self->col_num != self->row_num) {
1552  PyErr_SetString(PyExc_ValueError,
1553  "Matrix.invert(ed): "
1554  "only square matrices are supported");
1555  return false;
1556  }
1557 
1558  return true;
1559 }
1560 
1561 static bool matrix_invert_args_check(const MatrixObject *self, PyObject *args, bool check_type)
1562 {
1563  switch (PyTuple_GET_SIZE(args)) {
1564  case 0:
1565  return true;
1566  case 1:
1567  if (check_type) {
1568  const MatrixObject *fallback = (const MatrixObject *)PyTuple_GET_ITEM(args, 0);
1569  if (!MatrixObject_Check(fallback)) {
1570  PyErr_SetString(PyExc_TypeError,
1571  "Matrix.invert: "
1572  "expects a matrix argument or nothing");
1573  return false;
1574  }
1575 
1576  if ((self->col_num != fallback->col_num) || (self->row_num != fallback->row_num)) {
1577  PyErr_SetString(PyExc_TypeError,
1578  "Matrix.invert: "
1579  "matrix argument has different dimensions");
1580  return false;
1581  }
1582  }
1583 
1584  return true;
1585  default:
1586  PyErr_SetString(PyExc_ValueError,
1587  "Matrix.invert(ed): "
1588  "takes at most one argument");
1589  return false;
1590  }
1591 }
1592 
1594 {
1595  PyErr_SetString(PyExc_ValueError,
1596  "Matrix.invert(ed): "
1597  "matrix does not have an inverse");
1598 }
1599 
1601  Matrix_invert_doc,
1602  ".. method:: invert(fallback=None)\n"
1603  "\n"
1604  " Set the matrix to its inverse.\n"
1605  "\n"
1606  " :arg fallback: Set the matrix to this value when the inverse cannot be calculated\n"
1607  " (instead of raising a :exc:`ValueError` exception).\n"
1608  " :type fallback: :class:`Matrix`\n"
1609  "\n"
1610  " .. seealso:: `Inverse matrix <https://en.wikipedia.org/wiki/Inverse_matrix>`__ on "
1611  "Wikipedia.\n");
1612 static PyObject *Matrix_invert(MatrixObject *self, PyObject *args)
1613 {
1614  if (BaseMath_ReadCallback_ForWrite(self) == -1) {
1615  return NULL;
1616  }
1617 
1618  if (matrix_invert_is_compat(self) == false) {
1619  return NULL;
1620  }
1621 
1622  if (matrix_invert_args_check(self, args, true) == false) {
1623  return NULL;
1624  }
1625 
1626  if (matrix_invert_internal(self, self->matrix)) {
1627  /* pass */
1628  }
1629  else {
1630  if (PyTuple_GET_SIZE(args) == 1) {
1631  MatrixObject *fallback = (MatrixObject *)PyTuple_GET_ITEM(args, 0);
1632 
1633  if (BaseMath_ReadCallback(fallback) == -1) {
1634  return NULL;
1635  }
1636 
1637  if (self != fallback) {
1638  matrix_copy(self, fallback);
1639  }
1640  }
1641  else {
1643  return NULL;
1644  }
1645  }
1646 
1648  Py_RETURN_NONE;
1649 }
1650 
1651 PyDoc_STRVAR(Matrix_inverted_doc,
1652  ".. method:: inverted(fallback=None)\n"
1653  "\n"
1654  " Return an inverted copy of the matrix.\n"
1655  "\n"
1656  " :arg fallback: return this when the inverse can't be calculated\n"
1657  " (instead of raising a :exc:`ValueError`).\n"
1658  " :type fallback: any\n"
1659  " :return: the inverted matrix or fallback when given.\n"
1660  " :rtype: :class:`Matrix`\n");
1661 static PyObject *Matrix_inverted(MatrixObject *self, PyObject *args)
1662 {
1663  float mat[MATRIX_MAX_DIM * MATRIX_MAX_DIM];
1664 
1665  if (BaseMath_ReadCallback(self) == -1) {
1666  return NULL;
1667  }
1668 
1669  if (matrix_invert_args_check(self, args, false) == false) {
1670  return NULL;
1671  }
1672 
1673  if (matrix_invert_is_compat(self) == false) {
1674  return NULL;
1675  }
1676 
1677  if (matrix_invert_internal(self, mat)) {
1678  /* pass */
1679  }
1680  else {
1681  if (PyTuple_GET_SIZE(args) == 1) {
1682  PyObject *fallback = PyTuple_GET_ITEM(args, 0);
1683  Py_INCREF(fallback);
1684  return fallback;
1685  }
1686 
1688  return NULL;
1689  }
1690 
1691  return Matrix_copy_notest(self, mat);
1692 }
1693 
1694 static PyObject *Matrix_inverted_noargs(MatrixObject *self)
1695 {
1696  if (BaseMath_ReadCallback_ForWrite(self) == -1) {
1697  return NULL;
1698  }
1699 
1700  if (matrix_invert_is_compat(self) == false) {
1701  return NULL;
1702  }
1703 
1704  if (matrix_invert_internal(self, self->matrix)) {
1705  /* pass */
1706  }
1707  else {
1709  return NULL;
1710  }
1711 
1713  Py_RETURN_NONE;
1714 }
1715 
1717  Matrix_invert_safe_doc,
1718  ".. method:: invert_safe()\n"
1719  "\n"
1720  " Set the matrix to its inverse, will never error.\n"
1721  " If degenerated (e.g. zero scale on an axis), add some epsilon to its diagonal, "
1722  "to get an invertible one.\n"
1723  " If tweaked matrix is still degenerated, set to the identity matrix instead.\n"
1724  "\n"
1725  " .. seealso:: `Inverse Matrix <https://en.wikipedia.org/wiki/Inverse_matrix>`__ on "
1726  "Wikipedia.\n");
1727 static PyObject *Matrix_invert_safe(MatrixObject *self)
1728 {
1729  if (BaseMath_ReadCallback_ForWrite(self) == -1) {
1730  return NULL;
1731  }
1732 
1733  if (matrix_invert_is_compat(self) == false) {
1734  return NULL;
1735  }
1736 
1737  matrix_invert_safe_internal(self, self->matrix);
1738 
1740  Py_RETURN_NONE;
1741 }
1742 
1743 PyDoc_STRVAR(Matrix_inverted_safe_doc,
1744  ".. method:: inverted_safe()\n"
1745  "\n"
1746  " Return an inverted copy of the matrix, will never error.\n"
1747  " If degenerated (e.g. zero scale on an axis), add some epsilon to its diagonal, "
1748  "to get an invertible one.\n"
1749  " If tweaked matrix is still degenerated, return the identity matrix instead.\n"
1750  "\n"
1751  " :return: the inverted matrix.\n"
1752  " :rtype: :class:`Matrix`\n");
1753 static PyObject *Matrix_inverted_safe(MatrixObject *self)
1754 {
1755  float mat[MATRIX_MAX_DIM * MATRIX_MAX_DIM];
1756 
1757  if (BaseMath_ReadCallback(self) == -1) {
1758  return NULL;
1759  }
1760 
1761  if (matrix_invert_is_compat(self) == false) {
1762  return NULL;
1763  }
1764 
1765  matrix_invert_safe_internal(self, mat);
1766 
1767  return Matrix_copy_notest(self, mat);
1768 }
1769 
1772 /* -------------------------------------------------------------------- */
1777  Matrix_adjugate_doc,
1778  ".. method:: adjugate()\n"
1779  "\n"
1780  " Set the matrix to its adjugate.\n"
1781  "\n"
1782  " :raises ValueError: if the matrix cannot be adjugate.\n"
1783  "\n"
1784  " .. seealso:: `Adjugate matrix <https://en.wikipedia.org/wiki/Adjugate_matrix>`__ on "
1785  "Wikipedia.\n");
1786 static PyObject *Matrix_adjugate(MatrixObject *self)
1787 {
1788  if (BaseMath_ReadCallback_ForWrite(self) == -1) {
1789  return NULL;
1790  }
1791 
1792  if (self->col_num != self->row_num) {
1793  PyErr_SetString(PyExc_ValueError,
1794  "Matrix.adjugate(d): "
1795  "only square matrices are supported");
1796  return NULL;
1797  }
1798 
1799  /* calculate the classical adjoint */
1800  if (self->col_num <= 4) {
1801  adjoint_matrix_n(self->matrix, self->matrix, self->col_num);
1802  }
1803  else {
1804  PyErr_Format(
1805  PyExc_ValueError, "Matrix adjugate(d): size (%d) unsupported", (int)self->col_num);
1806  return NULL;
1807  }
1808 
1810  Py_RETURN_NONE;
1811 }
1812 
1813 PyDoc_STRVAR(Matrix_adjugated_doc,
1814  ".. method:: adjugated()\n"
1815  "\n"
1816  " Return an adjugated copy of the matrix.\n"
1817  "\n"
1818  " :return: the adjugated matrix.\n"
1819  " :rtype: :class:`Matrix`\n"
1820  " :raises ValueError: if the matrix cannot be adjugated\n");
1821 static PyObject *Matrix_adjugated(MatrixObject *self)
1822 {
1823  return matrix__apply_to_copy(Matrix_adjugate, self);
1824 }
1825 
1827  Matrix_rotate_doc,
1828  ".. method:: rotate(other)\n"
1829  "\n"
1830  " Rotates the matrix by another mathutils value.\n"
1831  "\n"
1832  " :arg other: rotation component of mathutils value\n"
1833  " :type other: :class:`Euler`, :class:`Quaternion` or :class:`Matrix`\n"
1834  "\n"
1835  " .. note:: If any of the columns are not unit length this may not have desired results.\n");
1836 static PyObject *Matrix_rotate(MatrixObject *self, PyObject *value)
1837 {
1838  float self_rmat[3][3], other_rmat[3][3], rmat[3][3];
1839 
1840  if (BaseMath_ReadCallback_ForWrite(self) == -1) {
1841  return NULL;
1842  }
1843 
1844  if (mathutils_any_to_rotmat(other_rmat, value, "matrix.rotate(value)") == -1) {
1845  return NULL;
1846  }
1847 
1848  if (self->row_num != 3 || self->col_num != 3) {
1849  PyErr_SetString(PyExc_ValueError,
1850  "Matrix.rotate(): "
1851  "must have 3x3 dimensions");
1852  return NULL;
1853  }
1854 
1855  matrix_as_3x3(self_rmat, self);
1856  mul_m3_m3m3(rmat, other_rmat, self_rmat);
1857 
1858  copy_m3_m3((float(*)[3])(self->matrix), rmat);
1859 
1861  Py_RETURN_NONE;
1862 }
1863 
1866 /* -------------------------------------------------------------------- */
1870 PyDoc_STRVAR(Matrix_decompose_doc,
1871  ".. method:: decompose()\n"
1872  "\n"
1873  " Return the translation, rotation, and scale components of this matrix.\n"
1874  "\n"
1875  " :return: tuple of translation, rotation, and scale\n"
1876  " :rtype: (:class:`Vector`, :class:`Quaternion`, :class:`Vector`)");
1877 static PyObject *Matrix_decompose(MatrixObject *self)
1878 {
1879  PyObject *ret;
1880  float loc[3];
1881  float rot[3][3];
1882  float quat[4];
1883  float size[3];
1884 
1885  if (self->row_num != 4 || self->col_num != 4) {
1886  PyErr_SetString(PyExc_ValueError,
1887  "Matrix.decompose(): "
1888  "inappropriate matrix size - expects 4x4 matrix");
1889  return NULL;
1890  }
1891 
1892  if (BaseMath_ReadCallback(self) == -1) {
1893  return NULL;
1894  }
1895 
1896  mat4_to_loc_rot_size(loc, rot, size, (const float(*)[4])self->matrix);
1897  mat3_to_quat(quat, rot);
1898 
1899  ret = PyTuple_New(3);
1901  Vector_CreatePyObject(loc, 3, NULL),
1904  return ret;
1905 }
1906 
1909 /* -------------------------------------------------------------------- */
1913 PyDoc_STRVAR(Matrix_lerp_doc,
1914  ".. function:: lerp(other, factor)\n"
1915  "\n"
1916  " Returns the interpolation of two matrices. Uses polar decomposition, see"
1917  " \"Matrix Animation and Polar Decomposition\", Shoemake and Duff, 1992.\n"
1918  "\n"
1919  " :arg other: value to interpolate with.\n"
1920  " :type other: :class:`Matrix`\n"
1921  " :arg factor: The interpolation value in [0.0, 1.0].\n"
1922  " :type factor: float\n"
1923  " :return: The interpolated matrix.\n"
1924  " :rtype: :class:`Matrix`\n");
1925 static PyObject *Matrix_lerp(MatrixObject *self, PyObject *args)
1926 {
1927  MatrixObject *mat2 = NULL;
1928  float fac, mat[MATRIX_MAX_DIM * MATRIX_MAX_DIM];
1929 
1930  if (!PyArg_ParseTuple(args, "O!f:lerp", &matrix_Type, &mat2, &fac)) {
1931  return NULL;
1932  }
1933 
1934  if (self->col_num != mat2->col_num || self->row_num != mat2->row_num) {
1935  PyErr_SetString(PyExc_ValueError,
1936  "Matrix.lerp(): "
1937  "expects both matrix objects of the same dimensions");
1938  return NULL;
1939  }
1940 
1941  if (BaseMath_ReadCallback(self) == -1 || BaseMath_ReadCallback(mat2) == -1) {
1942  return NULL;
1943  }
1944 
1945  /* TODO: different sized matrix. */
1946  if (self->col_num == 4 && self->row_num == 4) {
1947 #ifdef MATH_STANDALONE
1948  blend_m4_m4m4((float(*)[4])mat, (float(*)[4])self->matrix, (float(*)[4])mat2->matrix, fac);
1949 #else
1950  interp_m4_m4m4((float(*)[4])mat, (float(*)[4])self->matrix, (float(*)[4])mat2->matrix, fac);
1951 #endif
1952  }
1953  else if (self->col_num == 3 && self->row_num == 3) {
1954 #ifdef MATH_STANDALONE
1955  blend_m3_m3m3((float(*)[3])mat, (float(*)[3])self->matrix, (float(*)[3])mat2->matrix, fac);
1956 #else
1957  interp_m3_m3m3((float(*)[3])mat, (float(*)[3])self->matrix, (float(*)[3])mat2->matrix, fac);
1958 #endif
1959  }
1960  else {
1961  PyErr_SetString(PyExc_ValueError,
1962  "Matrix.lerp(): "
1963  "only 3x3 and 4x4 matrices supported");
1964  return NULL;
1965  }
1966 
1967  return Matrix_CreatePyObject(mat, self->col_num, self->row_num, Py_TYPE(self));
1968 }
1969 
1971  Matrix_determinant_doc,
1972  ".. method:: determinant()\n"
1973  "\n"
1974  " Return the determinant of a matrix.\n"
1975  "\n"
1976  " :return: Return the determinant of a matrix.\n"
1977  " :rtype: float\n"
1978  "\n"
1979  " .. seealso:: `Determinant <https://en.wikipedia.org/wiki/Determinant>`__ on Wikipedia.\n");
1980 static PyObject *Matrix_determinant(MatrixObject *self)
1981 {
1982  if (BaseMath_ReadCallback(self) == -1) {
1983  return NULL;
1984  }
1985 
1986  if (self->col_num != self->row_num) {
1987  PyErr_SetString(PyExc_ValueError,
1988  "Matrix.determinant(): "
1989  "only square matrices are supported");
1990  return NULL;
1991  }
1992 
1993  return PyFloat_FromDouble((double)matrix_determinant_internal(self));
1994 }
1995 
1998 /* -------------------------------------------------------------------- */
2003  Matrix_transpose_doc,
2004  ".. method:: transpose()\n"
2005  "\n"
2006  " Set the matrix to its transpose.\n"
2007  "\n"
2008  " .. seealso:: `Transpose <https://en.wikipedia.org/wiki/Transpose>`__ on Wikipedia.\n");
2009 static PyObject *Matrix_transpose(MatrixObject *self)
2010 {
2011  if (BaseMath_ReadCallback_ForWrite(self) == -1) {
2012  return NULL;
2013  }
2014 
2015  if (self->col_num != self->row_num) {
2016  PyErr_SetString(PyExc_ValueError,
2017  "Matrix.transpose(d): "
2018  "only square matrices are supported");
2019  return NULL;
2020  }
2021 
2022  if (self->col_num == 2) {
2023  const float t = MATRIX_ITEM(self, 1, 0);
2024  MATRIX_ITEM(self, 1, 0) = MATRIX_ITEM(self, 0, 1);
2025  MATRIX_ITEM(self, 0, 1) = t;
2026  }
2027  else if (self->col_num == 3) {
2028  transpose_m3((float(*)[3])self->matrix);
2029  }
2030  else {
2031  transpose_m4((float(*)[4])self->matrix);
2032  }
2033 
2035  Py_RETURN_NONE;
2036 }
2037 
2038 PyDoc_STRVAR(Matrix_transposed_doc,
2039  ".. method:: transposed()\n"
2040  "\n"
2041  " Return a new, transposed matrix.\n"
2042  "\n"
2043  " :return: a transposed matrix\n"
2044  " :rtype: :class:`Matrix`\n");
2045 static PyObject *Matrix_transposed(MatrixObject *self)
2046 {
2048 }
2049 
2052 /* -------------------------------------------------------------------- */
2056 PyDoc_STRVAR(Matrix_normalize_doc,
2057  ".. method:: normalize()\n"
2058  "\n"
2059  " Normalize each of the matrix columns.\n");
2060 static PyObject *Matrix_normalize(MatrixObject *self)
2061 {
2062  if (BaseMath_ReadCallback_ForWrite(self) == -1) {
2063  return NULL;
2064  }
2065 
2066  if (self->col_num != self->row_num) {
2067  PyErr_SetString(PyExc_ValueError,
2068  "Matrix.normalize(): "
2069  "only square matrices are supported");
2070  return NULL;
2071  }
2072 
2073  if (self->col_num == 3) {
2074  normalize_m3((float(*)[3])self->matrix);
2075  }
2076  else if (self->col_num == 4) {
2077  normalize_m4((float(*)[4])self->matrix);
2078  }
2079  else {
2080  PyErr_SetString(PyExc_ValueError,
2081  "Matrix.normalize(): "
2082  "can only use a 3x3 or 4x4 matrix");
2083  }
2084 
2086  Py_RETURN_NONE;
2087 }
2088 
2089 PyDoc_STRVAR(Matrix_normalized_doc,
2090  ".. method:: normalized()\n"
2091  "\n"
2092  " Return a column normalized matrix\n"
2093  "\n"
2094  " :return: a column normalized matrix\n"
2095  " :rtype: :class:`Matrix`\n");
2096 static PyObject *Matrix_normalized(MatrixObject *self)
2097 {
2099 }
2100 
2103 /* -------------------------------------------------------------------- */
2107 PyDoc_STRVAR(Matrix_zero_doc,
2108  ".. method:: zero()\n"
2109  "\n"
2110  " Set all the matrix values to zero.\n"
2111  "\n"
2112  " :rtype: :class:`Matrix`\n");
2113 static PyObject *Matrix_zero(MatrixObject *self)
2114 {
2115  if (BaseMath_Prepare_ForWrite(self) == -1) {
2116  return NULL;
2117  }
2118 
2119  copy_vn_fl(self->matrix, self->col_num * self->row_num, 0.0f);
2120 
2121  if (BaseMath_WriteCallback(self) == -1) {
2122  return NULL;
2123  }
2124 
2125  Py_RETURN_NONE;
2126 }
2127 
2130 /* -------------------------------------------------------------------- */
2135 {
2136  BLI_assert((self->col_num == self->row_num) && (self->row_num <= 4));
2137 
2138  if (self->col_num == 2) {
2139  unit_m2((float(*)[2])self->matrix);
2140  }
2141  else if (self->col_num == 3) {
2142  unit_m3((float(*)[3])self->matrix);
2143  }
2144  else {
2145  unit_m4((float(*)[4])self->matrix);
2146  }
2147 }
2148 
2149 PyDoc_STRVAR(Matrix_identity_doc,
2150  ".. method:: identity()\n"
2151  "\n"
2152  " Set the matrix to the identity matrix.\n"
2153  "\n"
2154  " .. note:: An object with a location and rotation of zero, and a scale of one\n"
2155  " will have an identity matrix.\n"
2156  "\n"
2157  " .. seealso:: `Identity matrix <https://en.wikipedia.org/wiki/Identity_matrix>`__ "
2158  "on Wikipedia.\n");
2159 static PyObject *Matrix_identity(MatrixObject *self)
2160 {
2161  if (BaseMath_ReadCallback_ForWrite(self) == -1) {
2162  return NULL;
2163  }
2164 
2165  if (self->col_num != self->row_num) {
2166  PyErr_SetString(PyExc_ValueError,
2167  "Matrix.identity(): "
2168  "only square matrices are supported");
2169  return NULL;
2170  }
2171 
2173 
2174  if (BaseMath_WriteCallback(self) == -1) {
2175  return NULL;
2176  }
2177 
2178  Py_RETURN_NONE;
2179 }
2180 
2183 /* -------------------------------------------------------------------- */
2188 static PyObject *Matrix_copy_notest(MatrixObject *self, const float *matrix)
2189 {
2190  return Matrix_CreatePyObject((const float *)matrix, self->col_num, self->row_num, Py_TYPE(self));
2191 }
2192 
2193 PyDoc_STRVAR(Matrix_copy_doc,
2194  ".. method:: copy()\n"
2195  "\n"
2196  " Returns a copy of this matrix.\n"
2197  "\n"
2198  " :return: an instance of itself\n"
2199  " :rtype: :class:`Matrix`\n");
2200 static PyObject *Matrix_copy(MatrixObject *self)
2201 {
2202  if (BaseMath_ReadCallback(self) == -1) {
2203  return NULL;
2204  }
2205 
2206  return Matrix_copy_notest(self, self->matrix);
2207 }
2208 
2210 static PyObject *Matrix_deepcopy(MatrixObject *self, PyObject *args)
2211 {
2212  if (!PyC_CheckArgs_DeepCopy(args)) {
2213  return NULL;
2214  }
2215  return Matrix_copy(self);
2216 }
2217 
2220 /* -------------------------------------------------------------------- */
2224 static PyObject *Matrix_repr(MatrixObject *self)
2225 {
2226  int col, row;
2227  PyObject *rows[MATRIX_MAX_DIM] = {NULL};
2228 
2229  if (BaseMath_ReadCallback(self) == -1) {
2230  return NULL;
2231  }
2232 
2233  for (row = 0; row < self->row_num; row++) {
2234  rows[row] = PyTuple_New(self->col_num);
2235  for (col = 0; col < self->col_num; col++) {
2236  PyTuple_SET_ITEM(rows[row], col, PyFloat_FromDouble(MATRIX_ITEM(self, row, col)));
2237  }
2238  }
2239  switch (self->row_num) {
2240  case 2:
2241  return PyUnicode_FromFormat(
2242  "Matrix((%R,\n"
2243  " %R))",
2244  rows[0],
2245  rows[1]);
2246 
2247  case 3:
2248  return PyUnicode_FromFormat(
2249  "Matrix((%R,\n"
2250  " %R,\n"
2251  " %R))",
2252  rows[0],
2253  rows[1],
2254  rows[2]);
2255 
2256  case 4:
2257  return PyUnicode_FromFormat(
2258  "Matrix((%R,\n"
2259  " %R,\n"
2260  " %R,\n"
2261  " %R))",
2262  rows[0],
2263  rows[1],
2264  rows[2],
2265  rows[3]);
2266  }
2267 
2268  Py_FatalError("Matrix(): invalid row size!");
2269  return NULL;
2270 }
2271 
2272 #ifndef MATH_STANDALONE
2273 static PyObject *Matrix_str(MatrixObject *self)
2274 {
2275  DynStr *ds;
2276 
2277  int maxsize[MATRIX_MAX_DIM];
2278  int row, col;
2279 
2280  char dummy_buf[64];
2281 
2282  if (BaseMath_ReadCallback(self) == -1) {
2283  return NULL;
2284  }
2285 
2286  ds = BLI_dynstr_new();
2287 
2288  /* First determine the maximum width for each column */
2289  for (col = 0; col < self->col_num; col++) {
2290  maxsize[col] = 0;
2291  for (row = 0; row < self->row_num; row++) {
2292  const int size = BLI_snprintf_rlen(
2293  dummy_buf, sizeof(dummy_buf), "%.4f", MATRIX_ITEM(self, row, col));
2294  maxsize[col] = max_ii(maxsize[col], size);
2295  }
2296  }
2297 
2298  /* Now write the unicode string to be printed */
2299  BLI_dynstr_appendf(ds, "<Matrix %dx%d (", self->row_num, self->col_num);
2300  for (row = 0; row < self->row_num; row++) {
2301  for (col = 0; col < self->col_num; col++) {
2302  BLI_dynstr_appendf(ds, col ? ", %*.4f" : "%*.4f", maxsize[col], MATRIX_ITEM(self, row, col));
2303  }
2304  BLI_dynstr_append(ds, row + 1 != self->row_num ? ")\n (" : ")");
2305  }
2306  BLI_dynstr_append(ds, ">");
2307 
2308  return mathutils_dynstr_to_py(ds); /* frees ds */
2309 }
2310 #endif
2311 
2314 /* -------------------------------------------------------------------- */
2318 static PyObject *Matrix_richcmpr(PyObject *a, PyObject *b, int op)
2319 {
2320  PyObject *res;
2321  int ok = -1; /* zero is true */
2322 
2324  MatrixObject *matA = (MatrixObject *)a;
2325  MatrixObject *matB = (MatrixObject *)b;
2326 
2327  if (BaseMath_ReadCallback(matA) == -1 || BaseMath_ReadCallback(matB) == -1) {
2328  return NULL;
2329  }
2330 
2331  ok = ((matA->row_num == matB->row_num) && (matA->col_num == matB->col_num) &&
2332  EXPP_VectorsAreEqual(matA->matrix, matB->matrix, (matA->col_num * matA->row_num), 1)) ?
2333  0 :
2334  -1;
2335  }
2336 
2337  switch (op) {
2338  case Py_NE:
2339  ok = !ok;
2341  case Py_EQ:
2342  res = ok ? Py_False : Py_True;
2343  break;
2344 
2345  case Py_LT:
2346  case Py_LE:
2347  case Py_GT:
2348  case Py_GE:
2349  res = Py_NotImplemented;
2350  break;
2351  default:
2352  PyErr_BadArgument();
2353  return NULL;
2354  }
2355 
2356  return Py_INCREF_RET(res);
2357 }
2358 
2361 /* -------------------------------------------------------------------- */
2365 static Py_hash_t Matrix_hash(MatrixObject *self)
2366 {
2367  float mat[MATRIX_MAX_DIM * MATRIX_MAX_DIM];
2368 
2369  if (BaseMath_ReadCallback(self) == -1) {
2370  return -1;
2371  }
2372 
2373  if (BaseMathObject_Prepare_ForHash(self) == -1) {
2374  return -1;
2375  }
2376 
2377  matrix_transpose_internal(mat, self);
2378 
2379  return mathutils_array_hash(mat, self->row_num * self->col_num);
2380 }
2381 
2384 /* -------------------------------------------------------------------- */
2389 static int Matrix_len(MatrixObject *self)
2390 {
2391  return self->row_num;
2392 }
2393 
2398 static PyObject *Matrix_item_row(MatrixObject *self, int row)
2399 {
2400  if (BaseMath_ReadCallback_ForWrite(self) == -1) {
2401  return NULL;
2402  }
2403 
2404  if (row < 0 || row >= self->row_num) {
2405  PyErr_SetString(PyExc_IndexError,
2406  "matrix[attribute]: "
2407  "array index out of range");
2408  return NULL;
2409  }
2410  return Vector_CreatePyObject_cb(
2411  (PyObject *)self, self->col_num, mathutils_matrix_row_cb_index, row);
2412 }
2417 static PyObject *Matrix_item_col(MatrixObject *self, int col)
2418 {
2419  if (BaseMath_ReadCallback_ForWrite(self) == -1) {
2420  return NULL;
2421  }
2422 
2423  if (col < 0 || col >= self->col_num) {
2424  PyErr_SetString(PyExc_IndexError,
2425  "matrix[attribute]: "
2426  "array index out of range");
2427  return NULL;
2428  }
2429  return Vector_CreatePyObject_cb(
2430  (PyObject *)self, self->row_num, mathutils_matrix_col_cb_index, col);
2431 }
2432 
2434 static int Matrix_ass_item_row(MatrixObject *self, int row, PyObject *value)
2435 {
2436  int col;
2437  float vec[MATRIX_MAX_DIM];
2438  if (BaseMath_ReadCallback_ForWrite(self) == -1) {
2439  return -1;
2440  }
2441 
2442  if (row >= self->row_num || row < 0) {
2443  PyErr_SetString(PyExc_IndexError, "matrix[attribute] = x: bad row");
2444  return -1;
2445  }
2446 
2448  vec, self->col_num, self->col_num, value, "matrix[i] = value assignment") == -1) {
2449  return -1;
2450  }
2451 
2452  /* Since we are assigning a row we cannot memcpy */
2453  for (col = 0; col < self->col_num; col++) {
2454  MATRIX_ITEM(self, row, col) = vec[col];
2455  }
2456 
2458  return 0;
2459 }
2460 
2462 static int Matrix_ass_item_col(MatrixObject *self, int col, PyObject *value)
2463 {
2464  int row;
2465  float vec[MATRIX_MAX_DIM];
2466  if (BaseMath_ReadCallback_ForWrite(self) == -1) {
2467  return -1;
2468  }
2469 
2470  if (col >= self->col_num || col < 0) {
2471  PyErr_SetString(PyExc_IndexError, "matrix[attribute] = x: bad col");
2472  return -1;
2473  }
2474 
2476  vec, self->row_num, self->row_num, value, "matrix[i] = value assignment") == -1) {
2477  return -1;
2478  }
2479 
2480  /* Since we are assigning a row we cannot memcpy */
2481  for (row = 0; row < self->row_num; row++) {
2482  MATRIX_ITEM(self, row, col) = vec[row];
2483  }
2484 
2486  return 0;
2487 }
2488 
2490 static PyObject *Matrix_slice(MatrixObject *self, int begin, int end)
2491 {
2492 
2493  PyObject *tuple;
2494  int count;
2495 
2496  if (BaseMath_ReadCallback(self) == -1) {
2497  return NULL;
2498  }
2499 
2500  CLAMP(begin, 0, self->row_num);
2501  CLAMP(end, 0, self->row_num);
2502  begin = MIN2(begin, end);
2503 
2504  tuple = PyTuple_New(end - begin);
2505  for (count = begin; count < end; count++) {
2506  PyTuple_SET_ITEM(tuple,
2507  count - begin,
2509  (PyObject *)self, self->col_num, mathutils_matrix_row_cb_index, count));
2510  }
2511 
2512  return tuple;
2513 }
2514 
2516 static int Matrix_ass_slice(MatrixObject *self, int begin, int end, PyObject *value)
2517 {
2518  PyObject *value_fast;
2519 
2520  if (BaseMath_ReadCallback_ForWrite(self) == -1) {
2521  return -1;
2522  }
2523 
2524  CLAMP(begin, 0, self->row_num);
2525  CLAMP(end, 0, self->row_num);
2526  begin = MIN2(begin, end);
2527 
2528  /* non list/tuple cases */
2529  if (!(value_fast = PySequence_Fast(value, "matrix[begin:end] = value"))) {
2530  /* PySequence_Fast sets the error */
2531  return -1;
2532  }
2533 
2534  PyObject **value_fast_items = PySequence_Fast_ITEMS(value_fast);
2535  const int size = end - begin;
2536  int row, col;
2537  float mat[MATRIX_MAX_DIM * MATRIX_MAX_DIM];
2538  float vec[4];
2539 
2540  if (PySequence_Fast_GET_SIZE(value_fast) != size) {
2541  Py_DECREF(value_fast);
2542  PyErr_SetString(PyExc_ValueError,
2543  "matrix[begin:end] = []: "
2544  "size mismatch in slice assignment");
2545  return -1;
2546  }
2547 
2548  memcpy(mat, self->matrix, self->col_num * self->row_num * sizeof(float));
2549 
2550  /* parse sub items */
2551  for (row = begin; row < end; row++) {
2552  /* parse each sub sequence */
2553  PyObject *item = value_fast_items[row - begin];
2554 
2556  vec, self->col_num, self->col_num, item, "matrix[begin:end] = value assignment") ==
2557  -1) {
2558  Py_DECREF(value_fast);
2559  return -1;
2560  }
2561 
2562  for (col = 0; col < self->col_num; col++) {
2563  mat[col * self->row_num + row] = vec[col];
2564  }
2565  }
2566 
2567  Py_DECREF(value_fast);
2568 
2569  /* Parsed well - now set in matrix. */
2570  memcpy(self->matrix, mat, self->col_num * self->row_num * sizeof(float));
2571 
2573  return 0;
2574 }
2575 
2577 static PyObject *Matrix_subscript(MatrixObject *self, PyObject *item)
2578 {
2579  if (PyIndex_Check(item)) {
2580  Py_ssize_t i;
2581  i = PyNumber_AsSsize_t(item, PyExc_IndexError);
2582  if (i == -1 && PyErr_Occurred()) {
2583  return NULL;
2584  }
2585  if (i < 0) {
2586  i += self->row_num;
2587  }
2588  return Matrix_item_row(self, i);
2589  }
2590  if (PySlice_Check(item)) {
2591  Py_ssize_t start, stop, step, slicelength;
2592 
2593  if (PySlice_GetIndicesEx(item, self->row_num, &start, &stop, &step, &slicelength) < 0) {
2594  return NULL;
2595  }
2596 
2597  if (slicelength <= 0) {
2598  return PyTuple_New(0);
2599  }
2600  if (step == 1) {
2601  return Matrix_slice(self, start, stop);
2602  }
2603 
2604  PyErr_SetString(PyExc_IndexError, "slice steps not supported with matrices");
2605  return NULL;
2606  }
2607 
2608  PyErr_Format(
2609  PyExc_TypeError, "matrix indices must be integers, not %.200s", Py_TYPE(item)->tp_name);
2610  return NULL;
2611 }
2612 
2614 static int Matrix_ass_subscript(MatrixObject *self, PyObject *item, PyObject *value)
2615 {
2616  if (PyIndex_Check(item)) {
2617  Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
2618  if (i == -1 && PyErr_Occurred()) {
2619  return -1;
2620  }
2621  if (i < 0) {
2622  i += self->row_num;
2623  }
2624  return Matrix_ass_item_row(self, i, value);
2625  }
2626  if (PySlice_Check(item)) {
2627  Py_ssize_t start, stop, step, slicelength;
2628 
2629  if (PySlice_GetIndicesEx(item, self->row_num, &start, &stop, &step, &slicelength) < 0) {
2630  return -1;
2631  }
2632 
2633  if (step == 1) {
2634  return Matrix_ass_slice(self, start, stop, value);
2635  }
2636 
2637  PyErr_SetString(PyExc_IndexError, "slice steps not supported with matrices");
2638  return -1;
2639  }
2640 
2641  PyErr_Format(
2642  PyExc_TypeError, "matrix indices must be integers, not %.200s", Py_TYPE(item)->tp_name);
2643  return -1;
2644 }
2645 
2648 /* -------------------------------------------------------------------- */
2653 static PyObject *Matrix_add(PyObject *m1, PyObject *m2)
2654 {
2655  float mat[MATRIX_MAX_DIM * MATRIX_MAX_DIM];
2656  MatrixObject *mat1 = NULL, *mat2 = NULL;
2657 
2658  mat1 = (MatrixObject *)m1;
2659  mat2 = (MatrixObject *)m2;
2660 
2661  if (!MatrixObject_Check(m1) || !MatrixObject_Check(m2)) {
2662  PyErr_Format(PyExc_TypeError,
2663  "Matrix addition: (%s + %s) "
2664  "invalid type for this operation",
2665  Py_TYPE(m1)->tp_name,
2666  Py_TYPE(m2)->tp_name);
2667  return NULL;
2668  }
2669 
2670  if (BaseMath_ReadCallback(mat1) == -1 || BaseMath_ReadCallback(mat2) == -1) {
2671  return NULL;
2672  }
2673 
2674  if (mat1->col_num != mat2->col_num || mat1->row_num != mat2->row_num) {
2675  PyErr_SetString(PyExc_ValueError,
2676  "Matrix addition: "
2677  "matrices must have the same dimensions for this operation");
2678  return NULL;
2679  }
2680 
2681  add_vn_vnvn(mat, mat1->matrix, mat2->matrix, mat1->col_num * mat1->row_num);
2682 
2683  return Matrix_CreatePyObject(mat, mat1->col_num, mat1->row_num, Py_TYPE(mat1));
2684 }
2685 
2687 static PyObject *Matrix_sub(PyObject *m1, PyObject *m2)
2688 {
2689  float mat[MATRIX_MAX_DIM * MATRIX_MAX_DIM];
2690  MatrixObject *mat1 = NULL, *mat2 = NULL;
2691 
2692  mat1 = (MatrixObject *)m1;
2693  mat2 = (MatrixObject *)m2;
2694 
2695  if (!MatrixObject_Check(m1) || !MatrixObject_Check(m2)) {
2696  PyErr_Format(PyExc_TypeError,
2697  "Matrix subtraction: (%s - %s) "
2698  "invalid type for this operation",
2699  Py_TYPE(m1)->tp_name,
2700  Py_TYPE(m2)->tp_name);
2701  return NULL;
2702  }
2703 
2704  if (BaseMath_ReadCallback(mat1) == -1 || BaseMath_ReadCallback(mat2) == -1) {
2705  return NULL;
2706  }
2707 
2708  if (mat1->col_num != mat2->col_num || mat1->row_num != mat2->row_num) {
2709  PyErr_SetString(PyExc_ValueError,
2710  "Matrix addition: "
2711  "matrices must have the same dimensions for this operation");
2712  return NULL;
2713  }
2714 
2715  sub_vn_vnvn(mat, mat1->matrix, mat2->matrix, mat1->col_num * mat1->row_num);
2716 
2717  return Matrix_CreatePyObject(mat, mat1->col_num, mat1->row_num, Py_TYPE(mat1));
2718 }
2719 
2721 static PyObject *matrix_mul_float(MatrixObject *mat, const float scalar)
2722 {
2723  float tmat[MATRIX_MAX_DIM * MATRIX_MAX_DIM];
2724  mul_vn_vn_fl(tmat, mat->matrix, mat->col_num * mat->row_num, scalar);
2725  return Matrix_CreatePyObject(tmat, mat->col_num, mat->row_num, Py_TYPE(mat));
2726 }
2727 
2728 static PyObject *Matrix_mul(PyObject *m1, PyObject *m2)
2729 {
2730  float scalar;
2731 
2732  MatrixObject *mat1 = NULL, *mat2 = NULL;
2733 
2734  if (MatrixObject_Check(m1)) {
2735  mat1 = (MatrixObject *)m1;
2736  if (BaseMath_ReadCallback(mat1) == -1) {
2737  return NULL;
2738  }
2739  }
2740  if (MatrixObject_Check(m2)) {
2741  mat2 = (MatrixObject *)m2;
2742  if (BaseMath_ReadCallback(mat2) == -1) {
2743  return NULL;
2744  }
2745  }
2746 
2747  if (mat1 && mat2) {
2748  /* MATRIX * MATRIX */
2749  float mat[MATRIX_MAX_DIM * MATRIX_MAX_DIM];
2750 
2751  if ((mat1->row_num != mat2->row_num) || (mat1->col_num != mat2->col_num)) {
2752  PyErr_SetString(PyExc_ValueError,
2753  "matrix1 * matrix2: matrix1 number of rows/columns "
2754  "and the matrix2 number of rows/columns must be the same");
2755  return NULL;
2756  }
2757 
2758  mul_vn_vnvn(mat, mat1->matrix, mat2->matrix, mat1->col_num * mat1->row_num);
2759 
2760  return Matrix_CreatePyObject(mat, mat2->col_num, mat1->row_num, Py_TYPE(mat1));
2761  }
2762  if (mat2) {
2763  /* FLOAT/INT * MATRIX */
2764  if (((scalar = PyFloat_AsDouble(m1)) == -1.0f && PyErr_Occurred()) == 0) {
2765  return matrix_mul_float(mat2, scalar);
2766  }
2767  }
2768  else if (mat1) {
2769  /* MATRIX * FLOAT/INT */
2770  if (((scalar = PyFloat_AsDouble(m2)) == -1.0f && PyErr_Occurred()) == 0) {
2771  return matrix_mul_float(mat1, scalar);
2772  }
2773  }
2774 
2775  PyErr_Format(PyExc_TypeError,
2776  "Element-wise multiplication: "
2777  "not supported between '%.200s' and '%.200s' types",
2778  Py_TYPE(m1)->tp_name,
2779  Py_TYPE(m2)->tp_name);
2780  return NULL;
2781 }
2782 
2784 static PyObject *Matrix_imul(PyObject *m1, PyObject *m2)
2785 {
2786  float scalar;
2787 
2788  MatrixObject *mat1 = NULL, *mat2 = NULL;
2789 
2790  if (MatrixObject_Check(m1)) {
2791  mat1 = (MatrixObject *)m1;
2792  if (BaseMath_ReadCallback(mat1) == -1) {
2793  return NULL;
2794  }
2795  }
2796  if (MatrixObject_Check(m2)) {
2797  mat2 = (MatrixObject *)m2;
2798  if (BaseMath_ReadCallback(mat2) == -1) {
2799  return NULL;
2800  }
2801  }
2802 
2803  if (mat1 && mat2) {
2804  /* MATRIX *= MATRIX */
2805  if ((mat1->row_num != mat2->row_num) || (mat1->col_num != mat2->col_num)) {
2806  PyErr_SetString(PyExc_ValueError,
2807  "matrix1 *= matrix2: matrix1 number of rows/columns "
2808  "and the matrix2 number of rows/columns must be the same");
2809  return NULL;
2810  }
2811 
2812  mul_vn_vn(mat1->matrix, mat2->matrix, mat1->col_num * mat1->row_num);
2813  }
2814  else if (mat1 && (((scalar = PyFloat_AsDouble(m2)) == -1.0f && PyErr_Occurred()) == 0)) {
2815  /* MATRIX *= FLOAT/INT */
2816  mul_vn_fl(mat1->matrix, mat1->row_num * mat1->col_num, scalar);
2817  }
2818  else {
2819  PyErr_Format(PyExc_TypeError,
2820  "In place element-wise multiplication: "
2821  "not supported between '%.200s' and '%.200s' types",
2822  Py_TYPE(m1)->tp_name,
2823  Py_TYPE(m2)->tp_name);
2824  return NULL;
2825  }
2826 
2828  Py_INCREF(m1);
2829  return m1;
2830 }
2831 
2833 static PyObject *Matrix_matmul(PyObject *m1, PyObject *m2)
2834 {
2835  int vec_num;
2836 
2837  MatrixObject *mat1 = NULL, *mat2 = NULL;
2838 
2839  if (MatrixObject_Check(m1)) {
2840  mat1 = (MatrixObject *)m1;
2841  if (BaseMath_ReadCallback(mat1) == -1) {
2842  return NULL;
2843  }
2844  }
2845  if (MatrixObject_Check(m2)) {
2846  mat2 = (MatrixObject *)m2;
2847  if (BaseMath_ReadCallback(mat2) == -1) {
2848  return NULL;
2849  }
2850  }
2851 
2852  if (mat1 && mat2) {
2853  /* MATRIX @ MATRIX */
2854  float mat[MATRIX_MAX_DIM * MATRIX_MAX_DIM];
2855 
2856  int col, row, item;
2857 
2858  if (mat1->col_num != mat2->row_num) {
2859  PyErr_SetString(PyExc_ValueError,
2860  "matrix1 * matrix2: matrix1 number of columns "
2861  "and the matrix2 number of rows must be the same");
2862  return NULL;
2863  }
2864 
2865  for (col = 0; col < mat2->col_num; col++) {
2866  for (row = 0; row < mat1->row_num; row++) {
2867  double dot = 0.0f;
2868  for (item = 0; item < mat1->col_num; item++) {
2869  dot += (double)(MATRIX_ITEM(mat1, row, item) * MATRIX_ITEM(mat2, item, col));
2870  }
2871  mat[(col * mat1->row_num) + row] = (float)dot;
2872  }
2873  }
2874 
2875  return Matrix_CreatePyObject(mat, mat2->col_num, mat1->row_num, Py_TYPE(mat1));
2876  }
2877  if (mat1) {
2878  /* MATRIX @ VECTOR */
2879  if (VectorObject_Check(m2)) {
2880  VectorObject *vec2 = (VectorObject *)m2;
2881  float tvec[MATRIX_MAX_DIM];
2882  if (BaseMath_ReadCallback(vec2) == -1) {
2883  return NULL;
2884  }
2885  if (column_vector_multiplication(tvec, vec2, mat1) == -1) {
2886  return NULL;
2887  }
2888 
2889  if (mat1->col_num == 4 && vec2->vec_num == 3) {
2890  vec_num = 3;
2891  }
2892  else {
2893  vec_num = mat1->row_num;
2894  }
2895 
2896  return Vector_CreatePyObject(tvec, vec_num, Py_TYPE(m2));
2897  }
2898  }
2899 
2900  PyErr_Format(PyExc_TypeError,
2901  "Matrix multiplication: "
2902  "not supported between '%.200s' and '%.200s' types",
2903  Py_TYPE(m1)->tp_name,
2904  Py_TYPE(m2)->tp_name);
2905  return NULL;
2906 }
2907 
2909 static PyObject *Matrix_imatmul(PyObject *m1, PyObject *m2)
2910 {
2911  MatrixObject *mat1 = NULL, *mat2 = NULL;
2912 
2913  if (MatrixObject_Check(m1)) {
2914  mat1 = (MatrixObject *)m1;
2915  if (BaseMath_ReadCallback(mat1) == -1) {
2916  return NULL;
2917  }
2918  }
2919  if (MatrixObject_Check(m2)) {
2920  mat2 = (MatrixObject *)m2;
2921  if (BaseMath_ReadCallback(mat2) == -1) {
2922  return NULL;
2923  }
2924  }
2925 
2926  if (mat1 && mat2) {
2927  /* MATRIX @= MATRIX */
2928  float mat[MATRIX_MAX_DIM * MATRIX_MAX_DIM];
2929  int col, row, item;
2930 
2931  if (mat1->col_num != mat2->row_num) {
2932  PyErr_SetString(PyExc_ValueError,
2933  "matrix1 * matrix2: matrix1 number of columns "
2934  "and the matrix2 number of rows must be the same");
2935  return NULL;
2936  }
2937 
2938  for (col = 0; col < mat2->col_num; col++) {
2939  for (row = 0; row < mat1->row_num; row++) {
2940  double dot = 0.0f;
2941  for (item = 0; item < mat1->col_num; item++) {
2942  dot += (double)(MATRIX_ITEM(mat1, row, item) * MATRIX_ITEM(mat2, item, col));
2943  }
2944  /* store in new matrix as overwriting original at this point will cause
2945  * subsequent iterations to use incorrect values */
2946  mat[(col * mat1->row_num) + row] = (float)dot;
2947  }
2948  }
2949 
2950  /* copy matrix back */
2951  memcpy(mat1->matrix, mat, (mat1->row_num * mat1->col_num) * sizeof(float));
2952  }
2953  else {
2954  PyErr_Format(PyExc_TypeError,
2955  "In place matrix multiplication: "
2956  "not supported between '%.200s' and '%.200s' types",
2957  Py_TYPE(m1)->tp_name,
2958  Py_TYPE(m2)->tp_name);
2959  return NULL;
2960  }
2961 
2963  Py_INCREF(m1);
2964  return m1;
2965 }
2966 
2969 /* -------------------------------------------------------------------- */
2973 static PySequenceMethods Matrix_SeqMethods = {
2974  (lenfunc)Matrix_len, /*sq_length*/
2975  (binaryfunc)NULL, /*sq_concat*/
2976  (ssizeargfunc)NULL, /*sq_repeat*/
2977  (ssizeargfunc)Matrix_item_row, /*sq_item*/
2978  (ssizessizeargfunc)NULL, /*sq_slice(DEPRECATED)*/
2979  (ssizeobjargproc)Matrix_ass_item_row, /*sq_ass_item*/
2980  (ssizessizeobjargproc)NULL, /*sq_ass_slice(DEPRECATED)*/
2981  (objobjproc)NULL, /*sq_contains*/
2982  (binaryfunc)NULL, /*sq_inplace_concat*/
2983  (ssizeargfunc)NULL, /*sq_inplace_repeat*/
2984 };
2985 
2986 static PyMappingMethods Matrix_AsMapping = {
2987  (lenfunc)Matrix_len,
2988  (binaryfunc)Matrix_subscript,
2989  (objobjargproc)Matrix_ass_subscript,
2990 };
2991 
2992 static PyNumberMethods Matrix_NumMethods = {
2993  (binaryfunc)Matrix_add, /*nb_add*/
2994  (binaryfunc)Matrix_sub, /*nb_subtract*/
2995  (binaryfunc)Matrix_mul, /*nb_multiply*/
2996  NULL, /*nb_remainder*/
2997  NULL, /*nb_divmod*/
2998  NULL, /*nb_power*/
2999  (unaryfunc)0, /*nb_negative*/
3000  (unaryfunc)0, /*tp_positive*/
3001  (unaryfunc)0, /*tp_absolute*/
3002  (inquiry)0, /*tp_bool*/
3003  (unaryfunc)Matrix_inverted_noargs, /*nb_invert*/
3004  NULL, /*nb_lshift*/
3005  (binaryfunc)0, /*nb_rshift*/
3006  NULL, /*nb_and*/
3007  NULL, /*nb_xor*/
3008  NULL, /*nb_or*/
3009  NULL, /*nb_int*/
3010  NULL, /*nb_reserved*/
3011  NULL, /*nb_float*/
3012  NULL, /*nb_inplace_add*/
3013  NULL, /*nb_inplace_subtract*/
3014  (binaryfunc)Matrix_imul, /*nb_inplace_multiply*/
3015  NULL, /*nb_inplace_remainder*/
3016  NULL, /*nb_inplace_power*/
3017  NULL, /*nb_inplace_lshift*/
3018  NULL, /*nb_inplace_rshift*/
3019  NULL, /*nb_inplace_and*/
3020  NULL, /*nb_inplace_xor*/
3021  NULL, /*nb_inplace_or*/
3022  NULL, /*nb_floor_divide*/
3023  NULL, /*nb_true_divide*/
3024  NULL, /*nb_inplace_floor_divide*/
3025  NULL, /*nb_inplace_true_divide*/
3026  NULL, /*nb_index*/
3027  (binaryfunc)Matrix_matmul, /*nb_matrix_multiply*/
3028  (binaryfunc)Matrix_imatmul, /*nb_inplace_matrix_multiply*/
3029 };
3030 
3033 /* -------------------------------------------------------------------- */
3037 PyDoc_STRVAR(Matrix_translation_doc, "The translation component of the matrix.\n\n:type: Vector");
3038 static PyObject *Matrix_translation_get(MatrixObject *self, void *UNUSED(closure))
3039 {
3040  PyObject *ret;
3041 
3042  if (BaseMath_ReadCallback(self) == -1) {
3043  return NULL;
3044  }
3045 
3046  /* Must be 4x4 square matrix. */
3047  if (self->row_num != 4 || self->col_num != 4) {
3048  PyErr_SetString(PyExc_AttributeError,
3049  "Matrix.translation: "
3050  "inappropriate matrix size, must be 4x4");
3051  return NULL;
3052  }
3053 
3054  ret = (PyObject *)Vector_CreatePyObject_cb(
3055  (PyObject *)self, 3, mathutils_matrix_translation_cb_index, 3);
3056 
3057  return ret;
3058 }
3059 
3060 static int Matrix_translation_set(MatrixObject *self, PyObject *value, void *UNUSED(closure))
3061 {
3062  float tvec[3];
3063 
3064  if (BaseMath_ReadCallback_ForWrite(self) == -1) {
3065  return -1;
3066  }
3067 
3068  /* Must be 4x4 square matrix. */
3069  if (self->row_num != 4 || self->col_num != 4) {
3070  PyErr_SetString(PyExc_AttributeError,
3071  "Matrix.translation: "
3072  "inappropriate matrix size, must be 4x4");
3073  return -1;
3074  }
3075 
3076  if (mathutils_array_parse(tvec, 3, 3, value, "Matrix.translation") == -1) {
3077  return -1;
3078  }
3079 
3080  copy_v3_v3(((float(*)[4])self->matrix)[3], tvec);
3081 
3083 
3084  return 0;
3085 }
3086 
3087 PyDoc_STRVAR(Matrix_row_doc,
3088  "Access the matrix by rows (default), (read-only).\n\n:type: Matrix Access");
3089 static PyObject *Matrix_row_get(MatrixObject *self, void *UNUSED(closure))
3090 {
3092 }
3093 
3095  Matrix_col_doc,
3096  "Access the matrix by columns, 3x3 and 4x4 only, (read-only).\n\n:type: Matrix Access");
3097 static PyObject *Matrix_col_get(MatrixObject *self, void *UNUSED(closure))
3098 {
3100 }
3101 
3102 PyDoc_STRVAR(Matrix_median_scale_doc,
3103  "The average scale applied to each axis (read-only).\n\n:type: float");
3104 static PyObject *Matrix_median_scale_get(MatrixObject *self, void *UNUSED(closure))
3105 {
3106  float mat[3][3];
3107 
3108  if (BaseMath_ReadCallback(self) == -1) {
3109  return NULL;
3110  }
3111 
3112  /* Must be 3-4 cols, 3-4 rows, square matrix. */
3113  if ((self->row_num < 3) || (self->col_num < 3)) {
3114  PyErr_SetString(PyExc_AttributeError,
3115  "Matrix.median_scale: "
3116  "inappropriate matrix size, 3x3 minimum");
3117  return NULL;
3118  }
3119 
3120  matrix_as_3x3(mat, self);
3121 
3122  return PyFloat_FromDouble(mat3_to_scale(mat));
3123 }
3124 
3125 PyDoc_STRVAR(Matrix_is_identity_doc,
3126  "True if this is an identity matrix (read-only).\n\n:type: bool");
3127 static PyObject *Matrix_is_identity_get(MatrixObject *self, void *UNUSED(closure))
3128 {
3129  if (BaseMath_ReadCallback(self) == -1) {
3130  return NULL;
3131  }
3132  return PyBool_FromLong(matrix_is_identity(self));
3133 }
3134 
3135 PyDoc_STRVAR(Matrix_is_negative_doc,
3136  "True if this matrix results in a negative scale, 3x3 and 4x4 only, "
3137  "(read-only).\n\n:type: bool");
3138 static PyObject *Matrix_is_negative_get(MatrixObject *self, void *UNUSED(closure))
3139 {
3140  if (BaseMath_ReadCallback(self) == -1) {
3141  return NULL;
3142  }
3143 
3144  /* Must be 3-4 cols, 3-4 rows, square matrix. */
3145  if (self->row_num == 4 && self->col_num == 4) {
3146  return PyBool_FromLong(is_negative_m4((const float(*)[4])self->matrix));
3147  }
3148  if (self->row_num == 3 && self->col_num == 3) {
3149  return PyBool_FromLong(is_negative_m3((const float(*)[3])self->matrix));
3150  }
3151 
3152  PyErr_SetString(PyExc_AttributeError,
3153  "Matrix.is_negative: "
3154  "inappropriate matrix size - expects 3x3 or 4x4 matrix");
3155  return NULL;
3156 }
3157 
3158 PyDoc_STRVAR(Matrix_is_orthogonal_doc,
3159  "True if this matrix is orthogonal, 3x3 and 4x4 only, (read-only).\n\n:type: bool");
3160 static PyObject *Matrix_is_orthogonal_get(MatrixObject *self, void *UNUSED(closure))
3161 {
3162  if (BaseMath_ReadCallback(self) == -1) {
3163  return NULL;
3164  }
3165 
3166  /* Must be 3-4 cols, 3-4 rows, square matrix. */
3167  if (self->row_num == 4 && self->col_num == 4) {
3168  return PyBool_FromLong(is_orthonormal_m4((const float(*)[4])self->matrix));
3169  }
3170  if (self->row_num == 3 && self->col_num == 3) {
3171  return PyBool_FromLong(is_orthonormal_m3((const float(*)[3])self->matrix));
3172  }
3173 
3174  PyErr_SetString(PyExc_AttributeError,
3175  "Matrix.is_orthogonal: "
3176  "inappropriate matrix size - expects 3x3 or 4x4 matrix");
3177  return NULL;
3178 }
3179 
3180 PyDoc_STRVAR(Matrix_is_orthogonal_axis_vectors_doc,
3181  "True if this matrix has got orthogonal axis vectors, 3x3 and 4x4 only, "
3182  "(read-only).\n\n:type: bool");
3183 static PyObject *Matrix_is_orthogonal_axis_vectors_get(MatrixObject *self, void *UNUSED(closure))
3184 {
3185  if (BaseMath_ReadCallback(self) == -1) {
3186  return NULL;
3187  }
3188 
3189  /* Must be 3-4 cols, 3-4 rows, square matrix. */
3190  if (self->row_num == 4 && self->col_num == 4) {
3191  return PyBool_FromLong(is_orthogonal_m4((const float(*)[4])self->matrix));
3192  }
3193  if (self->row_num == 3 && self->col_num == 3) {
3194  return PyBool_FromLong(is_orthogonal_m3((const float(*)[3])self->matrix));
3195  }
3196 
3197  PyErr_SetString(PyExc_AttributeError,
3198  "Matrix.is_orthogonal_axis_vectors: "
3199  "inappropriate matrix size - expects 3x3 or 4x4 matrix");
3200  return NULL;
3201 }
3202 
3205 /* -------------------------------------------------------------------- */
3209 static PyGetSetDef Matrix_getseters[] = {
3210  {"median_scale", (getter)Matrix_median_scale_get, (setter)NULL, Matrix_median_scale_doc, NULL},
3211  {"translation",
3212  (getter)Matrix_translation_get,
3213  (setter)Matrix_translation_set,
3214  Matrix_translation_doc,
3215  NULL},
3216  {"row", (getter)Matrix_row_get, (setter)NULL, Matrix_row_doc, NULL},
3217  {"col", (getter)Matrix_col_get, (setter)NULL, Matrix_col_doc, NULL},
3218  {"is_identity", (getter)Matrix_is_identity_get, (setter)NULL, Matrix_is_identity_doc, NULL},
3219  {"is_negative", (getter)Matrix_is_negative_get, (setter)NULL, Matrix_is_negative_doc, NULL},
3220  {"is_orthogonal",
3221  (getter)Matrix_is_orthogonal_get,
3222  (setter)NULL,
3223  Matrix_is_orthogonal_doc,
3224  NULL},
3225  {"is_orthogonal_axis_vectors",
3227  (setter)NULL,
3228  Matrix_is_orthogonal_axis_vectors_doc,
3229  NULL},
3230  {"is_wrapped",
3232  (setter)NULL,
3234  NULL},
3235  {"is_frozen",
3237  (setter)NULL,
3239  NULL},
3240  {"is_valid",
3242  (setter)NULL,
3244  NULL},
3245  {"owner", (getter)BaseMathObject_owner_get, (setter)NULL, BaseMathObject_owner_doc, NULL},
3246  {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
3247 };
3248 
3251 /* -------------------------------------------------------------------- */
3255 static struct PyMethodDef Matrix_methods[] = {
3256  /* Derived values. */
3257  {"determinant", (PyCFunction)Matrix_determinant, METH_NOARGS, Matrix_determinant_doc},
3258  {"decompose", (PyCFunction)Matrix_decompose, METH_NOARGS, Matrix_decompose_doc},
3259 
3260  /* In place only. */
3261  {"zero", (PyCFunction)Matrix_zero, METH_NOARGS, Matrix_zero_doc},
3262  {"identity", (PyCFunction)Matrix_identity, METH_NOARGS, Matrix_identity_doc},
3263 
3264  /* Operate on original or copy. */
3265  {"transpose", (PyCFunction)Matrix_transpose, METH_NOARGS, Matrix_transpose_doc},
3266  {"transposed", (PyCFunction)Matrix_transposed, METH_NOARGS, Matrix_transposed_doc},
3267  {"normalize", (PyCFunction)Matrix_normalize, METH_NOARGS, Matrix_normalize_doc},
3268  {"normalized", (PyCFunction)Matrix_normalized, METH_NOARGS, Matrix_normalized_doc},
3269  {"invert", (PyCFunction)Matrix_invert, METH_VARARGS, Matrix_invert_doc},
3270  {"inverted", (PyCFunction)Matrix_inverted, METH_VARARGS, Matrix_inverted_doc},
3271  {"invert_safe", (PyCFunction)Matrix_invert_safe, METH_NOARGS, Matrix_invert_safe_doc},
3272  {"inverted_safe", (PyCFunction)Matrix_inverted_safe, METH_NOARGS, Matrix_inverted_safe_doc},
3273  {"adjugate", (PyCFunction)Matrix_adjugate, METH_NOARGS, Matrix_adjugate_doc},
3274  {"adjugated", (PyCFunction)Matrix_adjugated, METH_NOARGS, Matrix_adjugated_doc},
3275  {"to_2x2", (PyCFunction)Matrix_to_2x2, METH_NOARGS, Matrix_to_2x2_doc},
3276  {"to_3x3", (PyCFunction)Matrix_to_3x3, METH_NOARGS, Matrix_to_3x3_doc},
3277  {"to_4x4", (PyCFunction)Matrix_to_4x4, METH_NOARGS, Matrix_to_4x4_doc},
3278  /* TODO: {"resize_3x3", (PyCFunction) Matrix_resize3x3, METH_NOARGS, Matrix_resize3x3_doc}, */
3279  {"resize_4x4", (PyCFunction)Matrix_resize_4x4, METH_NOARGS, Matrix_resize_4x4_doc},
3280  {"rotate", (PyCFunction)Matrix_rotate, METH_O, Matrix_rotate_doc},
3281 
3282  /* Return converted representation. */
3283  {"to_euler", (PyCFunction)Matrix_to_euler, METH_VARARGS, Matrix_to_euler_doc},
3284  {"to_quaternion", (PyCFunction)Matrix_to_quaternion, METH_NOARGS, Matrix_to_quaternion_doc},
3285  {"to_scale", (PyCFunction)Matrix_to_scale, METH_NOARGS, Matrix_to_scale_doc},
3286  {"to_translation", (PyCFunction)Matrix_to_translation, METH_NOARGS, Matrix_to_translation_doc},
3287 
3288  /* Operation between 2 or more types. */
3289  {"lerp", (PyCFunction)Matrix_lerp, METH_VARARGS, Matrix_lerp_doc},
3290  {"copy", (PyCFunction)Matrix_copy, METH_NOARGS, Matrix_copy_doc},
3291  {"__copy__", (PyCFunction)Matrix_copy, METH_NOARGS, Matrix_copy_doc},
3292  {"__deepcopy__", (PyCFunction)Matrix_deepcopy, METH_VARARGS, Matrix_copy_doc},
3293 
3294  /* Base-math methods. */
3295  {"freeze", (PyCFunction)BaseMathObject_freeze, METH_NOARGS, BaseMathObject_freeze_doc},
3296 
3297  /* Class methods. */
3298  {"Identity", (PyCFunction)C_Matrix_Identity, METH_VARARGS | METH_CLASS, C_Matrix_Identity_doc},
3299  {"Rotation", (PyCFunction)C_Matrix_Rotation, METH_VARARGS | METH_CLASS, C_Matrix_Rotation_doc},
3300  {"Scale", (PyCFunction)C_Matrix_Scale, METH_VARARGS | METH_CLASS, C_Matrix_Scale_doc},
3301  {"Shear", (PyCFunction)C_Matrix_Shear, METH_VARARGS | METH_CLASS, C_Matrix_Shear_doc},
3302  {"Diagonal", (PyCFunction)C_Matrix_Diagonal, METH_O | METH_CLASS, C_Matrix_Diagonal_doc},
3303  {"Translation",
3304  (PyCFunction)C_Matrix_Translation,
3305  METH_O | METH_CLASS,
3306  C_Matrix_Translation_doc},
3307  {"OrthoProjection",
3308  (PyCFunction)C_Matrix_OrthoProjection,
3309  METH_VARARGS | METH_CLASS,
3310  C_Matrix_OrthoProjection_doc},
3311  {"LocRotScale",
3312  (PyCFunction)C_Matrix_LocRotScale,
3313  METH_VARARGS | METH_CLASS,
3314  C_Matrix_LocRotScale_doc},
3315  {NULL, NULL, 0, NULL},
3316 };
3317 
3320 /* -------------------------------------------------------------------- */
3325  matrix_doc,
3326  ".. class:: Matrix([rows])\n"
3327  "\n"
3328  " This object gives access to Matrices in Blender, supporting square and rectangular\n"
3329  " matrices from 2x2 up to 4x4.\n"
3330  "\n"
3331  " :param rows: Sequence of rows.\n"
3332  " When omitted, a 4x4 identity matrix is constructed.\n"
3333  " :type rows: 2d number sequence\n");
3334 PyTypeObject matrix_Type = {
3335  PyVarObject_HEAD_INIT(NULL, 0) "Matrix", /*tp_name*/
3336  sizeof(MatrixObject), /*tp_basicsize*/
3337  0, /*tp_itemsize*/
3338  (destructor)BaseMathObject_dealloc, /*tp_dealloc*/
3339  (printfunc)NULL, /*tp_print*/
3340  NULL, /*tp_getattr*/
3341  NULL, /*tp_setattr*/
3342  NULL, /*tp_compare*/
3343  (reprfunc)Matrix_repr, /*tp_repr*/
3344  &Matrix_NumMethods, /*tp_as_number*/
3345  &Matrix_SeqMethods, /*tp_as_sequence*/
3346  &Matrix_AsMapping, /*tp_as_mapping*/
3347  (hashfunc)Matrix_hash, /*tp_hash*/
3348  NULL, /*tp_call*/
3349 #ifndef MATH_STANDALONE
3350  (reprfunc)Matrix_str, /*tp_str*/
3351 #else
3352  NULL, /*tp_str*/
3353 #endif
3354  NULL, /*tp_getattro*/
3355  NULL, /*tp_setattro*/
3356  NULL, /*tp_as_buffer*/
3357  Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
3358  matrix_doc, /*tp_doc*/
3359  (traverseproc)BaseMathObject_traverse, /* tp_traverse */
3360  (inquiry)BaseMathObject_clear, /*tp_clear*/
3361  (richcmpfunc)Matrix_richcmpr, /*tp_richcompare*/
3362  0, /*tp_weaklistoffset*/
3363  NULL, /*tp_iter*/
3364  NULL, /*tp_iternext*/
3365  Matrix_methods, /*tp_methods*/
3366  NULL, /*tp_members*/
3367  Matrix_getseters, /*tp_getset*/
3368  NULL, /*tp_base*/
3369  NULL, /*tp_dict*/
3370  NULL, /*tp_descr_get*/
3371  NULL, /*tp_descr_set*/
3372  0, /*tp_dictoffset*/
3373  NULL, /*tp_init*/
3374  NULL, /*tp_alloc*/
3375  Matrix_new, /*tp_new*/
3376  NULL, /*tp_free*/
3377  NULL, /*tp_is_gc*/
3378  NULL, /*tp_bases*/
3379  NULL, /*tp_mro*/
3380  NULL, /*tp_cache*/
3381  NULL, /*tp_subclasses*/
3382  NULL, /*tp_weaklist*/
3383  NULL, /*tp_del*/
3384 };
3385 
3388 /* -------------------------------------------------------------------- */
3392 PyObject *Matrix_CreatePyObject(const float *mat,
3393  const ushort col_num,
3394  const ushort row_num,
3395  PyTypeObject *base_type)
3396 {
3397  MatrixObject *self;
3398  float *mat_alloc;
3399 
3400  /* matrix objects can be any 2-4row x 2-4col matrix */
3401  if (col_num < 2 || col_num > 4 || row_num < 2 || row_num > 4) {
3402  PyErr_SetString(PyExc_RuntimeError,
3403  "Matrix(): "
3404  "row and column sizes must be between 2 and 4");
3405  return NULL;
3406  }
3407 
3408  mat_alloc = PyMem_Malloc(col_num * row_num * sizeof(float));
3409  if (UNLIKELY(mat_alloc == NULL)) {
3410  PyErr_SetString(PyExc_MemoryError,
3411  "Matrix(): "
3412  "problem allocating data");
3413  return NULL;
3414  }
3415 
3416  self = BASE_MATH_NEW(MatrixObject, matrix_Type, base_type);
3417  if (self) {
3418  self->matrix = mat_alloc;
3419  self->col_num = col_num;
3420  self->row_num = row_num;
3421 
3422  /* init callbacks as NULL */
3423  self->cb_user = NULL;
3424  self->cb_type = self->cb_subtype = 0;
3425 
3426  if (mat) { /* If a float array passed. */
3427  memcpy(self->matrix, mat, col_num * row_num * sizeof(float));
3428  }
3429  else if (col_num == row_num) {
3430  /* or if no arguments are passed return identity matrix for square matrices */
3432  }
3433  else {
3434  /* otherwise zero everything */
3435  memset(self->matrix, 0, col_num * row_num * sizeof(float));
3436  }
3437  self->flag = BASE_MATH_FLAG_DEFAULT;
3438  }
3439  else {
3440  PyMem_Free(mat_alloc);
3441  }
3442 
3443  return (PyObject *)self;
3444 }
3445 
3446 PyObject *Matrix_CreatePyObject_wrap(float *mat,
3447  const ushort col_num,
3448  const ushort row_num,
3449  PyTypeObject *base_type)
3450 {
3451  MatrixObject *self;
3452 
3453  /* matrix objects can be any 2-4row x 2-4col matrix */
3454  if (col_num < 2 || col_num > 4 || row_num < 2 || row_num > 4) {
3455  PyErr_SetString(PyExc_RuntimeError,
3456  "Matrix(): "
3457  "row and column sizes must be between 2 and 4");
3458  return NULL;
3459  }
3460 
3461  self = BASE_MATH_NEW(MatrixObject, matrix_Type, base_type);
3462  if (self) {
3463  self->col_num = col_num;
3464  self->row_num = row_num;
3465 
3466  /* init callbacks as NULL */
3467  self->cb_user = NULL;
3468  self->cb_type = self->cb_subtype = 0;
3469 
3470  self->matrix = mat;
3472  }
3473  return (PyObject *)self;
3474 }
3475 
3477  PyObject *cb_user, const ushort col_num, const ushort row_num, uchar cb_type, uchar cb_subtype)
3478 {
3479  MatrixObject *self = (MatrixObject *)Matrix_CreatePyObject(NULL, col_num, row_num, NULL);
3480  if (self) {
3481  Py_INCREF(cb_user);
3482  self->cb_user = cb_user;
3483  self->cb_type = cb_type;
3484  self->cb_subtype = cb_subtype;
3485  PyObject_GC_Track(self);
3486  }
3487  return (PyObject *)self;
3488 }
3489 
3490 PyObject *Matrix_CreatePyObject_alloc(float *mat,
3491  const ushort col_num,
3492  const ushort row_num,
3493  PyTypeObject *base_type)
3494 {
3495  MatrixObject *self;
3496  self = (MatrixObject *)Matrix_CreatePyObject_wrap(mat, col_num, row_num, base_type);
3497  if (self) {
3498  self->flag &= ~BASE_MATH_FLAG_IS_WRAP;
3499  }
3500 
3501  return (PyObject *)self;
3502 }
3503 
3506 /* -------------------------------------------------------------------- */
3513 static bool Matrix_ParseCheck(MatrixObject *pymat)
3514 {
3515  if (!MatrixObject_Check(pymat)) {
3516  PyErr_Format(
3517  PyExc_TypeError, "expected a mathutils.Matrix, not a %.200s", Py_TYPE(pymat)->tp_name);
3518  return false;
3519  }
3520  /* sets error */
3521  if (BaseMath_ReadCallback(pymat) == -1) {
3522  return false;
3523  }
3524  return true;
3525 }
3526 
3527 int Matrix_ParseAny(PyObject *o, void *p)
3528 {
3529  MatrixObject **pymat_p = p;
3530  MatrixObject *pymat = (MatrixObject *)o;
3531 
3532  if (!Matrix_ParseCheck(pymat)) {
3533  return 0;
3534  }
3535  *pymat_p = pymat;
3536  return 1;
3537 }
3538 
3539 int Matrix_Parse2x2(PyObject *o, void *p)
3540 {
3541  MatrixObject **pymat_p = p;
3542  MatrixObject *pymat = (MatrixObject *)o;
3543 
3544  if (!Matrix_ParseCheck(pymat)) {
3545  return 0;
3546  }
3547  if ((pymat->col_num != 2) || (pymat->row_num != 2)) {
3548  PyErr_SetString(PyExc_ValueError, "matrix must be 2x2");
3549  return 0;
3550  }
3551 
3552  *pymat_p = pymat;
3553  return 1;
3554 }
3555 
3556 int Matrix_Parse3x3(PyObject *o, void *p)
3557 {
3558  MatrixObject **pymat_p = p;
3559  MatrixObject *pymat = (MatrixObject *)o;
3560 
3561  if (!Matrix_ParseCheck(pymat)) {
3562  return 0;
3563  }
3564  if ((pymat->col_num != 3) || (pymat->row_num != 3)) {
3565  PyErr_SetString(PyExc_ValueError, "matrix must be 3x3");
3566  return 0;
3567  }
3568 
3569  *pymat_p = pymat;
3570  return 1;
3571 }
3572 
3573 int Matrix_Parse4x4(PyObject *o, void *p)
3574 {
3575  MatrixObject **pymat_p = p;
3576  MatrixObject *pymat = (MatrixObject *)o;
3577 
3578  if (!Matrix_ParseCheck(pymat)) {
3579  return 0;
3580  }
3581  if ((pymat->col_num != 4) || (pymat->row_num != 4)) {
3582  PyErr_SetString(PyExc_ValueError, "matrix must be 4x4");
3583  return 0;
3584  }
3585 
3586  *pymat_p = pymat;
3587  return 1;
3588 }
3589 
3592 /* -------------------------------------------------------------------- */
3596 typedef struct {
3597  PyObject_HEAD /* Required Python macro. */
3601 
3602 static int MatrixAccess_traverse(MatrixAccessObject *self, visitproc visit, void *arg)
3603 {
3604  Py_VISIT(self->matrix_user);
3605  return 0;
3606 }
3607 
3609 {
3610  Py_CLEAR(self->matrix_user);
3611  return 0;
3612 }
3613 
3615 {
3616  if (self->matrix_user) {
3617  PyObject_GC_UnTrack(self);
3618  MatrixAccess_clear(self);
3619  }
3620 
3621  Py_TYPE(self)->tp_free(self);
3622 }
3623 
3626 /* -------------------------------------------------------------------- */
3631 {
3632  return (self->type == MAT_ACCESS_ROW) ? self->matrix_user->row_num : self->matrix_user->col_num;
3633 }
3634 
3635 static PyObject *MatrixAccess_slice(MatrixAccessObject *self, int begin, int end)
3636 {
3637  PyObject *tuple;
3638  int count;
3639 
3640  /* row/col access */
3641  MatrixObject *matrix_user = self->matrix_user;
3642  int matrix_access_len;
3643  PyObject *(*Matrix_item_new)(MatrixObject *, int);
3644 
3645  if (self->type == MAT_ACCESS_ROW) {
3646  matrix_access_len = matrix_user->row_num;
3647  Matrix_item_new = Matrix_item_row;
3648  }
3649  else { /* MAT_ACCESS_ROW */
3650  matrix_access_len = matrix_user->col_num;
3651  Matrix_item_new = Matrix_item_col;
3652  }
3653 
3654  CLAMP(begin, 0, matrix_access_len);
3655  if (end < 0) {
3656  end = (matrix_access_len + 1) + end;
3657  }
3658  CLAMP(end, 0, matrix_access_len);
3659  begin = MIN2(begin, end);
3660 
3661  tuple = PyTuple_New(end - begin);
3662  for (count = begin; count < end; count++) {
3663  PyTuple_SET_ITEM(tuple, count - begin, Matrix_item_new(matrix_user, count));
3664  }
3665 
3666  return tuple;
3667 }
3668 
3669 static PyObject *MatrixAccess_subscript(MatrixAccessObject *self, PyObject *item)
3670 {
3671  MatrixObject *matrix_user = self->matrix_user;
3672 
3673  if (PyIndex_Check(item)) {
3674  Py_ssize_t i;
3675  i = PyNumber_AsSsize_t(item, PyExc_IndexError);
3676  if (i == -1 && PyErr_Occurred()) {
3677  return NULL;
3678  }
3679  if (self->type == MAT_ACCESS_ROW) {
3680  if (i < 0) {
3681  i += matrix_user->row_num;
3682  }
3683  return Matrix_item_row(matrix_user, i);
3684  }
3685  /* MAT_ACCESS_ROW */
3686  if (i < 0) {
3687  i += matrix_user->col_num;
3688  }
3689  return Matrix_item_col(matrix_user, i);
3690  }
3691  if (PySlice_Check(item)) {
3692  Py_ssize_t start, stop, step, slicelength;
3693 
3694  if (PySlice_GetIndicesEx(item, MatrixAccess_len(self), &start, &stop, &step, &slicelength) <
3695  0) {
3696  return NULL;
3697  }
3698 
3699  if (slicelength <= 0) {
3700  return PyTuple_New(0);
3701  }
3702  if (step == 1) {
3703  return MatrixAccess_slice(self, start, stop);
3704  }
3705 
3706  PyErr_SetString(PyExc_IndexError, "slice steps not supported with matrix accessors");
3707  return NULL;
3708  }
3709 
3710  PyErr_Format(
3711  PyExc_TypeError, "matrix indices must be integers, not %.200s", Py_TYPE(item)->tp_name);
3712  return NULL;
3713 }
3714 
3715 static int MatrixAccess_ass_subscript(MatrixAccessObject *self, PyObject *item, PyObject *value)
3716 {
3717  MatrixObject *matrix_user = self->matrix_user;
3718 
3719  if (PyIndex_Check(item)) {
3720  Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
3721  if (i == -1 && PyErr_Occurred()) {
3722  return -1;
3723  }
3724 
3725  if (self->type == MAT_ACCESS_ROW) {
3726  if (i < 0) {
3727  i += matrix_user->row_num;
3728  }
3729  return Matrix_ass_item_row(matrix_user, i, value);
3730  }
3731  /* MAT_ACCESS_ROW */
3732  if (i < 0) {
3733  i += matrix_user->col_num;
3734  }
3735  return Matrix_ass_item_col(matrix_user, i, value);
3736  }
3737  /* TODO: slice. */
3738 
3739  PyErr_Format(
3740  PyExc_TypeError, "matrix indices must be integers, not %.200s", Py_TYPE(item)->tp_name);
3741  return -1;
3742 }
3743 
3744 static PyObject *MatrixAccess_iter(MatrixAccessObject *self)
3745 {
3746  /* Try get values from a collection. */
3747  PyObject *ret;
3748  PyObject *iter = NULL;
3750 
3751  /* We know this is a tuple so no need to #PyIter_Check
3752  * otherwise it could be NULL (unlikely) if conversion failed. */
3753  if (ret) {
3754  iter = PyObject_GetIter(ret);
3755  Py_DECREF(ret);
3756  }
3757 
3758  return iter;
3759 }
3760 
3761 static PyMappingMethods MatrixAccess_AsMapping = {
3762  (lenfunc)MatrixAccess_len,
3763  (binaryfunc)MatrixAccess_subscript,
3764  (objobjargproc)MatrixAccess_ass_subscript,
3765 };
3766 
3769 /* -------------------------------------------------------------------- */
3773 PyTypeObject matrix_access_Type = {
3774  PyVarObject_HEAD_INIT(NULL, 0) "MatrixAccess", /*tp_name*/
3775  sizeof(MatrixAccessObject), /*tp_basicsize*/
3776  0, /*tp_itemsize*/
3777  (destructor)MatrixAccess_dealloc, /*tp_dealloc*/
3778  (printfunc)NULL, /*tp_print*/
3779  NULL, /*tp_getattr*/
3780  NULL, /*tp_setattr*/
3781  NULL, /*tp_compare*/
3782  NULL, /*tp_repr*/
3783  NULL, /*tp_as_number*/
3784  NULL /* &MatrixAccess_SeqMethods */ /* TODO */, /*tp_as_sequence*/
3785  &MatrixAccess_AsMapping, /*tp_as_mapping*/
3786  NULL, /*tp_hash*/
3787  NULL, /*tp_call*/
3788  NULL, /*tp_str*/
3789  NULL, /*tp_getattro*/
3790  NULL, /*tp_setattro*/
3791  NULL, /*tp_as_buffer*/
3792  Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
3793  NULL, /*tp_doc*/
3794  (traverseproc)MatrixAccess_traverse, /*tp_traverse*/
3795  (inquiry)MatrixAccess_clear, /*tp_clear*/
3796  NULL /* (richcmpfunc)MatrixAccess_richcmpr */ /* TODO*/, /*tp_richcompare*/
3797  0, /*tp_weaklistoffset*/
3798  (getiterfunc)MatrixAccess_iter, /* getiterfunc tp_iter; */
3799 };
3800 
3803 /* -------------------------------------------------------------------- */
3808 {
3809  MatrixAccessObject *matrix_access = (MatrixAccessObject *)PyObject_GC_New(MatrixObject,
3811 
3812  matrix_access->matrix_user = matrix;
3813  Py_INCREF(matrix);
3814 
3815  matrix_access->type = type;
3816 
3817  return (PyObject *)matrix_access;
3818 }
3819 
typedef float(TangentPoint)[2]
#define BLI_assert_unreachable()
Definition: BLI_assert.h:93
#define BLI_assert(a)
Definition: BLI_assert.h:46
#define ATTR_FALLTHROUGH
A dynamically sized string ADT.
DynStr * BLI_dynstr_new(void) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
Definition: BLI_dynstr.c:50
void BLI_dynstr_appendf(DynStr *__restrict ds, const char *__restrict format,...) ATTR_PRINTF_FORMAT(2
void BLI_dynstr_append(DynStr *__restrict ds, const char *cstr) ATTR_NONNULL()
Definition: BLI_dynstr.c:75
MINLINE int min_ii(int a, int b)
MINLINE int max_ii(int a, int b)
bool is_negative_m3(const float mat[3][3])
Definition: math_matrix.c:2502
void unit_m2(float m[2][2])
Definition: math_matrix.c:33
void negate_m3(float R[3][3])
Definition: math_matrix.c:989
void interp_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4], float t)
Definition: math_matrix.c:2481
void copy_m3_m3(float m1[3][3], const float m2[3][3])
Definition: math_matrix.c:71
void adjoint_m3_m3(float R[3][3], const float M[3][3])
Definition: math_matrix.c:1984
void unit_m3(float m[3][3])
Definition: math_matrix.c:40
void mat3_to_rot_size(float rot[3][3], float size[3], const float mat3[3][3])
Definition: math_matrix.c:2202
void blend_m4_m4m4(float out[4][4], const float dst[4][4], const float src[4][4], float srcweight)
Definition: math_matrix.c:2409
void copy_m3_m4(float m1[3][3], const float m2[4][4])
Definition: math_matrix.c:87
#define PSEUDOINVERSE_EPSILON
void unit_m4(float m[4][4])
Definition: rct.c:1090
void copy_m4_m3(float m1[4][4], const float m2[3][3])
Definition: math_matrix.c:102
void mat4_to_loc_rot_size(float loc[3], float rot[3][3], float size[3], const float wmat[4][4])
Definition: math_matrix.c:2224
void normalize_m3(float R[3][3]) ATTR_NONNULL()
Definition: math_matrix.c:1912
float determinant_m2(float a, float b, float c, float d)
Definition: math_matrix.c:2046
bool is_orthogonal_m3(const float mat[3][3])
Definition: math_matrix.c:1779
void rescale_m4(float mat[4][4], const float scale[3])
Definition: math_matrix.c:2362
bool is_orthonormal_m3(const float mat[3][3])
Definition: math_matrix.c:1809
float mat3_to_scale(const float M[3][3])
Definition: math_matrix.c:2176
void adjoint_m4_m4(float R[4][4], const float M[4][4])
Definition: math_matrix.c:2000
float determinant_m4(const float m[4][4])
Definition: math_matrix.c:2063
void copy_m2_m2(float m1[2][2], const float m2[2][2])
Definition: math_matrix.c:66
void copy_m4_m4(float m1[4][4], const float m2[4][4])
Definition: math_matrix.c:77
void interp_m3_m3m3(float R[3][3], const float A[3][3], const float B[3][3], float t)
Definition: math_matrix.c:2436
float determinant_m3_array(const float m[3][3])
Definition: math_matrix.c:1098
bool is_negative_m4(const float mat[4][4])
Definition: math_matrix.c:2509
void transpose_m3(float R[3][3])
Definition: math_matrix.c:1332
bool is_orthogonal_m4(const float mat[4][4])
Definition: math_matrix.c:1794
float determinant_m3(float a1, float a2, float a3, float b1, float b2, float b3, float c1, float c2, float c3)
Definition: math_matrix.c:2052
void blend_m3_m3m3(float out[3][3], const float dst[3][3], const float src[3][3], float srcweight)
Definition: math_matrix.c:2383
void mul_m3_m3m3(float R[3][3], const float A[3][3], const float B[3][3])
Definition: math_matrix.c:388
void transpose_m4(float R[4][4])
Definition: math_matrix.c:1377
bool is_orthonormal_m4(const float mat[4][4])
Definition: math_matrix.c:1826
void normalize_m4(float R[4][4]) ATTR_NONNULL()
Definition: math_matrix.c:1945
void adjoint_m2_m2(float R[2][2], const float M[2][2])
Definition: math_matrix.c:1975
void mat3_normalized_to_compatible_eulO(float eul[3], const float old[3], short order, const float mat[3][3])
void axis_angle_to_mat3_single(float R[3][3], char axis, float angle)
@ EULER_ORDER_XYZ
void mat3_to_quat(float q[4], const float mat[3][3])
void mat3_normalized_to_compatible_eul(float eul[3], const float old[3], float mat[3][3])
void angle_to_mat2(float R[2][2], float angle)
void mat3_normalized_to_eul(float eul[3], const float mat[3][3])
void eulO_to_mat4(float mat[4][4], const float eul[3], short order)
float angle_wrap_rad(float angle)
void axis_angle_to_mat3(float R[3][3], const float axis[3], float angle)
void mat3_normalized_to_quat(float q[4], const float mat[3][3])
void mat3_normalized_to_eulO(float eul[3], short order, const float mat[3][3])
void quat_to_mat4(float mat[4][4], const float q[4])
void mul_vn_fl(float *array_tar, int size, float f)
Definition: math_vector.c:1093
void sub_vn_vnvn(float *array_tar, const float *array_src_a, const float *array_src_b, int size)
Definition: math_vector.c:1171
MINLINE void copy_v3_v3(float r[3], const float a[3])
void add_vn_vnvn(float *array_tar, const float *array_src_a, const float *array_src_b, int size)
Definition: math_vector.c:1122
void copy_vn_fl(float *array_tar, int size, float val)
Definition: math_vector.c:1259
void mul_vn_vn(float *array_tar, const float *array_src, int size)
Definition: math_vector.c:1069
MINLINE void zero_v3(float r[3])
void mul_vn_vn_fl(float *array_tar, const float *array_src, int size, float f)
Definition: math_vector.c:1102
void mul_vn_vnvn(float *array_tar, const float *array_src_a, const float *array_src_b, int size)
Definition: math_vector.c:1079
size_t BLI_snprintf_rlen(char *__restrict dst, size_t maxncpy, const char *__restrict format,...) ATTR_NONNULL(1
unsigned char uchar
Definition: BLI_sys_types.h:70
unsigned int uint
Definition: BLI_sys_types.h:67
unsigned short ushort
Definition: BLI_sys_types.h:68
#define UNUSED(x)
#define UNLIKELY(x)
#define ELEM(...)
#define MIN2(a, b)
#define STREQ(a, b)
typedef double(DMatrix)[4][4]
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble t
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint order
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to used to fine tune the interpolation of the input Camera Retrieve information about the camera and how it relates to the current shading point s position CLAMP
PyObject * self
Definition: bpy_driver.c:165
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
SIMD_FORCE_INLINE btScalar norm() const
Return the norm (length) of the vector.
Definition: btVector3.h:263
SIMD_FORCE_INLINE btScalar angle(const btVector3 &v) const
Return the angle between this and another vector.
Definition: btVector3.h:356
SyclQueue void void size_t num_bytes void
#define rot(x, k)
uint col
int count
PyObject * BaseMathObject_freeze(BaseMathObject *self)
Definition: mathutils.c:681
PyObject * BaseMathObject_is_frozen_get(BaseMathObject *self, void *UNUSED(closure))
Definition: mathutils.c:661
PyObject * BaseMathObject_is_wrapped_get(BaseMathObject *self, void *UNUSED(closure))
Definition: mathutils.c:654
PyObject * mathutils_dynstr_to_py(struct DynStr *ds)
Definition: mathutils.c:531
Py_hash_t mathutils_array_hash(const float *array, size_t array_len)
Definition: mathutils.c:66
void BaseMathObject_dealloc(BaseMathObject *self)
Definition: mathutils.c:705
int EXPP_VectorsAreEqual(const float *vecA, const float *vecB, int size, int floatSteps)
Definition: mathutils.c:519
int mathutils_array_parse(float *array, int array_num_min, int array_num_max, PyObject *value, const char *error_prefix)
Definition: mathutils.c:98
char BaseMathObject_is_valid_doc[]
Definition: mathutils.c:666
PyObject * BaseMathObject_owner_get(BaseMathObject *self, void *UNUSED(closure))
Definition: mathutils.c:646
char BaseMathObject_is_wrapped_doc[]
Definition: mathutils.c:652
char BaseMathObject_is_frozen_doc[]
Definition: mathutils.c:659
int mathutils_any_to_rotmat(float rmat[3][3], PyObject *value, const char *error_prefix)
Definition: mathutils.c:439
PyObject * BaseMathObject_is_valid_get(BaseMathObject *self, void *UNUSED(closure))
Definition: mathutils.c:668
char BaseMathObject_owner_doc[]
Definition: mathutils.c:645
char BaseMathObject_freeze_doc[]
Definition: mathutils.c:673
int BaseMathObject_clear(BaseMathObject *self)
Definition: mathutils.c:699
int BaseMathObject_traverse(BaseMathObject *self, visitproc visit, void *arg)
Definition: mathutils.c:693
@ BASE_MATH_FLAG_IS_WRAP
Definition: mathutils.h:31
#define BaseMath_ReadCallback_ForWrite(_self)
Definition: mathutils.h:129
#define BaseMath_WriteCallback(_self)
Definition: mathutils.h:121
#define BASE_MATH_NEW(struct_name, root_type, base_type)
Definition: mathutils.h:20
#define BaseMathObject_Prepare_ForHash(_self)
Definition: mathutils.h:144
int column_vector_multiplication(float r_vec[4], VectorObject *vec, MatrixObject *mat)
#define BASE_MATH_FLAG_DEFAULT
Definition: mathutils.h:38
#define BaseMath_Prepare_ForWrite(_self)
Definition: mathutils.h:139
#define BaseMath_ReadCallback(_self)
Definition: mathutils.h:119
short euler_order_from_string(const char *str, const char *error_prefix)
PyTypeObject euler_Type
PyObject * Euler_CreatePyObject(const float eul[3], const short order, PyTypeObject *base_type)
#define EulerObject_Check(v)
int Matrix_Parse3x3(PyObject *o, void *p)
static bool matrix_invert_internal(const MatrixObject *self, float *r_mat)
static int Matrix_len(MatrixObject *self)
static PyObject * C_Matrix_Identity(PyObject *cls, PyObject *args)
static PyMappingMethods MatrixAccess_AsMapping
static PyGetSetDef Matrix_getseters[]
static PyObject * Matrix_to_4x4(MatrixObject *self)
static PyObject * Matrix_lerp(MatrixObject *self, PyObject *args)
static PyObject * Matrix_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
static int mathutils_matrix_col_set(BaseMathObject *bmo, int col)
static PyObject * Matrix_richcmpr(PyObject *a, PyObject *b, int op)
static PyObject * C_Matrix_OrthoProjection(PyObject *cls, PyObject *args)
int Matrix_ParseAny(PyObject *o, void *p)
static PyObject * matrix_mul_float(MatrixObject *mat, const float scalar)
static int mathutils_matrix_row_set(BaseMathObject *bmo, int row)
static int matrix_row_vector_check(MatrixObject *mat, VectorObject *vec, int row)
static int mathutils_matrix_row_get_index(BaseMathObject *bmo, int row, int col)
static PyObject * Matrix_resize_4x4(MatrixObject *self)
static int Matrix_ass_subscript(MatrixObject *self, PyObject *item, PyObject *value)
static int mathutils_matrix_row_set_index(BaseMathObject *bmo, int row, int col)
static PyObject * Matrix_invert_safe(MatrixObject *self)
static int mathutils_matrix_col_get(BaseMathObject *bmo, int col)
static PyObject * Matrix_item_col(MatrixObject *self, int col)
static PyObject * Matrix_to_euler(MatrixObject *self, PyObject *args)
static PyObject * Matrix_imul(PyObject *m1, PyObject *m2)
static PyObject * Matrix_translation_get(MatrixObject *self, void *UNUSED(closure))
static void matrix_transpose_internal(float mat_dst_fl[], const MatrixObject *mat_src)
static void matrix_identity_internal(MatrixObject *self)
static PyObject * Matrix_normalize(MatrixObject *self)
static int Matrix_translation_set(MatrixObject *self, PyObject *value, void *UNUSED(closure))
static PyObject * Matrix_add(PyObject *m1, PyObject *m2)
static PyObject * matrix__apply_to_copy(PyObject *(*matrix_func)(MatrixObject *), MatrixObject *self)
static PyObject * Matrix_to_quaternion(MatrixObject *self)
static int mathutils_matrix_row_check(BaseMathObject *bmo)
static PyObject * Matrix_mul(PyObject *m1, PyObject *m2)
static int MatrixAccess_clear(MatrixAccessObject *self)
static float matrix_determinant_internal(const MatrixObject *self)
static PyObject * Matrix_str(MatrixObject *self)
static PyObject * Matrix_row_get(MatrixObject *self, void *UNUSED(closure))
PyObject * Matrix_CreatePyObject(const float *mat, const ushort col_num, const ushort row_num, PyTypeObject *base_type)
static PyObject * Matrix_to_3x3(MatrixObject *self)
PyDoc_STRVAR(C_Matrix_Identity_doc, ".. classmethod:: Identity(size)\n" "\n" " Create an identity matrix.\n" "\n" " :arg size: The size of the identity matrix to construct [2, 4].\n" " :type size: int\n" " :return: A new identity matrix.\n" " :rtype: :class:`Matrix`\n")
static void matrix_unit_internal(MatrixObject *self)
Mathutils_Callback mathutils_matrix_col_cb
static void adjoint_matrix_n(float *mat_dst, const float *mat_src, const ushort dim)
static bool matrix_invert_is_compat(const MatrixObject *self)
static bool matrix_is_identity(MatrixObject *self)
static PyObject * Matrix_inverted_noargs(MatrixObject *self)
static int mathutils_matrix_translation_set_index(BaseMathObject *bmo, int col, int row)
PyTypeObject matrix_access_Type
static PyObject * Matrix_is_orthogonal_get(MatrixObject *self, void *UNUSED(closure))
static PyNumberMethods Matrix_NumMethods
static PyObject * C_Matrix_Translation(PyObject *cls, PyObject *value)
static PyObject * Matrix_transposed(MatrixObject *self)
static PyObject * Matrix_col_get(MatrixObject *self, void *UNUSED(closure))
static PyObject * MatrixAccess_iter(MatrixAccessObject *self)
static PyObject * Matrix_median_scale_get(MatrixObject *self, void *UNUSED(closure))
static PyObject * C_Matrix_Rotation(PyObject *cls, PyObject *args)
static PyObject * Matrix_is_orthogonal_axis_vectors_get(MatrixObject *self, void *UNUSED(closure))
static PySequenceMethods Matrix_SeqMethods
static PyObject * Matrix_decompose(MatrixObject *self)
static PyObject * Matrix_subscript(MatrixObject *self, PyObject *item)
static int mathutils_matrix_col_get_index(BaseMathObject *bmo, int col, int row)
static PyObject * Matrix_repr(MatrixObject *self)
static PyObject * C_Matrix_Scale(PyObject *cls, PyObject *args)
eMatrixAccess_t
@ MAT_ACCESS_ROW
@ MAT_ACCESS_COL
static PyObject * MatrixAccess_slice(MatrixAccessObject *self, int begin, int end)
static int mathutils_matrix_translation_get_index(BaseMathObject *bmo, int col, int row)
static void matrix_invert_with_det_n_internal(float *mat_dst, const float *mat_src, const float det, const ushort dim)
static PyObject * Matrix_is_identity_get(MatrixObject *self, void *UNUSED(closure))
static PyObject * Matrix_deepcopy(MatrixObject *self, PyObject *args)
static PyObject * Matrix_rotate(MatrixObject *self, PyObject *value)
static PyObject * Matrix_item_row(MatrixObject *self, int row)
void matrix_as_3x3(float mat[3][3], MatrixObject *self)
static bool Matrix_ParseCheck(MatrixObject *pymat)
static int MatrixAccess_len(MatrixAccessObject *self)
static PyMappingMethods Matrix_AsMapping
static PyObject * Matrix_copy(MatrixObject *self)
static void matrix_3x3_as_4x4(float mat[16])
int Matrix_Parse2x2(PyObject *o, void *p)
Mathutils_Callback mathutils_matrix_row_cb
static int mathutils_matrix_translation_get(BaseMathObject *bmo, int col)
static int MatrixAccess_traverse(MatrixAccessObject *self, visitproc visit, void *arg)
static int Matrix_ass_item_row(MatrixObject *self, int row, PyObject *value)
Mathutils_Callback mathutils_matrix_translation_cb
static PyObject * Matrix_inverted_safe(MatrixObject *self)
static PyObject * Matrix_is_negative_get(MatrixObject *self, void *UNUSED(closure))
static int Matrix_ass_slice(MatrixObject *self, int begin, int end, PyObject *value)
static PyObject * Matrix_to_NxN(MatrixObject *self, const int col_num, const int row_num)
int Matrix_Parse4x4(PyObject *o, void *p)
static PyObject * C_Matrix_Diagonal(PyObject *cls, PyObject *value)
PyObject * Matrix_CreatePyObject_wrap(float *mat, const ushort col_num, const ushort row_num, PyTypeObject *base_type)
uchar mathutils_matrix_col_cb_index
static int Matrix_ass_item_col(MatrixObject *self, int col, PyObject *value)
uchar mathutils_matrix_row_cb_index
static PyObject * Matrix_invert(MatrixObject *self, PyObject *args)
static PyObject * Matrix_imatmul(PyObject *m1, PyObject *m2)
static void matrix_invert_raise_degenerate(void)
static PyObject * Matrix_to_scale(MatrixObject *self)
static int MatrixAccess_ass_subscript(MatrixAccessObject *self, PyObject *item, PyObject *value)
PyObject * Matrix_CreatePyObject_cb(PyObject *cb_user, const ushort col_num, const ushort row_num, uchar cb_type, uchar cb_subtype)
static int mathutils_matrix_row_get(BaseMathObject *bmo, int row)
static int matrix_col_vector_check(MatrixObject *mat, VectorObject *vec, int col)
static PyObject * Matrix_normalized(MatrixObject *self)
static PyObject * Matrix_adjugated(MatrixObject *self)
static PyObject * Matrix_to_translation(MatrixObject *self)
static PyObject * C_Matrix_Shear(PyObject *cls, PyObject *args)
static bool matrix_invert_args_check(const MatrixObject *self, PyObject *args, bool check_type)
static int mathutils_matrix_translation_check(BaseMathObject *bmo)
static void MatrixAccess_dealloc(MatrixAccessObject *self)
PyObject * Matrix_CreatePyObject_alloc(float *mat, const ushort col_num, const ushort row_num, PyTypeObject *base_type)
static PyObject * Matrix_inverted(MatrixObject *self, PyObject *args)
static PyObject * Matrix_adjugate(MatrixObject *self)
static struct PyMethodDef Matrix_methods[]
static int mathutils_matrix_col_check(BaseMathObject *bmo)
static void matrix_copy(MatrixObject *mat_dst, const MatrixObject *mat_src)
static PyObject * Matrix_zero(MatrixObject *self)
static PyObject * Matrix_matmul(PyObject *m1, PyObject *m2)
static Py_hash_t Matrix_hash(MatrixObject *self)
static PyObject * Matrix_transpose(MatrixObject *self)
static int mathutils_matrix_col_set_index(BaseMathObject *bmo, int col, int row)
static PyObject * MatrixAccess_subscript(MatrixAccessObject *self, PyObject *item)
static int mathutils_matrix_translation_set(BaseMathObject *bmo, int col)
static PyObject * Matrix_to_2x2(MatrixObject *self)
static PyObject * C_Matrix_LocRotScale(PyObject *cls, PyObject *args)
static PyObject * Matrix_determinant(MatrixObject *self)
static PyObject * Matrix_sub(PyObject *m1, PyObject *m2)
static PyObject * Matrix_copy_notest(MatrixObject *self, const float *matrix)
static PyObject * MatrixAccess_CreatePyObject(MatrixObject *matrix, const eMatrixAccess_t type)
static void matrix_invert_safe_internal(const MatrixObject *self, float *r_mat)
static PyObject * Matrix_slice(MatrixObject *self, int begin, int end)
static PyObject * Matrix_identity(MatrixObject *self)
uchar mathutils_matrix_translation_cb_index
PyTypeObject matrix_Type
#define MATRIX_COL_PTR(_mat, _col)
#define MATRIX_MAX_DIM
#define MatrixObject_Check(v)
#define MATRIX_ITEM_INDEX_NUMROW(_totrow, _row, _col)
#define MATRIX_ITEM(_mat, _row, _col)
PyObject * Quaternion_CreatePyObject(const float quat[4], PyTypeObject *base_type)
#define QuaternionObject_Check(v)
PyObject * Vector_CreatePyObject(const float *vec, const int vec_num, PyTypeObject *base_type)
PyObject * Vector_CreatePyObject_cb(PyObject *cb_user, int vec_num, uchar cb_type, uchar cb_subtype)
#define VectorObject_Check(v)
#define sqrtf(x)
Definition: metal/compat.h:243
static unsigned a[3]
Definition: RandGen.cpp:78
T dot(const vec_base< T, Size > &a, const vec_base< T, Size > &b)
static const pxr::TfToken b("b", pxr::TfToken::Immortal)
const btScalar eps
Definition: poly34.cpp:11
int PyC_CheckArgs_DeepCopy(PyObject *args)
#define PyTuple_SET_ITEMS(op_arg,...)
return ret
unsigned char order
PyObject_HEAD MatrixObject * matrix_user
eMatrixAccess_t type