diff --git a/source/numerics.tex b/source/numerics.tex index bd3ff637f8..5a11a8b523 100644 --- a/source/numerics.tex +++ b/source/numerics.tex @@ -16232,20 +16232,29 @@ template using @\exposidnc{make-compatible-simd-t} = \seebelownc@; // \expos template - concept @\defexposconceptnc{simd-type}@ = // \expos + concept @\defexposconceptnc{simd-vec-type}@ = // \expos @\libconcept{same_as}@> && is_default_constructible_v; +template + concept @\defexposconceptnc{simd-mask-type}@ = // \expos + @\libconcept{same_as}@, typename V::abi_type>> && + is_default_constructible_v; + template concept @\defexposconceptnc{simd-floating-point}@ = // \expos - @\exposconcept{simd-type}@ && @\libconcept{floating_point}@; + @\exposconcept{simd-vec-type}@ && @\libconcept{floating_point}@; + +template + concept @\defexposconceptnc{simd-integral}@ = // \expos + @\exposconcept{simd-vec-type}@ && @\libconcept{integral}@; template using @\exposidnc{simd-complex-value-type}@ = typename V::value_type::value_type; // \expos template concept @\defexposconceptnc{simd-complex}@ = // \expos - @\exposconcept{simd-type}@ && @\libconcept{same_as}@>>; + @\exposconcept{simd-vec-type}@ && @\libconcept{same_as}@>>; template concept @\defexposconceptnc{math-floating-point}@ = // \expos @@ -16613,6 +16622,89 @@ constexpr void partial_store(const basic_simd& v, I first, S last, const typename basic_simd::mask_type& mask, flags f = {}); + // \ref{simd.permute.static}, Permute by static index generator + static constexpr @\exposid{simd-size-type}@ zero_element = @\impdefx{value of \tcode{simd::zero_element}}@; + static constexpr @\exposid{simd-size-type}@ uninit_element = @\impdefx{value of \tcode{simd::uninit_element}}@; + + template<@\exposid{simd-size-type}@ N = @\seebelow@, @\exposconcept{simd-vec-type}@ V, class IdxMap> + constexpr resize_t permute(const V& v, IdxMap&& idxmap); + template<@\exposid{simd-size-type}@ N = @\seebelow@, @\exposconcept{simd-mask-type}@ M, class IdxMap> + constexpr resize_t permute(const M& v, IdxMap&& idxmap); + + // \ref{simd.permute.dynamic}, Permute by dynamic index + template<@\exposconcept{simd-vec-type}@ V, @\exposconcept{simd-integral}@ I> + constexpr resize_t permute(const V& v, const I& indices); + template<@\exposconcept{simd-mask-type}@ V, @\exposconcept{simd-integral}@ I> + constexpr resize_t permute(const V& v, const I& indices); + + // \ref{simd.permute.mask}, Permute by active mask bits + template<@\exposconcept{simd-vec-type}@ V> + constexpr V compress(const V& v, const typename V::mask_type& selector); + template<@\exposconcept{simd-mask-type}@ V> + constexpr V compress(const V& v, const type_identity_t& selector); + template<@\exposconcept{simd-vec-type}@ V> + constexpr V compress(const V& v, const typename V::mask_type& selector, + const typename V::value_type& fill_value); + template<@\exposconcept{simd-mask-type}@ V> + constexpr V compress(const V& v, const type_identity_t& selector, + const typename V::value_type& fill_value); + + template<@\exposconcept{simd-vec-type}@ V> + constexpr V expand(const V& v, const typename V::mask_type& selector, + const V& original = {}); + template<@\exposconcept{simd-mask-type}@ V> + constexpr V expand(const V& v, const type_identity_t& selector, + const V& original = {}); + + // \ref{simd.permute.memory}, Permute to and from memory + template + requires ranges::@\libconcept{sized_range}@ + constexpr V + unchecked_gather_from(R&& in, + const I& indices, flags f = {}); + template + requires ranges::@\libconcept{sized_range}@ + constexpr V + unchecked_gather_from(R&& in, const typename I::mask_type& mask, + const I& indices, flags f = {}); + + template + requires ranges::@\libconcept{sized_range}@ + constexpr V + partial_gather_from(R&& in, + const I& indices, flags f = {}); + template + requires ranges::@\libconcept{sized_range}@ + constexpr V + partial_gather_from(R&& in, const typename I::mask_type& mask, + const I& indices, flags f = {}); + + template<@\exposconcept{simd-vec-type}@ V, ranges::@\libconcept{contiguous_range}@ R, @\exposconcept{simd-integral}@ I, class... Flags> + requires ranges::@\libconcept{sized_range}@ + constexpr void + unchecked_scatter_to(const V& v, R&& out, + const I& indices, flags f = {}); + template<@\exposconcept{simd-vec-type}@ V, ranges::@\libconcept{contiguous_range}@ R, @\exposconcept{simd-integral}@ I, class... Flags> + requires ranges::@\libconcept{sized_range}@ + constexpr void + unchecked_scatter_to(const V& v, R&& out, const typename I::mask_type& mask, + const I& indices, flags f = {}); + + template<@\exposconcept{simd-vec-type}@ V, ranges::@\libconcept{contiguous_range}@ R, @\exposconcept{simd-integral}@ I, class... Flags> + requires ranges::@\libconcept{sized_range}@ + constexpr void + partial_scatter_to(const V& v, R&& out, + const I& indices, flags f = {}); + template<@\exposconcept{simd-vec-type}@ V, ranges::@\libconcept{contiguous_range}@ R, @\exposconcept{simd-integral}@ I, class... Flags> + requires ranges::@\libconcept{sized_range}@ + constexpr void + partial_scatter_to(const V& v, R&& out, const typename I::mask_type& mask, + const I& indices, flags f = {}); + // \ref{simd.creation}, \tcode{basic_simd} and \tcode{basic_simd_mask} creation template constexpr auto chunk(const basic_simd& x) noexcept; @@ -16864,36 +16956,36 @@ sph_neumann(const rebind_t>& n, const V& x); // \ref{simd.bit}, Bit manipulation - template<@\exposconcept{simd-type}@ V> constexpr V byteswap(const V& v) noexcept; - template<@\exposconcept{simd-type}@ V> constexpr V bit_ceil(const V& v) noexcept; - template<@\exposconcept{simd-type}@ V> constexpr V bit_floor(const V& v) noexcept; + template<@\exposconcept{simd-vec-type}@ V> constexpr V byteswap(const V& v) noexcept; + template<@\exposconcept{simd-vec-type}@ V> constexpr V bit_ceil(const V& v) noexcept; + template<@\exposconcept{simd-vec-type}@ V> constexpr V bit_floor(const V& v) noexcept; - template<@\exposconcept{simd-type}@ V> + template<@\exposconcept{simd-vec-type}@ V> constexpr typename V::mask_type has_single_bit(const V& v) noexcept; - template<@\exposconcept{simd-type}@ V0, @\exposconcept{simd-type}@ V1> + template<@\exposconcept{simd-vec-type}@ V0, @\exposconcept{simd-vec-type}@ V1> constexpr V0 rotl(const V0& v, const V1& s) noexcept; - template<@\exposconcept{simd-type}@ V> + template<@\exposconcept{simd-vec-type}@ V> constexpr V rotl(const V& v, int s) noexcept; - template<@\exposconcept{simd-type}@ V0, @\exposconcept{simd-type}@ V1> + template<@\exposconcept{simd-vec-type}@ V0, @\exposconcept{simd-vec-type}@ V1> constexpr V0 rotr(const V0& v, const V1& s) noexcept; - template<@\exposconcept{simd-type}@ V> + template<@\exposconcept{simd-vec-type}@ V> constexpr V rotr(const V& v, int s) noexcept; - template<@\exposconcept{simd-type}@ V> + template<@\exposconcept{simd-vec-type}@ V> constexpr rebind_t, V> bit_width(const V& v) noexcept; - template<@\exposconcept{simd-type}@ V> + template<@\exposconcept{simd-vec-type}@ V> constexpr rebind_t, V> countl_zero(const V& v) noexcept; - template<@\exposconcept{simd-type}@ V> + template<@\exposconcept{simd-vec-type}@ V> constexpr rebind_t, V> countl_one(const V& v) noexcept; - template<@\exposconcept{simd-type}@ V> + template<@\exposconcept{simd-vec-type}@ V> constexpr rebind_t, V> countr_zero(const V& v) noexcept; - template<@\exposconcept{simd-type}@ V> + template<@\exposconcept{simd-vec-type}@ V> constexpr rebind_t, V> countr_one(const V& v) noexcept; - template<@\exposconcept{simd-type}@ V> + template<@\exposconcept{simd-vec-type}@ V> constexpr rebind_t, V> popcount(const V& v) noexcept; // \ref{simd.complex.math}, simd complex math @@ -17489,10 +17581,12 @@ constexpr basic_simd() noexcept = default; // \ref{simd.ctor}, \tcode{basic_simd} constructors - template constexpr explicit(@\seebelow@) basic_simd(U&& value) noexcept; + template + constexpr explicit(@\seebelow@) basic_simd(U&& value) noexcept; template constexpr explicit(@\seebelow@) basic_simd(const basic_simd&) noexcept; - template constexpr explicit basic_simd(G&& gen) noexcept; + template + constexpr explicit basic_simd(G&& gen) noexcept; template constexpr basic_simd(R&& range, flags = {}); template @@ -17502,6 +17596,8 @@ // \ref{simd.subscr}, \tcode{basic_simd} subscript operators constexpr value_type operator[](@\exposid{simd-size-type}@) const; + template<@\exposconcept{simd-integral}@ I> + constexpr resize_t operator[](const I& indices) const; // \ref{simd.unary}, \tcode{basic_simd} unary operators constexpr basic_simd& operator++() noexcept; @@ -17822,6 +17918,17 @@ Nothing. \end{itemdescr} +\begin{itemdecl} +template<@\exposconcept{simd-integral}@ I> + constexpr resize_t operator[](const I& indices) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return permute(*this, indices);} +\end{itemdescr} + \rSec3[simd.unary]{\tcode{basic_simd} unary operators} \pnum @@ -18599,6 +18706,365 @@ \tcode{ranges::data(r)[$i$] = v[$i$]}. \end{itemdescr} +\rSec3[simd.permute.static]{\tcode{simd} static permute} + +\begin{itemdecl} +template<@\exposid{simd-size-type}@ N = @\seebelow@, @\exposconcept{simd-vec-type}@ V, class IdxMap> + constexpr resize_t permute(const V& v, IdxMap&& idxmap); + +template<@\exposid{simd-size-type}@ N = @\seebelow@, @\exposconcept{simd-mask-type}@ V, class IdxMap> + constexpr resize_t permute(const V& v, IdxMap&& idxmap); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let: +\begin{itemize} +\item +\tcode{\exposid{gen-fn}(i)} be \tcode{idxmap(i, V::size())} +if that expression is well-formed, and \tcode{idxmap(i)} otherwise. +\item +\exposid{perm-fn} be the following exposition-only function template: +\begin{codeblock} +template<@\exposid{simd-size-type}@ I> +typename V::value_type @\exposid{perm-fn}@() { + constexpr auto src_index = @\exposid{gen-fn}@(I); + if constexpr (src_index == zero_element) { + return typename V::value_type(); + } else if constexpr (src_index == uninit_element) { + return @\exposid{unspecified-value}@; + } else { + return v[src_index]; + } +} +\end{codeblock} +\end{itemize} + +\pnum +\constraints +\tcode{integral> || +integral>} is \tcode{true}. + +\pnum +\mandates +\tcode{\exposid{gen-fn}($i$)} is a constant expression whose value is +\tcode{zero_element}, \tcode{uninit_element}, or in the range +\range{0}{V::size()}, for all $i$ in the range \range{0}{N}. + +\pnum +\returns +A \tcode{basic_simd} or \tcode{basic_simd_mask} object where the +$i^\text{th}$ element is initialized to the result of +\tcode{\exposid{perm-fn}<$i$>()} for all $i$ in the range \range{0}{N}. + +\pnum +\remarks +The default argument for template parameter \tcode{N} is \tcode{V::size()}. +\end{itemdescr} + +\rSec3[simd.permute.dynamic]{\tcode{simd} dynamic permute} + +\begin{itemdecl} +template<@\exposconcept{simd-vec-type}@ V, @\exposconcept{simd-integral}@ I> + constexpr resize_t permute(const V& v, const I& indices); + +template<@\exposconcept{simd-mask-type}@ V, @\exposconcept{simd-integral}@ I> + constexpr resize_t permute(const V& v, const I& indices); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +All values in \tcode{indices} are in the range \range{0}{V::size()}. + +\pnum +\returns +A \tcode{basic_simd} or \tcode{basic_simd_mask} object where the $i^\text{th}$ +element is initialized to the result of \tcode{v[indices[$i$]]} for all $i$ in +the range \range{0}{I::size()}. +\end{itemdescr} + +\rSec3[simd.permute.mask]{\tcode{simd} mask permute} + +\begin{itemdecl} +template<@\exposconcept{simd-vec-type}@ V> + constexpr V compress(const V& v, const typename V::mask_type& selector); + +template<@\exposconcept{simd-mask-type}@ V> + constexpr V compress(const V& v, const type_identity_t& selector); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let: +\begin{itemize} +\item +\tcode{\exposidnc{bit-index}($i$)} be a function which returns the index +of the $i^\text{th}$ element of \tcode{selector} that is \tcode{true}. +\item +\tcode{\exposidnc{select-value}($i$)} be a function which returns +\tcode{v[\exposidnc{bit-index}($i$)]} for $i$ in the range +\range{0}{reduce_count(selector)} and a valid but unspecified value +otherwise. +\begin{note} +Different calls to \exposidnc{select-value} can return different unspecified values. +\end{note} +\end{itemize} + +\pnum +\returns +A \tcode{basic_simd} or \tcode{basic_simd_mask} object where the $i^\text{th}$ +element is initialized to the result of \tcode{\exposidnc{select-value}($i$)} +for all $i$ in the range \range{0}{V::size()}. +\end{itemdescr} + +\begin{itemdecl} +template<@\exposconcept{simd-vec-type}@ V> + constexpr V compress(const V& v, const typename V::mask_type& selector, + const typename V::value_type& fill_value); + +template<@\exposconcept{simd-mask-type}@ V> + constexpr V compress(const V& v, const type_identity_t& selector, + const typename V::value_type& fill_value); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let: +\begin{itemize} +\item +\tcode{\exposidnc{bit-index}($i$)} be a function which returns the index +of the $i^\text{th}$ element of \tcode{selector} that is \tcode{true}. +\item +\tcode{\exposidnc{select-value}($i$)} be a function which returns +\tcode{v[\exposidnc{bit-index}($i$)]} for $i$ in the range +\range{0}{reduce_count(selector)} and \tcode{fill_value} otherwise. +\end{itemize} + +\pnum +\returns +A \tcode{basic_simd} or \tcode{basic_simd_mask} object where the $i^\text{th}$ +element is initialized to the result of \tcode{\exposidnc{select-value}($i$)} +for all $i$ in the range \range{0}{V::size()}. +\end{itemdescr} + +\begin{itemdecl} +template<@\exposconcept{simd-vec-type}@ V> + constexpr V expand(const V& v, const typename V::mask_type& selector, const V& original = {}); + +template<@\exposconcept{simd-mask-type}@ V> + constexpr V expand(const V& v, const type_identity_t& selector, const V& original = {}); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let: +\begin{itemize} +\item +\exposid{set-indices} be a list of the index positions of \tcode{true} +elements in \tcode{selector}. +\item +\tcode{\exposidnc{bit-lookup}($b$)} be a function which returns the index +where $b$ appears in \tcode{\exposid{set-indices}}. +\item +\tcode{\exposidnc{select-value}($i$)} be a function which returns +\tcode{v[\exposidnc{bit-lookup}($i$)]} if \tcode{selector[$i$]} is +\tcode{true}, otherwise returns \tcode{original[$i$]}. +\end{itemize} + +\pnum +\returns +A \tcode{basic_simd} or \tcode{basic_simd_mask} object where the $i^\text{th}$ +element is initialized to the result of \tcode{\exposidnc{select-value}($i$)} +for all $i$ in the range \range{0}{V::size()}. +\end{itemdescr} + +\rSec3[simd.permute.memory]{\tcode{simd} memory permute} + +\begin{itemdecl} +template + requires ranges::@\libconcept{sized_range}@ + constexpr V unchecked_gather_from(R&& in, const I& indices, flags f = {}); + +template + requires ranges::@\libconcept{sized_range}@ + constexpr V unchecked_gather_from(R&& in, const typename I::mask_type& mask, + const I& indices, flags f = {}); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{mask} be \tcode{typename I::mask_type(true)} for the overload with +no \tcode{mask} parameter. + +\pnum +\expects +All values in \tcode{select(mask, indices, typename I::value_type())} are in +the range \range{0}{ranges::size(in)}. + +\pnum +\effects +Equivalent to: \tcode{return partial_gather_from(in, mask, indices, f);} + +\pnum +\remarks +The default argument for template parameter \tcode{V} is +\tcode{simd, I::size()>}. +\end{itemdescr} + +\begin{itemdecl} +template + requires ranges::@\libconcept{sized_range}@ + constexpr V partial_gather_from(R&& in, const I& indices, flags f = {}); + +template + requires ranges::@\libconcept{sized_range}@ + constexpr V partial_gather_from(R&& in, const typename I::mask_type& mask, + const I& indices, flags f = {}); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let: +\begin{itemize} + \item + \tcode{mask} be \tcode{typename I::mask_type(true)} for the overload with no + \tcode{mask} parameter; + \item + \tcode{T} be \tcode{typename V::value_type}. +\end{itemize} + +\pnum +\mandates +\begin{itemize} +\item +\tcode{ranges::range_value_t} is a vectorizable type, +\item +\tcode{same_as, V>} is \tcode{true}, +\item +\tcode{V} is an enabled specialization of \tcode{basic_simd}, +\item +\tcode{V::size() == I::size()} is \tcode{true}, and +\item +if the template parameter pack \tcode{Flags} does not contain +\exposid{convert-flag}, then the conversion from +\tcode{ranges::range_value_t} to \tcode{T} is value-preserving. +\end{itemize} + +\pnum +\expects +\begin{itemize} +\item +If the template parameter pack \tcode{Flags} contains +\exposid{aligned-flag}, \tcode{ranges::data(in)} points to storage aligned by +\tcode{alignment_v>}. +\item +If the template parameter pack \tcode{Flags} contains +\tcode{\exposid{overaligned-flag}}, \tcode{ranges::data(in)} points to +storage aligned by \tcode{N}. +\end{itemize} + +\pnum +\returns +A \tcode{basic_simd} object where the $i^\text{th}$ +element is initialized to the result of +\begin{codeblock} +mask[@$i$@] && indices[@$i$@] < ranges::size(in) ? static_cast(ranges::data(in)[indices[@$i$@]]) : T() +\end{codeblock} +for all $i$ in the range \range{0}{I::size()}. + +\pnum +\remarks +The default argument for template parameter \tcode{V} is +\tcode{simd, I::size()>}. +\end{itemdescr} + +\begin{itemdecl} +template<@\exposconcept{simd-vec-type}@ V, ranges::@\libconcept{contiguous_range}@ R, @\exposconcept{simd-integral}@ I, class... Flags> + requires ranges::@\libconcept{sized_range}@ + constexpr void unchecked_scatter_to(const V& v, R&& out, + const I& indices, flags f = {}); + +template<@\exposconcept{simd-vec-type}@ V, ranges::@\libconcept{contiguous_range}@ R, @\exposconcept{simd-integral}@ I, class... Flags> + requires ranges::@\libconcept{sized_range}@ + constexpr void unchecked_scatter_to(const V& v, R&& out, const typename I::mask_type& mask, + const I& indices, flags f = {}); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{mask} be \tcode{typename I::mask_type(true)} for the overload with +no \tcode{mask} parameter. + +\pnum +\expects +All values in \tcode{select(mask, indices, typename I::value_type())} are in +the range \range{0}{ranges::size(out)}. + +\pnum +\effects +Equivalent to: \tcode{partial_scatter_to(v, out, mask, indices, f);} +\end{itemdescr} + +\begin{itemdecl} +template<@\exposconcept{simd-vec-type}@ V, ranges::@\libconcept{contiguous_range}@ R, @\exposconcept{simd-integral}@ I, class... Flags> + requires ranges::@\libconcept{sized_range}@ + constexpr void partial_scatter_to(const V& v, R&& out, + const I& indices, flags f = {}); + +template<@\exposconcept{simd-vec-type}@ V, ranges::@\libconcept{contiguous_range}@ R, @\exposconcept{simd-integral}@ I, class... Flags> + requires ranges::@\libconcept{sized_range}@ + constexpr void partial_scatter_to(const V& v, R&& out, const typename I::mask_type& mask, + const I& indices, flags f = {}); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{mask} be \tcode{typename I::mask_type(true)} for the overload with +no \tcode{mask} parameter. + +\pnum +\constraints +\tcode{V::size() == I::size()} is \tcode{true}. + +\pnum +\mandates +\begin{itemize} +\item +\tcode{ranges::range_value_t} is a vectorizable type, and +\item +if the template parameter pack \tcode{Flags} does not contain \exposid{convert-flag}, +then the conversion from \tcode{typename V::value_type} +to \tcode{ranges::range_value_t} is value-preserving. +\end{itemize} + +\pnum +\expects +\begin{itemize} +\item +For all selected indices $i$ the values \tcode{indices[$i$]} are unique. +\item +If the template parameter pack \tcode{Flags} contains \exposid{aligned-flag}, +\tcode{ranges::data(out)} points to storage aligned by +\tcode{alignment_v>}. +\item +If the template parameter pack \tcode{Flags} contains +\tcode{\exposid{overaligned-flag}}, +\tcode{ranges::data(out)} points to storage aligned by \tcode{N}. +\end{itemize} + +\pnum +\effects +For all $i$ in the range \range{0}{I::size()}, if \tcode{mask[$i$] \&\& +(indices[$i$] < ranges::size(out))} is \tcode{true}, evaluates +\tcode{ranges::data(out)[indices[$i$]] = v[$i$]}. +\end{itemdescr} + \rSec3[simd.creation]{\tcode{basic_simd} and \tcode{basic_simd_mask} creation} \begin{itemdecl} @@ -19136,7 +19602,7 @@ \rSec3[simd.bit]{\tcode{basic_simd} bit library} \begin{itemdecl} -template<@\exposconcept{simd-type}@ V> constexpr V byteswap(const V& v) noexcept; +template<@\exposconcept{simd-vec-type}@ V> constexpr V byteswap(const V& v) noexcept; \end{itemdecl} \begin{itemdescr} @@ -19152,7 +19618,7 @@ \end{itemdescr} \begin{itemdecl} -template<@\exposconcept{simd-type}@ V> constexpr V bit_ceil(const V& v) noexcept; +template<@\exposconcept{simd-vec-type}@ V> constexpr V bit_ceil(const V& v) noexcept; \end{itemdecl} \begin{itemdescr} @@ -19179,7 +19645,7 @@ \end{itemdescr} \begin{itemdecl} -template<@\exposconcept{simd-type}@ V> constexpr V bit_floor(const V& v) noexcept; +template<@\exposconcept{simd-vec-type}@ V> constexpr V bit_floor(const V& v) noexcept; \end{itemdecl} \begin{itemdescr} @@ -19195,7 +19661,7 @@ \end{itemdescr} \begin{itemdecl} -template<@\exposconcept{simd-type}@ V> +template<@\exposconcept{simd-vec-type}@ V> constexpr typename V::mask_type has_single_bit(const V& v) noexcept; \end{itemdecl} @@ -19212,9 +19678,9 @@ \end{itemdescr} \begin{itemdecl} -template<@\exposconcept{simd-type}@ V0, @\exposconcept{simd-type}@ V1> +template<@\exposconcept{simd-vec-type}@ V0, @\exposconcept{simd-vec-type}@ V1> constexpr V0 rotl(const V0& v0, const V1& v1) noexcept; -template<@\exposconcept{simd-type}@ V0, @\exposconcept{simd-type}@ V1> +template<@\exposconcept{simd-vec-type}@ V0, @\exposconcept{simd-vec-type}@ V1> constexpr V0 rotr(const V0& v0, const V1& v1) noexcept; \end{itemdecl} @@ -19241,8 +19707,8 @@ \end{itemdescr} \begin{itemdecl} -template<@\exposconcept{simd-type}@ V> constexpr V rotl(const V& v, int s) noexcept; -template<@\exposconcept{simd-type}@ V> constexpr V rotr(const V& v, int s) noexcept; +template<@\exposconcept{simd-vec-type}@ V> constexpr V rotl(const V& v, int s) noexcept; +template<@\exposconcept{simd-vec-type}@ V> constexpr V rotr(const V& v, int s) noexcept; \end{itemdecl} \begin{itemdescr} @@ -19259,17 +19725,17 @@ \end{itemdescr} \begin{itemdecl} -template<@\exposconcept{simd-type}@ V> +template<@\exposconcept{simd-vec-type}@ V> constexpr rebind_t, V> bit_width(const V& v) noexcept; -template<@\exposconcept{simd-type}@ V> +template<@\exposconcept{simd-vec-type}@ V> constexpr rebind_t, V> countl_zero(const V& v) noexcept; -template<@\exposconcept{simd-type}@ V> +template<@\exposconcept{simd-vec-type}@ V> constexpr rebind_t, V> countl_one(const V& v) noexcept; -template<@\exposconcept{simd-type}@ V> +template<@\exposconcept{simd-vec-type}@ V> constexpr rebind_t, V> countr_zero(const V& v) noexcept; -template<@\exposconcept{simd-type}@ V> +template<@\exposconcept{simd-vec-type}@ V> constexpr rebind_t, V> countr_one(const V& v) noexcept; -template<@\exposconcept{simd-type}@ V> +template<@\exposconcept{simd-vec-type}@ V> constexpr rebind_t, V> popcount(const V& v) noexcept; \end{itemdecl} @@ -19387,12 +19853,15 @@ constexpr explicit basic_simd_mask(value_type) noexcept; template constexpr explicit basic_simd_mask(const basic_simd_mask&) noexcept; - template constexpr explicit basic_simd_mask(G&& gen) noexcept; + template + constexpr explicit basic_simd_mask(G&& gen) noexcept; constexpr basic_simd_mask(const bitset& b) noexcept; constexpr explicit basic_simd_mask(@\libconcept{unsigned_integral}@ auto val) noexcept; // \ref{simd.mask.subscr}, \tcode{basic_simd_mask} subscript operators constexpr value_type operator[](@\exposid{simd-size-type}@) const; + template<@\exposconcept{simd-integral}@ I> + constexpr resize_t operator[](const I& indices) const; // \ref{simd.mask.unary}, \tcode{basic_simd_mask} unary operators constexpr basic_simd_mask operator!() const noexcept; @@ -19585,6 +20054,17 @@ Nothing. \end{itemdescr} +\begin{itemdecl} +template<@\exposconcept{simd-integral}@ I> + constexpr resize_t operator[](const I& indices) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return permute(*this, indices);} +\end{itemdescr} + \rSec3[simd.mask.unary]{\tcode{basic_simd_mask} unary operators} \begin{itemdecl} diff --git a/source/support.tex b/source/support.tex index 720f063f45..d845795893 100644 --- a/source/support.tex +++ b/source/support.tex @@ -823,6 +823,7 @@ #define @\defnlibxname{cpp_lib_shift}@ 202202L // also in \libheader{algorithm} #define @\defnlibxname{cpp_lib_simd}@ 202506L // also in \libheader{simd} #define @\defnlibxname{cpp_lib_simd_complex}@ 202502L // also in \libheader{simd} +#define @\defnlibxname{cpp_lib_simd_permutations}@ 202506L // also in \libheader{simd} #define @\defnlibxname{cpp_lib_smart_ptr_for_overwrite}@ 202002L // also in \libheader{memory} #define @\defnlibxname{cpp_lib_smart_ptr_owner_equality}@ 202306L // also in \libheader{memory} #define @\defnlibxname{cpp_lib_source_location}@ 201907L // freestanding, also in \libheader{source_location}