5#include "native_simd_utility.hpp"
6#include "../utility/module.hpp"
31struct native_simd<float16,8> {
32 using value_type = float16;
33 constexpr static size_t size = 8;
34 using register_type = __m128i;
38 native_simd(native_simd
const&)
noexcept =
default;
39 native_simd(native_simd &&) noexcept = default;
40 native_simd &operator=(native_simd const &) noexcept = default;
41 native_simd &operator=(native_simd &&) noexcept = default;
45 native_simd() noexcept : v(_mm_setzero_si128()) {}
47 explicit native_simd(native_simd<float,8>
const &a)
noexcept;
48 native_simd(native_simd<float,4>
const &a, native_simd<float,4>
const &b)
noexcept;
50 [[nodiscard]]
explicit native_simd(register_type
other) noexcept : v(
other) {}
52 [[nodiscard]]
explicit operator register_type () const noexcept {
63 [[nodiscard]] native_simd(value_type a, value_type b = value_type{}, value_type
c = value_type{}, value_type d = value_type{},
64 value_type e = value_type{}, value_type f = value_type{}, value_type g = value_type{},
65 value_type h = value_type{})
noexcept :
66 v(_mm_set_epi16(h.v, g.v, f.v, e.v, d.v,
c.v, b.v, a.v)) {}
68 [[nodiscard]]
explicit native_simd(value_type
const *
other) noexcept : v(_mm_loadu_si128(
reinterpret_cast<register_type
const *
>(
other))) {}
70 void store(value_type *out)
const noexcept
73 _mm_storeu_si128(
reinterpret_cast<register_type *
>(out), v);
76 [[nodiscard]]
explicit native_simd(
void const *
other) noexcept : v(_mm_loadu_si128(
static_cast<register_type
const *
>(
other))) {}
78 void store(
void *out)
const noexcept
81 _mm_storeu_si128(
static_cast<register_type *
>(out), v);
84 [[nodiscard]]
explicit native_simd(std::span<value_type const>
other)
noexcept
87 v = _mm_loadu_si128(
reinterpret_cast<register_type
const *
>(
other.data()));
90 void store(std::span<value_type> out)
const noexcept
93 _mm_storeu_si128(
reinterpret_cast<register_type *
>(out.data()), v);
97 [[nodiscard]]
explicit native_simd(
std::array<value_type, N> other)
noexcept requires (N >= size) : v(_mm_loadu_si128(reinterpret_cast<register_type const *>(
other.data()))) {}
103 _mm_storeu_si128(
reinterpret_cast<register_type *
>(r.data()), v);
121 [[nodiscard]]
static native_simd broadcast(int16_t a)
noexcept
123 return native_simd{_mm_set1_epi16(a)};
139 [[nodiscard]]
static native_simd broadcast(native_simd a)
noexcept
142 return native_simd{_mm_broadcastw_epi16(a.v)};
145 auto tmp = _mm_undefined_si128();
146 tmp = _mm_cmpeq_epi32(tmp, tmp);
147 tmp = _mm_slli_epi32(tmp, 16);
148 tmp = _mm_and_si128(tmp, a.v);
151 tmp = _mm_or_si128(tmp, _mm_slli_epi32(tmp, 16));
154 tmp = _mm_shuffle_epi32(tmp, 0b00'00'00'00);
155 return native_simd{tmp};
161 [[nodiscard]]
static native_simd from_mask(
size_t mask)
noexcept
166 mask & 0b0000'0001 ? value_type{} : value_type::from_uint16_t(0xffff),
167 mask & 0b0000'0010 ? value_type{} : value_type::from_uint16_t(0xffff),
168 mask & 0b0000'0100 ? value_type{} : value_type::from_uint16_t(0xffff),
169 mask & 0b0000'1000 ? value_type{} : value_type::from_uint16_t(0xffff),
170 mask & 0b0001'0000 ? value_type{} : value_type::from_uint16_t(0xffff),
171 mask & 0b0010'0000 ? value_type{} : value_type::from_uint16_t(0xffff),
172 mask & 0b0100'0000 ? value_type{} : value_type::from_uint16_t(0xffff),
173 mask & 0b1000'0000 ? value_type{} : value_type::from_uint16_t(0xffff)};
178 [[nodiscard]]
size_t mask() const noexcept
180 auto tmp = _mm_movemask_epi8(v);
186 return narrow_cast<size_t>(tmp);
190 [[nodiscard]]
friend native_simd operator==(native_simd a, native_simd b)
noexcept
192 return native_simd{_mm_cmpeq_epi16(a.v, b.v)};
195 [[nodiscard]]
friend native_simd
operator!=(native_simd a, native_simd b)
noexcept
200 [[nodiscard]]
friend native_simd operator&(native_simd a, native_simd b)
noexcept
202 return native_simd{_mm_and_si128(a.v, b.v)};
205 [[nodiscard]]
friend native_simd operator|(native_simd a, native_simd b)
noexcept
207 return native_simd{_mm_or_si128(a.v, b.v)};
210 [[nodiscard]]
friend native_simd operator^(native_simd a, native_simd b)
noexcept
212 return native_simd{_mm_xor_si128(a.v, b.v)};
215 [[nodiscard]]
friend native_simd operator~(native_simd a)
noexcept
217 auto ones = _mm_undefined_si128();
218 ones = _mm_cmpeq_epi32(ones, ones);
219 return native_simd{_mm_andnot_si128(a.v, ones)};
228 template<
size_t Mask>
229 [[nodiscard]]
friend native_simd set_zero(native_simd a)
noexcept
231 static_assert(Mask <= 0b1111'1111);
232 hilet mask = from_mask(Mask);
233 return not_and(mask, a);
243 template<
size_t Index>
244 [[nodiscard]]
friend native_simd insert(native_simd a, value_type b)
noexcept
246 static_assert(Index < 4);
247 return native_simd{_mm_insert_epi16(a, b.v, narrow_cast<int>(Index))};
256 template<
size_t Index>
257 [[nodiscard]]
friend value_type extract(native_simd a)
noexcept
259 return std::bit_cast<value_type>(_mm_extract_epi16(a, Index));
270 template<
size_t Mask>
271 [[nodiscard]]
friend native_simd blend(native_simd a, native_simd b)
noexcept
274 return native_simd{_mm_blend_epi16(a, b, Mask)};
276 hilet mask = from_mask(Mask);
277 return not_and(mask, a) | (mask & b);
321 template<fixed_
string SourceElements>
322 [[nodiscard]]
friend native_simd swizzle(native_simd a)
noexcept
324 constexpr auto one_mask = detail::native_swizzle_to_mask<SourceElements, size, '1'>();
325 constexpr auto zero_mask = detail::native_swizzle_to_mask<SourceElements, size, '0'>();
326 constexpr auto number_mask = one_mask | zero_mask;
328 if constexpr (number_mask == 0b11111111) {
330 return swizzle_numbers<SourceElements>();
332 }
else if constexpr (number_mask == 0b00000000) {
334 return permute<SourceElements>(a);
337 }
else if constexpr (number_mask == zero_mask) {
339 hilet ordered = permute<SourceElements>(a);
340 return set_zero<zero_mask>(ordered);
344 hilet ordered = permute<SourceElements>(a);
345 hilet numbers = swizzle_numbers<SourceElements>();
346 return blend<number_mask>(ordered, numbers);
355 [[nodiscard]]
friend native_simd not_and(native_simd a, native_simd b)
noexcept
357 return native_simd{_mm_andnot_si128(a.v, b.v)};
360 template<fixed_
string SourceElements>
361 [[nodiscard]]
static native_simd swizzle_numbers() noexcept
363 constexpr auto one_mask = detail::native_swizzle_to_mask<SourceElements, size, '1'>();
364 constexpr auto zero_mask = detail::native_swizzle_to_mask<SourceElements, size, '0'>();
365 constexpr auto number_mask = one_mask | zero_mask;
366 constexpr auto alpha_mask = ~number_mask & 0b11111111;
368 if constexpr ((zero_mask | alpha_mask) == 0b11111111) {
369 return native_simd{_mm_setzero_si128()};
371 }
else if constexpr ((one_mask | alpha_mask)== 0b11111111) {
372 return native_simd::broadcast(value_type::from_uint16_t(0x3c00));
376 to_bool(one_mask & 0b00000001) ? value_type::from_uint16_t(0x3c00) : value_type{},
377 to_bool(one_mask & 0b00000010) ? value_type::from_uint16_t(0x3c00) : value_type{},
378 to_bool(one_mask & 0b00000100) ? value_type::from_uint16_t(0x3c00) : value_type{},
379 to_bool(one_mask & 0b00001000) ? value_type::from_uint16_t(0x3c00) : value_type{},
380 to_bool(one_mask & 0b00010000) ? value_type::from_uint16_t(0x3c00) : value_type{},
381 to_bool(one_mask & 0b00100000) ? value_type::from_uint16_t(0x3c00) : value_type{},
382 to_bool(one_mask & 0b01000000) ? value_type::from_uint16_t(0x3c00) : value_type{},
383 to_bool(one_mask & 0b10000000) ? value_type::from_uint16_t(0x3c00) : value_type{}
#define hi_axiom(expression,...)
Specify an axiom; an expression that is true.
Definition assert.hpp:238
#define hi_axiom_not_null(expression,...)
Assert if an expression is not nullptr.
Definition assert.hpp:257
#define hilet
Invariant should be the default for variables.
Definition utility.hpp:23
@ other
The gui_event does not have associated data.
DOXYGEN BUG.
Definition algorithm.hpp:13
geometry/margins.hpp
Definition cache.hpp:11