Blender V4.5
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
8
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/* -------------------------------------------------------------------- */
49
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 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
132
133/* -------------------------------------------------------------------- */
136
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
183
184/* -------------------------------------------------------------------- */
187
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
412
413/* -------------------------------------------------------------------- */
416
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
439
440/* -------------------------------------------------------------------- */
443
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
482
483/* -------------------------------------------------------------------- */
486
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 (UNLIKELY(BaseMathObject_Prepare_ForResize(self, "Vector.resize()") == -1)) {
498 /* An exception has been raised. */
499 return nullptr;
500 }
501
502 if ((vec_num = PyC_Long_AsI32(value)) == -1) {
503 PyErr_SetString(PyExc_TypeError,
504 "Vector.resize(size): "
505 "expected size argument to be an integer");
506 return nullptr;
507 }
508
509 if (vec_num < 2) {
510 PyErr_SetString(PyExc_RuntimeError, "Vector.resize(): invalid size");
511 return nullptr;
512 }
513
514 self->vec = static_cast<float *>(PyMem_Realloc(self->vec, (vec_num * sizeof(float))));
515 if (self->vec == nullptr) {
516 PyErr_SetString(PyExc_MemoryError,
517 "Vector.resize(): "
518 "problem allocating pointer space");
519 return nullptr;
520 }
521
522 /* If the vector has increased in length, set all new elements to 0.0f */
523 if (vec_num > self->vec_num) {
524 copy_vn_fl(self->vec + self->vec_num, vec_num - self->vec_num, 0.0f);
525 }
526
527 self->vec_num = vec_num;
528 Py_RETURN_NONE;
529}
530
532 /* Wrap. */
533 Vector_resized_doc,
534 ".. method:: resized(size=3)\n"
535 "\n"
536 " Return a resized copy of the vector with size number of elements.\n"
537 "\n"
538 " :return: a new vector\n"
539 " :rtype: :class:`Vector`\n");
540static PyObject *Vector_resized(VectorObject *self, PyObject *value)
541{
542 int vec_num;
543 float *vec;
544
545 if ((vec_num = PyLong_AsLong(value)) == -1) {
546 return nullptr;
547 }
548
549 if (vec_num < 2) {
550 PyErr_SetString(PyExc_RuntimeError, "Vector.resized(): invalid size");
551 return nullptr;
552 }
553
554 vec = static_cast<float *>(PyMem_Malloc(vec_num * sizeof(float)));
555
556 if (vec == nullptr) {
557 PyErr_SetString(PyExc_MemoryError,
558 "Vector.resized(): "
559 "problem allocating pointer space");
560 return nullptr;
561 }
562
563 copy_vn_fl(vec, vec_num, 0.0f);
564 memcpy(vec, self->vec, self->vec_num * sizeof(float));
565
566 return Vector_CreatePyObject_alloc(vec, vec_num, nullptr);
567}
568
570 /* Wrap. */
571 Vector_resize_2d_doc,
572 ".. method:: resize_2d()\n"
573 "\n"
574 " Resize the vector to 2D (x, y).\n");
576{
577 if (UNLIKELY(BaseMathObject_Prepare_ForResize(self, "Vector.resize_2d()") == -1)) {
578 /* An exception has been raised. */
579 return nullptr;
580 }
581
582 self->vec = static_cast<float *>(PyMem_Realloc(self->vec, sizeof(float[2])));
583 if (self->vec == nullptr) {
584 PyErr_SetString(PyExc_MemoryError,
585 "Vector.resize_2d(): "
586 "problem allocating pointer space");
587 return nullptr;
588 }
589
590 self->vec_num = 2;
591 Py_RETURN_NONE;
592}
593
595 /* Wrap. */
596 Vector_resize_3d_doc,
597 ".. method:: resize_3d()\n"
598 "\n"
599 " Resize the vector to 3D (x, y, z).\n");
601{
602 if (UNLIKELY(BaseMathObject_Prepare_ForResize(self, "Vector.resize_3d()") == -1)) {
603 /* An exception has been raised. */
604 return nullptr;
605 }
606
607 self->vec = static_cast<float *>(PyMem_Realloc(self->vec, sizeof(float[3])));
608 if (self->vec == nullptr) {
609 PyErr_SetString(PyExc_MemoryError,
610 "Vector.resize_3d(): "
611 "problem allocating pointer space");
612 return nullptr;
613 }
614
615 if (self->vec_num == 2) {
616 self->vec[2] = 0.0f;
617 }
618
619 self->vec_num = 3;
620 Py_RETURN_NONE;
621}
622
624 /* Wrap. */
625 Vector_resize_4d_doc,
626 ".. method:: resize_4d()\n"
627 "\n"
628 " Resize the vector to 4D (x, y, z, w).\n");
630{
631 if (UNLIKELY(BaseMathObject_Prepare_ForResize(self, "Vector.resize_4d()") == -1)) {
632 /* An exception has been raised. */
633 return nullptr;
634 }
635
636 self->vec = static_cast<float *>(PyMem_Realloc(self->vec, sizeof(float[4])));
637 if (self->vec == nullptr) {
638 PyErr_SetString(PyExc_MemoryError,
639 "Vector.resize_4d(): "
640 "problem allocating pointer space");
641 return nullptr;
642 }
643
644 if (self->vec_num == 2) {
645 self->vec[2] = 0.0f;
646 self->vec[3] = 1.0f;
647 }
648 else if (self->vec_num == 3) {
649 self->vec[3] = 1.0f;
650 }
651 self->vec_num = 4;
652 Py_RETURN_NONE;
653}
654
656
657/* -------------------------------------------------------------------- */
660
662 /* Wrap. */
663 Vector_to_2d_doc,
664 ".. method:: to_2d()\n"
665 "\n"
666 " Return a 2d copy of the vector.\n"
667 "\n"
668 " :return: a new vector\n"
669 " :rtype: :class:`Vector`\n");
671{
672 if (BaseMath_ReadCallback(self) == -1) {
673 return nullptr;
674 }
675
676 return Vector_CreatePyObject(self->vec, 2, Py_TYPE(self));
677}
679 /* Wrap. */
680 Vector_to_3d_doc,
681 ".. method:: to_3d()\n"
682 "\n"
683 " Return a 3d copy of the vector.\n"
684 "\n"
685 " :return: a new vector\n"
686 " :rtype: :class:`Vector`\n");
688{
689 float tvec[3] = {0.0f};
690
691 if (BaseMath_ReadCallback(self) == -1) {
692 return nullptr;
693 }
694
695 memcpy(tvec, self->vec, sizeof(float) * std::min(self->vec_num, 3));
696 return Vector_CreatePyObject(tvec, 3, Py_TYPE(self));
697}
699 /* Wrap. */
700 Vector_to_4d_doc,
701 ".. method:: to_4d()\n"
702 "\n"
703 " Return a 4d copy of the vector.\n"
704 "\n"
705 " :return: a new vector\n"
706 " :rtype: :class:`Vector`\n");
708{
709 float tvec[4] = {0.0f, 0.0f, 0.0f, 1.0f};
710
711 if (BaseMath_ReadCallback(self) == -1) {
712 return nullptr;
713 }
714
715 memcpy(tvec, self->vec, sizeof(float) * std::min(self->vec_num, 4));
716 return Vector_CreatePyObject(tvec, 4, Py_TYPE(self));
717}
718
720
721/* -------------------------------------------------------------------- */
724
726 /* Wrap. */
727 Vector_to_tuple_doc,
728 ".. method:: to_tuple(precision=-1)\n"
729 "\n"
730 " Return this vector as a tuple with.\n"
731 "\n"
732 " :arg precision: The number to round the value to in [-1, 21].\n"
733 " :type precision: int\n"
734 " :return: the values of the vector rounded by *precision*\n"
735 " :rtype: tuple[float, ...]\n");
736static PyObject *Vector_to_tuple(VectorObject *self, PyObject *args)
737{
738 int ndigits = -1;
739
740 if (!PyArg_ParseTuple(args, "|i:to_tuple", &ndigits)) {
741 return nullptr;
742 }
743
744 if (ndigits > 22 || ndigits < -1) {
745 PyErr_SetString(PyExc_ValueError,
746 "Vector.to_tuple(precision): "
747 "precision must be between -1 and 21");
748 return nullptr;
749 }
750
751 if (BaseMath_ReadCallback(self) == -1) {
752 return nullptr;
753 }
754
755 return Vector_to_tuple_ex(self, ndigits);
756}
757
759
760/* -------------------------------------------------------------------- */
763
765 /* Wrap. */
766 Vector_to_track_quat_doc,
767 ".. method:: to_track_quat(track, up)\n"
768 "\n"
769 " Return a quaternion rotation from the vector and the track and up axis.\n"
770 "\n"
771 " :arg track: Track axis in ['X', 'Y', 'Z', '-X', '-Y', '-Z'].\n"
772 " :type track: str\n"
773 " :arg up: Up axis in ['X', 'Y', 'Z'].\n"
774 " :type up: str\n"
775 " :return: rotation from the vector and the track and up axis.\n"
776 " :rtype: :class:`Quaternion`\n");
777static PyObject *Vector_to_track_quat(VectorObject *self, PyObject *args)
778{
779 float vec[3], quat[4];
780 const char *strack = nullptr;
781 const char *sup = nullptr;
782 short track = 2, up = 1;
783
784 if (!PyArg_ParseTuple(args, "|ss:to_track_quat", &strack, &sup)) {
785 return nullptr;
786 }
787
788 if (self->vec_num != 3) {
789 PyErr_SetString(PyExc_TypeError,
790 "Vector.to_track_quat(): "
791 "only for 3D vectors");
792 return nullptr;
793 }
794
795 if (BaseMath_ReadCallback(self) == -1) {
796 return nullptr;
797 }
798
799 if (strack) {
800 const char *axis_err_msg = "only X, -X, Y, -Y, Z or -Z for track axis";
801
802 if (strlen(strack) == 2) {
803 if (strack[0] == '-') {
804 switch (strack[1]) {
805 case 'X':
806 track = 3;
807 break;
808 case 'Y':
809 track = 4;
810 break;
811 case 'Z':
812 track = 5;
813 break;
814 default:
815 PyErr_SetString(PyExc_ValueError, axis_err_msg);
816 return nullptr;
817 }
818 }
819 else {
820 PyErr_SetString(PyExc_ValueError, axis_err_msg);
821 return nullptr;
822 }
823 }
824 else if (strlen(strack) == 1) {
825 switch (strack[0]) {
826 case '-':
827 case 'X':
828 track = 0;
829 break;
830 case 'Y':
831 track = 1;
832 break;
833 case 'Z':
834 track = 2;
835 break;
836 default:
837 PyErr_SetString(PyExc_ValueError, axis_err_msg);
838 return nullptr;
839 }
840 }
841 else {
842 PyErr_SetString(PyExc_ValueError, axis_err_msg);
843 return nullptr;
844 }
845 }
846
847 if (sup) {
848 const char *axis_err_msg = "only X, Y or Z for up axis";
849 if (strlen(sup) == 1) {
850 switch (*sup) {
851 case 'X':
852 up = 0;
853 break;
854 case 'Y':
855 up = 1;
856 break;
857 case 'Z':
858 up = 2;
859 break;
860 default:
861 PyErr_SetString(PyExc_ValueError, axis_err_msg);
862 return nullptr;
863 }
864 }
865 else {
866 PyErr_SetString(PyExc_ValueError, axis_err_msg);
867 return nullptr;
868 }
869 }
870
871 if (track == up) {
872 PyErr_SetString(PyExc_ValueError, "Can't have the same axis for track and up");
873 return nullptr;
874 }
875
876 /* Flip vector around, since #vec_to_quat expect a vector from target to tracking object
877 * and the python function expects the inverse (a vector to the target). */
878 negate_v3_v3(vec, self->vec);
879
880 vec_to_quat(quat, vec, track, up);
881
882 return Quaternion_CreatePyObject(quat, nullptr);
883}
884
886
887/* -------------------------------------------------------------------- */
890
892 /* Wrap. */
893 Vector_orthogonal_doc,
894 ".. method:: orthogonal()\n"
895 "\n"
896 " Return a perpendicular vector.\n"
897 "\n"
898 " :return: a new vector 90 degrees from this vector.\n"
899 " :rtype: :class:`Vector`\n"
900 "\n"
901 " .. note:: the axis is undefined, only use when any orthogonal vector is acceptable.\n");
903{
904 float vec[3];
905
906 if (self->vec_num > 3) {
907 PyErr_SetString(PyExc_TypeError,
908 "Vector.orthogonal(): "
909 "Vector must be 3D or 2D");
910 return nullptr;
911 }
912
913 if (BaseMath_ReadCallback(self) == -1) {
914 return nullptr;
915 }
916
917 if (self->vec_num == 3) {
918 ortho_v3_v3(vec, self->vec);
919 }
920 else {
921 ortho_v2_v2(vec, self->vec);
922 }
923
924 return Vector_CreatePyObject(vec, self->vec_num, Py_TYPE(self));
925}
926
928
929/* -------------------------------------------------------------------- */
935
937 /* Wrap. */
938 Vector_reflect_doc,
939 ".. method:: reflect(mirror)\n"
940 "\n"
941 " Return the reflection vector from the *mirror* argument.\n"
942 "\n"
943 " :arg mirror: This vector could be a normal from the reflecting surface.\n"
944 " :type mirror: :class:`Vector`\n"
945 " :return: The reflected vector matching the size of this vector.\n"
946 " :rtype: :class:`Vector`\n");
947static PyObject *Vector_reflect(VectorObject *self, PyObject *value)
948{
949 int value_num;
950 float mirror[3], vec[3];
951 float reflect[3] = {0.0f};
952 float tvec[MAX_DIMENSIONS];
953
954 if (BaseMath_ReadCallback(self) == -1) {
955 return nullptr;
956 }
957
958 if ((value_num = mathutils_array_parse(
959 tvec, 2, 4, value, "Vector.reflect(other), invalid 'other' arg")) == -1)
960 {
961 return nullptr;
962 }
963
964 if (self->vec_num < 2 || self->vec_num > 4) {
965 PyErr_SetString(PyExc_ValueError, "Vector must be 2D, 3D or 4D");
966 return nullptr;
967 }
968
969 mirror[0] = tvec[0];
970 mirror[1] = tvec[1];
971 mirror[2] = (value_num > 2) ? tvec[2] : 0.0f;
972
973 vec[0] = self->vec[0];
974 vec[1] = self->vec[1];
975 vec[2] = (value_num > 2) ? self->vec[2] : 0.0f;
976
977 normalize_v3(mirror);
978 reflect_v3_v3v3(reflect, vec, mirror);
979
980 return Vector_CreatePyObject(reflect, self->vec_num, Py_TYPE(self));
981}
982
984
985/* -------------------------------------------------------------------- */
988
990 /* Wrap. */
991 Vector_cross_doc,
992 ".. method:: cross(other)\n"
993 "\n"
994 " Return the cross product of this vector and another.\n"
995 "\n"
996 " :arg other: The other vector to perform the cross product with.\n"
997 " :type other: :class:`Vector`\n"
998 " :return: The cross product as a vector or a float when 2D vectors are used.\n"
999 " :rtype: :class:`Vector` | float\n"
1000 "\n"
1001 " .. note:: both vectors must be 2D or 3D\n");
1002static PyObject *Vector_cross(VectorObject *self, PyObject *value)
1003{
1004 PyObject *ret;
1005 float tvec[3];
1006
1007 if (BaseMath_ReadCallback(self) == -1) {
1008 return nullptr;
1009 }
1010
1011 if (self->vec_num > 3) {
1012 PyErr_SetString(PyExc_ValueError, "Vector must be 2D or 3D");
1013 return nullptr;
1014 }
1015
1017 tvec, self->vec_num, self->vec_num, value, "Vector.cross(other), invalid 'other' arg") ==
1018 -1)
1019 {
1020 return nullptr;
1021 }
1022
1023 if (self->vec_num == 3) {
1024 ret = Vector_CreatePyObject(nullptr, 3, Py_TYPE(self));
1025 cross_v3_v3v3(((VectorObject *)ret)->vec, self->vec, tvec);
1026 }
1027 else {
1028 /* size == 2 */
1029 ret = PyFloat_FromDouble(cross_v2v2(self->vec, tvec));
1030 }
1031 return ret;
1032}
1033
1035
1036/* -------------------------------------------------------------------- */
1039
1041 /* Wrap. */
1042 Vector_dot_doc,
1043 ".. method:: dot(other)\n"
1044 "\n"
1045 " Return the dot product of this vector and another.\n"
1046 "\n"
1047 " :arg other: The other vector to perform the dot product with.\n"
1048 " :type other: :class:`Vector`\n"
1049 " :return: The dot product.\n"
1050 " :rtype: float\n");
1051static PyObject *Vector_dot(VectorObject *self, PyObject *value)
1052{
1053 float *tvec;
1054 PyObject *ret;
1055
1056 if (BaseMath_ReadCallback(self) == -1) {
1057 return nullptr;
1058 }
1059
1061 &tvec, self->vec_num, value, "Vector.dot(other), invalid 'other' arg") == -1)
1062 {
1063 return nullptr;
1064 }
1065
1066 ret = PyFloat_FromDouble(dot_vn_vn(self->vec, tvec, self->vec_num));
1067 PyMem_Free(tvec);
1068 return ret;
1069}
1070
1072
1073/* -------------------------------------------------------------------- */
1076
1078 /* Wrap. */
1079 Vector_angle_doc,
1080 ".. function:: angle(other, fallback=None)\n"
1081 "\n"
1082 " Return the angle between two vectors.\n"
1083 "\n"
1084 " :arg other: another vector to compare the angle with\n"
1085 " :type other: :class:`Vector`\n"
1086 " :arg fallback: return this when the angle can't be calculated (zero length vector),\n"
1087 " (instead of raising a :exc:`ValueError`).\n"
1088 " :type fallback: Any\n"
1089 " :return: angle in radians or fallback when given\n"
1090 " :rtype: float | Any\n");
1091static PyObject *Vector_angle(VectorObject *self, PyObject *args)
1092{
1093 const int vec_num = std::min(self->vec_num, 3); /* 4D angle makes no sense */
1094 float tvec[MAX_DIMENSIONS];
1095 PyObject *value;
1096 double dot = 0.0f, dot_self = 0.0f, dot_other = 0.0f;
1097 int x;
1098 PyObject *fallback = nullptr;
1099
1100 if (!PyArg_ParseTuple(args, "O|O:angle", &value, &fallback)) {
1101 return nullptr;
1102 }
1103
1104 if (BaseMath_ReadCallback(self) == -1) {
1105 return nullptr;
1106 }
1107
1108 /* don't use clamped size, rule of thumb is vector sizes must match,
1109 * even though n this case 'w' is ignored */
1111 tvec, self->vec_num, self->vec_num, value, "Vector.angle(other), invalid 'other' arg") ==
1112 -1)
1113 {
1114 return nullptr;
1115 }
1116
1117 if (self->vec_num > 4) {
1118 PyErr_SetString(PyExc_ValueError, "Vector must be 2D, 3D or 4D");
1119 return nullptr;
1120 }
1121
1122 for (x = 0; x < vec_num; x++) {
1123 dot_self += double(self->vec[x]) * double(self->vec[x]);
1124 dot_other += double(tvec[x]) * double(tvec[x]);
1125 dot += double(self->vec[x]) * double(tvec[x]);
1126 }
1127
1128 if (!dot_self || !dot_other) {
1129 /* avoid exception */
1130 if (fallback) {
1131 Py_INCREF(fallback);
1132 return fallback;
1133 }
1134
1135 PyErr_SetString(PyExc_ValueError,
1136 "Vector.angle(other): "
1137 "zero length vectors have no valid angle");
1138 return nullptr;
1139 }
1140
1141 return PyFloat_FromDouble(safe_acosf(dot / (sqrt(dot_self) * sqrt(dot_other))));
1142}
1143
1145
1146/* -------------------------------------------------------------------- */
1149
1151 /* Wrap. */
1152 Vector_angle_signed_doc,
1153 ".. function:: angle_signed(other, fallback=None)\n"
1154 "\n"
1155 " Return the signed angle between two 2D vectors (clockwise is positive).\n"
1156 "\n"
1157 " :arg other: another vector to compare the angle with\n"
1158 " :type other: :class:`Vector`\n"
1159 " :arg fallback: return this when the angle can't be calculated (zero length vector),\n"
1160 " (instead of raising a :exc:`ValueError`).\n"
1161 " :type fallback: Any\n"
1162 " :return: angle in radians or fallback when given\n"
1163 " :rtype: float | Any\n");
1164static PyObject *Vector_angle_signed(VectorObject *self, PyObject *args)
1165{
1166 float tvec[2];
1167
1168 PyObject *value;
1169 PyObject *fallback = nullptr;
1170
1171 if (!PyArg_ParseTuple(args, "O|O:angle_signed", &value, &fallback)) {
1172 return nullptr;
1173 }
1174
1175 if (BaseMath_ReadCallback(self) == -1) {
1176 return nullptr;
1177 }
1178
1180 tvec, 2, 2, value, "Vector.angle_signed(other), invalid 'other' arg") == -1)
1181 {
1182 return nullptr;
1183 }
1184
1185 if (self->vec_num != 2) {
1186 PyErr_SetString(PyExc_ValueError, "Vector must be 2D");
1187 return nullptr;
1188 }
1189
1190 if (is_zero_v2(self->vec) || is_zero_v2(tvec)) {
1191 /* avoid exception */
1192 if (fallback) {
1193 Py_INCREF(fallback);
1194 return fallback;
1195 }
1196
1197 PyErr_SetString(PyExc_ValueError,
1198 "Vector.angle_signed(other): "
1199 "zero length vectors have no valid angle");
1200 return nullptr;
1201 }
1202
1203 return PyFloat_FromDouble(angle_signed_v2v2(self->vec, tvec));
1204}
1205
1207
1208/* -------------------------------------------------------------------- */
1211
1213 /* Wrap. */
1214 Vector_rotation_difference_doc,
1215 ".. function:: rotation_difference(other)\n"
1216 "\n"
1217 " Returns a quaternion representing the rotational difference between this\n"
1218 " vector and another.\n"
1219 "\n"
1220 " :arg other: second vector.\n"
1221 " :type other: :class:`Vector`\n"
1222 " :return: the rotational difference between the two vectors.\n"
1223 " :rtype: :class:`Quaternion`\n"
1224 "\n"
1225 " .. note:: 2D vectors raise an :exc:`AttributeError`.\n");
1226static PyObject *Vector_rotation_difference(VectorObject *self, PyObject *value)
1227{
1228 float quat[4], vec_a[3], vec_b[3];
1229
1230 if (self->vec_num < 3 || self->vec_num > 4) {
1231 PyErr_SetString(PyExc_ValueError,
1232 "vec.difference(value): "
1233 "expects both vectors to be size 3 or 4");
1234 return nullptr;
1235 }
1236
1237 if (BaseMath_ReadCallback(self) == -1) {
1238 return nullptr;
1239 }
1240
1242 vec_b, 3, MAX_DIMENSIONS, value, "Vector.difference(other), invalid 'other' arg") == -1)
1243 {
1244 return nullptr;
1245 }
1246
1247 normalize_v3_v3(vec_a, self->vec);
1248 normalize_v3(vec_b);
1249
1250 rotation_between_vecs_to_quat(quat, vec_a, vec_b);
1251
1252 return Quaternion_CreatePyObject(quat, nullptr);
1253}
1254
1256
1257/* -------------------------------------------------------------------- */
1260
1262 /* Wrap. */
1263 Vector_project_doc,
1264 ".. function:: project(other)\n"
1265 "\n"
1266 " Return the projection of this vector onto the *other*.\n"
1267 "\n"
1268 " :arg other: second vector.\n"
1269 " :type other: :class:`Vector`\n"
1270 " :return: the parallel projection vector\n"
1271 " :rtype: :class:`Vector`\n");
1272static PyObject *Vector_project(VectorObject *self, PyObject *value)
1273{
1274 const int vec_num = self->vec_num;
1275 float *tvec;
1276 double dot = 0.0f, dot2 = 0.0f;
1277 int x;
1278
1279 if (BaseMath_ReadCallback(self) == -1) {
1280 return nullptr;
1281 }
1282
1284 &tvec, vec_num, value, "Vector.project(other), invalid 'other' arg") == -1)
1285 {
1286 return nullptr;
1287 }
1288
1289 /* get dot products */
1290 for (x = 0; x < vec_num; x++) {
1291 dot += double(self->vec[x] * tvec[x]);
1292 dot2 += double(tvec[x] * tvec[x]);
1293 }
1294 /* projection */
1295 dot /= dot2;
1296 for (x = 0; x < vec_num; x++) {
1297 tvec[x] *= float(dot);
1298 }
1299 return Vector_CreatePyObject_alloc(tvec, vec_num, Py_TYPE(self));
1300}
1301
1303
1304/* -------------------------------------------------------------------- */
1307
1309 /* Wrap. */
1310 Vector_lerp_doc,
1311 ".. function:: lerp(other, factor)\n"
1312 "\n"
1313 " Returns the interpolation of two vectors.\n"
1314 "\n"
1315 " :arg other: value to interpolate with.\n"
1316 " :type other: :class:`Vector`\n"
1317 " :arg factor: The interpolation value in [0.0, 1.0].\n"
1318 " :type factor: float\n"
1319 " :return: The interpolated vector.\n"
1320 " :rtype: :class:`Vector`\n");
1321static PyObject *Vector_lerp(VectorObject *self, PyObject *args)
1322{
1323 const int vec_num = self->vec_num;
1324 PyObject *value = nullptr;
1325 float fac;
1326 float *tvec;
1327
1328 if (!PyArg_ParseTuple(args, "Of:lerp", &value, &fac)) {
1329 return nullptr;
1330 }
1331
1332 if (BaseMath_ReadCallback(self) == -1) {
1333 return nullptr;
1334 }
1335
1337 &tvec, vec_num, value, "Vector.lerp(other), invalid 'other' arg") == -1)
1338 {
1339 return nullptr;
1340 }
1341
1342 interp_vn_vn(tvec, self->vec, 1.0f - fac, vec_num);
1343
1344 return Vector_CreatePyObject_alloc(tvec, vec_num, Py_TYPE(self));
1345}
1346
1348
1349/* -------------------------------------------------------------------- */
1352
1354 /* Wrap. */
1355 Vector_slerp_doc,
1356 ".. function:: slerp(other, factor, fallback=None)\n"
1357 "\n"
1358 " Returns the interpolation of two non-zero vectors (spherical coordinates).\n"
1359 "\n"
1360 " :arg other: value to interpolate with.\n"
1361 " :type other: :class:`Vector`\n"
1362 " :arg factor: The interpolation value typically in [0.0, 1.0].\n"
1363 " :type factor: float\n"
1364 " :arg fallback: return this when the vector can't be calculated (zero length "
1365 "vector or direct opposites),\n"
1366 " (instead of raising a :exc:`ValueError`).\n"
1367 " :type fallback: Any\n"
1368 " :return: The interpolated vector.\n"
1369 " :rtype: :class:`Vector`\n");
1370static PyObject *Vector_slerp(VectorObject *self, PyObject *args)
1371{
1372 const int vec_num = self->vec_num;
1373 PyObject *value = nullptr;
1374 float fac, cosom, w[2];
1375 float self_vec[3], other_vec[3], ret_vec[3];
1376 float self_len_sq, other_len_sq;
1377 int x;
1378 PyObject *fallback = nullptr;
1379
1380 if (!PyArg_ParseTuple(args, "Of|O:slerp", &value, &fac, &fallback)) {
1381 return nullptr;
1382 }
1383
1384 if (BaseMath_ReadCallback(self) == -1) {
1385 return nullptr;
1386 }
1387
1388 if (self->vec_num > 3) {
1389 PyErr_SetString(PyExc_ValueError, "Vector must be 2D or 3D");
1390 return nullptr;
1391 }
1392
1394 other_vec, vec_num, vec_num, value, "Vector.slerp(other), invalid 'other' arg") == -1)
1395 {
1396 return nullptr;
1397 }
1398
1399 self_len_sq = normalize_vn_vn(self_vec, self->vec, vec_num);
1400 other_len_sq = normalize_vn(other_vec, vec_num);
1401
1402 /* use fallbacks for zero length vectors */
1403 if (UNLIKELY((self_len_sq < FLT_EPSILON) || (other_len_sq < FLT_EPSILON))) {
1404 /* avoid exception */
1405 if (fallback) {
1406 Py_INCREF(fallback);
1407 return fallback;
1408 }
1409
1410 PyErr_SetString(PyExc_ValueError,
1411 "Vector.slerp(): "
1412 "zero length vectors unsupported");
1413 return nullptr;
1414 }
1415
1416 /* We have sane state, execute slerp */
1417 cosom = float(dot_vn_vn(self_vec, other_vec, vec_num));
1418
1419 /* direct opposite, can't slerp */
1420 if (UNLIKELY(cosom < (-1.0f + FLT_EPSILON))) {
1421 /* avoid exception */
1422 if (fallback) {
1423 Py_INCREF(fallback);
1424 return fallback;
1425 }
1426
1427 PyErr_SetString(PyExc_ValueError,
1428 "Vector.slerp(): "
1429 "opposite vectors unsupported");
1430 return nullptr;
1431 }
1432
1433 interp_dot_slerp(fac, cosom, w);
1434
1435 for (x = 0; x < vec_num; x++) {
1436 ret_vec[x] = (w[0] * self_vec[x]) + (w[1] * other_vec[x]);
1437 }
1438
1439 return Vector_CreatePyObject(ret_vec, vec_num, Py_TYPE(self));
1440}
1441
1443
1444/* -------------------------------------------------------------------- */
1447
1449 /* Wrap. */
1450 Vector_rotate_doc,
1451 ".. function:: rotate(other)\n"
1452 "\n"
1453 " Rotate the vector by a rotation value.\n"
1454 "\n"
1455 " .. note:: 2D vectors are a special case that can only be rotated by a 2x2 matrix.\n"
1456 "\n"
1457 " :arg other: rotation component of mathutils value\n"
1458 " :type other: :class:`Euler` | :class:`Quaternion` | :class:`Matrix`\n");
1459static PyObject *Vector_rotate(VectorObject *self, PyObject *value)
1460{
1462 return nullptr;
1463 }
1464
1465 if (self->vec_num == 2) {
1466 /* Special case for 2D Vector with 2x2 matrix, so we avoid resizing it to a 3x3. */
1467 float other_rmat[2][2];
1468 MatrixObject *pymat;
1469 if (!Matrix_Parse2x2(value, &pymat)) {
1470 return nullptr;
1471 }
1472 normalize_m2_m2(other_rmat, (const float(*)[2])pymat->matrix);
1473 /* Equivalent to a rotation along the Z axis. */
1474 mul_m2_v2(other_rmat, self->vec);
1475 }
1476 else {
1477 float other_rmat[3][3];
1478
1479 if (mathutils_any_to_rotmat(other_rmat, value, "Vector.rotate(value)") == -1) {
1480 return nullptr;
1481 }
1482
1483 mul_m3_v3(other_rmat, self->vec);
1484 }
1485
1487 Py_RETURN_NONE;
1488}
1489
1491
1492/* -------------------------------------------------------------------- */
1495
1497 /* Wrap. */
1498 Vector_negate_doc,
1499 ".. method:: negate()\n"
1500 "\n"
1501 " Set all values to their negative.\n");
1503{
1504 if (BaseMath_ReadCallback(self) == -1) {
1505 return nullptr;
1506 }
1507
1508 negate_vn(self->vec, self->vec_num);
1509
1510 (void)BaseMath_WriteCallback(self); /* already checked for error */
1511 Py_RETURN_NONE;
1512}
1513
1515
1516/* -------------------------------------------------------------------- */
1519
1521 /* Wrap. */
1522 Vector_copy_doc,
1523 ".. function:: copy()\n"
1524 "\n"
1525 " Returns a copy of this vector.\n"
1526 "\n"
1527 " :return: A copy of the vector.\n"
1528 " :rtype: :class:`Vector`\n"
1529 "\n"
1530 " .. note:: use this to get a copy of a wrapped vector with\n"
1531 " no reference to the original data.\n");
1533{
1534 if (BaseMath_ReadCallback(self) == -1) {
1535 return nullptr;
1536 }
1537
1538 return Vector_CreatePyObject(self->vec, self->vec_num, Py_TYPE(self));
1539}
1540static PyObject *Vector_deepcopy(VectorObject *self, PyObject *args)
1541{
1542 if (!PyC_CheckArgs_DeepCopy(args)) {
1543 return nullptr;
1544 }
1545 return Vector_copy(self);
1546}
1547
1549
1550/* -------------------------------------------------------------------- */
1553
1555{
1556 PyObject *ret, *tuple;
1557
1558 if (BaseMath_ReadCallback(self) == -1) {
1559 return nullptr;
1560 }
1561
1562 tuple = Vector_to_tuple_ex(self, -1);
1563 ret = PyUnicode_FromFormat("Vector(%R)", tuple);
1564 Py_DECREF(tuple);
1565 return ret;
1566}
1567
1568#ifndef MATH_STANDALONE
1569static PyObject *Vector_str(VectorObject *self)
1570{
1571 int i;
1572
1573 DynStr *ds;
1574
1575 if (BaseMath_ReadCallback(self) == -1) {
1576 return nullptr;
1577 }
1578
1579 ds = BLI_dynstr_new();
1580
1581 BLI_dynstr_append(ds, "<Vector (");
1582
1583 for (i = 0; i < self->vec_num; i++) {
1584 BLI_dynstr_appendf(ds, i ? ", %.4f" : "%.4f", self->vec[i]);
1585 }
1586
1587 BLI_dynstr_append(ds, ")>");
1588
1589 return mathutils_dynstr_to_py(ds); /* frees ds */
1590}
1591#endif
1592
1594
1595/* -------------------------------------------------------------------- */
1598
1599static PyObject *Vector_richcmpr(PyObject *objectA, PyObject *objectB, int comparison_type)
1600{
1601 VectorObject *vecA = nullptr, *vecB = nullptr;
1602 int result = 0;
1603 const double epsilon = 0.000001f;
1604 double lenA, lenB;
1605
1606 if (!VectorObject_Check(objectA) || !VectorObject_Check(objectB)) {
1607 if (comparison_type == Py_NE) {
1608 Py_RETURN_TRUE;
1609 }
1610
1611 Py_RETURN_FALSE;
1612 }
1613 vecA = (VectorObject *)objectA;
1614 vecB = (VectorObject *)objectB;
1615
1616 if (BaseMath_ReadCallback(vecA) == -1 || BaseMath_ReadCallback(vecB) == -1) {
1617 return nullptr;
1618 }
1619
1620 if (vecA->vec_num != vecB->vec_num) {
1621 if (comparison_type == Py_NE) {
1622 Py_RETURN_TRUE;
1623 }
1624
1625 Py_RETURN_FALSE;
1626 }
1627
1628 switch (comparison_type) {
1629 case Py_LT:
1630 lenA = len_squared_vn(vecA->vec, vecA->vec_num);
1631 lenB = len_squared_vn(vecB->vec, vecB->vec_num);
1632 if (lenA < lenB) {
1633 result = 1;
1634 }
1635 break;
1636 case Py_LE:
1637 lenA = len_squared_vn(vecA->vec, vecA->vec_num);
1638 lenB = len_squared_vn(vecB->vec, vecB->vec_num);
1639 if (lenA < lenB) {
1640 result = 1;
1641 }
1642 else {
1643 result = (((lenA + epsilon) > lenB) && ((lenA - epsilon) < lenB));
1644 }
1645 break;
1646 case Py_EQ:
1647 result = EXPP_VectorsAreEqual(vecA->vec, vecB->vec, vecA->vec_num, 1);
1648 break;
1649 case Py_NE:
1650 result = !EXPP_VectorsAreEqual(vecA->vec, vecB->vec, vecA->vec_num, 1);
1651 break;
1652 case Py_GT:
1653 lenA = len_squared_vn(vecA->vec, vecA->vec_num);
1654 lenB = len_squared_vn(vecB->vec, vecB->vec_num);
1655 if (lenA > lenB) {
1656 result = 1;
1657 }
1658 break;
1659 case Py_GE:
1660 lenA = len_squared_vn(vecA->vec, vecA->vec_num);
1661 lenB = len_squared_vn(vecB->vec, vecB->vec_num);
1662 if (lenA > lenB) {
1663 result = 1;
1664 }
1665 else {
1666 result = (((lenA + epsilon) > lenB) && ((lenA - epsilon) < lenB));
1667 }
1668 break;
1669 default:
1670 printf("The result of the comparison could not be evaluated");
1671 break;
1672 }
1673 if (result == 1) {
1674 Py_RETURN_TRUE;
1675 }
1676
1677 Py_RETURN_FALSE;
1678}
1679
1681
1682/* -------------------------------------------------------------------- */
1685
1687{
1688 if (BaseMath_ReadCallback(self) == -1) {
1689 return -1;
1690 }
1691
1693 return -1;
1694 }
1695
1696 return mathutils_array_hash(self->vec, self->vec_num);
1697}
1698
1700
1701/* -------------------------------------------------------------------- */
1704
1706static Py_ssize_t Vector_len(VectorObject *self)
1707{
1708 return self->vec_num;
1709}
1710
1711static PyObject *vector_item_internal(VectorObject *self, int i, const bool is_attr)
1712{
1713 if (i < 0) {
1714 i = self->vec_num - i;
1715 }
1716
1717 if (i < 0 || i >= self->vec_num) {
1718 if (is_attr) {
1719 PyErr_Format(PyExc_AttributeError,
1720 "Vector.%c: unavailable on %dd vector",
1721 *(((const char *)"xyzw") + i),
1722 self->vec_num);
1723 }
1724 else {
1725 PyErr_SetString(PyExc_IndexError, "vector[index]: out of range");
1726 }
1727 return nullptr;
1728 }
1729
1730 if (BaseMath_ReadIndexCallback(self, i) == -1) {
1731 return nullptr;
1732 }
1733
1734 return PyFloat_FromDouble(self->vec[i]);
1735}
1736
1738static PyObject *Vector_item(VectorObject *self, Py_ssize_t i)
1739{
1740 return vector_item_internal(self, i, false);
1741}
1742
1743static int vector_ass_item_internal(VectorObject *self, int i, PyObject *value, const bool is_attr)
1744{
1745 float scalar;
1746
1747 if (BaseMath_Prepare_ForWrite(self) == -1) {
1748 return -1;
1749 }
1750
1751 if ((scalar = PyFloat_AsDouble(value)) == -1.0f && PyErr_Occurred()) {
1752 /* parsed item not a number */
1753 PyErr_SetString(PyExc_TypeError,
1754 "vector[index] = x: "
1755 "assigned value not a number");
1756 return -1;
1757 }
1758
1759 if (i < 0) {
1760 i = self->vec_num - i;
1761 }
1762
1763 if (i < 0 || i >= self->vec_num) {
1764 if (is_attr) {
1765 PyErr_Format(PyExc_AttributeError,
1766 "Vector.%c = x: unavailable on %dd vector",
1767 *(((const char *)"xyzw") + i),
1768 self->vec_num);
1769 }
1770 else {
1771 PyErr_SetString(PyExc_IndexError,
1772 "vector[index] = x: "
1773 "assignment index out of range");
1774 }
1775 return -1;
1776 }
1777 self->vec[i] = scalar;
1778
1779 if (BaseMath_WriteIndexCallback(self, i) == -1) {
1780 return -1;
1781 }
1782 return 0;
1783}
1784
1786static int Vector_ass_item(VectorObject *self, Py_ssize_t i, PyObject *value)
1787{
1788 return vector_ass_item_internal(self, i, value, false);
1789}
1790
1792static PyObject *Vector_slice(VectorObject *self, int begin, int end)
1793{
1794 PyObject *tuple;
1795 int count;
1796
1797 if (BaseMath_ReadCallback(self) == -1) {
1798 return nullptr;
1799 }
1800
1801 CLAMP(begin, 0, self->vec_num);
1802 if (end < 0) {
1803 end = self->vec_num + end + 1;
1804 }
1805 CLAMP(end, 0, self->vec_num);
1806 begin = std::min(begin, end);
1807
1808 tuple = PyTuple_New(end - begin);
1809 for (count = begin; count < end; count++) {
1810 PyTuple_SET_ITEM(tuple, count - begin, PyFloat_FromDouble(self->vec[count]));
1811 }
1812
1813 return tuple;
1814}
1815
1817static int Vector_ass_slice(VectorObject *self, int begin, int end, PyObject *seq)
1818{
1819 int vec_num = 0;
1820 float *vec = nullptr;
1821
1823 return -1;
1824 }
1825
1826 CLAMP(begin, 0, self->vec_num);
1827 CLAMP(end, 0, self->vec_num);
1828 begin = std::min(begin, end);
1829
1830 vec_num = (end - begin);
1831 if (mathutils_array_parse_alloc(&vec, vec_num, seq, "vector[begin:end] = [...]") == -1) {
1832 return -1;
1833 }
1834
1835 if (vec == nullptr) {
1836 PyErr_SetString(PyExc_MemoryError,
1837 "vec[:] = seq: "
1838 "problem allocating pointer space");
1839 return -1;
1840 }
1841
1842 /* Parsed well - now set in vector. */
1843 memcpy(self->vec + begin, vec, vec_num * sizeof(float));
1844
1845 PyMem_Free(vec);
1846
1847 if (BaseMath_WriteCallback(self) == -1) {
1848 return -1;
1849 }
1850
1851 return 0;
1852}
1853
1855static PyObject *Vector_subscript(VectorObject *self, PyObject *item)
1856{
1857 if (PyIndex_Check(item)) {
1858 Py_ssize_t i;
1859 i = PyNumber_AsSsize_t(item, PyExc_IndexError);
1860 if (i == -1 && PyErr_Occurred()) {
1861 return nullptr;
1862 }
1863 if (i < 0) {
1864 i += self->vec_num;
1865 }
1866 return Vector_item(self, i);
1867 }
1868 if (PySlice_Check(item)) {
1869 Py_ssize_t start, stop, step, slicelength;
1870
1871 if (PySlice_GetIndicesEx(item, self->vec_num, &start, &stop, &step, &slicelength) < 0) {
1872 return nullptr;
1873 }
1874
1875 if (slicelength <= 0) {
1876 return PyTuple_New(0);
1877 }
1878 if (step == 1) {
1879 return Vector_slice(self, start, stop);
1880 }
1881
1882 PyErr_SetString(PyExc_IndexError, "slice steps not supported with vectors");
1883 return nullptr;
1884 }
1885
1886 PyErr_Format(
1887 PyExc_TypeError, "vector indices must be integers, not %.200s", Py_TYPE(item)->tp_name);
1888 return nullptr;
1889}
1890
1892static int Vector_ass_subscript(VectorObject *self, PyObject *item, PyObject *value)
1893{
1894 if (PyIndex_Check(item)) {
1895 Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
1896 if (i == -1 && PyErr_Occurred()) {
1897 return -1;
1898 }
1899 if (i < 0) {
1900 i += self->vec_num;
1901 }
1902 return Vector_ass_item(self, i, value);
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 -1;
1909 }
1910
1911 if (step == 1) {
1912 return Vector_ass_slice(self, start, stop, value);
1913 }
1914
1915 PyErr_SetString(PyExc_IndexError, "slice steps not supported with vectors");
1916 return -1;
1917 }
1918
1919 PyErr_Format(
1920 PyExc_TypeError, "vector indices must be integers, not %.200s", Py_TYPE(item)->tp_name);
1921 return -1;
1922}
1923
1925
1926/* -------------------------------------------------------------------- */
1929
1931static PyObject *Vector_add(PyObject *v1, PyObject *v2)
1932{
1933 VectorObject *vec1 = nullptr, *vec2 = nullptr;
1934 float *vec = nullptr;
1935
1937 PyErr_Format(PyExc_AttributeError,
1938 "Vector addition: (%s + %s) "
1939 "invalid type for this operation",
1940 Py_TYPE(v1)->tp_name,
1941 Py_TYPE(v2)->tp_name);
1942 return nullptr;
1943 }
1944 vec1 = (VectorObject *)v1;
1945 vec2 = (VectorObject *)v2;
1946
1947 if (BaseMath_ReadCallback(vec1) == -1 || BaseMath_ReadCallback(vec2) == -1) {
1948 return nullptr;
1949 }
1950
1951 /* VECTOR + VECTOR. */
1952 if (vec1->vec_num != vec2->vec_num) {
1953 PyErr_SetString(PyExc_AttributeError,
1954 "Vector addition: "
1955 "vectors must have the same dimensions for this operation");
1956 return nullptr;
1957 }
1958
1959 vec = static_cast<float *>(PyMem_Malloc(vec1->vec_num * sizeof(float)));
1960 if (vec == nullptr) {
1961 PyErr_SetString(PyExc_MemoryError,
1962 "Vector(): "
1963 "problem allocating pointer space");
1964 return nullptr;
1965 }
1966
1967 add_vn_vnvn(vec, vec1->vec, vec2->vec, vec1->vec_num);
1968
1969 return Vector_CreatePyObject_alloc(vec, vec1->vec_num, Py_TYPE(v1));
1970}
1971
1973static PyObject *Vector_iadd(PyObject *v1, PyObject *v2)
1974{
1975 VectorObject *vec1 = nullptr, *vec2 = nullptr;
1976
1978 PyErr_Format(PyExc_AttributeError,
1979 "Vector addition: (%s += %s) "
1980 "invalid type for this operation",
1981 Py_TYPE(v1)->tp_name,
1982 Py_TYPE(v2)->tp_name);
1983 return nullptr;
1984 }
1985 vec1 = (VectorObject *)v1;
1986 vec2 = (VectorObject *)v2;
1987
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 if (BaseMath_ReadCallback_ForWrite(vec1) == -1 || BaseMath_ReadCallback(vec2) == -1) {
1996 return nullptr;
1997 }
1998
1999 add_vn_vn(vec1->vec, vec2->vec, vec1->vec_num);
2000
2001 (void)BaseMath_WriteCallback(vec1);
2002 Py_INCREF(v1);
2003 return v1;
2004}
2005
2007static PyObject *Vector_sub(PyObject *v1, PyObject *v2)
2008{
2009 VectorObject *vec1 = nullptr, *vec2 = nullptr;
2010 float *vec;
2011
2013 PyErr_Format(PyExc_AttributeError,
2014 "Vector subtraction: (%s - %s) "
2015 "invalid type for this operation",
2016 Py_TYPE(v1)->tp_name,
2017 Py_TYPE(v2)->tp_name);
2018 return nullptr;
2019 }
2020 vec1 = (VectorObject *)v1;
2021 vec2 = (VectorObject *)v2;
2022
2023 if (BaseMath_ReadCallback(vec1) == -1 || BaseMath_ReadCallback(vec2) == -1) {
2024 return nullptr;
2025 }
2026
2027 if (vec1->vec_num != vec2->vec_num) {
2028 PyErr_SetString(PyExc_AttributeError,
2029 "Vector subtraction: "
2030 "vectors must have the same dimensions for this operation");
2031 return nullptr;
2032 }
2033
2034 vec = static_cast<float *>(PyMem_Malloc(vec1->vec_num * sizeof(float)));
2035 if (vec == nullptr) {
2036 PyErr_SetString(PyExc_MemoryError,
2037 "Vector(): "
2038 "problem allocating pointer space");
2039 return nullptr;
2040 }
2041
2042 sub_vn_vnvn(vec, vec1->vec, vec2->vec, vec1->vec_num);
2043
2044 return Vector_CreatePyObject_alloc(vec, vec1->vec_num, Py_TYPE(v1));
2045}
2046
2048static PyObject *Vector_isub(PyObject *v1, PyObject *v2)
2049{
2050 VectorObject *vec1 = nullptr, *vec2 = nullptr;
2051
2053 PyErr_Format(PyExc_AttributeError,
2054 "Vector subtraction: (%s -= %s) "
2055 "invalid type for this operation",
2056 Py_TYPE(v1)->tp_name,
2057 Py_TYPE(v2)->tp_name);
2058 return nullptr;
2059 }
2060 vec1 = (VectorObject *)v1;
2061 vec2 = (VectorObject *)v2;
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 if (BaseMath_ReadCallback_ForWrite(vec1) == -1 || BaseMath_ReadCallback(vec2) == -1) {
2071 return nullptr;
2072 }
2073
2074 sub_vn_vn(vec1->vec, vec2->vec, vec1->vec_num);
2075
2076 (void)BaseMath_WriteCallback(vec1);
2077 Py_INCREF(v1);
2078 return v1;
2079}
2080
2081/* Multiply internal implementation `object * object`, `object *= object`. */
2082
2084{
2085 float vec_cpy[MAX_DIMENSIONS];
2086 int row, col, z = 0;
2087
2088 if (mat->col_num != vec->vec_num) {
2089 if (mat->col_num == 4 && vec->vec_num == 3) {
2090 vec_cpy[3] = 1.0f;
2091 }
2092 else {
2093 PyErr_SetString(PyExc_ValueError,
2094 "matrix * vector: "
2095 "len(matrix.col) and len(vector) must be the same, "
2096 "except for 4x4 matrix * 3D vector.");
2097 return -1;
2098 }
2099 }
2100
2101 memcpy(vec_cpy, vec->vec, vec->vec_num * sizeof(float));
2102
2103 r_vec[3] = 1.0f;
2104
2105 for (row = 0; row < mat->row_num; row++) {
2106 double dot = 0.0f;
2107 for (col = 0; col < mat->col_num; col++) {
2108 dot += double(MATRIX_ITEM(mat, row, col) * vec_cpy[col]);
2109 }
2110 r_vec[z++] = float(dot);
2111 }
2112
2113 return 0;
2114}
2115
2116static PyObject *vector_mul_float(VectorObject *vec, const float scalar)
2117{
2118 float *tvec = static_cast<float *>(PyMem_Malloc(vec->vec_num * sizeof(float)));
2119 if (tvec == nullptr) {
2120 PyErr_SetString(PyExc_MemoryError,
2121 "vec * float: "
2122 "problem allocating pointer space");
2123 return nullptr;
2124 }
2125
2126 mul_vn_vn_fl(tvec, vec->vec, vec->vec_num, scalar);
2127 return Vector_CreatePyObject_alloc(tvec, vec->vec_num, Py_TYPE(vec));
2128}
2129
2130static PyObject *vector_mul_vec(VectorObject *vec1, VectorObject *vec2)
2131{
2132 float *tvec = static_cast<float *>(PyMem_Malloc(vec1->vec_num * sizeof(float)));
2133 if (tvec == nullptr) {
2134 PyErr_SetString(PyExc_MemoryError,
2135 "vec * vec: "
2136 "problem allocating pointer space");
2137 return nullptr;
2138 }
2139
2140 mul_vn_vnvn(tvec, vec1->vec, vec2->vec, vec1->vec_num);
2141 return Vector_CreatePyObject_alloc(tvec, vec1->vec_num, Py_TYPE(vec1));
2142}
2143
2145static PyObject *Vector_mul(PyObject *v1, PyObject *v2)
2146{
2147 VectorObject *vec1 = nullptr, *vec2 = nullptr;
2148 float scalar;
2149
2150 if (VectorObject_Check(v1)) {
2151 vec1 = (VectorObject *)v1;
2152 if (BaseMath_ReadCallback(vec1) == -1) {
2153 return nullptr;
2154 }
2155 }
2156 if (VectorObject_Check(v2)) {
2157 vec2 = (VectorObject *)v2;
2158 if (BaseMath_ReadCallback(vec2) == -1) {
2159 return nullptr;
2160 }
2161 }
2162
2163 /* Intentionally don't support (Quaternion) here, uses reverse order instead. */
2164
2165 /* make sure v1 is always the vector */
2166 if (vec1 && vec2) {
2167 if (vec1->vec_num != vec2->vec_num) {
2168 PyErr_SetString(PyExc_ValueError,
2169 "Vector multiplication: "
2170 "vectors must have the same dimensions for this operation");
2171 return nullptr;
2172 }
2173
2174 /* element-wise product */
2175 return vector_mul_vec(vec1, vec2);
2176 }
2177 if (vec1) {
2178 if (((scalar = PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred()) == 0) { /* VEC * FLOAT */
2179 return vector_mul_float(vec1, scalar);
2180 }
2181 }
2182 else if (vec2) {
2183 if (((scalar = PyFloat_AsDouble(v1)) == -1.0f && PyErr_Occurred()) == 0) { /* FLOAT * VEC */
2184 return vector_mul_float(vec2, scalar);
2185 }
2186 }
2187
2188 PyErr_Format(PyExc_TypeError,
2189 "Element-wise multiplication: "
2190 "not supported between '%.200s' and '%.200s' types",
2191 Py_TYPE(v1)->tp_name,
2192 Py_TYPE(v2)->tp_name);
2193 return nullptr;
2194}
2195
2197static PyObject *Vector_imul(PyObject *v1, PyObject *v2)
2198{
2199 VectorObject *vec1 = nullptr, *vec2 = nullptr;
2200 float scalar;
2201
2202 if (VectorObject_Check(v1)) {
2203 vec1 = (VectorObject *)v1;
2204 if (BaseMath_ReadCallback(vec1) == -1) {
2205 return nullptr;
2206 }
2207 }
2208 if (VectorObject_Check(v2)) {
2209 vec2 = (VectorObject *)v2;
2210 if (BaseMath_ReadCallback(vec2) == -1) {
2211 return nullptr;
2212 }
2213 }
2214
2215 if (BaseMath_ReadCallback_ForWrite(vec1) == -1) {
2216 return nullptr;
2217 }
2218
2219 /* Intentionally don't support (Quaternion, Matrix) here, uses reverse order instead. */
2220
2221 if (vec1 && vec2) {
2222 if (vec1->vec_num != vec2->vec_num) {
2223 PyErr_SetString(PyExc_ValueError,
2224 "Vector multiplication: "
2225 "vectors must have the same dimensions for this operation");
2226 return nullptr;
2227 }
2228
2229 /* Element-wise product in-place. */
2230 mul_vn_vn(vec1->vec, vec2->vec, vec1->vec_num);
2231 }
2232 else if (vec1 && (((scalar = PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred()) == 0)) {
2233 /* VEC *= FLOAT */
2234 mul_vn_fl(vec1->vec, vec1->vec_num, scalar);
2235 }
2236 else {
2237 PyErr_Format(PyExc_TypeError,
2238 "In place element-wise multiplication: "
2239 "not supported between '%.200s' and '%.200s' types",
2240 Py_TYPE(v1)->tp_name,
2241 Py_TYPE(v2)->tp_name);
2242 return nullptr;
2243 }
2244
2245 (void)BaseMath_WriteCallback(vec1);
2246 Py_INCREF(v1);
2247 return v1;
2248}
2249
2251static PyObject *Vector_matmul(PyObject *v1, PyObject *v2)
2252{
2253 VectorObject *vec1 = nullptr, *vec2 = nullptr;
2254 int vec_num;
2255
2256 if (VectorObject_Check(v1)) {
2257 vec1 = (VectorObject *)v1;
2258 if (BaseMath_ReadCallback(vec1) == -1) {
2259 return nullptr;
2260 }
2261 }
2262 if (VectorObject_Check(v2)) {
2263 vec2 = (VectorObject *)v2;
2264 if (BaseMath_ReadCallback(vec2) == -1) {
2265 return nullptr;
2266 }
2267 }
2268
2269 /* Intentionally don't support (Quaternion) here, uses reverse order instead. */
2270
2271 /* make sure v1 is always the vector */
2272 if (vec1 && vec2) {
2273 if (vec1->vec_num != vec2->vec_num) {
2274 PyErr_SetString(PyExc_ValueError,
2275 "Vector multiplication: "
2276 "vectors must have the same dimensions for this operation");
2277 return nullptr;
2278 }
2279
2280 /* Dot product. */
2281 return PyFloat_FromDouble(dot_vn_vn(vec1->vec, vec2->vec, vec1->vec_num));
2282 }
2283 if (vec1) {
2284 if (MatrixObject_Check(v2)) {
2285 /* VEC @ MATRIX */
2286 float tvec[MAX_DIMENSIONS];
2287
2288 if (BaseMath_ReadCallback((MatrixObject *)v2) == -1) {
2289 return nullptr;
2290 }
2291 if (row_vector_multiplication(tvec, vec1, (MatrixObject *)v2) == -1) {
2292 return nullptr;
2293 }
2294
2295 if (((MatrixObject *)v2)->row_num == 4 && vec1->vec_num == 3) {
2296 vec_num = 3;
2297 }
2298 else {
2299 vec_num = ((MatrixObject *)v2)->col_num;
2300 }
2301
2302 return Vector_CreatePyObject(tvec, vec_num, Py_TYPE(vec1));
2303 }
2304 }
2305
2306 PyErr_Format(PyExc_TypeError,
2307 "Vector multiplication: "
2308 "not supported between '%.200s' and '%.200s' types",
2309 Py_TYPE(v1)->tp_name,
2310 Py_TYPE(v2)->tp_name);
2311 return nullptr;
2312}
2313
2315static PyObject *Vector_imatmul(PyObject *v1, PyObject *v2)
2316{
2317 PyErr_Format(PyExc_TypeError,
2318 "In place vector multiplication: "
2319 "not supported between '%.200s' and '%.200s' types",
2320 Py_TYPE(v1)->tp_name,
2321 Py_TYPE(v2)->tp_name);
2322 return nullptr;
2323}
2324
2326static PyObject *Vector_div(PyObject *v1, PyObject *v2)
2327{
2328 float *vec = nullptr, scalar;
2329 VectorObject *vec1 = nullptr;
2330
2331 if (!VectorObject_Check(v1)) { /* not a vector */
2332 PyErr_SetString(PyExc_TypeError,
2333 "Vector division: "
2334 "Vector must be divided by a float");
2335 return nullptr;
2336 }
2337 vec1 = (VectorObject *)v1; /* vector */
2338
2339 if (BaseMath_ReadCallback(vec1) == -1) {
2340 return nullptr;
2341 }
2342
2343 if ((scalar = PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred()) {
2344 /* parsed item not a number */
2345 PyErr_SetString(PyExc_TypeError,
2346 "Vector division: "
2347 "Vector must be divided by a float");
2348 return nullptr;
2349 }
2350
2351 if (scalar == 0.0f) {
2352 PyErr_SetString(PyExc_ZeroDivisionError,
2353 "Vector division: "
2354 "divide by zero error");
2355 return nullptr;
2356 }
2357
2358 vec = static_cast<float *>(PyMem_Malloc(vec1->vec_num * sizeof(float)));
2359
2360 if (vec == nullptr) {
2361 PyErr_SetString(PyExc_MemoryError,
2362 "vec / value: "
2363 "problem allocating pointer space");
2364 return nullptr;
2365 }
2366
2367 mul_vn_vn_fl(vec, vec1->vec, vec1->vec_num, 1.0f / scalar);
2368
2369 return Vector_CreatePyObject_alloc(vec, vec1->vec_num, Py_TYPE(v1));
2370}
2371
2373static PyObject *Vector_idiv(PyObject *v1, PyObject *v2)
2374{
2375 float scalar;
2376 VectorObject *vec1 = (VectorObject *)v1;
2377
2378 if (BaseMath_ReadCallback_ForWrite(vec1) == -1) {
2379 return nullptr;
2380 }
2381
2382 if ((scalar = PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred()) {
2383 /* parsed item not a number */
2384 PyErr_SetString(PyExc_TypeError,
2385 "Vector division: "
2386 "Vector must be divided by a float");
2387 return nullptr;
2388 }
2389
2390 if (scalar == 0.0f) {
2391 PyErr_SetString(PyExc_ZeroDivisionError,
2392 "Vector division: "
2393 "divide by zero error");
2394 return nullptr;
2395 }
2396
2397 mul_vn_fl(vec1->vec, vec1->vec_num, 1.0f / scalar);
2398
2399 (void)BaseMath_WriteCallback(vec1);
2400
2401 Py_INCREF(v1);
2402 return v1;
2403}
2404
2406static PyObject *Vector_neg(VectorObject *self)
2407{
2408 float *tvec;
2409
2410 if (BaseMath_ReadCallback(self) == -1) {
2411 return nullptr;
2412 }
2413
2414 tvec = static_cast<float *>(PyMem_Malloc(self->vec_num * sizeof(float)));
2415 negate_vn_vn(tvec, self->vec, self->vec_num);
2416 return Vector_CreatePyObject_alloc(tvec, self->vec_num, Py_TYPE(self));
2417}
2418
2420
2421/* -------------------------------------------------------------------- */
2424
2425static PySequenceMethods Vector_SeqMethods = {
2426 /*sq_length*/ (lenfunc)Vector_len,
2427 /*sq_concat*/ nullptr,
2428 /*sq_repeat*/ nullptr,
2429 /*sq_item*/ (ssizeargfunc)Vector_item,
2430 /*was_sq_slice*/ nullptr, /* DEPRECATED. */
2431 /*sq_ass_item*/ (ssizeobjargproc)Vector_ass_item,
2432 /*was_sq_ass_slice*/ nullptr, /* DEPRECATED. */
2433 /*sq_contains*/ nullptr,
2434 /*sq_inplace_concat*/ nullptr,
2435 /*sq_inplace_repeat*/ nullptr,
2436};
2437
2438static PyMappingMethods Vector_AsMapping = {
2439 /*mp_length*/ (lenfunc)Vector_len,
2440 /*mp_subscript*/ (binaryfunc)Vector_subscript,
2441 /*mp_ass_subscript*/ (objobjargproc)Vector_ass_subscript,
2442};
2443
2444static PyNumberMethods Vector_NumMethods = {
2445 /*nb_add*/ (binaryfunc)Vector_add,
2446 /*nb_subtract*/ (binaryfunc)Vector_sub,
2447 /*nb_multiply*/ (binaryfunc)Vector_mul,
2448 /*nb_remainder*/ nullptr,
2449 /*nb_divmod*/ nullptr,
2450 /*nb_power*/ nullptr,
2451 /*nb_negative*/ (unaryfunc)Vector_neg,
2452 /*nb_positive*/ (unaryfunc)Vector_copy,
2453 /*nb_absolute*/ nullptr,
2454 /*nb_bool*/ nullptr,
2455 /*nb_invert*/ nullptr,
2456 /*nb_lshift*/ nullptr,
2457 /*nb_rshift*/ nullptr,
2458 /*nb_and*/ nullptr,
2459 /*nb_xor*/ nullptr,
2460 /*nb_or*/ nullptr,
2461 /*nb_int*/ nullptr,
2462 /*nb_reserved*/ nullptr,
2463 /*nb_float*/ nullptr,
2464 /*nb_inplace_add*/ Vector_iadd,
2465 /*nb_inplace_subtract*/ Vector_isub,
2466 /*nb_inplace_multiply*/ Vector_imul,
2467 /*nb_inplace_remainder*/ nullptr,
2468 /*nb_inplace_power*/ nullptr,
2469 /*nb_inplace_lshift*/ nullptr,
2470 /*nb_inplace_rshift*/ nullptr,
2471 /*nb_inplace_and*/ nullptr,
2472 /*nb_inplace_xor*/ nullptr,
2473 /*nb_inplace_or*/ nullptr,
2474 /*nb_floor_divide*/ nullptr,
2475 /*nb_true_divide*/ Vector_div,
2476 /*nb_inplace_floor_divide*/ nullptr,
2477 /*nb_inplace_true_divide*/ Vector_idiv,
2478 /*nb_index*/ nullptr,
2479 /*nb_matrix_multiply*/ (binaryfunc)Vector_matmul,
2480 /*nb_inplace_matrix_multiply*/ (binaryfunc)Vector_imatmul,
2481};
2482
2484
2485/* -------------------------------------------------------------------- */
2488
2489/* Vector axis: `vector.x/y/z/w`. */
2490
2492 /* Wrap. */
2493 Vector_axis_x_doc,
2494 "Vector X axis.\n"
2495 "\n"
2496 ":type: float");
2498 /* Wrap. */
2499 Vector_axis_y_doc,
2500 "Vector Y axis.\n"
2501 "\n"
2502 ":type: float");
2504 /* Wrap. */
2505 Vector_axis_z_doc,
2506 "Vector Z axis (3D Vectors only).\n"
2507 "\n"
2508 ":type: float");
2510 /* Wrap. */
2511 Vector_axis_w_doc,
2512 "Vector W axis (4D Vectors only).\n"
2513 "\n"
2514 ":type: float");
2515
2516static PyObject *Vector_axis_get(VectorObject *self, void *type)
2517{
2518 return vector_item_internal(self, POINTER_AS_INT(type), true);
2519}
2520
2521static int Vector_axis_set(VectorObject *self, PyObject *value, void *type)
2522{
2523 return vector_ass_item_internal(self, POINTER_AS_INT(type), value, true);
2524}
2525
2526/* `Vector.length`. */
2527
2529 /* Wrap. */
2530 Vector_length_doc,
2531 "Vector Length.\n"
2532 "\n"
2533 ":type: float");
2534static PyObject *Vector_length_get(VectorObject *self, void * /*closure*/)
2535{
2536 if (BaseMath_ReadCallback(self) == -1) {
2537 return nullptr;
2538 }
2539
2540 return PyFloat_FromDouble(sqrt(dot_vn_vn(self->vec, self->vec, self->vec_num)));
2541}
2542
2543static int Vector_length_set(VectorObject *self, PyObject *value)
2544{
2545 double dot = 0.0f, param;
2546
2548 return -1;
2549 }
2550
2551 if ((param = PyFloat_AsDouble(value)) == -1.0 && PyErr_Occurred()) {
2552 PyErr_SetString(PyExc_TypeError, "length must be set to a number");
2553 return -1;
2554 }
2555
2556 if (param < 0.0) {
2557 PyErr_SetString(PyExc_ValueError, "cannot set a vectors length to a negative value");
2558 return -1;
2559 }
2560 if (param == 0.0) {
2561 copy_vn_fl(self->vec, self->vec_num, 0.0f);
2562 return 0;
2563 }
2564
2565 dot = dot_vn_vn(self->vec, self->vec, self->vec_num);
2566
2567 if (!dot) {
2568 /* can't sqrt zero */
2569 return 0;
2570 }
2571
2572 dot = sqrt(dot);
2573
2574 if (dot == param) {
2575 return 0;
2576 }
2577
2578 dot = dot / param;
2579
2580 mul_vn_fl(self->vec, self->vec_num, 1.0 / dot);
2581
2582 (void)BaseMath_WriteCallback(self); /* checked already */
2583
2584 return 0;
2585}
2586
2587/* `Vector.length_squared`. */
2589 /* Wrap. */
2590 Vector_length_squared_doc,
2591 "Vector length squared (v.dot(v)).\n"
2592 "\n"
2593 ":type: float");
2594static PyObject *Vector_length_squared_get(VectorObject *self, void * /*closure*/)
2595{
2596 if (BaseMath_ReadCallback(self) == -1) {
2597 return nullptr;
2598 }
2599
2600 return PyFloat_FromDouble(dot_vn_vn(self->vec, self->vec, self->vec_num));
2601}
2602
2603/* `Vector.xyzw`, etc.. */
2605 /* Wrap. */
2606 Vector_swizzle_doc,
2607 ":type: :class:`Vector`");
2608
2691
2695static PyObject *Vector_swizzle_get(VectorObject *self, void *closure)
2696{
2697 size_t axis_to;
2698 size_t axis_from;
2699 float vec[MAX_DIMENSIONS];
2700 uint swizzleClosure;
2701
2702 if (BaseMath_ReadCallback(self) == -1) {
2703 return nullptr;
2704 }
2705
2706 /* Unpack the axes from the closure into an array. */
2707 axis_to = 0;
2708 swizzleClosure = POINTER_AS_INT(closure);
2709 while (swizzleClosure & SWIZZLE_VALID_AXIS) {
2710 axis_from = swizzleClosure & SWIZZLE_AXIS;
2711 if (axis_from >= self->vec_num) {
2712 PyErr_SetString(PyExc_AttributeError,
2713 "Vector swizzle: "
2714 "specified axis not present");
2715 return nullptr;
2716 }
2717
2718 vec[axis_to] = self->vec[axis_from];
2719 swizzleClosure = swizzleClosure >> SWIZZLE_BITS_PER_AXIS;
2720 axis_to++;
2721 }
2722
2723 return Vector_CreatePyObject(vec, axis_to, Py_TYPE(self));
2724}
2725
2737static int Vector_swizzle_set(VectorObject *self, PyObject *value, void *closure)
2738{
2739 size_t size_from;
2740 float scalarVal;
2741
2742 size_t axis_from;
2743 size_t axis_to;
2744
2745 uint swizzleClosure;
2746
2747 float tvec[MAX_DIMENSIONS];
2748 float vec_assign[MAX_DIMENSIONS];
2749
2751 return -1;
2752 }
2753
2754 /* Check that the closure can be used with this vector: even 2D vectors have
2755 * swizzles defined for axes z and w, but they would be invalid. */
2756 swizzleClosure = POINTER_AS_INT(closure);
2757 axis_from = 0;
2758
2759 while (swizzleClosure & SWIZZLE_VALID_AXIS) {
2760 axis_to = swizzleClosure & SWIZZLE_AXIS;
2761 if (axis_to >= self->vec_num) {
2762 PyErr_SetString(PyExc_AttributeError,
2763 "Vector swizzle: "
2764 "specified axis not present");
2765 return -1;
2766 }
2767 swizzleClosure = swizzleClosure >> SWIZZLE_BITS_PER_AXIS;
2768 axis_from++;
2769 }
2770
2771 if (((scalarVal = PyFloat_AsDouble(value)) == -1 && PyErr_Occurred()) == 0) {
2772 int i;
2773
2774 for (i = 0; i < MAX_DIMENSIONS; i++) {
2775 vec_assign[i] = scalarVal;
2776 }
2777
2778 size_from = axis_from;
2779 }
2780 else if (PyErr_Clear(), /* run but ignore the result */
2781 (size_from = size_t(mathutils_array_parse(
2782 vec_assign, 2, 4, value, "Vector.**** = swizzle assignment"))) == size_t(-1))
2783 {
2784 return -1;
2785 }
2786
2787 if (axis_from != size_from) {
2788 PyErr_SetString(PyExc_AttributeError, "Vector swizzle: size does not match swizzle");
2789 return -1;
2790 }
2791
2792 /* Copy vector contents onto swizzled axes. */
2793 axis_from = 0;
2794 swizzleClosure = POINTER_AS_INT(closure);
2795
2796 /* We must first copy current vec into tvec, else some org values may be lost.
2797 * See #31760.
2798 * Assuming self->vec_num can't be higher than MAX_DIMENSIONS! */
2799 memcpy(tvec, self->vec, self->vec_num * sizeof(float));
2800
2801 while (swizzleClosure & SWIZZLE_VALID_AXIS) {
2802 axis_to = swizzleClosure & SWIZZLE_AXIS;
2803 tvec[axis_to] = vec_assign[axis_from];
2804 swizzleClosure = swizzleClosure >> SWIZZLE_BITS_PER_AXIS;
2805 axis_from++;
2806 }
2807
2808 /* We must copy back the whole tvec into vec, else some changes may be lost (e.g. xz...).
2809 * See #31760. */
2810 memcpy(self->vec, tvec, self->vec_num * sizeof(float));
2811 /* continue with BaseMathObject_WriteCallback at the end */
2812
2813 if (BaseMath_WriteCallback(self) == -1) {
2814 return -1;
2815 }
2816
2817 return 0;
2818}
2819
2820#define _SWIZZLE1(a) ((a) | SWIZZLE_VALID_AXIS)
2821#define _SWIZZLE2(a, b) (_SWIZZLE1(a) | (((b) | SWIZZLE_VALID_AXIS) << (SWIZZLE_BITS_PER_AXIS)))
2822#define _SWIZZLE3(a, b, c) \
2823 (_SWIZZLE2(a, b) | (((c) | SWIZZLE_VALID_AXIS) << (SWIZZLE_BITS_PER_AXIS * 2)))
2824#define _SWIZZLE4(a, b, c, d) \
2825 (_SWIZZLE3(a, b, c) | (((d) | SWIZZLE_VALID_AXIS) << (SWIZZLE_BITS_PER_AXIS * 3)))
2826
2827#define SWIZZLE2(a, b) POINTER_FROM_INT(_SWIZZLE2(a, b))
2828#define SWIZZLE3(a, b, c) POINTER_FROM_INT(_SWIZZLE3(a, b, c))
2829#define SWIZZLE4(a, b, c, d) POINTER_FROM_INT(_SWIZZLE4(a, b, c, d))
2830
2831#define VECTOR_SWIZZLE2_RW_DEF(attr, a, b) \
2832 { \
2833 attr, (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, Vector_swizzle_doc, \
2834 SWIZZLE2(a, b), \
2835 }
2836#define VECTOR_SWIZZLE2_RO_DEF(attr, a, b) \
2837 { \
2838 attr, (getter)Vector_swizzle_get, (setter) nullptr, Vector_swizzle_doc, SWIZZLE2(a, b), \
2839 }
2840#define VECTOR_SWIZZLE3_RW_DEF(attr, a, b, c) \
2841 { \
2842 attr, (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, Vector_swizzle_doc, \
2843 SWIZZLE3(a, b, c), \
2844 }
2845#define VECTOR_SWIZZLE3_RO_DEF(attr, a, b, c) \
2846 { \
2847 attr, (getter)Vector_swizzle_get, (setter) nullptr, Vector_swizzle_doc, SWIZZLE3(a, b, c), \
2848 }
2849#define VECTOR_SWIZZLE4_RW_DEF(attr, a, b, c, d) \
2850 { \
2851 attr, (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, Vector_swizzle_doc, \
2852 SWIZZLE4(a, b, c, d), \
2853 }
2854#define VECTOR_SWIZZLE4_RO_DEF(attr, a, b, c, d) \
2855 { \
2856 attr, (getter)Vector_swizzle_get, (setter) nullptr, Vector_swizzle_doc, SWIZZLE4(a, b, c, d) \
2857 }
2858
2860
2861/* -------------------------------------------------------------------- */
2864
2865#ifdef __GNUC__
2866# ifdef __clang__
2867# pragma clang diagnostic push
2868# pragma clang diagnostic ignored "-Wcast-function-type"
2869# else
2870# pragma GCC diagnostic push
2871# pragma GCC diagnostic ignored "-Wcast-function-type"
2872# endif
2873#endif
2874
2875static PyGetSetDef Vector_getseters[] = {
2876 {"x",
2877 (getter)Vector_axis_get,
2878 (setter)Vector_axis_set,
2879 Vector_axis_x_doc,
2880 POINTER_FROM_INT(0)},
2881 {"y",
2882 (getter)Vector_axis_get,
2883 (setter)Vector_axis_set,
2884 Vector_axis_y_doc,
2885 POINTER_FROM_INT(1)},
2886 {"z",
2887 (getter)Vector_axis_get,
2888 (setter)Vector_axis_set,
2889 Vector_axis_z_doc,
2890 POINTER_FROM_INT(2)},
2891 {"w",
2892 (getter)Vector_axis_get,
2893 (setter)Vector_axis_set,
2894 Vector_axis_w_doc,
2895 POINTER_FROM_INT(3)},
2896 {"length", (getter)Vector_length_get, (setter)Vector_length_set, Vector_length_doc, nullptr},
2897 {"length_squared",
2899 (setter) nullptr,
2900 Vector_length_squared_doc,
2901 nullptr},
2902 {"magnitude",
2903 (getter)Vector_length_get,
2904 (setter)Vector_length_set,
2905 Vector_length_doc,
2906 nullptr},
2907 {"is_wrapped",
2909 (setter) nullptr,
2911 nullptr},
2912 {"is_frozen",
2914 (setter) nullptr,
2916 nullptr},
2917 {"is_valid",
2919 (setter) nullptr,
2921 nullptr},
2922 {"owner",
2924 (setter) nullptr,
2926 nullptr},
2927
2928 /* Auto-generated swizzle attributes, see Python script above. */
2929 VECTOR_SWIZZLE2_RO_DEF("xx", 0, 0),
2930 VECTOR_SWIZZLE3_RO_DEF("xxx", 0, 0, 0),
2931 VECTOR_SWIZZLE4_RO_DEF("xxxx", 0, 0, 0, 0),
2932 VECTOR_SWIZZLE4_RO_DEF("xxxy", 0, 0, 0, 1),
2933 VECTOR_SWIZZLE4_RO_DEF("xxxz", 0, 0, 0, 2),
2934 VECTOR_SWIZZLE4_RO_DEF("xxxw", 0, 0, 0, 3),
2935 VECTOR_SWIZZLE3_RO_DEF("xxy", 0, 0, 1),
2936 VECTOR_SWIZZLE4_RO_DEF("xxyx", 0, 0, 1, 0),
2937 VECTOR_SWIZZLE4_RO_DEF("xxyy", 0, 0, 1, 1),
2938 VECTOR_SWIZZLE4_RO_DEF("xxyz", 0, 0, 1, 2),
2939 VECTOR_SWIZZLE4_RO_DEF("xxyw", 0, 0, 1, 3),
2940 VECTOR_SWIZZLE3_RO_DEF("xxz", 0, 0, 2),
2941 VECTOR_SWIZZLE4_RO_DEF("xxzx", 0, 0, 2, 0),
2942 VECTOR_SWIZZLE4_RO_DEF("xxzy", 0, 0, 2, 1),
2943 VECTOR_SWIZZLE4_RO_DEF("xxzz", 0, 0, 2, 2),
2944 VECTOR_SWIZZLE4_RO_DEF("xxzw", 0, 0, 2, 3),
2945 VECTOR_SWIZZLE3_RO_DEF("xxw", 0, 0, 3),
2946 VECTOR_SWIZZLE4_RO_DEF("xxwx", 0, 0, 3, 0),
2947 VECTOR_SWIZZLE4_RO_DEF("xxwy", 0, 0, 3, 1),
2948 VECTOR_SWIZZLE4_RO_DEF("xxwz", 0, 0, 3, 2),
2949 VECTOR_SWIZZLE4_RO_DEF("xxww", 0, 0, 3, 3),
2950 VECTOR_SWIZZLE2_RW_DEF("xy", 0, 1),
2951 VECTOR_SWIZZLE3_RO_DEF("xyx", 0, 1, 0),
2952 VECTOR_SWIZZLE4_RO_DEF("xyxx", 0, 1, 0, 0),
2953 VECTOR_SWIZZLE4_RO_DEF("xyxy", 0, 1, 0, 1),
2954 VECTOR_SWIZZLE4_RO_DEF("xyxz", 0, 1, 0, 2),
2955 VECTOR_SWIZZLE4_RO_DEF("xyxw", 0, 1, 0, 3),
2956 VECTOR_SWIZZLE3_RO_DEF("xyy", 0, 1, 1),
2957 VECTOR_SWIZZLE4_RO_DEF("xyyx", 0, 1, 1, 0),
2958 VECTOR_SWIZZLE4_RO_DEF("xyyy", 0, 1, 1, 1),
2959 VECTOR_SWIZZLE4_RO_DEF("xyyz", 0, 1, 1, 2),
2960 VECTOR_SWIZZLE4_RO_DEF("xyyw", 0, 1, 1, 3),
2961 VECTOR_SWIZZLE3_RW_DEF("xyz", 0, 1, 2),
2962 VECTOR_SWIZZLE4_RO_DEF("xyzx", 0, 1, 2, 0),
2963 VECTOR_SWIZZLE4_RO_DEF("xyzy", 0, 1, 2, 1),
2964 VECTOR_SWIZZLE4_RO_DEF("xyzz", 0, 1, 2, 2),
2965 VECTOR_SWIZZLE4_RW_DEF("xyzw", 0, 1, 2, 3),
2966 VECTOR_SWIZZLE3_RW_DEF("xyw", 0, 1, 3),
2967 VECTOR_SWIZZLE4_RO_DEF("xywx", 0, 1, 3, 0),
2968 VECTOR_SWIZZLE4_RO_DEF("xywy", 0, 1, 3, 1),
2969 VECTOR_SWIZZLE4_RW_DEF("xywz", 0, 1, 3, 2),
2970 VECTOR_SWIZZLE4_RO_DEF("xyww", 0, 1, 3, 3),
2971 VECTOR_SWIZZLE2_RW_DEF("xz", 0, 2),
2972 VECTOR_SWIZZLE3_RO_DEF("xzx", 0, 2, 0),
2973 VECTOR_SWIZZLE4_RO_DEF("xzxx", 0, 2, 0, 0),
2974 VECTOR_SWIZZLE4_RO_DEF("xzxy", 0, 2, 0, 1),
2975 VECTOR_SWIZZLE4_RO_DEF("xzxz", 0, 2, 0, 2),
2976 VECTOR_SWIZZLE4_RO_DEF("xzxw", 0, 2, 0, 3),
2977 VECTOR_SWIZZLE3_RW_DEF("xzy", 0, 2, 1),
2978 VECTOR_SWIZZLE4_RO_DEF("xzyx", 0, 2, 1, 0),
2979 VECTOR_SWIZZLE4_RO_DEF("xzyy", 0, 2, 1, 1),
2980 VECTOR_SWIZZLE4_RO_DEF("xzyz", 0, 2, 1, 2),
2981 VECTOR_SWIZZLE4_RW_DEF("xzyw", 0, 2, 1, 3),
2982 VECTOR_SWIZZLE3_RO_DEF("xzz", 0, 2, 2),
2983 VECTOR_SWIZZLE4_RO_DEF("xzzx", 0, 2, 2, 0),
2984 VECTOR_SWIZZLE4_RO_DEF("xzzy", 0, 2, 2, 1),
2985 VECTOR_SWIZZLE4_RO_DEF("xzzz", 0, 2, 2, 2),
2986 VECTOR_SWIZZLE4_RO_DEF("xzzw", 0, 2, 2, 3),
2987 VECTOR_SWIZZLE3_RW_DEF("xzw", 0, 2, 3),
2988 VECTOR_SWIZZLE4_RO_DEF("xzwx", 0, 2, 3, 0),
2989 VECTOR_SWIZZLE4_RW_DEF("xzwy", 0, 2, 3, 1),
2990 VECTOR_SWIZZLE4_RO_DEF("xzwz", 0, 2, 3, 2),
2991 VECTOR_SWIZZLE4_RO_DEF("xzww", 0, 2, 3, 3),
2992 VECTOR_SWIZZLE2_RW_DEF("xw", 0, 3),
2993 VECTOR_SWIZZLE3_RO_DEF("xwx", 0, 3, 0),
2994 VECTOR_SWIZZLE4_RO_DEF("xwxx", 0, 3, 0, 0),
2995 VECTOR_SWIZZLE4_RO_DEF("xwxy", 0, 3, 0, 1),
2996 VECTOR_SWIZZLE4_RO_DEF("xwxz", 0, 3, 0, 2),
2997 VECTOR_SWIZZLE4_RO_DEF("xwxw", 0, 3, 0, 3),
2998 VECTOR_SWIZZLE3_RW_DEF("xwy", 0, 3, 1),
2999 VECTOR_SWIZZLE4_RO_DEF("xwyx", 0, 3, 1, 0),
3000 VECTOR_SWIZZLE4_RO_DEF("xwyy", 0, 3, 1, 1),
3001 VECTOR_SWIZZLE4_RW_DEF("xwyz", 0, 3, 1, 2),
3002 VECTOR_SWIZZLE4_RO_DEF("xwyw", 0, 3, 1, 3),
3003 VECTOR_SWIZZLE3_RW_DEF("xwz", 0, 3, 2),
3004 VECTOR_SWIZZLE4_RO_DEF("xwzx", 0, 3, 2, 0),
3005 VECTOR_SWIZZLE4_RW_DEF("xwzy", 0, 3, 2, 1),
3006 VECTOR_SWIZZLE4_RO_DEF("xwzz", 0, 3, 2, 2),
3007 VECTOR_SWIZZLE4_RO_DEF("xwzw", 0, 3, 2, 3),
3008 VECTOR_SWIZZLE3_RO_DEF("xww", 0, 3, 3),
3009 VECTOR_SWIZZLE4_RO_DEF("xwwx", 0, 3, 3, 0),
3010 VECTOR_SWIZZLE4_RO_DEF("xwwy", 0, 3, 3, 1),
3011 VECTOR_SWIZZLE4_RO_DEF("xwwz", 0, 3, 3, 2),
3012 VECTOR_SWIZZLE4_RO_DEF("xwww", 0, 3, 3, 3),
3013 VECTOR_SWIZZLE2_RW_DEF("yx", 1, 0),
3014 VECTOR_SWIZZLE3_RO_DEF("yxx", 1, 0, 0),
3015 VECTOR_SWIZZLE4_RO_DEF("yxxx", 1, 0, 0, 0),
3016 VECTOR_SWIZZLE4_RO_DEF("yxxy", 1, 0, 0, 1),
3017 VECTOR_SWIZZLE4_RO_DEF("yxxz", 1, 0, 0, 2),
3018 VECTOR_SWIZZLE4_RO_DEF("yxxw", 1, 0, 0, 3),
3019 VECTOR_SWIZZLE3_RO_DEF("yxy", 1, 0, 1),
3020 VECTOR_SWIZZLE4_RO_DEF("yxyx", 1, 0, 1, 0),
3021 VECTOR_SWIZZLE4_RO_DEF("yxyy", 1, 0, 1, 1),
3022 VECTOR_SWIZZLE4_RO_DEF("yxyz", 1, 0, 1, 2),
3023 VECTOR_SWIZZLE4_RO_DEF("yxyw", 1, 0, 1, 3),
3024 VECTOR_SWIZZLE3_RW_DEF("yxz", 1, 0, 2),
3025 VECTOR_SWIZZLE4_RO_DEF("yxzx", 1, 0, 2, 0),
3026 VECTOR_SWIZZLE4_RO_DEF("yxzy", 1, 0, 2, 1),
3027 VECTOR_SWIZZLE4_RO_DEF("yxzz", 1, 0, 2, 2),
3028 VECTOR_SWIZZLE4_RW_DEF("yxzw", 1, 0, 2, 3),
3029 VECTOR_SWIZZLE3_RW_DEF("yxw", 1, 0, 3),
3030 VECTOR_SWIZZLE4_RO_DEF("yxwx", 1, 0, 3, 0),
3031 VECTOR_SWIZZLE4_RO_DEF("yxwy", 1, 0, 3, 1),
3032 VECTOR_SWIZZLE4_RW_DEF("yxwz", 1, 0, 3, 2),
3033 VECTOR_SWIZZLE4_RO_DEF("yxww", 1, 0, 3, 3),
3034 VECTOR_SWIZZLE2_RO_DEF("yy", 1, 1),
3035 VECTOR_SWIZZLE3_RO_DEF("yyx", 1, 1, 0),
3036 VECTOR_SWIZZLE4_RO_DEF("yyxx", 1, 1, 0, 0),
3037 VECTOR_SWIZZLE4_RO_DEF("yyxy", 1, 1, 0, 1),
3038 VECTOR_SWIZZLE4_RO_DEF("yyxz", 1, 1, 0, 2),
3039 VECTOR_SWIZZLE4_RO_DEF("yyxw", 1, 1, 0, 3),
3040 VECTOR_SWIZZLE3_RO_DEF("yyy", 1, 1, 1),
3041 VECTOR_SWIZZLE4_RO_DEF("yyyx", 1, 1, 1, 0),
3042 VECTOR_SWIZZLE4_RO_DEF("yyyy", 1, 1, 1, 1),
3043 VECTOR_SWIZZLE4_RO_DEF("yyyz", 1, 1, 1, 2),
3044 VECTOR_SWIZZLE4_RO_DEF("yyyw", 1, 1, 1, 3),
3045 VECTOR_SWIZZLE3_RO_DEF("yyz", 1, 1, 2),
3046 VECTOR_SWIZZLE4_RO_DEF("yyzx", 1, 1, 2, 0),
3047 VECTOR_SWIZZLE4_RO_DEF("yyzy", 1, 1, 2, 1),
3048 VECTOR_SWIZZLE4_RO_DEF("yyzz", 1, 1, 2, 2),
3049 VECTOR_SWIZZLE4_RO_DEF("yyzw", 1, 1, 2, 3),
3050 VECTOR_SWIZZLE3_RO_DEF("yyw", 1, 1, 3),
3051 VECTOR_SWIZZLE4_RO_DEF("yywx", 1, 1, 3, 0),
3052 VECTOR_SWIZZLE4_RO_DEF("yywy", 1, 1, 3, 1),
3053 VECTOR_SWIZZLE4_RO_DEF("yywz", 1, 1, 3, 2),
3054 VECTOR_SWIZZLE4_RO_DEF("yyww", 1, 1, 3, 3),
3055 VECTOR_SWIZZLE2_RW_DEF("yz", 1, 2),
3056 VECTOR_SWIZZLE3_RW_DEF("yzx", 1, 2, 0),
3057 VECTOR_SWIZZLE4_RO_DEF("yzxx", 1, 2, 0, 0),
3058 VECTOR_SWIZZLE4_RO_DEF("yzxy", 1, 2, 0, 1),
3059 VECTOR_SWIZZLE4_RO_DEF("yzxz", 1, 2, 0, 2),
3060 VECTOR_SWIZZLE4_RW_DEF("yzxw", 1, 2, 0, 3),
3061 VECTOR_SWIZZLE3_RO_DEF("yzy", 1, 2, 1),
3062 VECTOR_SWIZZLE4_RO_DEF("yzyx", 1, 2, 1, 0),
3063 VECTOR_SWIZZLE4_RO_DEF("yzyy", 1, 2, 1, 1),
3064 VECTOR_SWIZZLE4_RO_DEF("yzyz", 1, 2, 1, 2),
3065 VECTOR_SWIZZLE4_RO_DEF("yzyw", 1, 2, 1, 3),
3066 VECTOR_SWIZZLE3_RO_DEF("yzz", 1, 2, 2),
3067 VECTOR_SWIZZLE4_RO_DEF("yzzx", 1, 2, 2, 0),
3068 VECTOR_SWIZZLE4_RO_DEF("yzzy", 1, 2, 2, 1),
3069 VECTOR_SWIZZLE4_RO_DEF("yzzz", 1, 2, 2, 2),
3070 VECTOR_SWIZZLE4_RO_DEF("yzzw", 1, 2, 2, 3),
3071 VECTOR_SWIZZLE3_RW_DEF("yzw", 1, 2, 3),
3072 VECTOR_SWIZZLE4_RW_DEF("yzwx", 1, 2, 3, 0),
3073 VECTOR_SWIZZLE4_RO_DEF("yzwy", 1, 2, 3, 1),
3074 VECTOR_SWIZZLE4_RO_DEF("yzwz", 1, 2, 3, 2),
3075 VECTOR_SWIZZLE4_RO_DEF("yzww", 1, 2, 3, 3),
3076 VECTOR_SWIZZLE2_RW_DEF("yw", 1, 3),
3077 VECTOR_SWIZZLE3_RW_DEF("ywx", 1, 3, 0),
3078 VECTOR_SWIZZLE4_RO_DEF("ywxx", 1, 3, 0, 0),
3079 VECTOR_SWIZZLE4_RO_DEF("ywxy", 1, 3, 0, 1),
3080 VECTOR_SWIZZLE4_RW_DEF("ywxz", 1, 3, 0, 2),
3081 VECTOR_SWIZZLE4_RO_DEF("ywxw", 1, 3, 0, 3),
3082 VECTOR_SWIZZLE3_RO_DEF("ywy", 1, 3, 1),
3083 VECTOR_SWIZZLE4_RO_DEF("ywyx", 1, 3, 1, 0),
3084 VECTOR_SWIZZLE4_RO_DEF("ywyy", 1, 3, 1, 1),
3085 VECTOR_SWIZZLE4_RO_DEF("ywyz", 1, 3, 1, 2),
3086 VECTOR_SWIZZLE4_RO_DEF("ywyw", 1, 3, 1, 3),
3087 VECTOR_SWIZZLE3_RW_DEF("ywz", 1, 3, 2),
3088 VECTOR_SWIZZLE4_RW_DEF("ywzx", 1, 3, 2, 0),
3089 VECTOR_SWIZZLE4_RO_DEF("ywzy", 1, 3, 2, 1),
3090 VECTOR_SWIZZLE4_RO_DEF("ywzz", 1, 3, 2, 2),
3091 VECTOR_SWIZZLE4_RO_DEF("ywzw", 1, 3, 2, 3),
3092 VECTOR_SWIZZLE3_RO_DEF("yww", 1, 3, 3),
3093 VECTOR_SWIZZLE4_RO_DEF("ywwx", 1, 3, 3, 0),
3094 VECTOR_SWIZZLE4_RO_DEF("ywwy", 1, 3, 3, 1),
3095 VECTOR_SWIZZLE4_RO_DEF("ywwz", 1, 3, 3, 2),
3096 VECTOR_SWIZZLE4_RO_DEF("ywww", 1, 3, 3, 3),
3097 VECTOR_SWIZZLE2_RW_DEF("zx", 2, 0),
3098 VECTOR_SWIZZLE3_RO_DEF("zxx", 2, 0, 0),
3099 VECTOR_SWIZZLE4_RO_DEF("zxxx", 2, 0, 0, 0),
3100 VECTOR_SWIZZLE4_RO_DEF("zxxy", 2, 0, 0, 1),
3101 VECTOR_SWIZZLE4_RO_DEF("zxxz", 2, 0, 0, 2),
3102 VECTOR_SWIZZLE4_RO_DEF("zxxw", 2, 0, 0, 3),
3103 VECTOR_SWIZZLE3_RW_DEF("zxy", 2, 0, 1),
3104 VECTOR_SWIZZLE4_RO_DEF("zxyx", 2, 0, 1, 0),
3105 VECTOR_SWIZZLE4_RO_DEF("zxyy", 2, 0, 1, 1),
3106 VECTOR_SWIZZLE4_RO_DEF("zxyz", 2, 0, 1, 2),
3107 VECTOR_SWIZZLE4_RW_DEF("zxyw", 2, 0, 1, 3),
3108 VECTOR_SWIZZLE3_RO_DEF("zxz", 2, 0, 2),
3109 VECTOR_SWIZZLE4_RO_DEF("zxzx", 2, 0, 2, 0),
3110 VECTOR_SWIZZLE4_RO_DEF("zxzy", 2, 0, 2, 1),
3111 VECTOR_SWIZZLE4_RO_DEF("zxzz", 2, 0, 2, 2),
3112 VECTOR_SWIZZLE4_RO_DEF("zxzw", 2, 0, 2, 3),
3113 VECTOR_SWIZZLE3_RW_DEF("zxw", 2, 0, 3),
3114 VECTOR_SWIZZLE4_RO_DEF("zxwx", 2, 0, 3, 0),
3115 VECTOR_SWIZZLE4_RW_DEF("zxwy", 2, 0, 3, 1),
3116 VECTOR_SWIZZLE4_RO_DEF("zxwz", 2, 0, 3, 2),
3117 VECTOR_SWIZZLE4_RO_DEF("zxww", 2, 0, 3, 3),
3118 VECTOR_SWIZZLE2_RW_DEF("zy", 2, 1),
3119 VECTOR_SWIZZLE3_RW_DEF("zyx", 2, 1, 0),
3120 VECTOR_SWIZZLE4_RO_DEF("zyxx", 2, 1, 0, 0),
3121 VECTOR_SWIZZLE4_RO_DEF("zyxy", 2, 1, 0, 1),
3122 VECTOR_SWIZZLE4_RO_DEF("zyxz", 2, 1, 0, 2),
3123 VECTOR_SWIZZLE4_RW_DEF("zyxw", 2, 1, 0, 3),
3124 VECTOR_SWIZZLE3_RO_DEF("zyy", 2, 1, 1),
3125 VECTOR_SWIZZLE4_RO_DEF("zyyx", 2, 1, 1, 0),
3126 VECTOR_SWIZZLE4_RO_DEF("zyyy", 2, 1, 1, 1),
3127 VECTOR_SWIZZLE4_RO_DEF("zyyz", 2, 1, 1, 2),
3128 VECTOR_SWIZZLE4_RO_DEF("zyyw", 2, 1, 1, 3),
3129 VECTOR_SWIZZLE3_RO_DEF("zyz", 2, 1, 2),
3130 VECTOR_SWIZZLE4_RO_DEF("zyzx", 2, 1, 2, 0),
3131 VECTOR_SWIZZLE4_RO_DEF("zyzy", 2, 1, 2, 1),
3132 VECTOR_SWIZZLE4_RO_DEF("zyzz", 2, 1, 2, 2),
3133 VECTOR_SWIZZLE4_RO_DEF("zyzw", 2, 1, 2, 3),
3134 VECTOR_SWIZZLE3_RW_DEF("zyw", 2, 1, 3),
3135 VECTOR_SWIZZLE4_RW_DEF("zywx", 2, 1, 3, 0),
3136 VECTOR_SWIZZLE4_RO_DEF("zywy", 2, 1, 3, 1),
3137 VECTOR_SWIZZLE4_RO_DEF("zywz", 2, 1, 3, 2),
3138 VECTOR_SWIZZLE4_RO_DEF("zyww", 2, 1, 3, 3),
3139 VECTOR_SWIZZLE2_RO_DEF("zz", 2, 2),
3140 VECTOR_SWIZZLE3_RO_DEF("zzx", 2, 2, 0),
3141 VECTOR_SWIZZLE4_RO_DEF("zzxx", 2, 2, 0, 0),
3142 VECTOR_SWIZZLE4_RO_DEF("zzxy", 2, 2, 0, 1),
3143 VECTOR_SWIZZLE4_RO_DEF("zzxz", 2, 2, 0, 2),
3144 VECTOR_SWIZZLE4_RO_DEF("zzxw", 2, 2, 0, 3),
3145 VECTOR_SWIZZLE3_RO_DEF("zzy", 2, 2, 1),
3146 VECTOR_SWIZZLE4_RO_DEF("zzyx", 2, 2, 1, 0),
3147 VECTOR_SWIZZLE4_RO_DEF("zzyy", 2, 2, 1, 1),
3148 VECTOR_SWIZZLE4_RO_DEF("zzyz", 2, 2, 1, 2),
3149 VECTOR_SWIZZLE4_RO_DEF("zzyw", 2, 2, 1, 3),
3150 VECTOR_SWIZZLE3_RO_DEF("zzz", 2, 2, 2),
3151 VECTOR_SWIZZLE4_RO_DEF("zzzx", 2, 2, 2, 0),
3152 VECTOR_SWIZZLE4_RO_DEF("zzzy", 2, 2, 2, 1),
3153 VECTOR_SWIZZLE4_RO_DEF("zzzz", 2, 2, 2, 2),
3154 VECTOR_SWIZZLE4_RO_DEF("zzzw", 2, 2, 2, 3),
3155 VECTOR_SWIZZLE3_RO_DEF("zzw", 2, 2, 3),
3156 VECTOR_SWIZZLE4_RO_DEF("zzwx", 2, 2, 3, 0),
3157 VECTOR_SWIZZLE4_RO_DEF("zzwy", 2, 2, 3, 1),
3158 VECTOR_SWIZZLE4_RO_DEF("zzwz", 2, 2, 3, 2),
3159 VECTOR_SWIZZLE4_RO_DEF("zzww", 2, 2, 3, 3),
3160 VECTOR_SWIZZLE2_RW_DEF("zw", 2, 3),
3161 VECTOR_SWIZZLE3_RW_DEF("zwx", 2, 3, 0),
3162 VECTOR_SWIZZLE4_RO_DEF("zwxx", 2, 3, 0, 0),
3163 VECTOR_SWIZZLE4_RW_DEF("zwxy", 2, 3, 0, 1),
3164 VECTOR_SWIZZLE4_RO_DEF("zwxz", 2, 3, 0, 2),
3165 VECTOR_SWIZZLE4_RO_DEF("zwxw", 2, 3, 0, 3),
3166 VECTOR_SWIZZLE3_RW_DEF("zwy", 2, 3, 1),
3167 VECTOR_SWIZZLE4_RW_DEF("zwyx", 2, 3, 1, 0),
3168 VECTOR_SWIZZLE4_RO_DEF("zwyy", 2, 3, 1, 1),
3169 VECTOR_SWIZZLE4_RO_DEF("zwyz", 2, 3, 1, 2),
3170 VECTOR_SWIZZLE4_RO_DEF("zwyw", 2, 3, 1, 3),
3171 VECTOR_SWIZZLE3_RO_DEF("zwz", 2, 3, 2),
3172 VECTOR_SWIZZLE4_RO_DEF("zwzx", 2, 3, 2, 0),
3173 VECTOR_SWIZZLE4_RO_DEF("zwzy", 2, 3, 2, 1),
3174 VECTOR_SWIZZLE4_RO_DEF("zwzz", 2, 3, 2, 2),
3175 VECTOR_SWIZZLE4_RO_DEF("zwzw", 2, 3, 2, 3),
3176 VECTOR_SWIZZLE3_RO_DEF("zww", 2, 3, 3),
3177 VECTOR_SWIZZLE4_RO_DEF("zwwx", 2, 3, 3, 0),
3178 VECTOR_SWIZZLE4_RO_DEF("zwwy", 2, 3, 3, 1),
3179 VECTOR_SWIZZLE4_RO_DEF("zwwz", 2, 3, 3, 2),
3180 VECTOR_SWIZZLE4_RO_DEF("zwww", 2, 3, 3, 3),
3181 VECTOR_SWIZZLE2_RW_DEF("wx", 3, 0),
3182 VECTOR_SWIZZLE3_RO_DEF("wxx", 3, 0, 0),
3183 VECTOR_SWIZZLE4_RO_DEF("wxxx", 3, 0, 0, 0),
3184 VECTOR_SWIZZLE4_RO_DEF("wxxy", 3, 0, 0, 1),
3185 VECTOR_SWIZZLE4_RO_DEF("wxxz", 3, 0, 0, 2),
3186 VECTOR_SWIZZLE4_RO_DEF("wxxw", 3, 0, 0, 3),
3187 VECTOR_SWIZZLE3_RW_DEF("wxy", 3, 0, 1),
3188 VECTOR_SWIZZLE4_RO_DEF("wxyx", 3, 0, 1, 0),
3189 VECTOR_SWIZZLE4_RO_DEF("wxyy", 3, 0, 1, 1),
3190 VECTOR_SWIZZLE4_RW_DEF("wxyz", 3, 0, 1, 2),
3191 VECTOR_SWIZZLE4_RO_DEF("wxyw", 3, 0, 1, 3),
3192 VECTOR_SWIZZLE3_RW_DEF("wxz", 3, 0, 2),
3193 VECTOR_SWIZZLE4_RO_DEF("wxzx", 3, 0, 2, 0),
3194 VECTOR_SWIZZLE4_RW_DEF("wxzy", 3, 0, 2, 1),
3195 VECTOR_SWIZZLE4_RO_DEF("wxzz", 3, 0, 2, 2),
3196 VECTOR_SWIZZLE4_RO_DEF("wxzw", 3, 0, 2, 3),
3197 VECTOR_SWIZZLE3_RO_DEF("wxw", 3, 0, 3),
3198 VECTOR_SWIZZLE4_RO_DEF("wxwx", 3, 0, 3, 0),
3199 VECTOR_SWIZZLE4_RO_DEF("wxwy", 3, 0, 3, 1),
3200 VECTOR_SWIZZLE4_RO_DEF("wxwz", 3, 0, 3, 2),
3201 VECTOR_SWIZZLE4_RO_DEF("wxww", 3, 0, 3, 3),
3202 VECTOR_SWIZZLE2_RW_DEF("wy", 3, 1),
3203 VECTOR_SWIZZLE3_RW_DEF("wyx", 3, 1, 0),
3204 VECTOR_SWIZZLE4_RO_DEF("wyxx", 3, 1, 0, 0),
3205 VECTOR_SWIZZLE4_RO_DEF("wyxy", 3, 1, 0, 1),
3206 VECTOR_SWIZZLE4_RW_DEF("wyxz", 3, 1, 0, 2),
3207 VECTOR_SWIZZLE4_RO_DEF("wyxw", 3, 1, 0, 3),
3208 VECTOR_SWIZZLE3_RO_DEF("wyy", 3, 1, 1),
3209 VECTOR_SWIZZLE4_RO_DEF("wyyx", 3, 1, 1, 0),
3210 VECTOR_SWIZZLE4_RO_DEF("wyyy", 3, 1, 1, 1),
3211 VECTOR_SWIZZLE4_RO_DEF("wyyz", 3, 1, 1, 2),
3212 VECTOR_SWIZZLE4_RO_DEF("wyyw", 3, 1, 1, 3),
3213 VECTOR_SWIZZLE3_RW_DEF("wyz", 3, 1, 2),
3214 VECTOR_SWIZZLE4_RW_DEF("wyzx", 3, 1, 2, 0),
3215 VECTOR_SWIZZLE4_RO_DEF("wyzy", 3, 1, 2, 1),
3216 VECTOR_SWIZZLE4_RO_DEF("wyzz", 3, 1, 2, 2),
3217 VECTOR_SWIZZLE4_RO_DEF("wyzw", 3, 1, 2, 3),
3218 VECTOR_SWIZZLE3_RO_DEF("wyw", 3, 1, 3),
3219 VECTOR_SWIZZLE4_RO_DEF("wywx", 3, 1, 3, 0),
3220 VECTOR_SWIZZLE4_RO_DEF("wywy", 3, 1, 3, 1),
3221 VECTOR_SWIZZLE4_RO_DEF("wywz", 3, 1, 3, 2),
3222 VECTOR_SWIZZLE4_RO_DEF("wyww", 3, 1, 3, 3),
3223 VECTOR_SWIZZLE2_RW_DEF("wz", 3, 2),
3224 VECTOR_SWIZZLE3_RW_DEF("wzx", 3, 2, 0),
3225 VECTOR_SWIZZLE4_RO_DEF("wzxx", 3, 2, 0, 0),
3226 VECTOR_SWIZZLE4_RW_DEF("wzxy", 3, 2, 0, 1),
3227 VECTOR_SWIZZLE4_RO_DEF("wzxz", 3, 2, 0, 2),
3228 VECTOR_SWIZZLE4_RO_DEF("wzxw", 3, 2, 0, 3),
3229 VECTOR_SWIZZLE3_RW_DEF("wzy", 3, 2, 1),
3230 VECTOR_SWIZZLE4_RW_DEF("wzyx", 3, 2, 1, 0),
3231 VECTOR_SWIZZLE4_RO_DEF("wzyy", 3, 2, 1, 1),
3232 VECTOR_SWIZZLE4_RO_DEF("wzyz", 3, 2, 1, 2),
3233 VECTOR_SWIZZLE4_RO_DEF("wzyw", 3, 2, 1, 3),
3234 VECTOR_SWIZZLE3_RO_DEF("wzz", 3, 2, 2),
3235 VECTOR_SWIZZLE4_RO_DEF("wzzx", 3, 2, 2, 0),
3236 VECTOR_SWIZZLE4_RO_DEF("wzzy", 3, 2, 2, 1),
3237 VECTOR_SWIZZLE4_RO_DEF("wzzz", 3, 2, 2, 2),
3238 VECTOR_SWIZZLE4_RO_DEF("wzzw", 3, 2, 2, 3),
3239 VECTOR_SWIZZLE3_RO_DEF("wzw", 3, 2, 3),
3240 VECTOR_SWIZZLE4_RO_DEF("wzwx", 3, 2, 3, 0),
3241 VECTOR_SWIZZLE4_RO_DEF("wzwy", 3, 2, 3, 1),
3242 VECTOR_SWIZZLE4_RO_DEF("wzwz", 3, 2, 3, 2),
3243 VECTOR_SWIZZLE4_RO_DEF("wzww", 3, 2, 3, 3),
3244 VECTOR_SWIZZLE2_RO_DEF("ww", 3, 3),
3245 VECTOR_SWIZZLE3_RO_DEF("wwx", 3, 3, 0),
3246 VECTOR_SWIZZLE4_RO_DEF("wwxx", 3, 3, 0, 0),
3247 VECTOR_SWIZZLE4_RO_DEF("wwxy", 3, 3, 0, 1),
3248 VECTOR_SWIZZLE4_RO_DEF("wwxz", 3, 3, 0, 2),
3249 VECTOR_SWIZZLE4_RO_DEF("wwxw", 3, 3, 0, 3),
3250 VECTOR_SWIZZLE3_RO_DEF("wwy", 3, 3, 1),
3251 VECTOR_SWIZZLE4_RO_DEF("wwyx", 3, 3, 1, 0),
3252 VECTOR_SWIZZLE4_RO_DEF("wwyy", 3, 3, 1, 1),
3253 VECTOR_SWIZZLE4_RO_DEF("wwyz", 3, 3, 1, 2),
3254 VECTOR_SWIZZLE4_RO_DEF("wwyw", 3, 3, 1, 3),
3255 VECTOR_SWIZZLE3_RO_DEF("wwz", 3, 3, 2),
3256 VECTOR_SWIZZLE4_RO_DEF("wwzx", 3, 3, 2, 0),
3257 VECTOR_SWIZZLE4_RO_DEF("wwzy", 3, 3, 2, 1),
3258 VECTOR_SWIZZLE4_RO_DEF("wwzz", 3, 3, 2, 2),
3259 VECTOR_SWIZZLE4_RO_DEF("wwzw", 3, 3, 2, 3),
3260 VECTOR_SWIZZLE3_RO_DEF("www", 3, 3, 3),
3261 VECTOR_SWIZZLE4_RO_DEF("wwwx", 3, 3, 3, 0),
3262 VECTOR_SWIZZLE4_RO_DEF("wwwy", 3, 3, 3, 1),
3263 VECTOR_SWIZZLE4_RO_DEF("wwwz", 3, 3, 3, 2),
3264 VECTOR_SWIZZLE4_RO_DEF("wwww", 3, 3, 3, 3),
3265
3266#undef AXIS_FROM_CHAR
3267#undef SWIZZLE1
3268#undef SWIZZLE2
3269#undef SWIZZLE3
3270#undef SWIZZLE4
3271#undef _SWIZZLE1
3272#undef _SWIZZLE2
3273#undef _SWIZZLE3
3274#undef _SWIZZLE4
3275
3276#undef VECTOR_SWIZZLE2_RW_DEF
3277#undef VECTOR_SWIZZLE2_RO_DEF
3278#undef VECTOR_SWIZZLE3_RW_DEF
3279#undef VECTOR_SWIZZLE3_RO_DEF
3280#undef VECTOR_SWIZZLE4_RW_DEF
3281#undef VECTOR_SWIZZLE4_RO_DEF
3282
3283 {nullptr, nullptr, nullptr, nullptr, nullptr} /* Sentinel */
3284};
3285
3286#ifdef __GNUC__
3287# ifdef __clang__
3288# pragma clang diagnostic pop
3289# else
3290# pragma GCC diagnostic pop
3291# endif
3292#endif
3293
3295
3296/* -------------------------------------------------------------------- */
3299
3300#ifdef __GNUC__
3301# ifdef __clang__
3302# pragma clang diagnostic push
3303# pragma clang diagnostic ignored "-Wcast-function-type"
3304# else
3305# pragma GCC diagnostic push
3306# pragma GCC diagnostic ignored "-Wcast-function-type"
3307# endif
3308#endif
3309
3310static PyMethodDef Vector_methods[] = {
3311 /* Class Methods */
3312 {"Fill", (PyCFunction)C_Vector_Fill, METH_VARARGS | METH_CLASS, C_Vector_Fill_doc},
3313 {"Range", (PyCFunction)C_Vector_Range, METH_VARARGS | METH_CLASS, C_Vector_Range_doc},
3314 {"Linspace", (PyCFunction)C_Vector_Linspace, METH_VARARGS | METH_CLASS, C_Vector_Linspace_doc},
3315 {"Repeat", (PyCFunction)C_Vector_Repeat, METH_VARARGS | METH_CLASS, C_Vector_Repeat_doc},
3316
3317 /* In place only. */
3318 {"zero", (PyCFunction)Vector_zero, METH_NOARGS, Vector_zero_doc},
3319 {"negate", (PyCFunction)Vector_negate, METH_NOARGS, Vector_negate_doc},
3320
3321 /* Operate on original or copy. */
3322 {"normalize", (PyCFunction)Vector_normalize, METH_NOARGS, Vector_normalize_doc},
3323 {"normalized", (PyCFunction)Vector_normalized, METH_NOARGS, Vector_normalized_doc},
3324
3325 {"resize", (PyCFunction)Vector_resize, METH_O, Vector_resize_doc},
3326 {"resized", (PyCFunction)Vector_resized, METH_O, Vector_resized_doc},
3327 {"to_2d", (PyCFunction)Vector_to_2d, METH_NOARGS, Vector_to_2d_doc},
3328 {"resize_2d", (PyCFunction)Vector_resize_2d, METH_NOARGS, Vector_resize_2d_doc},
3329 {"to_3d", (PyCFunction)Vector_to_3d, METH_NOARGS, Vector_to_3d_doc},
3330 {"resize_3d", (PyCFunction)Vector_resize_3d, METH_NOARGS, Vector_resize_3d_doc},
3331 {"to_4d", (PyCFunction)Vector_to_4d, METH_NOARGS, Vector_to_4d_doc},
3332 {"resize_4d", (PyCFunction)Vector_resize_4d, METH_NOARGS, Vector_resize_4d_doc},
3333 {"to_tuple", (PyCFunction)Vector_to_tuple, METH_VARARGS, Vector_to_tuple_doc},
3334 {"to_track_quat", (PyCFunction)Vector_to_track_quat, METH_VARARGS, Vector_to_track_quat_doc},
3335 {"orthogonal", (PyCFunction)Vector_orthogonal, METH_NOARGS, Vector_orthogonal_doc},
3336
3337 /* Operation between 2 or more types. */
3338 {"reflect", (PyCFunction)Vector_reflect, METH_O, Vector_reflect_doc},
3339 {"cross", (PyCFunction)Vector_cross, METH_O, Vector_cross_doc},
3340 {"dot", (PyCFunction)Vector_dot, METH_O, Vector_dot_doc},
3341 {"angle", (PyCFunction)Vector_angle, METH_VARARGS, Vector_angle_doc},
3342 {"angle_signed", (PyCFunction)Vector_angle_signed, METH_VARARGS, Vector_angle_signed_doc},
3343 {"rotation_difference",
3344 (PyCFunction)Vector_rotation_difference,
3345 METH_O,
3346 Vector_rotation_difference_doc},
3347 {"project", (PyCFunction)Vector_project, METH_O, Vector_project_doc},
3348 {"lerp", (PyCFunction)Vector_lerp, METH_VARARGS, Vector_lerp_doc},
3349 {"slerp", (PyCFunction)Vector_slerp, METH_VARARGS, Vector_slerp_doc},
3350 {"rotate", (PyCFunction)Vector_rotate, METH_O, Vector_rotate_doc},
3351
3352 /* Base-math methods. */
3353 {"freeze", (PyCFunction)BaseMathObject_freeze, METH_NOARGS, BaseMathObject_freeze_doc},
3354
3355 {"copy", (PyCFunction)Vector_copy, METH_NOARGS, Vector_copy_doc},
3356 {"__copy__", (PyCFunction)Vector_copy, METH_NOARGS, nullptr},
3357 {"__deepcopy__", (PyCFunction)Vector_deepcopy, METH_VARARGS, nullptr},
3358 {nullptr, nullptr, 0, nullptr},
3359};
3360
3361#ifdef __GNUC__
3362# ifdef __clang__
3363# pragma clang diagnostic pop
3364# else
3365# pragma GCC diagnostic pop
3366# endif
3367#endif
3368
3370
3371/* -------------------------------------------------------------------- */
3378
3379#ifdef MATH_STANDALONE
3380# define Vector_str nullptr
3381#endif
3382
3384 /* Wrap. */
3385 vector_doc,
3386 ".. class:: Vector(seq)\n"
3387 "\n"
3388 " This object gives access to Vectors in Blender.\n"
3389 "\n"
3390 " :arg seq: Components of the vector, must be a sequence of at least two.\n"
3391 " :type seq: Sequence[float]\n");
3392PyTypeObject vector_Type = {
3393 /*ob_base*/ PyVarObject_HEAD_INIT(nullptr, 0)
3394 /*tp_name*/ "Vector",
3395 /*tp_basicsize*/ sizeof(VectorObject),
3396 /*tp_itemsize*/ 0,
3397 /*tp_dealloc*/ (destructor)BaseMathObject_dealloc,
3398 /*tp_vectorcall_offset*/ 0,
3399 /*tp_getattr*/ nullptr,
3400 /*tp_setattr*/ nullptr,
3401 /*tp_as_async*/ nullptr,
3402 /*tp_repr*/ (reprfunc)Vector_repr,
3403 /*tp_as_number*/ &Vector_NumMethods,
3404 /*tp_as_sequence*/ &Vector_SeqMethods,
3405 /*tp_as_mapping*/ &Vector_AsMapping,
3406 /*tp_hash*/ (hashfunc)Vector_hash,
3407 /*tp_call*/ nullptr,
3408 /*tp_str*/ (reprfunc)Vector_str,
3409 /*tp_getattro*/ nullptr,
3410 /*tp_setattro*/ nullptr,
3411 /*tp_as_buffer*/ nullptr,
3412 /*tp_flags*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
3413 /*tp_doc*/ vector_doc,
3414 /*tp_traverse*/ (traverseproc)BaseMathObject_traverse,
3415 /*tp_clear*/ (inquiry)BaseMathObject_clear,
3416 /*tp_richcompare*/ (richcmpfunc)Vector_richcmpr,
3417 /*tp_weaklistoffset*/ 0,
3418 /*tp_iter*/ nullptr,
3419 /*tp_iternext*/ nullptr,
3420 /*tp_methods*/ Vector_methods,
3421 /*tp_members*/ nullptr,
3422 /*tp_getset*/ Vector_getseters,
3423 /*tp_base*/ nullptr,
3424 /*tp_dict*/ nullptr,
3425 /*tp_descr_get*/ nullptr,
3426 /*tp_descr_set*/ nullptr,
3427 /*tp_dictoffset*/ 0,
3428 /*tp_init*/ nullptr,
3429 /*tp_alloc*/ nullptr,
3430 /*tp_new*/ Vector_new,
3431 /*tp_free*/ nullptr,
3432 /*tp_is_gc*/ (inquiry)BaseMathObject_is_gc,
3433 /*tp_bases*/ nullptr,
3434 /*tp_mro*/ nullptr,
3435 /*tp_cache*/ nullptr,
3436 /*tp_subclasses*/ nullptr,
3437 /*tp_weaklist*/ nullptr,
3438 /*tp_del*/ nullptr,
3439 /*tp_version_tag*/ 0,
3440 /*tp_finalize*/ nullptr,
3441 /*tp_vectorcall*/ nullptr,
3442};
3443
3444#ifdef MATH_STANDALONE
3445# undef Vector_str nullptr
3446#endif
3447
3449
3450/* -------------------------------------------------------------------- */
3453
3454PyObject *Vector_CreatePyObject(const float *vec, const int vec_num, PyTypeObject *base_type)
3455{
3457 float *vec_alloc;
3458
3459 if (vec_num < 2) {
3460 PyErr_SetString(PyExc_RuntimeError, "Vector(): invalid size");
3461 return nullptr;
3462 }
3463
3464 vec_alloc = static_cast<float *>(PyMem_Malloc(vec_num * sizeof(float)));
3465 if (UNLIKELY(vec_alloc == nullptr)) {
3466 PyErr_SetString(PyExc_MemoryError,
3467 "Vector(): "
3468 "problem allocating data");
3469 return nullptr;
3470 }
3471
3473 if (self) {
3474 self->vec = vec_alloc;
3475 self->vec_num = vec_num;
3476
3477 /* Initialize callbacks as nullptr. */
3478 self->cb_user = nullptr;
3479 self->cb_type = self->cb_subtype = 0;
3480
3481 if (vec) {
3482 memcpy(self->vec, vec, vec_num * sizeof(float));
3483 }
3484 else { /* new empty */
3485 copy_vn_fl(self->vec, vec_num, 0.0f);
3486 if (vec_num == 4) { /* do the homogeneous thing */
3487 self->vec[3] = 1.0f;
3488 }
3489 }
3491 }
3492 else {
3493 PyMem_Free(vec_alloc);
3494 }
3495
3496 return (PyObject *)self;
3497}
3498
3499PyObject *Vector_CreatePyObject_wrap(float *vec, const int vec_num, PyTypeObject *base_type)
3500{
3502
3503 if (vec_num < 2) {
3504 PyErr_SetString(PyExc_RuntimeError, "Vector(): invalid size");
3505 return nullptr;
3506 }
3507
3509 if (self) {
3510 self->vec_num = vec_num;
3511
3512 /* Initialize callbacks as nullptr. */
3513 self->cb_user = nullptr;
3514 self->cb_type = self->cb_subtype = 0;
3515
3516 self->vec = vec;
3518 }
3519 return (PyObject *)self;
3520}
3521
3522PyObject *Vector_CreatePyObject_cb(PyObject *cb_user, int vec_num, uchar cb_type, uchar cb_subtype)
3523{
3524 VectorObject *self = (VectorObject *)Vector_CreatePyObject(nullptr, vec_num, nullptr);
3525 if (self) {
3526 Py_INCREF(cb_user);
3527 self->cb_user = cb_user;
3528 self->cb_type = cb_type;
3529 self->cb_subtype = cb_subtype;
3530 BLI_assert(!PyObject_GC_IsTracked((PyObject *)self));
3531 PyObject_GC_Track(self);
3532 }
3533
3534 return (PyObject *)self;
3535}
3536
3537PyObject *Vector_CreatePyObject_alloc(float *vec, const int vec_num, PyTypeObject *base_type)
3538{
3540 self = (VectorObject *)Vector_CreatePyObject_wrap(vec, vec_num, base_type);
3541 if (self) {
3543 }
3544
3545 return (PyObject *)self;
3546}
3547
#define BLI_assert(a)
Definition BLI_assert.h:46
A dynamically sized string ADT.
DynStr * BLI_dynstr_new(void) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
Definition BLI_dynstr.cc:36
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.cc:55
double double_round(double x, int ndigits)
Definition math_base.cc: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)
bool stop
Definition WM_types.hh:1016
#define MAX_DIMENSIONS
Definition bgl.cc:767
iter begin(iter)
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
dot(value.rgb, luminance_coefficients)") DEFINE_VALUE("REDUCE(lhs
uint col
VecBase< T, D > reflect(VecOp< T, D >, VecOp< T, D >) RET
#define sqrt
VecBase< float, D > step(VecOp< float, D >, VecOp< float, D >) RET
#define printf(...)
int count
int mathutils_array_parse_alloc(float **array, int array_num_min, PyObject *value, const char *error_prefix)
Definition mathutils.cc:192
int BaseMathObject_is_gc(BaseMathObject *self)
Definition mathutils.cc:727
Py_hash_t mathutils_array_hash(const float *array, size_t array_len)
Definition mathutils.cc:68
void BaseMathObject_dealloc(BaseMathObject *self)
Definition mathutils.cc:705
int EXPP_VectorsAreEqual(const float *vecA, const float *vecB, int size, int floatSteps)
Definition mathutils.cc:489
int mathutils_array_parse(float *array, int array_num_min, int array_num_max, PyObject *value, const char *error_prefix)
Definition mathutils.cc:96
char BaseMathObject_is_valid_doc[]
Definition mathutils.cc:655
char BaseMathObject_is_wrapped_doc[]
Definition mathutils.cc:641
PyObject * BaseMathObject_owner_get(BaseMathObject *self, void *)
Definition mathutils.cc:635
char BaseMathObject_is_frozen_doc[]
Definition mathutils.cc:648
PyObject * mathutils_dynstr_to_py(DynStr *ds)
Definition mathutils.cc:501
int mathutils_any_to_rotmat(float rmat[3][3], PyObject *value, const char *error_prefix)
Definition mathutils.cc:408
PyObject * BaseMathObject_is_frozen_get(BaseMathObject *self, void *)
Definition mathutils.cc:650
PyObject * BaseMathObject_freeze(BaseMathObject *self)
Definition mathutils.cc:669
PyObject * BaseMathObject_is_wrapped_get(BaseMathObject *self, void *)
Definition mathutils.cc:643
char BaseMathObject_owner_doc[]
Definition mathutils.cc:634
char BaseMathObject_freeze_doc[]
Definition mathutils.cc:661
PyObject * BaseMathObject_is_valid_get(BaseMathObject *self, void *)
Definition mathutils.cc:656
int BaseMathObject_clear(BaseMathObject *self)
Definition mathutils.cc:687
int BaseMathObject_traverse(BaseMathObject *self, visitproc visit, void *arg)
Definition mathutils.cc:681
#define BaseMathObject_Prepare_ForResize(_self, error_prefix)
Definition mathutils.hh:159
#define BaseMath_ReadCallback_ForWrite(_self)
Definition mathutils.hh:136
#define BaseMath_ReadIndexCallback(_self, _index)
Definition mathutils.hh:130
#define BaseMath_WriteCallback(_self)
Definition mathutils.hh:128
#define BASE_MATH_NEW(struct_name, root_type, base_type)
Definition mathutils.hh:27
#define BaseMathObject_Prepare_ForHash(_self)
Definition mathutils.hh:151
@ BASE_MATH_FLAG_IS_WRAP
Definition mathutils.hh:37
#define BASE_MATH_FLAG_DEFAULT
Definition mathutils.hh:44
#define BaseMath_Prepare_ForWrite(_self)
Definition mathutils.hh:146
#define BaseMath_ReadCallback(_self)
Definition mathutils.hh:126
#define BaseMath_WriteIndexCallback(_self, _index)
Definition mathutils.hh:132
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)
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
i
Definition text_draw.cc:230