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