25#ifndef _GLIBCXX_SIMD_DETAILS_H
26#define _GLIBCXX_SIMD_DETAILS_H 1
29#pragma GCC system_header
32#if __cplusplus >= 202400L
47#error "<simd> is not supported for CHAR_BIT != 8"
51#pragma GCC diagnostic push
52#pragma GCC diagnostic ignored "-Wpsabi"
54#if defined __x86_64__ || defined __i386__
60#ifndef _GLIBCXX_SIMD_NOEXCEPT
64#define _GLIBCXX_SIMD_NOEXCEPT noexcept
67#define _GLIBCXX_SIMD_TOSTRING_IMPL(x) #x
68#define _GLIBCXX_SIMD_TOSTRING(x) _GLIBCXX_SIMD_TOSTRING_IMPL(x)
71#define __glibcxx_simd_precondition(expr, msg, ...) \
72 __glibcxx_assert(expr)
74namespace std _GLIBCXX_VISIBILITY(default)
76_GLIBCXX_BEGIN_NAMESPACE_VERSION
80 template <
typename _Tp>
82 __iota = [] {
static_assert(
false,
"invalid __iota specialization"); }();
86 template <
typename _Tp>
87 concept __vectorizable_scalar
88 = same_as<remove_cv_t<_Tp>, _Tp>
89#ifdef __STDCPP_BFLOAT16_T__
90 && !same_as<_Tp, __gnu_cxx::__bfloat16_t>
92 && ((integral<_Tp> &&
sizeof(_Tp) <=
sizeof(0ULL) && !same_as<_Tp, bool>)
93 || (floating_point<_Tp> &&
sizeof(_Tp) <=
sizeof(double)));
96 template <
typename _Tp>
97 concept __vectorizable = __vectorizable_scalar<_Tp>;
102 enum class _AbiVariant :
unsigned long long
105 _MaskVariants = 0x0f,
111 consteval _AbiVariant
112 __filter_abi_variant(_AbiVariant __in, same_as<_AbiVariant>
auto... __to_keep)
115 return static_cast<_AbiVariant
>(
static_cast<_Up
>(__in) & (
static_cast<_Up
>(__to_keep) | ...));
121 struct _InvalidInteger
129 template <
size_t _Bytes>
131 =
decltype([]
consteval {
132 if constexpr (
sizeof(
signed char) == _Bytes)
133 return static_cast<signed char>(0);
134 else if constexpr (
sizeof(
signed short) == _Bytes)
135 return static_cast<signed short>(0);
136 else if constexpr (
sizeof(
signed int) == _Bytes)
137 return static_cast<signed int>(0);
138 else if constexpr (
sizeof(
signed long long) == _Bytes)
139 return static_cast<signed long long>(0);
141 return _InvalidInteger();
147 template <
size_t _Bytes>
155 template <
typename _Tp>
157 __div_ceil(_Tp __x, _Tp __y)
158 {
return (__x + __y - 1) / __y; }
163 template <
int _NBits>
164 requires (_NBits > 0 && _NBits <= numeric_limits<unsigned long long>::digits)
165 using _Bitmask = _UInt<__div_ceil(__bit_ceil(
unsigned(_NBits)),
unsigned(__CHAR_BIT__))>;
173 template <
typename _Tp>
174 struct __canonical_vec_type
175 {
using type = _Tp; };
177 template <
typename _Tp>
178 using __canonical_vec_type_t =
typename __canonical_vec_type<_Tp>::type;
180#if __SIZEOF_INT__ == __SIZEOF_LONG__
182 struct __canonical_vec_type<long>
183 {
using type = int; };
186 struct __canonical_vec_type<unsigned long>
187 {
using type =
unsigned int; };
188#elif __SIZEOF_LONG_LONG__ == __SIZEOF_LONG__
190 struct __canonical_vec_type<long>
191 {
using type =
long long; };
194 struct __canonical_vec_type<unsigned long>
195 {
using type =
unsigned long long; };
198 template <
typename _Tp>
199 requires std::is_enum_v<_Tp>
200 struct __canonical_vec_type<_Tp>
201 {
using type = __canonical_vec_type<std::underlying_type_t<_Tp>>::type; };
204 struct __canonical_vec_type<char>
206 {
using type =
unsigned char; };
208 {
using type =
signed char; };
212 struct __canonical_vec_type<char8_t>
213 {
using type =
unsigned char; };
216 struct __canonical_vec_type<char16_t>
217 {
using type = uint_least16_t; };
220 struct __canonical_vec_type<char32_t>
221 {
using type = uint_least32_t; };
224 struct __canonical_vec_type<wchar_t>
226 using type = std::__conditional_t<std::is_signed_v<wchar_t>,
227 simd::__integer_from<
sizeof(wchar_t)>,
228 simd::_UInt<
sizeof(
wchar_t)>>;
231#if defined(__FLT64_DIG__) && defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64)
233 struct __canonical_vec_type<_Float64>
234 {
using type = double; };
237#if defined(__FLT32_DIG__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
239 struct __canonical_vec_type<_Float32>
240 {
using type = float; };
250 template <
int _Np = 1>
253 static constexpr int _S_size = _Np;
255 static constexpr int _S_nreg = _Np;
257 static constexpr _AbiVariant _S_variant = {};
259 template <
typename _Tp>
260 using _DataType = __canonical_vec_type_t<_Tp>;
262 static constexpr bool _S_is_vecmask =
false;
265 static constexpr bool _S_is_bitmask =
false;
268 using _MaskDataType = bool;
270 template <
int _N2,
int _Nreg2 = _N2>
271 static consteval _ScalarAbi<_N2>
274 static_assert(_N2 == _Nreg2);
290 template <
int _Np,
int _Nreg, underlying_type_t<_AbiVariant> _Var>
293 static constexpr int _S_size = _Np;
306 static constexpr int _S_nreg = _Nreg;
308 static_assert(_S_size > 0);
309 static_assert(_S_nreg > 0);
311 static constexpr _AbiVariant _S_variant =
static_cast<_AbiVariant
>(_Var);
313 static constexpr bool _S_is_bitmask
314 = __filter_abi_variant(_S_variant, _AbiVariant::_BitMask) == _AbiVariant::_BitMask;
316 static constexpr bool _S_is_vecmask = !_S_is_bitmask;
318 template <
typename _Tp>
319 using _DataType =
decltype([] {
320 static_assert(_S_nreg == 1);
321 if constexpr (_S_size == 1)
322 return __canonical_vec_type_t<_Tp>();
325 constexpr int __n = __bit_ceil(
unsigned(_S_size));
326 using _Vp [[__gnu__::__vector_size__(
sizeof(_Tp) * __n)]]
327 = __canonical_vec_type_t<_Tp>;
332 template <
size_t _Bytes>
335 static_assert(_S_nreg == 1);
336 if constexpr (_S_size == 1)
338 else if constexpr (_S_is_vecmask)
340 constexpr unsigned __vbytes = _Bytes * __bit_ceil(
unsigned(_S_size));
341 using _Vp [[__gnu__::__vector_size__(__vbytes)]] = __integer_from<_Bytes>;
344 else if constexpr (_Nreg > 1)
345 return _InvalidInteger();
347 return _Bitmask<_S_size>();
350 template <
int _N2,
int _Nreg2 = __div_ceil(_N2, _S_size)>
351 static consteval auto
354 if constexpr (_N2 == 1)
355 return _Abi<1, 1, _Var>();
357 return _Abi<_N2, _Nreg2, _Var>();
373 template <
int _Np,
int _Nreg, _AbiVariant... _Vs>
380 {
static constexpr int _S_size = 0; };
386 template <
typename _Tp>
388 = same_as<
decltype(_Tp::_S_variant),
const _AbiVariant>
389 && (_Tp::_S_size >= _Tp::_S_nreg) && (_Tp::_S_nreg >= 1)
390 &&
requires(_Tp __x) {
391 { __x.template _S_resize<_Tp::_S_size, _Tp::_S_nreg>() } -> same_as<_Tp>;
394 template <
typename _Tp>
395 concept __scalar_abi_tag
396 = same_as<_Tp, _ScalarAbi<_Tp::_S_size>> && __abi_tag<_Tp>;
402#ifdef math_errhandling
404 requires requires {
typename bool_constant<0 != (math_errhandling & MATH_ERREXCEPT)>; }
406 __handle_fpexcept_impl(
int)
407 {
return 0 != (math_errhandling & MATH_ERREXCEPT); }
412 __handle_fpexcept_impl(
float)
422 _M_test(
int __bit)
const
423 {
return ((_M_build_flags >> __bit) & 1) == 1; }
427 _M_fp_may_signal()
const
428 {
return _M_test(0); }
432 _M_fp_may_raise()
const
433 {
return _M_test(12); }
437 {
return _M_test(1); }
440 _M_finite_math_only()
const
441 {
return _M_test(2); }
444 _M_no_signed_zeros()
const
445 {
return _M_test(3); }
448 _M_signed_zeros()
const
449 {
return !_M_test(3); }
452 _M_reciprocal_math()
const
453 {
return _M_test(4); }
456 _M_no_math_errno()
const
457 {
return _M_test(5); }
460 _M_math_errno()
const
461 {
return !_M_test(5); }
464 _M_associative_math()
const
465 {
return _M_test(6); }
468 _M_conforming_to_STDC_annex_G()
const
469 {
return _M_test(10) && !_M_finite_math_only(); }
472 _M_support_snan()
const
473 {
return _M_test(11); }
475 __UINT64_TYPE__ _M_build_flags
477#if !__NO_TRAPPING_MATH__
480 + (__handle_fpexcept_impl(0) << 12)
484#
if __FINITE_MATH_ONLY__
487#if __NO_SIGNED_ZEROS__
490#
if __RECIPROCAL_MATH__
496#
if __ASSOCIATIVE_MATH__
500#if __FLT_EVAL_METHOD__ == 1
502#elif __FLT_EVAL_METHOD__ == 2
504#elif __FLT_EVAL_METHOD__ != 0
511#
if defined __STDC_IEC_60559_COMPLEX__ || defined __STDC_IEC_559_COMPLEX__ || defined _GLIBCXX_CLANG
524 __streq_to_1(
const char* __s)
525 {
return __s !=
nullptr && __s[0] ==
'1' && __s[1] ==
'\0'; }
531#define _GLIBCXX_SIMD_ARCH_FLAG(off, feat) \
532 (static_cast<__UINT64_TYPE__>(std::simd::__streq_to_1(_GLIBCXX_SIMD_TOSTRING_IMPL(feat))) << off)
536#define _GLIBCXX_SIMD_ARCH_TRAITS_INIT { \
537 _GLIBCXX_SIMD_ARCH_FLAG(0, __MMX__) \
538 | _GLIBCXX_SIMD_ARCH_FLAG( 1, __SSE__) \
539 | _GLIBCXX_SIMD_ARCH_FLAG( 2, __SSE2__) \
540 | _GLIBCXX_SIMD_ARCH_FLAG( 3, __SSE3__) \
541 | _GLIBCXX_SIMD_ARCH_FLAG( 4, __SSSE3__) \
542 | _GLIBCXX_SIMD_ARCH_FLAG( 5, __SSE4_1__) \
543 | _GLIBCXX_SIMD_ARCH_FLAG( 6, __SSE4_2__) \
544 | _GLIBCXX_SIMD_ARCH_FLAG( 7, __POPCNT__) \
545 | _GLIBCXX_SIMD_ARCH_FLAG( 8, __AVX__) \
546 | _GLIBCXX_SIMD_ARCH_FLAG( 9, __F16C__) \
547 | _GLIBCXX_SIMD_ARCH_FLAG(10, __BMI__) \
548 | _GLIBCXX_SIMD_ARCH_FLAG(11, __BMI2__) \
549 | _GLIBCXX_SIMD_ARCH_FLAG(12, __LZCNT__) \
550 | _GLIBCXX_SIMD_ARCH_FLAG(13, __AVX2__) \
551 | _GLIBCXX_SIMD_ARCH_FLAG(14, __FMA__) \
552 | _GLIBCXX_SIMD_ARCH_FLAG(15, __AVX512F__) \
553 | _GLIBCXX_SIMD_ARCH_FLAG(16, __AVX512CD__) \
554 | _GLIBCXX_SIMD_ARCH_FLAG(17, __AVX512DQ__) \
555 | _GLIBCXX_SIMD_ARCH_FLAG(18, __AVX512BW__) \
556 | _GLIBCXX_SIMD_ARCH_FLAG(19, __AVX512VL__) \
557 | _GLIBCXX_SIMD_ARCH_FLAG(20, __AVX512BITALG__) \
558 | _GLIBCXX_SIMD_ARCH_FLAG(21, __AVX512VBMI__) \
559 | _GLIBCXX_SIMD_ARCH_FLAG(22, __AVX512VBMI2__) \
560 | _GLIBCXX_SIMD_ARCH_FLAG(23, __AVX512IFMA__) \
561 | _GLIBCXX_SIMD_ARCH_FLAG(24, __AVX512VNNI__) \
562 | _GLIBCXX_SIMD_ARCH_FLAG(25, __AVX512VPOPCNTDQ__) \
563 | _GLIBCXX_SIMD_ARCH_FLAG(26, __AVX512FP16__) \
564 | _GLIBCXX_SIMD_ARCH_FLAG(27, __AVX512BF16__) \
565 | _GLIBCXX_SIMD_ARCH_FLAG(28, __AVXIFMA__) \
566 | _GLIBCXX_SIMD_ARCH_FLAG(29, __AVXNECONVERT__) \
567 | _GLIBCXX_SIMD_ARCH_FLAG(30, __AVXVNNI__) \
568 | _GLIBCXX_SIMD_ARCH_FLAG(31, __AVXVNNIINT8__) \
569 | _GLIBCXX_SIMD_ARCH_FLAG(32, __AVXVNNIINT16__) \
570 | _GLIBCXX_SIMD_ARCH_FLAG(33, __AVX10_1__) \
571 | _GLIBCXX_SIMD_ARCH_FLAG(34, __AVX10_2__) \
572 | _GLIBCXX_SIMD_ARCH_FLAG(35, __AVX512VP2INTERSECT__) \
573 | _GLIBCXX_SIMD_ARCH_FLAG(36, __SSE4A__) \
574 | _GLIBCXX_SIMD_ARCH_FLAG(37, __FMA4__) \
575 | _GLIBCXX_SIMD_ARCH_FLAG(38, __XOP__) \
583 __UINT64_TYPE__ _M_flags = _GLIBCXX_SIMD_ARCH_TRAITS_INIT;
586 _M_test(
int __bit)
const
587 {
return ((_M_flags >> __bit) & 1) == 1; }
591 {
return _M_test(0); }
595 {
return _M_test(1); }
599 {
return _M_test(2); }
603 {
return _M_test(3); }
606 _M_have_ssse3()
const
607 {
return _M_test(4); }
610 _M_have_sse4_1()
const
611 {
return _M_test(5); }
614 _M_have_sse4_2()
const
615 {
return _M_test(6); }
618 _M_have_popcnt()
const
619 {
return _M_test(7); }
623 {
return _M_test(8); }
627 {
return _M_test(9); }
631 {
return _M_test(10); }
635 {
return _M_test(11); }
638 _M_have_lzcnt()
const
639 {
return _M_test(12); }
643 {
return _M_test(13); }
647 {
return _M_test(14); }
650 _M_have_avx512f()
const
651 {
return _M_test(15); }
654 _M_have_avx512cd()
const
655 {
return _M_test(16); }
658 _M_have_avx512dq()
const
659 {
return _M_test(17); }
662 _M_have_avx512bw()
const
663 {
return _M_test(18); }
666 _M_have_avx512vl()
const
667 {
return _M_test(19); }
670 _M_have_avx512bitalg()
const
671 {
return _M_test(20); }
674 _M_have_avx512vbmi()
const
675 {
return _M_test(21); }
678 _M_have_avx512vbmi2()
const
679 {
return _M_test(22); }
682 _M_have_avx512ifma()
const
683 {
return _M_test(23); }
686 _M_have_avx512vnni()
const
687 {
return _M_test(24); }
690 _M_have_avx512vpopcntdq()
const
691 {
return _M_test(25); }
694 _M_have_avx512fp16()
const
695 {
return _M_test(26); }
698 _M_have_avx512bf16()
const
699 {
return _M_test(27); }
702 _M_have_avxifma()
const
703 {
return _M_test(28); }
706 _M_have_avxneconvert()
const
707 {
return _M_test(29); }
710 _M_have_avxvnni()
const
711 {
return _M_test(30); }
714 _M_have_avxvnniint8()
const
715 {
return _M_test(31); }
718 _M_have_avxvnniint16()
const
719 {
return _M_test(32); }
722 _M_have_avx10_1()
const
723 {
return _M_test(33); }
726 _M_have_avx10_2()
const
727 {
return _M_test(34); }
730 _M_have_avx512vp2intersect()
const
731 {
return _M_test(35); }
734 _M_have_sse4a()
const
735 {
return _M_test(36); }
739 {
return _M_test(37); }
743 {
return _M_test(38); }
745 template <
typename _Tp>
747 _M_eval_as_f32()
const
748 {
return is_same_v<_Tp, _Float16> && !_M_have_avx512fp16(); }
751 template <
typename _Tp, _ArchTraits _Traits = {}>
755 constexpr int __adj_sizeof =
sizeof(_Tp) * (1 + is_same_v<_Tp, _Float16>);
756 if constexpr (!__vectorizable<_Tp>)
757 return _InvalidAbi();
758 else if constexpr (_Traits._M_have_avx512fp16())
759 return _Abi_t<64 /
sizeof(_Tp), 1, _AbiVariant::_BitMask>();
760 else if constexpr (_Traits._M_have_avx512f())
761 return _Abi_t<64 / __adj_sizeof, 1, _AbiVariant::_BitMask>();
762 else if constexpr (is_same_v<_Tp, _Float16> && !_Traits._M_have_f16c())
763 return _ScalarAbi<1>();
764 else if constexpr (_Traits._M_have_avx2())
765 return _Abi_t<32 / __adj_sizeof, 1>();
766 else if constexpr (_Traits._M_have_avx() && is_floating_point_v<_Tp>)
767 return _Abi_t<32 / __adj_sizeof, 1>();
768 else if constexpr (_Traits._M_have_sse2())
769 return _Abi_t<16 / __adj_sizeof, 1>();
770 else if constexpr (_Traits._M_have_sse() && is_floating_point_v<_Tp>
771 &&
sizeof(_Tp) ==
sizeof(
float))
772 return _Abi_t<16 / __adj_sizeof, 1>();
775 return _ScalarAbi<1>();
783 __UINT64_TYPE__ _M_flags = 0;
786 _M_test(
int __bit)
const
787 {
return ((_M_flags >> __bit) & 1) == 1; }
790 template <
typename _Tp>
794 if constexpr (!__vectorizable<_Tp>)
795 return _InvalidAbi();
797 return _ScalarAbi<1>();
807 : _ArchTraits, _OptTraits
818 template <
typename _Tp>
819 using __native_abi_t =
decltype(std::simd::__native_abi<_Tp>());
821 template <
typename _Tp,
int _Np, _TargetTraits _Target = {}>
825 constexpr auto __native = std::simd::__native_abi<_Tp>();
826 if constexpr (0 == __native._S_size || _Np <= 0)
827 return _InvalidAbi();
828 else if constexpr (_Np == __native._S_size)
831 return __native.template _S_resize<_Np>();
839 template <
typename _Tp,
int _Np>
840 using __deduce_abi_t =
decltype(std::simd::__deduce_abi<_Tp, _Np>());
846 template <
typename _Tp,
int _Np, __abi_tag _A0, _ArchTraits = {}>
850 if constexpr (_Np <= 0 || !__vectorizable<_Tp>)
851 return _InvalidAbi();
853 else if constexpr (__scalar_abi_tag<_A0>)
854 return _A0::template _S_resize<_Np>();
858 using _Native = remove_const_t<decltype(std::simd::__native_abi<_Tp>())>;
859 static_assert(0 != _Native::_S_size);
860 constexpr int __nreg = __div_ceil(_Np, _Native::_S_size);
862 if constexpr (__scalar_abi_tag<_Native>)
863 return _Native::template _S_resize<_Np>();
865 return _Abi_t<_Native::_S_size, 1, __filter_abi_variant(_A0::_S_variant,
866 _AbiVariant::_MaskVariants)
867 >::template _S_resize<_Np, __nreg>();
881 template <
size_t _Bytes,
int _Np, __abi_tag _A0,
bool _IsOnlyResize, _ArchTraits _Traits = {}>
885 if constexpr (_Bytes == 0 || _Np <= 0)
886 return _InvalidAbi();
888 else if constexpr (__scalar_abi_tag<_A0>)
889 return _A0::template _S_resize<_Np>();
896 else if constexpr (_IsOnlyResize
897 && _Traits._M_have_avx() && !_Traits._M_have_avx2()
898 && __bit_ceil(__div_ceil<unsigned>(
899 _A0::_S_size, _A0::_S_nreg)) * _Bytes == 32)
901 if constexpr (_Bytes ==
sizeof(double))
902 return __abi_rebind<double, _Np, _A0>();
903 else if constexpr (_Bytes ==
sizeof(float))
904 return __abi_rebind<float, _Np, _A0>();
905 else if constexpr (_Traits._M_have_f16c() && _Bytes ==
sizeof(_Float16))
906 return __abi_rebind<_Float16, _Np, _A0>();
908 static_assert(
false);
913 return __abi_rebind<__integer_from<_Bytes>, _Np, _A0>();
929 template <
typename _To,
typename _From>
931 __is_mask_conversion_explicit([[maybe_unused]]
size_t __b0, [[maybe_unused]]
size_t __b1)
933 constexpr int __n = _To::_S_size;
934 static_assert(__n == _From::_S_size);
935#ifndef _GLIBCXX_SIMD_COND_EXPLICIT_MASK_CONVERSION
943 if constexpr (__scalar_abi_tag<_To>)
945 else if constexpr (__scalar_abi_tag<_From>)
949 else if constexpr (_To::_S_is_vecmask != _From::_S_is_vecmask)
950 return _To::_S_is_vecmask;
953 else if constexpr (_From::_S_nreg != _To::_S_nreg)
954 return _From::_S_nreg < _To::_S_nreg;
957 __builtin_unreachable();
969 using __simd_size_type = int;
972 template <__simd_
size_type _Xp>
973 inline constexpr integral_constant<__simd_size_type, _Xp> __simd_size_c = {};
976 template <
typename _Tp,
typename _Ap = __native_abi_t<_Tp>>
979 template <typename _Tp, __simd_size_type _Np = __native_abi_t<_Tp>::_S_size>
980 using vec = basic_vec<_Tp, __deduce_abi_t<_Tp, _Np>>;
982 template <
size_t _Bytes,
typename _Ap = __native_abi_t<__
integer_from<_Bytes>>>
985 template <typename _Tp, __simd_size_type _Np = __native_abi_t<_Tp>::_S_size>
986 using mask = basic_mask<
sizeof(_Tp), __deduce_abi_t<_Tp, _Np>>;
989 template <
typename _Tp,
size_t _Np = -1uz>
990 concept __static_sized_range
991 = ranges::sized_range<_Tp> &&
requires(_Tp&& __r) {
992 typename integral_constant<size_t, ranges::size(__r)>;
993 requires (_Np == -1uz || ranges::size(__r) == _Np);
996 template <
typename _Rg>
998 __static_range_size(_Rg& __r)
1000 if constexpr (
requires {
typename integral_constant<size_t, ranges::size(__r)>; })
1001 return ranges::size(__r);
1003 return dynamic_extent;
1007 template <
typename _From,
typename _To>
1008 concept __arithmetic_only_value_preserving_convertible_to
1009 = convertible_to<_From, _To> && is_arithmetic_v<_From> && is_arithmetic_v<_To>
1010 && !(is_signed_v<_From> && is_unsigned_v<_To>)
1020 template <
typename _From,
typename _To>
1021 concept __value_preserving_convertible_to
1022 = __arithmetic_only_value_preserving_convertible_to<_From, _To>;
1025 template <
typename _From,
typename _To>
1026 concept __explicitly_convertible_to =
requires {
1033 template<
typename _Tp>
1034 concept __constexpr_wrapper_like
1035 = convertible_to<_Tp,
decltype(_Tp::value)>
1036 && equality_comparable_with<_Tp,
decltype(_Tp::value)>
1037 && bool_constant<_Tp() == _Tp::value>::value
1038 && bool_constant<static_cast<decltype(_Tp::value)>(_Tp()) == _Tp::value>::value;
1041 template <auto _From,
typename _To>
1042 concept __non_narrowing_constexpr_conversion
1043 = is_arithmetic_v<
decltype(_From)>
1044 &&
static_cast<decltype(_From)
>(
static_cast<_To
>(_From)) == _From
1045 && !(unsigned_integral<_To> && _From <
decltype(_From)())
1051 template <
typename _From,
typename _To>
1052 concept __broadcast_constructible
1053 = ((convertible_to<_From, _To> && !is_arithmetic_v<remove_cvref_t<_From>>
1054 && !__constexpr_wrapper_like<remove_cvref_t<_From>>)
1055 || __value_preserving_convertible_to<remove_cvref_t<_From>, _To>
1056 || (__constexpr_wrapper_like<remove_cvref_t<_From>>
1057 && __non_narrowing_constexpr_conversion<
auto(remove_cvref_t<_From>::value),
1061 template <
typename _From,
typename _To>
1063 __higher_floating_point_rank_than()
1065 return floating_point<_From> && floating_point<_To>
1066 && is_same_v<common_type_t<_From, _To>, _From> && !is_same_v<_From, _To>;
1070 template <
typename _From,
typename _To>
1072 __higher_integer_rank_than()
1074 return integral<_From> && integral<_To>
1075 && (
sizeof(_From) >
sizeof(_To) || is_same_v<common_type_t<_From, _To>, _From>)
1076 && !is_same_v<_From, _To>;
1079 template <
typename _From,
typename _To>
1080 concept __higher_rank_than
1081 = __higher_floating_point_rank_than<_From, _To>() || __higher_integer_rank_than<_From, _To>();
1083 struct __convert_flag;
1085 template <
typename _From,
typename _To,
typename... _Flags>
1086 concept __loadstore_convertible_to
1087 = same_as<_From, _To>
1088 || (__vectorizable<_From> && __vectorizable<_To>
1089 && (__value_preserving_convertible_to<_From, _To>
1090 || (__explicitly_convertible_to<_From, _To>
1091 && (std::is_same_v<_Flags, __convert_flag> || ...))));
1093 template <
typename _From,
typename _To>
1094 concept __simd_generator_convertible_to
1095 = std::convertible_to<_From, _To>
1096 && (!is_arithmetic_v<_From> || __value_preserving_convertible_to<_From, _To>);
1098 template <
typename _Fp,
typename _Tp, __simd_size_type... _Is>
1099 requires (__simd_generator_convertible_to<
1100 decltype(
declval<_Fp>()(__simd_size_c<_Is>)), _Tp> && ...)
1102 __simd_generator_invokable_impl(integer_sequence<__simd_size_type, _Is...>);
1104 template <
typename _Fp,
typename _Tp, __simd_
size_type _Np>
1105 concept __simd_generator_invokable =
requires {
1109 template <
typename _Fp>
1110 concept __index_permutation_function_sized =
requires(_Fp
const& __f)
1112 { __f(0, 0) } -> std::integral;
1115 template <
typename _Fp,
typename _Simd>
1116 concept __index_permutation_function
1117 = __index_permutation_function_sized<_Fp> ||
requires(_Fp
const& __f) {
1118 { __f(0) } -> std::integral;
1126 template <
typename _Tp>
1127 constexpr size_t __mask_element_size = 0;
1129 template <
size_t _Bytes, __abi_tag _Ap>
1130 constexpr size_t __mask_element_size<basic_mask<_Bytes, _Ap>> = _Bytes;
1133 template <
typename _Vp>
1134 concept __simd_vec_type
1135 = same_as<_Vp, basic_vec<typename _Vp::value_type, typename _Vp::abi_type>>
1136 && is_default_constructible_v<_Vp>;
1138 template <
typename _Vp>
1139 concept __simd_mask_type
1140 = same_as<_Vp, basic_mask<__mask_element_size<_Vp>,
typename _Vp::abi_type>>
1141 && is_default_constructible_v<_Vp>;
1146 template <
typename _Vp>
1147 concept __simd_vec_or_mask_type = __simd_vec_type<_Vp> || __simd_mask_type<_Vp>;
1149 template <
typename _Vp>
1150 concept __simd_floating_point
1151 = __simd_vec_type<_Vp> && floating_point<typename _Vp::value_type>;
1153 template <
typename _Vp>
1154 concept __simd_integral
1155 = __simd_vec_type<_Vp> && integral<typename _Vp::value_type>;
1157 template <
typename _Tp>
1158 concept __converts_to_vec
1161 template <__converts_to_vec _Tp>
1164 template <
typename _Vp,
typename _Tp>
1165 using __make_compatible_simd_t
1168 if constexpr (__simd_vec_type<_Up>)
1171 return vec<_Up, _Vp::size()>();
1174 template <
typename _Tp>
1175 concept __math_floating_point = __simd_floating_point<__deduced_vec_t<_Tp>>;
1177 template <
typename _BinaryOperation,
typename _Tp>
1178 concept __reduction_binary_operation
1179 =
requires (
const _BinaryOperation __binary_op,
const vec<_Tp, 1> __v) {
1180 { __binary_op(__v, __v) } -> same_as<vec<_Tp, 1>>;
1186 [[__gnu__::__always_inline__]]
1187 constexpr __simd_size_type
1188 __highest_bit(std::unsigned_integral
auto __bits)
1191 constexpr auto _Nd =
__int_traits<
decltype(__bits)>::__digits;
1192 return _Nd - 1 - __countl_zero(__bits);
1195 template <__vectorizable _Tp, __simd_
size_type _Np, __abi_tag _Ap>
1196 using __similar_mask = basic_mask<sizeof(_Tp), decltype(__abi_rebind<_Tp, _Np, _Ap>())>;
1199 template <
typename _Tp, __simd_
size_type _Np, __abi_tag _Ap>
1200 using __similar_vec = basic_vec<_Tp, decltype(__abi_rebind<_Tp, _Np, _Ap>())>;
1203 template <
size_t _Bytes,
typename _Ap>
1204 using __simd_vec_from_mask_t = __similar_vec<__integer_from<_Bytes>, _Ap::_S_size, _Ap>;
1206#if _GLIBCXX_SIMD_THROW_ON_BAD_VALUE
1207 class __bad_value_preserving_cast
1210#define __glibcxx_on_bad_value_preserving_cast throw __bad_value_preserving_cast
1212 void __bad_value_preserving_cast();
1214#define __glibcxx_on_bad_value_preserving_cast __bad_value_preserving_cast
1217 template <
typename _To,
typename _From>
1218#if _GLIBCXX_SIMD_THROW_ON_BAD_VALUE
1219 [[__gnu__::__optimize__(
"exceptions")]]
1222 __value_preserving_cast(
const _From& __x)
1224 static_assert(is_arithmetic_v<_From>);
1225 if constexpr (!__value_preserving_convertible_to<_From, _To>)
1227 using _Up =
typename __make_unsigned<_From>::__type;
1228 if (
static_cast<_Up
>(
static_cast<_To
>(__x)) !=
static_cast<_Up
>(__x))
1229 __glibcxx_on_bad_value_preserving_cast();
1230 else if constexpr (is_signed_v<_From> && is_unsigned_v<_To>)
1233 __glibcxx_on_bad_value_preserving_cast();
1235 else if constexpr (unsigned_integral<_From> && signed_integral<_To>)
1238 __glibcxx_on_bad_value_preserving_cast();
1241 return static_cast<_To
>(__x);
1244 template <
typename _From,
typename _To>
1245 concept __simd_vec_bcast_consteval
1246 = __explicitly_convertible_to<_From, _To>
1247 && is_arithmetic_v<remove_cvref_t<_From>> && convertible_to<_From, _To>
1248 && !__value_preserving_convertible_to<remove_cvref_t<_From>, _To>
1249 && (is_same_v<common_type_t<_From, _To>, _To>
1250 || (is_same_v<remove_cvref_t<_From>,
int> && is_integral_v<_To>)
1251 || (is_same_v<remove_cvref_t<_From>,
unsigned> && unsigned_integral<_To>));
1256 template <
typename _T0,
typename _T1>
1257 struct __trivial_pair
1263 template <
typename _From,
typename _To>
1264 concept __converts_trivially = convertible_to<_From, _To>
1265 &&
sizeof(_From) ==
sizeof(_To)
1266 && is_integral_v<_From> == is_integral_v<_To>
1267 && is_floating_point_v<_From> == is_floating_point_v<_To>;
1269 [[__gnu__::__always_inline__]]
1271 __bit_foreach(unsigned_integral
auto __bits,
auto&& __fun)
1273 static_assert(
sizeof(__bits) >=
sizeof(int));
1276 __fun(__countr_zero(__bits));
1277 __bits &= (__bits - 1);
1295 template <
size_t _Chunk,
size_t _Max>
1297 __memcpy_chunks(
byte* __restrict__ __dst,
const byte* __restrict__ __src,
1300 static_assert(_Max <= 64);
1301 static_assert(__has_single_bit(_Chunk) && _Chunk <= 8);
1302 size_t __bytes = _Chunk * __n;
1303 if (__builtin_constant_p(__bytes))
1306 __builtin_memcpy(__dst, __src, __bytes);
1308 else if (__bytes > 32 && _Max > 32)
1310 __builtin_memcpy(__dst, __src, 32);
1312 __builtin_memcpy(__dst + __bytes, __src + __bytes, 32);
1314 else if (__bytes > 16 && _Max > 16)
1316 __builtin_memcpy(__dst, __src, 16);
1317 if constexpr (_Chunk == 8)
1320 __builtin_memcpy(__dst + __bytes, __src + __bytes, 8);
1325 __builtin_memcpy(__dst + __bytes, __src + __bytes, 16);
1328 else if (__bytes > 8 && _Max > 8)
1330 __builtin_memcpy(__dst, __src, 8);
1331 if constexpr (_Chunk == 4)
1334 __builtin_memcpy(__dst + __bytes, __src + __bytes, 4);
1336 else if constexpr (_Chunk < 4)
1339 __builtin_memcpy(__dst + __bytes, __src + __bytes, 8);
1342 else if (__bytes > 4 && _Max > 4)
1344 __builtin_memcpy(__dst, __src, 4);
1345 if constexpr (_Chunk == 2)
1348 __builtin_memcpy(__dst + __bytes, __src + __bytes, 2);
1350 else if constexpr (_Chunk == 1)
1353 __builtin_memcpy(__dst + __bytes, __src + __bytes, 4);
1356 else if (__bytes >= 2)
1358 __builtin_memcpy(__dst, __src, 2);
1359 if constexpr (_Chunk == 2)
1362 __builtin_memcpy(__dst + __bytes, __src + __bytes, 2);
1364 else if constexpr (_Chunk == 1)
1367 __builtin_memcpy(__dst + __bytes, __src + __bytes, 1);
1370 else if (__bytes == 1)
1371 __builtin_memcpy(__dst, __src, 1);
1375 template <
typename _Tp,
typename _BinaryOperation>
1376 requires __is_one_of<_BinaryOperation,
1377 plus<>, multiplies<>, bit_and<>, bit_or<>, bit_xor<>>::value
1379 __default_identity_element()
1381 if constexpr (same_as<_BinaryOperation, multiplies<>>)
1383 else if constexpr (same_as<_BinaryOperation, bit_and<>>)
1389_GLIBCXX_END_NAMESPACE_VERSION
1392#pragma GCC diagnostic pop
typename underlying_type< _Tp >::type underlying_type_t
Alias template for underlying_type.
typename make_unsigned< _Tp >::type make_unsigned_t
Alias template for make_unsigned.
auto declval() noexcept -> decltype(__declval< _Tp >(0))
ISO C++ entities toplevel namespace is std.
__make_integer_seq< integer_sequence, _Tp, _Num > make_integer_sequence
Alias template make_integer_sequence.
__numeric_traits_integer< _Tp > __int_traits
Convenience alias for __numeric_traits<integer-type>.
static constexpr int digits
static constexpr _Tp max() noexcept
static constexpr _Tp lowest() noexcept