29 Numerics library [numerics]

29.10 Data-parallel types [simd]

29.10.7 basic_simd non-member operations [simd.nonmembers]

29.10.7.1 basic_simd binary operators [simd.binary]

friend constexpr basic_simd operator+(const basic_simd& lhs, const basic_simd& rhs) noexcept; friend constexpr basic_simd operator-(const basic_simd& lhs, const basic_simd& rhs) noexcept; friend constexpr basic_simd operator*(const basic_simd& lhs, const basic_simd& rhs) noexcept; friend constexpr basic_simd operator/(const basic_simd& lhs, const basic_simd& rhs) noexcept; friend constexpr basic_simd operator%(const basic_simd& lhs, const basic_simd& rhs) noexcept; friend constexpr basic_simd operator&(const basic_simd& lhs, const basic_simd& rhs) noexcept; friend constexpr basic_simd operator|(const basic_simd& lhs, const basic_simd& rhs) noexcept; friend constexpr basic_simd operator^(const basic_simd& lhs, const basic_simd& rhs) noexcept; friend constexpr basic_simd operator<<(const basic_simd& lhs, const basic_simd& rhs) noexcept; friend constexpr basic_simd operator>>(const basic_simd& lhs, const basic_simd& rhs) noexcept;
Let op be the operator.
Constraints: requires (value_type a, value_type b) { a op b; } is true.
Returns: A basic_simd object initialized with the results of applying op to lhs and rhs as a binary element-wise operation.
friend constexpr basic_simd operator<<(const basic_simd& v, simd-size-type n) noexcept; friend constexpr basic_simd operator>>(const basic_simd& v, simd-size-type n) noexcept;
Let op be the operator.
Constraints: requires (value_type a, simd-size-type b) { a op b; } is true.
Returns: A basic_simd object where the element is initialized to the result of applying op to v[i] and n for all i in the range of [0, size()).

29.10.7.2 basic_simd compound assignment [simd.cassign]

friend constexpr basic_simd& operator+=(basic_simd& lhs, const basic_simd& rhs) noexcept; friend constexpr basic_simd& operator-=(basic_simd& lhs, const basic_simd& rhs) noexcept; friend constexpr basic_simd& operator*=(basic_simd& lhs, const basic_simd& rhs) noexcept; friend constexpr basic_simd& operator/=(basic_simd& lhs, const basic_simd& rhs) noexcept; friend constexpr basic_simd& operator%=(basic_simd& lhs, const basic_simd& rhs) noexcept; friend constexpr basic_simd& operator&=(basic_simd& lhs, const basic_simd& rhs) noexcept; friend constexpr basic_simd& operator|=(basic_simd& lhs, const basic_simd& rhs) noexcept; friend constexpr basic_simd& operator^=(basic_simd& lhs, const basic_simd& rhs) noexcept; friend constexpr basic_simd& operator<<=(basic_simd& lhs, const basic_simd& rhs) noexcept; friend constexpr basic_simd& operator>>=(basic_simd& lhs, const basic_simd& rhs) noexcept;
Let op be the operator.
Constraints: requires (value_type a, value_type b) { a op b; } is true.
Effects: These operators apply the indicated operator to lhs and rhs as an element-wise operation.
Returns: lhs.
friend constexpr basic_simd& operator<<=(basic_simd& lhs, simd-size-type n) noexcept; friend constexpr basic_simd& operator>>=(basic_simd& lhs, simd-size-type n) noexcept;
Let op be the operator.
Constraints: requires (value_type a, simd-size-type b) { a op b; } is true.
Effects: Equivalent to: return operator op (lhs, basic_simd(n));

29.10.7.3 basic_simd compare operators [simd.comparison]

friend constexpr mask_type operator==(const basic_simd& lhs, const basic_simd& rhs) noexcept; friend constexpr mask_type operator!=(const basic_simd& lhs, const basic_simd& rhs) noexcept; friend constexpr mask_type operator>=(const basic_simd& lhs, const basic_simd& rhs) noexcept; friend constexpr mask_type operator<=(const basic_simd& lhs, const basic_simd& rhs) noexcept; friend constexpr mask_type operator>(const basic_simd& lhs, const basic_simd& rhs) noexcept; friend constexpr mask_type operator<(const basic_simd& lhs, const basic_simd& rhs) noexcept;
Let op be the operator.
Constraints: requires (value_type a, value_type b) { a op b; } is true.
Returns: A basic_simd_mask object initialized with the results of applying op to lhs and rhs as a binary element-wise operation.

29.10.7.4 basic_simd exposition only conditional operators [simd.cond]

friend constexpr basic_simd simd-select-impl(const mask_type& mask, const basic_simd& a, const basic_simd& b) noexcept;
Returns: A basic_simd object where the element equals mask[i] ? a[i] : b[i] for all i in the range of [0, size()).

29.10.7.5 basic_simd reductions [simd.reductions]

template<class T, class Abi, class BinaryOperation = plus<>> constexpr T reduce(const basic_simd<T, Abi>& x, BinaryOperation binary_op = {});
Constraints: BinaryOperation models reduction-binary-operation<T>.
Preconditions: binary_op does not modify x.
Returns: GENERALIZED_SUM(binary_op, simd<T, 1>(x[0]), , simd<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_simd<T, Abi>& x, const typename basic_simd<T, Abi>::mask_type& mask, BinaryOperation binary_op = {}, type_identity_t<T> identity_element = see below);
Constraints:
  • BinaryOperation models reduction-binary-operation<T>.
  • 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(simd<T, 1>(identity_element), simd<T, 1>(y))[0] and y == binary_op(simd<T, 1>(y), simd<T, 1>(identity_element))[0] are true.
Returns: If none_of(mask) is true, returns identity_element.
Otherwise, returns GENERALIZED_SUM(binary_op, simd<T, 1>(x[]), , simd<T, 1>(x[]))[0] where 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_simd<T, Abi>& x) noexcept;
Constraints: T models totally_ordered.
Returns: The value of an element x[j] for which x[i] < x[j] is false for all i in the range of [0, basic_simd<T, Abi>​::​size()).
template<class T, class Abi> constexpr T reduce_min( const basic_simd<T, Abi>&, const typename basic_simd<T, Abi>::mask_type&) noexcept;
Constraints: T models totally_ordered.
Returns: If none_of(mask) is true, returns numeric_limits<T>​::​max().
Otherwise, returns the value of a selected element x[j] for which x[i] < x[j] is false for all selected indices i of mask.
template<class T, class Abi> constexpr T reduce_max(const basic_simd<T, Abi>& x) noexcept;
Constraints: T models totally_ordered.
Returns: The value of an element x[j] for which x[j] < x[i] is false for all i in the range of [0, basic_simd<T, Abi>​::​size()).
template<class T, class Abi> constexpr T reduce_max( const basic_simd<T, Abi>&, const typename basic_simd<T, Abi>::mask_type&) noexcept;
Constraints: T models totally_ordered.
Returns: If none_of(mask) is true, returns numeric_limits<V​::​value_type>​::​lowest().
Otherwise, returns the value of a selected element x[j] for which x[j] < x[i] is false for all selected indices i of mask.

29.10.7.6 basic_simd load and store functions [simd.loadstore]

template<class V = see below, ranges::contiguous_range R, class... Flags> requires ranges::sized_range<R> constexpr V simd_unchecked_load(R&& r, simd_flags<Flags...> f = {}); template<class V = see below, ranges::contiguous_range R, class... Flags> requires ranges::sized_range<R> constexpr V simd_unchecked_load(R&& r, const typename V::mask_type& mask, simd_flags<Flags...> f = {}); template<class V = see below, contiguous_iterator I, class... Flags> constexpr V simd_unchecked_load(I first, iter_difference_t<I> n, simd_flags<Flags...> f = {}); template<class V = see below, contiguous_iterator I, class... Flags> constexpr V simd_unchecked_load(I first, iter_difference_t<I> n, const typename V::mask_type& mask, simd_flags<Flags...> f = {}); template<class V = see below, contiguous_iterator I, sized_sentinel_for<I> S, class... Flags> constexpr V simd_unchecked_load(I first, S last, simd_flags<Flags...> f = {}); template<class V = see below, contiguous_iterator I, sized_sentinel_for<I> S, class... Flags> constexpr V simd_unchecked_load(I first, S last, const typename V::mask_type& mask, simd_flags<Flags...> f = {});
Let
  • mask be V​::​mask_type(true) for the overloads with no mask parameter;
  • R be span<const iter_value_t<I>> 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 then ranges​::​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 simd_partial_load<V>(r, mask, f);
Remarks: The default argument for template parameter V is basic_simd<ranges​::​range_value_t<R>>.
template<class V = see below, ranges::contiguous_range R, class... Flags> requires ranges::sized_range<R> constexpr V simd_partial_load(R&& r, simd_flags<Flags...> f = {}); template<class V = see below, ranges::contiguous_range R, class... Flags> requires ranges::sized_range<R> constexpr V simd_partial_load(R&& r, const typename V::mask_type& mask, simd_flags<Flags...> f = {}); template<class V = see below, contiguous_iterator I, class... Flags> constexpr V simd_partial_load(I first, iter_difference_t<I> n, simd_flags<Flags...> f = {}); template<class V = see below, contiguous_iterator I, class... Flags> constexpr V simd_partial_load(I first, iter_difference_t<I> n, const typename V::mask_type& mask, simd_flags<Flags...> f = {}); template<class V = see below, contiguous_iterator I, sized_sentinel_for<I> S, class... Flags> constexpr V simd_partial_load(I first, S last, simd_flags<Flags...> f = {}); template<class V = see below, contiguous_iterator I, sized_sentinel_for<I> S, class... Flags> constexpr V simd_partial_load(I first, S last, const typename V::mask_type& mask, simd_flags<Flags...> f = {});
Let
  • mask be V​::​mask_type(true) for the overloads with no mask parameter;
  • R be span<const iter_value_t<I>> 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<R> is a vectorizable type,
  • same_as<remove_cvref_t<V>, V> is true,
  • V is an enabled specialization of basic_simd, and
  • if the template parameter pack Flags does not contain convert-flag, then the conversion from ranges​::​range_value_t<R> 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 simd_alignment_v<V, ranges​::​range_value_t<R>>.
  • If the template parameter pack Flags contains overaligned-flag<N>, ranges​::​data(r) points to storage aligned by N.
Effects: Initializes the element with
mask[i] && i < ranges​::​size(r) ? static_cast<T>(​ranges​::​data(r)[i]) : T() for all i in the range of [0, V​::​size()).
Remarks: The default argument for template parameter V is basic_simd<ranges​::​range_value_t<R>>.
template<class T, class Abi, ranges::contiguous_range R, class... Flags> requires ranges::sized_range<R> && indirectly_writable<ranges::iterator_t<R>, T> constexpr void simd_unchecked_store(const basic_simd<T, Abi>& v, R&& r, simd_flags<Flags...> f = {}); template<class T, class Abi, ranges::contiguous_range R, class... Flags> requires ranges::sized_range<R> && indirectly_writable<ranges::iterator_t<R>, T> constexpr void simd_unchecked_store(const basic_simd<T, Abi>& v, R&& r, const typename basic_simd<T, Abi>::mask_type& mask, simd_flags<Flags...> f = {}); template<class T, class Abi, contiguous_iterator I, class... Flags> requires indirectly_writable<I, T> constexpr void simd_unchecked_store(const basic_simd<T, Abi>& v, I first, iter_difference_t<I> n, simd_flags<Flags...> f = {}); template<class T, class Abi, contiguous_iterator I, class... Flags> requires indirectly_writable<I, T> constexpr void simd_unchecked_store(const basic_simd<T, Abi>& v, I first, iter_difference_t<I> n, const typename basic_simd<T, Abi>::mask_type& mask, simd_flags<Flags...> f = {}); template<class T, class Abi, contiguous_iterator I, sized_sentinel_for<I> S, class... Flags> requires indirectly_writable<I, T> constexpr void simd_unchecked_store(const basic_simd<T, Abi>& v, I first, S last, simd_flags<Flags...> f = {}); template<class T, class Abi, contiguous_iterator I, sized_sentinel_for<I> S, class... Flags> requires indirectly_writable<I, T> constexpr void simd_unchecked_store(const basic_simd<T, Abi>& v, I first, S last, const typename basic_simd<T, Abi>::mask_type& mask, simd_flags<Flags...> f = {});
Let
  • mask be basic_simd<T, Abi>​::​mask_type(true) for the overloads with no mask parameter;
  • R be span<iter_value_t<I>> 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 then ranges​::​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: simd_partial_store(v, r, mask, f).
template<class T, class Abi, ranges::contiguous_range R, class... Flags> requires ranges::sized_range<R> && indirectly_writable<ranges::iterator_t<R>, T> constexpr void simd_partial_store(const basic_simd<T, Abi>& v, R&& r, simd_flags<Flags...> f = {}); template<class T, class Abi, ranges::contiguous_range R, class... Flags> requires ranges::sized_range<R> && indirectly_writable<ranges::iterator_t<R>, T> constexpr void simd_partial_store(const basic_simd<T, Abi>& v, R&& r, const typename basic_simd<T, Abi>::mask_type& mask, simd_flags<Flags...> f = {}); template<class T, class Abi, contiguous_iterator I, class... Flags> requires indirectly_writable<I, T> constexpr void simd_partial_store(const basic_simd<T, Abi>& v, I first, iter_difference_t<I> n, simd_flags<Flags...> f = {}); template<class T, class Abi, contiguous_iterator I, class... Flags> requires indirectly_writable<I, T> constexpr void simd_partial_store(const basic_simd<T, Abi>& v, I first, iter_difference_t<I> n, const typename basic_simd<T, Abi>::mask_type& mask, simd_flags<Flags...> f = {}); template<class T, class Abi, contiguous_iterator I, sized_sentinel_for<I> S, class... Flags> requires indirectly_writable<I, T> constexpr void simd_partial_store(const basic_simd<T, Abi>& v, I first, S last, simd_flags<Flags...> f = {}); template<class T, class Abi, contiguous_iterator I, sized_sentinel_for<I> S, class... Flags> requires indirectly_writable<I, T> constexpr void simd_partial_store(const basic_simd<T, Abi>& v, I first, S last, const typename basic_simd<T, Abi>::mask_type& mask, simd_flags<Flags...> f = {});
Let
  • mask be basic_simd<T, Abi>​::​mask_type(true) for the overloads with no mask parameter;
  • R be span<iter_value_t<I>> 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<R> 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<R> 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 simd_alignment_v<basic_simd<T, Abi>, ranges​::​range_value_t<R>>.
  • If the template parameter pack Flags contains overaligned-flag<N>, ranges​::​data(r) points to storage aligned by N.
Effects: For all i in the range of [0, basic_simd<T, Abi>​::​size()), if mask[i] && i < ranges​::​​size(r) is true, evaluates ranges​::​data(r)[i] = v[i].

29.10.7.7 basic_simd and basic_simd_mask creation [simd.creation]

template<class T, class Abi> constexpr auto simd_split(const basic_simd<typename T::value_type, Abi>& x) noexcept; template<class T, class Abi> constexpr auto simd_split(const basic_simd_mask<mask-element-size<T>, Abi>& x) noexcept;
Constraints:
  • For the first overload T is an enabled specialization of basic_simd.
    If basic_simd<typename T​::​​value_type, Abi>​::​size() % T​::​size() is not 0 then resize_simd_t<basic_simd<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_simd_mask.
    If basic_simd_mask<mask-element-size<T>, Abi>​::​size() % T​::​size() is not 0 then resize_simd_t<​basic_simd_mask<mask-element-size<T>, 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 basic_simd or basic_simd_mask element of the 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_simd_t<x.size() % T​::​size(), T>.
    The basic_simd or basic_simd_mask element of the tuple element of type T is initialized to the value of the element in x with index i + j * T​::​size().
    The basic_simd or basic_simd_mask element of the tuple element is initialized to the value of the element in x with index i + N * T​::​size().
template<class T, class... Abis> constexpr simd<T, (basic_simd<T, Abis>::size() + ...)> simd_cat(const basic_simd<T, Abis>&... xs) noexcept; template<size_t Bytes, class... Abis> constexpr basic_simd_mask<Bytes, deduce-abi-t<integer-from<Bytes>, (basic_simd_mask<Bytes, Abis>::size() + ...)>> simd_cat(const basic_simd_mask<Bytes, Abis>&... xs) noexcept;
Constraints:
  • For the first overload simd<T, (basic_simd<T, Abis>​::​size() + ...)> is enabled.
  • For the second overload basic_simd_mask<Bytes, deduce-abi-t<integer-from<Bytes>, (basic_simd_mask<Bytes, Abis>​::​size() + ...)>> is enabled.
Returns: A data-parallel object initialized with the concatenated values in the xs pack of data-parallel objects: The basic_simd/basic_simd_mask element of the 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.7.8 Algorithms [simd.alg]

template<class T, class Abi> constexpr basic_simd<T, Abi> min(const basic_simd<T, Abi>& a, const basic_simd<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_simd<T, Abi>​::​size()).
template<class T, class Abi> constexpr basic_simd<T, Abi> max(const basic_simd<T, Abi>& a, const basic_simd<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_simd<T, Abi>​::​size()).
template<class T, class Abi> constexpr pair<basic_simd<T, Abi>, basic_simd<T, Abi>> minmax(const basic_simd<T, Abi>& a, const basic_simd<T, Abi>& b) noexcept;
Effects: Equivalent to: return pair{min(a, b), max(a, b)};
template<class T, class Abi> constexpr basic_simd<T, Abi> clamp( const basic_simd<T, Abi>& v, const basic_simd<T, Abi>& lo, const basic_simd<T, Abi>& hi);
Constraints: T models totally_ordered.
Preconditions: No element in lo shall be greater than the corresponding element in hi.
Returns: The result of element-wise application of clamp(v[i], lo[i], hi[i]) for all i in the range of [0, basic_simd<T, Abi>​::​size()).
template<class T, class U> constexpr auto simd_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 simd_select(const basic_simd_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.7.9 Mathematical functions [simd.math]

template<math-floating-point V> constexpr rebind_simd_t<int, deduced-simd-t<V>> ilogb(const V& x); template<math-floating-point V> constexpr deduced-simd-t<V> ldexp(const V& x, const rebind_simd_t<int, deduced-simd-t<V>>& exp); template<math-floating-point V> constexpr deduced-simd-t<V> scalbn(const V& x, const rebind_simd_t<int, deduced-simd-t<V>>& n); template<math-floating-point V> constexpr deduced-simd-t<V> scalbln(const V& x, const rebind_simd_t<long int, deduced-simd-t<V>>& n); template<signed_integral T, class Abi> constexpr basic_simd<T, Abi> abs(const basic_simd<T, Abi>& j); template<math-floating-point V> constexpr deduced-simd-t<V> abs(const V& j); template<math-floating-point V> constexpr deduced-simd-t<V> fabs(const V& x); template<math-floating-point V> constexpr deduced-simd-t<V> ceil(const V& x); template<math-floating-point V> constexpr deduced-simd-t<V> floor(const V& x); template<math-floating-point V> deduced-simd-t<V> nearbyint(const V& x); template<math-floating-point V> deduced-simd-t<V> rint(const V& x); template<math-floating-point V> rebind_simd_t<long int, deduced-simd-t<V>> lrint(const V& x); template<math-floating-point V> rebind_simd_t<long long int, deduced-simd-t<V>> llrint(const V& x); template<math-floating-point V> constexpr deduced-simd-t<V> round(const V& x); template<math-floating-point V> constexpr rebind_simd_t<long int, deduced-simd-t<V>> lround(const V& x); template<math-floating-point V> constexpr rebind_simd_t<long long int, deduced-simd-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 V> constexpr deduced-simd-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 V> constexpr rebind_simd_t<int, deduced-simd-t<V>> fpclassify(const V& x); template<math-floating-point V> constexpr typename deduced-simd-t<V>::mask_type isfinite(const V& x); template<math-floating-point V> constexpr typename deduced-simd-t<V>::mask_type isinf(const V& x); template<math-floating-point V> constexpr typename deduced-simd-t<V>::mask_type isnan(const V& x); template<math-floating-point V> constexpr typename deduced-simd-t<V>::mask_type isnormal(const V& x); template<math-floating-point V> constexpr typename deduced-simd-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-simd denote: template<class... Args> Ret math-func-simd(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-simd with the arguments of the above functions.
If in an invocation of a scalar overload of math-func for index i in math-func-simd 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 V> constexpr deduced-simd-t<V> acos(const V& x); template<math-floating-point V> constexpr deduced-simd-t<V> asin(const V& x); template<math-floating-point V> constexpr deduced-simd-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 V> constexpr deduced-simd-t<V> cos(const V& x); template<math-floating-point V> constexpr deduced-simd-t<V> sin(const V& x); template<math-floating-point V> constexpr deduced-simd-t<V> tan(const V& x); template<math-floating-point V> constexpr deduced-simd-t<V> acosh(const V& x); template<math-floating-point V> constexpr deduced-simd-t<V> asinh(const V& x); template<math-floating-point V> constexpr deduced-simd-t<V> atanh(const V& x); template<math-floating-point V> constexpr deduced-simd-t<V> cosh(const V& x); template<math-floating-point V> constexpr deduced-simd-t<V> sinh(const V& x); template<math-floating-point V> constexpr deduced-simd-t<V> tanh(const V& x); template<math-floating-point V> constexpr deduced-simd-t<V> exp(const V& x); template<math-floating-point V> constexpr deduced-simd-t<V> exp2(const V& x); template<math-floating-point V> constexpr deduced-simd-t<V> expm1(const V& x); template<math-floating-point V> constexpr deduced-simd-t<V> log(const V& x); template<math-floating-point V> constexpr deduced-simd-t<V> log10(const V& x); template<math-floating-point V> constexpr deduced-simd-t<V> log1p(const V& x); template<math-floating-point V> constexpr deduced-simd-t<V> log2(const V& x); template<math-floating-point V> constexpr deduced-simd-t<V> logb(const V& x); template<math-floating-point V> constexpr deduced-simd-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 V> constexpr deduced-simd-t<V> sqrt(const V& x); template<math-floating-point V> constexpr deduced-simd-t<V> erf(const V& x); template<math-floating-point V> constexpr deduced-simd-t<V> erfc(const V& x); template<math-floating-point V> constexpr deduced-simd-t<V> lgamma(const V& x); template<math-floating-point V> constexpr deduced-simd-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 V> deduced-simd-t<V> assoc_laguerre(const rebind_simd_t<unsigned, deduced-simd-t<V>>& n, const rebind_simd_t<unsigned, deduced-simd-t<V>>& m, const V& x); template<math-floating-point V> deduced-simd-t<V> assoc_legendre(const rebind_simd_t<unsigned, deduced-simd-t<V>>& l, const rebind_simd_t<unsigned, deduced-simd-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 V> deduced-simd-t<V> comp_ellint_1(const V& k); template<math-floating-point V> deduced-simd-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 V> deduced-simd-t<V> expint(const V& x); template<math-floating-point V> deduced-simd-t<V> hermite(const rebind_simd_t<unsigned, deduced-simd-t<V>>& n, const V& x); template<math-floating-point V> deduced-simd-t<V> laguerre(const rebind_simd_t<unsigned, deduced-simd-t<V>>& n, const V& x); template<math-floating-point V> deduced-simd-t<V> legendre(const rebind_simd_t<unsigned, deduced-simd-t<V>>& l, const V& x); template<math-floating-point V> deduced-simd-t<V> riemann_zeta(const V& x); template<math-floating-point V> deduced-simd-t<V> sph_bessel(const rebind_simd_t<unsigned, deduced-simd-t<V>>& n, const V& x); template<math-floating-point V> deduced-simd-t<V> sph_legendre(const rebind_simd_t<unsigned, deduced-simd-t<V>>& l, const rebind_simd_t<unsigned, deduced-simd-t<V>>& m, const V& theta); template<math-floating-point V> deduced-simd-t<V> sph_neumann(const rebind_simd_t<unsigned, deduced-simd-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-simd denote: template<class... Args> Ret math-func-simd(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-simd with the arguments of the above functions.
If in an invocation of a scalar overload of math-func for index i in math-func-simd 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 V> constexpr deduced-simd-t<V> frexp(const V& value, rebind_simd_t<int, deduced-simd-t<V>>* exp);
Let Ret be deduced-simd-t<V>.
Let frexp-simd denote: template<class V> pair<Ret, rebind_simd_t<int, Ret>> frexp-simd(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_simd_t<int, Ret>(r1)}; }
Let ret be a value of type pair<Ret, rebind_simd_t<int, Ret>> that is the same value as the result of calling frexp-simd(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_simd_t<int, math-common-simd-t<V0, V1>>* quo);
Let Ret be math-common-simd-t<V0, V1>.
Let remquo-simd denote: template<class V0, class V1> pair<Ret, rebind_simd_t<int, Ret>> remquo-simd(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_simd_t<int, Ret>(r1)}; }
Let ret be a value of type pair<Ret, rebind_simd_t<int, Ret>> that is the same value as the result of calling remquo-simd(x, y).
If in an invocation of a scalar overload of remquo for index i in remquo-simd 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_simd<T, Abi> modf(const type_identity_t<basic_simd<T, Abi>>& value, basic_simd<T, Abi>* iptr);
Let V be basic_simd<T, Abi>.
Let modf-simd denote: pair<V, V> modf-simd(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-simd(value).
Effects: Sets *iptr to ret.second.
Returns: ret.first.