50 tt_force_inline
ivec() noexcept :
ivec(_mm_setzero_si128()) {}
51 tt_force_inline
ivec(
ivec const &rhs) =
default;
52 tt_force_inline
ivec &operator=(
ivec const &rhs) =
default;
53 tt_force_inline
ivec(
ivec &&rhs) =
default;
54 tt_force_inline
ivec &operator=(
ivec &&rhs) =
default;
58 tt_force_inline
ivec(__m128i rhs) noexcept :
70 tt_force_inline
operator __m128i () const noexcept {
74 tt_force_inline
ivec(
vec const &rhs) noexcept :
75 ivec(_mm_cvtps_epi32(rhs)) {}
77 tt_force_inline ivec &operator=(vec
const &rhs)
noexcept {
78 return *
this = _mm_cvtps_epi32(rhs);
81 tt_force_inline
operator vec () const noexcept {
82 return _mm_cvtepi32_ps(*
this);
87 _mm_storeu_si128(
reinterpret_cast<__m128i*
>(r.
data()), *
this);
95 template<
typename T, std::enable_if_t<std::is_arithmetic_v<T>,
int> = 0>
96 explicit tt_force_inline
ivec(T rhs)
noexcept:
97 ivec(_mm_set1_epi32(numeric_cast<int32_t>(rhs))) {}
103 template<
typename T, std::enable_if_t<std::is_arithmetic_v<T>,
int> = 0>
105 return *
this = _mm_set1_epi32(numeric_cast<int32_t>(rhs));
113 template<
typename T,
typename U,
typename V=int,
typename W=int,
114 std::enable_if_t<std::is_arithmetic_v<T> && std::is_arithmetic_v<U> && std::is_arithmetic_v<V> && std::is_arithmetic_v<W>,
int> = 0>
115 tt_force_inline
ivec(T x, U y, V z=0, W w=0) noexcept :
117 numeric_cast<int32_t>(w),
118 numeric_cast<int32_t>(z),
119 numeric_cast<int32_t>(y),
120 numeric_cast<int32_t>(x)
128 template<
typename T,
typename U,
typename V=int,
typename W=int,
129 std::enable_if_t<std::is_arithmetic_v<T> && std::is_arithmetic_v<U> && std::is_arithmetic_v<V> && std::is_arithmetic_v<W>,
int> = 0>
130 [[nodiscard]] tt_force_inline
static ivec point(T x, U y, V z=0, W w=1) noexcept {
131 return ivec(x, y, z, w);
134 template<
size_t I,
typename T, std::enable_if_t<std::is_arithmetic_v<T>,
int> = 0>
135 tt_force_inline
ivec &set(T rhs)
noexcept {
136 static_assert(I <= 3);
137 return *
this = _mm_insert_epi32(*
this, numeric_cast<int32_t>(rhs), I);
141 tt_force_inline
int get() const noexcept {
142 static_assert(I <= 3);
143 return _mm_extract_epi32(*
this, I);
146 constexpr size_t size() const noexcept {
return 4; }
148 template<
typename T, std::enable_if_t<std::is_arithmetic_v<T>,
int> = 0>
149 tt_force_inline ivec &x(T rhs)
noexcept {
return set<0>(rhs); }
151 template<
typename T, std::enable_if_t<std::is_arithmetic_v<T>,
int> = 0>
152 tt_force_inline ivec &y(T rhs)
noexcept {
return set<1>(rhs); }
154 template<
typename T, std::enable_if_t<std::is_arithmetic_v<T>,
int> = 0>
155 tt_force_inline ivec &z(T rhs)
noexcept {
return set<2>(rhs); }
157 template<
typename T, std::enable_if_t<std::is_arithmetic_v<T>,
int> = 0>
158 tt_force_inline ivec &w(T rhs)
noexcept {
return set<3>(rhs); }
160 tt_force_inline
int x() const noexcept {
return get<0>(); }
161 tt_force_inline
int y() const noexcept {
return get<1>(); }
162 tt_force_inline
int z() const noexcept {
return get<2>(); }
163 tt_force_inline
int w() const noexcept {
return get<3>(); }
164 tt_force_inline
int width() const noexcept {
return get<0>(); }
165 tt_force_inline
int height() const noexcept {
return get<1>(); }
167 tt_force_inline ivec &operator+=(ivec
const &rhs)
noexcept {
168 return *
this = _mm_add_epi32(*
this, rhs);
171 tt_force_inline ivec &operator-=(ivec
const &rhs)
noexcept {
172 return *
this = _mm_sub_epi32(*
this, rhs);
175 tt_force_inline ivec &operator*=(ivec
const &rhs)
noexcept {
176 return *
this = _mm_mullo_epi32(*
this, rhs);
180 [[nodiscard]] tt_force_inline
friend ivec operator+(ivec
const &lhs, ivec
const &rhs)
noexcept {
181 return _mm_add_epi32(lhs, rhs);
184 [[nodiscard]] tt_force_inline
friend ivec operator-(ivec
const &lhs, ivec
const &rhs)
noexcept {
185 return _mm_sub_epi32(lhs, rhs);
188 [[nodiscard]] tt_force_inline
friend ivec operator*(ivec
const &lhs, ivec
const &rhs)
noexcept {
189 return _mm_mullo_epi32(lhs, rhs);
192 [[nodiscard]] tt_force_inline
friend ivec max(ivec
const &lhs, ivec
const &rhs)
noexcept {
193 return _mm_max_epi32(lhs, rhs);
196 [[nodiscard]] tt_force_inline
friend ivec min(ivec
const &lhs, ivec
const &rhs)
noexcept {
197 return _mm_min_epi32(lhs, rhs);
200 [[nodiscard]] tt_force_inline
friend bool operator==(ivec
const &lhs, ivec
const &rhs)
noexcept {
201 ttlet tmp2 = _mm_movemask_epi8(_mm_cmpeq_epi32(lhs, rhs));
202 return tmp2 == 0xffff;
205 [[nodiscard]] tt_force_inline
friend bool operator!=(ivec
const &lhs, ivec
const &rhs)
noexcept {
206 return !(lhs == rhs);
212 [[nodiscard]] tt_force_inline
friend int eq(
ivec const &lhs,
ivec const &rhs)
noexcept {
213 return _mm_movemask_epi8(_mm_cmpeq_epi32(lhs, rhs));
220 return _mm_movemask_epi8(_mm_cmplt_epi32(lhs, rhs));
227 return _mm_movemask_epi8(_mm_cmpgt_epi32(lhs, rhs));
230 [[nodiscard]] tt_force_inline
friend int operator<=(
ivec const &lhs,
ivec const &rhs)
noexcept {
231 return (~(lhs > rhs)) & 0xffff;
234 [[nodiscard]] tt_force_inline
friend int operator>=(ivec
const &lhs, ivec
const &rhs)
noexcept {
235 return (~(lhs < rhs)) & 0xffff;
238 [[nodiscard]]
friend std::string to_string(ivec
const &rhs)
noexcept {
239 return fmt::format(
"({}, {}, {}, {})", rhs.x(), rhs.y(), rhs.z(), rhs.w());
243 return lhs << to_string(rhs);
246 template<std::
size_t I>
247 [[nodiscard]] tt_force_inline
friend int get(ivec
const &rhs)
noexcept {
251 template<
char a,
char b,
char c,
char d>
252 [[nodiscard]]
constexpr static int swizzle_permute_mask() noexcept {
255 case 'x': r |= 0b00'00'00'00;
break;
256 case 'y': r |= 0b00'00'00'01;
break;
257 case 'z': r |= 0b00'00'00'10;
break;
258 case 'w': r |= 0b00'00'00'11;
break;
259 case '0': r |= 0b00'00'00'00;
break;
260 case '1': r |= 0b00'00'00'00;
break;
263 case 'x': r |= 0b00'00'00'00;
break;
264 case 'y': r |= 0b00'00'01'00;
break;
265 case 'z': r |= 0b00'00'10'00;
break;
266 case 'w': r |= 0b00'00'11'00;
break;
267 case '0': r |= 0b00'00'01'00;
break;
268 case '1': r |= 0b00'00'01'00;
break;
271 case 'x': r |= 0b00'00'00'00;
break;
272 case 'y': r |= 0b00'01'00'00;
break;
273 case 'z': r |= 0b00'10'00'00;
break;
274 case 'w': r |= 0b00'11'00'00;
break;
275 case '0': r |= 0b00'10'00'00;
break;
276 case '1': r |= 0b00'10'00'00;
break;
279 case 'x': r |= 0b00'00'00'00;
break;
280 case 'y': r |= 0b01'00'00'00;
break;
281 case 'z': r |= 0b10'00'00'00;
break;
282 case 'w': r |= 0b11'00'00'00;
break;
283 case '0': r |= 0b11'00'00'00;
break;
284 case '1': r |= 0b11'00'00'00;
break;
289 template<
char a,
char b,
char c,
char d>
290 [[nodiscard]] tt_force_inline ivec swizzle() const noexcept {
291 constexpr int permute_mask = vec::swizzle_permute_mask<a,b,c,d>();
295 if constexpr (permute_mask != 0b11'10'01'00) {
296 swizzled = _mm_shuffle_epi32(*
this, permute_mask);
301 if constexpr (a ==
'0' || a ==
'1') {
302 swizzled = _mm_insert_epi32(swizzled, a ==
'0' ? 0 : 1, 0);
304 if constexpr (b ==
'0' || b ==
'1') {
305 swizzled = _mm_insert_epi32(swizzled, b ==
'0' ? 0 : 1, 1);
307 if constexpr (c ==
'0' || c ==
'1') {
308 swizzled = _mm_insert_epi32(swizzled, c ==
'0' ? 0 : 1, 2);
310 if constexpr (d ==
'0' || d ==
'1') {
311 swizzled = _mm_insert_epi32(swizzled, d ==
'0' ? 0 : 1, 3);
317#define SWIZZLE4(name, A, B, C, D)\
318 [[nodiscard]] ivec name() const noexcept {\
319 return swizzle<A, B, C, D>();\
322#define SWIZZLE4_GEN3(name, A, B, C)\
323 SWIZZLE4(name ## 0, A, B, C, '0')\
324 SWIZZLE4(name ## 1, A, B, C, '1')\
325 SWIZZLE4(name ## x, A, B, C, 'x')\
326 SWIZZLE4(name ## y, A, B, C, 'y')\
327 SWIZZLE4(name ## z, A, B, C, 'z')\
328 SWIZZLE4(name ## w, A, B, C, 'w')
330#define SWIZZLE4_GEN2(name, A, B)\
331 SWIZZLE4_GEN3(name ## 0, A, B, '0')\
332 SWIZZLE4_GEN3(name ## 1, A, B, '1')\
333 SWIZZLE4_GEN3(name ## x, A, B, 'x')\
334 SWIZZLE4_GEN3(name ## y, A, B, 'y')\
335 SWIZZLE4_GEN3(name ## z, A, B, 'z')\
336 SWIZZLE4_GEN3(name ## w, A, B, 'w')
338#define SWIZZLE4_GEN1(name, A)\
339 SWIZZLE4_GEN2(name ## 0, A, '0')\
340 SWIZZLE4_GEN2(name ## 1, A, '1')\
341 SWIZZLE4_GEN2(name ## x, A, 'x')\
342 SWIZZLE4_GEN2(name ## y, A, 'y')\
343 SWIZZLE4_GEN2(name ## z, A, 'z')\
344 SWIZZLE4_GEN2(name ## w, A, 'w')
346 SWIZZLE4_GEN1(_0,
'0')
347 SWIZZLE4_GEN1(_1, '1')
348 SWIZZLE4_GEN1(x, 'x')
349 SWIZZLE4_GEN1(y, 'y')
350 SWIZZLE4_GEN1(z, 'z')
351 SWIZZLE4_GEN1(w, 'w')
353#define SWIZZLE3(name, A, B, C)\
354 [[nodiscard]] ivec name() const noexcept {\
355 return swizzle<A,B,C,'w'>();\
358#define SWIZZLE3_GEN2(name, A, B)\
359 SWIZZLE3(name ## 0, A, B, '0')\
360 SWIZZLE3(name ## 1, A, B, '1')\
361 SWIZZLE3(name ## x, A, B, 'x')\
362 SWIZZLE3(name ## y, A, B, 'y')\
363 SWIZZLE3(name ## z, A, B, 'z')\
364 SWIZZLE3(name ## w, A, B, 'w')
366#define SWIZZLE3_GEN1(name, A)\
367 SWIZZLE3_GEN2(name ## 0, A, '0')\
368 SWIZZLE3_GEN2(name ## 1, A, '1')\
369 SWIZZLE3_GEN2(name ## x, A, 'x')\
370 SWIZZLE3_GEN2(name ## y, A, 'y')\
371 SWIZZLE3_GEN2(name ## z, A, 'z')\
372 SWIZZLE3_GEN2(name ## w, A, 'w')
374 SWIZZLE3_GEN1(_0,
'0')
375 SWIZZLE3_GEN1(_1, '1')
376 SWIZZLE3_GEN1(x, 'x')
377 SWIZZLE3_GEN1(y, 'y')
378 SWIZZLE3_GEN1(z, 'z')
379 SWIZZLE3_GEN1(w, 'w')
381#define SWIZZLE2(name, A, B)\
382 [[nodiscard]] ivec name() const noexcept {\
383 return swizzle<A,B,'0','w'>();\
386#define SWIZZLE2_GEN1(name, A)\
387 SWIZZLE2(name ## 0, A, '0')\
388 SWIZZLE2(name ## 1, A, '1')\
389 SWIZZLE2(name ## x, A, 'x')\
390 SWIZZLE2(name ## y, A, 'y')\
391 SWIZZLE2(name ## z, A, 'z')\
392 SWIZZLE2(name ## w, A, 'w')
394 SWIZZLE2_GEN1(_0,
'0')
395 SWIZZLE2_GEN1(_1, '1')
396 SWIZZLE2_GEN1(x, 'x')
397 SWIZZLE2_GEN1(y, 'y')
398 SWIZZLE2_GEN1(z, 'z')
399 SWIZZLE2_GEN1(w, 'w')