native 0.0.1
Vectors, masks and wide register packs for C++26
Loading...
Searching...
No Matches
wide.h
1// SPDX-FileCopyrightText: 2026 Edward Kmett <ekmett@gmail.com>
2// SPDX-License-Identifier: BSD-2-Clause OR Apache-2.0
3#pragma once
4#include "native/attributes.h"
5#include "native/isa.h"
6#include "native/value_traits.h"
7#include "native/wide_pack.h"
8
9#include <array>
10#include <concepts>
11#include <cmath>
12#include <cstddef>
13#include <functional>
14#include <tuple>
15#include <type_traits>
16#include <utility>
17
18namespace native {
19 template<class T, std::size_t N> struct wide;
20 namespace detail {
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;
25 };
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;
30 };
31 }
32
33 namespace detail {
34 template<class T, class = void> struct wide_features {
35 static constexpr isa<> value=scalar;
36 };
37 template<class T> struct wide_features<T,std::void_t<decltype(T::architecture)>> {
38 static constexpr isa<> value=value_architecture_v<T>;
39 };
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;
45 };
46 // Only operands with a SIMD architecture participate. Scalar/custom values
47 // retain the generic ADL path. Arrays and nested packs contribute their
48 // element features; mixed conversions use the union of both endpoints.
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];
54 }();
55 template<class T> inline constexpr bool wide_equivalent_default=
56 value_traits<std::remove_cv_t<T>>::aggregate_default;
57 // MSVC's array can own a T with an attributed nontrivial constructor,
58 // including a dummy element at N == 0.
59 // Aggregate-initialize that storage in T's target scope, bypassing the
60 // library's unattributed implicit array constructor. Leave trivial/deleted
61 // defaults on the original defaulted path. Nonempty packs opt in only when
62 // their concrete element guarantees equivalent default/value initialization.
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>>;
68 }
82 template<class T, std::size_t N>
83 struct wide {
84 // Packed library aggregates can underalign arrays of native mask types.
85 alignas(T) std::array<T, N> registers;
86
88 constexpr wide() requires (!detail::wide_target_default<T,N>) = default;
90 template<std::size_t I> requires (I < N)
91 native_nodiscard native_inline constexpr T & get() & noexcept native_lifetimebound { return registers[I]; }
93 template<std::size_t I> requires (I < N)
94 native_nodiscard native_inline constexpr T const & get() const & noexcept native_lifetimebound { return registers[I]; }
96 template<std::size_t I> requires (I < N)
97 native_nodiscard native_inline constexpr T && get() && noexcept native_lifetimebound { return std::move(registers[I]); }
99 template<std::size_t I> requires (I < N)
100 native_nodiscard native_inline constexpr T const && get() const && noexcept native_lifetimebound { return std::move(registers[I]); }
101
102 private:
103 struct conversion_tag {};
104#define NATIVE_WIDE_INDEX 15
105#define NATIVE_WIDE_DETAIL detail::wide_generic_detail
106#define NATIVE_WIDE_TARGET
107// SPDX-FileCopyrightText: 2026 Edward Kmett <ekmett@gmail.com>
108// SPDX-License-Identifier: BSD-2-Clause OR Apache-2.0
109// Intentionally repeatable under one target family.
110 public:
112 NATIVE_WIDE_TARGET native_inline constexpr wide()
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>
115 : registers{} {}
116
117 NATIVE_WIDE_TARGET native_inline constexpr wide(std::array<T, N> values)
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)) {}
121
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>>) && ...))
126 explicit(N == 1) NATIVE_WIDE_TARGET native_inline constexpr wide(U &&... values)
127 noexcept((std::is_nothrow_constructible_v<T,U &&> && ...))
128 : registers{T(std::forward<U>(values))...} {}
129
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>)
133 explicit NATIVE_WIDE_TARGET native_inline constexpr wide(U const & value)
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>{}) {}
137
139 template<class U> requires (detail::wide_target<T,U> == NATIVE_WIDE_INDEX) && (!std::same_as<T,U>) && std::constructible_from<T,U const &>
140 explicit(!std::is_convertible_v<U const &,T>) NATIVE_WIDE_TARGET native_inline constexpr wide(wide<U,N> const & source)
141 noexcept(N == 0 || std::is_nothrow_constructible_v<T,U const &>)
142 : wide(conversion_tag{}, source, std::make_index_sequence<N>{}) {}
143
144 template<class U> requires (detail::wide_target<T,U> == NATIVE_WIDE_INDEX) && (!std::same_as<T,U>) && std::constructible_from<T,U &&>
145 explicit(!std::is_convertible_v<U &&,T>) NATIVE_WIDE_TARGET native_inline constexpr wide(wide<U,N> && source)
146 noexcept(N == 0 || std::is_nothrow_constructible_v<T,U &&>)
147 : wide(conversion_tag{}, std::move(source), std::make_index_sequence<N>{}) {}
148
150 native_nodiscard static NATIVE_WIDE_TARGET native_inline constexpr wide broadcast(T const & value)
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>{});
154 }
155
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>{});
160 }
161
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>{});
166 }
167 private:
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))...} {}
177 // Keep the callable on the force-inline path. MSVC can outline std::invoke
178 // inside std::apply even when both the caller and functor are force-inline.
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)...);
183 else
184 return std::forward<F>(f)(std::get<I>(a)...);
185 }
186
187#undef NATIVE_WIDE_TARGET
188#undef NATIVE_WIDE_DETAIL
189#undef NATIVE_WIDE_INDEX
190
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)))
195
196#undef NATIVE_WIDE_TARGET
197#undef NATIVE_WIDE_DETAIL
198#undef NATIVE_WIDE_INDEX
199#endif
200
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)))
205
206#undef NATIVE_WIDE_TARGET
207#undef NATIVE_WIDE_DETAIL
208#undef NATIVE_WIDE_INDEX
209#endif
210
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)))
215
216#undef NATIVE_WIDE_TARGET
217#undef NATIVE_WIDE_DETAIL
218#undef NATIVE_WIDE_INDEX
219#endif
220
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)))
225
226#undef NATIVE_WIDE_TARGET
227#undef NATIVE_WIDE_DETAIL
228#undef NATIVE_WIDE_INDEX
229#endif
230
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)))
235
236#undef NATIVE_WIDE_TARGET
237#undef NATIVE_WIDE_DETAIL
238#undef NATIVE_WIDE_INDEX
239#endif
240
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)))
245
246#undef NATIVE_WIDE_TARGET
247#undef NATIVE_WIDE_DETAIL
248#undef NATIVE_WIDE_INDEX
249#endif
250
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)))
255
256#undef NATIVE_WIDE_TARGET
257#undef NATIVE_WIDE_DETAIL
258#undef NATIVE_WIDE_INDEX
259#endif
260
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)))
265
266#undef NATIVE_WIDE_TARGET
267#undef NATIVE_WIDE_DETAIL
268#undef NATIVE_WIDE_INDEX
269#endif
270
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)))
275
276#undef NATIVE_WIDE_TARGET
277#undef NATIVE_WIDE_DETAIL
278#undef NATIVE_WIDE_INDEX
279#endif
280
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)))
285
286#undef NATIVE_WIDE_TARGET
287#undef NATIVE_WIDE_DETAIL
288#undef NATIVE_WIDE_INDEX
289#endif
290
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)))
295
296#undef NATIVE_WIDE_TARGET
297#undef NATIVE_WIDE_DETAIL
298#undef NATIVE_WIDE_INDEX
299#endif
300
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)))
305
306#undef NATIVE_WIDE_TARGET
307#undef NATIVE_WIDE_DETAIL
308#undef NATIVE_WIDE_INDEX
309#endif
310
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)))
315
316#undef NATIVE_WIDE_TARGET
317#undef NATIVE_WIDE_DETAIL
318#undef NATIVE_WIDE_INDEX
319#endif
320
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)))
325
326#undef NATIVE_WIDE_TARGET
327#undef NATIVE_WIDE_DETAIL
328#undef NATIVE_WIDE_INDEX
329#endif
330
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)))
335
336#undef NATIVE_WIDE_TARGET
337#undef NATIVE_WIDE_DETAIL
338#undef NATIVE_WIDE_INDEX
339#endif
340
341#if NATIVE_HOST_WASM
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)))
345
346#undef NATIVE_WIDE_TARGET
347#undef NATIVE_WIDE_DETAIL
348#undef NATIVE_WIDE_INDEX
349#endif
350
351 };
352
353 template<class T, class... U> requires (std::same_as<T,U> && ...)
354 wide(T,U...) -> wide<T,1 + sizeof...(U)>;
355
356#define NATIVE_WIDE_INDEX 15
357#define NATIVE_WIDE_DETAIL detail::wide_generic_detail
358// SPDX-FileCopyrightText: 2026 Edward Kmett <ekmett@gmail.com>
359// SPDX-License-Identifier: BSD-2-Clause OR Apache-2.0
360// Intentionally repeatable; each family owns its force-inline ADL helpers.
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;
369
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];
373 else return (value);
374 }
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))...}};
380 }
381 template<class T, std::size_t N, class F, std::size_t... I>
382 native_inline constexpr auto wide_unary(wide<T, N> const & a, F f, std::index_sequence<I...>) {
383 using R = std::remove_cvref_t<decltype(f(std::declval<T const &>()))>;
384 return wide<R, N>{{f(a.registers[I])...}};
385 }
386 template<class T, std::size_t N, class B, class F, std::size_t... I>
387 native_inline constexpr wide<T, N> & wide_mutate(wide<T, N> & a, B const & b, F f, std::index_sequence<I...>) {
388 if constexpr (wide_traits<B>::value) (f(a.registers[I], b.registers[I]), ...);
389 else if constexpr (N != 0) {
390 // A broadcast can alias a destination register. Snapshot it before
391 // publishing any lane, just as a register broadcast takes a value.
392 auto value = b;
393 (f(a.registers[I], value), ...);
394 }
395 return a;
396 }
397 }
398
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);
403 else return (a);
404 }
405 struct wide_add {
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); }
410 };
411 struct wide_sub {
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); }
416 };
417 struct wide_mul {
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); }
422 };
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))};
425 };
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)
430 noexcept([] {
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 &>()))});
433 else return false;
434 }()) {
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>>{});
437 }
438 }
439
440 // Reject non-pack operands before ISA routing: routing itself combines and
441 // compares ISA values whose ADL also sees these generic binary operators.
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; }
446 native_nodiscard native_inline constexpr auto operator+(A const & a, B const & 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{});
449 }
450
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; }
455 native_nodiscard native_inline constexpr auto operator-(A const & a, B const & 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{});
458 }
459
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; }
464 native_nodiscard native_inline constexpr auto operator*(A const & a, B const & 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{});
467 }
468
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; }
473 native_nodiscard native_inline constexpr auto operator/(A const & a, B const & 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>>{});
476 }
477
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; }
482 native_nodiscard native_inline constexpr auto operator%(A const & a, B const & 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>>{});
485 }
486
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; }
491 native_nodiscard native_inline constexpr auto operator&(A const & a, B const & 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>>{});
494 }
495
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; }
500 native_nodiscard native_inline constexpr auto operator|(A const & a, B const & 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>>{});
503 }
504
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; }
509 native_nodiscard native_inline constexpr auto operator^(A const & a, B const & 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>>{});
512 }
513
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; }
518 native_nodiscard native_inline constexpr auto operator<<(A const & a, B const & 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>>{});
521 }
522
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; }
527 native_nodiscard native_inline constexpr auto operator>>(A const & a, B const & 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>>{});
530 }
531
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; }
536 native_nodiscard native_inline constexpr auto operator==(A const & a, B const & 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>>{});
539 }
540
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; }
545 native_nodiscard native_inline constexpr auto operator!=(A const & a, B const & 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>>{});
548 }
549
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; }
554 native_nodiscard native_inline constexpr auto operator<(A const & a, B const & 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>>{});
557 }
558
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; }
563 native_nodiscard native_inline constexpr auto operator>(A const & a, B const & 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>>{});
566 }
567
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; }
572 native_nodiscard native_inline constexpr auto operator<=(A const & a, B const & 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>>{});
575 }
576
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; }
581 native_nodiscard native_inline constexpr auto operator>=(A const & a, B const & 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>>{});
584 }
585
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>{});
591 }
592
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>{});
598 }
599
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>{});
605 }
606
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>{});
612 }
613
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; })))
620 native_inline constexpr wide<T, N> & operator+=(wide<T, N> & a, B const & b)
621 noexcept([] {
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{}));
625 else return false;
626 }()) {
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>{});
630 }
631
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; })))
638 native_inline constexpr wide<T, N> & operator-=(wide<T, N> & a, B const & b)
639 noexcept([] {
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{}));
643 else return false;
644 }()) {
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>{});
648 }
649
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; })))
656 native_inline constexpr wide<T, N> & operator*=(wide<T, N> & a, B const & b)
657 noexcept([] {
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{}));
661 else return false;
662 }()) {
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>{});
666 }
667
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; }
673 native_inline constexpr wide<T, N> & operator/=(wide<T, N> & a, B const & b) {
674 return NATIVE_WIDE_DETAIL::wide_mutate(a, b, [](auto & x, auto const & y) { x /= y; }, std::make_index_sequence<N>{});
675 }
676
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; }
682 native_inline constexpr wide<T, N> & operator%=(wide<T, N> & a, B const & b) {
683 return NATIVE_WIDE_DETAIL::wide_mutate(a, b, [](auto & x, auto const & y) { x %= y; }, std::make_index_sequence<N>{});
684 }
685
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; }
691 native_inline constexpr wide<T, N> & operator&=(wide<T, N> & a, B const & b) {
692 return NATIVE_WIDE_DETAIL::wide_mutate(a, b, [](auto & x, auto const & y) { x &= y; }, std::make_index_sequence<N>{});
693 }
694
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; }
700 native_inline constexpr wide<T, N> & operator|=(wide<T, N> & a, B const & b) {
701 return NATIVE_WIDE_DETAIL::wide_mutate(a, b, [](auto & x, auto const & y) { x |= y; }, std::make_index_sequence<N>{});
702 }
703
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; }
709 native_inline constexpr wide<T, N> & operator^=(wide<T, N> & a, B const & b) {
710 return NATIVE_WIDE_DETAIL::wide_mutate(a, b, [](auto & x, auto const & y) { x ^= y; }, std::make_index_sequence<N>{});
711 }
712
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; }
718 native_inline constexpr wide<T, N> & operator<<=(wide<T, N> & a, B const & b) {
719 return NATIVE_WIDE_DETAIL::wide_mutate(a, b, [](auto & x, auto const & y) { x <<= y; }, std::make_index_sequence<N>{});
720 }
721
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; }
727 native_inline constexpr wide<T, N> & operator>>=(wide<T, N> & a, B const & b) {
728 return NATIVE_WIDE_DETAIL::wide_mutate(a, b, [](auto & x, auto const & y) { x >>= y; }, std::make_index_sequence<N>{});
729 }
730
731 namespace NATIVE_WIDE_DETAIL {
732 using namespace ::native::detail;
733 using std::abs;
734 using std::sqrt;
735 using std::fma;
736 using std::sin;
737 using std::cos;
738 using std::exp;
739 using std::exp2;
740 using std::expm1;
741 using std::log;
742 using std::log2;
743 using std::log1p;
744 using std::tanh;
745 using std::atan2;
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>{}); }
772 native_inline constexpr auto adl_exp(A const & a)
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>{});
776 }
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>{}); }
781 native_inline constexpr auto adl_exp(A const & a)
782 noexcept(noexcept(exp(a,std::bool_constant<Flush>{}))) -> decltype(exp(a,std::bool_constant<Flush>{})) {
783 return exp(a,std::bool_constant<Flush>{});
784 }
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>{}); })
793 native_inline constexpr auto adl_exp2(A const & a) noexcept(noexcept(exp2(a))) -> decltype(exp2(a)) { return exp2(a); }
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); }
798 }
799 namespace NATIVE_WIDE_DETAIL {
800 using namespace ::native::detail;
801 // Restrict standard fallbacks: some STLs leave their templates unconstrained.
802 template<class T> requires std::is_arithmetic_v<T>
803 native_inline constexpr auto isfinite(T const & x)
804 noexcept(noexcept(std::isfinite(x))) -> decltype(std::isfinite(x)) { return std::isfinite(x); }
805 template<class T> requires std::is_arithmetic_v<T>
806 native_inline constexpr auto isinf(T const & x)
807 noexcept(noexcept(std::isinf(x))) -> decltype(std::isinf(x)) { return std::isinf(x); }
808 template<class T> requires std::is_arithmetic_v<T>
809 native_inline constexpr auto isnan(T const & x)
810 noexcept(noexcept(std::isnan(x))) -> decltype(std::isnan(x)) { return std::isnan(x); }
811 template<class T> requires std::is_arithmetic_v<T>
812 native_inline constexpr auto signbit(T const & x)
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>
818 native_inline constexpr auto floor(T const & x)
819 noexcept(noexcept(std::floor(x))) -> decltype(std::floor(x)) { return std::floor(x); }
820 struct wide_floor {
821 template<class T> native_inline constexpr auto operator()(T const & x) const
822 noexcept(noexcept(floor(x))) -> decltype(floor(x)) { return floor(x); }
823 };
824 template<class T> requires std::is_floating_point_v<T>
825 native_inline constexpr auto ceil(T const & x)
826 noexcept(noexcept(std::ceil(x))) -> decltype(std::ceil(x)) { return std::ceil(x); }
827 struct wide_ceil {
828 template<class T> native_inline constexpr auto operator()(T const & x) const
829 noexcept(noexcept(ceil(x))) -> decltype(ceil(x)) { return ceil(x); }
830 };
831 template<class T> requires std::is_floating_point_v<T>
832 native_inline constexpr auto trunc(T const & x)
833 noexcept(noexcept(std::trunc(x))) -> decltype(std::trunc(x)) { return std::trunc(x); }
834 struct wide_trunc {
835 template<class T> native_inline constexpr auto operator()(T const & x) const
836 noexcept(noexcept(trunc(x))) -> decltype(trunc(x)) { return trunc(x); }
837 };
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...); }
841 };
842 struct wide_isinf {
843 template<class... T> native_inline constexpr auto operator()(T const &... x) const
844 noexcept(noexcept(isinf(x...))) -> decltype(isinf(x...)) { return isinf(x...); }
845 };
846 struct wide_isnan {
847 template<class... T> native_inline constexpr auto operator()(T const &... x) const
848 noexcept(noexcept(isnan(x...))) -> decltype(isnan(x...)) { return isnan(x...); }
849 };
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...); }
853 };
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...); }
857 };
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...)}; });
864
865 // Each lane is constructed directly from its ADL result; no default
866 // construction or assignment is required. The array then moves into wide.
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)
869 noexcept([] {
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 &>())}});
873 }()) {
874 auto const & [...x] = input;
875 return wide<wide_result<F,T>,N>{std::array<wide_result<F,T>,N>{F{}(x)...}};
876 }
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)
879 noexcept([] {
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 &>())}});
883 }()) {
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)...}};
887 }
888 }
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>
893 native_nodiscard native_inline constexpr auto isfinite(wide<T,N> const & input)
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);
896 }
897
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>
900 native_nodiscard native_inline constexpr auto isinf(wide<T,N> const & input)
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);
903 }
904
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>
907 native_nodiscard native_inline constexpr auto isnan(wide<T,N> const & input)
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);
910 }
911
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>
914 native_nodiscard native_inline constexpr auto signbit(wide<T,N> const & input)
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);
917 }
918
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);
926 }
927
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);
935 }
936
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);
943 }
944
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);
951 }
952
954 template<class R,std::size_t N> requires (::native::detail::wide_target<R> == NATIVE_WIDE_INDEX)
955 native_nodiscard native_inline constexpr wide<R,N> broadcast(R value) noexcept(noexcept(wide<R,N>::broadcast(value))) {
956 return wide<R,N>::broadcast(value);
957 }
958
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); }
962 noexcept([] {
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 &>())));
967 }()) {
968 if constexpr (requires { NATIVE_WIDE_DETAIL::adl_abs(input.registers); })
969 return wide<R,N>{NATIVE_WIDE_DETAIL::adl_abs(input.registers)};
970 else {
971 wide<R,N> result;
972 auto & [...value] = result;
973 auto const & [...x] = input;
974 ([&] { value = NATIVE_WIDE_DETAIL::adl_abs(x); }(), ...);
975 return result;
976 }
977 }
978
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); }
983 noexcept([] {
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 &>())));
988 }()) {
989 if constexpr (requires { NATIVE_WIDE_DETAIL::adl_sqrt(input.registers); })
990 return wide<R,N>{NATIVE_WIDE_DETAIL::adl_sqrt(input.registers)};
991 else {
992 wide<R,N> result;
993 auto & [...value] = result;
994 auto const & [...x] = input;
995 ([&] { value = NATIVE_WIDE_DETAIL::adl_sqrt(x); }(), ...);
996 return result;
997 }
998 }
999
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); }
1004 noexcept([] {
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 &>())));
1009 }()) {
1010 if constexpr (requires { NATIVE_WIDE_DETAIL::adl_sin(input.registers); })
1011 return wide<R,N>{NATIVE_WIDE_DETAIL::adl_sin(input.registers)};
1012 else {
1013 wide<R,N> result;
1014 auto & [...value] = result;
1015 auto const & [...x] = input;
1016 ([&] { value = NATIVE_WIDE_DETAIL::adl_sin(x); }(), ...);
1017 return result;
1018 }
1019 }
1020
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); }
1025 noexcept([] {
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 &>())));
1030 }()) {
1031 if constexpr (requires { NATIVE_WIDE_DETAIL::adl_cos(input.registers); })
1032 return wide<R,N>{NATIVE_WIDE_DETAIL::adl_cos(input.registers)};
1033 else {
1034 wide<R,N> result;
1035 auto & [...value] = result;
1036 auto const & [...x] = input;
1037 ([&] { value = NATIVE_WIDE_DETAIL::adl_cos(x); }(), ...);
1038 return result;
1039 }
1040 }
1041
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); }
1047 noexcept([] {
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 &>())));
1052 }()) {
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)};
1055 else {
1056 wide<R,N> result;
1057 auto & [...value] = result;
1058 auto const & [...x] = input;
1059 ([&] { value = NATIVE_WIDE_DETAIL::adl_exp<Flush,Degree>(x); }(), ...);
1060 return result;
1061 }
1062 }
1063
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); }
1068 noexcept([] {
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 &>())));
1073 }()) {
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)};
1076 else {
1077 wide<R,N> result;
1078 auto & [...value] = result;
1079 auto const & [...x] = input;
1080 ([&] { value = NATIVE_WIDE_DETAIL::adl_exp2<Flush>(x); }(), ...);
1081 return result;
1082 }
1083 }
1084
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); }
1089 noexcept([] {
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 &>())));
1094 }()) {
1095 if constexpr (requires { NATIVE_WIDE_DETAIL::adl_expm1(input.registers); })
1096 return wide<R,N>{NATIVE_WIDE_DETAIL::adl_expm1(input.registers)};
1097 else {
1098 wide<R,N> result;
1099 auto & [...value] = result;
1100 auto const & [...x] = input;
1101 ([&] { value = NATIVE_WIDE_DETAIL::adl_expm1(x); }(), ...);
1102 return result;
1103 }
1104 }
1105
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); }
1110 noexcept([] {
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 &>())));
1115 }()) {
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)};
1118 else {
1119 wide<R,N> result;
1120 auto & [...value] = result;
1121 auto const & [...x] = input;
1122 ([&] { value = NATIVE_WIDE_DETAIL::adl_damping_gain(x); }(), ...);
1123 return result;
1124 }
1125 }
1126
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); }
1131 noexcept([] {
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 &>())));
1136 }()) {
1137 if constexpr (requires { NATIVE_WIDE_DETAIL::adl_log(input.registers); })
1138 return wide<R,N>{NATIVE_WIDE_DETAIL::adl_log(input.registers)};
1139 else {
1140 wide<R,N> result;
1141 auto & [...value] = result;
1142 auto const & [...x] = input;
1143 ([&] { value = NATIVE_WIDE_DETAIL::adl_log(x); }(), ...);
1144 return result;
1145 }
1146 }
1147
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); }
1152 noexcept([] {
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 &>())));
1157 }()) {
1158 if constexpr (requires { NATIVE_WIDE_DETAIL::adl_log2(input.registers); })
1159 return wide<R,N>{NATIVE_WIDE_DETAIL::adl_log2(input.registers)};
1160 else {
1161 wide<R,N> result;
1162 auto & [...value] = result;
1163 auto const & [...x] = input;
1164 ([&] { value = NATIVE_WIDE_DETAIL::adl_log2(x); }(), ...);
1165 return result;
1166 }
1167 }
1168
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); }
1173 noexcept([] {
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 &>())));
1178 }()) {
1179 if constexpr (requires { NATIVE_WIDE_DETAIL::adl_log1p(input.registers); })
1180 return wide<R,N>{NATIVE_WIDE_DETAIL::adl_log1p(input.registers)};
1181 else {
1182 wide<R,N> result;
1183 auto & [...value] = result;
1184 auto const & [...x] = input;
1185 ([&] { value = NATIVE_WIDE_DETAIL::adl_log1p(x); }(), ...);
1186 return result;
1187 }
1188 }
1189
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); }
1194 noexcept([] {
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 &>())));
1199 }()) {
1200 if constexpr (requires { NATIVE_WIDE_DETAIL::adl_tanh(input.registers); })
1201 return wide<R,N>{NATIVE_WIDE_DETAIL::adl_tanh(input.registers)};
1202 else {
1203 wide<R,N> result;
1204 auto & [...value] = result;
1205 auto const & [...x] = input;
1206 ([&] { value = NATIVE_WIDE_DETAIL::adl_tanh(x); }(), ...);
1207 return result;
1208 }
1209 }
1210
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); }
1215 noexcept([] {
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 &>())));
1222 }()) {
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)};
1225 else {
1226 wide<R,N> result;
1227 auto & [...value] = result;
1228 auto const & [...a] = y;
1229 auto const & [...b] = x;
1230 ([&] { value = NATIVE_WIDE_DETAIL::adl_atan2(a,b); }(), ...);
1231 return result;
1232 }
1233 }
1234
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); }
1239 noexcept([] {
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 &>())));
1246 }()) {
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)};
1249 else {
1250 wide<R,N> result;
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); }(), ...);
1256 return result;
1257 }
1258 }
1259
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); }
1263 native_nodiscard native_inline constexpr auto sincos(wide<R,N> const & input)
1264 noexcept([] {
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)));
1271 }()) {
1272 if constexpr (requires { NATIVE_WIDE_DETAIL::adl_sincos(input.registers); }) {
1273 auto [sine,cosine] = NATIVE_WIDE_DETAIL::adl_sincos(input.registers);
1274 return std::pair{wide<R,N>{std::move(sine)},wide<R,N>{std::move(cosine)}};
1275 } else {
1276 wide<R,N> sine,cosine;
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)};
1282 }
1283 }
1284
1286 template <class R, std::size_t N> requires (::native::detail::wide_target<R> == NATIVE_WIDE_INDEX)
1287 native_nodiscard native_inline constexpr wide<R, N> select(wide<decltype(R{} == R{}), N> const & masks,
1288 wide<R, N> const & a, wide<R, N> const & b)
1289 noexcept([] {
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 &>());
1295 else
1296 return noexcept(wide<R,N>()) && std::is_nothrow_move_constructible_v<wide<R,N>> &&
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 &>()));
1300 }()) {
1301 wide<R, N> result;
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; }(), ...);
1308 else
1309 ([&] { value = NATIVE_WIDE_DETAIL::adl_select(mask, x, y); }(), ...);
1310 return result;
1311 }
1312
1313#undef NATIVE_WIDE_DETAIL
1314#undef NATIVE_WIDE_INDEX
1315
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)
1320
1321#pragma clang attribute pop
1322#undef NATIVE_WIDE_DETAIL
1323#undef NATIVE_WIDE_INDEX
1324#endif
1325
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)
1330
1331#pragma clang attribute pop
1332#undef NATIVE_WIDE_DETAIL
1333#undef NATIVE_WIDE_INDEX
1334#endif
1335
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)
1340
1341#pragma clang attribute pop
1342#undef NATIVE_WIDE_DETAIL
1343#undef NATIVE_WIDE_INDEX
1344#endif
1345
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)
1350
1351#pragma clang attribute pop
1352#undef NATIVE_WIDE_DETAIL
1353#undef NATIVE_WIDE_INDEX
1354#endif
1355
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)
1360
1361#pragma clang attribute pop
1362#undef NATIVE_WIDE_DETAIL
1363#undef NATIVE_WIDE_INDEX
1364#endif
1365
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)
1370
1371#pragma clang attribute pop
1372#undef NATIVE_WIDE_DETAIL
1373#undef NATIVE_WIDE_INDEX
1374#endif
1375
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)
1380
1381#pragma clang attribute pop
1382#undef NATIVE_WIDE_DETAIL
1383#undef NATIVE_WIDE_INDEX
1384#endif
1385
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)
1390
1391#pragma clang attribute pop
1392#undef NATIVE_WIDE_DETAIL
1393#undef NATIVE_WIDE_INDEX
1394#endif
1395
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)
1400
1401#pragma clang attribute pop
1402#undef NATIVE_WIDE_DETAIL
1403#undef NATIVE_WIDE_INDEX
1404#endif
1405
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)
1410
1411#pragma clang attribute pop
1412#undef NATIVE_WIDE_DETAIL
1413#undef NATIVE_WIDE_INDEX
1414#endif
1415
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)
1420
1421#pragma clang attribute pop
1422#undef NATIVE_WIDE_DETAIL
1423#undef NATIVE_WIDE_INDEX
1424#endif
1425
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)
1430
1431#pragma clang attribute pop
1432#undef NATIVE_WIDE_DETAIL
1433#undef NATIVE_WIDE_INDEX
1434#endif
1435
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)
1440
1441#pragma clang attribute pop
1442#undef NATIVE_WIDE_DETAIL
1443#undef NATIVE_WIDE_INDEX
1444#endif
1445
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)
1450
1451#pragma clang attribute pop
1452#undef NATIVE_WIDE_DETAIL
1453#undef NATIVE_WIDE_INDEX
1454#endif
1455
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)
1460
1461#pragma clang attribute pop
1462#undef NATIVE_WIDE_DETAIL
1463#undef NATIVE_WIDE_INDEX
1464#endif
1465
1466#if NATIVE_HOST_WASM
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)
1470
1471#pragma clang attribute pop
1472#undef NATIVE_WIDE_DETAIL
1473#undef NATIVE_WIDE_INDEX
1474#endif
1475
1476}
1477namespace std {
1478 // Structured binding lookup needs the primary names visible even when the
1479 // importer has not separately included <tuple>.
1480 using ::std::tuple_size;
1481 using ::std::tuple_element;
1482 using ::std::get;
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>> {};
1487}
1488namespace wide::detail {
1489 // The legacy class belongs to native.wide. Specialize its adapter here rather
1490 // than forward-declaring that class in a global module fragment.
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>;
1494#if NATIVE_HOST_WASM
1495 // Let generic demotion reach the caller before inlining SIMD128 constructors.
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};
1499 }
1500#endif
1501 };
1502}
Compiler attributes for host code, with shader-safe shared modifiers.
#define native_inline
inline [[always_inline]]
Definition attributes.h:212
#define native_nodiscard
C++17 [[nodiscard]].
Definition attributes.h:189
#define native_lifetimebound
[[lifetimebound]]
Definition attributes.h:161
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
Definition mask_traits.h:22
constexpr simd< float, L, Arch > atan2(simd< float, L, Arch > y, simd< float, L, Arch > x) noexcept
Definition exp_body.h:91
constexpr simd< float, N, Arch > ceil(simd< float, N, Arch > x) noexcept
constexpr simd< float, L, Arch > exp2(simd< float, L, Arch > input) noexcept
Definition exp_body.h:65
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...
Definition exp_body.h:109
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)))
Definition wide.h:923
constexpr auto operator!(wide< T, N > const &a)
Definition wide.h:610
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)));}())
Definition wide.h:1263
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 & >())));}())
Definition wide.h:1024
constexpr auto operator~(wide< T, N > const &a)
Definition wide.h:603
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 & >())));}())
Definition wide.h:1193
constexpr auto isnan(wide< T, N > const &input) noexcept(noexcept(detail::wide_generic_detail::wide_map< detail::wide_generic_detail::wide_isnan >(input)))
Definition wide.h:907
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 & >())));}())
Definition wide.h:1003
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 & >())));}())
Definition wide.h:1130
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 & >())));}())
Definition wide.h:1151
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 & >())));}())
Definition wide.h:1109
constexpr auto isfinite(wide< T, N > const &input) noexcept(noexcept(detail::wide_generic_detail::wide_map< detail::wide_generic_detail::wide_isfinite >(input)))
Definition wide.h:893
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 & >())));}())
Definition wide.h:1088
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 & >())));}())
Definition wide.h:1172
constexpr auto isinf(wide< T, N > const &input) noexcept(noexcept(detail::wide_generic_detail::wide_map< detail::wide_generic_detail::wide_isinf >(input)))
Definition wide.h:900
constexpr auto signbit(wide< T, N > const &input) noexcept(noexcept(detail::wide_generic_detail::wide_map< detail::wide_generic_detail::wide_signbit >(input)))
Definition wide.h:914
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.
Definition isa.h:396
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....
Definition wide.h:83
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.
Definition wide.h:133
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().
Definition wide.h:158
constexpr T const & get() const &noexcept
Access element I, preserving constness and the value category of the pack.
Definition wide.h:94
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().
Definition wide.h:164
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.
Definition wide.h:150
constexpr T & get() &noexcept
Access element I, preserving constness and the value category of the pack.
Definition wide.h:91
constexpr T const && get() const &&noexcept
Access element I, preserving constness and the value category of the pack.
Definition wide.h:100
constexpr T && get() &&noexcept
Access element I, preserving constness and the value category of the pack.
Definition wide.h:97
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.
Definition wide.h:140
constexpr wide() noexcept(std::is_nothrow_default_constructible_v< std::array< T, N > >)
Retain opted-in array initialization in the element's target scope.
Definition wide.h:112
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.
Definition wide.h:117
constexpr wide(U &&... values) noexcept((std::is_nothrow_constructible_v< T, U && > &&...))
Construct one element from each argument, preserving argument order.
Definition wide.h:126
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.
Definition wide.h:145