patch [#29651] Add a __str__ Method to Matutils Matrices so print(matrix) Shows Colum...
[blender.git] / source / blender / python / mathutils / mathutils_Matrix.c
1 /*
2  *
3  * ***** BEGIN GPL LICENSE BLOCK *****
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18  *
19  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
20  * All rights reserved.
21  *
22  * Contributor(s): Michel Selten & Joseph Gilbert
23  *
24  * ***** END GPL LICENSE BLOCK *****
25  */
26
27 /** \file blender/python/mathutils/mathutils_Matrix.c
28  *  \ingroup pymathutils
29  */
30
31
32 #include <Python.h>
33
34 #include "mathutils.h"
35
36 #include "BLI_math.h"
37 #include "BLI_utildefines.h"
38 #include "BLI_string.h"
39 #include "BLI_dynstr.h"
40
41 static PyObject *Matrix_copy(MatrixObject *self);
42 static int Matrix_ass_slice(MatrixObject *self, int begin, int end, PyObject *value);
43 static PyObject *matrix__apply_to_copy(PyNoArgsFunction matrix_func, MatrixObject *self);
44
45 /* matrix vector callbacks */
46 int mathutils_matrix_vector_cb_index= -1;
47
48 static int mathutils_matrix_vector_check(BaseMathObject *bmo)
49 {
50         MatrixObject *self= (MatrixObject *)bmo->cb_user;
51         return BaseMath_ReadCallback(self);
52 }
53
54 static int mathutils_matrix_vector_get(BaseMathObject *bmo, int subtype)
55 {
56         MatrixObject *self= (MatrixObject *)bmo->cb_user;
57         int index;
58
59         if (BaseMath_ReadCallback(self) == -1)
60                 return -1;
61
62         for (index=0; index < self->col_size; index++) {
63                 bmo->data[index] = MATRIX_ITEM(self, subtype, index);
64         }
65
66         return 0;
67 }
68
69 static int mathutils_matrix_vector_set(BaseMathObject *bmo, int subtype)
70 {
71         MatrixObject *self= (MatrixObject *)bmo->cb_user;
72         int index;
73
74         if (BaseMath_ReadCallback(self) == -1)
75                 return -1;
76
77         for (index=0; index < self->col_size; index++) {
78                 MATRIX_ITEM(self, subtype, index) = bmo->data[index];
79         }
80
81         (void)BaseMath_WriteCallback(self);
82         return 0;
83 }
84
85 static int mathutils_matrix_vector_get_index(BaseMathObject *bmo, int subtype, int index)
86 {
87         MatrixObject *self= (MatrixObject *)bmo->cb_user;
88
89         if (BaseMath_ReadCallback(self) == -1)
90                 return -1;
91
92         bmo->data[index]= MATRIX_ITEM(self, subtype, index);
93         return 0;
94 }
95
96 static int mathutils_matrix_vector_set_index(BaseMathObject *bmo, int subtype, int index)
97 {
98         MatrixObject *self= (MatrixObject *)bmo->cb_user;
99
100         if (BaseMath_ReadCallback(self) == -1)
101                 return -1;
102
103         MATRIX_ITEM(self, subtype, index) = bmo->data[index];
104
105         (void)BaseMath_WriteCallback(self);
106         return 0;
107 }
108
109 Mathutils_Callback mathutils_matrix_vector_cb = {
110         mathutils_matrix_vector_check,
111         mathutils_matrix_vector_get,
112         mathutils_matrix_vector_set,
113         mathutils_matrix_vector_get_index,
114         mathutils_matrix_vector_set_index
115 };
116 /* matrix vector callbacks, this is so you can do matrix[i][j] = val  */
117
118 //----------------------------------mathutils.Matrix() -----------------
119 //mat is a 1D array of floats - row[0][0], row[0][1], row[1][0], etc.
120 //create a new matrix type
121 static PyObject *Matrix_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
122 {
123         if (kwds && PyDict_Size(kwds)) {
124                 PyErr_SetString(PyExc_TypeError,
125                                 "Matrix(): "
126                                 "takes no keyword args");
127                 return NULL;
128         }
129
130         switch (PyTuple_GET_SIZE(args)) {
131                 case 0:
132                         return Matrix_CreatePyObject(NULL, 4, 4, Py_NEW, type);
133                 case 1:
134                 {
135                         PyObject *arg= PyTuple_GET_ITEM(args, 0);
136
137                         /* -1 is an error, size checks will accunt for this */
138                         const unsigned short row_size= PySequence_Size(arg);
139
140                         if (row_size >= 2 && row_size <= 4) {
141                                 PyObject *item= PySequence_GetItem(arg, 0);
142                                 const unsigned short col_size= PySequence_Size(item);
143                                 Py_XDECREF(item);
144
145                                 if (col_size >= 2 && col_size <= 4) {
146                                         /* sane row & col size, new matrix and assign as slice  */
147                                         PyObject *matrix= Matrix_CreatePyObject(NULL, row_size, col_size, Py_NEW, type);
148                                         if (Matrix_ass_slice((MatrixObject *)matrix, 0, INT_MAX, arg) == 0) {
149                                                 return matrix;
150                                         }
151                                         else { /* matrix ok, slice assignment not */
152                                                 Py_DECREF(matrix);
153                                         }
154                                 }
155                         }
156                 }
157         }
158
159         /* will overwrite error */
160         PyErr_SetString(PyExc_TypeError,
161                         "Matrix(): "
162                         "expects no args or 2-4 numeric sequences");
163         return NULL;
164 }
165
166 static PyObject *matrix__apply_to_copy(PyNoArgsFunction matrix_func, MatrixObject *self)
167 {
168         PyObject *ret= Matrix_copy(self);
169         PyObject *ret_dummy= matrix_func(ret);
170         if (ret_dummy) {
171                 Py_DECREF(ret_dummy);
172                 return (PyObject *)ret;
173         }
174         else { /* error */
175                 Py_DECREF(ret);
176                 return NULL;
177         }
178 }
179
180 /* when a matrix is 4x4 size but initialized as a 3x3, re-assign values for 4x4 */
181 static void matrix_3x3_as_4x4(float mat[16])
182 {
183         mat[10] = mat[8];
184         mat[9] = mat[7];
185         mat[8] = mat[6];
186         mat[7] = 0.0f;
187         mat[6] = mat[5];
188         mat[5] = mat[4];
189         mat[4] = mat[3];
190         mat[3] = 0.0f;
191 }
192
193 /*-----------------------CLASS-METHODS----------------------------*/
194
195 //mat is a 1D array of floats - row[0][0], row[0][1], row[1][0], etc.
196 PyDoc_STRVAR(C_Matrix_Rotation_doc,
197 ".. classmethod:: Rotation(angle, size, axis)\n"
198 "\n"
199 "   Create a matrix representing a rotation.\n"
200 "\n"
201 "   :arg angle: The angle of rotation desired, in radians.\n"
202 "   :type angle: float\n"
203 "   :arg size: The size of the rotation matrix to construct [2, 4].\n"
204 "   :type size: int\n"
205 "   :arg axis: a string in ['X', 'Y', 'Z'] or a 3D Vector Object\n"
206 "      (optional when size is 2).\n"
207 "   :type axis: string or :class:`Vector`\n"
208 "   :return: A new rotation matrix.\n"
209 "   :rtype: :class:`Matrix`\n"
210 );
211 static PyObject *C_Matrix_Rotation(PyObject *cls, PyObject *args)
212 {
213         PyObject *vec= NULL;
214         const char *axis= NULL;
215         int matSize;
216         double angle; /* use double because of precision problems at high values */
217         float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
218                 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
219
220         if (!PyArg_ParseTuple(args, "di|O", &angle, &matSize, &vec)) {
221                 PyErr_SetString(PyExc_TypeError,
222                                 "Matrix.Rotation(angle, size, axis): "
223                                 "expected float int and a string or vector");
224                 return NULL;
225         }
226
227         if (vec && PyUnicode_Check(vec)) {
228                 axis= _PyUnicode_AsString((PyObject *)vec);
229                 if (axis==NULL || axis[0]=='\0' || axis[1]!='\0' || axis[0] < 'X' || axis[0] > 'Z') {
230                         PyErr_SetString(PyExc_ValueError,
231                                         "Matrix.Rotation(): "
232                                         "3rd argument axis value must be a 3D vector "
233                                         "or a string in 'X', 'Y', 'Z'");
234                         return NULL;
235                 }
236                 else {
237                         /* use the string */
238                         vec= NULL;
239                 }
240         }
241
242         angle= angle_wrap_rad(angle);
243
244         if (matSize != 2 && matSize != 3 && matSize != 4) {
245                 PyErr_SetString(PyExc_ValueError,
246                                 "Matrix.Rotation(): "
247                                 "can only return a 2x2 3x3 or 4x4 matrix");
248                 return NULL;
249         }
250         if (matSize == 2 && (vec != NULL)) {
251                 PyErr_SetString(PyExc_ValueError,
252                                 "Matrix.Rotation(): "
253                                 "cannot create a 2x2 rotation matrix around arbitrary axis");
254                 return NULL;
255         }
256         if ((matSize == 3 || matSize == 4) && (axis == NULL) && (vec == NULL)) {
257                 PyErr_SetString(PyExc_ValueError,
258                                 "Matrix.Rotation(): "
259                                 "axis of rotation for 3d and 4d matrices is required");
260                 return NULL;
261         }
262
263         /* check for valid vector/axis above */
264         if (vec) {
265                 float tvec[3];
266
267                 if (mathutils_array_parse(tvec, 3, 3, vec, "Matrix.Rotation(angle, size, axis), invalid 'axis' arg") == -1)
268                         return NULL;
269
270                 axis_angle_to_mat3((float (*)[3])mat, tvec, angle);
271         }
272         else if (matSize == 2) {
273                 const float angle_cos= cosf(angle);
274                 const float angle_sin= sinf(angle);
275
276                 //2D rotation matrix
277                 mat[0] =  angle_cos;
278                 mat[1] =  angle_sin;
279                 mat[2] = -angle_sin;
280                 mat[3] =  angle_cos;
281         }
282         else {
283                 /* valid axis checked above */
284                 single_axis_angle_to_mat3((float (*)[3])mat, axis[0], angle);
285         }
286
287         if (matSize == 4) {
288                 matrix_3x3_as_4x4(mat);
289         }
290         //pass to matrix creation
291         return Matrix_CreatePyObject(mat, matSize, matSize, Py_NEW, (PyTypeObject *)cls);
292 }
293
294
295 PyDoc_STRVAR(C_Matrix_Translation_doc,
296 ".. classmethod:: Translation(vector)\n"
297 "\n"
298 "   Create a matrix representing a translation.\n"
299 "\n"
300 "   :arg vector: The translation vector.\n"
301 "   :type vector: :class:`Vector`\n"
302 "   :return: An identity matrix with a translation.\n"
303 "   :rtype: :class:`Matrix`\n"
304 );
305 static PyObject *C_Matrix_Translation(PyObject *cls, PyObject *value)
306 {
307         float mat[16], tvec[3];
308
309         if (mathutils_array_parse(tvec, 3, 4, value, "mathutils.Matrix.Translation(vector), invalid vector arg") == -1)
310                 return NULL;
311
312         /* create a identity matrix and add translation */
313         unit_m4((float(*)[4]) mat);
314         copy_v3_v3(mat + 12, tvec); /* 12, 13, 14 */
315         return Matrix_CreatePyObject(mat, 4, 4, Py_NEW, (PyTypeObject *)cls);
316 }
317 //----------------------------------mathutils.Matrix.Scale() -------------
318 //mat is a 1D array of floats - row[0][0], row[0][1], row[1][0], etc.
319 PyDoc_STRVAR(C_Matrix_Scale_doc,
320 ".. classmethod:: Scale(factor, size, axis)\n"
321 "\n"
322 "   Create a matrix representing a scaling.\n"
323 "\n"
324 "   :arg factor: The factor of scaling to apply.\n"
325 "   :type factor: float\n"
326 "   :arg size: The size of the scale matrix to construct [2, 4].\n"
327 "   :type size: int\n"
328 "   :arg axis: Direction to influence scale. (optional).\n"
329 "   :type axis: :class:`Vector`\n"
330 "   :return: A new scale matrix.\n"
331 "   :rtype: :class:`Matrix`\n"
332 );
333 static PyObject *C_Matrix_Scale(PyObject *cls, PyObject *args)
334 {
335         PyObject *vec= NULL;
336         int vec_size;
337         float tvec[3];
338         float factor;
339         int matSize;
340         float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
341                 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
342
343         if (!PyArg_ParseTuple(args, "fi|O:Matrix.Scale", &factor, &matSize, &vec)) {
344                 return NULL;
345         }
346         if (matSize != 2 && matSize != 3 && matSize != 4) {
347                 PyErr_SetString(PyExc_ValueError,
348                                 "Matrix.Scale(): "
349                                 "can only return a 2x2 3x3 or 4x4 matrix");
350                 return NULL;
351         }
352         if (vec) {
353                 vec_size= (matSize == 2 ? 2 : 3);
354                 if (mathutils_array_parse(tvec, vec_size, vec_size, vec, "Matrix.Scale(factor, size, axis), invalid 'axis' arg") == -1) {
355                         return NULL;
356                 }
357         }
358         if (vec == NULL) {      //scaling along axis
359                 if (matSize == 2) {
360                         mat[0] = factor;
361                         mat[3] = factor;
362                 }
363                 else {
364                         mat[0] = factor;
365                         mat[4] = factor;
366                         mat[8] = factor;
367                 }
368         }
369         else { //scaling in arbitrary direction
370                 //normalize arbitrary axis
371                 float norm = 0.0f;
372                 int x;
373                 for (x = 0; x < vec_size; x++) {
374                         norm += tvec[x] * tvec[x];
375                 }
376                 norm = (float) sqrt(norm);
377                 for (x = 0; x < vec_size; x++) {
378                         tvec[x] /= norm;
379                 }
380                 if (matSize == 2) {
381                         mat[0] = 1 + ((factor - 1) *(tvec[0] * tvec[0]));
382                         mat[1] =     ((factor - 1) *(tvec[0] * tvec[1]));
383                         mat[2] =     ((factor - 1) *(tvec[0] * tvec[1]));
384                         mat[3] = 1 + ((factor - 1) *(tvec[1] * tvec[1]));
385                 }
386                 else {
387                         mat[0] = 1 + ((factor - 1) *(tvec[0] * tvec[0]));
388                         mat[1] =     ((factor - 1) *(tvec[0] * tvec[1]));
389                         mat[2] =     ((factor - 1) *(tvec[0] * tvec[2]));
390                         mat[3] =     ((factor - 1) *(tvec[0] * tvec[1]));
391                         mat[4] = 1 + ((factor - 1) *(tvec[1] * tvec[1]));
392                         mat[5] =     ((factor - 1) *(tvec[1] * tvec[2]));
393                         mat[6] =     ((factor - 1) *(tvec[0] * tvec[2]));
394                         mat[7] =     ((factor - 1) *(tvec[1] * tvec[2]));
395                         mat[8] = 1 + ((factor - 1) *(tvec[2] * tvec[2]));
396                 }
397         }
398         if (matSize == 4) {
399                 matrix_3x3_as_4x4(mat);
400         }
401         //pass to matrix creation
402         return Matrix_CreatePyObject(mat, matSize, matSize, Py_NEW, (PyTypeObject *)cls);
403 }
404 //----------------------------------mathutils.Matrix.OrthoProjection() ---
405 //mat is a 1D array of floats - row[0][0], row[0][1], row[1][0], etc.
406 PyDoc_STRVAR(C_Matrix_OrthoProjection_doc,
407 ".. classmethod:: OrthoProjection(axis, size)\n"
408 "\n"
409 "   Create a matrix to represent an orthographic projection.\n"
410 "\n"
411 "   :arg axis: Can be any of the following: ['X', 'Y', 'XY', 'XZ', 'YZ'],\n"
412 "      where a single axis is for a 2D matrix.\n"
413 "      Or a vector for an arbitrary axis\n"
414 "   :type axis: string or :class:`Vector`\n"
415 "   :arg size: The size of the projection matrix to construct [2, 4].\n"
416 "   :type size: int\n"
417 "   :return: A new projection matrix.\n"
418 "   :rtype: :class:`Matrix`\n"
419 );
420 static PyObject *C_Matrix_OrthoProjection(PyObject *cls, PyObject *args)
421 {
422         PyObject *axis;
423
424         int matSize, x;
425         float norm = 0.0f;
426         float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
427                 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
428
429         if (!PyArg_ParseTuple(args, "Oi:Matrix.OrthoProjection", &axis, &matSize)) {
430                 return NULL;
431         }
432         if (matSize != 2 && matSize != 3 && matSize != 4) {
433                 PyErr_SetString(PyExc_ValueError,
434                                 "Matrix.OrthoProjection(): "
435                                 "can only return a 2x2 3x3 or 4x4 matrix");
436                 return NULL;
437         }
438
439         if (PyUnicode_Check(axis)) {    //ortho projection onto cardinal plane
440                 Py_ssize_t plane_len;
441                 const char *plane= _PyUnicode_AsStringAndSize(axis, &plane_len);
442                 if (matSize == 2) {
443                         if (plane_len == 1 && plane[0]=='X') {
444                                 mat[0]= 1.0f;
445                         }
446                         else if (plane_len == 1 && plane[0]=='Y') {
447                                 mat[3]= 1.0f;
448                         }
449                         else {
450                                 PyErr_Format(PyExc_ValueError,
451                                              "Matrix.OrthoProjection(): "
452                                              "unknown plane, expected: X, Y, not '%.200s'",
453                                              plane);
454                                 return NULL;
455                         }
456                 }
457                 else {
458                         if (plane_len == 2 && plane[0]=='X' && plane[1]=='Y') {
459                                 mat[0]= 1.0f;
460                                 mat[4]= 1.0f;
461                         }
462                         else if (plane_len == 2 && plane[0]=='X' && plane[1]=='Z') {
463                                 mat[0]= 1.0f;
464                                 mat[8]= 1.0f;
465                         }
466                         else if (plane_len == 2 && plane[0]=='Y' && plane[1]=='Z') {
467                                 mat[4]= 1.0f;
468                                 mat[8]= 1.0f;
469                         }
470                         else {
471                                 PyErr_Format(PyExc_ValueError,
472                                              "Matrix.OrthoProjection(): "
473                                              "unknown plane, expected: XY, XZ, YZ, not '%.200s'",
474                                              plane);
475                                 return NULL;
476                         }
477                 }
478         }
479         else {
480                 //arbitrary plane
481
482                 int vec_size= (matSize == 2 ? 2 : 3);
483                 float tvec[4];
484
485                 if (mathutils_array_parse(tvec, vec_size, vec_size, axis,
486                                           "Matrix.OrthoProjection(axis, size), invalid 'axis' arg") == -1)
487                 {
488                         return NULL;
489                 }
490
491                 //normalize arbitrary axis
492                 for (x = 0; x < vec_size; x++) {
493                         norm += tvec[x] * tvec[x];
494                 }
495                 norm = (float) sqrt(norm);
496                 for (x = 0; x < vec_size; x++) {
497                         tvec[x] /= norm;
498                 }
499                 if (matSize == 2) {
500                         mat[0] = 1 - (tvec[0] * tvec[0]);
501                         mat[1] = -(tvec[0] * tvec[1]);
502                         mat[2] = -(tvec[0] * tvec[1]);
503                         mat[3] = 1 - (tvec[1] * tvec[1]);
504                 }
505                 else if (matSize > 2) {
506                         mat[0] = 1 - (tvec[0] * tvec[0]);
507                         mat[1] = -(tvec[0] * tvec[1]);
508                         mat[2] = -(tvec[0] * tvec[2]);
509                         mat[3] = -(tvec[0] * tvec[1]);
510                         mat[4] = 1 - (tvec[1] * tvec[1]);
511                         mat[5] = -(tvec[1] * tvec[2]);
512                         mat[6] = -(tvec[0] * tvec[2]);
513                         mat[7] = -(tvec[1] * tvec[2]);
514                         mat[8] = 1 - (tvec[2] * tvec[2]);
515                 }
516         }
517         if (matSize == 4) {
518                 matrix_3x3_as_4x4(mat);
519         }
520         //pass to matrix creation
521         return Matrix_CreatePyObject(mat, matSize, matSize, Py_NEW, (PyTypeObject *)cls);
522 }
523
524 PyDoc_STRVAR(C_Matrix_Shear_doc,
525 ".. classmethod:: Shear(plane, size, factor)\n"
526 "\n"
527 "   Create a matrix to represent an shear transformation.\n"
528 "\n"
529 "   :arg plane: Can be any of the following: ['X', 'Y', 'XY', 'XZ', 'YZ'],\n"
530 "      where a single axis is for a 2D matrix only.\n"
531 "   :type plane: string\n"
532 "   :arg size: The size of the shear matrix to construct [2, 4].\n"
533 "   :type size: int\n"
534 "   :arg factor: The factor of shear to apply. For a 3 or 4 *size* matrix\n"
535 "      pass a pair of floats corrasponding with the *plane* axis.\n"
536 "   :type factor: float or float pair\n"
537 "   :return: A new shear matrix.\n"
538 "   :rtype: :class:`Matrix`\n"
539 );
540 static PyObject *C_Matrix_Shear(PyObject *cls, PyObject *args)
541 {
542         int matSize;
543         const char *plane;
544         PyObject *fac;
545         float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
546                 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
547
548         if (!PyArg_ParseTuple(args, "siO:Matrix.Shear", &plane, &matSize, &fac)) {
549                 return NULL;
550         }
551         if (matSize != 2 && matSize != 3 && matSize != 4) {
552                 PyErr_SetString(PyExc_ValueError,
553                                 "Matrix.Shear(): "
554                                 "can only return a 2x2 3x3 or 4x4 matrix");
555                 return NULL;
556         }
557
558         if (matSize == 2) {
559                 float const factor= PyFloat_AsDouble(fac);
560
561                 if (factor==-1.0f && PyErr_Occurred()) {
562                         PyErr_SetString(PyExc_TypeError,
563                                         "Matrix.Shear(): "
564                                         "the factor to be a float");
565                         return NULL;
566                 }
567
568                 /* unit */
569                 mat[0] = 1.0f;
570                 mat[3] = 1.0f;
571
572                 if (strcmp(plane, "X") == 0) {
573                         mat[2] = factor;
574                 }
575                 else if (strcmp(plane, "Y") == 0) {
576                         mat[1] = factor;
577                 }
578                 else {
579                         PyErr_SetString(PyExc_ValueError,
580                                         "Matrix.Shear(): "
581                                         "expected: X, Y or wrong matrix size for shearing plane");
582                         return NULL;
583                 }
584         }
585         else {
586                 /* 3 or 4, apply as 3x3, resize later if needed */
587                 float factor[2];
588
589                 if (mathutils_array_parse(factor, 2, 2, fac, "Matrix.Shear()") < 0) {
590                         return NULL;
591                 }
592
593                 /* unit */
594                 mat[0] = 1.0f;
595                 mat[4] = 1.0f;
596                 mat[8] = 1.0f;
597
598                 if (strcmp(plane, "XY") == 0) {
599                         mat[6] = factor[0];
600                         mat[7] = factor[1];
601                 }
602                 else if (strcmp(plane, "XZ") == 0) {
603                         mat[3] = factor[0];
604                         mat[5] = factor[1];
605                 }
606                 else if (strcmp(plane, "YZ") == 0) {
607                         mat[1] = factor[0];
608                         mat[2] = factor[1];
609                 }
610                 else {
611                         PyErr_SetString(PyExc_ValueError,
612                                         "Matrix.Shear(): "
613                                         "expected: X, Y, XY, XZ, YZ");
614                         return NULL;
615                 }
616         }
617
618         if (matSize == 4) {
619                 matrix_3x3_as_4x4(mat);
620         }
621         //pass to matrix creation
622         return Matrix_CreatePyObject(mat, matSize, matSize, Py_NEW, (PyTypeObject *)cls);
623 }
624
625 void matrix_as_3x3(float mat[3][3], MatrixObject *self)
626 {
627         copy_v3_v3(mat[0], MATRIX_ROW_PTR(self, 0));
628         copy_v3_v3(mat[1], MATRIX_ROW_PTR(self, 1));
629         copy_v3_v3(mat[2], MATRIX_ROW_PTR(self, 2));
630 }
631
632 /* assumes rowsize == colsize is checked and the read callback has run */
633 static float matrix_determinant_internal(MatrixObject *self)
634 {
635         if (self->row_size == 2) {
636                 return determinant_m2(MATRIX_ITEM(self, 0, 0), MATRIX_ITEM(self, 0, 1),
637                                       MATRIX_ITEM(self, 1, 0), MATRIX_ITEM(self, 1, 1));
638         }
639         else if (self->row_size == 3) {
640                 return determinant_m3(MATRIX_ITEM(self, 0, 0), MATRIX_ITEM(self, 0, 1), MATRIX_ITEM(self, 0, 2),
641                                       MATRIX_ITEM(self, 1, 0), MATRIX_ITEM(self, 1, 1), MATRIX_ITEM(self, 1, 2),
642                                       MATRIX_ITEM(self, 2, 0), MATRIX_ITEM(self, 2, 1), MATRIX_ITEM(self, 2, 2));
643         }
644         else {
645                 return determinant_m4((float (*)[4])self->contigPtr);
646         }
647 }
648
649
650 /*-----------------------------METHODS----------------------------*/
651 PyDoc_STRVAR(Matrix_to_quaternion_doc,
652 ".. method:: to_quaternion()\n"
653 "\n"
654 "   Return a quaternion representation of the rotation matrix.\n"
655 "\n"
656 "   :return: Quaternion representation of the rotation matrix.\n"
657 "   :rtype: :class:`Quaternion`\n"
658 );
659 static PyObject *Matrix_to_quaternion(MatrixObject *self)
660 {
661         float quat[4];
662
663         if (BaseMath_ReadCallback(self) == -1)
664                 return NULL;
665
666         /*must be 3-4 cols, 3-4 rows, square matrix*/
667         if ((self->col_size < 3) || (self->row_size < 3) || (self->col_size != self->row_size)) {
668                 PyErr_SetString(PyExc_ValueError,
669                                 "Matrix.to_quat(): "
670                                 "inappropriate matrix size - expects 3x3 or 4x4 matrix");
671                 return NULL;
672         }
673         if (self->col_size == 3) {
674                 mat3_to_quat(quat, (float (*)[3])self->contigPtr);
675         }
676         else {
677                 mat4_to_quat(quat, (float (*)[4])self->contigPtr);
678         }
679
680         return Quaternion_CreatePyObject(quat, Py_NEW, NULL);
681 }
682
683 /*---------------------------matrix.toEuler() --------------------*/
684 PyDoc_STRVAR(Matrix_to_euler_doc,
685 ".. method:: to_euler(order, euler_compat)\n"
686 "\n"
687 "   Return an Euler representation of the rotation matrix\n"
688 "   (3x3 or 4x4 matrix only).\n"
689 "\n"
690 "   :arg order: Optional rotation order argument in\n"
691 "      ['XYZ', 'XZY', 'YXZ', 'YZX', 'ZXY', 'ZYX'].\n"
692 "   :type order: string\n"
693 "   :arg euler_compat: Optional euler argument the new euler will be made\n"
694 "      compatible with (no axis flipping between them).\n"
695 "      Useful for converting a series of matrices to animation curves.\n"
696 "   :type euler_compat: :class:`Euler`\n"
697 "   :return: Euler representation of the matrix.\n"
698 "   :rtype: :class:`Euler`\n"
699 );
700 static PyObject *Matrix_to_euler(MatrixObject *self, PyObject *args)
701 {
702         const char *order_str= NULL;
703         short order= EULER_ORDER_XYZ;
704         float eul[3], eul_compatf[3];
705         EulerObject *eul_compat = NULL;
706
707         float tmat[3][3];
708         float (*mat)[3];
709
710         if (BaseMath_ReadCallback(self) == -1)
711                 return NULL;
712
713         if (!PyArg_ParseTuple(args, "|sO!:to_euler", &order_str, &euler_Type, &eul_compat))
714                 return NULL;
715
716         if (eul_compat) {
717                 if (BaseMath_ReadCallback(eul_compat) == -1)
718                         return NULL;
719
720                 copy_v3_v3(eul_compatf, eul_compat->eul);
721         }
722
723         /*must be 3-4 cols, 3-4 rows, square matrix*/
724         if (self->col_size ==3 && self->row_size ==3) {
725                 mat= (float (*)[3])self->contigPtr;
726         }
727         else if (self->col_size ==4 && self->row_size ==4) {
728                 copy_m3_m4(tmat, (float (*)[4])self->contigPtr);
729                 mat= tmat;
730         }
731         else {
732                 PyErr_SetString(PyExc_ValueError,
733                                 "Matrix.to_euler(): "
734                                 "inappropriate matrix size - expects 3x3 or 4x4 matrix");
735                 return NULL;
736         }
737
738         if (order_str) {
739                 order= euler_order_from_string(order_str, "Matrix.to_euler()");
740
741                 if (order == -1)
742                         return NULL;
743         }
744
745         if (eul_compat) {
746                 if (order == 1) mat3_to_compatible_eul(eul, eul_compatf, mat);
747                 else                    mat3_to_compatible_eulO(eul, eul_compatf, order, mat);
748         }
749         else {
750                 if (order == 1) mat3_to_eul(eul, mat);
751                 else                    mat3_to_eulO(eul, order, mat);
752         }
753
754         return Euler_CreatePyObject(eul, order, Py_NEW, NULL);
755 }
756
757 PyDoc_STRVAR(Matrix_resize_4x4_doc,
758 ".. method:: resize_4x4()\n"
759 "\n"
760 "   Resize the matrix to 4x4.\n"
761 );
762 static PyObject *Matrix_resize_4x4(MatrixObject *self)
763 {
764         int x, first_row_elem, curr_pos, new_pos, blank_columns, blank_rows, index;
765
766         if (self->wrapped==Py_WRAP) {
767                 PyErr_SetString(PyExc_TypeError,
768                                 "Matrix.resize_4x4(): "
769                                 "cannot resize wrapped data - make a copy and resize that");
770                 return NULL;
771         }
772         if (self->cb_user) {
773                 PyErr_SetString(PyExc_TypeError,
774                                 "Matrix.resize_4x4(): "
775                                 "cannot resize owned data - make a copy and resize that");
776                 return NULL;
777         }
778
779         self->contigPtr = PyMem_Realloc(self->contigPtr, (sizeof(float) * 16));
780         if (self->contigPtr == NULL) {
781                 PyErr_SetString(PyExc_MemoryError,
782                                 "Matrix.resize_4x4(): "
783                                 "problem allocating pointer space");
784                 return NULL;
785         }
786
787         /*move data to new spot in array + clean*/
788         for (blank_rows = (4 - self->row_size); blank_rows > 0; blank_rows--) {
789                 for (x = 0; x < 4; x++) {
790                         index = (4 * (self->row_size + (blank_rows - 1))) + x;
791                         if (index == 10 || index == 15) {
792                                 self->contigPtr[index] = 1.0f;
793                         }
794                         else {
795                                 self->contigPtr[index] = 0.0f;
796                         }
797                 }
798         }
799         for (x = 1; x <= self->row_size; x++) {
800                 first_row_elem = (self->col_size * (self->row_size - x));
801                 curr_pos = (first_row_elem + (self->col_size -1));
802                 new_pos = (4 * (self->row_size - x)) + (curr_pos - first_row_elem);
803                 for (blank_columns = (4 - self->col_size); blank_columns > 0; blank_columns--) {
804                         self->contigPtr[new_pos + blank_columns] = 0.0f;
805                 }
806                 for ( ; curr_pos >= first_row_elem; curr_pos--) {
807                         self->contigPtr[new_pos] = self->contigPtr[curr_pos];
808                         new_pos--;
809                 }
810         }
811         self->row_size = 4;
812         self->col_size = 4;
813
814         Py_RETURN_NONE;
815 }
816
817 PyDoc_STRVAR(Matrix_to_4x4_doc,
818 ".. method:: to_4x4()\n"
819 "\n"
820 "   Return a 4x4 copy of this matrix.\n"
821 "\n"
822 "   :return: a new matrix.\n"
823 "   :rtype: :class:`Matrix`\n"
824 );
825 static PyObject *Matrix_to_4x4(MatrixObject *self)
826 {
827         if (BaseMath_ReadCallback(self) == -1)
828                 return NULL;
829
830         if (self->col_size==4 && self->row_size==4) {
831                 return Matrix_CreatePyObject(self->contigPtr, 4, 4, Py_NEW, Py_TYPE(self));
832         }
833         else if (self->col_size==3 && self->row_size==3) {
834                 float mat[4][4];
835                 copy_m4_m3(mat, (float (*)[3])self->contigPtr);
836                 return Matrix_CreatePyObject((float *)mat, 4, 4, Py_NEW, Py_TYPE(self));
837         }
838         /* TODO, 2x2 matrix */
839
840         PyErr_SetString(PyExc_TypeError,
841                         "Matrix.to_4x4(): "
842                         "inappropriate matrix size");
843         return NULL;
844 }
845
846 PyDoc_STRVAR(Matrix_to_3x3_doc,
847 ".. method:: to_3x3()\n"
848 "\n"
849 "   Return a 3x3 copy of this matrix.\n"
850 "\n"
851 "   :return: a new matrix.\n"
852 "   :rtype: :class:`Matrix`\n"
853 );
854 static PyObject *Matrix_to_3x3(MatrixObject *self)
855 {
856         float mat[3][3];
857
858         if (BaseMath_ReadCallback(self) == -1)
859                 return NULL;
860
861         if ((self->col_size < 3) || (self->row_size < 3)) {
862                 PyErr_SetString(PyExc_TypeError,
863                                 "Matrix.to_3x3(): inappropriate matrix size");
864                 return NULL;
865         }
866
867         matrix_as_3x3(mat, self);
868
869         return Matrix_CreatePyObject((float *)mat, 3, 3, Py_NEW, Py_TYPE(self));
870 }
871
872 PyDoc_STRVAR(Matrix_to_translation_doc,
873 ".. method:: to_translation()\n"
874 "\n"
875 "   Return a the translation part of a 4 row matrix.\n"
876 "\n"
877 "   :return: Return a the translation of a matrix.\n"
878 "   :rtype: :class:`Vector`\n"
879 );
880 static PyObject *Matrix_to_translation(MatrixObject *self)
881 {
882         if (BaseMath_ReadCallback(self) == -1)
883                 return NULL;
884
885         if ((self->col_size < 3) || self->row_size < 4) {
886                 PyErr_SetString(PyExc_TypeError,
887                                 "Matrix.to_translation(): "
888                                 "inappropriate matrix size");
889                 return NULL;
890         }
891
892         return Vector_CreatePyObject(MATRIX_ROW_PTR(self, 3), 3, Py_NEW, NULL);
893 }
894
895 PyDoc_STRVAR(Matrix_to_scale_doc,
896 ".. method:: to_scale()\n"
897 "\n"
898 "   Return a the scale part of a 3x3 or 4x4 matrix.\n"
899 "\n"
900 "   :return: Return a the scale of a matrix.\n"
901 "   :rtype: :class:`Vector`\n"
902 "\n"
903 "   .. 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"
904 );
905 static PyObject *Matrix_to_scale(MatrixObject *self)
906 {
907         float rot[3][3];
908         float mat[3][3];
909         float size[3];
910
911         if (BaseMath_ReadCallback(self) == -1)
912                 return NULL;
913
914         /*must be 3-4 cols, 3-4 rows, square matrix*/
915         if ((self->col_size < 3) || (self->row_size < 3)) {
916                 PyErr_SetString(PyExc_TypeError,
917                                 "Matrix.to_scale(): "
918                                 "inappropriate matrix size, 3x3 minimum size");
919                 return NULL;
920         }
921
922         matrix_as_3x3(mat, self);
923
924         /* compatible mat4_to_loc_rot_size */
925         mat3_to_rot_size(rot, size, mat);
926
927         return Vector_CreatePyObject(size, 3, Py_NEW, NULL);
928 }
929
930 /*---------------------------matrix.invert() ---------------------*/
931 PyDoc_STRVAR(Matrix_invert_doc,
932 ".. method:: invert()\n"
933 "\n"
934 "   Set the matrix to its inverse.\n"
935 "\n"
936 "   .. note:: :exc:`ValueError` exception is raised.\n"
937 "\n"
938 "   .. seealso:: <http://en.wikipedia.org/wiki/Inverse_matrix>\n"
939 );
940 static PyObject *Matrix_invert(MatrixObject *self)
941 {
942
943         int x, y, z = 0;
944         float det = 0.0f;
945         float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f,
946                          0.0f, 0.0f, 0.0f, 0.0f,
947                          0.0f, 0.0f, 0.0f, 0.0f,
948                          0.0f, 0.0f, 0.0f, 1.0f};
949
950         if (BaseMath_ReadCallback(self) == -1)
951                 return NULL;
952
953         if (self->row_size != self->col_size) {
954                 PyErr_SetString(PyExc_TypeError,
955                                 "Matrix.invert(ed): "
956                                 "only square matrices are supported");
957                 return NULL;
958         }
959
960         /*calculate the determinant*/
961         det = matrix_determinant_internal(self);
962
963         if (det != 0) {
964                 /*calculate the classical adjoint*/
965                 if (self->row_size == 2) {
966                         mat[0] =  MATRIX_ITEM(self, 1, 1);
967                         mat[1] = -MATRIX_ITEM(self, 0, 1);
968                         mat[2] = -MATRIX_ITEM(self, 1, 0);
969                         mat[3] =  MATRIX_ITEM(self, 0, 0);
970                 }
971                 else if (self->row_size == 3) {
972                         adjoint_m3_m3((float (*)[3]) mat,(float (*)[3])self->contigPtr);
973                 }
974                 else if (self->row_size == 4) {
975                         adjoint_m4_m4((float (*)[4]) mat, (float (*)[4])self->contigPtr);
976                 }
977                 /*divide by determinate*/
978                 for (x = 0; x < (self->row_size * self->col_size); x++) {
979                         mat[x] /= det;
980                 }
981                 /*set values*/
982                 for (x = 0; x < self->row_size; x++) {
983                         for (y = 0; y < self->col_size; y++) {
984                                 MATRIX_ITEM(self, x, y) = mat[z];
985                                 z++;
986                         }
987                 }
988                 /*transpose
989                 Matrix_transpose(self);*/
990         }
991         else {
992                 PyErr_SetString(PyExc_ValueError,
993                                 "Matrix.invert(ed): "
994                                 "matrix does not have an inverse");
995                 return NULL;
996         }
997
998         (void)BaseMath_WriteCallback(self);
999         Py_RETURN_NONE;
1000 }
1001
1002 PyDoc_STRVAR(Matrix_inverted_doc,
1003 ".. method:: inverted()\n"
1004 "\n"
1005 "   Return an inverted copy of the matrix.\n"
1006 "\n"
1007 "   :return: the  inverted matrix.\n"
1008 "   :rtype: :class:`Matrix`\n"
1009 "\n"
1010 "   .. note:: :exc:`ValueError` exception is raised.\n"
1011 );
1012 static PyObject *Matrix_inverted(MatrixObject *self)
1013 {
1014         return matrix__apply_to_copy((PyNoArgsFunction)Matrix_invert, self);
1015 }
1016
1017 PyDoc_STRVAR(Matrix_rotate_doc,
1018 ".. method:: rotate(other)\n"
1019 "\n"
1020 "   Rotates the matrix a by another mathutils value.\n"
1021 "\n"
1022 "   :arg other: rotation component of mathutils value\n"
1023 "   :type other: :class:`Euler`, :class:`Quaternion` or :class:`Matrix`\n"
1024 "\n"
1025 "   .. note:: If any of the columns are not unit length this may not have desired results.\n"
1026 );
1027 static PyObject *Matrix_rotate(MatrixObject *self, PyObject *value)
1028 {
1029         float self_rmat[3][3], other_rmat[3][3], rmat[3][3];
1030
1031         if (BaseMath_ReadCallback(self) == -1)
1032                 return NULL;
1033
1034         if (mathutils_any_to_rotmat(other_rmat, value, "matrix.rotate(value)") == -1)
1035                 return NULL;
1036
1037         if (self->col_size != 3 || self->row_size != 3) {
1038                 PyErr_SetString(PyExc_TypeError,
1039                                 "Matrix.rotate(): "
1040                                 "must have 3x3 dimensions");
1041                 return NULL;
1042         }
1043
1044         matrix_as_3x3(self_rmat, self);
1045         mul_m3_m3m3(rmat, other_rmat, self_rmat);
1046
1047         copy_m3_m3((float (*)[3])(self->contigPtr), rmat);
1048
1049         (void)BaseMath_WriteCallback(self);
1050         Py_RETURN_NONE;
1051 }
1052
1053 /*---------------------------matrix.decompose() ---------------------*/
1054 PyDoc_STRVAR(Matrix_decompose_doc,
1055 ".. method:: decompose()\n"
1056 "\n"
1057 "   Return the location, rotaion and scale components of this matrix.\n"
1058 "\n"
1059 "   :return: loc, rot, scale triple.\n"
1060 "   :rtype: (:class:`Vector`, :class:`Quaternion`, :class:`Vector`)"
1061 );
1062 static PyObject *Matrix_decompose(MatrixObject *self)
1063 {
1064         PyObject *ret;
1065         float loc[3];
1066         float rot[3][3];
1067         float quat[4];
1068         float size[3];
1069
1070         if (self->col_size != 4 || self->row_size != 4) {
1071                 PyErr_SetString(PyExc_TypeError,
1072                                 "Matrix.decompose(): "
1073                                 "inappropriate matrix size - expects 4x4 matrix");
1074                 return NULL;
1075         }
1076
1077         if (BaseMath_ReadCallback(self) == -1)
1078                 return NULL;
1079
1080         mat4_to_loc_rot_size(loc, rot, size, (float (*)[4])self->contigPtr);
1081         mat3_to_quat(quat, rot);
1082
1083         ret= PyTuple_New(3);
1084         PyTuple_SET_ITEM(ret, 0, Vector_CreatePyObject(loc, 3, Py_NEW, NULL));
1085         PyTuple_SET_ITEM(ret, 1, Quaternion_CreatePyObject(quat, Py_NEW, NULL));
1086         PyTuple_SET_ITEM(ret, 2, Vector_CreatePyObject(size, 3, Py_NEW, NULL));
1087
1088         return ret;
1089 }
1090
1091
1092
1093 PyDoc_STRVAR(Matrix_lerp_doc,
1094 ".. function:: lerp(other, factor)\n"
1095 "\n"
1096 "   Returns the interpolation of two matrices.\n"
1097 "\n"
1098 "   :arg other: value to interpolate with.\n"
1099 "   :type other: :class:`Matrix`\n"
1100 "   :arg factor: The interpolation value in [0.0, 1.0].\n"
1101 "   :type factor: float\n"
1102 "   :return: The interpolated rotation.\n"
1103 "   :rtype: :class:`Matrix`\n"
1104 );
1105 static PyObject *Matrix_lerp(MatrixObject *self, PyObject *args)
1106 {
1107         MatrixObject *mat2 = NULL;
1108         float fac, mat[MATRIX_MAX_DIM*MATRIX_MAX_DIM];
1109
1110         if (!PyArg_ParseTuple(args, "O!f:lerp", &matrix_Type, &mat2, &fac))
1111                 return NULL;
1112
1113         if (self->row_size != mat2->row_size || self->col_size != mat2->col_size) {
1114                 PyErr_SetString(PyExc_ValueError,
1115                                 "Matrix.lerp(): "
1116                                 "expects both matrix objects of the same dimensions");
1117                 return NULL;
1118         }
1119
1120         if (BaseMath_ReadCallback(self) == -1 || BaseMath_ReadCallback(mat2) == -1)
1121                 return NULL;
1122
1123         /* TODO, different sized matrix */
1124         if (self->row_size==4 && self->col_size==4) {
1125                 blend_m4_m4m4((float (*)[4])mat, (float (*)[4])self->contigPtr, (float (*)[4])mat2->contigPtr, fac);
1126         }
1127         else if (self->row_size==3 && self->col_size==3) {
1128                 blend_m3_m3m3((float (*)[3])mat, (float (*)[3])self->contigPtr, (float (*)[3])mat2->contigPtr, fac);
1129         }
1130         else {
1131                 PyErr_SetString(PyExc_ValueError,
1132                                 "Matrix.lerp(): "
1133                                 "only 3x3 and 4x4 matrices supported");
1134                 return NULL;
1135         }
1136
1137         return Matrix_CreatePyObject(mat, self->row_size, self->col_size, Py_NEW, Py_TYPE(self));
1138 }
1139
1140 /*---------------------------matrix.determinant() ----------------*/
1141 PyDoc_STRVAR(Matrix_determinant_doc,
1142 ".. method:: determinant()\n"
1143 "\n"
1144 "   Return the determinant of a matrix.\n"
1145 "\n"
1146 "   :return: Return a the determinant of a matrix.\n"
1147 "   :rtype: float\n"
1148 "\n"
1149 "   .. seealso:: <http://en.wikipedia.org/wiki/Determinant>\n"
1150 );
1151 static PyObject *Matrix_determinant(MatrixObject *self)
1152 {
1153         if (BaseMath_ReadCallback(self) == -1)
1154                 return NULL;
1155
1156         if (self->row_size != self->col_size) {
1157                 PyErr_SetString(PyExc_TypeError,
1158                                 "Matrix.determinant(): "
1159                                 "only square matrices are supported");
1160                 return NULL;
1161         }
1162
1163         return PyFloat_FromDouble((double)matrix_determinant_internal(self));
1164 }
1165 /*---------------------------matrix.transpose() ------------------*/
1166 PyDoc_STRVAR(Matrix_transpose_doc,
1167 ".. method:: transpose()\n"
1168 "\n"
1169 "   Set the matrix to its transpose.\n"
1170 "\n"
1171 "   .. seealso:: <http://en.wikipedia.org/wiki/Transpose>\n"
1172 );
1173 static PyObject *Matrix_transpose(MatrixObject *self)
1174 {
1175         if (BaseMath_ReadCallback(self) == -1)
1176                 return NULL;
1177
1178         if (self->row_size != self->col_size) {
1179                 PyErr_SetString(PyExc_TypeError,
1180                                 "Matrix.transpose(d): "
1181                                 "only square matrices are supported");
1182                 return NULL;
1183         }
1184
1185         if (self->row_size == 2) {
1186                 const float t = MATRIX_ITEM(self, 1, 0);
1187                 MATRIX_ITEM(self, 1, 0) = MATRIX_ITEM(self, 0, 1);
1188                 MATRIX_ITEM(self, 0, 1) = t;
1189         }
1190         else if (self->row_size == 3) {
1191                 transpose_m3((float (*)[3])self->contigPtr);
1192         }
1193         else {
1194                 transpose_m4((float (*)[4])self->contigPtr);
1195         }
1196
1197         (void)BaseMath_WriteCallback(self);
1198         Py_RETURN_NONE;
1199 }
1200
1201 PyDoc_STRVAR(Matrix_transposed_doc,
1202 ".. method:: transposed()\n"
1203 "\n"
1204 "   Return a new, transposed matrix.\n"
1205 "\n"
1206 "   :return: a transposed matrix\n"
1207 "   :rtype: :class:`Matrix`\n"
1208 );
1209 static PyObject *Matrix_transposed(MatrixObject *self)
1210 {
1211         return matrix__apply_to_copy((PyNoArgsFunction)Matrix_transpose, self);
1212 }
1213
1214 /*---------------------------matrix.zero() -----------------------*/
1215 PyDoc_STRVAR(Matrix_zero_doc,
1216 ".. method:: zero()\n"
1217 "\n"
1218 "   Set all the matrix values to zero.\n"
1219 "\n"
1220 "   :return: an instance of itself\n"
1221 "   :rtype: :class:`Matrix`\n"
1222 );
1223 static PyObject *Matrix_zero(MatrixObject *self)
1224 {
1225         fill_vn_fl(self->contigPtr, self->row_size * self->col_size, 0.0f);
1226
1227         if (BaseMath_WriteCallback(self) == -1)
1228                 return NULL;
1229
1230         Py_RETURN_NONE;
1231 }
1232 /*---------------------------matrix.identity(() ------------------*/
1233 PyDoc_STRVAR(Matrix_identity_doc,
1234 ".. method:: identity()\n"
1235 "\n"
1236 "   Set the matrix to the identity matrix.\n"
1237 "\n"
1238 "   .. note:: An object with zero location and rotation, a scale of one,\n"
1239 "      will have an identity matrix.\n"
1240 "\n"
1241 "   .. seealso:: <http://en.wikipedia.org/wiki/Identity_matrix>\n"
1242 );
1243 static PyObject *Matrix_identity(MatrixObject *self)
1244 {
1245         if (BaseMath_ReadCallback(self) == -1)
1246                 return NULL;
1247
1248         if (self->row_size != self->col_size) {
1249                 PyErr_SetString(PyExc_TypeError,
1250                                 "Matrix.identity(): "
1251                                 "only square matrices are supported");
1252                 return NULL;
1253         }
1254
1255         if (self->row_size == 2) {
1256                 MATRIX_ITEM(self, 0, 0) = 1.0f;
1257                 MATRIX_ITEM(self, 0, 1) = 0.0f;
1258                 MATRIX_ITEM(self, 1, 0) = 0.0f;
1259                 MATRIX_ITEM(self, 1, 1) = 1.0f;
1260         }
1261         else if (self->row_size == 3) {
1262                 unit_m3((float (*)[3])self->contigPtr);
1263         }
1264         else {
1265                 unit_m4((float (*)[4])self->contigPtr);
1266         }
1267
1268         if (BaseMath_WriteCallback(self) == -1)
1269                 return NULL;
1270
1271         Py_RETURN_NONE;
1272 }
1273
1274 /*---------------------------Matrix.copy() ------------------*/
1275 PyDoc_STRVAR(Matrix_copy_doc,
1276 ".. method:: copy()\n"
1277 "\n"
1278 "   Returns a copy of this matrix.\n"
1279 "\n"
1280 "   :return: an instance of itself\n"
1281 "   :rtype: :class:`Matrix`\n"
1282 );
1283 static PyObject *Matrix_copy(MatrixObject *self)
1284 {
1285         if (BaseMath_ReadCallback(self) == -1)
1286                 return NULL;
1287
1288         return Matrix_CreatePyObject((float (*))self->contigPtr, self->row_size, self->col_size, Py_NEW, Py_TYPE(self));
1289 }
1290
1291 /*----------------------------print object (internal)-------------*/
1292 /*print the object to screen*/
1293 static PyObject *Matrix_repr(MatrixObject *self)
1294 {
1295         int x, y;
1296         PyObject *rows[MATRIX_MAX_DIM]= {NULL};
1297
1298         if (BaseMath_ReadCallback(self) == -1)
1299                 return NULL;
1300
1301         for (x = 0; x < self->row_size; x++) {
1302                 rows[x]= PyTuple_New(self->col_size);
1303                 for (y = 0; y < self->col_size; y++) {
1304                         PyTuple_SET_ITEM(rows[x], y, PyFloat_FromDouble(MATRIX_ITEM(self, x, y)));
1305                 }
1306         }
1307         switch (self->row_size) {
1308         case 2: return PyUnicode_FromFormat("Matrix((%R,\n"
1309                                                                                 "        %R))", rows[0], rows[1]);
1310
1311         case 3: return PyUnicode_FromFormat("Matrix((%R,\n"
1312                                                                                 "        %R,\n"
1313                                                                                 "        %R))", rows[0], rows[1], rows[2]);
1314
1315         case 4: return PyUnicode_FromFormat("Matrix((%R,\n"
1316                                                                                 "        %R,\n"
1317                                                                                 "        %R,\n"
1318                                                                                 "        %R))", rows[0], rows[1], rows[2], rows[3]);
1319         }
1320
1321         Py_FatalError("Matrix(): invalid row size!");
1322         return NULL;
1323 }
1324
1325 static PyObject* Matrix_str(MatrixObject *self)
1326 {
1327         DynStr *ds;
1328         char *ds_buf;
1329         int ds_size;
1330
1331         int row, col, *maxsize;
1332         PyObject *ret;
1333         char dummy_buf[1];
1334
1335         if (BaseMath_ReadCallback(self) == -1)
1336                 return NULL;
1337
1338         ds= BLI_dynstr_new();
1339
1340         maxsize= PyMem_Malloc(self->row_size * sizeof(int));
1341
1342         /* First determine the maximum width for each column */
1343         for (col = 0; col < self->row_size; col++) {
1344                 maxsize[col]= 0;
1345                 for (row = 0; row < self->col_size; row++) {
1346                         int size= BLI_snprintf(dummy_buf, sizeof(dummy_buf), "%.4f", MATRIX_ITEM(self, col, row));
1347                         maxsize[col]= MAX2(maxsize[col], size);
1348                 }
1349         }
1350
1351         /* Now write the unicode string to be printed */
1352         BLI_dynstr_appendf(ds, "<Matrix %dx%d (", self->col_size, self->row_size);
1353         for (row = 0; row < self->col_size; row++) {
1354                 for (col = 0; col < self->row_size; col++) {
1355                         BLI_dynstr_appendf(ds, col ? ", %*.4f" : "%*.4f", maxsize[col], MATRIX_ITEM(self, col, row));
1356                 }
1357                 BLI_dynstr_append(ds, row + 1 != self->col_size ? ")\n             " : ")");
1358         }
1359         BLI_dynstr_append(ds, " >");
1360
1361         ds_size= BLI_dynstr_get_len(ds) + 1; /* space for \n */
1362         ds_buf= PyMem_Malloc(ds_size);
1363         BLI_dynstr_get_cstring_ex(ds, ds_buf);
1364         BLI_dynstr_free(ds);
1365
1366         PyMem_Free(maxsize);
1367         ret= PyUnicode_FromStringAndSize(ds_buf, ds_size);
1368         PyMem_Free(ds_buf);
1369         return ret;
1370 }
1371
1372 static PyObject* Matrix_richcmpr(PyObject *a, PyObject *b, int op)
1373 {
1374         PyObject *res;
1375         int ok= -1; /* zero is true */
1376
1377         if (MatrixObject_Check(a) && MatrixObject_Check(b)) {
1378                 MatrixObject *matA= (MatrixObject*)a;
1379                 MatrixObject *matB= (MatrixObject*)b;
1380
1381                 if (BaseMath_ReadCallback(matA) == -1 || BaseMath_ReadCallback(matB) == -1)
1382                         return NULL;
1383
1384                 ok=     (       (matA->col_size == matB->col_size) &&
1385                                 (matA->row_size == matB->row_size) &&
1386                                 EXPP_VectorsAreEqual(matA->contigPtr, matB->contigPtr, (matA->row_size * matA->col_size), 1)
1387                         ) ? 0 : -1;
1388         }
1389
1390         switch (op) {
1391         case Py_NE:
1392                 ok = !ok; /* pass through */
1393         case Py_EQ:
1394                 res = ok ? Py_False : Py_True;
1395                 break;
1396
1397         case Py_LT:
1398         case Py_LE:
1399         case Py_GT:
1400         case Py_GE:
1401                 res = Py_NotImplemented;
1402                 break;
1403         default:
1404                 PyErr_BadArgument();
1405                 return NULL;
1406         }
1407
1408         return Py_INCREF(res), res;
1409 }
1410
1411 /*---------------------SEQUENCE PROTOCOLS------------------------
1412   ----------------------------len(object)------------------------
1413   sequence length*/
1414 static int Matrix_len(MatrixObject *self)
1415 {
1416         return (self->row_size);
1417 }
1418 /*----------------------------object[]---------------------------
1419   sequence accessor (get)
1420   the wrapped vector gives direct access to the matrix data*/
1421 static PyObject *Matrix_item(MatrixObject *self, int i)
1422 {
1423         if (BaseMath_ReadCallback(self) == -1)
1424                 return NULL;
1425
1426         if (i < 0 || i >= self->row_size) {
1427                 PyErr_SetString(PyExc_IndexError,
1428                                 "matrix[attribute]: "
1429                                 "array index out of range");
1430                 return NULL;
1431         }
1432         return Vector_CreatePyObject_cb((PyObject *)self, self->col_size, mathutils_matrix_vector_cb_index, i);
1433 }
1434 /*----------------------------object[]-------------------------
1435   sequence accessor (set) */
1436
1437 static int Matrix_ass_item(MatrixObject *self, int i, PyObject *value)
1438 {
1439         float vec[4];
1440         if (BaseMath_ReadCallback(self) == -1)
1441                 return -1;
1442
1443         if (i >= self->row_size || i < 0) {
1444                 PyErr_SetString(PyExc_IndexError,
1445                                 "matrix[attribute] = x: bad column");
1446                 return -1;
1447         }
1448
1449         if (mathutils_array_parse(vec, self->col_size, self->col_size, value, "matrix[i] = value assignment") < 0) {
1450                 return -1;
1451         }
1452
1453         memcpy(MATRIX_ROW_PTR(self, i), vec, self->col_size * sizeof(float));
1454
1455         (void)BaseMath_WriteCallback(self);
1456         return 0;
1457 }
1458
1459 /*----------------------------object[z:y]------------------------
1460   sequence slice (get)*/
1461 static PyObject *Matrix_slice(MatrixObject *self, int begin, int end)
1462 {
1463
1464         PyObject *tuple;
1465         int count;
1466
1467         if (BaseMath_ReadCallback(self) == -1)
1468                 return NULL;
1469
1470         CLAMP(begin, 0, self->row_size);
1471         CLAMP(end, 0, self->row_size);
1472         begin= MIN2(begin, end);
1473
1474         tuple= PyTuple_New(end - begin);
1475         for (count= begin; count < end; count++) {
1476                 PyTuple_SET_ITEM(tuple, count - begin,
1477                                 Vector_CreatePyObject_cb((PyObject *)self, self->col_size, mathutils_matrix_vector_cb_index, count));
1478
1479         }
1480
1481         return tuple;
1482 }
1483 /*----------------------------object[z:y]------------------------
1484   sequence slice (set)*/
1485 static int Matrix_ass_slice(MatrixObject *self, int begin, int end, PyObject *value)
1486 {
1487         PyObject *value_fast= NULL;
1488
1489         if (BaseMath_ReadCallback(self) == -1)
1490                 return -1;
1491
1492         CLAMP(begin, 0, self->row_size);
1493         CLAMP(end, 0, self->row_size);
1494         begin = MIN2(begin, end);
1495
1496         /* non list/tuple cases */
1497         if (!(value_fast=PySequence_Fast(value, "matrix[begin:end] = value"))) {
1498                 /* PySequence_Fast sets the error */
1499                 return -1;
1500         }
1501         else {
1502                 const int size= end - begin;
1503                 int i;
1504                 float mat[16];
1505
1506                 if (PySequence_Fast_GET_SIZE(value_fast) != size) {
1507                         Py_DECREF(value_fast);
1508                         PyErr_SetString(PyExc_ValueError,
1509                                         "matrix[begin:end] = []: "
1510                                         "size mismatch in slice assignment");
1511                         return -1;
1512                 }
1513
1514                 /*parse sub items*/
1515                 for (i = 0; i < size; i++) {
1516                         /*parse each sub sequence*/
1517                         PyObject *item= PySequence_Fast_GET_ITEM(value_fast, i);
1518
1519                         if (mathutils_array_parse(&mat[i * self->col_size], self->col_size, self->col_size, item,
1520                                                   "matrix[begin:end] = value assignment") < 0)
1521                         {
1522                                 return -1;
1523                         }
1524                 }
1525
1526                 Py_DECREF(value_fast);
1527
1528                 /*parsed well - now set in matrix*/
1529                 memcpy(self->contigPtr + (begin * self->col_size), mat, sizeof(float) * (size * self->col_size));
1530
1531                 (void)BaseMath_WriteCallback(self);
1532                 return 0;
1533         }
1534 }
1535 /*------------------------NUMERIC PROTOCOLS----------------------
1536   ------------------------obj + obj------------------------------*/
1537 static PyObject *Matrix_add(PyObject *m1, PyObject *m2)
1538 {
1539         float mat[16];
1540         MatrixObject *mat1 = NULL, *mat2 = NULL;
1541
1542         mat1 = (MatrixObject*)m1;
1543         mat2 = (MatrixObject*)m2;
1544
1545         if (!MatrixObject_Check(m1) || !MatrixObject_Check(m2)) {
1546                 PyErr_Format(PyExc_TypeError,
1547                              "Matrix addition: (%s + %s) "
1548                              "invalid type for this operation",
1549                              Py_TYPE(m1)->tp_name, Py_TYPE(m2)->tp_name);
1550                 return NULL;
1551         }
1552
1553         if (BaseMath_ReadCallback(mat1) == -1 || BaseMath_ReadCallback(mat2) == -1)
1554                 return NULL;
1555
1556         if (mat1->row_size != mat2->row_size || mat1->col_size != mat2->col_size) {
1557                 PyErr_SetString(PyExc_TypeError,
1558                                 "Matrix addition: "
1559                                 "matrices must have the same dimensions for this operation");
1560                 return NULL;
1561         }
1562
1563         add_vn_vnvn(mat, mat1->contigPtr, mat2->contigPtr, mat1->row_size * mat1->col_size);
1564
1565         return Matrix_CreatePyObject(mat, mat1->row_size, mat1->col_size, Py_NEW, Py_TYPE(mat1));
1566 }
1567 /*------------------------obj - obj------------------------------
1568   subtraction*/
1569 static PyObject *Matrix_sub(PyObject *m1, PyObject *m2)
1570 {
1571         float mat[16];
1572         MatrixObject *mat1 = NULL, *mat2 = NULL;
1573
1574         mat1 = (MatrixObject*)m1;
1575         mat2 = (MatrixObject*)m2;
1576
1577         if (!MatrixObject_Check(m1) || !MatrixObject_Check(m2)) {
1578                 PyErr_Format(PyExc_TypeError,
1579                              "Matrix subtraction: (%s - %s) "
1580                              "invalid type for this operation",
1581                              Py_TYPE(m1)->tp_name, Py_TYPE(m2)->tp_name
1582                              );
1583                 return NULL;
1584         }
1585
1586         if (BaseMath_ReadCallback(mat1) == -1 || BaseMath_ReadCallback(mat2) == -1)
1587                 return NULL;
1588
1589         if (mat1->row_size != mat2->row_size || mat1->col_size != mat2->col_size) {
1590                 PyErr_SetString(PyExc_TypeError,
1591                                 "Matrix addition: "
1592                                 "matrices must have the same dimensions for this operation");
1593                 return NULL;
1594         }
1595
1596         sub_vn_vnvn(mat, mat1->contigPtr, mat2->contigPtr, mat1->row_size * mat1->col_size);
1597
1598         return Matrix_CreatePyObject(mat, mat1->row_size, mat1->col_size, Py_NEW, Py_TYPE(mat1));
1599 }
1600 /*------------------------obj * obj------------------------------
1601   mulplication*/
1602 static PyObject *matrix_mul_float(MatrixObject *mat, const float scalar)
1603 {
1604         float tmat[16];
1605         mul_vn_vn_fl(tmat, mat->contigPtr, mat->row_size * mat->col_size, scalar);
1606         return Matrix_CreatePyObject(tmat, mat->row_size, mat->col_size, Py_NEW, Py_TYPE(mat));
1607 }
1608
1609 static PyObject *Matrix_mul(PyObject *m1, PyObject *m2)
1610 {
1611         float scalar;
1612
1613         MatrixObject *mat1 = NULL, *mat2 = NULL;
1614
1615         if (MatrixObject_Check(m1)) {
1616                 mat1 = (MatrixObject*)m1;
1617                 if (BaseMath_ReadCallback(mat1) == -1)
1618                         return NULL;
1619         }
1620         if (MatrixObject_Check(m2)) {
1621                 mat2 = (MatrixObject*)m2;
1622                 if (BaseMath_ReadCallback(mat2) == -1)
1623                         return NULL;
1624         }
1625
1626         if (mat1 && mat2) {
1627                 /*MATRIX * MATRIX*/
1628                 float mat[16]= {0.0f, 0.0f, 0.0f, 0.0f,
1629                                                 0.0f, 0.0f, 0.0f, 0.0f,
1630                                                 0.0f, 0.0f, 0.0f, 0.0f,
1631                                                 0.0f, 0.0f, 0.0f, 1.0f};
1632                 double dot = 0.0f;
1633                 int x, y, z;
1634
1635                 for (x = 0; x < mat2->row_size; x++) {
1636                         for (y = 0; y < mat1->col_size; y++) {
1637                                 for (z = 0; z < mat1->row_size; z++) {
1638                                         dot += MATRIX_ITEM(mat1, z, y) * MATRIX_ITEM(mat2, x, z);
1639                                 }
1640                                 mat[((x * mat1->col_size) + y)] = (float)dot;
1641                                 dot = 0.0f;
1642                         }
1643                 }
1644
1645                 return Matrix_CreatePyObject(mat, mat2->row_size, mat1->col_size, Py_NEW, Py_TYPE(mat1));
1646         }
1647         else if (mat2) {
1648                 /*FLOAT/INT * MATRIX */
1649                 if (((scalar= PyFloat_AsDouble(m1)) == -1.0f && PyErr_Occurred())==0) {
1650                         return matrix_mul_float(mat2, scalar);
1651                 }
1652         }
1653         else if (mat1) {
1654                 /*VEC * MATRIX */
1655                 if (VectorObject_Check(m2)) {
1656                         VectorObject *vec2= (VectorObject *)m2;
1657                         float tvec[4];
1658                         if (BaseMath_ReadCallback(vec2) == -1)
1659                                 return NULL;
1660                         if (column_vector_multiplication(tvec, vec2, mat1) == -1) {
1661                                 return NULL;
1662                         }
1663
1664                         return Vector_CreatePyObject(tvec, vec2->size, Py_NEW, Py_TYPE(m2));
1665                 }
1666                 /*FLOAT/INT * MATRIX */
1667                 else if (((scalar= PyFloat_AsDouble(m2)) == -1.0f && PyErr_Occurred())==0) {
1668                         return matrix_mul_float(mat1, scalar);
1669                 }
1670         }
1671         else {
1672                 BLI_assert(!"internal error");
1673         }
1674
1675         PyErr_Format(PyExc_TypeError,
1676                      "Matrix multiplication: "
1677                      "not supported between '%.200s' and '%.200s' types",
1678                      Py_TYPE(m1)->tp_name, Py_TYPE(m2)->tp_name);
1679         return NULL;
1680 }
1681 static PyObject* Matrix_inv(MatrixObject *self)
1682 {
1683         if (BaseMath_ReadCallback(self) == -1)
1684                 return NULL;
1685
1686         return Matrix_invert(self);
1687 }
1688
1689 /*-----------------PROTOCOL DECLARATIONS--------------------------*/
1690 static PySequenceMethods Matrix_SeqMethods = {
1691         (lenfunc) Matrix_len,                                           /* sq_length */
1692         (binaryfunc) NULL,                                                      /* sq_concat */
1693         (ssizeargfunc) NULL,                                            /* sq_repeat */
1694         (ssizeargfunc) Matrix_item,                                     /* sq_item */
1695         (ssizessizeargfunc) NULL,                                       /* sq_slice, deprecated */
1696         (ssizeobjargproc) Matrix_ass_item,                      /* sq_ass_item */
1697         (ssizessizeobjargproc) NULL,                            /* sq_ass_slice, deprecated */
1698         (objobjproc) NULL,                                                      /* sq_contains */
1699         (binaryfunc) NULL,                                                      /* sq_inplace_concat */
1700         (ssizeargfunc) NULL,                                            /* sq_inplace_repeat */
1701 };
1702
1703
1704 static PyObject *Matrix_subscript(MatrixObject* self, PyObject* item)
1705 {
1706         if (PyIndex_Check(item)) {
1707                 Py_ssize_t i;
1708                 i = PyNumber_AsSsize_t(item, PyExc_IndexError);
1709                 if (i == -1 && PyErr_Occurred())
1710                         return NULL;
1711                 if (i < 0)
1712                         i += self->row_size;
1713                 return Matrix_item(self, i);
1714         }
1715         else if (PySlice_Check(item)) {
1716                 Py_ssize_t start, stop, step, slicelength;
1717
1718                 if (PySlice_GetIndicesEx((void *)item, self->row_size, &start, &stop, &step, &slicelength) < 0)
1719                         return NULL;
1720
1721                 if (slicelength <= 0) {
1722                         return PyTuple_New(0);
1723                 }
1724                 else if (step == 1) {
1725                         return Matrix_slice(self, start, stop);
1726                 }
1727                 else {
1728                         PyErr_SetString(PyExc_IndexError,
1729                                         "slice steps not supported with matrices");
1730                         return NULL;
1731                 }
1732         }
1733         else {
1734                 PyErr_Format(PyExc_TypeError,
1735                              "matrix indices must be integers, not %.200s",
1736                              Py_TYPE(item)->tp_name);
1737                 return NULL;
1738         }
1739 }
1740
1741 static int Matrix_ass_subscript(MatrixObject* self, PyObject* item, PyObject* value)
1742 {
1743         if (PyIndex_Check(item)) {
1744                 Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
1745                 if (i == -1 && PyErr_Occurred())
1746                         return -1;
1747                 if (i < 0)
1748                         i += self->row_size;
1749                 return Matrix_ass_item(self, i, value);
1750         }
1751         else if (PySlice_Check(item)) {
1752                 Py_ssize_t start, stop, step, slicelength;
1753
1754                 if (PySlice_GetIndicesEx((void *)item, self->row_size, &start, &stop, &step, &slicelength) < 0)
1755                         return -1;
1756
1757                 if (step == 1)
1758                         return Matrix_ass_slice(self, start, stop, value);
1759                 else {
1760                         PyErr_SetString(PyExc_IndexError,
1761                                         "slice steps not supported with matrices");
1762                         return -1;
1763                 }
1764         }
1765         else {
1766                 PyErr_Format(PyExc_TypeError,
1767                              "matrix indices must be integers, not %.200s",
1768                              Py_TYPE(item)->tp_name);
1769                 return -1;
1770         }
1771 }
1772
1773 static PyMappingMethods Matrix_AsMapping = {
1774         (lenfunc)Matrix_len,
1775         (binaryfunc)Matrix_subscript,
1776         (objobjargproc)Matrix_ass_subscript
1777 };
1778
1779
1780 static PyNumberMethods Matrix_NumMethods = {
1781                 (binaryfunc)    Matrix_add,     /*nb_add*/
1782                 (binaryfunc)    Matrix_sub,     /*nb_subtract*/
1783                 (binaryfunc)    Matrix_mul,     /*nb_multiply*/
1784                 NULL,                                                   /*nb_remainder*/
1785                 NULL,                                                   /*nb_divmod*/
1786                 NULL,                                                   /*nb_power*/
1787                 (unaryfunc)     0,      /*nb_negative*/
1788                 (unaryfunc)     0,      /*tp_positive*/
1789                 (unaryfunc)     0,      /*tp_absolute*/
1790                 (inquiry)       0,      /*tp_bool*/
1791                 (unaryfunc)     Matrix_inv,     /*nb_invert*/
1792                 NULL,                           /*nb_lshift*/
1793                 (binaryfunc)0,  /*nb_rshift*/
1794                 NULL,                           /*nb_and*/
1795                 NULL,                           /*nb_xor*/
1796                 NULL,                           /*nb_or*/
1797                 NULL,                           /*nb_int*/
1798                 NULL,                           /*nb_reserved*/
1799                 NULL,                           /*nb_float*/
1800                 NULL,                           /* nb_inplace_add */
1801                 NULL,                           /* nb_inplace_subtract */
1802                 NULL,                           /* nb_inplace_multiply */
1803                 NULL,                           /* nb_inplace_remainder */
1804                 NULL,                           /* nb_inplace_power */
1805                 NULL,                           /* nb_inplace_lshift */
1806                 NULL,                           /* nb_inplace_rshift */
1807                 NULL,                           /* nb_inplace_and */
1808                 NULL,                           /* nb_inplace_xor */
1809                 NULL,                           /* nb_inplace_or */
1810                 NULL,                           /* nb_floor_divide */
1811                 NULL,                           /* nb_true_divide */
1812                 NULL,                           /* nb_inplace_floor_divide */
1813                 NULL,                           /* nb_inplace_true_divide */
1814                 NULL,                           /* nb_index */
1815 };
1816
1817 static PyObject *Matrix_getRowSize(MatrixObject *self, void *UNUSED(closure))
1818 {
1819         return PyLong_FromLong((long) self->row_size);
1820 }
1821
1822 static PyObject *Matrix_getColSize(MatrixObject *self, void *UNUSED(closure))
1823 {
1824         return PyLong_FromLong((long) self->col_size);
1825 }
1826
1827 static PyObject *Matrix_median_scale_get(MatrixObject *self, void *UNUSED(closure))
1828 {
1829         float mat[3][3];
1830
1831         if (BaseMath_ReadCallback(self) == -1)
1832                 return NULL;
1833
1834         /*must be 3-4 cols, 3-4 rows, square matrix*/
1835         if ((self->col_size < 3) || (self->row_size < 3)) {
1836                 PyErr_SetString(PyExc_AttributeError,
1837                                 "Matrix.median_scale: "
1838                                 "inappropriate matrix size, 3x3 minimum");
1839                 return NULL;
1840         }
1841
1842         matrix_as_3x3(mat, self);
1843
1844         return PyFloat_FromDouble(mat3_to_scale(mat));
1845 }
1846
1847 static PyObject *Matrix_is_negative_get(MatrixObject *self, void *UNUSED(closure))
1848 {
1849         if (BaseMath_ReadCallback(self) == -1)
1850                 return NULL;
1851
1852         /*must be 3-4 cols, 3-4 rows, square matrix*/
1853         if (self->col_size == 4 && self->row_size == 4)
1854                 return PyBool_FromLong(is_negative_m4((float (*)[4])self->contigPtr));
1855         else if (self->col_size == 3 && self->row_size == 3)
1856                 return PyBool_FromLong(is_negative_m3((float (*)[3])self->contigPtr));
1857         else {
1858                 PyErr_SetString(PyExc_AttributeError,
1859                                 "Matrix.is_negative: "
1860                                 "inappropriate matrix size - expects 3x3 or 4x4 matrix");
1861                 return NULL;
1862         }
1863 }
1864
1865 static PyObject *Matrix_is_orthogonal_get(MatrixObject *self, void *UNUSED(closure))
1866 {
1867         if (BaseMath_ReadCallback(self) == -1)
1868                 return NULL;
1869
1870         /*must be 3-4 cols, 3-4 rows, square matrix*/
1871         if (self->col_size == 4 && self->row_size == 4)
1872                 return PyBool_FromLong(is_orthogonal_m4((float (*)[4])self->contigPtr));
1873         else if (self->col_size == 3 && self->row_size == 3)
1874                 return PyBool_FromLong(is_orthogonal_m3((float (*)[3])self->contigPtr));
1875         else {
1876                 PyErr_SetString(PyExc_AttributeError,
1877                                 "Matrix.is_orthogonal: "
1878                                 "inappropriate matrix size - expects 3x3 or 4x4 matrix");
1879                 return NULL;
1880         }
1881 }
1882
1883 /*****************************************************************************/
1884 /* Python attributes get/set structure:                                      */
1885 /*****************************************************************************/
1886 static PyGetSetDef Matrix_getseters[] = {
1887         {(char *)"row_size", (getter)Matrix_getRowSize, (setter)NULL, (char *)"The row size of the matrix (readonly).\n\n:type: int", NULL},
1888         {(char *)"col_size", (getter)Matrix_getColSize, (setter)NULL, (char *)"The column size of the matrix (readonly).\n\n:type: int", NULL},
1889         {(char *)"median_scale", (getter)Matrix_median_scale_get, (setter)NULL, (char *)"The average scale applied to each axis (readonly).\n\n:type: float", NULL},
1890         {(char *)"is_negative", (getter)Matrix_is_negative_get, (setter)NULL, (char *)"True if this matrix results in a negative scale, 3x3 and 4x4 only, (readonly).\n\n:type: bool", NULL},
1891         {(char *)"is_orthogonal", (getter)Matrix_is_orthogonal_get, (setter)NULL, (char *)"True if this matrix is orthogonal, 3x3 and 4x4 only, (readonly).\n\n:type: bool", NULL},
1892         {(char *)"is_wrapped", (getter)BaseMathObject_getWrapped, (setter)NULL, (char *)BaseMathObject_Wrapped_doc, NULL},
1893         {(char *)"owner",(getter)BaseMathObject_getOwner, (setter)NULL, (char *)BaseMathObject_Owner_doc, NULL},
1894         {NULL, NULL, NULL, NULL, NULL}  /* Sentinel */
1895 };
1896
1897 /*-----------------------METHOD DEFINITIONS ----------------------*/
1898 static struct PyMethodDef Matrix_methods[] = {
1899         /* derived values */
1900         {"determinant", (PyCFunction) Matrix_determinant, METH_NOARGS, Matrix_determinant_doc},
1901         {"decompose", (PyCFunction) Matrix_decompose, METH_NOARGS, Matrix_decompose_doc},
1902
1903         /* in place only */
1904         {"zero", (PyCFunction) Matrix_zero, METH_NOARGS, Matrix_zero_doc},
1905         {"identity", (PyCFunction) Matrix_identity, METH_NOARGS, Matrix_identity_doc},
1906
1907         /* operate on original or copy */
1908         {"transpose", (PyCFunction) Matrix_transpose, METH_NOARGS, Matrix_transpose_doc},
1909         {"transposed", (PyCFunction) Matrix_transposed, METH_NOARGS, Matrix_transposed_doc},
1910         {"invert", (PyCFunction) Matrix_invert, METH_NOARGS, Matrix_invert_doc},
1911         {"inverted", (PyCFunction) Matrix_inverted, METH_NOARGS, Matrix_inverted_doc},
1912         {"to_3x3", (PyCFunction) Matrix_to_3x3, METH_NOARGS, Matrix_to_3x3_doc},
1913         // TODO. {"resize_3x3", (PyCFunction) Matrix_resize3x3, METH_NOARGS, Matrix_resize3x3_doc},
1914         {"to_4x4", (PyCFunction) Matrix_to_4x4, METH_NOARGS, Matrix_to_4x4_doc},
1915         {"resize_4x4", (PyCFunction) Matrix_resize_4x4, METH_NOARGS, Matrix_resize_4x4_doc},
1916         {"rotate", (PyCFunction) Matrix_rotate, METH_O, Matrix_rotate_doc},
1917
1918         /* return converted representation */
1919         {"to_euler", (PyCFunction) Matrix_to_euler, METH_VARARGS, Matrix_to_euler_doc},
1920         {"to_quaternion", (PyCFunction) Matrix_to_quaternion, METH_NOARGS, Matrix_to_quaternion_doc},
1921         {"to_scale", (PyCFunction) Matrix_to_scale, METH_NOARGS, Matrix_to_scale_doc},
1922         {"to_translation", (PyCFunction) Matrix_to_translation, METH_NOARGS, Matrix_to_translation_doc},
1923
1924         /* operation between 2 or more types  */
1925         {"lerp", (PyCFunction) Matrix_lerp, METH_VARARGS, Matrix_lerp_doc},
1926         {"copy", (PyCFunction) Matrix_copy, METH_NOARGS, Matrix_copy_doc},
1927         {"__copy__", (PyCFunction) Matrix_copy, METH_NOARGS, Matrix_copy_doc},
1928
1929         /* class methods */
1930         {"Rotation", (PyCFunction) C_Matrix_Rotation, METH_VARARGS | METH_CLASS, C_Matrix_Rotation_doc},
1931         {"Scale", (PyCFunction) C_Matrix_Scale, METH_VARARGS | METH_CLASS, C_Matrix_Scale_doc},
1932         {"Shear", (PyCFunction) C_Matrix_Shear, METH_VARARGS | METH_CLASS, C_Matrix_Shear_doc},
1933         {"Translation", (PyCFunction) C_Matrix_Translation, METH_O | METH_CLASS, C_Matrix_Translation_doc},
1934         {"OrthoProjection", (PyCFunction) C_Matrix_OrthoProjection,  METH_VARARGS | METH_CLASS, C_Matrix_OrthoProjection_doc},
1935         {NULL, NULL, 0, NULL}
1936 };
1937
1938 /*------------------PY_OBECT DEFINITION--------------------------*/
1939 PyDoc_STRVAR(matrix_doc,
1940 "This object gives access to Matrices in Blender."
1941 );
1942 PyTypeObject matrix_Type = {
1943         PyVarObject_HEAD_INIT(NULL, 0)
1944         "mathutils.Matrix",                                     /*tp_name*/
1945         sizeof(MatrixObject),                           /*tp_basicsize*/
1946         0,                                                                      /*tp_itemsize*/
1947         (destructor)BaseMathObject_dealloc,     /*tp_dealloc*/
1948         NULL,                                                           /*tp_print*/
1949         NULL,                                                           /*tp_getattr*/
1950         NULL,                                                           /*tp_setattr*/
1951         NULL,                                                           /*tp_compare*/
1952         (reprfunc) Matrix_repr,                         /*tp_repr*/
1953         &Matrix_NumMethods,                                     /*tp_as_number*/
1954         &Matrix_SeqMethods,                                     /*tp_as_sequence*/
1955         &Matrix_AsMapping,                                      /*tp_as_mapping*/
1956         NULL,                                                           /*tp_hash*/
1957         NULL,                                                           /*tp_call*/
1958         (reprfunc) Matrix_str,                          /*tp_str*/
1959         NULL,                                                           /*tp_getattro*/
1960         NULL,                                                           /*tp_setattro*/
1961         NULL,                                                           /*tp_as_buffer*/
1962         Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
1963         matrix_doc,                                                     /*tp_doc*/
1964         (traverseproc)BaseMathObject_traverse,  //tp_traverse
1965         (inquiry)BaseMathObject_clear,  //tp_clear
1966         (richcmpfunc)Matrix_richcmpr,           /*tp_richcompare*/
1967         0,                                                                      /*tp_weaklistoffset*/
1968         NULL,                                                           /*tp_iter*/
1969         NULL,                                                           /*tp_iternext*/
1970         Matrix_methods,                                         /*tp_methods*/
1971         NULL,                                                           /*tp_members*/
1972         Matrix_getseters,                                       /*tp_getset*/
1973         NULL,                                                           /*tp_base*/
1974         NULL,                                                           /*tp_dict*/
1975         NULL,                                                           /*tp_descr_get*/
1976         NULL,                                                           /*tp_descr_set*/
1977         0,                                                                      /*tp_dictoffset*/
1978         NULL,                                                           /*tp_init*/
1979         NULL,                                                           /*tp_alloc*/
1980         Matrix_new,                                                     /*tp_new*/
1981         NULL,                                                           /*tp_free*/
1982         NULL,                                                           /*tp_is_gc*/
1983         NULL,                                                           /*tp_bases*/
1984         NULL,                                                           /*tp_mro*/
1985         NULL,                                                           /*tp_cache*/
1986         NULL,                                                           /*tp_subclasses*/
1987         NULL,                                                           /*tp_weaklist*/
1988         NULL                                                            /*tp_del*/
1989 };
1990
1991 /* pass Py_WRAP - if vector is a WRAPPER for data allocated by BLENDER
1992  * (i.e. it was allocated elsewhere by MEM_mallocN())
1993  * pass Py_NEW - if vector is not a WRAPPER and managed by PYTHON
1994  * (i.e. it must be created here with PyMEM_malloc()) */
1995 PyObject *Matrix_CreatePyObject(float *mat,
1996                                 const unsigned short row_size, const unsigned short col_size,
1997                                 int type, PyTypeObject *base_type)
1998 {
1999         MatrixObject *self;
2000
2001         /* matrix objects can be any 2-4row x 2-4col matrix */
2002         if (row_size < 2 || row_size > 4 || col_size < 2 || col_size > 4) {
2003                 PyErr_SetString(PyExc_RuntimeError,
2004                                 "Matrix(): "
2005                                 "row and column sizes must be between 2 and 4");
2006                 return NULL;
2007         }
2008
2009         self= base_type ?       (MatrixObject *)base_type->tp_alloc(base_type, 0) :
2010                                                 (MatrixObject *)PyObject_GC_New(MatrixObject, &matrix_Type);
2011
2012         if (self) {
2013                 self->row_size = row_size;
2014                 self->col_size = col_size;
2015
2016                 /* init callbacks as NULL */
2017                 self->cb_user= NULL;
2018                 self->cb_type= self->cb_subtype= 0;
2019
2020                 if (type == Py_WRAP) {
2021                         self->contigPtr = mat;
2022                         self->wrapped = Py_WRAP;
2023                 }
2024                 else if (type == Py_NEW) {
2025                         self->contigPtr = PyMem_Malloc(row_size * col_size * sizeof(float));
2026                         if (self->contigPtr == NULL) { /*allocation failure*/
2027                                 PyErr_SetString(PyExc_MemoryError,
2028                                                 "Matrix(): "
2029                                                 "problem allocating pointer space");
2030                                 return NULL;
2031                         }
2032
2033                         if (mat) {      /*if a float array passed*/
2034                                 memcpy(self->contigPtr, mat, row_size * col_size * sizeof(float));
2035                         }
2036                         else if (row_size == col_size) {
2037                                 /* or if no arguments are passed return identity matrix for square matrices */
2038                                 PyObject *ret_dummy= Matrix_identity(self);
2039                                 Py_DECREF(ret_dummy);
2040                         }
2041                         else {
2042                                 /* otherwise zero everything */
2043                                 memset(self->contigPtr, 0, row_size * col_size * sizeof(float));
2044                         }
2045                         self->wrapped = Py_NEW;
2046                 }
2047                 else {
2048                         Py_FatalError("Matrix(): invalid type!");
2049                         return NULL;
2050                 }
2051         }
2052         return (PyObject *) self;
2053 }
2054
2055 PyObject *Matrix_CreatePyObject_cb(PyObject *cb_user, int rowSize, int colSize, int cb_type, int cb_subtype)
2056 {
2057         MatrixObject *self= (MatrixObject *)Matrix_CreatePyObject(NULL, rowSize, colSize, Py_NEW, NULL);
2058         if (self) {
2059                 Py_INCREF(cb_user);
2060                 self->cb_user=                  cb_user;
2061                 self->cb_type=                  (unsigned char)cb_type;
2062                 self->cb_subtype=               (unsigned char)cb_subtype;
2063                 PyObject_GC_Track(self);
2064         }
2065         return (PyObject *) self;
2066 }