6#include "native/value_traits.h"
7#include "native/wide_pack.h"
19 template<
class T, std::
size_t N>
struct wide;
21 template<
class T>
struct wide_traits {
22 using element_type = T;
23 static constexpr bool value =
false;
24 static constexpr std::size_t size = 0;
26 template<
class T, std::
size_t N>
struct wide_traits<
wide<T, N>> {
27 using element_type = T;
28 static constexpr bool value =
true;
29 static constexpr std::size_t size = N;
34 template<
class T,
class =
void>
struct wide_features {
35 static constexpr isa<> value=scalar;
37 template<
class T>
struct wide_features<T,std::void_t<decltype(T::architecture)>> {
38 static constexpr isa<> value=value_architecture_v<T>;
40 template<
class T,std::
size_t N>
struct wide_features<
wide<T,N>> : wide_features<T> {};
41 template<
class T,std::
size_t N>
struct wide_features<std::array<T,N>> : wide_features<T> {};
42 template<
class T,
class U>
struct wide_features<std::pair<T,U>> {
43 static constexpr isa<> value=wide_features<std::remove_cvref_t<T>>::value &
44 wide_features<std::remove_cvref_t<U>>::value;
49 template<
class... T>
inline constexpr auto wide_target=[] {
50 constexpr isa<> bits=(scalar & ... & wide_features<std::remove_cvref_t<T>>::value);
51 constexpr auto index=abi_lookup<bits,wide_kernel_policies>::index;
52 static_assert(index>=0,
"wide operands require an available host declaration scope");
53 return host_kernel_profiles::indices[index];
55 template<
class T>
inline constexpr bool wide_equivalent_default=
56 value_traits<std::remove_cv_t<T>>::aggregate_default;
63 template<
class T,std::
size_t N>
inline constexpr bool wide_target_default =
64 (N == 0 || wide_equivalent_default<T>) && std::is_default_constructible_v<T> &&
65 !std::is_trivially_default_constructible_v<T> &&
66 std::is_default_constructible_v<std::array<T,N>> &&
67 !std::is_trivially_default_constructible_v<std::array<T,N>>;
82 template<
class T, std::
size_t N>
85 alignas(T) std::array<T, N> registers;
88 constexpr wide()
requires (!detail::wide_target_default<T,N>) =
default;
90 template<std::
size_t I>
requires (I < N)
93 template<std::
size_t I>
requires (I < N)
96 template<std::
size_t I>
requires (I < N)
99 template<std::
size_t I>
requires (I < N)
103 struct conversion_tag {};
104#define NATIVE_WIDE_INDEX 15
105#define NATIVE_WIDE_DETAIL detail::wide_generic_detail
106#define NATIVE_WIDE_TARGET
113 noexcept(
std::is_nothrow_default_constructible_v<
std::array<T,N>>)
114 requires (detail::wide_target<T> == NATIVE_WIDE_INDEX) && detail::wide_target_default<T,N>
118 noexcept(std::is_nothrow_move_constructible_v<std::array<T, N>>)
119 requires (detail::wide_target<T> == NATIVE_WIDE_INDEX)
120 : registers(std::move(values)) {}
122 template<
class... U>
requires (detail::wide_target<T,U...> == NATIVE_WIDE_INDEX) && (
sizeof...(U) == N && N != 0) &&
123 (std::constructible_from<T,U &&> && ...) &&
124 (N != 1 || ((!detail::wide_traits<std::remove_cvref_t<U>>::value &&
125 !std::same_as<std::remove_cvref_t<U>,std::array<T,N>>) && ...))
127 noexcept((std::is_nothrow_constructible_v<T,U &&> && ...))
128 : registers{T(std::forward<U>(values))...} {}
130 template<
class U>
requires (detail::wide_target<T,U> == NATIVE_WIDE_INDEX) && (N != 1) && (!detail::wide_traits<std::remove_cvref_t<U>>::value) &&
131 (!std::same_as<std::remove_cvref_t<U>,std::array<T, N>>) &&
132 std::constructible_from<T,U const &> && (N == 0 || std::copy_constructible<T>)
134 noexcept(std::is_nothrow_constructible_v<T,U const &> &&
135 (N == 0 || std::is_nothrow_copy_constructible_v<T>))
136 :
wide(T(value),
std::make_index_sequence<N>{}) {}
139 template<
class U>
requires (detail::wide_target<T,U> == NATIVE_WIDE_INDEX) && (!std::same_as<T,U>) && std::constructible_from<T,U const &>
141 noexcept(N == 0 || std::is_nothrow_constructible_v<T,U const &>)
142 :
wide(conversion_tag{}, source,
std::make_index_sequence<N>{}) {}
144 template<
class U>
requires (detail::wide_target<T,U> == NATIVE_WIDE_INDEX) && (!std::same_as<T,U>) && std::constructible_from<T,U &&>
146 noexcept(N == 0 || std::is_nothrow_constructible_v<T,U &&>)
147 :
wide(conversion_tag{},
std::move(source),
std::make_index_sequence<N>{}) {}
151 noexcept(N == 0 || std::is_nothrow_copy_constructible_v<T>)
152 requires (detail::wide_target<T> == NATIVE_WIDE_INDEX) && (N == 0 || std::copy_constructible<T>) {
153 return wide(value, std::make_index_sequence<N>{});
157 template<
class F>
requires (detail::wide_target<T> == NATIVE_WIDE_INDEX)
158 NATIVE_WIDE_TARGET
native_inline constexpr decltype(
auto)
apply(F && f)
noexcept(
noexcept(std::apply(std::forward<F>(f), registers))) {
159 return apply_indices(std::forward<F>(f), registers, std::make_index_sequence<N>{});
163 template<
class F>
requires (detail::wide_target<T> == NATIVE_WIDE_INDEX)
164 NATIVE_WIDE_TARGET
native_inline constexpr decltype(
auto)
apply(F && f)
const noexcept(
noexcept(std::apply(std::forward<F>(f), registers))) {
165 return apply_indices(std::forward<F>(f), registers, std::make_index_sequence<N>{});
168 template<
class W, std::size_t... I>
requires (detail::wide_target<T,W> == NATIVE_WIDE_INDEX)
169 NATIVE_WIDE_TARGET
native_inline constexpr wide(conversion_tag, W && source, std::index_sequence<I...>)
170 noexcept((std::is_nothrow_constructible_v<T,
171 decltype(std::get<I>(std::forward<W>(source).registers))> && ...))
172 : registers{T(std::get<I>(std::forward<W>(source).registers))...} {}
173 template<
class U, std::size_t... I>
requires (detail::wide_target<T> == NATIVE_WIDE_INDEX) && std::same_as<std::remove_cvref_t<U>,T>
174 NATIVE_WIDE_TARGET
native_inline constexpr wide(U && value, std::index_sequence<I...>)
175 noexcept(N == 0 || std::is_nothrow_copy_constructible_v<T>)
176 : registers{((void)I,static_cast<T const &>(value))...} {}
179 template<
class F,
class A, std::size_t ... I>
requires (detail::wide_target<A> == NATIVE_WIDE_INDEX)
180 static NATIVE_WIDE_TARGET
native_inline constexpr decltype(
auto) apply_indices(F && f, A & a, std::index_sequence<I...>) {
181 if constexpr (std::is_member_pointer_v<std::remove_reference_t<F>>)
182 return std::invoke(std::forward<F>(f), std::get<I>(a)...);
184 return std::forward<F>(f)(std::get<I>(a)...);
187#undef NATIVE_WIDE_TARGET
188#undef NATIVE_WIDE_DETAIL
189#undef NATIVE_WIDE_INDEX
191#if defined(__x86_64__) || defined(_M_X64)
192#define NATIVE_WIDE_INDEX 10
193#define NATIVE_WIDE_DETAIL detail::wide_avx2_detail
194#define NATIVE_WIDE_TARGET __attribute__((target(NATIVE_KERNEL_TARGET_1)))
196#undef NATIVE_WIDE_TARGET
197#undef NATIVE_WIDE_DETAIL
198#undef NATIVE_WIDE_INDEX
201#if defined(__x86_64__) || defined(_M_X64)
202#define NATIVE_WIDE_INDEX 9
203#define NATIVE_WIDE_DETAIL detail::wide_avx512_base_detail
204#define NATIVE_WIDE_TARGET __attribute__((target(NATIVE_KERNEL_TARGET_2)))
206#undef NATIVE_WIDE_TARGET
207#undef NATIVE_WIDE_DETAIL
208#undef NATIVE_WIDE_INDEX
211#if defined(__x86_64__) || defined(_M_X64)
212#define NATIVE_WIDE_INDEX 7
213#define NATIVE_WIDE_DETAIL detail::wide_avx512_bw_detail
214#define NATIVE_WIDE_TARGET __attribute__((target(NATIVE_KERNEL_TARGET_3)))
216#undef NATIVE_WIDE_TARGET
217#undef NATIVE_WIDE_DETAIL
218#undef NATIVE_WIDE_INDEX
221#if defined(__x86_64__) || defined(_M_X64)
222#define NATIVE_WIDE_INDEX 8
223#define NATIVE_WIDE_DETAIL detail::wide_avx512_vl_detail
224#define NATIVE_WIDE_TARGET __attribute__((target(NATIVE_KERNEL_TARGET_4)))
226#undef NATIVE_WIDE_TARGET
227#undef NATIVE_WIDE_DETAIL
228#undef NATIVE_WIDE_INDEX
231#if defined(__x86_64__) || defined(_M_X64)
232#define NATIVE_WIDE_INDEX 3
233#define NATIVE_WIDE_DETAIL detail::wide_avx512_bw_vl_detail
234#define NATIVE_WIDE_TARGET __attribute__((target(NATIVE_KERNEL_TARGET_5)))
236#undef NATIVE_WIDE_TARGET
237#undef NATIVE_WIDE_DETAIL
238#undef NATIVE_WIDE_INDEX
241#if defined(__x86_64__) || defined(_M_X64)
242#define NATIVE_WIDE_INDEX 5
243#define NATIVE_WIDE_DETAIL detail::wide_avx512_bw_bf16_detail
244#define NATIVE_WIDE_TARGET __attribute__((target(NATIVE_KERNEL_TARGET_7)))
246#undef NATIVE_WIDE_TARGET
247#undef NATIVE_WIDE_DETAIL
248#undef NATIVE_WIDE_INDEX
251#if defined(__x86_64__) || defined(_M_X64)
252#define NATIVE_WIDE_INDEX 1
253#define NATIVE_WIDE_DETAIL detail::wide_avx512_bw_vl_bf16_detail
254#define NATIVE_WIDE_TARGET __attribute__((target(NATIVE_KERNEL_TARGET_9)))
256#undef NATIVE_WIDE_TARGET
257#undef NATIVE_WIDE_DETAIL
258#undef NATIVE_WIDE_INDEX
261#if defined(__x86_64__) || defined(_M_X64)
262#define NATIVE_WIDE_INDEX 6
263#define NATIVE_WIDE_DETAIL detail::wide_avx512_bw_fp16_detail
264#define NATIVE_WIDE_TARGET __attribute__((target(NATIVE_KERNEL_TARGET_11)))
266#undef NATIVE_WIDE_TARGET
267#undef NATIVE_WIDE_DETAIL
268#undef NATIVE_WIDE_INDEX
271#if defined(__x86_64__) || defined(_M_X64)
272#define NATIVE_WIDE_INDEX 2
273#define NATIVE_WIDE_DETAIL detail::wide_avx512_bw_vl_fp16_detail
274#define NATIVE_WIDE_TARGET __attribute__((target(NATIVE_KERNEL_TARGET_13)))
276#undef NATIVE_WIDE_TARGET
277#undef NATIVE_WIDE_DETAIL
278#undef NATIVE_WIDE_INDEX
281#if defined(__x86_64__) || defined(_M_X64)
282#define NATIVE_WIDE_INDEX 4
283#define NATIVE_WIDE_DETAIL detail::wide_avx512_bw_bf16_fp16_detail
284#define NATIVE_WIDE_TARGET __attribute__((target(NATIVE_KERNEL_TARGET_15)))
286#undef NATIVE_WIDE_TARGET
287#undef NATIVE_WIDE_DETAIL
288#undef NATIVE_WIDE_INDEX
291#if defined(__x86_64__) || defined(_M_X64)
292#define NATIVE_WIDE_INDEX 0
293#define NATIVE_WIDE_DETAIL detail::wide_avx512_bw_vl_bf16_fp16_detail
294#define NATIVE_WIDE_TARGET __attribute__((target(NATIVE_KERNEL_TARGET_17)))
296#undef NATIVE_WIDE_TARGET
297#undef NATIVE_WIDE_DETAIL
298#undef NATIVE_WIDE_INDEX
301#if defined(__aarch64__) || defined(_M_ARM64)
302#define NATIVE_WIDE_INDEX 14
303#define NATIVE_WIDE_DETAIL detail::wide_neon_detail
304#define NATIVE_WIDE_TARGET __attribute__((target(NATIVE_KERNEL_TARGET_20)))
306#undef NATIVE_WIDE_TARGET
307#undef NATIVE_WIDE_DETAIL
308#undef NATIVE_WIDE_INDEX
311#if defined(__aarch64__) || defined(_M_ARM64)
312#define NATIVE_WIDE_INDEX 12
313#define NATIVE_WIDE_DETAIL detail::wide_neon_bf16_detail
314#define NATIVE_WIDE_TARGET __attribute__((target(NATIVE_KERNEL_TARGET_21)))
316#undef NATIVE_WIDE_TARGET
317#undef NATIVE_WIDE_DETAIL
318#undef NATIVE_WIDE_INDEX
321#if defined(__aarch64__) || defined(_M_ARM64)
322#define NATIVE_WIDE_INDEX 13
323#define NATIVE_WIDE_DETAIL detail::wide_neon_fp16_detail
324#define NATIVE_WIDE_TARGET __attribute__((target(NATIVE_KERNEL_TARGET_22)))
326#undef NATIVE_WIDE_TARGET
327#undef NATIVE_WIDE_DETAIL
328#undef NATIVE_WIDE_INDEX
331#if defined(__aarch64__) || defined(_M_ARM64)
332#define NATIVE_WIDE_INDEX 11
333#define NATIVE_WIDE_DETAIL detail::wide_neon_half_detail
334#define NATIVE_WIDE_TARGET __attribute__((target(NATIVE_KERNEL_TARGET_23)))
336#undef NATIVE_WIDE_TARGET
337#undef NATIVE_WIDE_DETAIL
338#undef NATIVE_WIDE_INDEX
342#define NATIVE_WIDE_INDEX 16
343#define NATIVE_WIDE_DETAIL detail::wide_wasm_detail
344#define NATIVE_WIDE_TARGET __attribute__((target(NATIVE_KERNEL_TARGET_WASM)))
346#undef NATIVE_WIDE_TARGET
347#undef NATIVE_WIDE_DETAIL
348#undef NATIVE_WIDE_INDEX
353 template<
class T,
class... U>
requires (std::same_as<T,U> && ...)
356#define NATIVE_WIDE_INDEX 15
357#define NATIVE_WIDE_DETAIL detail::wide_generic_detail
361 namespace NATIVE_WIDE_DETAIL {
362 using namespace ::native::detail;
363 template<
class T>
using wide_element_t =
typename wide_traits<T>::element_type;
364 template<
class A,
class B>
concept wide_arguments =
365 (wide_traits<A>::value || wide_traits<B>::value) &&
366 (!wide_traits<A>::value || !wide_traits<B>::value || wide_traits<A>::size == wide_traits<B>::size);
367 template<
class A,
class B>
inline constexpr std::size_t wide_size =
368 wide_traits<A>::value ? wide_traits<A>::size : wide_traits<B>::size;
370 template<std::
size_t I,
class T>
371 native_inline constexpr decltype(
auto) wide_element(T
const & value) {
372 if constexpr (wide_traits<T>::value)
return value.registers[I];
375 template<
class A,
class B,
class F, std::size_t... I>
376 native_inline constexpr auto wide_binary(A
const & a, B
const & b, F f, std::index_sequence<I...>) {
377 using R = std::remove_cvref_t<
decltype(f(std::declval<wide_element_t<A>
const &>(),
378 std::declval<wide_element_t<B>
const &>()))>;
379 return wide<R,
sizeof...(I)>{{f(wide_element<I>(a), wide_element<I>(b))...}};
381 template<
class T, std::size_t N,
class F, std::size_t... I>
383 using R = std::remove_cvref_t<decltype(f(std::declval<T const &>()))>;
386 template<
class T, std::size_t N,
class B,
class F, std::size_t... I>
388 if constexpr (wide_traits<B>::value) (f(a.registers[I], b.registers[I]), ...);
389 else if constexpr (N != 0) {
393 (f(a.registers[I], value), ...);
399 namespace NATIVE_WIDE_DETAIL {
400 using namespace ::native::detail;
401 template<
class A>
native_inline constexpr decltype(
auto) wide_storage(A
const & a)
noexcept {
402 if constexpr (wide_traits<A>::value)
return (a.registers);
406 template<
class A,
class B>
native_inline constexpr auto operator()(A
const & a,B
const & b)
const
407 noexcept(
noexcept(a + b)) ->
decltype(a + b) {
return a + b; }
408 template<
class A,
class B>
native_inline constexpr auto batch(A
const & a,B
const & b)
const
409 noexcept(
noexcept(add(a,b))) ->
decltype(add(a,b)) {
return add(a,b); }
412 template<
class A,
class B>
native_inline constexpr auto operator()(A
const & a,B
const & b)
const
413 noexcept(
noexcept(a - b)) ->
decltype(a - b) {
return a - b; }
414 template<
class A,
class B>
native_inline constexpr auto batch(A
const & a,B
const & b)
const
415 noexcept(
noexcept(sub(a,b))) ->
decltype(sub(a,b)) {
return sub(a,b); }
418 template<
class A,
class B>
native_inline constexpr auto operator()(A
const & a,B
const & b)
const
419 noexcept(
noexcept(a * b)) ->
decltype(a * b) {
return a * b; }
420 template<
class A,
class B>
native_inline constexpr auto batch(A
const & a,B
const & b)
const
421 noexcept(
noexcept(mul(a,b))) ->
decltype(mul(a,b)) {
return mul(a,b); }
423 template<
class A,
class B,
class F>
concept wide_batch =
requires(A
const & a,B
const & b) {
424 wide{F{}.batch(wide_storage(a),wide_storage(b))};
426 template<
class A,
class B,
class F>
concept wide_batch_assignable = wide_batch<A,B,F> &&
427 requires(A & a,B
const & b) { a =
wide{F{}.batch(wide_storage(a),wide_storage(b))}; };
428 template<
class A,
class B,
class F>
429 native_inline constexpr auto wide_dispatch(A
const & a,B
const & b,F f)
431 if constexpr (wide_batch<A,B,F>)
432 return noexcept(wide{F{}.batch(wide_storage(std::declval<A const &>()),wide_storage(std::declval<B const &>()))});
435 if constexpr (wide_batch<A,B,F>)
return wide{f.batch(wide_storage(a),wide_storage(b))};
436 else return wide_binary(a,b,f,std::make_index_sequence<wide_size<A,B>>{});
444 template<
class A,
class B>
requires NATIVE_WIDE_DETAIL::wide_arguments<A, B> && (::native::detail::wide_target<A,B> == NATIVE_WIDE_INDEX) &&
445 requires(NATIVE_WIDE_DETAIL::wide_element_t<A>
const & a, NATIVE_WIDE_DETAIL::wide_element_t<B>
const & b) { a + b; }
447 noexcept(
noexcept(NATIVE_WIDE_DETAIL::wide_dispatch(a,b,NATIVE_WIDE_DETAIL::wide_add{}))) {
448 return NATIVE_WIDE_DETAIL::wide_dispatch(a,b,NATIVE_WIDE_DETAIL::wide_add{});
453 template<
class A,
class B>
requires NATIVE_WIDE_DETAIL::wide_arguments<A, B> && (::native::detail::wide_target<A,B> == NATIVE_WIDE_INDEX) &&
454 requires(NATIVE_WIDE_DETAIL::wide_element_t<A>
const & a, NATIVE_WIDE_DETAIL::wide_element_t<B>
const & b) { a - b; }
456 noexcept(
noexcept(NATIVE_WIDE_DETAIL::wide_dispatch(a,b,NATIVE_WIDE_DETAIL::wide_sub{}))) {
457 return NATIVE_WIDE_DETAIL::wide_dispatch(a,b,NATIVE_WIDE_DETAIL::wide_sub{});
462 template<
class A,
class B>
requires NATIVE_WIDE_DETAIL::wide_arguments<A, B> && (::native::detail::wide_target<A,B> == NATIVE_WIDE_INDEX) &&
463 requires(NATIVE_WIDE_DETAIL::wide_element_t<A>
const & a, NATIVE_WIDE_DETAIL::wide_element_t<B>
const & b) { a * b; }
465 noexcept(
noexcept(NATIVE_WIDE_DETAIL::wide_dispatch(a,b,NATIVE_WIDE_DETAIL::wide_mul{}))) {
466 return NATIVE_WIDE_DETAIL::wide_dispatch(a,b,NATIVE_WIDE_DETAIL::wide_mul{});
471 template<
class A,
class B>
requires NATIVE_WIDE_DETAIL::wide_arguments<A, B> && (::native::detail::wide_target<A,B> == NATIVE_WIDE_INDEX) &&
472 requires(NATIVE_WIDE_DETAIL::wide_element_t<A>
const & a, NATIVE_WIDE_DETAIL::wide_element_t<B>
const & b) { a / b; }
474 return NATIVE_WIDE_DETAIL::wide_binary(a, b, [](
auto const & x,
auto const & y) ->
decltype(x / y) {
return x / y; },
475 std::make_index_sequence<NATIVE_WIDE_DETAIL::wide_size<A, B>>{});
480 template<
class A,
class B>
requires NATIVE_WIDE_DETAIL::wide_arguments<A, B> && (::native::detail::wide_target<A,B> == NATIVE_WIDE_INDEX) &&
481 requires(NATIVE_WIDE_DETAIL::wide_element_t<A>
const & a, NATIVE_WIDE_DETAIL::wide_element_t<B>
const & b) { a % b; }
483 return NATIVE_WIDE_DETAIL::wide_binary(a, b, [](
auto const & x,
auto const & y) ->
decltype(x % y) {
return x % y; },
484 std::make_index_sequence<NATIVE_WIDE_DETAIL::wide_size<A, B>>{});
489 template<
class A,
class B>
requires NATIVE_WIDE_DETAIL::wide_arguments<A, B> && (::native::detail::wide_target<A,B> == NATIVE_WIDE_INDEX) &&
490 requires(NATIVE_WIDE_DETAIL::wide_element_t<A>
const & a, NATIVE_WIDE_DETAIL::wide_element_t<B>
const & b) { a & b; }
492 return NATIVE_WIDE_DETAIL::wide_binary(a, b, [](
auto const & x,
auto const & y) ->
decltype(x & y) {
return x & y; },
493 std::make_index_sequence<NATIVE_WIDE_DETAIL::wide_size<A, B>>{});
498 template<
class A,
class B>
requires NATIVE_WIDE_DETAIL::wide_arguments<A, B> && (::native::detail::wide_target<A,B> == NATIVE_WIDE_INDEX) &&
499 requires(NATIVE_WIDE_DETAIL::wide_element_t<A>
const & a, NATIVE_WIDE_DETAIL::wide_element_t<B>
const & b) { a | b; }
501 return NATIVE_WIDE_DETAIL::wide_binary(a, b, [](
auto const & x,
auto const & y) ->
decltype(x | y) {
return x | y; },
502 std::make_index_sequence<NATIVE_WIDE_DETAIL::wide_size<A, B>>{});
507 template<
class A,
class B>
requires NATIVE_WIDE_DETAIL::wide_arguments<A, B> && (::native::detail::wide_target<A,B> == NATIVE_WIDE_INDEX) &&
508 requires(NATIVE_WIDE_DETAIL::wide_element_t<A>
const & a, NATIVE_WIDE_DETAIL::wide_element_t<B>
const & b) { a ^ b; }
510 return NATIVE_WIDE_DETAIL::wide_binary(a, b, [](
auto const & x,
auto const & y) ->
decltype(x ^ y) {
return x ^ y; },
511 std::make_index_sequence<NATIVE_WIDE_DETAIL::wide_size<A, B>>{});
516 template<
class A,
class B>
requires NATIVE_WIDE_DETAIL::wide_arguments<A, B> && (::native::detail::wide_target<A,B> == NATIVE_WIDE_INDEX) &&
517 requires(NATIVE_WIDE_DETAIL::wide_element_t<A>
const & a, NATIVE_WIDE_DETAIL::wide_element_t<B>
const & b) { a << b; }
519 return NATIVE_WIDE_DETAIL::wide_binary(a, b, [](
auto const & x,
auto const & y) ->
decltype(x << y) {
return x << y; },
520 std::make_index_sequence<NATIVE_WIDE_DETAIL::wide_size<A, B>>{});
525 template<
class A,
class B>
requires NATIVE_WIDE_DETAIL::wide_arguments<A, B> && (::native::detail::wide_target<A,B> == NATIVE_WIDE_INDEX) &&
526 requires(NATIVE_WIDE_DETAIL::wide_element_t<A>
const & a, NATIVE_WIDE_DETAIL::wide_element_t<B>
const & b) { a >> b; }
528 return NATIVE_WIDE_DETAIL::wide_binary(a, b, [](
auto const & x,
auto const & y) ->
decltype(x >> y) {
return x >> y; },
529 std::make_index_sequence<NATIVE_WIDE_DETAIL::wide_size<A, B>>{});
534 template<
class A,
class B>
requires NATIVE_WIDE_DETAIL::wide_arguments<A, B> && (::native::detail::wide_target<A,B> == NATIVE_WIDE_INDEX) &&
535 requires(NATIVE_WIDE_DETAIL::wide_element_t<A>
const & a, NATIVE_WIDE_DETAIL::wide_element_t<B>
const & b) { a == b; }
537 return NATIVE_WIDE_DETAIL::wide_binary(a, b, [](
auto const & x,
auto const & y) ->
decltype(x == y) {
return x == y; },
538 std::make_index_sequence<NATIVE_WIDE_DETAIL::wide_size<A, B>>{});
543 template<
class A,
class B>
requires NATIVE_WIDE_DETAIL::wide_arguments<A, B> && (::native::detail::wide_target<A,B> == NATIVE_WIDE_INDEX) &&
544 requires(NATIVE_WIDE_DETAIL::wide_element_t<A>
const & a, NATIVE_WIDE_DETAIL::wide_element_t<B>
const & b) { a != b; }
546 return NATIVE_WIDE_DETAIL::wide_binary(a, b, [](
auto const & x,
auto const & y) ->
decltype(x != y) {
return x != y; },
547 std::make_index_sequence<NATIVE_WIDE_DETAIL::wide_size<A, B>>{});
552 template<
class A,
class B>
requires NATIVE_WIDE_DETAIL::wide_arguments<A, B> && (::native::detail::wide_target<A,B> == NATIVE_WIDE_INDEX) &&
553 requires(NATIVE_WIDE_DETAIL::wide_element_t<A>
const & a, NATIVE_WIDE_DETAIL::wide_element_t<B>
const & b) { a < b; }
555 return NATIVE_WIDE_DETAIL::wide_binary(a, b, [](
auto const & x,
auto const & y) ->
decltype(x < y) {
return x < y; },
556 std::make_index_sequence<NATIVE_WIDE_DETAIL::wide_size<A, B>>{});
561 template<
class A,
class B>
requires NATIVE_WIDE_DETAIL::wide_arguments<A, B> && (::native::detail::wide_target<A,B> == NATIVE_WIDE_INDEX) &&
562 requires(NATIVE_WIDE_DETAIL::wide_element_t<A>
const & a, NATIVE_WIDE_DETAIL::wide_element_t<B>
const & b) { a > b; }
564 return NATIVE_WIDE_DETAIL::wide_binary(a, b, [](
auto const & x,
auto const & y) ->
decltype(x > y) {
return x > y; },
565 std::make_index_sequence<NATIVE_WIDE_DETAIL::wide_size<A, B>>{});
570 template<
class A,
class B>
requires NATIVE_WIDE_DETAIL::wide_arguments<A, B> && (::native::detail::wide_target<A,B> == NATIVE_WIDE_INDEX) &&
571 requires(NATIVE_WIDE_DETAIL::wide_element_t<A>
const & a, NATIVE_WIDE_DETAIL::wide_element_t<B>
const & b) { a <= b; }
573 return NATIVE_WIDE_DETAIL::wide_binary(a, b, [](
auto const & x,
auto const & y) ->
decltype(x <= y) {
return x <= y; },
574 std::make_index_sequence<NATIVE_WIDE_DETAIL::wide_size<A, B>>{});
579 template<
class A,
class B>
requires NATIVE_WIDE_DETAIL::wide_arguments<A, B> && (::native::detail::wide_target<A,B> == NATIVE_WIDE_INDEX) &&
580 requires(NATIVE_WIDE_DETAIL::wide_element_t<A>
const & a, NATIVE_WIDE_DETAIL::wide_element_t<B>
const & b) { a >= b; }
582 return NATIVE_WIDE_DETAIL::wide_binary(a, b, [](
auto const & x,
auto const & y) ->
decltype(x >= y) {
return x >= y; },
583 std::make_index_sequence<NATIVE_WIDE_DETAIL::wide_size<A, B>>{});
588 template<
class T, std::
size_t N>
requires (::native::detail::wide_target<T> == NATIVE_WIDE_INDEX) &&
requires(T
const & a) { +a; }
590 return NATIVE_WIDE_DETAIL::wide_unary(a, [](
auto const & x) ->
decltype(+x) {
return +x; }, std::make_index_sequence<N>{});
595 template<
class T, std::
size_t N>
requires (::native::detail::wide_target<T> == NATIVE_WIDE_INDEX) &&
requires(T
const & a) { -a; }
597 return NATIVE_WIDE_DETAIL::wide_unary(a, [](
auto const & x) ->
decltype(-x) {
return -x; }, std::make_index_sequence<N>{});
602 template<
class T, std::
size_t N>
requires (::native::detail::wide_target<T> == NATIVE_WIDE_INDEX) &&
requires(T
const & a) { ~a; }
604 return NATIVE_WIDE_DETAIL::wide_unary(a, [](
auto const & x) ->
decltype(~x) {
return ~x; }, std::make_index_sequence<N>{});
609 template<
class T, std::
size_t N>
requires (::native::detail::wide_target<T> == NATIVE_WIDE_INDEX) &&
requires(T
const & a) { !a; }
611 return NATIVE_WIDE_DETAIL::wide_unary(a, [](
auto const & x) ->
decltype(!x) {
return !x; }, std::make_index_sequence<N>{});
616 template<
class T, std::
size_t N,
class B>
requires (::native::detail::wide_target<T,B> == NATIVE_WIDE_INDEX) && NATIVE_WIDE_DETAIL::wide_arguments<wide<T, N>, B> &&
617 (NATIVE_WIDE_DETAIL::wide_batch_assignable<wide<T,N>,B,NATIVE_WIDE_DETAIL::wide_add> ||
618 ((NATIVE_WIDE_DETAIL::wide_traits<B>::value || std::copy_constructible<B>) &&
619 requires(T & a, NATIVE_WIDE_DETAIL::wide_element_t<B>
const & b) { a += b; })))
622 if constexpr (NATIVE_WIDE_DETAIL::wide_batch_assignable<wide<T,N>,B,NATIVE_WIDE_DETAIL::wide_add>)
623 return noexcept(std::declval<
wide<T,N> &>() = NATIVE_WIDE_DETAIL::wide_dispatch(
624 std::declval<
wide<T,N> const &>(),std::declval<B const &>(),NATIVE_WIDE_DETAIL::wide_add{}));
627 if constexpr (NATIVE_WIDE_DETAIL::wide_batch_assignable<wide<T,N>,B,NATIVE_WIDE_DETAIL::wide_add>)
628 return a = NATIVE_WIDE_DETAIL::wide_dispatch(a,b,NATIVE_WIDE_DETAIL::wide_add{});
629 else return NATIVE_WIDE_DETAIL::wide_mutate(a, b, [](
auto & x,
auto const & y) { x += y; }, std::make_index_sequence<N>{});
634 template<
class T, std::
size_t N,
class B>
requires (::native::detail::wide_target<T,B> == NATIVE_WIDE_INDEX) && NATIVE_WIDE_DETAIL::wide_arguments<
wide<T, N>, B> &&
635 (NATIVE_WIDE_DETAIL::wide_batch_assignable<
wide<T,N>,B,NATIVE_WIDE_DETAIL::wide_sub> ||
636 ((NATIVE_WIDE_DETAIL::wide_traits<B>::value || std::copy_constructible<B>) &&
637 requires(T & a, NATIVE_WIDE_DETAIL::wide_element_t<B>
const & b) { a -= b; })))
640 if constexpr (NATIVE_WIDE_DETAIL::wide_batch_assignable<wide<T,N>,B,NATIVE_WIDE_DETAIL::wide_sub>)
641 return noexcept(std::declval<
wide<T,N> &>() = NATIVE_WIDE_DETAIL::wide_dispatch(
642 std::declval<
wide<T,N> const &>(),std::declval<B const &>(),NATIVE_WIDE_DETAIL::wide_sub{}));
645 if constexpr (NATIVE_WIDE_DETAIL::wide_batch_assignable<wide<T,N>,B,NATIVE_WIDE_DETAIL::wide_sub>)
646 return a = NATIVE_WIDE_DETAIL::wide_dispatch(a,b,NATIVE_WIDE_DETAIL::wide_sub{});
647 else return NATIVE_WIDE_DETAIL::wide_mutate(a, b, [](
auto & x,
auto const & y) { x -= y; }, std::make_index_sequence<N>{});
652 template<
class T, std::
size_t N,
class B>
requires (::native::detail::wide_target<T,B> == NATIVE_WIDE_INDEX) && NATIVE_WIDE_DETAIL::wide_arguments<
wide<T, N>, B> &&
653 (NATIVE_WIDE_DETAIL::wide_batch_assignable<
wide<T,N>,B,NATIVE_WIDE_DETAIL::wide_mul> ||
654 ((NATIVE_WIDE_DETAIL::wide_traits<B>::value || std::copy_constructible<B>) &&
655 requires(T & a, NATIVE_WIDE_DETAIL::wide_element_t<B>
const & b) { a *= b; })))
658 if constexpr (NATIVE_WIDE_DETAIL::wide_batch_assignable<wide<T,N>,B,NATIVE_WIDE_DETAIL::wide_mul>)
659 return noexcept(std::declval<
wide<T,N> &>() = NATIVE_WIDE_DETAIL::wide_dispatch(
660 std::declval<
wide<T,N> const &>(),std::declval<B const &>(),NATIVE_WIDE_DETAIL::wide_mul{}));
663 if constexpr (NATIVE_WIDE_DETAIL::wide_batch_assignable<wide<T,N>,B,NATIVE_WIDE_DETAIL::wide_mul>)
664 return a = NATIVE_WIDE_DETAIL::wide_dispatch(a,b,NATIVE_WIDE_DETAIL::wide_mul{});
665 else return NATIVE_WIDE_DETAIL::wide_mutate(a, b, [](
auto & x,
auto const & y) { x *= y; }, std::make_index_sequence<N>{});
670 template<
class T, std::
size_t N,
class B>
requires (::native::detail::wide_target<T,B> == NATIVE_WIDE_INDEX) && NATIVE_WIDE_DETAIL::wide_arguments<
wide<T, N>, B> &&
671 (NATIVE_WIDE_DETAIL::wide_traits<B>::value || std::copy_constructible<B>) &&
672 requires(T & a, NATIVE_WIDE_DETAIL::wide_element_t<B>
const & b) { a /= b; }
674 return NATIVE_WIDE_DETAIL::wide_mutate(a, b, [](
auto & x,
auto const & y) { x /= y; }, std::make_index_sequence<N>{});
679 template<
class T, std::
size_t N,
class B>
requires (::native::detail::wide_target<T,B> == NATIVE_WIDE_INDEX) && NATIVE_WIDE_DETAIL::wide_arguments<wide<T, N>, B> &&
680 (NATIVE_WIDE_DETAIL::wide_traits<B>::value || std::copy_constructible<B>) &&
681 requires(T & a, NATIVE_WIDE_DETAIL::wide_element_t<B>
const & b) { a %= b; }
683 return NATIVE_WIDE_DETAIL::wide_mutate(a, b, [](
auto & x,
auto const & y) { x %= y; }, std::make_index_sequence<N>{});
688 template<
class T, std::
size_t N,
class B>
requires (::native::detail::wide_target<T,B> == NATIVE_WIDE_INDEX) && NATIVE_WIDE_DETAIL::wide_arguments<wide<T, N>, B> &&
689 (NATIVE_WIDE_DETAIL::wide_traits<B>::value || std::copy_constructible<B>) &&
690 requires(T & a, NATIVE_WIDE_DETAIL::wide_element_t<B>
const & b) { a &= b; }
692 return NATIVE_WIDE_DETAIL::wide_mutate(a, b, [](
auto & x,
auto const & y) { x &= y; }, std::make_index_sequence<N>{});
697 template<
class T, std::
size_t N,
class B>
requires (::native::detail::wide_target<T,B> == NATIVE_WIDE_INDEX) && NATIVE_WIDE_DETAIL::wide_arguments<wide<T, N>, B> &&
698 (NATIVE_WIDE_DETAIL::wide_traits<B>::value || std::copy_constructible<B>) &&
699 requires(T & a, NATIVE_WIDE_DETAIL::wide_element_t<B>
const & b) { a |= b; }
701 return NATIVE_WIDE_DETAIL::wide_mutate(a, b, [](
auto & x,
auto const & y) { x |= y; }, std::make_index_sequence<N>{});
706 template<
class T, std::
size_t N,
class B>
requires (::native::detail::wide_target<T,B> == NATIVE_WIDE_INDEX) && NATIVE_WIDE_DETAIL::wide_arguments<wide<T, N>, B> &&
707 (NATIVE_WIDE_DETAIL::wide_traits<B>::value || std::copy_constructible<B>) &&
708 requires(T & a, NATIVE_WIDE_DETAIL::wide_element_t<B>
const & b) { a ^= b; }
710 return NATIVE_WIDE_DETAIL::wide_mutate(a, b, [](
auto & x,
auto const & y) { x ^= y; }, std::make_index_sequence<N>{});
715 template<
class T, std::
size_t N,
class B>
requires (::native::detail::wide_target<T,B> == NATIVE_WIDE_INDEX) && NATIVE_WIDE_DETAIL::wide_arguments<wide<T, N>, B> &&
716 (NATIVE_WIDE_DETAIL::wide_traits<B>::value || std::copy_constructible<B>) &&
717 requires(T & a, NATIVE_WIDE_DETAIL::wide_element_t<B>
const & b) { a <<= b; }
719 return NATIVE_WIDE_DETAIL::wide_mutate(a, b, [](
auto & x,
auto const & y) { x <<= y; }, std::make_index_sequence<N>{});
724 template<
class T, std::
size_t N,
class B>
requires (::native::detail::wide_target<T,B> == NATIVE_WIDE_INDEX) && NATIVE_WIDE_DETAIL::wide_arguments<wide<T, N>, B> &&
725 (NATIVE_WIDE_DETAIL::wide_traits<B>::value || std::copy_constructible<B>) &&
726 requires(T & a, NATIVE_WIDE_DETAIL::wide_element_t<B>
const & b) { a >>= b; }
728 return NATIVE_WIDE_DETAIL::wide_mutate(a, b, [](
auto & x,
auto const & y) { x >>= y; }, std::make_index_sequence<N>{});
731 namespace NATIVE_WIDE_DETAIL {
732 using namespace ::native::detail;
746 template<
class... A>
native_inline constexpr auto adl_abs(A
const &... a)
747 noexcept(
noexcept(abs(a...))) ->
decltype(abs(a...)) {
return abs(a...); }
748 template<
class... A>
native_inline constexpr auto adl_sqrt(A
const &... a)
749 noexcept(
noexcept(
sqrt(a...))) ->
decltype(
sqrt(a...)) {
return sqrt(a...); }
750 template<
class... A>
native_inline constexpr auto adl_fma(A
const &... a)
751 noexcept(
noexcept(
fma(a...))) ->
decltype(
fma(a...)) {
return fma(a...); }
752 template<
class... A>
native_inline constexpr auto adl_sin(A
const &... a)
753 noexcept(
noexcept(sin(a...))) ->
decltype(sin(a...)) {
return sin(a...); }
754 template<
class... A>
native_inline constexpr auto adl_cos(A
const &... a)
755 noexcept(
noexcept(cos(a...))) ->
decltype(cos(a...)) {
return cos(a...); }
756 template<
class... A>
native_inline constexpr auto adl_expm1(A
const &... a)
757 noexcept(
noexcept(expm1(a...))) ->
decltype(expm1(a...)) {
return expm1(a...); }
758 template<
class... A>
native_inline constexpr auto adl_damping_gain(A
const &... a)
759 noexcept(
noexcept(damping_gain(a...))) ->
decltype(damping_gain(a...)) {
return damping_gain(a...); }
760 template<
class... A>
native_inline constexpr auto adl_log(A
const &... a)
761 noexcept(
noexcept(log(a...))) ->
decltype(log(a...)) {
return log(a...); }
762 template<
class... A>
native_inline constexpr auto adl_log2(A
const &... a)
763 noexcept(
noexcept(log2(a...))) ->
decltype(log2(a...)) {
return log2(a...); }
764 template<
class... A>
native_inline constexpr auto adl_log1p(A
const &... a)
765 noexcept(
noexcept(log1p(a...))) ->
decltype(log1p(a...)) {
return log1p(a...); }
766 template<
class... A>
native_inline constexpr auto adl_atan2(A
const &... a)
767 noexcept(
noexcept(
atan2(a...))) ->
decltype(
atan2(a...)) {
return atan2(a...); }
768 template<
class... A>
native_inline constexpr auto adl_tanh(A
const &... a)
769 noexcept(
noexcept(tanh(a...))) ->
decltype(tanh(a...)) {
return tanh(a...); }
770 template<
bool Flush,
unsigned Degree,
class A>
771 requires requires(A
const & a) { exp(a,std::bool_constant<Flush>{},std::integral_constant<unsigned,Degree>{}); }
773 noexcept(
noexcept(exp(a,std::bool_constant<Flush>{},std::integral_constant<unsigned,Degree>{})))
774 ->
decltype(exp(a,std::bool_constant<Flush>{},std::integral_constant<unsigned,Degree>{})) {
775 return exp(a,std::bool_constant<Flush>{},std::integral_constant<unsigned,Degree>{});
777 template<
bool Flush,
unsigned Degree,
class A>
778 requires (Degree == 6) &&
779 (!
requires(A
const & a) { exp(a,std::bool_constant<Flush>{},std::integral_constant<unsigned,Degree>{}); }) &&
780 requires(A
const & a) { exp(a,std::bool_constant<Flush>{}); }
782 noexcept(
noexcept(exp(a,std::bool_constant<Flush>{}))) ->
decltype(exp(a,std::bool_constant<Flush>{})) {
783 return exp(a,std::bool_constant<Flush>{});
785 template<
bool Flush,
unsigned Degree,
class A>
786 requires (!Flush && Degree == 6) &&
787 (!
requires(A
const & a) { exp(a,std::bool_constant<Flush>{},std::integral_constant<unsigned,Degree>{}); }) &&
788 (!
requires(A
const & a) { exp(a,std::bool_constant<Flush>{}); })
789 native_inline constexpr auto adl_exp(A
const & a)
noexcept(
noexcept(exp(a))) ->
decltype(exp(a)) {
return exp(a); }
790 template<
bool Flush,
class A>
requires requires(A
const & a) {
exp2(a,std::bool_constant<Flush>{}); }
791 native_inline constexpr auto adl_exp2(A
const & a)
noexcept(
noexcept(
exp2(a,std::bool_constant<Flush>{}))) ->
decltype(
exp2(a,std::bool_constant<Flush>{})) {
return exp2(a,std::bool_constant<Flush>{}); }
792 template<
bool Flush,
class A>
requires (!Flush) && (!
requires(A
const & a) {
exp2(a,std::bool_constant<Flush>{}); })
794 template<
class A>
native_inline constexpr auto adl_sincos(A
const & a)
795 noexcept(
noexcept(sincos(a))) ->
decltype(sincos(a)) {
return sincos(a); }
796 template<
class M,
class T>
native_inline constexpr auto adl_select(M
const & m,T
const & a,T
const & b)
797 noexcept(
noexcept(select(m,a,b))) ->
decltype(select(m,a,b)) {
return select(m,a,b); }
799 namespace NATIVE_WIDE_DETAIL {
800 using namespace ::native::detail;
802 template<
class T>
requires std::is_arithmetic_v<T>
804 noexcept(
noexcept(std::isfinite(x))) ->
decltype(std::isfinite(x)) {
return std::isfinite(x); }
805 template<
class T>
requires std::is_arithmetic_v<T>
807 noexcept(
noexcept(std::isinf(x))) ->
decltype(std::isinf(x)) {
return std::isinf(x); }
808 template<
class T>
requires std::is_arithmetic_v<T>
811 template<
class T>
requires std::is_arithmetic_v<T>
813 noexcept(
noexcept(std::signbit(x))) ->
decltype(std::signbit(x)) {
return std::signbit(x); }
814 template<
class T>
requires std::is_arithmetic_v<T>
815 native_inline constexpr auto copysign(T
const & x,T
const & y)
816 noexcept(
noexcept(std::copysign(x,y))) ->
decltype(std::copysign(x,y)) {
return std::copysign(x,y); }
817 template<
class T>
requires std::is_floating_point_v<T>
819 noexcept(
noexcept(std::floor(x))) ->
decltype(std::floor(x)) {
return std::floor(x); }
821 template<
class T>
native_inline constexpr auto operator()(T
const & x)
const
822 noexcept(
noexcept(floor(x))) ->
decltype(floor(x)) {
return floor(x); }
824 template<
class T>
requires std::is_floating_point_v<T>
826 noexcept(
noexcept(std::ceil(x))) ->
decltype(std::ceil(x)) {
return std::ceil(x); }
828 template<
class T>
native_inline constexpr auto operator()(T
const & x)
const
829 noexcept(
noexcept(ceil(x))) ->
decltype(ceil(x)) {
return ceil(x); }
831 template<
class T>
requires std::is_floating_point_v<T>
833 noexcept(
noexcept(std::trunc(x))) ->
decltype(std::trunc(x)) {
return std::trunc(x); }
835 template<
class T>
native_inline constexpr auto operator()(T
const & x)
const
836 noexcept(
noexcept(trunc(x))) ->
decltype(trunc(x)) {
return trunc(x); }
838 struct wide_isfinite {
839 template<
class... T>
native_inline constexpr auto operator()(T
const &... x)
const
840 noexcept(
noexcept(isfinite(x...))) ->
decltype(isfinite(x...)) {
return isfinite(x...); }
843 template<
class... T>
native_inline constexpr auto operator()(T
const &... x)
const
844 noexcept(
noexcept(isinf(x...))) ->
decltype(isinf(x...)) {
return isinf(x...); }
847 template<
class... T>
native_inline constexpr auto operator()(T
const &... x)
const
848 noexcept(
noexcept(
isnan(x...))) ->
decltype(
isnan(x...)) {
return isnan(x...); }
850 struct wide_signbit {
851 template<
class... T>
native_inline constexpr auto operator()(T
const &... x)
const
852 noexcept(
noexcept(signbit(x...))) ->
decltype(signbit(x...)) {
return signbit(x...); }
854 struct wide_copysign {
855 template<
class... T>
native_inline constexpr auto operator()(T
const &... x)
const
856 noexcept(
noexcept(copysign(x...))) ->
decltype(copysign(x...)) {
return copysign(x...); }
858 template<
class F,
class... T>
859 using wide_result = std::remove_cvref_t<std::invoke_result_t<F,T
const &...>>;
860 template<std::size_t N,
class F,
class... T>
concept wide_value_operation =
861 std::invocable<F,T
const &...> && std::is_object_v<wide_result<F,T...>> &&
862 std::is_move_constructible_v<std::array<wide_result<F,T...>,N>> &&
863 (N == 0 ||
requires(T
const &... x) { std::array<wide_result<F,T...>,1>{F{}(x...)}; });
867 template<
class F,
class T,std::
size_t N>
requires wide_value_operation<N,F,T>
868 native_inline constexpr auto wide_map(wide<T,N>
const & input)
870 if constexpr (N == 0)
return true;
871 else return noexcept(wide<wide_result<F,T>,1>{
872 std::array<wide_result<F,T>,1>{F{}(std::declval<T const &>())}});
874 auto const & [...x] = input;
875 return wide<wide_result<F,T>,N>{std::array<wide_result<F,T>,N>{F{}(x)...}};
877 template<
class F,
class T,std::
size_t N>
requires wide_value_operation<N,F,T,T>
878 native_inline constexpr auto wide_map(wide<T,N>
const & a,wide<T,N>
const & b)
880 if constexpr (N == 0)
return true;
881 else return noexcept(wide<wide_result<F,T,T>,1>{
882 std::array<wide_result<F,T,T>,1>{F{}(std::declval<T const &>(),std::declval<T const &>())}});
884 auto const & [...x] = a;
885 auto const & [...y] = b;
886 return wide<wide_result<F,T,T>,N>{std::array<wide_result<F,T,T>,N>{F{}(x,y)...}};
892 template<
class T,std::
size_t N>
requires (::native::detail::wide_target<T> == NATIVE_WIDE_INDEX) && NATIVE_WIDE_DETAIL::wide_value_operation<N,NATIVE_WIDE_DETAIL::wide_isfinite,T>
894 noexcept(
noexcept(NATIVE_WIDE_DETAIL::wide_map<NATIVE_WIDE_DETAIL::wide_isfinite>(input))) {
895 return NATIVE_WIDE_DETAIL::wide_map<NATIVE_WIDE_DETAIL::wide_isfinite>(input);
899 template<
class T,std::
size_t N>
requires (::native::detail::wide_target<T> == NATIVE_WIDE_INDEX) && NATIVE_WIDE_DETAIL::wide_value_operation<N,NATIVE_WIDE_DETAIL::wide_isinf,T>
901 noexcept(
noexcept(NATIVE_WIDE_DETAIL::wide_map<NATIVE_WIDE_DETAIL::wide_isinf>(input))) {
902 return NATIVE_WIDE_DETAIL::wide_map<NATIVE_WIDE_DETAIL::wide_isinf>(input);
906 template<
class T,std::
size_t N>
requires (::native::detail::wide_target<T> == NATIVE_WIDE_INDEX) && NATIVE_WIDE_DETAIL::wide_value_operation<N,NATIVE_WIDE_DETAIL::wide_isnan,T>
908 noexcept(
noexcept(NATIVE_WIDE_DETAIL::wide_map<NATIVE_WIDE_DETAIL::wide_isnan>(input))) {
909 return NATIVE_WIDE_DETAIL::wide_map<NATIVE_WIDE_DETAIL::wide_isnan>(input);
913 template<
class T,std::
size_t N>
requires (::native::detail::wide_target<T> == NATIVE_WIDE_INDEX) && NATIVE_WIDE_DETAIL::wide_value_operation<N,NATIVE_WIDE_DETAIL::wide_signbit,T>
915 noexcept(
noexcept(NATIVE_WIDE_DETAIL::wide_map<NATIVE_WIDE_DETAIL::wide_signbit>(input))) {
916 return NATIVE_WIDE_DETAIL::wide_map<NATIVE_WIDE_DETAIL::wide_signbit>(input);
921 template<
class T,std::
size_t N>
requires (::native::detail::wide_target<T> == NATIVE_WIDE_INDEX) && NATIVE_WIDE_DETAIL::wide_value_operation<N,NATIVE_WIDE_DETAIL::wide_copysign,T,T> &&
922 std::same_as<NATIVE_WIDE_DETAIL::wide_result<NATIVE_WIDE_DETAIL::wide_copysign,T,T>,T>
924 noexcept(
noexcept(NATIVE_WIDE_DETAIL::wide_map<NATIVE_WIDE_DETAIL::wide_copysign>(a,b))) {
925 return NATIVE_WIDE_DETAIL::wide_map<NATIVE_WIDE_DETAIL::wide_copysign>(a,b);
930 template<
class T,std::
size_t N>
requires (::native::detail::wide_target<T> == NATIVE_WIDE_INDEX) && NATIVE_WIDE_DETAIL::wide_value_operation<N,NATIVE_WIDE_DETAIL::wide_floor,T> &&
931 std::same_as<NATIVE_WIDE_DETAIL::wide_result<NATIVE_WIDE_DETAIL::wide_floor,T>,T>
933 noexcept(
noexcept(NATIVE_WIDE_DETAIL::wide_map<NATIVE_WIDE_DETAIL::wide_floor>(input))) {
934 return NATIVE_WIDE_DETAIL::wide_map<NATIVE_WIDE_DETAIL::wide_floor>(input);
938 template<
class T,std::
size_t N>
requires (::native::detail::wide_target<T> == NATIVE_WIDE_INDEX) && NATIVE_WIDE_DETAIL::wide_value_operation<N,NATIVE_WIDE_DETAIL::wide_ceil,T> &&
939 std::same_as<NATIVE_WIDE_DETAIL::wide_result<NATIVE_WIDE_DETAIL::wide_ceil,T>,T>
941 noexcept(
noexcept(NATIVE_WIDE_DETAIL::wide_map<NATIVE_WIDE_DETAIL::wide_ceil>(input))) {
942 return NATIVE_WIDE_DETAIL::wide_map<NATIVE_WIDE_DETAIL::wide_ceil>(input);
946 template<
class T,std::
size_t N>
requires (::native::detail::wide_target<T> == NATIVE_WIDE_INDEX) && NATIVE_WIDE_DETAIL::wide_value_operation<N,NATIVE_WIDE_DETAIL::wide_trunc,T> &&
947 std::same_as<NATIVE_WIDE_DETAIL::wide_result<NATIVE_WIDE_DETAIL::wide_trunc,T>,T>
949 noexcept(
noexcept(NATIVE_WIDE_DETAIL::wide_map<NATIVE_WIDE_DETAIL::wide_trunc>(input))) {
950 return NATIVE_WIDE_DETAIL::wide_map<NATIVE_WIDE_DETAIL::wide_trunc>(input);
954 template<
class R,std::
size_t N>
requires (::native::detail::wide_target<R> == NATIVE_WIDE_INDEX)
960 template<
class R,std::
size_t N>
requires (::native::detail::wide_target<R> == NATIVE_WIDE_INDEX) &&
requires(R
const & x) { NATIVE_WIDE_DETAIL::adl_abs(x); }
963 if constexpr (
requires(std::array<R,N>
const & a) { NATIVE_WIDE_DETAIL::adl_abs(a); })
964 return noexcept(
wide<R,N>{NATIVE_WIDE_DETAIL::adl_abs(std::declval<std::array<R,N>
const &>())});
965 else return noexcept(
wide<R,N>()) && std::is_nothrow_move_constructible_v<
wide<R,N>> &&
966 (N == 0 ||
noexcept(std::declval<R &>() = NATIVE_WIDE_DETAIL::adl_abs(std::declval<R const &>())));
968 if constexpr (
requires { NATIVE_WIDE_DETAIL::adl_abs(input.registers); })
969 return wide<R,N>{NATIVE_WIDE_DETAIL::adl_abs(input.registers)};
972 auto & [...value] = result;
973 auto const & [...x] = input;
974 ([&] { value = NATIVE_WIDE_DETAIL::adl_abs(x); }(), ...);
981 template<
class R,std::
size_t N>
requires (::native::detail::wide_target<R> == NATIVE_WIDE_INDEX) &&
requires(R
const & x) { NATIVE_WIDE_DETAIL::adl_sqrt(x); }
984 if constexpr (
requires(std::array<R,N>
const & a) { NATIVE_WIDE_DETAIL::adl_sqrt(a); })
985 return noexcept(
wide<R,N>{NATIVE_WIDE_DETAIL::adl_sqrt(std::declval<std::array<R,N>
const &>())});
986 else return noexcept(
wide<R,N>()) && std::is_nothrow_move_constructible_v<
wide<R,N>> &&
987 (N == 0 ||
noexcept(std::declval<R &>() = NATIVE_WIDE_DETAIL::adl_sqrt(std::declval<R const &>())));
989 if constexpr (
requires { NATIVE_WIDE_DETAIL::adl_sqrt(input.registers); })
990 return wide<R,N>{NATIVE_WIDE_DETAIL::adl_sqrt(input.registers)};
993 auto & [...value] = result;
994 auto const & [...x] = input;
995 ([&] { value = NATIVE_WIDE_DETAIL::adl_sqrt(x); }(), ...);
1002 template<
class R,std::
size_t N>
requires (::native::detail::wide_target<R> == NATIVE_WIDE_INDEX) &&
requires(R
const & x) { NATIVE_WIDE_DETAIL::adl_sin(x); }
1005 if constexpr (
requires(std::array<R,N>
const & a) { NATIVE_WIDE_DETAIL::adl_sin(a); })
1006 return noexcept(
wide<R,N>{NATIVE_WIDE_DETAIL::adl_sin(std::declval<std::array<R,N>
const &>())});
1007 else return noexcept(
wide<R,N>()) && std::is_nothrow_move_constructible_v<
wide<R,N>> &&
1008 (N == 0 ||
noexcept(std::declval<R &>() = NATIVE_WIDE_DETAIL::adl_sin(std::declval<R const &>())));
1010 if constexpr (
requires { NATIVE_WIDE_DETAIL::adl_sin(input.registers); })
1011 return wide<R,N>{NATIVE_WIDE_DETAIL::adl_sin(input.registers)};
1014 auto & [...value] = result;
1015 auto const & [...x] = input;
1016 ([&] { value = NATIVE_WIDE_DETAIL::adl_sin(x); }(), ...);
1023 template<
class R,std::
size_t N>
requires (::native::detail::wide_target<R> == NATIVE_WIDE_INDEX) &&
requires(R
const & x) { NATIVE_WIDE_DETAIL::adl_cos(x); }
1026 if constexpr (
requires(std::array<R,N>
const & a) { NATIVE_WIDE_DETAIL::adl_cos(a); })
1027 return noexcept(
wide<R,N>{NATIVE_WIDE_DETAIL::adl_cos(std::declval<std::array<R,N>
const &>())});
1028 else return noexcept(
wide<R,N>()) && std::is_nothrow_move_constructible_v<
wide<R,N>> &&
1029 (N == 0 ||
noexcept(std::declval<R &>() = NATIVE_WIDE_DETAIL::adl_cos(std::declval<R const &>())));
1031 if constexpr (
requires { NATIVE_WIDE_DETAIL::adl_cos(input.registers); })
1032 return wide<R,N>{NATIVE_WIDE_DETAIL::adl_cos(input.registers)};
1035 auto & [...value] = result;
1036 auto const & [...x] = input;
1037 ([&] { value = NATIVE_WIDE_DETAIL::adl_cos(x); }(), ...);
1045 template<
bool Flush = false,
unsigned Degree = 6,
class R,std::
size_t N>
requires (Degree >= 1 && Degree <= 7) && (::native::detail::wide_target<R> == NATIVE_WIDE_INDEX) &&
requires(R
const & x) { NATIVE_WIDE_DETAIL::adl_exp<Flush,Degree>(x); }
1048 if constexpr (
requires(std::array<R,N>
const & a) { NATIVE_WIDE_DETAIL::adl_exp<Flush,Degree>(a); })
1049 return noexcept(
wide<R,N>{NATIVE_WIDE_DETAIL::adl_exp<Flush,Degree>(std::declval<std::array<R,N>
const &>())});
1050 else return noexcept(
wide<R,N>()) && std::is_nothrow_move_constructible_v<
wide<R,N>> &&
1051 (N == 0 ||
noexcept(std::declval<R &>() = NATIVE_WIDE_DETAIL::adl_exp<Flush,Degree>(std::declval<R const &>())));
1053 if constexpr (
requires { NATIVE_WIDE_DETAIL::adl_exp<Flush,Degree>(input.registers); })
1054 return wide<R,N>{NATIVE_WIDE_DETAIL::adl_exp<Flush,Degree>(input.registers)};
1057 auto & [...value] = result;
1058 auto const & [...x] = input;
1059 ([&] { value = NATIVE_WIDE_DETAIL::adl_exp<Flush,Degree>(x); }(), ...);
1066 template<
bool Flush = false,
class R,std::
size_t N>
requires (::native::detail::wide_target<R> == NATIVE_WIDE_INDEX) &&
requires(R
const & x) { NATIVE_WIDE_DETAIL::adl_exp2<Flush>(x); }
1069 if constexpr (
requires(std::array<R,N>
const & a) { NATIVE_WIDE_DETAIL::adl_exp2<Flush>(a); })
1070 return noexcept(
wide<R,N>{NATIVE_WIDE_DETAIL::adl_exp2<Flush>(std::declval<std::array<R,N>
const &>())});
1071 else return noexcept(
wide<R,N>()) && std::is_nothrow_move_constructible_v<
wide<R,N>> &&
1072 (N == 0 ||
noexcept(std::declval<R &>() = NATIVE_WIDE_DETAIL::adl_exp2<Flush>(std::declval<R const &>())));
1074 if constexpr (
requires { NATIVE_WIDE_DETAIL::adl_exp2<Flush>(input.registers); })
1075 return wide<R,N>{NATIVE_WIDE_DETAIL::adl_exp2<Flush>(input.registers)};
1078 auto & [...value] = result;
1079 auto const & [...x] = input;
1080 ([&] { value = NATIVE_WIDE_DETAIL::adl_exp2<Flush>(x); }(), ...);
1087 template<
class R,std::
size_t N>
requires (::native::detail::wide_target<R> == NATIVE_WIDE_INDEX) &&
requires(R
const & x) { NATIVE_WIDE_DETAIL::adl_expm1(x); }
1090 if constexpr (
requires(std::array<R,N>
const & a) { NATIVE_WIDE_DETAIL::adl_expm1(a); })
1091 return noexcept(
wide<R,N>{NATIVE_WIDE_DETAIL::adl_expm1(std::declval<std::array<R,N>
const &>())});
1092 else return noexcept(
wide<R,N>()) && std::is_nothrow_move_constructible_v<
wide<R,N>> &&
1093 (N == 0 ||
noexcept(std::declval<R &>() = NATIVE_WIDE_DETAIL::adl_expm1(std::declval<R const &>())));
1095 if constexpr (
requires { NATIVE_WIDE_DETAIL::adl_expm1(input.registers); })
1096 return wide<R,N>{NATIVE_WIDE_DETAIL::adl_expm1(input.registers)};
1099 auto & [...value] = result;
1100 auto const & [...x] = input;
1101 ([&] { value = NATIVE_WIDE_DETAIL::adl_expm1(x); }(), ...);
1108 template<
class R,std::
size_t N>
requires (::native::detail::wide_target<R> == NATIVE_WIDE_INDEX) &&
requires(R
const & x) { NATIVE_WIDE_DETAIL::adl_damping_gain(x); }
1111 if constexpr (
requires(std::array<R,N>
const & a) { NATIVE_WIDE_DETAIL::adl_damping_gain(a); })
1112 return noexcept(
wide<R,N>{NATIVE_WIDE_DETAIL::adl_damping_gain(std::declval<std::array<R,N>
const &>())});
1113 else return noexcept(
wide<R,N>()) && std::is_nothrow_move_constructible_v<
wide<R,N>> &&
1114 (N == 0 ||
noexcept(std::declval<R &>() = NATIVE_WIDE_DETAIL::adl_damping_gain(std::declval<R const &>())));
1116 if constexpr (
requires { NATIVE_WIDE_DETAIL::adl_damping_gain(input.registers); })
1117 return wide<R,N>{NATIVE_WIDE_DETAIL::adl_damping_gain(input.registers)};
1120 auto & [...value] = result;
1121 auto const & [...x] = input;
1122 ([&] { value = NATIVE_WIDE_DETAIL::adl_damping_gain(x); }(), ...);
1129 template<
class R,std::
size_t N>
requires (::native::detail::wide_target<R> == NATIVE_WIDE_INDEX) &&
requires(R
const & x) { NATIVE_WIDE_DETAIL::adl_log(x); }
1132 if constexpr (
requires(std::array<R,N>
const & a) { NATIVE_WIDE_DETAIL::adl_log(a); })
1133 return noexcept(
wide<R,N>{NATIVE_WIDE_DETAIL::adl_log(std::declval<std::array<R,N>
const &>())});
1134 else return noexcept(
wide<R,N>()) && std::is_nothrow_move_constructible_v<
wide<R,N>> &&
1135 (N == 0 ||
noexcept(std::declval<R &>() = NATIVE_WIDE_DETAIL::adl_log(std::declval<R const &>())));
1137 if constexpr (
requires { NATIVE_WIDE_DETAIL::adl_log(input.registers); })
1138 return wide<R,N>{NATIVE_WIDE_DETAIL::adl_log(input.registers)};
1141 auto & [...value] = result;
1142 auto const & [...x] = input;
1143 ([&] { value = NATIVE_WIDE_DETAIL::adl_log(x); }(), ...);
1150 template<
class R,std::
size_t N>
requires (::native::detail::wide_target<R> == NATIVE_WIDE_INDEX) &&
requires(R
const & x) { NATIVE_WIDE_DETAIL::adl_log2(x); }
1153 if constexpr (
requires(std::array<R,N>
const & a) { NATIVE_WIDE_DETAIL::adl_log2(a); })
1154 return noexcept(
wide<R,N>{NATIVE_WIDE_DETAIL::adl_log2(std::declval<std::array<R,N>
const &>())});
1155 else return noexcept(
wide<R,N>()) && std::is_nothrow_move_constructible_v<
wide<R,N>> &&
1156 (N == 0 ||
noexcept(std::declval<R &>() = NATIVE_WIDE_DETAIL::adl_log2(std::declval<R const &>())));
1158 if constexpr (
requires { NATIVE_WIDE_DETAIL::adl_log2(input.registers); })
1159 return wide<R,N>{NATIVE_WIDE_DETAIL::adl_log2(input.registers)};
1162 auto & [...value] = result;
1163 auto const & [...x] = input;
1164 ([&] { value = NATIVE_WIDE_DETAIL::adl_log2(x); }(), ...);
1171 template<
class R,std::
size_t N>
requires (::native::detail::wide_target<R> == NATIVE_WIDE_INDEX) &&
requires(R
const & x) { NATIVE_WIDE_DETAIL::adl_log1p(x); }
1174 if constexpr (
requires(std::array<R,N>
const & a) { NATIVE_WIDE_DETAIL::adl_log1p(a); })
1175 return noexcept(
wide<R,N>{NATIVE_WIDE_DETAIL::adl_log1p(std::declval<std::array<R,N>
const &>())});
1176 else return noexcept(
wide<R,N>()) && std::is_nothrow_move_constructible_v<
wide<R,N>> &&
1177 (N == 0 ||
noexcept(std::declval<R &>() = NATIVE_WIDE_DETAIL::adl_log1p(std::declval<R const &>())));
1179 if constexpr (
requires { NATIVE_WIDE_DETAIL::adl_log1p(input.registers); })
1180 return wide<R,N>{NATIVE_WIDE_DETAIL::adl_log1p(input.registers)};
1183 auto & [...value] = result;
1184 auto const & [...x] = input;
1185 ([&] { value = NATIVE_WIDE_DETAIL::adl_log1p(x); }(), ...);
1192 template<
class R,std::
size_t N>
requires (::native::detail::wide_target<R> == NATIVE_WIDE_INDEX) &&
requires(R
const & x) { NATIVE_WIDE_DETAIL::adl_tanh(x); }
1195 if constexpr (
requires(std::array<R,N>
const & a) { NATIVE_WIDE_DETAIL::adl_tanh(a); })
1196 return noexcept(
wide<R,N>{NATIVE_WIDE_DETAIL::adl_tanh(std::declval<std::array<R,N>
const &>())});
1197 else return noexcept(
wide<R,N>()) && std::is_nothrow_move_constructible_v<
wide<R,N>> &&
1198 (N == 0 ||
noexcept(std::declval<R &>() = NATIVE_WIDE_DETAIL::adl_tanh(std::declval<R const &>())));
1200 if constexpr (
requires { NATIVE_WIDE_DETAIL::adl_tanh(input.registers); })
1201 return wide<R,N>{NATIVE_WIDE_DETAIL::adl_tanh(input.registers)};
1204 auto & [...value] = result;
1205 auto const & [...x] = input;
1206 ([&] { value = NATIVE_WIDE_DETAIL::adl_tanh(x); }(), ...);
1213 template<
class R,std::
size_t N>
requires (::native::detail::wide_target<R> == NATIVE_WIDE_INDEX) &&
requires(R
const & x) { NATIVE_WIDE_DETAIL::adl_atan2(x,x); }
1216 if constexpr (
requires(std::array<R,N>
const & a) { NATIVE_WIDE_DETAIL::adl_atan2(a,a); })
1217 return noexcept(
wide<R,N>{NATIVE_WIDE_DETAIL::adl_atan2(std::declval<std::array<R,N>
const &>(),
1218 std::declval<std::array<R,N>
const &>())});
1219 else return noexcept(
wide<R,N>()) && std::is_nothrow_move_constructible_v<
wide<R,N>> &&
1220 (N == 0 ||
noexcept(std::declval<R &>() = NATIVE_WIDE_DETAIL::adl_atan2(
1221 std::declval<R const &>(),std::declval<R const &>())));
1223 if constexpr (
requires { NATIVE_WIDE_DETAIL::adl_atan2(y.registers,x.registers); })
1224 return wide<R,N>{NATIVE_WIDE_DETAIL::adl_atan2(y.registers,x.registers)};
1227 auto & [...value] = result;
1228 auto const & [...a] = y;
1229 auto const & [...b] = x;
1230 ([&] { value = NATIVE_WIDE_DETAIL::adl_atan2(a,b); }(), ...);
1237 template<
class R,std::
size_t N>
requires (::native::detail::wide_target<R> == NATIVE_WIDE_INDEX) &&
requires(R
const & x) { NATIVE_WIDE_DETAIL::adl_fma(x,x,x); }
1240 if constexpr (
requires(std::array<R,N>
const & x) { NATIVE_WIDE_DETAIL::adl_fma(x,x,x); })
1241 return noexcept(
wide<R,N>{NATIVE_WIDE_DETAIL::adl_fma(std::declval<std::array<R,N>
const &>(),
1242 std::declval<std::array<R,N>
const &>(),std::declval<std::array<R,N>
const &>())});
1243 else return noexcept(
wide<R,N>()) && std::is_nothrow_move_constructible_v<
wide<R,N>> &&
1244 (N == 0 ||
noexcept(std::declval<R &>() = NATIVE_WIDE_DETAIL::adl_fma(
1245 std::declval<R const &>(),std::declval<R const &>(),std::declval<R const &>())));
1247 if constexpr (
requires { NATIVE_WIDE_DETAIL::adl_fma(a.registers,b.registers,c.registers); })
1248 return wide<R,N>{NATIVE_WIDE_DETAIL::adl_fma(a.registers,b.registers,c.registers)};
1251 auto & [...value] = result;
1252 auto const & [...x] = a;
1253 auto const & [...y] = b;
1254 auto const & [...z] = c;
1255 ([&] { value = NATIVE_WIDE_DETAIL::adl_fma(x,y,z); }(), ...);
1262 template<
class R,std::
size_t N>
requires (::native::detail::wide_target<R> == NATIVE_WIDE_INDEX) &&
requires(R
const & x) { NATIVE_WIDE_DETAIL::adl_sincos(x); }
1265 if constexpr (
requires(std::array<R,N>
const & x) { NATIVE_WIDE_DETAIL::adl_sincos(x); })
1266 return noexcept(NATIVE_WIDE_DETAIL::adl_sincos(std::declval<std::array<R,N>
const &>())) &&
1267 std::is_nothrow_move_constructible_v<std::array<R,N>>;
1268 else return noexcept(
wide<R,N>()) && std::is_nothrow_move_constructible_v<
wide<R,N>> &&
1269 (N == 0 || (
noexcept(NATIVE_WIDE_DETAIL::adl_sincos(std::declval<R const &>())) &&
noexcept(std::declval<R &>() = std::declval<
decltype(NATIVE_WIDE_DETAIL::adl_sincos(std::declval<R const &>())) &>().first) &&
1270 noexcept(std::declval<R &>() = std::declval<
decltype(NATIVE_WIDE_DETAIL::adl_sincos(std::declval<R const &>())) &>().second)));
1272 if constexpr (
requires { NATIVE_WIDE_DETAIL::adl_sincos(input.registers); }) {
1273 auto [sine,cosine] = NATIVE_WIDE_DETAIL::adl_sincos(input.registers);
1277 auto & [...s] = sine;
1278 auto & [...c] = cosine;
1279 auto const & [...x] = input;
1280 ([&] {
auto pair = NATIVE_WIDE_DETAIL::adl_sincos(x); s = pair.first; c = pair.second; }(), ...);
1281 return std::pair{std::move(sine),std::move(cosine)};
1286 template <
class R, std::
size_t N>
requires (::native::detail::wide_target<R> == NATIVE_WIDE_INDEX)
1290 if constexpr (N == 0)
1291 return noexcept(
wide<R,N>()) && std::is_nothrow_move_constructible_v<wide<R,N>>;
1292 else if constexpr (std::is_same_v<
decltype(R{} == R{}),
bool>)
1293 return noexcept(
wide<R,N>()) && std::is_nothrow_move_constructible_v<wide<R,N>> &&
1294 noexcept(std::declval<R &>() = std::declval<R const &>());
1297 noexcept(std::declval<R &>() = NATIVE_WIDE_DETAIL::adl_select(
1298 std::declval<
decltype(R{} == R{})
const &>(),
1299 std::declval<R const &>(), std::declval<R const &>()));
1302 auto & [...value] = result;
1303 auto const & [...mask] = masks;
1304 auto const & [...x] = a;
1305 auto const & [...y] = b;
1306 if constexpr (std::is_same_v<
decltype(R{} == R{}),
bool>)
1307 ([&] { value =
mask ? x : y; }(), ...);
1309 ([&] { value = NATIVE_WIDE_DETAIL::adl_select(
mask, x, y); }(), ...);
1313#undef NATIVE_WIDE_DETAIL
1314#undef NATIVE_WIDE_INDEX
1316#if defined(__x86_64__) || defined(_M_X64)
1317#define NATIVE_WIDE_INDEX 10
1318#define NATIVE_WIDE_DETAIL detail::wide_avx2_detail
1319#pragma clang attribute push(__attribute__((target(NATIVE_KERNEL_TARGET_1))), apply_to=function)
1321#pragma clang attribute pop
1322#undef NATIVE_WIDE_DETAIL
1323#undef NATIVE_WIDE_INDEX
1326#if defined(__x86_64__) || defined(_M_X64)
1327#define NATIVE_WIDE_INDEX 9
1328#define NATIVE_WIDE_DETAIL detail::wide_avx512_base_detail
1329#pragma clang attribute push(__attribute__((target(NATIVE_KERNEL_TARGET_2))), apply_to=function)
1331#pragma clang attribute pop
1332#undef NATIVE_WIDE_DETAIL
1333#undef NATIVE_WIDE_INDEX
1336#if defined(__x86_64__) || defined(_M_X64)
1337#define NATIVE_WIDE_INDEX 7
1338#define NATIVE_WIDE_DETAIL detail::wide_avx512_bw_detail
1339#pragma clang attribute push(__attribute__((target(NATIVE_KERNEL_TARGET_3))), apply_to=function)
1341#pragma clang attribute pop
1342#undef NATIVE_WIDE_DETAIL
1343#undef NATIVE_WIDE_INDEX
1346#if defined(__x86_64__) || defined(_M_X64)
1347#define NATIVE_WIDE_INDEX 8
1348#define NATIVE_WIDE_DETAIL detail::wide_avx512_vl_detail
1349#pragma clang attribute push(__attribute__((target(NATIVE_KERNEL_TARGET_4))), apply_to=function)
1351#pragma clang attribute pop
1352#undef NATIVE_WIDE_DETAIL
1353#undef NATIVE_WIDE_INDEX
1356#if defined(__x86_64__) || defined(_M_X64)
1357#define NATIVE_WIDE_INDEX 3
1358#define NATIVE_WIDE_DETAIL detail::wide_avx512_bw_vl_detail
1359#pragma clang attribute push(__attribute__((target(NATIVE_KERNEL_TARGET_5))), apply_to=function)
1361#pragma clang attribute pop
1362#undef NATIVE_WIDE_DETAIL
1363#undef NATIVE_WIDE_INDEX
1366#if defined(__x86_64__) || defined(_M_X64)
1367#define NATIVE_WIDE_INDEX 5
1368#define NATIVE_WIDE_DETAIL detail::wide_avx512_bw_bf16_detail
1369#pragma clang attribute push(__attribute__((target(NATIVE_KERNEL_TARGET_7))), apply_to=function)
1371#pragma clang attribute pop
1372#undef NATIVE_WIDE_DETAIL
1373#undef NATIVE_WIDE_INDEX
1376#if defined(__x86_64__) || defined(_M_X64)
1377#define NATIVE_WIDE_INDEX 1
1378#define NATIVE_WIDE_DETAIL detail::wide_avx512_bw_vl_bf16_detail
1379#pragma clang attribute push(__attribute__((target(NATIVE_KERNEL_TARGET_9))), apply_to=function)
1381#pragma clang attribute pop
1382#undef NATIVE_WIDE_DETAIL
1383#undef NATIVE_WIDE_INDEX
1386#if defined(__x86_64__) || defined(_M_X64)
1387#define NATIVE_WIDE_INDEX 6
1388#define NATIVE_WIDE_DETAIL detail::wide_avx512_bw_fp16_detail
1389#pragma clang attribute push(__attribute__((target(NATIVE_KERNEL_TARGET_11))), apply_to=function)
1391#pragma clang attribute pop
1392#undef NATIVE_WIDE_DETAIL
1393#undef NATIVE_WIDE_INDEX
1396#if defined(__x86_64__) || defined(_M_X64)
1397#define NATIVE_WIDE_INDEX 2
1398#define NATIVE_WIDE_DETAIL detail::wide_avx512_bw_vl_fp16_detail
1399#pragma clang attribute push(__attribute__((target(NATIVE_KERNEL_TARGET_13))), apply_to=function)
1401#pragma clang attribute pop
1402#undef NATIVE_WIDE_DETAIL
1403#undef NATIVE_WIDE_INDEX
1406#if defined(__x86_64__) || defined(_M_X64)
1407#define NATIVE_WIDE_INDEX 4
1408#define NATIVE_WIDE_DETAIL detail::wide_avx512_bw_bf16_fp16_detail
1409#pragma clang attribute push(__attribute__((target(NATIVE_KERNEL_TARGET_15))), apply_to=function)
1411#pragma clang attribute pop
1412#undef NATIVE_WIDE_DETAIL
1413#undef NATIVE_WIDE_INDEX
1416#if defined(__x86_64__) || defined(_M_X64)
1417#define NATIVE_WIDE_INDEX 0
1418#define NATIVE_WIDE_DETAIL detail::wide_avx512_bw_vl_bf16_fp16_detail
1419#pragma clang attribute push(__attribute__((target(NATIVE_KERNEL_TARGET_17))), apply_to=function)
1421#pragma clang attribute pop
1422#undef NATIVE_WIDE_DETAIL
1423#undef NATIVE_WIDE_INDEX
1426#if defined(__aarch64__) || defined(_M_ARM64)
1427#define NATIVE_WIDE_INDEX 14
1428#define NATIVE_WIDE_DETAIL detail::wide_neon_detail
1429#pragma clang attribute push(__attribute__((target(NATIVE_KERNEL_TARGET_20))), apply_to=function)
1431#pragma clang attribute pop
1432#undef NATIVE_WIDE_DETAIL
1433#undef NATIVE_WIDE_INDEX
1436#if defined(__aarch64__) || defined(_M_ARM64)
1437#define NATIVE_WIDE_INDEX 12
1438#define NATIVE_WIDE_DETAIL detail::wide_neon_bf16_detail
1439#pragma clang attribute push(__attribute__((target(NATIVE_KERNEL_TARGET_21))), apply_to=function)
1441#pragma clang attribute pop
1442#undef NATIVE_WIDE_DETAIL
1443#undef NATIVE_WIDE_INDEX
1446#if defined(__aarch64__) || defined(_M_ARM64)
1447#define NATIVE_WIDE_INDEX 13
1448#define NATIVE_WIDE_DETAIL detail::wide_neon_fp16_detail
1449#pragma clang attribute push(__attribute__((target(NATIVE_KERNEL_TARGET_22))), apply_to=function)
1451#pragma clang attribute pop
1452#undef NATIVE_WIDE_DETAIL
1453#undef NATIVE_WIDE_INDEX
1456#if defined(__aarch64__) || defined(_M_ARM64)
1457#define NATIVE_WIDE_INDEX 11
1458#define NATIVE_WIDE_DETAIL detail::wide_neon_half_detail
1459#pragma clang attribute push(__attribute__((target(NATIVE_KERNEL_TARGET_23))), apply_to=function)
1461#pragma clang attribute pop
1462#undef NATIVE_WIDE_DETAIL
1463#undef NATIVE_WIDE_INDEX
1467#define NATIVE_WIDE_INDEX 16
1468#define NATIVE_WIDE_DETAIL detail::wide_wasm_detail
1469#pragma clang attribute push(__attribute__((target(NATIVE_KERNEL_TARGET_WASM))), apply_to=function)
1471#pragma clang attribute pop
1472#undef NATIVE_WIDE_DETAIL
1473#undef NATIVE_WIDE_INDEX
1480 using ::std::tuple_size;
1481 using ::std::tuple_element;
1483 template<
class T,
size_t N>
1484 struct tuple_size<::
native::wide<T, N>> : integral_constant<size_t, N> {};
1485 template<
size_t I,
class T,
size_t N>
1486 struct tuple_element<I, ::
native::wide<T, N>> : tuple_element<I, array<T, N>> {};
1488namespace wide::detail {
1491 template<
class T,std::
size_t N>
struct shape<::
native::wide<T,N>> : array_shape<T,N> {
1492 static constexpr auto kind=family::legacy;
1493 template<
class R>
using rebind=::native::wide<R,N>;
1496 template<
class R>
requires (::native::detail::wide_target<R> == 16)
1497 __attribute__((
target(
"simd128")))
static inline constexpr rebind<R> restore(std::array<R,N>
const & values) {
1498 return rebind<R>{values};
Compiler attributes for host code, with shader-safe shared modifiers.
#define native_inline
inline [[always_inline]]
#define native_nodiscard
C++17 [[nodiscard]].
#define native_lifetimebound
[[lifetimebound]]
constexpr simd< T, N, Arch > select(M m, simd< T, N, Arch > a, simd< T, N, Arch > b) noexcept
typename mask_traits< std::remove_cvref_t< T > >::type mask
constexpr simd< float, L, Arch > atan2(simd< float, L, Arch > y, simd< float, L, Arch > x) noexcept
constexpr simd< float, N, Arch > ceil(simd< float, N, Arch > x) noexcept
constexpr simd< float, L, Arch > exp2(simd< float, L, Arch > input) noexcept
constexpr auto abs(simd< float, N, Arch > a) noexcept
constexpr simd< float, N, Arch > trunc(simd< float, N, Arch > x) noexcept
constexpr simd< float, L, Arch > exp(simd< float, L, Arch > input) noexcept
Evaluate the binary32 range-reduced exponential approximation. Degree selects a polynomial from one t...
constexpr simd< float, N, Arch > floor(simd< float, N, Arch > x) noexcept
constexpr wide< T, N > copysign(wide< T, N > const &a, wide< T, N > const &b) noexcept(noexcept(detail::wide_generic_detail::wide_map< detail::wide_generic_detail::wide_copysign >(a, b)))
constexpr auto operator!(wide< T, N > const &a)
constexpr auto sincos(wide< R, N > const &input) noexcept([] { if constexpr(requires(std::array< R, N > const &x) { detail::wide_generic_detail::adl_sincos(x);}) return noexcept(detail::wide_generic_detail::adl_sincos(std::declval< std::array< R, N > const & >())) &&std::is_nothrow_move_constructible_v< std::array< R, N > >;else return noexcept(wide< R, N >()) &&std::is_nothrow_move_constructible_v< wide< R, N > > &&(N==0||(noexcept(detail::wide_generic_detail::adl_sincos(std::declval< R const & >())) &&noexcept(std::declval< R & >()=std::declval< decltype(detail::wide_generic_detail::adl_sincos(std::declval< R const & >())) & >().first) &&noexcept(std::declval< R & >()=std::declval< decltype(detail::wide_generic_detail::adl_sincos(std::declval< R const & >())) & >().second)));}())
constexpr wide< R, N > cos(wide< R, N > const &input) noexcept([] { if constexpr(requires(std::array< R, N > const &a) { detail::wide_generic_detail::adl_cos(a);}) return noexcept(wide< R, N >{detail::wide_generic_detail::adl_cos(std::declval< std::array< R, N > const & >())});else return noexcept(wide< R, N >()) &&std::is_nothrow_move_constructible_v< wide< R, N > > &&(N==0||noexcept(std::declval< R & >()=detail::wide_generic_detail::adl_cos(std::declval< R const & >())));}())
constexpr auto operator~(wide< T, N > const &a)
constexpr wide< R, N > tanh(wide< R, N > const &input) noexcept([] { if constexpr(requires(std::array< R, N > const &a) { detail::wide_generic_detail::adl_tanh(a);}) return noexcept(wide< R, N >{detail::wide_generic_detail::adl_tanh(std::declval< std::array< R, N > const & >())});else return noexcept(wide< R, N >()) &&std::is_nothrow_move_constructible_v< wide< R, N > > &&(N==0||noexcept(std::declval< R & >()=detail::wide_generic_detail::adl_tanh(std::declval< R const & >())));}())
constexpr auto isnan(wide< T, N > const &input) noexcept(noexcept(detail::wide_generic_detail::wide_map< detail::wide_generic_detail::wide_isnan >(input)))
constexpr wide< R, N > sin(wide< R, N > const &input) noexcept([] { if constexpr(requires(std::array< R, N > const &a) { detail::wide_generic_detail::adl_sin(a);}) return noexcept(wide< R, N >{detail::wide_generic_detail::adl_sin(std::declval< std::array< R, N > const & >())});else return noexcept(wide< R, N >()) &&std::is_nothrow_move_constructible_v< wide< R, N > > &&(N==0||noexcept(std::declval< R & >()=detail::wide_generic_detail::adl_sin(std::declval< R const & >())));}())
constexpr wide< R, N > log(wide< R, N > const &input) noexcept([] { if constexpr(requires(std::array< R, N > const &a) { detail::wide_generic_detail::adl_log(a);}) return noexcept(wide< R, N >{detail::wide_generic_detail::adl_log(std::declval< std::array< R, N > const & >())});else return noexcept(wide< R, N >()) &&std::is_nothrow_move_constructible_v< wide< R, N > > &&(N==0||noexcept(std::declval< R & >()=detail::wide_generic_detail::adl_log(std::declval< R const & >())));}())
constexpr wide< R, N > log2(wide< R, N > const &input) noexcept([] { if constexpr(requires(std::array< R, N > const &a) { detail::wide_generic_detail::adl_log2(a);}) return noexcept(wide< R, N >{detail::wide_generic_detail::adl_log2(std::declval< std::array< R, N > const & >())});else return noexcept(wide< R, N >()) &&std::is_nothrow_move_constructible_v< wide< R, N > > &&(N==0||noexcept(std::declval< R & >()=detail::wide_generic_detail::adl_log2(std::declval< R const & >())));}())
constexpr wide< R, N > damping_gain(wide< R, N > const &input) noexcept([] { if constexpr(requires(std::array< R, N > const &a) { detail::wide_generic_detail::adl_damping_gain(a);}) return noexcept(wide< R, N >{detail::wide_generic_detail::adl_damping_gain(std::declval< std::array< R, N > const & >())});else return noexcept(wide< R, N >()) &&std::is_nothrow_move_constructible_v< wide< R, N > > &&(N==0||noexcept(std::declval< R & >()=detail::wide_generic_detail::adl_damping_gain(std::declval< R const & >())));}())
constexpr auto isfinite(wide< T, N > const &input) noexcept(noexcept(detail::wide_generic_detail::wide_map< detail::wide_generic_detail::wide_isfinite >(input)))
constexpr wide< R, N > expm1(wide< R, N > const &input) noexcept([] { if constexpr(requires(std::array< R, N > const &a) { detail::wide_generic_detail::adl_expm1(a);}) return noexcept(wide< R, N >{detail::wide_generic_detail::adl_expm1(std::declval< std::array< R, N > const & >())});else return noexcept(wide< R, N >()) &&std::is_nothrow_move_constructible_v< wide< R, N > > &&(N==0||noexcept(std::declval< R & >()=detail::wide_generic_detail::adl_expm1(std::declval< R const & >())));}())
constexpr wide< R, N > log1p(wide< R, N > const &input) noexcept([] { if constexpr(requires(std::array< R, N > const &a) { detail::wide_generic_detail::adl_log1p(a);}) return noexcept(wide< R, N >{detail::wide_generic_detail::adl_log1p(std::declval< std::array< R, N > const & >())});else return noexcept(wide< R, N >()) &&std::is_nothrow_move_constructible_v< wide< R, N > > &&(N==0||noexcept(std::declval< R & >()=detail::wide_generic_detail::adl_log1p(std::declval< R const & >())));}())
constexpr auto isinf(wide< T, N > const &input) noexcept(noexcept(detail::wide_generic_detail::wide_map< detail::wide_generic_detail::wide_isinf >(input)))
constexpr auto signbit(wide< T, N > const &input) noexcept(noexcept(detail::wide_generic_detail::wide_map< detail::wide_generic_detail::wide_signbit >(input)))
Architecture-tagged vectors, register packs and supporting value types. Native arithmetic follows its...
void operator%=(simd< T, N, A > &, simd< U, M, B >)=delete
Reject mixed architectures and mismatched short-vector widths before native conversions can participa...
void operator-(simd< T, N, A >, simd< U, M, B >)=delete
Reject mixed architectures and mismatched short-vector widths before native conversions can participa...
constexpr simd< T, N, A > sqrt(simd< T, N, A > v) noexcept
Compute correctly rounded square roots; negative finite lanes produce NaN.
void operator/(simd< T, N, A >, simd< U, M, B >)=delete
Reject mixed architectures and mismatched short-vector widths before native conversions can participa...
void operator>>=(simd< T, N, A > &, simd< U, M, B >)=delete
Reject mixed architectures and mismatched short-vector widths before native conversions can participa...
void operator>>(simd< T, N, A >, simd< U, M, B >)=delete
Reject mixed architectures and mismatched short-vector widths before native conversions can participa...
wide(T, U...) -> wide< T, 1+sizeof...(U)>
Deduce the common element type and the number of homogeneous constructor arguments.
void operator*=(simd< T, N, A > &, simd< U, M, B >)=delete
Reject mixed architectures and mismatched short-vector widths before native conversions can participa...
void operator==(simd< T, N, A >, simd< U, M, B >)=delete
Reject mixed architectures and mismatched short-vector widths before native conversions can participa...
void operator%(simd< T, N, A >, simd< U, M, B >)=delete
Reject mixed architectures and mismatched short-vector widths before native conversions can participa...
void operator>=(simd< T, N, A >, simd< U, M, B >)=delete
Reject mixed architectures and mismatched short-vector widths before native conversions can participa...
void operator>(simd< T, N, A >, simd< U, M, B >)=delete
Reject mixed architectures and mismatched short-vector widths before native conversions can participa...
void operator&=(simd< T, N, A > &, simd< U, M, B >)=delete
Reject mixed architectures and mismatched short-vector widths before native conversions can participa...
void operator/=(simd< T, N, A > &, simd< U, M, B >)=delete
Reject mixed architectures and mismatched short-vector widths before native conversions can participa...
void operator|(simd< T, N, A >, simd< U, M, B >)=delete
Reject mixed architectures and mismatched short-vector widths before native conversions can participa...
void operator+=(simd< T, N, A > &, simd< U, M, B >)=delete
Reject mixed architectures and mismatched short-vector widths before native conversions can participa...
void operator*(simd< T, N, A >, simd< U, M, B >)=delete
Reject mixed architectures and mismatched short-vector widths before native conversions can participa...
void operator-=(simd< T, N, A > &, simd< U, M, B >)=delete
Reject mixed architectures and mismatched short-vector widths before native conversions can participa...
constexpr simd< fp16, 32, Arch > fma(simd< fp16, 32, Arch > a, simd< fp16, 32, Arch > b, simd< fp16, 32, Arch > c) noexcept
void operator<=(simd< T, N, A >, simd< U, M, B >)=delete
Reject mixed architectures and mismatched short-vector widths before native conversions can participa...
void operator^=(simd< T, N, A > &, simd< U, M, B >)=delete
Reject mixed architectures and mismatched short-vector widths before native conversions can participa...
constexpr simd< T, N, A > broadcast(simd< T, N, A > v, imm_t< I >) noexcept
Broadcast one compile-time-selected lane.
void operator<<(simd< T, N, A >, simd< U, M, B >)=delete
Reject mixed architectures and mismatched short-vector widths before native conversions can participa...
constexpr int target
First matching requirement, with every later choice checked for shadowing.
void operator&(simd< T, N, A >, simd< U, M, B >)=delete
Reject mixed architectures and mismatched short-vector widths before native conversions can participa...
void operator^(simd< T, N, A >, simd< U, M, B >)=delete
Reject mixed architectures and mismatched short-vector widths before native conversions can participa...
void operator+(simd< T, N, A >, simd< U, M, B >)=delete
Reject mixed architectures and mismatched short-vector widths before native conversions can participa...
void operator!=(simd< T, N, A >, simd< U, M, B >)=delete
Reject mixed architectures and mismatched short-vector widths before native conversions can participa...
void operator<(simd< T, N, A >, simd< U, M, B >)=delete
Reject mixed architectures and mismatched short-vector widths before native conversions can participa...
void operator|=(simd< T, N, A > &, simd< U, M, B >)=delete
Reject mixed architectures and mismatched short-vector widths before native conversions can participa...
void operator<<=(simd< T, N, A > &, simd< U, M, B >)=delete
Reject mixed architectures and mismatched short-vector widths before native conversions can participa...
Standard-library adaptations documented here for SIMD value types.
constexpr bool isnan(::native::fp16 x) noexcept
Classify the stored bits as NaN without performing a floating-point conversion.
Own N values of T, including an empty pack when N == 0. registers is the underlying array....
constexpr wide(U const &value) noexcept(std::is_nothrow_constructible_v< T, U const & > &&(N==0||std::is_nothrow_copy_constructible_v< T >))
Convert one value to T, then copy it across the pack.
constexpr decltype(auto) apply(F &&f) noexcept(noexcept(std::apply(std::forward< F >(f), registers)))
Invoke f with all elements as arguments; the empty pack calls f().
constexpr T const & get() const &noexcept
Access element I, preserving constness and the value category of the pack.
constexpr decltype(auto) apply(F &&f) const noexcept(noexcept(std::apply(std::forward< F >(f), registers)))
Invoke f with all elements as arguments; the empty pack calls f().
static constexpr wide broadcast(T const &value) noexcept(N==0||std::is_nothrow_copy_constructible_v< T >)
Copy value to every element; an empty pack makes no copies.
constexpr T & get() &noexcept
Access element I, preserving constness and the value category of the pack.
constexpr T const && get() const &&noexcept
Access element I, preserving constness and the value category of the pack.
constexpr T && get() &&noexcept
Access element I, preserving constness and the value category of the pack.
constexpr wide(wide< U, N > const &source) noexcept(N==0||std::is_nothrow_constructible_v< T, U const & >)
Convert each element of a same-size pack; explicitness follows the element conversion.
constexpr wide() noexcept(std::is_nothrow_default_constructible_v< std::array< T, N > >)
Retain opted-in array initialization in the element's target scope.
constexpr wide()=default
Default-initialize the underlying array. Use wide{} for value initialization.
constexpr wide(std::array< T, N > values) noexcept(std::is_nothrow_move_constructible_v< std::array< T, N > >)
Take an array of exactly the pack extent.
constexpr wide(U &&... values) noexcept((std::is_nothrow_constructible_v< T, U && > &&...))
Construct one element from each argument, preserving argument order.
constexpr wide(wide< U, N > &&source) noexcept(N==0||std::is_nothrow_constructible_v< T, U && >)
Convert each element of a same-size pack; explicitness follows the element conversion.