3e5dcc28903dfa3183abb673bf887bc610d9d143
[blender.git] / source / blender / python / mathutils / mathutils_Matrix.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * Contributor(s): Michel Selten & Joseph Gilbert
19  *
20  * ***** END GPL LICENSE BLOCK *****
21  */
22
23 /** \file blender/python/mathutils/mathutils_Matrix.c
24  *  \ingroup pymathutils
25  */
26
27
28 #include <Python.h>
29
30 #include "mathutils.h"
31
32 #include "BLI_math.h"
33 #include "BLI_utildefines.h"
34 #include "BLI_string.h"
35
36 #ifndef MATH_STANDALONE
37 #  include "BLI_dynstr.h"
38 #endif
39
40 typedef enum eMatrixAccess_t {
41         MAT_ACCESS_ROW,
42         MAT_ACCESS_COL
43 } eMatrixAccess_t;
44
45 static PyObject *Matrix_copy(MatrixObject *self);
46 static PyObject *Matrix_deepcopy(MatrixObject *self, PyObject *args);
47 static int Matrix_ass_slice(MatrixObject *self, int begin, int end, PyObject *value);
48 static PyObject *matrix__apply_to_copy(PyNoArgsFunction matrix_func, MatrixObject *self);
49 static PyObject *MatrixAccess_CreatePyObject(MatrixObject *matrix, const eMatrixAccess_t type);
50
51 static int matrix_row_vector_check(MatrixObject *mat, VectorObject *vec, int row)
52 {
53         if ((vec->size != mat->num_col) || (row >= mat->num_row)) {
54                 PyErr_SetString(PyExc_AttributeError,
55                                 "Matrix(): "
56                                 "owner matrix has been resized since this row vector was created");
57                 return 0;
58         }
59         else {
60                 return 1;
61         }
62 }
63
64 static int matrix_col_vector_check(MatrixObject *mat, VectorObject *vec, int col)
65 {
66         if ((vec->size != mat->num_row) || (col >= mat->num_col)) {
67                 PyErr_SetString(PyExc_AttributeError,
68                                 "Matrix(): "
69                                 "owner matrix has been resized since this column vector was created");
70                 return 0;
71         }
72         else {
73                 return 1;
74         }
75 }
76
77 /* ----------------------------------------------------------------------------
78  * matrix row callbacks
79  * this is so you can do matrix[i][j] = val OR matrix.row[i][j] = val */
80
81 unsigned char mathutils_matrix_row_cb_index = -1;
82
83 static int mathutils_matrix_row_check(BaseMathObject *bmo)
84 {
85         MatrixObject *self = (MatrixObject *)bmo->cb_user;
86         return BaseMath_ReadCallback(self);
87 }
88
89 static int mathutils_matrix_row_get(BaseMathObject *bmo, int row)
90 {
91         MatrixObject *self = (MatrixObject *)bmo->cb_user;
92         int col;
93
94         if (BaseMath_ReadCallback(self) == -1)
95                 return -1;
96         if (!matrix_row_vector_check(self, (VectorObject *)bmo, row))
97                 return -1;
98
99         for (col = 0; col < self->num_col; col++) {
100                 bmo->data[col] = MATRIX_ITEM(self, row, col);
101         }
102
103         return 0;
104 }
105
106 static int mathutils_matrix_row_set(BaseMathObject *bmo, int row)
107 {
108         MatrixObject *self = (MatrixObject *)bmo->cb_user;
109         int col;
110
111         if (BaseMath_ReadCallback(self) == -1)
112                 return -1;
113         if (!matrix_row_vector_check(self, (VectorObject *)bmo, row))
114                 return -1;
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         if (!matrix_row_vector_check(self, (VectorObject *)bmo, row))
131                 return -1;
132
133         bmo->data[col] = MATRIX_ITEM(self, row, col);
134         return 0;
135 }
136
137 static int mathutils_matrix_row_set_index(BaseMathObject *bmo, int row, int col)
138 {
139         MatrixObject *self = (MatrixObject *)bmo->cb_user;
140
141         if (BaseMath_ReadCallback(self) == -1)
142                 return -1;
143         if (!matrix_row_vector_check(self, (VectorObject *)bmo, row))
144                 return -1;
145
146         MATRIX_ITEM(self, row, col) = bmo->data[col];
147
148         (void)BaseMath_WriteCallback(self);
149         return 0;
150 }
151
152 Mathutils_Callback mathutils_matrix_row_cb = {
153         mathutils_matrix_row_check,
154         mathutils_matrix_row_get,
155         mathutils_matrix_row_set,
156         mathutils_matrix_row_get_index,
157         mathutils_matrix_row_set_index
158 };
159
160
161 /* ----------------------------------------------------------------------------
162  * matrix row callbacks
163  * this is so you can do matrix.col[i][j] = val */
164
165 unsigned char mathutils_matrix_col_cb_index = -1;
166
167 static int mathutils_matrix_col_check(BaseMathObject *bmo)
168 {
169         MatrixObject *self = (MatrixObject *)bmo->cb_user;
170         return BaseMath_ReadCallback(self);
171 }
172
173 static int mathutils_matrix_col_get(BaseMathObject *bmo, int col)
174 {
175         MatrixObject *self = (MatrixObject *)bmo->cb_user;
176         int num_row;
177         int row;
178
179         if (BaseMath_ReadCallback(self) == -1)
180                 return -1;
181         if (!matrix_col_vector_check(self, (VectorObject *)bmo, col))
182                 return -1;
183
184         /* for 'translation' size will always be '3' even on 4x4 vec */
185         num_row = min_ii(self->num_row, ((VectorObject *)bmo)->size);
186
187         for (row = 0; row < num_row; row++) {
188                 bmo->data[row] = MATRIX_ITEM(self, row, col);
189         }
190
191         return 0;
192 }
193
194 static int mathutils_matrix_col_set(BaseMathObject *bmo, int col)
195 {
196         MatrixObject *self = (MatrixObject *)bmo->cb_user;
197         int num_row;
198         int row;
199
200         if (BaseMath_ReadCallback(self) == -1)
201                 return -1;
202         if (!matrix_col_vector_check(self, (VectorObject *)bmo, col))
203                 return -1;
204
205         /* for 'translation' size will always be '3' even on 4x4 vec */
206         num_row = min_ii(self->num_row, ((VectorObject *)bmo)->size);
207
208         for (row = 0; row < num_row; row++) {
209                 MATRIX_ITEM(self, row, col) = bmo->data[row];
210         }
211
212         (void)BaseMath_WriteCallback(self);
213         return 0;
214 }
215
216 static int mathutils_matrix_col_get_index(BaseMathObject *bmo, int col, int row)
217 {
218         MatrixObject *self = (MatrixObject *)bmo->cb_user;
219
220         if (BaseMath_ReadCallback(self) == -1)
221                 return -1;
222         if (!matrix_col_vector_check(self, (VectorObject *)bmo, col))
223                 return -1;
224
225         bmo->data[row] = MATRIX_ITEM(self, row, col);
226         return 0;
227 }
228
229 static int mathutils_matrix_col_set_index(BaseMathObject *bmo, int col, int row)
230 {
231         MatrixObject *self = (MatrixObject *)bmo->cb_user;
232
233         if (BaseMath_ReadCallback(self) == -1)
234                 return -1;
235         if (!matrix_col_vector_check(self, (VectorObject *)bmo, col))
236                 return -1;
237
238         MATRIX_ITEM(self, row, col) = bmo->data[row];
239
240         (void)BaseMath_WriteCallback(self);
241         return 0;
242 }
243
244 Mathutils_Callback mathutils_matrix_col_cb = {
245         mathutils_matrix_col_check,
246         mathutils_matrix_col_get,
247         mathutils_matrix_col_set,
248         mathutils_matrix_col_get_index,
249         mathutils_matrix_col_set_index
250 };
251
252
253 /* ----------------------------------------------------------------------------
254  * matrix row callbacks
255  * this is so you can do matrix.translation = val
256  * note, this is _exactly like matrix.col except the 4th component is always omitted */
257
258 unsigned char mathutils_matrix_translation_cb_index = -1;
259
260 static int mathutils_matrix_translation_check(BaseMathObject *bmo)
261 {
262         MatrixObject *self = (MatrixObject *)bmo->cb_user;
263         return BaseMath_ReadCallback(self);
264 }
265
266 static int mathutils_matrix_translation_get(BaseMathObject *bmo, int col)
267 {
268         MatrixObject *self = (MatrixObject *)bmo->cb_user;
269         int row;
270
271         if (BaseMath_ReadCallback(self) == -1)
272                 return -1;
273
274         for (row = 0; row < 3; row++) {
275                 bmo->data[row] = MATRIX_ITEM(self, row, col);
276         }
277
278         return 0;
279 }
280
281 static int mathutils_matrix_translation_set(BaseMathObject *bmo, int col)
282 {
283         MatrixObject *self = (MatrixObject *)bmo->cb_user;
284         int row;
285
286         if (BaseMath_ReadCallback(self) == -1)
287                 return -1;
288
289         for (row = 0; row < 3; row++) {
290                 MATRIX_ITEM(self, row, col) = bmo->data[row];
291         }
292
293         (void)BaseMath_WriteCallback(self);
294         return 0;
295 }
296
297 static int mathutils_matrix_translation_get_index(BaseMathObject *bmo, int col, int row)
298 {
299         MatrixObject *self = (MatrixObject *)bmo->cb_user;
300
301         if (BaseMath_ReadCallback(self) == -1)
302                 return -1;
303
304         bmo->data[row] = MATRIX_ITEM(self, row, col);
305         return 0;
306 }
307
308 static int mathutils_matrix_translation_set_index(BaseMathObject *bmo, int col, int row)
309 {
310         MatrixObject *self = (MatrixObject *)bmo->cb_user;
311
312         if (BaseMath_ReadCallback(self) == -1)
313                 return -1;
314
315         MATRIX_ITEM(self, row, col) = bmo->data[row];
316
317         (void)BaseMath_WriteCallback(self);
318         return 0;
319 }
320
321 Mathutils_Callback mathutils_matrix_translation_cb = {
322         mathutils_matrix_translation_check,
323         mathutils_matrix_translation_get,
324         mathutils_matrix_translation_set,
325         mathutils_matrix_translation_get_index,
326         mathutils_matrix_translation_set_index
327 };
328
329
330 /* matrix column callbacks, this is so you can do matrix.translation = Vector()  */
331
332 /* ----------------------------------mathutils.Matrix() ----------------- */
333 /* mat is a 1D array of floats - row[0][0], row[0][1], row[1][0], etc. */
334 /* create a new matrix type */
335 static PyObject *Matrix_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
336 {
337         if (kwds && PyDict_Size(kwds)) {
338                 PyErr_SetString(PyExc_TypeError,
339                                 "Matrix(): "
340                                 "takes no keyword args");
341                 return NULL;
342         }
343
344         switch (PyTuple_GET_SIZE(args)) {
345                 case 0:
346                         return Matrix_CreatePyObject(NULL, 4, 4, Py_NEW, type);
347                 case 1:
348                 {
349                         PyObject *arg = PyTuple_GET_ITEM(args, 0);
350
351                         /* Input is now as a sequence of rows so length of sequence
352                          * is the number of rows */
353                         /* -1 is an error, size checks will accunt for this */
354                         const unsigned short num_row = PySequence_Size(arg);
355
356                         if (num_row >= 2 && num_row <= 4) {
357                                 PyObject *item = PySequence_GetItem(arg, 0);
358                                 /* Since each item is a row, number of items is the
359                                  * same as the number of columns */
360                                 const unsigned short num_col = PySequence_Size(item);
361                                 Py_XDECREF(item);
362
363                                 if (num_col >= 2 && num_col <= 4) {
364                                         /* sane row & col size, new matrix and assign as slice  */
365                                         PyObject *matrix = Matrix_CreatePyObject(NULL, num_col, num_row, Py_NEW, type);
366                                         if (Matrix_ass_slice((MatrixObject *)matrix, 0, INT_MAX, arg) == 0) {
367                                                 return matrix;
368                                         }
369                                         else { /* matrix ok, slice assignment not */
370                                                 Py_DECREF(matrix);
371                                         }
372                                 }
373                         }
374                         break;
375                 }
376         }
377
378         /* will overwrite error */
379         PyErr_SetString(PyExc_TypeError,
380                         "Matrix(): "
381                         "expects no args or 2-4 numeric sequences");
382         return NULL;
383 }
384
385 static PyObject *matrix__apply_to_copy(PyNoArgsFunction matrix_func, MatrixObject *self)
386 {
387         PyObject *ret = Matrix_copy(self);
388         if (ret) {
389                 PyObject *ret_dummy = matrix_func(ret);
390                 if (ret_dummy) {
391                         Py_DECREF(ret_dummy);
392                         return (PyObject *)ret;
393                 }
394                 else { /* error */
395                         Py_DECREF(ret);
396                         return NULL;
397                 }
398         }
399         else {
400                 /* copy may fail if the read callback errors out */
401                 return NULL;
402         }
403 }
404
405 /* when a matrix is 4x4 size but initialized as a 3x3, re-assign values for 4x4 */
406 static void matrix_3x3_as_4x4(float mat[16])
407 {
408         mat[10] = mat[8];
409         mat[9] = mat[7];
410         mat[8] = mat[6];
411         mat[7] = 0.0f;
412         mat[6] = mat[5];
413         mat[5] = mat[4];
414         mat[4] = mat[3];
415         mat[3] = 0.0f;
416 }
417
418 /*-----------------------CLASS-METHODS----------------------------*/
419
420 /* mat is a 1D array of floats - row[0][0], row[0][1], row[1][0], etc. */
421 PyDoc_STRVAR(C_Matrix_Identity_doc,
422 ".. classmethod:: Identity(size)\n"
423 "\n"
424 "   Create an identity matrix.\n"
425 "\n"
426 "   :arg size: The size of the identity matrix to construct [2, 4].\n"
427 "   :type size: int\n"
428 "   :return: A new identity matrix.\n"
429 "   :rtype: :class:`Matrix`\n"
430 );
431 static PyObject *C_Matrix_Identity(PyObject *cls, PyObject *args)
432 {
433         int matSize;
434
435         if (!PyArg_ParseTuple(args, "i:Matrix.Identity", &matSize)) {
436                 return NULL;
437         }
438
439         if (matSize < 2 || matSize > 4) {
440                 PyErr_SetString(PyExc_RuntimeError,
441                                 "Matrix.Identity(): "
442                                 "size must be between 2 and 4");
443                 return NULL;
444         }
445
446         return Matrix_CreatePyObject(NULL, matSize, matSize, Py_NEW, (PyTypeObject *)cls);
447 }
448
449 PyDoc_STRVAR(C_Matrix_Rotation_doc,
450 ".. classmethod:: Rotation(angle, size, axis)\n"
451 "\n"
452 "   Create a matrix representing a rotation.\n"
453 "\n"
454 "   :arg angle: The angle of rotation desired, in radians.\n"
455 "   :type angle: float\n"
456 "   :arg size: The size of the rotation matrix to construct [2, 4].\n"
457 "   :type size: int\n"
458 "   :arg axis: a string in ['X', 'Y', 'Z'] or a 3D Vector Object\n"
459 "      (optional when size is 2).\n"
460 "   :type axis: string or :class:`Vector`\n"
461 "   :return: A new rotation matrix.\n"
462 "   :rtype: :class:`Matrix`\n"
463 );
464 static PyObject *C_Matrix_Rotation(PyObject *cls, PyObject *args)
465 {
466         PyObject *vec = NULL;
467         const char *axis = NULL;
468         int matSize;
469         double angle; /* use double because of precision problems at high values */
470         float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f,
471                              0.0f, 0.0f, 0.0f, 0.0f,
472                              0.0f, 0.0f, 0.0f, 0.0f,
473                              0.0f, 0.0f, 0.0f, 1.0f};
474
475         if (!PyArg_ParseTuple(args, "di|O:Matrix.Rotation", &angle, &matSize, &vec)) {
476                 return NULL;
477         }
478
479         if (vec && PyUnicode_Check(vec)) {
480                 axis = _PyUnicode_AsString((PyObject *)vec);
481                 if (axis == NULL || axis[0] == '\0' || axis[1] != '\0' || axis[0] < 'X' || axis[0] > 'Z') {
482                         PyErr_SetString(PyExc_ValueError,
483                                         "Matrix.Rotation(): "
484                                         "3rd argument axis value must be a 3D vector "
485                                         "or a string in 'X', 'Y', 'Z'");
486                         return NULL;
487                 }
488                 else {
489                         /* use the string */
490                         vec = NULL;
491                 }
492         }
493
494         angle = angle_wrap_rad(angle);
495
496         if (matSize != 2 && matSize != 3 && matSize != 4) {
497                 PyErr_SetString(PyExc_ValueError,
498                                 "Matrix.Rotation(): "
499                                 "can only return a 2x2 3x3 or 4x4 matrix");
500                 return NULL;
501         }
502         if (matSize == 2 && (vec != NULL)) {
503                 PyErr_SetString(PyExc_ValueError,
504                                 "Matrix.Rotation(): "
505                                 "cannot create a 2x2 rotation matrix around arbitrary axis");
506                 return NULL;
507         }
508         if ((matSize == 3 || matSize == 4) && (axis == NULL) && (vec == NULL)) {
509                 PyErr_SetString(PyExc_ValueError,
510                                 "Matrix.Rotation(): "
511                                 "axis of rotation for 3d and 4d matrices is required");
512                 return NULL;
513         }
514
515         /* check for valid vector/axis above */
516         if (vec) {
517                 float tvec[3];
518
519                 if (mathutils_array_parse(tvec, 3, 3, vec, "Matrix.Rotation(angle, size, axis), invalid 'axis' arg") == -1)
520                         return NULL;
521
522                 axis_angle_to_mat3((float (*)[3])mat, tvec, angle);
523         }
524         else if (matSize == 2) {
525                 angle_to_mat2((float (*)[2])mat, angle);
526
527         }
528         else {
529                 /* valid axis checked above */
530                 axis_angle_to_mat3_single((float (*)[3])mat, axis[0], angle);
531         }
532
533         if (matSize == 4) {
534                 matrix_3x3_as_4x4(mat);
535         }
536         /* pass to matrix creation */
537         return Matrix_CreatePyObject(mat, matSize, matSize, Py_NEW, (PyTypeObject *)cls);
538 }
539
540
541 PyDoc_STRVAR(C_Matrix_Translation_doc,
542 ".. classmethod:: Translation(vector)\n"
543 "\n"
544 "   Create a matrix representing a translation.\n"
545 "\n"
546 "   :arg vector: The translation vector.\n"
547 "   :type vector: :class:`Vector`\n"
548 "   :return: An identity matrix with a translation.\n"
549 "   :rtype: :class:`Matrix`\n"
550 );
551 static PyObject *C_Matrix_Translation(PyObject *cls, PyObject *value)
552 {
553         float mat[4][4] = MAT4_UNITY;
554
555         if (mathutils_array_parse(mat[3], 3, 4, value, "mathutils.Matrix.Translation(vector), invalid vector arg") == -1)
556                 return NULL;
557
558         return Matrix_CreatePyObject(&mat[0][0], 4, 4, Py_NEW, (PyTypeObject *)cls);
559 }
560 /* ----------------------------------mathutils.Matrix.Scale() ------------- */
561 /* mat is a 1D array of floats - row[0][0], row[0][1], row[1][0], etc. */
562 PyDoc_STRVAR(C_Matrix_Scale_doc,
563 ".. classmethod:: Scale(factor, size, axis)\n"
564 "\n"
565 "   Create a matrix representing a scaling.\n"
566 "\n"
567 "   :arg factor: The factor of scaling to apply.\n"
568 "   :type factor: float\n"
569 "   :arg size: The size of the scale matrix to construct [2, 4].\n"
570 "   :type size: int\n"
571 "   :arg axis: Direction to influence scale. (optional).\n"
572 "   :type axis: :class:`Vector`\n"
573 "   :return: A new scale matrix.\n"
574 "   :rtype: :class:`Matrix`\n"
575 );
576 static PyObject *C_Matrix_Scale(PyObject *cls, PyObject *args)
577 {
578         PyObject *vec = NULL;
579         int vec_size;
580         float tvec[3];
581         float factor;
582         int matSize;
583         float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f,
584                          0.0f, 0.0f, 0.0f, 0.0f,
585                          0.0f, 0.0f, 0.0f, 0.0f,
586                          0.0f, 0.0f, 0.0f, 1.0f};
587
588         if (!PyArg_ParseTuple(args, "fi|O:Matrix.Scale", &factor, &matSize, &vec)) {
589                 return NULL;
590         }
591         if (matSize != 2 && matSize != 3 && matSize != 4) {
592                 PyErr_SetString(PyExc_ValueError,
593                                 "Matrix.Scale(): "
594                                 "can only return a 2x2 3x3 or 4x4 matrix");
595                 return NULL;
596         }
597         if (vec) {
598                 vec_size = (matSize == 2 ? 2 : 3);
599                 if (mathutils_array_parse(tvec, vec_size, vec_size, vec,
600                                           "Matrix.Scale(factor, size, axis), invalid 'axis' arg") == -1)
601                 {
602                         return NULL;
603                 }
604         }
605         if (vec == NULL) {  /* scaling along axis */
606                 if (matSize == 2) {
607                         mat[0] = factor;
608                         mat[3] = factor;
609                 }
610                 else {
611                         mat[0] = factor;
612                         mat[4] = factor;
613                         mat[8] = factor;
614                 }
615         }
616         else {
617                 /* scaling in arbitrary direction
618                  * normalize arbitrary axis */
619                 float norm = 0.0f;
620                 int x;
621                 for (x = 0; x < vec_size; x++) {
622                         norm += tvec[x] * tvec[x];
623                 }
624                 norm = (float) sqrt(norm);
625                 for (x = 0; x < vec_size; x++) {
626                         tvec[x] /= norm;
627                 }
628                 if (matSize == 2) {
629                         mat[0] = 1 + ((factor - 1) * (tvec[0] * tvec[0]));
630                         mat[1] =     ((factor - 1) * (tvec[0] * tvec[1]));
631                         mat[2] =     ((factor - 1) * (tvec[0] * tvec[1]));
632                         mat[3] = 1 + ((factor - 1) * (tvec[1] * tvec[1]));
633                 }
634                 else {
635                         mat[0] = 1 + ((factor - 1) * (tvec[0] * tvec[0]));
636                         mat[1] =     ((factor - 1) * (tvec[0] * tvec[1]));
637                         mat[2] =     ((factor - 1) * (tvec[0] * tvec[2]));
638                         mat[3] =     ((factor - 1) * (tvec[0] * tvec[1]));
639                         mat[4] = 1 + ((factor - 1) * (tvec[1] * tvec[1]));
640                         mat[5] =     ((factor - 1) * (tvec[1] * tvec[2]));
641                         mat[6] =     ((factor - 1) * (tvec[0] * tvec[2]));
642                         mat[7] =     ((factor - 1) * (tvec[1] * tvec[2]));
643                         mat[8] = 1 + ((factor - 1) * (tvec[2] * tvec[2]));
644                 }
645         }
646         if (matSize == 4) {
647                 matrix_3x3_as_4x4(mat);
648         }
649         /* pass to matrix creation */
650         return Matrix_CreatePyObject(mat, matSize, matSize, Py_NEW, (PyTypeObject *)cls);
651 }
652 /* ----------------------------------mathutils.Matrix.OrthoProjection() --- */
653 /* mat is a 1D array of floats - row[0][0], row[0][1], row[1][0], etc. */
654 PyDoc_STRVAR(C_Matrix_OrthoProjection_doc,
655 ".. classmethod:: OrthoProjection(axis, size)\n"
656 "\n"
657 "   Create a matrix to represent an orthographic projection.\n"
658 "\n"
659 "   :arg axis: Can be any of the following: ['X', 'Y', 'XY', 'XZ', 'YZ'],\n"
660 "      where a single axis is for a 2D matrix.\n"
661 "      Or a vector for an arbitrary axis\n"
662 "   :type axis: string or :class:`Vector`\n"
663 "   :arg size: The size of the projection matrix to construct [2, 4].\n"
664 "   :type size: int\n"
665 "   :return: A new projection matrix.\n"
666 "   :rtype: :class:`Matrix`\n"
667 );
668 static PyObject *C_Matrix_OrthoProjection(PyObject *cls, PyObject *args)
669 {
670         PyObject *axis;
671
672         int matSize, x;
673         float norm = 0.0f;
674         float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f,
675                          0.0f, 0.0f, 0.0f, 0.0f,
676                          0.0f, 0.0f, 0.0f, 0.0f,
677                          0.0f, 0.0f, 0.0f, 1.0f};
678
679         if (!PyArg_ParseTuple(args, "Oi:Matrix.OrthoProjection", &axis, &matSize)) {
680                 return NULL;
681         }
682         if (matSize != 2 && matSize != 3 && matSize != 4) {
683                 PyErr_SetString(PyExc_ValueError,
684                                 "Matrix.OrthoProjection(): "
685                                 "can only return a 2x2 3x3 or 4x4 matrix");
686                 return NULL;
687         }
688
689         if (PyUnicode_Check(axis)) {  /* ortho projection onto cardinal plane */
690                 Py_ssize_t plane_len;
691                 const char *plane = _PyUnicode_AsStringAndSize(axis, &plane_len);
692                 if (matSize == 2) {
693                         if (plane_len == 1 && plane[0] == 'X') {
694                                 mat[0] = 1.0f;
695                         }
696                         else if (plane_len == 1 && plane[0] == 'Y') {
697                                 mat[3] = 1.0f;
698                         }
699                         else {
700                                 PyErr_Format(PyExc_ValueError,
701                                              "Matrix.OrthoProjection(): "
702                                              "unknown plane, expected: X, Y, not '%.200s'",
703                                              plane);
704                                 return NULL;
705                         }
706                 }
707                 else {
708                         if (plane_len == 2 && plane[0] == 'X' && plane[1] == 'Y') {
709                                 mat[0] = 1.0f;
710                                 mat[4] = 1.0f;
711                         }
712                         else if (plane_len == 2 && plane[0] == 'X' && plane[1] == 'Z') {
713                                 mat[0] = 1.0f;
714                                 mat[8] = 1.0f;
715                         }
716                         else if (plane_len == 2 && plane[0] == 'Y' && plane[1] == 'Z') {
717                                 mat[4] = 1.0f;
718                                 mat[8] = 1.0f;
719                         }
720                         else {
721                                 PyErr_Format(PyExc_ValueError,
722                                              "Matrix.OrthoProjection(): "
723                                              "unknown plane, expected: XY, XZ, YZ, not '%.200s'",
724                                              plane);
725                                 return NULL;
726                         }
727                 }
728         }
729         else {
730                 /* arbitrary plane */
731
732                 int vec_size = (matSize == 2 ? 2 : 3);
733                 float tvec[4];
734
735                 if (mathutils_array_parse(tvec, vec_size, vec_size, axis,
736                                           "Matrix.OrthoProjection(axis, size), invalid 'axis' arg") == -1)
737                 {
738                         return NULL;
739                 }
740
741                 /* normalize arbitrary axis */
742                 for (x = 0; x < vec_size; x++) {
743                         norm += tvec[x] * tvec[x];
744                 }
745                 norm = (float) sqrt(norm);
746                 for (x = 0; x < vec_size; x++) {
747                         tvec[x] /= norm;
748                 }
749                 if (matSize == 2) {
750                         mat[0] = 1 - (tvec[0] * tvec[0]);
751                         mat[1] =   - (tvec[0] * tvec[1]);
752                         mat[2] =   - (tvec[0] * tvec[1]);
753                         mat[3] = 1 - (tvec[1] * tvec[1]);
754                 }
755                 else if (matSize > 2) {
756                         mat[0] = 1 - (tvec[0] * tvec[0]);
757                         mat[1] =   - (tvec[0] * tvec[1]);
758                         mat[2] =   - (tvec[0] * tvec[2]);
759                         mat[3] =   - (tvec[0] * tvec[1]);
760                         mat[4] = 1 - (tvec[1] * tvec[1]);
761                         mat[5] =   - (tvec[1] * tvec[2]);
762                         mat[6] =   - (tvec[0] * tvec[2]);
763                         mat[7] =   - (tvec[1] * tvec[2]);
764                         mat[8] = 1 - (tvec[2] * tvec[2]);
765                 }
766         }
767         if (matSize == 4) {
768                 matrix_3x3_as_4x4(mat);
769         }
770         /* pass to matrix creation */
771         return Matrix_CreatePyObject(mat, matSize, matSize, Py_NEW, (PyTypeObject *)cls);
772 }
773
774 PyDoc_STRVAR(C_Matrix_Shear_doc,
775 ".. classmethod:: Shear(plane, size, factor)\n"
776 "\n"
777 "   Create a matrix to represent an shear transformation.\n"
778 "\n"
779 "   :arg plane: Can be any of the following: ['X', 'Y', 'XY', 'XZ', 'YZ'],\n"
780 "      where a single axis is for a 2D matrix only.\n"
781 "   :type plane: string\n"
782 "   :arg size: The size of the shear matrix to construct [2, 4].\n"
783 "   :type size: int\n"
784 "   :arg factor: The factor of shear to apply. For a 3 or 4 *size* matrix\n"
785 "      pass a pair of floats corresponding with the *plane* axis.\n"
786 "   :type factor: float or float pair\n"
787 "   :return: A new shear matrix.\n"
788 "   :rtype: :class:`Matrix`\n"
789 );
790 static PyObject *C_Matrix_Shear(PyObject *cls, PyObject *args)
791 {
792         int matSize;
793         const char *plane;
794         PyObject *fac;
795         float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f,
796                          0.0f, 0.0f, 0.0f, 0.0f,
797                          0.0f, 0.0f, 0.0f, 0.0f,
798                          0.0f, 0.0f, 0.0f, 1.0f};
799
800         if (!PyArg_ParseTuple(args, "siO:Matrix.Shear", &plane, &matSize, &fac)) {
801                 return NULL;
802         }
803         if (matSize != 2 && matSize != 3 && matSize != 4) {
804                 PyErr_SetString(PyExc_ValueError,
805                                 "Matrix.Shear(): "
806                                 "can only return a 2x2 3x3 or 4x4 matrix");
807                 return NULL;
808         }
809
810         if (matSize == 2) {
811                 float const factor = PyFloat_AsDouble(fac);
812
813                 if (factor == -1.0f && PyErr_Occurred()) {
814                         PyErr_SetString(PyExc_TypeError,
815                                         "Matrix.Shear(): "
816                                         "the factor to be a float");
817                         return NULL;
818                 }
819
820                 /* unit */
821                 mat[0] = 1.0f;
822                 mat[3] = 1.0f;
823
824                 if (STREQ(plane, "X")) {
825                         mat[2] = factor;
826                 }
827                 else if (STREQ(plane, "Y")) {
828                         mat[1] = factor;
829                 }
830                 else {
831                         PyErr_SetString(PyExc_ValueError,
832                                         "Matrix.Shear(): "
833                                         "expected: X, Y or wrong matrix size for shearing plane");
834                         return NULL;
835                 }
836         }
837         else {
838                 /* 3 or 4, apply as 3x3, resize later if needed */
839                 float factor[2];
840
841                 if (mathutils_array_parse(factor, 2, 2, fac, "Matrix.Shear()") < 0) {
842                         return NULL;
843                 }
844
845                 /* unit */
846                 mat[0] = 1.0f;
847                 mat[4] = 1.0f;
848                 mat[8] = 1.0f;
849
850                 if (STREQ(plane, "XY")) {
851                         mat[6] = factor[0];
852                         mat[7] = factor[1];
853                 }
854                 else if (STREQ(plane, "XZ")) {
855                         mat[3] = factor[0];
856                         mat[5] = factor[1];
857                 }
858                 else if (STREQ(plane, "YZ")) {
859                         mat[1] = factor[0];
860                         mat[2] = factor[1];
861                 }
862                 else {
863                         PyErr_SetString(PyExc_ValueError,
864                                         "Matrix.Shear(): "
865                                         "expected: X, Y, XY, XZ, YZ");
866                         return NULL;
867                 }
868         }
869
870         if (matSize == 4) {
871                 matrix_3x3_as_4x4(mat);
872         }
873         /* pass to matrix creation */
874         return Matrix_CreatePyObject(mat, matSize, matSize, Py_NEW, (PyTypeObject *)cls);
875 }
876
877 void matrix_as_3x3(float mat[3][3], MatrixObject *self)
878 {
879         copy_v3_v3(mat[0], MATRIX_COL_PTR(self, 0));
880         copy_v3_v3(mat[1], MATRIX_COL_PTR(self, 1));
881         copy_v3_v3(mat[2], MATRIX_COL_PTR(self, 2));
882 }
883
884 /* assumes rowsize == colsize is checked and the read callback has run */
885 static float matrix_determinant_internal(MatrixObject *self)
886 {
887         if (self->num_col == 2) {
888                 return determinant_m2(MATRIX_ITEM(self, 0, 0), MATRIX_ITEM(self, 0, 1),
889                                       MATRIX_ITEM(self, 1, 0), MATRIX_ITEM(self, 1, 1));
890         }
891         else if (self->num_col == 3) {
892                 return determinant_m3(MATRIX_ITEM(self, 0, 0), MATRIX_ITEM(self, 0, 1), MATRIX_ITEM(self, 0, 2),
893                                       MATRIX_ITEM(self, 1, 0), MATRIX_ITEM(self, 1, 1), MATRIX_ITEM(self, 1, 2),
894                                       MATRIX_ITEM(self, 2, 0), MATRIX_ITEM(self, 2, 1), MATRIX_ITEM(self, 2, 2));
895         }
896         else {
897                 return determinant_m4((float (*)[4])self->matrix);
898         }
899 }
900
901
902 /*-----------------------------METHODS----------------------------*/
903 PyDoc_STRVAR(Matrix_to_quaternion_doc,
904 ".. method:: to_quaternion()\n"
905 "\n"
906 "   Return a quaternion representation of the rotation matrix.\n"
907 "\n"
908 "   :return: Quaternion representation of the rotation matrix.\n"
909 "   :rtype: :class:`Quaternion`\n"
910 );
911 static PyObject *Matrix_to_quaternion(MatrixObject *self)
912 {
913         float quat[4];
914
915         if (BaseMath_ReadCallback(self) == -1)
916                 return NULL;
917
918         /* must be 3-4 cols, 3-4 rows, square matrix */
919         if ((self->num_row < 3) || (self->num_col < 3) || (self->num_row != self->num_col)) {
920                 PyErr_SetString(PyExc_ValueError,
921                                 "Matrix.to_quat(): "
922                                 "inappropriate matrix size - expects 3x3 or 4x4 matrix");
923                 return NULL;
924         }
925         if (self->num_row == 3) {
926                 mat3_to_quat(quat, (float (*)[3])self->matrix);
927         }
928         else {
929                 mat4_to_quat(quat, (float (*)[4])self->matrix);
930         }
931
932         return Quaternion_CreatePyObject(quat, Py_NEW, NULL);
933 }
934
935 /*---------------------------matrix.toEuler() --------------------*/
936 PyDoc_STRVAR(Matrix_to_euler_doc,
937 ".. method:: to_euler(order, euler_compat)\n"
938 "\n"
939 "   Return an Euler representation of the rotation matrix\n"
940 "   (3x3 or 4x4 matrix only).\n"
941 "\n"
942 "   :arg order: Optional rotation order argument in\n"
943 "      ['XYZ', 'XZY', 'YXZ', 'YZX', 'ZXY', 'ZYX'].\n"
944 "   :type order: string\n"
945 "   :arg euler_compat: Optional euler argument the new euler will be made\n"
946 "      compatible with (no axis flipping between them).\n"
947 "      Useful for converting a series of matrices to animation curves.\n"
948 "   :type euler_compat: :class:`Euler`\n"
949 "   :return: Euler representation of the matrix.\n"
950 "   :rtype: :class:`Euler`\n"
951 );
952 static PyObject *Matrix_to_euler(MatrixObject *self, PyObject *args)
953 {
954         const char *order_str = NULL;
955         short order = EULER_ORDER_XYZ;
956         float eul[3], eul_compatf[3];
957         EulerObject *eul_compat = NULL;
958
959         float tmat[3][3];
960         float (*mat)[3];
961
962         if (BaseMath_ReadCallback(self) == -1)
963                 return NULL;
964
965         if (!PyArg_ParseTuple(args, "|sO!:to_euler", &order_str, &euler_Type, &eul_compat))
966                 return NULL;
967
968         if (eul_compat) {
969                 if (BaseMath_ReadCallback(eul_compat) == -1)
970                         return NULL;
971
972                 copy_v3_v3(eul_compatf, eul_compat->eul);
973         }
974
975         /*must be 3-4 cols, 3-4 rows, square matrix */
976         if (self->num_row == 3 && self->num_col == 3) {
977                 mat = (float (*)[3])self->matrix;
978         }
979         else if (self->num_row == 4 && self->num_col == 4) {
980                 copy_m3_m4(tmat, (float (*)[4])self->matrix);
981                 mat = tmat;
982         }
983         else {
984                 PyErr_SetString(PyExc_ValueError,
985                                 "Matrix.to_euler(): "
986                                 "inappropriate matrix size - expects 3x3 or 4x4 matrix");
987                 return NULL;
988         }
989
990         if (order_str) {
991                 order = euler_order_from_string(order_str, "Matrix.to_euler()");
992
993                 if (order == -1)
994                         return NULL;
995         }
996
997         if (eul_compat) {
998                 if (order == 1) mat3_to_compatible_eul(eul, eul_compatf, mat);
999                 else            mat3_to_compatible_eulO(eul, eul_compatf, order, mat);
1000         }
1001         else {
1002                 if (order == 1) mat3_to_eul(eul, mat);
1003                 else mat3_to_eulO(eul, order, mat);
1004         }
1005
1006         return Euler_CreatePyObject(eul, order, Py_NEW, NULL);
1007 }
1008
1009 PyDoc_STRVAR(Matrix_resize_4x4_doc,
1010 ".. method:: resize_4x4()\n"
1011 "\n"
1012 "   Resize the matrix to 4x4.\n"
1013 );
1014 static PyObject *Matrix_resize_4x4(MatrixObject *self)
1015 {
1016         float mat[4][4] = MAT4_UNITY;
1017         int col;
1018
1019         if (self->wrapped == Py_WRAP) {
1020                 PyErr_SetString(PyExc_ValueError,
1021                                 "Matrix.resize_4x4(): "
1022                                 "cannot resize wrapped data - make a copy and resize that");
1023                 return NULL;
1024         }
1025         if (self->cb_user) {
1026                 PyErr_SetString(PyExc_ValueError,
1027                                 "Matrix.resize_4x4(): "
1028                                 "cannot resize owned data - make a copy and resize that");
1029                 return NULL;
1030         }
1031
1032         self->matrix = PyMem_Realloc(self->matrix, (sizeof(float) * 16));
1033         if (self->matrix == NULL) {
1034                 PyErr_SetString(PyExc_MemoryError,
1035                                 "Matrix.resize_4x4(): "
1036                                 "problem allocating pointer space");
1037                 return NULL;
1038         }
1039
1040         for (col = 0; col < self->num_col; col++) {
1041                 memcpy(mat[col], MATRIX_COL_PTR(self, col), self->num_row * sizeof(float));
1042         }
1043
1044         copy_m4_m4((float (*)[4])self->matrix, (float (*)[4])mat);
1045
1046         self->num_col = 4;
1047         self->num_row = 4;
1048
1049         Py_RETURN_NONE;
1050 }
1051
1052 PyDoc_STRVAR(Matrix_to_4x4_doc,
1053 ".. method:: to_4x4()\n"
1054 "\n"
1055 "   Return a 4x4 copy of this matrix.\n"
1056 "\n"
1057 "   :return: a new matrix.\n"
1058 "   :rtype: :class:`Matrix`\n"
1059 );
1060 static PyObject *Matrix_to_4x4(MatrixObject *self)
1061 {
1062         if (BaseMath_ReadCallback(self) == -1)
1063                 return NULL;
1064
1065         if (self->num_row == 4 && self->num_col == 4) {
1066                 return Matrix_CreatePyObject(self->matrix, 4, 4, Py_NEW, Py_TYPE(self));
1067         }
1068         else if (self->num_row == 3 && self->num_col == 3) {
1069                 float mat[4][4];
1070                 copy_m4_m3(mat, (float (*)[3])self->matrix);
1071                 return Matrix_CreatePyObject((float *)mat, 4, 4, Py_NEW, Py_TYPE(self));
1072         }
1073         /* TODO, 2x2 matrix */
1074
1075         PyErr_SetString(PyExc_ValueError,
1076                         "Matrix.to_4x4(): "
1077                         "inappropriate matrix size");
1078         return NULL;
1079 }
1080
1081 PyDoc_STRVAR(Matrix_to_3x3_doc,
1082 ".. method:: to_3x3()\n"
1083 "\n"
1084 "   Return a 3x3 copy of this matrix.\n"
1085 "\n"
1086 "   :return: a new matrix.\n"
1087 "   :rtype: :class:`Matrix`\n"
1088 );
1089 static PyObject *Matrix_to_3x3(MatrixObject *self)
1090 {
1091         float mat[3][3];
1092
1093         if (BaseMath_ReadCallback(self) == -1)
1094                 return NULL;
1095
1096         if ((self->num_row < 3) || (self->num_col < 3)) {
1097                 PyErr_SetString(PyExc_ValueError,
1098                                 "Matrix.to_3x3(): inappropriate matrix size");
1099                 return NULL;
1100         }
1101
1102         matrix_as_3x3(mat, self);
1103
1104         return Matrix_CreatePyObject((float *)mat, 3, 3, Py_NEW, Py_TYPE(self));
1105 }
1106
1107 PyDoc_STRVAR(Matrix_to_translation_doc,
1108 ".. method:: to_translation()\n"
1109 "\n"
1110 "   Return a the translation part of a 4 row matrix.\n"
1111 "\n"
1112 "   :return: Return a the translation of a matrix.\n"
1113 "   :rtype: :class:`Vector`\n"
1114 );
1115 static PyObject *Matrix_to_translation(MatrixObject *self)
1116 {
1117         if (BaseMath_ReadCallback(self) == -1)
1118                 return NULL;
1119
1120         if ((self->num_row < 3) || self->num_col < 4) {
1121                 PyErr_SetString(PyExc_ValueError,
1122                                 "Matrix.to_translation(): "
1123                                 "inappropriate matrix size");
1124                 return NULL;
1125         }
1126
1127         return Vector_CreatePyObject(MATRIX_COL_PTR(self, 3), 3, Py_NEW, NULL);
1128 }
1129
1130 PyDoc_STRVAR(Matrix_to_scale_doc,
1131 ".. method:: to_scale()\n"
1132 "\n"
1133 "   Return a the scale part of a 3x3 or 4x4 matrix.\n"
1134 "\n"
1135 "   :return: Return a the scale of a matrix.\n"
1136 "   :rtype: :class:`Vector`\n"
1137 "\n"
1138 "   .. note:: This method does not return negative a scale on any axis because it is not possible to obtain this data from the matrix alone.\n"
1139 );
1140 static PyObject *Matrix_to_scale(MatrixObject *self)
1141 {
1142         float rot[3][3];
1143         float mat[3][3];
1144         float size[3];
1145
1146         if (BaseMath_ReadCallback(self) == -1)
1147                 return NULL;
1148
1149         /*must be 3-4 cols, 3-4 rows, square matrix */
1150         if ((self->num_row < 3) || (self->num_col < 3)) {
1151                 PyErr_SetString(PyExc_ValueError,
1152                                 "Matrix.to_scale(): "
1153                                 "inappropriate matrix size, 3x3 minimum size");
1154                 return NULL;
1155         }
1156
1157         matrix_as_3x3(mat, self);
1158
1159         /* compatible mat4_to_loc_rot_size */
1160         mat3_to_rot_size(rot, size, mat);
1161
1162         return Vector_CreatePyObject(size, 3, Py_NEW, NULL);
1163 }
1164
1165 /*---------------------------matrix.invert() ---------------------*/
1166 PyDoc_STRVAR(Matrix_invert_doc,
1167 ".. method:: invert()\n"
1168 "\n"
1169 "   Set the matrix to its inverse.\n"
1170 "\n"
1171 "   .. note:: When the matrix cant be inverted a :exc:`ValueError` exception is raised.\n"
1172 "\n"
1173 "   .. seealso:: <http://en.wikipedia.org/wiki/Inverse_matrix>\n"
1174 );
1175 static PyObject *Matrix_invert(MatrixObject *self)
1176 {
1177
1178         int x, y, z = 0;
1179         float det = 0.0f;
1180         float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f,
1181                          0.0f, 0.0f, 0.0f, 0.0f,
1182                          0.0f, 0.0f, 0.0f, 0.0f,
1183                          0.0f, 0.0f, 0.0f, 1.0f};
1184
1185         if (BaseMath_ReadCallback(self) == -1)
1186                 return NULL;
1187
1188         if (self->num_col != self->num_row) {
1189                 PyErr_SetString(PyExc_ValueError,
1190                                 "Matrix.invert(ed): "
1191                                 "only square matrices are supported");
1192                 return NULL;
1193         }
1194
1195         /* calculate the determinant */
1196         det = matrix_determinant_internal(self);
1197
1198         if (det != 0) {
1199                 /* calculate the classical adjoint */
1200                 switch (self->num_col) {
1201                         case 2:
1202                         {
1203                                 adjoint_m2_m2((float (*)[2])mat, (float (*)[2])self->matrix);
1204                                 break;
1205                         }
1206                         case 3:
1207                         {
1208                                 adjoint_m3_m3((float (*)[3])mat, (float (*)[3])self->matrix);
1209                                 break;
1210                         }
1211                         case 4:
1212                         {
1213                                 adjoint_m4_m4((float (*)[4])mat, (float (*)[4])self->matrix);
1214                                 break;
1215                         }
1216                         default:
1217                                 PyErr_Format(PyExc_ValueError,
1218                                              "Matrix invert(ed): size (%d) unsupported",
1219                                              (int)self->num_col);
1220                                 return NULL;
1221                 }
1222                 /* divide by determinate */
1223                 for (x = 0; x < (self->num_col * self->num_row); x++) {
1224                         mat[x] /= det;
1225                 }
1226                 /* set values */
1227                 for (x = 0; x < self->num_col; x++) {
1228                         for (y = 0; y < self->num_row; y++) {
1229                                 MATRIX_ITEM(self, y, x) = mat[z];
1230                                 z++;
1231                         }
1232                 }
1233         }
1234         else {
1235                 PyErr_SetString(PyExc_ValueError,
1236                                 "Matrix.invert(ed): "
1237                                 "matrix does not have an inverse");
1238                 return NULL;
1239         }
1240
1241         (void)BaseMath_WriteCallback(self);
1242         Py_RETURN_NONE;
1243 }
1244
1245 PyDoc_STRVAR(Matrix_inverted_doc,
1246 ".. method:: inverted()\n"
1247 "\n"
1248 "   Return an inverted copy of the matrix.\n"
1249 "\n"
1250 "   :return: the inverted matrix.\n"
1251 "   :rtype: :class:`Matrix`\n"
1252 "\n"
1253 "   .. note:: When the matrix cant be inverted a :exc:`ValueError` exception is raised.\n"
1254 );
1255 static PyObject *Matrix_inverted(MatrixObject *self)
1256 {
1257         return matrix__apply_to_copy((PyNoArgsFunction)Matrix_invert, self);
1258 }
1259
1260 /*---------------------------matrix.adjugate() ---------------------*/
1261 PyDoc_STRVAR(Matrix_adjugate_doc,
1262 ".. method:: adjugate()\n"
1263 "\n"
1264 "   Set the matrix to its adjugate.\n"
1265 "\n"
1266 "   .. note:: When the matrix cant be adjugated a :exc:`ValueError` exception is raised.\n"
1267 "\n"
1268 "   .. seealso:: <http://en.wikipedia.org/wiki/Adjugate_matrix>\n"
1269 );
1270 static PyObject *Matrix_adjugate(MatrixObject *self)
1271 {
1272         if (BaseMath_ReadCallback(self) == -1)
1273                 return NULL;
1274
1275         if (self->num_col != self->num_row) {
1276                 PyErr_SetString(PyExc_ValueError,
1277                                 "Matrix.adjugate(d): "
1278                                 "only square matrices are supported");
1279                 return NULL;
1280         }
1281
1282         /* calculate the classical adjoint */
1283         switch (self->num_col) {
1284                 case 2:
1285                 {
1286                         float mat[2][2];
1287                         adjoint_m2_m2(mat, (float (*)[2])self->matrix);
1288                         copy_v4_v4((float *)self->matrix, (float *)mat);
1289                         break;
1290                 }
1291                 case 3:
1292                 {
1293                         float mat[3][3];
1294                         adjoint_m3_m3(mat, (float (*)[3])self->matrix);
1295                         copy_m3_m3((float (*)[3])self->matrix, mat);
1296                         break;
1297                 }
1298                 case 4:
1299                 {
1300                         float mat[4][4];
1301                         adjoint_m4_m4(mat, (float (*)[4])self->matrix);
1302                         copy_m4_m4((float (*)[4])self->matrix, mat);
1303                         break;
1304                 }
1305                 default:
1306                         PyErr_Format(PyExc_ValueError,
1307                                      "Matrix adjugate(d): size (%d) unsupported",
1308                                      (int)self->num_col);
1309                         return NULL;
1310         }
1311
1312         (void)BaseMath_WriteCallback(self);
1313         Py_RETURN_NONE;
1314 }
1315
1316 PyDoc_STRVAR(Matrix_adjugated_doc,
1317 ".. method:: adjugated()\n"
1318 "\n"
1319 "   Return an adjugated copy of the matrix.\n"
1320 "\n"
1321 "   :return: the adjugated matrix.\n"
1322 "   :rtype: :class:`Matrix`\n"
1323 "\n"
1324 "   .. note:: When the matrix cant be adjugated a :exc:`ValueError` exception is raised.\n"
1325 );
1326 static PyObject *Matrix_adjugated(MatrixObject *self)
1327 {
1328         return matrix__apply_to_copy((PyNoArgsFunction)Matrix_adjugate, self);
1329 }
1330
1331 PyDoc_STRVAR(Matrix_rotate_doc,
1332 ".. method:: rotate(other)\n"
1333 "\n"
1334 "   Rotates the matrix a by another mathutils value.\n"
1335 "\n"
1336 "   :arg other: rotation component of mathutils value\n"
1337 "   :type other: :class:`Euler`, :class:`Quaternion` or :class:`Matrix`\n"
1338 "\n"
1339 "   .. note:: If any of the columns are not unit length this may not have desired results.\n"
1340 );
1341 static PyObject *Matrix_rotate(MatrixObject *self, PyObject *value)
1342 {
1343         float self_rmat[3][3], other_rmat[3][3], rmat[3][3];
1344
1345         if (BaseMath_ReadCallback(self) == -1)
1346                 return NULL;
1347
1348         if (mathutils_any_to_rotmat(other_rmat, value, "matrix.rotate(value)") == -1)
1349                 return NULL;
1350
1351         if (self->num_row != 3 || self->num_col != 3) {
1352                 PyErr_SetString(PyExc_ValueError,
1353                                 "Matrix.rotate(): "
1354                                 "must have 3x3 dimensions");
1355                 return NULL;
1356         }
1357
1358         matrix_as_3x3(self_rmat, self);
1359         mul_m3_m3m3(rmat, other_rmat, self_rmat);
1360
1361         copy_m3_m3((float (*)[3])(self->matrix), rmat);
1362
1363         (void)BaseMath_WriteCallback(self);
1364         Py_RETURN_NONE;
1365 }
1366
1367 /*---------------------------matrix.decompose() ---------------------*/
1368 PyDoc_STRVAR(Matrix_decompose_doc,
1369 ".. method:: decompose()\n"
1370 "\n"
1371 "   Return the location, rotaion and scale components of this matrix.\n"
1372 "\n"
1373 "   :return: loc, rot, scale triple.\n"
1374 "   :rtype: (:class:`Vector`, :class:`Quaternion`, :class:`Vector`)"
1375 );
1376 static PyObject *Matrix_decompose(MatrixObject *self)
1377 {
1378         PyObject *ret;
1379         float loc[3];
1380         float rot[3][3];
1381         float quat[4];
1382         float size[3];
1383
1384         if (self->num_row != 4 || self->num_col != 4) {
1385                 PyErr_SetString(PyExc_ValueError,
1386                                 "Matrix.decompose(): "
1387                                 "inappropriate matrix size - expects 4x4 matrix");
1388                 return NULL;
1389         }
1390
1391         if (BaseMath_ReadCallback(self) == -1)
1392                 return NULL;
1393
1394         mat4_to_loc_rot_size(loc, rot, size, (float (*)[4])self->matrix);
1395         mat3_to_quat(quat, rot);
1396
1397         ret = PyTuple_New(3);
1398         PyTuple_SET_ITEM(ret, 0, Vector_CreatePyObject(loc, 3, Py_NEW, NULL));
1399         PyTuple_SET_ITEM(ret, 1, Quaternion_CreatePyObject(quat, Py_NEW, NULL));
1400         PyTuple_SET_ITEM(ret, 2, Vector_CreatePyObject(size, 3, Py_NEW, NULL));
1401
1402         return ret;
1403 }
1404
1405
1406
1407 PyDoc_STRVAR(Matrix_lerp_doc,
1408 ".. function:: lerp(other, factor)\n"
1409 "\n"
1410 "   Returns the interpolation of two matrices.\n"
1411 "\n"
1412 "   :arg other: value to interpolate with.\n"
1413 "   :type other: :class:`Matrix`\n"
1414 "   :arg factor: The interpolation value in [0.0, 1.0].\n"
1415 "   :type factor: float\n"
1416 "   :return: The interpolated rotation.\n"
1417 "   :rtype: :class:`Matrix`\n"
1418 );
1419 static PyObject *Matrix_lerp(MatrixObject *self, PyObject *args)
1420 {
1421         MatrixObject *mat2 = NULL;
1422         float fac, mat[MATRIX_MAX_DIM * MATRIX_MAX_DIM];
1423
1424         if (!PyArg_ParseTuple(args, "O!f:lerp", &matrix_Type, &mat2, &fac))
1425                 return NULL;
1426
1427         if (self->num_col != mat2->num_col || self->num_row != mat2->num_row) {
1428                 PyErr_SetString(PyExc_ValueError,
1429                                 "Matrix.lerp(): "
1430                                 "expects both matrix objects of the same dimensions");
1431                 return NULL;
1432         }
1433
1434         if (BaseMath_ReadCallback(self) == -1 || BaseMath_ReadCallback(mat2) == -1)
1435                 return NULL;
1436
1437         /* TODO, different sized matrix */
1438         if (self->num_col == 4 && self->num_row == 4) {
1439                 blend_m4_m4m4((float (*)[4])mat, (float (*)[4])self->matrix, (float (*)[4])mat2->matrix, fac);
1440         }
1441         else if (self->num_col == 3 && self->num_row == 3) {
1442                 blend_m3_m3m3((float (*)[3])mat, (float (*)[3])self->matrix, (float (*)[3])mat2->matrix, fac);
1443         }
1444         else {
1445                 PyErr_SetString(PyExc_ValueError,
1446                                 "Matrix.lerp(): "
1447                                 "only 3x3 and 4x4 matrices supported");
1448                 return NULL;
1449         }
1450
1451         return Matrix_CreatePyObject(mat, self->num_col, self->num_row, Py_NEW, Py_TYPE(self));
1452 }
1453
1454 /*---------------------------matrix.determinant() ----------------*/
1455 PyDoc_STRVAR(Matrix_determinant_doc,
1456 ".. method:: determinant()\n"
1457 "\n"
1458 "   Return the determinant of a matrix.\n"
1459 "\n"
1460 "   :return: Return a the determinant of a matrix.\n"
1461 "   :rtype: float\n"
1462 "\n"
1463 "   .. seealso:: <http://en.wikipedia.org/wiki/Determinant>\n"
1464 );
1465 static PyObject *Matrix_determinant(MatrixObject *self)
1466 {
1467         if (BaseMath_ReadCallback(self) == -1)
1468                 return NULL;
1469
1470         if (self->num_col != self->num_row) {
1471                 PyErr_SetString(PyExc_ValueError,
1472                                 "Matrix.determinant(): "
1473                                 "only square matrices are supported");
1474                 return NULL;
1475         }
1476
1477         return PyFloat_FromDouble((double)matrix_determinant_internal(self));
1478 }
1479 /*---------------------------matrix.transpose() ------------------*/
1480 PyDoc_STRVAR(Matrix_transpose_doc,
1481 ".. method:: transpose()\n"
1482 "\n"
1483 "   Set the matrix to its transpose.\n"
1484 "\n"
1485 "   .. seealso:: <http://en.wikipedia.org/wiki/Transpose>\n"
1486 );
1487 static PyObject *Matrix_transpose(MatrixObject *self)
1488 {
1489         if (BaseMath_ReadCallback(self) == -1)
1490                 return NULL;
1491
1492         if (self->num_col != self->num_row) {
1493                 PyErr_SetString(PyExc_ValueError,
1494                                 "Matrix.transpose(d): "
1495                                 "only square matrices are supported");
1496                 return NULL;
1497         }
1498
1499         if (self->num_col == 2) {
1500                 const float t = MATRIX_ITEM(self, 1, 0);
1501                 MATRIX_ITEM(self, 1, 0) = MATRIX_ITEM(self, 0, 1);
1502                 MATRIX_ITEM(self, 0, 1) = t;
1503         }
1504         else if (self->num_col == 3) {
1505                 transpose_m3((float (*)[3])self->matrix);
1506         }
1507         else {
1508                 transpose_m4((float (*)[4])self->matrix);
1509         }
1510
1511         (void)BaseMath_WriteCallback(self);
1512         Py_RETURN_NONE;
1513 }
1514
1515 PyDoc_STRVAR(Matrix_transposed_doc,
1516 ".. method:: transposed()\n"
1517 "\n"
1518 "   Return a new, transposed matrix.\n"
1519 "\n"
1520 "   :return: a transposed matrix\n"
1521 "   :rtype: :class:`Matrix`\n"
1522 );
1523 static PyObject *Matrix_transposed(MatrixObject *self)
1524 {
1525         return matrix__apply_to_copy((PyNoArgsFunction)Matrix_transpose, self);
1526 }
1527
1528 /*---------------------------matrix.normalize() ------------------*/
1529 PyDoc_STRVAR(Matrix_normalize_doc,
1530 ".. method:: normalize()\n"
1531 "\n"
1532 "   Normalize each of the matrix columns.\n"
1533 );
1534 static PyObject *Matrix_normalize(MatrixObject *self)
1535 {
1536         if (BaseMath_ReadCallback(self) == -1)
1537                 return NULL;
1538
1539         if (self->num_col != self->num_row) {
1540                 PyErr_SetString(PyExc_ValueError,
1541                                 "Matrix.normalize(): "
1542                                 "only square matrices are supported");
1543                 return NULL;
1544         }
1545
1546         if (self->num_col == 3) {
1547                 normalize_m3((float (*)[3])self->matrix);
1548         }
1549         else if (self->num_col == 4) {
1550                 normalize_m4((float (*)[4])self->matrix);
1551         }
1552         else {
1553                 PyErr_SetString(PyExc_ValueError,
1554                                 "Matrix.normalize(): "
1555                                 "can only use a 3x3 or 4x4 matrix");
1556         }
1557
1558         (void)BaseMath_WriteCallback(self);
1559         Py_RETURN_NONE;
1560 }
1561
1562 PyDoc_STRVAR(Matrix_normalized_doc,
1563 ".. method:: normalized()\n"
1564 "\n"
1565 "   Return a column normalized matrix\n"
1566 "\n"
1567 "   :return: a column normalized matrix\n"
1568 "   :rtype: :class:`Matrix`\n"
1569 );
1570 static PyObject *Matrix_normalized(MatrixObject *self)
1571 {
1572         return matrix__apply_to_copy((PyNoArgsFunction)Matrix_normalize, self);
1573 }
1574
1575 /*---------------------------matrix.zero() -----------------------*/
1576 PyDoc_STRVAR(Matrix_zero_doc,
1577 ".. method:: zero()\n"
1578 "\n"
1579 "   Set all the matrix values to zero.\n"
1580 "\n"
1581 "   :return: an instance of itself\n"
1582 "   :rtype: :class:`Matrix`\n"
1583 );
1584 static PyObject *Matrix_zero(MatrixObject *self)
1585 {
1586         fill_vn_fl(self->matrix, self->num_col * self->num_row, 0.0f);
1587
1588         if (BaseMath_WriteCallback(self) == -1)
1589                 return NULL;
1590
1591         Py_RETURN_NONE;
1592 }
1593 /*---------------------------matrix.identity(() ------------------*/
1594 PyDoc_STRVAR(Matrix_identity_doc,
1595 ".. method:: identity()\n"
1596 "\n"
1597 "   Set the matrix to the identity matrix.\n"
1598 "\n"
1599 "   .. note:: An object with zero location and rotation, a scale of one,\n"
1600 "      will have an identity matrix.\n"
1601 "\n"
1602 "   .. seealso:: <http://en.wikipedia.org/wiki/Identity_matrix>\n"
1603 );
1604 static PyObject *Matrix_identity(MatrixObject *self)
1605 {
1606         if (BaseMath_ReadCallback(self) == -1)
1607                 return NULL;
1608
1609         if (self->num_col != self->num_row) {
1610                 PyErr_SetString(PyExc_ValueError,
1611                                 "Matrix.identity(): "
1612                                 "only square matrices are supported");
1613                 return NULL;
1614         }
1615
1616         if (self->num_col == 2) {
1617                 MATRIX_ITEM(self, 0, 0) = 1.0f;
1618                 MATRIX_ITEM(self, 0, 1) = 0.0f;
1619                 MATRIX_ITEM(self, 1, 0) = 0.0f;
1620                 MATRIX_ITEM(self, 1, 1) = 1.0f;
1621         }
1622         else if (self->num_col == 3) {
1623                 unit_m3((float (*)[3])self->matrix);
1624         }
1625         else {
1626                 unit_m4((float (*)[4])self->matrix);
1627         }
1628
1629         if (BaseMath_WriteCallback(self) == -1)
1630                 return NULL;
1631
1632         Py_RETURN_NONE;
1633 }
1634
1635 /*---------------------------Matrix.copy() ------------------*/
1636 PyDoc_STRVAR(Matrix_copy_doc,
1637 ".. method:: copy()\n"
1638 "\n"
1639 "   Returns a copy of this matrix.\n"
1640 "\n"
1641 "   :return: an instance of itself\n"
1642 "   :rtype: :class:`Matrix`\n"
1643 );
1644 static PyObject *Matrix_copy(MatrixObject *self)
1645 {
1646         if (BaseMath_ReadCallback(self) == -1)
1647                 return NULL;
1648
1649         return Matrix_CreatePyObject((float (*))self->matrix, self->num_col, self->num_row, Py_NEW, Py_TYPE(self));
1650 }
1651 static PyObject *Matrix_deepcopy(MatrixObject *self, PyObject *args)
1652 {
1653         if (!mathutils_deepcopy_args_check(args))
1654                 return NULL;
1655         return Matrix_copy(self);
1656 }
1657
1658 /*----------------------------print object (internal)-------------*/
1659 /* print the object to screen */
1660 static PyObject *Matrix_repr(MatrixObject *self)
1661 {
1662         int col, row;
1663         PyObject *rows[MATRIX_MAX_DIM] = {NULL};
1664
1665         if (BaseMath_ReadCallback(self) == -1)
1666                 return NULL;
1667
1668         for (row = 0; row < self->num_row; row++) {
1669                 rows[row] = PyTuple_New(self->num_col);
1670                 for (col = 0; col < self->num_col; col++) {
1671                         PyTuple_SET_ITEM(rows[row], col, PyFloat_FromDouble(MATRIX_ITEM(self, row, col)));
1672                 }
1673         }
1674         switch (self->num_row) {
1675                 case 2: return PyUnicode_FromFormat("Matrix((%R,\n"
1676                                                     "        %R))", rows[0], rows[1]);
1677
1678                 case 3: return PyUnicode_FromFormat("Matrix((%R,\n"
1679                                                     "        %R,\n"
1680                                                     "        %R))", rows[0], rows[1], rows[2]);
1681
1682                 case 4: return PyUnicode_FromFormat("Matrix((%R,\n"
1683                                                     "        %R,\n"
1684                                                     "        %R,\n"
1685                                                     "        %R))", rows[0], rows[1], rows[2], rows[3]);
1686         }
1687
1688         Py_FatalError("Matrix(): invalid row size!");
1689         return NULL;
1690 }
1691
1692 #ifndef MATH_STANDALONE
1693 static PyObject *Matrix_str(MatrixObject *self)
1694 {
1695         DynStr *ds;
1696
1697         int maxsize[MATRIX_MAX_DIM];
1698         int row, col;
1699
1700         char dummy_buf[64];
1701
1702         if (BaseMath_ReadCallback(self) == -1)
1703                 return NULL;
1704
1705         ds = BLI_dynstr_new();
1706
1707         /* First determine the maximum width for each column */
1708         for (col = 0; col < self->num_col; col++) {
1709                 maxsize[col] = 0;
1710                 for (row = 0; row < self->num_row; row++) {
1711                         int size = BLI_snprintf(dummy_buf, sizeof(dummy_buf), "%.4f", MATRIX_ITEM(self, row, col));
1712                         maxsize[col] = max_ii(maxsize[col], size);
1713                 }
1714         }
1715
1716         /* Now write the unicode string to be printed */
1717         BLI_dynstr_appendf(ds, "<Matrix %dx%d (", self->num_row, self->num_col);
1718         for (row = 0; row < self->num_row; row++) {
1719                 for (col = 0; col < self->num_col; col++) {
1720                         BLI_dynstr_appendf(ds, col ? ", %*.4f" : "%*.4f", maxsize[col], MATRIX_ITEM(self, row, col));
1721                 }
1722                 BLI_dynstr_append(ds, row + 1 != self->num_row ? ")\n            (" : ")");
1723         }
1724         BLI_dynstr_append(ds, ">");
1725
1726         return mathutils_dynstr_to_py(ds); /* frees ds */
1727 }
1728 #endif
1729
1730 static PyObject *Matrix_richcmpr(PyObject *a, PyObject *b, int op)
1731 {
1732         PyObject *res;
1733         int ok = -1; /* zero is true */
1734
1735         if (MatrixObject_Check(a) && MatrixObject_Check(b)) {
1736                 MatrixObject *matA = (MatrixObject *)a;
1737                 MatrixObject *matB = (MatrixObject *)b;
1738
1739                 if (BaseMath_ReadCallback(matA) == -1 || BaseMath_ReadCallback(matB) == -1)
1740                         return NULL;
1741
1742                 ok = ((matA->num_row == matB->num_row) &&
1743                       (matA->num_col == matB->num_col) &&
1744                       EXPP_VectorsAreEqual(matA->matrix, matB->matrix, (matA->num_col * matA->num_row), 1)
1745                       ) ? 0 : -1;
1746         }
1747
1748         switch (op) {
1749                 case Py_NE:
1750                         ok = !ok;
1751                         /* fall-through */
1752                 case Py_EQ:
1753                         res = ok ? Py_False : Py_True;
1754                         break;
1755
1756                 case Py_LT:
1757                 case Py_LE:
1758                 case Py_GT:
1759                 case Py_GE:
1760                         res = Py_NotImplemented;
1761                         break;
1762                 default:
1763                         PyErr_BadArgument();
1764                         return NULL;
1765         }
1766
1767         return Py_INCREF(res), res;
1768 }
1769
1770 /*---------------------SEQUENCE PROTOCOLS------------------------
1771  * ----------------------------len(object)------------------------
1772  * sequence length */
1773 static int Matrix_len(MatrixObject *self)
1774 {
1775         return self->num_row;
1776 }
1777 /*----------------------------object[]---------------------------
1778  * sequence accessor (get)
1779  * the wrapped vector gives direct access to the matrix data */
1780 static PyObject *Matrix_item_row(MatrixObject *self, int row)
1781 {
1782         if (BaseMath_ReadCallback(self) == -1)
1783                 return NULL;
1784
1785         if (row < 0 || row >= self->num_row) {
1786                 PyErr_SetString(PyExc_IndexError,
1787                                 "matrix[attribute]: "
1788                                 "array index out of range");
1789                 return NULL;
1790         }
1791         return Vector_CreatePyObject_cb((PyObject *)self, self->num_col, mathutils_matrix_row_cb_index, row);
1792 }
1793 /* same but column access */
1794 static PyObject *Matrix_item_col(MatrixObject *self, int col)
1795 {
1796         if (BaseMath_ReadCallback(self) == -1)
1797                 return NULL;
1798
1799         if (col < 0 || col >= self->num_col) {
1800                 PyErr_SetString(PyExc_IndexError,
1801                                 "matrix[attribute]: "
1802                                 "array index out of range");
1803                 return NULL;
1804         }
1805         return Vector_CreatePyObject_cb((PyObject *)self, self->num_row, mathutils_matrix_col_cb_index, col);
1806 }
1807
1808 /*----------------------------object[]-------------------------
1809  * sequence accessor (set) */
1810
1811 static int Matrix_ass_item_row(MatrixObject *self, int row, PyObject *value)
1812 {
1813         int col;
1814         float vec[4];
1815         if (BaseMath_ReadCallback(self) == -1)
1816                 return -1;
1817
1818         if (row >= self->num_row || row < 0) {
1819                 PyErr_SetString(PyExc_IndexError,
1820                                 "matrix[attribute] = x: bad row");
1821                 return -1;
1822         }
1823
1824         if (mathutils_array_parse(vec, self->num_col, self->num_col, value, "matrix[i] = value assignment") < 0) {
1825                 return -1;
1826         }
1827
1828         /* Since we are assigning a row we cannot memcpy */
1829         for (col = 0; col < self->num_col; col++) {
1830                 MATRIX_ITEM(self, row, col) = vec[col];
1831         }
1832
1833         (void)BaseMath_WriteCallback(self);
1834         return 0;
1835 }
1836 static int Matrix_ass_item_col(MatrixObject *self, int col, PyObject *value)
1837 {
1838         int row;
1839         float vec[4];
1840         if (BaseMath_ReadCallback(self) == -1)
1841                 return -1;
1842
1843         if (col >= self->num_col || col < 0) {
1844                 PyErr_SetString(PyExc_IndexError,
1845                                 "matrix[attribute] = x: bad col");
1846                 return -1;
1847         }
1848
1849         if (mathutils_array_parse(vec, self->num_row, self->num_row, value, "matrix[i] = value assignment") < 0) {
1850                 return -1;
1851         }
1852
1853         /* Since we are assigning a row we cannot memcpy */
1854         for (row = 0; row < self->num_row; row++) {
1855                 MATRIX_ITEM(self, row, col) = vec[row];
1856         }
1857
1858         (void)BaseMath_WriteCallback(self);
1859         return 0;
1860 }
1861
1862
1863 /*----------------------------object[z:y]------------------------
1864  * sequence slice (get)*/
1865 static PyObject *Matrix_slice(MatrixObject *self, int begin, int end)
1866 {
1867
1868         PyObject *tuple;
1869         int count;
1870
1871         if (BaseMath_ReadCallback(self) == -1)
1872                 return NULL;
1873
1874         CLAMP(begin, 0, self->num_row);
1875         CLAMP(end, 0, self->num_row);
1876         begin = MIN2(begin, end);
1877
1878         tuple = PyTuple_New(end - begin);
1879         for (count = begin; count < end; count++) {
1880                 PyTuple_SET_ITEM(tuple, count - begin,
1881                                  Vector_CreatePyObject_cb((PyObject *)self, self->num_col, mathutils_matrix_row_cb_index, count));
1882         }
1883
1884         return tuple;
1885 }
1886 /*----------------------------object[z:y]------------------------
1887  * sequence slice (set)*/
1888 static int Matrix_ass_slice(MatrixObject *self, int begin, int end, PyObject *value)
1889 {
1890         PyObject *value_fast = NULL;
1891
1892         if (BaseMath_ReadCallback(self) == -1)
1893                 return -1;
1894
1895         CLAMP(begin, 0, self->num_row);
1896         CLAMP(end, 0, self->num_row);
1897         begin = MIN2(begin, end);
1898
1899         /* non list/tuple cases */
1900         if (!(value_fast = PySequence_Fast(value, "matrix[begin:end] = value"))) {
1901                 /* PySequence_Fast sets the error */
1902                 return -1;
1903         }
1904         else {
1905                 const int size = end - begin;
1906                 int row, col;
1907                 float mat[16];
1908                 float vec[4];
1909
1910                 if (PySequence_Fast_GET_SIZE(value_fast) != size) {
1911                         Py_DECREF(value_fast);
1912                         PyErr_SetString(PyExc_ValueError,
1913                                         "matrix[begin:end] = []: "
1914                                         "size mismatch in slice assignment");
1915                         return -1;
1916                 }
1917
1918                 memcpy(mat, self->matrix, self->num_col * self->num_row * sizeof(float));
1919
1920                 /* parse sub items */
1921                 for (row = begin; row < end; row++) {
1922                         /* parse each sub sequence */
1923                         PyObject *item = PySequence_Fast_GET_ITEM(value_fast, row - begin);
1924
1925                         if (mathutils_array_parse(vec, self->num_col, self->num_col, item,
1926                                                   "matrix[begin:end] = value assignment") < 0)
1927                         {
1928                                 return -1;
1929                         }
1930
1931                         for (col = 0; col < self->num_col; col++) {
1932                                 mat[col * self->num_row + row] = vec[col];
1933                         }
1934                 }
1935
1936                 Py_DECREF(value_fast);
1937
1938                 /*parsed well - now set in matrix*/
1939                 memcpy(self->matrix, mat, self->num_col * self->num_row * sizeof(float));
1940
1941                 (void)BaseMath_WriteCallback(self);
1942                 return 0;
1943         }
1944 }
1945 /*------------------------NUMERIC PROTOCOLS----------------------
1946  *------------------------obj + obj------------------------------*/
1947 static PyObject *Matrix_add(PyObject *m1, PyObject *m2)
1948 {
1949         float mat[16];
1950         MatrixObject *mat1 = NULL, *mat2 = NULL;
1951
1952         mat1 = (MatrixObject *)m1;
1953         mat2 = (MatrixObject *)m2;
1954
1955         if (!MatrixObject_Check(m1) || !MatrixObject_Check(m2)) {
1956                 PyErr_Format(PyExc_TypeError,
1957                              "Matrix addition: (%s + %s) "
1958                              "invalid type for this operation",
1959                              Py_TYPE(m1)->tp_name, Py_TYPE(m2)->tp_name);
1960                 return NULL;
1961         }
1962
1963         if (BaseMath_ReadCallback(mat1) == -1 || BaseMath_ReadCallback(mat2) == -1)
1964                 return NULL;
1965
1966         if (mat1->num_col != mat2->num_col || mat1->num_row != mat2->num_row) {
1967                 PyErr_SetString(PyExc_ValueError,
1968                                 "Matrix addition: "
1969                                 "matrices must have the same dimensions for this operation");
1970                 return NULL;
1971         }
1972
1973         add_vn_vnvn(mat, mat1->matrix, mat2->matrix, mat1->num_col * mat1->num_row);
1974
1975         return Matrix_CreatePyObject(mat, mat1->num_col, mat1->num_row, Py_NEW, Py_TYPE(mat1));
1976 }
1977 /*------------------------obj - obj------------------------------
1978  * subtraction */
1979 static PyObject *Matrix_sub(PyObject *m1, PyObject *m2)
1980 {
1981         float mat[16];
1982         MatrixObject *mat1 = NULL, *mat2 = NULL;
1983
1984         mat1 = (MatrixObject *)m1;
1985         mat2 = (MatrixObject *)m2;
1986
1987         if (!MatrixObject_Check(m1) || !MatrixObject_Check(m2)) {
1988                 PyErr_Format(PyExc_TypeError,
1989                              "Matrix subtraction: (%s - %s) "
1990                              "invalid type for this operation",
1991                              Py_TYPE(m1)->tp_name, Py_TYPE(m2)->tp_name);
1992                 return NULL;
1993         }
1994
1995         if (BaseMath_ReadCallback(mat1) == -1 || BaseMath_ReadCallback(mat2) == -1)
1996                 return NULL;
1997
1998         if (mat1->num_col != mat2->num_col || mat1->num_row != mat2->num_row) {
1999                 PyErr_SetString(PyExc_ValueError,
2000                                 "Matrix addition: "
2001                                 "matrices must have the same dimensions for this operation");
2002                 return NULL;
2003         }
2004
2005         sub_vn_vnvn(mat, mat1->matrix, mat2->matrix, mat1->num_col * mat1->num_row);
2006
2007         return Matrix_CreatePyObject(mat, mat1->num_col, mat1->num_row, Py_NEW, Py_TYPE(mat1));
2008 }
2009 /*------------------------obj * obj------------------------------
2010  * multiplication */
2011 static PyObject *matrix_mul_float(MatrixObject *mat, const float scalar)
2012 {
2013         float tmat[16];
2014         mul_vn_vn_fl(tmat, mat->matrix, mat->num_col * mat->num_row, scalar);
2015         return Matrix_CreatePyObject(tmat, mat->num_col, mat->num_row, Py_NEW, Py_TYPE(mat));
2016 }
2017
2018 static PyObject *Matrix_mul(PyObject *m1, PyObject *m2)
2019 {
2020         float scalar;
2021         int vec_size;
2022
2023         MatrixObject *mat1 = NULL, *mat2 = NULL;
2024
2025         if (MatrixObject_Check(m1)) {
2026                 mat1 = (MatrixObject *)m1;
2027                 if (BaseMath_ReadCallback(mat1) == -1)
2028                         return NULL;
2029         }
2030         if (MatrixObject_Check(m2)) {
2031                 mat2 = (MatrixObject *)m2;
2032                 if (BaseMath_ReadCallback(mat2) == -1)
2033                         return NULL;
2034         }
2035
2036         if (mat1 && mat2) {
2037                 /* MATRIX * MATRIX */
2038                 float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f,
2039                                  0.0f, 0.0f, 0.0f, 0.0f,
2040                                  0.0f, 0.0f, 0.0f, 0.0f,
2041                                  0.0f, 0.0f, 0.0f, 1.0f};
2042
2043                 int col, row, item;
2044
2045                 if (mat1->num_col != mat2->num_row) {
2046                         PyErr_SetString(PyExc_ValueError,
2047                                         "matrix1 * matrix2: matrix1 number of columns "
2048                                         "and the matrix2 number of rows must be the same");
2049                         return NULL;
2050                 }
2051
2052                 for (col = 0; col < mat2->num_col; col++) {
2053                         for (row = 0; row < mat1->num_row; row++) {
2054                                 double dot = 0.0f;
2055                                 for (item = 0; item < mat1->num_col; item++) {
2056                                         dot += (double)(MATRIX_ITEM(mat1, row, item) * MATRIX_ITEM(mat2, item, col));
2057                                 }
2058                                 mat[(col * mat1->num_row) + row] = (float)dot;
2059                         }
2060                 }
2061
2062                 return Matrix_CreatePyObject(mat, mat2->num_col, mat1->num_row, Py_NEW, Py_TYPE(mat1));
2063         }
2064         else if (mat2) {
2065                 /*FLOAT/INT * MATRIX */
2066                 if (((scalar = PyFloat_AsDouble(m1)) == -1.0f && PyErr_Occurred()) == 0) {
2067                         return matrix_mul_float(mat2, scalar);
2068                 }
2069         }
2070         else if (mat1) {
2071                 /* MATRIX * VECTOR */
2072                 if (VectorObject_Check(m2)) {
2073                         VectorObject *vec2 = (VectorObject *)m2;
2074                         float tvec[4];
2075                         if (BaseMath_ReadCallback(vec2) == -1)
2076                                 return NULL;
2077                         if (column_vector_multiplication(tvec, vec2, mat1) == -1) {
2078                                 return NULL;
2079                         }
2080
2081                         if (mat1->num_col == 4 && vec2->size == 3) {
2082                                 vec_size = 3;
2083                         }
2084                         else {
2085                                 vec_size = mat1->num_row;
2086                         }
2087
2088                         return Vector_CreatePyObject(tvec, vec_size, Py_NEW, Py_TYPE(m2));
2089                 }
2090                 /*FLOAT/INT * MATRIX */
2091                 else if (((scalar = PyFloat_AsDouble(m2)) == -1.0f && PyErr_Occurred()) == 0) {
2092                         return matrix_mul_float(mat1, scalar);
2093                 }
2094         }
2095         else {
2096                 BLI_assert(!"internal error");
2097         }
2098
2099         PyErr_Format(PyExc_TypeError,
2100                      "Matrix multiplication: "
2101                      "not supported between '%.200s' and '%.200s' types",
2102                      Py_TYPE(m1)->tp_name, Py_TYPE(m2)->tp_name);
2103         return NULL;
2104 }
2105
2106 /*-----------------PROTOCOL DECLARATIONS--------------------------*/
2107 static PySequenceMethods Matrix_SeqMethods = {
2108         (lenfunc) Matrix_len,                       /* sq_length */
2109         (binaryfunc) NULL,                          /* sq_concat */
2110         (ssizeargfunc) NULL,                        /* sq_repeat */
2111         (ssizeargfunc) Matrix_item_row,             /* sq_item */
2112         (ssizessizeargfunc) NULL,                   /* sq_slice, deprecated */
2113         (ssizeobjargproc) Matrix_ass_item_row,      /* sq_ass_item */
2114         (ssizessizeobjargproc) NULL,                /* sq_ass_slice, deprecated */
2115         (objobjproc) NULL,                          /* sq_contains */
2116         (binaryfunc) NULL,                          /* sq_inplace_concat */
2117         (ssizeargfunc) NULL,                        /* sq_inplace_repeat */
2118 };
2119
2120
2121 static PyObject *Matrix_subscript(MatrixObject *self, PyObject *item)
2122 {
2123         if (PyIndex_Check(item)) {
2124                 Py_ssize_t i;
2125                 i = PyNumber_AsSsize_t(item, PyExc_IndexError);
2126                 if (i == -1 && PyErr_Occurred())
2127                         return NULL;
2128                 if (i < 0)
2129                         i += self->num_row;
2130                 return Matrix_item_row(self, i);
2131         }
2132         else if (PySlice_Check(item)) {
2133                 Py_ssize_t start, stop, step, slicelength;
2134
2135                 if (PySlice_GetIndicesEx(item, self->num_row, &start, &stop, &step, &slicelength) < 0)
2136                         return NULL;
2137
2138                 if (slicelength <= 0) {
2139                         return PyTuple_New(0);
2140                 }
2141                 else if (step == 1) {
2142                         return Matrix_slice(self, start, stop);
2143                 }
2144                 else {
2145                         PyErr_SetString(PyExc_IndexError,
2146                                         "slice steps not supported with matrices");
2147                         return NULL;
2148                 }
2149         }
2150         else {
2151                 PyErr_Format(PyExc_TypeError,
2152                              "matrix indices must be integers, not %.200s",
2153                              Py_TYPE(item)->tp_name);
2154                 return NULL;
2155         }
2156 }
2157
2158 static int Matrix_ass_subscript(MatrixObject *self, PyObject *item, PyObject *value)
2159 {
2160         if (PyIndex_Check(item)) {
2161                 Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
2162                 if (i == -1 && PyErr_Occurred())
2163                         return -1;
2164                 if (i < 0)
2165                         i += self->num_row;
2166                 return Matrix_ass_item_row(self, i, value);
2167         }
2168         else if (PySlice_Check(item)) {
2169                 Py_ssize_t start, stop, step, slicelength;
2170
2171                 if (PySlice_GetIndicesEx(item, self->num_row, &start, &stop, &step, &slicelength) < 0)
2172                         return -1;
2173
2174                 if (step == 1)
2175                         return Matrix_ass_slice(self, start, stop, value);
2176                 else {
2177                         PyErr_SetString(PyExc_IndexError,
2178                                         "slice steps not supported with matrices");
2179                         return -1;
2180                 }
2181         }
2182         else {
2183                 PyErr_Format(PyExc_TypeError,
2184                              "matrix indices must be integers, not %.200s",
2185                              Py_TYPE(item)->tp_name);
2186                 return -1;
2187         }
2188 }
2189
2190 static PyMappingMethods Matrix_AsMapping = {
2191         (lenfunc)Matrix_len,
2192         (binaryfunc)Matrix_subscript,
2193         (objobjargproc)Matrix_ass_subscript
2194 };
2195
2196
2197 static PyNumberMethods Matrix_NumMethods = {
2198         (binaryfunc)    Matrix_add,     /*nb_add*/
2199         (binaryfunc)    Matrix_sub,     /*nb_subtract*/
2200         (binaryfunc)    Matrix_mul,     /*nb_multiply*/
2201         NULL,                               /*nb_remainder*/
2202         NULL,                               /*nb_divmod*/
2203         NULL,                               /*nb_power*/
2204         (unaryfunc)     0,      /*nb_negative*/
2205         (unaryfunc)     0,      /*tp_positive*/
2206         (unaryfunc)     0,      /*tp_absolute*/
2207         (inquiry)   0,      /*tp_bool*/
2208         (unaryfunc) Matrix_inverted,        /*nb_invert*/
2209         NULL,                   /*nb_lshift*/
2210         (binaryfunc)0,      /*nb_rshift*/
2211         NULL,                   /*nb_and*/
2212         NULL,                   /*nb_xor*/
2213         NULL,                   /*nb_or*/
2214         NULL,                   /*nb_int*/
2215         NULL,                   /*nb_reserved*/
2216         NULL,                   /*nb_float*/
2217         NULL,                   /* nb_inplace_add */
2218         NULL,                   /* nb_inplace_subtract */
2219         NULL,                   /* nb_inplace_multiply */
2220         NULL,                   /* nb_inplace_remainder */
2221         NULL,                   /* nb_inplace_power */
2222         NULL,                   /* nb_inplace_lshift */
2223         NULL,                   /* nb_inplace_rshift */
2224         NULL,                   /* nb_inplace_and */
2225         NULL,                   /* nb_inplace_xor */
2226         NULL,                   /* nb_inplace_or */
2227         NULL,                   /* nb_floor_divide */
2228         NULL,                   /* nb_true_divide */
2229         NULL,                   /* nb_inplace_floor_divide */
2230         NULL,                   /* nb_inplace_true_divide */
2231         NULL,                   /* nb_index */
2232 };
2233
2234 PyDoc_STRVAR(Matrix_translation_doc,
2235 "The translation component of the matrix.\n\n:type: Vector"
2236 );
2237 static PyObject *Matrix_translation_get(MatrixObject *self, void *UNUSED(closure))
2238 {
2239         PyObject *ret;
2240
2241         if (BaseMath_ReadCallback(self) == -1)
2242                 return NULL;
2243
2244         /*must be 4x4 square matrix*/
2245         if (self->num_row != 4 || self->num_col != 4) {
2246                 PyErr_SetString(PyExc_AttributeError,
2247                                 "Matrix.translation: "
2248                                 "inappropriate matrix size, must be 4x4");
2249                 return NULL;
2250         }
2251
2252         ret = (PyObject *)Vector_CreatePyObject_cb((PyObject *)self, 3, mathutils_matrix_translation_cb_index, 3);
2253
2254         return ret;
2255 }
2256
2257 static int Matrix_translation_set(MatrixObject *self, PyObject *value, void *UNUSED(closure))
2258 {
2259         float tvec[3];
2260
2261         if (BaseMath_ReadCallback(self) == -1)
2262                 return -1;
2263
2264         /*must be 4x4 square matrix*/
2265         if (self->num_row != 4 || self->num_col != 4) {
2266                 PyErr_SetString(PyExc_AttributeError,
2267                                 "Matrix.translation: "
2268                                 "inappropriate matrix size, must be 4x4");
2269                 return -1;
2270         }
2271
2272         if ((mathutils_array_parse(tvec, 3, 3, value, "Matrix.translation")) == -1) {
2273                 return -1;
2274         }
2275
2276         copy_v3_v3(((float (*)[4])self->matrix)[3], tvec);
2277
2278         (void)BaseMath_WriteCallback(self);
2279
2280         return 0;
2281 }
2282
2283 PyDoc_STRVAR(Matrix_row_doc,
2284 "Access the matix by rows (default), (read-only).\n\n:type: Matrix Access"
2285 );
2286 static PyObject *Matrix_row_get(MatrixObject *self, void *UNUSED(closure))
2287 {
2288         return MatrixAccess_CreatePyObject(self, MAT_ACCESS_ROW);
2289 }
2290
2291 PyDoc_STRVAR(Matrix_col_doc,
2292 "Access the matix by colums, 3x3 and 4x4 only, (read-only).\n\n:type: Matrix Access"
2293 );
2294 static PyObject *Matrix_col_get(MatrixObject *self, void *UNUSED(closure))
2295 {
2296         return MatrixAccess_CreatePyObject(self, MAT_ACCESS_COL);
2297 }
2298
2299 PyDoc_STRVAR(Matrix_median_scale_doc,
2300 "The average scale applied to each axis (read-only).\n\n:type: float"
2301 );
2302 static PyObject *Matrix_median_scale_get(MatrixObject *self, void *UNUSED(closure))
2303 {
2304         float mat[3][3];
2305
2306         if (BaseMath_ReadCallback(self) == -1)
2307                 return NULL;
2308
2309         /*must be 3-4 cols, 3-4 rows, square matrix*/
2310         if ((self->num_row < 3) || (self->num_col < 3)) {
2311                 PyErr_SetString(PyExc_AttributeError,
2312                                 "Matrix.median_scale: "
2313                                 "inappropriate matrix size, 3x3 minimum");
2314                 return NULL;
2315         }
2316
2317         matrix_as_3x3(mat, self);
2318
2319         return PyFloat_FromDouble(mat3_to_scale(mat));
2320 }
2321
2322 PyDoc_STRVAR(Matrix_is_negative_doc,
2323 "True if this matrix results in a negative scale, 3x3 and 4x4 only, (read-only).\n\n:type: bool"
2324 );
2325 static PyObject *Matrix_is_negative_get(MatrixObject *self, void *UNUSED(closure))
2326 {
2327         if (BaseMath_ReadCallback(self) == -1)
2328                 return NULL;
2329
2330         /*must be 3-4 cols, 3-4 rows, square matrix*/
2331         if (self->num_row == 4 && self->num_col == 4)
2332                 return PyBool_FromLong(is_negative_m4((float (*)[4])self->matrix));
2333         else if (self->num_row == 3 && self->num_col == 3)
2334                 return PyBool_FromLong(is_negative_m3((float (*)[3])self->matrix));
2335         else {
2336                 PyErr_SetString(PyExc_AttributeError,
2337                                 "Matrix.is_negative: "
2338                                 "inappropriate matrix size - expects 3x3 or 4x4 matrix");
2339                 return NULL;
2340         }
2341 }
2342
2343 PyDoc_STRVAR(Matrix_is_orthogonal_doc,
2344 "True if this matrix is orthogonal, 3x3 and 4x4 only, (read-only).\n\n:type: bool"
2345 );
2346 static PyObject *Matrix_is_orthogonal_get(MatrixObject *self, void *UNUSED(closure))
2347 {
2348         if (BaseMath_ReadCallback(self) == -1)
2349                 return NULL;
2350
2351         /*must be 3-4 cols, 3-4 rows, square matrix*/
2352         if (self->num_row == 4 && self->num_col == 4)
2353                 return PyBool_FromLong(is_orthonormal_m4((float (*)[4])self->matrix));
2354         else if (self->num_row == 3 && self->num_col == 3)
2355                 return PyBool_FromLong(is_orthonormal_m3((float (*)[3])self->matrix));
2356         else {
2357                 PyErr_SetString(PyExc_AttributeError,
2358                                 "Matrix.is_orthogonal: "
2359                                 "inappropriate matrix size - expects 3x3 or 4x4 matrix");
2360                 return NULL;
2361         }
2362 }
2363
2364 PyDoc_STRVAR(Matrix_is_orthogonal_axis_vectors_doc,
2365 "True if this matrix has got orthogonal axis vectors, 3x3 and 4x4 only, (read-only).\n\n:type: bool"
2366 );
2367 static PyObject *Matrix_is_orthogonal_axis_vectors_get(MatrixObject *self, void *UNUSED(closure))
2368 {
2369         if (BaseMath_ReadCallback(self) == -1)
2370                 return NULL;
2371
2372         /*must be 3-4 cols, 3-4 rows, square matrix*/
2373         if (self->num_row == 4 && self->num_col == 4)
2374                 return PyBool_FromLong(is_orthogonal_m4((float (*)[4])self->matrix));
2375         else if (self->num_row == 3 && self->num_col == 3)
2376                 return PyBool_FromLong(is_orthogonal_m3((float (*)[3])self->matrix));
2377         else {
2378                 PyErr_SetString(PyExc_AttributeError,
2379                                 "Matrix.is_orthogonal_axis_vectors: "
2380                                 "inappropriate matrix size - expects 3x3 or 4x4 matrix");
2381                 return NULL;
2382         }
2383 }
2384
2385 /*****************************************************************************/
2386 /* Python attributes get/set structure:                                      */
2387 /*****************************************************************************/
2388 static PyGetSetDef Matrix_getseters[] = {
2389         {(char *)"median_scale", (getter)Matrix_median_scale_get, (setter)NULL, Matrix_median_scale_doc, NULL},
2390         {(char *)"translation", (getter)Matrix_translation_get, (setter)Matrix_translation_set, Matrix_translation_doc, NULL},
2391         {(char *)"row", (getter)Matrix_row_get, (setter)NULL, Matrix_row_doc, NULL},
2392         {(char *)"col", (getter)Matrix_col_get, (setter)NULL, Matrix_col_doc, NULL},
2393         {(char *)"is_negative", (getter)Matrix_is_negative_get, (setter)NULL, Matrix_is_negative_doc, NULL},
2394         {(char *)"is_orthogonal", (getter)Matrix_is_orthogonal_get, (setter)NULL, Matrix_is_orthogonal_doc, NULL},
2395         {(char *)"is_orthogonal_axis_vectors", (getter)Matrix_is_orthogonal_axis_vectors_get, (setter)NULL, Matrix_is_orthogonal_axis_vectors_doc, NULL},
2396         {(char *)"is_wrapped", (getter)BaseMathObject_is_wrapped_get, (setter)NULL, BaseMathObject_is_wrapped_doc, NULL},
2397         {(char *)"owner", (getter)BaseMathObject_owner_get, (setter)NULL, BaseMathObject_owner_doc, NULL},
2398         {NULL, NULL, NULL, NULL, NULL}  /* Sentinel */
2399 };
2400
2401 /*-----------------------METHOD DEFINITIONS ----------------------*/
2402 static struct PyMethodDef Matrix_methods[] = {
2403         /* derived values */
2404         {"determinant", (PyCFunction) Matrix_determinant, METH_NOARGS, Matrix_determinant_doc},
2405         {"decompose", (PyCFunction) Matrix_decompose, METH_NOARGS, Matrix_decompose_doc},
2406
2407         /* in place only */
2408         {"zero", (PyCFunction) Matrix_zero, METH_NOARGS, Matrix_zero_doc},
2409         {"identity", (PyCFunction) Matrix_identity, METH_NOARGS, Matrix_identity_doc},
2410
2411         /* operate on original or copy */
2412         {"transpose", (PyCFunction) Matrix_transpose, METH_NOARGS, Matrix_transpose_doc},
2413         {"transposed", (PyCFunction) Matrix_transposed, METH_NOARGS, Matrix_transposed_doc},
2414         {"normalize", (PyCFunction) Matrix_normalize, METH_NOARGS, Matrix_normalize_doc},
2415         {"normalized", (PyCFunction) Matrix_normalized, METH_NOARGS, Matrix_normalized_doc},
2416         {"invert", (PyCFunction) Matrix_invert, METH_NOARGS, Matrix_invert_doc},
2417         {"inverted", (PyCFunction) Matrix_inverted, METH_NOARGS, Matrix_inverted_doc},
2418         {"adjugate", (PyCFunction) Matrix_adjugate, METH_NOARGS, Matrix_adjugate_doc},
2419         {"adjugated", (PyCFunction) Matrix_adjugated, METH_NOARGS, Matrix_adjugated_doc},
2420         {"to_3x3", (PyCFunction) Matrix_to_3x3, METH_NOARGS, Matrix_to_3x3_doc},
2421         /* TODO. {"resize_3x3", (PyCFunction) Matrix_resize3x3, METH_NOARGS, Matrix_resize3x3_doc}, */
2422         {"to_4x4", (PyCFunction) Matrix_to_4x4, METH_NOARGS, Matrix_to_4x4_doc},
2423         {"resize_4x4", (PyCFunction) Matrix_resize_4x4, METH_NOARGS, Matrix_resize_4x4_doc},
2424         {"rotate", (PyCFunction) Matrix_rotate, METH_O, Matrix_rotate_doc},
2425
2426         /* return converted representation */
2427         {"to_euler", (PyCFunction) Matrix_to_euler, METH_VARARGS, Matrix_to_euler_doc},
2428         {"to_quaternion", (PyCFunction) Matrix_to_quaternion, METH_NOARGS, Matrix_to_quaternion_doc},
2429         {"to_scale", (PyCFunction) Matrix_to_scale, METH_NOARGS, Matrix_to_scale_doc},
2430         {"to_translation", (PyCFunction) Matrix_to_translation, METH_NOARGS, Matrix_to_translation_doc},
2431
2432         /* operation between 2 or more types  */
2433         {"lerp", (PyCFunction) Matrix_lerp, METH_VARARGS, Matrix_lerp_doc},
2434         {"copy", (PyCFunction) Matrix_copy, METH_NOARGS, Matrix_copy_doc},
2435         {"__copy__", (PyCFunction) Matrix_copy, METH_NOARGS, Matrix_copy_doc},
2436         {"__deepcopy__", (PyCFunction) Matrix_deepcopy, METH_VARARGS, Matrix_copy_doc},
2437
2438         /* class methods */
2439         {"Identity", (PyCFunction) C_Matrix_Identity, METH_VARARGS | METH_CLASS, C_Matrix_Identity_doc},
2440         {"Rotation", (PyCFunction) C_Matrix_Rotation, METH_VARARGS | METH_CLASS, C_Matrix_Rotation_doc},
2441         {"Scale", (PyCFunction) C_Matrix_Scale, METH_VARARGS | METH_CLASS, C_Matrix_Scale_doc},
2442         {"Shear", (PyCFunction) C_Matrix_Shear, METH_VARARGS | METH_CLASS, C_Matrix_Shear_doc},
2443         {"Translation", (PyCFunction) C_Matrix_Translation, METH_O | METH_CLASS, C_Matrix_Translation_doc},
2444         {"OrthoProjection", (PyCFunction) C_Matrix_OrthoProjection,  METH_VARARGS | METH_CLASS, C_Matrix_OrthoProjection_doc},
2445         {NULL, NULL, 0, NULL}
2446 };
2447
2448 /*------------------PY_OBECT DEFINITION--------------------------*/
2449 PyDoc_STRVAR(matrix_doc,
2450 "This object gives access to Matrices in Blender."
2451 );
2452 PyTypeObject matrix_Type = {
2453         PyVarObject_HEAD_INIT(NULL, 0)
2454         "Matrix",                           /*tp_name*/
2455         sizeof(MatrixObject),               /*tp_basicsize*/
2456         0,                                  /*tp_itemsize*/
2457         (destructor)BaseMathObject_dealloc, /*tp_dealloc*/
2458         NULL,                               /*tp_print*/
2459         NULL,                               /*tp_getattr*/
2460         NULL,                               /*tp_setattr*/
2461         NULL,                               /*tp_compare*/
2462         (reprfunc) Matrix_repr,             /*tp_repr*/
2463         &Matrix_NumMethods,                 /*tp_as_number*/
2464         &Matrix_SeqMethods,                 /*tp_as_sequence*/
2465         &Matrix_AsMapping,                  /*tp_as_mapping*/
2466         NULL,                               /*tp_hash*/
2467         NULL,                               /*tp_call*/
2468 #ifndef MATH_STANDALONE
2469         (reprfunc) Matrix_str,              /*tp_str*/
2470 #else
2471         NULL,                               /*tp_str*/
2472 #endif
2473         NULL,                               /*tp_getattro*/
2474         NULL,                               /*tp_setattro*/
2475         NULL,                               /*tp_as_buffer*/
2476         Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
2477         matrix_doc,                         /*tp_doc*/
2478         (traverseproc)BaseMathObject_traverse,  /* tp_traverse */
2479         (inquiry)BaseMathObject_clear,      /*tp_clear*/
2480         (richcmpfunc)Matrix_richcmpr,       /*tp_richcompare*/
2481         0,                                  /*tp_weaklistoffset*/
2482         NULL,                               /*tp_iter*/
2483         NULL,                               /*tp_iternext*/
2484         Matrix_methods,                     /*tp_methods*/
2485         NULL,                               /*tp_members*/
2486         Matrix_getseters,                   /*tp_getset*/
2487         NULL,                               /*tp_base*/
2488         NULL,                               /*tp_dict*/
2489         NULL,                               /*tp_descr_get*/
2490         NULL,                               /*tp_descr_set*/
2491         0,                                  /*tp_dictoffset*/
2492         NULL,                               /*tp_init*/
2493         NULL,                               /*tp_alloc*/
2494         Matrix_new,                         /*tp_new*/
2495         NULL,                               /*tp_free*/
2496         NULL,                               /*tp_is_gc*/
2497         NULL,                               /*tp_bases*/
2498         NULL,                               /*tp_mro*/
2499         NULL,                               /*tp_cache*/
2500         NULL,                               /*tp_subclasses*/
2501         NULL,                               /*tp_weaklist*/
2502         NULL                                /*tp_del*/
2503 };
2504
2505 /* pass Py_WRAP - if vector is a WRAPPER for data allocated by BLENDER
2506  * (i.e. it was allocated elsewhere by MEM_mallocN())
2507  * pass Py_NEW - if vector is not a WRAPPER and managed by PYTHON
2508  * (i.e. it must be created here with PyMEM_malloc()) */
2509 PyObject *Matrix_CreatePyObject(float *mat,
2510                                 const unsigned short num_col, const unsigned short num_row,
2511                                 int type, PyTypeObject *base_type)
2512 {
2513         MatrixObject *self;
2514
2515         /* matrix objects can be any 2-4row x 2-4col matrix */
2516         if (num_col < 2 || num_col > 4 || num_row < 2 || num_row > 4) {
2517                 PyErr_SetString(PyExc_RuntimeError,
2518                                 "Matrix(): "
2519                                 "row and column sizes must be between 2 and 4");
2520                 return NULL;
2521         }
2522
2523         self = base_type ? (MatrixObject *)base_type->tp_alloc(base_type, 0) :
2524                            (MatrixObject *)PyObject_GC_New(MatrixObject, &matrix_Type);
2525
2526         if (self) {
2527                 self->num_col = num_col;
2528                 self->num_row = num_row;
2529
2530                 /* init callbacks as NULL */
2531                 self->cb_user = NULL;
2532                 self->cb_type = self->cb_subtype = 0;
2533
2534                 if (type == Py_WRAP) {
2535                         self->matrix = mat;
2536                         self->wrapped = Py_WRAP;
2537                 }
2538                 else if (type == Py_NEW) {
2539                         self->matrix = PyMem_Malloc(num_col * num_row * sizeof(float));
2540                         if (self->matrix == NULL) { /*allocation failure*/
2541                                 PyErr_SetString(PyExc_MemoryError,
2542                                                 "Matrix(): "
2543                                                 "problem allocating pointer space");
2544                                 return NULL;
2545                         }
2546
2547                         if (mat) {  /*if a float array passed*/
2548                                 memcpy(self->matrix, mat, num_col * num_row * sizeof(float));
2549                         }
2550                         else if (num_col == num_row) {
2551                                 /* or if no arguments are passed return identity matrix for square matrices */
2552                                 PyObject *ret_dummy = Matrix_identity(self);
2553                                 Py_DECREF(ret_dummy);
2554                         }
2555                         else {
2556                                 /* otherwise zero everything */
2557                                 memset(self->matrix, 0, num_col * num_row * sizeof(float));
2558                         }
2559                         self->wrapped = Py_NEW;
2560                 }
2561                 else {
2562                         Py_FatalError("Matrix(): invalid type!");
2563                         return NULL;
2564                 }
2565         }
2566         return (PyObject *) self;
2567 }
2568
2569 PyObject *Matrix_CreatePyObject_cb(PyObject *cb_user,
2570                                    const unsigned short num_col, const unsigned short num_row,
2571                                    unsigned char cb_type, unsigned char cb_subtype)
2572 {
2573         MatrixObject *self = (MatrixObject *)Matrix_CreatePyObject(NULL, num_col, num_row, Py_NEW, NULL);
2574         if (self) {
2575                 Py_INCREF(cb_user);
2576                 self->cb_user         = cb_user;
2577                 self->cb_type         = cb_type;
2578                 self->cb_subtype      = cb_subtype;
2579                 PyObject_GC_Track(self);
2580         }
2581         return (PyObject *) self;
2582 }
2583
2584
2585 /* ----------------------------------------------------------------------------
2586  * special type for alternate access */
2587
2588 typedef struct {
2589         PyObject_HEAD /* required python macro   */
2590         MatrixObject *matrix_user;
2591         eMatrixAccess_t type;
2592 } MatrixAccessObject;
2593
2594 static int MatrixAccess_traverse(MatrixAccessObject *self, visitproc visit, void *arg)
2595 {
2596         Py_VISIT(self->matrix_user);
2597         return 0;
2598 }
2599
2600 static int MatrixAccess_clear(MatrixAccessObject *self)
2601 {
2602         Py_CLEAR(self->matrix_user);
2603         return 0;
2604 }
2605
2606 static void MatrixAccess_dealloc(MatrixAccessObject *self)
2607 {
2608         if (self->matrix_user) {
2609                 PyObject_GC_UnTrack(self);
2610                 MatrixAccess_clear(self);
2611         }
2612
2613         Py_TYPE(self)->tp_free(self);
2614 }
2615
2616 /* sequence access */
2617
2618 static int MatrixAccess_len(MatrixAccessObject *self)
2619 {
2620         return (self->type == MAT_ACCESS_ROW) ?
2621                self->matrix_user->num_row :
2622                self->matrix_user->num_col;
2623 }
2624
2625 static PyObject *MatrixAccess_slice(MatrixAccessObject *self, int begin, int end)
2626 {
2627         PyObject *tuple;
2628         int count;
2629
2630         /* row/col access */
2631         MatrixObject *matrix_user = self->matrix_user;
2632         int matrix_access_len;
2633         PyObject *(*Matrix_item_new)(MatrixObject *, int);
2634
2635         if (self->type == MAT_ACCESS_ROW) {
2636                 matrix_access_len = matrix_user->num_row;
2637                 Matrix_item_new = Matrix_item_row;
2638         }
2639         else { /* MAT_ACCESS_ROW */
2640                 matrix_access_len = matrix_user->num_col;
2641                 Matrix_item_new = Matrix_item_col;
2642         }
2643
2644         CLAMP(begin, 0, matrix_access_len);
2645         if (end < 0) end = (matrix_access_len + 1) + end;
2646         CLAMP(end, 0, matrix_access_len);
2647         begin = MIN2(begin, end);
2648
2649         tuple = PyTuple_New(end - begin);
2650         for (count = begin; count < end; count++) {
2651                 PyTuple_SET_ITEM(tuple, count - begin, Matrix_item_new(matrix_user, count));
2652         }
2653
2654         return tuple;
2655 }
2656
2657 static PyObject *MatrixAccess_subscript(MatrixAccessObject *self, PyObject *item)
2658 {
2659         MatrixObject *matrix_user = self->matrix_user;
2660
2661         if (PyIndex_Check(item)) {
2662                 Py_ssize_t i;
2663                 i = PyNumber_AsSsize_t(item, PyExc_IndexError);
2664                 if (i == -1 && PyErr_Occurred())
2665                         return NULL;
2666                 if (self->type == MAT_ACCESS_ROW) {
2667                         if (i < 0)
2668                                 i += matrix_user->num_row;
2669                         return Matrix_item_row(matrix_user, i);
2670                 }
2671                 else { /* MAT_ACCESS_ROW */
2672                         if (i < 0)
2673                                 i += matrix_user->num_col;
2674                         return Matrix_item_col(matrix_user, i);
2675                 }
2676         }
2677         else if (PySlice_Check(item)) {
2678                 Py_ssize_t start, stop, step, slicelength;
2679
2680                 if (PySlice_GetIndicesEx(item, MatrixAccess_len(self), &start, &stop, &step, &slicelength) < 0)
2681                         return NULL;
2682
2683                 if (slicelength <= 0) {
2684                         return PyTuple_New(0);
2685                 }
2686                 else if (step == 1) {
2687                         return MatrixAccess_slice(self, start, stop);
2688                 }
2689                 else {
2690                         PyErr_SetString(PyExc_IndexError,
2691                                         "slice steps not supported with matrix accessors");
2692                         return NULL;
2693                 }
2694         }
2695         else {
2696                 PyErr_Format(PyExc_TypeError,
2697                              "matrix indices must be integers, not %.200s",
2698                              Py_TYPE(item)->tp_name);
2699                 return NULL;
2700         }
2701 }
2702
2703 static int MatrixAccess_ass_subscript(MatrixAccessObject *self, PyObject *item, PyObject *value)
2704 {
2705         MatrixObject *matrix_user = self->matrix_user;
2706
2707         if (PyIndex_Check(item)) {
2708                 Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
2709                 if (i == -1 && PyErr_Occurred())
2710                         return -1;
2711
2712                 if (self->type == MAT_ACCESS_ROW) {
2713                         if (i < 0)
2714                                 i += matrix_user->num_row;
2715                         return Matrix_ass_item_row(matrix_user, i, value);
2716                 }
2717                 else { /* MAT_ACCESS_ROW */
2718                         if (i < 0)
2719                                 i += matrix_user->num_col;
2720                         return Matrix_ass_item_col(matrix_user, i, value);
2721                 }
2722
2723         }
2724         /* TODO, slice */
2725         else {
2726                 PyErr_Format(PyExc_TypeError,
2727                              "matrix indices must be integers, not %.200s",
2728                              Py_TYPE(item)->tp_name);
2729                 return -1;
2730         }
2731 }
2732
2733 static PyObject *MatrixAccess_iter(MatrixAccessObject *self)
2734 {
2735         /* Try get values from a collection */
2736         PyObject *ret;
2737         PyObject *iter = NULL;
2738         ret = MatrixAccess_slice(self, 0, MATRIX_MAX_DIM);
2739
2740         /* we know this is a tuple so no need to PyIter_Check
2741          * otherwise it could be NULL (unlikely) if conversion failed */
2742         if (ret) {
2743                 iter = PyObject_GetIter(ret);
2744                 Py_DECREF(ret);
2745         }
2746
2747         return iter;
2748 }
2749
2750 static PyMappingMethods MatrixAccess_AsMapping = {
2751         (lenfunc)MatrixAccess_len,
2752         (binaryfunc)MatrixAccess_subscript,
2753         (objobjargproc) MatrixAccess_ass_subscript
2754 };
2755
2756 PyTypeObject matrix_access_Type = {
2757         PyVarObject_HEAD_INIT(NULL, 0)
2758         "MatrixAccess",                     /*tp_name*/
2759         sizeof(MatrixAccessObject),         /*tp_basicsize*/
2760         0,                                  /*tp_itemsize*/
2761         (destructor)MatrixAccess_dealloc,   /*tp_dealloc*/
2762         NULL,                               /*tp_print*/
2763         NULL,                               /*tp_getattr*/
2764         NULL,                               /*tp_setattr*/
2765         NULL,                               /*tp_compare*/
2766         NULL,                               /*tp_repr*/
2767         NULL,                               /*tp_as_number*/
2768         NULL /*&MatrixAccess_SeqMethods*/ /* TODO */,           /*tp_as_sequence*/
2769         &MatrixAccess_AsMapping,            /*tp_as_mapping*/
2770         NULL,                               /*tp_hash*/
2771         NULL,                               /*tp_call*/
2772         NULL,                               /*tp_str*/
2773         NULL,                               /*tp_getattro*/
2774         NULL,                               /*tp_setattro*/
2775         NULL,                               /*tp_as_buffer*/
2776         Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
2777         NULL,                               /*tp_doc*/
2778         (traverseproc)MatrixAccess_traverse,/*tp_traverse*/
2779         (inquiry)MatrixAccess_clear,        /*tp_clear*/
2780         NULL /* (richcmpfunc)MatrixAccess_richcmpr */ /* TODO*/, /*tp_richcompare*/
2781         0,                                  /*tp_weaklistoffset*/
2782         (getiterfunc)MatrixAccess_iter, /* getiterfunc tp_iter; */
2783 };
2784
2785 static PyObject *MatrixAccess_CreatePyObject(MatrixObject *matrix, const eMatrixAccess_t type)
2786 {
2787         MatrixAccessObject *matrix_access = (MatrixAccessObject *)PyObject_GC_New(MatrixObject, &matrix_access_Type);
2788
2789         matrix_access->matrix_user = matrix;
2790         Py_INCREF(matrix);
2791
2792         matrix_access->type = type;
2793
2794         return (PyObject *)matrix_access;
2795 }
2796
2797 /* end special access
2798  * -------------------------------------------------------------------------- */