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