Blender V4.3
BLI_math_vector_types.hh
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2022 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#pragma once
6
11#include <array>
12#include <cmath>
13#include <ostream>
14#include <type_traits>
15
17#include "BLI_unroll.hh"
18#include "BLI_utildefines.h"
19
20namespace blender {
21
22/* clang-format off */
23template<typename T>
24using as_uint_type = std::conditional_t<sizeof(T) == sizeof(uint8_t), uint8_t,
25 std::conditional_t<sizeof(T) == sizeof(uint16_t), uint16_t,
26 std::conditional_t<sizeof(T) == sizeof(uint32_t), uint32_t,
27 std::conditional_t<sizeof(T) == sizeof(uint64_t), uint64_t, void>>>>;
28/* clang-format on */
29
30template<typename T, int Size> struct vec_struct_base {
31 std::array<T, Size> values;
32};
33
34template<typename T> struct vec_struct_base<T, 2> {
35 T x, y;
36};
37
38template<typename T> struct vec_struct_base<T, 3> {
39 T x, y, z;
40};
41
42template<typename T> struct vec_struct_base<T, 4> {
43 T x, y, z, w;
44};
45
46namespace math {
47
48template<typename T> uint64_t vector_hash(const T &vec)
49{
50 BLI_STATIC_ASSERT(T::type_length <= 4, "Longer types need to implement vector_hash themself.");
51 const typename T::uint_type &uvec = *reinterpret_cast<const typename T::uint_type *>(&vec);
53 result = uvec[0] * uint64_t(435109);
54 if constexpr (T::type_length > 1) {
55 result ^= uvec[1] * uint64_t(380867);
56 }
57 if constexpr (T::type_length > 2) {
58 result ^= uvec[2] * uint64_t(1059217);
59 }
60 if constexpr (T::type_length > 3) {
61 result ^= uvec[3] * uint64_t(2002613);
62 }
63 return result;
64}
65
66} // namespace math
67
68template<typename T, int Size> struct VecBase : public vec_struct_base<T, Size> {
69
70 BLI_STATIC_ASSERT(alignof(T) <= sizeof(T),
71 "VecBase is not compatible with aligned type for now.");
72
73/* Workaround issue with template BLI_ENABLE_IF((Size == 2)) not working. */
74#define BLI_ENABLE_IF_VEC(_size, _test) int S = _size, BLI_ENABLE_IF((S _test))
75
76 static constexpr int type_length = Size;
77
78 using base_type = T;
80
81 VecBase() = default;
82
83 template<BLI_ENABLE_IF_VEC(Size, > 1)> explicit VecBase(T value)
84 {
85 for (int i = 0; i < Size; i++) {
86 (*this)[i] = value;
87 }
88 }
89
90 template<typename U, BLI_ENABLE_IF((std::is_convertible_v<U, T>))>
91 explicit VecBase(U value) : VecBase(T(value))
92 {
93 }
94
95 template<BLI_ENABLE_IF_VEC(Size, == 1)> VecBase(T _x)
96 {
97 this->x = _x;
98 }
99
100 template<BLI_ENABLE_IF_VEC(Size, == 2)> VecBase(T _x, T _y)
101 {
102 this->x = _x;
103 this->y = _y;
104 }
105
106 template<BLI_ENABLE_IF_VEC(Size, == 3)> VecBase(T _x, T _y, T _z)
107 {
108 this->x = _x;
109 this->y = _y;
110 this->z = _z;
111 }
112
113 template<BLI_ENABLE_IF_VEC(Size, == 4)> VecBase(T _x, T _y, T _z, T _w)
114 {
115 this->x = _x;
116 this->y = _y;
117 this->z = _z;
118 this->w = _w;
119 }
120
123 template<typename U, BLI_ENABLE_IF_VEC(Size, == 3)>
124 constexpr VecBase(const VecBase<U, 2> &xy, T z) : VecBase(T(xy.x), T(xy.y), z)
125 {
126 }
127
128 template<typename U, BLI_ENABLE_IF_VEC(Size, == 3)>
129 constexpr VecBase(T x, const VecBase<U, 2> &yz) : VecBase(x, T(yz.x), T(yz.y))
130 {
131 }
132
133 template<typename U, BLI_ENABLE_IF_VEC(Size, == 4)>
134 VecBase(VecBase<U, 3> xyz, T w) : VecBase(T(xyz.x), T(xyz.y), T(xyz.z), T(w))
135 {
136 }
137
138 template<typename U, BLI_ENABLE_IF_VEC(Size, == 4)>
139 VecBase(T x, VecBase<U, 3> yzw) : VecBase(T(x), T(yzw.x), T(yzw.y), T(yzw.z))
140 {
141 }
142
143 template<typename U, typename V, BLI_ENABLE_IF_VEC(Size, == 4)>
144 VecBase(VecBase<U, 2> xy, VecBase<V, 2> zw) : VecBase(T(xy.x), T(xy.y), T(zw.x), T(zw.y))
145 {
146 }
147
148 template<typename U, BLI_ENABLE_IF_VEC(Size, == 4)>
149 VecBase(VecBase<U, 2> xy, T z, T w) : VecBase(T(xy.x), T(xy.y), T(z), T(w))
150 {
151 }
152
153 template<typename U, BLI_ENABLE_IF_VEC(Size, == 4)>
154 VecBase(T x, VecBase<U, 2> yz, T w) : VecBase(T(x), T(yz.x), T(yz.y), T(w))
155 {
156 }
157
158 template<typename U, BLI_ENABLE_IF_VEC(Size, == 4)>
159 VecBase(T x, T y, VecBase<U, 2> zw) : VecBase(T(x), T(y), T(zw.x), T(zw.y))
160 {
161 }
162
165 template<typename U, int OtherSize, BLI_ENABLE_IF(OtherSize > Size)>
166 explicit VecBase(const VecBase<U, OtherSize> &other)
167 {
168 for (int i = 0; i < Size; i++) {
169 (*this)[i] = T(other[i]);
170 }
171 }
172
175 template<BLI_ENABLE_IF_VEC(Size, >= 2)> VecBase<T, 2> xy() const
176 {
177 return *reinterpret_cast<const VecBase<T, 2> *>(this);
178 }
179
180 template<BLI_ENABLE_IF_VEC(Size, >= 3)> VecBase<T, 2> yz() const
181 {
182 return *reinterpret_cast<const VecBase<T, 2> *>(&((*this)[1]));
183 }
184
185 template<BLI_ENABLE_IF_VEC(Size, >= 4)> VecBase<T, 2> zw() const
186 {
187 return *reinterpret_cast<const VecBase<T, 2> *>(&((*this)[2]));
188 }
189
190 template<BLI_ENABLE_IF_VEC(Size, >= 3)> VecBase<T, 3> xyz() const
191 {
192 return *reinterpret_cast<const VecBase<T, 3> *>(this);
193 }
194
195 template<BLI_ENABLE_IF_VEC(Size, >= 4)> VecBase<T, 3> yzw() const
196 {
197 return *reinterpret_cast<const VecBase<T, 3> *>(&((*this)[1]));
198 }
199
200 template<BLI_ENABLE_IF_VEC(Size, >= 4)> VecBase<T, 4> xyzw() const
201 {
202 return *reinterpret_cast<const VecBase<T, 4> *>(this);
203 }
204
205#undef BLI_ENABLE_IF_VEC
206
209 /* False positive warning with GCC: it sees array access like [3] but
210 * input is only a 3-element array. But it fails to realize that the
211 * [3] access is within "if constexpr (Size == 4)" check already. */
212#ifdef __GNUC__
213# pragma GCC diagnostic push
214# pragma GCC diagnostic ignored "-Warray-bounds"
215#endif
216
221
222 template<typename U, BLI_ENABLE_IF((std::is_convertible_v<U, T>))> explicit VecBase(const U *ptr)
223 {
225 }
226
227 VecBase(const T (*ptr)[Size]) : VecBase(static_cast<const T *>(ptr[0])) {}
228
229#ifdef __GNUC__
230# pragma GCC diagnostic pop
231#endif
232
235 template<typename U> explicit VecBase(const VecBase<U, Size> &vec)
236 {
238 }
239
242 operator const T *() const
243 {
244 return reinterpret_cast<const T *>(this);
245 }
246
247 operator T *()
248 {
249 return reinterpret_cast<T *>(this);
250 }
251
254 const T &operator[](int index) const
255 {
256 BLI_assert(index >= 0);
257 BLI_assert(index < Size);
258 return reinterpret_cast<const T *>(this)[index];
259 }
260
261 T &operator[](int index)
262 {
263 BLI_assert(index >= 0);
264 BLI_assert(index < Size);
265 return reinterpret_cast<T *>(this)[index];
266 }
267
270#define BLI_INT_OP(_T) template<typename U = _T, BLI_ENABLE_IF((std::is_integral_v<U>))>
271
274 friend VecBase operator+(const VecBase &a, const VecBase &b)
275 {
277 }
278
279 friend VecBase operator+(const VecBase &a, const T &b)
280 {
282 }
283
284 friend VecBase operator+(const T &a, const VecBase &b)
285 {
287 }
288
293
298
299 friend VecBase operator-(const VecBase &a)
300 {
302 }
303
304 friend VecBase operator-(const VecBase &a, const VecBase &b)
305 {
307 }
308
309 friend VecBase operator-(const VecBase &a, const T &b)
310 {
312 }
313
314 friend VecBase operator-(const T &a, const VecBase &b)
315 {
317 }
318
323
328
329 friend VecBase operator*(const VecBase &a, const VecBase &b)
330 {
332 }
333
334 template<typename FactorT> friend VecBase operator*(const VecBase &a, FactorT b)
335 {
337 }
338
339 friend VecBase operator*(T a, const VecBase &b)
340 {
342 }
343
348
353
354 friend VecBase operator/(const VecBase &a, const VecBase &b)
355 {
356 for (int i = 0; i < Size; i++) {
357 BLI_assert(b[i] != T(0));
358 }
360 }
361
362 friend VecBase operator/(const VecBase &a, T b)
363 {
364 BLI_assert(b != T(0));
366 }
367
368 friend VecBase operator/(T a, const VecBase &b)
369 {
370 for (int i = 0; i < Size; i++) {
371 BLI_assert(b[i] != T(0));
372 }
374 }
375
381
383 {
384 for (int i = 0; i < Size; i++) {
385 BLI_assert(b[i] != T(0));
386 }
388 }
389
392 BLI_INT_OP(T) friend VecBase operator&(const VecBase &a, const VecBase &b)
393 {
395 }
396
397 BLI_INT_OP(T) friend VecBase operator&(const VecBase &a, T b)
398 {
400 }
401
402 BLI_INT_OP(T) friend VecBase operator&(T a, const VecBase &b)
403 {
405 }
406
408 {
410 }
411
413 {
415 }
416
417 BLI_INT_OP(T) friend VecBase operator|(const VecBase &a, const VecBase &b)
418 {
420 }
421
422 BLI_INT_OP(T) friend VecBase operator|(const VecBase &a, T b)
423 {
425 }
426
427 BLI_INT_OP(T) friend VecBase operator|(T a, const VecBase &b)
428 {
430 }
431
433 {
435 }
436
438 {
440 }
441
442 BLI_INT_OP(T) friend VecBase operator^(const VecBase &a, const VecBase &b)
443 {
445 }
446
447 BLI_INT_OP(T) friend VecBase operator^(const VecBase &a, T b)
448 {
450 }
451
452 BLI_INT_OP(T) friend VecBase operator^(T a, const VecBase &b)
453 {
455 }
456
458 {
460 }
461
463 {
465 }
466
467 BLI_INT_OP(T) friend VecBase operator~(const VecBase &a)
468 {
470 }
471
474 BLI_INT_OP(T) friend VecBase operator<<(const VecBase &a, const VecBase &b)
475 {
477 }
478
479 BLI_INT_OP(T) friend VecBase operator<<(const VecBase &a, T b)
480 {
482 }
483
485 {
487 }
488
490 {
492 }
493
494 BLI_INT_OP(T) friend VecBase operator>>(const VecBase &a, const VecBase &b)
495 {
497 }
498
499 BLI_INT_OP(T) friend VecBase operator>>(const VecBase &a, T b)
500 {
502 }
503
505 {
507 }
508
510 {
512 }
513
516 BLI_INT_OP(T) friend VecBase operator%(const VecBase &a, const VecBase &b)
517 {
518 for (int i = 0; i < Size; i++) {
519 BLI_assert(b[i] != T(0));
520 }
522 }
523
524 BLI_INT_OP(T) friend VecBase operator%(const VecBase &a, T b)
525 {
526 BLI_assert(b != 0);
528 }
529
530 BLI_INT_OP(T) friend VecBase operator%(T a, const VecBase &b)
531 {
532 for (int i = 0; i < Size; i++) {
533 BLI_assert(b[i] != T(0));
534 }
536 }
537
538#undef BLI_INT_OP
539
542 friend bool operator==(const VecBase &a, const VecBase &b)
543 {
544 for (int i = 0; i < Size; i++) {
545 if (a[i] != b[i]) {
546 return false;
547 }
548 }
549 return true;
550 }
551
552 friend bool operator!=(const VecBase &a, const VecBase &b)
553 {
554 return !(a == b);
555 }
556
559 uint64_t hash() const
560 {
561 return math::vector_hash(*this);
562 }
563
564 friend std::ostream &operator<<(std::ostream &stream, const VecBase &v)
565 {
566 stream << "(";
567 for (int i = 0; i < Size; i++) {
568 stream << v[i];
569 if (i != Size - 1) {
570 stream << ", ";
571 }
572 }
573 stream << ")";
574 return stream;
575 }
576};
577
578namespace math {
579
580template<typename T> struct AssertUnitEpsilon {
582 static constexpr T value = T(0.0002);
583};
584
585} // namespace math
586
590
593
597
601
605
609
614
618
619} // namespace blender
#define BLI_STATIC_ASSERT(a, msg)
Definition BLI_assert.h:87
#define BLI_assert(a)
Definition BLI_assert.h:50
#define BLI_INT_OP(_T)
#define BLI_UNROLL_MATH_VEC_OP_INIT_INDEX(a)
#define BLI_UNROLL_MATH_VEC_OP_VEC_SCALAR(op, a, b)
#define BLI_UNROLL_MATH_VEC_OP_VEC(op, a)
#define BLI_UNROLL_MATH_VEC_OP_SCALAR_VEC(op, a, b)
#define BLI_UNROLL_MATH_VEC_OP_VEC_VEC(op, a, b)
#define BLI_UNROLL_MATH_VEC_OP_ASSIGN_SCALAR(op, b)
#define BLI_UNROLL_MATH_VEC_OP_INIT_VECTOR(a)
#define BLI_UNROLL_MATH_VEC_OP_ASSIGN_VEC(op, b)
ATTR_WARN_UNUSED_RESULT const BMVert * v
unsigned int U
Definition btGjkEpa3.h:78
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
ccl_device_inline const float4 operator^(const float4 a, const float4 b)
ccl_device_inline int4 operator>>(const int4 a, int i)
Definition math_int4.h:44
ccl_device_inline int4 & operator|=(int4 &a, const int4 b)
Definition math_int4.h:170
ccl_device_inline int4 & operator&=(int4 &a, const int4 b)
Definition math_int4.h:161
ccl_device_inline int4 operator|(const int4 a, const int4 b)
Definition math_int4.h:113
ccl_device_inline int4 & operator>>=(int4 &a, const int32_t b)
Definition math_int4.h:192
ccl_device_inline int4 & operator<<=(int4 &a, const int32_t b)
Definition math_int4.h:188
ccl_device_inline int4 & operator^=(int4 &a, const int4 b)
Definition math_int4.h:179
ccl_device_inline int4 operator&(const int4 a, const int4 b)
Definition math_int4.h:104
#define T
GPUState operator~(const GPUState &a)
uint64_t vector_hash(const T &vec)
constexpr bool operator!=(StringRef a, StringRef b)
constexpr bool operator==(StringRef a, StringRef b)
std::ostream & operator<<(std::ostream &stream, const eAlpha &space)
Definition BLI_color.cc:11
std::conditional_t< sizeof(T)==sizeof(uint8_t), uint8_t, std::conditional_t< sizeof(T)==sizeof(uint16_t), uint16_t, std::conditional_t< sizeof(T)==sizeof(uint32_t), uint32_t, std::conditional_t< sizeof(T)==sizeof(uint64_t), uint64_t, void > > > > as_uint_type
#define hash
Definition noise.c:154
unsigned short uint16_t
Definition stdint.h:79
unsigned int uint32_t
Definition stdint.h:80
unsigned char uint8_t
Definition stdint.h:78
unsigned __int64 uint64_t
Definition stdint.h:90
constexpr VecBase(const VecBase< U, 2 > &xy, T z)
VecBase()=default
VecBase< T, 4 > xyzw() const
VecBase< T, 2 > zw() const
const T & operator[](int index) const
VecBase< T, 3 > yzw() const
friend VecBase operator-(const T &a, const VecBase &b)
VecBase & operator+=(const VecBase &b)
friend VecBase operator-(const VecBase &a, const VecBase &b)
VecBase(const VecBase< U, OtherSize > &other)
BLI_STATIC_ASSERT(alignof(T)<=sizeof(T), "VecBase is not compatible with aligned type for now.")
friend VecBase operator/(const VecBase &a, T b)
friend VecBase operator*(const VecBase &a, FactorT b)
static constexpr int type_length
friend VecBase operator*(const VecBase &a, const VecBase &b)
friend VecBase operator/(T a, const VecBase &b)
VecBase(T _x, T _y, T _z)
VecBase(T x, VecBase< U, 2 > yz, T w)
VecBase< T, 2 > xy() const
friend VecBase operator/(const VecBase &a, const VecBase &b)
VecBase< T, 3 > xyz() const
constexpr VecBase(T x, const VecBase< U, 2 > &yz)
friend VecBase operator+(const VecBase &a, const VecBase &b)
VecBase(T x, VecBase< U, 3 > yzw)
VecBase & operator/=(const VecBase &b)
VecBase & operator-=(const VecBase &b)
VecBase(T _x, T _y, T _z, T _w)
VecBase & operator+=(const T &b)
VecBase(const VecBase< U, Size > &vec)
VecBase(const T(*ptr)[Size])
friend VecBase operator-(const VecBase &a)
VecBase(T x, T y, VecBase< U, 2 > zw)
friend VecBase operator+(const T &a, const VecBase &b)
friend VecBase operator+(const VecBase &a, const T &b)
friend VecBase operator*(T a, const VecBase &b)
VecBase(VecBase< U, 2 > xy, T z, T w)
VecBase & operator*=(const VecBase &b)
VecBase< T, 2 > yz() const
friend VecBase operator-(const VecBase &a, const T &b)
VecBase(VecBase< U, 3 > xyz, T w)
BLI_INT_OP(T) friend VecBase operator&(T a
VecBase(VecBase< U, 2 > xy, VecBase< V, 2 > zw)
VecBase & operator-=(const T &b)
PointerRNA * ptr
Definition wm_files.cc:4126