Blender V5.0
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
10
11#include <array>
12#include <ostream>
13#include <type_traits>
14
16#include "BLI_utildefines.h"
17
18namespace blender {
19
20/* clang-format off */
21template<typename T>
22using as_uint_type = std::conditional_t<sizeof(T) == sizeof(uint8_t), uint8_t,
23 std::conditional_t<sizeof(T) == sizeof(uint16_t), uint16_t,
24 std::conditional_t<sizeof(T) == sizeof(uint32_t), uint32_t,
25 std::conditional_t<sizeof(T) == sizeof(uint64_t), uint64_t, void>>>>;
26/* clang-format on */
27
28template<typename T, int Size> struct vec_struct_base {
29 std::array<T, Size> values;
30};
31
32template<typename T> struct vec_struct_base<T, 2> {
33 T x, y;
34};
35
36template<typename T> struct vec_struct_base<T, 3> {
37 T x, y, z;
38};
39
40template<typename T> struct vec_struct_base<T, 4> {
41 T x, y, z, w;
42};
43
44namespace math {
45
46template<typename T> uint64_t vector_hash(const T &vec)
47{
48 BLI_STATIC_ASSERT(T::type_length <= 4, "Longer types need to implement vector_hash themself.");
49 const typename T::uint_type &uvec = *reinterpret_cast<const typename T::uint_type *>(&vec);
51 result = uvec[0] * uint64_t(435109);
52 if constexpr (T::type_length > 1) {
53 result ^= uvec[1] * uint64_t(380867);
54 }
55 if constexpr (T::type_length > 2) {
56 result ^= uvec[2] * uint64_t(1059217);
57 }
58 if constexpr (T::type_length > 3) {
59 result ^= uvec[3] * uint64_t(2002613);
60 }
61 return result;
62}
63
64} // namespace math
65
66template<typename T, int Size> struct VecBase : public vec_struct_base<T, Size> {
67
68 BLI_STATIC_ASSERT(alignof(T) <= sizeof(T),
69 "VecBase is not compatible with aligned type for now.");
70
71/* Workaround issue with template BLI_ENABLE_IF((Size == 2)) not working. */
72#define BLI_ENABLE_IF_VEC(_size, _test) int S = _size, BLI_ENABLE_IF((S _test))
73
74 static constexpr int type_length = Size;
75
76 using base_type = T;
78
79 VecBase() = default;
80
81 template<BLI_ENABLE_IF_VEC(Size, > 1)> explicit VecBase(T value)
82 {
83 for (int i = 0; i < Size; i++) {
84 (*this)[i] = value;
85 }
86 }
87
88 template<typename U, BLI_ENABLE_IF((std::is_convertible_v<U, T>))>
89 explicit VecBase(U value) : VecBase(T(value))
90 {
91 }
92
93 template<BLI_ENABLE_IF_VEC(Size, == 1)> VecBase(T _x)
94 {
95 this->x = _x;
96 }
97
98 template<BLI_ENABLE_IF_VEC(Size, == 2)> VecBase(T _x, T _y)
99 {
100 this->x = _x;
101 this->y = _y;
102 }
103
104 template<BLI_ENABLE_IF_VEC(Size, == 3)> VecBase(T _x, T _y, T _z)
105 {
106 this->x = _x;
107 this->y = _y;
108 this->z = _z;
109 }
110
111 template<BLI_ENABLE_IF_VEC(Size, == 4)> VecBase(T _x, T _y, T _z, T _w)
112 {
113 this->x = _x;
114 this->y = _y;
115 this->z = _z;
116 this->w = _w;
117 }
118
120
121 template<typename U, BLI_ENABLE_IF_VEC(Size, == 3)>
122 constexpr VecBase(const VecBase<U, 2> &xy, T z) : VecBase(T(xy.x), T(xy.y), z)
123 {
124 }
125
126 template<typename U, BLI_ENABLE_IF_VEC(Size, == 3)>
127 constexpr VecBase(T x, const VecBase<U, 2> &yz) : VecBase(x, T(yz.x), T(yz.y))
128 {
129 }
130
131 template<typename U, BLI_ENABLE_IF_VEC(Size, == 4)>
133 {
134 }
135
136 template<typename U, BLI_ENABLE_IF_VEC(Size, == 4)>
138 {
139 }
140
141 template<typename U, typename V, BLI_ENABLE_IF_VEC(Size, == 4)>
143 {
144 }
145
146 template<typename U, BLI_ENABLE_IF_VEC(Size, == 4)>
148 {
149 }
150
151 template<typename U, BLI_ENABLE_IF_VEC(Size, == 4)>
153 {
154 }
155
156 template<typename U, BLI_ENABLE_IF_VEC(Size, == 4)>
158 {
159 }
160
166 template<typename U, int OtherSize, BLI_ENABLE_IF(OtherSize < Size)>
167 VecBase(const VecBase<U, OtherSize> &other) = delete;
168
170
171 template<typename U, int OtherSize, BLI_ENABLE_IF(OtherSize > Size)>
172 explicit VecBase(const VecBase<U, OtherSize> &other)
173 {
174 for (int i = 0; i < Size; i++) {
175 (*this)[i] = T(other[i]);
176 }
177 }
178
180
181 template<BLI_ENABLE_IF_VEC(Size, >= 2)> VecBase<T, 2> xy() const
182 {
183 return *reinterpret_cast<const VecBase<T, 2> *>(this);
184 }
185
186 template<BLI_ENABLE_IF_VEC(Size, >= 3)> VecBase<T, 2> yz() const
187 {
188 return *reinterpret_cast<const VecBase<T, 2> *>(&((*this)[1]));
189 }
190
191 template<BLI_ENABLE_IF_VEC(Size, >= 4)> VecBase<T, 2> zw() const
192 {
193 return *reinterpret_cast<const VecBase<T, 2> *>(&((*this)[2]));
194 }
195
196 template<BLI_ENABLE_IF_VEC(Size, >= 3)> VecBase<T, 3> xyz() const
197 {
198 return *reinterpret_cast<const VecBase<T, 3> *>(this);
199 }
200
201 template<BLI_ENABLE_IF_VEC(Size, >= 4)> VecBase<T, 3> yzw() const
202 {
203 return *reinterpret_cast<const VecBase<T, 3> *>(&((*this)[1]));
204 }
205
206 template<BLI_ENABLE_IF_VEC(Size, >= 4)> VecBase<T, 4> xyzw() const
207 {
208 return *reinterpret_cast<const VecBase<T, 4> *>(this);
209 }
210
211#undef BLI_ENABLE_IF_VEC
212
214
215 /* False positive warning with GCC: it sees array access like [3] but
216 * input is only a 3-element array. But it fails to realize that the
217 * [3] access is within "if constexpr (Size == 4)" check already. */
218#ifdef __GNUC__
219# pragma GCC diagnostic push
220# pragma GCC diagnostic ignored "-Warray-bounds"
221#endif
222
227
228 template<typename U, BLI_ENABLE_IF((std::is_convertible_v<U, T>))> explicit VecBase(const U *ptr)
229 {
231 }
232
233 VecBase(const T (*ptr)[Size]) : VecBase(static_cast<const T *>(ptr[0])) {}
234
235#ifdef __GNUC__
236# pragma GCC diagnostic pop
237#endif
238
240
241 template<typename U> explicit VecBase(const VecBase<U, Size> &vec)
242 {
244 }
245
247
248 operator const T *() const
249 {
250 return reinterpret_cast<const T *>(this);
251 }
252
253 operator T *()
254 {
255 return reinterpret_cast<T *>(this);
256 }
257
259
260 const T &operator[](int index) const
261 {
262 BLI_assert(index >= 0);
263 BLI_assert(index < Size);
264 return reinterpret_cast<const T *>(this)[index];
265 }
266
267 T &operator[](int index)
268 {
269 BLI_assert(index >= 0);
270 BLI_assert(index < Size);
271 return reinterpret_cast<T *>(this)[index];
272 }
273
275
276#define BLI_INT_OP(_T) template<typename U = _T, BLI_ENABLE_IF((std::is_integral_v<U>))>
277
279
280 friend VecBase operator+(const VecBase &a, const VecBase &b)
281 {
283 }
284
285 friend VecBase operator+(const VecBase &a, const T &b)
286 {
288 }
289
290 friend VecBase operator+(const T &a, const VecBase &b)
291 {
293 }
294
299
301 {
303 }
304
305 friend VecBase operator-(const VecBase &a)
306 {
308 }
309
310 friend VecBase operator-(const VecBase &a, const VecBase &b)
311 {
313 }
314
315 friend VecBase operator-(const VecBase &a, const T &b)
316 {
318 }
319
320 friend VecBase operator-(const T &a, const VecBase &b)
321 {
323 }
324
329
331 {
333 }
334
335 friend VecBase operator*(const VecBase &a, const VecBase &b)
336 {
338 }
339
340 template<typename FactorT> friend VecBase operator*(const VecBase &a, FactorT b)
341 {
343 }
344
345 friend VecBase operator*(T a, const VecBase &b)
346 {
348 }
349
354
359
360 friend VecBase operator/(const VecBase &a, const VecBase &b)
361 {
362 for (int i = 0; i < Size; i++) {
363 BLI_assert(b[i] != T(0));
364 }
366 }
367
368 friend VecBase operator/(const VecBase &a, T b)
369 {
370 BLI_assert(b != T(0));
372 }
373
374 friend VecBase operator/(T a, const VecBase &b)
375 {
376 for (int i = 0; i < Size; i++) {
377 BLI_assert(b[i] != T(0));
378 }
380 }
381
383 {
384 BLI_assert(b != T(0));
386 }
387
389 {
390 for (int i = 0; i < Size; i++) {
391 BLI_assert(b[i] != T(0));
392 }
394 }
395
397
398 BLI_INT_OP(T) friend VecBase operator&(const VecBase &a, const VecBase &b)
399 {
401 }
402
404 {
406 }
407
409 {
411 }
412
414 {
416 }
417
419 {
421 }
422
423 BLI_INT_OP(T) friend VecBase operator|(const VecBase &a, const VecBase &b)
424 {
426 }
427
428 BLI_INT_OP(T) friend VecBase operator|(const VecBase &a, T b)
429 {
431 }
432
433 BLI_INT_OP(T) friend VecBase operator|(T a, const VecBase &b)
434 {
436 }
437
439 {
441 }
442
444 {
446 }
447
448 BLI_INT_OP(T) friend VecBase operator^(const VecBase &a, const VecBase &b)
449 {
451 }
452
453 BLI_INT_OP(T) friend VecBase operator^(const VecBase &a, T b)
454 {
456 }
457
458 BLI_INT_OP(T) friend VecBase operator^(T a, const VecBase &b)
459 {
461 }
462
464 {
466 }
467
469 {
471 }
472
473 BLI_INT_OP(T) friend VecBase operator~(const VecBase &a)
474 {
476 }
477
479
480 BLI_INT_OP(T) friend VecBase operator<<(const VecBase &a, const VecBase &b)
481 {
483 }
484
485 BLI_INT_OP(T) friend VecBase operator<<(const VecBase &a, T b)
486 {
488 }
489
491 {
493 }
494
496 {
498 }
499
500 BLI_INT_OP(T) friend VecBase operator>>(const VecBase &a, const VecBase &b)
501 {
503 }
504
505 BLI_INT_OP(T) friend VecBase operator>>(const VecBase &a, T b)
506 {
508 }
509
511 {
513 }
514
516 {
518 }
519
521
522 BLI_INT_OP(T) friend VecBase operator%(const VecBase &a, const VecBase &b)
523 {
524 for (int i = 0; i < Size; i++) {
525 BLI_assert(b[i] != T(0));
526 }
528 }
529
530 BLI_INT_OP(T) friend VecBase operator%(const VecBase &a, T b)
531 {
532 BLI_assert(b != 0);
534 }
535
536 BLI_INT_OP(T) friend VecBase operator%(T a, const VecBase &b)
537 {
538 for (int i = 0; i < Size; i++) {
539 BLI_assert(b[i] != T(0));
540 }
542 }
543
544#undef BLI_INT_OP
545
547
548 friend bool operator==(const VecBase &a, const VecBase &b)
549 {
550 for (int i = 0; i < Size; i++) {
551 if (a[i] != b[i]) {
552 return false;
553 }
554 }
555 return true;
556 }
557
558 friend bool operator!=(const VecBase &a, const VecBase &b)
559 {
560 return !(a == b);
561 }
562
564
565 uint64_t hash() const
566 {
567 return math::vector_hash(*this);
568 }
569
570 friend std::ostream &operator<<(std::ostream &stream, const VecBase &v)
571 {
572 stream << "(";
573 for (int i = 0; i < Size; i++) {
574 stream << v[i];
575 if (i != Size - 1) {
576 stream << ", ";
577 }
578 }
579 stream << ")";
580 return stream;
581 }
582};
583
584namespace math {
585
586template<typename T> struct AssertUnitEpsilon {
588 static constexpr T value = T(0.0002);
589};
590
591} // namespace math
592
596
600
604
608
612
616
621
625
626} // namespace blender
#define BLI_STATIC_ASSERT(a, msg)
Definition BLI_assert.h:83
#define BLI_assert(a)
Definition BLI_assert.h:46
#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)
#define U
ATTR_WARN_UNUSED_RESULT const BMVert * v
unsigned long long int uint64_t
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 float4 operator^(const float4 a, const float4 b)
ccl_device_inline int2 operator&(const int2 a, const int2 b)
Definition math_int2.h:48
ccl_device_inline int2 operator>>(const int2 a, const int i)
Definition math_int2.h:43
ccl_device_inline int4 & operator|=(int4 &a, const int4 b)
Definition math_int4.h:173
ccl_device_inline int4 & operator&=(int4 &a, const int4 b)
Definition math_int4.h:164
ccl_device_inline int4 operator|(const int4 a, const int4 b)
Definition math_int4.h:116
ccl_device_inline int4 & operator>>=(int4 &a, const int32_t b)
Definition math_int4.h:195
ccl_device_inline int4 & operator<<=(int4 &a, const int32_t b)
Definition math_int4.h:191
ccl_device_inline int4 & operator^=(int4 &a, const int4 b)
Definition math_int4.h:182
#define T
GPUState operator~(const GPUState &a)
uint64_t vector_hash(const T &vec)
VecBase< uint32_t, 2 > uint2
blender::VecBase< uint8_t, 2 > uchar2
blender::VecBase< int8_t, 2 > char2
VecBase< float, 1 > float1
VecBase< int32_t, 4 > int4
bool operator!=(const CPPType &a, const CPPType &b)
blender::VecBase< uint8_t, 3 > uchar3
blender::VecBase< int16_t, 3 > short3
VecBase< uint32_t, 4 > uint4
VecBase< double, 2 > double2
std::ostream & operator<<(std::ostream &stream, const eAlpha &space)
Definition BLI_color.cc:15
VecBase< uint32_t, 3 > uint3
blender::VecBase< int16_t, 4 > short4
blender::VecBase< uint8_t, 4 > uchar4
VecBase< float, 4 > float4
blender::VecBase< int8_t, 4 > char4
VecBase< int32_t, 2 > int2
VecBase< float, 2 > float2
VecBase< int32_t, 3 > int3
blender::VecBase< uint16_t, 3 > ushort3
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
VecBase< uint16_t, 2 > ushort2
VecBase< double, 3 > double3
blender::VecBase< int8_t, 3 > char3
blender::VecBase< uint16_t, 4 > ushort4
VecBase< float, 3 > float3
blender::VecBase< int16_t, 2 > short2
VecBase< double, 4 > double4
bool operator==(const CPPType &a, const CPPType &b)
#define hash
Definition noise_c.cc:154
VecBase< as_uint_type< T >, Size > uint_type
constexpr VecBase(const VecBase< U, 2 > &xy, T z)
VecBase()=default
VecBase< T, 4 > xyzw() const
const T & operator[](int index) const
VecBase< T, 3 > yzw() const
friend VecBase operator-(const T &a, 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
VecBase & operator-=(const T &b) &
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)
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(T _x, T _y, T _z, T _w)
VecBase & operator+=(const VecBase &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)
VecBase & operator/=(const VecBase &b) &
friend VecBase operator+(const T &a, const VecBase &b)
VecBase & operator/=(T 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 & operator+=(const T &b) &
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 VecBase &b) &
VecBase & operator*=(T b) &
i
Definition text_draw.cc:230
PointerRNA * ptr
Definition wm_files.cc:4238