Blender V4.3
mathutils_Vector.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include <algorithm>
10
11#include <Python.h>
12
13#include "mathutils.hh"
14
15#include "BLI_math_base_safe.h"
16#include "BLI_math_matrix.h"
17#include "BLI_math_rotation.h"
18#include "BLI_math_vector.h"
19#include "BLI_utildefines.h"
20
22
23#ifndef MATH_STANDALONE
24# include "BLI_dynstr.h"
25#endif
26
32#define MAX_DIMENSIONS 4
33
39#define SWIZZLE_BITS_PER_AXIS 3
40#define SWIZZLE_VALID_AXIS 0x4
41#define SWIZZLE_AXIS 0x3
42
43static PyObject *Vector_copy(VectorObject *self);
44static PyObject *Vector_deepcopy(VectorObject *self, PyObject *args);
45
46/* -------------------------------------------------------------------- */
60 VectorObject *vec,
61 MatrixObject *mat)
62{
63 float vec_cpy[MAX_DIMENSIONS];
64 int row, col, z = 0, vec_num = vec->vec_num;
65
66 if (mat->row_num != vec_num) {
67 if (mat->row_num == 4 && vec_num == 3) {
68 vec_cpy[3] = 1.0f;
69 }
70 else {
71 PyErr_SetString(PyExc_ValueError,
72 "vector * matrix: matrix column size "
73 "and the vector size must be the same");
74 return -1;
75 }
76 }
77
78 if (BaseMath_ReadCallback(vec) == -1 || BaseMath_ReadCallback(mat) == -1) {
79 return -1;
80 }
81
82 memcpy(vec_cpy, vec->vec, vec_num * sizeof(float));
83
84 r_vec[3] = 1.0f;
85 /* Multiplication. */
86 for (col = 0; col < mat->col_num; col++) {
87 double dot = 0.0;
88 for (row = 0; row < mat->row_num; row++) {
89 dot += double(MATRIX_ITEM(mat, row, col) * vec_cpy[row]);
90 }
91 r_vec[z++] = float(dot);
92 }
93 return 0;
94}
95
96static PyObject *vec__apply_to_copy(PyObject *(*vec_func)(VectorObject *), VectorObject *self)
97{
98 PyObject *ret = Vector_copy(self);
99 PyObject *ret_dummy = vec_func((VectorObject *)ret);
100 if (ret_dummy) {
101 Py_DECREF(ret_dummy);
102 return (PyObject *)ret;
103 }
104 /* error */
105 Py_DECREF(ret);
106 return nullptr;
107}
108
110static PyObject *Vector_to_tuple_ex(VectorObject *self, int ndigits)
111{
112 PyObject *ret;
113 int i;
114
115 ret = PyTuple_New(self->vec_num);
116
117 if (ndigits >= 0) {
118 for (i = 0; i < self->vec_num; i++) {
119 PyTuple_SET_ITEM(ret, i, PyFloat_FromDouble(double_round(double(self->vec[i]), ndigits)));
120 }
121 }
122 else {
123 for (i = 0; i < self->vec_num; i++) {
124 PyTuple_SET_ITEM(ret, i, PyFloat_FromDouble(self->vec[i]));
125 }
126 }
127
128 return ret;
129}
130
133/* -------------------------------------------------------------------- */
141static PyObject *Vector_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
142{
143 float *vec = nullptr;
144 int vec_num = 3; /* default to a 3D vector */
145
146 if (kwds && PyDict_Size(kwds)) {
147 PyErr_SetString(PyExc_TypeError,
148 "Vector(): "
149 "takes no keyword args");
150 return nullptr;
151 }
152
153 switch (PyTuple_GET_SIZE(args)) {
154 case 0:
155 vec = static_cast<float *>(PyMem_Malloc(vec_num * sizeof(float)));
156
157 if (vec == nullptr) {
158 PyErr_SetString(PyExc_MemoryError,
159 "Vector(): "
160 "problem allocating pointer space");
161 return nullptr;
162 }
163
164 copy_vn_fl(vec, vec_num, 0.0f);
165 break;
166 case 1:
167 if ((vec_num = mathutils_array_parse_alloc(
168 &vec, 2, PyTuple_GET_ITEM(args, 0), "mathutils.Vector()")) == -1)
169 {
170 return nullptr;
171 }
172 break;
173 default:
174 PyErr_SetString(PyExc_TypeError,
175 "mathutils.Vector(): "
176 "more than a single arg given");
177 return nullptr;
178 }
179 return Vector_CreatePyObject_alloc(vec, vec_num, type);
180}
181
184/* -------------------------------------------------------------------- */
189 /* Wrap. */
190 C_Vector_Fill_doc,
191 ".. classmethod:: Fill(size, fill=0.0)\n"
192 "\n"
193 " Create a vector of length size with all values set to fill.\n"
194 "\n"
195 " :arg size: The length of the vector to be created.\n"
196 " :type size: int\n"
197 " :arg fill: The value used to fill the vector.\n"
198 " :type fill: float\n");
199static PyObject *C_Vector_Fill(PyObject *cls, PyObject *args)
200{
201 float *vec;
202 int vec_num;
203 float fill = 0.0f;
204
205 if (!PyArg_ParseTuple(args, "i|f:Vector.Fill", &vec_num, &fill)) {
206 return nullptr;
207 }
208
209 if (vec_num < 2) {
210 PyErr_SetString(PyExc_RuntimeError, "Vector(): invalid size");
211 return nullptr;
212 }
213
214 vec = static_cast<float *>(PyMem_Malloc(vec_num * sizeof(float)));
215
216 if (vec == nullptr) {
217 PyErr_SetString(PyExc_MemoryError,
218 "Vector.Fill(): "
219 "problem allocating pointer space");
220 return nullptr;
221 }
222
223 copy_vn_fl(vec, vec_num, fill);
224
225 return Vector_CreatePyObject_alloc(vec, vec_num, (PyTypeObject *)cls);
226}
227
229 /* Wrap. */
230 C_Vector_Range_doc,
231 ".. classmethod:: Range(start, stop, step=1)\n"
232 "\n"
233 " Create a filled with a range of values.\n"
234 "\n"
235 " :arg start: The start of the range used to fill the vector.\n"
236 " :type start: int\n"
237 " :arg stop: The end of the range used to fill the vector.\n"
238 " :type stop: int\n"
239 " :arg step: The step between successive values in the vector.\n"
240 " :type step: int\n");
241static PyObject *C_Vector_Range(PyObject *cls, PyObject *args)
242{
243 float *vec;
244 int stop, vec_num;
245 int start = 0;
246 int step = 1;
247
248 if (!PyArg_ParseTuple(args, "i|ii:Vector.Range", &start, &stop, &step)) {
249 return nullptr;
250 }
251
252 switch (PyTuple_GET_SIZE(args)) {
253 case 1:
254 vec_num = start;
255 start = 0;
256 break;
257 case 2:
258 if (start >= stop) {
259 PyErr_SetString(PyExc_RuntimeError,
260 "Start value is larger "
261 "than the stop value");
262 return nullptr;
263 }
264
265 vec_num = stop - start;
266 break;
267 default:
268 if (start >= stop) {
269 PyErr_SetString(PyExc_RuntimeError,
270 "Start value is larger "
271 "than the stop value");
272 return nullptr;
273 }
274
275 vec_num = (stop - start);
276
277 if ((vec_num % step) != 0) {
278 vec_num += step;
279 }
280
281 vec_num /= step;
282
283 break;
284 }
285
286 if (vec_num < 2) {
287 PyErr_SetString(PyExc_RuntimeError, "Vector(): invalid size");
288 return nullptr;
289 }
290
291 vec = static_cast<float *>(PyMem_Malloc(vec_num * sizeof(float)));
292
293 if (vec == nullptr) {
294 PyErr_SetString(PyExc_MemoryError,
295 "Vector.Range(): "
296 "problem allocating pointer space");
297 return nullptr;
298 }
299
300 range_vn_fl(vec, vec_num, float(start), float(step));
301
302 return Vector_CreatePyObject_alloc(vec, vec_num, (PyTypeObject *)cls);
303}
304
306 /* Wrap. */
307 C_Vector_Linspace_doc,
308 ".. classmethod:: Linspace(start, stop, size)\n"
309 "\n"
310 " Create a vector of the specified size which is filled with linearly spaced "
311 "values between start and stop values.\n"
312 "\n"
313 " :arg start: The start of the range used to fill the vector.\n"
314 " :type start: int\n"
315 " :arg stop: The end of the range used to fill the vector.\n"
316 " :type stop: int\n"
317 " :arg size: The size of the vector to be created.\n"
318 " :type size: int\n");
319static PyObject *C_Vector_Linspace(PyObject *cls, PyObject *args)
320{
321 float *vec;
322 int vec_num;
323 float start, end, step;
324
325 if (!PyArg_ParseTuple(args, "ffi:Vector.Linspace", &start, &end, &vec_num)) {
326 return nullptr;
327 }
328
329 if (vec_num < 2) {
330 PyErr_SetString(PyExc_RuntimeError, "Vector.Linspace(): invalid size");
331 return nullptr;
332 }
333
334 step = (end - start) / float(vec_num - 1);
335
336 vec = static_cast<float *>(PyMem_Malloc(vec_num * sizeof(float)));
337
338 if (vec == nullptr) {
339 PyErr_SetString(PyExc_MemoryError,
340 "Vector.Linspace(): "
341 "problem allocating pointer space");
342 return nullptr;
343 }
344
345 range_vn_fl(vec, vec_num, start, step);
346
347 return Vector_CreatePyObject_alloc(vec, vec_num, (PyTypeObject *)cls);
348}
349
351 /* Wrap. */
352 C_Vector_Repeat_doc,
353 ".. classmethod:: Repeat(vector, size)\n"
354 "\n"
355 " Create a vector by repeating the values in vector until the required size is reached.\n"
356 "\n"
357 " :arg vector: The vector to draw values from.\n"
358 " :type vector: :class:`mathutils.Vector`\n"
359 " :arg size: The size of the vector to be created.\n"
360 " :type size: int\n");
361static PyObject *C_Vector_Repeat(PyObject *cls, PyObject *args)
362{
363 float *vec;
364 float *iter_vec = nullptr;
365 int i, vec_num, value_num;
366 PyObject *value;
367
368 if (!PyArg_ParseTuple(args, "Oi:Vector.Repeat", &value, &vec_num)) {
369 return nullptr;
370 }
371
372 if (vec_num < 2) {
373 PyErr_SetString(PyExc_RuntimeError, "Vector.Repeat(): invalid vec_num");
374 return nullptr;
375 }
376
377 if ((value_num = mathutils_array_parse_alloc(
378 &iter_vec, 2, value, "Vector.Repeat(vector, vec_num), invalid 'vector' arg")) == -1)
379 {
380 return nullptr;
381 }
382
383 if (iter_vec == nullptr) {
384 PyErr_SetString(PyExc_MemoryError,
385 "Vector.Repeat(): "
386 "problem allocating pointer space");
387 return nullptr;
388 }
389
390 vec = static_cast<float *>(PyMem_Malloc(vec_num * sizeof(float)));
391
392 if (vec == nullptr) {
393 PyMem_Free(iter_vec);
394 PyErr_SetString(PyExc_MemoryError,
395 "Vector.Repeat(): "
396 "problem allocating pointer space");
397 return nullptr;
398 }
399
400 i = 0;
401 while (i < vec_num) {
402 vec[i] = iter_vec[i % value_num];
403 i++;
404 }
405
406 PyMem_Free(iter_vec);
407
408 return Vector_CreatePyObject_alloc(vec, vec_num, (PyTypeObject *)cls);
409}
410
413/* -------------------------------------------------------------------- */
418 /* Wrap. */
419 Vector_zero_doc,
420 ".. method:: zero()\n"
421 "\n"
422 " Set all values to zero.\n");
423static PyObject *Vector_zero(VectorObject *self)
424{
425 if (BaseMath_Prepare_ForWrite(self) == -1) {
426 return nullptr;
427 }
428
429 copy_vn_fl(self->vec, self->vec_num, 0.0f);
430
431 if (BaseMath_WriteCallback(self) == -1) {
432 return nullptr;
433 }
434
435 Py_RETURN_NONE;
436}
437
440/* -------------------------------------------------------------------- */
445 /* Wrap. */
446 Vector_normalize_doc,
447 ".. method:: normalize()\n"
448 "\n"
449 " Normalize the vector, making the length of the vector always 1.0.\n"
450 "\n"
451 " .. warning:: Normalizing a vector where all values are zero has no effect.\n"
452 "\n"
453 " .. note:: Normalize works for vectors of all sizes,\n"
454 " however 4D Vectors w axis is left untouched.\n");
456{
457 const int vec_num = (self->vec_num == 4 ? 3 : self->vec_num);
459 return nullptr;
460 }
461
462 normalize_vn(self->vec, vec_num);
463
465 Py_RETURN_NONE;
466}
468 /* Wrap. */
469 Vector_normalized_doc,
470 ".. method:: normalized()\n"
471 "\n"
472 " Return a new, normalized vector.\n"
473 "\n"
474 " :return: a normalized copy of the vector\n"
475 " :rtype: :class:`Vector`\n");
480
483/* -------------------------------------------------------------------- */
488 /* Wrap. */
489 Vector_resize_doc,
490 ".. method:: resize(size=3)\n"
491 "\n"
492 " Resize the vector to have size number of elements.\n");
493static PyObject *Vector_resize(VectorObject *self, PyObject *value)
494{
495 int vec_num;
496
497 if (self->flag & BASE_MATH_FLAG_IS_WRAP) {
498 PyErr_SetString(PyExc_TypeError,
499 "Vector.resize(): "
500 "cannot resize wrapped data - only Python vectors");
501 return nullptr;
502 }
503 if (self->cb_user) {
504 PyErr_SetString(PyExc_TypeError,
505 "Vector.resize(): "
506 "cannot resize a vector that has an owner");
507 return nullptr;
508 }
509
510 if ((vec_num = PyC_Long_AsI32(value)) == -1) {
511 PyErr_SetString(PyExc_TypeError,
512 "Vector.resize(size): "
513 "expected size argument to be an integer");
514 return nullptr;
515 }
516
517 if (vec_num < 2) {
518 PyErr_SetString(PyExc_RuntimeError, "Vector.resize(): invalid size");
519 return nullptr;
520 }
521
522 self->vec = static_cast<float *>(PyMem_Realloc(self->vec, (vec_num * sizeof(float))));
523 if (self->vec == nullptr) {
524 PyErr_SetString(PyExc_MemoryError,
525 "Vector.resize(): "
526 "problem allocating pointer space");
527 return nullptr;
528 }
529
530 /* If the vector has increased in length, set all new elements to 0.0f */
531 if (vec_num > self->vec_num) {
532 copy_vn_fl(self->vec + self->vec_num, vec_num - self->vec_num, 0.0f);
533 }
534
535 self->vec_num = vec_num;
536 Py_RETURN_NONE;
537}
538
540 /* Wrap. */
541 Vector_resized_doc,
542 ".. method:: resized(size=3)\n"
543 "\n"
544 " Return a resized copy of the vector with size number of elements.\n"
545 "\n"
546 " :return: a new vector\n"
547 " :rtype: :class:`Vector`\n");
548static PyObject *Vector_resized(VectorObject *self, PyObject *value)
549{
550 int vec_num;
551 float *vec;
552
553 if ((vec_num = PyLong_AsLong(value)) == -1) {
554 return nullptr;
555 }
556
557 if (vec_num < 2) {
558 PyErr_SetString(PyExc_RuntimeError, "Vector.resized(): invalid size");
559 return nullptr;
560 }
561
562 vec = static_cast<float *>(PyMem_Malloc(vec_num * sizeof(float)));
563
564 if (vec == nullptr) {
565 PyErr_SetString(PyExc_MemoryError,
566 "Vector.resized(): "
567 "problem allocating pointer space");
568 return nullptr;
569 }
570
571 copy_vn_fl(vec, vec_num, 0.0f);
572 memcpy(vec, self->vec, self->vec_num * sizeof(float));
573
574 return Vector_CreatePyObject_alloc(vec, vec_num, nullptr);
575}
576
578 /* Wrap. */
579 Vector_resize_2d_doc,
580 ".. method:: resize_2d()\n"
581 "\n"
582 " Resize the vector to 2D (x, y).\n");
584{
585 if (self->flag & BASE_MATH_FLAG_IS_WRAP) {
586 PyErr_SetString(PyExc_TypeError,
587 "Vector.resize_2d(): "
588 "cannot resize wrapped data - only Python vectors");
589 return nullptr;
590 }
591 if (self->cb_user) {
592 PyErr_SetString(PyExc_TypeError,
593 "Vector.resize_2d(): "
594 "cannot resize a vector that has an owner");
595 return nullptr;
596 }
597
598 self->vec = static_cast<float *>(PyMem_Realloc(self->vec, sizeof(float[2])));
599 if (self->vec == nullptr) {
600 PyErr_SetString(PyExc_MemoryError,
601 "Vector.resize_2d(): "
602 "problem allocating pointer space");
603 return nullptr;
604 }
605
606 self->vec_num = 2;
607 Py_RETURN_NONE;
608}
609
611 /* Wrap. */
612 Vector_resize_3d_doc,
613 ".. method:: resize_3d()\n"
614 "\n"
615 " Resize the vector to 3D (x, y, z).\n");
617{
618 if (self->flag & BASE_MATH_FLAG_IS_WRAP) {
619 PyErr_SetString(PyExc_TypeError,
620 "Vector.resize_3d(): "
621 "cannot resize wrapped data - only Python vectors");
622 return nullptr;
623 }
624 if (self->cb_user) {
625 PyErr_SetString(PyExc_TypeError,
626 "Vector.resize_3d(): "
627 "cannot resize a vector that has an owner");
628 return nullptr;
629 }
630
631 self->vec = static_cast<float *>(PyMem_Realloc(self->vec, sizeof(float[3])));
632 if (self->vec == nullptr) {
633 PyErr_SetString(PyExc_MemoryError,
634 "Vector.resize_3d(): "
635 "problem allocating pointer space");
636 return nullptr;
637 }
638
639 if (self->vec_num == 2) {
640 self->vec[2] = 0.0f;
641 }
642
643 self->vec_num = 3;
644 Py_RETURN_NONE;
645}
646
648 /* Wrap. */
649 Vector_resize_4d_doc,
650 ".. method:: resize_4d()\n"
651 "\n"
652 " Resize the vector to 4D (x, y, z, w).\n");
654{
655 if (self->flag & BASE_MATH_FLAG_IS_WRAP) {
656 PyErr_SetString(PyExc_TypeError,
657 "Vector.resize_4d(): "
658 "cannot resize wrapped data - only Python vectors");
659 return nullptr;
660 }
661 if (self->cb_user) {
662 PyErr_SetString(PyExc_TypeError,
663 "Vector.resize_4d(): "
664 "cannot resize a vector that has an owner");
665 return nullptr;
666 }
667
668 self->vec = static_cast<float *>(PyMem_Realloc(self->vec, sizeof(float[4])));
669 if (self->vec == nullptr) {
670 PyErr_SetString(PyExc_MemoryError,
671 "Vector.resize_4d(): "
672 "problem allocating pointer space");
673 return nullptr;
674 }
675
676 if (self->vec_num == 2) {
677 self->vec[2] = 0.0f;
678 self->vec[3] = 1.0f;
679 }
680 else if (self->vec_num == 3) {
681 self->vec[3] = 1.0f;
682 }
683 self->vec_num = 4;
684 Py_RETURN_NONE;
685}
686
689/* -------------------------------------------------------------------- */
694 /* Wrap. */
695 Vector_to_2d_doc,
696 ".. method:: to_2d()\n"
697 "\n"
698 " Return a 2d copy of the vector.\n"
699 "\n"
700 " :return: a new vector\n"
701 " :rtype: :class:`Vector`\n");
703{
704 if (BaseMath_ReadCallback(self) == -1) {
705 return nullptr;
706 }
707
708 return Vector_CreatePyObject(self->vec, 2, Py_TYPE(self));
709}
711 /* Wrap. */
712 Vector_to_3d_doc,
713 ".. method:: to_3d()\n"
714 "\n"
715 " Return a 3d copy of the vector.\n"
716 "\n"
717 " :return: a new vector\n"
718 " :rtype: :class:`Vector`\n");
720{
721 float tvec[3] = {0.0f};
722
723 if (BaseMath_ReadCallback(self) == -1) {
724 return nullptr;
725 }
726
727 memcpy(tvec, self->vec, sizeof(float) * std::min(self->vec_num, 3));
728 return Vector_CreatePyObject(tvec, 3, Py_TYPE(self));
729}
731 /* Wrap. */
732 Vector_to_4d_doc,
733 ".. method:: to_4d()\n"
734 "\n"
735 " Return a 4d copy of the vector.\n"
736 "\n"
737 " :return: a new vector\n"
738 " :rtype: :class:`Vector`\n");
740{
741 float tvec[4] = {0.0f, 0.0f, 0.0f, 1.0f};
742
743 if (BaseMath_ReadCallback(self) == -1) {
744 return nullptr;
745 }
746
747 memcpy(tvec, self->vec, sizeof(float) * std::min(self->vec_num, 4));
748 return Vector_CreatePyObject(tvec, 4, Py_TYPE(self));
749}
750
753/* -------------------------------------------------------------------- */
758 /* Wrap. */
759 Vector_to_tuple_doc,
760 ".. method:: to_tuple(precision=-1)\n"
761 "\n"
762 " Return this vector as a tuple with.\n"
763 "\n"
764 " :arg precision: The number to round the value to in [-1, 21].\n"
765 " :type precision: int\n"
766 " :return: the values of the vector rounded by *precision*\n"
767 " :rtype: tuple[float]\n");
768static PyObject *Vector_to_tuple(VectorObject *self, PyObject *args)
769{
770 int ndigits = 0;
771
772 if (!PyArg_ParseTuple(args, "|i:to_tuple", &ndigits)) {
773 return nullptr;
774 }
775
776 if (ndigits > 22 || ndigits < 0) {
777 PyErr_SetString(PyExc_ValueError,
778 "Vector.to_tuple(ndigits): "
779 "ndigits must be between 0 and 21");
780 return nullptr;
781 }
782
783 if (PyTuple_GET_SIZE(args) == 0) {
784 ndigits = -1;
785 }
786
787 if (BaseMath_ReadCallback(self) == -1) {
788 return nullptr;
789 }
790
791 return Vector_to_tuple_ex(self, ndigits);
792}
793
796/* -------------------------------------------------------------------- */
801 /* Wrap. */
802 Vector_to_track_quat_doc,
803 ".. method:: to_track_quat(track, up)\n"
804 "\n"
805 " Return a quaternion rotation from the vector and the track and up axis.\n"
806 "\n"
807 " :arg track: Track axis in ['X', 'Y', 'Z', '-X', '-Y', '-Z'].\n"
808 " :type track: str\n"
809 " :arg up: Up axis in ['X', 'Y', 'Z'].\n"
810 " :type up: str\n"
811 " :return: rotation from the vector and the track and up axis.\n"
812 " :rtype: :class:`Quaternion`\n");
813static PyObject *Vector_to_track_quat(VectorObject *self, PyObject *args)
814{
815 float vec[3], quat[4];
816 const char *strack = nullptr;
817 const char *sup = nullptr;
818 short track = 2, up = 1;
819
820 if (!PyArg_ParseTuple(args, "|ss:to_track_quat", &strack, &sup)) {
821 return nullptr;
822 }
823
824 if (self->vec_num != 3) {
825 PyErr_SetString(PyExc_TypeError,
826 "Vector.to_track_quat(): "
827 "only for 3D vectors");
828 return nullptr;
829 }
830
831 if (BaseMath_ReadCallback(self) == -1) {
832 return nullptr;
833 }
834
835 if (strack) {
836 const char *axis_err_msg = "only X, -X, Y, -Y, Z or -Z for track axis";
837
838 if (strlen(strack) == 2) {
839 if (strack[0] == '-') {
840 switch (strack[1]) {
841 case 'X':
842 track = 3;
843 break;
844 case 'Y':
845 track = 4;
846 break;
847 case 'Z':
848 track = 5;
849 break;
850 default:
851 PyErr_SetString(PyExc_ValueError, axis_err_msg);
852 return nullptr;
853 }
854 }
855 else {
856 PyErr_SetString(PyExc_ValueError, axis_err_msg);
857 return nullptr;
858 }
859 }
860 else if (strlen(strack) == 1) {
861 switch (strack[0]) {
862 case '-':
863 case 'X':
864 track = 0;
865 break;
866 case 'Y':
867 track = 1;
868 break;
869 case 'Z':
870 track = 2;
871 break;
872 default:
873 PyErr_SetString(PyExc_ValueError, axis_err_msg);
874 return nullptr;
875 }
876 }
877 else {
878 PyErr_SetString(PyExc_ValueError, axis_err_msg);
879 return nullptr;
880 }
881 }
882
883 if (sup) {
884 const char *axis_err_msg = "only X, Y or Z for up axis";
885 if (strlen(sup) == 1) {
886 switch (*sup) {
887 case 'X':
888 up = 0;
889 break;
890 case 'Y':
891 up = 1;
892 break;
893 case 'Z':
894 up = 2;
895 break;
896 default:
897 PyErr_SetString(PyExc_ValueError, axis_err_msg);
898 return nullptr;
899 }
900 }
901 else {
902 PyErr_SetString(PyExc_ValueError, axis_err_msg);
903 return nullptr;
904 }
905 }
906
907 if (track == up) {
908 PyErr_SetString(PyExc_ValueError, "Can't have the same axis for track and up");
909 return nullptr;
910 }
911
912 /* Flip vector around, since #vec_to_quat expect a vector from target to tracking object
913 * and the python function expects the inverse (a vector to the target). */
914 negate_v3_v3(vec, self->vec);
915
916 vec_to_quat(quat, vec, track, up);
917
918 return Quaternion_CreatePyObject(quat, nullptr);
919}
920
923/* -------------------------------------------------------------------- */
928 /* Wrap. */
929 Vector_orthogonal_doc,
930 ".. method:: orthogonal()\n"
931 "\n"
932 " Return a perpendicular vector.\n"
933 "\n"
934 " :return: a new vector 90 degrees from this vector.\n"
935 " :rtype: :class:`Vector`\n"
936 "\n"
937 " .. note:: the axis is undefined, only use when any orthogonal vector is acceptable.\n");
939{
940 float vec[3];
941
942 if (self->vec_num > 3) {
943 PyErr_SetString(PyExc_TypeError,
944 "Vector.orthogonal(): "
945 "Vector must be 3D or 2D");
946 return nullptr;
947 }
948
949 if (BaseMath_ReadCallback(self) == -1) {
950 return nullptr;
951 }
952
953 if (self->vec_num == 3) {
954 ortho_v3_v3(vec, self->vec);
955 }
956 else {
957 ortho_v2_v2(vec, self->vec);
958 }
959
960 return Vector_CreatePyObject(vec, self->vec_num, Py_TYPE(self));
961}
962
965/* -------------------------------------------------------------------- */
973 /* Wrap. */
974 Vector_reflect_doc,
975 ".. method:: reflect(mirror)\n"
976 "\n"
977 " Return the reflection vector from the *mirror* argument.\n"
978 "\n"
979 " :arg mirror: This vector could be a normal from the reflecting surface.\n"
980 " :type mirror: :class:`Vector`\n"
981 " :return: The reflected vector matching the size of this vector.\n"
982 " :rtype: :class:`Vector`\n");
983static PyObject *Vector_reflect(VectorObject *self, PyObject *value)
984{
985 int value_num;
986 float mirror[3], vec[3];
987 float reflect[3] = {0.0f};
988 float tvec[MAX_DIMENSIONS];
989
990 if (BaseMath_ReadCallback(self) == -1) {
991 return nullptr;
992 }
993
994 if ((value_num = mathutils_array_parse(
995 tvec, 2, 4, value, "Vector.reflect(other), invalid 'other' arg")) == -1)
996 {
997 return nullptr;
998 }
999
1000 if (self->vec_num < 2 || self->vec_num > 4) {
1001 PyErr_SetString(PyExc_ValueError, "Vector must be 2D, 3D or 4D");
1002 return nullptr;
1003 }
1004
1005 mirror[0] = tvec[0];
1006 mirror[1] = tvec[1];
1007 mirror[2] = (value_num > 2) ? tvec[2] : 0.0f;
1008
1009 vec[0] = self->vec[0];
1010 vec[1] = self->vec[1];
1011 vec[2] = (value_num > 2) ? self->vec[2] : 0.0f;
1012
1013 normalize_v3(mirror);
1014 reflect_v3_v3v3(reflect, vec, mirror);
1015
1016 return Vector_CreatePyObject(reflect, self->vec_num, Py_TYPE(self));
1017}
1018
1021/* -------------------------------------------------------------------- */
1026 /* Wrap. */
1027 Vector_cross_doc,
1028 ".. method:: cross(other)\n"
1029 "\n"
1030 " Return the cross product of this vector and another.\n"
1031 "\n"
1032 " :arg other: The other vector to perform the cross product with.\n"
1033 " :type other: :class:`Vector`\n"
1034 " :return: The cross product as a vector or a float when 2D vectors are used.\n"
1035 " :rtype: :class:`Vector` | float\n"
1036 "\n"
1037 " .. note:: both vectors must be 2D or 3D\n");
1038static PyObject *Vector_cross(VectorObject *self, PyObject *value)
1039{
1040 PyObject *ret;
1041 float tvec[3];
1042
1043 if (BaseMath_ReadCallback(self) == -1) {
1044 return nullptr;
1045 }
1046
1047 if (self->vec_num > 3) {
1048 PyErr_SetString(PyExc_ValueError, "Vector must be 2D or 3D");
1049 return nullptr;
1050 }
1051
1053 tvec, self->vec_num, self->vec_num, value, "Vector.cross(other), invalid 'other' arg") ==
1054 -1)
1055 {
1056 return nullptr;
1057 }
1058
1059 if (self->vec_num == 3) {
1060 ret = Vector_CreatePyObject(nullptr, 3, Py_TYPE(self));
1061 cross_v3_v3v3(((VectorObject *)ret)->vec, self->vec, tvec);
1062 }
1063 else {
1064 /* size == 2 */
1065 ret = PyFloat_FromDouble(cross_v2v2(self->vec, tvec));
1066 }
1067 return ret;
1068}
1069
1072/* -------------------------------------------------------------------- */
1077 /* Wrap. */
1078 Vector_dot_doc,
1079 ".. method:: dot(other)\n"
1080 "\n"
1081 " Return the dot product of this vector and another.\n"
1082 "\n"
1083 " :arg other: The other vector to perform the dot product with.\n"
1084 " :type other: :class:`Vector`\n"
1085 " :return: The dot product.\n"
1086 " :rtype: float\n");
1087static PyObject *Vector_dot(VectorObject *self, PyObject *value)
1088{
1089 float *tvec;
1090 PyObject *ret;
1091
1092 if (BaseMath_ReadCallback(self) == -1) {
1093 return nullptr;
1094 }
1095
1097 &tvec, self->vec_num, value, "Vector.dot(other), invalid 'other' arg") == -1)
1098 {
1099 return nullptr;
1100 }
1101
1102 ret = PyFloat_FromDouble(dot_vn_vn(self->vec, tvec, self->vec_num));
1103 PyMem_Free(tvec);
1104 return ret;
1105}
1106
1109/* -------------------------------------------------------------------- */
1114 /* Wrap. */
1115 Vector_angle_doc,
1116 ".. function:: angle(other, fallback=None)\n"
1117 "\n"
1118 " Return the angle between two vectors.\n"
1119 "\n"
1120 " :arg other: another vector to compare the angle with\n"
1121 " :type other: :class:`Vector`\n"
1122 " :arg fallback: return this when the angle can't be calculated (zero length vector),\n"
1123 " (instead of raising a :exc:`ValueError`).\n"
1124 " :type fallback: Any\n"
1125 " :return: angle in radians or fallback when given\n"
1126 " :rtype: float | Any\n");
1127static PyObject *Vector_angle(VectorObject *self, PyObject *args)
1128{
1129 const int vec_num = std::min(self->vec_num, 3); /* 4D angle makes no sense */
1130 float tvec[MAX_DIMENSIONS];
1131 PyObject *value;
1132 double dot = 0.0f, dot_self = 0.0f, dot_other = 0.0f;
1133 int x;
1134 PyObject *fallback = nullptr;
1135
1136 if (!PyArg_ParseTuple(args, "O|O:angle", &value, &fallback)) {
1137 return nullptr;
1138 }
1139
1140 if (BaseMath_ReadCallback(self) == -1) {
1141 return nullptr;
1142 }
1143
1144 /* don't use clamped size, rule of thumb is vector sizes must match,
1145 * even though n this case 'w' is ignored */
1147 tvec, self->vec_num, self->vec_num, value, "Vector.angle(other), invalid 'other' arg") ==
1148 -1)
1149 {
1150 return nullptr;
1151 }
1152
1153 if (self->vec_num > 4) {
1154 PyErr_SetString(PyExc_ValueError, "Vector must be 2D, 3D or 4D");
1155 return nullptr;
1156 }
1157
1158 for (x = 0; x < vec_num; x++) {
1159 dot_self += double(self->vec[x]) * double(self->vec[x]);
1160 dot_other += double(tvec[x]) * double(tvec[x]);
1161 dot += double(self->vec[x]) * double(tvec[x]);
1162 }
1163
1164 if (!dot_self || !dot_other) {
1165 /* avoid exception */
1166 if (fallback) {
1167 Py_INCREF(fallback);
1168 return fallback;
1169 }
1170
1171 PyErr_SetString(PyExc_ValueError,
1172 "Vector.angle(other): "
1173 "zero length vectors have no valid angle");
1174 return nullptr;
1175 }
1176
1177 return PyFloat_FromDouble(safe_acosf(dot / (sqrt(dot_self) * sqrt(dot_other))));
1178}
1179
1182/* -------------------------------------------------------------------- */
1187 /* Wrap. */
1188 Vector_angle_signed_doc,
1189 ".. function:: angle_signed(other, fallback)\n"
1190 "\n"
1191 " Return the signed angle between two 2D vectors (clockwise is positive).\n"
1192 "\n"
1193 " :arg other: another vector to compare the angle with\n"
1194 " :type other: :class:`Vector`\n"
1195 " :arg fallback: return this when the angle can't be calculated (zero length vector),\n"
1196 " (instead of raising a :exc:`ValueError`).\n"
1197 " :type fallback: Any\n"
1198 " :return: angle in radians or fallback when given\n"
1199 " :rtype: float | Any\n");
1200static PyObject *Vector_angle_signed(VectorObject *self, PyObject *args)
1201{
1202 float tvec[2];
1203
1204 PyObject *value;
1205 PyObject *fallback = nullptr;
1206
1207 if (!PyArg_ParseTuple(args, "O|O:angle_signed", &value, &fallback)) {
1208 return nullptr;
1209 }
1210
1211 if (BaseMath_ReadCallback(self) == -1) {
1212 return nullptr;
1213 }
1214
1216 tvec, 2, 2, value, "Vector.angle_signed(other), invalid 'other' arg") == -1)
1217 {
1218 return nullptr;
1219 }
1220
1221 if (self->vec_num != 2) {
1222 PyErr_SetString(PyExc_ValueError, "Vector must be 2D");
1223 return nullptr;
1224 }
1225
1226 if (is_zero_v2(self->vec) || is_zero_v2(tvec)) {
1227 /* avoid exception */
1228 if (fallback) {
1229 Py_INCREF(fallback);
1230 return fallback;
1231 }
1232
1233 PyErr_SetString(PyExc_ValueError,
1234 "Vector.angle_signed(other): "
1235 "zero length vectors have no valid angle");
1236 return nullptr;
1237 }
1238
1239 return PyFloat_FromDouble(angle_signed_v2v2(self->vec, tvec));
1240}
1241
1244/* -------------------------------------------------------------------- */
1249 /* Wrap. */
1250 Vector_rotation_difference_doc,
1251 ".. function:: rotation_difference(other)\n"
1252 "\n"
1253 " Returns a quaternion representing the rotational difference between this\n"
1254 " vector and another.\n"
1255 "\n"
1256 " :arg other: second vector.\n"
1257 " :type other: :class:`Vector`\n"
1258 " :return: the rotational difference between the two vectors.\n"
1259 " :rtype: :class:`Quaternion`\n"
1260 "\n"
1261 " .. note:: 2D vectors raise an :exc:`AttributeError`.\n");
1262static PyObject *Vector_rotation_difference(VectorObject *self, PyObject *value)
1263{
1264 float quat[4], vec_a[3], vec_b[3];
1265
1266 if (self->vec_num < 3 || self->vec_num > 4) {
1267 PyErr_SetString(PyExc_ValueError,
1268 "vec.difference(value): "
1269 "expects both vectors to be size 3 or 4");
1270 return nullptr;
1271 }
1272
1273 if (BaseMath_ReadCallback(self) == -1) {
1274 return nullptr;
1275 }
1276
1278 vec_b, 3, MAX_DIMENSIONS, value, "Vector.difference(other), invalid 'other' arg") == -1)
1279 {
1280 return nullptr;
1281 }
1282
1283 normalize_v3_v3(vec_a, self->vec);
1284 normalize_v3(vec_b);
1285
1286 rotation_between_vecs_to_quat(quat, vec_a, vec_b);
1287
1288 return Quaternion_CreatePyObject(quat, nullptr);
1289}
1290
1293/* -------------------------------------------------------------------- */
1298 /* Wrap. */
1299 Vector_project_doc,
1300 ".. function:: project(other)\n"
1301 "\n"
1302 " Return the projection of this vector onto the *other*.\n"
1303 "\n"
1304 " :arg other: second vector.\n"
1305 " :type other: :class:`Vector`\n"
1306 " :return: the parallel projection vector\n"
1307 " :rtype: :class:`Vector`\n");
1308static PyObject *Vector_project(VectorObject *self, PyObject *value)
1309{
1310 const int vec_num = self->vec_num;
1311 float *tvec;
1312 double dot = 0.0f, dot2 = 0.0f;
1313 int x;
1314
1315 if (BaseMath_ReadCallback(self) == -1) {
1316 return nullptr;
1317 }
1318
1320 &tvec, vec_num, value, "Vector.project(other), invalid 'other' arg") == -1)
1321 {
1322 return nullptr;
1323 }
1324
1325 /* get dot products */
1326 for (x = 0; x < vec_num; x++) {
1327 dot += double(self->vec[x] * tvec[x]);
1328 dot2 += double(tvec[x] * tvec[x]);
1329 }
1330 /* projection */
1331 dot /= dot2;
1332 for (x = 0; x < vec_num; x++) {
1333 tvec[x] *= float(dot);
1334 }
1335 return Vector_CreatePyObject_alloc(tvec, vec_num, Py_TYPE(self));
1336}
1337
1340/* -------------------------------------------------------------------- */
1345 /* Wrap. */
1346 Vector_lerp_doc,
1347 ".. function:: lerp(other, factor)\n"
1348 "\n"
1349 " Returns the interpolation of two vectors.\n"
1350 "\n"
1351 " :arg other: value to interpolate with.\n"
1352 " :type other: :class:`Vector`\n"
1353 " :arg factor: The interpolation value in [0.0, 1.0].\n"
1354 " :type factor: float\n"
1355 " :return: The interpolated vector.\n"
1356 " :rtype: :class:`Vector`\n");
1357static PyObject *Vector_lerp(VectorObject *self, PyObject *args)
1358{
1359 const int vec_num = self->vec_num;
1360 PyObject *value = nullptr;
1361 float fac;
1362 float *tvec;
1363
1364 if (!PyArg_ParseTuple(args, "Of:lerp", &value, &fac)) {
1365 return nullptr;
1366 }
1367
1368 if (BaseMath_ReadCallback(self) == -1) {
1369 return nullptr;
1370 }
1371
1373 &tvec, vec_num, value, "Vector.lerp(other), invalid 'other' arg") == -1)
1374 {
1375 return nullptr;
1376 }
1377
1378 interp_vn_vn(tvec, self->vec, 1.0f - fac, vec_num);
1379
1380 return Vector_CreatePyObject_alloc(tvec, vec_num, Py_TYPE(self));
1381}
1382
1385/* -------------------------------------------------------------------- */
1390 /* Wrap. */
1391 Vector_slerp_doc,
1392 ".. function:: slerp(other, factor, fallback=None)\n"
1393 "\n"
1394 " Returns the interpolation of two non-zero vectors (spherical coordinates).\n"
1395 "\n"
1396 " :arg other: value to interpolate with.\n"
1397 " :type other: :class:`Vector`\n"
1398 " :arg factor: The interpolation value typically in [0.0, 1.0].\n"
1399 " :type factor: float\n"
1400 " :arg fallback: return this when the vector can't be calculated (zero length "
1401 "vector or direct opposites),\n"
1402 " (instead of raising a :exc:`ValueError`).\n"
1403 " :type fallback: Any\n"
1404 " :return: The interpolated vector.\n"
1405 " :rtype: :class:`Vector`\n");
1406static PyObject *Vector_slerp(VectorObject *self, PyObject *args)
1407{
1408 const int vec_num = self->vec_num;
1409 PyObject *value = nullptr;
1410 float fac, cosom, w[2];
1411 float self_vec[3], other_vec[3], ret_vec[3];
1412 float self_len_sq, other_len_sq;
1413 int x;
1414 PyObject *fallback = nullptr;
1415
1416 if (!PyArg_ParseTuple(args, "Of|O:slerp", &value, &fac, &fallback)) {
1417 return nullptr;
1418 }
1419
1420 if (BaseMath_ReadCallback(self) == -1) {
1421 return nullptr;
1422 }
1423
1424 if (self->vec_num > 3) {
1425 PyErr_SetString(PyExc_ValueError, "Vector must be 2D or 3D");
1426 return nullptr;
1427 }
1428
1430 other_vec, vec_num, vec_num, value, "Vector.slerp(other), invalid 'other' arg") == -1)
1431 {
1432 return nullptr;
1433 }
1434
1435 self_len_sq = normalize_vn_vn(self_vec, self->vec, vec_num);
1436 other_len_sq = normalize_vn(other_vec, vec_num);
1437
1438 /* use fallbacks for zero length vectors */
1439 if (UNLIKELY((self_len_sq < FLT_EPSILON) || (other_len_sq < FLT_EPSILON))) {
1440 /* avoid exception */
1441 if (fallback) {
1442 Py_INCREF(fallback);
1443 return fallback;
1444 }
1445
1446 PyErr_SetString(PyExc_ValueError,
1447 "Vector.slerp(): "
1448 "zero length vectors unsupported");
1449 return nullptr;
1450 }
1451
1452 /* We have sane state, execute slerp */
1453 cosom = float(dot_vn_vn(self_vec, other_vec, vec_num));
1454
1455 /* direct opposite, can't slerp */
1456 if (UNLIKELY(cosom < (-1.0f + FLT_EPSILON))) {
1457 /* avoid exception */
1458 if (fallback) {
1459 Py_INCREF(fallback);
1460 return fallback;
1461 }
1462
1463 PyErr_SetString(PyExc_ValueError,
1464 "Vector.slerp(): "
1465 "opposite vectors unsupported");
1466 return nullptr;
1467 }
1468
1469 interp_dot_slerp(fac, cosom, w);
1470
1471 for (x = 0; x < vec_num; x++) {
1472 ret_vec[x] = (w[0] * self_vec[x]) + (w[1] * other_vec[x]);
1473 }
1474
1475 return Vector_CreatePyObject(ret_vec, vec_num, Py_TYPE(self));
1476}
1477
1480/* -------------------------------------------------------------------- */
1485 /* Wrap. */
1486 Vector_rotate_doc,
1487 ".. function:: rotate(other)\n"
1488 "\n"
1489 " Rotate the vector by a rotation value.\n"
1490 "\n"
1491 " .. note:: 2D vectors are a special case that can only be rotated by a 2x2 matrix.\n"
1492 "\n"
1493 " :arg other: rotation component of mathutils value\n"
1494 " :type other: :class:`Euler` | :class:`Quaternion` | :class:`Matrix`\n");
1495static PyObject *Vector_rotate(VectorObject *self, PyObject *value)
1496{
1498 return nullptr;
1499 }
1500
1501 if (self->vec_num == 2) {
1502 /* Special case for 2D Vector with 2x2 matrix, so we avoid resizing it to a 3x3. */
1503 float other_rmat[2][2];
1504 MatrixObject *pymat;
1505 if (!Matrix_Parse2x2(value, &pymat)) {
1506 return nullptr;
1507 }
1508 normalize_m2_m2(other_rmat, (const float(*)[2])pymat->matrix);
1509 /* Equivalent to a rotation along the Z axis. */
1510 mul_m2_v2(other_rmat, self->vec);
1511 }
1512 else {
1513 float other_rmat[3][3];
1514
1515 if (mathutils_any_to_rotmat(other_rmat, value, "Vector.rotate(value)") == -1) {
1516 return nullptr;
1517 }
1518
1519 mul_m3_v3(other_rmat, self->vec);
1520 }
1521
1523 Py_RETURN_NONE;
1524}
1525
1528/* -------------------------------------------------------------------- */
1533 /* Wrap. */
1534 Vector_negate_doc,
1535 ".. method:: negate()\n"
1536 "\n"
1537 " Set all values to their negative.\n");
1539{
1540 if (BaseMath_ReadCallback(self) == -1) {
1541 return nullptr;
1542 }
1543
1544 negate_vn(self->vec, self->vec_num);
1545
1546 (void)BaseMath_WriteCallback(self); /* already checked for error */
1547 Py_RETURN_NONE;
1548}
1549
1552/* -------------------------------------------------------------------- */
1557 /* Wrap. */
1558 Vector_copy_doc,
1559 ".. function:: copy()\n"
1560 "\n"
1561 " Returns a copy of this vector.\n"
1562 "\n"
1563 " :return: A copy of the vector.\n"
1564 " :rtype: :class:`Vector`\n"
1565 "\n"
1566 " .. note:: use this to get a copy of a wrapped vector with\n"
1567 " no reference to the original data.\n");
1569{
1570 if (BaseMath_ReadCallback(self) == -1) {
1571 return nullptr;
1572 }
1573
1574 return Vector_CreatePyObject(self->vec, self->vec_num, Py_TYPE(self));
1575}
1576static PyObject *Vector_deepcopy(VectorObject *self, PyObject *args)
1577{
1578 if (!PyC_CheckArgs_DeepCopy(args)) {
1579 return nullptr;
1580 }
1581 return Vector_copy(self);
1582}
1583
1586/* -------------------------------------------------------------------- */
1591{
1592 PyObject *ret, *tuple;
1593
1594 if (BaseMath_ReadCallback(self) == -1) {
1595 return nullptr;
1596 }
1597
1598 tuple = Vector_to_tuple_ex(self, -1);
1599 ret = PyUnicode_FromFormat("Vector(%R)", tuple);
1600 Py_DECREF(tuple);
1601 return ret;
1602}
1603
1604#ifndef MATH_STANDALONE
1605static PyObject *Vector_str(VectorObject *self)
1606{
1607 int i;
1608
1609 DynStr *ds;
1610
1611 if (BaseMath_ReadCallback(self) == -1) {
1612 return nullptr;
1613 }
1614
1615 ds = BLI_dynstr_new();
1616
1617 BLI_dynstr_append(ds, "<Vector (");
1618
1619 for (i = 0; i < self->vec_num; i++) {
1620 BLI_dynstr_appendf(ds, i ? ", %.4f" : "%.4f", self->vec[i]);
1621 }
1622
1623 BLI_dynstr_append(ds, ")>");
1624
1625 return mathutils_dynstr_to_py(ds); /* frees ds */
1626}
1627#endif
1628
1631/* -------------------------------------------------------------------- */
1635static PyObject *Vector_richcmpr(PyObject *objectA, PyObject *objectB, int comparison_type)
1636{
1637 VectorObject *vecA = nullptr, *vecB = nullptr;
1638 int result = 0;
1639 const double epsilon = 0.000001f;
1640 double lenA, lenB;
1641
1642 if (!VectorObject_Check(objectA) || !VectorObject_Check(objectB)) {
1643 if (comparison_type == Py_NE) {
1644 Py_RETURN_TRUE;
1645 }
1646
1647 Py_RETURN_FALSE;
1648 }
1649 vecA = (VectorObject *)objectA;
1650 vecB = (VectorObject *)objectB;
1651
1652 if (BaseMath_ReadCallback(vecA) == -1 || BaseMath_ReadCallback(vecB) == -1) {
1653 return nullptr;
1654 }
1655
1656 if (vecA->vec_num != vecB->vec_num) {
1657 if (comparison_type == Py_NE) {
1658 Py_RETURN_TRUE;
1659 }
1660
1661 Py_RETURN_FALSE;
1662 }
1663
1664 switch (comparison_type) {
1665 case Py_LT:
1666 lenA = len_squared_vn(vecA->vec, vecA->vec_num);
1667 lenB = len_squared_vn(vecB->vec, vecB->vec_num);
1668 if (lenA < lenB) {
1669 result = 1;
1670 }
1671 break;
1672 case Py_LE:
1673 lenA = len_squared_vn(vecA->vec, vecA->vec_num);
1674 lenB = len_squared_vn(vecB->vec, vecB->vec_num);
1675 if (lenA < lenB) {
1676 result = 1;
1677 }
1678 else {
1679 result = (((lenA + epsilon) > lenB) && ((lenA - epsilon) < lenB));
1680 }
1681 break;
1682 case Py_EQ:
1683 result = EXPP_VectorsAreEqual(vecA->vec, vecB->vec, vecA->vec_num, 1);
1684 break;
1685 case Py_NE:
1686 result = !EXPP_VectorsAreEqual(vecA->vec, vecB->vec, vecA->vec_num, 1);
1687 break;
1688 case Py_GT:
1689 lenA = len_squared_vn(vecA->vec, vecA->vec_num);
1690 lenB = len_squared_vn(vecB->vec, vecB->vec_num);
1691 if (lenA > lenB) {
1692 result = 1;
1693 }
1694 break;
1695 case Py_GE:
1696 lenA = len_squared_vn(vecA->vec, vecA->vec_num);
1697 lenB = len_squared_vn(vecB->vec, vecB->vec_num);
1698 if (lenA > lenB) {
1699 result = 1;
1700 }
1701 else {
1702 result = (((lenA + epsilon) > lenB) && ((lenA - epsilon) < lenB));
1703 }
1704 break;
1705 default:
1706 printf("The result of the comparison could not be evaluated");
1707 break;
1708 }
1709 if (result == 1) {
1710 Py_RETURN_TRUE;
1711 }
1712
1713 Py_RETURN_FALSE;
1714}
1715
1718/* -------------------------------------------------------------------- */
1723{
1724 if (BaseMath_ReadCallback(self) == -1) {
1725 return -1;
1726 }
1727
1729 return -1;
1730 }
1731
1732 return mathutils_array_hash(self->vec, self->vec_num);
1733}
1734
1737/* -------------------------------------------------------------------- */
1742static Py_ssize_t Vector_len(VectorObject *self)
1743{
1744 return self->vec_num;
1745}
1746
1747static PyObject *vector_item_internal(VectorObject *self, int i, const bool is_attr)
1748{
1749 if (i < 0) {
1750 i = self->vec_num - i;
1751 }
1752
1753 if (i < 0 || i >= self->vec_num) {
1754 if (is_attr) {
1755 PyErr_Format(PyExc_AttributeError,
1756 "Vector.%c: unavailable on %dd vector",
1757 *(((const char *)"xyzw") + i),
1758 self->vec_num);
1759 }
1760 else {
1761 PyErr_SetString(PyExc_IndexError, "vector[index]: out of range");
1762 }
1763 return nullptr;
1764 }
1765
1766 if (BaseMath_ReadIndexCallback(self, i) == -1) {
1767 return nullptr;
1768 }
1769
1770 return PyFloat_FromDouble(self->vec[i]);
1771}
1772
1774static PyObject *Vector_item(VectorObject *self, Py_ssize_t i)
1775{
1776 return vector_item_internal(self, i, false);
1777}
1778
1779static int vector_ass_item_internal(VectorObject *self, int i, PyObject *value, const bool is_attr)
1780{
1781 float scalar;
1782
1783 if (BaseMath_Prepare_ForWrite(self) == -1) {
1784 return -1;
1785 }
1786
1787 if ((scalar = PyFloat_AsDouble(value)) == -1.0f && PyErr_Occurred()) {
1788 /* parsed item not a number */
1789 PyErr_SetString(PyExc_TypeError,
1790 "vector[index] = x: "
1791 "assigned value not a number");
1792 return -1;
1793 }
1794
1795 if (i < 0) {
1796 i = self->vec_num - i;
1797 }
1798
1799 if (i < 0 || i >= self->vec_num) {
1800 if (is_attr) {
1801 PyErr_Format(PyExc_AttributeError,
1802 "Vector.%c = x: unavailable on %dd vector",
1803 *(((const char *)"xyzw") + i),
1804 self->vec_num);
1805 }
1806 else {
1807 PyErr_SetString(PyExc_IndexError,
1808 "vector[index] = x: "
1809 "assignment index out of range");
1810 }
1811 return -1;
1812 }
1813 self->vec[i] = scalar;
1814
1815 if (BaseMath_WriteIndexCallback(self, i) == -1) {
1816 return -1;
1817 }
1818 return 0;
1819}
1820
1822static int Vector_ass_item(VectorObject *self, Py_ssize_t i, PyObject *value)
1823{
1824 return vector_ass_item_internal(self, i, value, false);
1825}
1826
1828static PyObject *Vector_slice(VectorObject *self, int begin, int end)
1829{
1830 PyObject *tuple;
1831 int count;
1832
1833 if (BaseMath_ReadCallback(self) == -1) {
1834 return nullptr;
1835 }
1836
1837 CLAMP(begin, 0, self->vec_num);
1838 if (end < 0) {
1839 end = self->vec_num + end + 1;
1840 }
1841 CLAMP(end, 0, self->vec_num);
1842 begin = std::min(begin, end);
1843
1844 tuple = PyTuple_New(end - begin);
1845 for (count = begin; count < end; count++) {
1846 PyTuple_SET_ITEM(tuple, count - begin, PyFloat_FromDouble(self->vec[count]));
1847 }
1848
1849 return tuple;
1850}
1851
1853static int Vector_ass_slice(VectorObject *self, int begin, int end, PyObject *seq)
1854{
1855 int vec_num = 0;
1856 float *vec = nullptr;
1857
1859 return -1;
1860 }
1861
1862 CLAMP(begin, 0, self->vec_num);
1863 CLAMP(end, 0, self->vec_num);
1864 begin = std::min(begin, end);
1865
1866 vec_num = (end - begin);
1867 if (mathutils_array_parse_alloc(&vec, vec_num, seq, "vector[begin:end] = [...]") == -1) {
1868 return -1;
1869 }
1870
1871 if (vec == nullptr) {
1872 PyErr_SetString(PyExc_MemoryError,
1873 "vec[:] = seq: "
1874 "problem allocating pointer space");
1875 return -1;
1876 }
1877
1878 /* Parsed well - now set in vector. */
1879 memcpy(self->vec + begin, vec, vec_num * sizeof(float));
1880
1881 PyMem_Free(vec);
1882
1883 if (BaseMath_WriteCallback(self) == -1) {
1884 return -1;
1885 }
1886
1887 return 0;
1888}
1889
1891static PyObject *Vector_subscript(VectorObject *self, PyObject *item)
1892{
1893 if (PyIndex_Check(item)) {
1894 Py_ssize_t i;
1895 i = PyNumber_AsSsize_t(item, PyExc_IndexError);
1896 if (i == -1 && PyErr_Occurred()) {
1897 return nullptr;
1898 }
1899 if (i < 0) {
1900 i += self->vec_num;
1901 }
1902 return Vector_item(self, i);
1903 }
1904 if (PySlice_Check(item)) {
1905 Py_ssize_t start, stop, step, slicelength;
1906
1907 if (PySlice_GetIndicesEx(item, self->vec_num, &start, &stop, &step, &slicelength) < 0) {
1908 return nullptr;
1909 }
1910
1911 if (slicelength <= 0) {
1912 return PyTuple_New(0);
1913 }
1914 if (step == 1) {
1915 return Vector_slice(self, start, stop);
1916 }
1917
1918 PyErr_SetString(PyExc_IndexError, "slice steps not supported with vectors");
1919 return nullptr;
1920 }
1921
1922 PyErr_Format(
1923 PyExc_TypeError, "vector indices must be integers, not %.200s", Py_TYPE(item)->tp_name);
1924 return nullptr;
1925}
1926
1928static int Vector_ass_subscript(VectorObject *self, PyObject *item, PyObject *value)
1929{
1930 if (PyIndex_Check(item)) {
1931 Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
1932 if (i == -1 && PyErr_Occurred()) {
1933 return -1;
1934 }
1935 if (i < 0) {
1936 i += self->vec_num;
1937 }
1938 return Vector_ass_item(self, i, value);
1939 }
1940 if (PySlice_Check(item)) {
1941 Py_ssize_t start, stop, step, slicelength;
1942
1943 if (PySlice_GetIndicesEx(item, self->vec_num, &start, &stop, &step, &slicelength) < 0) {
1944 return -1;
1945 }
1946
1947 if (step == 1) {
1948 return Vector_ass_slice(self, start, stop, value);
1949 }
1950
1951 PyErr_SetString(PyExc_IndexError, "slice steps not supported with vectors");
1952 return -1;
1953 }
1954
1955 PyErr_Format(
1956 PyExc_TypeError, "vector indices must be integers, not %.200s", Py_TYPE(item)->tp_name);
1957 return -1;
1958}
1959
1962/* -------------------------------------------------------------------- */
1967static PyObject *Vector_add(PyObject *v1, PyObject *v2)
1968{
1969 VectorObject *vec1 = nullptr, *vec2 = nullptr;
1970 float *vec = nullptr;
1971
1973 PyErr_Format(PyExc_AttributeError,
1974 "Vector addition: (%s + %s) "
1975 "invalid type for this operation",
1976 Py_TYPE(v1)->tp_name,
1977 Py_TYPE(v2)->tp_name);
1978 return nullptr;
1979 }
1980 vec1 = (VectorObject *)v1;
1981 vec2 = (VectorObject *)v2;
1982
1983 if (BaseMath_ReadCallback(vec1) == -1 || BaseMath_ReadCallback(vec2) == -1) {
1984 return nullptr;
1985 }
1986
1987 /* VECTOR + VECTOR. */
1988 if (vec1->vec_num != vec2->vec_num) {
1989 PyErr_SetString(PyExc_AttributeError,
1990 "Vector addition: "
1991 "vectors must have the same dimensions for this operation");
1992 return nullptr;
1993 }
1994
1995 vec = static_cast<float *>(PyMem_Malloc(vec1->vec_num * sizeof(float)));
1996 if (vec == nullptr) {
1997 PyErr_SetString(PyExc_MemoryError,
1998 "Vector(): "
1999 "problem allocating pointer space");
2000 return nullptr;
2001 }
2002
2003 add_vn_vnvn(vec, vec1->vec, vec2->vec, vec1->vec_num);
2004
2005 return Vector_CreatePyObject_alloc(vec, vec1->vec_num, Py_TYPE(v1));
2006}
2007
2009static PyObject *Vector_iadd(PyObject *v1, PyObject *v2)
2010{
2011 VectorObject *vec1 = nullptr, *vec2 = nullptr;
2012
2014 PyErr_Format(PyExc_AttributeError,
2015 "Vector addition: (%s += %s) "
2016 "invalid type for this operation",
2017 Py_TYPE(v1)->tp_name,
2018 Py_TYPE(v2)->tp_name);
2019 return nullptr;
2020 }
2021 vec1 = (VectorObject *)v1;
2022 vec2 = (VectorObject *)v2;
2023
2024 if (vec1->vec_num != vec2->vec_num) {
2025 PyErr_SetString(PyExc_AttributeError,
2026 "Vector addition: "
2027 "vectors must have the same dimensions for this operation");
2028 return nullptr;
2029 }
2030
2031 if (BaseMath_ReadCallback_ForWrite(vec1) == -1 || BaseMath_ReadCallback(vec2) == -1) {
2032 return nullptr;
2033 }
2034
2035 add_vn_vn(vec1->vec, vec2->vec, vec1->vec_num);
2036
2037 (void)BaseMath_WriteCallback(vec1);
2038 Py_INCREF(v1);
2039 return v1;
2040}
2041
2043static PyObject *Vector_sub(PyObject *v1, PyObject *v2)
2044{
2045 VectorObject *vec1 = nullptr, *vec2 = nullptr;
2046 float *vec;
2047
2049 PyErr_Format(PyExc_AttributeError,
2050 "Vector subtraction: (%s - %s) "
2051 "invalid type for this operation",
2052 Py_TYPE(v1)->tp_name,
2053 Py_TYPE(v2)->tp_name);
2054 return nullptr;
2055 }
2056 vec1 = (VectorObject *)v1;
2057 vec2 = (VectorObject *)v2;
2058
2059 if (BaseMath_ReadCallback(vec1) == -1 || BaseMath_ReadCallback(vec2) == -1) {
2060 return nullptr;
2061 }
2062
2063 if (vec1->vec_num != vec2->vec_num) {
2064 PyErr_SetString(PyExc_AttributeError,
2065 "Vector subtraction: "
2066 "vectors must have the same dimensions for this operation");
2067 return nullptr;
2068 }
2069
2070 vec = static_cast<float *>(PyMem_Malloc(vec1->vec_num * sizeof(float)));
2071 if (vec == nullptr) {
2072 PyErr_SetString(PyExc_MemoryError,
2073 "Vector(): "
2074 "problem allocating pointer space");
2075 return nullptr;
2076 }
2077
2078 sub_vn_vnvn(vec, vec1->vec, vec2->vec, vec1->vec_num);
2079
2080 return Vector_CreatePyObject_alloc(vec, vec1->vec_num, Py_TYPE(v1));
2081}
2082
2084static PyObject *Vector_isub(PyObject *v1, PyObject *v2)
2085{
2086 VectorObject *vec1 = nullptr, *vec2 = nullptr;
2087
2089 PyErr_Format(PyExc_AttributeError,
2090 "Vector subtraction: (%s -= %s) "
2091 "invalid type for this operation",
2092 Py_TYPE(v1)->tp_name,
2093 Py_TYPE(v2)->tp_name);
2094 return nullptr;
2095 }
2096 vec1 = (VectorObject *)v1;
2097 vec2 = (VectorObject *)v2;
2098
2099 if (vec1->vec_num != vec2->vec_num) {
2100 PyErr_SetString(PyExc_AttributeError,
2101 "Vector subtraction: "
2102 "vectors must have the same dimensions for this operation");
2103 return nullptr;
2104 }
2105
2106 if (BaseMath_ReadCallback_ForWrite(vec1) == -1 || BaseMath_ReadCallback(vec2) == -1) {
2107 return nullptr;
2108 }
2109
2110 sub_vn_vn(vec1->vec, vec2->vec, vec1->vec_num);
2111
2112 (void)BaseMath_WriteCallback(vec1);
2113 Py_INCREF(v1);
2114 return v1;
2115}
2116
2117/* Multiply internal implementation `object * object`, `object *= object`. */
2118
2120{
2121 float vec_cpy[MAX_DIMENSIONS];
2122 int row, col, z = 0;
2123
2124 if (mat->col_num != vec->vec_num) {
2125 if (mat->col_num == 4 && vec->vec_num == 3) {
2126 vec_cpy[3] = 1.0f;
2127 }
2128 else {
2129 PyErr_SetString(PyExc_ValueError,
2130 "matrix * vector: "
2131 "len(matrix.col) and len(vector) must be the same, "
2132 "except for 4x4 matrix * 3D vector.");
2133 return -1;
2134 }
2135 }
2136
2137 memcpy(vec_cpy, vec->vec, vec->vec_num * sizeof(float));
2138
2139 r_vec[3] = 1.0f;
2140
2141 for (row = 0; row < mat->row_num; row++) {
2142 double dot = 0.0f;
2143 for (col = 0; col < mat->col_num; col++) {
2144 dot += double(MATRIX_ITEM(mat, row, col) * vec_cpy[col]);
2145 }
2146 r_vec[z++] = float(dot);
2147 }
2148
2149 return 0;
2150}
2151
2152static PyObject *vector_mul_float(VectorObject *vec, const float scalar)
2153{
2154 float *tvec = static_cast<float *>(PyMem_Malloc(vec->vec_num * sizeof(float)));
2155 if (tvec == nullptr) {
2156 PyErr_SetString(PyExc_MemoryError,
2157 "vec * float: "
2158 "problem allocating pointer space");
2159 return nullptr;
2160 }
2161
2162 mul_vn_vn_fl(tvec, vec->vec, vec->vec_num, scalar);
2163 return Vector_CreatePyObject_alloc(tvec, vec->vec_num, Py_TYPE(vec));
2164}
2165
2166static PyObject *vector_mul_vec(VectorObject *vec1, VectorObject *vec2)
2167{
2168 float *tvec = static_cast<float *>(PyMem_Malloc(vec1->vec_num * sizeof(float)));
2169 if (tvec == nullptr) {
2170 PyErr_SetString(PyExc_MemoryError,
2171 "vec * vec: "
2172 "problem allocating pointer space");
2173 return nullptr;
2174 }
2175
2176 mul_vn_vnvn(tvec, vec1->vec, vec2->vec, vec1->vec_num);
2177 return Vector_CreatePyObject_alloc(tvec, vec1->vec_num, Py_TYPE(vec1));
2178}
2179
2181static PyObject *Vector_mul(PyObject *v1, PyObject *v2)
2182{
2183 VectorObject *vec1 = nullptr, *vec2 = nullptr;
2184 float scalar;
2185
2186 if (VectorObject_Check(v1)) {
2187 vec1 = (VectorObject *)v1;
2188 if (BaseMath_ReadCallback(vec1) == -1) {
2189 return nullptr;
2190 }
2191 }
2192 if (VectorObject_Check(v2)) {
2193 vec2 = (VectorObject *)v2;
2194 if (BaseMath_ReadCallback(vec2) == -1) {
2195 return nullptr;
2196 }
2197 }
2198
2199 /* Intentionally don't support (Quaternion) here, uses reverse order instead. */
2200
2201 /* make sure v1 is always the vector */
2202 if (vec1 && vec2) {
2203 if (vec1->vec_num != vec2->vec_num) {
2204 PyErr_SetString(PyExc_ValueError,
2205 "Vector multiplication: "
2206 "vectors must have the same dimensions for this operation");
2207 return nullptr;
2208 }
2209
2210 /* element-wise product */
2211 return vector_mul_vec(vec1, vec2);
2212 }
2213 if (vec1) {
2214 if (((scalar = PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred()) == 0) { /* VEC * FLOAT */
2215 return vector_mul_float(vec1, scalar);
2216 }
2217 }
2218 else if (vec2) {
2219 if (((scalar = PyFloat_AsDouble(v1)) == -1.0f && PyErr_Occurred()) == 0) { /* FLOAT * VEC */
2220 return vector_mul_float(vec2, scalar);
2221 }
2222 }
2223
2224 PyErr_Format(PyExc_TypeError,
2225 "Element-wise multiplication: "
2226 "not supported between '%.200s' and '%.200s' types",
2227 Py_TYPE(v1)->tp_name,
2228 Py_TYPE(v2)->tp_name);
2229 return nullptr;
2230}
2231
2233static PyObject *Vector_imul(PyObject *v1, PyObject *v2)
2234{
2235 VectorObject *vec1 = nullptr, *vec2 = nullptr;
2236 float scalar;
2237
2238 if (VectorObject_Check(v1)) {
2239 vec1 = (VectorObject *)v1;
2240 if (BaseMath_ReadCallback(vec1) == -1) {
2241 return nullptr;
2242 }
2243 }
2244 if (VectorObject_Check(v2)) {
2245 vec2 = (VectorObject *)v2;
2246 if (BaseMath_ReadCallback(vec2) == -1) {
2247 return nullptr;
2248 }
2249 }
2250
2251 if (BaseMath_ReadCallback_ForWrite(vec1) == -1) {
2252 return nullptr;
2253 }
2254
2255 /* Intentionally don't support (Quaternion, Matrix) here, uses reverse order instead. */
2256
2257 if (vec1 && vec2) {
2258 if (vec1->vec_num != vec2->vec_num) {
2259 PyErr_SetString(PyExc_ValueError,
2260 "Vector multiplication: "
2261 "vectors must have the same dimensions for this operation");
2262 return nullptr;
2263 }
2264
2265 /* Element-wise product in-place. */
2266 mul_vn_vn(vec1->vec, vec2->vec, vec1->vec_num);
2267 }
2268 else if (vec1 && (((scalar = PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred()) == 0)) {
2269 /* VEC *= FLOAT */
2270 mul_vn_fl(vec1->vec, vec1->vec_num, scalar);
2271 }
2272 else {
2273 PyErr_Format(PyExc_TypeError,
2274 "In place element-wise multiplication: "
2275 "not supported between '%.200s' and '%.200s' types",
2276 Py_TYPE(v1)->tp_name,
2277 Py_TYPE(v2)->tp_name);
2278 return nullptr;
2279 }
2280
2281 (void)BaseMath_WriteCallback(vec1);
2282 Py_INCREF(v1);
2283 return v1;
2284}
2285
2287static PyObject *Vector_matmul(PyObject *v1, PyObject *v2)
2288{
2289 VectorObject *vec1 = nullptr, *vec2 = nullptr;
2290 int vec_num;
2291
2292 if (VectorObject_Check(v1)) {
2293 vec1 = (VectorObject *)v1;
2294 if (BaseMath_ReadCallback(vec1) == -1) {
2295 return nullptr;
2296 }
2297 }
2298 if (VectorObject_Check(v2)) {
2299 vec2 = (VectorObject *)v2;
2300 if (BaseMath_ReadCallback(vec2) == -1) {
2301 return nullptr;
2302 }
2303 }
2304
2305 /* Intentionally don't support (Quaternion) here, uses reverse order instead. */
2306
2307 /* make sure v1 is always the vector */
2308 if (vec1 && vec2) {
2309 if (vec1->vec_num != vec2->vec_num) {
2310 PyErr_SetString(PyExc_ValueError,
2311 "Vector multiplication: "
2312 "vectors must have the same dimensions for this operation");
2313 return nullptr;
2314 }
2315
2316 /* Dot product. */
2317 return PyFloat_FromDouble(dot_vn_vn(vec1->vec, vec2->vec, vec1->vec_num));
2318 }
2319 if (vec1) {
2320 if (MatrixObject_Check(v2)) {
2321 /* VEC @ MATRIX */
2322 float tvec[MAX_DIMENSIONS];
2323
2324 if (BaseMath_ReadCallback((MatrixObject *)v2) == -1) {
2325 return nullptr;
2326 }
2327 if (row_vector_multiplication(tvec, vec1, (MatrixObject *)v2) == -1) {
2328 return nullptr;
2329 }
2330
2331 if (((MatrixObject *)v2)->row_num == 4 && vec1->vec_num == 3) {
2332 vec_num = 3;
2333 }
2334 else {
2335 vec_num = ((MatrixObject *)v2)->col_num;
2336 }
2337
2338 return Vector_CreatePyObject(tvec, vec_num, Py_TYPE(vec1));
2339 }
2340 }
2341
2342 PyErr_Format(PyExc_TypeError,
2343 "Vector multiplication: "
2344 "not supported between '%.200s' and '%.200s' types",
2345 Py_TYPE(v1)->tp_name,
2346 Py_TYPE(v2)->tp_name);
2347 return nullptr;
2348}
2349
2351static PyObject *Vector_imatmul(PyObject *v1, PyObject *v2)
2352{
2353 PyErr_Format(PyExc_TypeError,
2354 "In place vector multiplication: "
2355 "not supported between '%.200s' and '%.200s' types",
2356 Py_TYPE(v1)->tp_name,
2357 Py_TYPE(v2)->tp_name);
2358 return nullptr;
2359}
2360
2362static PyObject *Vector_div(PyObject *v1, PyObject *v2)
2363{
2364 float *vec = nullptr, scalar;
2365 VectorObject *vec1 = nullptr;
2366
2367 if (!VectorObject_Check(v1)) { /* not a vector */
2368 PyErr_SetString(PyExc_TypeError,
2369 "Vector division: "
2370 "Vector must be divided by a float");
2371 return nullptr;
2372 }
2373 vec1 = (VectorObject *)v1; /* vector */
2374
2375 if (BaseMath_ReadCallback(vec1) == -1) {
2376 return nullptr;
2377 }
2378
2379 if ((scalar = PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred()) {
2380 /* parsed item not a number */
2381 PyErr_SetString(PyExc_TypeError,
2382 "Vector division: "
2383 "Vector must be divided by a float");
2384 return nullptr;
2385 }
2386
2387 if (scalar == 0.0f) {
2388 PyErr_SetString(PyExc_ZeroDivisionError,
2389 "Vector division: "
2390 "divide by zero error");
2391 return nullptr;
2392 }
2393
2394 vec = static_cast<float *>(PyMem_Malloc(vec1->vec_num * sizeof(float)));
2395
2396 if (vec == nullptr) {
2397 PyErr_SetString(PyExc_MemoryError,
2398 "vec / value: "
2399 "problem allocating pointer space");
2400 return nullptr;
2401 }
2402
2403 mul_vn_vn_fl(vec, vec1->vec, vec1->vec_num, 1.0f / scalar);
2404
2405 return Vector_CreatePyObject_alloc(vec, vec1->vec_num, Py_TYPE(v1));
2406}
2407
2409static PyObject *Vector_idiv(PyObject *v1, PyObject *v2)
2410{
2411 float scalar;
2412 VectorObject *vec1 = (VectorObject *)v1;
2413
2414 if (BaseMath_ReadCallback_ForWrite(vec1) == -1) {
2415 return nullptr;
2416 }
2417
2418 if ((scalar = PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred()) {
2419 /* parsed item not a number */
2420 PyErr_SetString(PyExc_TypeError,
2421 "Vector division: "
2422 "Vector must be divided by a float");
2423 return nullptr;
2424 }
2425
2426 if (scalar == 0.0f) {
2427 PyErr_SetString(PyExc_ZeroDivisionError,
2428 "Vector division: "
2429 "divide by zero error");
2430 return nullptr;
2431 }
2432
2433 mul_vn_fl(vec1->vec, vec1->vec_num, 1.0f / scalar);
2434
2435 (void)BaseMath_WriteCallback(vec1);
2436
2437 Py_INCREF(v1);
2438 return v1;
2439}
2440
2442static PyObject *Vector_neg(VectorObject *self)
2443{
2444 float *tvec;
2445
2446 if (BaseMath_ReadCallback(self) == -1) {
2447 return nullptr;
2448 }
2449
2450 tvec = static_cast<float *>(PyMem_Malloc(self->vec_num * sizeof(float)));
2451 negate_vn_vn(tvec, self->vec, self->vec_num);
2452 return Vector_CreatePyObject_alloc(tvec, self->vec_num, Py_TYPE(self));
2453}
2454
2457/* -------------------------------------------------------------------- */
2461static PySequenceMethods Vector_SeqMethods = {
2462 /*sq_length*/ (lenfunc)Vector_len,
2463 /*sq_concat*/ nullptr,
2464 /*sq_repeat*/ nullptr,
2465 /*sq_item*/ (ssizeargfunc)Vector_item,
2466 /*was_sq_slice*/ nullptr, /* DEPRECATED. */
2467 /*sq_ass_item*/ (ssizeobjargproc)Vector_ass_item,
2468 /*was_sq_ass_slice*/ nullptr, /* DEPRECATED. */
2469 /*sq_contains*/ nullptr,
2470 /*sq_inplace_concat*/ nullptr,
2471 /*sq_inplace_repeat*/ nullptr,
2472};
2473
2474static PyMappingMethods Vector_AsMapping = {
2475 /*mp_length*/ (lenfunc)Vector_len,
2476 /*mp_subscript*/ (binaryfunc)Vector_subscript,
2477 /*mp_ass_subscript*/ (objobjargproc)Vector_ass_subscript,
2478};
2479
2480static PyNumberMethods Vector_NumMethods = {
2481 /*nb_add*/ (binaryfunc)Vector_add,
2482 /*nb_subtract*/ (binaryfunc)Vector_sub,
2483 /*nb_multiply*/ (binaryfunc)Vector_mul,
2484 /*nb_remainder*/ nullptr,
2485 /*nb_divmod*/ nullptr,
2486 /*nb_power*/ nullptr,
2487 /*nb_negative*/ (unaryfunc)Vector_neg,
2488 /*nb_positive*/ (unaryfunc)Vector_copy,
2489 /*nb_absolute*/ nullptr,
2490 /*nb_bool*/ nullptr,
2491 /*nb_invert*/ nullptr,
2492 /*nb_lshift*/ nullptr,
2493 /*nb_rshift*/ nullptr,
2494 /*nb_and*/ nullptr,
2495 /*nb_xor*/ nullptr,
2496 /*nb_or*/ nullptr,
2497 /*nb_int*/ nullptr,
2498 /*nb_reserved*/ nullptr,
2499 /*nb_float*/ nullptr,
2500 /*nb_inplace_add*/ Vector_iadd,
2501 /*nb_inplace_subtract*/ Vector_isub,
2502 /*nb_inplace_multiply*/ Vector_imul,
2503 /*nb_inplace_remainder*/ nullptr,
2504 /*nb_inplace_power*/ nullptr,
2505 /*nb_inplace_lshift*/ nullptr,
2506 /*nb_inplace_rshift*/ nullptr,
2507 /*nb_inplace_and*/ nullptr,
2508 /*nb_inplace_xor*/ nullptr,
2509 /*nb_inplace_or*/ nullptr,
2510 /*nb_floor_divide*/ nullptr,
2511 /*nb_true_divide*/ Vector_div,
2512 /*nb_inplace_floor_divide*/ nullptr,
2513 /*nb_inplace_true_divide*/ Vector_idiv,
2514 /*nb_index*/ nullptr,
2515 /*nb_matrix_multiply*/ (binaryfunc)Vector_matmul,
2516 /*nb_inplace_matrix_multiply*/ (binaryfunc)Vector_imatmul,
2517};
2518
2521/* -------------------------------------------------------------------- */
2525/* Vector axis: `vector.x/y/z/w`. */
2526
2528 /* Wrap. */
2529 Vector_axis_x_doc,
2530 "Vector X axis.\n"
2531 "\n"
2532 ":type: float");
2534 /* Wrap. */
2535 Vector_axis_y_doc,
2536 "Vector Y axis.\n"
2537 "\n"
2538 ":type: float");
2540 /* Wrap. */
2541 Vector_axis_z_doc,
2542 "Vector Z axis (3D Vectors only).\n"
2543 "\n"
2544 ":type: float");
2546 /* Wrap. */
2547 Vector_axis_w_doc,
2548 "Vector W axis (4D Vectors only).\n"
2549 "\n"
2550 ":type: float");
2551
2552static PyObject *Vector_axis_get(VectorObject *self, void *type)
2553{
2554 return vector_item_internal(self, POINTER_AS_INT(type), true);
2555}
2556
2557static int Vector_axis_set(VectorObject *self, PyObject *value, void *type)
2558{
2559 return vector_ass_item_internal(self, POINTER_AS_INT(type), value, true);
2560}
2561
2562/* `Vector.length`. */
2563
2565 /* Wrap. */
2566 Vector_length_doc,
2567 "Vector Length.\n"
2568 "\n"
2569 ":type: float");
2570static PyObject *Vector_length_get(VectorObject *self, void * /*closure*/)
2571{
2572 if (BaseMath_ReadCallback(self) == -1) {
2573 return nullptr;
2574 }
2575
2576 return PyFloat_FromDouble(sqrt(dot_vn_vn(self->vec, self->vec, self->vec_num)));
2577}
2578
2579static int Vector_length_set(VectorObject *self, PyObject *value)
2580{
2581 double dot = 0.0f, param;
2582
2584 return -1;
2585 }
2586
2587 if ((param = PyFloat_AsDouble(value)) == -1.0 && PyErr_Occurred()) {
2588 PyErr_SetString(PyExc_TypeError, "length must be set to a number");
2589 return -1;
2590 }
2591
2592 if (param < 0.0) {
2593 PyErr_SetString(PyExc_ValueError, "cannot set a vectors length to a negative value");
2594 return -1;
2595 }
2596 if (param == 0.0) {
2597 copy_vn_fl(self->vec, self->vec_num, 0.0f);
2598 return 0;
2599 }
2600
2601 dot = dot_vn_vn(self->vec, self->vec, self->vec_num);
2602
2603 if (!dot) {
2604 /* can't sqrt zero */
2605 return 0;
2606 }
2607
2608 dot = sqrt(dot);
2609
2610 if (dot == param) {
2611 return 0;
2612 }
2613
2614 dot = dot / param;
2615
2616 mul_vn_fl(self->vec, self->vec_num, 1.0 / dot);
2617
2618 (void)BaseMath_WriteCallback(self); /* checked already */
2619
2620 return 0;
2621}
2622
2623/* `Vector.length_squared`. */
2625 /* Wrap. */
2626 Vector_length_squared_doc,
2627 "Vector length squared (v.dot(v)).\n"
2628 "\n"
2629 ":type: float");
2630static PyObject *Vector_length_squared_get(VectorObject *self, void * /*closure*/)
2631{
2632 if (BaseMath_ReadCallback(self) == -1) {
2633 return nullptr;
2634 }
2635
2636 return PyFloat_FromDouble(dot_vn_vn(self->vec, self->vec, self->vec_num));
2637}
2638
2639/* `Vector.xyzw`, etc.. */
2641 /* Wrap. */
2642 Vector_swizzle_doc,
2643 ":type: :class:`Vector`");
2644
2731static PyObject *Vector_swizzle_get(VectorObject *self, void *closure)
2732{
2733 size_t axis_to;
2734 size_t axis_from;
2735 float vec[MAX_DIMENSIONS];
2736 uint swizzleClosure;
2737
2738 if (BaseMath_ReadCallback(self) == -1) {
2739 return nullptr;
2740 }
2741
2742 /* Unpack the axes from the closure into an array. */
2743 axis_to = 0;
2744 swizzleClosure = POINTER_AS_INT(closure);
2745 while (swizzleClosure & SWIZZLE_VALID_AXIS) {
2746 axis_from = swizzleClosure & SWIZZLE_AXIS;
2747 if (axis_from >= self->vec_num) {
2748 PyErr_SetString(PyExc_AttributeError,
2749 "Vector swizzle: "
2750 "specified axis not present");
2751 return nullptr;
2752 }
2753
2754 vec[axis_to] = self->vec[axis_from];
2755 swizzleClosure = swizzleClosure >> SWIZZLE_BITS_PER_AXIS;
2756 axis_to++;
2757 }
2758
2759 return Vector_CreatePyObject(vec, axis_to, Py_TYPE(self));
2760}
2761
2773static int Vector_swizzle_set(VectorObject *self, PyObject *value, void *closure)
2774{
2775 size_t size_from;
2776 float scalarVal;
2777
2778 size_t axis_from;
2779 size_t axis_to;
2780
2781 uint swizzleClosure;
2782
2783 float tvec[MAX_DIMENSIONS];
2784 float vec_assign[MAX_DIMENSIONS];
2785
2787 return -1;
2788 }
2789
2790 /* Check that the closure can be used with this vector: even 2D vectors have
2791 * swizzles defined for axes z and w, but they would be invalid. */
2792 swizzleClosure = POINTER_AS_INT(closure);
2793 axis_from = 0;
2794
2795 while (swizzleClosure & SWIZZLE_VALID_AXIS) {
2796 axis_to = swizzleClosure & SWIZZLE_AXIS;
2797 if (axis_to >= self->vec_num) {
2798 PyErr_SetString(PyExc_AttributeError,
2799 "Vector swizzle: "
2800 "specified axis not present");
2801 return -1;
2802 }
2803 swizzleClosure = swizzleClosure >> SWIZZLE_BITS_PER_AXIS;
2804 axis_from++;
2805 }
2806
2807 if (((scalarVal = PyFloat_AsDouble(value)) == -1 && PyErr_Occurred()) == 0) {
2808 int i;
2809
2810 for (i = 0; i < MAX_DIMENSIONS; i++) {
2811 vec_assign[i] = scalarVal;
2812 }
2813
2814 size_from = axis_from;
2815 }
2816 else if ((void)PyErr_Clear(), /* run but ignore the result */
2817 (size_from = size_t(mathutils_array_parse(
2818 vec_assign, 2, 4, value, "Vector.**** = swizzle assignment"))) == size_t(-1))
2819 {
2820 return -1;
2821 }
2822
2823 if (axis_from != size_from) {
2824 PyErr_SetString(PyExc_AttributeError, "Vector swizzle: size does not match swizzle");
2825 return -1;
2826 }
2827
2828 /* Copy vector contents onto swizzled axes. */
2829 axis_from = 0;
2830 swizzleClosure = POINTER_AS_INT(closure);
2831
2832 /* We must first copy current vec into tvec, else some org values may be lost.
2833 * See #31760.
2834 * Assuming self->vec_num can't be higher than MAX_DIMENSIONS! */
2835 memcpy(tvec, self->vec, self->vec_num * sizeof(float));
2836
2837 while (swizzleClosure & SWIZZLE_VALID_AXIS) {
2838 axis_to = swizzleClosure & SWIZZLE_AXIS;
2839 tvec[axis_to] = vec_assign[axis_from];
2840 swizzleClosure = swizzleClosure >> SWIZZLE_BITS_PER_AXIS;
2841 axis_from++;
2842 }
2843
2844 /* We must copy back the whole tvec into vec, else some changes may be lost (e.g. xz...).
2845 * See #31760. */
2846 memcpy(self->vec, tvec, self->vec_num * sizeof(float));
2847 /* continue with BaseMathObject_WriteCallback at the end */
2848
2849 if (BaseMath_WriteCallback(self) == -1) {
2850 return -1;
2851 }
2852
2853 return 0;
2854}
2855
2856#define _SWIZZLE1(a) ((a) | SWIZZLE_VALID_AXIS)
2857#define _SWIZZLE2(a, b) (_SWIZZLE1(a) | (((b) | SWIZZLE_VALID_AXIS) << (SWIZZLE_BITS_PER_AXIS)))
2858#define _SWIZZLE3(a, b, c) \
2859 (_SWIZZLE2(a, b) | (((c) | SWIZZLE_VALID_AXIS) << (SWIZZLE_BITS_PER_AXIS * 2)))
2860#define _SWIZZLE4(a, b, c, d) \
2861 (_SWIZZLE3(a, b, c) | (((d) | SWIZZLE_VALID_AXIS) << (SWIZZLE_BITS_PER_AXIS * 3)))
2862
2863#define SWIZZLE2(a, b) POINTER_FROM_INT(_SWIZZLE2(a, b))
2864#define SWIZZLE3(a, b, c) POINTER_FROM_INT(_SWIZZLE3(a, b, c))
2865#define SWIZZLE4(a, b, c, d) POINTER_FROM_INT(_SWIZZLE4(a, b, c, d))
2866
2867#define VECTOR_SWIZZLE2_RW_DEF(attr, a, b) \
2868 { \
2869 attr, (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, Vector_swizzle_doc, \
2870 SWIZZLE2(a, b), \
2871 }
2872#define VECTOR_SWIZZLE2_RO_DEF(attr, a, b) \
2873 { \
2874 attr, (getter)Vector_swizzle_get, (setter) nullptr, Vector_swizzle_doc, SWIZZLE2(a, b), \
2875 }
2876#define VECTOR_SWIZZLE3_RW_DEF(attr, a, b, c) \
2877 { \
2878 attr, (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, Vector_swizzle_doc, \
2879 SWIZZLE3(a, b, c), \
2880 }
2881#define VECTOR_SWIZZLE3_RO_DEF(attr, a, b, c) \
2882 { \
2883 attr, (getter)Vector_swizzle_get, (setter) nullptr, Vector_swizzle_doc, SWIZZLE3(a, b, c), \
2884 }
2885#define VECTOR_SWIZZLE4_RW_DEF(attr, a, b, c, d) \
2886 { \
2887 attr, (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, Vector_swizzle_doc, \
2888 SWIZZLE4(a, b, c, d), \
2889 }
2890#define VECTOR_SWIZZLE4_RO_DEF(attr, a, b, c, d) \
2891 { \
2892 attr, (getter)Vector_swizzle_get, (setter) nullptr, Vector_swizzle_doc, SWIZZLE4(a, b, c, d) \
2893 }
2894
2897/* -------------------------------------------------------------------- */
2901#if (defined(__GNUC__) && !defined(__clang__))
2902# pragma GCC diagnostic push
2903# pragma GCC diagnostic ignored "-Wcast-function-type"
2904#endif
2905
2906static PyGetSetDef Vector_getseters[] = {
2907 {"x",
2908 (getter)Vector_axis_get,
2909 (setter)Vector_axis_set,
2910 Vector_axis_x_doc,
2911 POINTER_FROM_INT(0)},
2912 {"y",
2913 (getter)Vector_axis_get,
2914 (setter)Vector_axis_set,
2915 Vector_axis_y_doc,
2916 POINTER_FROM_INT(1)},
2917 {"z",
2918 (getter)Vector_axis_get,
2919 (setter)Vector_axis_set,
2920 Vector_axis_z_doc,
2921 POINTER_FROM_INT(2)},
2922 {"w",
2923 (getter)Vector_axis_get,
2924 (setter)Vector_axis_set,
2925 Vector_axis_w_doc,
2926 POINTER_FROM_INT(3)},
2927 {"length", (getter)Vector_length_get, (setter)Vector_length_set, Vector_length_doc, nullptr},
2928 {"length_squared",
2930 (setter) nullptr,
2931 Vector_length_squared_doc,
2932 nullptr},
2933 {"magnitude",
2934 (getter)Vector_length_get,
2935 (setter)Vector_length_set,
2936 Vector_length_doc,
2937 nullptr},
2938 {"is_wrapped",
2940 (setter) nullptr,
2942 nullptr},
2943 {"is_frozen",
2945 (setter) nullptr,
2947 nullptr},
2948 {"is_valid",
2950 (setter) nullptr,
2952 nullptr},
2953 {"owner",
2955 (setter) nullptr,
2957 nullptr},
2958
2959 /* Auto-generated swizzle attributes, see Python script above. */
2960 VECTOR_SWIZZLE2_RO_DEF("xx", 0, 0),
2961 VECTOR_SWIZZLE3_RO_DEF("xxx", 0, 0, 0),
2962 VECTOR_SWIZZLE4_RO_DEF("xxxx", 0, 0, 0, 0),
2963 VECTOR_SWIZZLE4_RO_DEF("xxxy", 0, 0, 0, 1),
2964 VECTOR_SWIZZLE4_RO_DEF("xxxz", 0, 0, 0, 2),
2965 VECTOR_SWIZZLE4_RO_DEF("xxxw", 0, 0, 0, 3),
2966 VECTOR_SWIZZLE3_RO_DEF("xxy", 0, 0, 1),
2967 VECTOR_SWIZZLE4_RO_DEF("xxyx", 0, 0, 1, 0),
2968 VECTOR_SWIZZLE4_RO_DEF("xxyy", 0, 0, 1, 1),
2969 VECTOR_SWIZZLE4_RO_DEF("xxyz", 0, 0, 1, 2),
2970 VECTOR_SWIZZLE4_RO_DEF("xxyw", 0, 0, 1, 3),
2971 VECTOR_SWIZZLE3_RO_DEF("xxz", 0, 0, 2),
2972 VECTOR_SWIZZLE4_RO_DEF("xxzx", 0, 0, 2, 0),
2973 VECTOR_SWIZZLE4_RO_DEF("xxzy", 0, 0, 2, 1),
2974 VECTOR_SWIZZLE4_RO_DEF("xxzz", 0, 0, 2, 2),
2975 VECTOR_SWIZZLE4_RO_DEF("xxzw", 0, 0, 2, 3),
2976 VECTOR_SWIZZLE3_RO_DEF("xxw", 0, 0, 3),
2977 VECTOR_SWIZZLE4_RO_DEF("xxwx", 0, 0, 3, 0),
2978 VECTOR_SWIZZLE4_RO_DEF("xxwy", 0, 0, 3, 1),
2979 VECTOR_SWIZZLE4_RO_DEF("xxwz", 0, 0, 3, 2),
2980 VECTOR_SWIZZLE4_RO_DEF("xxww", 0, 0, 3, 3),
2981 VECTOR_SWIZZLE2_RW_DEF("xy", 0, 1),
2982 VECTOR_SWIZZLE3_RO_DEF("xyx", 0, 1, 0),
2983 VECTOR_SWIZZLE4_RO_DEF("xyxx", 0, 1, 0, 0),
2984 VECTOR_SWIZZLE4_RO_DEF("xyxy", 0, 1, 0, 1),
2985 VECTOR_SWIZZLE4_RO_DEF("xyxz", 0, 1, 0, 2),
2986 VECTOR_SWIZZLE4_RO_DEF("xyxw", 0, 1, 0, 3),
2987 VECTOR_SWIZZLE3_RO_DEF("xyy", 0, 1, 1),
2988 VECTOR_SWIZZLE4_RO_DEF("xyyx", 0, 1, 1, 0),
2989 VECTOR_SWIZZLE4_RO_DEF("xyyy", 0, 1, 1, 1),
2990 VECTOR_SWIZZLE4_RO_DEF("xyyz", 0, 1, 1, 2),
2991 VECTOR_SWIZZLE4_RO_DEF("xyyw", 0, 1, 1, 3),
2992 VECTOR_SWIZZLE3_RW_DEF("xyz", 0, 1, 2),
2993 VECTOR_SWIZZLE4_RO_DEF("xyzx", 0, 1, 2, 0),
2994 VECTOR_SWIZZLE4_RO_DEF("xyzy", 0, 1, 2, 1),
2995 VECTOR_SWIZZLE4_RO_DEF("xyzz", 0, 1, 2, 2),
2996 VECTOR_SWIZZLE4_RW_DEF("xyzw", 0, 1, 2, 3),
2997 VECTOR_SWIZZLE3_RW_DEF("xyw", 0, 1, 3),
2998 VECTOR_SWIZZLE4_RO_DEF("xywx", 0, 1, 3, 0),
2999 VECTOR_SWIZZLE4_RO_DEF("xywy", 0, 1, 3, 1),
3000 VECTOR_SWIZZLE4_RW_DEF("xywz", 0, 1, 3, 2),
3001 VECTOR_SWIZZLE4_RO_DEF("xyww", 0, 1, 3, 3),
3002 VECTOR_SWIZZLE2_RW_DEF("xz", 0, 2),
3003 VECTOR_SWIZZLE3_RO_DEF("xzx", 0, 2, 0),
3004 VECTOR_SWIZZLE4_RO_DEF("xzxx", 0, 2, 0, 0),
3005 VECTOR_SWIZZLE4_RO_DEF("xzxy", 0, 2, 0, 1),
3006 VECTOR_SWIZZLE4_RO_DEF("xzxz", 0, 2, 0, 2),
3007 VECTOR_SWIZZLE4_RO_DEF("xzxw", 0, 2, 0, 3),
3008 VECTOR_SWIZZLE3_RW_DEF("xzy", 0, 2, 1),
3009 VECTOR_SWIZZLE4_RO_DEF("xzyx", 0, 2, 1, 0),
3010 VECTOR_SWIZZLE4_RO_DEF("xzyy", 0, 2, 1, 1),
3011 VECTOR_SWIZZLE4_RO_DEF("xzyz", 0, 2, 1, 2),
3012 VECTOR_SWIZZLE4_RW_DEF("xzyw", 0, 2, 1, 3),
3013 VECTOR_SWIZZLE3_RO_DEF("xzz", 0, 2, 2),
3014 VECTOR_SWIZZLE4_RO_DEF("xzzx", 0, 2, 2, 0),
3015 VECTOR_SWIZZLE4_RO_DEF("xzzy", 0, 2, 2, 1),
3016 VECTOR_SWIZZLE4_RO_DEF("xzzz", 0, 2, 2, 2),
3017 VECTOR_SWIZZLE4_RO_DEF("xzzw", 0, 2, 2, 3),
3018 VECTOR_SWIZZLE3_RW_DEF("xzw", 0, 2, 3),
3019 VECTOR_SWIZZLE4_RO_DEF("xzwx", 0, 2, 3, 0),
3020 VECTOR_SWIZZLE4_RW_DEF("xzwy", 0, 2, 3, 1),
3021 VECTOR_SWIZZLE4_RO_DEF("xzwz", 0, 2, 3, 2),
3022 VECTOR_SWIZZLE4_RO_DEF("xzww", 0, 2, 3, 3),
3023 VECTOR_SWIZZLE2_RW_DEF("xw", 0, 3),
3024 VECTOR_SWIZZLE3_RO_DEF("xwx", 0, 3, 0),
3025 VECTOR_SWIZZLE4_RO_DEF("xwxx", 0, 3, 0, 0),
3026 VECTOR_SWIZZLE4_RO_DEF("xwxy", 0, 3, 0, 1),
3027 VECTOR_SWIZZLE4_RO_DEF("xwxz", 0, 3, 0, 2),
3028 VECTOR_SWIZZLE4_RO_DEF("xwxw", 0, 3, 0, 3),
3029 VECTOR_SWIZZLE3_RW_DEF("xwy", 0, 3, 1),
3030 VECTOR_SWIZZLE4_RO_DEF("xwyx", 0, 3, 1, 0),
3031 VECTOR_SWIZZLE4_RO_DEF("xwyy", 0, 3, 1, 1),
3032 VECTOR_SWIZZLE4_RW_DEF("xwyz", 0, 3, 1, 2),
3033 VECTOR_SWIZZLE4_RO_DEF("xwyw", 0, 3, 1, 3),
3034 VECTOR_SWIZZLE3_RW_DEF("xwz", 0, 3, 2),
3035 VECTOR_SWIZZLE4_RO_DEF("xwzx", 0, 3, 2, 0),
3036 VECTOR_SWIZZLE4_RW_DEF("xwzy", 0, 3, 2, 1),
3037 VECTOR_SWIZZLE4_RO_DEF("xwzz", 0, 3, 2, 2),
3038 VECTOR_SWIZZLE4_RO_DEF("xwzw", 0, 3, 2, 3),
3039 VECTOR_SWIZZLE3_RO_DEF("xww", 0, 3, 3),
3040 VECTOR_SWIZZLE4_RO_DEF("xwwx", 0, 3, 3, 0),
3041 VECTOR_SWIZZLE4_RO_DEF("xwwy", 0, 3, 3, 1),
3042 VECTOR_SWIZZLE4_RO_DEF("xwwz", 0, 3, 3, 2),
3043 VECTOR_SWIZZLE4_RO_DEF("xwww", 0, 3, 3, 3),
3044 VECTOR_SWIZZLE2_RW_DEF("yx", 1, 0),
3045 VECTOR_SWIZZLE3_RO_DEF("yxx", 1, 0, 0),
3046 VECTOR_SWIZZLE4_RO_DEF("yxxx", 1, 0, 0, 0),
3047 VECTOR_SWIZZLE4_RO_DEF("yxxy", 1, 0, 0, 1),
3048 VECTOR_SWIZZLE4_RO_DEF("yxxz", 1, 0, 0, 2),
3049 VECTOR_SWIZZLE4_RO_DEF("yxxw", 1, 0, 0, 3),
3050 VECTOR_SWIZZLE3_RO_DEF("yxy", 1, 0, 1),
3051 VECTOR_SWIZZLE4_RO_DEF("yxyx", 1, 0, 1, 0),
3052 VECTOR_SWIZZLE4_RO_DEF("yxyy", 1, 0, 1, 1),
3053 VECTOR_SWIZZLE4_RO_DEF("yxyz", 1, 0, 1, 2),
3054 VECTOR_SWIZZLE4_RO_DEF("yxyw", 1, 0, 1, 3),
3055 VECTOR_SWIZZLE3_RW_DEF("yxz", 1, 0, 2),
3056 VECTOR_SWIZZLE4_RO_DEF("yxzx", 1, 0, 2, 0),
3057 VECTOR_SWIZZLE4_RO_DEF("yxzy", 1, 0, 2, 1),
3058 VECTOR_SWIZZLE4_RO_DEF("yxzz", 1, 0, 2, 2),
3059 VECTOR_SWIZZLE4_RW_DEF("yxzw", 1, 0, 2, 3),
3060 VECTOR_SWIZZLE3_RW_DEF("yxw", 1, 0, 3),
3061 VECTOR_SWIZZLE4_RO_DEF("yxwx", 1, 0, 3, 0),
3062 VECTOR_SWIZZLE4_RO_DEF("yxwy", 1, 0, 3, 1),
3063 VECTOR_SWIZZLE4_RW_DEF("yxwz", 1, 0, 3, 2),
3064 VECTOR_SWIZZLE4_RO_DEF("yxww", 1, 0, 3, 3),
3065 VECTOR_SWIZZLE2_RO_DEF("yy", 1, 1),
3066 VECTOR_SWIZZLE3_RO_DEF("yyx", 1, 1, 0),
3067 VECTOR_SWIZZLE4_RO_DEF("yyxx", 1, 1, 0, 0),
3068 VECTOR_SWIZZLE4_RO_DEF("yyxy", 1, 1, 0, 1),
3069 VECTOR_SWIZZLE4_RO_DEF("yyxz", 1, 1, 0, 2),
3070 VECTOR_SWIZZLE4_RO_DEF("yyxw", 1, 1, 0, 3),
3071 VECTOR_SWIZZLE3_RO_DEF("yyy", 1, 1, 1),
3072 VECTOR_SWIZZLE4_RO_DEF("yyyx", 1, 1, 1, 0),
3073 VECTOR_SWIZZLE4_RO_DEF("yyyy", 1, 1, 1, 1),
3074 VECTOR_SWIZZLE4_RO_DEF("yyyz", 1, 1, 1, 2),
3075 VECTOR_SWIZZLE4_RO_DEF("yyyw", 1, 1, 1, 3),
3076 VECTOR_SWIZZLE3_RO_DEF("yyz", 1, 1, 2),
3077 VECTOR_SWIZZLE4_RO_DEF("yyzx", 1, 1, 2, 0),
3078 VECTOR_SWIZZLE4_RO_DEF("yyzy", 1, 1, 2, 1),
3079 VECTOR_SWIZZLE4_RO_DEF("yyzz", 1, 1, 2, 2),
3080 VECTOR_SWIZZLE4_RO_DEF("yyzw", 1, 1, 2, 3),
3081 VECTOR_SWIZZLE3_RO_DEF("yyw", 1, 1, 3),
3082 VECTOR_SWIZZLE4_RO_DEF("yywx", 1, 1, 3, 0),
3083 VECTOR_SWIZZLE4_RO_DEF("yywy", 1, 1, 3, 1),
3084 VECTOR_SWIZZLE4_RO_DEF("yywz", 1, 1, 3, 2),
3085 VECTOR_SWIZZLE4_RO_DEF("yyww", 1, 1, 3, 3),
3086 VECTOR_SWIZZLE2_RW_DEF("yz", 1, 2),
3087 VECTOR_SWIZZLE3_RW_DEF("yzx", 1, 2, 0),
3088 VECTOR_SWIZZLE4_RO_DEF("yzxx", 1, 2, 0, 0),
3089 VECTOR_SWIZZLE4_RO_DEF("yzxy", 1, 2, 0, 1),
3090 VECTOR_SWIZZLE4_RO_DEF("yzxz", 1, 2, 0, 2),
3091 VECTOR_SWIZZLE4_RW_DEF("yzxw", 1, 2, 0, 3),
3092 VECTOR_SWIZZLE3_RO_DEF("yzy", 1, 2, 1),
3093 VECTOR_SWIZZLE4_RO_DEF("yzyx", 1, 2, 1, 0),
3094 VECTOR_SWIZZLE4_RO_DEF("yzyy", 1, 2, 1, 1),
3095 VECTOR_SWIZZLE4_RO_DEF("yzyz", 1, 2, 1, 2),
3096 VECTOR_SWIZZLE4_RO_DEF("yzyw", 1, 2, 1, 3),
3097 VECTOR_SWIZZLE3_RO_DEF("yzz", 1, 2, 2),
3098 VECTOR_SWIZZLE4_RO_DEF("yzzx", 1, 2, 2, 0),
3099 VECTOR_SWIZZLE4_RO_DEF("yzzy", 1, 2, 2, 1),
3100 VECTOR_SWIZZLE4_RO_DEF("yzzz", 1, 2, 2, 2),
3101 VECTOR_SWIZZLE4_RO_DEF("yzzw", 1, 2, 2, 3),
3102 VECTOR_SWIZZLE3_RW_DEF("yzw", 1, 2, 3),
3103 VECTOR_SWIZZLE4_RW_DEF("yzwx", 1, 2, 3, 0),
3104 VECTOR_SWIZZLE4_RO_DEF("yzwy", 1, 2, 3, 1),
3105 VECTOR_SWIZZLE4_RO_DEF("yzwz", 1, 2, 3, 2),
3106 VECTOR_SWIZZLE4_RO_DEF("yzww", 1, 2, 3, 3),
3107 VECTOR_SWIZZLE2_RW_DEF("yw", 1, 3),
3108 VECTOR_SWIZZLE3_RW_DEF("ywx", 1, 3, 0),
3109 VECTOR_SWIZZLE4_RO_DEF("ywxx", 1, 3, 0, 0),
3110 VECTOR_SWIZZLE4_RO_DEF("ywxy", 1, 3, 0, 1),
3111 VECTOR_SWIZZLE4_RW_DEF("ywxz", 1, 3, 0, 2),
3112 VECTOR_SWIZZLE4_RO_DEF("ywxw", 1, 3, 0, 3),
3113 VECTOR_SWIZZLE3_RO_DEF("ywy", 1, 3, 1),
3114 VECTOR_SWIZZLE4_RO_DEF("ywyx", 1, 3, 1, 0),
3115 VECTOR_SWIZZLE4_RO_DEF("ywyy", 1, 3, 1, 1),
3116 VECTOR_SWIZZLE4_RO_DEF("ywyz", 1, 3, 1, 2),
3117 VECTOR_SWIZZLE4_RO_DEF("ywyw", 1, 3, 1, 3),
3118 VECTOR_SWIZZLE3_RW_DEF("ywz", 1, 3, 2),
3119 VECTOR_SWIZZLE4_RW_DEF("ywzx", 1, 3, 2, 0),
3120 VECTOR_SWIZZLE4_RO_DEF("ywzy", 1, 3, 2, 1),
3121 VECTOR_SWIZZLE4_RO_DEF("ywzz", 1, 3, 2, 2),
3122 VECTOR_SWIZZLE4_RO_DEF("ywzw", 1, 3, 2, 3),
3123 VECTOR_SWIZZLE3_RO_DEF("yww", 1, 3, 3),
3124 VECTOR_SWIZZLE4_RO_DEF("ywwx", 1, 3, 3, 0),
3125 VECTOR_SWIZZLE4_RO_DEF("ywwy", 1, 3, 3, 1),
3126 VECTOR_SWIZZLE4_RO_DEF("ywwz", 1, 3, 3, 2),
3127 VECTOR_SWIZZLE4_RO_DEF("ywww", 1, 3, 3, 3),
3128 VECTOR_SWIZZLE2_RW_DEF("zx", 2, 0),
3129 VECTOR_SWIZZLE3_RO_DEF("zxx", 2, 0, 0),
3130 VECTOR_SWIZZLE4_RO_DEF("zxxx", 2, 0, 0, 0),
3131 VECTOR_SWIZZLE4_RO_DEF("zxxy", 2, 0, 0, 1),
3132 VECTOR_SWIZZLE4_RO_DEF("zxxz", 2, 0, 0, 2),
3133 VECTOR_SWIZZLE4_RO_DEF("zxxw", 2, 0, 0, 3),
3134 VECTOR_SWIZZLE3_RW_DEF("zxy", 2, 0, 1),
3135 VECTOR_SWIZZLE4_RO_DEF("zxyx", 2, 0, 1, 0),
3136 VECTOR_SWIZZLE4_RO_DEF("zxyy", 2, 0, 1, 1),
3137 VECTOR_SWIZZLE4_RO_DEF("zxyz", 2, 0, 1, 2),
3138 VECTOR_SWIZZLE4_RW_DEF("zxyw", 2, 0, 1, 3),
3139 VECTOR_SWIZZLE3_RO_DEF("zxz", 2, 0, 2),
3140 VECTOR_SWIZZLE4_RO_DEF("zxzx", 2, 0, 2, 0),
3141 VECTOR_SWIZZLE4_RO_DEF("zxzy", 2, 0, 2, 1),
3142 VECTOR_SWIZZLE4_RO_DEF("zxzz", 2, 0, 2, 2),
3143 VECTOR_SWIZZLE4_RO_DEF("zxzw", 2, 0, 2, 3),
3144 VECTOR_SWIZZLE3_RW_DEF("zxw", 2, 0, 3),
3145 VECTOR_SWIZZLE4_RO_DEF("zxwx", 2, 0, 3, 0),
3146 VECTOR_SWIZZLE4_RW_DEF("zxwy", 2, 0, 3, 1),
3147 VECTOR_SWIZZLE4_RO_DEF("zxwz", 2, 0, 3, 2),
3148 VECTOR_SWIZZLE4_RO_DEF("zxww", 2, 0, 3, 3),
3149 VECTOR_SWIZZLE2_RW_DEF("zy", 2, 1),
3150 VECTOR_SWIZZLE3_RW_DEF("zyx", 2, 1, 0),
3151 VECTOR_SWIZZLE4_RO_DEF("zyxx", 2, 1, 0, 0),
3152 VECTOR_SWIZZLE4_RO_DEF("zyxy", 2, 1, 0, 1),
3153 VECTOR_SWIZZLE4_RO_DEF("zyxz", 2, 1, 0, 2),
3154 VECTOR_SWIZZLE4_RW_DEF("zyxw", 2, 1, 0, 3),
3155 VECTOR_SWIZZLE3_RO_DEF("zyy", 2, 1, 1),
3156 VECTOR_SWIZZLE4_RO_DEF("zyyx", 2, 1, 1, 0),
3157 VECTOR_SWIZZLE4_RO_DEF("zyyy", 2, 1, 1, 1),
3158 VECTOR_SWIZZLE4_RO_DEF("zyyz", 2, 1, 1, 2),
3159 VECTOR_SWIZZLE4_RO_DEF("zyyw", 2, 1, 1, 3),
3160 VECTOR_SWIZZLE3_RO_DEF("zyz", 2, 1, 2),
3161 VECTOR_SWIZZLE4_RO_DEF("zyzx", 2, 1, 2, 0),
3162 VECTOR_SWIZZLE4_RO_DEF("zyzy", 2, 1, 2, 1),
3163 VECTOR_SWIZZLE4_RO_DEF("zyzz", 2, 1, 2, 2),
3164 VECTOR_SWIZZLE4_RO_DEF("zyzw", 2, 1, 2, 3),
3165 VECTOR_SWIZZLE3_RW_DEF("zyw", 2, 1, 3),
3166 VECTOR_SWIZZLE4_RW_DEF("zywx", 2, 1, 3, 0),
3167 VECTOR_SWIZZLE4_RO_DEF("zywy", 2, 1, 3, 1),
3168 VECTOR_SWIZZLE4_RO_DEF("zywz", 2, 1, 3, 2),
3169 VECTOR_SWIZZLE4_RO_DEF("zyww", 2, 1, 3, 3),
3170 VECTOR_SWIZZLE2_RO_DEF("zz", 2, 2),
3171 VECTOR_SWIZZLE3_RO_DEF("zzx", 2, 2, 0),
3172 VECTOR_SWIZZLE4_RO_DEF("zzxx", 2, 2, 0, 0),
3173 VECTOR_SWIZZLE4_RO_DEF("zzxy", 2, 2, 0, 1),
3174 VECTOR_SWIZZLE4_RO_DEF("zzxz", 2, 2, 0, 2),
3175 VECTOR_SWIZZLE4_RO_DEF("zzxw", 2, 2, 0, 3),
3176 VECTOR_SWIZZLE3_RO_DEF("zzy", 2, 2, 1),
3177 VECTOR_SWIZZLE4_RO_DEF("zzyx", 2, 2, 1, 0),
3178 VECTOR_SWIZZLE4_RO_DEF("zzyy", 2, 2, 1, 1),
3179 VECTOR_SWIZZLE4_RO_DEF("zzyz", 2, 2, 1, 2),
3180 VECTOR_SWIZZLE4_RO_DEF("zzyw", 2, 2, 1, 3),
3181 VECTOR_SWIZZLE3_RO_DEF("zzz", 2, 2, 2),
3182 VECTOR_SWIZZLE4_RO_DEF("zzzx", 2, 2, 2, 0),
3183 VECTOR_SWIZZLE4_RO_DEF("zzzy", 2, 2, 2, 1),
3184 VECTOR_SWIZZLE4_RO_DEF("zzzz", 2, 2, 2, 2),
3185 VECTOR_SWIZZLE4_RO_DEF("zzzw", 2, 2, 2, 3),
3186 VECTOR_SWIZZLE3_RO_DEF("zzw", 2, 2, 3),
3187 VECTOR_SWIZZLE4_RO_DEF("zzwx", 2, 2, 3, 0),
3188 VECTOR_SWIZZLE4_RO_DEF("zzwy", 2, 2, 3, 1),
3189 VECTOR_SWIZZLE4_RO_DEF("zzwz", 2, 2, 3, 2),
3190 VECTOR_SWIZZLE4_RO_DEF("zzww", 2, 2, 3, 3),
3191 VECTOR_SWIZZLE2_RW_DEF("zw", 2, 3),
3192 VECTOR_SWIZZLE3_RW_DEF("zwx", 2, 3, 0),
3193 VECTOR_SWIZZLE4_RO_DEF("zwxx", 2, 3, 0, 0),
3194 VECTOR_SWIZZLE4_RW_DEF("zwxy", 2, 3, 0, 1),
3195 VECTOR_SWIZZLE4_RO_DEF("zwxz", 2, 3, 0, 2),
3196 VECTOR_SWIZZLE4_RO_DEF("zwxw", 2, 3, 0, 3),
3197 VECTOR_SWIZZLE3_RW_DEF("zwy", 2, 3, 1),
3198 VECTOR_SWIZZLE4_RW_DEF("zwyx", 2, 3, 1, 0),
3199 VECTOR_SWIZZLE4_RO_DEF("zwyy", 2, 3, 1, 1),
3200 VECTOR_SWIZZLE4_RO_DEF("zwyz", 2, 3, 1, 2),
3201 VECTOR_SWIZZLE4_RO_DEF("zwyw", 2, 3, 1, 3),
3202 VECTOR_SWIZZLE3_RO_DEF("zwz", 2, 3, 2),
3203 VECTOR_SWIZZLE4_RO_DEF("zwzx", 2, 3, 2, 0),
3204 VECTOR_SWIZZLE4_RO_DEF("zwzy", 2, 3, 2, 1),
3205 VECTOR_SWIZZLE4_RO_DEF("zwzz", 2, 3, 2, 2),
3206 VECTOR_SWIZZLE4_RO_DEF("zwzw", 2, 3, 2, 3),
3207 VECTOR_SWIZZLE3_RO_DEF("zww", 2, 3, 3),
3208 VECTOR_SWIZZLE4_RO_DEF("zwwx", 2, 3, 3, 0),
3209 VECTOR_SWIZZLE4_RO_DEF("zwwy", 2, 3, 3, 1),
3210 VECTOR_SWIZZLE4_RO_DEF("zwwz", 2, 3, 3, 2),
3211 VECTOR_SWIZZLE4_RO_DEF("zwww", 2, 3, 3, 3),
3212 VECTOR_SWIZZLE2_RW_DEF("wx", 3, 0),
3213 VECTOR_SWIZZLE3_RO_DEF("wxx", 3, 0, 0),
3214 VECTOR_SWIZZLE4_RO_DEF("wxxx", 3, 0, 0, 0),
3215 VECTOR_SWIZZLE4_RO_DEF("wxxy", 3, 0, 0, 1),
3216 VECTOR_SWIZZLE4_RO_DEF("wxxz", 3, 0, 0, 2),
3217 VECTOR_SWIZZLE4_RO_DEF("wxxw", 3, 0, 0, 3),
3218 VECTOR_SWIZZLE3_RW_DEF("wxy", 3, 0, 1),
3219 VECTOR_SWIZZLE4_RO_DEF("wxyx", 3, 0, 1, 0),
3220 VECTOR_SWIZZLE4_RO_DEF("wxyy", 3, 0, 1, 1),
3221 VECTOR_SWIZZLE4_RW_DEF("wxyz", 3, 0, 1, 2),
3222 VECTOR_SWIZZLE4_RO_DEF("wxyw", 3, 0, 1, 3),
3223 VECTOR_SWIZZLE3_RW_DEF("wxz", 3, 0, 2),
3224 VECTOR_SWIZZLE4_RO_DEF("wxzx", 3, 0, 2, 0),
3225 VECTOR_SWIZZLE4_RW_DEF("wxzy", 3, 0, 2, 1),
3226 VECTOR_SWIZZLE4_RO_DEF("wxzz", 3, 0, 2, 2),
3227 VECTOR_SWIZZLE4_RO_DEF("wxzw", 3, 0, 2, 3),
3228 VECTOR_SWIZZLE3_RO_DEF("wxw", 3, 0, 3),
3229 VECTOR_SWIZZLE4_RO_DEF("wxwx", 3, 0, 3, 0),
3230 VECTOR_SWIZZLE4_RO_DEF("wxwy", 3, 0, 3, 1),
3231 VECTOR_SWIZZLE4_RO_DEF("wxwz", 3, 0, 3, 2),
3232 VECTOR_SWIZZLE4_RO_DEF("wxww", 3, 0, 3, 3),
3233 VECTOR_SWIZZLE2_RW_DEF("wy", 3, 1),
3234 VECTOR_SWIZZLE3_RW_DEF("wyx", 3, 1, 0),
3235 VECTOR_SWIZZLE4_RO_DEF("wyxx", 3, 1, 0, 0),
3236 VECTOR_SWIZZLE4_RO_DEF("wyxy", 3, 1, 0, 1),
3237 VECTOR_SWIZZLE4_RW_DEF("wyxz", 3, 1, 0, 2),
3238 VECTOR_SWIZZLE4_RO_DEF("wyxw", 3, 1, 0, 3),
3239 VECTOR_SWIZZLE3_RO_DEF("wyy", 3, 1, 1),
3240 VECTOR_SWIZZLE4_RO_DEF("wyyx", 3, 1, 1, 0),
3241 VECTOR_SWIZZLE4_RO_DEF("wyyy", 3, 1, 1, 1),
3242 VECTOR_SWIZZLE4_RO_DEF("wyyz", 3, 1, 1, 2),
3243 VECTOR_SWIZZLE4_RO_DEF("wyyw", 3, 1, 1, 3),
3244 VECTOR_SWIZZLE3_RW_DEF("wyz", 3, 1, 2),
3245 VECTOR_SWIZZLE4_RW_DEF("wyzx", 3, 1, 2, 0),
3246 VECTOR_SWIZZLE4_RO_DEF("wyzy", 3, 1, 2, 1),
3247 VECTOR_SWIZZLE4_RO_DEF("wyzz", 3, 1, 2, 2),
3248 VECTOR_SWIZZLE4_RO_DEF("wyzw", 3, 1, 2, 3),
3249 VECTOR_SWIZZLE3_RO_DEF("wyw", 3, 1, 3),
3250 VECTOR_SWIZZLE4_RO_DEF("wywx", 3, 1, 3, 0),
3251 VECTOR_SWIZZLE4_RO_DEF("wywy", 3, 1, 3, 1),
3252 VECTOR_SWIZZLE4_RO_DEF("wywz", 3, 1, 3, 2),
3253 VECTOR_SWIZZLE4_RO_DEF("wyww", 3, 1, 3, 3),
3254 VECTOR_SWIZZLE2_RW_DEF("wz", 3, 2),
3255 VECTOR_SWIZZLE3_RW_DEF("wzx", 3, 2, 0),
3256 VECTOR_SWIZZLE4_RO_DEF("wzxx", 3, 2, 0, 0),
3257 VECTOR_SWIZZLE4_RW_DEF("wzxy", 3, 2, 0, 1),
3258 VECTOR_SWIZZLE4_RO_DEF("wzxz", 3, 2, 0, 2),
3259 VECTOR_SWIZZLE4_RO_DEF("wzxw", 3, 2, 0, 3),
3260 VECTOR_SWIZZLE3_RW_DEF("wzy", 3, 2, 1),
3261 VECTOR_SWIZZLE4_RW_DEF("wzyx", 3, 2, 1, 0),
3262 VECTOR_SWIZZLE4_RO_DEF("wzyy", 3, 2, 1, 1),
3263 VECTOR_SWIZZLE4_RO_DEF("wzyz", 3, 2, 1, 2),
3264 VECTOR_SWIZZLE4_RO_DEF("wzyw", 3, 2, 1, 3),
3265 VECTOR_SWIZZLE3_RO_DEF("wzz", 3, 2, 2),
3266 VECTOR_SWIZZLE4_RO_DEF("wzzx", 3, 2, 2, 0),
3267 VECTOR_SWIZZLE4_RO_DEF("wzzy", 3, 2, 2, 1),
3268 VECTOR_SWIZZLE4_RO_DEF("wzzz", 3, 2, 2, 2),
3269 VECTOR_SWIZZLE4_RO_DEF("wzzw", 3, 2, 2, 3),
3270 VECTOR_SWIZZLE3_RO_DEF("wzw", 3, 2, 3),
3271 VECTOR_SWIZZLE4_RO_DEF("wzwx", 3, 2, 3, 0),
3272 VECTOR_SWIZZLE4_RO_DEF("wzwy", 3, 2, 3, 1),
3273 VECTOR_SWIZZLE4_RO_DEF("wzwz", 3, 2, 3, 2),
3274 VECTOR_SWIZZLE4_RO_DEF("wzww", 3, 2, 3, 3),
3275 VECTOR_SWIZZLE2_RO_DEF("ww", 3, 3),
3276 VECTOR_SWIZZLE3_RO_DEF("wwx", 3, 3, 0),
3277 VECTOR_SWIZZLE4_RO_DEF("wwxx", 3, 3, 0, 0),
3278 VECTOR_SWIZZLE4_RO_DEF("wwxy", 3, 3, 0, 1),
3279 VECTOR_SWIZZLE4_RO_DEF("wwxz", 3, 3, 0, 2),
3280 VECTOR_SWIZZLE4_RO_DEF("wwxw", 3, 3, 0, 3),
3281 VECTOR_SWIZZLE3_RO_DEF("wwy", 3, 3, 1),
3282 VECTOR_SWIZZLE4_RO_DEF("wwyx", 3, 3, 1, 0),
3283 VECTOR_SWIZZLE4_RO_DEF("wwyy", 3, 3, 1, 1),
3284 VECTOR_SWIZZLE4_RO_DEF("wwyz", 3, 3, 1, 2),
3285 VECTOR_SWIZZLE4_RO_DEF("wwyw", 3, 3, 1, 3),
3286 VECTOR_SWIZZLE3_RO_DEF("wwz", 3, 3, 2),
3287 VECTOR_SWIZZLE4_RO_DEF("wwzx", 3, 3, 2, 0),
3288 VECTOR_SWIZZLE4_RO_DEF("wwzy", 3, 3, 2, 1),
3289 VECTOR_SWIZZLE4_RO_DEF("wwzz", 3, 3, 2, 2),
3290 VECTOR_SWIZZLE4_RO_DEF("wwzw", 3, 3, 2, 3),
3291 VECTOR_SWIZZLE3_RO_DEF("www", 3, 3, 3),
3292 VECTOR_SWIZZLE4_RO_DEF("wwwx", 3, 3, 3, 0),
3293 VECTOR_SWIZZLE4_RO_DEF("wwwy", 3, 3, 3, 1),
3294 VECTOR_SWIZZLE4_RO_DEF("wwwz", 3, 3, 3, 2),
3295 VECTOR_SWIZZLE4_RO_DEF("wwww", 3, 3, 3, 3),
3296
3297#undef AXIS_FROM_CHAR
3298#undef SWIZZLE1
3299#undef SWIZZLE2
3300#undef SWIZZLE3
3301#undef SWIZZLE4
3302#undef _SWIZZLE1
3303#undef _SWIZZLE2
3304#undef _SWIZZLE3
3305#undef _SWIZZLE4
3306
3307#undef VECTOR_SWIZZLE2_RW_DEF
3308#undef VECTOR_SWIZZLE2_RO_DEF
3309#undef VECTOR_SWIZZLE3_RW_DEF
3310#undef VECTOR_SWIZZLE3_RO_DEF
3311#undef VECTOR_SWIZZLE4_RW_DEF
3312#undef VECTOR_SWIZZLE4_RO_DEF
3313
3314 {nullptr, nullptr, nullptr, nullptr, nullptr} /* Sentinel */
3315};
3316
3317#if (defined(__GNUC__) && !defined(__clang__))
3318# pragma GCC diagnostic pop
3319#endif
3320
3323/* -------------------------------------------------------------------- */
3327#if (defined(__GNUC__) && !defined(__clang__))
3328# pragma GCC diagnostic push
3329# pragma GCC diagnostic ignored "-Wcast-function-type"
3330#endif
3331
3332static PyMethodDef Vector_methods[] = {
3333 /* Class Methods */
3334 {"Fill", (PyCFunction)C_Vector_Fill, METH_VARARGS | METH_CLASS, C_Vector_Fill_doc},
3335 {"Range", (PyCFunction)C_Vector_Range, METH_VARARGS | METH_CLASS, C_Vector_Range_doc},
3336 {"Linspace", (PyCFunction)C_Vector_Linspace, METH_VARARGS | METH_CLASS, C_Vector_Linspace_doc},
3337 {"Repeat", (PyCFunction)C_Vector_Repeat, METH_VARARGS | METH_CLASS, C_Vector_Repeat_doc},
3338
3339 /* In place only. */
3340 {"zero", (PyCFunction)Vector_zero, METH_NOARGS, Vector_zero_doc},
3341 {"negate", (PyCFunction)Vector_negate, METH_NOARGS, Vector_negate_doc},
3342
3343 /* Operate on original or copy. */
3344 {"normalize", (PyCFunction)Vector_normalize, METH_NOARGS, Vector_normalize_doc},
3345 {"normalized", (PyCFunction)Vector_normalized, METH_NOARGS, Vector_normalized_doc},
3346
3347 {"resize", (PyCFunction)Vector_resize, METH_O, Vector_resize_doc},
3348 {"resized", (PyCFunction)Vector_resized, METH_O, Vector_resized_doc},
3349 {"to_2d", (PyCFunction)Vector_to_2d, METH_NOARGS, Vector_to_2d_doc},
3350 {"resize_2d", (PyCFunction)Vector_resize_2d, METH_NOARGS, Vector_resize_2d_doc},
3351 {"to_3d", (PyCFunction)Vector_to_3d, METH_NOARGS, Vector_to_3d_doc},
3352 {"resize_3d", (PyCFunction)Vector_resize_3d, METH_NOARGS, Vector_resize_3d_doc},
3353 {"to_4d", (PyCFunction)Vector_to_4d, METH_NOARGS, Vector_to_4d_doc},
3354 {"resize_4d", (PyCFunction)Vector_resize_4d, METH_NOARGS, Vector_resize_4d_doc},
3355 {"to_tuple", (PyCFunction)Vector_to_tuple, METH_VARARGS, Vector_to_tuple_doc},
3356 {"to_track_quat", (PyCFunction)Vector_to_track_quat, METH_VARARGS, Vector_to_track_quat_doc},
3357 {"orthogonal", (PyCFunction)Vector_orthogonal, METH_NOARGS, Vector_orthogonal_doc},
3358
3359 /* Operation between 2 or more types. */
3360 {"reflect", (PyCFunction)Vector_reflect, METH_O, Vector_reflect_doc},
3361 {"cross", (PyCFunction)Vector_cross, METH_O, Vector_cross_doc},
3362 {"dot", (PyCFunction)Vector_dot, METH_O, Vector_dot_doc},
3363 {"angle", (PyCFunction)Vector_angle, METH_VARARGS, Vector_angle_doc},
3364 {"angle_signed", (PyCFunction)Vector_angle_signed, METH_VARARGS, Vector_angle_signed_doc},
3365 {"rotation_difference",
3366 (PyCFunction)Vector_rotation_difference,
3367 METH_O,
3368 Vector_rotation_difference_doc},
3369 {"project", (PyCFunction)Vector_project, METH_O, Vector_project_doc},
3370 {"lerp", (PyCFunction)Vector_lerp, METH_VARARGS, Vector_lerp_doc},
3371 {"slerp", (PyCFunction)Vector_slerp, METH_VARARGS, Vector_slerp_doc},
3372 {"rotate", (PyCFunction)Vector_rotate, METH_O, Vector_rotate_doc},
3373
3374 /* Base-math methods. */
3375 {"freeze", (PyCFunction)BaseMathObject_freeze, METH_NOARGS, BaseMathObject_freeze_doc},
3376
3377 {"copy", (PyCFunction)Vector_copy, METH_NOARGS, Vector_copy_doc},
3378 {"__copy__", (PyCFunction)Vector_copy, METH_NOARGS, nullptr},
3379 {"__deepcopy__", (PyCFunction)Vector_deepcopy, METH_VARARGS, nullptr},
3380 {nullptr, nullptr, 0, nullptr},
3381};
3382
3383#if (defined(__GNUC__) && !defined(__clang__))
3384# pragma GCC diagnostic pop
3385#endif
3386
3389/* -------------------------------------------------------------------- */
3397#ifdef MATH_STANDALONE
3398# define Vector_str nullptr
3399#endif
3400
3402 /* Wrap. */
3403 vector_doc,
3404 ".. class:: Vector(seq)\n"
3405 "\n"
3406 " This object gives access to Vectors in Blender.\n"
3407 "\n"
3408 " :arg seq: Components of the vector, must be a sequence of at least two.\n"
3409 " :type seq: Sequence[float]\n");
3410PyTypeObject vector_Type = {
3411 /*ob_base*/ PyVarObject_HEAD_INIT(nullptr, 0)
3412 /*tp_name*/ "Vector",
3413 /*tp_basicsize*/ sizeof(VectorObject),
3414 /*tp_itemsize*/ 0,
3415 /*tp_dealloc*/ (destructor)BaseMathObject_dealloc,
3416 /*tp_vectorcall_offset*/ 0,
3417 /*tp_getattr*/ nullptr,
3418 /*tp_setattr*/ nullptr,
3419 /*tp_as_async*/ nullptr,
3420 /*tp_repr*/ (reprfunc)Vector_repr,
3421 /*tp_as_number*/ &Vector_NumMethods,
3422 /*tp_as_sequence*/ &Vector_SeqMethods,
3423 /*tp_as_mapping*/ &Vector_AsMapping,
3424 /*tp_hash*/ (hashfunc)Vector_hash,
3425 /*tp_call*/ nullptr,
3426 /*tp_str*/ (reprfunc)Vector_str,
3427 /*tp_getattro*/ nullptr,
3428 /*tp_setattro*/ nullptr,
3429 /*tp_as_buffer*/ nullptr,
3430 /*tp_flags*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
3431 /*tp_doc*/ vector_doc,
3432 /*tp_traverse*/ (traverseproc)BaseMathObject_traverse,
3433 /*tp_clear*/ (inquiry)BaseMathObject_clear,
3434 /*tp_richcompare*/ (richcmpfunc)Vector_richcmpr,
3435 /*tp_weaklistoffset*/ 0,
3436 /*tp_iter*/ nullptr,
3437 /*tp_iternext*/ nullptr,
3438 /*tp_methods*/ Vector_methods,
3439 /*tp_members*/ nullptr,
3440 /*tp_getset*/ Vector_getseters,
3441 /*tp_base*/ nullptr,
3442 /*tp_dict*/ nullptr,
3443 /*tp_descr_get*/ nullptr,
3444 /*tp_descr_set*/ nullptr,
3445 /*tp_dictoffset*/ 0,
3446 /*tp_init*/ nullptr,
3447 /*tp_alloc*/ nullptr,
3448 /*tp_new*/ Vector_new,
3449 /*tp_free*/ nullptr,
3450 /*tp_is_gc*/ (inquiry)BaseMathObject_is_gc,
3451 /*tp_bases*/ nullptr,
3452 /*tp_mro*/ nullptr,
3453 /*tp_cache*/ nullptr,
3454 /*tp_subclasses*/ nullptr,
3455 /*tp_weaklist*/ nullptr,
3456 /*tp_del*/ nullptr,
3457 /*tp_version_tag*/ 0,
3458 /*tp_finalize*/ nullptr,
3459 /*tp_vectorcall*/ nullptr,
3460};
3461
3462#ifdef MATH_STANDALONE
3463# undef Vector_str nullptr
3464#endif
3465
3468/* -------------------------------------------------------------------- */
3472PyObject *Vector_CreatePyObject(const float *vec, const int vec_num, PyTypeObject *base_type)
3473{
3475 float *vec_alloc;
3476
3477 if (vec_num < 2) {
3478 PyErr_SetString(PyExc_RuntimeError, "Vector(): invalid size");
3479 return nullptr;
3480 }
3481
3482 vec_alloc = static_cast<float *>(PyMem_Malloc(vec_num * sizeof(float)));
3483 if (UNLIKELY(vec_alloc == nullptr)) {
3484 PyErr_SetString(PyExc_MemoryError,
3485 "Vector(): "
3486 "problem allocating data");
3487 return nullptr;
3488 }
3489
3491 if (self) {
3492 self->vec = vec_alloc;
3493 self->vec_num = vec_num;
3494
3495 /* Initialize callbacks as nullptr. */
3496 self->cb_user = nullptr;
3497 self->cb_type = self->cb_subtype = 0;
3498
3499 if (vec) {
3500 memcpy(self->vec, vec, vec_num * sizeof(float));
3501 }
3502 else { /* new empty */
3503 copy_vn_fl(self->vec, vec_num, 0.0f);
3504 if (vec_num == 4) { /* do the homogeneous thing */
3505 self->vec[3] = 1.0f;
3506 }
3507 }
3509 }
3510 else {
3511 PyMem_Free(vec_alloc);
3512 }
3513
3514 return (PyObject *)self;
3515}
3516
3517PyObject *Vector_CreatePyObject_wrap(float *vec, const int vec_num, PyTypeObject *base_type)
3518{
3520
3521 if (vec_num < 2) {
3522 PyErr_SetString(PyExc_RuntimeError, "Vector(): invalid size");
3523 return nullptr;
3524 }
3525
3527 if (self) {
3528 self->vec_num = vec_num;
3529
3530 /* Initialize callbacks as nullptr. */
3531 self->cb_user = nullptr;
3532 self->cb_type = self->cb_subtype = 0;
3533
3534 self->vec = vec;
3536 }
3537 return (PyObject *)self;
3538}
3539
3540PyObject *Vector_CreatePyObject_cb(PyObject *cb_user, int vec_num, uchar cb_type, uchar cb_subtype)
3541{
3542 VectorObject *self = (VectorObject *)Vector_CreatePyObject(nullptr, vec_num, nullptr);
3543 if (self) {
3544 Py_INCREF(cb_user);
3545 self->cb_user = cb_user;
3546 self->cb_type = cb_type;
3547 self->cb_subtype = cb_subtype;
3548 BLI_assert(!PyObject_GC_IsTracked((PyObject *)self));
3549 PyObject_GC_Track(self);
3550 }
3551
3552 return (PyObject *)self;
3553}
3554
3555PyObject *Vector_CreatePyObject_alloc(float *vec, const int vec_num, PyTypeObject *base_type)
3556{
3558 self = (VectorObject *)Vector_CreatePyObject_wrap(vec, vec_num, base_type);
3559 if (self) {
3560 self->flag &= ~BASE_MATH_FLAG_IS_WRAP;
3561 }
3562
3563 return (PyObject *)self;
3564}
3565
#define BLI_assert(a)
Definition BLI_assert.h:50
A dynamically sized string ADT.
DynStr * BLI_dynstr_new(void) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
Definition BLI_dynstr.c:37
void BLI_dynstr_appendf(DynStr *__restrict ds, const char *__restrict format,...) ATTR_PRINTF_FORMAT(2
void BLI_dynstr_append(DynStr *__restrict ds, const char *cstr) ATTR_NONNULL()
Definition BLI_dynstr.c:62
sqrt(x)+1/max(0
double double_round(double x, int ndigits)
Definition math_base.c:28
MINLINE float safe_acosf(float a)
void mul_m3_v3(const float M[3][3], float r[3])
void normalize_m2_m2(float R[2][2], const float M[2][2]) ATTR_NONNULL()
void mul_m2_v2(const float mat[2][2], float vec[2])
void rotation_between_vecs_to_quat(float q[4], const float v1[3], const float v2[3])
void vec_to_quat(float q[4], const float vec[3], short axis, short upflag)
void interp_dot_slerp(float t, float cosom, float r_w[2])
void add_vn_vn(float *array_tar, const float *array_src, int size)
double len_squared_vn(const float *array, int size) ATTR_WARN_UNUSED_RESULT
void mul_vn_fl(float *array_tar, int size, float f)
float normalize_vn(float *array_tar, int size)
void negate_vn(float *array_tar, int size)
void reflect_v3_v3v3(float out[3], const float v[3], const float normal[3])
void range_vn_fl(float *array_tar, int size, float start, float step)
void sub_vn_vnvn(float *array_tar, const float *array_src_a, const float *array_src_b, int size)
MINLINE bool is_zero_v2(const float v[2]) ATTR_WARN_UNUSED_RESULT
void add_vn_vnvn(float *array_tar, const float *array_src_a, const float *array_src_b, int size)
MINLINE void negate_v3_v3(float r[3], const float a[3])
void copy_vn_fl(float *array_tar, int size, float val)
MINLINE void cross_v3_v3v3(float r[3], const float a[3], const float b[3])
float normalize_vn_vn(float *array_tar, const float *array_src, int size)
void ortho_v3_v3(float out[3], const float v[3])
double dot_vn_vn(const float *array_src_a, const float *array_src_b, int size) ATTR_WARN_UNUSED_RESULT
float angle_signed_v2v2(const float v1[2], const float v2[2]) ATTR_WARN_UNUSED_RESULT
MINLINE float cross_v2v2(const float a[2], const float b[2]) ATTR_WARN_UNUSED_RESULT
MINLINE float normalize_v3_v3(float r[3], const float a[3])
void mul_vn_vn(float *array_tar, const float *array_src, int size)
void ortho_v2_v2(float out[2], const float v[2])
void negate_vn_vn(float *array_tar, const float *array_src, int size)
void mul_vn_vn_fl(float *array_tar, const float *array_src, int size, float f)
void mul_vn_vnvn(float *array_tar, const float *array_src_a, const float *array_src_b, int size)
void interp_vn_vn(float *array_tar, const float *array_src, float t, int size)
MINLINE float normalize_v3(float n[3])
void sub_vn_vn(float *array_tar, const float *array_src, int size)
unsigned char uchar
unsigned int uint
#define CLAMP(a, b, c)
#define POINTER_FROM_INT(i)
#define POINTER_AS_INT(i)
#define UNLIKELY(x)
typedef double(DMatrix)[4][4]
ATTR_WARN_UNUSED_RESULT const BMVert * v2
PyObject * self
SIMD_FORCE_INLINE const btScalar & z() const
Return the z value.
Definition btQuadWord.h:117
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition btQuadWord.h:119
#define printf
draw_view in_light_buf[] float
uint col
int count
ccl_device_inline float3 reflect(const float3 incident, const float3 unit_normal)
int mathutils_array_parse_alloc(float **array, int array_num_min, PyObject *value, const char *error_prefix)
Definition mathutils.cc:193
int BaseMathObject_is_gc(BaseMathObject *self)
Definition mathutils.cc:711
Py_hash_t mathutils_array_hash(const float *array, size_t array_len)
Definition mathutils.cc:69
void BaseMathObject_dealloc(BaseMathObject *self)
Definition mathutils.cc:689
int EXPP_VectorsAreEqual(const float *vecA, const float *vecB, int size, int floatSteps)
Definition mathutils.cc:490
int mathutils_array_parse(float *array, int array_num_min, int array_num_max, PyObject *value, const char *error_prefix)
Definition mathutils.cc:97
char BaseMathObject_is_valid_doc[]
Definition mathutils.cc:639
char BaseMathObject_is_wrapped_doc[]
Definition mathutils.cc:625
PyObject * BaseMathObject_owner_get(BaseMathObject *self, void *)
Definition mathutils.cc:619
char BaseMathObject_is_frozen_doc[]
Definition mathutils.cc:632
PyObject * mathutils_dynstr_to_py(DynStr *ds)
Definition mathutils.cc:502
int mathutils_any_to_rotmat(float rmat[3][3], PyObject *value, const char *error_prefix)
Definition mathutils.cc:409
PyObject * BaseMathObject_is_frozen_get(BaseMathObject *self, void *)
Definition mathutils.cc:634
PyObject * BaseMathObject_freeze(BaseMathObject *self)
Definition mathutils.cc:653
PyObject * BaseMathObject_is_wrapped_get(BaseMathObject *self, void *)
Definition mathutils.cc:627
char BaseMathObject_owner_doc[]
Definition mathutils.cc:618
char BaseMathObject_freeze_doc[]
Definition mathutils.cc:645
PyObject * BaseMathObject_is_valid_get(BaseMathObject *self, void *)
Definition mathutils.cc:640
int BaseMathObject_clear(BaseMathObject *self)
Definition mathutils.cc:671
int BaseMathObject_traverse(BaseMathObject *self, visitproc visit, void *arg)
Definition mathutils.cc:665
@ BASE_MATH_FLAG_IS_WRAP
Definition mathutils.hh:36
#define BaseMath_ReadCallback_ForWrite(_self)
Definition mathutils.hh:135
#define BaseMath_ReadIndexCallback(_self, _index)
Definition mathutils.hh:129
#define BaseMath_WriteCallback(_self)
Definition mathutils.hh:127
#define BASE_MATH_NEW(struct_name, root_type, base_type)
Definition mathutils.hh:26
#define BaseMathObject_Prepare_ForHash(_self)
Definition mathutils.hh:150
#define BASE_MATH_FLAG_DEFAULT
Definition mathutils.hh:43
#define BaseMath_Prepare_ForWrite(_self)
Definition mathutils.hh:145
#define BaseMath_ReadCallback(_self)
Definition mathutils.hh:125
#define BaseMath_WriteIndexCallback(_self, _index)
Definition mathutils.hh:131
int Matrix_Parse2x2(PyObject *o, void *p)
#define MatrixObject_Check(v)
#define MATRIX_ITEM(_mat, _row, _col)
PyObject * Quaternion_CreatePyObject(const float quat[4], PyTypeObject *base_type)
static PyObject * Vector_repr(VectorObject *self)
static PySequenceMethods Vector_SeqMethods
static PyObject * Vector_add(PyObject *v1, PyObject *v2)
static PyObject * Vector_neg(VectorObject *self)
static PyObject * Vector_normalize(VectorObject *self)
static PyObject * Vector_length_get(VectorObject *self, void *)
static PyObject * Vector_swizzle_get(VectorObject *self, void *closure)
PyDoc_STRVAR(C_Vector_Fill_doc, ".. classmethod:: Fill(size, fill=0.0)\n" "\n" " Create a vector of length size with all values set to fill.\n" "\n" " :arg size: The length of the vector to be created.\n" " :type size: int\n" " :arg fill: The value used to fill the vector.\n" " :type fill: float\n")
static PyObject * vector_mul_float(VectorObject *vec, const float scalar)
static PyObject * C_Vector_Repeat(PyObject *cls, PyObject *args)
static PyObject * C_Vector_Linspace(PyObject *cls, PyObject *args)
static PyObject * vector_item_internal(VectorObject *self, int i, const bool is_attr)
static PyObject * Vector_length_squared_get(VectorObject *self, void *)
static PyObject * Vector_rotation_difference(VectorObject *self, PyObject *value)
static PyObject * Vector_to_track_quat(VectorObject *self, PyObject *args)
#define VECTOR_SWIZZLE2_RO_DEF(attr, a, b)
static PyObject * Vector_richcmpr(PyObject *objectA, PyObject *objectB, int comparison_type)
static int Vector_swizzle_set(VectorObject *self, PyObject *value, void *closure)
static int vector_ass_item_internal(VectorObject *self, int i, PyObject *value, const bool is_attr)
#define VECTOR_SWIZZLE3_RW_DEF(attr, a, b, c)
static PyObject * Vector_resize_2d(VectorObject *self)
static PyObject * C_Vector_Range(PyObject *cls, PyObject *args)
static Py_ssize_t Vector_len(VectorObject *self)
PyTypeObject vector_Type
static PyObject * Vector_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
static PyObject * Vector_to_2d(VectorObject *self)
static PyObject * Vector_mul(PyObject *v1, PyObject *v2)
#define SWIZZLE_VALID_AXIS
static PyObject * Vector_iadd(PyObject *v1, PyObject *v2)
static int Vector_ass_item(VectorObject *self, Py_ssize_t i, PyObject *value)
static PyObject * Vector_zero(VectorObject *self)
static PyObject * vec__apply_to_copy(PyObject *(*vec_func)(VectorObject *), VectorObject *self)
static int Vector_ass_subscript(VectorObject *self, PyObject *item, PyObject *value)
static PyObject * Vector_str(VectorObject *self)
PyObject * Vector_CreatePyObject(const float *vec, const int vec_num, PyTypeObject *base_type)
#define MAX_DIMENSIONS
static PyObject * Vector_dot(VectorObject *self, PyObject *value)
static Py_hash_t Vector_hash(VectorObject *self)
static PyObject * Vector_project(VectorObject *self, PyObject *value)
static PyObject * Vector_to_3d(VectorObject *self)
static PyObject * Vector_imatmul(PyObject *v1, PyObject *v2)
static PyObject * Vector_to_4d(VectorObject *self)
static PyObject * Vector_axis_get(VectorObject *self, void *type)
static PyObject * Vector_to_tuple(VectorObject *self, PyObject *args)
PyObject * Vector_CreatePyObject_alloc(float *vec, const int vec_num, PyTypeObject *base_type)
static int Vector_ass_slice(VectorObject *self, int begin, int end, PyObject *seq)
static PyObject * Vector_reflect(VectorObject *self, PyObject *value)
static PyObject * Vector_slice(VectorObject *self, int begin, int end)
static PyObject * Vector_resize_3d(VectorObject *self)
static PyObject * Vector_imul(PyObject *v1, PyObject *v2)
static PyObject * Vector_resize(VectorObject *self, PyObject *value)
static PyObject * Vector_angle_signed(VectorObject *self, PyObject *args)
static PyNumberMethods Vector_NumMethods
static PyObject * Vector_isub(PyObject *v1, PyObject *v2)
static PyObject * Vector_normalized(VectorObject *self)
static PyMethodDef Vector_methods[]
static int row_vector_multiplication(float r_vec[MAX_DIMENSIONS], VectorObject *vec, MatrixObject *mat)
static PyObject * Vector_rotate(VectorObject *self, PyObject *value)
static PyObject * Vector_copy(VectorObject *self)
static PyObject * Vector_lerp(VectorObject *self, PyObject *args)
static PyObject * Vector_item(VectorObject *self, Py_ssize_t i)
static PyObject * Vector_angle(VectorObject *self, PyObject *args)
static int Vector_length_set(VectorObject *self, PyObject *value)
static PyObject * Vector_deepcopy(VectorObject *self, PyObject *args)
static PyObject * C_Vector_Fill(PyObject *cls, PyObject *args)
#define SWIZZLE_AXIS
#define VECTOR_SWIZZLE2_RW_DEF(attr, a, b)
static PyObject * Vector_sub(PyObject *v1, PyObject *v2)
static PyObject * Vector_resize_4d(VectorObject *self)
static PyObject * Vector_cross(VectorObject *self, PyObject *value)
#define SWIZZLE_BITS_PER_AXIS
PyObject * Vector_CreatePyObject_cb(PyObject *cb_user, int vec_num, uchar cb_type, uchar cb_subtype)
static PyObject * Vector_idiv(PyObject *v1, PyObject *v2)
#define VECTOR_SWIZZLE4_RO_DEF(attr, a, b, c, d)
#define VECTOR_SWIZZLE3_RO_DEF(attr, a, b, c)
static PyGetSetDef Vector_getseters[]
static int Vector_axis_set(VectorObject *self, PyObject *value, void *type)
static PyObject * Vector_resized(VectorObject *self, PyObject *value)
static PyObject * Vector_to_tuple_ex(VectorObject *self, int ndigits)
static PyObject * vector_mul_vec(VectorObject *vec1, VectorObject *vec2)
static PyObject * Vector_div(PyObject *v1, PyObject *v2)
static PyObject * Vector_matmul(PyObject *v1, PyObject *v2)
static PyMappingMethods Vector_AsMapping
static PyObject * Vector_subscript(VectorObject *self, PyObject *item)
static PyObject * Vector_orthogonal(VectorObject *self)
PyObject * Vector_CreatePyObject_wrap(float *vec, const int vec_num, PyTypeObject *base_type)
#define VECTOR_SWIZZLE4_RW_DEF(attr, a, b, c, d)
int column_vector_multiplication(float r_vec[MAX_DIMENSIONS], VectorObject *vec, MatrixObject *mat)
static PyObject * Vector_slerp(VectorObject *self, PyObject *args)
static PyObject * Vector_negate(VectorObject *self)
#define VectorObject_Check(v)
int PyC_CheckArgs_DeepCopy(PyObject *args)
return ret