230 KiB
[simd]
29 Numerics library [numerics]
29.10 Data-parallel types [simd]
29.10.1 General [simd.general]
Subclause [simd] defines data-parallel types and operations on these types.
[Note 1:
The intent is to support acceleration through data-parallel execution resources where available, such as SIMD registers and instructions or execution units driven by a common instruction decoder.
SIMD stands for âSingle Instruction Stream â Multiple Data Streamâ; it is defined in Flynn 1966[bib].
â end note]
The set of vectorizable types comprises
all standard integer types, character types, and the types float and double ([basic.fundamental]);
std::float16_t, std::float32_t, and std::float64_t if defined ([basic.extended.fp]); and
complex where T is a vectorizable floating-point type.
The term data-parallel type refers to all enabled specializations of the basic_vec and basic_mask class templates.
A data-parallel object is an object of data-parallel type.
Each specialization of basic_vec or basic_mask is either enabled or disabled, as described in [simd.overview] and[simd.mask.overview].
A data-parallel type consists of one or more elements of an underlying vectorizable type, called the element type.
The number of elements is a constant for each data-parallel type and called thewidth of that type.
The elements in a data-parallel type are indexed from 0 to widthâ1.
An element-wise operation applies a specified operation to the elements of one or more data-parallel objects.
Each such application is unsequenced with respect to the others.
A unary element-wise operation is an element-wise operation that applies a unary operation to each element of a data-parallel object.
A binary element-wise operation is an element-wise operation that applies a binary operation to corresponding elements of two data-parallel objects.
Given a basic_mask<Bytes, Abi> object mask, theselected indices signify the integers i in the range [0, mask.size()) for which mask[i] is true.
Given a data-parallel object data, the selected elements signify the elements data[i] for all selected indices i.
The conversion from an arithmetic type U to a vectorizable typeT is value-preserving if all possible values of U can be represented with type T.
29.10.2 Exposition-only types, variables, and concepts [simd.expos]
using simd-size-type = see below; // exposition onlytemplate<size_t Bytes> using integer-from = see below; // exposition onlytemplate<class T, class Abi>constexpr simd-size-type simd-size-v = see below; // exposition onlytemplate constexpr size_t mask-element-size = see below; // exposition onlytemplateconcept constexpr-wrapper-like = // exposition onlyconvertible_to<T, decltype(T::value)> &&equality_comparable_with<T, decltype(T::value)> && bool_constant<T() == T::value>::value && bool_constant<static_cast<decltype(T::value)>(T()) == T::value>::value;
template using deduced-vec-t = see below; // exposition onlytemplate<class V, class T> using make-compatible-simd-t = see below; // exposition onlytemplateconcept simd-vec-type = // exposition onlysame_as<V, basic_vec<typename V::value_type, typename V::abi_type>> && is_default_constructible_v;
templateconcept simd-mask-type = // exposition onlysame_as<V, basic_mask<mask-element-size, typename V::abi_type>> && is_default_constructible_v;
templateconcept simd-floating-point = // exposition onlysimd-vec-type && floating_point;
templateconcept simd-integral = // exposition onlysimd-vec-type && integral;
templateusing simd-complex-value-type = typename V::value_type::value_type; // exposition onlytemplateconcept simd-complex = // exposition onlysimd-vec-type && same_as<typename V::value_type, complex<simd-complex-value-type>>;
template<class... Ts>concept math-floating-point = // exposition only(simd-floating-point<deduced-vec-t> || ...);
template<class... Ts>requires math-floating-point<Ts...>using math-common-simd-t = see below; // exposition onlytemplate<class BinaryOperation, class T>concept reduction-binary-operation = see below; // exposition only// [simd.expos.abi], simd ABI tagstemplate using native-abi = see below; // exposition onlytemplate<class T, simd-size-type N> using deduce-abi-t = see below; // exposition only// [simd.flags], Load and store flagsstruct convert-flag; // exposition onlystruct aligned-flag; // exposition onlytemplate<size_t N> struct overaligned-flag; // exposition only
29.10.2.1 Exposition-only helpers [simd.expos.defn]
using simd-size-type = see below;
simd-size-type is an alias for a signed integer type.
template<size_t Bytes> using integer-from = see below;
integer-from is an alias for a signed integer typeT such that sizeof(T) equals Bytes.
template<class T, class Abi> constexpr simd-size-type simd-size-v = see below;
simd-size-v<T, Abi> denotes the width of basic_vec<T, Abi> if the specialization basic_vec<T, Abi> is enabled, or 0 otherwise.
template<class T> constexpr size_t mask-element-size = see below;
mask-element-size<basic_mask<Bytes, Abi>> has the valueBytes.
template<class T> using deduced-vec-t = see below;
Let x denote an lvalue of type const T.
deduced-vec-t is an alias for
decltype(x + x), if the type of x + x is an enabled specialization of basic_vec; otherwise
void.
template<class V, class T> using make-compatible-simd-t = see below;
Let x denote an lvalue of type const T.
make-compatible-simd-t<V, T> is an alias for
deduced-vec-t, if that type is not void, otherwise
vec<decltype(x + x), V::size()>.
template<class... Ts> requires [math-floating-point](#concept:math-floating-point "29.10.2 Exposition-only types, variables, and concepts [simd.expos]")<Ts...> using math-common-simd-t = see below;
Let T0 denote Ts...[0].
Let T1 denote Ts...[1].
Let TRest denote a pack such that T0, T1, TRest... is equivalent to Ts....
Let math-common-simd-t<Ts...> be an alias for
deduced-vec-t, if sizeof...(Ts) equals 1; otherwise
common_type_t<deduced-vec-t, deduced-vec-t>, if sizeof...(Ts) equals 2 and math-floating-point &&math-floating-point is true; otherwise
common_type_t<deduced-vec-t, T1>, if sizeof...(Ts) equals 2 and math-floating-point<T0> is true; otherwise
common_type_t<T0, deduced-vec-t>, if sizeof...(Ts) equals 2; otherwise
common_type_t<math-common-simd-t<T0, T1>, TRest...>, if math-common-simd-t<T0, T1> is valid and denotes a type; otherwise
common_type_t<math-common-simd-t<TRest...>, T0, T1>.
template<class BinaryOperation, class T> concept [reduction-binary-operation](#concept:reduction-binary-operation "29.10.2.1 Exposition-only helpers [simd.expos.defn]") = requires (const BinaryOperation binary_op, const vec<T, 1> v) { { binary_op(v, v) } -> [same_as](concept.same#concept:same_as "18.4.2 Concept same_as [concept.same]")<vec<T, 1>>; };
Types BinaryOperation and T modelreduction-binary-operation<BinaryOperation, T> only if:
-
BinaryOperation is a binary element-wise operation and the operation is commutative.
-
An object of type BinaryOperation can be invoked with two arguments of type basic_vec<T, Abi>, with unspecified ABI tagAbi, returning a basic_vec<T, Abi>.
29.10.2.2 simd ABI tags [simd.expos.abi]
template<class T> using native-abi = see below; template<class T, simd-size-type N> using deduce-abi-t = see below;
An ABI tag is a type that indicates a choice of size and binary representation for objects of data-parallel type.
[Note 1:
The intent is for the size and binary representation to depend on the target architecture and compiler flags.
The ABI tag, together with a given element type, implies the width.
â end note]
[Note 2:
The ABI tag is orthogonal to selecting the machine instruction set.
The selected machine instruction set limits the usable ABI tag types, though (see [simd.overview]).
The ABI tags enable users to safely pass objects of data-parallel type between translation unit boundaries (e.g., function calls or I/O).
â end note]
An implementation defines ABI tag types as necessary for the following aliases.
deduce-abi-t<T, N> is defined if
T is a vectorizable type,
N is greater than zero, and
N is not larger than an implementation-defined maximum.
The implementation-defined maximum forN is not smaller than 64 and can differ depending on T.
Where present, deduce-abi-t<T, N> names an ABI tag type such that
simd-size-v<T, deduce-abi-t<T, N>> equals N,
basic_vec<T, deduce-abi-t<T, N>> is enabled ([simd.overview]), and
basic_mask<sizeof(T), deduce-abi-t<integer-from<sizeof(T)>, N>> is enabled.
native-abi is an implementation-defined alias for an ABI tag.
basic_vec<T, native-abi> is an enabled specialization.
[Note 3:
The intent is to use the ABI tag producing the most efficient data-parallel execution for the element type T on the currently targeted system.
For target architectures with ISA extensions, compiler flags can change the type of the native-abi alias.
â end note]
[Example 1:
Consider a target architecture supporting the ABI tags __simd128 and__simd256, where hardware support for __simd256 exists only for floating-point types.
The implementation therefore defines native-abi as an alias for
__simd256 if T is a floating-point type, and
__simd128 otherwise.
â end example]
29.10.3 Header synopsis [simd.syn]
namespace std::simd {// [simd.traits], type traitstemplate<class T, class U = typename T::value_type> struct alignment; template<class T, class U = typename T::value_type>constexpr size_t alignment_v = alignment<T, U>::value; template<class T, class V> struct rebind { using type = see below; }; template<class T, class V> using rebind_t = typename rebind<T, V>::type; template<simd-size-type N, class V> struct resize { using type = see below; }; template<simd-size-type N, class V> using resize_t = typename resize<N, V>::type; // [simd.flags], load and store flagstemplate<class... Flags> struct flags; inline constexpr flags<> flag_default{}; inline constexpr flags<convert-flag> flag_convert{}; inline constexpr flags<aligned-flag> flag_aligned{}; template<size_t N> requires (has_single_bit(N))constexpr flags<overaligned-flag> flag_overaligned{}; // [simd.iterator], class template simd-iteratortemplateclass simd-iterator; // exposition only// [simd.class], class template basic_vectemplate<class T, class Abi = native-abi> class basic_vec; template<class T, simd-size-type N = simd-size-v<T, native-abi>>using vec = basic_vec<T, deduce-abi-t<T, N>>; // [simd.mask.class], class template basic_masktemplate<size_t Bytes, class Abi = native-abi<integer-from>> class basic_mask; template<class T, simd-size-type N = simd-size-v<T, native-abi>>using mask = basic_mask<sizeof(T), deduce-abi-t<T, N>>; // [simd.loadstore], basic_vec load and store functionstemplate<class V = see below, ranges::contiguous_range R, class... Flags>requires ranges::sized_rangeconstexpr V unchecked_load(R&& r, flags<Flags...> f = {}); template<class V = see below, ranges::contiguous_range R, class... Flags>requires ranges::sized_rangeconstexpr V unchecked_load(R&& r, const typename V::mask_type& k, flags<Flags...> f = {}); template<class V = see below, contiguous_iterator I, class... Flags>constexpr V unchecked_load(I first, iter_difference_t n, flags<Flags...> f = {}); template<class V = see below, contiguous_iterator I, class... Flags>constexpr V unchecked_load(I first, iter_difference_t n, const typename V::mask_type& k, flags<Flags...> f = {}); template<class V = see below, contiguous_iterator I, sized_sentinel_for S, class... Flags>constexpr V unchecked_load(I first, S last, flags<Flags...> f = {}); template<class V = see below, contiguous_iterator I, sized_sentinel_for S, class... Flags>constexpr V unchecked_load(I first, S last, const typename V::mask_type& k, flags<Flags...> f = {}); template<class V = see below, ranges::contiguous_range R, class... Flags>requires ranges::sized_rangeconstexpr V partial_load(R&& r, flags<Flags...> f = {}); template<class V = see below, ranges::contiguous_range R, class... Flags>requires ranges::sized_rangeconstexpr V partial_load(R&& r, const typename V::mask_type& k, flags<Flags...> f = {}); template<class V = see below, contiguous_iterator I, class... Flags>constexpr V partial_load(I first, iter_difference_t n, flags<Flags...> f = {}); template<class V = see below, contiguous_iterator I, class... Flags>constexpr V partial_load(I first, iter_difference_t n, const typename V::mask_type& k, flags<Flags...> f = {}); template<class V = see below, contiguous_iterator I, sized_sentinel_for S, class... Flags>constexpr V partial_load(I first, S last, flags<Flags...> f = {}); template<class V = see below, contiguous_iterator I, sized_sentinel_for S, class... Flags>constexpr V partial_load(I first, S last, const typename V::mask_type& k, flags<Flags...> f = {}); template<class T, class Abi, ranges::contiguous_range R, class... Flags>requires ranges::sized_range && indirectly_writable<ranges::iterator_t, T>constexpr void unchecked_store(const basic_vec<T, Abi>& v, R&& r, flags<Flags...> f = {}); template<class T, class Abi, ranges::contiguous_range R, class... Flags>requires ranges::sized_range && indirectly_writable<ranges::iterator_t, T>constexpr void unchecked_store(const basic_vec<T, Abi>& v, R&& r, const typename basic_vec<T, Abi>::mask_type& mask, flags<Flags...> f = {}); template<class T, class Abi, contiguous_iterator I, class... Flags>requires indirectly_writable<I, T>constexpr void unchecked_store(const basic_vec<T, Abi>& v, I first, iter_difference_t n, flags<Flags...> f = {}); template<class T, class Abi, contiguous_iterator I, class... Flags>requires indirectly_writable<I, T>constexpr void unchecked_store(const basic_vec<T, Abi>& v, I first, iter_difference_t n, const typename basic_vec<T, Abi>::mask_type& mask, flags<Flags...> f = {}); template<class T, class Abi, contiguous_iterator I, sized_sentinel_for S, class... Flags>requires indirectly_writable<I, T>constexpr void unchecked_store(const basic_vec<T, Abi>& v, I first, S last, flags<Flags...> f = {}); template<class T, class Abi, contiguous_iterator I, sized_sentinel_for S, class... Flags>requires indirectly_writable<I, T>constexpr void unchecked_store(const basic_vec<T, Abi>& v, I first, S last, const typename basic_vec<T, Abi>::mask_type& mask, flags<Flags...> f = {}); template<class T, class Abi, ranges::contiguous_range R, class... Flags>requires ranges::sized_range && indirectly_writable<ranges::iterator_t, T>constexpr void partial_store(const basic_vec<T, Abi>& v, R&& r, flags<Flags...> f = {}); template<class T, class Abi, ranges::contiguous_range R, class... Flags>requires ranges::sized_range && indirectly_writable<ranges::iterator_t, T>constexpr void partial_store(const basic_vec<T, Abi>& v, R&& r, const typename basic_vec<T, Abi>::mask_type& mask, flags<Flags...> f = {}); template<class T, class Abi, contiguous_iterator I, class... Flags>requires indirectly_writable<I, T>constexpr void partial_store(const basic_vec<T, Abi>& v, I first, iter_difference_t n, flags<Flags...> f = {}); template<class T, class Abi, contiguous_iterator I, class... Flags>requires indirectly_writable<I, T>constexpr void partial_store(const basic_vec<T, Abi>& v, I first, iter_difference_t n, const typename basic_vec<T, Abi>::mask_type& mask, flags<Flags...> f = {}); template<class T, class Abi, contiguous_iterator I, sized_sentinel_for S, class... Flags>requires indirectly_writable<I, T>constexpr void partial_store(const basic_vec<T, Abi>& v, I first, S last, flags<Flags...> f = {}); template<class T, class Abi, contiguous_iterator I, sized_sentinel_for S, class... Flags>requires indirectly_writable<I, T>constexpr void partial_store(const basic_vec<T, Abi>& v, I first, S last, const typename basic_vec<T, Abi>::mask_type& mask, flags<Flags...> f = {}); // [simd.permute.static], permute by static index generatorstatic constexpr simd-size-type zero_element = implementation-defined; static constexpr simd-size-type uninit_element = implementation-defined; template<simd-size-type N = see below, simd-vec-type V, class IdxMap>constexpr resize_t<N, V> permute(const V& v, IdxMap&& idxmap); template<simd-size-type N = see below, simd-mask-type M, class IdxMap>constexpr resize_t<N, M> permute(const M& v, IdxMap&& idxmap); // [simd.permute.dynamic], permute by dynamic indextemplate<simd-vec-type V, simd-integral I>constexpr resize_t<I::size(), V> permute(const V& v, const I& indices); template<simd-mask-type M, simd-integral I>constexpr resize_t<I::size(), M> permute(const M& v, const I& indices); // [simd.permute.mask], permute by active mask bitstemplate<simd-vec-type V>constexpr V compress(const V& v, const typename V::mask_type& selector); template<simd-mask-type M>constexpr M compress(const M& v, const type_identity_t& selector); template<simd-vec-type V>constexpr V compress(const V& v, const typename V::mask_type& selector, const typename V::value_type& fill_value); template<simd-mask-type M>constexpr M compress(const M& v, const type_identity_t& selector, const typename M::value_type& fill_value); template<simd-vec-type V>constexpr V expand(const V& v, const typename V::mask_type& selector, const V& original = {}); template<simd-mask-type M>constexpr M expand(const M& v, const type_identity_t& selector, const M& original = {}); // [simd.permute.memory], permute to and from memorytemplate<class V = see below, ranges::contiguous_range R, simd-integral I, class... Flags>requires ranges::sized_rangeconstexpr V unchecked_gather_from(R&& in, const I& indices, flags<Flags...> f = {}); template<class V = see below, ranges::contiguous_range R, simd-integral I, class... Flags>requires ranges::sized_rangeconstexpr V unchecked_gather_from(R&& in, const typename I::mask_type& mask, const I& indices, flags<Flags...> f = {}); template<class V = see below, ranges::contiguous_range R, simd-integral I, class... Flags>requires ranges::sized_rangeconstexpr V partial_gather_from(R&& in, const I& indices, flags<Flags...> f = {}); template<class V = see below, ranges::contiguous_range R, simd-integral I, class... Flags>requires ranges::sized_rangeconstexpr V partial_gather_from(R&& in, const typename I::mask_type& mask, const I& indices, flags<Flags...> f = {}); template<simd-vec-type V, ranges::contiguous_range R, simd-integral I, class... Flags>requires ranges::sized_rangeconstexpr void unchecked_scatter_to(const V& v, R&& out, const I& indices, flags<Flags...> f = {}); template<simd-vec-type V, ranges::contiguous_range R, simd-integral I, class... Flags>requires ranges::sized_rangeconstexpr void unchecked_scatter_to(const V& v, R&& out, const typename I::mask_type& mask, const I& indices, flags<Flags...> f = {}); template<simd-vec-type V, ranges::contiguous_range R, simd-integral I, class... Flags>requires ranges::sized_rangeconstexpr void partial_scatter_to(const V& v, R&& out, const I& indices, flags<Flags...> f = {}); template<simd-vec-type V, ranges::contiguous_range R, simd-integral I, class... Flags>requires ranges::sized_rangeconstexpr void partial_scatter_to(const V& v, R&& out, const typename I::mask_type& mask, const I& indices, flags<Flags...> f = {}); // [simd.creation], basic_vec and basic_mask creationtemplate<class T, class Abi>constexpr auto chunk(const basic_vec<typename T::value_type, Abi>& x) noexcept; template<class T, class Abi>constexpr auto chunk(const basic_mask<mask-element-size, Abi>& x) noexcept; template<simd-size-type N, class T, class Abi>constexpr auto chunk(const basic_vec<T, Abi>& x) noexcept; template<simd-size-type N, size_t Bytes, class Abi>constexpr auto chunk(const basic_mask<Bytes, Abi>& x) noexcept; template<class T, class... Abis>constexpr basic_vec<T, deduce-abi-t<T, (basic_vec<T, Abis>::size() + ...)>> cat(const basic_vec<T, Abis>&...) noexcept; template<size_t Bytes, class... Abis>constexpr basic_mask<Bytes, deduce-abi-t<integer-from, (basic_mask<Bytes, Abis>::size() + ...)>> cat(const basic_mask<Bytes, Abis>&...) noexcept; // [simd.mask.reductions], basic_mask reductionstemplate<size_t Bytes, class Abi>constexpr bool all_of(const basic_mask<Bytes, Abi>&) noexcept; template<size_t Bytes, class Abi>constexpr bool any_of(const basic_mask<Bytes, Abi>&) noexcept; template<size_t Bytes, class Abi>constexpr bool none_of(const basic_mask<Bytes, Abi>&) noexcept; template<size_t Bytes, class Abi>constexpr simd-size-type reduce_count(const basic_mask<Bytes, Abi>&) noexcept; template<size_t Bytes, class Abi>constexpr simd-size-type reduce_min_index(const basic_mask<Bytes, Abi>&); template<size_t Bytes, class Abi>constexpr simd-size-type reduce_max_index(const basic_mask<Bytes, Abi>&); constexpr bool all_of(same_as auto) noexcept; constexpr bool any_of(same_as auto) noexcept; constexpr bool none_of(same_as auto) noexcept; constexpr simd-size-type reduce_count(same_as auto) noexcept; constexpr simd-size-type reduce_min_index(same_as auto); constexpr simd-size-type reduce_max_index(same_as auto); // [simd.reductions], basic_vec reductionstemplate<class T, class Abi, class BinaryOperation = plus<>>constexpr T reduce(const basic_vec<T, Abi>&, BinaryOperation = {}); template<class T, class Abi, class BinaryOperation = plus<>>constexpr T reduce(const basic_vec<T, Abi>& x, const typename basic_vec<T, Abi>::mask_type& mask, BinaryOperation binary_op = {}, type_identity_t identity_element = see below); template<class T, class Abi>constexpr T reduce_min(const basic_vec<T, Abi>&) noexcept; template<class T, class Abi>constexpr T reduce_min(const basic_vec<T, Abi>&, const typename basic_vec<T, Abi>::mask_type&) noexcept; template<class T, class Abi>constexpr T reduce_max(const basic_vec<T, Abi>&) noexcept; template<class T, class Abi>constexpr T reduce_max(const basic_vec<T, Abi>&, const typename basic_vec<T, Abi>::mask_type&) noexcept; // [simd.alg], algorithmstemplate<class T, class Abi>constexpr basic_vec<T, Abi> min(const basic_vec<T, Abi>& a, const basic_vec<T, Abi>& b) noexcept; template<class T, class Abi>constexpr basic_vec<T, Abi> max(const basic_vec<T, Abi>& a, const basic_vec<T, Abi>& b) noexcept; template<class T, class Abi>constexpr pair<basic_vec<T, Abi>, basic_vec<T, Abi>> minmax(const basic_vec<T, Abi>& a, const basic_vec<T, Abi>& b) noexcept; template<class T, class Abi>constexpr basic_vec<T, Abi> clamp(const basic_vec<T, Abi>& v, const basic_vec<T, Abi>& lo, const basic_vec<T, Abi>& hi); template<class T, class U>constexpr auto select(bool c, const T& a, const U& b)-> remove_cvref_t<decltype(c ? a : b)>; template<size_t Bytes, class Abi, class T, class U>constexpr auto select(const basic_mask<Bytes, Abi>& c, const T& a, const U& b)noexcept -> decltype(simd-select-impl(c, a, b)); // [simd.math], mathematical functionstemplate<math-floating-point V> constexpr deduced-vec-t acos(const V& x); template<math-floating-point V> constexpr deduced-vec-t asin(const V& x); template<math-floating-point V> constexpr deduced-vec-t atan(const V& x); template<class V0, class V1>constexpr math-common-simd-t<V0, V1> atan2(const V0& y, const V1& x); template<math-floating-point V> constexpr deduced-vec-t cos(const V& x); template<math-floating-point V> constexpr deduced-vec-t sin(const V& x); template<math-floating-point V> constexpr deduced-vec-t tan(const V& x); template<math-floating-point V> constexpr deduced-vec-t acosh(const V& x); template<math-floating-point V> constexpr deduced-vec-t asinh(const V& x); template<math-floating-point V> constexpr deduced-vec-t atanh(const V& x); template<math-floating-point V> constexpr deduced-vec-t cosh(const V& x); template<math-floating-point V> constexpr deduced-vec-t sinh(const V& x); template<math-floating-point V> constexpr deduced-vec-t tanh(const V& x); template<math-floating-point V> constexpr deduced-vec-t exp(const V& x); template<math-floating-point V> constexpr deduced-vec-t exp2(const V& x); template<math-floating-point V> constexpr deduced-vec-t expm1(const V& x); template<math-floating-point V>constexpr deduced-vec-t frexp(const V& value, rebind_t<int, deduced-vec-t>* exp); template<math-floating-point V>constexpr rebind_t<int, deduced-vec-t> ilogb(const V& x); template<math-floating-point V>constexpr deduced-vec-t ldexp(const V& x, const rebind_t<int, deduced-vec-t>& exp); template<math-floating-point V> constexpr deduced-vec-t log(const V& x); template<math-floating-point V> constexpr deduced-vec-t log10(const V& x); template<math-floating-point V> constexpr deduced-vec-t log1p(const V& x); template<math-floating-point V> constexpr deduced-vec-t log2(const V& x); template<math-floating-point V> constexpr deduced-vec-t logb(const V& x); template<class T, class Abi>constexpr basic_vec<T, Abi> modf(const type_identity_t<basic_vec<T, Abi>>& value, basic_vec<T, Abi>* iptr); template<math-floating-point V>constexpr deduced-vec-t scalbn(const V& x, const rebind_t<int, deduced-vec-t>& n); template<math-floating-point V>constexpr deduced-vec-t scalbln(const V& x, const rebind_t<long int, deduced-vec-t>& n); template<math-floating-point V> constexpr deduced-vec-t cbrt(const V& x); template<signed_integral T, class Abi>constexpr basic_vec<T, Abi> abs(const basic_vec<T, Abi>& j); template<math-floating-point V> constexpr deduced-vec-t abs(const V& j); template<math-floating-point V> constexpr deduced-vec-t fabs(const V& x); template<class V0, class V1>constexpr math-common-simd-t<V0, V1> hypot(const V0& x, const V1& y); template<class V0, class V1, class V2>constexpr math-common-simd-t<V0, V1, V2> hypot(const V0& x, const V1& y, const V2& z); template<class V0, class V1>constexpr math-common-simd-t<V0, V1> pow(const V0& x, const V1& y); template<math-floating-point V> constexpr deduced-vec-t sqrt(const V& x); template<math-floating-point V> constexpr deduced-vec-t erf(const V& x); template<math-floating-point V> constexpr deduced-vec-t erfc(const V& x); template<math-floating-point V> constexpr deduced-vec-t lgamma(const V& x); template<math-floating-point V> constexpr deduced-vec-t tgamma(const V& x); template<math-floating-point V> constexpr deduced-vec-t ceil(const V& x); template<math-floating-point V> constexpr deduced-vec-t floor(const V& x); template<math-floating-point V> deduced-vec-t nearbyint(const V& x); template<math-floating-point V> deduced-vec-t rint(const V& x); template<math-floating-point V> rebind_t<long int, deduced-vec-t> lrint(const V& x); template<math-floating-point V> rebind_t<long long int, V> llrint(const deduced-vec-t& x); template<math-floating-point V>constexpr deduced-vec-t round(const V& x); template<math-floating-point V>constexpr rebind_t<long int, deduced-vec-t> lround(const V& x); template<math-floating-point V>constexpr rebind_t<long long int, deduced-vec-t> llround(const V& x); template<math-floating-point V>constexpr deduced-vec-t trunc(const V& x); template<class V0, class V1>constexpr math-common-simd-t<V0, V1> fmod(const V0& x, const V1& y); template<class V0, class V1>constexpr math-common-simd-t<V0, V1> remainder(const V0& x, const V1& y); template<class V0, class V1>constexpr math-common-simd-t<V0, V1> remquo(const V0& x, const V1& y, rebind_t<int, math-common-simd-t<V0, V1>>* quo); template<class V0, class V1>constexpr math-common-simd-t<V0, V1> copysign(const V0& x, const V1& y); template<class V0, class V1>constexpr math-common-simd-t<V0, V1> nextafter(const V0& x, const V1& y); template<class V0, class V1>constexpr math-common-simd-t<V0, V1> fdim(const V0& x, const V1& y); template<class V0, class V1>constexpr math-common-simd-t<V0, V1> fmax(const V0& x, const V1& y); template<class V0, class V1>constexpr math-common-simd-t<V0, V1> fmin(const V0& x, const V1& y); template<class V0, class V1, class V2>constexpr math-common-simd-t<V0, V1, V2> fma(const V0& x, const V1& y, const V2& z); template<class V0, class V1, class V2>constexpr math-common-simd-t<V0, V1, V2> lerp(const V0& a, const V1& b, const V2& t) noexcept; template<math-floating-point V>constexpr rebind_t<int, deduced-vec-t> fpclassify(const V& x); template<math-floating-point V>constexpr typename deduced-vec-t::mask_type isfinite(const V& x); template<math-floating-point V>constexpr typename deduced-vec-t::mask_type isinf(const V& x); template<math-floating-point V>constexpr typename deduced-vec-t::mask_type isnan(const V& x); template<math-floating-point V>constexpr typename deduced-vec-t::mask_type isnormal(const V& x); template<math-floating-point V>constexpr typename deduced-vec-t::mask_type signbit(const V& x); template<class V0, class V1>constexpr typename math-common-simd-t<V0, V1>::mask_type isgreater(const V0& x, const V1& y); template<class V0, class V1>constexpr typename math-common-simd-t<V0, V1>::mask_type isgreaterequal(const V0& x, const V1& y); template<class V0, class V1>constexpr typename math-common-simd-t<V0, V1>::mask_type isless(const V0& x, const V1& y); template<class V0, class V1>constexpr typename math-common-simd-t<V0, V1>::mask_type islessequal(const V0& x, const V1& y); template<class V0, class V1>constexpr typename math-common-simd-t<V0, V1>::mask_type islessgreater(const V0& x, const V1& y); template<class V0, class V1>constexpr typename math-common-simd-t<V0, V1>::mask_type isunordered(const V0& x, const V1& y); template<math-floating-point V>deduced-vec-t assoc_laguerre(const rebind_t<unsigned, deduced-vec-t>& n, const rebind_t<unsigned, deduced-vec-t>& m, const V& x); template<math-floating-point V>deduced-vec-t assoc_legendre(const rebind_t<unsigned, deduced-vec-t>& l, const rebind_t<unsigned, deduced-vec-t>& m, const V& x); template<class V0, class V1>math-common-simd-t<V0, V1> beta(const V0& x, const V1& y); template<math-floating-point V> deduced-vec-t comp_ellint_1(const V& k); template<math-floating-point V> deduced-vec-t comp_ellint_2(const V& k); template<class V0, class V1>math-common-simd-t<V0, V1> comp_ellint_3(const V0& k, const V1& nu); template<class V0, class V1>math-common-simd-t<V0, V1> cyl_bessel_i(const V0& nu, const V1& x); template<class V0, class V1>math-common-simd-t<V0, V1> cyl_bessel_j(const V0& nu, const V1& x); template<class V0, class V1>math-common-simd-t<V0, V1> cyl_bessel_k(const V0& nu, const V1& x); template<class V0, class V1>math-common-simd-t<V0, V1> cyl_neumann(const V0& nu, const V1& x); template<class V0, class V1>math-common-simd-t<V0, V1> ellint_1(const V0& k, const V1& phi); template<class V0, class V1>math-common-simd-t<V0, V1> ellint_2(const V0& k, const V1& phi); template<class V0, class V1, class V2>math-common-simd-t<V0, V1, V2> ellint_3(const V0& k, const V1& nu, const V2& phi); template<math-floating-point V> deduced-vec-t expint(const V& x); template<math-floating-point V>deduced-vec-t hermite(const rebind_t<unsigned, deduced-vec-t>& n, const V& x); template<math-floating-point V>deduced-vec-t laguerre(const rebind_t<unsigned, deduced-vec-t>& n, const V& x); template<math-floating-point V>deduced-vec-t legendre(const rebind_t<unsigned, deduced-vec-t>& l, const V& x); template<math-floating-point V>deduced-vec-t riemann_zeta(const V& x); template<math-floating-point V>deduced-vec-t sph_bessel(const rebind_t<unsigned, deduced-vec-t>& n, const V& x); template<math-floating-point V>deduced-vec-t sph_legendre(const rebind_t<unsigned, deduced-vec-t>& l, const rebind_t<unsigned, deduced-vec-t>& m, const V& theta); template<math-floating-point V>deduced-vec-t sph_neumann(const rebind_t<unsigned, deduced-vec-t>& n, const V& x); // [simd.bit], bit manipulationtemplate<simd-vec-type V> constexpr V byteswap(const V& v) noexcept; template<simd-vec-type V> constexpr V bit_ceil(const V& v) noexcept; template<simd-vec-type V> constexpr V bit_floor(const V& v) noexcept; template<simd-vec-type V>constexpr typename V::mask_type has_single_bit(const V& v) noexcept; template<simd-vec-type V0, simd-vec-type V1>constexpr V0 rotl(const V0& v, const V1& s) noexcept; template<simd-vec-type V>constexpr V rotl(const V& v, int s) noexcept; template<simd-vec-type V0, simd-vec-type V1>constexpr V0 rotr(const V0& v, const V1& s) noexcept; template<simd-vec-type V>constexpr V rotr(const V& v, int s) noexcept; template<simd-vec-type V>constexpr rebind_t<make_signed_t, V> bit_width(const V& v) noexcept; template<simd-vec-type V>constexpr rebind_t<make_signed_t, V> countl_zero(const V& v) noexcept; template<simd-vec-type V>constexpr rebind_t<make_signed_t, V> countl_one(const V& v) noexcept; template<simd-vec-type V>constexpr rebind_t<make_signed_t, V> countr_zero(const V& v) noexcept; template<simd-vec-type V>constexpr rebind_t<make_signed_t, V> countr_one(const V& v) noexcept; template<simd-vec-type V>constexpr rebind_t<make_signed_t, V> popcount(const V& v) noexcept; // [simd.complex.math], vec complex mathtemplate<simd-complex V>constexpr rebind_t<simd-complex-value-type, V> real(const V&) noexcept; template<simd-complex V>constexpr rebind_t<simd-complex-value-type, V> imag(const V&) noexcept; template<simd-complex V>constexpr rebind_t<simd-complex-value-type, V> abs(const V&); template<simd-complex V>constexpr rebind_t<simd-complex-value-type, V> arg(const V&); template<simd-complex V>constexpr rebind_t<simd-complex-value-type, V> norm(const V&); template<simd-complex V> constexpr V conj(const V&); template<simd-complex V> constexpr V proj(const V&); template<simd-complex V> constexpr V exp(const V& v); template<simd-complex V> constexpr V log(const V& v); template<simd-complex V> constexpr V log10(const V& v); template<simd-complex V> constexpr V sqrt(const V& v); template<simd-complex V> constexpr V sin(const V& v); template<simd-complex V> constexpr V asin(const V& v); template<simd-complex V> constexpr V cos(const V& v); template<simd-complex V> constexpr V acos(const V& v); template<simd-complex V> constexpr V tan(const V& v); template<simd-complex V> constexpr V atan(const V& v); template<simd-complex V> constexpr V sinh(const V& v); template<simd-complex V> constexpr V asinh(const V& v); template<simd-complex V> constexpr V cosh(const V& v); template<simd-complex V> constexpr V acosh(const V& v); template<simd-complex V> constexpr V tanh(const V& v); template<simd-complex V> constexpr V atanh(const V& v); template<simd-floating-point V> rebind_t<complex, V> polar(const V& x, const V& y = {}); template<simd-complex V> constexpr V pow(const V& x, const V& y);}namespace std {// See [simd.alg], algorithmsusing simd::min; using simd::max; using simd::minmax; using simd::clamp; // See [simd.math], mathematical functionsusing simd::acos; using simd::asin; using simd::atan; using simd::atan2; using simd::cos; using simd::sin; using simd::tan; using simd::acosh; using simd::asinh; using simd::atanh; using simd::cosh; using simd::sinh; using simd::tanh; using simd::exp; using simd::exp2; using simd::expm1; using simd::frexp; using simd::ilogb; using simd::ldexp; using simd::log; using simd::log10; using simd::log1p; using simd::log2; using simd::logb; using simd::modf; using simd::scalbn; using simd::scalbln; using simd::cbrt; using simd::abs; using simd::fabs; using simd::hypot; using simd::pow; using simd::sqrt; using simd::erf; using simd::erfc; using simd::lgamma; using simd::tgamma; using simd::ceil; using simd::floor; using simd::nearbyint; using simd::rint; using simd::lrint; using simd::llrint; using simd::round; using simd::lround; using simd::llround; using simd::trunc; using simd::fmod; using simd::remainder; using simd::remquo; using simd::copysign; using simd::nextafter; using simd::fdim; using simd::fmax; using simd::fmin; using simd::fma; using simd::lerp; using simd::fpclassify; using simd::isfinite; using simd::isinf; using simd::isnan; using simd::isnormal; using simd::signbit; using simd::isgreater; using simd::isgreaterequal; using simd::isless; using simd::islessequal; using simd::islessgreater; using simd::isunordered; using simd::assoc_laguerre; using simd::assoc_legendre; using simd::beta; using simd::comp_ellint_1; using simd::comp_ellint_2; using simd::comp_ellint_3; using simd::cyl_bessel_i; using simd::cyl_bessel_j; using simd::cyl_bessel_k; using simd::cyl_neumann; using simd::ellint_1; using simd::ellint_2; using simd::ellint_3; using simd::expint; using simd::hermite; using simd::laguerre; using simd::legendre; using simd::riemann_zeta; using simd::sph_bessel; using simd::sph_legendre; using simd::sph_neumann; // See [simd.bit], bit manipulationusing simd::byteswap; using simd::bit_ceil; using simd::bit_floor; using simd::has_single_bit; using simd::rotl; using simd::rotr; using simd::bit_width; using simd::countl_zero; using simd::countl_one; using simd::countr_zero; using simd::countr_one; using simd::popcount; // See [simd.complex.math], vec complex mathusing simd::real; using simd::imag; using simd::arg; using simd::norm; using simd::conj; using simd::proj; using simd::polar;}
29.10.4 Type traits [simd.traits]
template<class T, class U = typename T::value_type> struct alignment { see below };
alignment<T, U> has a member value if and only if
T is a specialization of basic_mask and U is bool, or
T is a specialization of basic_vec and U is a vectorizable type.
If value is present, the type alignment<T, U> is aBinaryTypeTrait with a base characteristic ofintegral_constant<size_t, N> for some unspecifiedN ([simd.ctor], [simd.loadstore]).
[Note 1:
value identifies the alignment restrictions on pointers used for (converting) loads and stores for the given type T on arrays of typeU.
â end note]
The behavior of a program that adds specializations for alignment is undefined.
template<class T, class V> struct rebind { using type = see below; };
The member type is present if and only if
V is a data-parallel type,
T is a vectorizable type, and
deduce-abi-t<T, V::size()> has a member type type.
If V is a specialization of basic_vec, let Abi1 denote an ABI tag such that basic_vec<T, Abi1>::size() equalsV::size().
If V is a specialization of basic_mask, let Abi1 denote an ABI tag such that basic_mask<sizeof(T), Abi1>::size() equals V::size().
Where present, the member typedef type names basic_vec<T, Abi1> if V is a specialization of basic_vec orbasic_mask<sizeof(T), Abi1> if V is a specialization ofbasic_mask.
template<simd-size-type N, class V> struct resize { using type = see below; };
Let T denote
typename V::value_type if V is a specialization of basic_vec,
otherwise integer-from<mask-element-size> if V is a specialization of basic_mask.
The member type is present if and only if
V is a data-parallel type, and
deduce-abi-t<T, N> has a member type type.
If V is a specialization of basic_vec, let Abi1 denote an ABI tag such that basic_vec<T, Abi1>::size() equals N.
If V is a specialization of basic_mask, let Abi1 denote an ABI tag such that basic_mask<sizeof(T), Abi1>::size() equals N.
Where present, the member typedef type names basic_vec<T, Abi1> if V is a specialization of basic_vec orbasic_mask<sizeof(T), Abi1> if V is a specialization ofbasic_mask.
29.10.5 Load and store flags [simd.flags]
29.10.5.1 Class template flags overview [simd.flags.overview]
namespace std::simd {template<class... Flags> struct flags {// [simd.flags.oper], flags operatorstemplate<class... Other>friend consteval auto operator|(flags, flags<Other...>); };}
[Note 1:
The class template flags acts like an integer bit-flag for types.
â end note]
Constraints: Every type in the parameter pack Flags is one of convert-flag,aligned-flag, or overaligned-flag.
29.10.5.2 flags operators [simd.flags.oper]
template<class... Other> friend consteval auto operator|(flags a, flags<Other...> b);
Returns: A default-initialized object of type flags<Flags2...> for some Flags2 where every type in Flags2 is present either in template parameter pack Flags or in template parameter pack Other, and every type in template parameter packs Flags and Other is present in Flags2.
If the packs Flags and Other contain two different specializations overaligned-flag and overaligned-flag, Flags2 is not required to contain the specialization overaligned-flag<std::min(N1, N2)>.
29.10.6 Class template simd-iterator [simd.iterator]
namespace std::simd {templateclass simd-iterator { // exposition only V* data_ = nullptr; // exposition only**simd-size-type offset_ = 0; // exposition onlyconstexpr simd-iterator(V& d, simd-size-type off) noexcept; // exposition onlypublic:using value_type = typename V::value_type; using iterator_category = input_iterator_tag; using iterator_concept = random_access_iterator_tag; using difference_type = simd-size-type; constexpr simd-iterator() = default; constexpr simd-iterator(const simd-iterator&) = default; constexpr simd-iterator& operator=(const simd-iterator&) = default; constexpr simd-iterator(const simd-iterator<remove_const_t>&) requires is_const_v; constexpr value_type operator*() const; constexpr simd-iterator& operator++(); constexpr simd-iterator operator++(int); constexpr simd-iterator& operator--(); constexpr simd-iterator operator--(int); constexpr simd-iterator& operator+=(difference_type n); constexpr simd-iterator& operator-=(difference_type n); constexpr value_type operator[](difference_type n) const; friend constexpr bool operator==(simd-iterator a, simd-iterator b) = default; friend constexpr bool operator==(simd-iterator a, default_sentinel_t) noexcept; friend constexpr auto operator<=>(simd-iterator a, simd-iterator b); friend constexpr simd-iterator operator+(simd-iterator i, difference_type n); friend constexpr simd-iterator operator+(difference_type n, simd-iterator i); friend constexpr simd-iterator operator-(simd-iterator i, difference_type n); friend constexpr difference_type operator-(simd-iterator a, simd-iterator b); friend constexpr difference_type operator-(simd-iterator i, default_sentinel_t) noexcept; friend constexpr difference_type operator-(default_sentinel_t, simd-iterator i) noexcept; };}
constexpr simd-iterator(V& d, simd-size-type off) noexcept;
Effects: Initializes data_ with addressof(d) and offset_ with off.
constexpr simd-iterator(const simd-iterator<remove_const_t<V>>& i) requires is_const_v<V>;
Effects: Initializes data_ with i.data_ and offset_ with i.offset_.
constexpr value_type operator*() const;
Effects: Equivalent to: return (**data_*)[offset_];
constexpr simd-iterator& operator++();
Effects: Equivalent to: return *this += 1;
constexpr simd-iterator operator++(int);
Effects: Equivalent to:simd-iterator tmp = *this;*this += 1;return tmp;
constexpr simd-iterator& operator--();
Effects: Equivalent to: return *this -= 1;
constexpr simd-iterator operator--(int);
Effects: Equivalent to:simd-iterator tmp = *this;*this -= 1;return tmp;
constexpr simd-iterator& operator+=(difference_type n);
Preconditions: offset_ + n is in the range [0, V::size()].
Effects: Equivalent to:offset_ += n;return *this;
constexpr simd-iterator& operator-=(difference_type n);
Preconditions: offset_ - n is in the range [0, V::size()].
Effects: Equivalent to:offset_ -= n;return *this;
constexpr value_type operator[](difference_type n) const;
Effects: Equivalent to: return (**data_*)[offset_ + n];
friend constexpr bool operator==(simd-iterator i, default_sentinel_t) noexcept;
Effects: Equivalent to: return i.offset_ == V::size();
friend constexpr auto operator<=>(simd-iterator a, simd-iterator b);
Preconditions: a.data_ == b.data_ is true.
Effects: Equivalent to: return a.offset_ <=> b.offset_;
friend constexpr simd-iterator operator+(simd-iterator i, difference_type n); friend constexpr simd-iterator operator+(difference_type n, simd-iterator i);
Effects: Equivalent to: return i += n;
friend constexpr simd-iterator operator-(simd-iterator i, difference_type n);
Effects: Equivalent to: return i -= n;
friend constexpr difference_type operator-(simd-iterator a, simd-iterator b);
Preconditions: a.data_ == b.data_ is true.
Effects: Equivalent to: return a.offset_ - b.offset_;
friend constexpr difference_type operator-(simd-iterator i, default_sentinel_t) noexcept;
Effects: Equivalent to: return i.offset_ - V::size();
friend constexpr difference_type operator-(default_sentinel_t, simd-iterator i) noexcept;
Effects: Equivalent to: return V::size() - i.offset_;
29.10.7 Class template basic_vec [simd.class]
29.10.7.1 Class template basic_vec overview [simd.overview]
namespace std::simd {template<class T, class Abi> class basic_vec {public:using value_type = T; using mask_type = basic_mask<sizeof(T), Abi>; using abi_type = Abi; using iterator = simd-iterator<basic_vec>; using const_iterator = simd-iterator; constexpr iterator begin() noexcept { return {*this, 0}; }constexpr const_iterator begin() const noexcept { return {this, 0}; }constexpr const_iterator cbegin() const noexcept { return {this, 0}; }constexpr default_sentinel_t end() const noexcept { return {}; }constexpr default_sentinel_t cend() const noexcept { return {}; }static constexpr integral_constant<simd-size-type, simd-size-v<T, Abi>> size {}; constexpr basic_vec() noexcept = default; // [simd.ctor], basic_vec constructorstemplateconstexpr explicit(see below) basic_vec(U&& value) noexcept; template<class U, class UAbi>constexpr explicit(see below) basic_vec(const basic_vec<U, UAbi>&) noexcept; templateconstexpr explicit basic_vec(G&& gen) noexcept; template<class R, class... Flags>constexpr basic_vec(R&& range, flags<Flags...> = {}); template<class R, class... Flags>constexpr basic_vec(R&& range, const mask_type& mask, flags<Flags...> = {}); template<simd-floating-point V>constexpr explicit(see below) basic_vec(const V& reals, const V& imags = {}) noexcept; // [simd.subscr], basic_vec subscript operatorsconstexpr value_type operator const; template<simd-integral I>constexpr resize_t<I::size(), basic_vec> operator[](const I& indices) const; // [simd.complex.access], basic_vec complex accessorsconstexpr auto real() const noexcept; constexpr auto imag() const noexcept; template<simd-floating-point V>constexpr void real(const V& v) noexcept; template<simd-floating-point V>constexpr void imag(const V& v) noexcept; // [simd.unary], basic_vec unary operatorsconstexpr basic_vec& operator++() noexcept; constexpr basic_vec operator++(int) noexcept; constexpr basic_vec& operator--() noexcept; constexpr basic_vec operator--(int) noexcept; constexpr mask_type operator!() const noexcept; constexpr basic_vec operator~() const noexcept; constexpr basic_vec operator+() const noexcept; constexpr basic_vec operator-() const noexcept; // [simd.binary], basic_vec binary operatorsfriend constexpr basic_vec operator+(const basic_vec&, const basic_vec&) noexcept; friend constexpr basic_vec operator-(const basic_vec&, const basic_vec&) noexcept; friend constexpr basic_vec operator(const basic_vec&, const basic_vec&) noexcept; friend constexpr basic_vec operator/(const basic_vec&, const basic_vec&) noexcept; friend constexpr basic_vec operator%(const basic_vec&, const basic_vec&) noexcept; friend constexpr basic_vec operator&(const basic_vec&, const basic_vec&) noexcept; friend constexpr basic_vec operator|(const basic_vec&, const basic_vec&) noexcept; friend constexpr basic_vec operator^(const basic_vec&, const basic_vec&) noexcept; friend constexpr basic_vec operator<<(const basic_vec&, const basic_vec&) noexcept; friend constexpr basic_vec operator>>(const basic_vec&, const basic_vec&) noexcept; friend constexpr basic_vec operator<<(const basic_vec&, simd-size-type) noexcept; friend constexpr basic_vec operator>>(const basic_vec&, simd-size-type) noexcept; // [simd.cassign], basic_vec compound assignmentfriend constexpr basic_vec& operator+=(basic_vec&, const basic_vec&) noexcept; friend constexpr basic_vec& operator-=(basic_vec&, const basic_vec&) noexcept; friend constexpr basic_vec& operator=(basic_vec&, const basic_vec&) noexcept; friend constexpr basic_vec& operator/=(basic_vec&, const basic_vec&) noexcept; friend constexpr basic_vec& operator%=(basic_vec&, const basic_vec&) noexcept; friend constexpr basic_vec& operator&=(basic_vec&, const basic_vec&) noexcept; friend constexpr basic_vec& operator|=(basic_vec&, const basic_vec&) noexcept; friend constexpr basic_vec& operator^=(basic_vec&, const basic_vec&) noexcept; friend constexpr basic_vec& operator<<=(basic_vec&, const basic_vec&) noexcept; friend constexpr basic_vec& operator>>=(basic_vec&, const basic_vec&) noexcept; friend constexpr basic_vec& operator<<=(basic_vec&, simd-size-type) noexcept; friend constexpr basic_vec& operator>>=(basic_vec&, simd-size-type) noexcept; // [simd.comparison], basic_vec compare operatorsfriend constexpr mask_type operator==(const basic_vec&, const basic_vec&) noexcept; friend constexpr mask_type operator!=(const basic_vec&, const basic_vec&) noexcept; friend constexpr mask_type operator>=(const basic_vec&, const basic_vec&) noexcept; friend constexpr mask_type operator<=(const basic_vec&, const basic_vec&) noexcept; friend constexpr mask_type operator>(const basic_vec&, const basic_vec&) noexcept; friend constexpr mask_type operator<(const basic_vec&, const basic_vec&) noexcept; // [simd.cond], basic_vec exposition only conditional operatorsfriend constexpr basic_vec simd-select-impl( // exposition onlyconst mask_type&, const basic_vec&, const basic_vec&) noexcept; }; template<class R, class... Ts> basic_vec(R&& r, Ts...) -> see below;}
Every specialization of basic_vec is a complete type.
The specialization of basic_vec<T, Abi> is
enabled, if T is a vectorizable type, and there exists value N in the range [1, 64], such that Abi is deduce-abi-t<T, N>,
otherwise, disabled, if T is not a vectorizable type,
otherwise, it is implementation-defined if such a specialization is enabled.
If basic_vec<T, Abi> is disabled, then the specialization has a deleted default constructor, deleted destructor, deleted copy constructor, and deleted copy assignment.
In addition only the value_type, abi_type, andmask_type members are present.
If basic_vec<T, Abi> is enabled, then basic_vec<T, Abi> is trivially copyable, default-initialization of an object of such a type default-initializes all elements, and value-initialization value-initializes all elements ([dcl.init.general]).
Recommended practice: Implementations should support implicit conversions between specializations ofbasic_vec and appropriate implementation-defined types.
[Note 1:
Appropriate types are non-standard vector types which are available in the implementation.
â end note]
29.10.7.2 basic_vec constructors [simd.ctor]
template<class U> constexpr explicit(see below) basic_vec(U&& value) noexcept;
Let From denote the type remove_cvref_t.
Constraints: value_type satisfies constructible_from.
Effects: Initializes each element to the value of the argument after conversion tovalue_type.
Remarks: The expression inside explicit evaluates to false if and only ifU satisfies convertible_to<value_type>, and either
From is not an arithmetic type and does not satisfy constexpr-wrapper-like,
From is an arithmetic type and the conversion from From to value_type is value-preserving ([simd.general]), or
From satisfies constexpr-wrapper-like, remove_const_t<decltype(From::value)> is an arithmetic type, and From::value is representable by value_type.
template<class U, class UAbi> constexpr explicit(see below) basic_vec(const basic_vec<U, UAbi>& x) noexcept;
Constraints: simd-size-v<U, UAbi> == size() is true.
Effects: Initializes the ith element with static_cast(x[i]) for all i in the range of [0, size()).
Remarks: The expression inside explicit evaluates to true if either
the conversion from U to value_type is not value-preserving, or
both U and value_type are integral types and the integer conversion rank ([conv.rank]) of U is greater than the integer conversion rank of value_type, or
both U and value_type are floating-point types and the floating-point conversion rank ([conv.rank]) of U is greater than the floating-point conversion rank of value_type.
template<class G> constexpr explicit basic_vec(G&& gen);
Let Fromi denote the typedecltype(gen(integral_constant<simd-size-type, i>())).
Constraints: Fromi satisfies convertible_to<value_type> for all i in the range of [0, size()).
In addition, for all i in the range of [0, size()), if Fromi is an arithmetic type, conversion from Fromi to value_type is value-preserving.
Effects: Initializes the ith element withstatic_cast<value_type>(gen(integral_constant<simd-size-type, i>())) for all i in the range of [0, size()).
Remarks: gen is invoked exactly once for each i, in increasing order of i.
template<class R, class... Flags> constexpr basic_vec(R&& r, flags<Flags...> = {}); template<class R, class... Flags> constexpr basic_vec(R&& r, const mask_type& mask, flags<Flags...> = {});
Let mask be mask_type(true) for the overload with nomask parameter.
Constraints:
R models ranges::contiguous_range and ranges::sized_range,
ranges::size(r) is a constant expression, and
ranges::size(r) is equal to size().
Mandates:
ranges::range_value_t is a vectorizable type, and
if the template parameter pack Flags does not contain convert-flag, then the conversion from ranges::range_value_t to value_type is value-preserving.
Preconditions:
-
If the template parameter pack Flags contains aligned-flag, ranges::data(r) points to storage aligned by alignment_v<basic_vec, ranges::range_value_t>.
-
If the template parameter pack Flags contains overaligned-flag, ranges::data(r) points to storage aligned by N.
Effects: Initializes the ith element with mask[i] ?static_cast(ranges::data(r)[i]) : T() for all i in the range of [0, size()).
template<class R, class... Ts> basic_vec(R&& r, Ts...) -> see below;
Constraints:
R models ranges::contiguous_range and ranges::sized_range, and
ranges::size(r) is a constant expression.
Remarks: The deduced type is equivalent to vec<ranges::range_value_t, ranges::size(r)>.
template<[simd-floating-point](#concept:simd-floating-point "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V> constexpr explicit(see below) basic_vec(const V& reals, const V& imags = {}) noexcept;
Constraints:
simd-complex<basic_vec> is modeled, and
V::size() == size() is true.
Effects: Initializes the ith element with value_type(reals[i], imags[i]) for all i in the range [0, size()).
Remarks: The expression inside explicit evaluates to false if and only if the floating-point conversion rank of T::value_type is greater than or equal to the floating-point conversion rank of V::value_type.
29.10.7.3 basic_vec subscript operator [simd.subscr]
constexpr value_type operator[](simd-size-type i) const;
Preconditions: i >= 0 && i < size() is true.
Returns: The value of the ith element.
Throws: Nothing.
template<[simd-integral](#concept:simd-integral "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") I> constexpr resize_t<I::size(), basic_vec> operator[](const I& indices) const;
Effects: Equivalent to: return permute(*this, indices);
29.10.7.4 basic_vec complex accessors [simd.complex.access]
constexpr auto real() const noexcept; constexpr auto imag() const noexcept;
Constraints: simd-complex<basic_vec> is modeled.
Returns: An object of type rebind_t<typename T::value_type, basic_vec> where the ith element is initialized to the result ofcmplx-func(operator) for all i in the range [0, size()), where cmplx-func is the corresponding function from .
template<[simd-floating-point](#concept:simd-floating-point "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V> constexpr void real(const V& v) noexcept; template<[simd-floating-point](#concept:simd-floating-point "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V> constexpr void imag(const V& v) noexcept;
Constraints:
simd-complex<basic_vec> is modeled,
same_as<typename V::value_type, typename T::value_type> is modeled, and
V::size() == size() is true.
Effects: Replaces each element of the basic_vec object such that theith element is replaced with value_type(v[i],operator.imag()) or value_type(operator.real(), v[i]) for real and imag respectively, for all i in the range [0, size()).
29.10.7.5 basic_vec unary operators [simd.unary]
Effects in [simd.unary] are applied as unary element-wise operations.
constexpr basic_vec& operator++() noexcept;
Constraints: requires (value_type a) { ++a; } is true.
Effects: Increments every element by one.
Returns: *this.
constexpr basic_vec operator++(int) noexcept;
Constraints: requires (value_type a) { a++; } is true.
Effects: Increments every element by one.
Returns: A copy of *this before incrementing.
constexpr basic_vec& operator--() noexcept;
Constraints: requires (value_type a) { --a; } is true.
Effects: Decrements every element by one.
Returns: *this.
constexpr basic_vec operator--(int) noexcept;
Constraints: requires (value_type a) { a--; } is true.
Effects: Decrements every element by one.
Returns: A copy of *this before decrementing.
constexpr mask_type operator!() const noexcept;
Constraints: requires (const value_type a) { !a; } is true.
Returns: A basic_mask object with the ith element set to!operator for all i in the range of [0, size()).
constexpr basic_vec operator~() const noexcept;
Constraints: requires (const value_type a) { ~a; } is true.
Returns: A basic_vec object with the ith element set to~operator for all i in the range of [0, size()).
constexpr basic_vec operator+() const noexcept;
Constraints: requires (const value_type a) { +a; } is true.
Returns: *this.
constexpr basic_vec operator-() const noexcept;
Constraints: requires (const value_type a) { -a; } is true.
Returns: A basic_vec object where the ith element is initialized to-operator for all i in the range of [0, size()).
29.10.8 basic_vec non-member operations [simd.nonmembers]
29.10.8.1 basic_vec binary operators [simd.binary]
friend constexpr basic_vec operator+(const basic_vec& lhs, const basic_vec& rhs) noexcept; friend constexpr basic_vec operator-(const basic_vec& lhs, const basic_vec& rhs) noexcept; friend constexpr basic_vec operator*(const basic_vec& lhs, const basic_vec& rhs) noexcept; friend constexpr basic_vec operator/(const basic_vec& lhs, const basic_vec& rhs) noexcept; friend constexpr basic_vec operator%(const basic_vec& lhs, const basic_vec& rhs) noexcept; friend constexpr basic_vec operator&(const basic_vec& lhs, const basic_vec& rhs) noexcept; friend constexpr basic_vec operator|(const basic_vec& lhs, const basic_vec& rhs) noexcept; friend constexpr basic_vec operator^(const basic_vec& lhs, const basic_vec& rhs) noexcept; friend constexpr basic_vec operator<<(const basic_vec& lhs, const basic_vec& rhs) noexcept; friend constexpr basic_vec operator>>(const basic_vec& lhs, const basic_vec& rhs) noexcept;
Let op be the operator.
Constraints: requires (value_type a, value_type b) { a op b; } istrue.
Returns: A basic_vec object initialized with the results of applyingop to lhs and rhs as a binary element-wise operation.
friend constexpr basic_vec operator<<(const basic_vec& v, simd-size-type n) noexcept; friend constexpr basic_vec operator>>(const basic_vec& v, simd-size-type n) noexcept;
Let op be the operator.
Constraints: requires (value_type a, simd-size-type b) { aop b; } is true.
Returns: A basic_vec object where the ith element is initialized to the result of applying op to v[i] and n for alli in the range of [0, size()).
29.10.8.2 basic_vec compound assignment [simd.cassign]
friend constexpr basic_vec& operator+=(basic_vec& lhs, const basic_vec& rhs) noexcept; friend constexpr basic_vec& operator-=(basic_vec& lhs, const basic_vec& rhs) noexcept; friend constexpr basic_vec& operator*=(basic_vec& lhs, const basic_vec& rhs) noexcept; friend constexpr basic_vec& operator/=(basic_vec& lhs, const basic_vec& rhs) noexcept; friend constexpr basic_vec& operator%=(basic_vec& lhs, const basic_vec& rhs) noexcept; friend constexpr basic_vec& operator&=(basic_vec& lhs, const basic_vec& rhs) noexcept; friend constexpr basic_vec& operator|=(basic_vec& lhs, const basic_vec& rhs) noexcept; friend constexpr basic_vec& operator^=(basic_vec& lhs, const basic_vec& rhs) noexcept; friend constexpr basic_vec& operator<<=(basic_vec& lhs, const basic_vec& rhs) noexcept; friend constexpr basic_vec& operator>>=(basic_vec& lhs, const basic_vec& rhs) noexcept;
Let op be the operator.
Constraints: requires (value_type a, value_type b) { a op b; } istrue.
Effects: These operators apply the indicated operator to lhs and rhs as an element-wise operation.
Returns: lhs.
friend constexpr basic_vec& operator<<=(basic_vec& lhs, simd-size-type n) noexcept; friend constexpr basic_vec& operator>>=(basic_vec& lhs, simd-size-type n) noexcept;
Let op be the operator.
Constraints: requires (value_type a, simd-size-type b) { aop b; } is true.
Effects: Equivalent to: return operator op (lhs, basic_vec(n));
29.10.8.3 basic_vec compare operators [simd.comparison]
friend constexpr mask_type operator==(const basic_vec& lhs, const basic_vec& rhs) noexcept; friend constexpr mask_type operator!=(const basic_vec& lhs, const basic_vec& rhs) noexcept; friend constexpr mask_type operator>=(const basic_vec& lhs, const basic_vec& rhs) noexcept; friend constexpr mask_type operator<=(const basic_vec& lhs, const basic_vec& rhs) noexcept; friend constexpr mask_type operator>(const basic_vec& lhs, const basic_vec& rhs) noexcept; friend constexpr mask_type operator<(const basic_vec& lhs, const basic_vec& rhs) noexcept;
Let op be the operator.
Constraints: requires (value_type a, value_type b) { a op b; } istrue.
Returns: A basic_mask object initialized with the results of applyingop to lhs and rhs as a binary element-wise operation.
29.10.8.4 basic_vec exposition only conditional operators [simd.cond]
friend constexpr basic_vec simd-select-impl(const mask_type& mask, const basic_vec& a, const basic_vec& b) noexcept;
Returns: A basic_vec object where the ith element equalsmask[i] ? a[i] : b[i] for all i in the range of [0, size()).
29.10.8.5 basic_vec reductions [simd.reductions]
template<class T, class Abi, class BinaryOperation = plus<>> constexpr T reduce(const basic_vec<T, Abi>& x, BinaryOperation binary_op = {});
Constraints: BinaryOperation modelsreduction-binary-operation.
Preconditions: binary_op does not modify x.
Returns: GENERALIZED_SUM(binary_op, vec<T, 1>(x[0]), …, vec<T, 1>(x[x.size() - 1]))[0] ([numerics.defns]).
Throws: Any exception thrown from binary_op.
template<class T, class Abi, class BinaryOperation = plus<>> constexpr T reduce( const basic_vec<T, Abi>& x, const typename basic_vec<T, Abi>::mask_type& mask, BinaryOperation binary_op = {}, type_identity_t<T> identity_element = see below);
Constraints:
-
BinaryOperation models reduction-binary-operation.
-
An argument for identity_element is provided for the invocation, unless BinaryOperation is one of plus<>, multiplies<>, bit_and<>, bit_or<>, or bit_xor<>.
Preconditions:
-
binary_op does not modify x.
-
For all finite values y representable by T, the results of y == binary_op(vec<T, 1>(identity_element), vec<T, 1>(y))[0] and y == binary_op(vec<T, 1>(y), vec<T, 1>(identity_element))[0] are true.
Returns: If none_of(mask) is true, returns identity_element.
Otherwise, returns GENERALIZED_SUM(binary_op, vec<T,1>(x[k0]), …, vec<T, 1>(x[kn]))[0] where k0,â¦,kn are the selected indices of mask.
Throws: Any exception thrown from binary_op.
Remarks: The default argument for identity_element is equal to
T() if BinaryOperation is plus<>,
T(1) if BinaryOperation is multiplies<>,
T(~T()) if BinaryOperation is bit_and<>,
T() if BinaryOperation is bit_or<>, or
T() if BinaryOperation is bit_xor<>.
template<class T, class Abi> constexpr T reduce_min(const basic_vec<T, Abi>& x) noexcept;
Constraints: T models totally_ordered.
Returns: The value of an element x[j] for which x[i] < x[j] isfalse for all i in the range of [0, basic_vec<T, Abi>::size()).
template<class T, class Abi> constexpr T reduce_min( const basic_vec<T, Abi>&, const typename basic_vec<T, Abi>::mask_type&) noexcept;
Constraints: T models totally_ordered.
Returns: If none_of(mask) is true, returnsnumeric_limits::max().
Otherwise, returns the value of a selected element x[j] for whichx[i] < x[j] is false for all selected indices i ofmask.
template<class T, class Abi> constexpr T reduce_max(const basic_vec<T, Abi>& x) noexcept;
Constraints: T models totally_ordered.
Returns: The value of an element x[j] for which x[j] < x[i] isfalse for all i in the range of [0, basic_vec<T, Abi>::size()).
template<class T, class Abi> constexpr T reduce_max( const basic_vec<T, Abi>&, const typename basic_vec<T, Abi>::mask_type&) noexcept;
Constraints: T models totally_ordered.
Returns: If none_of(mask) is true, returnsnumeric_limits<V::value_type>::lowest().
Otherwise, returns the value of a selected element x[j] for whichx[j] < x[i] is false for all selected indices i ofmask.
29.10.8.6 basic_vec load and store functions [simd.loadstore]
template<class V = see below, ranges::[contiguous_range](range.refinements#concept:contiguous_range "25.4.6 Other range refinements [range.refinements]") R, class... Flags> requires ranges::[sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<R> constexpr V unchecked_load(R&& r, flags<Flags...> f = {}); template<class V = see below, ranges::[contiguous_range](range.refinements#concept:contiguous_range "25.4.6 Other range refinements [range.refinements]") R, class... Flags> requires ranges::[sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<R> constexpr V unchecked_load(R&& r, const typename V::mask_type& mask, flags<Flags...> f = {}); template<class V = see below, [contiguous_iterator](iterator.concept.contiguous#concept:contiguous_iterator "24.3.4.14 Concept contiguous_iterator [iterator.concept.contiguous]") I, class... Flags> constexpr V unchecked_load(I first, iter_difference_t<I> n, flags<Flags...> f = {}); template<class V = see below, [contiguous_iterator](iterator.concept.contiguous#concept:contiguous_iterator "24.3.4.14 Concept contiguous_iterator [iterator.concept.contiguous]") I, class... Flags> constexpr V unchecked_load(I first, iter_difference_t<I> n, const typename V::mask_type& mask, flags<Flags...> f = {}); template<class V = see below, [contiguous_iterator](iterator.concept.contiguous#concept:contiguous_iterator "24.3.4.14 Concept contiguous_iterator [iterator.concept.contiguous]") I, [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_sentinel_for [iterator.concept.sizedsentinel]")<I> S, class... Flags> constexpr V unchecked_load(I first, S last, flags<Flags...> f = {}); template<class V = see below, [contiguous_iterator](iterator.concept.contiguous#concept:contiguous_iterator "24.3.4.14 Concept contiguous_iterator [iterator.concept.contiguous]") I, [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_sentinel_for [iterator.concept.sizedsentinel]")<I> S, class... Flags> constexpr V unchecked_load(I first, S last, const typename V::mask_type& mask, flags<Flags...> f = {});
Let
mask be V::mask_type(true) for the overloads with no mask parameter;
R be span<const iter_value_t> for the overloads with no template parameter R;
r be R(first, n) for the overloads with an n parameter and R(first, last) for the overloads with a last parameter.
Mandates: If ranges::size(r) is a constant expression thenranges::size(r) ⥠V::size().
Preconditions:
-
[first, first + n) is a valid range for the overloads with an n parameter.
-
[first, last) is a valid range for the overloads with a last parameter.
-
ranges::size(r) ⥠V::size()
Effects: Equivalent to: return partial_load(r, mask, f);
Remarks: The default argument for template parameter V isbasic_vec<ranges::range_value_t>.
template<class V = see below, ranges::[contiguous_range](range.refinements#concept:contiguous_range "25.4.6 Other range refinements [range.refinements]") R, class... Flags> requires ranges::[sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<R> constexpr V partial_load(R&& r, flags<Flags...> f = {}); template<class V = see below, ranges::[contiguous_range](range.refinements#concept:contiguous_range "25.4.6 Other range refinements [range.refinements]") R, class... Flags> requires ranges::[sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<R> constexpr V partial_load(R&& r, const typename V::mask_type& mask, flags<Flags...> f = {}); template<class V = see below, [contiguous_iterator](iterator.concept.contiguous#concept:contiguous_iterator "24.3.4.14 Concept contiguous_iterator [iterator.concept.contiguous]") I, class... Flags> constexpr V partial_load(I first, iter_difference_t<I> n, flags<Flags...> f = {}); template<class V = see below, [contiguous_iterator](iterator.concept.contiguous#concept:contiguous_iterator "24.3.4.14 Concept contiguous_iterator [iterator.concept.contiguous]") I, class... Flags> constexpr V partial_load(I first, iter_difference_t<I> n, const typename V::mask_type& mask, flags<Flags...> f = {}); template<class V = see below, [contiguous_iterator](iterator.concept.contiguous#concept:contiguous_iterator "24.3.4.14 Concept contiguous_iterator [iterator.concept.contiguous]") I, [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_sentinel_for [iterator.concept.sizedsentinel]")<I> S, class... Flags> constexpr V partial_load(I first, S last, flags<Flags...> f = {}); template<class V = see below, [contiguous_iterator](iterator.concept.contiguous#concept:contiguous_iterator "24.3.4.14 Concept contiguous_iterator [iterator.concept.contiguous]") I, [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_sentinel_for [iterator.concept.sizedsentinel]")<I> S, class... Flags> constexpr V partial_load(I first, S last, const typename V::mask_type& mask, flags<Flags...> f = {});
Let
mask be V::mask_type(true) for the overloads with no mask parameter;
R be span<const iter_value_t> for the overloads with no template parameter R;
r be R(first, n) for the overloads with an n parameter and R(first, last) for the overloads with a last parameter.
Mandates:
ranges::range_value_t is a vectorizable type,
same_as<remove_cvref_t, V> is true,
V is an enabled specialization of basic_vec, and
if the template parameter pack Flags does not contain convert-flag, then the conversion from ranges::range_value_t to V::value_type is value-preserving.
Preconditions:
-
[first, first + n) is a valid range for the overloads with an n parameter.
-
[first, last) is a valid range for the overloads with a last parameter.
-
If the template parameter pack Flags contains aligned-flag, ranges::data(r) points to storage aligned by alignment_v<V, ranges::range_value_t>.
-
If the template parameter pack Flags contains overaligned-flag, ranges::data(r) points to storage aligned by N.
Effects: Initializes the ith element with
mask[i] && i < ranges::size(r) ?static_cast(ranges::data(r)[i]) : T() for all i in the range of [0, V::size()).
Remarks: The default argument for template parameter V isbasic_vec<ranges::range_value_t>.
template<class T, class Abi, ranges::[contiguous_range](range.refinements#concept:contiguous_range "25.4.6 Other range refinements [range.refinements]") R, class... Flags> requires ranges::[sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<R> && [indirectly_writable](iterator.concept.writable#concept:indirectly_writable "24.3.4.3 Concept indirectly_writable [iterator.concept.writable]")<ranges::iterator_t<R>, T> constexpr void unchecked_store(const basic_vec<T, Abi>& v, R&& r, flags<Flags...> f = {}); template<class T, class Abi, ranges::[contiguous_range](range.refinements#concept:contiguous_range "25.4.6 Other range refinements [range.refinements]") R, class... Flags> requires ranges::[sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<R> && [indirectly_writable](iterator.concept.writable#concept:indirectly_writable "24.3.4.3 Concept indirectly_writable [iterator.concept.writable]")<ranges::iterator_t<R>, T> constexpr void unchecked_store(const basic_vec<T, Abi>& v, R&& r, const typename basic_vec<T, Abi>::mask_type& mask, flags<Flags...> f = {}); template<class T, class Abi, [contiguous_iterator](iterator.concept.contiguous#concept:contiguous_iterator "24.3.4.14 Concept contiguous_iterator [iterator.concept.contiguous]") I, class... Flags> requires [indirectly_writable](iterator.concept.writable#concept:indirectly_writable "24.3.4.3 Concept indirectly_writable [iterator.concept.writable]")<I, T> constexpr void unchecked_store(const basic_vec<T, Abi>& v, I first, iter_difference_t<I> n, flags<Flags...> f = {}); template<class T, class Abi, [contiguous_iterator](iterator.concept.contiguous#concept:contiguous_iterator "24.3.4.14 Concept contiguous_iterator [iterator.concept.contiguous]") I, class... Flags> requires [indirectly_writable](iterator.concept.writable#concept:indirectly_writable "24.3.4.3 Concept indirectly_writable [iterator.concept.writable]")<I, T> constexpr void unchecked_store(const basic_vec<T, Abi>& v, I first, iter_difference_t<I> n, const typename basic_vec<T, Abi>::mask_type& mask, flags<Flags...> f = {}); template<class T, class Abi, [contiguous_iterator](iterator.concept.contiguous#concept:contiguous_iterator "24.3.4.14 Concept contiguous_iterator [iterator.concept.contiguous]") I, [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_sentinel_for [iterator.concept.sizedsentinel]")<I> S, class... Flags> requires [indirectly_writable](iterator.concept.writable#concept:indirectly_writable "24.3.4.3 Concept indirectly_writable [iterator.concept.writable]")<I, T> constexpr void unchecked_store(const basic_vec<T, Abi>& v, I first, S last, flags<Flags...> f = {}); template<class T, class Abi, [contiguous_iterator](iterator.concept.contiguous#concept:contiguous_iterator "24.3.4.14 Concept contiguous_iterator [iterator.concept.contiguous]") I, [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_sentinel_for [iterator.concept.sizedsentinel]")<I> S, class... Flags> requires [indirectly_writable](iterator.concept.writable#concept:indirectly_writable "24.3.4.3 Concept indirectly_writable [iterator.concept.writable]")<I, T> constexpr void unchecked_store(const basic_vec<T, Abi>& v, I first, S last, const typename basic_vec<T, Abi>::mask_type& mask, flags<Flags...> f = {});
Let
mask be basic_vec<T, Abi>::mask_type(true) for the overloads with no mask parameter;
R be span<iter_value_t> for the overloads with no template parameter R;
r be R(first, n) for the overloads with an n parameter and R(first, last) for the overloads with a last parameter.
Mandates: If ranges::size(r) is a constant expression thenranges::size(r) ⥠simd-size-v<T, Abi>.
Preconditions:
-
[first, first + n) is a valid range for the overloads with an n parameter.
-
[first, last) is a valid range for the overloads with a last parameter.
-
ranges::size(r) ⥠simd-size-v<T, Abi>
Effects: Equivalent to: partial_store(v, r, mask, f).
template<class T, class Abi, ranges::[contiguous_range](range.refinements#concept:contiguous_range "25.4.6 Other range refinements [range.refinements]") R, class... Flags> requires ranges::[sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<R> && [indirectly_writable](iterator.concept.writable#concept:indirectly_writable "24.3.4.3 Concept indirectly_writable [iterator.concept.writable]")<ranges::iterator_t<R>, T> constexpr void partial_store(const basic_vec<T, Abi>& v, R&& r, flags<Flags...> f = {}); template<class T, class Abi, ranges::[contiguous_range](range.refinements#concept:contiguous_range "25.4.6 Other range refinements [range.refinements]") R, class... Flags> requires ranges::[sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<R> && [indirectly_writable](iterator.concept.writable#concept:indirectly_writable "24.3.4.3 Concept indirectly_writable [iterator.concept.writable]")<ranges::iterator_t<R>, T> constexpr void partial_store(const basic_vec<T, Abi>& v, R&& r, const typename basic_vec<T, Abi>::mask_type& mask, flags<Flags...> f = {}); template<class T, class Abi, [contiguous_iterator](iterator.concept.contiguous#concept:contiguous_iterator "24.3.4.14 Concept contiguous_iterator [iterator.concept.contiguous]") I, class... Flags> requires [indirectly_writable](iterator.concept.writable#concept:indirectly_writable "24.3.4.3 Concept indirectly_writable [iterator.concept.writable]")<I, T> constexpr void partial_store(const basic_vec<T, Abi>& v, I first, iter_difference_t<I> n, flags<Flags...> f = {}); template<class T, class Abi, [contiguous_iterator](iterator.concept.contiguous#concept:contiguous_iterator "24.3.4.14 Concept contiguous_iterator [iterator.concept.contiguous]") I, class... Flags> requires [indirectly_writable](iterator.concept.writable#concept:indirectly_writable "24.3.4.3 Concept indirectly_writable [iterator.concept.writable]")<I, T> constexpr void partial_store(const basic_vec<T, Abi>& v, I first, iter_difference_t<I> n, const typename basic_vec<T, Abi>::mask_type& mask, flags<Flags...> f = {}); template<class T, class Abi, [contiguous_iterator](iterator.concept.contiguous#concept:contiguous_iterator "24.3.4.14 Concept contiguous_iterator [iterator.concept.contiguous]") I, [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_sentinel_for [iterator.concept.sizedsentinel]")<I> S, class... Flags> requires [indirectly_writable](iterator.concept.writable#concept:indirectly_writable "24.3.4.3 Concept indirectly_writable [iterator.concept.writable]")<I, T> constexpr void partial_store(const basic_vec<T, Abi>& v, I first, S last, flags<Flags...> f = {}); template<class T, class Abi, [contiguous_iterator](iterator.concept.contiguous#concept:contiguous_iterator "24.3.4.14 Concept contiguous_iterator [iterator.concept.contiguous]") I, [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_sentinel_for [iterator.concept.sizedsentinel]")<I> S, class... Flags> requires [indirectly_writable](iterator.concept.writable#concept:indirectly_writable "24.3.4.3 Concept indirectly_writable [iterator.concept.writable]")<I, T> constexpr void partial_store(const basic_vec<T, Abi>& v, I first, S last, const typename basic_vec<T, Abi>::mask_type& mask, flags<Flags...> f = {});
Let
mask be basic_vec<T, Abi>::mask_type(true) for the overloads with no mask parameter;
R be span<iter_value_t> for the overloads with no template parameter R;
r be R(first, n) for the overloads with an n parameter and R(first, last) for the overloads with a last parameter.
Mandates:
ranges::range_value_t is a vectorizable type, and
if the template parameter pack Flags does not contain convert-flag, then the conversion from T to ranges::range_value_t is value-preserving.
Preconditions:
-
[first, first + n) is a valid range for the overloads with an n parameter.
-
[first, last) is a valid range for the overloads with a last parameter.
-
If the template parameter pack Flags contains aligned-flag, ranges::data(r) points to storage aligned by alignment_v<basic_vec<T, Abi>, ranges::range_value_t>.
-
If the template parameter pack Flags contains overaligned-flag, ranges::data(r) points to storage aligned by N.
Effects: For all i in the range of [0, basic_vec<T, Abi>::size()), ifmask[i] && i < ranges::size(r) is true, evaluatesranges::data(r)[i] = v[i].
29.10.8.7 vec static permute [simd.permute.static]
template<simd-size-type N = see below, [simd-vec-type](#concept:simd-vec-type "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V, class IdxMap> constexpr resize_t<N, V> permute(const V& v, IdxMap&& idxmap); template<simd-size-type N = see below, [simd-mask-type](#concept:simd-mask-type "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") M, class IdxMap> constexpr resize_t<N, M> permute(const M& v, IdxMap&& idxmap);
Let:
gen-fn(i) be idxmap(i, V::size()) if that expression is well-formed, and idxmap(i) otherwise.
perm-fn be the following exposition-only function template:template<simd-size-type I>typename V::value_type perm-fn() {constexpr auto src_index = gen-fn(I); if constexpr (src_index == zero_element) {return typename V::value_type(); } else if constexpr (src_index == uninit_element) {return unspecified-value; } else {return v[src_index]; }}
Constraints: integral<invoke_result_t<IdxMap&, simd-size-type>> ||integral<invoke_result_t<IdxMap&, simd-size-type,simd-size-type>> is true.
Mandates: gen-fn(i) is a constant expression whose value iszero_element, uninit_element, or in the range [0, V::size()), for all i in the range [0, N).
Returns: A data-parallel object where theith element is initialized to the result ofperm-fn() for all i in the range [0, N).
Remarks: The default argument for template parameter N is V::size().
29.10.8.8 vec dynamic permute [simd.permute.dynamic]
template<[simd-vec-type](#concept:simd-vec-type "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V, [simd-integral](#concept:simd-integral "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") I> constexpr resize_t<I::size(), V> permute(const V& v, const I& indices); template<[simd-mask-type](#concept:simd-mask-type "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") M, [simd-integral](#concept:simd-integral "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") I> constexpr resize_t<I::size(), M> permute(const M& v, const I& indices);
Preconditions: All values in indices are in the range [0, V::size()).
Returns: A data-parallel object where the ith element is initialized to the result of v[indices[i]] for all i in the range [0, I::size()).
29.10.8.9 vec mask permute [simd.permute.mask]
template<[simd-vec-type](#concept:simd-vec-type "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V> constexpr V compress(const V& v, const typename V::mask_type& selector); template<[simd-mask-type](#concept:simd-mask-type "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") M> constexpr M compress(const M& v, const type_identity_t<M>& selector);
Let:
-
bit-index(i) be a function which returns the index of the ith element of selector that is true.
-
select-value(i) be a function which returnsv[bit-index(i)] for i in the range [0, reduce_count(selector)) and a valid but unspecified value otherwise. [Note 1: Different calls to select-value can return different unspecified values. â end note]
Returns: A data-parallel object where the ith element is initialized to the result of select-value(i) for all i in the range [0, V::size()).
template<[simd-vec-type](#concept:simd-vec-type "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V> constexpr V compress(const V& v, const typename V::mask_type& selector, const typename V::value_type& fill_value); template<[simd-mask-type](#concept:simd-mask-type "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") M> constexpr M compress(const M& v, const type_identity_t<M>& selector, const typename M::value_type& fill_value);
Let:
-
bit-index(i) be a function which returns the index of the ith element of selector that is true.
-
select-value(i) be a function which returnsv[bit-index(i)] for i in the range [0, reduce_count(selector)) and fill_value otherwise.
Returns: A data-parallel object where the ith element is initialized to the result of select-value(i) for all i in the range [0, V::size()).
template<[simd-vec-type](#concept:simd-vec-type "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V> constexpr V expand(const V& v, const typename V::mask_type& selector, const V& original = {}); template<[simd-mask-type](#concept:simd-mask-type "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") M> constexpr M expand(const M& v, const type_identity_t<M>& selector, const M& original = {});
Let:
-
set-indices be a list of the index positions of true elements in selector.
-
bit-lookup(b) be a function which returns the index where b appears in set-indices.
-
select-value(i) be a function which returnsv[bit-lookup(i)] if selector[i] istrue, otherwise returns original[i].
Returns: A data-parallel object where the ith element is initialized to the result of select-value(i) for all i in the range [0, V::size()).
29.10.8.10 simd memory permute [simd.permute.memory]
template<class V = see below, ranges::[contiguous_range](range.refinements#concept:contiguous_range "25.4.6 Other range refinements [range.refinements]") R, [simd-integral](#concept:simd-integral "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") I, class... Flags> requires ranges::[sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<R> constexpr V unchecked_gather_from(R&& in, const I& indices, flags<Flags...> f = {}); template<class V = see below, ranges::[contiguous_range](range.refinements#concept:contiguous_range "25.4.6 Other range refinements [range.refinements]") R, [simd-integral](#concept:simd-integral "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") I, class... Flags> requires ranges::[sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<R> constexpr V unchecked_gather_from(R&& in, const typename I::mask_type& mask, const I& indices, flags<Flags...> f = {});
Let mask be typename I::mask_type(true) for the overload with no mask parameter.
Preconditions: All values in select(mask, indices, typename I::value_type()) are in the range [0, ranges::size(in)).
Effects: Equivalent to: return partial_gather_from(in, mask, indices, f);
Remarks: The default argument for template parameter V isvec<ranges::range_value_t, I::size()>.
template<class V = see below, ranges::[contiguous_range](range.refinements#concept:contiguous_range "25.4.6 Other range refinements [range.refinements]") R, [simd-integral](#concept:simd-integral "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") I, class... Flags> requires ranges::[sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<R> constexpr V partial_gather_from(R&& in, const I& indices, flags<Flags...> f = {}); template<class V = see below, ranges::[contiguous_range](range.refinements#concept:contiguous_range "25.4.6 Other range refinements [range.refinements]") R, [simd-integral](#concept:simd-integral "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") I, class... Flags> requires ranges::[sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<R> constexpr V partial_gather_from(R&& in, const typename I::mask_type& mask, const I& indices, flags<Flags...> f = {});
Let:
mask be typename I::mask_type(true) for the overload with no mask parameter;
T be typename V::value_type.
Mandates:
ranges::range_value_t is a vectorizable type,
same_as<remove_cvref_t, V> is true,
V is an enabled specialization of basic_vec,
V::size() == I::size() is true, and
if the template parameter pack Flags does not containconvert-flag, then the conversion fromranges::range_value_t to T is value-preserving.
Preconditions:
-
If the template parameter pack Flags containsaligned-flag, ranges::data(in) points to storage aligned byalignment_v<V, ranges::range_value_t>.
-
If the template parameter pack Flags containsoveraligned-flag, ranges::data(in) points to storage aligned by N.
Returns: A basic_vec object where the ith element is initialized to the result ofmask[i] && indices[i] < ranges::size(in) ? static_cast(ranges::data(in)[indices[i]]) : T() for all i in the range [0, I::size()).
Remarks: The default argument for template parameter V isvec<ranges::range_value_t, I::size()>.
template<[simd-vec-type](#concept:simd-vec-type "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V, ranges::[contiguous_range](range.refinements#concept:contiguous_range "25.4.6 Other range refinements [range.refinements]") R, [simd-integral](#concept:simd-integral "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") I, class... Flags> requires ranges::[sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<R> constexpr void unchecked_scatter_to(const V& v, R&& out, const I& indices, flags<Flags...> f = {}); template<[simd-vec-type](#concept:simd-vec-type "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V, ranges::[contiguous_range](range.refinements#concept:contiguous_range "25.4.6 Other range refinements [range.refinements]") R, [simd-integral](#concept:simd-integral "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") I, class... Flags> requires ranges::[sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<R> constexpr void unchecked_scatter_to(const V& v, R&& out, const typename I::mask_type& mask, const I& indices, flags<Flags...> f = {});
Let mask be typename I::mask_type(true) for the overload with no mask parameter.
Preconditions: All values in select(mask, indices, typename I::value_type()) are in the range [0, ranges::size(out)).
Effects: Equivalent to: partial_scatter_to(v, out, mask, indices, f);
template<[simd-vec-type](#concept:simd-vec-type "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V, ranges::[contiguous_range](range.refinements#concept:contiguous_range "25.4.6 Other range refinements [range.refinements]") R, [simd-integral](#concept:simd-integral "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") I, class... Flags> requires ranges::[sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<R> constexpr void partial_scatter_to(const V& v, R&& out, const I& indices, flags<Flags...> f = {}); template<[simd-vec-type](#concept:simd-vec-type "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V, ranges::[contiguous_range](range.refinements#concept:contiguous_range "25.4.6 Other range refinements [range.refinements]") R, [simd-integral](#concept:simd-integral "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") I, class... Flags> requires ranges::[sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<R> constexpr void partial_scatter_to(const V& v, R&& out, const typename I::mask_type& mask, const I& indices, flags<Flags...> f = {});
Let mask be typename I::mask_type(true) for the overload with no mask parameter.
Constraints: V::size() == I::size() is true.
Mandates:
ranges::range_value_t is a vectorizable type, and
if the template parameter pack Flags does not contain convert-flag, then the conversion from typename V::value_type to ranges::range_value_t is value-preserving.
Preconditions:
-
For all selected indices i the values indices[i] are unique.
-
If the template parameter pack Flags contains aligned-flag,ranges::data(out) points to storage aligned byalignment_v<V, ranges::range_value_t>.
-
If the template parameter pack Flags containsoveraligned-flag,ranges::data(out) points to storage aligned by N.
Effects: For all i in the range [0, I::size()), if mask[i] &&(indices[i] < ranges::size(out)) is true, evaluatesranges::data(out)[indices[i]] = v[i].
29.10.8.11 basic_vec and basic_mask creation [simd.creation]
template<class T, class Abi> constexpr auto chunk(const basic_vec<typename T::value_type, Abi>& x) noexcept; template<class T, class Abi> constexpr auto chunk(const basic_mask<mask-element-size<T>, Abi>& x) noexcept;
Constraints:
-
For the first overload, T is an enabled specialization of basic_vec. If basic_vec<typename T::value_type, Abi>::size() % T::size() is not 0, then resize_t<basic_vec<typename T::value_type, Abi>::size()% T::size(), T> is valid and denotes a type.
-
For the second overload, T is an enabled specialization of basic_mask. If basic_mask<mask-element-size, Abi>::size() % T::size() is not 0, then resize_t<basic_mask<mask-element-size, Abi>::size() % T::size(), T> is valid and denotes a type.
Let N be x.size() / T::size().
Returns:
-
If x.size() % T::size() == 0 is true, an array<T, N> with the ith basic_vec or basic_mask element of the jth array element initialized to the value of the element in x with index i + j * T::size().
-
Otherwise, a tuple of N objects of type T and one object of type resize_t<x.size() % T::size(), T>. The ith basic_vec or basic_mask element of the jth tuple element of type T is initialized to the value of the element in x with index i + j * T::size(). The ith basic_vec or basic_mask element of the Nth tuple element is initialized to the value of the element in x with index i + N * T::size().
template<simd-size-type N, class T, class Abi> constexpr auto chunk(const basic_vec<T, Abi>& x) noexcept;
Effects: Equivalent to: return chunk<resize_t<N, basic_vec<T, Abi>>>(x);
template<simd-size-type N, size_t Bytes, class Abi> constexpr auto chunk(const basic_mask<Bytes, Abi>& x) noexcept;
Effects: Equivalent to: return chunk<resize_t<N, basic_mask<Bytes, Abi>>>(x);
template<class T, class... Abis> constexpr vec<T, (basic_vec<T, Abis>::size() + ...)> cat(const basic_vec<T, Abis>&... xs) noexcept; template<size_t Bytes, class... Abis> constexpr basic_mask<Bytes, deduce-abi-t<integer-from<Bytes>, (basic_mask<Bytes, Abis>::size() + ...)>> cat(const basic_mask<Bytes, Abis>&... xs) noexcept;
Constraints:
-
For the first overload vec<T, (basic_vec<T, Abis>::size() + ...)> is enabled.
-
For the second overload basic_mask<Bytes, deduce-abi-t<integer-from, (basic_mask<Bytes, Abis>::size() + ...)>> is enabled.
Returns: A data-parallel object initialized with the concatenated values in thexs pack of data-parallel objects: The ithbasic_vec/basic_mask element of the jth parameter in the xs pack is copied to the return value's element with index i + the sum of the width of the first j parameters in the xs pack.
29.10.8.12 Algorithms [simd.alg]
template<class T, class Abi> constexpr basic_vec<T, Abi> min(const basic_vec<T, Abi>& a, const basic_vec<T, Abi>& b) noexcept;
Constraints: T models totally_ordered.
Returns: The result of the element-wise application of min(a[i], b[i]) for all i in the range of [0, basic_vec<T, Abi>::size()).
template<class T, class Abi> constexpr basic_vec<T, Abi> max(const basic_vec<T, Abi>& a, const basic_vec<T, Abi>& b) noexcept;
Constraints: T models totally_ordered.
Returns: The result of the element-wise application of max(a[i], b[i]) for all i in the range of [0, basic_vec<T, Abi>::size()).
template<class T, class Abi> constexpr pair<basic_vec<T, Abi>, basic_vec<T, Abi>> minmax(const basic_vec<T, Abi>& a, const basic_vec<T, Abi>& b) noexcept;
Effects: Equivalent to: return pair{min(a, b), max(a, b)};
template<class T, class Abi> constexpr basic_vec<T, Abi> clamp( const basic_vec<T, Abi>& v, const basic_vec<T, Abi>& lo, const basic_vec<T, Abi>& hi);
Constraints: T models totally_ordered.
Preconditions: No element in lo shall be greater than the corresponding element inhi.
Returns: The result of element-wise application of clamp(v[i], lo[i], hi[i]) for all i in the range of [0, basic_vec<T, Abi>::size()).
template<class T, class U> constexpr auto select(bool c, const T& a, const U& b) -> remove_cvref_t<decltype(c ? a : b)>;
Effects: Equivalent to: return c ? a : b;
template<size_t Bytes, class Abi, class T, class U> constexpr auto select(const basic_mask<Bytes, Abi>& c, const T& a, const U& b) noexcept -> decltype(simd-select-impl(c, a, b));
Effects: Equivalent to:return simd-select-impl(c, a, b); where simd-select-impl is found by argument-dependent lookup ([basic.lookup.argdep]) contrary to [contents].
29.10.8.13 Mathematical functions [simd.math]
template<[math-floating-point](#concept:math-floating-point "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V> constexpr rebind_t<int, deduced-vec-t<V>> ilogb(const V& x); template<[math-floating-point](#concept:math-floating-point "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V> constexpr deduced-vec-t<V> ldexp(const V& x, const rebind_t<int, deduced-vec-t<V>>& exp); template<[math-floating-point](#concept:math-floating-point "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V> constexpr deduced-vec-t<V> scalbn(const V& x, const rebind_t<int, deduced-vec-t<V>>& n); template<[math-floating-point](#concept:math-floating-point "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V> constexpr deduced-vec-t<V> scalbln(const V& x, const rebind_t<long int, deduced-vec-t<V>>& n); template<[signed_integral](concepts.arithmetic#concept:signed_integral "18.4.7 Arithmetic concepts [concepts.arithmetic]") T, class Abi> constexpr basic_vec<T, Abi> abs(const basic_vec<T, Abi>& j); template<[math-floating-point](#concept:math-floating-point "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V> constexpr deduced-vec-t<V> abs(const V& j); template<[math-floating-point](#concept:math-floating-point "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V> constexpr deduced-vec-t<V> fabs(const V& x); template<[math-floating-point](#concept:math-floating-point "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V> constexpr deduced-vec-t<V> ceil(const V& x); template<[math-floating-point](#concept:math-floating-point "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V> constexpr deduced-vec-t<V> floor(const V& x); template<[math-floating-point](#concept:math-floating-point "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V> deduced-vec-t<V> nearbyint(const V& x); template<[math-floating-point](#concept:math-floating-point "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V> deduced-vec-t<V> rint(const V& x); template<[math-floating-point](#concept:math-floating-point "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V> rebind_t<long int, deduced-vec-t<V>> lrint(const V& x); template<[math-floating-point](#concept:math-floating-point "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V> rebind_t<long long int, deduced-vec-t<V>> llrint(const V& x); template<[math-floating-point](#concept:math-floating-point "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V> constexpr deduced-vec-t<V> round(const V& x); template<[math-floating-point](#concept:math-floating-point "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V> constexpr rebind_t<long int, deduced-vec-t<V>> lround(const V& x); template<[math-floating-point](#concept:math-floating-point "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V> constexpr rebind_t<long long int, deduced-vec-t<V>> llround(const V& x); template<class V0, class V1> constexpr math-common-simd-t<V0, V1> fmod(const V0& x, const V1& y); template<[math-floating-point](#concept:math-floating-point "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V> constexpr deduced-vec-t<V> trunc(const V& x); template<class V0, class V1> constexpr math-common-simd-t<V0, V1> remainder(const V0& x, const V1& y); template<class V0, class V1> constexpr math-common-simd-t<V0, V1> copysign(const V0& x, const V1& y); template<class V0, class V1> constexpr math-common-simd-t<V0, V1> nextafter(const V0& x, const V1& y); template<class V0, class V1> constexpr math-common-simd-t<V0, V1> fdim(const V0& x, const V1& y); template<class V0, class V1> constexpr math-common-simd-t<V0, V1> fmax(const V0& x, const V1& y); template<class V0, class V1> constexpr math-common-simd-t<V0, V1> fmin(const V0& x, const V1& y); template<class V0, class V1, class V2> constexpr math-common-simd-t<V0, V1, V2> fma(const V0& x, const V1& y, const V2& z); template<[math-floating-point](#concept:math-floating-point "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V> constexpr rebind_t<int, deduced-vec-t<V>> fpclassify(const V& x); template<[math-floating-point](#concept:math-floating-point "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V> constexpr typename deduced-vec-t<V>::mask_type isfinite(const V& x); template<[math-floating-point](#concept:math-floating-point "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V> constexpr typename deduced-vec-t<V>::mask_type isinf(const V& x); template<[math-floating-point](#concept:math-floating-point "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V> constexpr typename deduced-vec-t<V>::mask_type isnan(const V& x); template<[math-floating-point](#concept:math-floating-point "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V> constexpr typename deduced-vec-t<V>::mask_type isnormal(const V& x); template<[math-floating-point](#concept:math-floating-point "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V> constexpr typename deduced-vec-t<V>::mask_type signbit(const V& x); template<class V0, class V1> constexpr typename math-common-simd-t<V0, V1>::mask_type isgreater(const V0& x, const V1& y); template<class V0, class V1> constexpr typename math-common-simd-t<V0, V1>::mask_type isgreaterequal(const V0& x, const V1& y); template<class V0, class V1> constexpr typename math-common-simd-t<V0, V1>::mask_type isless(const V0& x, const V1& y); template<class V0, class V1> constexpr typename math-common-simd-t<V0, V1>::mask_type islessequal(const V0& x, const V1& y); template<class V0, class V1> constexpr typename math-common-simd-t<V0, V1>::mask_type islessgreater(const V0& x, const V1& y); template<class V0, class V1> constexpr typename math-common-simd-t<V0, V1>::mask_type isunordered(const V0& x, const V1& y);
Let Ret denote the return type of the specialization of a function template with the name math-func.
Let math-func-vec denote:template<class... Args> Ret math-func-vec(Args... args) {return Ret([&](simd-size-type i) {math-func(make-compatible-simd-t<Ret, Args>(args)[i]...); });}
Returns: A value ret of type Ret, that is element-wise equal to the result of calling math-func-vec with the arguments of the above functions.
If in an invocation of a scalar overload of math-func for indexi in math-func-vec a domain, pole, or range error would occur, the value of ret[i] is unspecified.
Remarks: It is unspecified whether errno ([errno]) is accessed.
template<[math-floating-point](#concept:math-floating-point "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V> constexpr deduced-vec-t<V> acos(const V& x); template<[math-floating-point](#concept:math-floating-point "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V> constexpr deduced-vec-t<V> asin(const V& x); template<[math-floating-point](#concept:math-floating-point "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V> constexpr deduced-vec-t<V> atan(const V& x); template<class V0, class V1> constexpr math-common-simd-t<V0, V1> atan2(const V0& y, const V1& x); template<[math-floating-point](#concept:math-floating-point "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V> constexpr deduced-vec-t<V> cos(const V& x); template<[math-floating-point](#concept:math-floating-point "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V> constexpr deduced-vec-t<V> sin(const V& x); template<[math-floating-point](#concept:math-floating-point "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V> constexpr deduced-vec-t<V> tan(const V& x); template<[math-floating-point](#concept:math-floating-point "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V> constexpr deduced-vec-t<V> acosh(const V& x); template<[math-floating-point](#concept:math-floating-point "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V> constexpr deduced-vec-t<V> asinh(const V& x); template<[math-floating-point](#concept:math-floating-point "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V> constexpr deduced-vec-t<V> atanh(const V& x); template<[math-floating-point](#concept:math-floating-point "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V> constexpr deduced-vec-t<V> cosh(const V& x); template<[math-floating-point](#concept:math-floating-point "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V> constexpr deduced-vec-t<V> sinh(const V& x); template<[math-floating-point](#concept:math-floating-point "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V> constexpr deduced-vec-t<V> tanh(const V& x); template<[math-floating-point](#concept:math-floating-point "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V> constexpr deduced-vec-t<V> exp(const V& x); template<[math-floating-point](#concept:math-floating-point "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V> constexpr deduced-vec-t<V> exp2(const V& x); template<[math-floating-point](#concept:math-floating-point "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V> constexpr deduced-vec-t<V> expm1(const V& x); template<[math-floating-point](#concept:math-floating-point "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V> constexpr deduced-vec-t<V> log(const V& x); template<[math-floating-point](#concept:math-floating-point "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V> constexpr deduced-vec-t<V> log10(const V& x); template<[math-floating-point](#concept:math-floating-point "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V> constexpr deduced-vec-t<V> log1p(const V& x); template<[math-floating-point](#concept:math-floating-point "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V> constexpr deduced-vec-t<V> log2(const V& x); template<[math-floating-point](#concept:math-floating-point "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V> constexpr deduced-vec-t<V> logb(const V& x); template<[math-floating-point](#concept:math-floating-point "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V> constexpr deduced-vec-t<V> cbrt(const V& x); template<class V0, class V1> constexpr math-common-simd-t<V0, V1> hypot(const V0& x, const V1& y); template<class V0, class V1, class V2> constexpr math-common-simd-t<V0, V1, V2> hypot(const V0& x, const V1& y, const V2& z); template<class V0, class V1> constexpr math-common-simd-t<V0, V1> pow(const V0& x, const V1& y); template<[math-floating-point](#concept:math-floating-point "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V> constexpr deduced-vec-t<V> sqrt(const V& x); template<[math-floating-point](#concept:math-floating-point "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V> constexpr deduced-vec-t<V> erf(const V& x); template<[math-floating-point](#concept:math-floating-point "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V> constexpr deduced-vec-t<V> erfc(const V& x); template<[math-floating-point](#concept:math-floating-point "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V> constexpr deduced-vec-t<V> lgamma(const V& x); template<[math-floating-point](#concept:math-floating-point "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V> constexpr deduced-vec-t<V> tgamma(const V& x); template<class V0, class V1, class V2> constexpr math-common-simd-t<V0, V1, V2> lerp(const V0& a, const V1& b, const V2& t) noexcept; template<[math-floating-point](#concept:math-floating-point "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V> deduced-vec-t<V> assoc_laguerre(const rebind_t<unsigned, deduced-vec-t<V>>& n, const rebind_t<unsigned, deduced-vec-t<V>>& m, const V& x); template<[math-floating-point](#concept:math-floating-point "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V> deduced-vec-t<V> assoc_legendre(const rebind_t<unsigned, deduced-vec-t<V>>& l, const rebind_t<unsigned, deduced-vec-t<V>>& m, const V& x); template<class V0, class V1> math-common-simd-t<V0, V1> beta(const V0& x, const V1& y); template<[math-floating-point](#concept:math-floating-point "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V> deduced-vec-t<V> comp_ellint_1(const V& k); template<[math-floating-point](#concept:math-floating-point "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V> deduced-vec-t<V> comp_ellint_2(const V& k); template<class V0, class V1> math-common-simd-t<V0, V1> comp_ellint_3(const V0& k, const V1& nu); template<class V0, class V1> math-common-simd-t<V0, V1> cyl_bessel_i(const V0& nu, const V1& x); template<class V0, class V1> math-common-simd-t<V0, V1> cyl_bessel_j(const V0& nu, const V1& x); template<class V0, class V1> math-common-simd-t<V0, V1> cyl_bessel_k(const V0& nu, const V1& x); template<class V0, class V1> math-common-simd-t<V0, V1> cyl_neumann(const V0& nu, const V1& x); template<class V0, class V1> math-common-simd-t<V0, V1> ellint_1(const V0& k, const V1& phi); template<class V0, class V1> math-common-simd-t<V0, V1> ellint_2(const V0& k, const V1& phi); template<class V0, class V1, class V2> math-common-simd-t<V0, V1, V2> ellint_3(const V0& k, const V1& nu, const V2& phi); template<[math-floating-point](#concept:math-floating-point "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V> deduced-vec-t<V> expint(const V& x); template<[math-floating-point](#concept:math-floating-point "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V> deduced-vec-t<V> hermite(const rebind_t<unsigned, deduced-vec-t<V>>& n, const V& x); template<[math-floating-point](#concept:math-floating-point "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V> deduced-vec-t<V> laguerre(const rebind_t<unsigned, deduced-vec-t<V>>& n, const V& x); template<[math-floating-point](#concept:math-floating-point "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V> deduced-vec-t<V> legendre(const rebind_t<unsigned, deduced-vec-t<V>>& l, const V& x); template<[math-floating-point](#concept:math-floating-point "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V> deduced-vec-t<V> riemann_zeta(const V& x); template<[math-floating-point](#concept:math-floating-point "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V> deduced-vec-t<V> sph_bessel(const rebind_t<unsigned, deduced-vec-t<V>>& n, const V& x); template<[math-floating-point](#concept:math-floating-point "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V> deduced-vec-t<V> sph_legendre(const rebind_t<unsigned, deduced-vec-t<V>>& l, const rebind_t<unsigned, deduced-vec-t<V>>& m, const V& theta); template<[math-floating-point](#concept:math-floating-point "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V> deduced-vec-t<V> sph_neumann(const rebind_t<unsigned, deduced-vec-t<V>>& n, const V& x);
Let Ret denote the return type of the specialization of a function template with the name math-func.
Let math-func-vec denote:template<class... Args> Ret math-func-vec(Args... args) {return Ret([&](simd-size-type i) {math-func(make-compatible-simd-t<Ret, Args>(args)[i]...); });}
Returns: A value ret of type Ret, that is element-wise approximately equal to the result of calling math-func-vec with the arguments of the above functions.
If in an invocation of a scalar overload of math-func for indexi in math-func-vec a domain, pole, or range error would occur, the value of ret[i] is unspecified.
Remarks: It is unspecified whether errno ([errno]) is accessed.
template<[math-floating-point](#concept:math-floating-point "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V> constexpr deduced-vec-t<V> frexp(const V& value, rebind_t<int, deduced-vec-t<V>>* exp);
Let Ret be deduced-vec-t.
Let frexp-vec denote:template pair<Ret, rebind_t<int, Ret>> frexp-vec(const V& x) {int r1[Ret::size()]; Ret r0([&](simd-size-type i) { frexp(make-compatible-simd-t<Ret, V>(x)[i], &r1[i]); }); return {r0, rebind_t<int, Ret>(r1)};}
Let ret be a value of type pair<Ret, rebind_t<int, Ret>> that is the same value as the result of callingfrexp-vec(x).
Effects: Sets *exp to ret.second.
Returns: ret.first.
template<class V0, class V1> constexpr math-common-simd-t<V0, V1> remquo(const V0& x, const V1& y, rebind_t<int, math-common-simd-t<V0, V1>>* quo);
Let Ret be math-common-simd-t<V0, V1>.
Let remquo-vec denote:template<class V0, class V1> pair<Ret, rebind_t<int, Ret>> remquo-vec(const V0& x, const V1& y) {int r1[Ret::size()]; Ret r0([&](simd-size-type i) { remquo(make-compatible-simd-t<Ret, V0>(x)[i], make-compatible-simd-t<Ret, V1>(y)[i], &r1[i]); }); return {r0, rebind_t<int, Ret>(r1)};}
Let ret be a value of type pair<Ret, rebind_t<int, Ret>> that is the same value as the result of callingremquo-vec(x, y).
If in an invocation of a scalar overload of remquo for index i in remquo-vec a domain, pole, or range error would occur, the value of ret[i] is unspecified.
Effects: Sets *quo to ret.second.
Returns: ret.first.
Remarks: It is unspecified whether errno ([errno]) is accessed.
template<class T, class Abi> constexpr basic_vec<T, Abi> modf(const type_identity_t<basic_vec<T, Abi>>& value, basic_vec<T, Abi>* iptr);
Let V be basic_vec<T, Abi>.
Let modf-vec denote:pair<V, V> modf-vec(const V& x) { T r1[Ret::size()]; V r0([&](simd-size-type i) { modf(V(x)[i], &r1[i]); }); return {r0, V(r1)};}
Let ret be a value of type pair<V, V> that is the same value as the result of calling modf-vec(value).
Effects: Sets *iptr to ret.second.
Returns: ret.first.
29.10.8.14 basic_vec bit library [simd.bit]
template<[simd-vec-type](#concept:simd-vec-type "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V> constexpr V byteswap(const V& v) noexcept;
Constraints: The type V::value_type models integral.
Returns: A basic_vec object where the ith element is initialized to the result of std::byteswap(v[i]) for all i in the range [0, V::size()).
template<[simd-vec-type](#concept:simd-vec-type "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V> constexpr V bit_ceil(const V& v) noexcept;
Constraints: The type V::value_type is an unsigned integer type ([basic.fundamental]).
Preconditions: For every i in the range [0, V::size()), the smallest power of 2 greater than or equal to v[i] is representable as a value of typeV::value_type.
Returns: A basic_vec object where the ith element is initialized to the result of std::bit_ceil(v[i]) for all i in the range [0, V::size()).
Remarks: A function call expression that violates the precondition in the Preconditions: element is not a core constant expression ([expr.const]).
template<[simd-vec-type](#concept:simd-vec-type "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V> constexpr V bit_floor(const V& v) noexcept;
Constraints: The type V::value_type is an unsigned integer type ([basic.fundamental]).
Returns: A basic_vec object where the ith element is initialized to the result of std::bit_floor(v[i]) for all i in the range [0, V::size()).
template<[simd-vec-type](#concept:simd-vec-type "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V> constexpr typename V::mask_type has_single_bit(const V& v) noexcept;
Constraints: The type V::value_type is an unsigned integer type ([basic.fundamental]).
Returns: A basic_mask object where the ith element is initialized to the result of std::has_single_bit(v[i]) for all i in the range [0, V::size()).
template<[simd-vec-type](#concept:simd-vec-type "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V0, [simd-vec-type](#concept:simd-vec-type "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V1> constexpr V0 rotl(const V0& v0, const V1& v1) noexcept; template<[simd-vec-type](#concept:simd-vec-type "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V0, [simd-vec-type](#concept:simd-vec-type "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V1> constexpr V0 rotr(const V0& v0, const V1& v1) noexcept;
Constraints:
The type V0::value_type is an unsigned integer type ([basic.fundamental]),
the type V1::value_type models integral,
V0::size() == V1::size() is true, and
sizeof(typename V0::value_type) == sizeof(typename V1::value_type) is true.
Returns: A basic_vec object where the ith element is initialized to the result of bit-func(v0[i],static_cast(v1[i])) for all i in the range [0, V0::size()), where bit-func is the corresponding scalar function from .
template<[simd-vec-type](#concept:simd-vec-type "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V> constexpr V rotl(const V& v, int s) noexcept; template<[simd-vec-type](#concept:simd-vec-type "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V> constexpr V rotr(const V& v, int s) noexcept;
Constraints: The type V::value_type is an unsigned integer type ([basic.fundamental]).
Returns: A basic_vec object where the ith element is initialized to the result of bit-func(v[i], s) for all i in the range [0, V::size()), where bit-func is the corresponding scalar function from .
template<[simd-vec-type](#concept:simd-vec-type "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V> constexpr rebind_t<make_signed_t<typename V::value_type>, V> bit_width(const V& v) noexcept; template<[simd-vec-type](#concept:simd-vec-type "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V> constexpr rebind_t<make_signed_t<typename V::value_type>, V> countl_zero(const V& v) noexcept; template<[simd-vec-type](#concept:simd-vec-type "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V> constexpr rebind_t<make_signed_t<typename V::value_type>, V> countl_one(const V& v) noexcept; template<[simd-vec-type](#concept:simd-vec-type "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V> constexpr rebind_t<make_signed_t<typename V::value_type>, V> countr_zero(const V& v) noexcept; template<[simd-vec-type](#concept:simd-vec-type "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V> constexpr rebind_t<make_signed_t<typename V::value_type>, V> countr_one(const V& v) noexcept; template<[simd-vec-type](#concept:simd-vec-type "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V> constexpr rebind_t<make_signed_t<typename V::value_type>, V> popcount(const V& v) noexcept;
Constraints: The type V::value_type is an unsigned integer type ([basic.fundamental]).
Returns: A basic_vec object where the ith element is initialized to the result of bit-func(v[i]) for all i in the range [0, V::size()), where bit-func is the corresponding scalar function from .
29.10.8.15 vec complex math [simd.complex.math]
`template<simd-complex V> constexpr rebind_t<simd-complex-value-type, V> real(const V&) noexcept; template<simd-complex V> constexpr rebind_t<simd-complex-value-type, V> imag(const V&) noexcept;
template<simd-complex V> constexpr rebind_t<simd-complex-value-type, V> abs(const V&); template<simd-complex V> constexpr rebind_t<simd-complex-value-type, V> arg(const V&); template<simd-complex V> constexpr rebind_t<simd-complex-value-type, V> norm(const V&); template<simd-complex V> constexpr V conj(const V&); template<simd-complex V> constexpr V proj(const V&);
template<simd-complex V> constexpr V exp(const V& v); template<simd-complex V> constexpr V log(const V& v); template<simd-complex V> constexpr V log10(const V& v);
template<simd-complex V> constexpr V sqrt(const V& v); template<simd-complex V> constexpr V sin(const V& v); template<simd-complex V> constexpr V asin(const V& v); template<simd-complex V> constexpr V cos(const V& v); template<simd-complex V> constexpr V acos(const V& v); template<simd-complex V> constexpr V tan(const V& v); template<simd-complex V> constexpr V atan(const V& v); template<simd-complex V> constexpr V sinh(const V& v); template<simd-complex V> constexpr V asinh(const V& v); template<simd-complex V> constexpr V cosh(const V& v); template<simd-complex V> constexpr V acosh(const V& v); template<simd-complex V> constexpr V tanh(const V& v); template<simd-complex V> constexpr V atanh(const V& v); `
Returns: A basic_vec object ret where the ith element is initialized to the result of cmplx-func(v[i]) for alli in the range [0, V::size()), where cmplx-func is the corresponding function from .
If in an invocation ofcmplx-func for index i a domain, pole, or range error would occur, the value of ret[i] is unspecified.
Remarks: It is unspecified whether errno ([errno]) is accessed.
`template<simd-floating-point V> rebind_t<complex, V> polar(const V& x, const V& y = {});
template<simd-complex V> constexpr V pow(const V& x, const V& y); `
Returns: A basic_vec object ret where the ith element is initialized to the result of cmplx-func(x[i], y[i]) for all i in the range [0, V::size()), where cmplx-func is the corresponding function from .
If in an invocation ofcmplx-func for index i a domain, pole, or range error would occur, the value of ret[i] is unspecified.
Remarks: It is unspecified whether errno ([errno]) is accessed.
29.10.9 Class template basic_mask [simd.mask.class]
29.10.9.1 Class template basic_mask overview [simd.mask.overview]
namespace std::simd {template<size_t Bytes, class Abi> class basic_mask {public:using value_type = bool; using abi_type = Abi; using iterator = simd-iterator<basic_mask>; using const_iterator = simd-iterator; constexpr iterator begin() noexcept { return {*this, 0}; }constexpr const_iterator begin() const noexcept { return {*this, 0}; }constexpr const_iterator cbegin() const noexcept { return {*this, 0}; }constexpr default_sentinel_t end() const noexcept { return {}; }constexpr default_sentinel_t cend() const noexcept { return {}; }static constexpr integral_constant<simd-size-type, simd-size-v<integer-from, Abi>>size {}; constexpr basic_mask() noexcept = default; // [simd.mask.ctor], basic_mask constructorsconstexpr explicit basic_mask(value_type) noexcept; template<size_t UBytes, class UAbi>constexpr explicit basic_mask(const basic_mask<UBytes, UAbi>&) noexcept; templateconstexpr explicit basic_mask(G&& gen) noexcept; constexpr basic_mask(const bitset<size()>& b) noexcept; constexpr explicit basic_mask(unsigned_integral auto val) noexcept; // [simd.mask.subscr], basic_mask subscript operatorsconstexpr value_type operator const; template<simd-integral I>constexpr resize_t<I::size(), basic_mask> operator[](const I& indices) const; // [simd.mask.unary], basic_mask unary operatorsconstexpr basic_mask operator!() const noexcept; constexpr basic_vec<integer-from, Abi> operator+() const noexcept; constexpr basic_vec<integer-from, Abi> operator-() const noexcept; constexpr basic_vec<integer-from, Abi> operator~() const noexcept; // [simd.mask.conv], basic_mask conversionstemplate<class U, class A>constexpr explicit(sizeof(U) != Bytes) operator basic_vec<U, A>() const noexcept; constexpr bitset<size()> to_bitset() const noexcept; constexpr unsigned long long to_ullong() const; // [simd.mask.binary], basic_mask binary operatorsfriend constexpr basic_mask operator&&(const basic_mask&, const basic_mask&) noexcept; friend constexpr basic_mask operator||(const basic_mask&, const basic_mask&) noexcept; friend constexpr basic_mask operator&(const basic_mask&, const basic_mask&) noexcept; friend constexpr basic_mask operator|(const basic_mask&, const basic_mask&) noexcept; friend constexpr basic_mask operator^(const basic_mask&, const basic_mask&) noexcept; // [simd.mask.cassign], basic_mask compound assignmentfriend constexpr basic_mask&operator&=(basic_mask&, const basic_mask&) noexcept; friend constexpr basic_mask&operator|=(basic_mask&, const basic_mask&) noexcept; friend constexpr basic_mask&operator^=(basic_mask&, const basic_mask&) noexcept; // [simd.mask.comparison], basic_mask comparisonsfriend constexpr basic_mask operator==(const basic_mask&, const basic_mask&) noexcept; friend constexpr basic_mask operator!=(const basic_mask&, const basic_mask&) noexcept; friend constexpr basic_mask operator>=(const basic_mask&, const basic_mask&) noexcept; friend constexpr basic_mask operator<=(const basic_mask&, const basic_mask&) noexcept; friend constexpr basic_mask operator>(const basic_mask&, const basic_mask&) noexcept; friend constexpr basic_mask operator<(const basic_mask&, const basic_mask&) noexcept; // [simd.mask.cond], basic_mask exposition only conditional operatorsfriend constexpr basic_mask simd-select-impl( // exposition onlyconst basic_mask&, const basic_mask&, const basic_mask&) noexcept; friend constexpr basic_mask simd-select-impl( // exposition onlyconst basic_mask&, same_as auto, same_as auto) noexcept; template<class T0, class T1>friend constexpr vec<see below, size()>simd-select-impl(const basic_mask&, const T0&, const T1&) noexcept; // exposition only};}
Every specialization of basic_mask is a complete type.
The specialization of basic_mask<Bytes, Abi> is:
disabled, if there is no vectorizable type T such that Bytes is equal to sizeof(T),
otherwise, enabled, if there exists a vectorizable type T and a value N in the range [1, 64] such that Bytes is equal to sizeof(T) and Abi is deduce-abi-t<T, N>,
otherwise, it is implementation-defined if such a specialization is enabled.
If basic_mask<Bytes, Abi> is disabled, the specialization has a deleted default constructor, deleted destructor, deleted copy constructor, and deleted copy assignment.
In addition only the value_type and abi_type members are present.
If basic_mask<Bytes, Abi> is enabled,basic_mask<Bytes, Abi> is trivially copyable.
Recommended practice: Implementations should support implicit conversions between specializations of basic_mask and appropriate implementation-defined types.
[Note 1:
Appropriate types are non-standard vector types which are available in the implementation.
â end note]
29.10.9.2 basic_mask constructors [simd.mask.ctor]
constexpr explicit basic_mask(value_type x) noexcept;
Effects: Initializes each element with x.
template<size_t UBytes, class UAbi> constexpr explicit basic_mask(const basic_mask<UBytes, UAbi>& x) noexcept;
Constraints: basic_mask<UBytes, UAbi>::size() == size() istrue.
Effects: Initializes the ith element with x[i] for all i in the range of [0, size()).
template<class G> constexpr explicit basic_mask(G&& gen);
Constraints: The expression gen(integral_constant<simd-size-type, i>()) is well-formed and its type is bool for all i in the range of [0, size()).
Effects: Initializes the ith element withgen(integral_constant<simd-size-type, i>()) for all i in the range of [0, size()).
Remarks: gen is invoked exactly once for each i, in increasing order of i.
constexpr basic_mask(const bitset<size()>& b) noexcept;
Effects: Initializes the ith element with b[i] for all i in the range [0, size()).
constexpr explicit basic_mask([unsigned_integral](concepts.arithmetic#concept:unsigned_integral "18.4.7 Arithmetic concepts [concepts.arithmetic]") auto val) noexcept;
Effects: Initializes the first M elements to the corresponding bit values inval, where M is the smaller of size() and the number of bits in the value representation ([basic.types.general]) of the type of val.
IfM is less than size(), the remaining elements are initialized to zero.
29.10.9.3 basic_mask subscript operator [simd.mask.subscr]
constexpr value_type operator[](simd-size-type i) const;
Preconditions: i >= 0 && i < size() is true.
Returns: The value of the ith element.
Throws: Nothing.
template<[simd-integral](#concept:simd-integral "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") I> constexpr resize_t<I::size(), basic_mask> operator[](const I& indices) const;
Effects: Equivalent to: return permute(*this, indices);
29.10.9.4 basic_mask unary operators [simd.mask.unary]
constexpr basic_mask operator!() const noexcept; constexpr basic_vec<integer-from<Bytes>, Abi> operator+() const noexcept; constexpr basic_vec<integer-from<Bytes>, Abi> operator-() const noexcept; constexpr basic_vec<integer-from<Bytes>, Abi> operator~() const noexcept;
Let op be the operator.
Returns: A data-parallel object where the ith element is initialized to the results of applying op to operator for all i in the range of [0, size()).
29.10.9.5 basic_mask conversions [simd.mask.conv]
template<class U, class A> constexpr explicit(sizeof(U) != Bytes) operator basic_vec<U, A>() const noexcept;
Constraints: simd-size-v<U, A> == simd-size-v<T, Abi>.
Returns: A data-parallel object where the ith element is initialized tostatic_cast(operator).
constexpr bitset<size()> to_bitset() const noexcept;
Returns: A bitset<size()> object where the ith element is initialized tooperator for all i in the range [0, size()).
constexpr unsigned long long to_ullong() const;
Let N be the width of unsigned long long.
Preconditions:
size() <= N is true, or
for all i in the range [N, size()), operator returns false.
Returns: The integral value corresponding to the bits in *this.
Throws: Nothing.
29.10.10 basic_mask non-member operations [simd.mask.nonmembers]
29.10.10.1 basic_mask binary operators [simd.mask.binary]
friend constexpr basic_mask operator&&(const basic_mask& lhs, const basic_mask& rhs) noexcept; friend constexpr basic_mask operator||(const basic_mask& lhs, const basic_mask& rhs) noexcept; friend constexpr basic_mask operator& (const basic_mask& lhs, const basic_mask& rhs) noexcept; friend constexpr basic_mask operator| (const basic_mask& lhs, const basic_mask& rhs) noexcept; friend constexpr basic_mask operator^ (const basic_mask& lhs, const basic_mask& rhs) noexcept;
Let op be the operator.
Returns: A basic_mask object initialized with the results of applyingop to lhs and rhs as a binary element-wise operation.
29.10.10.2 basic_mask compound assignment [simd.mask.cassign]
friend constexpr basic_mask& operator&=(basic_mask& lhs, const basic_mask& rhs) noexcept; friend constexpr basic_mask& operator|=(basic_mask& lhs, const basic_mask& rhs) noexcept; friend constexpr basic_mask& operator^=(basic_mask& lhs, const basic_mask& rhs) noexcept;
Let op be the operator.
Effects: These operators apply op to lhs and rhs as a binary element-wise operation.
Returns: lhs.
29.10.10.3 basic_mask comparisons [simd.mask.comparison]
friend constexpr basic_mask operator==(const basic_mask& lhs, const basic_mask& rhs) noexcept; friend constexpr basic_mask operator!=(const basic_mask& lhs, const basic_mask& rhs) noexcept; friend constexpr basic_mask operator>=(const basic_mask& lhs, const basic_mask& rhs) noexcept; friend constexpr basic_mask operator<=(const basic_mask& lhs, const basic_mask& rhs) noexcept; friend constexpr basic_mask operator>(const basic_mask& lhs, const basic_mask& rhs) noexcept; friend constexpr basic_mask operator<(const basic_mask& lhs, const basic_mask& rhs) noexcept;
Let op be the operator.
Returns: A basic_mask object initialized with the results of applyingop to lhs and rhs as a binary element-wise operation.
29.10.10.4 basic_mask exposition only conditional operators [simd.mask.cond]
friend constexpr basic_mask simd-select-impl( const basic_mask& mask, const basic_mask& a, const basic_mask& b) noexcept;
Returns: A basic_mask object where the ith element equalsmask[i] ? a[i] : b[i] for all i in the range of [0, size()).
friend constexpr basic_mask simd-select-impl(const basic_mask& mask, [same_as](concept.same#concept:same_as "18.4.2 Concept same_as [concept.same]")<bool> auto a, [same_as](concept.same#concept:same_as "18.4.2 Concept same_as [concept.same]")<bool> auto b) noexcept;
Returns: A basic_mask object where the ith element equalsmask[i] ? a : b for all i in the range of [0, size()).
template<class T0, class T1> friend constexpr vec<see below, size()> simd-select-impl(const basic_mask& mask, const T0& a, const T1& b) noexcept;
Constraints:
same_as<T0, T1> is true,
T0 is a vectorizable type, and
sizeof(T0) == Bytes.
Returns: A vec<T0, size()> object where the ith element equalsmask[i] ? a : b for all i in the range of [0, size()).
29.10.10.5 basic_mask reductions [simd.mask.reductions]
template<size_t Bytes, class Abi> constexpr bool all_of(const basic_mask<Bytes, Abi>& k) noexcept;
Returns: true if all boolean elements in k are true, otherwisefalse.
template<size_t Bytes, class Abi> constexpr bool any_of(const basic_mask<Bytes, Abi>& k) noexcept;
Returns: true if at least one boolean element in k is true, otherwise false.
template<size_t Bytes, class Abi> constexpr bool none_of(const basic_mask<Bytes, Abi>& k) noexcept;
Returns: !any_of(k).
template<size_t Bytes, class Abi> constexpr simd-size-type reduce_count(const basic_mask<Bytes, Abi>& k) noexcept;
Returns: The number of boolean elements in k that are true.
template<size_t Bytes, class Abi> constexpr simd-size-type reduce_min_index(const basic_mask<Bytes, Abi>& k);
Preconditions: any_of(k) is true.
Returns: The lowest element index i where k[i] is true.
template<size_t Bytes, class Abi> constexpr simd-size-type reduce_max_index(const basic_mask<Bytes, Abi>& k);
Preconditions: any_of(k) is true.
Returns: The greatest element index i where k[i] is true.
constexpr bool all_of([same_as](concept.same#concept:same_as "18.4.2 Concept same_as [concept.same]")<bool> auto x) noexcept; constexpr bool any_of([same_as](concept.same#concept:same_as "18.4.2 Concept same_as [concept.same]")<bool> auto x) noexcept; constexpr simd-size-type reduce_count([same_as](concept.same#concept:same_as "18.4.2 Concept same_as [concept.same]")<bool> auto x) noexcept;
Returns: x.
constexpr bool none_of([same_as](concept.same#concept:same_as "18.4.2 Concept same_as [concept.same]")<bool> auto x) noexcept;
Returns: !x.
constexpr simd-size-type reduce_min_index([same_as](concept.same#concept:same_as "18.4.2 Concept same_as [concept.same]")<bool> auto x); constexpr simd-size-type reduce_max_index([same_as](concept.same#concept:same_as "18.4.2 Concept same_as [concept.same]")<bool> auto x);
Preconditions: x is true.
Returns: 0.