Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
201 changes: 201 additions & 0 deletions source/numerics.tex
Original file line number Diff line number Diff line change
Expand Up @@ -16125,6 +16125,11 @@

template<class V, class T> using @\exposidnc{make-compatible-simd-t} = \seebelownc@; // \expos

template<class V>
concept @\defexposconceptnc{simd-type}@ = // \expos
@\libconcept{same_as}@<V, basic_simd<typename V::value_type, typename V::abi_type>> &&
is_default_constructible_v<V>;

template<class V>
concept @\defexposconceptnc{simd-floating-point}@ = // \expos
@\libconcept{same_as}@<V, basic_simd<typename V::value_type, typename V::abi_type>> &&
Expand Down Expand Up @@ -16743,6 +16748,43 @@
template<@\exposconcept{math-floating-point}@ V>
@\exposid{deduced-simd-t}@<V>
sph_neumann(const rebind_simd_t<unsigned, @\exposid{deduced-simd-t}@<V>>& n, const V& x);

// \ref{simd.bit}, Bit manipulation
template<@\exposconcept{simd-type}@ V> constexpr V byteswap(const V& v) noexcept;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Out of curiosity: Why this "simd-type" formulation instead of taking a suitably-parameterized std::basic_simd parameter type?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I asked that question in LWG but I don't recall an answer. What difference does it make (other than style)?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

None, as far as I know; that's why I'm asking. It just feels a bit backwards to say "this function takes arguments of any type, except satisfaction checking of constraints will then check whether we have a specialization of X" instead of "this function takes a specialization of X".

(Maybe compiling is faster one way or the other.)

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-type}@ V>
constexpr typename V::mask_type has_single_bit(const V& v) noexcept;

template<@\exposconcept{simd-type}@ V0, @\exposconcept{simd-type}@ V1>
constexpr V0 rotl(const V0& v, const V1& s) noexcept;
template<@\exposconcept{simd-type}@ V>
constexpr V rotl(const V& v, int s) noexcept;

template<@\exposconcept{simd-type}@ V0, @\exposconcept{simd-type}@ V1>
constexpr V0 rotr(const V0& v, const V1& s) noexcept;
template<@\exposconcept{simd-type}@ V>
constexpr V rotr(const V& v, int s) noexcept;

template<@\exposconcept{simd-type}@ V>
constexpr rebind_simd_t<make_signed_t<typename V::value_type>, V>
bit_width(const V& v) noexcept;
template<@\exposconcept{simd-type}@ V>
constexpr rebind_simd_t<make_signed_t<typename V::value_type>, V>
countl_zero(const V& v) noexcept;
template<@\exposconcept{simd-type}@ V>
constexpr rebind_simd_t<make_signed_t<typename V::value_type>, V>
countl_one(const V& v) noexcept;
template<@\exposconcept{simd-type}@ V>
constexpr rebind_simd_t<make_signed_t<typename V::value_type>, V>
countr_zero(const V& v) noexcept;
template<@\exposconcept{simd-type}@ V>
constexpr rebind_simd_t<make_signed_t<typename V::value_type>, V>
countr_one(const V& v) noexcept;
template<@\exposconcept{simd-type}@ V>
constexpr rebind_simd_t<make_signed_t<typename V::value_type>, V>
popcount(const V& v) noexcept;
}
\end{codeblock}

Expand Down Expand Up @@ -18471,6 +18513,165 @@
\tcode{ret.first}.
\end{itemdescr}

\rSec3[simd.bit]{\tcode{basic_simd} bit library}

\begin{itemdecl}
template<@\exposconcept{simd-type}@ V> constexpr V byteswap(const V& v) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
The type \tcode{V::value_type} models \tcode{integral}.

\pnum
\returns
A \tcode{basic_simd} object where the $i^\text{th}$ element is initialized to
the result of \tcode{std::byteswap(v[$i$])} for all $i$ in the range
\range{0}{V::size()}.
\end{itemdescr}

\begin{itemdecl}
template<@\exposconcept{simd-type}@ V> constexpr V bit_ceil(const V& v) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
The type \tcode{V::value_type} is an unsigned integer type\iref{basic.fundamental}.

\pnum
\expects
For every $i$ in the range \range{0}{V::size()}, the smallest power of 2
greater than or equal to \tcode{v[$i$]} is representable as a value of type
\tcode{V::value_type}.

\pnum
\returns
A \tcode{basic_simd} object where the $i^\text{th}$ element is initialized to
the result of \tcode{std::bit_ceil(v[$i$])} for all $i$ in the range
\range{0}{V::size()}.

\pnum
\remarks
A function call expression that violates the precondition in the \expects
element is not a core constant expression\iref{expr.const}.
\end{itemdescr}

\begin{itemdecl}
template<@\exposconcept{simd-type}@ V> constexpr V bit_floor(const V& v) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
The type \tcode{V::value_type} is an unsigned integer type\iref{basic.fundamental}.

\pnum
\returns
A \tcode{basic_simd} object where the $i^\text{th}$ element is initialized to
the result of \tcode{std::bit_floor(v[$i$])} for all $i$ in the range
\range{0}{V::size()}.
\end{itemdescr}

\begin{itemdecl}
template<@\exposconcept{simd-type}@ V>
constexpr typename V::mask_type has_single_bit(const V& v) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
The type \tcode{V::value_type} is an unsigned integer type\iref{basic.fundamental}.

\pnum
\returns
A \tcode{basic_simd_mask} object where the $i^\text{th}$ element is initialized
to the result of \tcode{std::has_single_bit(v[$i$])} for all $i$ in the range
\range{0}{V::size()}.
\end{itemdescr}

\begin{itemdecl}
template<@\exposconcept{simd-type}@ V0, @\exposconcept{simd-type}@ V1>
constexpr V0 rotl(const V0& v0, const V1& v1) noexcept;
template<@\exposconcept{simd-type}@ V0, @\exposconcept{simd-type}@ V1>
constexpr V0 rotr(const V0& v0, const V1& v1) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\begin{itemize}
\item
The type \tcode{V0::value_type} is an unsigned integer type\iref{basic.fundamental},
\item
the type \tcode{V1::value_type} models \tcode{integral},
\item
\tcode{V0::size() == V1::size()} is \tcode{true}, and
\item
\tcode{sizeof(typename V0::value_type) == sizeof(typename V1::value_type)} is \tcode{true}.
\end{itemize}

\pnum
\returns
A \tcode{basic_simd} object where the $i^\text{th}$ element is initialized to
the result of \tcode{\placeholder{bit-func}(v0[$i$],
static_cast<int>(v1[$i$]))} for all $i$ in the range \range{0}{V0::size()},
where \placeholder{bit-func} is the corresponding scalar function from \libheader{bit}.
\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;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
The type \tcode{V::value_type} is an unsigned integer type\iref{basic.fundamental}

\pnum
\returns
A \tcode{basic_simd} object where the $i^\text{th}$ element is initialized to
the result of \tcode{\placeholder{bit-func}(v[$i$], s)} for all $i$ in the
range \range{0}{V::size()}, where \placeholder{bit-func} is the corresponding
scalar function from \libheader{bit}.
\end{itemdescr}

\begin{itemdecl}
template<@\exposconcept{simd-type}@ V>
constexpr rebind_simd_t<make_signed_t<typename V::value_type>, V>
bit_width(const V& v) noexcept;
template<@\exposconcept{simd-type}@ V>
constexpr rebind_simd_t<make_signed_t<typename V::value_type>, V>
countl_zero(const V& v) noexcept;
template<@\exposconcept{simd-type}@ V>
constexpr rebind_simd_t<make_signed_t<typename V::value_type>, V>
countl_one(const V& v) noexcept;
template<@\exposconcept{simd-type}@ V>
constexpr rebind_simd_t<make_signed_t<typename V::value_type>, V>
countr_zero(const V& v) noexcept;
template<@\exposconcept{simd-type}@ V>
constexpr rebind_simd_t<make_signed_t<typename V::value_type>, V>
countr_one(const V& v) noexcept;
template<@\exposconcept{simd-type}@ V>
constexpr rebind_simd_t<make_signed_t<typename V::value_type>, V>
popcount(const V& v) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
The type \tcode{V::value_type} is an unsigned integer type\iref{basic.fundamental}

\pnum
\returns
A \tcode{basic_simd} object where the $i^\text{th}$ element is initialized to
the result of \tcode{\placeholder{bit-func}(v[$i$])} for all $i$ in the range
\range{0}{V::size()}, where \placeholder{bit-func} is the corresponding scalar
function from \libheader{bit}.
\end{itemdescr}

\rSec2[simd.mask.class]{Class template \tcode{basic_simd_mask}}

\rSec3[simd.mask.overview]{Class template \tcode{basic_simd_mask} overview}
Expand Down
2 changes: 1 addition & 1 deletion source/support.tex
Original file line number Diff line number Diff line change
Expand Up @@ -799,7 +799,7 @@
#define @\defnlibxname{cpp_lib_shared_ptr_weak_type}@ 201606L // also in \libheader{memory}
#define @\defnlibxname{cpp_lib_shared_timed_mutex}@ 201402L // also in \libheader{shared_mutex}
#define @\defnlibxname{cpp_lib_shift}@ 202202L // also in \libheader{algorithm}
#define @\defnlibxname{cpp_lib_simd}@ 202411L // also in \libheader{simd}
#define @\defnlibxname{cpp_lib_simd}@ 202502L // 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}
Expand Down