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