33 static_assert(std::has_single_bit(N));
41 std::conditional_t<
sizeof(T) * CHAR_BIT == 8, uint8_t,
42 std::conditional_t<
sizeof(T) * CHAR_BIT == 16, uint16_t,
43 std::conditional_t<
sizeof(T) * CHAR_BIT == 32, uint32_t,
44 std::conditional_t<
sizeof(T) * CHAR_BIT == 64, uint64_t,
void>>>>;
46 using signed_mask_type = std::make_signed_t<mask_type>;
48 [[nodiscard]] hi_force_inline
constexpr static mask_type
to_mask(value_type a)
noexcept
50 return std::bit_cast<mask_type>(a);
53 [[nodiscard]] hi_force_inline
constexpr static signed_mask_type to_signed_mask(value_type a)
noexcept
55 return std::bit_cast<signed_mask_type>(a);
58 template<std::
unsigned_
integral M>
59 [[nodiscard]] hi_force_inline
constexpr static value_type to_value(M a)
noexcept
61 return std::bit_cast<value_type>(
static_cast<mask_type
>(a));
64 template<std::
signed_
integral M>
65 [[nodiscard]] hi_force_inline
constexpr static value_type to_value(M a)
noexcept
67 return std::bit_cast<value_type>(
static_cast<signed_mask_type
>(a));
70 constexpr static value_type _zero_mask = to_value(mask_type{0});
71 constexpr static value_type _ones_mask = to_value(~mask_type{0});
73 [[nodiscard]] hi_force_inline
static array_type undefined()
noexcept
75 if (not std::is_constant_evaluated()) {
76 if constexpr (
requires { intrinsic_type::undefined(); }) {
77 return intrinsic_type::undefined();
84 template<std::same_as<value_type>... Args>
85 [[nodiscard]] hi_force_inline
constexpr static array_type set(Args... args)
noexcept
86 requires(
sizeof...(Args) == N)
88 if (not std::is_constant_evaluated()) {
89 if constexpr (
requires { intrinsic_type::set(args...); }) {
90 return intrinsic_type::set(args...);
93 return array_type{args...};
96 [[nodiscard]] hi_force_inline
constexpr static array_type set(value_type arg)
noexcept
98 if (not std::is_constant_evaluated()) {
99 if constexpr (
requires { intrinsic_type::set(arg); }) {
100 return intrinsic_type::set(arg);
103 auto r = array_type{};
104 std::get<0>(r) = arg;
108 [[nodiscard]] hi_force_inline
constexpr static array_type set_zero()
noexcept
110 if (not std::is_constant_evaluated()) {
111 if constexpr (
requires { intrinsic_type::set_zero(); }) {
112 return intrinsic_type::set_zero();
115 auto r = array_type{};
122 [[nodiscard]] hi_force_inline
constexpr static array_type set_all_ones()
noexcept
124 if (not std::is_constant_evaluated()) {
125 if constexpr (
requires { intrinsic_type::set_all_ones(); }) {
126 return intrinsic_type::set_all_ones();
129 auto r = array_type{};
136 [[nodiscard]] hi_force_inline
constexpr static array_type set_one()
noexcept
138 if (not std::is_constant_evaluated()) {
139 if constexpr (
requires { intrinsic_type::set_one(); }) {
140 return intrinsic_type::set_one();
143 auto r = array_type{};
145 r[i] = value_type{1};
150 [[nodiscard]] hi_force_inline
constexpr static array_type broadcast(value_type a)
noexcept
152 if (not std::is_constant_evaluated()) {
153 if constexpr (
requires { intrinsic_type::broadcast(a); }) {
154 return intrinsic_type::broadcast(a);
157 auto r = array_type{};
164 [[nodiscard]] hi_force_inline
constexpr static array_type broadcast(array_type a)
noexcept
166 if (not std::is_constant_evaluated()) {
167 if constexpr (
requires { intrinsic_type::broadcast(a); }) {
168 return intrinsic_type::broadcast(a);
171 auto r = array_type{};
173 r[i] = std::get<0>(a);
179 [[nodiscard]] hi_force_inline
constexpr static value_type get(array_type a)
noexcept
181 if (not std::is_constant_evaluated()) {
182 if constexpr (
requires { intrinsic_type::template get<I>(a); }) {
183 return intrinsic_type::template get<I>(a);
186 return std::get<I>(a);
193 [[nodiscard]] hi_force_inline
constexpr static array_type
set_mask(
size_t mask)
noexcept
195 if (not std::is_constant_evaluated()) {
196 if constexpr (
requires { intrinsic_type::set_mask(mask); }) {
197 return intrinsic_type::set_mask(mask);
200 auto r = array_type{};
202 r[i] = mask & 1 ? _ones_mask : _zero_mask;
212 [[nodiscard]] hi_force_inline
constexpr static size_t get_mask(array_type a)
noexcept
214 if (not std::is_constant_evaluated()) {
215 if constexpr (
requires { intrinsic_type::get_mask(a); }) {
216 return intrinsic_type::get_mask(a);
221 auto const tmp = to_signed_mask(a[i]) < 0 ?
size_t{1} :
size_t{0};
227 template<array_
generic_convertible_to<value_type> O>
228 [[nodiscard]] hi_force_inline
constexpr static array_type convert(
std::array<O, N> a)
noexcept
230 if (not std::is_constant_evaluated()) {
231 if constexpr (
requires { intrinsic_type::convert(a); }) {
232 return intrinsic_type::convert(a);
236 auto r = array_type{};
237 for (std::size_t i = 0; i != N; ++i) {
238 r[i] =
static_cast<value_type
>(a[i]);
243 [[nodiscard]] hi_force_inline
constexpr static array_type neg(array_type a)
noexcept
245 if (not std::is_constant_evaluated()) {
246 if constexpr (
requires { intrinsic_type::neg(a); }) {
247 return intrinsic_type::neg(a);
251 for (std::size_t i = 0; i != N; ++i) {
257 template<std::
size_t Mask>
258 [[nodiscard]] hi_force_inline
constexpr static array_type neg_mask(array_type a)
noexcept
260 if (not std::is_constant_evaluated()) {
261 if constexpr (
requires { intrinsic_type::template neg_mask<Mask>(a); }) {
262 return intrinsic_type::template neg_mask<Mask>(a);
266 return blend<Mask>(a, neg(a));
269 [[nodiscard]] hi_force_inline
constexpr static array_type inv(array_type a)
noexcept
271 if (not std::is_constant_evaluated()) {
272 if constexpr (
requires { intrinsic_type::inv(a); }) {
273 return intrinsic_type::inv(a);
277 for (std::size_t i = 0; i != N; ++i) {
278 a[i] = to_value(~to_mask(a[i]));
283 [[nodiscard]] hi_force_inline
constexpr static array_type rcp(array_type a)
noexcept
285 if (not std::is_constant_evaluated()) {
286 if constexpr (
requires { intrinsic_type::rcp(a); }) {
287 return intrinsic_type::rcp(a);
291 for (std::size_t i = 0; i != N; ++i) {
292 a[i] = value_type{1} / a[i];
297 [[nodiscard]] hi_force_inline
static array_type sqrt(array_type a)
noexcept
299 if (not std::is_constant_evaluated()) {
300 if constexpr (
requires { intrinsic_type::sqrt(a); }) {
301 return intrinsic_type::sqrt(a);
305 for (std::size_t i = 0; i != N; ++i) {
311 [[nodiscard]] hi_force_inline
static array_type rsqrt(array_type a)
noexcept
313 if (not std::is_constant_evaluated()) {
314 if constexpr (
requires { intrinsic_type::rsqrt(a); }) {
315 return intrinsic_type::rsqrt(a);
319 for (std::size_t i = 0; i != N; ++i) {
325 [[nodiscard]] hi_force_inline
constexpr static array_type abs(array_type a)
noexcept
327 if (not std::is_constant_evaluated()) {
328 if constexpr (
requires { intrinsic_type::abs(a); }) {
329 return intrinsic_type::abs(a);
333 for (std::size_t i = 0; i != N; ++i) {
334 a[i] = std::abs(a[i]);
339 [[nodiscard]] hi_force_inline
constexpr static array_type round(array_type a)
noexcept
341 if (not std::is_constant_evaluated()) {
342 if constexpr (
requires { intrinsic_type::round(a); }) {
343 return intrinsic_type::round(a);
347 for (std::size_t i = 0; i != N; ++i) {
353 [[nodiscard]] hi_force_inline
constexpr static array_type floor(array_type a)
noexcept
355 if (not std::is_constant_evaluated()) {
356 if constexpr (
requires { intrinsic_type::floor(a); }) {
357 return intrinsic_type::floor(a);
361 for (std::size_t i = 0; i != N; ++i) {
367 [[nodiscard]] hi_force_inline
constexpr static array_type ceil(array_type a)
noexcept
369 if (not std::is_constant_evaluated()) {
370 if constexpr (
requires { intrinsic_type::ceil(a); }) {
371 return intrinsic_type::ceil(a);
375 for (std::size_t i = 0; i != N; ++i) {
381 [[nodiscard]] hi_force_inline
constexpr static array_type add(array_type a, array_type b)
noexcept
383 if (not std::is_constant_evaluated()) {
384 if constexpr (
requires { intrinsic_type::add(a, b); }) {
385 return intrinsic_type::add(a, b);
389 for (std::size_t i = 0; i != N; ++i) {
395 [[nodiscard]] hi_force_inline
constexpr static array_type sub(array_type a, array_type b)
noexcept
397 if (not std::is_constant_evaluated()) {
398 if constexpr (
requires { intrinsic_type::sub(a, b); }) {
399 return intrinsic_type::sub(a, b);
403 for (std::size_t i = 0; i != N; ++i) {
413 template<std::
size_t Mask>
414 [[nodiscard]] hi_force_inline
constexpr static array_type
addsub_mask(array_type a, array_type b)
noexcept
416 if (not std::is_constant_evaluated()) {
422 return blend<Mask>(sub(a, b), add(a, b));
425 [[nodiscard]] hi_force_inline
constexpr static array_type mul(array_type a, array_type b)
noexcept
427 if (not std::is_constant_evaluated()) {
428 if constexpr (
requires { intrinsic_type::mul(a, b); }) {
429 return intrinsic_type::mul(a, b);
433 for (std::size_t i = 0; i != N; ++i) {
439 [[nodiscard]] hi_force_inline
constexpr static array_type div(array_type a, array_type b)
noexcept
441 if (not std::is_constant_evaluated()) {
442 if constexpr (
requires { intrinsic_type::div(a, b); }) {
443 return intrinsic_type::div(a, b);
447 for (std::size_t i = 0; i != N; ++i) {
453 [[nodiscard]] hi_force_inline
constexpr static array_type mod(array_type a, array_type b)
noexcept
455 if (not std::is_constant_evaluated()) {
456 if constexpr (
requires { intrinsic_type::mod(a, b); }) {
457 return intrinsic_type::mod(a, b);
461 for (std::size_t i = 0; i != N; ++i) {
462 if constexpr (std::floating_point<T>) {
471 [[nodiscard]] hi_force_inline
constexpr static array_type eq(array_type a, array_type b)
noexcept
473 if (not std::is_constant_evaluated()) {
474 if constexpr (
requires { intrinsic_type::eq(a, b); }) {
475 return intrinsic_type::eq(a, b);
479 for (std::size_t i = 0; i != N; ++i) {
480 a[i] = a[i] == b[i] ? _ones_mask : _zero_mask;
485 [[nodiscard]] hi_force_inline
constexpr static array_type ne(array_type a, array_type b)
noexcept
487 if (not std::is_constant_evaluated()) {
488 if constexpr (
requires { intrinsic_type::ne(a, b); }) {
489 return intrinsic_type::ne(a, b);
493 for (std::size_t i = 0; i != N; ++i) {
494 a[i] = a[i] != b[i] ? _ones_mask : _zero_mask;
499 [[nodiscard]] hi_force_inline
constexpr static array_type lt(array_type a, array_type b)
noexcept
501 if (not std::is_constant_evaluated()) {
502 if constexpr (
requires { intrinsic_type::lt(a, b); }) {
503 return intrinsic_type::lt(a, b);
507 for (std::size_t i = 0; i != N; ++i) {
508 a[i] = a[i] < b[i] ? _ones_mask : _zero_mask;
513 [[nodiscard]] hi_force_inline
constexpr static array_type gt(array_type a, array_type b)
noexcept
515 if (not std::is_constant_evaluated()) {
516 if constexpr (
requires { intrinsic_type::gt(a, b); }) {
517 return intrinsic_type::gt(a, b);
521 for (std::size_t i = 0; i != N; ++i) {
522 a[i] = a[i] > b[i] ? _ones_mask : _zero_mask;
527 [[nodiscard]] hi_force_inline
constexpr static array_type le(array_type a, array_type b)
noexcept
529 if (not std::is_constant_evaluated()) {
530 if constexpr (
requires { intrinsic_type::le(a, b); }) {
531 return intrinsic_type::le(a, b);
535 for (std::size_t i = 0; i != N; ++i) {
536 a[i] = a[i] <= b[i] ? _ones_mask : _zero_mask;
541 [[nodiscard]] hi_force_inline
constexpr static array_type ge(array_type a, array_type b)
noexcept
543 if (not std::is_constant_evaluated()) {
544 if constexpr (
requires { intrinsic_type::ge(a, b); }) {
545 return intrinsic_type::ge(a, b);
549 for (std::size_t i = 0; i != N; ++i) {
550 a[i] = a[i] >= b[i] ? _ones_mask : _zero_mask;
560 [[nodiscard]] hi_force_inline
constexpr static bool test(array_type a, array_type b)
noexcept
562 if (not std::is_constant_evaluated()) {
563 if constexpr (
requires { intrinsic_type::test(a, b); }) {
564 return intrinsic_type::test(a, b);
568 auto r = mask_type{0};
570 r |= to_mask(a[i]) & to_mask(b[i]);
579 [[nodiscard]] hi_force_inline
constexpr static bool all_equal(array_type a, array_type b)
noexcept
582 auto const tmp = ne(a, b);
584 return test(tmp, tmp);
587 [[nodiscard]] hi_force_inline
constexpr static array_type max(array_type a, array_type b)
noexcept
589 if (not std::is_constant_evaluated()) {
590 if constexpr (
requires { intrinsic_type::max(a, b); }) {
591 return intrinsic_type::max(a, b);
595 for (std::size_t i = 0; i != N; ++i) {
601 [[nodiscard]] hi_force_inline
constexpr static array_type min(array_type a, array_type b)
noexcept
603 if (not std::is_constant_evaluated()) {
604 if constexpr (
requires { intrinsic_type::min(a, b); }) {
605 return intrinsic_type::min(a, b);
609 for (std::size_t i = 0; i != N; ++i) {
615 [[nodiscard]] hi_force_inline
constexpr static array_type clamp(array_type v, array_type lo, array_type hi)
noexcept
617 if (not std::is_constant_evaluated()) {
618 if constexpr (
requires { intrinsic_type::clamp(v, lo, hi); }) {
619 return intrinsic_type::clamp(v, lo, hi);
623 for (std::size_t i = 0; i != N; ++i) {
624 v[i] = std::clamp(v[i], lo[i], hi[i]);
629 [[nodiscard]] hi_force_inline
constexpr static array_type _or(array_type a, array_type b)
noexcept
631 if (not std::is_constant_evaluated()) {
632 if constexpr (
requires { intrinsic_type::_or(a, b); }) {
633 return intrinsic_type::_or(a, b);
637 for (std::size_t i = 0; i != N; ++i) {
638 a[i] = to_value(to_mask(a[i]) | to_mask(b[i]));
643 [[nodiscard]] hi_force_inline
constexpr static array_type _and(array_type a, array_type b)
noexcept
645 if (not std::is_constant_evaluated()) {
646 if constexpr (
requires { intrinsic_type::_and(a, b); }) {
647 return intrinsic_type::_and(a, b);
651 for (std::size_t i = 0; i != N; ++i) {
652 a[i] = to_value(to_mask(a[i]) & to_mask(b[i]));
657 [[nodiscard]] hi_force_inline
constexpr static array_type _xor(array_type a, array_type b)
noexcept
659 if (not std::is_constant_evaluated()) {
660 if constexpr (
requires { intrinsic_type::_xor(a, b); }) {
661 return intrinsic_type::_xor(a, b);
665 for (std::size_t i = 0; i != N; ++i) {
666 a[i] = to_value(to_mask(a[i]) ^ to_mask(b[i]));
677 [[nodiscard]] hi_force_inline
constexpr static array_type
andnot(array_type a, array_type b)
noexcept
679 if (not std::is_constant_evaluated()) {
680 if constexpr (
requires { intrinsic_type::andnot(a, b); }) {
681 return intrinsic_type::andnot(a, b);
686 a[i] = to_value(~to_mask(a[i]) & to_mask(b[i]));
691 [[nodiscard]] hi_force_inline
constexpr static array_type sll(array_type a,
unsigned int b)
noexcept
693 if (not std::is_constant_evaluated()) {
694 if constexpr (
requires { intrinsic_type::sll(a, b); }) {
695 return intrinsic_type::sll(a, b);
699 if (b >=
sizeof(value_type) * CHAR_BIT) {
702 for (std::size_t i = 0; i != N; ++i) {
703 a[i] = to_value(to_mask(a[0]) << b);
709 [[nodiscard]] hi_force_inline
constexpr static array_type srl(array_type a,
unsigned int b)
noexcept
711 if (not std::is_constant_evaluated()) {
712 if constexpr (
requires { intrinsic_type::srl(a, b); }) {
713 return intrinsic_type::srl(a, b);
717 if (b >=
sizeof(value_type) * CHAR_BIT) {
720 for (std::size_t i = 0; i != N; ++i) {
721 a[i] = to_value(to_mask(a[0]) >> b);
727 [[nodiscard]] hi_force_inline
constexpr static array_type sra(array_type a,
unsigned int b)
noexcept
729 if (not std::is_constant_evaluated()) {
730 if constexpr (
requires { intrinsic_type::sra(a, b); }) {
731 return intrinsic_type::sra(a, b);
735 if (b >=
sizeof(value_type) * CHAR_BIT) {
736 b =
sizeof(value_type) * CHAR_BIT - 1;
739 for (std::size_t i = 0; i != N; ++i) {
740 a[i] = to_value(to_signed_mask(a[0]) >> b);
748 [[nodiscard]] hi_force_inline
constexpr static array_type
hadd(array_type a, array_type b)
noexcept
750 if (not std::is_constant_evaluated()) {
751 if constexpr (
requires { intrinsic_type::hadd(a, b); }) {
752 return intrinsic_type::hadd(a, b);
756 auto r = array_type{};
759 for (
std::size_t src_i = 0; src_i != N; src_i += 2) {
760 r[dst_i++] = a[src_i] + a[src_i + 1];
763 for (
std::size_t src_i = 0; src_i != N; src_i += 2) {
764 r[dst_i++] = b[src_i] + b[src_i + 1];
769 [[nodiscard]] hi_force_inline
constexpr static array_type hsub(array_type a, array_type b)
noexcept
771 if (not std::is_constant_evaluated()) {
772 if constexpr (
requires { intrinsic_type::hsub(a, b); }) {
773 return intrinsic_type::hsub(a, b);
777 auto r = array_type{};
780 for (std::size_t src_i = 0; src_i != N; src_i += 2) {
781 r[dst_i++] = a[src_i] - a[src_i + 1];
784 for (std::size_t src_i = 0; src_i != N; src_i += 2) {
785 r[dst_i++] = b[src_i] - b[src_i + 1];
790 template<
size_t I,
int First,
int... Rest>
791 hi_force_inline
constexpr static void _shuffle(array_type& r, array_type a)
noexcept
793 static_assert(std::cmp_less(First, N));
795 if constexpr (First < 0) {
796 std::get<I>(r) = std::get<I>(a);
798 std::get<I>(r) = std::get<First>(a);
801 if constexpr (
sizeof...(Rest)) {
802 _shuffle<I + 1, Rest...>(r, a);
806 template<
size_t I,
int First,
int... Rest>
807 [[nodiscard]]
constexpr static bool _have_to_shuffle() noexcept
809 static_assert(std::cmp_less(First, N));
811 if constexpr (First >= 0 and First != I) {
815 if constexpr (
sizeof...(Rest)) {
816 return _have_to_shuffle<I + 1, Rest...>();
822 template<
int... Indices>
823 [[nodiscard]] hi_force_inline
constexpr static array_type shuffle(array_type a)
noexcept
825 static_assert(
sizeof...(Indices) == N);
827 if constexpr (not _have_to_shuffle<0, Indices...>()) {
832 if (not std::is_constant_evaluated()) {
833 if constexpr (
requires { intrinsic_type::template shuffle<Indices...>(a); }) {
834 return intrinsic_type::template shuffle<Indices...>(a);
838 auto r = array_type{};
839 _shuffle<0, Indices...>(r, a);
843 template<
size_t Mask>
844 [[nodiscard]] hi_force_inline
constexpr static array_type blend(array_type a, array_type b)
noexcept
846 if constexpr (Mask == 0) {
849 }
else if constexpr (Mask == (1ULL << N) - 1) {
854 if (not std::is_constant_evaluated()) {
855 if constexpr (
requires { intrinsic_type::template blend<Mask>(a, b); }) {
856 return intrinsic_type::template blend<Mask>(a, b);
861 for (std::size_t i = 0; i != N; ++i) {
862 a[i] = mask & 1 ? b[i] : a[i];
871 hi_warning_ignore_msvc(26494);
872 template<std::derived_from<array_type>... Columns>
873 [[nodiscard]]
constexpr static std::array<array_type, N> transpose(Columns... columns)
noexcept
874 requires(
sizeof...(Columns) == N)
876 if (not std::is_constant_evaluated()) {
877 if constexpr (
requires { intrinsic_type::transpose(columns...); }) {
878 return intrinsic_type::transpose(columns...);
882 auto r = std::array<array_type, N>{};
883 auto f = [&r, &columns... ]<std::size_t... Ints>(std::index_sequence<Ints...>)
885 auto tf = [&r](
auto i,
auto v) {
886 for (std::size_t j = 0; j != N; ++j) {
891 static_cast<void>((tf(Ints, columns) + ...));
893 f(std::make_index_sequence<
sizeof...(columns)>{});
898 template<
size_t I,
int Value,
int First,
int... Rest>
899 constexpr static void _make_swizzle_blend_mask(std::size_t& r)
noexcept
901 if constexpr (First == Value) {
905 if constexpr (
sizeof...(Rest)) {
906 _make_swizzle_blend_mask<I + 1, Value, Rest...>(r);
910 template<
int Value,
int... Indices>
911 [[nodiscard]]
constexpr static std::size_t _make_swizzle_blend_mask() noexcept
913 auto r = std::size_t{0};
914 _make_swizzle_blend_mask<0, Value, Indices...>(r);
928 template<
int... Indices>
929 [[nodiscard]] hi_force_inline
constexpr static array_type
swizzle(array_type a)
noexcept
931 constexpr auto zero_mask = _make_swizzle_blend_mask<-1, Indices...>();
932 constexpr auto one_mask = _make_swizzle_blend_mask<-2, Indices...>();
934 auto tmp = shuffle<Indices...>(a);
935 if constexpr (zero_mask != 0) {
936 tmp = blend<zero_mask>(tmp, set_zero());
938 if constexpr (one_mask != 0) {
939 tmp = blend<one_mask>(tmp, set_one());
944 [[nodiscard]] hi_force_inline
constexpr static array_type sum(array_type a)
noexcept
946 if (not std::is_constant_evaluated()) {
947 if constexpr (
requires { intrinsic_type::sum(a); }) {
948 return intrinsic_type::sum(a);
952 auto r = value_type{0};
953 for (std::size_t i = 0; i != N; ++i) {
959 template<
size_t Mask>
960 [[nodiscard]] hi_force_inline
constexpr static array_type dot(array_type a, array_type b)
noexcept
962 if (not std::is_constant_evaluated()) {
963 if constexpr (
requires { intrinsic_type::template dot<Mask>(a, b); }) {
964 return intrinsic_type::template dot<Mask>(a, b);
968 auto const tmp1 = mul(a, b);
969 auto const tmp2 = blend<Mask>(set_zero(), tmp1);
973 template<
size_t Mask>
974 [[nodiscard]] hi_force_inline
constexpr static array_type hypot(array_type a)
noexcept
976 if (not std::is_constant_evaluated()) {
977 if constexpr (
requires { intrinsic_type::template hypot<Mask>(a); }) {
978 return intrinsic_type::template hypot<Mask>(a);
982 return sqrt(dot<Mask>(a, a));
985 template<
size_t Mask>
986 [[nodiscard]] hi_force_inline
constexpr static array_type rhypot(array_type a)
noexcept
988 if (not std::is_constant_evaluated()) {
989 if constexpr (
requires { intrinsic_type::template rhypot<Mask>(a); }) {
990 return intrinsic_type::template rhypot<Mask>(a);
994 return rsqrt(dot<Mask>(a, a));
997 template<
size_t Mask>
998 [[nodiscard]] hi_force_inline
constexpr static array_type normalize(array_type a)
noexcept
1000 if (not std::is_constant_evaluated()) {
1001 if constexpr (
requires { intrinsic_type::template normalize<Mask>(a); }) {
1002 return intrinsic_type::template normalize<Mask>(a);
1006 return mul(rhypot<Mask>(a), a);