51 i32x4() noexcept :
i32x4(_mm_setzero_si128()) {}
71 operator __m128i () const noexcept {
76 i32x4(_mm_cvtps_epi32(rhs)) {}
78 i32x4 &operator=(f32x4
const &rhs)
noexcept {
79 return *
this = _mm_cvtps_epi32(rhs);
82 operator f32x4 () const noexcept {
83 return _mm_cvtepi32_ps(*
this);
88 _mm_storeu_si128(
reinterpret_cast<__m128i*
>(r.
data()), *
this);
96 template<
typename T, std::enable_if_t<std::is_arithmetic_v<T>,
int> = 0>
98 i32x4(_mm_set1_epi32(narrow_cast<int32_t>(rhs))) {}
104 template<
typename T, std::enable_if_t<std::is_arithmetic_v<T>,
int> = 0>
106 return *
this = _mm_set1_epi32(narrow_cast<int32_t>(rhs));
114 template<
typename T,
typename U,
typename V=int,
typename W=int,
115 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>
116 i32x4(T x, U y, V z=0, W w=0) noexcept :
118 narrow_cast<int32_t>(w),
119 narrow_cast<int32_t>(z),
120 narrow_cast<int32_t>(y),
121 narrow_cast<int32_t>(x)
129 template<
typename T,
typename U,
typename V=int,
typename W=int,
130 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>
131 [[nodiscard]]
static i32x4 point(T x, U y, V z=0, W w=1) noexcept {
132 return i32x4(x, y, z, w);
135 template<
size_t I,
typename T, std::enable_if_t<std::is_arithmetic_v<T>,
int> = 0>
136 i32x4 &set(T rhs)
noexcept {
137 static_assert(I <= 3);
138 return *
this = _mm_insert_epi32(*
this, narrow_cast<int32_t>(rhs), I);
142 int get() const noexcept {
143 static_assert(I <= 3);
144 return _mm_extract_epi32(*
this, I);
147 constexpr size_t size() const noexcept {
return 4; }
149 template<
typename T, std::enable_if_t<std::is_arithmetic_v<T>,
int> = 0>
150 i32x4 &x(T rhs)
noexcept {
return set<0>(rhs); }
152 template<
typename T, std::enable_if_t<std::is_arithmetic_v<T>,
int> = 0>
153 i32x4 &y(T rhs)
noexcept {
return set<1>(rhs); }
155 template<
typename T, std::enable_if_t<std::is_arithmetic_v<T>,
int> = 0>
156 i32x4 &z(T rhs)
noexcept {
return set<2>(rhs); }
158 template<
typename T, std::enable_if_t<std::is_arithmetic_v<T>,
int> = 0>
159 i32x4 &w(T rhs)
noexcept {
return set<3>(rhs); }
161 int x() const noexcept {
return get<0>(); }
162 int y() const noexcept {
return get<1>(); }
163 int z() const noexcept {
return get<2>(); }
164 int w() const noexcept {
return get<3>(); }
165 int width() const noexcept {
return get<0>(); }
166 int height() const noexcept {
return get<1>(); }
168 i32x4 &operator+=(i32x4
const &rhs)
noexcept {
169 return *
this = _mm_add_epi32(*
this, rhs);
172 i32x4 &operator-=(i32x4
const &rhs)
noexcept {
173 return *
this = _mm_sub_epi32(*
this, rhs);
176 i32x4 &operator*=(i32x4
const &rhs)
noexcept {
177 return *
this = _mm_mullo_epi32(*
this, rhs);
181 [[nodiscard]]
friend i32x4 operator+(i32x4
const &lhs, i32x4
const &rhs)
noexcept {
182 return _mm_add_epi32(lhs, rhs);
185 [[nodiscard]]
friend i32x4 operator-(i32x4
const &lhs, i32x4
const &rhs)
noexcept {
186 return _mm_sub_epi32(lhs, rhs);
189 [[nodiscard]]
friend i32x4 operator*(i32x4
const &lhs, i32x4
const &rhs)
noexcept {
190 return _mm_mullo_epi32(lhs, rhs);
193 [[nodiscard]]
friend i32x4 max(i32x4
const &lhs, i32x4
const &rhs)
noexcept {
194 return _mm_max_epi32(lhs, rhs);
197 [[nodiscard]]
friend i32x4 min(i32x4
const &lhs, i32x4
const &rhs)
noexcept {
198 return _mm_min_epi32(lhs, rhs);
201 [[nodiscard]]
friend bool operator==(i32x4
const &lhs, i32x4
const &rhs)
noexcept {
202 ttlet tmp2 = _mm_movemask_epi8(_mm_cmpeq_epi32(lhs, rhs));
203 return tmp2 == 0xffff;
206 [[nodiscard]]
friend bool operator!=(i32x4
const &lhs, i32x4
const &rhs)
noexcept {
207 return !(lhs == rhs);
213 [[nodiscard]]
friend int eq(
i32x4 const &lhs,
i32x4 const &rhs)
noexcept {
214 return _mm_movemask_epi8(_mm_cmpeq_epi32(lhs, rhs));
221 return _mm_movemask_epi8(_mm_cmplt_epi32(lhs, rhs));
228 return _mm_movemask_epi8(_mm_cmpgt_epi32(lhs, rhs));
231 [[nodiscard]]
friend int operator<=(
i32x4 const &lhs,
i32x4 const &rhs)
noexcept {
232 return (~(lhs > rhs)) & 0xffff;
235 [[nodiscard]]
friend int operator>=(i32x4
const &lhs, i32x4
const &rhs)
noexcept {
236 return (~(lhs < rhs)) & 0xffff;
239 [[nodiscard]]
friend std::string to_string(i32x4
const &rhs)
noexcept {
240 return fmt::format(
"({}, {}, {}, {})", rhs.x(), rhs.y(), rhs.z(), rhs.w());
244 return lhs << to_string(rhs);
247 template<std::
size_t I>
248 [[nodiscard]]
friend int get(i32x4
const &rhs)
noexcept {
252 template<
char a,
char b,
char c,
char d>
253 [[nodiscard]]
constexpr static int swizzle_permute_mask() noexcept {
256 case 'x': r |= 0b00'00'00'00;
break;
257 case 'y': r |= 0b00'00'00'01;
break;
258 case 'z': r |= 0b00'00'00'10;
break;
259 case 'w': r |= 0b00'00'00'11;
break;
260 case '0': r |= 0b00'00'00'00;
break;
261 case '1': r |= 0b00'00'00'00;
break;
264 case 'x': r |= 0b00'00'00'00;
break;
265 case 'y': r |= 0b00'00'01'00;
break;
266 case 'z': r |= 0b00'00'10'00;
break;
267 case 'w': r |= 0b00'00'11'00;
break;
268 case '0': r |= 0b00'00'01'00;
break;
269 case '1': r |= 0b00'00'01'00;
break;
272 case 'x': r |= 0b00'00'00'00;
break;
273 case 'y': r |= 0b00'01'00'00;
break;
274 case 'z': r |= 0b00'10'00'00;
break;
275 case 'w': r |= 0b00'11'00'00;
break;
276 case '0': r |= 0b00'10'00'00;
break;
277 case '1': r |= 0b00'10'00'00;
break;
280 case 'x': r |= 0b00'00'00'00;
break;
281 case 'y': r |= 0b01'00'00'00;
break;
282 case 'z': r |= 0b10'00'00'00;
break;
283 case 'w': r |= 0b11'00'00'00;
break;
284 case '0': r |= 0b11'00'00'00;
break;
285 case '1': r |= 0b11'00'00'00;
break;
290 template<
char a,
char b,
char c,
char d>
291 [[nodiscard]] i32x4 swizzle() const noexcept {
292 constexpr int permute_mask = f32x4::swizzle_permute_mask<a,b,c,d>();
296 if constexpr (permute_mask != 0b11'10'01'00) {
297 swizzled = _mm_shuffle_epi32(*
this, permute_mask);
302 if constexpr (a ==
'0' || a ==
'1') {
303 swizzled = _mm_insert_epi32(swizzled, a ==
'0' ? 0 : 1, 0);
305 if constexpr (b ==
'0' || b ==
'1') {
306 swizzled = _mm_insert_epi32(swizzled, b ==
'0' ? 0 : 1, 1);
308 if constexpr (c ==
'0' || c ==
'1') {
309 swizzled = _mm_insert_epi32(swizzled, c ==
'0' ? 0 : 1, 2);
311 if constexpr (d ==
'0' || d ==
'1') {
312 swizzled = _mm_insert_epi32(swizzled, d ==
'0' ? 0 : 1, 3);
318#define SWIZZLE4(name, A, B, C, D)\
319 [[nodiscard]] i32x4 name() const noexcept {\
320 return swizzle<A, B, C, D>();\
323#define SWIZZLE4_GEN3(name, A, B, C)\
324 SWIZZLE4(name ## 0, A, B, C, '0')\
325 SWIZZLE4(name ## 1, A, B, C, '1')\
326 SWIZZLE4(name ## x, A, B, C, 'x')\
327 SWIZZLE4(name ## y, A, B, C, 'y')\
328 SWIZZLE4(name ## z, A, B, C, 'z')\
329 SWIZZLE4(name ## w, A, B, C, 'w')
331#define SWIZZLE4_GEN2(name, A, B)\
332 SWIZZLE4_GEN3(name ## 0, A, B, '0')\
333 SWIZZLE4_GEN3(name ## 1, A, B, '1')\
334 SWIZZLE4_GEN3(name ## x, A, B, 'x')\
335 SWIZZLE4_GEN3(name ## y, A, B, 'y')\
336 SWIZZLE4_GEN3(name ## z, A, B, 'z')\
337 SWIZZLE4_GEN3(name ## w, A, B, 'w')
339#define SWIZZLE4_GEN1(name, A)\
340 SWIZZLE4_GEN2(name ## 0, A, '0')\
341 SWIZZLE4_GEN2(name ## 1, A, '1')\
342 SWIZZLE4_GEN2(name ## x, A, 'x')\
343 SWIZZLE4_GEN2(name ## y, A, 'y')\
344 SWIZZLE4_GEN2(name ## z, A, 'z')\
345 SWIZZLE4_GEN2(name ## w, A, 'w')
347 SWIZZLE4_GEN1(_0,
'0')
348 SWIZZLE4_GEN1(_1, '1')
349 SWIZZLE4_GEN1(x, 'x')
350 SWIZZLE4_GEN1(y, 'y')
351 SWIZZLE4_GEN1(z, 'z')
352 SWIZZLE4_GEN1(w, 'w')
354#define SWIZZLE3(name, A, B, C)\
355 [[nodiscard]] i32x4 name() const noexcept {\
356 return swizzle<A,B,C,'w'>();\
359#define SWIZZLE3_GEN2(name, A, B)\
360 SWIZZLE3(name ## 0, A, B, '0')\
361 SWIZZLE3(name ## 1, A, B, '1')\
362 SWIZZLE3(name ## x, A, B, 'x')\
363 SWIZZLE3(name ## y, A, B, 'y')\
364 SWIZZLE3(name ## z, A, B, 'z')\
365 SWIZZLE3(name ## w, A, B, 'w')
367#define SWIZZLE3_GEN1(name, A)\
368 SWIZZLE3_GEN2(name ## 0, A, '0')\
369 SWIZZLE3_GEN2(name ## 1, A, '1')\
370 SWIZZLE3_GEN2(name ## x, A, 'x')\
371 SWIZZLE3_GEN2(name ## y, A, 'y')\
372 SWIZZLE3_GEN2(name ## z, A, 'z')\
373 SWIZZLE3_GEN2(name ## w, A, 'w')
375 SWIZZLE3_GEN1(_0,
'0')
376 SWIZZLE3_GEN1(_1, '1')
377 SWIZZLE3_GEN1(x, 'x')
378 SWIZZLE3_GEN1(y, 'y')
379 SWIZZLE3_GEN1(z, 'z')
380 SWIZZLE3_GEN1(w, 'w')
382#define SWIZZLE2(name, A, B)\
383 [[nodiscard]] i32x4 name() const noexcept {\
384 return swizzle<A,B,'0','w'>();\
387#define SWIZZLE2_GEN1(name, A)\
388 SWIZZLE2(name ## 0, A, '0')\
389 SWIZZLE2(name ## 1, A, '1')\
390 SWIZZLE2(name ## x, A, 'x')\
391 SWIZZLE2(name ## y, A, 'y')\
392 SWIZZLE2(name ## z, A, 'z')\
393 SWIZZLE2(name ## w, A, 'w')
395 SWIZZLE2_GEN1(_0,
'0')
396 SWIZZLE2_GEN1(_1, '1')
397 SWIZZLE2_GEN1(x, 'x')
398 SWIZZLE2_GEN1(y, 'y')
399 SWIZZLE2_GEN1(z, 'z')
400 SWIZZLE2_GEN1(w, 'w')
i32x4(T x, U y, V z=0, W w=0) noexcept
Create a i32x4 out of 2 to 4 values.
Definition ivec.hpp:116
static i32x4 point(T x, U y, V z=0, W w=1) noexcept
Create a i32x4 out of 2 to 4 values.
Definition ivec.hpp:131