1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16 
17 /** \file
18  * \ingroup pymathutils
19  */
20 
21 #include <Python.h>
22 
23 #include "mathutils.h"
24 
25 #include "BLI_math.h"
26 #include "BLI_utildefines.h"
27 
28 #include "../generic/py_capi_utils.h"
29 #include "../generic/python_utildefines.h"
30 
31 #ifndef MATH_STANDALONE
32 #  include "BLI_dynstr.h"
33 #endif
34 
35 PyDoc_STRVAR(
36     M_Mathutils_doc,
37     "This module provides access to math operations.\n"
38     "\n"
39     ".. note::\n"
40     "\n"
41     "   Classes, methods and attributes that accept vectors also accept other numeric sequences,\n"
42     "   such as tuples, lists.\n"
43     "\n"
44     "The :mod:`mathutils` module provides the following classes:\n"
45     "\n"
46     "- :class:`Color`,\n"
47     "- :class:`Euler`,\n"
48     "- :class:`Matrix`,\n"
49     "- :class:`Quaternion`,\n"
50     "- :class:`Vector`,\n");
mathutils_array_parse_fast(float * array,int size,PyObject * value_fast,const char * error_prefix)51 static int mathutils_array_parse_fast(float *array,
52                                       int size,
53                                       PyObject *value_fast,
54                                       const char *error_prefix)
55 {
56   PyObject *item;
57   PyObject **value_fast_items = PySequence_Fast_ITEMS(value_fast);
58 
59   int i;
60 
61   i = size;
62   do {
63     i--;
64     if (((array[i] = PyFloat_AsDouble((item = value_fast_items[i]))) == -1.0f) &&
65         PyErr_Occurred()) {
66       PyErr_Format(PyExc_TypeError,
67                    "%.200s: sequence index %d expected a number, "
68                    "found '%.200s' type, ",
69                    error_prefix,
70                    i,
71                    Py_TYPE(item)->tp_name);
72       size = -1;
73       break;
74     }
75   } while (i);
76 
77   return size;
78 }
79 
80 /**
81  * helper function that returns a Python ``__hash__``.
82  *
83  * \note consistent with the equivalent tuple of floats (CPython's 'tuplehash')
84  */
mathutils_array_hash(const float * array,size_t array_len)85 Py_hash_t mathutils_array_hash(const float *array, size_t array_len)
86 {
87   int i;
88   Py_uhash_t x; /* Unsigned for defined overflow behavior. */
89   Py_hash_t y;
90   Py_uhash_t mult;
91   Py_ssize_t len;
92 
93   mult = _PyHASH_MULTIPLIER;
94   len = array_len;
95   x = 0x345678UL;
96   i = 0;
97   while (--len >= 0) {
98     y = _Py_HashDouble((double)(array[i++]));
99     if (y == -1) {
100       return -1;
101     }
102     x = (x ^ y) * mult;
103     /* the cast might truncate len; that doesn't change hash stability */
104     mult += (Py_hash_t)(82520UL + len + len);
105   }
106   x += 97531UL;
107   if (x == (Py_uhash_t)-1) {
108     x = -2;
109   }
110   return x;
111 }
112 
113 /* helper function returns length of the 'value', -1 on error */
mathutils_array_parse(float * array,int array_min,int array_max,PyObject * value,const char * error_prefix)114 int mathutils_array_parse(
115     float *array, int array_min, int array_max, PyObject *value, const char *error_prefix)
116 {
117   const uint flag = array_max;
118   int size;
119 
120   array_max &= ~MU_ARRAY_FLAGS;
121 
122 #if 1 /* approx 6x speedup for mathutils types */
123 
124   if ((size = VectorObject_Check(value) ? ((VectorObject *)value)->size : 0) ||
125       (size = EulerObject_Check(value) ? 3 : 0) ||
126       (size = QuaternionObject_Check(value) ? 4 : 0) ||
127       (size = ColorObject_Check(value) ? 3 : 0)) {
128     if (BaseMath_ReadCallback((BaseMathObject *)value) == -1) {
129       return -1;
130     }
131 
132     if (flag & MU_ARRAY_SPILL) {
133       CLAMP_MAX(size, array_max);
134     }
135 
136     if (size > array_max || size < array_min) {
137       if (array_max == array_min) {
138         PyErr_Format(PyExc_ValueError,
139                      "%.200s: sequence size is %d, expected %d",
140                      error_prefix,
141                      size,
142                      array_max);
143       }
144       else {
145         PyErr_Format(PyExc_ValueError,
146                      "%.200s: sequence size is %d, expected [%d - %d]",
147                      error_prefix,
148                      size,
149                      array_min,
150                      array_max);
151       }
152       return -1;
153     }
154 
155     memcpy(array, ((BaseMathObject *)value)->data, size * sizeof(float));
156   }
157   else
158 #endif
159   {
160     PyObject *value_fast = NULL;
161 
162     /* non list/tuple cases */
163     if (!(value_fast = PySequence_Fast(value, error_prefix))) {
164       /* PySequence_Fast sets the error */
165       return -1;
166     }
167 
168     size = PySequence_Fast_GET_SIZE(value_fast);
169 
170     if (flag & MU_ARRAY_SPILL) {
171       CLAMP_MAX(size, array_max);
172     }
173 
174     if (size > array_max || size < array_min) {
175       if (array_max == array_min) {
176         PyErr_Format(PyExc_ValueError,
177                      "%.200s: sequence size is %d, expected %d",
178                      error_prefix,
179                      size,
180                      array_max);
181       }
182       else {
183         PyErr_Format(PyExc_ValueError,
184                      "%.200s: sequence size is %d, expected [%d - %d]",
185                      error_prefix,
186                      size,
187                      array_min,
188                      array_max);
189       }
190       Py_DECREF(value_fast);
191       return -1;
192     }
193 
194     size = mathutils_array_parse_fast(array, size, value_fast, error_prefix);
195     Py_DECREF(value_fast);
196   }
197 
198   if (size != -1) {
199     if (flag & MU_ARRAY_ZERO) {
200       const int size_left = array_max - size;
201       if (size_left) {
202         memset(&array[size], 0, sizeof(float) * size_left);
203       }
204     }
205   }
206 
207   return size;
208 }
209 
210 /* on error, -1 is returned and no allocation is made */
mathutils_array_parse_alloc(float ** array,int array_min,PyObject * value,const char * error_prefix)211 int mathutils_array_parse_alloc(float **array,
212                                 int array_min,
213                                 PyObject *value,
214                                 const char *error_prefix)
215 {
216   int size;
217 
218 #if 1 /* approx 6x speedup for mathutils types */
219 
220   if ((size = VectorObject_Check(value) ? ((VectorObject *)value)->size : 0) ||
221       (size = EulerObject_Check(value) ? 3 : 0) ||
222       (size = QuaternionObject_Check(value) ? 4 : 0) ||
223       (size = ColorObject_Check(value) ? 3 : 0)) {
224     if (BaseMath_ReadCallback((BaseMathObject *)value) == -1) {
225       return -1;
226     }
227 
228     if (size < array_min) {
229       PyErr_Format(PyExc_ValueError,
230                    "%.200s: sequence size is %d, expected > %d",
231                    error_prefix,
232                    size,
233                    array_min);
234       return -1;
235     }
236 
237     *array = PyMem_Malloc(size * sizeof(float));
238     memcpy(*array, ((BaseMathObject *)value)->data, size * sizeof(float));
239     return size;
240   }
241 
242 #endif
243 
244   PyObject *value_fast = NULL;
245   // *array = NULL;
246   int ret;
247 
248   /* non list/tuple cases */
249   if (!(value_fast = PySequence_Fast(value, error_prefix))) {
250     /* PySequence_Fast sets the error */
251     return -1;
252   }
253 
254   size = PySequence_Fast_GET_SIZE(value_fast);
255 
256   if (size < array_min) {
257     Py_DECREF(value_fast);
258     PyErr_Format(PyExc_ValueError,
259                  "%.200s: sequence size is %d, expected > %d",
260                  error_prefix,
261                  size,
262                  array_min);
263     return -1;
264   }
265 
266   *array = PyMem_Malloc(size * sizeof(float));
267 
268   ret = mathutils_array_parse_fast(*array, size, value_fast, error_prefix);
269   Py_DECREF(value_fast);
270 
271   if (ret == -1) {
272     PyMem_Free(*array);
273   }
274 
275   return ret;
276 }
277 
278 /* parse an array of vectors */
mathutils_array_parse_alloc_v(float ** array,int array_dim,PyObject * value,const char * error_prefix)279 int mathutils_array_parse_alloc_v(float **array,
280                                   int array_dim,
281                                   PyObject *value,
282                                   const char *error_prefix)
283 {
284   PyObject *value_fast;
285   const int array_dim_flag = array_dim;
286   int i, size;
287 
288   /* non list/tuple cases */
289   if (!(value_fast = PySequence_Fast(value, error_prefix))) {
290     /* PySequence_Fast sets the error */
291     return -1;
292   }
293 
294   size = PySequence_Fast_GET_SIZE(value_fast);
295 
296   if (size != 0) {
297     PyObject **value_fast_items = PySequence_Fast_ITEMS(value_fast);
298     float *fp;
299 
300     array_dim &= ~MU_ARRAY_FLAGS;
301 
302     fp = *array = PyMem_Malloc(size * array_dim * sizeof(float));
303 
304     for (i = 0; i < size; i++, fp += array_dim) {
305       PyObject *item = value_fast_items[i];
306 
307       if (mathutils_array_parse(fp, array_dim, array_dim_flag, item, error_prefix) == -1) {
308         PyMem_Free(*array);
309         *array = NULL;
310         size = -1;
311         break;
312       }
313     }
314   }
315 
316   Py_DECREF(value_fast);
317   return size;
318 }
319 
320 /* Parse an sequence array_dim integers into array. */
mathutils_int_array_parse(int * array,int array_dim,PyObject * value,const char * error_prefix)321 int mathutils_int_array_parse(int *array, int array_dim, PyObject *value, const char *error_prefix)
322 {
323   int size, i;
324   PyObject *value_fast, **value_fast_items, *item;
325 
326   if (!(value_fast = PySequence_Fast(value, error_prefix))) {
327     /* PySequence_Fast sets the error */
328     return -1;
329   }
330 
331   if ((size = PySequence_Fast_GET_SIZE(value_fast)) != array_dim) {
332     PyErr_Format(PyExc_ValueError,
333                  "%.200s: sequence size is %d, expected %d",
334                  error_prefix,
335                  size,
336                  array_dim);
337     Py_DECREF(value_fast);
338     return -1;
339   }
340 
341   value_fast_items = PySequence_Fast_ITEMS(value_fast);
342   i = size;
343   while (i > 0) {
344     i--;
345     if (((array[i] = PyC_Long_AsI32((item = value_fast_items[i]))) == -1) && PyErr_Occurred()) {
346       PyErr_Format(PyExc_TypeError, "%.200s: sequence index %d expected an int", error_prefix, i);
347       size = -1;
348       break;
349     }
350   }
351   Py_DECREF(value_fast);
352 
353   return size;
354 }
355 
356 /* Parse sequence of array_dim sequences of integers and return allocated result. */
mathutils_array_parse_alloc_vi(int ** array,int array_dim,PyObject * value,const char * error_prefix)357 int mathutils_array_parse_alloc_vi(int **array,
358                                    int array_dim,
359                                    PyObject *value,
360                                    const char *error_prefix)
361 {
362   PyObject *value_fast;
363   int i, size;
364 
365   if (!(value_fast = PySequence_Fast(value, error_prefix))) {
366     /* PySequence_Fast sets the error */
367     return -1;
368   }
369 
370   size = PySequence_Fast_GET_SIZE(value_fast);
371 
372   if (size != 0) {
373     PyObject **value_fast_items = PySequence_Fast_ITEMS(value_fast);
374     int *ip;
375 
376     ip = *array = PyMem_Malloc(size * array_dim * sizeof(int));
377 
378     for (i = 0; i < size; i++, ip += array_dim) {
379       PyObject *item = value_fast_items[i];
380 
381       if (mathutils_int_array_parse(ip, array_dim, item, error_prefix) == -1) {
382         PyMem_Free(*array);
383         *array = NULL;
384         size = -1;
385         break;
386       }
387     }
388   }
389 
390   Py_DECREF(value_fast);
391   return size;
392 }
393 
394 /* Parse sequence of variable-length sequences of int and return allocated
395  * triple of arrays to represent the result:
396  * The flattened sequences are put into *array.
397  * The start index of each sequence goes into start_table.
398  * The length of each index goes into len_table.
399  */
mathutils_array_parse_alloc_viseq(int ** array,int ** start_table,int ** len_table,PyObject * value,const char * error_prefix)400 int mathutils_array_parse_alloc_viseq(
401     int **array, int **start_table, int **len_table, PyObject *value, const char *error_prefix)
402 {
403   PyObject *value_fast, *subseq;
404   int i, size, start, subseq_len;
405   int *ip;
406 
407   *array = NULL;
408   *start_table = NULL;
409   *len_table = NULL;
410   if (!(value_fast = PySequence_Fast(value, error_prefix))) {
411     /* PySequence_Fast sets the error */
412     return -1;
413   }
414 
415   size = PySequence_Fast_GET_SIZE(value_fast);
416 
417   if (size != 0) {
418     PyObject **value_fast_items = PySequence_Fast_ITEMS(value_fast);
419 
420     *start_table = PyMem_Malloc(size * sizeof(int));
421     *len_table = PyMem_Malloc(size * sizeof(int));
422 
423     /* First pass to set starts and len, and calculate size of array needed */
424     start = 0;
425     for (i = 0; i < size; i++) {
426       subseq = value_fast_items[i];
427       if ((subseq_len = (int)PySequence_Size(subseq)) == -1) {
428         PyErr_Format(
429             PyExc_ValueError, "%.200s: sequence expected to have subsequences", error_prefix);
430         PyMem_Free(*start_table);
431         PyMem_Free(*len_table);
432         Py_DECREF(value_fast);
433         *start_table = NULL;
434         *len_table = NULL;
435         return -1;
436       }
437       (*start_table)[i] = start;
438       (*len_table)[i] = subseq_len;
439       start += subseq_len;
440     }
441 
442     ip = *array = PyMem_Malloc(start * sizeof(int));
443 
444     /* Second pass to parse the subsequences into array */
445     for (i = 0; i < size; i++) {
446       subseq = value_fast_items[i];
447       subseq_len = (*len_table)[i];
448 
449       if (mathutils_int_array_parse(ip, subseq_len, subseq, error_prefix) == -1) {
450         PyMem_Free(*array);
451         PyMem_Free(*start_table);
452         PyMem_Free(*len_table);
453         *array = NULL;
454         *len_table = NULL;
455         *start_table = NULL;
456         size = -1;
457         break;
458       }
459       ip += subseq_len;
460     }
461   }
462 
463   Py_DECREF(value_fast);
464   return size;
465 }
466 
mathutils_any_to_rotmat(float rmat[3][3],PyObject * value,const char * error_prefix)467 int mathutils_any_to_rotmat(float rmat[3][3], PyObject *value, const char *error_prefix)
468 {
469   if (EulerObject_Check(value)) {
470     if (BaseMath_ReadCallback((BaseMathObject *)value) == -1) {
471       return -1;
472     }
473 
474     eulO_to_mat3(rmat, ((EulerObject *)value)->eul, ((EulerObject *)value)->order);
475     return 0;
476   }
477   if (QuaternionObject_Check(value)) {
478     if (BaseMath_ReadCallback((BaseMathObject *)value) == -1) {
479       return -1;
480     }
481 
482     float tquat[4];
483     normalize_qt_qt(tquat, ((QuaternionObject *)value)->quat);
484     quat_to_mat3(rmat, tquat);
485     return 0;
486   }
487   if (MatrixObject_Check(value)) {
488     if (BaseMath_ReadCallback((BaseMathObject *)value) == -1) {
489       return -1;
490     }
491     if (((MatrixObject *)value)->num_row < 3 || ((MatrixObject *)value)->num_col < 3) {
492       PyErr_Format(
493           PyExc_ValueError, "%.200s: matrix must have minimum 3x3 dimensions", error_prefix);
494       return -1;
495     }
496 
497     matrix_as_3x3(rmat, (MatrixObject *)value);
498     normalize_m3(rmat);
499     return 0;
500   }
501 
502   PyErr_Format(PyExc_TypeError,
503                "%.200s: expected a Euler, Quaternion or Matrix type, "
504                "found %.200s",
505                error_prefix,
506                Py_TYPE(value)->tp_name);
507   return -1;
508 }
509 
510 /* ----------------------------------MATRIX FUNCTIONS-------------------- */
511 
512 /* Utility functions */
513 
514 /* LomontRRDCompare4, Ever Faster Float Comparisons by Randy Dillon */
515 /* XXX We may want to use 'safer' BLI's compare_ff_relative ultimately?
516  * LomontRRDCompare4() is an optimized version of Dawson's AlmostEqual2sComplement()
517  * (see [1] and [2]).
518  * Dawson himself now claims this is not a 'safe' thing to do
519  * (pushing ULP method beyond its limits),
520  * an recommends using work from [3] instead, which is done in BLI func...
521  *
522  * [1] http://www.randydillon.org/Papers/2007/everfast.htm
523  * [2] http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
524  * [3] https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/
525  * instead.
526  */
527 #define SIGNMASK(i) (-(int)(((uint)(i)) >> 31))
528 
EXPP_FloatsAreEqual(float af,float bf,int maxDiff)529 int EXPP_FloatsAreEqual(float af, float bf, int maxDiff)
530 {
531   /* solid, fast routine across all platforms
532    * with constant time behavior */
533   const int ai = *(int *)(&af);
534   const int bi = *(int *)(&bf);
535   const int test = SIGNMASK(ai ^ bi);
536   int diff, v1, v2;
537 
538   BLI_assert((0 == test) || (0xFFFFFFFF == test));
539   diff = (ai ^ (test & 0x7fffffff)) - bi;
540   v1 = maxDiff + diff;
541   v2 = maxDiff - diff;
542   return (v1 | v2) >= 0;
543 }
544 
545 /*---------------------- EXPP_VectorsAreEqual -------------------------
546  * Builds on EXPP_FloatsAreEqual to test vectors */
EXPP_VectorsAreEqual(const float * vecA,const float * vecB,int size,int floatSteps)547 int EXPP_VectorsAreEqual(const float *vecA, const float *vecB, int size, int floatSteps)
548 {
549   int x;
550   for (x = 0; x < size; x++) {
551     if (EXPP_FloatsAreEqual(vecA[x], vecB[x], floatSteps) == 0) {
552       return 0;
553     }
554   }
555   return 1;
556 }
557 
558 #ifndef MATH_STANDALONE
559 /* dynstr as python string utility functions, frees 'ds'! */
mathutils_dynstr_to_py(struct DynStr * ds)560 PyObject *mathutils_dynstr_to_py(struct DynStr *ds)
561 {
562   const int ds_len = BLI_dynstr_get_len(ds); /* space for \0 */
563   char *ds_buf = PyMem_Malloc(ds_len + 1);
564   PyObject *ret;
565   BLI_dynstr_get_cstring_ex(ds, ds_buf);
566   BLI_dynstr_free(ds);
567   ret = PyUnicode_FromStringAndSize(ds_buf, ds_len);
568   PyMem_Free(ds_buf);
569   return ret;
570 }
571 #endif
572 
573 /* Mathutils Callbacks */
574 
575 /* For mathutils internal use only,
576  * eventually should re-alloc but to start with we only have a few users. */
577 #define MATHUTILS_TOT_CB 17
578 static Mathutils_Callback *mathutils_callbacks[MATHUTILS_TOT_CB] = {NULL};
579 
Mathutils_RegisterCallback(Mathutils_Callback * cb)580 uchar Mathutils_RegisterCallback(Mathutils_Callback *cb)
581 {
582   uchar i;
583 
584   /* find the first free slot */
585   for (i = 0; mathutils_callbacks[i]; i++) {
586     if (mathutils_callbacks[i] == cb) {
587       /* already registered? */
588       return i;
589     }
590   }
591 
592   BLI_assert(i + 1 < MATHUTILS_TOT_CB);
593 
594   mathutils_callbacks[i] = cb;
595   return i;
596 }
597 
598 /* use macros to check for NULL */
_BaseMathObject_ReadCallback(BaseMathObject * self)599 int _BaseMathObject_ReadCallback(BaseMathObject *self)
600 {
601   Mathutils_Callback *cb = mathutils_callbacks[self->cb_type];
602   if (LIKELY(cb->get(self, self->cb_subtype) != -1)) {
603     return 0;
604   }
605 
606   if (!PyErr_Occurred()) {
607     PyErr_Format(PyExc_RuntimeError, "%s read, user has become invalid", Py_TYPE(self)->tp_name);
608   }
609   return -1;
610 }
611 
_BaseMathObject_WriteCallback(BaseMathObject * self)612 int _BaseMathObject_WriteCallback(BaseMathObject *self)
613 {
614   Mathutils_Callback *cb = mathutils_callbacks[self->cb_type];
615   if (LIKELY(cb->set(self, self->cb_subtype) != -1)) {
616     return 0;
617   }
618 
619   if (!PyErr_Occurred()) {
620     PyErr_Format(PyExc_RuntimeError, "%s write, user has become invalid", Py_TYPE(self)->tp_name);
621   }
622   return -1;
623 }
624 
_BaseMathObject_ReadIndexCallback(BaseMathObject * self,int index)625 int _BaseMathObject_ReadIndexCallback(BaseMathObject *self, int index)
626 {
627   Mathutils_Callback *cb = mathutils_callbacks[self->cb_type];
628   if (LIKELY(cb->get_index(self, self->cb_subtype, index) != -1)) {
629     return 0;
630   }
631 
632   if (!PyErr_Occurred()) {
633     PyErr_Format(
634         PyExc_RuntimeError, "%s read index, user has become invalid", Py_TYPE(self)->tp_name);
635   }
636   return -1;
637 }
638 
_BaseMathObject_WriteIndexCallback(BaseMathObject * self,int index)639 int _BaseMathObject_WriteIndexCallback(BaseMathObject *self, int index)
640 {
641   Mathutils_Callback *cb = mathutils_callbacks[self->cb_type];
642   if (LIKELY(cb->set_index(self, self->cb_subtype, index) != -1)) {
643     return 0;
644   }
645 
646   if (!PyErr_Occurred()) {
647     PyErr_Format(
648         PyExc_RuntimeError, "%s write index, user has become invalid", Py_TYPE(self)->tp_name);
649   }
650   return -1;
651 }
652 
_BaseMathObject_RaiseFrozenExc(const BaseMathObject * self)653 void _BaseMathObject_RaiseFrozenExc(const BaseMathObject *self)
654 {
655   PyErr_Format(PyExc_TypeError, "%s is frozen (immutable)", Py_TYPE(self)->tp_name);
656 }
657 
_BaseMathObject_RaiseNotFrozenExc(const BaseMathObject * self)658 void _BaseMathObject_RaiseNotFrozenExc(const BaseMathObject *self)
659 {
660   PyErr_Format(
661       PyExc_TypeError, "%s is not frozen (mutable), call freeze first", Py_TYPE(self)->tp_name);
662 }
663 
664 /* BaseMathObject generic functions for all mathutils types */
665 char BaseMathObject_owner_doc[] = "The item this is wrapping or None  (read-only).";
BaseMathObject_owner_get(BaseMathObject * self,void * UNUSED (closure))666 PyObject *BaseMathObject_owner_get(BaseMathObject *self, void *UNUSED(closure))
667 {
668   PyObject *ret = self->cb_user ? self->cb_user : Py_None;
669   return Py_INCREF_RET(ret);
670 }
671 
672 char BaseMathObject_is_wrapped_doc[] =
673     "True when this object wraps external data (read-only).\n\n:type: boolean";
BaseMathObject_is_wrapped_get(BaseMathObject * self,void * UNUSED (closure))674 PyObject *BaseMathObject_is_wrapped_get(BaseMathObject *self, void *UNUSED(closure))
675 {
676   return PyBool_FromLong((self->flag & BASE_MATH_FLAG_IS_WRAP) != 0);
677 }
678 
679 char BaseMathObject_is_frozen_doc[] =
680     "True when this object has been frozen (read-only).\n\n:type: boolean";
BaseMathObject_is_frozen_get(BaseMathObject * self,void * UNUSED (closure))681 PyObject *BaseMathObject_is_frozen_get(BaseMathObject *self, void *UNUSED(closure))
682 {
683   return PyBool_FromLong((self->flag & BASE_MATH_FLAG_IS_FROZEN) != 0);
684 }
685 
686 char BaseMathObject_freeze_doc[] =
687     ".. function:: freeze()\n"
688     "\n"
689     "   Make this object immutable.\n"
690     "\n"
691     "   After this the object can be hashed, used in dictionaries & sets.\n"
692     "\n"
693     "   :return: An instance of this object.\n";
BaseMathObject_freeze(BaseMathObject * self)694 PyObject *BaseMathObject_freeze(BaseMathObject *self)
695 {
696   if ((self->flag & BASE_MATH_FLAG_IS_WRAP) || (self->cb_user != NULL)) {
697     PyErr_SetString(PyExc_TypeError, "Cannot freeze wrapped/owned data");
698     return NULL;
699   }
700 
701   self->flag |= BASE_MATH_FLAG_IS_FROZEN;
702 
703   return Py_INCREF_RET((PyObject *)self);
704 }
705 
BaseMathObject_traverse(BaseMathObject * self,visitproc visit,void * arg)706 int BaseMathObject_traverse(BaseMathObject *self, visitproc visit, void *arg)
707 {
708   Py_VISIT(self->cb_user);
709   return 0;
710 }
711 
BaseMathObject_clear(BaseMathObject * self)712 int BaseMathObject_clear(BaseMathObject *self)
713 {
714   Py_CLEAR(self->cb_user);
715   return 0;
716 }
717 
BaseMathObject_dealloc(BaseMathObject * self)718 void BaseMathObject_dealloc(BaseMathObject *self)
719 {
720   /* only free non wrapped */
721   if ((self->flag & BASE_MATH_FLAG_IS_WRAP) == 0) {
722     PyMem_Free(self->data);
723   }
724 
725   if (self->cb_user) {
726     PyObject_GC_UnTrack(self);
727     BaseMathObject_clear(self);
728   }
729 
730   Py_TYPE(self)->tp_free(self);  // PyObject_DEL(self); /* breaks subtypes. */
731 }
732 
733 /*----------------------------MODULE INIT-------------------------*/
734 static struct PyMethodDef M_Mathutils_methods[] = {
735     {NULL, NULL, 0, NULL},
736 };
737 
738 static struct PyModuleDef M_Mathutils_module_def = {
739     PyModuleDef_HEAD_INIT,
740     "mathutils",         /* m_name */
741     M_Mathutils_doc,     /* m_doc */
742     0,                   /* m_size */
743     M_Mathutils_methods, /* m_methods */
744     NULL,                /* m_reload */
745     NULL,                /* m_traverse */
746     NULL,                /* m_clear */
747     NULL,                /* m_free */
748 };
749 
750 /* submodules only */
751 #include "mathutils_geometry.h"
752 #include "mathutils_interpolate.h"
753 #ifndef MATH_STANDALONE
754 #  include "mathutils_bvhtree.h"
755 #  include "mathutils_kdtree.h"
756 #  include "mathutils_noise.h"
757 #endif
758 
PyInit_mathutils(void)759 PyMODINIT_FUNC PyInit_mathutils(void)
760 {
761   PyObject *mod;
762   PyObject *submodule;
763   PyObject *sys_modules = PyImport_GetModuleDict();
764 
765   if (PyType_Ready(&vector_Type) < 0) {
766     return NULL;
767   }
768   if (PyType_Ready(&matrix_Type) < 0) {
769     return NULL;
770   }
771   if (PyType_Ready(&matrix_access_Type) < 0) {
772     return NULL;
773   }
774   if (PyType_Ready(&euler_Type) < 0) {
775     return NULL;
776   }
777   if (PyType_Ready(&quaternion_Type) < 0) {
778     return NULL;
779   }
780   if (PyType_Ready(&color_Type) < 0) {
781     return NULL;
782   }
783 
784   mod = PyModule_Create(&M_Mathutils_module_def);
785 
786   /* each type has its own new() function */
787   PyModule_AddObject(mod, vector_Type.tp_name, (PyObject *)&vector_Type);
788   PyModule_AddObject(mod, matrix_Type.tp_name, (PyObject *)&matrix_Type);
789   PyModule_AddObject(mod, euler_Type.tp_name, (PyObject *)&euler_Type);
790   PyModule_AddObject(mod, quaternion_Type.tp_name, (PyObject *)&quaternion_Type);
791   PyModule_AddObject(mod, color_Type.tp_name, (PyObject *)&color_Type);
792 
793   /* submodule */
794   PyModule_AddObject(mod, "geometry", (submodule = PyInit_mathutils_geometry()));
795   /* XXX, python doesn't do imports with this usefully yet
796    * 'from mathutils.geometry import PolyFill'
797    * ...fails without this. */
798   PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule);
799 
800   PyModule_AddObject(mod, "interpolate", (submodule = PyInit_mathutils_interpolate()));
801   /* XXX, python doesn't do imports with this usefully yet
802    * 'from mathutils.geometry import PolyFill'
803    * ...fails without this. */
804   PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule);
805 
806 #ifndef MATH_STANDALONE
807   /* Noise submodule */
808   PyModule_AddObject(mod, "noise", (submodule = PyInit_mathutils_noise()));
809   PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule);
810 
811   /* BVHTree submodule */
812   PyModule_AddObject(mod, "bvhtree", (submodule = PyInit_mathutils_bvhtree()));
813   PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule);
814 
815   /* KDTree_3d submodule */
816   PyModule_AddObject(mod, "kdtree", (submodule = PyInit_mathutils_kdtree()));
817   PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule);
818 #endif
819 
820   mathutils_matrix_row_cb_index = Mathutils_RegisterCallback(&mathutils_matrix_row_cb);
821   mathutils_matrix_col_cb_index = Mathutils_RegisterCallback(&mathutils_matrix_col_cb);
822   mathutils_matrix_translation_cb_index = Mathutils_RegisterCallback(
823       &mathutils_matrix_translation_cb);
824 
825   return mod;
826 }
827