%!TEX root = std.tex
\rSec0[numerics]{Numerics library}

\rSec1[numerics.general]{General}

\pnum
This Clause describes components that \Cpp{} programs may use to perform
seminumerical operations.

\pnum
The following subclauses describe components for
complex number types, random number generation,
numeric (%
\textit{n}-at-a-time)
arrays, generalized numeric algorithms, and
mathematical constants and functions for floating-point types,
as summarized in \tref{numerics.summary}.

\begin{libsumtab}{Numerics library summary}{numerics.summary}
\ref{numeric.requirements}  & Requirements               & \\ \rowsep
\ref{cfenv}                 & Floating-point environment & \tcode{<cfenv>}     \\ \rowsep
\ref{complex.numbers}       & Complex numbers            & \tcode{<complex>}   \\ \rowsep
\ref{rand}                  & Random number generation   & \tcode{<random>}    \\ \rowsep
\ref{numarray}              & Numeric arrays             & \tcode{<valarray>}  \\ \rowsep
\ref{c.math}                & Mathematical functions for
                              floating-point types       & \tcode{<cmath>}, \tcode{<cstdlib>}  \\ \rowsep
\ref{numbers}               & Numbers                    & \tcode{<numbers>}   \\ \rowsep
\ref{linalg}                & Linear algebra             & \tcode{<linalg>}    \\ \rowsep
\ref{simd}                  & Data-parallel types        & \tcode{<simd>}      \\
\end{libsumtab}

\rSec1[numeric.requirements]{Numeric type requirements}
\indextext{requirements!numeric type}

\pnum
The
\tcode{complex}
and
\tcode{valarray}
components are parameterized by the type of information they contain and manipulate.
A \Cpp{} program shall instantiate these components only with a numeric type.
A \defnadj{numeric}{type} is a cv-unqualified object type \tcode{T}
that meets the
\oldconcept{DefaultConstructible},
\oldconcept{CopyConstructible},
\oldconcept{CopyAssignable}, and
\oldconcept{Destructible}
requirements\iref{utility.arg.requirements}.
\begin{footnote}
In other words, value types.
These include arithmetic types,
pointers, the library class
\tcode{complex},
and specializations of
\tcode{valarray}
for value types.
\end{footnote}

\pnum
If any operation on \tcode{T}
throws an exception the effects are undefined.

\pnum
In addition, many member and related functions of
\tcode{valarray<T>}
can be successfully instantiated
and will exhibit well-defined behavior if and only if
\tcode{T} meets additional requirements specified for each such member
or related function.

\pnum
\begin{example}
It is valid to instantiate
\tcode{valarray<complex>},
but
\tcode{operator>()}
will not be successfully instantiated for
\tcode{valarray<complex>}
operands, since
\tcode{complex}
does not have any ordering operators.
\end{example}

\rSec1[cfenv]{The floating-point environment}
\rSec2[cfenv.syn]{Header \tcode{<cfenv>} synopsis}

\indexheader{cfenv}%
\indexlibraryglobal{fenv_t}%
\indexlibraryglobal{fexcept_t}%
\indexlibraryglobal{feclearexcept}%
\indexlibraryglobal{fegetexceptflag}%
\indexlibraryglobal{feraiseexcept}%
\indexlibraryglobal{fesetexceptflag}%
\indexlibraryglobal{fetestexcept}%
\indexlibraryglobal{fegetround}%
\indexlibraryglobal{fesetround}%
\indexlibraryglobal{fegetenv}%
\indexlibraryglobal{feholdexcept}%
\indexlibraryglobal{fesetenv}%
\indexlibraryglobal{feupdateenv}%
\begin{codeblock}
#define @\libmacro{FE_ALL_EXCEPT}@ @\seebelow@
#define @\libmacro{FE_DIVBYZERO}@ @\seebelow@    // optional
#define @\libmacro{FE_INEXACT}@ @\seebelow@      // optional
#define @\libmacro{FE_INVALID}@ @\seebelow@      // optional
#define @\libmacro{FE_OVERFLOW}@ @\seebelow@     // optional
#define @\libmacro{FE_UNDERFLOW}@ @\seebelow@    // optional

#define @\libmacro{FE_DOWNWARD}@ @\seebelow@     // optional
#define @\libmacro{FE_TONEAREST}@ @\seebelow@    // optional
#define @\libmacro{FE_TOWARDZERO}@ @\seebelow@   // optional
#define @\libmacro{FE_UPWARD}@ @\seebelow@       // optional

#define @\libmacro{FE_DFL_ENV}@ @\seebelow@

namespace std {
  // types
  using fenv_t    = @\textit{object type}@;
  using fexcept_t = @\textit{object type}@;

  // functions
  int feclearexcept(int except);
  int fegetexceptflag(fexcept_t* pflag, int except);
  int feraiseexcept(int except);
  int fesetexceptflag(const fexcept_t* pflag, int except);
  int fetestexcept(int except);

  int fegetround();
  int fesetround(int mode);

  int fegetenv(fenv_t* penv);
  int feholdexcept(fenv_t* penv);
  int fesetenv(const fenv_t* penv);
  int feupdateenv(const fenv_t* penv);
}
\end{codeblock}

\pnum
The contents and meaning of the header \libheader{cfenv}
are a subset of the C standard library header \libheader{fenv.h} and
only the declarations shown in the synopsis above are present.
\begin{note}
This document does not require an implementation to support the
\tcode{FENV_ACCESS} pragma;
it is \impldef{whether pragma \tcode{FENV_ACCESS} is supported}\iref{cpp.pragma}
whether the pragma is supported. As a consequence,
it is \impldef{whether \tcode{<cfenv>} functions can be used to manage floating-point status}
whether these functions can be used to test floating-point status flags,
set floating-point control modes, or run under non-default mode settings.
If the pragma is used to enable control over the floating-point environment,
this document does not specify the effect on
floating-point evaluation in constant expressions.
\end{note}

\xrefc{7.6}

\rSec2[cfenv.thread]{Threads}

\pnum
The floating-point environment has thread storage
duration\iref{basic.stc.thread}. The initial state for a thread's floating-point
environment is the state of the floating-point environment of the thread that constructs
the corresponding \tcode{thread} object\iref{thread.thread.class}
or \tcode{jthread} object\iref{thread.jthread.class}
at the time it
constructed the object.
\begin{note}
That is, the child thread gets the floating-point
state of the parent thread at the time of the child's creation.
\end{note}

\pnum
A separate floating-point environment is maintained for each thread. Each function
accesses the environment corresponding to its calling thread.

\rSec1[complex.numbers]{Complex numbers}

\rSec2[complex.numbers.general]{General}

\pnum
The header \libheader{complex} defines a class template,
and numerous functions for representing and manipulating complex numbers.

\pnum
The effect of instantiating the primary template of \tcode{complex} for any type
that is not a cv-unqualified floating-point type\iref{basic.fundamental}
is unspecified.
Specializations of \tcode{complex} for cv-unqualified floating-point types
are trivially copyable literal types\iref{term.literal.type}.

\pnum
If the result of a function is not mathematically defined or not in
the range of representable values for its type, the behavior is
undefined.

\pnum
If \tcode{z} is an lvalue of type \cv{} \tcode{complex<T>} then:
\begin{itemize}
\item the expression \tcode{reinterpret_cast<\cv{} T(\&)[2]>(z)} is well-formed,
\item \tcode{reinterpret_cast<\cv{} T(\&)[2]>(z)[0]} designates the real part of \tcode{z}, and
\item \tcode{reinterpret_cast<\cv{} T(\&)[2]>(z)[1]} designates the imaginary part of \tcode{z}.
\end{itemize}

Moreover, if \tcode{a} is an expression of type \cv{}~\tcode{complex<T>*} and the expression \tcode{a[i]} is well-defined for an integer expression \tcode{i}, then:
\begin{itemize}
\item \tcode{reinterpret_cast<\cv{} T*>(a)[2 * i]} designates the real part of \tcode{a[i]}, and
\item \tcode{reinterpret_cast<\cv{} T*>(a)[2 * i + 1]} designates the imaginary part of \tcode{a[i]}.
\end{itemize}

\rSec2[complex.syn]{Header \tcode{<complex>} synopsis}

\indexheader{complex}%
\begin{codeblock}
namespace std {
  // \ref{complex}, class template \tcode{complex}
  template<class T> class complex;

  // \ref{complex.ops}, operators
  template<class T> constexpr complex<T> operator+(const complex<T>&, const complex<T>&);
  template<class T> constexpr complex<T> operator+(const complex<T>&, const T&);
  template<class T> constexpr complex<T> operator+(const T&, const complex<T>&);

  template<class T> constexpr complex<T> operator-(const complex<T>&, const complex<T>&);
  template<class T> constexpr complex<T> operator-(const complex<T>&, const T&);
  template<class T> constexpr complex<T> operator-(const T&, const complex<T>&);

  template<class T> constexpr complex<T> operator*(const complex<T>&, const complex<T>&);
  template<class T> constexpr complex<T> operator*(const complex<T>&, const T&);
  template<class T> constexpr complex<T> operator*(const T&, const complex<T>&);

  template<class T> constexpr complex<T> operator/(const complex<T>&, const complex<T>&);
  template<class T> constexpr complex<T> operator/(const complex<T>&, const T&);
  template<class T> constexpr complex<T> operator/(const T&, const complex<T>&);

  template<class T> constexpr complex<T> operator+(const complex<T>&);
  template<class T> constexpr complex<T> operator-(const complex<T>&);

  template<class T> constexpr bool operator==(const complex<T>&, const complex<T>&);
  template<class T> constexpr bool operator==(const complex<T>&, const T&);

  template<class T, class charT, class traits>
    basic_istream<charT, traits>& operator>>(basic_istream<charT, traits>&, complex<T>&);

  template<class T, class charT, class traits>
    basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>&, const complex<T>&);

  // \ref{complex.value.ops}, values
  template<class T> constexpr T real(const complex<T>&);
  template<class T> constexpr T imag(const complex<T>&);

  template<class T> constexpr T abs(const complex<T>&);
  template<class T> constexpr T arg(const complex<T>&);
  template<class T> constexpr T norm(const complex<T>&);

  template<class T> constexpr complex<T> conj(const complex<T>&);
  template<class T> constexpr complex<T> proj(const complex<T>&);
  template<class T> constexpr complex<T> polar(const T&, const T& = T());

  // \ref{complex.transcendentals}, transcendentals
  template<class T> constexpr complex<T> acos(const complex<T>&);
  template<class T> constexpr complex<T> asin(const complex<T>&);
  template<class T> constexpr complex<T> atan(const complex<T>&);

  template<class T> constexpr complex<T> acosh(const complex<T>&);
  template<class T> constexpr complex<T> asinh(const complex<T>&);
  template<class T> constexpr complex<T> atanh(const complex<T>&);

  template<class T> constexpr complex<T> cos  (const complex<T>&);
  template<class T> constexpr complex<T> cosh (const complex<T>&);
  template<class T> constexpr complex<T> exp  (const complex<T>&);
  template<class T> constexpr complex<T> log  (const complex<T>&);
  template<class T> constexpr complex<T> log10(const complex<T>&);

  template<class T> constexpr complex<T> pow  (const complex<T>&, const T&);
  template<class T> constexpr complex<T> pow  (const complex<T>&, const complex<T>&);
  template<class T> constexpr complex<T> pow  (const T&, const complex<T>&);

  template<class T> constexpr complex<T> sin  (const complex<T>&);
  template<class T> constexpr complex<T> sinh (const complex<T>&);
  template<class T> constexpr complex<T> sqrt (const complex<T>&);
  template<class T> constexpr complex<T> tan  (const complex<T>&);
  template<class T> constexpr complex<T> tanh (const complex<T>&);

  // \ref{complex.tuple}, tuple interface
  template<class T> struct tuple_size;
  template<size_t I, class T> struct tuple_element;
  template<class T> struct tuple_size<complex<T>>;
  template<size_t I, class T> struct tuple_element<I, complex<T>>;
  template<size_t I, class T>
    constexpr T& get(complex<T>&) noexcept;
  template<size_t I, class T>
    constexpr T&& get(complex<T>&&) noexcept;
  template<size_t I, class T>
    constexpr const T& get(const complex<T>&) noexcept;
  template<size_t I, class T>
    constexpr const T&& get(const complex<T>&&) noexcept;

  // \ref{complex.literals}, complex literals
  inline namespace literals {
    inline namespace complex_literals {
      constexpr complex<long double> operator""il(long double);
      constexpr complex<long double> operator""il(unsigned long long);
      constexpr complex<double> operator""i(long double);
      constexpr complex<double> operator""i(unsigned long long);
      constexpr complex<float> operator""if(long double);
      constexpr complex<float> operator""if(unsigned long long);
    }
  }
}
\end{codeblock}

\rSec2[complex]{Class template \tcode{complex}}

\indexlibraryglobal{complex}%
\indexlibrarymember{value_type}{complex}%
\begin{codeblock}
namespace std {
  template<class T> class complex {
  public:
    using value_type = T;

    constexpr complex(const T& re = T(), const T& im = T());
    constexpr complex(const complex&) = default;
    template<class X> constexpr explicit(@\seebelow@) complex(const complex<X>&);

    constexpr T real() const;
    constexpr void real(T);
    constexpr T imag() const;
    constexpr void imag(T);

    constexpr complex& operator= (const T&);
    constexpr complex& operator+=(const T&);
    constexpr complex& operator-=(const T&);
    constexpr complex& operator*=(const T&);
    constexpr complex& operator/=(const T&);

    constexpr complex& operator=(const complex&);
    template<class X> constexpr complex& operator= (const complex<X>&);
    template<class X> constexpr complex& operator+=(const complex<X>&);
    template<class X> constexpr complex& operator-=(const complex<X>&);
    template<class X> constexpr complex& operator*=(const complex<X>&);
    template<class X> constexpr complex& operator/=(const complex<X>&);
  };
}
\end{codeblock}

\pnum
The class
\tcode{complex}
describes an object that can
store the Cartesian components,
\tcode{real()}
and
\tcode{imag()},
of a complex
number.

\rSec2[complex.members]{Member functions}

\indexlibraryctor{complex}%
\begin{itemdecl}
constexpr complex(const T& re = T(), const T& im = T());
\end{itemdecl}

\begin{itemdescr}
\pnum
\ensures
\tcode{real() == re \&\& imag() == im} is \tcode{true}.
\end{itemdescr}

\indexlibraryctor{complex}%
\begin{itemdecl}
template<class X> constexpr explicit(@\seebelow@) complex(const complex<X>& other);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes the real part with \tcode{other.real()} and
the imaginary part with \tcode{other.imag()}.

\pnum
\remarks
The expression inside \tcode{explicit} evaluates to \tcode{false}
if and only if the floating-point conversion rank of \tcode{T}
is greater than or equal to the floating-point conversion rank of \tcode{X}.
\end{itemdescr}

\indexlibrarymember{real}{complex}%
\begin{itemdecl}
constexpr T real() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
The value of the real component.
\end{itemdescr}

\indexlibrarymember{real}{complex}%
\begin{itemdecl}
constexpr void real(T val);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Assigns \tcode{val} to the real component.
\end{itemdescr}

\indexlibrarymember{imag}{complex}%
\begin{itemdecl}
constexpr T imag() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
The value of the imaginary component.
\end{itemdescr}

\indexlibrarymember{imag}{complex}%
\begin{itemdecl}
constexpr void imag(T val);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Assigns \tcode{val} to the imaginary component.
\end{itemdescr}

\rSec2[complex.member.ops]{Member operators}

\indexlibrarymember{operator+=}{complex}%
\begin{itemdecl}
constexpr complex& operator+=(const T& rhs);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Adds the scalar value \tcode{rhs} to the real part of the complex value
\tcode{*this}
and stores the result in the real part of
\tcode{*this},
leaving the imaginary part unchanged.

\pnum
\returns
\tcode{*this}.
\end{itemdescr}

\indexlibrarymember{operator-=}{complex}%
\begin{itemdecl}
constexpr complex& operator-=(const T& rhs);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Subtracts the scalar value \tcode{rhs} from the real part of the complex value
\tcode{*this}
and stores the result in the real part of
\tcode{*this},
leaving the imaginary part unchanged.

\pnum
\returns
\tcode{*this}.
\end{itemdescr}

\indexlibrarymember{operator*=}{complex}%
\begin{itemdecl}
constexpr complex& operator*=(const T& rhs);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Multiplies the scalar value \tcode{rhs} by the complex value
\tcode{*this}
and stores the result in
\tcode{*this}.

\pnum
\returns
\tcode{*this}.
\end{itemdescr}

\indexlibrarymember{operator/=}{complex}%
\begin{itemdecl}
constexpr complex& operator/=(const T& rhs);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Divides the scalar value \tcode{rhs} into the complex value
\tcode{*this}
and stores the result in
\tcode{*this}.

\pnum
\returns
\tcode{*this}.
\end{itemdescr}

\indexlibrarymember{operator=}{complex}%
\begin{itemdecl}
template<class X> constexpr complex& operator=(const complex<X>& rhs);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Assigns the value \tcode{rhs.real()} to the real part and
the value \tcode{rhs.imag()} to the imaginary part
of the complex value \tcode{*this}.

\pnum
\returns
\tcode{*this}.
\end{itemdescr}

\indexlibrarymember{operator+=}{complex}%
\begin{itemdecl}
template<class X> constexpr complex& operator+=(const complex<X>& rhs);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Adds the complex value \tcode{rhs} to the complex value
\tcode{*this}
and stores the sum in
\tcode{*this}.

\pnum
\returns
\tcode{*this}.
\end{itemdescr}

\indexlibrarymember{operator-=}{complex}%
\begin{itemdecl}
template<class X> constexpr complex& operator-=(const complex<X>& rhs);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Subtracts the complex value \tcode{rhs} from the complex value
\tcode{*this}
and stores the difference in
\tcode{*this}.

\pnum
\returns
\tcode{*this}.
\end{itemdescr}

\indexlibrarymember{operator*=}{complex}%
\begin{itemdecl}
template<class X> constexpr complex& operator*=(const complex<X>& rhs);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Multiplies the complex value \tcode{rhs} by the complex value
\tcode{*this}
and stores the product in
\tcode{*this}.

\pnum
\returns
\tcode{*this}.
\end{itemdescr}

\indexlibrarymember{operator/=}{complex}%
\begin{itemdecl}
template<class X> constexpr complex& operator/=(const complex<X>& rhs);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Divides the complex value \tcode{rhs} into the complex value
\tcode{*this}
and stores the quotient in
\tcode{*this}.

\pnum
\returns
\tcode{*this}.
\end{itemdescr}

\rSec2[complex.ops]{Non-member operations}

\indexlibrarymember{operator+}{complex}%
\begin{itemdecl}
template<class T> constexpr complex<T> operator+(const complex<T>& lhs);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{complex<T>(lhs)}.

\end{itemdescr}

\begin{itemdecl}
template<class T> constexpr complex<T> operator+(const complex<T>& lhs, const complex<T>& rhs);
template<class T> constexpr complex<T> operator+(const complex<T>& lhs, const T& rhs);
template<class T> constexpr complex<T> operator+(const T& lhs, const complex<T>& rhs);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{complex<T>(lhs) += rhs}.
\end{itemdescr}

\indexlibrarymember{operator-}{complex}%
\begin{itemdecl}
template<class T> constexpr complex<T> operator-(const complex<T>& lhs);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{complex<T>(-lhs.real(),-lhs.imag())}.
\end{itemdescr}

\indexlibrarymember{operator-}{complex}%
\begin{itemdecl}
template<class T> constexpr complex<T> operator-(const complex<T>& lhs, const complex<T>& rhs);
template<class T> constexpr complex<T> operator-(const complex<T>& lhs, const T& rhs);
template<class T> constexpr complex<T> operator-(const T& lhs, const complex<T>& rhs);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{complex<T>(lhs) -= rhs}.
\end{itemdescr}

\indexlibrarymember{operator*}{complex}%
\begin{itemdecl}
template<class T> constexpr complex<T> operator*(const complex<T>& lhs, const complex<T>& rhs);
template<class T> constexpr complex<T> operator*(const complex<T>& lhs, const T& rhs);
template<class T> constexpr complex<T> operator*(const T& lhs, const complex<T>& rhs);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{complex<T>(lhs) *= rhs}.
\end{itemdescr}

\indexlibrarymember{operator/}{complex}%
\begin{itemdecl}
template<class T> constexpr complex<T> operator/(const complex<T>& lhs, const complex<T>& rhs);
template<class T> constexpr complex<T> operator/(const complex<T>& lhs, const T& rhs);
template<class T> constexpr complex<T> operator/(const T& lhs, const complex<T>& rhs);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{complex<T>(lhs) /= rhs}.
\end{itemdescr}

\indexlibrarymember{operator==}{complex}%
\begin{itemdecl}
template<class T> constexpr bool operator==(const complex<T>& lhs, const complex<T>& rhs);
template<class T> constexpr bool operator==(const complex<T>& lhs, const T& rhs);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{lhs.real() == rhs.real() \&\& lhs.imag() == rhs.imag()}.

\pnum
\remarks
The imaginary part is assumed to be
\tcode{T()},
or 0.0, for the
\tcode{T}
arguments.
\end{itemdescr}

\indexlibrarymember{operator>>}{complex}%
\begin{itemdecl}
template<class T, class charT, class traits>
  basic_istream<charT, traits>& operator>>(basic_istream<charT, traits>& is, complex<T>& x);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
The input values are convertible to
\tcode{T}.

\pnum
\effects
Extracts a complex number \tcode{x} of the form:
\tcode{u},
\tcode{(u)},
or
\tcode{(u,v)},
where
\tcode{u}
is the real part and
\tcode{v}
is the imaginary part\iref{istream.formatted}.

\pnum
If bad input is encountered, calls
\tcode{is.setstate(ios_base::failbit)}
(which may throw
\tcode{ios_base::\brk{}failure}\iref{iostate.flags}).

\pnum
\returns
\tcode{is}.

\pnum
\remarks
This extraction is performed as a series of simpler
extractions.
Therefore, the skipping of whitespace is specified to be
the same for each of the simpler extractions.
\end{itemdescr}

\indexlibrarymember{operator<<}{complex}%
\begin{itemdecl}
template<class T, class charT, class traits>
  basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& o, const complex<T>& x);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Inserts the complex number \tcode{x}
onto the stream \tcode{o} as if it were implemented as follows:

\begin{codeblock}
basic_ostringstream<charT, traits> s;
s.flags(o.flags());
s.imbue(o.getloc());
s.precision(o.precision());
s << '(' << x.real() << ',' << x.imag() << ')';
return o << s.str();
\end{codeblock}

\pnum
\begin{note}
In a locale in which comma is used as a decimal point character, the
use of comma as a field separator can be ambiguous. Inserting
\tcode{showpoint} into the output stream forces all outputs to
show an explicit decimal point character; as a result, all inserted sequences of
complex numbers can be extracted unambiguously.
\end{note}
\end{itemdescr}

\rSec2[complex.value.ops]{Value operations}

\indexlibrarymember{real}{complex}%
\begin{itemdecl}
template<class T> constexpr T real(const complex<T>& x);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{x.real()}.
\end{itemdescr}

\indexlibrarymember{imag}{complex}%
\begin{itemdecl}
template<class T> constexpr T imag(const complex<T>& x);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{x.imag()}.
\end{itemdescr}

\indexlibrarymember{abs}{complex}%
\begin{itemdecl}
template<class T> constexpr T abs(const complex<T>& x);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
The magnitude of \tcode{x}.
\end{itemdescr}

\indexlibrarymember{arg}{complex}%
\begin{itemdecl}
template<class T> constexpr T arg(const complex<T>& x);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
The phase angle of \tcode{x}, or \tcode{atan2(imag(x), real(x))}.
\end{itemdescr}

\indexlibrarymember{norm}{complex}%
\begin{itemdecl}
template<class T> constexpr T norm(const complex<T>& x);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
The squared magnitude of \tcode{x}.
\end{itemdescr}

\indexlibrarymember{conj}{complex}%
\begin{itemdecl}
template<class T> constexpr complex<T> conj(const complex<T>& x);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
The complex conjugate of \tcode{x}.
\end{itemdescr}

\indexlibrarymember{proj}{complex}%
\begin{itemdecl}
template<class T> constexpr complex<T> proj(const complex<T>& x);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
The projection of \tcode{x} onto the Riemann sphere.

\pnum
\remarks
Behaves the same as the C function \tcode{cproj}.
\xrefc{7.3.9.5}
\end{itemdescr}

\indexlibrarymember{polar}{complex}%
\begin{itemdecl}
template<class T> constexpr complex<T> polar(const T& rho, const T& theta = T());
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{rho} is non-negative and non-NaN\@. \tcode{theta} is finite.

\pnum
\returns
The
\tcode{complex}
value corresponding
to a complex number whose magnitude is \tcode{rho} and whose phase angle
is \tcode{theta}.
\end{itemdescr}

\rSec2[complex.transcendentals]{Transcendentals}

\indexlibrarymember{acos}{complex}%
\indexlibrarymember{cacos}{complex}%
\begin{itemdecl}
template<class T> constexpr complex<T> acos(const complex<T>& x);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
The complex arc cosine of \tcode{x}.

\pnum
\remarks
Behaves the same as the C function \tcode{cacos}.
\xrefc{7.3.5.1}
\end{itemdescr}

\indexlibrarymember{asin}{complex}%
\indexlibrarymember{casin}{complex}%
\begin{itemdecl}
template<class T> constexpr complex<T> asin(const complex<T>& x);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
The complex arc sine of \tcode{x}.

\pnum
\remarks
Behaves the same as the C function \tcode{casin}.
\xrefc{7.3.5.2}
\end{itemdescr}

\indexlibrarymember{atan}{complex}%
\indexlibrarymember{catan}{complex}%
\begin{itemdecl}
template<class T> constexpr complex<T> atan(const complex<T>& x);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
The complex arc tangent of \tcode{x}.

\pnum
\remarks
Behaves the same as the C function \tcode{catan}.
\xrefc{7.3.5.3}
\end{itemdescr}

\indexlibrarymember{acosh}{complex}%
\indexlibrarymember{cacosh}{complex}%
\begin{itemdecl}
template<class T> constexpr complex<T> acosh(const complex<T>& x);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
The complex arc hyperbolic cosine of \tcode{x}.

\pnum
\remarks
Behaves the same as the C function \tcode{cacosh}.
\xrefc{7.3.6.1}
\end{itemdescr}

\indexlibrarymember{asinh}{complex}%
\indexlibrarymember{casinh}{complex}%
\begin{itemdecl}
template<class T> constexpr complex<T> asinh(const complex<T>& x);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
The complex arc hyperbolic sine of \tcode{x}.

\pnum
\remarks
Behaves the same as the C function \tcode{casinh}.
\xrefc{7.3.6.2}
\end{itemdescr}

\indexlibrarymember{atanh}{complex}%
\indexlibrarymember{catanh}{complex}%
\begin{itemdecl}
template<class T> constexpr complex<T> atanh(const complex<T>& x);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
The complex arc hyperbolic tangent of \tcode{x}.

\pnum
\remarks
Behaves the same as the C function \tcode{catanh}.
\xrefc{7.3.6.3}
\end{itemdescr}

\indexlibrarymember{cos}{complex}%
\begin{itemdecl}
template<class T> constexpr complex<T> cos(const complex<T>& x);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
The complex cosine of \tcode{x}.
\end{itemdescr}

\indexlibrarymember{cosh}{complex}%
\begin{itemdecl}
template<class T> constexpr complex<T> cosh(const complex<T>& x);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
The complex hyperbolic cosine of \tcode{x}.
\end{itemdescr}

\indexlibrarymember{exp}{complex}%
\begin{itemdecl}
template<class T> constexpr complex<T> exp(const complex<T>& x);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
The complex base-$e$ exponential of \tcode{x}.
\end{itemdescr}

\indexlibrarymember{log}{complex}%
\begin{itemdecl}
template<class T> constexpr complex<T> log(const complex<T>& x);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
The complex natural (base-$e$) logarithm of \tcode{x}. For all \tcode{x},
\tcode{imag(log(x))} lies in the interval \crange{$-\pi$}{$\pi$}.
\begin{note}
The semantics of this function are intended to be the same in \Cpp{}
as they are for \tcode{clog} in C.
\end{note}

\pnum
\remarks
The branch cuts are along the negative real axis.
\end{itemdescr}

\indexlibrarymember{log10}{complex}%
\begin{itemdecl}
template<class T> constexpr complex<T> log10(const complex<T>& x);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
The complex common (base-$10$) logarithm of \tcode{x}, defined as
\tcode{log(x) / log(10)}.

\pnum
\remarks
The branch cuts are along the negative real axis.
\end{itemdescr}

\indexlibrarymember{pow}{complex}%
\begin{itemdecl}
template<class T> constexpr complex<T> pow(const complex<T>& x, const complex<T>& y);
template<class T> constexpr complex<T> pow(const complex<T>& x, const T& y);
template<class T> constexpr complex<T> pow(const T& x, const complex<T>& y);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
The complex power of base \tcode{x} raised to the $\tcode{y}^\text{th}$ power,
defined as
\tcode{exp(y * log(x))}.
The value returned for
\tcode{pow(0, 0)}
is \impldef{value of \tcode{pow(0,0)}}.

\pnum
\remarks
The branch cuts are along the negative real axis.
\end{itemdescr}

\indexlibrarymember{sin}{complex}%
\begin{itemdecl}
template<class T> constexpr complex<T> sin(const complex<T>& x);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
The complex sine of \tcode{x}.
\end{itemdescr}

\indexlibrarymember{sinh}{complex}%
\begin{itemdecl}
template<class T> constexpr complex<T> sinh(const complex<T>& x);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
The complex hyperbolic sine of \tcode{x}.
\end{itemdescr}

\indexlibrarymember{sqrt}{complex}%
\begin{itemdecl}
template<class T> constexpr complex<T> sqrt(const complex<T>& x);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
The complex square root of \tcode{x}, in the range of the right
half-plane.
\begin{note}
The semantics of this function are intended to be the same in \Cpp{}
as they are for \tcode{csqrt} in C.
\end{note}

\pnum
\remarks
The branch cuts are along the negative real axis.
\end{itemdescr}

\indexlibrarymember{tan}{complex}%
\begin{itemdecl}
template<class T> constexpr complex<T> tan(const complex<T>& x);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
The complex tangent of \tcode{x}.
\end{itemdescr}

\indexlibrarymember{tanh}{complex}%
\begin{itemdecl}
template<class T> constexpr complex<T> tanh(const complex<T>& x);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
The complex hyperbolic tangent of \tcode{x}.
\end{itemdescr}

\rSec2[complex.tuple]{Tuple interface}

\indexlibraryglobal{tuple_size}%
\indexlibraryglobal{tuple_element}%
\begin{itemdecl}
template<class T>
struct tuple_size<complex<T>> : integral_constant<size_t, 2> {};

template<size_t I, class T>
struct tuple_element<I, complex<T>> {
  using type = T;
};
\end{itemdecl}

\begin{itemdescr}
\pnum
\mandates
\tcode{I < 2} is \tcode{true}.
\end{itemdescr}

\indexlibrarymember{get}{complex}%
\begin{itemdecl}
template<size_t I, class T>
  constexpr T& get(complex<T>& z) noexcept;
template<size_t I, class T>
  constexpr T&& get(complex<T>&& z) noexcept;
template<size_t I, class T>
  constexpr const T& get(const complex<T>& z) noexcept;
template<size_t I, class T>
  constexpr const T&& get(const complex<T>&& z) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\mandates
\tcode{I < 2} is \tcode{true}.

\pnum
\returns
A reference to the real part of \tcode{z} if \tcode{I == 0} is \tcode{true},
otherwise a reference to the imaginary part of \tcode{z}.
\end{itemdescr}

\rSec2[cmplx.over]{Additional overloads}

\pnum
\indexlibraryglobal{arg}%
\indexlibraryglobal{conj}%
\indexlibraryglobal{imag}%
\indexlibraryglobal{norm}%
\indexlibraryglobal{real}%
The following function templates have additional constexpr overloads:
\begin{codeblock}
arg                   norm
conj                  proj
imag                  real
\end{codeblock}

\pnum
\indextext{overloads!floating-point}%
The additional constexpr overloads are sufficient to ensure:
\begin{itemize}
\item
If the argument has a floating-point type \tcode{T},
then it is effectively cast to \tcode{complex<T>}.
\item
Otherwise, if the argument has integer type,
then it is effectively cast to \tcode{complex<double>}.
\end{itemize}

\pnum
\indexlibraryglobal{pow}%
Function template \tcode{pow} has additional constexpr overloads sufficient to ensure,
for a call with one argument of type \tcode{complex<T1>} and
the other argument of type \tcode{T2} or \tcode{complex<T2>},
both arguments are effectively cast to \tcode{complex<common_type_t<T1, T3>>},
where \tcode{T3} is
\tcode{double} if \tcode{T2} is an integer type and \tcode{T2} otherwise.
If \tcode{common_type_t<T1, T3>} is not well-formed,
then the program is ill-formed.

\rSec2[complex.literals]{Suffixes for complex number literals}

\indextext{literal!complex}%
\pnum
This subclause describes literal suffixes for constructing complex number literals.
The suffixes \tcode{i}, \tcode{il}, and \keyword{if} create complex numbers of
the types \tcode{complex<double>}, \tcode{complex<long double>}, and
\tcode{complex<float>} respectively, with their imaginary part denoted by the
given literal number and the real part being zero.

\indexlibrarymember{operator""""il}{complex}%
\begin{itemdecl}
constexpr complex<long double> operator""il(long double d);
constexpr complex<long double> operator""il(unsigned long long d);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{complex<long double>\{0.0L, static_cast<long double>(d)\}}.
\end{itemdescr}

\indexlibrarymember{operator""""i}{complex}%
\begin{itemdecl}
constexpr complex<double> operator""i(long double d);
constexpr complex<double> operator""i(unsigned long long d);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{complex<double>\{0.0, static_cast<double>(d)\}}.
\end{itemdescr}

\indexlibrarymember{operator""""if}{complex}%
\begin{itemdecl}
constexpr complex<float> operator""if(long double d);
constexpr complex<float> operator""if(unsigned long long d);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{complex<float>\{0.0f, static_cast<float>(d)\}}.
\end{itemdescr}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%                                                                %%%
%%%                                                                %%%
%%%      Numerical facilities:  Random number generation           %%%
%%%                    (without concepts)                          %%%
%%%                                                                %%%
%%%                                                                %%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\rSec1[rand]{Random number generation}

\rSec2[rand.general]{General}

\indextext{random number generation|(}%
\indextext{distribution|see{random number distribution}}%
\indextext{engine|see{random number engine}}%
\indextext{engine adaptor|see{random number engine adaptor}}%
\indextext{random number generator|see{uniform random bit generator}}

\pnum
Subclause \ref{rand} defines a facility
for generating (pseudo-)random numbers.

\pnum
In addition to a few utilities,
four categories of entities are described:
\term{uniform random bit generators},
\term{random number engines},
\term{random number engine adaptors},
and
\term{random number distributions}.
These categorizations are applicable
to types that meet the corresponding requirements,
to objects instantiated from such types,
and to templates producing such types when instantiated.
\begin{note}
 These entities are specified in such a way
 as to permit the binding
 of any uniform random bit generator object \tcode{e}
 as the argument
 to any random number distribution object \tcode{d},
 thus producing a zero-argument function object
 such as given by
 \tcode{bind(d,e)}.
\end{note}

\pnum
Each of the entities specified in \ref{rand}
has an associated arithmetic type\iref{basic.fundamental}
identified as \tcode{result_type}.
With \tcode{T} as the \tcode{result_type}
thus associated with such an entity,
that entity is characterized:
\begin{itemize}
 \item
   as \term{boolean} or equivalently as \term{boolean-valued},
   if \tcode{T} is \tcode{bool};
 \item
   otherwise
   as \term{integral} or equivalently as \term{integer-valued},
   if \tcode{numeric_limits<T>::is_integer} is \tcode{true};
 \item
   otherwise
   as \term{floating-point} or equivalently as \term{real-valued}.
\end{itemize}
\noindent
If integer-valued,
an entity may optionally be further characterized as
\term{signed} or \term{unsigned},
according to \tcode{numeric_limits<T>::is_signed}.

\pnum
Unless otherwise specified,
all descriptions of calculations
in \ref{rand}
use mathematical real numbers.

\pnum
Throughout \ref{rand},
the operators
\bitand, \bitor, and \xor{}
denote the respective conventional bitwise operations.
Further:
\begin{itemize}
 \item
   the operator \rightshift{} denotes a bitwise right shift
   with zero-valued bits appearing in the high bits of the result, and
 \item
   the operator \leftshift{w} denotes a bitwise left shift
   with zero-valued bits appearing in the low bits of the result,
   and whose result is always taken modulo $2^w$.
\end{itemize}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
%% Header synopsis subclause
%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


\rSec2[rand.synopsis]{Header \tcode{<random>} synopsis}

\indexheader{random}
\indextext{random number generation!synopsis|(}

\begin{codeblock}
#include <initializer_list>     // see \ref{initializer.list.syn}

namespace std {
  // \ref{rand.req.urng}, uniform random bit generator requirements
  template<class G>
    concept uniform_random_bit_generator = @\seebelow@;           // freestanding

  // \ref{rand.eng.lcong}, class template \tcode{linear_congruential_engine}
  template<class UIntType, UIntType a, UIntType c, UIntType m>
    class linear_congruential_engine;                           // partially freestanding

  // \ref{rand.eng.mers}, class template \tcode{mersenne_twister_engine}
  template<class UIntType, size_t w, size_t n, size_t m, size_t r,
           UIntType a, size_t u, UIntType d, size_t s,
           UIntType b, size_t t,
           UIntType c, size_t l, UIntType f>
    class mersenne_twister_engine;

  // \ref{rand.eng.sub}, class template \tcode{subtract_with_carry_engine}
  template<class UIntType, size_t w, size_t s, size_t r>
    class subtract_with_carry_engine;                           // partially freestanding

  // \ref{rand.adapt.disc}, class template \tcode{discard_block_engine}
  template<class Engine, size_t p, size_t r>
    class discard_block_engine;                                 // partially freestanding

  // \ref{rand.adapt.ibits}, class template \tcode{independent_bits_engine}
  template<class Engine, size_t w, class UIntType>
    class independent_bits_engine;                              // partially freestanding

  // \ref{rand.adapt.shuf}, class template \tcode{shuffle_order_engine}
  template<class Engine, size_t k>
    class shuffle_order_engine;

  // \ref{rand.eng.philox}, class template \tcode{philox_engine}
  template<class UIntType, size_t w, size_t n, size_t r, UIntType... consts>
    class philox_engine;                                        // partially freestanding

  // \ref{rand.predef}, engines and engine adaptors with predefined parameters
  using minstd_rand0  = @\seebelow@;      // freestanding
  using minstd_rand   = @\seebelow@;      // freestanding
  using mt19937       = @\seebelow@;      // freestanding
  using mt19937_64    = @\seebelow@;      // freestanding
  using ranlux24_base = @\seebelow@;      // freestanding
  using ranlux48_base = @\seebelow@;      // freestanding
  using ranlux24      = @\seebelow@;      // freestanding
  using ranlux48      = @\seebelow@;      // freestanding
  using knuth_b       = @\seebelow@;
  using philox4x32    = @\seebelow@;      // freestanding
  using philox4x64    = @\seebelow@;      // freestanding

  using default_random_engine = @\seebelow@;

  // \ref{rand.device}, class \tcode{random_device}
  class random_device;

  // \ref{rand.util.seedseq}, class \tcode{seed_seq}
  class seed_seq;

  // \ref{rand.util.canonical}, function template \tcode{generate_canonical}
  template<class RealType, size_t digits, class URBG>
    RealType generate_canonical(URBG& g);

  namespace ranges {
    // \ref{alg.rand.generate}, \tcode{generate_random}
    template<class R, class G>
      requires @\libconcept{output_range}@<R, invoke_result_t<G&>> &&
               @\libconcept{uniform_random_bit_generator}@<remove_cvref_t<G>>
      constexpr borrowed_iterator_t<R> generate_random(R&& r, G&& g);

    template<class G, @\libconcept{output_iterator}@<invoke_result_t<G&>> O, @\libconcept{sentinel_for}@<O> S>
      requires @\libconcept{uniform_random_bit_generator}@<remove_cvref_t<G>>
      constexpr O generate_random(O first, S last, G&& g);

    template<class R, class G, class D>
      requires @\libconcept{output_range}@<R, invoke_result_t<D&, G&>> && @\libconcept{invocable}@<D&, G&> &&
               @\libconcept{uniform_random_bit_generator}@<remove_cvref_t<G>> &&
               is_arithmetic_v<invoke_result_t<D&, G&>>
    constexpr borrowed_iterator_t<R> generate_random(R&& r, G&& g, D&& d);

    template<class G, class D, @\libconcept{output_iterator}@<invoke_result_t<D&, G&>> O, @\libconcept{sentinel_for}@<O> S>
      requires @\libconcept{invocable}@<D&, G&> && @\libconcept{uniform_random_bit_generator}@<remove_cvref_t<G>> &&
               is_arithmetic_v<invoke_result_t<D&, G&>>
    constexpr O generate_random(O first, S last, G&& g, D&& d);
  }

  // \ref{rand.dist.uni.int}, class template \tcode{uniform_int_distribution}
  template<class IntType = int>
    class uniform_int_distribution;                             // partially freestanding

  // \ref{rand.dist.uni.real}, class template \tcode{uniform_real_distribution}
  template<class RealType = double>
    class uniform_real_distribution;

  // \ref{rand.dist.bern.bernoulli}, class \tcode{bernoulli_distribution}
  class bernoulli_distribution;

  // \ref{rand.dist.bern.bin}, class template \tcode{binomial_distribution}
  template<class IntType = int>
    class binomial_distribution;

  // \ref{rand.dist.bern.geo}, class template \tcode{geometric_distribution}
  template<class IntType = int>
    class geometric_distribution;

  // \ref{rand.dist.bern.negbin}, class template \tcode{negative_binomial_distribution}
  template<class IntType = int>
    class negative_binomial_distribution;

  // \ref{rand.dist.pois.poisson}, class template \tcode{poisson_distribution}
  template<class IntType = int>
    class poisson_distribution;

  // \ref{rand.dist.pois.exp}, class template \tcode{exponential_distribution}
  template<class RealType = double>
    class exponential_distribution;

  // \ref{rand.dist.pois.gamma}, class template \tcode{gamma_distribution}
  template<class RealType = double>
    class gamma_distribution;

  // \ref{rand.dist.pois.weibull}, class template \tcode{weibull_distribution}
  template<class RealType = double>
    class weibull_distribution;

  // \ref{rand.dist.pois.extreme}, class template \tcode{extreme_value_distribution}
  template<class RealType = double>
    class extreme_value_distribution;

  // \ref{rand.dist.norm.normal}, class template \tcode{normal_distribution}
  template<class RealType = double>
    class normal_distribution;

  // \ref{rand.dist.norm.lognormal}, class template \tcode{lognormal_distribution}
  template<class RealType = double>
    class lognormal_distribution;

  // \ref{rand.dist.norm.chisq}, class template \tcode{chi_squared_distribution}
  template<class RealType = double>
    class chi_squared_distribution;

  // \ref{rand.dist.norm.cauchy}, class template \tcode{cauchy_distribution}
  template<class RealType = double>
    class cauchy_distribution;

  // \ref{rand.dist.norm.f}, class template \tcode{fisher_f_distribution}
  template<class RealType = double>
    class fisher_f_distribution;

  // \ref{rand.dist.norm.t}, class template \tcode{student_t_distribution}
  template<class RealType = double>
    class student_t_distribution;

  // \ref{rand.dist.samp.discrete}, class template \tcode{discrete_distribution}
  template<class IntType = int>
    class discrete_distribution;

  // \ref{rand.dist.samp.pconst}, class template \tcode{piecewise_constant_distribution}
  template<class RealType = double>
    class piecewise_constant_distribution;

  // \ref{rand.dist.samp.plinear}, class template \tcode{piecewise_linear_distribution}
  template<class RealType = double>
    class piecewise_linear_distribution;
}
\end{codeblock}%
\indextext{random number generation!synopsis|)}%


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
%% Requirements subclause
%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\rSec2[rand.req]{Requirements}%
\indextext{random number generation!requirements|(}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
%%  general requirements subclause
%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\rSec3[rand.req.genl]{General requirements}%

\pnum
Throughout \ref{rand},
the effect of instantiating a template:
\begin{itemize}
  \item
    that has a template type parameter
    named \tcode{Sseq}
    is undefined unless the corresponding template argument
    is cv-unqualified and
    meets the requirements
    of seed sequence\iref{rand.req.seedseq}.
  \item
    that has a template type parameter
    named \tcode{URBG}
    is undefined unless the corresponding template argument
    is cv-unqualified and
    meets the requirements
    of uniform random bit generator\iref{rand.req.urng}.
  \item
    that has a template type parameter
    named \tcode{Engine}
    is undefined unless the corresponding template argument
    is cv-unqualified and
    meets the requirements
    of random number engine\iref{rand.req.eng}.
  \item
    that has a template type parameter
    named \tcode{RealType}
    is undefined unless the corresponding template argument
    is cv-unqualified and
    is one of
    \tcode{float}, \tcode{double}, or \tcode{long double}.
  \item
    that has a template type parameter
    named \tcode{IntType}
    is undefined unless the corresponding template argument
    is cv-unqualified and
    is one of
      \tcode{short},
      \tcode{int},
      \tcode{long},
      \tcode{long long},
      \tcode{unsigned short},
      \tcode{unsigned int},
      \tcode{unsigned long},
      or
      \tcode{unsigned long long}.
  \item
    that has a template type parameter
    named \tcode{UIntType}
    is undefined unless the corresponding template argument
    is cv-unqualified and
    is one of
      \tcode{unsigned short},
      \tcode{unsigned int},
      \tcode{unsigned long},
      or
      \tcode{unsigned long long}.
\end{itemize}

\pnum
Throughout \ref{rand},
phrases of the form ``\tcode{x} is an iterator of a specific kind''
shall be interpreted as equivalent to the more formal requirement that
``\tcode{x} is a value
of a type meeting the requirements
of the specified iterator type''.

\pnum
Throughout \ref{rand},
any constructor that can be called with a single argument
and that meets a requirement specified in this subclause
shall be declared \keyword{explicit}.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Seed Sequence requirements:

\rSec3[rand.req.seedseq]{Seed sequence requirements}%
\indextext{seed sequence!requirements|(}%
\indextext{requirements!seed sequence|(}

\pnum
 A \defn{seed sequence}
 is an object
 that consumes a sequence
 of integer-valued data
 and produces a requested number
 of unsigned integer values $i$, $0 \le i < 2^{32}$,
 based on the consumed data.
\begin{note}
 Such an object provides a mechanism
 to avoid replication of streams of random variates.
 This can be useful, for example, in applications
 requiring large numbers of random number engines.
\end{note}

\pnum
A class \tcode{S}
meets the requirements
of a seed sequence
if the expressions shown
in \tref{rand.req.seedseq}
are valid and have the indicated semantics,
and if \tcode{S} also meets all other requirements
of \ref{rand.req.seedseq}.
In \tref{rand.req.seedseq} and throughout this subclause:
\begin{itemize}
  \item
    \tcode{T} is the type named by
    \tcode{S}'s associated \tcode{result_type};
  \item
    \tcode{q} is a value of type \tcode{S}
    and
    \tcode{r} is a value of type \tcode{S} or \tcode{const S};
  \item
    \tcode{ib} and \tcode{ie} are input iterators
    with an unsigned integer \tcode{value_type} of at least 32 bits;
  \item
    \tcode{rb} and \tcode{re} are mutable random access iterators
    with an unsigned integer \tcode{value_type} of at least 32 bits;
  \item
    \tcode{ob} is an output iterator;
  and
  \item
    \tcode{il} is a value of type \tcode{initializer_list<T>}.
\end{itemize}


\begin{libreqtab4d}
  {Seed sequence requirements}
  {rand.req.seedseq}
\\ \topline
\lhdr{Expression}
  & \chdr{Return type}
  & \chdr{Pre/post-condition}
  & \rhdr{Complexity}
  \\ \capsep
\endfirsthead
\continuedcaption\\
\hline
\lhdr{Expression}
  & \chdr{Return type}
  & \chdr{Pre/post-condition}
  & \rhdr{Complexity}
  \\ \capsep
\endhead
\tcode{S::result_type}
  & \tcode{T}
  & \tcode{T} is an unsigned integer type\iref{basic.fundamental}
    of at least 32 bits.
  &
  \\ \rowsep
\tcode{S()}%
  &
  & Creates a seed sequence
    with the same initial state as all other default-constructed seed sequences
    of type \tcode{S}.
  & constant
  \\ \rowsep
\tcode{S(ib,ie)}%
  &
  & Creates a seed sequence
    having internal state
    that depends on some or all of the bits
    of the supplied sequence $[\tcode{ib},\tcode{ie})$.
  & \bigoh{\tcode{ie} - \tcode{ib}}
  \\ \rowsep
\tcode{S(il)}%
  &
  & Same as \tcode{S(il.begin(), il.end())}.
  & same as \tcode{S(il.begin(), il.end())}
  \\ \rowsep
\tcode{q.generate(rb,re)}%
  & \keyword{void}
  & Does nothing if \tcode{rb == re}.
    Otherwise,
    fills the supplied sequence $[\tcode{rb},\tcode{re})$
    with 32-bit quantities
    that depend on the sequence supplied to the constructor
    and possibly also depend on the history
    of \tcode{generate}'s previous invocations.
  & \bigoh{\tcode{re} - \tcode{rb}}
  \\ \rowsep
\tcode{r.size()}%
  & \tcode{size_t}
  & The number of 32-bit units
    that would be copied
    by a call to \tcode{r.param}.
  & constant
  \\ \rowsep
\tcode{\tcode{r.param(ob)}}%
  & \keyword{void}
  & Copies to the given destination
    a sequence of 32-bit units
    that can be provided
    to the constructor of a second object of type \tcode{S},
    and that would reproduce in that second object
    a state indistinguishable
    from the state of the first object.
  & \bigoh{\tcode{r.size()}}
  \\
\end{libreqtab4d}%

\indextext{requirements!seed sequence|)}
\indextext{seed sequence!requirements|)}%


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Uniform Random Number Generator requirements:

\rSec3[rand.req.urng]{Uniform random bit generator requirements}%
\indextext{uniform random bit generator!requirements|(}%
\indextext{requirements!uniform random bit generator|(}

\pnum
A \term{uniform random bit generator}
\tcode{g} of type \tcode{G}
is a function object
returning unsigned integer values
such that each value
in the range of possible results
has (ideally) equal probability
of being returned.
\begin{note}
 The degree to which \tcode{g}'s results
 approximate the ideal
 is often determined statistically.
\end{note}

\begin{codeblock}
template<class G>
  concept @\deflibconcept{uniform_random_bit_generator}@ =
    @\libconcept{invocable}@<G&> && @\libconcept{unsigned_integral}@<invoke_result_t<G&>> &&
    requires {
      { G::min() } -> @\libconcept{same_as}@<invoke_result_t<G&>>;
      { G::max() } -> @\libconcept{same_as}@<invoke_result_t<G&>>;
      requires bool_constant<(G::min() < G::max())>::value;
    };
\end{codeblock}

\pnum
Let \tcode{g} be an object of type \tcode{G}. \tcode{G} models
\libconcept{uniform_random_bit_generator} only if
\begin{itemize}
\item \tcode{G::min() <= g()},
\item \tcode{g() <= G::max()}, and
\item \tcode{g()} has amortized constant complexity.
\end{itemize}

\indextext{requirements!uniform random bit generator|)}%
\indextext{uniform random bit generator!requirements|)}%
\pnum
A class \tcode{G} meets the \term{uniform random bit generator} requirements if
\tcode{G} models \libconcept{uniform_random_bit_generator},
\tcode{invoke_result_t<G\&>} is an unsigned integer type\iref{basic.fundamental},
and
\tcode{G} provides a nested \grammarterm{typedef-name} \tcode{result_type}
that denotes the same type as \tcode{invoke_result_t<G\&>}.


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Random Number Engine requirements:

\rSec3[rand.req.eng]{Random number engine requirements}%
\indextext{random number engine!requirements|(}%
\indextext{requirements!random number engine|(}

\pnum
A \term{random number engine}
(commonly shortened to \term{engine})
\tcode{e} of type \tcode{E}
is a uniform random bit generator
that additionally meets the requirements
(e.g., for seeding and for input/output)
specified in this subclause.

\pnum
At any given time,
\tcode{e} has a state \state{e}{i}
for some integer $i \geq 0$.
Upon construction,
\tcode{e}
has an initial state \state{e}{0}.
An engine's state may be established via
 a constructor,
 a \tcode{seed} function,
 assignment,
 or a suitable \tcode{operator>>}.

\pnum
\tcode{E}'s specification shall define:
\begin{itemize}
 \item
   the size of \tcode{E}'s state
   in multiples of the size of \tcode{result_type},
   given as an integral constant expression;
 \item
   the \term{transition algorithm}
   $\mathsf{TA}$
   by which \tcode{e}'s state \state{e}{i}
   is advanced to its \term{successor state}
   \state{e}{i+1};
 and
 \item
   the \term{generation algorithm}
   $\mathsf{GA}$
   by which an engine's state is mapped
   to a value of type \tcode{result_type}.
\end{itemize}

\pnum
A class \tcode{E}
that meets the requirements
of a uniform random bit generator\iref{rand.req.urng}
also meets the requirements
of a \term{random number engine}
if the expressions shown
in \tref{rand.req.eng}
are valid and have the indicated semantics,
and if \tcode{E} also meets all other requirements
of \ref{rand.req.eng}.
In \tref{rand.req.eng} and throughout this subclause:
\begin{itemize}
  \item
    \tcode{T} is the type named by
    \tcode{E}'s associated \tcode{result_type};
  \item
    \tcode{e} is a value of \tcode{E},
    \tcode{v} is an lvalue of \tcode{E},
    \tcode{x} and \tcode{y} are (possibly const) values of \tcode{E};
  \item
    \tcode{s} is a value of \tcode{T};
  \item
    \tcode{q} is an lvalue
    meeting the requirements of a seed sequence\iref{rand.req.seedseq};
  \item
    \tcode{z} is a value
    of type \tcode{unsigned long long};
  \item
    \tcode{os} is an lvalue of the type of some class template specialization
    \tcode{basic_ostream<charT,} \tcode{traits>};
  and
  \item
    \tcode{is} is an lvalue of the type of some class template specialization
    \tcode{basic_istream<charT,} \tcode{traits>};
\end{itemize}
where \tcode{charT} and \tcode{traits} are constrained
according to \ref{strings} and \ref{input.output}.

\begin{libreqtab4d}
  {Random number engine requirements}
  {rand.req.eng}
\\ \topline
\lhdr{Expression}
  & \chdr{Return type}
  & \chdr{Pre/post-condition}
  & \rhdr{Complexity}
  \\ \capsep
\endfirsthead
\continuedcaption\\
\topline
\lhdr{Expression}
  & \chdr{Return type}
  & \chdr{Pre/post-condition}
  & \rhdr{Complexity}
  \\ \capsep
\endhead
\tcode{E()}%
  &
  & Creates an engine
    with the same initial state
    as all other default-constructed engines
    of type \tcode{E}.
  & \bigoh{$\text{size of state}$}
  \\ \rowsep
\tcode{E(x)}
  &
  & Creates an engine
    that compares equal to \tcode{x}.
  & \bigoh{$\text{size of state}$}
  \\ \rowsep
\tcode{E(s)}%
  &
  & Creates an engine
      with initial state determined by \tcode{s}.
  & \bigoh{$\text{size of state}$}
  \\ \rowsep
\tcode{E(q)}%
\begin{footnote}
  This constructor
  (as well as the subsequent corresponding \tcode{seed()} function)
  can be particularly useful
  to applications requiring
  a large number of independent random sequences.
\end{footnote}
  &
  & Creates an engine
    with an initial state
    that depends on a sequence
    produced by one call
    to \tcode{q.generate}.
  & same as complexity of \tcode{q.generate}
    called on a sequence
    whose length is size of state
  \\ \rowsep
\tcode{e.seed()}%
  & \keyword{void}
  & \ensures
    \tcode{e == E()}.
  & same as \tcode{E()}
  \\ \rowsep
\tcode{e.seed(s)}%
  & \keyword{void}
  & \ensures
    \tcode{e == E(s)}.
  & same as \tcode{E(s)}
  \\ \rowsep
\tcode{e.seed(q)}%
  & \keyword{void}
  & \ensures
    \tcode{e == E(q)}.
  & same as \tcode{E(q)}
  \\ \rowsep
\tcode{e()}%
  & \tcode{T}
  & Advances \tcode{e}'s state \state{e}{i} to
      \state{e}{i+1} $= \mathsf{TA}($\state{e}{i}$)$
    and returns
      $\mathsf{GA}($\state{e}{i}$)$.
  & per \ref{rand.req.urng}
  \\ \rowsep
\tcode{e.discard(z)}%
\begin{footnote}
  This operation is common
  in user code,
  and can often be implemented
  in an engine-specific manner
  so as to provide significant performance improvements
  over an equivalent naive loop
  that makes \tcode{z} consecutive calls \tcode{e()}.
\end{footnote}
  & \keyword{void}
  & Advances \tcode{e}'s state \state{e}{i}
      to $\tcode{e}_{i+\tcode{z}}$
      by any means equivalent to \tcode{z} consecutive calls \tcode{e()}.
  & no worse than the complexity
    of \tcode{z} consecutive calls \tcode{e()}
  \\ \rowsep
\tcode{x == y}%
  & \tcode{bool}
  & This operator is an equivalence relation.
    With $S_x$ and $S_y$
    as the infinite sequences of values
    that would be generated
    by repeated future calls
    to \tcode{x()} and \tcode{y()},
    respectively,
    returns \tcode{true}
      if $S_x = S_y$;
    else returns \tcode{false}.
  & \bigoh{$\text{size of state}$}
  \\ \rowsep
\tcode{x != y}%
  & \tcode{bool}
  & \tcode{!(x == y)}.
  & \bigoh{$\text{size of state}$}
  \\
\end{libreqtab4d}

\pnum
\tcode{E} shall meet the
\oldconcept{CopyConstructible} (\tref{cpp17.copyconstructible})
and \oldconcept{CopyAssignable} (\tref{cpp17.copyassignable}) requirements.
These operations shall each be of complexity
no worse than \bigoh{\text{size of state}}.

\pnum
On hosted implementations,
the following expressions are well-formed and have the specified semantics.

\begin{itemdecl}
os << x
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
With \tcode{os.\placeholdernc{fmtflags}} set to
\tcode{ios_base::dec|ios_base::left}
and the fill character set to the space character,
writes to \tcode{os}
the textual representation
of \tcode{x}'s current state.
In the output,
adjacent numbers are separated
by one or more space characters.

\pnum
\ensures
The \tcode{os.\placeholdernc{fmtflags}} and fill character are unchanged.

\pnum
\result
reference to the type of \tcode{os}.

\pnum
\returns
\tcode{os}.

\pnum
\complexity
\bigoh{$\text{size of state}$}
\end{itemdescr}

\begin{itemdecl}
is >> v
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{is} provides a textual representation
that was previously written
using an output stream
whose imbued locale
was the same as that of \tcode{is},
and whose type's template specialization arguments
\tcode{charT} and \tcode{traits}
were respectively the same as those of \tcode{is}.

\pnum
\effects
With \tcode{is.\placeholdernc{fmtflags}}
set to \tcode{ios_base::dec},
sets \tcode{v}'s state
as determined by reading its textual representation from \tcode{is}.
If bad input is encountered,
ensures that \tcode{v}'s state is unchanged by the operation
and
calls \tcode{is.setstate(ios_base::failbit)}
(which may throw \tcode{ios_base::failure}\iref{iostate.flags}).
If a textual representation written via \tcode{os << x}
was subsequently read via \tcode{is >> v},
then \tcode{x == v}
provided that there have been no intervening invocations
of \tcode{x} or of \tcode{v}.

\pnum
\ensures
The \tcode{is.\placeholdernc{fmtflags}} are unchanged.

\pnum
\result
reference to the type of \tcode{is}.

\pnum
\returns
\tcode{is}.

\pnum
\complexity
\bigoh{$\text{size of state}$}
\end{itemdescr}

\indextext{requirements!random number engine|)}
\indextext{random number engine!requirements|)}%


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Random Number Engine Adaptor requirements:

\rSec3[rand.req.adapt]{Random number engine adaptor requirements}%

\pnum
A \term{random number engine adaptor}
(commonly shortened to \term{adaptor})
\tcode{a} of type \tcode{A}
is a random number engine
that takes values
produced by some other random number engine,
and applies an algorithm to those values
in order to deliver a sequence of values
with different randomness properties.
An engine \tcode{b} of type \tcode{B} adapted in this way
is termed a \term{base engine}
in this context.
The expression \tcode{a.base()} shall be valid and shall return a
const reference to \tcode{a}'s base engine.

\pnum
The requirements of a random number engine type
shall be interpreted as follows
with respect to a random number engine adaptor type.

\begin{itemdecl}
A::A();
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
 The base engine is initialized
 as if by its default constructor.
\end{itemdescr}

\begin{itemdecl}
bool operator==(const A& a1, const A& a2);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
 \tcode{true} if \tcode{a1}'s base engine is equal to \tcode{a2}'s base engine.
 Otherwise returns \tcode{false}.
\end{itemdescr}

\begin{itemdecl}
A::A(result_type s);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
 The base engine is initialized
 with \tcode{s}.
\end{itemdescr}

\begin{itemdecl}
template<class Sseq> A::A(Sseq& q);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
 The base engine is initialized
 with \tcode{q}.
\end{itemdescr}

\begin{itemdecl}
void seed();
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
 With \tcode{b} as the base engine, invokes \tcode{b.seed()}.
\end{itemdescr}

\begin{itemdecl}
void seed(result_type s);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
 With \tcode{b} as the base engine, invokes \tcode{b.seed(s)}.
\end{itemdescr}

\begin{itemdecl}
template<class Sseq> void seed(Sseq& q);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
 With \tcode{b} as the base engine, invokes \tcode{b.seed(q)}.
\end{itemdescr}

\pnum
\tcode{A} shall also meet
the following additional requirements:
\begin{itemize}
 \item
   The complexity
   of each function
   shall not exceed the complexity
   of the corresponding function
   applied to the base engine.
 \item
   The state
   of \tcode{A}
   shall include the state
   of its base engine.
   The size of \tcode{A}'s state
   shall be no less than the size of the base engine.
 \item
   Copying \tcode{A}'s state
   (e.g., during copy construction or copy assignment)
   shall include copying
   the state of the base engine of \tcode{A}.
 \item
   The textual representation
   of \tcode{A}
   shall include
   the textual representation of its base engine.
\end{itemize}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Random Number Distribution requirements:

\rSec3[rand.req.dist]{Random number distribution requirements}%
\indextext{random number distribution!requirements|(}%
\indextext{requirements!random number distribution|(}

\pnum
A \term{random number distribution}
(commonly shortened to \term{distribution})
\tcode{d} of type \tcode{D}
is a function object
returning values
that are distributed according to
an associated mathematical \term{probability density function}
$p(z)$
or according to
an associated \term{discrete probability function}
$P(z_i)$.
A distribution's specification
identifies its associated probability function
$p(z)$ or $P(z_i)$.

\pnum
An associated probability function is typically expressed
using certain externally-supplied quantities
known as the \term{parameters of the distribution}.
Such distribution parameters are identified
in this context by writing, for example,
  $p(z\,|\,a,b)$ or $P(z_i\,|\,a,b)$,
  to name specific parameters,
or by writing, for example,
  $p(z\,|\left\{\tcode{p}\right\})$
  or $P(z_i\,|\left\{\tcode{p}\right\})$,
  to denote a distribution's parameters \tcode{p} taken as a whole.

\pnum
A class \tcode{D}
meets the requirements
of a \term{random number distribution}
if the expressions shown
in \tref{rand.req.dist}
are valid and have the indicated semantics,
and if \tcode{D} and its associated types
also meet all other requirements
of \ref{rand.req.dist}.
In \tref{rand.req.dist} and throughout this subclause,
\begin{itemize}
  \item
    \tcode{T} is the type named by
    \tcode{D}'s associated \tcode{result_type};
  \item
    \tcode{P} is the type named by
    \tcode{D}'s associated \tcode{param_type};
  \item
    \tcode{d} is a
    value of \tcode{D},
    and
    \tcode{x} and \tcode{y} are (possibly const) values of \tcode{D};
  \item
    \tcode{glb} and \tcode{lub}
    are values of \tcode{T}
    respectively corresponding to
    the greatest lower bound and the least upper bound
    on the values potentially returned by \tcode{d}'s \tcode{operator()},
    as determined by the current values of \tcode{d}'s parameters;
  \item
    \tcode{p} is a (possibly const) value of \tcode{P};
  \item
    \tcode{g}, \tcode{g1}, and \tcode{g2} are lvalues of a type
    meeting the requirements
    of a uniform random bit generator\iref{rand.req.urng};
  \item
    \tcode{os} is an lvalue of the type of some class template specialization
    \tcode{basic_ostream<charT,} \tcode{traits>};
  and
  \item
    \tcode{is} is an lvalue of the type of some class template specialization
    \tcode{basic_istream<charT,} \tcode{traits>};
\end{itemize}
where \tcode{charT} and \tcode{traits} are constrained
according to \ref{strings} and \ref{input.output}.

\begin{libreqtab4d}
  {Random number distribution requirements}
  {rand.req.dist}
\\ \topline
\lhdr{Expression}
  & \chdr{Return type}
  & \chdr{Pre/post-condition}
  & \rhdr{Complexity}
  \\ \capsep
\endfirsthead
\continuedcaption\\
\topline
\lhdr{Expression}
  & \chdr{Return type}
  & \chdr{Pre/post-condition}
  & \rhdr{Complexity}
  \\ \capsep
\endhead
\tcode{D::result_type}
  & \tcode{T}
  & \tcode{T} is an arithmetic type\iref{basic.fundamental}.
  &
  \\ \rowsep
\tcode{D::param_type}
  & \tcode{P}
  &
  &
  \\ \rowsep
\tcode{D()}%
  &
  & Creates a distribution whose behavior is indistinguishable
    from that of any other newly default-constructed distribution
    of type \tcode{D}.
  & constant
  \\ \rowsep
\tcode{D(p)}
  &
  & Creates a distribution whose behavior is indistinguishable
    from that of a distribution
    newly constructed directly from the values used to construct \tcode{p}.
  & same as \tcode{p}'s construction
  \\ \rowsep
\tcode{d.reset()}
  & \keyword{void}
  & Subsequent uses of \tcode{d} do not depend
    on values produced by any engine
    prior to invoking \tcode{reset}.
  & constant
  \\ \rowsep
\tcode{x.param()}
  & \tcode{P}
  & Returns a value
    \tcode{p} such that \tcode{D(p).param() == p}.
  & no worse than the complexity of \tcode{D(p)}
  \\ \rowsep
\tcode{d.param(p)}
  & \keyword{void}
  & \ensures \tcode{d.param() == p}.
  & no worse than the complexity of \tcode{D(p)}
  \\ \rowsep
\tcode{d(g)}
  & \tcode{T}
  & With $\texttt{p} = \texttt{d.param()}$,
    the sequence of numbers
    returned by successive invocations
    with the same object \tcode{g}
    is randomly distributed
    according to the associated
      $p(z\,|\left\{\texttt{p}\right\})$
    or
      $P(z_i\,|\left\{\texttt{p}\right\})$
    function.
  & amortized constant number of invocations of \tcode{g}
  \\ \rowsep
\tcode{d(g,p)}
  & \tcode{T}
  & The sequence of numbers
    returned by successive invocations
    with the same objects \tcode{g} and \tcode{p}
    is randomly distributed
    according to the associated
      $p(z\,|\left\{\texttt{p}\right\})$
    or
      $P(z_i\,|\left\{\texttt{p}\right\})$
    function.
  & amortized constant number of invocations of \tcode{g}
  \\ \rowsep
\tcode{x.min()}
  & \tcode{T}
  & Returns \tcode{glb}.
  & constant
  \\ \rowsep
\tcode{x.max()}
  & \tcode{T}
  & Returns \tcode{lub}.
  & constant
  \\ \rowsep
\tcode{x == y}%
  & \tcode{bool}
  & This operator is an equivalence relation.
    Returns \tcode{true}
      if \tcode{x.param() == y.param()} and $S_1 = S_2$,
      where $S_1$ and $S_2$ are
      the infinite sequences of values
      that would be generated, respectively,
      by repeated future calls
      to \tcode{x(g1)} and \tcode{y(g2)}
      whenever \tcode{g1 == g2}.
      Otherwise returns \tcode{false}.
  & constant
  \\ \rowsep
\tcode{x != y}%
  & \tcode{bool}
  & \tcode{!(x == y)}.
  & same as \tcode{x == y}.
  \\
\end{libreqtab4d}

\pnum
\tcode{D} shall meet the
\oldconcept{CopyConstructible} (\tref{cpp17.copyconstructible})
and \oldconcept{CopyAssignable} (\tref{cpp17.copyassignable}) requirements.

\pnum
The sequence of numbers
produced by repeated invocations of \tcode{d(g)}
shall be independent of any invocation of
\tcode{os << d}
or of
any \keyword{const} member function of \tcode{D}
between any of the invocations of \tcode{d(g)}.

\pnum
If a textual representation is written using \tcode{os << x}
and that representation is restored
into the same or a different object \tcode{y}
of the same type using \tcode{is >> y},
repeated invocations of \tcode{y(g)}
shall produce the same sequence of numbers
as would repeated invocations of \tcode{x(g)}.

\pnum
It is unspecified whether \tcode{D::param_type}
is declared as a (nested) \keyword{class}
or via a \keyword{typedef}.
In \ref{rand},
declarations of \tcode{D::param_type}
are in the form of \keyword{typedef}s
for convenience of exposition only.

\pnum
\tcode{P} shall meet the
\oldconcept{CopyConstructible} (\tref{cpp17.copyconstructible}),
\oldconcept{CopyAssignable} (\tref{cpp17.copyassignable}),
and
\oldconcept{Equality\-Comp\-arable} (\tref{cpp17.equalitycomparable}) requirements.

\pnum
For each of the constructors of \tcode{D}
taking arguments corresponding to parameters of the distribution,
\tcode{P} shall have a corresponding constructor
subject to the same requirements
and taking arguments identical in number, type, and default values.
Moreover,
for each of the member functions of \tcode{D}
that return values corresponding to parameters of the distribution,
\tcode{P} shall have a corresponding member function
with the identical name, type, and semantics.

\pnum
\tcode{P} shall have a declaration of the form
\begin{codeblock}
using distribution_type =  D;
\end{codeblock}

\pnum
On hosted implementations,
the following expressions are well-formed and have the specified semantics.

\begin{itemdecl}
os << x
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Writes to \tcode{os} a textual representation
for the parameters and the additional internal data of \tcode{x}.

\pnum
\ensures
The \tcode{os.\placeholdernc{fmtflags}} and fill character are unchanged.

\pnum
\result
reference to the type of \tcode{os}.

\pnum
\returns
\tcode{os}.
\end{itemdescr}

\begin{itemdecl}
is >> d
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{is} provides a textual representation
that was previously written
using an \tcode{os} whose imbued locale
and whose type's template specialization arguments
\tcode{charT} and \tcode{traits}
were the same as those of \tcode{is}.

\pnum
\effects
Restores from \tcode{is}
the parameters and additional internal data of the lvalue \tcode{d}.
If bad input is encountered,
ensures that \tcode{d} is unchanged by the operation
and
calls \tcode{is.setstate(ios_base::failbit)}
(which may throw \tcode{ios_base::failure}\iref{iostate.flags}).

\pnum
\ensures
The \tcode{is.\placeholdernc{fmtflags}} are unchanged.

\pnum
\result
reference to the type of \tcode{is}.

\pnum
\returns
\tcode{is}.
\end{itemdescr}

\indextext{requirements!random number distribution|)}%
\indextext{random number distribution!requirements|)}%
\indextext{random number generation!requirements|)}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
%% Engine class templates subclause
%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


\rSec2[rand.eng]{Random number engine class templates}%

\rSec3[rand.eng.general]{General}%
\indextext{random number generation!engines|(}

\pnum
Each type instantiated
from a class template specified in \ref{rand.eng}
meets the requirements
of a random number engine\iref{rand.req.eng} type.

\pnum
Except where specified otherwise,
the complexity of each function
specified in \ref{rand.eng}
is constant.

\pnum
Except where specified otherwise,
no function described in \ref{rand.eng}
throws an exception.

\pnum
Every function described in \ref{rand.eng}
that has a function parameter \tcode{q} of type \tcode{Sseq\&}
for a template type parameter named \tcode{Sseq}
that is different from type \tcode{seed_seq}
throws what and when the invocation of \tcode{q.generate} throws.

\pnum
Descriptions are provided in \ref{rand.eng}
only for engine operations
that are not described in \ref{rand.req.eng}
or for operations where there is additional semantic information.
In particular,
declarations for copy constructors,
for copy assignment operators,
for streaming operators,
and for equality and inequality operators
are not shown in the synopses.

\pnum
Each template specified in \ref{rand.eng}
requires one or more relationships,
involving the value(s) of its constant template parameter(s), to hold.
A program instantiating any of these templates
is ill-formed
if any such required relationship fails to hold.

\pnum
For every random number engine and for every random number engine adaptor \tcode{X}
defined in \ref{rand.eng} and in \ref{rand.adapt}:
\begin{itemize}
\item
if the constructor
\begin{codeblock}
template<class Sseq> explicit X(Sseq& q);
\end{codeblock}
is called with a type \tcode{Sseq} that does not qualify as a seed sequence, then this
constructor shall not participate in overload resolution;

\item
if the member function
\begin{codeblock}
template<class Sseq> void seed(Sseq& q);
\end{codeblock}
is called with a type \tcode{Sseq} that does not qualify as a seed sequence, then this
function shall not participate in overload resolution.
\end{itemize}

The extent to which an implementation determines that a type cannot be a seed sequence
is unspecified, except that as a minimum a type shall not qualify as a seed sequence
if it is implicitly convertible to \tcode{X::result_type}.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% linear_congruential_engine engine:

\rSec3[rand.eng.lcong]{Class template \tcode{linear_congruential_engine}}%
\indexlibraryglobal{linear_congruential_engine}%

\pnum
A \tcode{linear_congruential_engine} random number engine
produces unsigned integer random numbers.
The state \state{x}{i}
of a \tcode{linear_congruential_engine} object \tcode{x}
is of size $1$
and consists of a single integer.
The transition algorithm
is a modular linear function of the form
$\mathsf{TA}(\state{x}{i}) = (a \cdot \state{x}{i} + c) \bmod m$;
the generation algorithm
is $\mathsf{GA}(\state{x}{i}) = \state{x}{i+1}$.

\indexlibraryglobal{linear_congruential_engine}%
\indexlibrarymember{result_type}{linear_congruential_engine}%
\begin{codeblock}
namespace std {
  template<class UIntType, UIntType a, UIntType c, UIntType m>
  class linear_congruential_engine {
  public:
    // types
    using result_type = UIntType;

    // engine characteristics
    static constexpr result_type multiplier = a;
    static constexpr result_type increment = c;
    static constexpr result_type modulus = m;
    static constexpr result_type min() { return c == 0u ? 1u: 0u; }
    static constexpr result_type max() { return m - 1u; }
    static constexpr result_type default_seed = 1u;

    // constructors and seeding functions
    linear_congruential_engine() : linear_congruential_engine(default_seed) {}
    explicit linear_congruential_engine(result_type s);
    template<class Sseq> explicit linear_congruential_engine(Sseq& q);
    void seed(result_type s = default_seed);
    template<class Sseq> void seed(Sseq& q);

    // equality operators
    friend bool operator==(const linear_congruential_engine& x,
                           const linear_congruential_engine& y);

    // generating functions
    result_type operator()();
    void discard(unsigned long long z);

    // inserters and extractors
    template<class charT, class traits>
      friend basic_ostream<charT, traits>&
        operator<<(basic_ostream<charT, traits>& os,            // hosted
                   const linear_congruential_engine& x);
    template<class charT, class traits>
      friend basic_istream<charT, traits>&
        operator>>(basic_istream<charT, traits>& is,            // hosted
                   linear_congruential_engine& x);
  };
}
\end{codeblock}

\pnum
If the template parameter
\tcode{m} is $0$,
the modulus $m$
used throughout \ref{rand.eng.lcong}
is \tcode{numeric_limits<result_type>::max()} plus $1$.
\begin{note}
 $m$ need not be representable
 as a value of type \tcode{result_type}.
\end{note}

\pnum
If the template parameter
\tcode{m} is not $0$,
the following relations shall hold:
  \tcode{a < m}
and
  \tcode{c < m}.

\pnum
The textual representation
consists of
the value of \state{x}{i}.

\indexlibraryctor{linear_congruential_engine}%
\begin{itemdecl}
explicit linear_congruential_engine(result_type s);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
 If $c \bmod m$ is $0$ and $\tcode{s} \bmod m$ is $0$,
 sets the engine's state to $1$,
 otherwise sets the engine's state to $\tcode{s} \bmod m$.
\end{itemdescr}

\indexlibraryctor{linear_congruential_engine}%
\begin{itemdecl}
template<class Sseq> explicit linear_congruential_engine(Sseq& q);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
 With
 $k = \left\lceil \frac{\log_2 m}{32} \right\rceil$
 and $a$ an array (or equivalent)
 of length $k + 3$,
 invokes \tcode{q.generate($a + 0$, $a + k + 3$)}
 and then computes
 $S = \left(\sum_{j = 0}^{k - 1} a_{j + 3} \cdot 2^{32j} \right) \bmod m$.
 If $c \bmod m$ is $0$ and $S$ is $0$,
 sets the engine's state to $1$,
 else sets the engine's state
 to $S$.
\end{itemdescr}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% mersenne_twister_engine engine:

\rSec3[rand.eng.mers]{Class template \tcode{mersenne_twister_engine}}%
\indexlibraryglobal{mersenne_twister_engine}%

\pnum
A \tcode{mersenne_twister_engine} random number
engine
\begin{footnote}
The name of this engine refers, in part, to a property of its period:
 For properly-selected values of the parameters,
 the period is closely related to a large Mersenne prime number.
\end{footnote}
produces unsigned integer random numbers
in the closed interval $[0,2^w-1]$.
The
state
\state{x}{i}
of a \tcode{mersenne_twister_engine} object \tcode{x}
is of size $n$
and consists of a sequence $X$
of $n$ values of the type delivered by \tcode{x};
all subscripts applied to $X$ are to be taken modulo $n$.

\pnum
The transition algorithm
employs a twisted generalized feedback shift register
defined by shift values $n$ and $m$, a twist value $r$,
and a conditional xor-mask $a$.
To improve the uniformity of the result,
the bits of the raw shift register are additionally \term{tempered}
(i.e., scrambled) according to a bit-scrambling matrix
defined by values $u$, $d$, $s$, $b$, $t$, $c$, and $\ell$.

The state transition is performed as follows:
\begin{itemize}
 \item
   Concatenate
     the upper $w-r$ bits of $X_{i-n}$
   with
     the lower $r$ bits of $X_{i+1-n}$
   to obtain an unsigned integer value $Y$.
 \item
   With $\alpha = a \cdot (Y \bitand 1)$,
   set $X_i$ to
     $X_{i+m-n} \xor (Y \rightshift 1) \xor \alpha$.
\end{itemize}
The sequence $X$ is initialized
with the help of an initialization multiplier $f$.

\pnum
The generation algorithm
 determines the unsigned integer values $z_1, z_2, z_3, z_4$ as follows,
 then delivers $z_4$ as its result:
\begin{itemize}
 \item
   Let $z_1 = X_i \xor \bigl(( X_i \rightshift u ) \bitand d\bigr)$.
 \item
   Let $z_2 = z_1 \xor \bigl( (z_1 \leftshift{w} s) \bitand b \bigr)$.
 \item
   Let $z_3 = z_2 \xor \bigl( (z_2 \leftshift{w} t) \bitand c \bigr)$.
 \item
   Let $z_4 = z_3 \xor ( z_3 \rightshift \ell )$.
\end{itemize}

\indexlibraryglobal{mersenne_twister_engine}%
\indexlibrarymember{result_type}{mersenne_twister_engine}%
\begin{codeblock}
namespace std {
  template<class UIntType, size_t w, size_t n, size_t m, size_t r,
           UIntType a, size_t u, UIntType d, size_t s,
           UIntType b, size_t t,
           UIntType c, size_t l, UIntType f>
  class mersenne_twister_engine {
  public:
    // types
    using result_type = UIntType;

    // engine characteristics
    static constexpr size_t word_size = w;
    static constexpr size_t state_size = n;
    static constexpr size_t shift_size = m;
    static constexpr size_t mask_bits = r;
    static constexpr UIntType xor_mask = a;
    static constexpr size_t tempering_u = u;
    static constexpr UIntType tempering_d = d;
    static constexpr size_t tempering_s = s;
    static constexpr UIntType tempering_b = b;
    static constexpr size_t tempering_t = t;
    static constexpr UIntType tempering_c = c;
    static constexpr size_t tempering_l = l;
    static constexpr UIntType initialization_multiplier = f;
    static constexpr result_type min() { return 0; }
    static constexpr result_type max() { return  @$2^w - 1$@; }
    static constexpr result_type default_seed = 5489u;

    // constructors and seeding functions
    mersenne_twister_engine() : mersenne_twister_engine(default_seed) {}
    explicit mersenne_twister_engine(result_type value);
    template<class Sseq> explicit mersenne_twister_engine(Sseq& q);
    void seed(result_type value = default_seed);
    template<class Sseq> void seed(Sseq& q);

    // equality operators
    friend bool operator==(const mersenne_twister_engine& x, const mersenne_twister_engine& y);

    // generating functions
    result_type operator()();
    void discard(unsigned long long z);

    // inserters and extractors
    template<class charT, class traits>
      friend basic_ostream<charT, traits>&
        operator<<(basic_ostream<charT, traits>& os,            // hosted
                   const mersenne_twister_engine& x);
    template<class charT, class traits>
      friend basic_istream<charT, traits>&
        operator>>(basic_istream<charT, traits>& is,            // hosted
                   mersenne_twister_engine& x);
  };
}
\end{codeblock}

\pnum
The following relations shall hold:
  \tcode{0 < m},
  \tcode{m <= n},
  \tcode{2u < w},
  \tcode{r <= w},
  \tcode{u <= w},
  \tcode{s <= w},
  \tcode{t <= w},
  \tcode{l <= w},
  \tcode{w <= numeric_limits<UIntType>::digits},
  \tcode{a <= (1u << w) - 1u},
  \tcode{b <= (1u << w) - 1u},
  \tcode{c <= (1u << w) - 1u},
  \tcode{d <= (1u << w) - 1u},
and
  \tcode{f <= (1u << w) - 1u}.

\pnum
The textual representation
of \state{x}{i}
consists of the values of $X_{i - n}, \dotsc, X_{i - 1}$,
in that order.

\indexlibraryctor{mersenne_twister_engine}%
\begin{itemdecl}
explicit mersenne_twister_engine(result_type value);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Sets $X_{-n}$ to $\tcode{value} \bmod 2^w$.
Then, iteratively for $i = 1 - n, \dotsc, -1$, sets $X_i$ to
\[%
 \bigl[f \cdot
       \bigl(X_{i-1} \xor \bigl(X_{i-1} \rightshift (w-2)\bigr)
       \bigr)
       + i \bmod n
 \bigr] \bmod 2^w
\; \mbox{.}
\]%

\pnum
\complexity
\bigoh{n}.
\end{itemdescr}

\indexlibraryctor{mersenne_twister_engine}%
\begin{itemdecl}
template<class Sseq> explicit mersenne_twister_engine(Sseq& q);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
 With
 $k = \left\lceil w / 32 \right\rceil$
 and $a$ an array (or equivalent)
 of length $n \cdot k$,
 invokes \tcode{q.generate($a+0$, $a+n \cdot k$)}
 and then, iteratively for $i = -n,\dotsc,-1$,
 sets $X_i$
 to $\left(\sum_{j=0}^{k-1}a_{k(i+n)+j} \cdot 2^{32j} \right) \bmod 2^w$.
 Finally,
 if the most significant $w-r$ bits of $X_{-n}$
 are zero,
 and if each of the other resulting $X_i$ is $0$,
 changes $X_{-n}$
 to $ 2^{w-1} $.
\end{itemdescr}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% subtract_with_carry_engine engine:

\rSec3[rand.eng.sub]{Class template \tcode{subtract_with_carry_engine}}%
\indexlibraryglobal{subtract_with_carry_engine}%

\pnum
A \tcode{subtract_with_carry_engine} random number engine
produces unsigned integer random numbers.

\pnum
The state \state{x}{i}
of a \tcode{subtract_with_carry_engine} object \tcode{x}
is of size
\bigoh{r},
and consists of
a sequence $X$ of $r$ integer values $0 \leq X_i < m \,= 2^w$;
all subscripts applied to $X$ are to be taken modulo $r$.
The state \state{x}{i}
additionally consists of an integer $c$
(known as the \term{carry})
whose value is either $0$ or $1$.

\pnum
The state transition
is performed as follows:
\begin{itemize}
 \item
   Let $Y = X_{i-s} - X_{i-r} - c$.
 \item
   Set $X_i$ to $y = Y \bmod m$.
   Set $c$ to 1 if $Y < 0$,
   otherwise set $c$ to 0.
\end{itemize}
\begin{note}
 This algorithm corresponds
 to a modular linear function
 of the form
 $\mathsf{TA}(\state{x}{i}) = (a \cdot \state{x}{i}) \bmod b$,
 where $b$ is of the form
 $m^r - m^s + 1$
 and $a = b - (b - 1) / m$.
\end{note}

\pnum
The generation algorithm
is given by $\mathsf{GA}(\state{x}{i}) = y$,
where $y$ is the value produced as a result
of advancing the engine's state as described above.

\indexlibraryglobal{subtract_with_carry_engine}%
\indexlibrarymember{result_type}{subtract_with_carry_engine}%
\begin{codeblock}
namespace std {
  template<class UIntType, size_t w, size_t s, size_t r>
  class subtract_with_carry_engine {
  public:
    // types
    using result_type = UIntType;

    // engine characteristics
    static constexpr size_t word_size = w;
    static constexpr size_t short_lag = s;
    static constexpr size_t long_lag = r;
    static constexpr result_type min() { return 0; }
    static constexpr result_type max() { return @$m - 1$@; }
    static constexpr uint_least32_t default_seed = 19780503u;

    // constructors and seeding functions
    subtract_with_carry_engine() : subtract_with_carry_engine(0u) {}
    explicit subtract_with_carry_engine(result_type value);
    template<class Sseq> explicit subtract_with_carry_engine(Sseq& q);
    void seed(result_type value = 0u);
    template<class Sseq> void seed(Sseq& q);

    // equality operators
    friend bool operator==(const subtract_with_carry_engine& x,
                           const subtract_with_carry_engine& y);

    // generating functions
    result_type operator()();
    void discard(unsigned long long z);

    // inserters and extractors
    template<class charT, class traits>
      friend basic_ostream<charT, traits>&
        operator<<(basic_ostream<charT, traits>& os,            // hosted
                   const subtract_with_carry_engine& x);
    template<class charT, class traits>
      friend basic_istream<charT, traits>&
        operator>>(basic_istream<charT, traits>& is,            // hosted
                   subtract_with_carry_engine& x);
  };
}
\end{codeblock}

\pnum
The following relations shall hold:
  \tcode{0u < s},
  \tcode{s < r},
  \tcode{0 < w},
and
  \tcode{w <= numeric_limits<UIntType>::digits}.

\pnum
The textual representation
consists of the values of
 $X_{i-r}, \dotsc, X_{i-1}$,
in that order, followed by $c$.

\indexlibraryctor{subtract_with_carry_engine}%
\begin{itemdecl}
explicit subtract_with_carry_engine(result_type value);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
 Sets the values of
 $X_{-r}, \dotsc, X_{-1}$,
 in that order, as specified below.
 If $X_{-1}$ is then $0$,
 sets $c$ to $1$;
 otherwise sets $c$ to $0$.

 To set the values $X_k$,
 first construct \tcode{e}, a \tcode{linear_congruential_engine} object,
 as if by the following definition:
\begin{codeblock}
linear_congruential_engine<uint_least32_t, 40014u, 0u, 2147483563u> e(
  value == 0u ? default_seed : static_cast<uint_least32_t>(value % 2147483563u));
\end{codeblock}
 Then, to set each $X_k$,
 obtain new values $z_0, \dotsc, z_{n-1}$
 from $n = \lceil w/32 \rceil$ successive invocations
 of \tcode{e}.
 Set $X_k$ to $\left( \sum_{j=0}^{n-1} z_j \cdot 2^{32j}\right) \bmod m$.

\pnum
\complexity
Exactly $n \cdot \tcode{r}$ invocations
 of \tcode{e}.
\end{itemdescr}

\indexlibraryctor{subtract_with_carry_engine}%
\begin{itemdecl}
template<class Sseq> explicit subtract_with_carry_engine(Sseq& q);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
 With
 $k = \left\lceil w / 32 \right\rceil$
 and $a$ an array (or equivalent)
 of length $r \cdot k$,
 invokes \tcode{q.generate($a + 0$, $a + r \cdot k$)}
 and then, iteratively for $i = -r, \dotsc, -1$,
 sets $X_i$
 to $ \left(\sum_{j=0}^{k-1}a_{k(i+r)+j} \cdot 2^{32j} \right) \bmod m $.
 If $X_{-1}$ is then $0$,
 sets $c$ to $1$;
 otherwise sets $c$ to $0$.
\end{itemdescr}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% philox_engine engine:

\rSec3[rand.eng.philox]{Class template \tcode{philox_engine}}%
\indexlibraryglobal{philox_engine}%

\pnum
A \tcode{philox_engine} random number engine produces
unsigned integer random numbers in the interval \range{0}{$m$},
where $m = 2^w$ and
the template parameter $w$ defines the range of the produced numbers.
The state of a \tcode{philox_engine} object consists of
a sequence $X$ of $n$ unsigned integer values of width $w$,
a sequence $K$ of $n/2$ values of \tcode{result_type},
a sequence $Y$ of $n$ values of \tcode{result_type}, and
a scalar $i$, where
\begin{itemize}
\item
$X$ is the interpretation of the unsigned integer \term{counter} value
$Z \cedef \sum_{j = 0}^{n - 1} X_j \cdot 2^{wj}$ of $n \cdot w$ bits,
\item
$K$ are keys, which are generated once from the seed (see constructors below)
and remain constant unless the \tcode{seed} function\iref{rand.req.eng} is invoked,
\item
$Y$ stores a batch of output values, and
\item
$i$ is an index for an element of the sequence $Y$.
\end{itemize}

\pnum
The generation algorithm returns $Y_i$,
the value stored in the $i^\text{th}$ element of $Y$ after applying
the transition algorithm.

\pnum
The state transition is performed as if by the following algorithm:
\begin{codeblock}
@$i$@ = @$i$@ + 1
if (@$i$@ == @$n$@) {
  @$Y$@ = Philox(@$K$@, @$X$@) // \seebelow
  @$Z$@ = @$Z$@ + 1
  @$i$@ = 0
}
\end{codeblock}

\pnum
The \tcode{Philox} function maps the length-$n/2$ sequence $K$ and
the length-$n$ sequence $X$ into a length-$n$ output sequence $Y$.
Philox applies an $r$-round substitution-permutation network to the values in $X$.
A single round of the generation algorithm performs the following steps:
\begin{itemize}
\item
The output sequence $X'$ of the previous round
($X$ in case of the first round)
is permuted to obtain the intermediate state $V$:
\begin{codeblock}
@$V_j = X'_{f_n(j)}$@
\end{codeblock}
where $j = 0, \dotsc, n - 1$ and
$f_n(j)$ is defined in \tref{rand.eng.philox.f}.

\begin{floattable}{Values for the word permutation $\bm{f}_{\bm{n}}\bm{(j)}$}{rand.eng.philox.f}
{l|l|l|l|l|l}
\topline
  \multicolumn{2}{|c|}{$\bm{f}_{\bm{n}}\bm{(j)}$} & \multicolumn{4}{c|}{$\bm{j}$} \\ \cline{3-6}
  \multicolumn{2}{|c|}{}
    & 0 & 1 & 2 & 3 \\ \hline
  $\bm{n} $ & 2 & 0 & 1 & \multicolumn{2}{c|}{} \\ \cline{2-6}
  & 4 & 2 & 1 & 0 & 3 \\ \cline{2-6}
\end{floattable}
\begin{note}
For $n = 2$ the sequence is not permuted.
\end{note}

\item
The following computations are applied to the elements of the $V$ sequence:
\begin{codeblock}
@$X_{2k + 0} = \mulhi(V_{2k}, M_{k}, w) \xor \mathit{key}^q_k \xor V_{2k + 1}$@
@$X_{2k + 1} = \mullo(V_{2k}, M_{k}, w)$@
\end{codeblock}
where:
  \begin{itemize}
  \item
  $\mullo(\tcode{a}, \tcode{b}, \tcode{w})$ is
  the low half of the modular multiplication of \tcode{a} and \tcode{b}:
  $(\tcode{a} \cdot \tcode{b}) \mod 2^w$,

  \item
  $\mulhi(\tcode{a}, \tcode{b}, \tcode{w})$ is
  the high half of the modular multiplication of \tcode{a} and \tcode{b}:
  $(\left\lfloor (\tcode{a} \cdot \tcode{b}) / 2^w \right\rfloor)$,

  \item
  $k = 0, \dotsc, n/2 - 1$ is the index in the sequences,

  \item
  $q = 0, \dotsc, r - 1$ is the index of the round,

  \item
  $\mathit{key}^q_k$ is the $k^\text{th}$ round key for round $q$,
  $\mathit{key}^q_k \cedef (K_k + q \cdot C_k) \mod 2^w$,

  \item
  $K_k$ are the elements of the key sequence $K$,

  \item
  $M_k$ is \tcode{multipliers[$k$]}, and

  \item
  $C_k$ is \tcode{round_consts[$k$]}.
  \end{itemize}
\end{itemize}

\pnum
After $r$ applications of the single-round function,
\tcode{Philox} returns the sequence $Y = X'$.

\indexlibraryglobal{philox_engine}%
\indexlibrarymember{result_type}{philox_engine}%
\begin{codeblock}
namespace std {
  template<class UIntType, size_t w, size_t n, size_t r, UIntType... consts>
  class philox_engine {
    static constexpr size_t @\exposid{array-size}@ = n / 2;   // \expos
  public:
    // types
    using result_type = UIntType;

    // engine characteristics
    static constexpr size_t word_size = w;
    static constexpr size_t word_count = n;
    static constexpr size_t round_count = r;
    static constexpr array<result_type, @\exposid{array-size}@> multipliers;
    static constexpr array<result_type, @\exposid{array-size>}@ round_consts;
    static constexpr result_type min() { return 0; }
    static constexpr result_type max() { return m - 1; }
    static constexpr result_type default_seed = 20111115u;

    // constructors and seeding functions
    philox_engine() : philox_engine(default_seed) {}
    explicit philox_engine(result_type value);
    template<class Sseq> explicit philox_engine(Sseq& q);
    void seed(result_type value = default_seed);
    template<class Sseq> void seed(Sseq& q);

    void set_counter(const array<result_type, n>& counter);

    // equality operators
    friend bool operator==(const philox_engine& x, const philox_engine& y);

    // generating functions
    result_type operator()();
    void discard(unsigned long long z);

    // inserters and extractors
    template<class charT, class traits>
      friend basic_ostream<charT, traits>&
        operator<<(basic_ostream<charT, traits>& os, const philox_engine& x);   // hosted
    template<class charT, class traits>
      friend basic_istream<charT, traits>&
        operator>>(basic_istream<charT, traits>& is, philox_engine& x);         // hosted
  };
}
\end{codeblock}

\pnum
\mandates
\begin{itemize}
\item \tcode{sizeof...(consts) == n} is \tcode{true}, and
\item \tcode{n == 2 || n == 4} is \tcode{true}, and
\item \tcode{0 < r} is \tcode{true}, and
\item \tcode{0 < w \&\& w <= numeric_limits<UIntType>::digits} is \tcode{true}.
\end{itemize}

\pnum
The template parameter pack \tcode{consts} represents
the $M_k$ and $C_k$ constants which are grouped as follows:
$[ M_0, C_0, M_1, C_1, M_2, C_2, \dotsc, M_{n/2 - 1}, C_{n/2 - 1} ]$.

\pnum
The textual representation consists of the values of
$K_0, \dotsc, K_{n/2 - 1}, X_{0}, \dotsc, X_{n - 1}, i$, in that order.
\begin{note}
The stream extraction operator can reconstruct $Y$ from $K$ and $X$, as needed.
\end{note}

\indexlibraryctor{philox_engine}
\begin{itemdecl}
explicit philox_engine(result_type value);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Sets the $K_0$ element of sequence $K$ to $\tcode{value} \mod 2^w$.
All elements of sequences $X$ and $K$ (except $K_0$) are set to \tcode{0}.
The value of $i$ is set to $n - 1$.
\end{itemdescr}

\indexlibraryctor{philox_engine}
\begin{itemdecl}
template<class Sseq> explicit philox_engine(Sseq& q);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
With $p = \left\lceil w / 32 \right\rceil$ and
an array (or equivalent) \tcode{a} of length $(n/2) \cdot p$,
invokes \tcode{q.generate(a + 0, a + n / 2 * $p$)} and
then iteratively for $k = 0, \dotsc, n/2 - 1$,
sets $K_k$ to
$\left(\sum_{j = 0}^{p - 1} a_{k p + j} \cdot 2^{32j} \right) \mod 2^w$.
All elements of sequence $X$ are set to \tcode{0}.
The value of $i$ is set to $n - 1$.
\end{itemdescr}

\indexlibrarymember{set_counter}{philox_engine}%
\begin{itemdecl}
void set_counter(const array<result_type, n>& c);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
For $j = 0, \dotsc, n - 1$ sets $X_j$ to $C_{n - 1 - j} \mod 2^w$.
The value of $i$ is set to $n - 1$.
\begin{note}
The counter is the value $Z$ introduced at the beginning of this subclause.
\end{note}
\end{itemdescr}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
%% Engine adaptors class templates subclause
%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


\rSec2[rand.adapt]{Random number engine adaptor class templates}

\rSec3[rand.adapt.general]{General}

\pnum
Each type instantiated
from a class template specified in \ref{rand.adapt}
meets the requirements
of a random number engine adaptor\iref{rand.req.adapt} type.

\pnum
Except where specified otherwise,
the complexity of each function
specified in \ref{rand.adapt}
is constant.

\pnum
Except where specified otherwise,
no function described in \ref{rand.adapt}
throws an exception.

\pnum
Every function described in \ref{rand.adapt}
that has a function parameter \tcode{q} of type \tcode{Sseq\&}
for a template type parameter named \tcode{Sseq}
that is different from type \tcode{seed_seq}
throws what and when the invocation of \tcode{q.generate} throws.

\pnum
Descriptions are provided in \ref{rand.adapt}
only for adaptor operations
that are not described in subclause~\ref{rand.req.adapt}
or for operations where there is additional semantic information.
In particular,
declarations for copy constructors,
for copy assignment operators,
for streaming operators,
and for equality and inequality operators
are not shown in the synopses.

\pnum
Each template specified in \ref{rand.adapt}
requires one or more relationships,
involving the value(s) of its constant template parameter(s), to hold.
A program instantiating any of these templates
is ill-formed
if any such required relationship fails to hold.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% discard_block_engine engine adaptor:

\rSec3[rand.adapt.disc]{Class template \tcode{discard_block_engine}}%
\indexlibraryglobal{discard_block_engine}%

\pnum
A \tcode{discard_block_engine} random number engine adaptor
produces random numbers
selected from those produced by some base engine $e$.
The state \state{x}{i}
of a \tcode{discard_block_engine} engine adaptor object \tcode{x}
consists of the state \state{e}{i} of its base engine \tcode{e}
and an additional integer $n$.
The size of the state is
 the size of $e$'s state plus $1$.

\pnum
The transition algorithm
discards all but $r > 0$ values
from each block of $p \geq r$ values delivered by $e$.
The state transition is performed as follows:
If $n \geq r$,
 advance the state of \tcode{e} from \state{e}{i} to \state{e}{i+p-r}
 and set $n$ to $0$.
In any case,
 then increment $n$
 and advance \tcode{e}'s then-current state \state{e}{j}
 to \state{e}{j+1}.

\pnum
The generation algorithm
yields the value returned by the last invocation of \tcode{e()}
 while advancing \tcode{e}'s state as described above.

\indexlibraryglobal{discard_block_engine}%
\indexlibrarymember{result_type}{discard_block_engine}%
\begin{codeblock}
namespace std {
  template<class Engine, size_t p, size_t r>
  class discard_block_engine {
  public:
    // types
    using result_type = Engine::result_type;

    // engine characteristics
    static constexpr size_t block_size = p;
    static constexpr size_t used_block = r;
    static constexpr result_type min() { return Engine::min(); }
    static constexpr result_type max() { return Engine::max(); }

    // constructors and seeding functions
    discard_block_engine();
    explicit discard_block_engine(const Engine& e);
    explicit discard_block_engine(Engine&& e);
    explicit discard_block_engine(result_type s);
    template<class Sseq> explicit discard_block_engine(Sseq& q);
    void seed();
    void seed(result_type s);
    template<class Sseq> void seed(Sseq& q);

    // equality operators
    friend bool operator==(const discard_block_engine& x, const discard_block_engine& y);

    // generating functions
    result_type operator()();
    void discard(unsigned long long z);

    // property functions
    const Engine& base() const noexcept { return e; }

    // inserters and extractors
    template<class charT, class traits>
      friend basic_ostream<charT, traits>&
        operator<<(basic_ostream<charT, traits>& os, const discard_block_engine& x);    // hosted
    template<class charT, class traits>
      friend basic_istream<charT, traits>&
        operator>>(basic_istream<charT, traits>& is, discard_block_engine& x);          // hosted

  private:
    Engine e;   // \expos
    size_t n;   // \expos
  };
}
\end{codeblock}

\pnum
The following relations shall hold:
  \tcode{0 < r}
and
  \tcode{r <= p}.

\pnum
The textual representation
consists of
 the textual representation of \tcode{e}
followed by
 the value of \tcode{n}.

\pnum
In addition to its behavior
pursuant to subclause~\ref{rand.req.adapt},
each constructor%
\indexlibraryctor{discard_block_engine}
that is not a copy constructor
sets \tcode{n} to $0$.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% independent_bits_engine engine adaptor:\exposid{

\rSec3[rand.adapt.ibits]{Class template \tcode{independent_bits_engine}}%
\indexlibraryglobal{independent_bits_engine}%

\pnum
An \tcode{independent_bits_engine}
random number engine adaptor
combines random numbers
that are produced by some base engine $e$,
so as to produce random numbers
with a specified number of bits $w$.
The state \state{x}{i}
of an \tcode{independent_bits_engine}
engine adaptor object \tcode{x}
consists of
 the state \state{e}{i} of its base engine \tcode{e};
the size of the state is
 the size of $e$'s state.

\pnum
The transition and generation algorithms
are described in terms
of the following integral constants:%
\begin{itemize}
 \item
   Let
     $R = \tcode{e.max() - e.min() + 1}$
   and
     $m = \left\lfloor \log_2 R \right\rfloor$.
 \item
   With $n$ as determined below,
   let
     $w_0 = \left\lfloor w / n \right\rfloor$,
     $n_0 = n - w \bmod n$,
     $y_0 = 2^{w_0} \left\lfloor R / 2^{w_0} \right\rfloor$,
   and
     $y_1 = 2^{w_0 + 1} \left\lfloor R / 2^{w_0 + 1} \right\rfloor$.
 \item
   Let
     $n = \left\lceil w / m \right\rceil$
   if and only if the relation
     $R - y_0 \leq \left\lfloor y_0 / n \right\rfloor$
   holds as a result.
   Otherwise let
     $n = 1 + \left\lceil w / m \right\rceil$.
\end{itemize}
\begin{note}
 The relation
 $w = n_0 w_0 + (n - n_0)(w_0 + 1)$
 always holds.
\end{note}

\pnum
The transition algorithm
is carried out by invoking \tcode{e()}
as often as needed to obtain $n_0$
values less than $y_0 + \tcode{e.min()}$
and $n - n_0$ values less than $y_1 + \tcode{e.min()}$.

\pnum
The generation algorithm
uses the values produced
while advancing the state as described above
to yield a quantity $S$
obtained as if by the following algorithm:
\begin{codeblock}
@$S$@ = 0;
for (@$k$@ = @$0$@; @$k \neq n_0$@; @$k$@ += @$1$@)  {
 do @$u$@ = e() - e.min(); while (@$u \ge y_0$@);
 @$S$@ = @$2^{w_0} \cdot S + u \bmod 2^{w_0}$@;
}
for (@$k$@ = @$n_0$@; @$k \neq n$@; @$k$@ += @$1$@)  {
 do @$u$@ = e() - e.min(); while (@$u \ge y_1$@);
 @$S$@ = @$2^{w_0 + 1} \cdot S + u \bmod 2^{w_0 + 1}$@;
}
\end{codeblock}

\indexlibraryglobal{independent_bits_engine}%
\indexlibrarymember{result_type}{independent_bits_engine}%
\begin{codeblock}
namespace std {
  template<class Engine, size_t w, class UIntType>
  class independent_bits_engine {
  public:
    // types
    using result_type = UIntType;

    // engine characteristics
    static constexpr result_type min() { return 0; }
    static constexpr result_type max() { return @$2^w - 1$@; }

    // constructors and seeding functions
    independent_bits_engine();
    explicit independent_bits_engine(const Engine& e);
    explicit independent_bits_engine(Engine&& e);
    explicit independent_bits_engine(result_type s);
    template<class Sseq> explicit independent_bits_engine(Sseq& q);
    void seed();
    void seed(result_type s);
    template<class Sseq> void seed(Sseq& q);

    // equality operators
    friend bool operator==(const independent_bits_engine& x, const independent_bits_engine& y);

    // generating functions
    result_type operator()();
    void discard(unsigned long long z);

    // property functions
    const Engine& base() const noexcept { return e; }

    // inserters and extractors
    template<class charT, class traits>
      friend basic_ostream<charT, traits>&
        operator<<(basic_ostream<charT, traits>& os, const independent_bits_engine& x); // hosted
    template<class charT, class traits>
      friend basic_istream<charT, traits>&
        operator>>(basic_istream<charT, traits>& is, independent_bits_engine& x);       // hosted

  private:
    Engine e;   // \expos
  };
}
\end{codeblock}%

\pnum
The following relations shall hold:
  \tcode{0 < w}
and
  \tcode{w <= numeric_limits<result_type>::digits}.

\pnum
The textual representation
consists of the textual representation of \tcode{e}.


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% shuffle_order_engine engine adaptor:

\rSec3[rand.adapt.shuf]{Class template \tcode{shuffle_order_engine}}%
\indexlibraryglobal{shuffle_order_engine}%

\pnum
A \tcode{shuffle_order_engine} random number engine adaptor
produces the same random numbers
that are produced by some base engine $e$,
but delivers them in a different sequence.
The state \state{x}{i}
of a \tcode{shuffle_order_engine} engine adaptor object \tcode{x}
consists of
 the state \state{e}{i} of its base engine \tcode{e},
 an additional value $Y$ of the type delivered by \tcode{e},
and
 an additional sequence $V$ of $k$ values
 also of the type delivered by \tcode{e}.
The size of the state is
 the size of $e$'s state plus $k + 1$.

\pnum
The transition algorithm
permutes the values produced by $e$.
The state transition is performed as follows:
\begin{itemize}
 \item
   Calculate an integer
   $j = \left\lfloor \frac{k \cdot (Y - e_{\min})}
                          {e_{\max} - e_{\min} +1}
        \right\rfloor
   $%
   .
 \item
   Set $Y$ to $V_j$ and then set $V_j$ to $\tcode{e()}$.
\end{itemize}

\pnum
The generation algorithm
yields the last value of \tcode{Y}
 produced while advancing \tcode{e}'s state as described above.

\indexlibraryglobal{shuffle_order_engine}%
\indexlibrarymember{result_type}{shuffle_order_engine}%
\begin{codeblock}
namespace std {
  template<class Engine, size_t k>
  class shuffle_order_engine {
  public:
    // types
    using result_type = Engine::result_type;

    // engine characteristics
    static constexpr size_t table_size = k;
    static constexpr result_type min() { return Engine::min(); }
    static constexpr result_type max() { return Engine::max(); }

    // constructors and seeding functions
    shuffle_order_engine();
    explicit shuffle_order_engine(const Engine& e);
    explicit shuffle_order_engine(Engine&& e);
    explicit shuffle_order_engine(result_type s);
    template<class Sseq> explicit shuffle_order_engine(Sseq& q);
    void seed();
    void seed(result_type s);
    template<class Sseq> void seed(Sseq& q);

    // equality operators
    friend bool operator==(const shuffle_order_engine& x, const shuffle_order_engine& y);

    // generating functions
    result_type operator()();
    void discard(unsigned long long z);

    // property functions
    const Engine& base() const noexcept { return e; }

    // inserters and extractors
    template<class charT, class traits>
      friend basic_ostream<charT, traits>&
        operator<<(basic_ostream<charT, traits>& os, const shuffle_order_engine& x);
    template<class charT, class traits>
      friend basic_istream<charT, traits>&
        operator>>(basic_istream<charT, traits>& is, shuffle_order_engine& x);

  private:
    Engine e;           // \expos
    result_type V[k];   // \expos
    result_type Y;      // \expos
  };
}
\end{codeblock}

\pnum
The following relation shall hold:
  \tcode{0 < k}.

\pnum
The textual representation
consists of
 the textual representation of \tcode{e},
followed by
 the \tcode{k} values of $V$,
followed by
 the value of $Y$.

\pnum
In addition to its behavior
pursuant to subclause~\ref{rand.req.adapt},
each constructor%
\indexlibraryctor{shuffle_order_engine}
that is not a copy constructor
initializes $\tcode{V[0]}, \dotsc, \tcode{V[k - 1]}$ and $Y$,
in that order,
with values returned by successive invocations of \tcode{e()}.%
\indextext{random number generation!engines|)}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
%% Engines with predefined parameters subclause
%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


\rSec2[rand.predef]{Engines and engine adaptors with predefined parameters}%
\indextext{random number engine!with predefined parameters|(}%
\indextext{random number engine adaptor!with predefined parameters|(}%
\indextext{random number generation!predefined engines and adaptors|(}

\indexlibraryglobal{minstd_rand0}%
\begin{itemdecl}
using minstd_rand0 =
      linear_congruential_engine<uint_fast32_t, 16'807, 0, 2'147'483'647>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\required
 The $10000^\text{th}$ consecutive invocation
 of a default-constructed object
 of type \tcode{minstd_rand0}
 produces the value $1043618065$.
\end{itemdescr}

\indexlibraryglobal{minstd_rand}%
\begin{itemdecl}
using minstd_rand =
      linear_congruential_engine<uint_fast32_t, 48'271, 0, 2'147'483'647>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\required
 The $10000^\text{th}$ consecutive invocation
 of a default-constructed object
 of type \tcode{minstd_rand}
 produces the value $399268537$.
\end{itemdescr}

\indexlibraryglobal{mt19937}%
\begin{itemdecl}
using mt19937 =
      mersenne_twister_engine<uint_fast32_t, 32, 624, 397, 31,
       0x9908'b0df, 11, 0xffff'ffff, 7, 0x9d2c'5680, 15, 0xefc6'0000, 18, 1'812'433'253>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\required
 The $10000^\text{th}$ consecutive invocation
 of a default-constructed object
 of type \tcode{mt19937}
 produces the value $4123659995$.
\end{itemdescr}

\indexlibraryglobal{mt19937_64}%
\begin{itemdecl}
using mt19937_64 =
      mersenne_twister_engine<uint_fast64_t, 64, 312, 156, 31,
       0xb502'6f5a'a966'19e9, 29, 0x5555'5555'5555'5555, 17,
       0x71d6'7fff'eda6'0000, 37, 0xfff7'eee0'0000'0000, 43, 6'364'136'223'846'793'005>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\required
 The $10000^\text{th}$ consecutive invocation
 of a default-constructed object
 of type \tcode{mt19937_64}
 produces the value $9981545732273789042$.
\end{itemdescr}

\indexlibraryglobal{ranlux24_base}%
\begin{itemdecl}
using ranlux24_base =
      subtract_with_carry_engine<uint_fast32_t, 24, 10, 24>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\required
 The $10000^\text{th}$ consecutive invocation
 of a default-constructed object
 of type \tcode{ran\-lux24_base}
 produces the value
 $7937952$.
\end{itemdescr}

\indexlibraryglobal{ranlux48_base}%
\begin{itemdecl}
using ranlux48_base =
      subtract_with_carry_engine<uint_fast64_t, 48, 5, 12>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\required
 The $10000^\text{th}$ consecutive invocation
 of a default-constructed object
 of type \tcode{ran\-lux48_base}
 produces the value
 $61839128582725$.
\end{itemdescr}

\indexlibraryglobal{ranlux24}%
\begin{itemdecl}
using ranlux24 = discard_block_engine<ranlux24_base, 223, 23>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\required
 The $10000^\text{th}$ consecutive invocation
 of a default-constructed object
 of type \tcode{ranlux24}
 produces the value
 $9901578$.
\end{itemdescr}

\indexlibraryglobal{ranlux48}%
\begin{itemdecl}
using ranlux48 = discard_block_engine<ranlux48_base, 389, 11>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\required
 The $10000^\text{th}$ consecutive invocation
 of a default-constructed object
 of type \tcode{ranlux48}
 produces the value
 $249142670248501$.
\end{itemdescr}

\indexlibraryglobal{knuth_b}%
\begin{itemdecl}
using knuth_b = shuffle_order_engine<minstd_rand0,256>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\required
 The $10000^\text{th}$ consecutive invocation
 of a default-constructed object
 of type \tcode{knuth_b}
 produces the value $1112339016$.
\end{itemdescr}%

\indexlibraryglobal{default_random_engine}%
\begin{itemdecl}
using default_random_engine = @\textit{\impldef{type of \tcode{default_random_engine}}}@;
\end{itemdecl}

\begin{itemdescr}
\pnum
\remarks
The choice of engine type
named by this \keyword{typedef}
is \impldef{type of \tcode{default_random_engine}}.
\begin{note}
 The implementation
 can select this type
 on the basis of performance,
 size,
 quality,
 or any combination of such factors,
 so as to provide at least acceptable engine behavior
 for relatively casual, inexpert, and/or lightweight use.
 Because different implementations
 can select different underlying engine types,
 code that uses this \keyword{typedef}
 need not generate identical sequences across implementations.
\end{note}
\end{itemdescr}%

\indexlibraryglobal{philox4x32}%
\begin{itemdecl}
using philox4x32 =
      philox_engine<uint_fast32_t, 32, 4, 10,
       0xCD9E8D57, 0x9E3779B9, 0xD2511F53, 0xBB67AE85>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\required
The $10000^\text{th}$ consecutive invocation
a default-constructed object of type \tcode{philox4x32}
produces the value $1955073260$.
\end{itemdescr}%

\indexlibraryglobal{philox4x64}%
\begin{itemdecl}
using philox4x64 =
      philox_engine<uint_fast64_t, 64, 4, 10,
       0xCA5A826395121157, 0x9E3779B97F4A7C15, 0xD2E7470EE14C6C93, 0xBB67AE8584CAA73B>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\required
The $10000^\text{th}$ consecutive invocation
a default-constructed object of type \tcode{philox4x64}
produces the value $3409172418970261260$.
\end{itemdescr}%
\indextext{random number generation!predefined engines and adaptors|)}%
\indextext{random number engine adaptor!with predefined parameters|)}%
\indextext{random number engine!with predefined parameters|)}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
%% random_device class subclause
%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


\rSec2[rand.device]{Class \tcode{random_device}}%
\indexlibraryglobal{random_device}%

\pnum
A \tcode{random_device}
uniform random bit generator
produces nondeterministic random numbers.

\pnum
If implementation limitations
prevent generating nondeterministic random numbers,
the implementation may employ a random number engine.

\indexlibraryglobal{random_device}%
\indexlibrarymember{result_type}{random_device}%
\begin{codeblock}
namespace std {
  class random_device {
  public:
    // types
    using result_type = unsigned int;

    // generator characteristics
    static constexpr result_type min() { return numeric_limits<result_type>::min(); }
    static constexpr result_type max() { return numeric_limits<result_type>::max(); }

    // constructors
    random_device() : random_device(@\textit{implementation-defined}@) {}
    explicit random_device(const string& token);

    // generating functions
    result_type operator()();

    // property functions
    double entropy() const noexcept;

    // no copy functions
    random_device(const random_device&) = delete;
    void operator=(const random_device&) = delete;
  };
}
\end{codeblock}


\indexlibraryctor{random_device}%
\begin{itemdecl}
explicit random_device(const string& token);
\end{itemdecl}

\begin{itemdescr}
\pnum
\throws
A value of an \impldef{exception type when \tcode{random_device} constructor fails} type
 derived from \tcode{exception}
 if the \tcode{random_device} cannot be initialized.

\pnum
\remarks
 The semantics of the \tcode{token} parameter
 and the token value used by the default constructor are
 \impldef{semantics of \tcode{token} parameter and default token value used by \tcode{random_device} constructors}.
\begin{footnote}
The parameter is intended
   to allow an implementation to differentiate
   between different sources of randomness.
\end{footnote}
\end{itemdescr}

\indexlibrarymember{entropy}{random_device}%
\begin{itemdecl}
double entropy() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
If the implementation employs a random number engine,
 returns $0.0$.
 Otherwise, returns an entropy estimate
\begin{footnote}
If a device has $n$ states
   whose respective probabilities are
   $P_0, \dotsc, P_{n-1}$,
   the device entropy $S$ is defined as\\
   $S = - \sum_{i=0}^{n-1} P_i \cdot \log P_i$.
\end{footnote}
 for the random numbers returned by \tcode{operator()},
 in the range
   \tcode{min()}
 to
   $\log_2( \tcode{max()}+1)$.
\end{itemdescr}

\indexlibrarymember{operator()}{random_device}%
\begin{itemdecl}
result_type operator()();
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
A nondeterministic random value,
 uniformly distributed
 between \tcode{min()} and \tcode{max()} (inclusive).
 It is \impldef{how \tcode{random_device::operator()} generates values}
 how these values are generated.

\pnum
\throws
A value of an \impldef{exception type when \tcode{random_device::operator()} fails}
 type derived from \tcode{exception}
 if a random number cannot be obtained.
\end{itemdescr}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
%% utilities subclause
%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


\rSec2[rand.util]{Utilities}%
\indextext{random number generation!utilities|(}%

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% class seed_seq:

\rSec3[rand.util.seedseq]{Class \tcode{seed_seq}}%

\indexlibraryglobal{seed_seq}%
\indexlibrarymember{result_type}{seed_seq}%
\begin{codeblock}
namespace std {
  class seed_seq {
  public:
    // types
    using result_type = uint_least32_t;

    // constructors
    seed_seq() noexcept;
    template<class T>
      seed_seq(initializer_list<T> il);
    template<class InputIterator>
      seed_seq(InputIterator begin, InputIterator end);

    // generating functions
    template<class RandomAccessIterator>
      void generate(RandomAccessIterator begin, RandomAccessIterator end);

    // property functions
    size_t size() const noexcept;
    template<class OutputIterator>
      void param(OutputIterator dest) const;

    // no copy functions
    seed_seq(const seed_seq&) = delete;
    void operator=(const seed_seq&) = delete;

  private:
    vector<result_type> v;      // \expos
  };
}
\end{codeblock}


\indexlibraryctor{seed_seq}%
\begin{itemdecl}
seed_seq() noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\ensures
\tcode{v.empty()} is \tcode{true}.
\end{itemdescr}


\indexlibraryctor{seed_seq}%
\begin{itemdecl}
template<class T>
  seed_seq(initializer_list<T> il);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{T} is an integer type.

\pnum
\effects
 Same as \tcode{seed_seq(il.begin(), il.end())}.
\end{itemdescr}


\indexlibraryctor{seed_seq}%
\begin{itemdecl}
template<class InputIterator>
  seed_seq(InputIterator begin, InputIterator end);
\end{itemdecl}

\begin{itemdescr}
\pnum
\mandates
  \tcode{iterator_traits<InputIterator>::value_type}
  is an integer type.

\pnum
\expects
  \tcode{InputIterator} meets the
  \oldconcept{InputIterator} requirements\iref{input.iterators}.

\pnum
\effects
Initializes \tcode{v}
by the following algorithm:
\begin{codeblock}
for (InputIterator s = begin; s != end; ++s)
 v.push_back((*s)@$\bmod 2^{32}$@);
\end{codeblock}%
\end{itemdescr}

\indexlibrarymember{generate}{seed_seq}%
\begin{itemdecl}
template<class RandomAccessIterator>
  void generate(RandomAccessIterator begin, RandomAccessIterator end);
\end{itemdecl}

\begin{itemdescr}
\pnum
\mandates
  \tcode{iterator_traits<RandomAccessIterator>::\brk{}value_type}
  is an unsigned integer type capable of accommodating 32-bit quantities.

\pnum
\expects
  \tcode{RandomAccessIterator} meets the
  \oldconcept{RandomAccessIterator} requirements\iref{random.access.iterators}
  and the requirements of a mutable iterator.

\pnum
\effects
 Does nothing if \tcode{begin == end}.
 Otherwise,
 with $s = \tcode{v.size()}$
 and  $n = \tcode{end} - \tcode{begin}$,
 fills the supplied range $[\tcode{begin},\tcode{end})$
 according to the following algorithm
 in which
 each operation is to be carried out modulo $2^{32}$,
 each indexing operator applied to \tcode{begin} is to be taken modulo $n$,
 and $T(x)$ is defined as $x \xor (x \rightshift 27)$:

\begin{itemize}
 \item
   By way of initialization,
   set each element of the range to the value \tcode{0x8b8b8b8b}.
   Additionally,
   for use in subsequent steps,
   let $p = (n - t) / 2$
   and let $q = p + t$,
   where
   \[%
     t = (n \ge 623) \mbox{ ? } 11 \mbox{ : } (n \ge 68) \mbox{ ? } 7 \mbox{ : } (n \ge 39) \mbox{ ? } 5 \mbox{ : } (n \ge 7) \mbox{ ? } 3 \mbox{ : } (n - 1)/2;
   \]%
 \item
   With $m$ as the larger of $s + 1$ and $n$,
   transform the elements of the range:
   iteratively for $k = 0, \dotsc, m - 1$,
   calculate values
   \begin{eqnarray*}
     r_1 & = &
       1664525 \cdot T(    \tcode{begin[}k\tcode{]}
                      \xor \tcode{begin[}k+p\tcode{]}
                      \xor \tcode{begin[}k-1 \tcode{]}
                      )
     \\
     r_2 & = & r_1 + \left\{
       \begin{array}{cl}
         s                                  & \mbox{,  } k = 0
         \\
         k \bmod n + \tcode{v[}k-1\tcode{]} & \mbox{,  } 0 < k \le s
         \\
         k \bmod n                          & \mbox{,  } s < k
       \end{array}
     \right.
   \end{eqnarray*}
   and, in order,
   increment \tcode{begin[$k+p$]} by $r_1$,
   increment \tcode{begin[$k+q$]} by $r_2$,
   and
   set \tcode{begin[$k$]} to $r_2$.
 \item
   Transform the elements of the range again,
   beginning where the previous step ended:
   iteratively for $k = m, \dotsc, m + n - 1$,
   calculate values
   \begin{eqnarray*}
     r_3 & = &
       1566083941 \cdot T( \tcode{begin[}k  \tcode{]}
                         + \tcode{begin[}k+p\tcode{]}
                         + \tcode{begin[}k-1\tcode{]}
                         )
     \\
     r_4 & = & r_3 - (k \bmod n)
   \end{eqnarray*}
   and, in order,
   \noindent
   update \tcode{begin[$k+p$]} by xoring it with $r_3$,
   update \tcode{begin[$k+q$]} by xoring it with $r_4$,
   and
   set \tcode{begin[$k$]} to $r_4$.
\end{itemize}

\pnum
\throws
What and when \tcode{RandomAccessIterator} operations of \tcode{begin}
and \tcode{end} throw.
\end{itemdescr}

\indexlibrarymember{size}{seed_seq}%
\begin{itemdecl}
size_t size() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
The number of 32-bit units
 that would be returned
 by a call to \tcode{param()}.

\pnum
\complexity
Constant time.
\end{itemdescr}

\indexlibrarymember{param}{seed_seq}%
\begin{itemdecl}
template<class OutputIterator>
  void param(OutputIterator dest) const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\mandates
  Values of type \tcode{result_type} are writable\iref{iterator.requirements.general} to \tcode{dest}.

\pnum
\expects
  \tcode{OutputIterator} meets the
  \oldconcept{OutputIterator} requirements\iref{output.iterators}.

\pnum
\effects
Copies the sequence of prepared 32-bit units
 to the given destination,
 as if by executing the following statement:
\begin{codeblock}
copy(v.begin(), v.end(), dest);
\end{codeblock}

\pnum
\throws
What and when \tcode{OutputIterator} operations of \tcode{dest} throw.
\end{itemdescr}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% generate_canonical function template:

\rSec3[rand.util.canonical]{Function template \tcode{generate_canonical}}%

\indexlibraryglobal{generate_canonical}%
\begin{itemdecl}
template<class RealType, size_t digits, class URBG>
  RealType generate_canonical(URBG& g);
\end{itemdecl}

\begin{itemdescr}
\pnum
Let
\begin{itemize}
\item $r$ be \tcode{numeric_limits<RealType>::radix},
\item $R$ be $\tcode{g.max()} - \tcode{g.min()} + 1$,
\item $d$ be the smaller of
  \tcode{digits} and \tcode{numeric_limits<RealType>::digits},
  \begin{footnote}
  $d$ is introduced to avoid any attempt
  to produce more bits of randomness
  than can be held in \tcode{RealType}.
  \end{footnote}
\item $k$ be the smallest integer such that $R^k \ge r^d$, and
\item $x$ be $\left\lfloor R^k / r^d \right\rfloor$.
\end{itemize}
An \defn{attempt} is $k$ invocations of \tcode{g()}
to obtain values $g_0, \dotsc, g_{k-1}$, respectively,
and the calculation of a quantity $S$ given by \eqref{rand.gencanonical}:
\begin{formula}{rand.gencanonical}
S = \sum_{i=0}^{k-1} (g_i - \tcode{g.min()}) \cdot R^i
\end{formula}

\pnum
\effects
Attempts are made until $S < xr^d$.
\begin{note}
When $R$ is a power of $r$, precisely one attempt is made.
\end{note}

\pnum
\returns
$\left\lfloor S / x \right\rfloor / r^d$.
\begin{note}
The return value $c$ satisfies
$0 \leq c < 1$.
\end{note}

\pnum
\throws
What and when \tcode{g} throws.

\pnum
\complexity
Exactly $k$ invocations of \tcode{g} per attempt.

\pnum
\begin{note}
If the values $g_i$ produced by \tcode{g} are uniformly distributed,
\tcode{generate_canonical}'s results are distributed as uniformly as possible.
Obtaining a value in this way
can be a useful step
in the process of transforming
a value generated by a uniform random bit generator
into a value
that can be delivered by a random number distribution.
\end{note}

\pnum
\begin{note}
When $R$ is a power of $r$,
an implementation can avoid using an arithmetic type that is wider
than the output when computing $S$.
\end{note}
\end{itemdescr}

\indextext{random number generation!utilities|)}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
%% Distribution class templates subclause
%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


\rSec2[rand.dist]{Random number distribution class templates}%
\indextext{random number generation!distributions|(}

\rSec3[rand.dist.general]{General}

\pnum
Each type instantiated
from a class template specified in \ref{rand.dist}
meets the requirements
of a random number distribution\iref{rand.req.dist} type.

\pnum
Descriptions are provided in \ref{rand.dist}
only for distribution operations
that are not described in \ref{rand.req.dist}
or for operations where there is additional semantic information.
In particular,
declarations for copy constructors,
for copy assignment operators,
for streaming operators,
and for equality and inequality operators
are not shown in the synopses.

\pnum
The algorithms for producing each
of the specified distributions are
\impldef{algorithms for producing the standard random number distributions}.

\pnum
The value of each probability density function $p(z)$
and of each discrete probability function $P(z_i)$
specified in this subclause
is $0$
everywhere outside its stated domain.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
%% Uniform distributions subclause
%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\rSec3[rand.dist.uni]{Uniform distributions}%
\indextext{uniform distributions|(}%
\indextext{random number distributions!uniform|(}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% uniform_int_distribution distribution:

\rSec4[rand.dist.uni.int]{Class template \tcode{uniform_int_distribution}}%
\indexlibraryglobal{uniform_int_distribution}%

\pnum
A \tcode{uniform_int_distribution} random number distribution
produces random integers $i$,
$a \leq i \leq b$,
distributed according to
the constant discrete probability function in \eqref{rand.dist.uni.int}.

\begin{formula}{rand.dist.uni.int}
P(i\,|\,a,b) = 1 / (b - a + 1)
\end{formula}

\indexlibraryglobal{uniform_int_distribution}%
\indexlibrarymember{result_type}{uniform_int_distribution}%
\begin{codeblock}
namespace std {
  template<class IntType = int>
  class uniform_int_distribution {
  public:
    // types
    using result_type = IntType;
    using param_type  = @\unspec@;

    // constructors and reset functions
    uniform_int_distribution() : uniform_int_distribution(0) {}
    explicit uniform_int_distribution(IntType a, IntType b = numeric_limits<IntType>::max());
    explicit uniform_int_distribution(const param_type& parm);
    void reset();

    // equality operators
    friend bool operator==(const uniform_int_distribution& x, const uniform_int_distribution& y);

    // generating functions
    template<class URBG>
      result_type operator()(URBG& g);
    template<class URBG>
      result_type operator()(URBG& g, const param_type& parm);

    // property functions
    result_type a() const;
    result_type b() const;
    param_type param() const;
    void param(const param_type& parm);
    result_type min() const;
    result_type max() const;

    // inserters and extractors
    template<class charT, class traits>
      friend basic_ostream<charT, traits>&
        operator<<(basic_ostream<charT, traits>& os,            // hosted
                   const uniform_int_distribution& x);
    template<class charT, class traits>
      friend basic_istream<charT, traits>&
        operator>>(basic_istream<charT, traits>& is,            // hosted
                   uniform_int_distribution& x);
  };
}
\end{codeblock}


\indexlibraryctor{uniform_int_distribution}%
\begin{itemdecl}
explicit uniform_int_distribution(IntType a, IntType b = numeric_limits<IntType>::max());
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
$\tcode{a} \leq \tcode{b}$.

\pnum
\remarks
 \tcode{a} and \tcode{b}
 correspond to the respective parameters of the distribution.
\end{itemdescr}

\indexlibrarymember{a}{uniform_int_distribution}%
\begin{itemdecl}
result_type a() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
The value of the \tcode{a} parameter
 with which the object was constructed.
\end{itemdescr}

\indexlibrarymember{b}{uniform_int_distribution}%
\begin{itemdecl}
result_type b() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
The value of the \tcode{b} parameter
 with which the object was constructed.
\end{itemdescr}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% uniform_real distribution:

\rSec4[rand.dist.uni.real]{Class template \tcode{uniform_real_distribution}}%
\indexlibraryglobal{uniform_real_distribution}%

\pnum
A \tcode{uniform_real_distribution} random number distribution
produces random numbers $x$,
$a \leq x < b$,
distributed according to
the constant probability density function in \eqref{rand.dist.uni.real}.
\begin{formula}{rand.dist.uni.real}
p(x\,|\,a,b) = 1 / (b - a)
\end{formula}
\begin{note}
This implies that $p(x\,|\,a,b)$ is undefined when \tcode{a == b}.
\end{note}

\indexlibraryglobal{uniform_real_distribution}%
\indexlibrarymember{result_type}{uniform_real_distribution}%
\begin{codeblock}
namespace std {
  template<class RealType = double>
  class uniform_real_distribution {
  public:
    // types
    using result_type = RealType;
    using param_type  = @\unspec@;

    // constructors and reset functions
    uniform_real_distribution() : uniform_real_distribution(0.0) {}
    explicit uniform_real_distribution(RealType a, RealType b = 1.0);
    explicit uniform_real_distribution(const param_type& parm);
    void reset();

    // equality operators
    friend bool operator==(const uniform_real_distribution& x,
                           const uniform_real_distribution& y);

    // generating functions
    template<class URBG>
      result_type operator()(URBG& g);
    template<class URBG>
      result_type operator()(URBG& g, const param_type& parm);

    // property functions
    result_type a() const;
    result_type b() const;
    param_type param() const;
    void param(const param_type& parm);
    result_type min() const;
    result_type max() const;

    // inserters and extractors
    template<class charT, class traits>
      friend basic_ostream<charT, traits>&
        operator<<(basic_ostream<charT, traits>& os, const uniform_real_distribution& x);
    template<class charT, class traits>
      friend basic_istream<charT, traits>&
        operator>>(basic_istream<charT, traits>& is, uniform_real_distribution& x);
  };
}
\end{codeblock}


\indexlibraryctor{uniform_real_distribution}%
\begin{itemdecl}
explicit uniform_real_distribution(RealType a, RealType b = 1.0);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
$\tcode{a} \leq \tcode{b}$
and
$\tcode{b} - \tcode{a} \leq \tcode{numeric_limits<RealType>::max()}$.

\pnum
\remarks
 \tcode{a} and \tcode{b}
 correspond to the respective parameters of the distribution.
\end{itemdescr}

\indexlibrarymember{a}{uniform_real_distribution}%
\begin{itemdecl}
result_type a() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
The value of the \tcode{a} parameter
 with which the object was constructed.
\end{itemdescr}

\indexlibrarymember{b}{uniform_real_distribution}%
\begin{itemdecl}
result_type b() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
The value of the \tcode{b} parameter
 with which the object was constructed.
\end{itemdescr}%
\indextext{random number distributions!uniform|)}%
\indextext{uniform distributions|)}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
%% Bernoulli distributions subclause
%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\rSec3[rand.dist.bern]{Bernoulli distributions}%
\indextext{Bernoulli distributions|(}%
\indextext{random number distributions!Bernoulli|(}%

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% bernoulli_distribution

\rSec4[rand.dist.bern.bernoulli]{Class \tcode{bernoulli_distribution}}%
\indexlibraryglobal{bernoulli_distribution}%

\pnum
A \tcode{bernoulli_distribution} random number distribution
produces \tcode{bool} values $b$
distributed according to
the discrete probability function in \eqref{rand.dist.bern.bernoulli}.
\begin{formula}{rand.dist.bern.bernoulli}
P(b\,|\,p) = \left\{ \begin{array}{ll}
                          p     & \text{ if $b = \tcode{true}$} \\
                          1 - p & \text{ if $b = \tcode{false}$}
                          \end{array}\right.
\end{formula}

\indexlibraryglobal{bernoulli_distribution}%
\indexlibrarymember{result_type}{bernoulli_distribution}%
\begin{codeblock}
namespace std {
  class bernoulli_distribution {
  public:
    // types
    using result_type = bool;
    using param_type  = @\unspec@;

    // constructors and reset functions
    bernoulli_distribution() : bernoulli_distribution(0.5) {}
    explicit bernoulli_distribution(double p);
    explicit bernoulli_distribution(const param_type& parm);
    void reset();

    // equality operators
    friend bool operator==(const bernoulli_distribution& x, const bernoulli_distribution& y);

    // generating functions
    template<class URBG>
      result_type operator()(URBG& g);
    template<class URBG>
      result_type operator()(URBG& g, const param_type& parm);

    // property functions
    double p() const;
    param_type param() const;
    void param(const param_type& parm);
    result_type min() const;
    result_type max() const;

    // inserters and extractors
    template<class charT, class traits>
      friend basic_ostream<charT, traits>&
        operator<<(basic_ostream<charT, traits>& os, const bernoulli_distribution& x);
    template<class charT, class traits>
      friend basic_istream<charT, traits>&
        operator>>(basic_istream<charT, traits>& is, bernoulli_distribution& x);
  };
}
\end{codeblock}


\indexlibraryctor{bernoulli_distribution}%
\begin{itemdecl}
explicit bernoulli_distribution(double p);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
$0 \leq \tcode{p} \leq 1$.

\pnum
\remarks
 \tcode{p}
 corresponds to the parameter of the distribution.
\end{itemdescr}

\indexlibrarymember{p}{bernoulli_distribution}%
\begin{itemdecl}
double p() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
The value of the \tcode{p} parameter
 with which the object was constructed.
\end{itemdescr}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% binomial_distribution

\rSec4[rand.dist.bern.bin]{Class template \tcode{binomial_distribution}}%
\indexlibraryglobal{binomial_distribution}%

\pnum
A \tcode{binomial_distribution} random number distribution
produces integer values $i \geq 0$
distributed according to
the discrete probability function in \eqref{rand.dist.bern.bin}.

\begin{formula}{rand.dist.bern.bin}
P(i\,|\,t,p) = \binom{t}{i} \cdot p^i \cdot (1-p)^{t-i}
\end{formula}

\indexlibraryglobal{binomial_distribution}%
\indexlibrarymember{result_type}{binomial_distribution}%
\begin{codeblock}
namespace std {
  template<class IntType = int>
  class binomial_distribution {
  public:
    // types
    using result_type = IntType;
    using param_type  = @\unspec@;

    // constructors and reset functions
    binomial_distribution() : binomial_distribution(1) {}
    explicit binomial_distribution(IntType t, double p = 0.5);
    explicit binomial_distribution(const param_type& parm);
    void reset();

    // equality operators
    friend bool operator==(const binomial_distribution& x, const binomial_distribution& y);

    // generating functions
    template<class URBG>
      result_type operator()(URBG& g);
    template<class URBG>
      result_type operator()(URBG& g, const param_type& parm);

    // property functions
    IntType t() const;
    double p() const;
    param_type param() const;
    void param(const param_type& parm);
    result_type min() const;
    result_type max() const;

    // inserters and extractors
    template<class charT, class traits>
      friend basic_ostream<charT, traits>&
        operator<<(basic_ostream<charT, traits>& os, const binomial_distribution& x);
    template<class charT, class traits>
      friend basic_istream<charT, traits>&
        operator>>(basic_istream<charT, traits>& is, binomial_distribution& x);
  };
}
\end{codeblock}


\indexlibraryctor{binomial_distribution}%
\begin{itemdecl}
explicit binomial_distribution(IntType t, double p = 0.5);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
$0 \leq \tcode{p} \leq 1$ and $0 \leq \tcode{t} $.

\pnum
\remarks
 \tcode{t} and \tcode{p}
 correspond to the respective parameters of the distribution.
\end{itemdescr}

\indexlibrarymember{t}{binomial_distribution}%
\begin{itemdecl}
IntType t() const;
\end{itemdecl}%
\begin{itemdescr}
\pnum
\returns
The value of the \tcode{t} parameter
 with which the object was constructed.
\end{itemdescr}

\indexlibrarymember{p}{binomial_distribution}%
\begin{itemdecl}
double p() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
The value of the \tcode{p} parameter
 with which the object was constructed.
\end{itemdescr}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% geometric_distribution

\rSec4[rand.dist.bern.geo]{Class template \tcode{geometric_distribution}}
\indexlibraryglobal{geometric_distribution}%

\pnum
A \tcode{geometric_distribution} random number distribution
produces integer values $i \geq 0$
distributed according to
the discrete probability function in \eqref{rand.dist.bern.geo}.
\begin{formula}{rand.dist.bern.geo}
P(i\,|\,p) = p \cdot (1-p)^{i}
\end{formula}

\indexlibraryglobal{geometric_distribution}%
\indexlibrarymember{result_type}{geometric_distribution}%
\begin{codeblock}
namespace std {
  template<class IntType = int>
  class geometric_distribution {
  public:
    // types
    using result_type = IntType;
    using param_type  = @\unspec@;

    // constructors and reset functions
    geometric_distribution() : geometric_distribution(0.5) {}
    explicit geometric_distribution(double p);
    explicit geometric_distribution(const param_type& parm);
    void reset();

    // equality operators
    friend bool operator==(const geometric_distribution& x, const geometric_distribution& y);

    // generating functions
    template<class URBG>
      result_type operator()(URBG& g);
    template<class URBG>
      result_type operator()(URBG& g, const param_type& parm);

    // property functions
    double p() const;
    param_type param() const;
    void param(const param_type& parm);
    result_type min() const;
    result_type max() const;

    // inserters and extractors
    template<class charT, class traits>
      friend basic_ostream<charT, traits>&
        operator<<(basic_ostream<charT, traits>& os, const geometric_distribution& x);
    template<class charT, class traits>
      friend basic_istream<charT, traits>&
        operator>>(basic_istream<charT, traits>& is, geometric_distribution& x);
  };
}
\end{codeblock}


\indexlibraryctor{geometric_distribution}%
\begin{itemdecl}
explicit geometric_distribution(double p);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
$0 < \tcode{p} < 1$.

\pnum
\remarks
 \tcode{p}
 corresponds to the parameter of the distribution.
\end{itemdescr}

\indexlibrarymember{p}{geometric_distribution}%
\begin{itemdecl}
double p() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
The value of the \tcode{p} parameter
 with which the object was constructed.
\end{itemdescr}

% ----------------------------------------------------------------------
% Class template negative_binomial_distribution
% ----------------------------------------------------------------------

\rSec4[rand.dist.bern.negbin]{Class template \tcode{negative_binomial_distribution}}
\indexlibraryglobal{negative_binomial_distribution}%

\pnum
A \tcode{negative_binomial_distribution} random number distribution
produces random integers $i \geq 0$
distributed according to
the discrete probability function in \eqref{rand.dist.bern.negbin}.
\begin{formula}{rand.dist.bern.negbin}
P(i\,|\,k,p) = \binom{k+i-1}{i} \cdot p^k \cdot (1-p)^i
\end{formula}
\begin{note}
This implies that $P(i\,|\,k,p)$ is undefined when \tcode{p == 1}.
\end{note}

\indexlibraryglobal{negative_binomial_distribution}%
\indexlibrarymember{result_type}{negative_binomial_distribution}%
\begin{codeblock}
namespace std {
  template<class IntType = int>
  class negative_binomial_distribution {
  public:
    // types
    using result_type = IntType;
    using param_type  = @\unspec@;

    // constructor and reset functions
    negative_binomial_distribution() : negative_binomial_distribution(1) {}
    explicit negative_binomial_distribution(IntType k, double p = 0.5);
    explicit negative_binomial_distribution(const param_type& parm);
    void reset();

    // equality operators
    friend bool operator==(const negative_binomial_distribution& x,
                           const negative_binomial_distribution& y);

    // generating functions
    template<class URBG>
      result_type operator()(URBG& g);
    template<class URBG>
      result_type operator()(URBG& g, const param_type& parm);

    // property functions
    IntType k() const;
    double p() const;
    param_type param() const;
    void param(const param_type& parm);
    result_type min() const;
    result_type max() const;

    // inserters and extractors
    template<class charT, class traits>
      friend basic_ostream<charT, traits>&
        operator<<(basic_ostream<charT, traits>& os, const negative_binomial_distribution& x);
    template<class charT, class traits>
      friend basic_istream<charT, traits>&
        operator>>(basic_istream<charT, traits>& is, negative_binomial_distribution& x);
  };
}
\end{codeblock}


\indexlibraryctor{negative_binomial_distribution}%
\begin{itemdecl}
explicit negative_binomial_distribution(IntType k, double p = 0.5);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
$0 < \tcode{p} \leq 1$
and $0 < \tcode{k} $.

\pnum
\remarks
 \tcode{k} and \tcode{p}
 correspond to the respective parameters of the distribution.
\end{itemdescr}

\indexlibrarymember{k}{negative_binomial_distribution}%
\begin{itemdecl}
IntType k() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
The value of the \tcode{k} parameter
 with which the object was constructed.
\end{itemdescr}

\indexlibrarymember{p}{negative_binomial_distribution}%
\begin{itemdecl}
double p() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
The value of the \tcode{p} parameter
 with which the object was constructed.
\end{itemdescr}%
\indextext{random number distributions!Bernoulli|)}%
\indextext{Bernoulli distributions|)}%


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
%% Poisson distributions subclause
%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\rSec3[rand.dist.pois]{Poisson distributions}%
\indextext{Poisson distributions|(}%
\indextext{random number distributions!Poisson|(}%

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% poisson_distribution

\rSec4[rand.dist.pois.poisson]{Class template \tcode{poisson_distribution}}%
\indexlibraryglobal{poisson_distribution}%

\pnum
A \tcode{poisson_distribution} random number distribution
produces integer values $i \geq 0$
distributed according to
the discrete probability function in \eqref{rand.dist.pois.poisson}.
\begin{formula}{rand.dist.pois.poisson}
P(i\,|\,\mu) = \frac{e^{-\mu} \mu^{i}}{i\,!}
\end{formula}
The distribution parameter $\mu$
is also known as this distribution's \term{mean}.

\indexlibraryglobal{poisson_distribution}%
\indexlibrarymember{result_type}{poisson_distribution}%
\begin{codeblock}
namespace std {
  template<class IntType = int>
  class poisson_distribution {
  public:
    // types
    using result_type = IntType;
    using param_type  = @\unspec@;

    // constructors and reset functions
    poisson_distribution() : poisson_distribution(1.0) {}
    explicit poisson_distribution(double mean);
    explicit poisson_distribution(const param_type& parm);
    void reset();

    // equality operators
    friend bool operator==(const poisson_distribution& x, const poisson_distribution& y);

    // generating functions
    template<class URBG>
      result_type operator()(URBG& g);
    template<class URBG>
      result_type operator()(URBG& g, const param_type& parm);

    // property functions
    double mean() const;
    param_type param() const;
    void param(const param_type& parm);
    result_type min() const;
    result_type max() const;

    // inserters and extractors
    template<class charT, class traits>
      friend basic_ostream<charT, traits>&
        operator<<(basic_ostream<charT, traits>& os, const poisson_distribution& x);
    template<class charT, class traits>
      friend basic_istream<charT, traits>&
        operator>>(basic_istream<charT, traits>& is, poisson_distribution& x);
  };
}
\end{codeblock}

\indexlibraryctor{poisson_distribution}%
\begin{itemdecl}
explicit poisson_distribution(double mean);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
$0 < \tcode{mean}$.

\pnum
\remarks
\tcode{mean} corresponds to the parameter of the distribution.
\end{itemdescr}

\indexlibrarymember{mean}{poisson_distribution}%
\begin{itemdecl}
double mean() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
The value of the \tcode{mean} parameter
 with which the object was constructed.
\end{itemdescr}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% exponential_distribution

\rSec4[rand.dist.pois.exp]{Class template \tcode{exponential_distribution}}%
\indexlibraryglobal{exponential_distribution}%

\pnum
An \tcode{exponential_distribution} random number distribution
produces random numbers $x > 0$
distributed according to
the probability density function in \eqref{rand.dist.pois.exp}.
\begin{formula}{rand.dist.pois.exp}
p(x\,|\,\lambda) = \lambda e^{-\lambda x}
\end{formula}

\indexlibraryglobal{exponential_distribution}%
\indexlibrarymember{result_type}{exponential_distribution}%
\begin{codeblock}
namespace std {
  template<class RealType = double>
  class exponential_distribution {
  public:
    // types
    using result_type = RealType;
    using param_type  = @\unspec@;

    // constructors and reset functions
    exponential_distribution() : exponential_distribution(1.0) {}
    explicit exponential_distribution(RealType lambda);
    explicit exponential_distribution(const param_type& parm);
    void reset();

    // equality operators
    friend bool operator==(const exponential_distribution& x, const exponential_distribution& y);

    // generating functions
    template<class URBG>
      result_type operator()(URBG& g);
    template<class URBG>
      result_type operator()(URBG& g, const param_type& parm);

    // property functions
    RealType lambda() const;
    param_type param() const;
    void param(const param_type& parm);
    result_type min() const;
    result_type max() const;

    // inserters and extractors
    template<class charT, class traits>
      friend basic_ostream<charT, traits>&
        operator<<(basic_ostream<charT, traits>& os, const exponential_distribution& x);
    template<class charT, class traits>
      friend basic_istream<charT, traits>&
        operator>>(basic_istream<charT, traits>& is, exponential_distribution& x);
  };
}
\end{codeblock}


\indexlibraryctor{exponential_distribution}%
\begin{itemdecl}
explicit exponential_distribution(RealType lambda);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
$0 < \tcode{lambda}$.

\pnum
\remarks
\tcode{lambda} corresponds to the parameter of the distribution.
\end{itemdescr}

\indexlibrarymember{lambda}{exponential_distribution}%
\begin{itemdecl}
RealType lambda() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
The value of the \tcode{lambda} parameter
 with which the object was constructed.
\end{itemdescr}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% gamma_distribution

\rSec4[rand.dist.pois.gamma]{Class template \tcode{gamma_distribution}}%
\indexlibraryglobal{gamma_distribution}%

\pnum
A \tcode{gamma_distribution} random number distribution
produces random numbers $x > 0$
distributed according to
the probability density function in \eqref{rand.dist.pois.gamma}.
\begin{formula}{rand.dist.pois.gamma}
p(x\,|\,\alpha,\beta) =
     \frac{e^{-x/\beta}}{\beta^{\alpha} \cdot \Gamma(\alpha)} \, \cdot \, x^{\, \alpha-1}
\end{formula}

\indexlibraryglobal{gamma_distribution}%
\indexlibrarymember{result_type}{gamma_distribution}%
\begin{codeblock}
namespace std {
  template<class RealType = double>
  class gamma_distribution {
  public:
    // types
    using result_type = RealType;
    using param_type  = @\unspec@;

    // constructors and reset functions
    gamma_distribution() : gamma_distribution(1.0) {}
    explicit gamma_distribution(RealType alpha, RealType beta = 1.0);
    explicit gamma_distribution(const param_type& parm);
    void reset();

    // equality operators
    friend bool operator==(const gamma_distribution& x, const gamma_distribution& y);

    // generating functions
    template<class URBG>
      result_type operator()(URBG& g);
    template<class URBG>
      result_type operator()(URBG& g, const param_type& parm);

    // property functions
    RealType alpha() const;
    RealType beta() const;
    param_type param() const;
    void param(const param_type& parm);
    result_type min() const;
    result_type max() const;

    // inserters and extractors
    template<class charT, class traits>
      friend basic_ostream<charT, traits>&
        operator<<(basic_ostream<charT, traits>& os, const gamma_distribution& x);
    template<class charT, class traits>
      friend basic_istream<charT, traits>&
        operator>>(basic_istream<charT, traits>& is, gamma_distribution& x);
  };
}
\end{codeblock}


\indexlibraryctor{gamma_distribution}%
\begin{itemdecl}
explicit gamma_distribution(RealType alpha, RealType beta = 1.0);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
$0 < \tcode{alpha}$ and $0 < \tcode{beta}$.

\pnum
\remarks
\tcode{alpha} and \tcode{beta}
correspond to the parameters of the distribution.
\end{itemdescr}

\indexlibrarymember{alpha}{gamma_distribution}%
\begin{itemdecl}
RealType alpha() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
The value of the \tcode{alpha} parameter
 with which the object was constructed.
\end{itemdescr}

\indexlibrarymember{beta}{gamma_distribution}%
\begin{itemdecl}
RealType beta() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
The value of the \tcode{beta} parameter
 with which the object was constructed.
\end{itemdescr}

% ----------------------------------------------------------------------
% Class template weibull_distribution
% ----------------------------------------------------------------------

\rSec4[rand.dist.pois.weibull]{Class template \tcode{weibull_distribution}}%
\indexlibraryglobal{weibull_distribution}%

\pnum
A \tcode{weibull_distribution} random number distribution
produces random numbers $x \geq 0$
distributed according to
the probability density function in \eqref{rand.dist.pois.weibull}.
\begin{formula}{rand.dist.pois.weibull}
p(x\,|\,a,b) = \frac{a}{b}
     \cdot \left(\frac{x}{b}\right)^{a-1}
     \cdot \, \exp\left( -\left(\frac{x}{b}\right)^a\right)
\end{formula}

\indexlibraryglobal{weibull_distribution}%
\indexlibrarymember{result_type}{weibull_distribution}%
\begin{codeblock}
namespace std {
  template<class RealType = double>
  class weibull_distribution {
  public:
    // types
    using result_type = RealType;
    using param_type  = @\unspec@;

    // constructor and reset functions
    weibull_distribution() : weibull_distribution(1.0) {}
    explicit weibull_distribution(RealType a, RealType b = 1.0);
    explicit weibull_distribution(const param_type& parm);
    void reset();

    // equality operators
    friend bool operator==(const weibull_distribution& x, const weibull_distribution& y);

    // generating functions
    template<class URBG>
      result_type operator()(URBG& g);
    template<class URBG>
      result_type operator()(URBG& g, const param_type& parm);

    // property functions
    RealType a() const;
    RealType b() const;
    param_type param() const;
    void param(const param_type& parm);
    result_type min() const;
    result_type max() const;

    // inserters and extractors
    template<class charT, class traits>
      friend basic_ostream<charT, traits>&
        operator<<(basic_ostream<charT, traits>& os, const weibull_distribution& x);
    template<class charT, class traits>
      friend basic_istream<charT, traits>&
        operator>>(basic_istream<charT, traits>& is, weibull_distribution& x);
  };
}
\end{codeblock}

\indexlibraryctor{weibull_distribution}%
\begin{itemdecl}
explicit weibull_distribution(RealType a, RealType b = 1.0);
\end{itemdecl}%

\begin{itemdescr}
\pnum
\expects
$0 < \tcode{a}$ and $0 < \tcode{b}$.

\pnum
\remarks
\tcode{a} and \tcode{b}
correspond to the respective parameters of the distribution.
\end{itemdescr}

\indexlibrarymember{a}{weibull_distribution}%
\begin{itemdecl}
RealType a() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
The value of the \tcode{a} parameter
 with which the object was constructed.
\end{itemdescr}

\indexlibrarymember{b}{weibull_distribution}%
\begin{itemdecl}
RealType b() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
The value of the \tcode{b} parameter
 with which the object was constructed.
\end{itemdescr}

% ----------------------------------------------------------------------
% Class template extreme_value_distribution
% ----------------------------------------------------------------------

\rSec4[rand.dist.pois.extreme]{Class template \tcode{extreme_value_distribution}}
\indexlibraryglobal{extreme_value_distribution}%

\pnum
An \tcode{extreme_value_distribution} random number distribution
produces random numbers $x$
distributed according to
the probability density function in \eqref{rand.dist.pois.extreme}.
\begin{footnote}
The distribution corresponding to
 this probability density function
 is also known
 (with a possible change of variable)
 as the Gumbel Type I,
 the log-Weibull,
 or the Fisher-Tippett Type I
 distribution.
\end{footnote}
\begin{formula}{rand.dist.pois.extreme}
p(x\,|\,a,b) = \frac{1}{b}
     \cdot \exp\left(\frac{a-x}{b} - \exp\left(\frac{a-x}{b}\right)\right)
\end{formula}

\indexlibraryglobal{extreme_value_distribution}%
\indexlibrarymember{result_type}{extreme_value_distribution}%
\begin{codeblock}
namespace std {
  template<class RealType = double>
  class extreme_value_distribution {
  public:
    // types
    using result_type = RealType;
    using param_type  = @\unspec@;

    // constructor and reset functions
    extreme_value_distribution() : extreme_value_distribution(0.0) {}
    explicit extreme_value_distribution(RealType a, RealType b = 1.0);
    explicit extreme_value_distribution(const param_type& parm);
    void reset();

    // equality operators
    friend bool operator==(const extreme_value_distribution& x,
                           const extreme_value_distribution& y);

    // generating functions
    template<class URBG>
      result_type operator()(URBG& g);
    template<class URBG>
      result_type operator()(URBG& g, const param_type& parm);

    // property functions
    RealType a() const;
    RealType b() const;
    param_type param() const;
    void param(const param_type& parm);
    result_type min() const;
    result_type max() const;

    // inserters and extractors
    template<class charT, class traits>
      friend basic_ostream<charT, traits>&
        operator<<(basic_ostream<charT, traits>& os, const extreme_value_distribution& x);
    template<class charT, class traits>
      friend basic_istream<charT, traits>&
        operator>>(basic_istream<charT, traits>& is, extreme_value_distribution& x);
  };
}
\end{codeblock}


\indexlibraryctor{extreme_value_distribution}%
\begin{itemdecl}
explicit extreme_value_distribution(RealType a, RealType b = 1.0);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
$0 < \tcode{b}$.

\pnum
\remarks
\tcode{a} and \tcode{b}
correspond to the respective parameters of the distribution.
\end{itemdescr}

\indexlibrarymember{a}{extreme_value_distribution}%
\begin{itemdecl}
RealType a() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
The value of the \tcode{a} parameter
 with which the object was constructed.
\end{itemdescr}

\indexlibrarymember{b}{extreme_value_distribution}%
\begin{itemdecl}
RealType b() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
The value of the \tcode{b} parameter
 with which the object was constructed.
\end{itemdescr}%
\indextext{random number distributions!Poisson|)}%
\indextext{Poisson distributions|)}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
%% Normal distributions subclause
%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\rSec3[rand.dist.norm]{Normal distributions}%
\indextext{normal distributions|(}%
\indextext{random number distributions!normal|(}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% normal_distribution

\rSec4[rand.dist.norm.normal]{Class template \tcode{normal_distribution}}%
\indexlibraryglobal{normal_distribution}%

\pnum
A \tcode{normal_distribution} random number distribution
produces random numbers $x$
distributed according to
the probability density function in \eqref{rand.dist.norm.normal}.
\begin{formula}{rand.dist.norm.normal}
 p(x\,|\,\mu,\sigma)
      = \frac{1}{\sigma \sqrt{2\pi}}
        \cdot
        % e^{-(x-\mu)^2 / (2\sigma^2)}
        \exp{\left(- \, \frac{(x - \mu)^2}
                             {2 \sigma^2}
             \right)
            }
\end{formula}
The distribution parameters $\mu$ and $\sigma$
are also known as this distribution's \term{mean}
and \term{standard deviation}.

\indexlibraryglobal{normal_distribution}%
\indexlibrarymember{result_type}{normal_distribution}%
\begin{codeblock}
namespace std {
  template<class RealType = double>
  class normal_distribution {
  public:
    // types
    using result_type = RealType;
    using param_type  = @\unspec@;

    // constructors and reset functions
    normal_distribution() : normal_distribution(0.0) {}
    explicit normal_distribution(RealType mean, RealType stddev = 1.0);
    explicit normal_distribution(const param_type& parm);
    void reset();

    // equality operators
    friend bool operator==(const normal_distribution& x, const normal_distribution& y);

    // generating functions
    template<class URBG>
      result_type operator()(URBG& g);
    template<class URBG>
      result_type operator()(URBG& g, const param_type& parm);

    // property functions
    RealType mean() const;
    RealType stddev() const;
    param_type param() const;
    void param(const param_type& parm);
    result_type min() const;
    result_type max() const;

    // inserters and extractors
    template<class charT, class traits>
      friend basic_ostream<charT, traits>&
        operator<<(basic_ostream<charT, traits>& os, const normal_distribution& x);
    template<class charT, class traits>
      friend basic_istream<charT, traits>&
        operator>>(basic_istream<charT, traits>& is, normal_distribution& x);
  };
}
\end{codeblock}


\indexlibraryctor{normal_distribution}%
\begin{itemdecl}
explicit normal_distribution(RealType mean, RealType stddev = 1.0);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
$0 < \tcode{stddev}$.

\pnum
\remarks
\tcode{mean} and \tcode{stddev}
correspond to the respective parameters of the distribution.
\end{itemdescr}

\indexlibrarymember{mean}{normal_distribution}%
\begin{itemdecl}
RealType mean() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
The value of the \tcode{mean} parameter
 with which the object was constructed.
\end{itemdescr}

\indexlibrarymember{stddev}{normal_distribution}%
\begin{itemdecl}
RealType stddev() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
The value of the \tcode{stddev} parameter
 with which the object was constructed.
\end{itemdescr}

% ----------------------------------------------------------------------
% Class template lognormal_distribution
% ----------------------------------------------------------------------

\rSec4[rand.dist.norm.lognormal]{Class template \tcode{lognormal_distribution}}%
\indexlibraryglobal{lognormal_distribution}%

\pnum
A \tcode{lognormal_distribution} random number distribution
produces random numbers $x > 0$
distributed according to
the probability density function in \eqref{rand.dist.norm.lognormal}.
\begin{formula}{rand.dist.norm.lognormal}
p(x\,|\,m,s) = \frac{1}{s x \sqrt{2 \pi}}
     \cdot \exp{\left(-\frac{(\ln{x} - m)^2}{2 s^2}\right)}
\end{formula}

\indexlibraryglobal{lognormal_distribution}%
\indexlibrarymember{result_type}{lognormal_distribution}%
\begin{codeblock}
namespace std {
  template<class RealType = double>
  class lognormal_distribution {
  public:
    // types
    using result_type = RealType;
    using param_type  = @\unspec@;

    // constructor and reset functions
    lognormal_distribution() : lognormal_distribution(0.0) {}
    explicit lognormal_distribution(RealType m, RealType s = 1.0);
    explicit lognormal_distribution(const param_type& parm);
    void reset();

    // equality operators
    friend bool operator==(const lognormal_distribution& x, const lognormal_distribution& y);

    // generating functions
    template<class URBG>
      result_type operator()(URBG& g);
    template<class URBG>
      result_type operator()(URBG& g, const param_type& parm);

    // property functions
    RealType m() const;
    RealType s() const;
    param_type param() const;
    void param(const param_type& parm);
    result_type min() const;
    result_type max() const;

    // inserters and extractors
    template<class charT, class traits>
      friend basic_ostream<charT, traits>&
        operator<<(basic_ostream<charT, traits>& os, const lognormal_distribution& x);
    template<class charT, class traits>
      friend basic_istream<charT, traits>&
        operator>>(basic_istream<charT, traits>& is, lognormal_distribution& x);
  };
}
\end{codeblock}


\indexlibraryctor{lognormal_distribution}%
\begin{itemdecl}
explicit lognormal_distribution(RealType m, RealType s = 1.0);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
$0 < \tcode{s}$.

\pnum
\remarks
\tcode{m} and \tcode{s}
correspond to the respective parameters of the distribution.
\end{itemdescr}

\indexlibrarymember{m}{lognormal_distribution}%
\begin{itemdecl}
RealType m() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
The value of the \tcode{m} parameter
 with which the object was constructed.
\end{itemdescr}

\indexlibrarymember{s}{lognormal_distribution}%
\begin{itemdecl}
RealType s() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
The value of the \tcode{s} parameter
 with which the object was constructed.
\end{itemdescr}

% ----------------------------------------------------------------------
% Class template chi_squared_distribution
% ----------------------------------------------------------------------

\rSec4[rand.dist.norm.chisq]{Class template \tcode{chi_squared_distribution}}%
\indexlibraryglobal{chi_squared_distribution}%

\pnum
A \tcode{chi_squared_distribution} random number distribution
produces random numbers $x > 0$
distributed according to
the probability density function in \eqref{rand.dist.norm.chisq}.
\begin{formula}{rand.dist.norm.chisq}
p(x\,|\,n) = \frac{x^{(n/2)-1} \cdot e^{-x/2}}{\Gamma(n/2) \cdot 2^{n/2}}
\end{formula}

\indexlibraryglobal{chi_squared_distribution}%
\indexlibrarymember{result_type}{chi_squared_distribution}%
\begin{codeblock}
namespace std {
  template<class RealType = double>
  class chi_squared_distribution {
  public:
    // types
    using result_type = RealType;
    using param_type  = @\unspec@;

    // constructor and reset functions
    chi_squared_distribution() : chi_squared_distribution(1.0) {}
    explicit chi_squared_distribution(RealType n);
    explicit chi_squared_distribution(const param_type& parm);
    void reset();

    // equality operators
    friend bool operator==(const chi_squared_distribution& x, const chi_squared_distribution& y);

    // generating functions
    template<class URBG>
      result_type operator()(URBG& g);
    template<class URBG>
      result_type operator()(URBG& g, const param_type& parm);

    // property functions
    RealType n() const;
    param_type param() const;
    void param(const param_type& parm);
    result_type min() const;
    result_type max() const;

    // inserters and extractors
    template<class charT, class traits>
      friend basic_ostream<charT, traits>&
        operator<<(basic_ostream<charT, traits>& os, const chi_squared_distribution& x);
    template<class charT, class traits>
      friend basic_istream<charT, traits>&
        operator>>(basic_istream<charT, traits>& is, chi_squared_distribution& x);
  };
}
\end{codeblock}


\indexlibraryctor{chi_squared_distribution}%
\begin{itemdecl}
explicit chi_squared_distribution(RealType n);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
$0 < \tcode{n}$.

\pnum
\remarks
\tcode{n} corresponds to the parameter of the distribution.
\end{itemdescr}

\indexlibrarymember{n}{chi_squared_distribution}%
\begin{itemdecl}
RealType n() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
The value of the \tcode{n} parameter
 with which the object was constructed.
\end{itemdescr}

% ----------------------------------------------------------------------
% Class template cauchy_distribution
% ----------------------------------------------------------------------

\rSec4[rand.dist.norm.cauchy]{Class template \tcode{cauchy_distribution}}%
\indexlibraryglobal{cauchy_distribution}%

\pnum
A \tcode{cauchy_distribution} random number distribution
produces random numbers $x$
distributed according to
the probability density function in \eqref{rand.dist.norm.cauchy}.
\begin{formula}{rand.dist.norm.cauchy}
p(x\,|\,a,b) = \left(\pi b \left(1 + \left(\frac{x-a}{b} \right)^2 \, \right)\right)^{-1}
\end{formula}

\indexlibraryglobal{cauchy_distribution}%
\indexlibrarymember{result_type}{cauchy_distribution}%
\begin{codeblock}
namespace std {
  template<class RealType = double>
  class cauchy_distribution {
  public:
    // types
    using result_type = RealType;
    using param_type  = @\unspec@;

    // constructor and reset functions
    cauchy_distribution() : cauchy_distribution(0.0) {}
    explicit cauchy_distribution(RealType a, RealType b = 1.0);
    explicit cauchy_distribution(const param_type& parm);
    void reset();

    // equality operators
    friend bool operator==(const cauchy_distribution& x, const cauchy_distribution& y);

    // generating functions
    template<class URBG>
      result_type operator()(URBG& g);
    template<class URBG>
      result_type operator()(URBG& g, const param_type& parm);

    // property functions
    RealType a() const;
    RealType b() const;
    param_type param() const;
    void param(const param_type& parm);
    result_type min() const;
    result_type max() const;

    // inserters and extractors
    template<class charT, class traits>
      friend basic_ostream<charT, traits>&
        operator<<(basic_ostream<charT, traits>& os, const cauchy_distribution& x);
    template<class charT, class traits>
      friend basic_istream<charT, traits>&
        operator>>(basic_istream<charT, traits>& is, cauchy_distribution& x);
  };
}
\end{codeblock}


\indexlibraryctor{cauchy_distribution}%
\begin{itemdecl}
explicit cauchy_distribution(RealType a, RealType b = 1.0);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
$0 < \tcode{b}$.

\pnum
\remarks
\tcode{a} and \tcode{b}
correspond to the respective parameters of the distribution.
\end{itemdescr}

\indexlibrarymember{a}{cauchy_distribution}%
\begin{itemdecl}
RealType a() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
The value of the \tcode{a} parameter
 with which the object was constructed.
\end{itemdescr}

\indexlibrarymember{b}{cauchy_distribution}%
\begin{itemdecl}
RealType b() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
The value of the \tcode{b} parameter
 with which the object was constructed.
\end{itemdescr}

% ----------------------------------------------------------------------
% Class template fisher_f_distribution
% ----------------------------------------------------------------------

\rSec4[rand.dist.norm.f]{Class template \tcode{fisher_f_distribution}}%
\indexlibraryglobal{fisher_f_distribution}%

\pnum
A \tcode{fisher_f_distribution} random number distribution
produces random numbers $x \ge 0$
distributed according to
the probability density function in \eqref{rand.dist.norm.f}.
\begin{formula}{rand.dist.norm.f}
p(x\,|\,m,n) = \frac{\Gamma\big((m+n)/2\big)}{\Gamma(m/2) \; \Gamma(n/2)}
     \cdot \left(\frac{m}{n}\right)^{m/2}
     \cdot x^{(m/2)-1}
     \cdot \left(1 + \frac{m x}{n}\right)^{-(m + n)/2}
\end{formula}

\indexlibraryglobal{fisher_f_distribution}%
\indexlibrarymember{result_type}{fisher_f_distribution}%
\begin{codeblock}
namespace std {
  template<class RealType = double>
  class fisher_f_distribution {
  public:
    // types
    using result_type = RealType;
    using param_type  = @\unspec@;

    // constructor and reset functions
    fisher_f_distribution() : fisher_f_distribution(1.0) {}
    explicit fisher_f_distribution(RealType m, RealType n = 1.0);
    explicit fisher_f_distribution(const param_type& parm);
    void reset();

    // equality operators
    friend bool operator==(const fisher_f_distribution& x, const fisher_f_distribution& y);

    // generating functions
    template<class URBG>
      result_type operator()(URBG& g);
    template<class URBG>
      result_type operator()(URBG& g, const param_type& parm);

    // property functions
    RealType m() const;
    RealType n() const;
    param_type param() const;
    void param(const param_type& parm);
    result_type min() const;
    result_type max() const;

    // inserters and extractors
    template<class charT, class traits>
      friend basic_ostream<charT, traits>&
        operator<<(basic_ostream<charT, traits>& os, const fisher_f_distribution& x);
    template<class charT, class traits>
      friend basic_istream<charT, traits>&
        operator>>(basic_istream<charT, traits>& is, fisher_f_distribution& x);
  };
}
\end{codeblock}


\indexlibraryctor{fisher_f_distribution}%
\begin{itemdecl}
explicit fisher_f_distribution(RealType m, RealType n = 1);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
$0 < \tcode{m}$ and $0 < \tcode{n}$.

\pnum
\remarks
\tcode{m} and \tcode{n}
correspond to the respective parameters of the distribution.
\end{itemdescr}

\indexlibrarymember{m}{fisher_f_distribution}%
\begin{itemdecl}
RealType m() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
The value of the \tcode{m} parameter
 with which the object was constructed.
\end{itemdescr}

\indexlibrarymember{n}{fisher_f_distribution}%
\begin{itemdecl}
RealType n() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
The value of the \tcode{n} parameter
 with which the object was constructed.
\end{itemdescr}

% ----------------------------------------------------------------------
% Class template student_t_distribution
% ----------------------------------------------------------------------

\rSec4[rand.dist.norm.t]{Class template \tcode{student_t_distribution}}%
\indexlibraryglobal{student_t_distribution}%

\pnum
A \tcode{student_t_distribution} random number distribution
produces random numbers $x$
distributed according to
the probability density function in \eqref{rand.dist.norm.t}.
\begin{formula}{rand.dist.norm.t}
p(x\,|\,n) = \frac{1}{\sqrt{n \pi}}
     \cdot \frac{\Gamma\big((n+1)/2\big)}{\Gamma(n/2)}
     \cdot \left(1 + \frac{x^2}{n} \right)^{-(n+1)/2}
\end{formula}

\indexlibraryglobal{student_t_distribution}%
\indexlibrarymember{result_type}{student_t_distribution}%
\begin{codeblock}
namespace std {
  template<class RealType = double>
  class student_t_distribution {
  public:
    // types
    using result_type = RealType;
    using param_type  = @\unspec@;

    // constructor and reset functions
    student_t_distribution() : student_t_distribution(1.0) {}
    explicit student_t_distribution(RealType n);
    explicit student_t_distribution(const param_type& parm);
    void reset();

    // equality operators
    friend bool operator==(const student_t_distribution& x, const student_t_distribution& y);

    // generating functions
    template<class URBG>
      result_type operator()(URBG& g);
    template<class URBG>
      result_type operator()(URBG& g, const param_type& parm);

    // property functions
    RealType n() const;
    param_type param() const;
    void param(const param_type& parm);
    result_type min() const;
    result_type max() const;

    // inserters and extractors
    template<class charT, class traits>
      friend basic_ostream<charT, traits>&
        operator<<(basic_ostream<charT, traits>& os, const student_t_distribution& x);
    template<class charT, class traits>
      friend basic_istream<charT, traits>&
        operator>>(basic_istream<charT, traits>& is, student_t_distribution& x);
  };
}
\end{codeblock}


\indexlibraryctor{student_t_distribution}%
\begin{itemdecl}
explicit student_t_distribution(RealType n);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
$0 < \tcode{n}$.

\pnum
\remarks
\tcode{n} corresponds to the parameter of the distribution.
\end{itemdescr}

\indexlibrarymember{mean}{student_t_distribution}%
\begin{itemdecl}
RealType n() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
The value of the \tcode{n} parameter
 with which the object was constructed.
\end{itemdescr}%
\indextext{random number distributions!normal|)}%
\indextext{normal distributions|)}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
%% Sampling distributions subclause
%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\rSec3[rand.dist.samp]{Sampling distributions}%
\indextext{sampling distributions|(}%
\indextext{random number distributions!sampling|(}


% ----------------------------------------------------------------------
% Class template discrete_distribution
% ----------------------------------------------------------------------

\rSec4[rand.dist.samp.discrete]{Class template \tcode{discrete_distribution}}%
\indexlibraryglobal{discrete_distribution}%

\pnum
A \tcode{discrete_distribution} random number distribution
produces random integers $i$, $0 \leq i < n$,
distributed according to
the discrete probability function in \eqref{rand.dist.samp.discrete}.
\begin{formula}{rand.dist.samp.discrete}
P(i \,|\, p_0, \dotsc, p_{n-1}) = p_i
\end{formula}

\pnum
Unless specified otherwise,
the distribution parameters are calculated as:
$p_k = {w_k / S}$ for $k = 0, \dotsc, n - 1$,
in which the values $w_k$,
commonly known as the \term{weights}%
, shall be non-negative, non-NaN, and non-infinity.
Moreover, the following relation shall hold:
$0 < S = w_0 + \dotsb + w_{n - 1}$.

\indexlibraryglobal{discrete_distribution}%
\indexlibrarymember{result_type}{discrete_distribution}%
\begin{codeblock}
namespace std {
  template<class IntType = int>
  class discrete_distribution {
  public:
    // types
    using result_type = IntType;
    using param_type  = @\unspec@;

    // constructor and reset functions
    discrete_distribution();
    template<class InputIterator>
      discrete_distribution(InputIterator firstW, InputIterator lastW);
    discrete_distribution(initializer_list<double> wl);
    template<class UnaryOperation>
      discrete_distribution(size_t nw, double xmin, double xmax, UnaryOperation fw);
    explicit discrete_distribution(const param_type& parm);
    void reset();

    // equality operators
    friend bool operator==(const discrete_distribution& x, const discrete_distribution& y);

    // generating functions
    template<class URBG>
      result_type operator()(URBG& g);
    template<class URBG>
      result_type operator()(URBG& g, const param_type& parm);

    // property functions
    vector<double> probabilities() const;
    param_type param() const;
    void param(const param_type& parm);
    result_type min() const;
    result_type max() const;

    // inserters and extractors
    template<class charT, class traits>
      friend basic_ostream<charT, traits>&
        operator<<(basic_ostream<charT, traits>& os, const discrete_distribution& x);
    template<class charT, class traits>
      friend basic_istream<charT, traits>&
        operator>>(basic_istream<charT, traits>& is, discrete_distribution& x);
  };
}
\end{codeblock}

\indexlibraryctor{discrete_distribution}
\begin{itemdecl}
discrete_distribution();
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Constructs a \tcode{discrete_distribution} object
with $n = 1$ and $p_0 = 1$.
\begin{note}
Such an object will always deliver the value $0$.
\end{note}
\end{itemdescr}


\indexlibraryctor{discrete_distribution}%
\begin{itemdecl}
template<class InputIterator>
  discrete_distribution(InputIterator firstW, InputIterator lastW);
\end{itemdecl}

\begin{itemdescr}
\pnum
\mandates
\tcode{is_convertible_v<iterator_traits<InputIterator>::value_type,
double>} is \tcode{true}.

\pnum
\expects
  \tcode{InputIterator} meets the
  \oldconcept{InputIterator} requirements\iref{input.iterators}.
 If \tcode{firstW == lastW},
 let $n = 1$ and $w_0 = 1$.
 Otherwise,
 $\bigl[\tcode{firstW}, \tcode{lastW}\bigr)$
 forms a sequence $w$ of length $n > 0$.

\pnum
\effects
Constructs a \tcode{discrete_distribution} object
with probabilities given by the \eqref{rand.dist.samp.discrete}.
\end{itemdescr}


\indexlibraryctor{discrete_distribution}%
\begin{itemdecl}
discrete_distribution(initializer_list<double> wl);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
 Same as \tcode{discrete_distribution(wl.begin(), wl.end())}.
\end{itemdescr}

\indexlibraryctor{discrete_distribution}
\begin{itemdecl}
template<class UnaryOperation>
  discrete_distribution(size_t nw, double xmin, double xmax, UnaryOperation fw);
\end{itemdecl}

\begin{itemdescr}
\pnum
\mandates
\tcode{is_invocable_r_v<double, UnaryOperation\&, double>} is \tcode{true}.

\pnum
\expects
 If $\tcode{nw} = 0$, let $n = 1$, otherwise let $n = \tcode{nw}$.
 The relation
   $0 < \delta = (\tcode{xmax} - \tcode{xmin}) / n$
 holds.

\pnum
\effects
Constructs a \tcode{discrete_distribution} object
 with probabilities given by the formula above,
 using the following values:
 If $\tcode{nw} = 0$,
 let $w_0 = 1$.
 Otherwise,
 let $w_k = \tcode{fw}(\tcode{xmin} + k \cdot \delta + \delta / 2)$
 for $k = 0, \dotsc, n - 1$.

\pnum
\complexity
The number of invocations of \tcode{fw} does not exceed $n$.
\end{itemdescr}

\indexlibrarymember{probabilities}{discrete_distribution}%
\begin{itemdecl}
vector<double> probabilities() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
A \tcode{vector<double>}
 whose \tcode{size} member returns $n$
 and whose \tcode{operator[]} member returns $p_k$
 when invoked with argument $k$ for $k = 0, \dotsc, n - 1$.
\end{itemdescr}


% ----------------------------------------------------------------------
% Class template piecewise_constant_distribution
% ----------------------------------------------------------------------

\rSec4[rand.dist.samp.pconst]{Class template \tcode{piecewise_constant_distribution}}%
\indexlibraryglobal{piecewise_constant_distribution}%

\pnum
A \tcode{piecewise_constant_distribution} random number distribution
produces random numbers $x$,
$b_0 \leq x < b_n$,
uniformly distributed over each subinterval
$[ b_i, b_{i+1} )$
according to the probability density function in \eqref{rand.dist.samp.pconst}.
\begin{formula}{rand.dist.samp.pconst}
p(x \,|\, b_0, \dotsc, b_n, \; \rho_0, \dotsc, \rho_{n-1}) = \rho_i
   \text{ , for $b_i \le x < b_{i+1}$}
\end{formula}

\pnum
The $n + 1$ distribution parameters $b_i$,
also known as this distribution's \term{interval boundaries}%
, shall satisfy the relation
$b_i < b_{i + 1}$ for $i = 0, \dotsc, n - 1$.
Unless specified otherwise,
the remaining $n$ distribution parameters are calculated as:
\[ \rho_k = \frac{w_k}{S \cdot (b_{k+1}-b_k)} \text{ for } k = 0, \dotsc, n - 1 \text{ ,} \]
in which the values $w_k$,
commonly known as the \term{weights}%
, shall be non-negative, non-NaN, and non-infinity.
Moreover, the following relation shall hold:
 $0 < S = w_0 + \dotsb + w_{n-1}$.

\indexlibraryglobal{piecewise_constant_distribution}%
\indexlibrarymember{result_type}{piecewise_constant_distribution}%
\begin{codeblock}
namespace std {
  template<class RealType = double>
  class piecewise_constant_distribution {
  public:
    // types
    using result_type = RealType;
    using param_type  = @\unspec@;

    // constructor and reset functions
    piecewise_constant_distribution();
    template<class InputIteratorB, class InputIteratorW>
      piecewise_constant_distribution(InputIteratorB firstB, InputIteratorB lastB,
                                      InputIteratorW firstW);
    template<class UnaryOperation>
      piecewise_constant_distribution(initializer_list<RealType> bl, UnaryOperation fw);
    template<class UnaryOperation>
      piecewise_constant_distribution(size_t nw, RealType xmin, RealType xmax,
                                      UnaryOperation fw);
    explicit piecewise_constant_distribution(const param_type& parm);
    void reset();

    // equality operators
    friend bool operator==(const piecewise_constant_distribution& x,
                           const piecewise_constant_distribution& y);

    // generating functions
    template<class URBG>
      result_type operator()(URBG& g);
    template<class URBG>
      result_type operator()(URBG& g, const param_type& parm);

    // property functions
    vector<result_type> intervals() const;
    vector<result_type> densities() const;
    param_type param() const;
    void param(const param_type& parm);
    result_type min() const;
    result_type max() const;

    // inserters and extractors
    template<class charT, class traits>
      friend basic_ostream<charT, traits>&
        operator<<(basic_ostream<charT, traits>& os, const piecewise_constant_distribution& x);
    template<class charT, class traits>
      friend basic_istream<charT, traits>&
        operator>>(basic_istream<charT, traits>& is, piecewise_constant_distribution& x);
  };
}
\end{codeblock}


\indexlibraryctor{piecewise_constant_distribution}%
\begin{itemdecl}
piecewise_constant_distribution();
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Constructs a \tcode{piecewise_constant_distribution} object
 with $n = 1$,
 $\rho_0 = 1$,
 $b_0 = 0$,
 and $b_1 = 1$.
\end{itemdescr}


\indexlibraryctor{piecewise_constant_distribution}%
\begin{itemdecl}
template<class InputIteratorB, class InputIteratorW>
  piecewise_constant_distribution(InputIteratorB firstB, InputIteratorB lastB,
                                  InputIteratorW firstW);
\end{itemdecl}

\begin{itemdescr}
\pnum
\mandates
Both of
\begin{itemize}
\item{\tcode{is_convertible_v<iterator_traits<InputIteratorB>::value_type, double>}}
\item{\tcode{is_convertible_v<iterator_traits<InputIteratorW>::value_type, double>}}
\end{itemize}
are \tcode{true}.

\pnum
\expects
  \tcode{InputIteratorB} and \tcode{InputIteratorW}
   each meet the
  \oldconcept{InputIterator} requirements\iref{input.iterators}.
 If \tcode{firstB == lastB}
 or \tcode{++firstB == lastB},
 let $n = 1$,
     $w_0 = 1$,
     $b_0 = 0$,
 and $b_1 = 1$.
 Otherwise,
 $\bigl[\tcode{firstB}, \tcode{lastB}\bigr)$
 forms a sequence $b$ of length $n+1$,
 the length of the sequence $w$ starting from \tcode{firstW}
 is at least $n$,
 and any $w_k$ for  $k \geq n$ are ignored by the distribution.

\pnum
\effects
Constructs a \tcode{piecewise_constant_distribution} object
 with parameters as specified above.
\end{itemdescr}


\indexlibraryctor{piecewise_constant_distribution}%
\begin{itemdecl}
template<class UnaryOperation>
  piecewise_constant_distribution(initializer_list<RealType> bl, UnaryOperation fw);
\end{itemdecl}

\begin{itemdescr}
\pnum
\mandates
\tcode{is_invocable_r_v<double, UnaryOperation\&, double>} is \tcode{true}.

\pnum
\effects
Constructs a \tcode{piecewise_constant_distribution} object
 with parameters taken or calculated
 from the following values:
 If $\tcode{bl.size()} < 2$,
 let $n = 1$,
     $w_0 = 1$,
     $b_0 = 0$,
 and $b_1 = 1$.
 Otherwise,
 let $\bigl[\tcode{bl.begin()}, \tcode{bl.end()}\bigr)$
 form a sequence $b_0, \dotsc, b_n$,
 and
 let $w_k = \tcode{fw}\bigl(\bigl(b_{k+1} + b_k\bigr) / 2\bigr)$
 for $k = 0, \dotsc, n - 1$.

\pnum
\complexity
The number of invocations of \tcode{fw} does not exceed $n$.
\end{itemdescr}


\indexlibraryctor{piecewise_constant_distribution}%
\begin{itemdecl}
template<class UnaryOperation>
  piecewise_constant_distribution(size_t nw, RealType xmin, RealType xmax, UnaryOperation fw);
\end{itemdecl}

\begin{itemdescr}
\pnum
\mandates
\tcode{is_invocable_r_v<double, UnaryOperation\&, double>} is \tcode{true}.

\pnum
\expects
 If $\tcode{nw} = 0$, let $n = 1$, otherwise let $n = \tcode{nw}$.
 The relation $0 < \delta = (\tcode{xmax} - \tcode{xmin}) / n$
 holds.

\pnum
\effects
Constructs a \tcode{piecewise_constant_distribution} object
 with parameters taken or calculated
 from the following values:
 Let $b_k = \tcode{xmin} + k \cdot \delta $ for $ k = 0, \dotsc, n$,
 and $w_k = \tcode{fw}(b_k + \delta / 2) $ for $ k = 0, \dotsc, n - 1$.

\pnum
\complexity
The number of invocations of \tcode{fw} does not exceed $n$.
\end{itemdescr}

\indexlibrarymember{intervals}{piecewise_constant_distribution}%
\begin{itemdecl}
vector<result_type> intervals() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
A \tcode{vector<result_type>}
 whose \tcode{size} member returns $n + 1$
 and whose $ \tcode{operator[]} $ member returns $b_k$
 when invoked with argument $k$ for $k = 0, \dotsc, n $.
\end{itemdescr}

\indexlibrarymember{densities}{piecewise_constant_distribution}%
\begin{itemdecl}
vector<result_type> densities() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
A \tcode{vector<result_type>}
 whose \tcode{size} member returns $n$
 and whose $ \tcode{operator[]} $ member returns $\rho_k$
 when invoked with argument $k$ for $k = 0, \dotsc, n - 1$.
\end{itemdescr}


% ----------------------------------------------------------------------
% Class template piecewise_linear_distribution
% ----------------------------------------------------------------------

\rSec4[rand.dist.samp.plinear]{Class template \tcode{piecewise_linear_distribution}}%
\indexlibraryglobal{piecewise_linear_distribution}%

\pnum
A \tcode{piecewise_linear_distribution} random number distribution
produces random numbers $x$,
$b_0 \leq x < b_n$,
distributed over each subinterval
$[b_i, b_{i+1})$
according to the probability density function in \eqref{rand.dist.samp.plinear}.
\begin{formula}{rand.dist.samp.plinear}
p(x \,|\, b_0, \dotsc, b_n, \; \rho_0, \dotsc, \rho_n)
     = \rho_{i}   \cdot {\frac{b_{i+1} - x}{b_{i+1} - b_i}}
     + \rho_{i+1} \cdot {\frac{x - b_i}{b_{i+1} - b_i}}
     \text{ , for $b_i \le x < b_{i+1}$.}
\end{formula}

\pnum
The $n + 1$ distribution parameters $b_i$,
also known as this distribution's \term{interval boundaries}%
, shall satisfy the relation $b_i < b_{i+1}$ for $i = 0, \dotsc, n - 1$.
Unless specified otherwise,
the remaining $n + 1$ distribution parameters are calculated as
$\rho_k = {w_k / S}$ for $k = 0, \dotsc, n$, in which the values $w_k$,
commonly known as the \term{weights at boundaries}%
, shall be non-negative, non-NaN, and non-infinity.
Moreover, the following relation shall hold:
\[ 0 < S = \frac{1}{2} \cdot \sum_{k=0}^{n-1} (w_k + w_{k+1}) \cdot (b_{k+1} - b_k) \text{ .} \]

\indexlibraryglobal{piecewise_linear_distribution}%
\indexlibrarymember{result_type}{piecewise_linear_distribution}%
\begin{codeblock}
namespace std {
  template<class RealType = double>
  class piecewise_linear_distribution {
  public:
    // types
    using result_type = RealType;
    using param_type  = @\unspec@;

    // constructor and reset functions
    piecewise_linear_distribution();
    template<class InputIteratorB, class InputIteratorW>
      piecewise_linear_distribution(InputIteratorB firstB, InputIteratorB lastB,
                                    InputIteratorW firstW);
    template<class UnaryOperation>
      piecewise_linear_distribution(initializer_list<RealType> bl, UnaryOperation fw);
    template<class UnaryOperation>
      piecewise_linear_distribution(size_t nw, RealType xmin, RealType xmax, UnaryOperation fw);
    explicit piecewise_linear_distribution(const param_type& parm);
    void reset();

    // equality operators
    friend bool operator==(const piecewise_linear_distribution& x,
                           const piecewise_linear_distribution& y);

    // generating functions
    template<class URBG>
      result_type operator()(URBG& g);
    template<class URBG>
      result_type operator()(URBG& g, const param_type& parm);

    // property functions
    vector<result_type> intervals() const;
    vector<result_type> densities() const;
    param_type param() const;
    void param(const param_type& parm);
    result_type min() const;
    result_type max() const;

    // inserters and extractors
    template<class charT, class traits>
      friend basic_ostream<charT, traits>&
        operator<<(basic_ostream<charT, traits>& os, const piecewise_linear_distribution& x);
    template<class charT, class traits>
      friend basic_istream<charT, traits>&
        operator>>(basic_istream<charT, traits>& is, piecewise_linear_distribution& x);
  };
}
\end{codeblock}

\indexlibraryctor{piecewise_linear_distribution}
\begin{itemdecl}
piecewise_linear_distribution();
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Constructs a \tcode{piecewise_linear_distribution} object
 with $n = 1$,
 $\rho_0 = \rho_1 = 1$,
 $b_0 = 0$,
 and $b_1 = 1$.
\end{itemdescr}

\indexlibraryctor{piecewise_linear_distribution}
\begin{itemdecl}
template<class InputIteratorB, class InputIteratorW>
  piecewise_linear_distribution(InputIteratorB firstB, InputIteratorB lastB,
                                InputIteratorW firstW);
\end{itemdecl}

\begin{itemdescr}
\pnum
\mandates
Both of
\begin{itemize}
\item{\tcode{is_convertible_v<iterator_traits<InputIteratorB>::value_type, double>}}
\item{\tcode{is_convertible_v<iterator_traits<InputIteratorW>::value_type, double>}}
\end{itemize}
are \tcode{true}.

\pnum
\expects
  \tcode{InputIteratorB} and \tcode{InputIteratorW}
   each meet the
  \oldconcept{InputIterator} requirements\iref{input.iterators}.
 If \tcode{firstB == lastB}
 or \tcode{++firstB == lastB},
 let $n = 1$,
     $\rho_0 = \rho_1 = 1$,
     $b_0 = 0$,
 and $b_1 = 1$.
 Otherwise,
 $\bigl[\tcode{firstB}, \tcode{lastB}\bigr)$
 forms a sequence $b$ of length $n+1$,
 the length of the sequence $w$ starting from \tcode{firstW}
 is at least $n+1$,
 and any $w_k$ for $k \geq n + 1$ are ignored by the distribution.

\pnum
\effects
Constructs a \tcode{piecewise_linear_distribution} object
 with parameters as specified above.
\end{itemdescr}


\indexlibraryctor{piecewise_linear_distribution}%
\begin{itemdecl}
template<class UnaryOperation>
  piecewise_linear_distribution(initializer_list<RealType> bl, UnaryOperation fw);
\end{itemdecl}

\begin{itemdescr}
\pnum
\mandates
\tcode{is_invocable_r_v<double, UnaryOperation\&, double>} is \tcode{true}.

\pnum
\effects
Constructs a \tcode{piecewise_linear_distribution} object
 with parameters taken or calculated
 from the following values:
 If $\tcode{bl.size()} < 2$,
 let $n = 1$,
     $\rho_0 = \rho_1 = 1$,
     $b_0 = 0$,
 and $b_1 = 1$.
 Otherwise,
 let $\bigl[\tcode{bl.begin(),} \tcode{bl.end()}\bigr)$
 form a sequence $b_0, \dotsc, b_n$,
 and
 let $w_k = \tcode{fw}(b_k)$
 for $k = 0, \dotsc, n$.

\pnum
\complexity
The number of invocations of \tcode{fw} does not exceed $n+1$.
\end{itemdescr}


\indexlibraryctor{piecewise_linear_distribution}%
\begin{itemdecl}
template<class UnaryOperation>
  piecewise_linear_distribution(size_t nw, RealType xmin, RealType xmax, UnaryOperation fw);
\end{itemdecl}

\begin{itemdescr}
\pnum
\mandates
\tcode{is_invocable_r_v<double, UnaryOperation\&, double>} is \tcode{true}.

\pnum
\expects
 If $\tcode{nw} = 0$, let $n = 1$, otherwise let $n = \tcode{nw}$.
 The relation $0 < \delta = (\tcode{xmax} - \tcode{xmin}) / n$
 holds.

\pnum
\effects
Constructs a \tcode{piecewise_linear_distribution} object
 with parameters taken or calculated
 from the following values:
 Let $b_k = \tcode{xmin} + k \cdot \delta$ for $k = 0, \dotsc, n$,
 and $w_k = \tcode{fw}(b_k)$ for $k = 0, \dotsc, n$.

\pnum
\complexity
The number of invocations of \tcode{fw} does not exceed $n+1$.
\end{itemdescr}

\indexlibrarymember{intervals}{piecewise_linear_distribution}%
\begin{itemdecl}
vector<result_type> intervals() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
A \tcode{vector<result_type>}
 whose \tcode{size} member returns $n + 1$
 and whose $ \tcode{operator[]} $ member returns $b_k$
 when invoked with argument $k$ for $k = 0, \dotsc, n$.
\end{itemdescr}

\indexlibrarymember{densities}{piecewise_linear_distribution}%
\begin{itemdecl}
vector<result_type> densities() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
A \tcode{vector<result_type>}
 whose \tcode{size} member returns $n$
 and whose $ \tcode{operator[]} $ member returns $\rho_k$
 when invoked with argument $k$ for $k = 0, \dotsc, n$.
\end{itemdescr}%
%
\indextext{random number distributions!sampling|)}%
\indextext{sampling distributions|)}%
\indextext{random number generation!distributions|)}%

\rSec2[c.math.rand]{Low-quality random number generation}

\pnum
\begin{note}
The header \libheaderref{cstdlib}
declares the functions described in this subclause.
\end{note}

\indexlibraryglobal{rand}%
\indexlibraryglobal{srand}%
\begin{itemdecl}
int rand();
void srand(unsigned int seed);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
The
\tcode{rand} and \tcode{srand}
functions have the semantics specified in the C standard library.

\pnum
\remarks
The implementation
may specify that particular library functions may call
\tcode{rand}.
It is \impldef{whether \tcode{rand} may introduce a data race}
whether the \tcode{rand} function
may introduce data races\iref{res.on.data.races}.
\begin{note}
\indexlibrary{\idxcode{rand}!discouraged}%
The other random
number generation facilities in this document\iref{rand} are often preferable
to \tcode{rand}, because \tcode{rand}'s underlying algorithm is unspecified.
Use of \tcode{rand} therefore continues to be non-portable, with unpredictable
and oft-questionable quality and performance.
\end{note}
\end{itemdescr}

\xrefc{7.24.3}

\indextext{random number generation|)}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\rSec1[numarray]{Numeric arrays}

\rSec2[valarray.syn]{Header \tcode{<valarray>} synopsis}
\indexheader{valarray}%
\begin{codeblock}
#include <initializer_list>     // see \ref{initializer.list.syn}

namespace std {
  template<class T> class valarray;         // An array of type \tcode{T}
  class slice;                              // a BLAS-like slice out of an array
  template<class T> class slice_array;
  class gslice;                             // a generalized slice out of an array
  template<class T> class gslice_array;
  template<class T> class mask_array;       // a masked array
  template<class T> class indirect_array;   // an indirected array

  template<class T> void swap(valarray<T>&, valarray<T>&) noexcept;

  template<class T> valarray<T> operator* (const valarray<T>&, const valarray<T>&);
  template<class T> valarray<T> operator* (const valarray<T>&,
                                           const typename valarray<T>::value_type&);
  template<class T> valarray<T> operator* (const typename valarray<T>::value_type&,
                                           const valarray<T>&);

  template<class T> valarray<T> operator/ (const valarray<T>&, const valarray<T>&);
  template<class T> valarray<T> operator/ (const valarray<T>&,
                                           const typename valarray<T>::value_type&);
  template<class T> valarray<T> operator/ (const typename valarray<T>::value_type&,
                                           const valarray<T>&);

  template<class T> valarray<T> operator% (const valarray<T>&, const valarray<T>&);
  template<class T> valarray<T> operator% (const valarray<T>&,
                                           const typename valarray<T>::value_type&);
  template<class T> valarray<T> operator% (const typename valarray<T>::value_type&,
                                           const valarray<T>&);

  template<class T> valarray<T> operator+ (const valarray<T>&, const valarray<T>&);
  template<class T> valarray<T> operator+ (const valarray<T>&,
                                           const typename valarray<T>::value_type&);
  template<class T> valarray<T> operator+ (const typename valarray<T>::value_type&,
                                           const valarray<T>&);

  template<class T> valarray<T> operator- (const valarray<T>&, const valarray<T>&);
  template<class T> valarray<T> operator- (const valarray<T>&,
                                           const typename valarray<T>::value_type&);
  template<class T> valarray<T> operator- (const typename valarray<T>::value_type&,
                                           const valarray<T>&);

  template<class T> valarray<T> operator^ (const valarray<T>&, const valarray<T>&);
  template<class T> valarray<T> operator^ (const valarray<T>&,
                                           const typename valarray<T>::value_type&);
  template<class T> valarray<T> operator^ (const typename valarray<T>::value_type&,
                                           const valarray<T>&);

  template<class T> valarray<T> operator& (const valarray<T>&, const valarray<T>&);
  template<class T> valarray<T> operator& (const valarray<T>&,
                                           const typename valarray<T>::value_type&);
  template<class T> valarray<T> operator& (const typename valarray<T>::value_type&,
                                           const valarray<T>&);

  template<class T> valarray<T> operator| (const valarray<T>&, const valarray<T>&);
  template<class T> valarray<T> operator| (const valarray<T>&,
                                           const typename valarray<T>::value_type&);
  template<class T> valarray<T> operator| (const typename valarray<T>::value_type&,
                                           const valarray<T>&);

  template<class T> valarray<T> operator<<(const valarray<T>&, const valarray<T>&);
  template<class T> valarray<T> operator<<(const valarray<T>&,
                                           const typename valarray<T>::value_type&);
  template<class T> valarray<T> operator<<(const typename valarray<T>::value_type&,
                                           const valarray<T>&);

  template<class T> valarray<T> operator>>(const valarray<T>&, const valarray<T>&);
  template<class T> valarray<T> operator>>(const valarray<T>&,
                                           const typename valarray<T>::value_type&);
  template<class T> valarray<T> operator>>(const typename valarray<T>::value_type&,
                                           const valarray<T>&);

  template<class T> valarray<bool> operator&&(const valarray<T>&, const valarray<T>&);
  template<class T> valarray<bool> operator&&(const valarray<T>&,
                                              const typename valarray<T>::value_type&);
  template<class T> valarray<bool> operator&&(const typename valarray<T>::value_type&,
                                              const valarray<T>&);

  template<class T> valarray<bool> operator||(const valarray<T>&, const valarray<T>&);
  template<class T> valarray<bool> operator||(const valarray<T>&,
                                              const typename valarray<T>::value_type&);
  template<class T> valarray<bool> operator||(const typename valarray<T>::value_type&,
                                              const valarray<T>&);

  template<class T> valarray<bool> operator==(const valarray<T>&, const valarray<T>&);
  template<class T> valarray<bool> operator==(const valarray<T>&,
                                              const typename valarray<T>::value_type&);
  template<class T> valarray<bool> operator==(const typename valarray<T>::value_type&,
                                              const valarray<T>&);
  template<class T> valarray<bool> operator!=(const valarray<T>&, const valarray<T>&);
  template<class T> valarray<bool> operator!=(const valarray<T>&,
                                              const typename valarray<T>::value_type&);
  template<class T> valarray<bool> operator!=(const typename valarray<T>::value_type&,
                                              const valarray<T>&);

  template<class T> valarray<bool> operator< (const valarray<T>&, const valarray<T>&);
  template<class T> valarray<bool> operator< (const valarray<T>&,
                                              const typename valarray<T>::value_type&);
  template<class T> valarray<bool> operator< (const typename valarray<T>::value_type&,
                                              const valarray<T>&);
  template<class T> valarray<bool> operator> (const valarray<T>&, const valarray<T>&);
  template<class T> valarray<bool> operator> (const valarray<T>&,
                                              const typename valarray<T>::value_type&);
  template<class T> valarray<bool> operator> (const typename valarray<T>::value_type&,
                                              const valarray<T>&);
  template<class T> valarray<bool> operator<=(const valarray<T>&, const valarray<T>&);
  template<class T> valarray<bool> operator<=(const valarray<T>&,
                                              const typename valarray<T>::value_type&);
  template<class T> valarray<bool> operator<=(const typename valarray<T>::value_type&,
                                              const valarray<T>&);
  template<class T> valarray<bool> operator>=(const valarray<T>&, const valarray<T>&);
  template<class T> valarray<bool> operator>=(const valarray<T>&,
                                              const typename valarray<T>::value_type&);
  template<class T> valarray<bool> operator>=(const typename valarray<T>::value_type&,
                                              const valarray<T>&);

  template<class T> valarray<T> abs  (const valarray<T>&);
  template<class T> valarray<T> acos (const valarray<T>&);
  template<class T> valarray<T> asin (const valarray<T>&);
  template<class T> valarray<T> atan (const valarray<T>&);

  template<class T> valarray<T> atan2(const valarray<T>&, const valarray<T>&);
  template<class T> valarray<T> atan2(const valarray<T>&,
                                      const typename valarray<T>::value_type&);
  template<class T> valarray<T> atan2(const typename valarray<T>::value_type&,
                                      const valarray<T>&);

  template<class T> valarray<T> cos  (const valarray<T>&);
  template<class T> valarray<T> cosh (const valarray<T>&);
  template<class T> valarray<T> exp  (const valarray<T>&);
  template<class T> valarray<T> log  (const valarray<T>&);
  template<class T> valarray<T> log10(const valarray<T>&);

  template<class T> valarray<T> pow(const valarray<T>&, const valarray<T>&);
  template<class T> valarray<T> pow(const valarray<T>&, const typename valarray<T>::value_type&);
  template<class T> valarray<T> pow(const typename valarray<T>::value_type&, const valarray<T>&);

  template<class T> valarray<T> sin  (const valarray<T>&);
  template<class T> valarray<T> sinh (const valarray<T>&);
  template<class T> valarray<T> sqrt (const valarray<T>&);
  template<class T> valarray<T> tan  (const valarray<T>&);
  template<class T> valarray<T> tanh (const valarray<T>&);
}
\end{codeblock}

\pnum
The header \libheader{valarray} defines five class templates
(\tcode{valarray},
\tcode{slice_array},
\tcode{gslice_array},
\tcode{mask_array},
and
\tcode{indirect_array}),
two classes (\tcode{slice}
and
\tcode{gslice}),
and a series of related
function templates
for representing
and manipulating arrays of values.

\pnum
The
\tcode{valarray}
array classes
are defined to be free of certain forms of aliasing, thus allowing
operations on these classes to be optimized.

\pnum
Any function returning a
\tcode{valarray<T>}
is permitted to return an object of another type, provided all the
const member functions of
\tcode{valarray<T>}
other than \tcode{begin} and \tcode{end}
are also applicable to this type.
This return type shall not add
more than two levels of template nesting over the most deeply nested
argument type.
\begin{footnote}
\ref{implimits} recommends a minimum number
of recursively nested template
instantiations.
This requirement thus indirectly suggests a minimum
allowable complexity for valarray expressions.
\end{footnote}

\pnum
Implementations introducing such replacement types shall provide
additional functions and operators as follows:
\begin{itemize}
\item
for every function taking a
\tcode{const valarray<T>\&},
identical functions taking the replacement types shall be added;
\item
for every function taking two
\tcode{const valarray<T>\&}
arguments, identical functions taking every combination of
\tcode{const valarray<T>\&}
and replacement types shall be added.
\end{itemize}

\pnum
In particular, an implementation shall allow a
\tcode{valarray<T>}
to be constructed from such replacement types and shall allow assignments
and compound assignments of such types to
\tcode{valarray<T>},
\tcode{slice_array<T>},
\tcode{gslice_array<T>},
\tcode{mask_array<T>}
and
\tcode{indirect_array<T>}
objects.

\pnum
These library functions are permitted to throw a
\tcode{bad_alloc}\iref{bad.alloc} exception if there are not sufficient resources available
to carry out the operation.
Note that the exception is not mandated.

\rSec2[template.valarray]{Class template \tcode{valarray}}

\rSec3[template.valarray.overview]{Overview}

\indexlibraryglobal{valarray}%
\begin{codeblock}
namespace std {
  template<class T> class valarray {
  public:
    using value_type     = T;
    using iterator       = @\unspec@;
    using const_iterator = @\unspec@;

    // \ref{valarray.cons}, construct/destroy
    valarray();
    explicit valarray(size_t);
    valarray(const T&, size_t);
    valarray(const T*, size_t);
    valarray(const valarray&);
    valarray(valarray&&) noexcept;
    valarray(const slice_array<T>&);
    valarray(const gslice_array<T>&);
    valarray(const mask_array<T>&);
    valarray(const indirect_array<T>&);
    valarray(initializer_list<T>);
    ~valarray();

    // \ref{valarray.assign}, assignment
    valarray& operator=(const valarray&);
    valarray& operator=(valarray&&) noexcept;
    valarray& operator=(initializer_list<T>);
    valarray& operator=(const T&);
    valarray& operator=(const slice_array<T>&);
    valarray& operator=(const gslice_array<T>&);
    valarray& operator=(const mask_array<T>&);
    valarray& operator=(const indirect_array<T>&);

    // \ref{valarray.access}, element access
    const T&          operator[](size_t) const;
    T&                operator[](size_t);

    // \ref{valarray.sub}, subset operations
    valarray          operator[](slice) const;
    slice_array<T>    operator[](slice);
    valarray          operator[](const gslice&) const;
    gslice_array<T>   operator[](const gslice&);
    valarray          operator[](const valarray<bool>&) const;
    mask_array<T>     operator[](const valarray<bool>&);
    valarray          operator[](const valarray<size_t>&) const;
    indirect_array<T> operator[](const valarray<size_t>&);

    // \ref{valarray.unary}, unary operators
    valarray operator+() const;
    valarray operator-() const;
    valarray operator~() const;
    valarray<bool> operator!() const;

    // \ref{valarray.cassign}, compound assignment
    valarray& operator*= (const T&);
    valarray& operator/= (const T&);
    valarray& operator%= (const T&);
    valarray& operator+= (const T&);
    valarray& operator-= (const T&);
    valarray& operator^= (const T&);
    valarray& operator&= (const T&);
    valarray& operator|= (const T&);
    valarray& operator<<=(const T&);
    valarray& operator>>=(const T&);

    valarray& operator*= (const valarray&);
    valarray& operator/= (const valarray&);
    valarray& operator%= (const valarray&);
    valarray& operator+= (const valarray&);
    valarray& operator-= (const valarray&);
    valarray& operator^= (const valarray&);
    valarray& operator|= (const valarray&);
    valarray& operator&= (const valarray&);
    valarray& operator<<=(const valarray&);
    valarray& operator>>=(const valarray&);

    // \ref{valarray.range}, range access
    iterator begin();
    iterator end();
    const_iterator begin() const;
    const_iterator end() const;

    // \ref{valarray.members}, member functions
    void swap(valarray&) noexcept;

    size_t size() const;

    T sum() const;
    T min() const;
    T max() const;

    valarray shift (int) const;
    valarray cshift(int) const;
    valarray apply(T func(T)) const;
    valarray apply(T func(const T&)) const;
    void resize(size_t sz, T c = T());
  };

  template<class T, size_t cnt> valarray(const T(&)[cnt], size_t) -> valarray<T>;
}
\end{codeblock}

\pnum
The
class template
\tcode{valarray<T>}
is a
one-dimensional smart array, with elements numbered sequentially from zero.
It is a representation of the mathematical concept
of an ordered set of values.
For convenience, an object of type \tcode{valarray<T>} is referred
to as an ``array'' throughout the remainder of~\ref{numarray}.
The illusion of higher dimensionality
may be produced by the familiar idiom of computed indices, together
with the powerful subsetting capabilities provided
by the generalized subscript operators.
\begin{footnote}
The intent is to specify
an array template that has the minimum functionality
necessary to address aliasing ambiguities and the proliferation of
temporary objects.
Thus, the
\tcode{valarray}
template is neither a
matrix class nor a field class.
However, it is a very useful building block for designing such classes.
\end{footnote}

\rSec3[valarray.cons]{Constructors}

\indexlibraryctor{valarray}%
\begin{itemdecl}
valarray();
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Constructs a \tcode{valarray}
that has zero length.
\begin{footnote}
This default constructor is essential,
since arrays of
\tcode{valarray}
can be useful.
After initialization, the length of an empty array can be increased with the
\tcode{resize}
member function.
\end{footnote}
\end{itemdescr}

\indexlibraryctor{valarray}%
\begin{itemdecl}
explicit valarray(size_t n);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Constructs a \tcode{valarray} that has length \tcode{n}.
Each element of the array is value-initialized\iref{dcl.init}.
\end{itemdescr}

\indexlibraryctor{valarray}%
\begin{itemdecl}
valarray(const T& v, size_t n);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Constructs a \tcode{valarray} that has length \tcode{n}.
Each element of the array is initialized with \tcode{v}.
\end{itemdescr}

\indexlibraryctor{valarray}%
\begin{itemdecl}
valarray(const T* p, size_t n);
\end{itemdecl}

\begin{itemdescr}

\pnum
\expects
\range{p}{p + n} is a valid range.

\pnum
\effects
Constructs a \tcode{valarray} that has length \tcode{n}.
The values of the elements of the array are initialized with the
first
\tcode{n}
values pointed to by the first argument.
\begin{footnote}
This constructor is the
preferred method for converting a C array to a
\tcode{valarray}
object.
\end{footnote}
\end{itemdescr}

\indexlibraryctor{valarray}%
\begin{itemdecl}
valarray(const valarray& v);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Constructs a \tcode{valarray} that has the same length as \tcode{v}.
The elements are initialized with the values of the corresponding
elements of \tcode{v}.
\begin{footnote}
This copy constructor creates
a distinct array rather than an alias.
Implementations in which arrays share storage are permitted, but they
would need to implement a copy-on-reference mechanism to ensure that arrays are
conceptually distinct.
\end{footnote}
\end{itemdescr}

\indexlibraryctor{valarray}%
\begin{itemdecl}
valarray(valarray&& v) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Constructs a \tcode{valarray} that has the same length as \tcode{v}.
The elements are initialized with the values of the corresponding
elements of \tcode{v}.

\pnum
\complexity
Constant.
\end{itemdescr}

\indexlibraryctor{valarray}%
\begin{itemdecl}
valarray(initializer_list<T> il);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to \tcode{valarray(il.data(), il.size())}.
\end{itemdescr}

\indexlibraryctor{valarray}%
\begin{itemdecl}
valarray(const slice_array<T>&);
valarray(const gslice_array<T>&);
valarray(const mask_array<T>&);
valarray(const indirect_array<T>&);
\end{itemdecl}

\begin{itemdescr}
\pnum
These conversion constructors convert one of the four reference templates
to a
\tcode{valarray}.
\end{itemdescr}

\indexlibrarydtor{valarray}%
\begin{itemdecl}
~valarray();
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
The destructor is applied to every element of
\tcode{*this};
an implementation may return all allocated memory.
\end{itemdescr}

\rSec3[valarray.assign]{Assignment}

\indexlibrarymember{operator=}{valarray}%
\begin{itemdecl}
valarray& operator=(const valarray& v);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Each element of the
\tcode{*this}
array is assigned the value of the corresponding element of \tcode{v}.
If the length of \tcode{v} is not equal to the length of \tcode{*this},
resizes \tcode{*this} to make the two arrays the same length,
as if by calling \tcode{resize(v.size())}, before performing the assignment.

\pnum
\ensures
\tcode{size() == v.size()}.

\pnum
\returns
\tcode{*this}.
\end{itemdescr}

\indexlibrarymember{operator=}{valarray}%
\begin{itemdecl}
valarray& operator=(valarray&& v) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
\tcode{*this} obtains the value of \tcode{v}.
The value of \tcode{v} after the assignment is not specified.

\pnum
\returns
\tcode{*this}.

\pnum
\complexity
Linear.
\end{itemdescr}

\indexlibrarymember{operator=}{valarray}%
\begin{itemdecl}
valarray& operator=(initializer_list<T> il);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return *this = valarray(il);}
\end{itemdescr}


\indexlibrarymember{operator=}{valarray}%
\begin{itemdecl}
valarray& operator=(const T& v);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Assigns \tcode{v} to each element of \tcode{*this}.

\pnum
\returns
\tcode{*this}.
\end{itemdescr}

\indexlibrarymember{operator=}{valarray}%
\begin{itemdecl}
valarray& operator=(const slice_array<T>&);
valarray& operator=(const gslice_array<T>&);
valarray& operator=(const mask_array<T>&);
valarray& operator=(const indirect_array<T>&);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
The length of the array to which the argument refers equals \tcode{size()}.
The value of an element in the left-hand side of a \tcode{valarray} assignment
operator does not depend on the value of another element in that left-hand side.

\pnum
These operators allow the results of a generalized subscripting operation
to be assigned directly to a
\tcode{valarray}.
\end{itemdescr}

\rSec3[valarray.access]{Element access}

\indexlibrarymember{operator[]}{valarray}%
\begin{itemdecl}
const T& operator[](size_t n) const;
T& operator[](size_t n);
\end{itemdecl}

\begin{itemdescr}
\pnum
\hardexpects
\tcode{n < size()} is \tcode{true}.

\pnum
\returns
A reference to the corresponding element of the array.
\begin{note}
The expression \tcode{(a[i] = q, a[i]) == q}
evaluates to \tcode{true} for any non-constant \tcode{valarray<T> a},
any \tcode{T q}, and for any \tcode{size_t i}
such that the value of \tcode{i} is less than the length of \tcode{a}.
\end{note}

\pnum
\remarks
The expression \tcode{addressof(a[i + j]) == addressof(a[i]) + j}
evaluates to \tcode{true} for all \tcode{size_t i} and \tcode{size_t j}
such that \tcode{i + j < a.size()}.

\pnum
The expression \tcode{addressof(a[i]) != addressof(b[j])}
evaluates to \tcode{true} for any two arrays
\tcode{a} and \tcode{b} and for any
\tcode{size_t i} and \tcode{size_t j}
such that \tcode{i < a.size()}
and \tcode{j < b.size()}.
\begin{note}
This property indicates an absence of aliasing and can be used to
advantage by optimizing compilers. Compilers can take advantage
of inlining, constant propagation, loop fusion,
tracking of pointers obtained from
\tcode{operator new},
and other techniques to generate efficient
\tcode{valarray}s.
\end{note}

\pnum
The reference returned by the subscript operator for an array shall
be valid until the member function
\tcode{resize(size_t, T)}\iref{valarray.members} is called for that array or until the lifetime of
that array ends, whichever happens first.
\end{itemdescr}

\rSec3[valarray.sub]{Subset operations}

\indexlibrary{\idxcode{operator[]}!\idxcode{valarray}}%
\pnum
The member \tcode{operator[]} is overloaded to provide several ways to select
sequences of elements from among those controlled by \tcode{*this}. Each of these
operations returns a subset of the array. The const-qualified versions return this
subset as a new \tcode{valarray} object. The non-const versions return a class
template object which has reference semantics to the original array, working in
conjunction with various overloads of \tcode{operator=} and other assigning
operators to allow selective replacement (slicing) of the controlled sequence.
In each case the selected element(s) shall exist.

\indexlibrarymember{operator[]}{valarray}%
\begin{itemdecl}
valarray operator[](slice slicearr) const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
A \tcode{valarray} containing those
elements of the controlled sequence designated by \tcode{slicearr}.
\begin{example}
\begin{codeblock}
const valarray<char> v0("abcdefghijklmnop", 16);
// \tcode{v0[slice(2, 5, 3)]} returns \tcode{valarray<char>("cfilo", 5)}
\end{codeblock}
\end{example}
\end{itemdescr}

\indexlibrarymember{operator[]}{valarray}%
\begin{itemdecl}
slice_array<T> operator[](slice slicearr);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
An object that holds references to elements of the controlled
sequence selected by \tcode{slicearr}.
\begin{example}
\begin{codeblock}
valarray<char> v0("abcdefghijklmnop", 16);
valarray<char> v1("ABCDE", 5);
v0[slice(2, 5, 3)] = v1;
// \tcode{v0 == valarray<char>("abAdeBghCjkDmnEp", 16);}
\end{codeblock}
\end{example}
\end{itemdescr}

\indexlibrarymember{operator[]}{valarray}%
\begin{itemdecl}
valarray operator[](const gslice& gslicearr) const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
A \tcode{valarray} containing those
elements of the controlled sequence designated by \tcode{gslicearr}.
\begin{example}
\begin{codeblock}
const valarray<char> v0("abcdefghijklmnop", 16);
const size_t lv[] = { 2, 3 };
const size_t dv[] = { 7, 2 };
const valarray<size_t> len(lv, 2), str(dv, 2);
// \tcode{v0[gslice(3, len, str)]} returns
// \tcode{valarray<char>("dfhkmo", 6)}
\end{codeblock}
\end{example}
\end{itemdescr}

\indexlibrarymember{operator[]}{valarray}%
\begin{itemdecl}
gslice_array<T> operator[](const gslice& gslicearr);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
An object that holds references to elements of the controlled
sequence selected by \tcode{gslicearr}.
\begin{example}
\begin{codeblock}
valarray<char> v0("abcdefghijklmnop", 16);
valarray<char> v1("ABCDEF", 6);
const size_t lv[] = { 2, 3 };
const size_t dv[] = { 7, 2 };
const valarray<size_t> len(lv, 2), str(dv, 2);
v0[gslice(3, len, str)] = v1;
// \tcode{v0 == valarray<char>("abcAeBgCijDlEnFp", 16)}
\end{codeblock}
\end{example}
\end{itemdescr}

\indexlibrarymember{operator[]}{valarray}%
\begin{itemdecl}
valarray operator[](const valarray<bool>& boolarr) const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
A \tcode{valarray} containing those
elements of the controlled sequence designated by \tcode{boolarr}.
\begin{example}
\begin{codeblock}
const valarray<char> v0("abcdefghijklmnop", 16);
const bool vb[] = { false, false, true, true, false, true };
// \tcode{v0[valarray<bool>(vb, 6)]} returns
// \tcode{valarray<char>("cdf", 3)}
\end{codeblock}
\end{example}
\end{itemdescr}

\indexlibrarymember{operator[]}{valarray}%
\begin{itemdecl}
mask_array<T> operator[](const valarray<bool>& boolarr);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
An object that holds references to elements of the controlled
sequence selected by \tcode{boolarr}.
\begin{example}
\begin{codeblock}
valarray<char> v0("abcdefghijklmnop", 16);
valarray<char> v1("ABC", 3);
const bool vb[] = { false, false, true, true, false, true };
v0[valarray<bool>(vb, 6)] = v1;
// \tcode{v0 == valarray<char>("abABeCghijklmnop", 16)}
\end{codeblock}
\end{example}
\end{itemdescr}

\indexlibrarymember{operator[]}{valarray}%
\begin{itemdecl}
valarray operator[](const valarray<size_t>& indarr) const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
A \tcode{valarray} containing those
elements of the controlled sequence designated by \tcode{indarr}.
\begin{example}
\begin{codeblock}
const valarray<char> v0("abcdefghijklmnop", 16);
const size_t vi[] = { 7, 5, 2, 3, 8 };
// \tcode{v0[valarray<size_t>(vi, 5)]} returns
// \tcode{valarray<char>("hfcdi", 5)}
\end{codeblock}
\end{example}
\end{itemdescr}

\indexlibrarymember{operator[]}{valarray}%
\begin{itemdecl}
indirect_array<T> operator[](const valarray<size_t>& indarr);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
An object that holds references to elements of the controlled
sequence selected by \tcode{indarr}.
\begin{example}
\begin{codeblock}
valarray<char> v0("abcdefghijklmnop", 16);
valarray<char> v1("ABCDE", 5);
const size_t vi[] = { 7, 5, 2, 3, 8 };
v0[valarray<size_t>(vi, 5)] = v1;
// \tcode{v0 == valarray<char>("abCDeBgAEjklmnop", 16)}
\end{codeblock}
\end{example}
\end{itemdescr}

\rSec3[valarray.unary]{Unary operators}

\indexlibrarymember{operator+}{valarray}%
\indexlibrarymember{operator-}{valarray}%
\indexlibrarymember{operator\~{}}{valarray}%
\indexlibrarymember{operator"!}{valarray}%
\begin{itemdecl}
valarray operator+() const;
valarray operator-() const;
valarray operator~() const;
valarray<bool> operator!() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\mandates
The indicated operator can be applied to operands of type \tcode{T}
and returns a value of type \tcode{T} (\tcode{bool} for
\tcode{operator!}) or which may be unambiguously implicitly converted to type
\tcode{T} (\tcode{bool} for \tcode{operator!}).

\pnum
\returns
A \tcode{valarray} whose length is \tcode{size()}.
Each element of the returned array is initialized with the result of
applying the indicated operator to the corresponding element of the array.
\end{itemdescr}

\rSec3[valarray.cassign]{Compound assignment}

\indexlibrarymember{operator*=}{valarray}%
\indexlibrarymember{operator/=}{valarray}%
\indexlibrarymember{operator\%=}{valarray}%
\indexlibrarymember{operator+=}{valarray}%
\indexlibrarymember{operator-=}{valarray}%
\indexlibrarymember{operator\caret=}{valarray}%
\indexlibrarymember{operator\&=}{valarray}%
\indexlibrarymember{operator"|=}{valarray}%
\indexlibrarymember{operator<<=}{valarray}%
\indexlibrarymember{operator>>=}{valarray}%
\begin{itemdecl}
valarray& operator*= (const valarray& v);
valarray& operator/= (const valarray& v);
valarray& operator%= (const valarray& v);
valarray& operator+= (const valarray& v);
valarray& operator-= (const valarray& v);
valarray& operator^= (const valarray& v);
valarray& operator&= (const valarray& v);
valarray& operator|= (const valarray& v);
valarray& operator<<=(const valarray& v);
valarray& operator>>=(const valarray& v);
\end{itemdecl}

\begin{itemdescr}
\pnum
\mandates
The indicated operator can be applied to two operands of type \tcode{T}.

\pnum
\expects
\tcode{size() == v.size()} is \tcode{true}.

The value of an element in the left-hand side of a valarray compound
assignment operator does not depend on the value of another element in that left
hand side.

\pnum
\effects
Each of these operators
performs the indicated operation on each of the elements of \tcode{*this} and the
corresponding element of \tcode{v}.

\pnum
\returns
\tcode{*this}.

\pnum
\remarks
The appearance of an array on the left-hand side of a compound assignment
does not invalidate references or pointers.
\end{itemdescr}

\indexlibrarymember{operator*=}{valarray}%
\indexlibrarymember{operator/=}{valarray}%
\indexlibrarymember{operator\%=}{valarray}%
\indexlibrarymember{operator+=}{valarray}%
\indexlibrarymember{operator-=}{valarray}%
\indexlibrarymember{operator\caret=}{valarray}%
\indexlibrarymember{operator\&=}{valarray}%
\indexlibrarymember{operator"|=}{valarray}%
\indexlibrarymember{operator<<=}{valarray}%
\indexlibrarymember{operator>>=}{valarray}%
\begin{itemdecl}
valarray& operator*= (const T& v);
valarray& operator/= (const T& v);
valarray& operator%= (const T& v);
valarray& operator+= (const T& v);
valarray& operator-= (const T& v);
valarray& operator^= (const T& v);
valarray& operator&= (const T& v);
valarray& operator|= (const T& v);
valarray& operator<<=(const T& v);
valarray& operator>>=(const T& v);
\end{itemdecl}

\begin{itemdescr}
\pnum
\mandates
The indicated operator can be applied to two operands of type \tcode{T}.

\pnum
\effects
Each of these operators applies the indicated operation to each element
of \tcode{*this} and \tcode{v}.

\pnum
\returns
\tcode{*this}.

\pnum
\remarks
The appearance of an array on the left-hand side of a compound assignment
does not
invalidate references or pointers to the elements of the array.
\end{itemdescr}

\rSec3[valarray.members]{Member functions}

\indexlibrarymember{swap}{valarray}%
\begin{itemdecl}
void swap(valarray& v) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
\tcode{*this} obtains the value of
\tcode{v}. \tcode{v} obtains the value of \tcode{*this}.

\pnum
\complexity
Constant.
\end{itemdescr}

\indexlibrarymember{size}{valarray}%
\begin{itemdecl}
size_t size() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
The number of elements in the array.

\pnum
\complexity
Constant time.
\end{itemdescr}

\indexlibrarymember{sum}{valarray}%
\begin{itemdecl}
T sum() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\mandates
\tcode{operator+=} can be applied to operands of type \tcode{T}.

\pnum
\expects
\tcode{size() > 0} is \tcode{true}.

\pnum
\returns
The sum of all the elements of the array.
If the array has length 1, returns the value of element 0.
Otherwise, the returned value is calculated by applying
\tcode{operator+=}
to a copy of an element of the array and
all other elements of the array in an unspecified order.%
\end{itemdescr}

\indexlibrarymember{min}{valarray}%
\begin{itemdecl}
T min() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{size() > 0} is \tcode{true}.

\pnum
\returns
The minimum value contained in \tcode{*this}.
For an array of length 1, the value of element 0 is returned.
For all other array
lengths, the determination is made using
\tcode{operator<}.
\end{itemdescr}

\indexlibrarymember{max}{valarray}%
\begin{itemdecl}
T max() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{size() > 0} is \tcode{true}.

\pnum
\returns
The maximum value contained in \tcode{*this}.
For an array of length 1, the value of element 0 is returned.
For all other array
lengths, the determination is made using
\tcode{operator<}.
\end{itemdescr}

\indexlibrarymember{shift}{valarray}%
\begin{itemdecl}
valarray shift(int n) const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
A \tcode{valarray} of length \tcode{size()}, each of whose elements
\placeholder{I} is
\tcode{(*this)[\placeholder{I} + n]}
if \tcode{\placeholder{I} + n}
is non-negative and less than
\tcode{size()}, otherwise \tcode{T()}.
\begin{note}
If element zero is taken as the leftmost element,
a positive value of \tcode{n} shifts the elements left \tcode{n}
places, with zero fill.
\end{note}

\pnum
\begin{example}
If the argument has the value $-2$,
the first two elements of the result will be value-initialized\iref{dcl.init}; the third element of the result will be assigned the value
of the first element of \tcode{*this}; etc.
\end{example}
\end{itemdescr}

\indexlibrarymember{cshift}{valarray}%
\begin{itemdecl}
valarray cshift(int n) const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
A \tcode{valarray} of length \tcode{size()}
that is a circular shift of \tcode{*this}. If element zero is taken as
the leftmost element, a non-negative value of $n$ shifts
the elements circularly left $n$ places and a negative
value of $n$ shifts the elements circularly right $-n$ places.
\end{itemdescr}

\indexlibrarymember{apply}{valarray}%
\begin{itemdecl}
valarray apply(T func(T)) const;
valarray apply(T func(const T&)) const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
A \tcode{valarray} whose length is \tcode{size()}.
Each element of the returned array is assigned
the value returned by applying the argument function to the
corresponding element of \tcode{*this}.
\end{itemdescr}

\indexlibrarymember{resize}{valarray}%
\begin{itemdecl}
void resize(size_t sz, T c = T());
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Changes the length of the \tcode{*this} array to \tcode{sz}
and then assigns to each element the value of the second argument.
Resizing invalidates all pointers and references to elements in the array.
\end{itemdescr}

\rSec2[valarray.nonmembers]{\tcode{valarray} non-member operations}

\rSec3[valarray.binary]{Binary operators}

\indexlibrarymember{operator*}{valarray}%
\indexlibrarymember{operator/}{valarray}%
\indexlibrarymember{operator\%}{valarray}%
\indexlibrarymember{operator+}{valarray}%
\indexlibrarymember{operator-}{valarray}%
\indexlibrarymember{operator\caret}{valarray}%
\indexlibrarymember{operator\&}{valarray}%
\indexlibrarymember{operator"|}{valarray}%
\indexlibrarymember{operator<<}{valarray}%
\indexlibrarymember{operator>>}{valarray}%
\begin{itemdecl}
template<class T> valarray<T> operator* (const valarray<T>&, const valarray<T>&);
template<class T> valarray<T> operator/ (const valarray<T>&, const valarray<T>&);
template<class T> valarray<T> operator% (const valarray<T>&, const valarray<T>&);
template<class T> valarray<T> operator+ (const valarray<T>&, const valarray<T>&);
template<class T> valarray<T> operator- (const valarray<T>&, const valarray<T>&);
template<class T> valarray<T> operator^ (const valarray<T>&, const valarray<T>&);
template<class T> valarray<T> operator& (const valarray<T>&, const valarray<T>&);
template<class T> valarray<T> operator| (const valarray<T>&, const valarray<T>&);
template<class T> valarray<T> operator<<(const valarray<T>&, const valarray<T>&);
template<class T> valarray<T> operator>>(const valarray<T>&, const valarray<T>&);
\end{itemdecl}

\begin{itemdescr}
\pnum
\mandates
The indicated operator can be applied to operands of type \tcode{T} and returns
a value of type \tcode{T} or which can be unambiguously
implicitly converted to \tcode{T}.

\pnum
\expects
The argument arrays have the same length.

\pnum
\returns
A \tcode{valarray} whose length is equal to the
lengths of the argument arrays.
Each element of the returned array is
initialized with the result of applying the indicated operator to the
corresponding elements of the argument arrays.
\end{itemdescr}

\indexlibrarymember{operator*}{valarray}%
\indexlibrarymember{operator/}{valarray}%
\indexlibrarymember{operator\%}{valarray}%
\indexlibrarymember{operator+}{valarray}%
\indexlibrarymember{operator-}{valarray}%
\indexlibrarymember{operator\caret}{valarray}%
\indexlibrarymember{operator\&}{valarray}%
\indexlibrarymember{operator"|}{valarray}%
\indexlibrarymember{operator<<}{valarray}%
\indexlibrarymember{operator>>}{valarray}%
\begin{itemdecl}
template<class T> valarray<T> operator* (const valarray<T>&,
                                         const typename valarray<T>::value_type&);
template<class T> valarray<T> operator* (const typename valarray<T>::value_type&,
                                         const valarray<T>&);
template<class T> valarray<T> operator/ (const valarray<T>&,
                                         const typename valarray<T>::value_type&);
template<class T> valarray<T> operator/ (const typename valarray<T>::value_type&,
                                         const valarray<T>&);
template<class T> valarray<T> operator% (const valarray<T>&,
                                         const typename valarray<T>::value_type&);
template<class T> valarray<T> operator% (const typename valarray<T>::value_type&,
                                         const valarray<T>&);
template<class T> valarray<T> operator+ (const valarray<T>&,
                                         const typename valarray<T>::value_type&);
template<class T> valarray<T> operator+ (const typename valarray<T>::value_type&,
                                         const valarray<T>&);
template<class T> valarray<T> operator- (const valarray<T>&,
                                         const typename valarray<T>::value_type&);
template<class T> valarray<T> operator- (const typename valarray<T>::value_type&,
                                         const valarray<T>&);
template<class T> valarray<T> operator^ (const valarray<T>&,
                                         const typename valarray<T>::value_type&);
template<class T> valarray<T> operator^ (const typename valarray<T>::value_type&,
                                         const valarray<T>&);
template<class T> valarray<T> operator& (const valarray<T>&,
                                         const typename valarray<T>::value_type&);
template<class T> valarray<T> operator& (const typename valarray<T>::value_type&,
                                         const valarray<T>&);
template<class T> valarray<T> operator| (const valarray<T>&,
                                         const typename valarray<T>::value_type&);
template<class T> valarray<T> operator| (const typename valarray<T>::value_type&,
                                         const valarray<T>&);
template<class T> valarray<T> operator<<(const valarray<T>&,
                                         const typename valarray<T>::value_type&);
template<class T> valarray<T> operator<<(const typename valarray<T>::value_type&,
                                         const valarray<T>&);
template<class T> valarray<T> operator>>(const valarray<T>&,
                                         const typename valarray<T>::value_type&);
template<class T> valarray<T> operator>>(const typename valarray<T>::value_type&,
                                         const valarray<T>&);
\end{itemdecl}

\begin{itemdescr}
\pnum
\mandates
The indicated operator can be applied to operands of type \tcode{T} and returns
a value of type \tcode{T} or which can be unambiguously
implicitly converted to \tcode{T}.

\pnum
\returns
A \tcode{valarray} whose length is equal to the
length of the array argument.
Each element of the returned array is
initialized with the result of applying the indicated operator to the
corresponding element of the array argument and the non-array argument.
\end{itemdescr}

\rSec3[valarray.comparison]{Logical operators}

\indexlibrarymember{operator==}{valarray}%
\indexlibrarymember{operator"!=}{valarray}%
\indexlibrarymember{operator<}{valarray}%
\indexlibrarymember{operator>}{valarray}%
\indexlibrarymember{operator<=}{valarray}%
\indexlibrarymember{operator>=}{valarray}%
\indexlibrarymember{operator\&\&}{valarray}%
\indexlibrarymember{operator"|"|}{valarray}%
\begin{itemdecl}
template<class T> valarray<bool> operator==(const valarray<T>&, const valarray<T>&);
template<class T> valarray<bool> operator!=(const valarray<T>&, const valarray<T>&);
template<class T> valarray<bool> operator< (const valarray<T>&, const valarray<T>&);
template<class T> valarray<bool> operator> (const valarray<T>&, const valarray<T>&);
template<class T> valarray<bool> operator<=(const valarray<T>&, const valarray<T>&);
template<class T> valarray<bool> operator>=(const valarray<T>&, const valarray<T>&);
template<class T> valarray<bool> operator&&(const valarray<T>&, const valarray<T>&);
template<class T> valarray<bool> operator||(const valarray<T>&, const valarray<T>&);
\end{itemdecl}

\begin{itemdescr}
\pnum
\mandates
The indicated operator can be applied to operands of type \tcode{T} and returns
a value of type \tcode{bool} or which can be unambiguously
implicitly converted to \tcode{bool}.

\pnum
\expects
The two array arguments have the same length.
\indextext{undefined}

\pnum
\returns
A \tcode{valarray<bool>} whose length
is equal to the length of the array arguments.
Each element of the returned
array is initialized with the result of applying the indicated
operator to the corresponding elements of the argument arrays.
\end{itemdescr}

\indexlibrarymember{operator==}{valarray}%
\indexlibrarymember{operator"!=}{valarray}%
\indexlibrarymember{operator<}{valarray}%
\indexlibrarymember{operator>}{valarray}%
\indexlibrarymember{operator<=}{valarray}%
\indexlibrarymember{operator>=}{valarray}%
\indexlibrarymember{operator\&\&}{valarray}%
\indexlibrarymember{operator"|"|}{valarray}%
\begin{itemdecl}
template<class T> valarray<bool> operator==(const valarray<T>&,
                                            const typename valarray<T>::value_type&);
template<class T> valarray<bool> operator==(const typename valarray<T>::value_type&,
                                            const valarray<T>&);
template<class T> valarray<bool> operator!=(const valarray<T>&,
                                            const typename valarray<T>::value_type&);
template<class T> valarray<bool> operator!=(const typename valarray<T>::value_type&,
                                            const valarray<T>&);
template<class T> valarray<bool> operator< (const valarray<T>&,
                                            const typename valarray<T>::value_type&);
template<class T> valarray<bool> operator< (const typename valarray<T>::value_type&,
                                            const valarray<T>&);
template<class T> valarray<bool> operator> (const valarray<T>&,
                                            const typename valarray<T>::value_type&);
template<class T> valarray<bool> operator> (const typename valarray<T>::value_type&,
                                            const valarray<T>&);
template<class T> valarray<bool> operator<=(const valarray<T>&,
                                            const typename valarray<T>::value_type&);
template<class T> valarray<bool> operator<=(const typename valarray<T>::value_type&,
                                            const valarray<T>&);
template<class T> valarray<bool> operator>=(const valarray<T>&,
                                            const typename valarray<T>::value_type&);
template<class T> valarray<bool> operator>=(const typename valarray<T>::value_type&,
                                            const valarray<T>&);
template<class T> valarray<bool> operator&&(const valarray<T>&,
                                            const typename valarray<T>::value_type&);
template<class T> valarray<bool> operator&&(const typename valarray<T>::value_type&,
                                            const valarray<T>&);
template<class T> valarray<bool> operator||(const valarray<T>&,
                                            const typename valarray<T>::value_type&);
template<class T> valarray<bool> operator||(const typename valarray<T>::value_type&,
                                            const valarray<T>&);
\end{itemdecl}

\begin{itemdescr}
\pnum
\mandates
The indicated operator can be applied to operands of type \tcode{T} and returns
a value of type \tcode{bool} or which can be unambiguously
implicitly converted to \tcode{bool}.

\pnum
\returns
A \tcode{valarray<bool>} whose
length is equal to the length of the array argument.
Each element
of the returned array is initialized with the result of applying the
indicated operator to the corresponding element of the array and the non-array argument.
\end{itemdescr}

\rSec3[valarray.transcend]{Transcendentals}

\indexlibrarymember{abs}{valarray}%
\indexlibrarymember{acos}{valarray}%
\indexlibrarymember{asin}{valarray}%
\indexlibrarymember{atan}{valarray}%
\indexlibrarymember{atan2}{valarray}%
\indexlibrarymember{cos}{valarray}%
\indexlibrarymember{cosh}{valarray}%
\indexlibrarymember{exp}{valarray}%
\indexlibrarymember{log}{valarray}%
\indexlibrarymember{log10}{valarray}%
\indexlibrarymember{pow}{valarray}%
\indexlibrarymember{sin}{valarray}%
\indexlibrarymember{sinh}{valarray}%
\indexlibrarymember{sqrt}{valarray}%
\indexlibrarymember{tan}{valarray}%
\indexlibrarymember{tanh}{valarray}%
\begin{itemdecl}
template<class T> valarray<T> abs  (const valarray<T>&);
template<class T> valarray<T> acos (const valarray<T>&);
template<class T> valarray<T> asin (const valarray<T>&);
template<class T> valarray<T> atan (const valarray<T>&);
template<class T> valarray<T> atan2(const valarray<T>&, const valarray<T>&);
template<class T> valarray<T> atan2(const valarray<T>&, const typename valarray<T>::value_type&);
template<class T> valarray<T> atan2(const typename valarray<T>::value_type&, const valarray<T>&);
template<class T> valarray<T> cos  (const valarray<T>&);
template<class T> valarray<T> cosh (const valarray<T>&);
template<class T> valarray<T> exp  (const valarray<T>&);
template<class T> valarray<T> log  (const valarray<T>&);
template<class T> valarray<T> log10(const valarray<T>&);
template<class T> valarray<T> pow  (const valarray<T>&, const valarray<T>&);
template<class T> valarray<T> pow  (const valarray<T>&, const typename valarray<T>::value_type&);
template<class T> valarray<T> pow  (const typename valarray<T>::value_type&, const valarray<T>&);
template<class T> valarray<T> sin  (const valarray<T>&);
template<class T> valarray<T> sinh (const valarray<T>&);
template<class T> valarray<T> sqrt (const valarray<T>&);
template<class T> valarray<T> tan  (const valarray<T>&);
template<class T> valarray<T> tanh (const valarray<T>&);
\end{itemdecl}

\begin{itemdescr}
\pnum
\mandates
A unique function with the indicated name can be applied (unqualified)
to an operand of type \tcode{T}.
This function returns a value of type \tcode{T}
or which can be unambiguously implicitly converted to type \tcode{T}.

\end{itemdescr}

\rSec3[valarray.special]{Specialized algorithms}

\indexlibrarymember{swap}{valarray}%
\begin{itemdecl}
template<class T> void swap(valarray<T>& x, valarray<T>& y) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to \tcode{x.swap(y)}.
\end{itemdescr}


\rSec2[class.slice]{Class \tcode{slice}}

\rSec3[class.slice.overview]{Overview}

\indexlibraryglobal{slice}%
\begin{codeblock}
namespace std {
  class slice {
  public:
    slice();
    slice(size_t, size_t, size_t);
    slice(const slice&);

    size_t start() const;
    size_t size() const;
    size_t stride() const;

    friend bool operator==(const slice& x, const slice& y);
  };
}
\end{codeblock}

\pnum
The \tcode{slice}
class represents a BLAS-like slice from an array.
Such a slice is specified by a starting index, a length, and a
stride.
\begin{footnote}
BLAS stands for
\textit{Basic Linear Algebra Subprograms}.
\Cpp{} programs can instantiate this class.
See, for example,
Dongarra, Du Croz, Duff, and Hammerling:
\textit{A set of Level 3 Basic Linear Algebra Subprograms};
Technical Report MCS-P1-0888,
Argonne National Laboratory (USA),
Mathematics and Computer Science Division,
August, 1988.
\end{footnote}

\rSec3[cons.slice]{Constructors}

\indexlibraryctor{slice}%
\begin{itemdecl}
slice();
slice(size_t start, size_t length, size_t stride);
\end{itemdecl}

\begin{itemdescr}
\pnum
The default constructor is equivalent to \tcode{slice(0, 0, 0)}.
A default constructor is provided only to permit the declaration of arrays of slices.
The constructor with arguments for a slice takes a start, length, and stride
parameter.

\pnum
\begin{example}
\tcode{slice(3, 8, 2)}
constructs a slice which selects elements $3, 5, 7, \dotsc, 17$ from an array.
\end{example}
\end{itemdescr}

\rSec3[slice.access]{Access functions}
\indexlibrarymember{start}{slice}%
\indexlibrarymember{size}{slice}%
\indexlibrarymember{stride}{slice}%
\begin{itemdecl}
size_t start() const;
size_t size() const;
size_t stride() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
The start, length, or stride specified
by a \tcode{slice} object.

\pnum
\complexity
Constant time.
\end{itemdescr}

\rSec3[slice.ops]{Operators}

\indexlibrarymember{stride}{slice}%
\begin{itemdecl}
friend bool operator==(const slice& x, const slice& y);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
return x.start() == y.start() && x.size() == y.size() && x.stride() == y.stride();
\end{codeblock}
\end{itemdescr}

\rSec2[template.slice.array]{Class template \tcode{slice_array}}

\rSec3[template.slice.array.overview]{Overview}

\indexlibraryglobal{slice_array}%
\indexlibrarymember{value_type}{slice_array}%
\begin{codeblock}
namespace std {
  template<class T> class slice_array {
  public:
    using value_type = T;

    void operator=  (const valarray<T>&) const;
    void operator*= (const valarray<T>&) const;
    void operator/= (const valarray<T>&) const;
    void operator%= (const valarray<T>&) const;
    void operator+= (const valarray<T>&) const;
    void operator-= (const valarray<T>&) const;
    void operator^= (const valarray<T>&) const;
    void operator&= (const valarray<T>&) const;
    void operator|= (const valarray<T>&) const;
    void operator<<=(const valarray<T>&) const;
    void operator>>=(const valarray<T>&) const;

    slice_array(const slice_array&);
    ~slice_array();
    const slice_array& operator=(const slice_array&) const;
    void operator=(const T&) const;

    slice_array() = delete;     // as implied by declaring copy constructor above
  };
}
\end{codeblock}

\pnum
This template is a helper template used by the
\tcode{slice} subscript operator
\begin{codeblock}
slice_array<T> valarray<T>::operator[](slice);
\end{codeblock}

\pnum
It has reference semantics to a subset of an array specified by a
\tcode{slice}
object.
\begin{example}
The expression
\tcode{a[slice(1, 5, 3)] = b;}
has the effect of assigning the elements of
\tcode{b}
to a slice of the elements in
\tcode{a}.
For the slice shown, the elements
selected from
\tcode{a}
are $1, 4, \dotsc, 13$.
\end{example}

\rSec3[slice.arr.assign]{Assignment}

\indexlibrarymember{operator=}{slice_array}%
\begin{itemdecl}
void operator=(const valarray<T>&) const;
const slice_array& operator=(const slice_array&) const;
\end{itemdecl}

\begin{itemdescr}
\pnum
These assignment operators have reference semantics,
assigning the values of the argument array elements to selected
elements of the
\tcode{valarray<T>}
object to which the
\tcode{slice_array}
object refers.
\end{itemdescr}

\rSec3[slice.arr.comp.assign]{Compound assignment}

\indexlibrarymember{operator*=}{slice_array}%
\indexlibrarymember{operator/=}{slice_array}%
\indexlibrarymember{operator\%=}{slice_array}%
\indexlibrarymember{operator+=}{slice_array}%
\indexlibrarymember{operator-=}{slice_array}%
\indexlibrarymember{operator\caret=}{slice_array}%
\indexlibrarymember{operator\&=}{slice_array}%
\indexlibrarymember{operator"|=}{slice_array}%
\indexlibrarymember{operator<<=}{slice_array}%
\indexlibrarymember{operator>>=}{slice_array}%
\begin{itemdecl}
void operator*= (const valarray<T>&) const;
void operator/= (const valarray<T>&) const;
void operator%= (const valarray<T>&) const;
void operator+= (const valarray<T>&) const;
void operator-= (const valarray<T>&) const;
void operator^= (const valarray<T>&) const;
void operator&= (const valarray<T>&) const;
void operator|= (const valarray<T>&) const;
void operator<<=(const valarray<T>&) const;
void operator>>=(const valarray<T>&) const;
\end{itemdecl}

\begin{itemdescr}
\pnum
These compound assignments have reference semantics, applying the
indicated operation to the elements of the argument array
and selected elements of the
\tcode{valarray<T>}
object to which the
\tcode{slice_array}
object refers.
\end{itemdescr}

\rSec3[slice.arr.fill]{Fill function}

\indexlibrarymember{operator=}{slice_array}%
\begin{itemdecl}
void operator=(const T&) const;
\end{itemdecl}

\begin{itemdescr}
\pnum
This function has reference semantics, assigning the value of its argument
to the elements of the
\tcode{valarray<T>}
object to which the
\tcode{slice_array}
object refers.
\end{itemdescr}

\rSec2[class.gslice]{The \tcode{gslice} class}

\rSec3[class.gslice.overview]{Overview}

\indexlibraryglobal{gslice}%
\begin{codeblock}
namespace std {
  class gslice {
  public:
    gslice();
    gslice(size_t s, const valarray<size_t>& l, const valarray<size_t>& d);

    size_t           start() const;
    valarray<size_t> size() const;
    valarray<size_t> stride() const;
  };
}
\end{codeblock}

\pnum
This class represents a generalized slice out of an array.
A
\tcode{gslice}
is defined by a starting offset ($s$),
a set of lengths ($l_j$),
and a set of strides ($d_j$).
The number of lengths shall equal the number of strides.

\pnum
A
\tcode{gslice}
represents a mapping from a set of indices ($i_j$),
equal in number to the number of strides, to a single index $k$.
It is useful for building multidimensional array classes using
the
\tcode{valarray}
template, which is one-dimensional.
The set of one-dimensional index values specified by a \tcode{gslice} are
\[ k = s + \sum_j i_j d_j \]
where the multidimensional indices $i_j$ range in value from
0 to $l_{ij} - 1$.

\pnum
\begin{example}
The
\tcode{gslice}
specification
\begin{codeblock}
start  = 3
length = {2, 4, 3}
stride = {19, 4, 1}
\end{codeblock}
yields the sequence of one-dimensional indices
\[ k = 3 + (0, 1) \times 19 + (0, 1, 2, 3) \times 4 + (0, 1, 2) \times 1 \]
which are ordered as shown in the following table:

\begin{tabbing}
\hspace{.5in}\=\hspace{.4in}\=\kill%
\>$(i_0,\quad i_1,\quad i_2,\quad k)\quad =$\\
\>\>$(0,\quad 0,\quad 0,\quad \ 3)$,    \\
\>\>$(0,\quad 0,\quad 1,\quad \ 4)$,    \\
\>\>$(0,\quad 0,\quad 2,\quad \ 5)$,    \\
\>\>$(0,\quad 1,\quad 0,\quad \ 7)$,    \\
\>\>$(0,\quad 1,\quad 1,\quad \ 8)$,    \\
\>\>$(0,\quad 1,\quad 2,\quad \ 9)$,    \\
\>\>$(0,\quad 2,\quad 0,\quad 11)$, \\
\>\>$(0,\quad 2,\quad 1,\quad 12)$, \\
\>\>$(0,\quad 2,\quad 2,\quad 13)$, \\
\>\>$(0,\quad 3,\quad 0,\quad 15)$, \\
\>\>$(0,\quad 3,\quad 1,\quad 16)$, \\
\>\>$(0,\quad 3,\quad 2,\quad 17)$, \\
\>\>$(1,\quad 0,\quad 0,\quad 22)$, \\
\>\>$(1,\quad 0,\quad 1,\quad 23)$, \\
\>\>$\ldots$      \\
\>\>$(1,\quad 3,\quad 2,\quad 36)$
\end{tabbing}

That is, the highest-ordered index turns fastest.
\end{example}

\pnum
It is possible to have degenerate generalized slices in which an address
is repeated.

\pnum
\begin{example}
If the stride parameters in the previous
example are changed to \{1, 1, 1\}, the first few elements of the
resulting sequence of indices will be

\begin{tabbing}
\hspace{.9in}\=\kill%
\>$(0,\quad 0,\quad 0,\quad \ 3)$,  \\
\>$(0,\quad 0,\quad 1,\quad \ 4)$,  \\
\>$(0,\quad 0,\quad 2,\quad \ 5)$,  \\
\>$(0,\quad 1,\quad 0,\quad \ 4)$,  \\
\>$(0,\quad 1,\quad 1,\quad \ 5)$,  \\
\>$(0,\quad 1,\quad 2,\quad \ 6)$,  \\
\>$\ldots$
\end{tabbing}
\end{example}

\pnum
If a degenerate slice is used as the argument to the
non-\keyword{const}
version of
\tcode{operator[](const gslice\&)},
the behavior is undefined.
\indextext{undefined}%

\rSec3[gslice.cons]{Constructors}

\indexlibraryctor{gslice}%
\begin{itemdecl}
gslice();
gslice(size_t start, const valarray<size_t>& lengths,
       const valarray<size_t>& strides);
\end{itemdecl}

\begin{itemdescr}
\pnum
The default constructor is equivalent to
\tcode{gslice(0, valarray<size_t>(), valarray<size_t>())}.
The constructor with arguments builds a
\tcode{gslice}
based on a specification of start, lengths, and strides, as explained
in the previous subclause.
\end{itemdescr}

\rSec3[gslice.access]{Access functions}

\indexlibrarymember{start}{gslice}%
\indexlibrarymember{size}{gslice}%
\indexlibrarymember{stride}{gslice}%
\begin{itemdecl}
size_t           start()  const;
valarray<size_t> size() const;
valarray<size_t> stride() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
The representation of the
start, lengths, or strides specified for the \tcode{gslice}.

\pnum
\complexity
\tcode{start()} is constant time. \tcode{size()} and \tcode{stride()}
are linear in the number of strides.
\end{itemdescr}

\rSec2[template.gslice.array]{Class template \tcode{gslice_array}}

\rSec3[template.gslice.array.overview]{Overview}

\indexlibraryglobal{gslice_array}%
\indexlibrarymember{value_type}{gslice_array}%
\begin{codeblock}
namespace std {
  template<class T> class gslice_array {
  public:
    using value_type = T;

    void operator=  (const valarray<T>&) const;
    void operator*= (const valarray<T>&) const;
    void operator/= (const valarray<T>&) const;
    void operator%= (const valarray<T>&) const;
    void operator+= (const valarray<T>&) const;
    void operator-= (const valarray<T>&) const;
    void operator^= (const valarray<T>&) const;
    void operator&= (const valarray<T>&) const;
    void operator|= (const valarray<T>&) const;
    void operator<<=(const valarray<T>&) const;
    void operator>>=(const valarray<T>&) const;

    gslice_array(const gslice_array&);
    ~gslice_array();
    const gslice_array& operator=(const gslice_array&) const;
    void operator=(const T&) const;

    gslice_array() = delete;    // as implied by declaring copy constructor above
  };
}
\end{codeblock}

\pnum
This template is a helper template used by the
\tcode{gslice}
subscript operator

\indexlibraryglobal{gslice_array}%
\indexlibraryglobal{valarray}%
\begin{itemdecl}
gslice_array<T> valarray<T>::operator[](const gslice&);
\end{itemdecl}

\pnum
It has reference semantics to a subset of an array specified by a
\tcode{gslice}
object.
Thus, the expression
\tcode{a[gslice(1, length, stride)] = b}
has the effect of assigning the elements of
\tcode{b}
to a
generalized slice of the elements in
\tcode{a}.

\rSec3[gslice.array.assign]{Assignment}

\indexlibrarymember{operator=}{gslice_array}%
\begin{itemdecl}
void operator=(const valarray<T>&) const;
const gslice_array& operator=(const gslice_array&) const;
\end{itemdecl}

\begin{itemdescr}
\pnum
These assignment operators have reference semantics, assigning the values
of the argument array elements to selected elements of the
\tcode{valarray<T>}
object to which the
\tcode{gslice_array}
refers.
\end{itemdescr}

\rSec3[gslice.array.comp.assign]{Compound assignment}

\indexlibrarymember{operator*=}{gslice_array}%
\indexlibrarymember{operator/=}{gslice_array}%
\indexlibrarymember{operator\%=}{gslice_array}%
\indexlibrarymember{operator+=}{gslice_array}%
\indexlibrarymember{operator-=}{gslice_array}%
\indexlibrarymember{operator\caret=}{gslice_array}%
\indexlibrarymember{operator\&=}{gslice_array}%
\indexlibrarymember{operator"|=}{gslice_array}%
\indexlibrarymember{operator<<=}{gslice_array}%
\indexlibrarymember{operator>>=}{gslice_array}%
\begin{itemdecl}
void operator*= (const valarray<T>&) const;
void operator/= (const valarray<T>&) const;
void operator%= (const valarray<T>&) const;
void operator+= (const valarray<T>&) const;
void operator-= (const valarray<T>&) const;
void operator^= (const valarray<T>&) const;
void operator&= (const valarray<T>&) const;
void operator|= (const valarray<T>&) const;
void operator<<=(const valarray<T>&) const;
void operator>>=(const valarray<T>&) const;
\end{itemdecl}

\begin{itemdescr}
\pnum
These compound assignments have reference semantics, applying the
indicated operation to the elements of the argument array and selected
elements of the
\tcode{valarray<T>}
object to which the
\tcode{gslice_array}
object refers.
\end{itemdescr}

\rSec3[gslice.array.fill]{Fill function}

\indexlibrarymember{operator=}{gslice_array}%
\begin{itemdecl}
void operator=(const T&) const;
\end{itemdecl}

\begin{itemdescr}
\pnum
This function has reference semantics, assigning the value of its argument
to the elements of the
\tcode{valarray<T>}
object to which the
\tcode{gslice_array}
object refers.
\end{itemdescr}

\rSec2[template.mask.array]{Class template \tcode{mask_array}}

\rSec3[template.mask.array.overview]{Overview}

\indexlibraryglobal{mask_array}%
\indexlibrarymember{value_type}{mask_array}%
\begin{codeblock}
namespace std {
  template<class T> class mask_array {
  public:
    using value_type = T;

    void operator=  (const valarray<T>&) const;
    void operator*= (const valarray<T>&) const;
    void operator/= (const valarray<T>&) const;
    void operator%= (const valarray<T>&) const;
    void operator+= (const valarray<T>&) const;
    void operator-= (const valarray<T>&) const;
    void operator^= (const valarray<T>&) const;
    void operator&= (const valarray<T>&) const;
    void operator|= (const valarray<T>&) const;
    void operator<<=(const valarray<T>&) const;
    void operator>>=(const valarray<T>&) const;

    mask_array(const mask_array&);
    ~mask_array();
    const mask_array& operator=(const mask_array&) const;
    void operator=(const T&) const;

    mask_array() = delete;      // as implied by declaring copy constructor above
  };
}
\end{codeblock}

\pnum
This template is a helper template used by the mask subscript operator:

\indexlibrarymember{operator[]}{mask_array}%
\begin{itemdecl}
mask_array<T> valarray<T>::operator[](const valarray<bool>&);
\end{itemdecl}

\pnum
It has reference semantics to a subset of an array specified by a boolean mask.
Thus, the expression \tcode{a[mask] = b;}
has the effect of assigning the elements of
\tcode{b} to the masked elements in \tcode{a}
(those for which the corresponding element in
\tcode{mask} is \tcode{true}).

\rSec3[mask.array.assign]{Assignment}

\indexlibrarymember{operator=}{mask_array}%
\begin{itemdecl}
void operator=(const valarray<T>&) const;
const mask_array& operator=(const mask_array&) const;
\end{itemdecl}

\begin{itemdescr}
\pnum
These assignment operators have reference semantics, assigning the values
of the argument array elements to selected elements of the
\tcode{valarray<T>}
object to which the \tcode{mask_array} object refers.
\end{itemdescr}

\rSec3[mask.array.comp.assign]{Compound assignment}

\indexlibrarymember{operator*=}{mask_array}%
\indexlibrarymember{operator/=}{mask_array}%
\indexlibrarymember{operator\%=}{mask_array}%
\indexlibrarymember{operator+=}{mask_array}%
\indexlibrarymember{operator-=}{mask_array}%
\indexlibrarymember{operator\caret=}{mask_array}%
\indexlibrarymember{operator\&=}{mask_array}%
\indexlibrarymember{operator"|=}{mask_array}%
\indexlibrarymember{operator<<=}{mask_array}%
\indexlibrarymember{operator>>=}{mask_array}%
\begin{itemdecl}
void operator*= (const valarray<T>&) const;
void operator/= (const valarray<T>&) const;
void operator%= (const valarray<T>&) const;
void operator+= (const valarray<T>&) const;
void operator-= (const valarray<T>&) const;
void operator^= (const valarray<T>&) const;
void operator&= (const valarray<T>&) const;
void operator|= (const valarray<T>&) const;
void operator<<=(const valarray<T>&) const;
void operator>>=(const valarray<T>&) const;
\end{itemdecl}

\begin{itemdescr}
\pnum
These compound assignments have reference semantics, applying the
indicated operation to the elements of the argument array and selected elements
of the
\tcode{valarray<T>}
object to which the \tcode{mask_array} object refers.
\end{itemdescr}

\rSec3[mask.array.fill]{Fill function}

\indexlibrarymember{operator=}{mask_array}%
\begin{itemdecl}
void operator=(const T&) const;
\end{itemdecl}

\begin{itemdescr}
\pnum
This function has reference semantics, assigning the value of its
argument to the elements of the
\tcode{valarray<T>}
object to which the
\tcode{mask_array}
object refers.
\end{itemdescr}

\rSec2[template.indirect.array]{Class template \tcode{indirect_array}}

\rSec3[template.indirect.array.overview]{Overview}

\indexlibraryglobal{indirect_array}%
\indexlibrarymember{value_type}{indirect_array}%
\begin{codeblock}
namespace std {
  template<class T> class indirect_array {
  public:
    using value_type = T;

    void operator=  (const valarray<T>&) const;
    void operator*= (const valarray<T>&) const;
    void operator/= (const valarray<T>&) const;
    void operator%= (const valarray<T>&) const;
    void operator+= (const valarray<T>&) const;
    void operator-= (const valarray<T>&) const;
    void operator^= (const valarray<T>&) const;
    void operator&= (const valarray<T>&) const;
    void operator|= (const valarray<T>&) const;
    void operator<<=(const valarray<T>&) const;
    void operator>>=(const valarray<T>&) const;

    indirect_array(const indirect_array&);
    ~indirect_array();
    const indirect_array& operator=(const indirect_array&) const;
    void operator=(const T&) const;

    indirect_array() = delete;  // as implied by declaring copy constructor above
  };
}
\end{codeblock}

\pnum
This template is a helper template used by the indirect subscript operator

\indexlibrarymember{operator[]}{indirect_array}%
\begin{itemdecl}
indirect_array<T> valarray<T>::operator[](const valarray<size_t>&);
\end{itemdecl}

\pnum
It has reference semantics to a subset of an array specified by an
\tcode{indirect_array}.
Thus, the expression
\tcode{a[\brk{}indirect] = b;}
has the effect of assigning the elements of
\tcode{b}
to the elements in
\tcode{a}
whose indices appear in
\tcode{indirect}.

\rSec3[indirect.array.assign]{Assignment}

\indexlibrarymember{operator=}{indirect_array}%
\begin{itemdecl}
void operator=(const valarray<T>&) const;
const indirect_array& operator=(const indirect_array&) const;
\end{itemdecl}

\begin{itemdescr}
\pnum
These assignment operators have reference semantics, assigning the values
of the argument array elements to selected elements of the
\tcode{valarray<T>}
object to which it refers.

\pnum
If the
\tcode{indirect_array}
specifies an element in the
\tcode{valarray<T>}
object to which it refers more than once, the behavior is undefined.
\indextext{undefined}%

\pnum
\begin{example}
\begin{codeblock}
int addr[] = {2, 3, 1, 4, 4};
valarray<size_t> indirect(addr, 5);
valarray<double> a(0., 10), b(1., 5);
a[indirect] = b;
\end{codeblock}
results in undefined behavior since element 4 is specified twice in the
indirection.
\end{example}
\end{itemdescr}

\rSec3[indirect.array.comp.assign]{Compound assignment}

\indexlibrarymember{operator*=}{indirect_array}%
\indexlibrarymember{operator/=}{indirect_array}%
\indexlibrarymember{operator\%=}{indirect_array}%
\indexlibrarymember{operator+=}{indirect_array}%
\indexlibrarymember{operator-=}{indirect_array}%
\indexlibrarymember{operator\caret=}{indirect_array}%
\indexlibrarymember{operator\&=}{indirect_array}%
\indexlibrarymember{operator"|=}{indirect_array}%
\indexlibrarymember{operator<<=}{indirect_array}%
\indexlibrarymember{operator>>=}{indirect_array}%
\begin{itemdecl}
void operator*= (const valarray<T>&) const;
void operator/= (const valarray<T>&) const;
void operator%= (const valarray<T>&) const;
void operator+= (const valarray<T>&) const;
void operator-= (const valarray<T>&) const;
void operator^= (const valarray<T>&) const;
void operator&= (const valarray<T>&) const;
void operator|= (const valarray<T>&) const;
void operator<<=(const valarray<T>&) const;
void operator>>=(const valarray<T>&) const;
\end{itemdecl}

\begin{itemdescr}
\pnum
These compound assignments have reference semantics, applying the indicated
operation to the elements of the argument array and selected elements of the
\tcode{valarray<T>}
object to which the
\tcode{indirect_array}
object refers.

\pnum
If the
\tcode{indirect_array}
specifies an element in the
\tcode{valarray<T>}
object to which it refers more than once,
the behavior is undefined.
\indextext{undefined}
\end{itemdescr}

\rSec3[indirect.array.fill]{Fill function}

\indexlibrarymember{operator=}{indirect_array}%
\begin{itemdecl}
void operator=(const T&) const;
\end{itemdecl}

\begin{itemdescr}
\pnum
This function has reference semantics, assigning the value of its argument
to the elements of the
\tcode{valarray<T>}
object to which the
\tcode{indirect_array}
object refers.
\end{itemdescr}

\rSec2[valarray.range]{Range access}

\pnum
The \tcode{iterator} type
is a type that meets the requirements of a mutable
\oldconcept{RandomAccessIterator}\iref{random.access.iterators}
and models \libconcept{contiguous_iterator}\iref{iterator.concept.contiguous}.
Its \tcode{value_type} is the template
parameter \tcode{T} and its \tcode{reference} type is \tcode{T\&}.
The \tcode{const_iterator} type meets the requirements of a constant
\oldconcept{RandomAccessIterator}
and models \libconcept{contiguous_iterator}.
Its \tcode{value_type} is the template
parameter \tcode{T} and its \tcode{reference} type is \tcode{const T\&}.

\pnum
The iterators returned by \tcode{begin} and \tcode{end} for an array
are guaranteed to be valid until the member function
\tcode{resize(size_t, T)}\iref{valarray.members} is called for that
array or until the lifetime of that array ends, whichever happens
first.

\indexlibrarymember{begin}{valarray}%
\begin{itemdecl}
iterator begin();
const_iterator begin() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
An iterator referencing the first value in the array.
\end{itemdescr}

\indexlibrarymember{end}{valarray}%
\begin{itemdecl}
iterator end();
const_iterator end() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
An iterator referencing one past the last value in the array.
\end{itemdescr}

\rSec1[c.math]{Mathematical functions for floating-point types}

\rSec2[cmath.syn]{Header \tcode{<cmath>} synopsis}

\indexheader{cmath}%
\indexlibraryglobal{abs}%
\indexlibraryglobal{acos}%
\indexlibraryglobal{acosf}%
\indexlibraryglobal{acosh}%
\indexlibraryglobal{acoshf}%
\indexlibraryglobal{acoshl}%
\indexlibraryglobal{acosl}%
\indexlibraryglobal{asin}%
\indexlibraryglobal{asinf}%
\indexlibraryglobal{asinh}%
\indexlibraryglobal{asinhf}%
\indexlibraryglobal{asinhl}%
\indexlibraryglobal{asinl}%
\indexlibraryglobal{atan}%
\indexlibraryglobal{atan2}%
\indexlibraryglobal{atan2f}%
\indexlibraryglobal{atan2l}%
\indexlibraryglobal{atanf}%
\indexlibraryglobal{atanh}%
\indexlibraryglobal{atanhf}%
\indexlibraryglobal{atanhl}%
\indexlibraryglobal{atanl}%
\indexlibraryglobal{cbrt}%
\indexlibraryglobal{cbrtf}%
\indexlibraryglobal{cbrtl}%
\indexlibraryglobal{ceil}%
\indexlibraryglobal{ceilf}%
\indexlibraryglobal{ceill}%
\indexlibraryglobal{copysign}%
\indexlibraryglobal{copysignf}%
\indexlibraryglobal{copysignl}%
\indexlibraryglobal{cos}%
\indexlibraryglobal{cosf}%
\indexlibraryglobal{cosh}%
\indexlibraryglobal{coshf}%
\indexlibraryglobal{coshl}%
\indexlibraryglobal{cosl}%
\indexlibraryglobal{double_t}%
\indexlibraryglobal{erf}%
\indexlibraryglobal{erfc}%
\indexlibraryglobal{erfcf}%
\indexlibraryglobal{erfcl}%
\indexlibraryglobal{erff}%
\indexlibraryglobal{erfl}%
\indexlibraryglobal{exp}%
\indexlibraryglobal{exp2}%
\indexlibraryglobal{exp2f}%
\indexlibraryglobal{exp2l}%
\indexlibraryglobal{expf}%
\indexlibraryglobal{expl}%
\indexlibraryglobal{expm1}%
\indexlibraryglobal{expm1f}%
\indexlibraryglobal{expm1l}%
\indexlibraryglobal{fabs}%
\indexlibraryglobal{fabsf}%
\indexlibraryglobal{fabsl}%
\indexlibraryglobal{fdim}%
\indexlibraryglobal{fdimf}%
\indexlibraryglobal{fdiml}%
\indexlibraryglobal{float_t}%
\indexlibraryglobal{floor}%
\indexlibraryglobal{floorf}%
\indexlibraryglobal{floorl}%
\indexlibraryglobal{fma}%
\indexlibraryglobal{fmaf}%
\indexlibraryglobal{fmal}%
\indexlibraryglobal{fmax}%
\indexlibraryglobal{fmaxf}%
\indexlibraryglobal{fmaxl}%
\indexlibraryglobal{fmaximum}%
\indexlibraryglobal{fmaximum_num}%
\indexlibraryglobal{fmin}%
\indexlibraryglobal{fminf}%
\indexlibraryglobal{fminl}%
\indexlibraryglobal{fminimum}%
\indexlibraryglobal{fminimum_num}%
\indexlibraryglobal{fmod}%
\indexlibraryglobal{fmodf}%
\indexlibraryglobal{fmodl}%
\indexlibraryglobal{fpclassify}%
\indexlibraryglobal{frexp}%
\indexlibraryglobal{frexpf}%
\indexlibraryglobal{frexpl}%
\indexlibraryglobal{hypot}%
\indexlibraryglobal{hypotf}%
\indexlibraryglobal{hypotl}%
\indexlibraryglobal{ilogb}%
\indexlibraryglobal{ilogbf}%
\indexlibraryglobal{ilogbl}%
\indexlibraryglobal{isfinite}%
\indexlibraryglobal{isgreater}%
\indexlibraryglobal{isgreaterequal}%
\indexlibraryglobal{isinf}%
\indexlibraryglobal{isless}%
\indexlibraryglobal{islessequal}%
\indexlibraryglobal{islessgreater}%
\indexlibraryglobal{isnan}%
\indexlibraryglobal{isnormal}%
\indexlibraryglobal{isunordered}%
\indexlibraryglobal{ldexp}%
\indexlibraryglobal{ldexpf}%
\indexlibraryglobal{ldexpl}%
\indexlibraryglobal{lgamma}%
\indexlibraryglobal{lgammaf}%
\indexlibraryglobal{lgammal}%
\indexlibraryglobal{llrint}%
\indexlibraryglobal{llrintf}%
\indexlibraryglobal{llrintl}%
\indexlibraryglobal{llround}%
\indexlibraryglobal{llroundf}%
\indexlibraryglobal{llroundl}%
\indexlibraryglobal{log}%
\indexlibraryglobal{log10}%
\indexlibraryglobal{log10f}%
\indexlibraryglobal{log10l}%
\indexlibraryglobal{log1p}%
\indexlibraryglobal{log1pf}%
\indexlibraryglobal{log1pl}%
\indexlibraryglobal{log2}%
\indexlibraryglobal{log2f}%
\indexlibraryglobal{log2l}%
\indexlibraryglobal{logb}%
\indexlibraryglobal{logbf}%
\indexlibraryglobal{logbl}%
\indexlibraryglobal{logf}%
\indexlibraryglobal{logl}%
\indexlibraryglobal{lrint}%
\indexlibraryglobal{lrintf}%
\indexlibraryglobal{lrintl}%
\indexlibraryglobal{lround}%
\indexlibraryglobal{lroundf}%
\indexlibraryglobal{lroundl}%
\indexlibraryglobal{modf}%
\indexlibraryglobal{modff}%
\indexlibraryglobal{modfl}%
\indexlibraryglobal{nan}%
\indexlibraryglobal{nanf}%
\indexlibraryglobal{nanl}%
\indexlibraryglobal{nearbyint}%
\indexlibraryglobal{nearbyintf}%
\indexlibraryglobal{nearbyintl}%
\indexlibraryglobal{nextafter}%
\indexlibraryglobal{nextafterf}%
\indexlibraryglobal{nextafterl}%
\indexlibraryglobal{nexttoward}%
\indexlibraryglobal{nexttowardf}%
\indexlibraryglobal{nexttowardl}%
\indexlibraryglobal{nextup}%
\indexlibraryglobal{nextupf}%
\indexlibraryglobal{nextupl}%
\indexlibraryglobal{nextdown}%
\indexlibraryglobal{nextdownf}%
\indexlibraryglobal{nextdownl}%
\indexlibraryglobal{pow}%
\indexlibraryglobal{powf}%
\indexlibraryglobal{powl}%
\indexlibraryglobal{remainder}%
\indexlibraryglobal{remainderf}%
\indexlibraryglobal{remainderl}%
\indexlibraryglobal{remquo}%
\indexlibraryglobal{remquof}%
\indexlibraryglobal{remquol}%
\indexlibraryglobal{rint}%
\indexlibraryglobal{rintf}%
\indexlibraryglobal{rintl}%
\indexlibraryglobal{round}%
\indexlibraryglobal{roundf}%
\indexlibraryglobal{roundl}%
\indexlibraryglobal{scalbln}%
\indexlibraryglobal{scalblnf}%
\indexlibraryglobal{scalblnl}%
\indexlibraryglobal{scalbn}%
\indexlibraryglobal{scalbnf}%
\indexlibraryglobal{scalbnl}%
\indexlibraryglobal{signbit}%
\indexlibraryglobal{sin}%
\indexlibraryglobal{sinf}%
\indexlibraryglobal{sinh}%
\indexlibraryglobal{sinhf}%
\indexlibraryglobal{sinhl}%
\indexlibraryglobal{sinl}%
\indexlibraryglobal{sqrt}%
\indexlibraryglobal{sqrtf}%
\indexlibraryglobal{sqrtl}%
\indexlibraryglobal{tan}%
\indexlibraryglobal{tanf}%
\indexlibraryglobal{tanh}%
\indexlibraryglobal{tanhf}%
\indexlibraryglobal{tanhl}%
\indexlibraryglobal{tanl}%
\indexlibraryglobal{tgamma}%
\indexlibraryglobal{tgammaf}%
\indexlibraryglobal{tgammal}%
\indexlibraryglobal{trunc}%
\indexlibraryglobal{truncf}%
\indexlibraryglobal{truncl}%
\begin{codeblock}
#define @\libmacro{HUGE_VAL}@ @\seebelow@
#define @\libmacro{HUGE_VALF}@ @\seebelow@
#define @\libmacro{HUGE_VALL}@ @\seebelow@
#define @\libmacro{INFINITY}@ @\seebelow@
#define @\libmacro{NAN}@ @\seebelow@
#define @\libmacro{FP_INFINITE}@ @\seebelow@
#define @\libmacro{FP_NAN}@ @\seebelow@
#define @\libmacro{FP_NORMAL}@ @\seebelow@
#define @\libmacro{FP_SUBNORMAL}@ @\seebelow@
#define @\libmacro{FP_ZERO}@ @\seebelow@
#define @\libmacro{FP_FAST_FMA}@ @\seebelow@
#define @\libmacro{FP_FAST_FMAF}@ @\seebelow@
#define @\libmacro{FP_FAST_FMAL}@ @\seebelow@
#define @\libmacro{FP_ILOGB0}@ @\seebelow@
#define @\libmacro{FP_ILOGBNAN}@ @\seebelow@
#define @\libmacro{MATH_ERRNO}@ @\seebelow@
#define @\libmacro{MATH_ERREXCEPT}@ @\seebelow@

#define @\libmacro{math_errhandling}@ @\seebelow@

namespace std {
  using float_t = @\seebelow@;
  using double_t = @\seebelow@;

  constexpr @\placeholdernc{floating-point-type}@ acos(@\placeholdernc{floating-point-type}@ x);
  constexpr float               acosf(float x);
  constexpr long double         acosl(long double x);

  constexpr @\placeholdernc{floating-point-type}@ asin(@\placeholdernc{floating-point-type}@ x);
  constexpr float               asinf(float x);
  constexpr long double         asinl(long double x);

  constexpr @\placeholdernc{floating-point-type}@ atan(@\placeholdernc{floating-point-type}@ x);
  constexpr float               atanf(float x);
  constexpr long double         atanl(long double x);

  constexpr @\placeholdernc{floating-point-type}@ atan2(@\placeholdernc{floating-point-type}@ y, @\placeholdernc{floating-point-type}@ x);
  constexpr float               atan2f(float y, float x);
  constexpr long double         atan2l(long double y, long double x);

  constexpr @\placeholdernc{floating-point-type}@ cos(@\placeholdernc{floating-point-type}@ x);
  constexpr float               cosf(float x);
  constexpr long double         cosl(long double x);

  constexpr @\placeholdernc{floating-point-type}@ sin(@\placeholdernc{floating-point-type}@ x);
  constexpr float               sinf(float x);
  constexpr long double         sinl(long double x);

  constexpr @\placeholdernc{floating-point-type}@ tan(@\placeholdernc{floating-point-type}@ x);
  constexpr float               tanf(float x);
  constexpr long double         tanl(long double x);

  constexpr @\placeholdernc{floating-point-type}@ acosh(@\placeholdernc{floating-point-type}@ x);
  constexpr float               acoshf(float x);
  constexpr long double         acoshl(long double x);

  constexpr @\placeholdernc{floating-point-type}@ asinh(@\placeholdernc{floating-point-type}@ x);
  constexpr float               asinhf(float x);
  constexpr long double         asinhl(long double x);

  constexpr @\placeholdernc{floating-point-type}@ atanh(@\placeholdernc{floating-point-type}@ x);
  constexpr float               atanhf(float x);
  constexpr long double         atanhl(long double x);

  constexpr @\placeholdernc{floating-point-type}@ cosh(@\placeholdernc{floating-point-type}@ x);
  constexpr float               coshf(float x);
  constexpr long double         coshl(long double x);

  constexpr @\placeholdernc{floating-point-type}@ sinh(@\placeholdernc{floating-point-type}@ x);
  constexpr float               sinhf(float x);
  constexpr long double         sinhl(long double x);

  constexpr @\placeholdernc{floating-point-type}@ tanh(@\placeholdernc{floating-point-type}@ x);
  constexpr float               tanhf(float x);
  constexpr long double         tanhl(long double x);

  constexpr @\placeholdernc{floating-point-type}@ exp(@\placeholdernc{floating-point-type}@ x);
  constexpr float               expf(float x);
  constexpr long double         expl(long double x);

  constexpr @\placeholdernc{floating-point-type}@ exp2(@\placeholdernc{floating-point-type}@ x);
  constexpr float               exp2f(float x);
  constexpr long double         exp2l(long double x);

  constexpr @\placeholdernc{floating-point-type}@ expm1(@\placeholdernc{floating-point-type}@ x);
  constexpr float               expm1f(float x);
  constexpr long double         expm1l(long double x);

  constexpr @\placeholdernc{floating-point-type}@ frexp(@\placeholdernc{floating-point-type}@ value, int* exp);
  constexpr float               frexpf(float value, int* exp);
  constexpr long double         frexpl(long double value, int* exp);

  constexpr int ilogb(@\placeholdernc{floating-point-type}@ x);
  constexpr int ilogbf(float x);
  constexpr int ilogbl(long double x);

  constexpr @\placeholdernc{floating-point-type}@ ldexp(@\placeholdernc{floating-point-type}@ x, int exp);
  constexpr float               ldexpf(float x, int exp);
  constexpr long double         ldexpl(long double x, int exp);

  constexpr @\placeholdernc{floating-point-type}@ log(@\placeholdernc{floating-point-type}@ x);
  constexpr float               logf(float x);
  constexpr long double         logl(long double x);

  constexpr @\placeholdernc{floating-point-type}@ log10(@\placeholdernc{floating-point-type}@ x);
  constexpr float               log10f(float x);
  constexpr long double         log10l(long double x);

  constexpr @\placeholdernc{floating-point-type}@ log1p(@\placeholdernc{floating-point-type}@ x);
  constexpr float               log1pf(float x);
  constexpr long double         log1pl(long double x);

  constexpr @\placeholdernc{floating-point-type}@ log2(@\placeholdernc{floating-point-type}@ x);
  constexpr float               log2f(float x);
  constexpr long double         log2l(long double x);

  constexpr @\placeholdernc{floating-point-type}@ logb(@\placeholdernc{floating-point-type}@ x);
  constexpr float               logbf(float x);
  constexpr long double         logbl(long double x);

  constexpr @\placeholdernc{floating-point-type}@ modf(@\placeholdernc{floating-point-type}@ value, @\placeholdernc{floating-point-type}@* iptr);
  constexpr float               modff(float value, float* iptr);
  constexpr long double         modfl(long double value, long double* iptr);

  constexpr @\placeholdernc{floating-point-type}@ scalbn(@\placeholdernc{floating-point-type}@ x, int n);
  constexpr float               scalbnf(float x, int n);
  constexpr long double         scalbnl(long double x, int n);

  constexpr @\placeholdernc{floating-point-type}@ scalbln(@\placeholdernc{floating-point-type}@ x, long int n);
  constexpr float               scalblnf(float x, long int n);
  constexpr long double         scalblnl(long double x, long int n);

  constexpr @\placeholdernc{floating-point-type}@ cbrt(@\placeholdernc{floating-point-type}@ x);
  constexpr float               cbrtf(float x);
  constexpr long double         cbrtl(long double x);

  // \ref{c.math.abs}, absolute values
  constexpr int                 abs(int j);                             // freestanding
  constexpr long int            abs(long int j);                        // freestanding
  constexpr long long int       abs(long long int j);                   // freestanding
  constexpr @\placeholdernc{floating-point-type}@ abs(@\placeholdernc{floating-point-type}@ j);             // freestanding-deleted

  constexpr @\placeholdernc{floating-point-type}@ fabs(@\placeholdernc{floating-point-type}@ x);
  constexpr float               fabsf(float x);
  constexpr long double         fabsl(long double x);

  constexpr @\placeholdernc{floating-point-type}@ hypot(@\placeholdernc{floating-point-type}@ x, @\placeholdernc{floating-point-type}@ y);
  constexpr float               hypotf(float x, float y);
  constexpr long double         hypotl(long double x, long double y);

  // \ref{c.math.hypot3}, three-dimensional hypotenuse
  constexpr @\placeholdernc{floating-point-type}@ hypot(@\placeholdernc{floating-point-type}@ x, @\placeholdernc{floating-point-type}@ y,
                                      @\placeholdernc{floating-point-type}@ z);

  constexpr @\placeholdernc{floating-point-type}@ pow(@\placeholdernc{floating-point-type}@ x, @\placeholdernc{floating-point-type}@ y);
  constexpr float               powf(float x, float y);
  constexpr long double         powl(long double x, long double y);

  constexpr @\placeholdernc{floating-point-type}@ sqrt(@\placeholdernc{floating-point-type}@ x);
  constexpr float               sqrtf(float x);
  constexpr long double         sqrtl(long double x);

  constexpr @\placeholdernc{floating-point-type}@ erf(@\placeholdernc{floating-point-type}@ x);
  constexpr float               erff(float x);
  constexpr long double         erfl(long double x);

  constexpr @\placeholdernc{floating-point-type}@ erfc(@\placeholdernc{floating-point-type}@ x);
  constexpr float               erfcf(float x);
  constexpr long double         erfcl(long double x);

  constexpr @\placeholdernc{floating-point-type}@ lgamma(@\placeholdernc{floating-point-type}@ x);
  constexpr float               lgammaf(float x);
  constexpr long double         lgammal(long double x);

  constexpr @\placeholdernc{floating-point-type}@ tgamma(@\placeholdernc{floating-point-type}@ x);
  constexpr float               tgammaf(float x);
  constexpr long double         tgammal(long double x);

  constexpr @\placeholdernc{floating-point-type}@ ceil(@\placeholdernc{floating-point-type}@ x);
  constexpr float               ceilf(float x);
  constexpr long double         ceill(long double x);

  constexpr @\placeholdernc{floating-point-type}@ floor(@\placeholdernc{floating-point-type}@ x);
  constexpr float               floorf(float x);
  constexpr long double         floorl(long double x);

  @\placeholdernc{floating-point-type}@ nearbyint(@\placeholdernc{floating-point-type}@ x);
  float               nearbyintf(float x);
  long double         nearbyintl(long double x);

  @\placeholdernc{floating-point-type}@ rint(@\placeholdernc{floating-point-type}@ x);
  float               rintf(float x);
  long double         rintl(long double x);

  long int lrint(@\placeholdernc{floating-point-type}@ x);
  long int lrintf(float x);
  long int lrintl(long double x);

  long long int llrint(@\placeholdernc{floating-point-type}@ x);
  long long int llrintf(float x);
  long long int llrintl(long double x);

  constexpr @\placeholdernc{floating-point-type}@ round(@\placeholdernc{floating-point-type}@ x);
  constexpr float               roundf(float x);
  constexpr long double         roundl(long double x);

  constexpr long int lround(@\placeholdernc{floating-point-type}@ x);
  constexpr long int lroundf(float x);
  constexpr long int lroundl(long double x);

  constexpr long long int llround(@\placeholdernc{floating-point-type}@ x);
  constexpr long long int llroundf(float x);
  constexpr long long int llroundl(long double x);

  constexpr @\placeholdernc{floating-point-type}@ trunc(@\placeholdernc{floating-point-type}@ x);
  constexpr float               truncf(float x);
  constexpr long double         truncl(long double x);

  constexpr @\placeholdernc{floating-point-type}@ fmod(@\placeholdernc{floating-point-type}@ x, @\placeholdernc{floating-point-type}@ y);
  constexpr float               fmodf(float x, float y);
  constexpr long double         fmodl(long double x, long double y);

  constexpr @\placeholdernc{floating-point-type}@ remainder(@\placeholdernc{floating-point-type}@ x, @\placeholdernc{floating-point-type}@ y);
  constexpr float               remainderf(float x, float y);
  constexpr long double         remainderl(long double x, long double y);

  constexpr @\placeholdernc{floating-point-type}@ remquo(@\placeholdernc{floating-point-type}@ x, @\placeholdernc{floating-point-type}@ y, int* quo);
  constexpr float               remquof(float x, float y, int* quo);
  constexpr long double         remquol(long double x, long double y, int* quo);

  constexpr @\placeholdernc{floating-point-type}@ copysign(@\placeholdernc{floating-point-type}@ x, @\placeholdernc{floating-point-type}@ y);
  constexpr float               copysignf(float x, float y);
  constexpr long double         copysignl(long double x, long double y);

  double      nan(const char* tagp);
  float       nanf(const char* tagp);
  long double nanl(const char* tagp);

  constexpr @\placeholdernc{floating-point-type}@ nextafter(@\placeholdernc{floating-point-type}@ x, @\placeholdernc{floating-point-type}@ y);
  constexpr float               nextafterf(float x, float y);
  constexpr long double         nextafterl(long double x, long double y);

  constexpr @\placeholdernc{floating-point-type}@ nexttoward(@\placeholdernc{floating-point-type}@ x, long double y);
  constexpr float               nexttowardf(float x, long double y);
  constexpr long double         nexttowardl(long double x, long double y);

  constexpr @\placeholdernc{floating-point-type}@ nextup(@\placeholdernc{floating-point-type}@ x);
  constexpr float               nextupf(float x);
  constexpr long double         nextupl(long double x);

  constexpr @\placeholdernc{floating-point-type}@ nextdown(@\placeholdernc{floating-point-type}@ x);
  constexpr float               nextdownf(float x);
  constexpr long double         nextdownl(long double x);

  constexpr @\placeholdernc{floating-point-type}@ fdim(@\placeholdernc{floating-point-type}@ x, @\placeholdernc{floating-point-type}@ y);
  constexpr float               fdimf(float x, float y);
  constexpr long double         fdiml(long double x, long double y);

  constexpr @\placeholdernc{floating-point-type}@ fmax(@\placeholdernc{floating-point-type}@ x, @\placeholdernc{floating-point-type}@ y);
  constexpr float               fmaxf(float x, float y);
  constexpr long double         fmaxl(long double x, long double y);

  constexpr @\placeholdernc{floating-point-type}@ fmin(@\placeholdernc{floating-point-type}@ x, @\placeholdernc{floating-point-type}@ y);
  constexpr float               fminf(float x, float y);
  constexpr long double         fminl(long double x, long double y);

  constexpr @\placeholdernc{floating-point-type}@ fmaximum(@\placeholdernc{floating-point-type}@ x, @\placeholdernc{floating-point-type}@ y);
  constexpr @\placeholdernc{floating-point-type}@ fmaximum_num(@\placeholdernc{floating-point-type}@ x, @\placeholdernc{floating-point-type}@ y);
  constexpr @\placeholdernc{floating-point-type}@ fminimum(@\placeholdernc{floating-point-type}@ x, @\placeholdernc{floating-point-type}@ y);
  constexpr @\placeholdernc{floating-point-type}@ fminimum_num(@\placeholdernc{floating-point-type}@ x, @\placeholdernc{floating-point-type}@ y);

  constexpr @\placeholdernc{floating-point-type}@ fma(@\placeholdernc{floating-point-type}@ x, @\placeholdernc{floating-point-type}@ y,
                                    @\placeholdernc{floating-point-type}@ z);
  constexpr float               fmaf(float x, float y, float z);
  constexpr long double         fmal(long double x, long double y, long double z);

  // \ref{c.math.lerp}, linear interpolation
  constexpr @\placeholdernc{floating-point-type}@ lerp(@\placeholdernc{floating-point-type}@ a, @\placeholdernc{floating-point-type}@ b,
                                     @\placeholdernc{floating-point-type}@ t) noexcept;

  // \ref{c.math.fpclass}, classification / comparison functions
  constexpr int fpclassify(@\placeholdernc{floating-point-type}@ x);
  constexpr bool isfinite(@\placeholdernc{floating-point-type}@ x);
  constexpr bool isinf(@\placeholdernc{floating-point-type}@ x);
  constexpr bool isnan(@\placeholdernc{floating-point-type}@ x);
  constexpr bool isnormal(@\placeholdernc{floating-point-type}@ x);
  constexpr bool signbit(@\placeholdernc{floating-point-type}@ x);
  constexpr bool isgreater(@\placeholdernc{floating-point-type}@ x, @\placeholdernc{floating-point-type}@ y);
  constexpr bool isgreaterequal(@\placeholdernc{floating-point-type}@ x, @\placeholdernc{floating-point-type}@ y);
  constexpr bool isless(@\placeholdernc{floating-point-type}@ x, @\placeholdernc{floating-point-type}@ y);
  constexpr bool islessequal(@\placeholdernc{floating-point-type}@ x, @\placeholdernc{floating-point-type}@ y);
  constexpr bool islessgreater(@\placeholdernc{floating-point-type}@ x, @\placeholdernc{floating-point-type}@ y);
  constexpr bool isunordered(@\placeholdernc{floating-point-type}@ x, @\placeholdernc{floating-point-type}@ y);

  // \ref{sf.cmath}, mathematical special functions

  // \ref{sf.cmath.assoc.laguerre}, associated Laguerre polynomials
  @\placeholdernc{floating-point-type}@ assoc_laguerre(unsigned n, unsigned m, @\placeholdernc{floating-point-type}@ x);
  float               assoc_laguerref(unsigned n, unsigned m, float x);
  long double         assoc_laguerrel(unsigned n, unsigned m, long double x);

  // \ref{sf.cmath.assoc.legendre}, associated Legendre functions
  @\placeholdernc{floating-point-type}@ assoc_legendre(unsigned l, unsigned m, @\placeholdernc{floating-point-type}@ x);
  float               assoc_legendref(unsigned l, unsigned m, float x);
  long double         assoc_legendrel(unsigned l, unsigned m, long double x);

  // \ref{sf.cmath.beta}, beta function
  @\placeholdernc{floating-point-type}@ beta(@\placeholdernc{floating-point-type}@ x, @\placeholdernc{floating-point-type}@ y);
  float               betaf(float x, float y);
  long double         betal(long double x, long double y);

  // \ref{sf.cmath.comp.ellint.1}, complete elliptic integral of the first kind
  @\placeholdernc{floating-point-type}@ comp_ellint_1(@\placeholdernc{floating-point-type}@ k);
  float               comp_ellint_1f(float k);
  long double         comp_ellint_1l(long double k);

  // \ref{sf.cmath.comp.ellint.2}, complete elliptic integral of the second kind
  @\placeholdernc{floating-point-type}@ comp_ellint_2(@\placeholdernc{floating-point-type}@ k);
  float               comp_ellint_2f(float k);
  long double         comp_ellint_2l(long double k);

  // \ref{sf.cmath.comp.ellint.3}, complete elliptic integral of the third kind
  @\placeholdernc{floating-point-type}@ comp_ellint_3(@\placeholdernc{floating-point-type}@ k, @\placeholdernc{floating-point-type}@ nu);
  float               comp_ellint_3f(float k, float nu);
  long double         comp_ellint_3l(long double k, long double nu);

  // \ref{sf.cmath.cyl.bessel.i}, regular modified cylindrical Bessel functions
  @\placeholdernc{floating-point-type}@ cyl_bessel_i(@\placeholdernc{floating-point-type}@ nu, @\placeholdernc{floating-point-type}@ x);
  float               cyl_bessel_if(float nu, float x);
  long double         cyl_bessel_il(long double nu, long double x);

  // \ref{sf.cmath.cyl.bessel.j}, cylindrical Bessel functions of the first kind
  @\placeholdernc{floating-point-type}@ cyl_bessel_j(@\placeholdernc{floating-point-type}@ nu, @\placeholdernc{floating-point-type}@ x);
  float               cyl_bessel_jf(float nu, float x);
  long double         cyl_bessel_jl(long double nu, long double x);

  // \ref{sf.cmath.cyl.bessel.k}, irregular modified cylindrical Bessel functions
  @\placeholdernc{floating-point-type}@ cyl_bessel_k(@\placeholdernc{floating-point-type}@ nu, @\placeholdernc{floating-point-type}@ x);
  float               cyl_bessel_kf(float nu, float x);
  long double         cyl_bessel_kl(long double nu, long double x);

  // \ref{sf.cmath.cyl.neumann}, cylindrical Neumann functions
  // cylindrical Bessel functions of the second kind
  @\placeholdernc{floating-point-type}@ cyl_neumann(@\placeholdernc{floating-point-type}@ nu, @\placeholdernc{floating-point-type}@ x);
  float               cyl_neumannf(float nu, float x);
  long double         cyl_neumannl(long double nu, long double x);

  // \ref{sf.cmath.ellint.1}, incomplete elliptic integral of the first kind
  @\placeholdernc{floating-point-type}@ ellint_1(@\placeholdernc{floating-point-type}@ k, @\placeholdernc{floating-point-type}@ phi);
  float               ellint_1f(float k, float phi);
  long double         ellint_1l(long double k, long double phi);

  // \ref{sf.cmath.ellint.2}, incomplete elliptic integral of the second kind
  @\placeholdernc{floating-point-type}@ ellint_2(@\placeholdernc{floating-point-type}@ k, @\placeholdernc{floating-point-type}@ phi);
  float               ellint_2f(float k, float phi);
  long double         ellint_2l(long double k, long double phi);

  // \ref{sf.cmath.ellint.3}, incomplete elliptic integral of the third kind
  @\placeholdernc{floating-point-type}@ ellint_3(@\placeholdernc{floating-point-type}@ k, @\placeholdernc{floating-point-type}@ nu,
                               @\placeholdernc{floating-point-type}@ phi);
  float               ellint_3f(float k, float nu, float phi);
  long double         ellint_3l(long double k, long double nu, long double phi);

  // \ref{sf.cmath.expint}, exponential integral
  @\placeholdernc{floating-point-type}@ expint(@\placeholdernc{floating-point-type}@ x);
  float               expintf(float x);
  long double         expintl(long double x);

  // \ref{sf.cmath.hermite}, Hermite polynomials
  @\placeholdernc{floating-point-type}@ hermite(unsigned n, @\placeholdernc{floating-point-type}@ x);
  float               hermitef(unsigned n, float x);
  long double         hermitel(unsigned n, long double x);

  // \ref{sf.cmath.laguerre}, Laguerre polynomials
  @\placeholdernc{floating-point-type}@ laguerre(unsigned n, @\placeholdernc{floating-point-type}@ x);
  float               laguerref(unsigned n, float x);
  long double         laguerrel(unsigned n, long double x);

  // \ref{sf.cmath.legendre}, Legendre polynomials
  @\placeholdernc{floating-point-type}@ legendre(unsigned l, @\placeholdernc{floating-point-type}@ x);
  float               legendref(unsigned l, float x);
  long double         legendrel(unsigned l, long double x);

  // \ref{sf.cmath.riemann.zeta}, Riemann zeta function
  @\placeholdernc{floating-point-type}@ riemann_zeta(@\placeholdernc{floating-point-type}@ x);
  float               riemann_zetaf(float x);
  long double         riemann_zetal(long double x);

  // \ref{sf.cmath.sph.bessel}, spherical Bessel functions of the first kind
  @\placeholdernc{floating-point-type}@ sph_bessel(unsigned n, @\placeholdernc{floating-point-type}@ x);
  float               sph_besself(unsigned n, float x);
  long double         sph_bessell(unsigned n, long double x);

  // \ref{sf.cmath.sph.legendre}, spherical associated Legendre functions
  @\placeholdernc{floating-point-type}@ sph_legendre(unsigned l, unsigned m, @\placeholdernc{floating-point-type}@ theta);
  float               sph_legendref(unsigned l, unsigned m, float theta);
  long double         sph_legendrel(unsigned l, unsigned m, long double theta);

  // \ref{sf.cmath.sph.neumann}, spherical Neumann functions;
  // spherical Bessel functions of the second kind
  @\placeholdernc{floating-point-type}@ sph_neumann(unsigned n, @\placeholdernc{floating-point-type}@ x);
  float               sph_neumannf(unsigned n, float x);
  long double         sph_neumannl(unsigned n, long double x);
}
\end{codeblock}

\pnum
The contents and meaning of the header \libheader{cmath}
are a subset of the C standard library header \libheader{math.h} and
only the declarations shown in the synopsis above are present,
with the addition of
a three-dimensional hypotenuse function\iref{c.math.hypot3},
a linear interpolation function\iref{c.math.lerp}, and
the mathematical special functions described in \ref{sf.cmath}.
\begin{note}
Several functions have additional overloads in this document,
but they have the same behavior as in the C standard library\iref{library.c}.
\end{note}

\pnum
For each function
with at least one parameter of type \tcode{\placeholder{floating-point-type}},
the implementation provides
an overload for each cv-unqualified floating-point type\iref{basic.fundamental}
where all uses of \tcode{\placeholder{floating-point-type}} in the function signature
are replaced with that floating-point type.

\pnum
For each function
with at least one parameter of type \tcode{\placeholder{floating-point-type}}
other than \tcode{abs},
the implementation also provides additional overloads sufficient to ensure that,
if every argument corresponding to
a \tcode{\placeholder{floating-point-type}} parameter has arithmetic type,
then every such argument is effectively cast to the floating-point type
with the greatest floating-point conversion rank and
greatest floating-point conversion subrank
among the types of all such arguments,
where arguments of integer type are considered to have
the same floating-point conversion rank as \tcode{double}.
If no such floating-point type with the greatest rank and subrank exists,
then overload resolution does not result in
a usable candidate\iref{over.match.general}
from the overloads provided by the implementation.

\pnum
An invocation of \tcode{nexttoward} is ill-formed if
the argument corresponding to the \tcode{\placeholder{floating-point-type}} parameter
has extended floating-point type.

\xrefc{7.12}

\rSec2[c.math.abs]{Absolute values}

\pnum
\begin{note}
The headers \libheaderref{cstdlib} and
\libheaderref{cmath}
declare the functions described in this subclause.
\end{note}

\indexlibraryglobal{abs}%
\begin{itemdecl}
constexpr int abs(int j);
constexpr long int abs(long int j);
constexpr long long int abs(long long int j);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
These
functions have the semantics specified in the C standard library
for the functions \tcode{abs}, \tcode{labs}, and \tcode{llabs}, respectively.

\pnum
\remarks
If \tcode{abs} is called with an argument of type \tcode{X}
for which \tcode{is_unsigned_v<X>} is \tcode{true} and
if \tcode{X} cannot be converted to \tcode{int}
by integral promotion\iref{conv.prom}, the program is ill-formed.
\begin{note}
Allowing arguments that can be promoted to \tcode{int}
provides compatibility with C.
\end{note}
\end{itemdescr}

\begin{itemdecl}
constexpr @\placeholder{floating-point-type}@ abs(@\placeholder{floating-point-type}@ x);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
The absolute value of \tcode{x}.
\end{itemdescr}

\xrefc{7.12.8.3, 7.24.7.1}

\rSec2[c.math.hypot3]{Three-dimensional hypotenuse}

\indexlibrary{\idxcode{hypot}!3-argument form}%
\begin{itemdecl}
constexpr @\placeholder{floating-point-type}@ hypot(@\placeholder{floating-point-type}@ x, @\placeholder{floating-point-type}@ y,
                                    @\placeholder{floating-point-type}@ z);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
$\sqrt{x^2+y^2+z^2}$.
\end{itemdescr}

\rSec2[c.math.lerp]{Linear interpolation}

\indexlibraryglobal{lerp}%
\begin{itemdecl}
constexpr @\placeholder{floating-point-type}@ lerp(@\placeholder{floating-point-type}@ a, @\placeholder{floating-point-type}@ b,
                                   @\placeholder{floating-point-type}@ t) noexcept;
\end{itemdecl}
\begin{itemdescr}
\pnum
\returns
$a+t(b-a)$.

\pnum
\remarks
Let \tcode{r} be the value returned.
If \tcode{isfinite(a) \&\& isfinite(b)}, then:
\begin{itemize}
\item If \tcode{t == 0}, then \tcode{r == a}.
\item If \tcode{t == 1}, then \tcode{r == b}.
\item If \tcode{t >= 0 \&\& t <= 1}, then \tcode{isfinite(r)}.
\item If \tcode{isfinite(t) \&\& a == b}, then \tcode{r == a}.
\item If \tcode{isfinite(t) || !isnan(t) \&\& b - a != 0}, then \tcode{!isnan(r)}.
\end{itemize}
Let \tcode{\placeholder{CMP}(x,y)} be \tcode{1} if \tcode{x > y},
\tcode{-1} if \tcode{x < y}, and \tcode{0} otherwise.
For any \tcode{t1} and \tcode{t2}, the product of
\tcode{\placeholder{CMP}(lerp(a, b, t2), lerp(a, b, t1))},
\tcode{\placeholder{CMP}(t2, t1)}, and
\tcode{\placeholder{CMP}(b, a)}
is non-negative.
\end{itemdescr}

\rSec2[c.math.fpclass]{Classification / comparison functions}

\pnum
The classification / comparison functions behave the same as the C macros with the
corresponding names defined in the C standard library.

\xrefc{7.12.4, 7.12.18}

\rSec2[sf.cmath]{Mathematical special functions}%

\rSec3[sf.cmath.general]{General}%
\indextext{mathematical special functions|(}%

\pnum
\indextext{NaN}\indextext{domain error}%
If any argument value
to any of the functions specified in \ref{sf.cmath}
is a NaN (Not a Number),
the function shall return a NaN
but it shall not report a domain error.
Otherwise,
the function shall report a domain error
for just those argument values
for which:
\begin{itemize}
  \item
  the function description's \returns element
  explicitly specifies a domain
  and those argument values fall
  outside the specified domain,
  or

  \item
  the corresponding mathematical function value
  has a nonzero imaginary component,
  or

  \item
  the corresponding mathematical function
  is not mathematically defined.
\begin{footnote}
    A mathematical function
    is mathematically defined
    for a given set of argument values
    (a)
      if it is explicitly defined
      for that set of argument values,
      or
    (b)
      if its limiting value exists
      and does not depend
      on the direction of approach.
\end{footnote}
\end{itemize}

\pnum
Unless otherwise specified,
each function is defined
for all finite values,
for negative infinity,
and for positive infinity.

\rSec3[sf.cmath.assoc.laguerre]{Associated Laguerre polynomials}%
\indexlibraryglobal{assoc_laguerre}%
\indexlibraryglobal{assoc_laguerref}%
\indexlibraryglobal{assoc_laguerrel}%
\indextext{Laguerre polynomials!$\mathsf{L}_n^m$}%
\indextext{L nm@$\mathsf{L}_n^m$ (associated Laguerre polynomials)}%
\begin{itemdecl}
@\placeholder{floating-point-type}@ assoc_laguerre(unsigned n, unsigned m, @\placeholder{floating-point-type}@ x);
float        assoc_laguerref(unsigned n, unsigned m, float x);
long double  assoc_laguerrel(unsigned n, unsigned m, long double x);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
These functions compute
the associated Laguerre polynomials
of their respective arguments
\tcode{n}, \tcode{m}, and \tcode{x}.

\pnum
\returns
$\mathsf{L}_n^m(x)$,
where $\mathsf{L}_n^m$ is given by \eqref{sf.cmath.assoc.laguerre},
$\mathsf{L}_{n+m}$ is given by \eqref{sf.cmath.laguerre},
$n$ is \tcode{n},
$m$ is \tcode{m}, and
$x$ is \tcode{x}.
\begin{formula}{sf.cmath.assoc.laguerre}
\mathsf{L}_n^m(x) =
   (-1)^m \frac{\mathsf{d} ^ m}{\mathsf{d}x ^ m} \, \mathsf{L}_{n+m}(x)
   \text{ ,\quad for $x \ge 0$}
\end{formula}

\pnum
\remarks
The effect of calling each of these functions
is \impldef{effect of calling associated Laguerre polynomials with \tcode{n >= 128} or \tcode{m >= 128}}
if \tcode{n >= 128} or if \tcode{m >= 128}.
\end{itemdescr}

\rSec3[sf.cmath.assoc.legendre]{Associated Legendre functions}%
\indexlibraryglobal{assoc_legendre}%
\indexlibraryglobal{assoc_legendref}%
\indexlibraryglobal{assoc_legendrel}%
\indextext{Legendre polynomials!$\mathsf{P}_\ell^m$}%
\indextext{P lm@$\mathsf{P}_\ell^m$ (associated Legendre polynomials)}%
\begin{itemdecl}
@\placeholder{floating-point-type}@ assoc_legendre(unsigned l, unsigned m, @\placeholder{floating-point-type}@ x);
float        assoc_legendref(unsigned l, unsigned m, float x);
long double  assoc_legendrel(unsigned l, unsigned m, long double x);
\end{itemdecl}

\begin{itemdescr}

\pnum
\effects
These functions compute
the associated Legendre functions
of their respective arguments
\tcode{l}, \tcode{m}, and \tcode{x}.

\pnum
\returns
$\mathsf{P}_\ell^m(x)$,
where $\mathsf{P}_\ell^m$ is given by \eqref{sf.cmath.assoc.legendre},
$\mathsf{P}_\ell$ is given by \eqref{sf.cmath.legendre},
$\ell$ is \tcode{l},
$m$ is \tcode{m}, and
$x$ is \tcode{x}.
\begin{formula}{sf.cmath.assoc.legendre}
\mathsf{P}_\ell^m(x) = (1 - x^2) ^ {m/2} \:
   \frac{\mathsf{d} ^ m}{\mathsf{d}x ^ m} \, \mathsf{P}_\ell(x)
   \text{ ,\quad for $|x| \le 1$}
\end{formula}

\pnum
\remarks
The effect of calling each of these functions
is \impldef{effect of calling associated Legendre polynomials with \tcode{l >= 128}}
if \tcode{l >= 128}.
\end{itemdescr}

\rSec3[sf.cmath.beta]{Beta function}%
\indexlibraryglobal{beta}%
\indexlibraryglobal{betaf}%
\indexlibraryglobal{betal}%
\indextext{Eulerian integral of the first kind|see{beta functions $\mathsf{B}$}}%
\indextext{beta functions $\mathsf{B}$}%
\begin{itemdecl}
@\placeholder{floating-point-type}@ beta(@\placeholder{floating-point-type}@ x, @\placeholder{floating-point-type}@ y);
float        betaf(float x, float y);
long double  betal(long double x, long double y);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
These functions compute
the beta function
of their respective arguments
\tcode{x} and \tcode{y}.

\pnum
\returns
$\mathsf{B}(x, y)$,
where $\mathsf{B}$ is given by \eqref{sf.cmath.beta},
$x$ is \tcode{x} and
$y$ is \tcode{y}.
\begin{formula}{sf.cmath.beta}
\mathsf{B}(x, y) = \frac{\Gamma(x) \, \Gamma(y)}{\Gamma(x + y)}
   \text{ ,\quad for $x > 0$,\, $y > 0$}
\end{formula}
\end{itemdescr}

\rSec3[sf.cmath.comp.ellint.1]{Complete elliptic integral of the first kind}%
\indexlibraryglobal{comp_ellint_1}%
\indexlibraryglobal{comp_ellint_1f}%
\indexlibraryglobal{comp_ellint_1l}%
\indextext{elliptic integrals!complete $\mathsf{K}$}%
\indextext{K complete@$\mathsf{K}$ (complete elliptic integrals)}%
\begin{itemdecl}
@\placeholder{floating-point-type}@ comp_ellint_1(@\placeholder{floating-point-type}@ k);
float        comp_ellint_1f(float k);
long double  comp_ellint_1l(long double k);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
These functions compute
the complete elliptic integral of the first kind
of their respective arguments
\tcode{k}.

\pnum
\returns
$\mathsf{K}(k)$,
where $\mathsf{K}$ is given by \eqref{sf.cmath.comp.ellint.1} and
$k$ is \tcode{k}.
\begin{formula}{sf.cmath.comp.ellint.1}
\mathsf{K}(k) = \mathsf{F}(k, \pi / 2) \text{ ,\quad for $|k| \le 1$}
\end{formula}

\pnum
See also \ref{sf.cmath.ellint.1}.
\end{itemdescr}

\rSec3[sf.cmath.comp.ellint.2]{Complete elliptic integral of the second kind}%
\indexlibraryglobal{comp_ellint_2}%
\indexlibraryglobal{comp_ellint_2f}%
\indexlibraryglobal{comp_ellint_2l}%
\indextext{elliptic integrals!complete $\mathsf{E}$}%
\indextext{E complete@$\mathsf{E}$ (complete elliptic integrals)}%
\begin{itemdecl}
@\placeholder{floating-point-type}@ comp_ellint_2(@\placeholder{floating-point-type}@ k);
float        comp_ellint_2f(float k);
long double  comp_ellint_2l(long double k);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
These functions compute
the complete elliptic integral of the second kind
of their respective arguments
\tcode{k}.

\pnum
\returns
$\mathsf{E}(k)$,
where $\mathsf{E}$ is given by \eqref{sf.cmath.comp.ellint.2} and
$k$ is \tcode{k}.
\begin{formula}{sf.cmath.comp.ellint.2}
\mathsf{E}(k) = \mathsf{E}(k, \pi / 2) \text{ ,\quad for $|k| \le 1$}
\end{formula}

\pnum
See also \ref{sf.cmath.ellint.2}.
\end{itemdescr}

\rSec3[sf.cmath.comp.ellint.3]{Complete elliptic integral of the third kind}%
\indexlibraryglobal{comp_ellint_3}%
\indexlibraryglobal{comp_ellint_3f}%
\indexlibraryglobal{comp_ellint_3l}%
\indextext{elliptic integrals!complete $\mathsf{\Pi}$}%
\indextext{Pi complete@$\mathsf{\Pi}$ (complete elliptic integrals)}%
\begin{itemdecl}
@\placeholder{floating-point-type}@ comp_ellint_3(@\placeholder{floating-point-type}@ k, @\placeholder{floating-point-type}@ nu);
float        comp_ellint_3f(float k, float nu);
long double  comp_ellint_3l(long double k, long double nu);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
These functions compute
the complete elliptic integral of the third kind
of their respective arguments
\tcode{k} and \tcode{nu}.

\pnum
\returns
$\mathsf{\Pi}(\nu, k)$,
where $\mathsf{\Pi}$ is given by \eqref{sf.cmath.comp.ellint.3},
$k$ is \tcode{k}, and
$\nu$ is \tcode{nu}.
\begin{formula}{sf.cmath.comp.ellint.3}
\mathsf{\Pi}(\nu, k) = \mathsf{\Pi}(\nu, k, \pi / 2) \text{ ,\quad for $|k| \le 1$}
\end{formula}

\pnum
See also \ref{sf.cmath.ellint.3}.
\end{itemdescr}

\rSec3[sf.cmath.cyl.bessel.i]{Regular modified cylindrical Bessel functions}%
\indexlibraryglobal{cyl_bessel_i}%
\indexlibraryglobal{cyl_bessel_if}%
\indexlibraryglobal{cyl_bessel_il}%
\indextext{Bessel functions!$\mathsf{I}_\nu$}%
\indextext{I nu@$\mathsf{I}_\nu$ (Bessel functions)}%
\begin{itemdecl}
@\placeholder{floating-point-type}@ cyl_bessel_i(@\placeholder{floating-point-type}@ nu, @\placeholder{floating-point-type}@ x);
float        cyl_bessel_if(float nu, float x);
long double  cyl_bessel_il(long double nu, long double x);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
These functions compute
the regular modified cylindrical Bessel functions
of their respective arguments
\tcode{nu} and \tcode{x}.

\pnum
\returns
$\mathsf{I}_\nu(x)$,
where $\mathsf{I}_\nu$ is given by \eqref{sf.cmath.cyl.bessel.i},
$\nu$ is \tcode{nu}, and
$x$ is \tcode{x}.
\begin{formula}{sf.cmath.cyl.bessel.i}
\mathsf{I}_\nu(x) =
     \mathrm{i}^{-\nu} \mathsf{J}_\nu(\mathrm{i}x) =
     \sum_{k=0}^\infty \frac{(x/2)^{\nu+2k}}{k! \: \Gamma(\nu+k+1)}
     \text{ ,\quad for $x \ge 0$}
\end{formula}

\pnum
\remarks
The effect of calling each of these functions
is \impldef{effect of calling regular modified cylindrical Bessel functions with \tcode{nu >= 128}}
if \tcode{nu >= 128}.

\pnum
See also \ref{sf.cmath.cyl.bessel.j}.
\end{itemdescr}

\rSec3[sf.cmath.cyl.bessel.j]{Cylindrical Bessel functions of the first kind}%
\indexlibraryglobal{cyl_bessel_j}%
\indexlibraryglobal{cyl_bessel_jf}%
\indexlibraryglobal{cyl_bessel_jl}%
\indextext{Bessel functions!$\mathsf{J}_\nu$}%
\indextext{J nu@$\mathsf{J}_\nu$ (Bessel functions)}%
\begin{itemdecl}
@\placeholder{floating-point-type}@ cyl_bessel_j(@\placeholder{floating-point-type}@ nu, @\placeholder{floating-point-type}@ x);
float        cyl_bessel_jf(float nu, float x);
long double  cyl_bessel_jl(long double nu, long double x);
\end{itemdecl}

\begin{itemdescr}

\pnum
\effects
These functions compute
the cylindrical Bessel functions of the first kind
of their respective arguments
\tcode{nu} and \tcode{x}.

\pnum
\returns
$\mathsf{J}_\nu(x)$,
where $\mathsf{J}_\nu$ is given by \eqref{sf.cmath.cyl.bessel.j},
$\nu$ is \tcode{nu}, and
$x$ is \tcode{x}.
\begin{formula}{sf.cmath.cyl.bessel.j}
\mathsf{J}_\nu(x) =
   \sum_{k=0}^\infty \frac{(-1)^k (x/2)^{\nu+2k}}{k! \: \Gamma(\nu+k+1)}
   \text{ ,\quad for $x \ge 0$}
\end{formula}

\pnum
\remarks
The effect of calling each of these functions
is \impldef{effect of calling cylindrical Bessel functions of the first kind with \tcode{nu >= 128}}
if \tcode{nu >= 128}.
\end{itemdescr}

\rSec3[sf.cmath.cyl.bessel.k]{Irregular modified cylindrical Bessel functions}%
\indexlibraryglobal{cyl_bessel_k}%
\indexlibraryglobal{cyl_bessel_kf}%
\indexlibraryglobal{cyl_bessel_kl}%
\indextext{Bessel functions!$\mathsf{K}_\nu$}%
\indextext{K nu@$\mathsf{K}_\nu$ (Bessel functions)}%
\begin{itemdecl}
@\placeholder{floating-point-type}@ cyl_bessel_k(@\placeholder{floating-point-type}@ nu, @\placeholder{floating-point-type}@ x);
float        cyl_bessel_kf(float nu, float x);
long double  cyl_bessel_kl(long double nu, long double x);
\end{itemdecl}

\begin{itemdescr}

\pnum
\effects
These functions compute
the irregular modified cylindrical Bessel functions
of their respective arguments
\tcode{nu} and \tcode{x}.

\pnum
\returns
$\mathsf{K}_\nu(x)$,
where $\mathsf{K}_\nu$ is given by \eqref{sf.cmath.cyl.bessel.k},
$\nu$ is \tcode{nu}, and
$x$ is \tcode{x}.
\begin{formula}{sf.cmath.cyl.bessel.k}
  \mathsf{K}_\nu(x) =
  (\pi/2)\mathrm{i}^{\nu+1} (            \mathsf{J}_\nu(\mathrm{i}x)
			    + \mathrm{i} \mathsf{N}_\nu(\mathrm{i}x)
			    )
  =
  \left\{
  \begin{array}{cl}
  \displaystyle
  \frac{\pi}{2}
  \frac{\mathsf{I}_{-\nu}(x) - \mathsf{I}_{\nu}(x)}
       {\sin \nu\pi },
  & \mbox{for $x \ge 0$ and non-integral $\nu$}
  \\
  \\
  \displaystyle
  \frac{\pi}{2}
  \lim_{\mu \rightarrow \nu} \frac{\mathsf{I}_{-\mu}(x) - \mathsf{I}_{\mu}(x)}
                                  {\sin \mu\pi },
  & \mbox{for $x \ge 0$ and integral $\nu$}
  \end{array}
  \right.
\end{formula}

\pnum
\remarks
The effect of calling each of these functions
is \impldef{effect of calling irregular modified cylindrical Bessel functions with \tcode{nu >= 128}}
if \tcode{nu >= 128}.

\pnum
See also \ref{sf.cmath.cyl.bessel.i}, \ref{sf.cmath.cyl.bessel.j}, \ref{sf.cmath.cyl.neumann}.
\end{itemdescr}

\rSec3[sf.cmath.cyl.neumann]{Cylindrical Neumann functions}%
\indexlibraryglobal{cyl_neumann}%
\indexlibraryglobal{cyl_neumannf}%
\indexlibraryglobal{cyl_neumannl}%
\indextext{Bessel functions!$\mathsf{N}_\nu$}%
\indextext{Neumann functions!$\mathsf{N}_\nu$}%
\indextext{N nu@$\mathsf{N}_\nu$ (Neumann functions)}%
\begin{itemdecl}
@\placeholder{floating-point-type}@ cyl_neumann(@\placeholder{floating-point-type}@ nu, @\placeholder{floating-point-type}@ x);
float        cyl_neumannf(float nu, float x);
long double  cyl_neumannl(long double nu, long double x);
\end{itemdecl}

\begin{itemdescr}

\pnum
\effects
These functions compute the cylindrical Neumann functions,
also known as the cylindrical Bessel functions of the second kind,
of their respective arguments
\tcode{nu} and \tcode{x}.

\pnum
\returns
$\mathsf{N}_\nu(x)$,
where $\mathsf{N}_\nu$ is given by \eqref{sf.cmath.cyl.neumann},
$\nu$ is \tcode{nu}, and
$x$ is \tcode{x}.
\begin{formula}{sf.cmath.cyl.neumann}
  \mathsf{N}_\nu(x) =
  \left\{
  \begin{array}{cl}
  \displaystyle
  \frac{\mathsf{J}_\nu(x) \cos \nu\pi - \mathsf{J}_{-\nu}(x)}
       {\sin \nu\pi },
  & \mbox{for $x \ge 0$ and non-integral $\nu$}
  \\
  \\
  \displaystyle
  \lim_{\mu \rightarrow \nu} \frac{\mathsf{J}_\mu(x) \cos \mu\pi - \mathsf{J}_{-\mu}(x)}
                                {\sin \mu\pi },
  & \mbox{for $x \ge 0$ and integral $\nu$}
  \end{array}
  \right.
\end{formula}

\pnum
\remarks
The effect of calling each of these functions
is \impldef{effect of calling cylindrical Neumann functions with \tcode{nu >= 128}}
if \tcode{nu >= 128}.

\pnum
See also \ref{sf.cmath.cyl.bessel.j}.
\end{itemdescr}

\rSec3[sf.cmath.ellint.1]{Incomplete elliptic integral of the first kind}%
\indexlibraryglobal{ellint_1}%
\indexlibraryglobal{ellint_1f}%
\indexlibraryglobal{ellint_1l}%
\indextext{elliptic integrals!incomplete $\mathsf{F}$}%
\indextext{F incomplete@$\mathsf{F}$ (incomplete elliptic integrals)}%
\begin{itemdecl}
@\placeholder{floating-point-type}@ ellint_1(@\placeholder{floating-point-type}@ k, @\placeholder{floating-point-type}@ phi);
float        ellint_1f(float k, float phi);
long double  ellint_1l(long double k, long double phi);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
These functions compute
the incomplete elliptic integral of the first kind
of their respective arguments
\tcode{k} and \tcode{phi} (\tcode{phi} measured in radians).

\pnum
\returns
$\mathsf{F}(k, \phi)$,
where $\mathsf{F}$ is given by \eqref{sf.cmath.ellint.1},
$k$ is \tcode{k}, and
$\phi$ is \tcode{phi}.
\begin{formula}{sf.cmath.ellint.1}
\mathsf{F}(k, \phi) =
     \int_0^\phi \! \frac{\mathsf{d}\theta}{\sqrt{1 - k^2 \sin^2 \theta}}
     \text{ ,\quad for $|k| \le 1$}
\end{formula}
\end{itemdescr}

\rSec3[sf.cmath.ellint.2]{Incomplete elliptic integral of the second kind}%
\indexlibraryglobal{ellint_2}%
\indexlibraryglobal{ellint_2f}%
\indexlibraryglobal{ellint_2l}%
\indextext{elliptic integrals!incomplete $\mathsf{E}$}%
\indextext{E incomplete@$\mathsf{E}$ (incomplete elliptic integrals)}%
\begin{itemdecl}
@\placeholder{floating-point-type}@ ellint_2(@\placeholder{floating-point-type}@ k, @\placeholder{floating-point-type}@ phi);
float        ellint_2f(float k, float phi);
long double  ellint_2l(long double k, long double phi);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
These functions compute
the incomplete elliptic integral of the second kind
of their respective arguments
\tcode{k} and \tcode{phi} (\tcode{phi} measured in radians).

\pnum
\returns
$\mathsf{E}(k, \phi)$,
where $\mathsf{E}$ is given by \eqref{sf.cmath.ellint.2},
$k$ is \tcode{k}, and
$\phi$ is \tcode{phi}.
\begin{formula}{sf.cmath.ellint.2}
\mathsf{E}(k, \phi) = \int_0^\phi \! \sqrt{1 - k^2 \sin^2 \theta} \, \mathsf{d}\theta
   \text{ ,\quad for $|k| \le 1$}
\end{formula}
\end{itemdescr}

\rSec3[sf.cmath.ellint.3]{Incomplete elliptic integral of the third kind}%
\indexlibraryglobal{ellint_3}%
\indexlibraryglobal{ellint_3f}%
\indexlibraryglobal{ellint_3l}%
\indextext{elliptic integrals!incomplete $\mathsf{\Pi}$}%
\indextext{Pi incomplete@$\mathsf{\Pi}$ (incomplete elliptic integrals)}%
\begin{itemdecl}
@\placeholder{floating-point-type}@ ellint_3(@\placeholder{floating-point-type}@ k, @\placeholder{floating-point-type}@ nu,
                             @\placeholder{floating-point-type}@ phi);
float        ellint_3f(float k, float nu, float phi);
long double  ellint_3l(long double k, long double nu, long double phi);
\end{itemdecl}

\begin{itemdescr}

\pnum
\effects
These functions compute
the incomplete elliptic integral of the third kind
of their respective arguments
\tcode{k}, \tcode{nu}, and \tcode{phi} (\tcode{phi} measured in radians).

\pnum
\returns
$\mathsf{\Pi}(\nu, k, \phi)$,
where $\mathsf{\Pi}$ is given by \eqref{sf.cmath.ellint.3},
$\nu$ is \tcode{nu},
$k$ is \tcode{k}, and
$\phi$ is \tcode{phi}.
\begin{formula}{sf.cmath.ellint.3}
\mathsf{\Pi}(\nu, k, \phi) = \int_0^\phi \!
   \frac{ \mathsf{d}\theta }{ (1 - \nu \, \sin^2 \theta) \sqrt{1 - k^2 \sin^2 \theta} } \text{ ,\quad for $|k| \le 1$}
\end{formula}
\end{itemdescr}

\rSec3[sf.cmath.expint]{Exponential integral}%
\indexlibraryglobal{expint}%
\indexlibraryglobal{expintf}%
\indexlibraryglobal{expintl}%
\indextext{exponential integrals $\mathsf{Ei}$}%
\indextext{Ei@$\mathsf{Ei}$ (exponential integrals)}%
\begin{itemdecl}
@\placeholder{floating-point-type}@ expint(@\placeholder{floating-point-type}@ x);
float        expintf(float x);
long double  expintl(long double x);
\end{itemdecl}

\begin{itemdescr}

\pnum
\effects
These functions compute the exponential integral
of their respective arguments
\tcode{x}.

\pnum
\returns
$\mathsf{Ei}(x)$,
where $\mathsf{Ei}$  is given by \eqref{sf.cmath.expint} and
$x$ is \tcode{x}.
\begin{formula}{sf.cmath.expint}
  \mathsf{Ei}(x) =
  - \int_{-x}^\infty \frac{e^{-t}}
                          {t     } \, \mathsf{d}t
\end{formula}
\end{itemdescr}

\rSec3[sf.cmath.hermite]{Hermite polynomials}%
\indexlibraryglobal{hermite}%
\indexlibraryglobal{hermitef}%
\indexlibraryglobal{hermitel}%
\indextext{Hermite polynomials $\mathsf{H}_n$}%
\indextext{H n@$\mathsf{H}_n$ (Hermite polynomials)}%
\begin{itemdecl}
@\placeholder{floating-point-type}@ hermite(unsigned n, @\placeholder{floating-point-type}@ x);
float        hermitef(unsigned n, float x);
long double  hermitel(unsigned n, long double x);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
These functions compute the Hermite polynomials
of their respective arguments
\tcode{n} and \tcode{x}.

\pnum
\returns
$\mathsf{H}_n(x)$,
where $\mathsf{H}_n$ is given by \eqref{sf.cmath.hermite},
$n$ is \tcode{n}, and
$x$ is \tcode{x}.
\begin{formula}{sf.cmath.hermite}
  \mathsf{H}_n(x) =
  (-1)^n e^{x^2} \frac{ \mathsf{d} ^n}
		      { \mathsf{d}x^n} \, e^{-x^2}
\end{formula}

\pnum
\remarks
The effect of calling each of these functions
is \impldef{effect of calling Hermite polynomials with \tcode{n >= 128}}
if \tcode{n >= 128}.
\end{itemdescr}

\rSec3[sf.cmath.laguerre]{Laguerre polynomials}%
\indexlibraryglobal{laguerre}%
\indexlibraryglobal{laguerref}%
\indexlibraryglobal{laguerrel}%
\indextext{Laguerre polynomials!$\mathsf{L}_n$}%
\indextext{L n@$\mathsf{L}_n$ (Laguerre polynomials)}%
\begin{itemdecl}
@\placeholder{floating-point-type}@ laguerre(unsigned n, @\placeholder{floating-point-type}@ x);
float        laguerref(unsigned n, float x);
long double  laguerrel(unsigned n, long double x);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
These functions compute the Laguerre polynomials
of their respective arguments
\tcode{n} and \tcode{x}.

\pnum
\returns
$\mathsf{L}_n(x)$,
where $\mathsf{L}_n$ is given by \eqref{sf.cmath.laguerre},
$n$ is \tcode{n}, and
$x$ is \tcode{x}.
\begin{formula}{sf.cmath.laguerre}
\mathsf{L}_n(x) =
     \frac{e^x}{n!} \frac{\mathsf{d}^n}{\mathsf{d}x^n} \, (x^n e^{-x})
     \text{ ,\quad for $x \ge 0$}
\end{formula}

\pnum
\remarks
The effect of calling each of these functions
is \impldef{effect of calling Laguerre polynomials with \tcode{n >= 128}}
if \tcode{n >= 128}.
\end{itemdescr}

\rSec3[sf.cmath.legendre]{Legendre polynomials}%
\indexlibraryglobal{legendre}%
\indexlibraryglobal{legendref}%
\indexlibraryglobal{legendrel}%
\indextext{Legendre polynomials!$\mathsf{P}_\ell$}%
\indextext{P l@$\mathsf{P}_\ell$ (Legendre polynomials)}%
\begin{itemdecl}
@\placeholder{floating-point-type}@ legendre(unsigned l, @\placeholder{floating-point-type}@ x);
float        legendref(unsigned l, float x);
long double  legendrel(unsigned l, long double x);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
These functions compute the Legendre polynomials of their
respective arguments
\tcode{l} and \tcode{x}.

\pnum
\returns
$\mathsf{P}_\ell(x)$,
where $\mathsf{P}_\ell$ is given by \eqref{sf.cmath.legendre},
$l$ is \tcode{l}, and
$x$ is \tcode{x}.
\begin{formula}{sf.cmath.legendre}
\mathsf{P}_\ell(x) =
     \frac{1}{2^\ell \, \ell!}
     \frac{\mathsf{d}^\ell}{\mathsf{d}x^\ell} \, (x^2 - 1) ^ \ell
     \text{ ,\quad for $|x| \le 1$}
\end{formula}

\pnum
\remarks
The effect of calling each of these functions
is \impldef{effect of calling Legendre polynomials with \tcode{l >= 128}}
if \tcode{l >= 128}.
\end{itemdescr}

\rSec3[sf.cmath.riemann.zeta]{Riemann zeta function}%
\indexlibraryglobal{riemann_zeta}%
\indexlibraryglobal{riemann_zetaf}%
\indexlibraryglobal{riemann_zetal}%
\indextext{zeta functions $\zeta$}%
\begin{itemdecl}
@\placeholder{floating-point-type}@ riemann_zeta(@\placeholder{floating-point-type}@ x);
float        riemann_zetaf(float x);
long double  riemann_zetal(long double x);
\end{itemdecl}

\begin{itemdescr}

\pnum
\effects
These functions compute the Riemann zeta function
of their respective arguments
\tcode{x}.

\pnum
\returns
$\mathsf{\zeta}(x)$,
where $\mathsf{\zeta}$ is given by \eqref{sf.cmath.riemann.zeta} and
$x$ is \tcode{x}.
\begin{formula}{sf.cmath.riemann.zeta}
  \mathsf{\zeta}(x) =
  \left\{
  \begin{array}{cl}
  \displaystyle
  \sum_{k=1}^\infty k^{-x},
  & \mbox{for $x > 1$}
  \\
  \\
  \displaystyle
  \frac{1}
	{1 - 2^{1-x}}
  \sum_{k=1}^\infty (-1)^{k-1} k^{-x},
  & \mbox{for $0 \le x \le 1$}
  \\
  \\
  \displaystyle
  2^x \pi^{x-1} \sin(\frac{\pi x}{2}) \, \Gamma(1-x) \, \zeta(1-x),
  & \mbox{for $x < 0$}
  \end{array}
  \right.
\end{formula}
\end{itemdescr}

\rSec3[sf.cmath.sph.bessel]{Spherical Bessel functions of the first kind}%
\indexlibraryglobal{sph_bessel}%
\indexlibraryglobal{sph_besself}%
\indexlibraryglobal{sph_bessell}%
\indextext{Bessel functions!$\mathsf{j}_n$}%
\indextext{j n@$\mathsf{j}_n$ (spherical Bessel functions)}%
\begin{itemdecl}
@\placeholder{floating-point-type}@ sph_bessel(unsigned n, @\placeholder{floating-point-type}@ x);
float        sph_besself(unsigned n, float x);
long double  sph_bessell(unsigned n, long double x);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
These functions compute
the spherical Bessel functions of the first kind
of their respective arguments
\tcode{n} and \tcode{x}.

\pnum
\returns
$\mathsf{j}_n(x)$,
where $\mathsf{j}_n$ is given by \eqref{sf.cmath.sph.bessel},
$n$ is \tcode{n}, and
$x$ is \tcode{x}.
\begin{formula}{sf.cmath.sph.bessel}
\mathsf{j}_n(x) = (\pi/2x)^{1\!/\!2} \mathsf{J}_{n + 1\!/\!2}(x) \text{ ,\quad for $x \ge 0$}
\end{formula}

\pnum
\remarks
The effect of calling each of these functions
is \impldef{effect of calling spherical Bessel functions with \tcode{n >= 128}}
if \tcode{n >= 128}.

\pnum
See also \ref{sf.cmath.cyl.bessel.j}.
\end{itemdescr}

\rSec3[sf.cmath.sph.legendre]{Spherical associated Legendre functions}%
\indexlibraryglobal{sph_legendre}%
\indexlibraryglobal{sph_legendref}%
\indexlibraryglobal{sph_legendrel}%
\indextext{spherical harmonics $\mathsf{Y}_\ell^m$}%
\indextext{Legendre functions $\mathsf{Y}_\ell^m$}%
\indextext{Y lm@$\mathsf{Y}_\ell^m$ (spherical associated Legendre functions)}%
\begin{itemdecl}
@\placeholder{floating-point-type}@ sph_legendre(unsigned l, unsigned m, @\placeholder{floating-point-type}@ theta);
float        sph_legendref(unsigned l, unsigned m, float theta);
long double  sph_legendrel(unsigned l, unsigned m, long double theta);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
These functions compute the spherical associated Legendre functions
of their respective arguments
\tcode{l}, \tcode{m}, and \tcode{theta} (\tcode{theta} measured in radians).

\pnum
\returns
$\mathsf{Y}_\ell^m(\theta, 0)$,
where $\mathsf{Y}_\ell^m$ is given by \eqref{sf.cmath.sph.legendre},
$l$ is \tcode{l},
$m$ is \tcode{m}, and
$\theta$ is \tcode{theta}.
\begin{formula}{sf.cmath.sph.legendre}
\mathsf{Y}_\ell^m(\theta, \phi) =
     (-1)^m \left[\frac{(2 \ell + 1)}{4 \pi} \frac{(\ell - m)!}{(\ell + m)!}\right]^{1/2}
     \mathsf{P}_\ell^m (\cos\theta) e^{i m \phi}
     \text{ ,\quad for $|m| \le \ell$}
\end{formula}

\pnum
\remarks
The effect of calling each of these functions
is \impldef{effect of calling spherical associated Legendre functions with \tcode{l >= 128}}
if \tcode{l >= 128}.

\pnum
See also \ref{sf.cmath.assoc.legendre}.
\end{itemdescr}

\rSec3[sf.cmath.sph.neumann]{Spherical Neumann functions}%
\indexlibraryglobal{sph_neumann}%
\indexlibraryglobal{sph_neumannf}%
\indexlibraryglobal{sph_neumannl}%
\indextext{Bessel functions!$\mathsf{n}_n$}%
\indextext{Neumann functions!$\mathsf{n}_n$}%
\indextext{n n spherical@$\mathsf{n}_n$ (spherical Neumann functions)}%
\begin{itemdecl}
@\placeholder{floating-point-type}@ sph_neumann(unsigned n, @\placeholder{floating-point-type}@ x);
float        sph_neumannf(unsigned n, float x);
long double  sph_neumannl(unsigned n, long double x);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
These functions compute the spherical Neumann functions,
also known as the spherical Bessel functions of the second kind,
of their respective arguments
\tcode{n} and \tcode{x}.

\pnum
\returns
$\mathsf{n}_n(x)$,
where $\mathsf{n}_n$ is given by \eqref{sf.cmath.sph.neumann},
$n$ is \tcode{n}, and
$x$ is \tcode{x}.
\begin{formula}{sf.cmath.sph.neumann}
\mathsf{n}_n(x) = (\pi/2x)^{1\!/\!2} \mathsf{N}_{n + 1\!/\!2}(x)
   \text{ ,\quad for $x \ge 0$}
\end{formula}

\pnum
\remarks
The effect of calling each of these functions
is \impldef{effect of calling spherical Neumann functions with \tcode{n >= 128}}
if \tcode{n >= 128}.

\pnum
See also \ref{sf.cmath.cyl.neumann}.
\end{itemdescr}

\indextext{mathematical special functions|)}

\rSec1[numbers]{Numbers}

\rSec2[numbers.syn]{Header \tcode{<numbers>} synopsis}

\indexheader{numbers}%
\begin{codeblock}
namespace std::numbers {
  template<class T> constexpr T @\libglobal{e_v}@          = @\unspec@;
  template<class T> constexpr T @\libglobal{log2e_v}@      = @\unspec@;
  template<class T> constexpr T @\libglobal{log10e_v}@     = @\unspec@;
  template<class T> constexpr T @\libglobal{pi_v}@         = @\unspec@;
  template<class T> constexpr T @\libglobal{inv_pi_v}@     = @\unspec@;
  template<class T> constexpr T @\libglobal{inv_sqrtpi_v}@ = @\unspec@;
  template<class T> constexpr T @\libglobal{ln2_v}@        = @\unspec@;
  template<class T> constexpr T @\libglobal{ln10_v}@       = @\unspec@;
  template<class T> constexpr T @\libglobal{sqrt2_v}@      = @\unspec@;
  template<class T> constexpr T @\libglobal{sqrt3_v}@      = @\unspec@;
  template<class T> constexpr T @\libglobal{inv_sqrt3_v}@  = @\unspec@;
  template<class T> constexpr T @\libglobal{egamma_v}@     = @\unspec@;
  template<class T> constexpr T @\libglobal{phi_v}@        = @\unspec@;

  template<@\libconcept{floating_point}@ T> constexpr T e_v<T>          = @\seebelow@;
  template<@\libconcept{floating_point}@ T> constexpr T log2e_v<T>      = @\seebelow@;
  template<@\libconcept{floating_point}@ T> constexpr T log10e_v<T>     = @\seebelow@;
  template<@\libconcept{floating_point}@ T> constexpr T pi_v<T>         = @\seebelow@;
  template<@\libconcept{floating_point}@ T> constexpr T inv_pi_v<T>     = @\seebelow@;
  template<@\libconcept{floating_point}@ T> constexpr T inv_sqrtpi_v<T> = @\seebelow@;
  template<@\libconcept{floating_point}@ T> constexpr T ln2_v<T>        = @\seebelow@;
  template<@\libconcept{floating_point}@ T> constexpr T ln10_v<T>       = @\seebelow@;
  template<@\libconcept{floating_point}@ T> constexpr T sqrt2_v<T>      = @\seebelow@;
  template<@\libconcept{floating_point}@ T> constexpr T sqrt3_v<T>      = @\seebelow@;
  template<@\libconcept{floating_point}@ T> constexpr T inv_sqrt3_v<T>  = @\seebelow@;
  template<@\libconcept{floating_point}@ T> constexpr T egamma_v<T>     = @\seebelow@;
  template<@\libconcept{floating_point}@ T> constexpr T phi_v<T>        = @\seebelow@;

  inline constexpr double @\libglobal{e}@          = e_v<double>;
  inline constexpr double @\libglobal{log2e}@      = log2e_v<double>;
  inline constexpr double @\libglobal{log10e}@     = log10e_v<double>;
  inline constexpr double @\libglobal{pi}@         = pi_v<double>;
  inline constexpr double @\libglobal{inv_pi}@     = inv_pi_v<double>;
  inline constexpr double @\libglobal{inv_sqrtpi}@ = inv_sqrtpi_v<double>;
  inline constexpr double @\libglobal{ln2}@        = ln2_v<double>;
  inline constexpr double @\libglobal{ln10}@       = ln10_v<double>;
  inline constexpr double @\libglobal{sqrt2}@      = sqrt2_v<double>;
  inline constexpr double @\libglobal{sqrt3}@      = sqrt3_v<double>;
  inline constexpr double @\libglobal{inv_sqrt3}@  = inv_sqrt3_v<double>;
  inline constexpr double @\libglobal{egamma}@     = egamma_v<double>;
  inline constexpr double @\libglobal{phi}@        = phi_v<double>;
}
\end{codeblock}

\rSec2[math.constants]{Mathematical constants}

\pnum
The library-defined partial specializations
of mathematical constant variable templates
are initialized with the nearest representable values of
$\mathrm{e}$,
$\log_{2} \mathrm{e}$,
$\log_{10} \mathrm{e}$,
$\pi$,
$\frac{1}{\pi}$,
$\frac{1}{\sqrt{\pi}}$,
$\ln 2$,
$\ln 10$,
$\sqrt{2}$,
$\sqrt{3}$,
$\frac{1}{\sqrt{3}}$,
the Euler-Mascheroni $\gamma$ constant, and
the golden ratio $\phi$ constant $\frac{1+\sqrt{5}}{2}$,
respectively.

\pnum
Pursuant to \ref{namespace.std},
a program may partially or explicitly specialize
a mathematical constant variable template
provided that the specialization depends on a program-defined type.

\pnum
A program that instantiates a primary template
of a mathematical constant variable template is ill-formed.

\rSec1[linalg]{Basic linear algebra algorithms}

\rSec2[linalg.overview]{Overview}

\pnum
Subclause \ref{linalg} defines basic linear algebra algorithms.
The algorithms that access the elements of arrays
view those elements through \tcode{mdspan}\iref{views.multidim}.

\rSec2[linalg.syn]{Header \tcode{<linalg>} synopsis}

\indexheader{linalg}%
\begin{codeblock}
namespace std::linalg {
  // \ref{linalg.tags.order}, storage order tags
  struct column_major_t;
  inline constexpr column_major_t column_major;
  struct row_major_t;
  inline constexpr row_major_t row_major;

  // \ref{linalg.tags.triangle}, triangle tags
  struct upper_triangle_t;
  inline constexpr upper_triangle_t upper_triangle;
  struct lower_triangle_t;
  inline constexpr lower_triangle_t lower_triangle;

  // \ref{linalg.tags.diagonal}, diagonal tags
  struct implicit_unit_diagonal_t;
  inline constexpr implicit_unit_diagonal_t implicit_unit_diagonal;
  struct explicit_diagonal_t;
  inline constexpr explicit_diagonal_t explicit_diagonal;

  // \ref{linalg.layout.packed}, class template \tcode{layout_blas_packed}
  template<class Triangle, class StorageOrder>
    class layout_blas_packed;

  // \ref{linalg.helpers}, exposition-only helpers

  // \ref{linalg.helpers.concepts}, linear algebra argument concepts
  template<class T>
    constexpr bool @\exposid{is-mdspan}@ = @\seebelow@;               // \expos

  template<class T>
    concept @\exposconcept{in-vector}@ = @\seebelow@;                      // \expos

  template<class T>
    concept @\exposconcept{out-vector}@ = @\seebelow@;                     // \expos

  template<class T>
    concept @\exposconcept{inout-vector}@ = @\seebelow@;                   // \expos

  template<class T>
    concept @\exposconcept{in-matrix}@ = @\seebelow@;                      // \expos

  template<class T>
    concept @\exposconcept{out-matrix}@ = @\seebelow@;                     // \expos

  template<class T>
    concept @\exposconcept{inout-matrix}@ = @\seebelow@;                   // \expos

  template<class T>
    concept @\exposconcept{possibly-packed-out-matrix}@ = @\seebelow@;     // \expos

  template<class T>
    concept @\exposconcept{in-object}@ = @\seebelow@;                      // \expos

  template<class T>
    concept @\exposconcept{out-object}@ = @\seebelow@;                     // \expos

  template<class T>
    concept @\exposconcept{inout-object}@ = @\seebelow@;                   // \expos

  template<class T>
    concept @\exposconcept{scalar}@ = @\seebelow@;                         // \expos

  // \ref{linalg.scaled}, scaled in-place transformation

  // \ref{linalg.scaled.scaledaccessor}, class template \tcode{scaled_accessor}
  template<class ScalingFactor, class NestedAccessor>
    class scaled_accessor;

  // \ref{linalg.scaled.scaled}, function template \tcode{scaled}
  template<class ScalingFactor,
           class ElementType, class Extents, class Layout, class Accessor>
    constexpr auto scaled(ScalingFactor alpha, mdspan<ElementType, Extents, Layout, Accessor> x);

  // \ref{linalg.conj}, conjugated in-place transformation

  // \ref{linalg.conj.conjugatedaccessor}, class template \tcode{conjugated_accessor}
  template<class NestedAccessor>
    class conjugated_accessor;

  // \ref{linalg.conj.conjugated}, function template \tcode{conjugated}
  template<class ElementType, class Extents, class Layout, class Accessor>
    constexpr auto conjugated(mdspan<ElementType, Extents, Layout, Accessor> a);

  // \ref{linalg.transp}, transpose in-place transformation

  // \ref{linalg.transp.layout.transpose}, class template \tcode{layout_transpose}
  template<class Layout>
    class layout_transpose;

  // \ref{linalg.transp.transposed}, function template \tcode{transposed}
  template<class ElementType, class Extents, class Layout, class Accessor>
    constexpr auto transposed(mdspan<ElementType, Extents, Layout, Accessor> a);

  // \ref{linalg.conjtransposed}, conjugated transpose in-place transformation
  template<class ElementType, class Extents, class Layout, class Accessor>
    constexpr auto conjugate_transposed(mdspan<ElementType, Extents, Layout, Accessor> a);

  // \ref{linalg.algs.blas1}, BLAS 1 algorithms

  // \ref{linalg.algs.blas1.givens}, Givens rotations

  // \ref{linalg.algs.blas1.givens.lartg}, compute Givens rotation

  template<class Real>
    struct setup_givens_rotation_result {
      Real c;
      Real s;
      Real r;
    };
  template<class Real>
    struct setup_givens_rotation_result<complex<Real>> {
      Real c;
      complex<Real> s;
      complex<Real> r;
    };

  template<class Real>
    setup_givens_rotation_result<Real> setup_givens_rotation(Real a, Real b) noexcept;

  template<class Real>
    setup_givens_rotation_result<complex<Real>>
      setup_givens_rotation(complex<Real> a, complex<Real> b) noexcept;

  // \ref{linalg.algs.blas1.givens.rot}, apply computed Givens rotation
  template<@\exposconcept{inout-vector}@ InOutVec1, @\exposconcept{inout-vector}@ InOutVec2, class Real>
    void apply_givens_rotation(InOutVec1 x, InOutVec2 y, Real c, Real s);
  template<class ExecutionPolicy, @\exposconcept{inout-vector}@ InOutVec1, @\exposconcept{inout-vector}@ InOutVec2, class Real>
    void apply_givens_rotation(ExecutionPolicy&& exec,
                               InOutVec1 x, InOutVec2 y, Real c, Real s);
  template<@\exposconcept{inout-vector}@ InOutVec1, @\exposconcept{inout-vector}@ InOutVec2, class Real>
    void apply_givens_rotation(InOutVec1 x, InOutVec2 y, Real c, complex<Real> s);
  template<class ExecutionPolicy, @\exposconcept{inout-vector}@ InOutVec1, @\exposconcept{inout-vector}@ InOutVec2, class Real>
    void apply_givens_rotation(ExecutionPolicy&& exec,
                               InOutVec1 x, InOutVec2 y, Real c, complex<Real> s);

  // \ref{linalg.algs.blas1.swap}, swap elements
  template<@\exposconcept{inout-object}@ InOutObj1, @\exposconcept{inout-object}@ InOutObj2>
    void swap_elements(InOutObj1 x, InOutObj2 y);
  template<class ExecutionPolicy, @\exposconcept{inout-object}@ InOutObj1, @\exposconcept{inout-object}@ InOutObj2>
    void swap_elements(ExecutionPolicy&& exec, InOutObj1 x, InOutObj2 y);

  // \ref{linalg.algs.blas1.scal}, multiply elements by scalar
  template<@\exposconcept{scalar}@ Scalar, @\exposconcept{inout-object}@ InOutObj>
    void scale(Scalar alpha, InOutObj x);
  template<class ExecutionPolicy, @\exposconcept{scalar}@ Scalar, @\exposconcept{inout-object}@ InOutObj>
    void scale(ExecutionPolicy&& exec, Scalar alpha, InOutObj x);

  // \ref{linalg.algs.blas1.copy}, copy elements
  template<@\exposconcept{in-object}@ InObj, @\exposconcept{out-object}@ OutObj>
    void copy(InObj x, OutObj y);
  template<class ExecutionPolicy, @\exposconcept{in-object}@ InObj, @\exposconcept{out-object}@ OutObj>
    void copy(ExecutionPolicy&& exec, InObj x, OutObj y);

  // \ref{linalg.algs.blas1.add}, add elementwise
  template<@\exposconcept{in-object}@ InObj1, @\exposconcept{in-object}@ InObj2, @\exposconcept{out-object}@ OutObj>
    void add(InObj1 x, InObj2 y, OutObj z);
  template<class ExecutionPolicy, @\exposconcept{in-object}@ InObj1, @\exposconcept{in-object}@ InObj2, @\exposconcept{out-object}@ OutObj>
    void add(ExecutionPolicy&& exec, InObj1 x, InObj2 y, OutObj z);

  // \ref{linalg.algs.blas1.dot}, dot product of two vectors
  template<@\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, @\exposconcept{scalar}@ Scalar>
    Scalar dot(InVec1 v1, InVec2 v2, Scalar init);
  template<class ExecutionPolicy, @\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, @\exposconcept{scalar}@ Scalar>
    Scalar dot(ExecutionPolicy&& exec, InVec1 v1, InVec2 v2, Scalar init);
  template<@\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2>
    auto dot(InVec1 v1, InVec2 v2);
  template<class ExecutionPolicy, @\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2>
    auto dot(ExecutionPolicy&& exec, InVec1 v1, InVec2 v2);

  template<@\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, @\exposconcept{scalar}@ Scalar>
    Scalar dotc(InVec1 v1, InVec2 v2, Scalar init);
  template<class ExecutionPolicy, @\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, @\exposconcept{scalar}@ Scalar>
    Scalar dotc(ExecutionPolicy&& exec, InVec1 v1, InVec2 v2, Scalar init);
  template<@\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2>
    auto dotc(InVec1 v1, InVec2 v2);
  template<class ExecutionPolicy, @\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2>
    auto dotc(ExecutionPolicy&& exec, InVec1 v1, InVec2 v2);

  // \ref{linalg.algs.blas1.nrm2}, Euclidean norm of a vector
  template<@\exposconcept{in-vector}@ InVec, @\exposconcept{scalar}@ Scalar>
    Scalar vector_two_norm(InVec v, Scalar init);
  template<class ExecutionPolicy, @\exposconcept{in-vector}@ InVec, @\exposconcept{scalar}@ Scalar>
    Scalar vector_two_norm(ExecutionPolicy&& exec, InVec v, Scalar init);
  template<@\exposconcept{in-vector}@ InVec>
    auto vector_two_norm(InVec v);
  template<class ExecutionPolicy, @\exposconcept{in-vector}@ InVec>
    auto vector_two_norm(ExecutionPolicy&& exec, InVec v);

  // \ref{linalg.algs.blas1.asum}, sum of absolute values of vector elements
  template<@\exposconcept{in-vector}@ InVec, @\exposconcept{scalar}@ Scalar>
    Scalar vector_abs_sum(InVec v, Scalar init);
  template<class ExecutionPolicy, @\exposconcept{in-vector}@ InVec, @\exposconcept{scalar}@ Scalar>
    Scalar vector_abs_sum(ExecutionPolicy&& exec, InVec v, Scalar init);
  template<@\exposconcept{in-vector}@ InVec>
    auto vector_abs_sum(InVec v);
  template<class ExecutionPolicy, @\exposconcept{in-vector}@ InVec>
    auto vector_abs_sum(ExecutionPolicy&& exec, InVec v);

  // \ref{linalg.algs.blas1.iamax}, index of maximum absolute value of vector elements
  template<@\exposconcept{in-vector}@ InVec>
    typename InVec::extents_type vector_idx_abs_max(InVec v);
  template<class ExecutionPolicy, @\exposconcept{in-vector}@ InVec>
    typename InVec::extents_type vector_idx_abs_max(ExecutionPolicy&& exec, InVec v);

  // \ref{linalg.algs.blas1.matfrobnorm}, Frobenius norm of a matrix
  template<@\exposconcept{in-matrix}@ InMat, @\exposconcept{scalar}@ Scalar>
    Scalar matrix_frob_norm(InMat A, Scalar init);
  template<class ExecutionPolicy, @\exposconcept{in-matrix}@ InMat, @\exposconcept{scalar}@ Scalar>
    Scalar matrix_frob_norm(ExecutionPolicy&& exec, InMat A, Scalar init);
  template<@\exposconcept{in-matrix}@ InMat>
    auto matrix_frob_norm(InMat A);
  template<class ExecutionPolicy, @\exposconcept{in-matrix}@ InMat>
    auto matrix_frob_norm(ExecutionPolicy&& exec, InMat A);

  // \ref{linalg.algs.blas1.matonenorm}, one norm of a matrix
  template<@\exposconcept{in-matrix}@ InMat, @\exposconcept{scalar}@ Scalar>
    Scalar matrix_one_norm(InMat A, Scalar init);
  template<class ExecutionPolicy, @\exposconcept{in-matrix}@ InMat, @\exposconcept{scalar}@ Scalar>
    Scalar matrix_one_norm(ExecutionPolicy&& exec, InMat A, Scalar init);
  template<@\exposconcept{in-matrix}@ InMat>
    auto matrix_one_norm(InMat A);
  template<class ExecutionPolicy, @\exposconcept{in-matrix}@ InMat>
    auto matrix_one_norm(ExecutionPolicy&& exec, InMat A);

  // \ref{linalg.algs.blas1.matinfnorm}, infinity norm of a matrix
  template<@\exposconcept{in-matrix}@ InMat, @\exposconcept{scalar}@ Scalar>
    Scalar matrix_inf_norm(InMat A, Scalar init);
  template<class ExecutionPolicy, @\exposconcept{in-matrix}@ InMat, @\exposconcept{scalar}@ Scalar>
    Scalar matrix_inf_norm(ExecutionPolicy&& exec, InMat A, Scalar init);
  template<@\exposconcept{in-matrix}@ InMat>
    auto matrix_inf_norm(InMat A);
  template<class ExecutionPolicy, @\exposconcept{in-matrix}@ InMat>
    auto matrix_inf_norm(ExecutionPolicy&& exec, InMat A);

  // \ref{linalg.algs.blas2}, BLAS 2 algorithms

  // \ref{linalg.algs.blas2.gemv}, general matrix-vector product
  template<@\exposconcept{in-matrix}@ InMat, @\exposconcept{in-vector}@ InVec, @\exposconcept{out-vector}@ OutVec>
    void matrix_vector_product(InMat A, InVec x, OutVec y);
  template<class ExecutionPolicy, @\exposconcept{in-matrix}@ InMat, @\exposconcept{in-vector}@ InVec, @\exposconcept{out-vector}@ OutVec>
    void matrix_vector_product(ExecutionPolicy&& exec, InMat A, InVec x, OutVec y);
  template<@\exposconcept{in-matrix}@ InMat, @\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, @\exposconcept{out-vector}@ OutVec>
    void matrix_vector_product(InMat A, InVec1 x, InVec2 y, OutVec z);
  template<class ExecutionPolicy,
           @\exposconcept{in-matrix}@ InMat, @\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, @\exposconcept{out-vector}@ OutVec>
    void matrix_vector_product(ExecutionPolicy&& exec, InMat A, InVec1 x, InVec2 y, OutVec z);

  // \ref{linalg.algs.blas2.symv}, symmetric matrix-vector product
  template<@\exposconcept{in-matrix}@ InMat, class Triangle, @\exposconcept{in-vector}@ InVec, @\exposconcept{out-vector}@ OutVec>
    void symmetric_matrix_vector_product(InMat A, Triangle t, InVec x, OutVec y);
  template<class ExecutionPolicy,
           @\exposconcept{in-matrix}@ InMat, class Triangle, @\exposconcept{in-vector}@ InVec, @\exposconcept{out-vector}@ OutVec>
    void symmetric_matrix_vector_product(ExecutionPolicy&& exec,
                                         InMat A, Triangle t, InVec x, OutVec y);
  template<@\exposconcept{in-matrix}@ InMat, class Triangle, @\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2,
           @\exposconcept{out-vector}@ OutVec>
    void symmetric_matrix_vector_product(InMat A, Triangle t, InVec1 x, InVec2 y, OutVec z);
  template<class ExecutionPolicy,
           @\exposconcept{in-matrix}@ InMat, class Triangle, @\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2,
           @\exposconcept{out-vector}@ OutVec>
    void symmetric_matrix_vector_product(ExecutionPolicy&& exec,
                                         InMat A, Triangle t, InVec1 x, InVec2 y, OutVec z);

  // \ref{linalg.algs.blas2.hemv}, Hermitian matrix-vector product
  template<@\exposconcept{in-matrix}@ InMat, class Triangle, @\exposconcept{in-vector}@ InVec, @\exposconcept{out-vector}@ OutVec>
    void hermitian_matrix_vector_product(InMat A, Triangle t, InVec x, OutVec y);
  template<class ExecutionPolicy,
           @\exposconcept{in-matrix}@ InMat, class Triangle, @\exposconcept{in-vector}@ InVec, @\exposconcept{out-vector}@ OutVec>
    void hermitian_matrix_vector_product(ExecutionPolicy&& exec,
                                         InMat A, Triangle t, InVec x, OutVec y);
  template<@\exposconcept{in-matrix}@ InMat, class Triangle, @\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2,
           @\exposconcept{out-vector}@ OutVec>
    void hermitian_matrix_vector_product(InMat A, Triangle t, InVec1 x, InVec2 y, OutVec z);
  template<class ExecutionPolicy,
           @\exposconcept{in-matrix}@ InMat, class Triangle, @\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2,
           @\exposconcept{out-vector}@ OutVec>
    void hermitian_matrix_vector_product(ExecutionPolicy&& exec,
                                         InMat A, Triangle t, InVec1 x, InVec2 y, OutVec z);

  // \ref{linalg.algs.blas2.trmv}, triangular matrix-vector product

  // Overwriting triangular matrix-vector product
  template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, @\exposconcept{in-vector}@ InVec,
           @\exposconcept{out-vector}@ OutVec>
    void triangular_matrix_vector_product(InMat A, Triangle t, DiagonalStorage d,
                                          InVec x, OutVec y);
  template<class ExecutionPolicy,
           @\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, @\exposconcept{in-vector}@ InVec,
           @\exposconcept{out-vector}@ OutVec>
    void triangular_matrix_vector_product(ExecutionPolicy&& exec,
                                          InMat A, Triangle t, DiagonalStorage d,
                                          InVec x, OutVec y);

  // In-place triangular matrix-vector product
  template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, @\exposconcept{inout-vector}@ InOutVec>
    void triangular_matrix_vector_product(InMat A, Triangle t, DiagonalStorage d, InOutVec y);
  template<class ExecutionPolicy,
           @\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, @\exposconcept{inout-vector}@ InOutVec>
    void triangular_matrix_vector_product(ExecutionPolicy&& exec,
                                          InMat A, Triangle t, DiagonalStorage d, InOutVec y);

  // Updating triangular matrix-vector product
  template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage,
           @\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, @\exposconcept{out-vector}@ OutVec>
    void triangular_matrix_vector_product(InMat A, Triangle t, DiagonalStorage d,
                                          InVec1 x, InVec2 y, OutVec z);
  template<class ExecutionPolicy, @\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage,
           @\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, @\exposconcept{out-vector}@ OutVec>
    void triangular_matrix_vector_product(ExecutionPolicy&& exec,
                                          InMat A, Triangle t, DiagonalStorage d,
                                          InVec1 x, InVec2 y, OutVec z);

  // \ref{linalg.algs.blas2.trsv}, solve a triangular linear system

  // Solve a triangular linear system, not in place
  template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage,
           @\exposconcept{in-vector}@ InVec, @\exposconcept{out-vector}@ OutVec, class BinaryDivideOp>
    void triangular_matrix_vector_solve(InMat A, Triangle t, DiagonalStorage d,
                                        InVec b, OutVec x, BinaryDivideOp divide);
  template<class ExecutionPolicy, @\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage,
           @\exposconcept{in-vector}@ InVec, @\exposconcept{out-vector}@ OutVec, class BinaryDivideOp>
    void triangular_matrix_vector_solve(ExecutionPolicy&& exec,
                                        InMat A, Triangle t, DiagonalStorage d,
                                        InVec b, OutVec x, BinaryDivideOp divide);
  template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage,
           @\exposconcept{in-vector}@ InVec, @\exposconcept{out-vector}@ OutVec>
    void triangular_matrix_vector_solve(InMat A, Triangle t, DiagonalStorage d,
                                        InVec b, OutVec x);
  template<class ExecutionPolicy, @\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage,
           @\exposconcept{in-vector}@ InVec, @\exposconcept{out-vector}@ OutVec>
    void triangular_matrix_vector_solve(ExecutionPolicy&& exec,
                                        InMat A, Triangle t, DiagonalStorage d,
                                        InVec b, OutVec x);

  // Solve a triangular linear system, in place
  template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage,
           @\exposconcept{inout-vector}@ InOutVec, class BinaryDivideOp>
    void triangular_matrix_vector_solve(InMat A, Triangle t, DiagonalStorage d,
                                        InOutVec b, BinaryDivideOp divide);
  template<class ExecutionPolicy, @\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage,
           @\exposconcept{inout-vector}@ InOutVec, class BinaryDivideOp>
    void triangular_matrix_vector_solve(ExecutionPolicy&& exec,
                                        InMat A, Triangle t, DiagonalStorage d,
                                        InOutVec b, BinaryDivideOp divide);
  template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, @\exposconcept{inout-vector}@ InOutVec>
    void triangular_matrix_vector_solve(InMat A, Triangle t, DiagonalStorage d, InOutVec b);
  template<class ExecutionPolicy,
           @\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, @\exposconcept{inout-vector}@ InOutVec>
    void triangular_matrix_vector_solve(ExecutionPolicy&& exec,
                                        InMat A, Triangle t, DiagonalStorage d, InOutVec b);

  // \ref{linalg.algs.blas2.rank1}, nonsymmetric rank-1 matrix update

  // overwriting nonsymmetric rank-1 matrix update
  template<@\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, @\exposconcept{out-matrix}@ OutMat>
    void matrix_rank_1_update(InVec1 x, InVec2 y, OutMat A);
  template<class ExecutionPolicy, @\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, @\exposconcept{out-matrix}@ OutMat>
    void matrix_rank_1_update(ExecutionPolicy&& exec, InVec1 x, InVec2 y, OutMat A);

  template<@\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, @\exposconcept{out-matrix}@ OutMat>
    void matrix_rank_1_update_c(InVec1 x, InVec2 y, OutMat A);
  template<class ExecutionPolicy, @\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, @\exposconcept{out-matrix}@ OutMat>
    void matrix_rank_1_update_c(ExecutionPolicy&& exec, InVec1 x, InVec2 y, OutMat A);

  // updating nonsymmetric rank-1 matrix update
  template<@\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, @\exposconcept{in-matrix}@ InMat, @\exposconcept{out-matrix}@ OutMat>
    void matrix_rank_1_update(InVec1 x, InVec2 y, InMat E, OutMat A);
  template<class ExecutionPolicy, @\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, @\exposconcept{in-matrix}@ InMat,
           @\exposconcept{out-matrix}@ OutMat>
    void matrix_rank_1_update(ExecutionPolicy&& exec,
                              InVec1 x, InVec2 y, InMat E, OutMat A);

  template<@\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, @\exposconcept{in-matrix}@ InMat, @\exposconcept{out-matrix}@ OutMat>
    void matrix_rank_1_update_c(InVec1 x, InVec2 y, InMat E, OutMat A);
  template<class ExecutionPolicy, @\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, @\exposconcept{in-matrix}@ InMat,
           @\exposconcept{out-matrix}@ OutMat>
    void matrix_rank_1_update_c(ExecutionPolicy&& exec,
                                InVec1 x, InVec2 y, InMat E, OutMat A);

  // \ref{linalg.algs.blas2.symherrank1}, symmetric or Hermitian rank-1 matrix update

  // overwriting symmetric rank-1 matrix update
  template<@\exposconcept{scalar}@ Scalar, @\exposconcept{in-vector}@ InVec, @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle>
    void symmetric_matrix_rank_1_update(Scalar alpha, InVec x, OutMat A, Triangle t);
  template<class ExecutionPolicy,
           @\exposconcept{scalar}@ Scalar, @\exposconcept{in-vector}@ InVec, @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle>
    void symmetric_matrix_rank_1_update(ExecutionPolicy&& exec,
                                        Scalar alpha, InVec x, OutMat A, Triangle t);

  // overwriting Hermitian rank-1 matrix update
  template<@\exposconcept{scalar}@ Scalar, @\exposconcept{in-vector}@ InVec, @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle>
    void hermitian_matrix_rank_1_update(Scalar alpha, InVec x, OutMat A, Triangle t);
  template<class ExecutionPolicy,
           @\exposconcept{scalar}@ Scalar, @\exposconcept{in-vector}@ InVec, @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle>
    void hermitian_matrix_rank_1_update(ExecutionPolicy&& exec,
                                        Scalar alpha, InVec x, OutMat A, Triangle t);

  // updating symmetric rank-1 matrix update
  template<@\exposconcept{scalar}@ Scalar, @\exposconcept{in-vector}@ InVec, @\exposconcept{in-matrix}@ InMat, @\exposconcept{possibly-packed-out-matrix}@ OutMat,
           class Triangle>
    void symmetric_matrix_rank_1_update(Scalar alpha, InVec x, InMat E, OutMat A, Triangle t);
  template<class ExecutionPolicy,
           @\exposconcept{scalar}@ Scalar, @\exposconcept{in-vector}@ InVec, @\exposconcept{in-matrix}@ InMat, @\exposconcept{possibly-packed-out-matrix}@ OutMat,
           class Triangle>
    void symmetric_matrix_rank_1_update(ExecutionPolicy&& exec,
                                        Scalar alpha, InVec x, InMat E, OutMat A, Triangle t);

  // updating Hermitian rank-1 matrix update
  template<@\exposconcept{scalar}@ Scalar, @\exposconcept{in-vector}@ InVec, @\exposconcept{in-matrix}@ InMat, @\exposconcept{possibly-packed-out-matrix}@ OutMat,
           class Triangle>
    void hermitian_matrix_rank_1_update(Scalar alpha, InVec x, InMat E, OutMat A, Triangle t);
  template<class ExecutionPolicy,
           @\exposconcept{scalar}@ Scalar, @\exposconcept{in-vector}@ InVec, @\exposconcept{in-matrix}@ InMat, @\exposconcept{possibly-packed-out-matrix}@ OutMat,
           class Triangle>
    void hermitian_matrix_rank_1_update(ExecutionPolicy&& exec,
                                        Scalar alpha, InVec x, InMat E, OutMat A, Triangle t);

  // \ref{linalg.algs.blas2.rank2}, symmetric and Hermitian rank-2 matrix updates

  // overwriting symmetric rank-2 matrix update
  template<@\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2,
           @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle>
    void symmetric_matrix_rank_2_update(InVec1 x, InVec2 y, OutMat A, Triangle t);
  template<class ExecutionPolicy, @\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2,
           @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle>
    void symmetric_matrix_rank_2_update(ExecutionPolicy&& exec,
                                        InVec1 x, InVec2 y, OutMat A, Triangle t);

  // overwriting Hermitian rank-2 matrix update
  template<@\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2,
           @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle>
    void hermitian_matrix_rank_2_update(InVec1 x, InVec2 y, OutMat A, Triangle t);
  template<class ExecutionPolicy, @\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2,
           @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle>
    void hermitian_matrix_rank_2_update(ExecutionPolicy&& exec,
                                        InVec1 x, InVec2 y, OutMat A, Triangle t);

  // updating symmetric rank-2 matrix update
  template<@\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2,
           @\exposconcept{in-matrix}@ InMat,
           @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle>
    void symmetric_matrix_rank_2_update(InVec1 x, InVec2 y, InMat E, OutMat A, Triangle t);
  template<class ExecutionPolicy, @\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2,
           @\exposconcept{in-matrix}@ InMat,
           @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle>
    void symmetric_matrix_rank_2_update(ExecutionPolicy&& exec,
                                        InVec1 x, InVec2 y, InMat E, OutMat A, Triangle t);

  // updating Hermitian rank-2 matrix update
  template<@\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2,
           @\exposconcept{in-matrix}@ InMat,
           @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle>
    void hermitian_matrix_rank_2_update(InVec1 x, InVec2 y, InMat E, OutMat A, Triangle t);
  template<class ExecutionPolicy, @\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2,
           @\exposconcept{in-matrix}@ InMat,
           @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle>
    void hermitian_matrix_rank_2_update(ExecutionPolicy&& exec,
                                        InVec1 x, InVec2 y, InMat E, OutMat A, Triangle t);

  // \ref{linalg.algs.blas3}, BLAS 3 algorithms

  // \ref{linalg.algs.blas3.gemm}, general matrix-matrix product
  template<@\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, @\exposconcept{out-matrix}@ OutMat>
    void matrix_product(InMat1 A, InMat2 B, OutMat C);
  template<class ExecutionPolicy, @\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, @\exposconcept{out-matrix}@ OutMat>
    void matrix_product(ExecutionPolicy&& exec,
                        InMat1 A, InMat2 B, OutMat C);
  template<@\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, @\exposconcept{in-matrix}@ InMat3, @\exposconcept{out-matrix}@ OutMat>
    void matrix_product(InMat1 A, InMat2 B, InMat3 E, OutMat C);
  template<class ExecutionPolicy,
           @\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, @\exposconcept{in-matrix}@ InMat3, @\exposconcept{out-matrix}@ OutMat>
    void matrix_product(ExecutionPolicy&& exec,
                        InMat1 A, InMat2 B, InMat3 E, OutMat C);

  // \ref{linalg.algs.blas3.xxmm}, symmetric, Hermitian, and triangular matrix-matrix product

  template<@\exposconcept{in-matrix}@ InMat1, class Triangle, @\exposconcept{in-matrix}@ InMat2, @\exposconcept{out-matrix}@ OutMat>
    void symmetric_matrix_product(InMat1 A, Triangle t, InMat2 B, OutMat C);
  template<class ExecutionPolicy,
           @\exposconcept{in-matrix}@ InMat1, class Triangle, @\exposconcept{in-matrix}@ InMat2, @\exposconcept{out-matrix}@ OutMat>
    void symmetric_matrix_product(ExecutionPolicy&& exec,
                                  InMat1 A, Triangle t, InMat2 B, OutMat C);

  template<@\exposconcept{in-matrix}@ InMat1, class Triangle, @\exposconcept{in-matrix}@ InMat2, @\exposconcept{out-matrix}@ OutMat>
    void hermitian_matrix_product(InMat1 A, Triangle t, InMat2 B, OutMat C);
  template<class ExecutionPolicy,
           @\exposconcept{in-matrix}@ InMat1, class Triangle, @\exposconcept{in-matrix}@ InMat2, @\exposconcept{out-matrix}@ OutMat>
    void hermitian_matrix_product(ExecutionPolicy&& exec,
                                  InMat1 A, Triangle t, InMat2 B, OutMat C);

  template<@\exposconcept{in-matrix}@ InMat1, class Triangle, class DiagonalStorage,
           @\exposconcept{in-matrix}@ InMat2, @\exposconcept{out-matrix}@ OutMat>
    void triangular_matrix_product(InMat1 A, Triangle t, DiagonalStorage d, InMat2 B, OutMat C);
  template<class ExecutionPolicy,
           @\exposconcept{in-matrix}@ InMat1, class Triangle, class DiagonalStorage,
           @\exposconcept{in-matrix}@ InMat2, @\exposconcept{out-matrix}@ OutMat>
    void triangular_matrix_product(ExecutionPolicy&& exec,
                                   InMat1 A, Triangle t, DiagonalStorage d, InMat2 B, OutMat C);

  template<@\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, class Triangle, @\exposconcept{out-matrix}@ OutMat>
    void symmetric_matrix_product(InMat1 A, InMat2 B, Triangle t, OutMat C);
  template<class ExecutionPolicy,
           @\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, class Triangle, @\exposconcept{out-matrix}@ OutMat>
    void symmetric_matrix_product(ExecutionPolicy&& exec,
                                  InMat1 A, InMat2 B, Triangle t, OutMat C);

  template<@\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, class Triangle, @\exposconcept{out-matrix}@ OutMat>
    void hermitian_matrix_product(InMat1 A, InMat2 B, Triangle t, OutMat C);
  template<class ExecutionPolicy,
           @\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, class Triangle, @\exposconcept{out-matrix}@ OutMat>
    void hermitian_matrix_product(ExecutionPolicy&& exec,
                                  InMat1 A, InMat2 B, Triangle t, OutMat C);

  template<@\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, class Triangle, class DiagonalStorage,
           @\exposconcept{out-matrix}@ OutMat>
    void triangular_matrix_product(InMat1 A, InMat2 B, Triangle t, DiagonalStorage d, OutMat C);
  template<class ExecutionPolicy,
           @\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, class Triangle, class DiagonalStorage,
           @\exposconcept{out-matrix}@ OutMat>
    void triangular_matrix_product(ExecutionPolicy&& exec,
                                   InMat1 A, InMat2 B, Triangle t, DiagonalStorage d, OutMat C);

  template<@\exposconcept{in-matrix}@ InMat1, class Triangle, @\exposconcept{in-matrix}@ InMat2, @\exposconcept{in-matrix}@ InMat3,
           @\exposconcept{out-matrix}@ OutMat>
    void symmetric_matrix_product(InMat1 A, Triangle t, InMat2 B, InMat3 E, OutMat C);
  template<class ExecutionPolicy,
           @\exposconcept{in-matrix}@ InMat1, class Triangle, @\exposconcept{in-matrix}@ InMat2, @\exposconcept{in-matrix}@ InMat3,
           @\exposconcept{out-matrix}@ OutMat>
    void symmetric_matrix_product(ExecutionPolicy&& exec,
                                  InMat1 A, Triangle t, InMat2 B, InMat3 E, OutMat C);

  template<@\exposconcept{in-matrix}@ InMat1, class Triangle, @\exposconcept{in-matrix}@ InMat2, @\exposconcept{in-matrix}@ InMat3,
           @\exposconcept{out-matrix}@ OutMat>
    void hermitian_matrix_product(InMat1 A, Triangle t, InMat2 B, InMat3 E, OutMat C);
  template<class ExecutionPolicy,
           @\exposconcept{in-matrix}@ InMat1, class Triangle, @\exposconcept{in-matrix}@ InMat2, @\exposconcept{in-matrix}@ InMat3,
           @\exposconcept{out-matrix}@ OutMat>
    void hermitian_matrix_product(ExecutionPolicy&& exec,
                                  InMat1 A, Triangle t, InMat2 B, InMat3 E, OutMat C);

  template<@\exposconcept{in-matrix}@ InMat1, class Triangle, class DiagonalStorage,
           @\exposconcept{in-matrix}@ InMat2, @\exposconcept{in-matrix}@ InMat3, @\exposconcept{out-matrix}@ OutMat>
    void triangular_matrix_product(InMat1 A, Triangle t, DiagonalStorage d, InMat2 B, InMat3 E,
                                   OutMat C);
  template<class ExecutionPolicy,
           @\exposconcept{in-matrix}@ InMat1, class Triangle, class DiagonalStorage,
           @\exposconcept{in-matrix}@ InMat2, @\exposconcept{in-matrix}@ InMat3, @\exposconcept{out-matrix}@ OutMat>
    void triangular_matrix_product(ExecutionPolicy&& exec,
                                   InMat1 A, Triangle t, DiagonalStorage d, InMat2 B, InMat3 E,
                                   OutMat C);

  template<@\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, class Triangle, @\exposconcept{in-matrix}@ InMat3,
           @\exposconcept{out-matrix}@ OutMat>
    void symmetric_matrix_product(InMat1 A, InMat2 B, Triangle t, InMat3 E, OutMat C);
  template<class ExecutionPolicy,
           @\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, class Triangle, @\exposconcept{in-matrix}@ InMat3,
           @\exposconcept{out-matrix}@ OutMat>
    void symmetric_matrix_product(ExecutionPolicy&& exec,
                                  InMat1 A, InMat2 B, Triangle t, InMat3 E, OutMat C);

  template<@\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, class Triangle, @\exposconcept{in-matrix}@ InMat3,
           @\exposconcept{out-matrix}@ OutMat>
    void hermitian_matrix_product(InMat1 A, InMat2 B, Triangle t, InMat3 E, OutMat C);
  template<class ExecutionPolicy,
           @\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, class Triangle, @\exposconcept{in-matrix}@ InMat3,
           @\exposconcept{out-matrix}@ OutMat>
    void hermitian_matrix_product(ExecutionPolicy&& exec,
                                  InMat1 A, InMat2 B, Triangle t, InMat3 E, OutMat C);

  template<@\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, class Triangle, class DiagonalStorage,
           @\exposconcept{in-matrix}@ InMat3, @\exposconcept{out-matrix}@ OutMat>
    void triangular_matrix_product(InMat1 A, InMat2 B, Triangle t, DiagonalStorage d, InMat3 E,
                                   OutMat C);
  template<class ExecutionPolicy,
           @\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, class Triangle, class DiagonalStorage,
           @\exposconcept{in-matrix}@ InMat3, @\exposconcept{out-matrix}@ OutMat>
    void triangular_matrix_product(ExecutionPolicy&& exec,
                                   InMat1 A, InMat2 B, Triangle t, DiagonalStorage d, InMat3 E,
                                   OutMat C);

  // \ref{linalg.algs.blas3.trmm}, in-place triangular matrix-matrix product

  template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, @\exposconcept{inout-matrix}@ InOutMat>
    void triangular_matrix_left_product(InMat A, Triangle t, DiagonalStorage d, InOutMat C);
  template<class ExecutionPolicy,
           @\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, @\exposconcept{inout-matrix}@ InOutMat>
    void triangular_matrix_left_product(ExecutionPolicy&& exec,
                                        InMat A, Triangle t, DiagonalStorage d, InOutMat C);

  template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, @\exposconcept{inout-matrix}@ InOutMat>
    void triangular_matrix_right_product(InMat A, Triangle t, DiagonalStorage d, InOutMat C);
  template<class ExecutionPolicy,
           @\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, @\exposconcept{inout-matrix}@ InOutMat>
    void triangular_matrix_right_product(ExecutionPolicy&& exec,
                                         InMat A, Triangle t, DiagonalStorage d, InOutMat C);

  // \ref{linalg.algs.blas3.rankk}, rank-k update of a symmetric or Hermitian matrix

  // overwriting rank-k symmetric matrix update
  template<@\exposconcept{scalar}@ Scalar, @\exposconcept{in-matrix}@ InMat, @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle>
    void symmetric_matrix_rank_k_update(Scalar alpha, InMat A, OutMat C, Triangle t);
  template<class ExecutionPolicy, @\exposconcept{scalar}@ Scalar,
           @\exposconcept{in-matrix}@ InMat, @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle>
    void symmetric_matrix_rank_k_update(ExecutionPolicy&& exec,
                                        Scalar alpha, InMat A, OutMat C, Triangle t);

  // overwriting rank-k Hermitian matrix update
  template<@\exposconcept{scalar}@ Scalar, @\exposconcept{in-matrix}@ InMat, @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle>
    void hermitian_matrix_rank_k_update(Scalar alpha, InMat A, OutMat C, Triangle t);
  template<class ExecutionPolicy,
           @\exposconcept{scalar}@ Scalar, @\exposconcept{in-matrix}@ InMat, @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle>
    void hermitian_matrix_rank_k_update(ExecutionPolicy&& exec,
                                        Scalar alpha, InMat A, OutMat C, Triangle t);

  // updating rank-k symmetric matrix update
  template<@\exposconcept{scalar}@ Scalar, @\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2,
           @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle>
    void symmetric_matrix_rank_k_update(Scalar alpha, InMat1 A, InMat2 E, OutMat C, Triangle t);
  template<class ExecutionPolicy,
           @\exposconcept{scalar}@ Scalar, @\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2,
           @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle>
    void symmetric_matrix_rank_k_update(ExecutionPolicy&& exec, Scalar alpha,
                                        InMat1 A, InMat2 E, OutMat C, Triangle t);

  // updating rank-k Hermitian matrix update
  template<@\exposconcept{scalar}@ Scalar, @\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2,
           @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle>
    void hermitian_matrix_rank_k_update(Scalar alpha, InMat1 A, InMat2 E, OutMat C, Triangle t);
  template<class ExecutionPolicy,
           @\exposconcept{scalar}@ Scalar, @\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2,
           @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle>
    void hermitian_matrix_rank_k_update(ExecutionPolicy&& exec, Scalar alpha,
                                        InMat1 A, InMat2 E, OutMat C, Triangle t);

  // \ref{linalg.algs.blas3.rank2k}, rank-2k update of a symmetric or Hermitian matrix

  // overwriting rank-2k symmetric matrix update
  template<@\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2,
           @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle>
    void symmetric_matrix_rank_2k_update(InMat1 A, InMat2 B, OutMat C, Triangle t);
  template<class ExecutionPolicy,
           @\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2,
           @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle>
    void symmetric_matrix_rank_2k_update(ExecutionPolicy&& exec,
                                         InMat1 A, InMat2 B, OutMat C, Triangle t);

  // overwriting rank-2k Hermitian matrix update
  template<@\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2,
           @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle>
    void hermitian_matrix_rank_2k_update(InMat1 A, InMat2 B, OutMat C, Triangle t);
  template<class ExecutionPolicy,
           @\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2,
           @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle>
    void hermitian_matrix_rank_2k_update(ExecutionPolicy&& exec,
                                         InMat1 A, InMat2 B, OutMat C, Triangle t);

  // updating symmetric rank-2k matrix update
  template<@\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, @\exposconcept{in-matrix}@ InMat3,
           @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle>
    void symmetric_matrix_rank_2k_update(InMat1 A, InMat2 B, InMat3 E, OutMat C, Triangle t);
  template<class ExecutionPolicy,
           @\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, @\exposconcept{in-matrix}@ InMat3,
           @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle>
    void symmetric_matrix_rank_2k_update(ExecutionPolicy&& exec,
                                         InMat1 A, InMat2 B, InMat3 E, OutMat C, Triangle t);

  // updating Hermitian rank-2k matrix update
  template<@\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, @\exposconcept{in-matrix}@ InMat3,
           @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle>
    void hermitian_matrix_rank_2k_update(InMat1 A, InMat2 B, InMat3 E, OutMat C, Triangle t);
  template<class ExecutionPolicy,
           @\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, @\exposconcept{in-matrix}@ InMat3,
           @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle>
    void hermitian_matrix_rank_2k_update(ExecutionPolicy&& exec,
                                         InMat1 A, InMat2 B, InMat3 E, OutMat C, Triangle t);

  // \ref{linalg.algs.blas3.trsm}, solve multiple triangular linear systems

  // solve multiple triangular systems on the left, not-in-place
  template<@\exposconcept{in-matrix}@ InMat1, class Triangle, class DiagonalStorage,
           @\exposconcept{in-matrix}@ InMat2, @\exposconcept{out-matrix}@ OutMat, class BinaryDivideOp>
    void triangular_matrix_matrix_left_solve(InMat1 A, Triangle t, DiagonalStorage d,
                                             InMat2 B, OutMat X, BinaryDivideOp divide);
  template<class ExecutionPolicy,
           @\exposconcept{in-matrix}@ InMat1, class Triangle, class DiagonalStorage,
           @\exposconcept{in-matrix}@ InMat2, @\exposconcept{out-matrix}@ OutMat, class BinaryDivideOp>
    void triangular_matrix_matrix_left_solve(ExecutionPolicy&& exec,
                                             InMat1 A, Triangle t, DiagonalStorage d,
                                             InMat2 B, OutMat X, BinaryDivideOp divide);
  template<@\exposconcept{in-matrix}@ InMat1, class Triangle, class DiagonalStorage,
           @\exposconcept{in-matrix}@ InMat2, @\exposconcept{out-matrix}@ OutMat>
    void triangular_matrix_matrix_left_solve(InMat1 A, Triangle t, DiagonalStorage d,
                                             InMat2 B, OutMat X);
  template<class ExecutionPolicy,
           @\exposconcept{in-matrix}@ InMat1, class Triangle, class DiagonalStorage,
           @\exposconcept{in-matrix}@ InMat2, @\exposconcept{out-matrix}@ OutMat>
    void triangular_matrix_matrix_left_solve(ExecutionPolicy&& exec,
                                             InMat1 A, Triangle t, DiagonalStorage d,
                                             InMat2 B, OutMat X);

  // solve multiple triangular systems on the right, not-in-place
  template<@\exposconcept{in-matrix}@ InMat1, class Triangle, class DiagonalStorage,
           @\exposconcept{in-matrix}@ InMat2, @\exposconcept{out-matrix}@ OutMat, class BinaryDivideOp>
    void triangular_matrix_matrix_right_solve(InMat1 A, Triangle t, DiagonalStorage d,
                                              InMat2 B, OutMat X, BinaryDivideOp divide);
  template<class ExecutionPolicy,
           @\exposconcept{in-matrix}@ InMat1, class Triangle, class DiagonalStorage,
           @\exposconcept{in-matrix}@ InMat2, @\exposconcept{out-matrix}@ OutMat, class BinaryDivideOp>
    void triangular_matrix_matrix_right_solve(ExecutionPolicy&& exec,
                                              InMat1 A, Triangle t, DiagonalStorage d,
                                              InMat2 B, OutMat X, BinaryDivideOp divide);
  template<@\exposconcept{in-matrix}@ InMat1, class Triangle, class DiagonalStorage,
           @\exposconcept{in-matrix}@ InMat2, @\exposconcept{out-matrix}@ OutMat>
    void triangular_matrix_matrix_right_solve(InMat1 A, Triangle t, DiagonalStorage d,
                                              InMat2 B, OutMat X);
  template<class ExecutionPolicy,
           @\exposconcept{in-matrix}@ InMat1, class Triangle, class DiagonalStorage,
           @\exposconcept{in-matrix}@ InMat2, @\exposconcept{out-matrix}@ OutMat>
    void triangular_matrix_matrix_right_solve(ExecutionPolicy&& exec,
                                              InMat1 A, Triangle t, DiagonalStorage d,
                                              InMat2 B, OutMat X);

  // solve multiple triangular systems on the left, in-place
  template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage,
           @\exposconcept{inout-matrix}@ InOutMat, class BinaryDivideOp>
    void triangular_matrix_matrix_left_solve(InMat A, Triangle t, DiagonalStorage d,
                                             InOutMat B, BinaryDivideOp divide);
  template<class ExecutionPolicy,
           @\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage,
           @\exposconcept{inout-matrix}@ InOutMat, class BinaryDivideOp>
    void triangular_matrix_matrix_left_solve(ExecutionPolicy&& exec,
                                             InMat A, Triangle t, DiagonalStorage d,
                                             InOutMat B, BinaryDivideOp divide);
  template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, @\exposconcept{inout-matrix}@ InOutMat>
    void triangular_matrix_matrix_left_solve(InMat A, Triangle t, DiagonalStorage d,
                                             InOutMat B);
  template<class ExecutionPolicy,
           @\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, @\exposconcept{inout-matrix}@ InOutMat>
    void triangular_matrix_matrix_left_solve(ExecutionPolicy&& exec,
                                             InMat A, Triangle t, DiagonalStorage d,
                                             InOutMat B);

  // solve multiple triangular systems on the right, in-place
  template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage,
           @\exposconcept{inout-matrix}@ InOutMat, class BinaryDivideOp>
    void triangular_matrix_matrix_right_solve(InMat A, Triangle t, DiagonalStorage d,
                                              InOutMat B, BinaryDivideOp divide);
  template<class ExecutionPolicy,
           @\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage,
           @\exposconcept{inout-matrix}@ InOutMat, class BinaryDivideOp>
    void triangular_matrix_matrix_right_solve(ExecutionPolicy&& exec,
                                              InMat A, Triangle t, DiagonalStorage d,
                                              InOutMat B, BinaryDivideOp divide);
  template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, @\exposconcept{inout-matrix}@ InOutMat>
    void triangular_matrix_matrix_right_solve(InMat A, Triangle t, DiagonalStorage d,
                                              InOutMat B);
  template<class ExecutionPolicy,
           @\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, @\exposconcept{inout-matrix}@ InOutMat>
    void triangular_matrix_matrix_right_solve(ExecutionPolicy&& exec,
                                              InMat A, Triangle t, DiagonalStorage d,
                                              InOutMat B);
}
\end{codeblock}

\rSec2[linalg.general]{General}

\pnum
For the effects of all functions in \ref{linalg},
when the effects are described as
``computes $R = E$'' or ``compute $R = E$''
(for some $R$ and mathematical expression $E$),
the following apply:
\begin{itemize}
\item
$E$ has
      the conventional mathematical meaning as written.
\item
The pattern $x^T$ should be read as
      ``the transpose of $x$.''
\item
The pattern $x^H$ should be read as
      ``the conjugate transpose of $x$.''
\item
When $R$ is the same name as a function parameter
      whose type is a template parameter with \tcode{Out} in its name,
      the intent is that the result of the computation
      is written to the elements of the function parameter \tcode{R}.
\end{itemize}

\pnum
Some of the functions and types in \ref{linalg} distinguish between
the ``rows'' and the ``columns'' of a matrix.
For a matrix \tcode{A} and a multidimensional index \tcode{i, j} in \tcode{A.extents()},
\begin{itemize}
\item
\term{row} \tcode{i} of \tcode{A} is the set of elements \tcode{A[i, k1]}
      for all \tcode{k1} such that \tcode{i, k1} is in \tcode{A.extents()}; and
\item
\term{column} \tcode{j} of \tcode{A} is the set of elements \tcode{A[k0, j]}
      for all \tcode{k0} such that \tcode{k0, j} is in \tcode{A.extents()}.
\end{itemize}

\pnum
Some of the functions in \ref{linalg} distinguish between
the ``upper triangle,'' ``lower triangle,'' and ``diagonal'' of a matrix.
\begin{itemize}
\item
The \defn{diagonal} is the set of all elements of \tcode{A} accessed by
      \tcode{A[i,i]} for 0 $\le$ \tcode{i} < min(\tcode{A.extent(0)}, \tcode{A.extent(1)}).
\item
The \defnadj{upper}{triangle} of a matrix \tcode{A} is the set of all elements of
      \tcode{A} accessed by \tcode{A[i,j]} with \tcode{i} $\le$ \tcode{j}.  It includes the diagonal.
\item
The \defnadj{lower}{triangle} of \tcode{A} is the set of all elements of \tcode{A}
      accessed by \tcode{A[i,j]} with \tcode{i} $\ge$ \tcode{j}.  It includes the diagonal.
\end{itemize}

\pnum
For any function \tcode{F} that takes
a parameter named \tcode{t},
\tcode{t} applies to accesses done through the parameter preceding \tcode{t} in the parameter list of \tcode{F}.
Let \tcode{m} be such an access-modified function parameter.
\tcode{F} will only access the triangle of \tcode{m} specified by \tcode{t}.
For accesses of diagonal elements \tcode{m[i, i]},
\tcode{F} will use the value \tcode{\exposid{real-if-needed}(m[i, i])}
if the name of \tcode{F} starts with \tcode{hermitian}.
For accesses \tcode{m[i, j]} outside the triangle specified by \tcode{t},
\tcode{F} will use the value
\begin{itemize}
\item
\tcode{\exposid{conj-if-needed}(m[j, i])} if the name of \tcode{F} starts with \tcode{hermitian},
\item
\tcode{m[j, i]} if the name of \tcode{F} starts with \tcode{symmetric}, or
\item
the additive identity if the name of \tcode{F} starts with \tcode{triangular}.
\end{itemize}
\begin{example}
Small vector product accessing only specified triangle.
It would not be a precondition violation for the non-accessed
matrix element to be non-zero.
\begin{codeblock}
template<class Triangle>
void triangular_matrix_vector_2x2_product(
       mdspan<const float, extents<int, 2, 2>> m,
       Triangle t,
       mdspan<const float, extents<int, 2>> x,
       mdspan<float, extents<int, 2>> y) {

  static_assert(is_same_v<Triangle, lower_triangle_t> ||
                is_same_v<Triangle, upper_triangle_t>);

  if constexpr (is_same_v<Triangle, lower_triangle_t>) {
    y[0] = m[0,0] * x[0];       // \tcode{+ 0 * x[1]}
    y[1] = m[1,0] * x[0] + m[1,1] * x[1];
  } else {                      // upper_triangle_t
    y[0] = m[0,0] * x[0] + m[0,1] * x[1];
    y[1] = /* 0 * x[0] + */ m[1,1] * x[1];
  }
}
\end{codeblock}
\end{example}

\pnum
For any function \tcode{F} that takes a parameter named \tcode{d},
\tcode{d} applies to accesses done through
the previous-of-the-previous parameter of \tcode{d}
in the parameter list of \tcode{F}.
Let \tcode{m} be such an access-modified function parameter.
If \tcode{d} specifies that an implicit unit diagonal is to be assumed, then
\begin{itemize}
\item
\tcode{F} will not access the diagonal of \tcode{m}; and
\item
the algorithm will interpret \tcode{m} as if it has a unit diagonal, that is,
a diagonal each of whose elements behaves as a two-sided multiplicative identity
(even if \tcode{m}'s value type does not have
a two-sided multiplicative identity).
\end{itemize}
Otherwise,
if \tcode{d} specifies that an explicit diagonal is to be assumed,
then \tcode{F} will access the diagonal of \tcode{m}.

\pnum
Within all the functions in \ref{linalg},
any calls to \tcode{abs}, \tcode{conj}, \tcode{imag}, and \tcode{real}
are unqualified.

\pnum
Two \tcode{mdspan} objects \tcode{x} and \tcode{y} \term{alias} each other,
if they have the same extents \tcode{e}, and
for every pack of integers \tcode{i}
which is a multidimensional index in \tcode{e},
\tcode{x[i...]} and \tcode{y[i...]} refer to the same element.
\begin{note}
This means that
\tcode{x} and \tcode{y} view the same elements in the same order.
\end{note}

\pnum
Two \tcode{mdspan} objects \tcode{x} and \tcode{y} \term{overlap} each other,
if for some pack of integers \tcode{i}
that is a multidimensional index in \tcode{x.extents()},
there exists a pack of integers \tcode{j}
that is a multidimensional index in \tcode{y.extents()},
such that \tcode{x[i...]} and \tcode{y[j...]} refer to the same element.
\begin{note}
Aliasing is a special case of overlapping.
If \tcode{x} and \tcode{y} do not overlap,
then they also do not alias each other.
\end{note}

\rSec2[linalg.reqs]{Requirements}

\rSec3[linalg.reqs.val]{Linear algebra value types}

\pnum
Throughout \ref{linalg},
the following types are
\defnadjx{linear algebra}{value types}{value type}:
\begin{itemize}
\item
the \tcode{value_type} type alias of
any input or output \tcode{mdspan} parameter(s) of
any function in \ref{linalg}; and
\item
the \tcode{Scalar} template parameter (if any) of
any function or class in \ref{linalg}.
\end{itemize}

\pnum
Linear algebra value types shall model \exposconcept{scalar}.

\pnum
A value-initialized object of linear algebra value type
shall act as the additive identity.

\rSec3[linalg.reqs.alg]{Algorithm and class requirements}

\pnum
\ref{linalg.reqs.alg} lists common requirements for
all algorithms and classes in \ref{linalg}.

\pnum
All of the following statements presume
that the algorithm's asymptotic complexity requirements, if any, are satisfied.
\begin{itemize}
\item
The function may make arbitrarily many objects of any linear algebra value type,
value-initializing or direct-initializing them
with any existing object of that type.
\item
The \term{triangular solve algorithms} in
\ref{linalg.algs.blas2.trsv},
\ref{linalg.algs.blas3.trmm},
\ref{linalg.algs.blas3.trsm}, and
\ref{linalg.algs.blas3.inplacetrsm}
either have
a \tcode{BinaryDi\-videOp} template parameter (see \ref{linalg.algs.reqs}) and
a binary function object parameter \tcode{divide} of that type,
or they have effects equivalent to invoking such an algorithm.
Triangular solve algorithms interpret \tcode{divide(a, b)} as
\tcode{a} times the multiplicative inverse of \tcode{b}.
Each triangular solve algorithm uses a sequence of evaluations of
\tcode{*}, \tcode{*=}, \tcode{divide},
unary \tcode{+}, binary \tcode{+}, \tcode{+=},
unary \tcode{-}, binary \tcode{-}, \tcode{-=},
and \tcode{=} operators
that would produce the result
specified by the algorithm's \Fundescx{Effects} and \Fundescx{Remarks}
when operating on elements of a field with noncommutative multiplication.
It is a precondition of the algorithm that
any addend,
any subtrahend,
any partial sum of addends in any order
(treating any difference as a sum with the second term negated),
any factor,
any partial product of factors respecting their order,
any numerator (first argument of \tcode{divide}),
any denominator (second argument of \tcode{divide}),
and any assignment
is a well-formed expression.
\item
Each function in
\ref{linalg.algs.blas1}, \ref{linalg.algs.blas2}, and \ref{linalg.algs.blas3}
that is not a triangular solve algorithm
will use a sequence of evaluations of
\tcode{*}, \tcode{*=}, \tcode{+}, \tcode{+=}, and \tcode{=} operators
that would produce the result
specified by the algorithm's \Fundescx{Effects} and \Fundescx{Remarks}
when operating on elements of a semiring with noncommutative multiplication.
It is a precondition of the algorithm that
any addend,
any partial sum of addends in any order,
any factor,
any partial product of factors respecting their order,
and any assignment
is a well-formed expression.
\item
If the function has an output \tcode{mdspan},
then all addends,
subtrahends (for the triangular solve algorithms),
or results of the \tcode{divide} parameter on intermediate terms
(if the function takes a \tcode{divide} parameter)
are assignable and convertible to
the output \tcode{mdspan}'s \tcode{value_type}.
\item
The function may reorder addends and partial sums arbitrarily.
\begin{note}
Factors in each product are not reordered;
multiplication is not necessarily commutative.
\end{note}
\end{itemize}
\begin{note}
The above requirements do not prohibit
implementation approaches and optimization techniques
which are not user-observable.
In particular, if for all input and output arguments
the \tcode{value_type} is a floating-point type,
implementers are free to leverage approximations,
use arithmetic operations not explicitly listed above, and
compute floating-point sums in any way that improves their accuracy.
\end{note}

\pnum
\begin{note}
For all functions in \ref{linalg},
suppose that all input and output \tcode{mdspan} have as \tcode{value_type}
a floating-point type, and
any \tcode{Scalar} template argument has a floating-point type.
Then, functions can do all of the following:
\begin{itemize}
\item
compute floating-point sums in any way
that improves their accuracy for arbitrary input;
\item
perform additional arithmetic operations
(other than those specified by the function's wording and \ref{linalg.reqs.alg})
in order to improve performance or accuracy; and
\item
use approximations
(that might not be exact even if computing with real numbers),
instead of computations that would be exact
if it were possible to compute without rounding error;
\end{itemize}
as long as
\begin{itemize}
\item
the function satisfies the complexity requirements; and
\item
the function is logarithmically stable,
as defined in Demmel 2007\supercite{linalg-stable}.
Strassen's algorithm for matrix-matrix multiply
is an example of a logarithmically stable algorithm.
\end{itemize}
\end{note}

\rSec2[linalg.tags]{Tag classes}

\rSec3[linalg.tags.order]{Storage order tags}

\pnum
The storage order tags describe
the order of elements in an \tcode{mdspan} with
\tcode{layout_blas_packed}\iref{linalg.layout.packed} layout.
\begin{itemdecl}
struct @\libglobal{column_major_t}@ {
  explicit column_major_t() = default;
};
inline constexpr column_major_t @\libglobal{column_major}@{};

struct @\libglobal{row_major_t}@ {
  explicit row_major_t() = default;
};
inline constexpr row_major_t @\libglobal{row_major}@{};
\end{itemdecl}

\begin{itemdescr}
\pnum
\tcode{column_major_t} indicates a column-major order,
and \tcode{row_major_t} indicates a row-major order.
\end{itemdescr}

\rSec3[linalg.tags.triangle]{Triangle tags}

\begin{itemdecl}
struct @\libglobal{upper_triangle_t}@ {
  explicit upper_triangle_t() = default;
};
inline constexpr upper_triangle_t @\libglobal{upper_triangle}@{};

struct @\libglobal{lower_triangle_t}@ {
  explicit lower_triangle_t() = default;
};
inline constexpr lower_triangle_t @\libglobal{lower_triangle}@{};
\end{itemdecl}

\begin{itemdescr}
\pnum
These tag classes specify whether
algorithms and other users of a matrix (represented as an \tcode{mdspan})
access the
upper triangle (\tcode{upper_triangle_t}) or
lower triangle (\tcode{lower_triangle_t})
of the matrix (see also \ref{linalg.general}).
This is also subject to the restrictions of \tcode{implicit_unit_diagonal_t}
if that tag is also used as a function argument; see below.
\end{itemdescr}

\rSec3[linalg.tags.diagonal]{Diagonal tags}

\begin{itemdecl}
struct @\libglobal{implicit_unit_diagonal_t}@ {
  explicit implicit_unit_diagonal_t() = default;
};
inline constexpr implicit_unit_diagonal_t @\libglobal{implicit_unit_diagonal}@{};

struct @\libglobal{explicit_diagonal_t}@ {
  explicit explicit_diagonal_t() = default;
};
inline constexpr explicit_diagonal_t @\libglobal{explicit_diagonal}@{};
\end{itemdecl}

\begin{itemdescr}
\pnum
These tag classes specify whether algorithms
access the matrix's diagonal entries, and if not,
then how algorithms interpret
the matrix's implicitly represented diagonal values.

\pnum
The \tcode{implicit_unit_diagonal_t} tag indicates that
an implicit unit diagonal is to be assumed\iref{linalg.general}.

\pnum
The \tcode{explicit_diagonal_t} tag indicates that
an explicit diagonal is used\iref{linalg.general}.
\end{itemdescr}

\rSec2[linalg.layout.packed]{Layouts for packed matrix types}

\rSec3[linalg.layout.packed.overview]{Overview}

\pnum
\tcode{layout_blas_packed} is an \tcode{mdspan} layout mapping policy
that represents a square matrix that stores only the entries in one
triangle, in a packed contiguous format.
Its \tcode{Triangle} template parameter determines
whether an \tcode{mdspan} with this layout
stores the upper or lower triangle of the matrix.
Its \tcode{StorageOrder} template parameter determines
whether the layout packs the matrix's elements
in column-major or row-major order.

\pnum
A \tcode{StorageOrder} of \tcode{column_major_t}
indicates column-major ordering.
This packs matrix elements
starting with the leftmost (least column index) column, and
proceeding column by column, from the top entry (least row index).

\pnum
A \tcode{StorageOrder} of \tcode{row_major_t}
indicates row-major ordering.
This packs matrix elements
starting with the topmost (least row index) row, and
proceeding row by row, from the leftmost (least column index) entry.

\pnum
\begin{note}
\tcode{layout_blas_packed} describes the data layout used by
the BLAS'
Symmetric Packed (SP), Hermitian Packed (HP), and Triangular Packed (TP)
matrix types.
\end{note}
\begin{codeblock}
namespace std::linalg {
  template<class Triangle, class StorageOrder>
  class @\libglobal{layout_blas_packed}@ {
  public:
    using @\libmember{triangle_type}{layout_blas_packed}@ = Triangle;
    using @\libmember{storage_order_type}{layout_blas_packed}@ = StorageOrder;

    template<class Extents>
    struct @\libmember{mapping}{layout_blas_packed}@ {
    public:
      using @\libmember{extents_type}{layout_blas_packed::mapping}@ = Extents;
      using @\libmember{index_type}{layout_blas_packed::mapping}@ = extents_type::index_type;
      using @\libmember{size_type}{layout_blas_packed::mapping}@ = extents_type::size_type;
      using @\libmember{rank_type}{layout_blas_packed::mapping}@ = extents_type::rank_type;
      using @\libmember{layout_type}{layout_blas_packed::mapping}@ = layout_blas_packed;

      // \ref{linalg.layout.packed.cons}, constructors
      constexpr mapping() noexcept = default;
      constexpr mapping(const mapping&) noexcept = default;
      constexpr mapping(const extents_type&) noexcept;
      template<class OtherExtents>
        constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
          mapping(const mapping<OtherExtents>& other) noexcept;

      constexpr mapping& operator=(const mapping&) noexcept = default;

      // \ref{linalg.layout.packed.obs}, observers
      constexpr const extents_type& @\libmember{extents}{layout_blas_packed::mapping}@() const noexcept { return @\exposid{extents_}@; }

      constexpr index_type required_span_size() const noexcept;

      template<class Index0, class Index1>
        constexpr index_type operator() (Index0 ind0, Index1 ind1) const noexcept;

      static constexpr bool @\libmember{is_always_unique}{layout_blas_packed::mapping}@() noexcept {
        return (extents_type::static_extent(0) != dynamic_extent &&
                extents_type::static_extent(0) < 2) ||
               (extents_type::static_extent(1) != dynamic_extent &&
                extents_type::static_extent(1) < 2);
      }
      static constexpr bool @\libmember{is_always_exhaustive}{layout_blas_packed::mapping}@() noexcept { return true; }
      static constexpr bool @\libmember{is_always_strided}{layout_blas_packed::mapping}@() noexcept
        { return is_always_unique(); }

      constexpr bool @\libmember{is_unique}{layout_blas_packed::mapping}@() const noexcept {
        return @\exposid{extents_}@.extent(0) < 2;
      }
      constexpr bool @\libmember{is_exhaustive}{layout_blas_packed::mapping}@() const noexcept { return true; }
      constexpr bool @\libmember{is_strided}{layout_blas_packed::mapping}@() const noexcept {
        return @\exposid{extents_}@.extent(0) < 2;
      }

      constexpr index_type stride(rank_type) const noexcept;

      template<class OtherExtents>
        friend constexpr bool operator==(const mapping&, const mapping<OtherExtents>&) noexcept;

    private:
      extents_type @\exposid{extents_}@{};     // \expos
    };
  };
}
\end{codeblock}

\begin{itemdescr}
\pnum
\mandates
\begin{itemize}
\item
\tcode{Triangle} is either \tcode{upper_triangle_t} or \tcode{lower_triangle_t},
\item
\tcode{StorageOrder} is either \tcode{column_major_t} or \tcode{row_major_t},
\item
\tcode{Extents} is a specialization of \tcode{std::extents},
\item
\tcode{Extents::rank()} equals 2,
\item
one of
\begin{codeblock}
extents_type::static_extent(0) == dynamic_extent@\textrm{,}@
extents_type::static_extent(1) == dynamic_extent@\textrm{, or}@
extents_type::static_extent(0) == extents_type::static_extent(1)
\end{codeblock}
is \tcode{true}, and
\item
if \tcode{Extents::rank_dynamic() == 0} is \tcode{true},
let $N_s$ be equal to \tcode{Extents::static_extent(0)}; then,
$N_s \times (N_s + 1)$ is representable as a value of type \tcode{index_type}.
\end{itemize}

\pnum
\tcode{layout_blas_packed<T, SO>::mapping<E>} is a trivially copyable type
that models \libconcept{regular} for each \tcode{T}, \tcode{SO}, and \tcode{E}.
\end{itemdescr}

\rSec3[linalg.layout.packed.cons]{Constructors}

\indexlibraryctor{layout_blas_packed::mapping}%
\begin{itemdecl}
constexpr mapping(const extents_type& e) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\begin{itemize}
\item
Let $N$ be equal to \tcode{e.extent(0)}.
Then, $N \times (N+1)$ is representable as
a value of type \tcode{index_type}\iref{basic.fundamental}.
\item
\tcode{e.extent(0)} equals \tcode{e.extent(1)}.
\end{itemize}

\pnum
\effects
Direct-non-list-initializes \exposid{extents_} with \tcode{e}.
\end{itemdescr}

\indexlibraryctor{layout_blas_packed::mapping}%
\begin{itemdecl}
template<class OtherExtents>
  explicit(!is_convertible_v<OtherExtents, extents_type>)
    constexpr mapping(const mapping<OtherExtents>& other) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{is_constructible_v<extents_type, OtherExtents>} is \tcode{true}.

\pnum
\expects
Let $N$ be \tcode{other.extents().extent(0)}.
Then, $N \times (N+1)$ is representable as
a value of type \tcode{index_type}\iref{basic.fundamental}.

\pnum
\effects
Direct-non-list-initializes \exposid{extents_} with \tcode{other.extents()}.
\end{itemdescr}

\rSec3[linalg.layout.packed.obs]{Observers}

\indexlibrarymember{layout_blas_packed::mapping}{required_span_size}%
\begin{itemdecl}
constexpr index_type required_span_size() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{\exposid{extents_}.extent(0) * (\exposid{extents_}.extent(0) + 1)/2}.
\begin{note}
For example, a 5 x 5 packed matrix
only stores 15 matrix elements.
\end{note}
\end{itemdescr}

\indexlibrarymember{layout_blas_packed::mapping}{operator()}%
\begin{itemdecl}
template<class Index0, class Index1>
  constexpr index_type operator() (Index0 ind0, Index1 ind1) const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\begin{itemize}
\item
\tcode{is_convertible_v<Index0, index_type>} is \tcode{true},
\item
\tcode{is_convertible_v<Index1, index_type>} is \tcode{true},
\item
\tcode{is_nothrow_constructible_v<index_type, Index0>} is \tcode{true}, and
\item
\tcode{is_nothrow_constructible_v<index_type, Index1>} is \tcode{true}.
\end{itemize}

\pnum
Let \tcode{i} be \tcode{extents_type::\exposid{index-cast}(ind0)}, and
let \tcode{j} be \tcode{extents_type::\exposid{index-cast}(ind1)}.

\pnum
\expects
\tcode{i, j}
is a multidimensional index in \exposid{extents_}\iref{mdspan.overview}.

\pnum
\returns
Let \tcode{N} be \tcode{\exposid{extents_}.extent(0)}.
Then
\begin{itemize}
\item
\tcode{(*this)(j, i)} if \tcode{i > j} is \tcode{true}; otherwise
\item
\tcode{i + j * (j + 1)/2} if
\begin{codeblock}
is_same_v<StorageOrder, column_major_t> && is_same_v<Triangle, upper_triangle_t>
\end{codeblock}
is \tcode{true} or
\begin{codeblock}
is_same_v<StorageOrder, row_major_t> && is_same_v<Triangle, lower_triangle_t>
\end{codeblock}
is \tcode{true}; otherwise
\item
\tcode{j + N * i - i * (i + 1)/2}.
\end{itemize}
\end{itemdescr}

\indexlibrarymember{layout_blas_packed::mapping}{stride}%
\begin{itemdecl}
constexpr index_type stride(rank_type r) const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\begin{itemize}
\item
\tcode{is_strided()} is \tcode{true}, and
\item
\tcode{r < extents_type::rank()} is \tcode{true}.
\end{itemize}

\pnum
\returns
\tcode{1}.
\end{itemdescr}

\indexlibrarymember{layout_blas_packed::mapping}{operator==}%
\begin{itemdecl}
template<class OtherExtents>
  friend constexpr bool operator==(const mapping& x, const mapping<OtherExtents>& y) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return x.extents() == y.extents();}
\end{itemdescr}

\rSec2[linalg.helpers]{Exposition-only helpers}

\rSec3[linalg.helpers.abs]{\exposid{abs-if-needed}}

\pnum
The name \exposid{abs-if-needed} denotes an exposition-only function object.
The expression \tcode{\exposid{abs-if-needed}(E)} for a subexpression \tcode{E}
whose type is \tcode{T} is expression-equivalent to:
\begin{itemize}
\item
\tcode{E} if \tcode{T} is an unsigned integer;
\item
otherwise, \tcode{std::abs(E)} if \tcode{T} is an arithmetic type,
\item
otherwise, \tcode{abs(E)},
if that expression is valid,
with overload resolution performed in a context that includes the declaration
\begin{codeblock}
template<class U> U abs(U) = delete;
\end{codeblock}
If the function selected by overload resolution
does not return the absolute value of its input,
the program is ill-formed, no diagnostic required.
\end{itemize}

\rSec3[linalg.helpers.conj]{\exposid{conj-if-needed}}

\pnum
The name \exposid{conj-if-needed} denotes an exposition-only function object.
The expression \tcode{\exposid{conj-if-needed}(E)} for a subexpression \tcode{E}
whose type is \tcode{T} is expression-equivalent to:
\begin{itemize}
\item
\tcode{conj(E)},
if \tcode{T} is not an arithmetic type and
the expression \tcode{conj(E)} is valid,
with overload resolution performed in a context that includes the declaration
\begin{codeblock}
template<class U> U conj(const U&) = delete;
\end{codeblock}
If the function selected by overload resolution
does not return the complex conjugate of its input,
the program is ill-formed, no diagnostic required;
\item
otherwise, \tcode{E}.
\end{itemize}

\rSec3[linalg.helpers.real]{\exposid{real-if-needed}}

\pnum
The name \exposid{real-if-needed} denotes an exposition-only function object.
The expression \tcode{\exposid{real-if-needed}(E)} for a subexpression \tcode{E}
whose type is \tcode{T} is expression-equivalent to:
\begin{itemize}
\item
\tcode{real(E)},
if \tcode{T} is not an arithmetic type and
the expression \tcode{real(E)} is valid,
with overload resolution performed in a context that includes the declaration
\begin{codeblock}
template<class U> U real(const U&) = delete;
\end{codeblock}
If the function selected by overload resolution
does not return the real part of its input,
the program is ill-formed, no diagnostic required;
\item
otherwise, \tcode{E}.
\end{itemize}

\rSec3[linalg.helpers.imag]{\exposid{imag-if-needed}}

\pnum
The name \exposid{imag-if-needed} denotes an exposition-only function object.
The expression \tcode{\exposid{imag-if-needed}(E)} for a subexpression \tcode{E}
whose type is \tcode{T} is expression-equivalent to:
\begin{itemize}
\item
\tcode{imag(E)},
if \tcode{T} is not an arithmetic type and the expression \tcode{imag(E)}
is valid, with overload resolution performed in a context
that includes the declaration
\begin{codeblock}
template<class U> U imag(const U&) = delete;
\end{codeblock}
If the function selected by overload resolution
does not return the imaginary part of its input,
the program is ill-formed, no diagnostic required;
\item
otherwise, \tcode{((void)E, T\{\})}.
\end{itemize}

\rSec3[linalg.helpers.concepts]{Argument concepts}

\pnum
The exposition-only concepts defined in this section
constrain the algorithms in \ref{linalg}.
\begin{codeblock}
template<class T>
  constexpr bool @\exposid{is-mdspan}@ = false;

template<class ElementType, class Extents, class Layout, class Accessor>
  constexpr bool @\exposid{is-mdspan}@<mdspan<ElementType, Extents, Layout, Accessor>> = true;

template<class T>
  concept @\defexposconcept{in-vector}@ =
    @\exposid{is-mdspan}@<T> && T::rank() == 1;

template<class T>
  concept @\defexposconcept{out-vector}@ =
    @\exposid{is-mdspan}@<T> && T::rank() == 1 &&
    is_assignable_v<typename T::reference, typename T::element_type> && T::is_always_unique();

template<class T>
  concept @\defexposconcept{inout-vector}@ =
    @\exposid{is-mdspan}@<T> && T::rank() == 1 &&
    is_assignable_v<typename T::reference, typename T::element_type> && T::is_always_unique();

template<class T>
  concept @\defexposconcept{in-matrix}@ =
    @\exposid{is-mdspan}@<T> && T::rank() == 2;

template<class T>
  concept @\defexposconcept{out-matrix}@ =
    @\exposid{is-mdspan}@<T> && T::rank() == 2 &&
    is_assignable_v<typename T::reference, typename T::element_type> && T::is_always_unique();

template<class T>
  concept @\defexposconcept{inout-matrix}@ =
    @\exposid{is-mdspan}@<T> && T::rank() == 2 &&
    is_assignable_v<typename T::reference, typename T::element_type> && T::is_always_unique();

template<class T>
  constexpr bool @\exposid{is-layout-blas-packed}@ = false;    // \expos

template<class Triangle, class StorageOrder>
  constexpr bool @\exposid{is-layout-blas-packed}@<layout_blas_packed<Triangle, StorageOrder>> = true;

template<class T>
  concept @\defexposconcept{possibly-packed-out-matrix}@ =
    @\exposid{is-mdspan}@<T> && T::rank() == 2 &&
    is_assignable_v<typename T::reference, typename T::element_type> &&
    (T::is_always_unique() || @\exposid{is-layout-blas-packed}@<typename T::layout_type>);

template<class T>
  concept @\defexposconcept{in-object}@ =
    @\exposid{is-mdspan}@<T> && (T::rank() == 1 || T::rank() == 2);

template<class T>
  concept @\defexposconcept{out-object}@ =
    @\exposid{is-mdspan}@<T> && (T::rank() == 1 || T::rank() == 2) &&
    is_assignable_v<typename T::reference, typename T::element_type> && T::is_always_unique();

template<class T>
  concept @\defexposconcept{inout-object}@ =
    @\exposid{is-mdspan}@<T> && (T::rank() == 1 || T::rank() == 2) &&
    is_assignable_v<typename T::reference, typename T::element_type> && T::is_always_unique();

template<class T>
  concept @\defexposconcept{scalar}@ =
    @\libconcept{semiregular}@<T> && (!@\exposid{is-mdspan}@<T>) && (!is_execution_policy_v<T>);
\end{codeblock}

\pnum
If a function in \ref{linalg} accesses the elements
of a parameter constrained by
\exposconcept{in-vector},
\exposconcept{in-matrix}, or
\exposconcept{in-object},
those accesses will not modify the elements.

\pnum
Unless explicitly permitted, any
\exposconcept{inout-vector},
\exposconcept{inout-matrix},
\exposconcept{inout-object},
\exposconcept{out-vector},
\exposconcept{out-matrix},
\exposconcept{out-object}, or
\exposconcept{possibly-packed-out-matrix}
parameter of a function in \ref{linalg}
shall not overlap any other \tcode{mdspan} parameter of the function.

\rSec3[linalg.helpers.mandates]{Mandates}

\pnum
\begin{note}
These exposition-only helper functions use
the less constraining input concepts even for the output arguments,
because the additional constraint for assignability of elements
is not necessary, and
they are sometimes used in a context
where the third argument is an input type too.
\end{note}

\begin{codeblock}
template<class MDS1, class MDS2>
  requires(@\exposid{is-mdspan}@<MDS1> && @\exposid{is-mdspan}@<MDS2>)
  constexpr
  bool @\exposid{compatible-static-extents}@(size_t r1, size_t r2) {         // \expos
    return MDS1::static_extent(r1) == dynamic_extent ||
           MDS2::static_extent(r2) == dynamic_extent ||
           MDS1::static_extent(r1) == MDS2::static_extent(r2);
  }

template<@\exposconcept{in-vector}@ In1, @\exposconcept{in-vector}@ In2, @\exposconcept{in-vector}@ Out>
  constexpr bool @\exposid{possibly-addable}@() {                            // \expos
    return @\exposid{compatible-static-extents}@<Out, In1>(0, 0) &&
           @\exposid{compatible-static-extents}@<Out, In2>(0, 0) &&
           @\exposid{compatible-static-extents}@<In1, In2>(0, 0);
  }

template<@\exposconcept{in-matrix}@ In1, @\exposconcept{in-matrix}@ In2, @\exposconcept{in-matrix}@ Out>
  constexpr bool @\exposid{possibly-addable}@() {                            // \expos
    return @\exposid{compatible-static-extents}@<Out, In1>(0, 0) &&
           @\exposid{compatible-static-extents}@<Out, In1>(1, 1) &&
           @\exposid{compatible-static-extents}@<Out, In2>(0, 0) &&
           @\exposid{compatible-static-extents}@<Out, In2>(1, 1) &&
           @\exposid{compatible-static-extents}@<In1, In2>(0, 0) &&
           @\exposid{compatible-static-extents}@<In1, In2>(1, 1);
  }

template<@\exposconcept{in-matrix}@ InMat, @\exposconcept{in-vector}@ InVec, @\exposconcept{in-vector}@ OutVec>
  constexpr bool @\exposid{possibly-multipliable}@() {                       // \expos
    return @\exposid{compatible-static-extents}@<OutVec, InMat>(0, 0) &&
           @\exposid{compatible-static-extents}@<InMat, InVec>(1, 0);
  }

template<@\exposconcept{in-vector}@ InVec, @\exposconcept{in-matrix}@ InMat, @\exposconcept{in-vector}@ OutVec>
  constexpr bool @\exposid{possibly-multipliable}@() {                       // \expos
    return @\exposid{compatible-static-extents}@<OutVec, InMat>(0, 1) &&
           @\exposid{compatible-static-extents}@<InMat, InVec>(0, 0);
  }

template<@\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, @\exposconcept{in-matrix}@ OutMat>
  constexpr bool @\exposid{possibly-multipliable}@() {                       // \expos
    return @\exposid{compatible-static-extents}@<OutMat, InMat1>(0, 0) &&
           @\exposid{compatible-static-extents}@<OutMat, InMat2>(1, 1) &&
           @\exposid{compatible-static-extents}@<InMat1, InMat2>(1, 0);
  }
\end{codeblock}

\rSec3[linalg.helpers.precond]{Preconditions}

\pnum
\begin{note}
These exposition-only helper functions use
the less constraining input concepts even for the output arguments,
because the additional constraint for assignability of elements
is not necessary, and
they are sometimes used in a context
where the third argument is an input type too.
\end{note}

\begin{codeblock}
constexpr bool @\exposid{addable}@(                                          // \expos
  const @\exposconcept{in-vector}@ auto& in1, const @\exposconcept{in-vector}@ auto& in2, const @\exposconcept{in-vector}@ auto& out) {
  return out.extent(0) == in1.extent(0) && out.extent(0) == in2.extent(0);
}

constexpr bool @\exposid{addable}@(                                          // \expos
  const @\exposconcept{in-matrix}@ auto& in1,  const @\exposconcept{in-matrix}@ auto& in2, const @\exposconcept{in-matrix}@ auto& out) {
  return out.extent(0) == in1.extent(0) && out.extent(1) == in1.extent(1) &&
         out.extent(0) == in2.extent(0) && out.extent(1) == in2.extent(1);
}

constexpr bool @\exposid{multipliable}@(                                     // \expos
  const @\exposconcept{in-matrix}@ auto& in_mat, const @\exposconcept{in-vector}@ auto& in_vec, const @\exposconcept{in-vector}@ auto& out_vec) {
  return out_vec.extent(0) == in_mat.extent(0) && in_mat.extent(1) == in_vec.extent(0);
}

constexpr bool @\exposid{multipliable}@( // \expos
  const @\exposconcept{in-vector}@ auto& in_vec, const @\exposconcept{in-matrix}@ auto& in_mat, const @\exposconcept{in-vector}@ auto& out_vec) {
  return out_vec.extent(0) == in_mat.extent(1) && in_mat.extent(0) == in_vec.extent(0);
}

constexpr bool @\exposid{multipliable}@(                                     // \expos
  const @\exposconcept{in-matrix}@ auto& in_mat1, const @\exposconcept{in-matrix}@ auto& in_mat2, const @\exposconcept{in-matrix}@ auto& out_mat) {
  return out_mat.extent(0) == in_mat1.extent(0) && out_mat.extent(1) == in_mat2.extent(1) &&
         in_mat1.extent(1) == in_mat2.extent(0);
}
\end{codeblock}

\rSec2[linalg.scaled]{Scaled in-place transformation}

\rSec3[linalg.scaled.intro]{Introduction}

\pnum
The \tcode{scaled} function
takes a value \tcode{alpha} and an \tcode{mdspan} \tcode{x}, and
returns a new read-only \tcode{mdspan}
that represents
the elementwise product of \tcode{alpha} with each element of \tcode{x}.
\begin{example}
\begin{codeblock}
using Vec = mdspan<double, dextents<size_t, 1>>;

// z = alpha * x + y
void z_equals_alpha_times_x_plus_y(double alpha, Vec x, Vec y, Vec z) {
  add(scaled(alpha, x), y, z);
}

// z = alpha * x + beta * y
void z_equals_alpha_times_x_plus_beta_times_y(double alpha, Vec x, double beta, Vec y, Vec z) {
  add(scaled(alpha, x), scaled(beta, y), z);
}
\end{codeblock}
\end{example}

\rSec3[linalg.scaled.scaledaccessor]{Class template \tcode{scaled_accessor}}

\pnum
The class template \tcode{scaled_accessor} is an \tcode{mdspan} accessor policy
which upon access produces scaled elements.
It is part of the implementation of \tcode{scaled}\iref{linalg.scaled.scaled}.
\begin{codeblock}
namespace std::linalg {
  template<class ScalingFactor, class NestedAccessor>
  class @\libglobal{scaled_accessor}@ {
  public:
    using @\libmember{element_type}{scaled_accessor}@ =
      const decltype(declval<ScalingFactor>() * declval<NestedAccessor::element_type>());
    using @\libmember{reference}{scaled_accessor}@ = remove_const_t<element_type>;
    using @\libmember{data_handle_type}{scaled_accessor}@ = NestedAccessor::data_handle_type;
    using @\libmember{offset_policy}{scaled_accessor}@ = scaled_accessor<ScalingFactor, NestedAccessor::offset_policy>;

    constexpr scaled_accessor() = default;
    template<class OtherNestedAccessor>
      explicit(!is_convertible_v<OtherNestedAccessor, NestedAccessor>)
        constexpr scaled_accessor(const scaled_accessor<ScalingFactor,
                                                        OtherNestedAccessor>& other);
    constexpr scaled_accessor(const ScalingFactor& s, const NestedAccessor& a);

    constexpr reference access(data_handle_type p, size_t i) const;
    constexpr offset_policy::data_handle_type offset(data_handle_type p, size_t i) const;

    constexpr const ScalingFactor& @\libmember{scaling_factor}{scaled_accessor}@() const noexcept { return @\exposid{scaling-factor}@; }
    constexpr const NestedAccessor& @\libmember{nested_accessor}{scaled_accessor}@() const noexcept { return @\exposid{nested-accessor}@; }

  private:
    ScalingFactor @\exposid{scaling-factor}@{};                              // \expos
    NestedAccessor @\exposid{nested-accessor}@{};                            // \expos
  };
}
\end{codeblock}

\pnum
\mandates
\begin{itemize}
\item
\tcode{element_type} is valid and denotes a type,
\item
\tcode{is_copy_constructible_v<reference>} is \tcode{true},
\item
\tcode{is_reference_v<element_type>} is \tcode{false},
\item
\tcode{ScalingFactor} models \libconcept{semiregular}, and
\item
\tcode{NestedAccessor} meets the accessor policy requirements\iref{mdspan.accessor.reqmts}.
\end{itemize}

\indexlibraryctor{scaled_accessor}%
\begin{itemdecl}
template<class OtherNestedAccessor>
  explicit(!is_convertible_v<OtherNestedAccessor, NestedAccessor>)
    constexpr scaled_accessor(const scaled_accessor<ScalingFactor, OtherNestedAccessor>& other);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{is_constructible_v<NestedAccessor, const OtherNestedAccessor\&>} is \tcode{true}.

\pnum
\effects
\begin{itemize}
\item
Direct-non-list-initializes \exposid{scaling-factor}
with \tcode{other.scaling_factor()}, and
\item
direct-non-list-initializes \exposid{nested-accessor}
with \tcode{other.nested_accessor()}.
\end{itemize}
\end{itemdescr}

\indexlibraryctor{scaled_accessor}%
\begin{itemdecl}
constexpr scaled_accessor(const ScalingFactor& s, const NestedAccessor& a);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
\begin{itemize}
\item
Direct-non-list-initializes \exposid{scaling-factor} with \tcode{s}, and
\item
direct-non-list-initializes \exposid{nested-accessor} with \tcode{a}.
\end{itemize}
\end{itemdescr}

\indexlibrarymember{scaled_accessor}{access}%
\begin{itemdecl}
constexpr reference access(data_handle_type p, size_t i) const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\begin{codeblock}
scaling_factor() * NestedAccessor::element_type(@\exposid{nested-accessor}@.access(p, i))
\end{codeblock}
\end{itemdescr}

\indexlibrarymember{scaled_accessor}{offset}%
\begin{itemdecl}
constexpr offset_policy::data_handle_type offset(data_handle_type p, size_t i) const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{\exposid{nested-accessor}.offset(p, i)}
\end{itemdescr}

\rSec3[linalg.scaled.scaled]{Function template \tcode{scaled}}

\pnum
The \tcode{scaled} function template takes
a scaling factor \tcode{alpha} and
an \tcode{mdspan} \tcode{x}, and
returns a new read-only \tcode{mdspan} with the same domain as \tcode{x},
that represents the elementwise product of \tcode{alpha}
with each element of \tcode{x}.

\indexlibraryglobal{scaled}%
\begin{itemdecl}
  template<class ScalingFactor,
           class ElementType, class Extents, class Layout, class Accessor>
    constexpr auto scaled(ScalingFactor alpha, mdspan<ElementType, Extents, Layout, Accessor> x);
\end{itemdecl}

\begin{itemdescr}
\pnum
Let \tcode{SA} be \tcode{scaled_accessor<ScalingFactor, Accessor>}.

\pnum
\returns
\begin{codeblock}
mdspan<typename SA::element_type, Extents, Layout, SA>(x.data_handle(), x.mapping(),
                                                       SA(alpha, x.accessor()))
\end{codeblock}
\end{itemdescr}

\pnum
\begin{example}
\begin{codeblock}
void test_scaled(mdspan<double, extents<int, 10>> x)
{
  auto x_scaled = scaled(5.0, x);
  for (int i = 0; i < x.extent(0); ++i) {
    assert(x_scaled[i] == 5.0 * x[i]);
  }
}
\end{codeblock}
\end{example}

\rSec2[linalg.conj]{Conjugated in-place transformation}

\rSec3[linalg.conj.intro]{Introduction}

\pnum
The \tcode{conjugated} function takes an \tcode{mdspan} \tcode{x},
and returns a new read-only \tcode{mdspan} \tcode{y}
with the same domain as \tcode{x},
whose elements are the complex conjugates
of the corresponding elements of \tcode{x}.

\rSec3[linalg.conj.conjugatedaccessor]{Class template \tcode{conjugated_accessor}}

\pnum
The class template \tcode{conjugated_accessor}
is an \tcode{mdspan} accessor policy
which upon access produces conjugate elements.
It is part of the implementation of
\tcode{conjugated}\iref{linalg.conj.conjugated}.

\begin{codeblock}
namespace std::linalg {
  template<class NestedAccessor>
  class @\libglobal{conjugated_accessor}@ {
  public:
    using @\libmember{element_type}{conjugated_accessor}@ =
      const decltype(@\exposid{conj-if-needed}@(declval<NestedAccessor::element_type>()));
    using @\libmember{reference}{conjugated_accessor}@ = remove_const_t<element_type>;
    using @\libmember{data_handle_type}{conjugated_accessor}@ = NestedAccessor::data_handle_type;
    using @\libmember{offset_policy}{conjugated_accessor}@ = conjugated_accessor<NestedAccessor::offset_policy>;

    constexpr conjugated_accessor() = default;
    constexpr conjugated_accessor(const NestedAccessor& acc);
    template<class OtherNestedAccessor>
      explicit(!is_convertible_v<OtherNestedAccessor, NestedAccessor>)
      constexpr conjugated_accessor(const conjugated_accessor<OtherNestedAccessor>& other);

    constexpr reference access(data_handle_type p, size_t i) const;

    constexpr typename offset_policy::data_handle_type
      offset(data_handle_type p, size_t i) const;

    constexpr const NestedAccessor& @\libmember{nested_accessor}{conjugated_accessor}@() const noexcept { return @\exposid{nested-accessor_}@; }

  private:
    NestedAccessor @\exposid{nested-accessor_}@{};                           // \expos
  };
}
\end{codeblock}

\pnum
\mandates
\begin{itemize}
\item
\tcode{element_type} is valid and denotes a type,
\item
\tcode{is_copy_constructible_v<reference>} is \tcode{true},
\item
\tcode{is_reference_v<element_type>} is \tcode{false}, and
\item
\tcode{NestedAccessor} meets the accessor policy requirements\iref{mdspan.accessor.reqmts}.
\end{itemize}

\indexlibraryctor{conjugated_accessor}%
\begin{itemdecl}
constexpr conjugated_accessor(const NestedAccessor& acc);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Direct-non-list-initializes
\exposid{nested-accessor_} with \tcode{acc}.
\end{itemdescr}

\indexlibraryctor{conjugated_accessor}%
\begin{itemdecl}
template<class OtherNestedAccessor>
  explicit(!is_convertible_v<OtherNestedAccessor, NestedAccessor>)
    constexpr conjugated_accessor(const conjugated_accessor<OtherNestedAccessor>& other);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{is_constructible_v<NestedAccessor, const OtherNestedAccessor\&>}
is \tcode{true}.

\pnum
\effects
Direct-non-list-initializes \exposid{nested-accessor_}
with \tcode{other.nested_accessor()}.
\end{itemdescr}

\indexlibrarymember{conjugated_accessor}{access}%
\begin{itemdecl}
constexpr reference access(data_handle_type p, size_t i) const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{\exposid{conj-if-needed}(NestedAccessor::element_type(\exposid{nested-accessor_}.access(p, i)))}
\end{itemdescr}

\indexlibrarymember{conjugated_accessor}{offset}%
\begin{itemdecl}
constexpr typename offset_policy::data_handle_type offset(data_handle_type p, size_t i) const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{\exposid{nested-accessor_}.offset(p, i)}
\end{itemdescr}

\rSec3[linalg.conj.conjugated]{Function template \tcode{conjugated}}

\begin{itemdecl}
  template<class ElementType, class Extents, class Layout, class Accessor>
    constexpr auto @\libglobal{conjugated}@(mdspan<ElementType, Extents, Layout, Accessor> a);
\end{itemdecl}

\begin{itemdescr}
\pnum
Let \tcode{A} be
\begin{itemize}
\item
\tcode{remove_cvref_t<decltype(a.accessor().nested_accessor())>}
if \tcode{Accessor} is a specialization of \tcode{conjugated_accessor};
\item
otherwise,
\tcode{Accessor} if \tcode{remove_cvref_t<ElementType>} is an arithmetic type;
\item
otherwise,
\tcode{conjugated_accessor<Accessor>}
if the expression \tcode{conj(E)} is valid for any subexpression \tcode{E}
whose type is \tcode{remove_cvref_t<ElementType>}
with overload resolution performed in a context that includes the declaration
\tcode{template<class U> U conj(const U\&) = delete;};
\item
otherwise,
\tcode{Accessor}.
\end{itemize}

\pnum
\returns
Let \tcode{MD} be \tcode{mdspan<typename A::element_type, Extents, Layout, A>}.
\begin{itemize}
\item
\tcode{MD(a.data_handle(), a.mapping(), a.accessor().nested_accessor())}
if \tcode{Accessor} is a\newline specialization of \tcode{conjugated_accessor};
\item
otherwise,
\tcode{a}, if \tcode{is_same_v<A, Accessor>} is \tcode{true};
\item
otherwise,
\tcode{MD(a.data_handle(), a.mapping(), conjugated_accessor(a.accessor()))}.
\end{itemize}
\end{itemdescr}

\pnum
\begin{example}
\begin{codeblock}
void test_conjugated_complex(mdspan<complex<double>, extents<int, 10>> a) {
  auto a_conj = conjugated(a);
  for (int i = 0; i < a.extent(0); ++i) {
    assert(a_conj[i] == conj(a[i]);
  }
  auto a_conj_conj = conjugated(a_conj);
  for (int i = 0; i < a.extent(0); ++i) {
    assert(a_conj_conj[i] == a[i]);
  }
}

void test_conjugated_real(mdspan<double, extents<int, 10>> a) {
  auto a_conj = conjugated(a);
  for (int i = 0; i < a.extent(0); ++i) {
    assert(a_conj[i] == a[i]);
  }
  auto a_conj_conj = conjugated(a_conj);
  for (int i = 0; i < a.extent(0); ++i) {
    assert(a_conj_conj[i] == a[i]);
  }
}
\end{codeblock}
\end{example}

\rSec2[linalg.transp]{Transpose in-place transformation}

\rSec3[linalg.transp.intro]{Introduction}

\pnum
\tcode{layout_transpose} is an \tcode{mdspan} layout mapping policy
that swaps the two indices, extents, and strides
of any unique \tcode{mdspan} layout mapping policy.

\pnum
The \tcode{transposed} function takes an \tcode{mdspan}
representing a matrix, and returns a new \tcode{mdspan}
representing the transpose of the input matrix.

\rSec3[linalg.transp.helpers]{Exposition-only helpers for \tcode{layout_transpose} and \tcode{transposed}}

\pnum
The exposition-only \exposid{transpose-extents} function
takes an \tcode{extents} object representing the extents of a matrix,
and returns a new \tcode{extents} object
representing the extents of the transpose of the matrix.

\pnum
The exposition-only alias template
\tcode{\exposid{transpose-extents-t}<InputExtents>}
gives the type of \tcode{\exposid{transpose-ex\-tents}(e)}
for a given \tcode{extents} object \tcode{e} of type \tcode{InputExtents}.
\begin{itemdecl}
template<class IndexType, size_t InputExtent0, size_t InputExtent1>
  constexpr extents<IndexType, InputExtent1, InputExtent0>
    @\exposid{transpose-extents}@(const extents<IndexType, InputExtent0, InputExtent1>& in);   // \expos
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{extents<IndexType, InputExtent1, InputExtent0>(in.extent(1), in.extent(0))}
\end{itemdescr}

\begin{codeblock}
template<class InputExtents>
  using @\exposid{transpose-extents-t}@ =
    decltype(@\exposid{transpose-extents}@(declval<InputExtents>()));        // \expos
\end{codeblock}

\rSec3[linalg.transp.layout.transpose]{Class template \tcode{layout_transpose}}

\pnum
\tcode{layout_transpose} is an \tcode{mdspan} layout mapping policy
that swaps the two indices, extents, and strides
of any \tcode{mdspan} layout mapping policy.

\begin{codeblock}
namespace std::linalg {
  template<class Layout>
  class @\libglobal{layout_transpose}@ {
  public:
    using @\libmember{nested_layout_type}{layout_transpose}@ = Layout;

    template<class Extents>
    struct @\libmember{mapping}{layout_transpose}@ {
    private:
      using @\exposid{nested-mapping-type}@ =
        Layout::template mapping<@\exposid{transpose-extents-t}@<Extents>>;  // \expos

    public:
      using @\libmember{extents_type}{layout_transpose::mapping}@ = Extents;
      using @\libmember{index_type}{layout_transpose::mapping}@ = extents_type::index_type;
      using @\libmember{size_type}{layout_transpose::mapping}@ = extents_type::size_type;
      using @\libmember{rank_type}{layout_transpose::mapping}@ = extents_type::rank_type;
      using @\libmember{layout_type}{layout_transpose::mapping}@ = layout_transpose;

      constexpr explicit mapping(const @\exposid{nested-mapping-type}@&);

      constexpr const extents_type& @\libmember{extents}{layout_transpose::mapping}@() const noexcept { return @\exposid{extents_}@; }

      constexpr index_type @\libmember{required_span_size}{layout_transpose::mapping}@() const
        { return @\exposid{nested-mapping_}@.required_span_size(); }

      template<class Index0, class Index1>
        constexpr index_type @\libmember{operator()}{layout_transpose::mapping}@(Index0 ind0, Index1 ind1) const
        { return @\exposid{nested-mapping_}@(ind1, ind0); }

      constexpr const @\exposid{nested-mapping-type}@& @\libmember{nested_mapping}{layout_transpose::mapping}@() const noexcept
        { return @\exposid{nested-mapping_}@; }

      static constexpr bool @\libmember{is_always_unique}{layout_transpose::mapping}@() noexcept
        { return @\exposid{nested-mapping-type}@::is_always_unique(); }
      static constexpr bool @\libmember{is_always_exhaustive}{layout_transpose::mapping}@() noexcept
        { return @\exposid{nested-mapping-type}@::is_always_exhaustive(); }
      static constexpr bool @\libmember{is_always_strided}{layout_transpose::mapping}@() noexcept
        { return @\exposid{nested-mapping-type}@::is_always_strided(); }

      constexpr bool @\libmember{is_unique}{layout_transpose::mapping}@() const { return @\exposid{nested-mapping_}@.is_unique(); }
      constexpr bool @\libmember{is_exhaustive}{layout_transpose::mapping}@() const { return @\exposid{nested-mapping_}@.is_exhaustive(); }
      constexpr bool @\libmember{is_strided}{layout_transpose::mapping}@() const { return @\exposid{nested-mapping_}@.is_strided(); }

      constexpr index_type stride(size_t r) const;

      template<class OtherExtents>
        friend constexpr bool operator==(const mapping& x, const mapping<OtherExtents>& y);

    private:
      @\exposid{nested-mapping-type}@ @\exposid{nested-mapping_}@;                       // \expos
      extents_type @\exposid{extents_}@;                                     // \expos
    };
  };
}
\end{codeblock}

\pnum
\tcode{Layout} shall meet
the layout mapping policy requirements\iref{mdspan.layout.policy.reqmts}.

\pnum
\mandates
\begin{itemize}
\item
\tcode{Extents} is a specialization of \tcode{std::extents}, and
\item
\tcode{Extents::rank()} equals 2.
\end{itemize}

\indexlibraryctor{layout_transpose::mapping}%
\begin{itemdecl}
constexpr explicit mapping(const @\exposid{nested-mapping-type}@& map);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
\begin{itemize}
\item
Initializes \exposid{nested-mapping_} with \tcode{map}, and
\item
initializes \exposid{extents_}
with \tcode{\exposid{transpose-extents}(map.extents())}.
\end{itemize}
\end{itemdescr}

\indexlibrarymember{layout_transpose::mapping}{stride}%
\begin{itemdecl}
constexpr index_type stride(size_t r) const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\begin{itemize}
\item
\tcode{is_strided()} is \tcode{true}, and
\item
\tcode{r < 2} is \tcode{true}.
\end{itemize}

\pnum
\returns
\tcode{\exposid{nested-mapping_}.stride(r == 0 ? 1 : 0)}
\end{itemdescr}

\indexlibrarymember{layout_transpose::mapping}{operator==}%
\begin{itemdecl}
template<class OtherExtents>
  friend constexpr bool operator==(const mapping& x, const mapping<OtherExtents>& y);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
The expression
\tcode{x.\exposid{nested-mapping_} == y.\exposid{nested-mapping_}}
is well-formed and its result is convertible to \tcode{bool}.

\pnum
\returns
\tcode{x.\exposid{nested-mapping_} == y.\exposid{nested-mapping_}}.
\end{itemdescr}

\rSec3[linalg.transp.transposed]{Function template \tcode{transposed}}

\pnum
The \tcode{transposed} function
takes a rank-2 \tcode{mdspan} representing a matrix, and
returns a new \tcode{mdspan} representing the input matrix's transpose.
The input matrix's data are not modified, and
the returned \tcode{mdspan} accesses the input matrix's data in place.
\indexlibraryglobal{transposed}%
\begin{itemdecl}
  template<class ElementType, class Extents, class Layout, class Accessor>
    constexpr auto transposed(mdspan<ElementType, Extents, Layout, Accessor> a);
\end{itemdecl}

\begin{itemdescr}
\pnum
\mandates
\tcode{Extents::rank() == 2} is \tcode{true}.

\pnum
Let \tcode{ReturnExtents} be
\tcode{\exposid{transpose-extents-t}<Extents>}.
Let \tcode{R} be
\tcode{mdspan<ElementType, ReturnEx\-tents, ReturnLayout, Accessor>},
where \tcode{ReturnLayout} is:
\begin{itemize}
\item
\tcode{layout_right} if \tcode{Layout} is \tcode{layout_left};
\item
otherwise, \tcode{layout_left} if \tcode{Layout} is \tcode{layout_right};
\item
otherwise, \tcode{layout_right_padded<PaddingValue>} if \tcode{Layout} is\newline
\tcode{layout_left_padded<PaddingValue>}
for some \tcode{size_t} value \tcode{PaddingValue};
\item
otherwise, \tcode{layout_left_padded<PaddingValue>} if \tcode{Layout} is\newline
\tcode{layout_right_padded<PaddingValue>}
for some \tcode{size_t} value \tcode{PaddingValue};
\item
otherwise, \tcode{layout_stride} if \tcode{Layout} is \tcode{layout_stride};
\item
otherwise,
\tcode{layout_blas_packed<OppositeTriangle, OppositeStorageOrder>},
if \tcode{Layout} is\newline
\tcode{layout_blas_packed<Triangle, StorageOrder>}
for some \tcode{Triangle} and \tcode{StorageOrder}, where
\begin{itemize}
\item
\tcode{OppositeTriangle} is
\begin{codeblock}
conditional_t<is_same_v<Triangle, upper_triangle_t>,
              lower_triangle_t, upper_triangle_t>
\end{codeblock}
and
\item
\tcode{OppositeStorageOrder} is
\begin{codeblock}
conditional_t<is_same_v<StorageOrder, column_major_t>, row_major_t, column_major_t>
\end{codeblock}
\end{itemize}
\item
otherwise, \tcode{NestedLayout}
if \tcode{Layout} is \tcode{layout_transpose<NestedLayout>}
for some \tcode{NestedLay\-out};
\item
otherwise, \tcode{layout_transpose<Layout>}.
\end{itemize}

\pnum
\returns
With \tcode{ReturnMapping} being
the type \tcode{typename ReturnLayout::template mapping<Return\-Extents>}:
\begin{itemize}
\item
if \tcode{Layout} is \tcode{layout_left}, \tcode{layout_right}, or
a specialization of \tcode{layout_blas_packed},
\begin{codeblock}
R(a.data_handle(), ReturnMapping(@\exposid{transpose-extents}@(a.mapping().extents())),
  a.accessor())
\end{codeblock}
\item
otherwise,
\begin{codeblock}
R(a.data_handle(), ReturnMapping(@\exposid{transpose-extents}@(a.mapping().extents()),
  a.mapping().stride(1)), a.accessor())
\end{codeblock}
if \tcode{Layout} is \tcode{layout_left_padded<PaddingValue>}
for some \tcode{size_t} value \tcode{PaddingValue};
\item
otherwise,
\begin{codeblock}
R(a.data_handle(), ReturnMapping(@\exposid{transpose-extents}@(a.mapping().extents()),
  a.mapping().stride(0)), a.accessor())
\end{codeblock}
if \tcode{Layout} is \tcode{layout_right_padded<PaddingValue>}
for some \tcode{size_t} value \tcode{PaddingValue};
\item
otherwise, if \tcode{Layout} is \tcode{layout_stride},
\begin{codeblock}
R(a.data_handle(), ReturnMapping(@\exposid{transpose-extents}@(a.mapping().extents()),
  array{a.mapping().stride(1), a.mapping().stride(0)}), a.accessor())
\end{codeblock}
\item
otherwise, if \tcode{Layout} is a specialization of \tcode{layout_transpose},
\begin{codeblock}
R(a.data_handle(), a.mapping().nested_mapping(), a.accessor())
\end{codeblock}
\item
otherwise,
\begin{codeblock}
R(a.data_handle(), ReturnMapping(a.mapping()), a.accessor())
\end{codeblock}
\end{itemize}
\end{itemdescr}

\pnum
\begin{example}
\begin{codeblock}
void test_transposed(mdspan<double, extents<size_t, 3, 4>> a) {
  const auto num_rows = a.extent(0);
  const auto num_cols = a.extent(1);

  auto a_t = transposed(a);
  assert(num_rows == a_t.extent(1));
  assert(num_cols == a_t.extent(0));
  assert(a.stride(0) == a_t.stride(1));
  assert(a.stride(1) == a_t.stride(0));

  for (size_t row = 0; row < num_rows; ++row) {
    for (size_t col = 0; col < num_rows; ++col) {
      assert(a[row, col] == a_t[col, row]);
    }
  }

  auto a_t_t = transposed(a_t);
  assert(num_rows == a_t_t.extent(0));
  assert(num_cols == a_t_t.extent(1));
  assert(a.stride(0) == a_t_t.stride(0));
  assert(a.stride(1) == a_t_t.stride(1));

  for (size_t row = 0; row < num_rows; ++row) {
    for (size_t col = 0; col < num_rows; ++col) {
      assert(a[row, col] == a_t_t[row, col]);
    }
  }
}
\end{codeblock}
\end{example}

\rSec2[linalg.conjtransposed]{Conjugate transpose in-place transform}

\pnum
The \tcode{conjugate_transposed} function
returns a conjugate transpose view of an object.
This combines the effects of \tcode{transposed} and \tcode{conjugated}.
\indexlibraryglobal{conjugate_transposed}%
\begin{itemdecl}
  template<class ElementType, class Extents, class Layout, class Accessor>
    constexpr auto conjugate_transposed(mdspan<ElementType, Extents, Layout, Accessor> a);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return conjugated(transposed(a));}
\end{itemdescr}

\pnum
\begin{example}
\begin{codeblock}
void test_conjugate_transposed(mdspan<complex<double>, extents<size_t, 3, 4>> a) {
  const auto num_rows = a.extent(0);
  const auto num_cols = a.extent(1);

  auto a_ct = conjugate_transposed(a);
  assert(num_rows == a_ct.extent(1));
  assert(num_cols == a_ct.extent(0));
  assert(a.stride(0) == a_ct.stride(1));
  assert(a.stride(1) == a_ct.stride(0));

  for (size_t row = 0; row < num_rows; ++row) {
    for (size_t col = 0; col < num_rows; ++col) {
      assert(a[row, col] == conj(a_ct[col, row]));
    }
  }

  auto a_ct_ct = conjugate_transposed(a_ct);
  assert(num_rows == a_ct_ct.extent(0));
  assert(num_cols == a_ct_ct.extent(1));
  assert(a.stride(0) == a_ct_ct.stride(0));
  assert(a.stride(1) == a_ct_ct.stride(1));

  for (size_t row = 0; row < num_rows; ++row) {
    for (size_t col = 0; col < num_rows; ++col) {
      assert(a[row, col] == a_ct_ct[row, col]);
      assert(conj(a_ct[col, row]) == a_ct_ct[row, col]);
    }
  }
}
\end{codeblock}
\end{example}

\rSec2[linalg.algs.reqs]{Algorithm requirements based on template parameter name}

\pnum
Throughout
\ref{linalg.algs.blas1}, \ref{linalg.algs.blas2}, and \ref{linalg.algs.blas3},
where the template parameters are not constrained,
the names of template parameters are used to express the following constraints.
\begin{itemize}
\item
\tcode{is_execution_policy<ExecutionPolicy>::value}
is \tcode{true}\iref{execpol.type}.
\item
\tcode{Real} is any type such that \tcode{complex<Real>} is
specified\iref{complex.numbers.general}.
\item
\tcode{Triangle} is either \tcode{upper_triangle_t} or \tcode{lower_triangle_t}.
\item
\tcode{DiagonalStorage} is
either \tcode{implicit_unit_diagonal_t} or \tcode{explicit_diagonal_t}.
\end{itemize}
\begin{note}
Function templates that have a template parameter named \tcode{ExecutionPolicy}
are parallel algorithms\iref{algorithms.parallel.defns}.
\end{note}

\rSec2[linalg.algs.blas1]{BLAS 1 algorithms}

\rSec3[linalg.algs.blas1.complexity]{Complexity}

\pnum
\complexity
All algorithms in \ref{linalg.algs.blas1} with \tcode{mdspan} parameters
perform a count of \tcode{mdspan} array accesses
and arithmetic operations that is linear in
the maximum product of extents of any \tcode{mdspan} parameter.

\rSec3[linalg.algs.blas1.givens]{Givens rotations}

\rSec4[linalg.algs.blas1.givens.lartg]{Compute Givens rotation}

\indexlibraryglobal{setup_givens_rotation}%
\begin{itemdecl}
template<class Real>
  setup_givens_rotation_result<Real> setup_givens_rotation(Real a, Real b) noexcept;

template<class Real>
  setup_givens_rotation_result<complex<Real>>
    setup_givens_rotation(complex<Real> a, complex<Real> b) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
These functions compute the Givens plane rotation
represented by the two values $c$ and $s$
such that the 2 x 2 system of equations
\begin{equation*}
\left[ \begin{matrix}
c             & s \\
-\overline{s} & c \\
\end{matrix} \right]
\cdot
\left[ \begin{matrix}
a \\
b \\
\end{matrix} \right]
=
\left[ \begin{matrix}
r \\
0 \\
\end{matrix} \right]
\end{equation*}

holds, where $c$ is always a real scalar, and $c^2 + |s|^2 = 1$.
That is, $c$ and $s$ represent a 2 x 2 matrix,
that when multiplied by the right by the input vector
whose components are $a$ and $b$,
produces a result vector
whose first component $r$ is the Euclidean norm of the input vector, and
whose second component is zero.
\begin{note}
These functions correspond to the LAPACK function \tcode{xLARTG}\supercite{lapack}.
\end{note}

\pnum
\returns
\tcode{{c, s, r}},
where \tcode{c} and \tcode{s} form the Givens plane rotation
corresponding to the input \tcode{a} and \tcode{b},
and \tcode{r} is the Euclidean norm of the two-component vector
formed by \tcode{a} and \tcode{b}.
\end{itemdescr}

\rSec4[linalg.algs.blas1.givens.rot]{Apply a computed Givens rotation to vectors}

\indexlibraryglobal{apply_givens_rotation}%
\begin{itemdecl}
template<@\exposconcept{inout-vector}@ InOutVec1, @\exposconcept{inout-vector}@ InOutVec2, class Real>
  void apply_givens_rotation(InOutVec1 x, InOutVec2 y, Real c, Real s);
template<class ExecutionPolicy, @\exposconcept{inout-vector}@ InOutVec1, @\exposconcept{inout-vector}@ InOutVec2, class Real>
  void apply_givens_rotation(ExecutionPolicy&& exec,
                             InOutVec1 x, InOutVec2 y, Real c, Real s);
template<@\exposconcept{inout-vector}@ InOutVec1, @\exposconcept{inout-vector}@ InOutVec2, class Real>
  void apply_givens_rotation(InOutVec1 x, InOutVec2 y, Real c, complex<Real> s);
template<class ExecutionPolicy, @\exposconcept{inout-vector}@ InOutVec1, @\exposconcept{inout-vector}@ InOutVec2, class Real>
  void apply_givens_rotation(ExecutionPolicy&& exec,
                             InOutVec1 x, InOutVec2 y, Real c, complex<Real> s);
\end{itemdecl}

\begin{itemdescr}
\pnum
\begin{note}
These functions correspond to the BLAS function \tcode{xROT}\supercite{blas1}.
\end{note}

\pnum
\mandates
\tcode{\exposid{compatible-static-extents}<InOutVec1, InOutVec2>(0, 0)} is \tcode{true}.

\pnum
\expects
\tcode{x.extent(0)} equals \tcode{y.extent(0)}.

\pnum
\effects
Applies the plane rotation
specified by \tcode{c} and \tcode{s} to
the input vectors \tcode{x} and \tcode{y},
as if the rotation were a 2 x 2 matrix and
the input vectors were successive rows of a matrix with two rows.
\end{itemdescr}

\rSec3[linalg.algs.blas1.swap]{Swap matrix or vector elements}

\indexlibraryglobal{swap_elements}%
\begin{itemdecl}
template<@\exposconcept{inout-object}@ InOutObj1, @\exposconcept{inout-object}@ InOutObj2>
  void swap_elements(InOutObj1 x, InOutObj2 y);
template<class ExecutionPolicy, @\exposconcept{inout-object}@ InOutObj1, @\exposconcept{inout-object}@ InOutObj2>
  void swap_elements(ExecutionPolicy&& exec, InOutObj1 x, InOutObj2 y);
\end{itemdecl}

\begin{itemdescr}
\pnum
\begin{note}
These functions correspond to the BLAS function \tcode{xSWAP}\supercite{blas1}.
\end{note}

\pnum
\constraints
\tcode{x.rank()} equals \tcode{y.rank()}.

\pnum
\mandates
For all \tcode{r} in the range $[0, \tcode{x.rank()})$,
\begin{codeblock}
@\exposid{compatible-static-extents}@<InOutObj1, InOutObj2>(r, r)
\end{codeblock}
is \tcode{true}.

\pnum
\expects
\tcode{x.extents()} equals \tcode{y.extents()}.

\pnum
\effects
Swaps all corresponding elements of \tcode{x} and \tcode{y}.
\end{itemdescr}

\rSec3[linalg.algs.blas1.scal]{Multiply the elements of an object in place by a scalar}

\indexlibraryglobal{scale}%
\begin{itemdecl}
template<@\exposconcept{scalar}@ Scalar, @\exposconcept{inout-object}@ InOutObj>
  void scale(Scalar alpha, InOutObj x);
template<class ExecutionPolicy, @\exposconcept{scalar}@ Scalar, @\exposconcept{inout-object}@ InOutObj>
  void scale(ExecutionPolicy&& exec, Scalar alpha, InOutObj x);
\end{itemdecl}

\begin{itemdescr}
\pnum
\begin{note}
These functions correspond to the BLAS function \tcode{xSCAL}\supercite{blas1}.
\end{note}

\pnum
\effects
Overwrites $x$ with the result of
computing the elementwise multiplication $\alpha x$,
where the scalar $\alpha$ is \tcode{alpha}.
\end{itemdescr}

\rSec3[linalg.algs.blas1.copy]{Copy elements of one matrix or vector into another}

\indexlibraryglobal{copy}%
\begin{itemdecl}
template<@\exposconcept{in-object}@ InObj, @\exposconcept{out-object}@ OutObj>
  void copy(InObj x, OutObj y);
template<class ExecutionPolicy, @\exposconcept{in-object}@ InObj, @\exposconcept{out-object}@ OutObj>
  void copy(ExecutionPolicy&& exec, InObj x, OutObj y);
\end{itemdecl}

\begin{itemdescr}
\pnum
\begin{note}
These functions correspond to the BLAS function \tcode{xCOPY\supercite{blas1}}.
\end{note}

\pnum
\constraints
\tcode{x.rank()} equals \tcode{y.rank()}.

\pnum
\mandates
For all \tcode{r} in the range $[ 0, \tcode{x.rank()})$,
\begin{codeblock}
@\exposid{compatible-static-extents}@<InObj, OutObj>(r, r)
\end{codeblock}
is \tcode{true}.

\pnum
\expects
\tcode{x.extents()} equals \tcode{y.extents()}.

\pnum
\effects
Assigns each element of $x$ to the corresponding element of $y$.
\end{itemdescr}

\rSec3[linalg.algs.blas1.add]{Add vectors or matrices elementwise}

\indexlibraryglobal{add}%
\begin{itemdecl}
template<@\exposconcept{in-object}@ InObj1, @\exposconcept{in-object}@ InObj2, @\exposconcept{out-object}@ OutObj>
  void add(InObj1 x, InObj2 y, OutObj z);
template<class ExecutionPolicy, @\exposconcept{in-object}@ InObj1, @\exposconcept{in-object}@ InObj2, @\exposconcept{out-object}@ OutObj>
  void add(ExecutionPolicy&& exec,
           InObj1 x, InObj2 y, OutObj z);
\end{itemdecl}

\begin{itemdescr}
\pnum
\begin{note}
These functions correspond to the BLAS function \tcode{xAXPY}\supercite{blas1}.
\end{note}

\pnum
\constraints
\tcode{x.rank()}, \tcode{y.rank()}, and \tcode{z.rank()} are all equal.

\pnum
\mandates
\tcode{\exposid{possibly-addable}<InObj1, InObj2, OutObj>()} is \tcode{true}.

\pnum
\expects
\tcode{\exposid{addable}(x,y,z)} is \tcode{true}.

\pnum
\effects
Computes $z = x + y$.

\pnum
\remarks
\tcode{z} may alias \tcode{x} or \tcode{y}.
\end{itemdescr}

\rSec3[linalg.algs.blas1.dot]{Dot product of two vectors}

\pnum
\begin{note}
The functions in this section correspond to the BLAS
functions \tcode{xDOT}, \tcode{xDOTU}, and \tcode{xDOTC}\supercite{blas1}.
\end{note}

\pnum
The following elements apply to all functions in \ref{linalg.algs.blas1.dot}.

\pnum
\mandates
\tcode{\exposid{compatible-static-extents}<InVec1, InVec2>(0, 0)} is \tcode{true}.

\pnum
\expects
\tcode{v1.extent(0)} equals \tcode{v2.extent(0)}.

\indexlibraryglobal{dot}%
\begin{itemdecl}
template<@\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, @\exposconcept{scalar}@ Scalar>
  Scalar dot(InVec1 v1, InVec2 v2, Scalar init);
template<class ExecutionPolicy, @\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, @\exposconcept{scalar}@ Scalar>
  Scalar dot(ExecutionPolicy&& exec,
             InVec1 v1, InVec2 v2, Scalar init);
\end{itemdecl}

\begin{itemdescr}
\pnum
These functions compute a non-conjugated dot product
with an explicitly specified result type.

\pnum
\returns
Let \tcode{N} be \tcode{v1.extent(0)}.
\begin{itemize}
\item
\tcode{init} if \tcode{N} is zero;
\item
otherwise,
\tcode{\placeholdernc{GENERALIZED_SUM}(plus<>(), init, v1[0]*v2[0], \ldots, v1[N-1]*v2[N-1])}.
\end{itemize}

\pnum
\remarks
If \tcode{InVec1::value_type}, \tcode{InVec2::value_type}, and \tcode{Scalar}
are all floating-point types or specializations of \tcode{complex},
and if \tcode{Scalar} has higher precision
than \tcode{InVec1::value_type} or \tcode{InVec2::value_type},
then intermediate terms in the sum use \tcode{Scalar}'s precision or greater.
\end{itemdescr}

\indexlibraryglobal{dot}%
\begin{itemdecl}
  template<@\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2>
    auto dot(InVec1 v1, InVec2 v2);
  template<class ExecutionPolicy, @\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2>
    auto dot(ExecutionPolicy&& exec,
             InVec1 v1, InVec2 v2);
\end{itemdecl}

\begin{itemdescr}
\pnum
These functions compute a non-conjugated dot product with a default result type.

\pnum
\effects
Let \tcode{T} be
\tcode{decltype(declval<typename InVec1::value_type>() * declval<typename In\-Vec2::value_type>())}.
Then,
\begin{itemize}
\item
the two-parameter overload is equivalent to:
\begin{codeblock}
return dot(v1, v2, T{});
\end{codeblock}
and
\item
the three-parameter overload is equivalent to:
\begin{codeblock}
return dot(std::forward<ExecutionPolicy>(exec), v1, v2, T{});
\end{codeblock}
\end{itemize}
\end{itemdescr}

\indexlibraryglobal{dotc}%
\begin{itemdecl}
template<@\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, @\exposconcept{scalar}@ Scalar>
  Scalar dotc(InVec1 v1, InVec2 v2, Scalar init);
template<class ExecutionPolicy, @\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, @\exposconcept{scalar}@ Scalar>
  Scalar dotc(ExecutionPolicy&& exec,
              InVec1 v1, InVec2 v2, Scalar init);
\end{itemdecl}

\begin{itemdescr}

\pnum
These functions compute a conjugated dot product
with an explicitly specified result type.

\pnum
\effects
\begin{itemize}
\item
The three-parameter overload is equivalent to:
\begin{codeblock}
return dot(conjugated(v1), v2, init);
\end{codeblock}
and
\item
the four-parameter overload is equivalent to:
\begin{codeblock}
return dot(std::forward<ExecutionPolicy>(exec), conjugated(v1), v2, init);
\end{codeblock}
\end{itemize}
\end{itemdescr}

\indexlibraryglobal{dotc}%
\begin{itemdecl}
template<@\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2>
  auto dotc(InVec1 v1, InVec2 v2);
template<class ExecutionPolicy, @\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2>
  auto dotc(ExecutionPolicy&& exec,
            InVec1 v1, InVec2 v2);
\end{itemdecl}

\begin{itemdescr}

\pnum
These functions compute a conjugated dot product with a default result type.

\pnum
\effects
Let \tcode{T} be \tcode{decltype(\exposid{conj-if-needed}(declval<typename InVec1::value_type>()) * decl\-val<typename InVec2::value_type>())}.
Then,
\begin{itemize}
\item
the two-parameter overload is equivalent to:
\begin{codeblock}
return dotc(v1, v2, T{});
\end{codeblock}
and
\item
the three-parameter overload is equivalent to
\begin{codeblock}
return dotc(std::forward<ExecutionPolicy>(exec), v1, v2, T{});
\end{codeblock}
\end{itemize}
\end{itemdescr}

\rSec3[linalg.algs.blas1.nrm2]{Euclidean norm of a vector}

\indexlibraryglobal{vector_two_norm}%
\begin{itemdecl}
template<@\exposconcept{in-vector}@ InVec, @\exposconcept{scalar}@ Scalar>
  Scalar vector_two_norm(InVec v, Scalar init);
template<class ExecutionPolicy, @\exposconcept{in-vector}@ InVec, @\exposconcept{scalar}@ Scalar>
  Scalar vector_two_norm(ExecutionPolicy&& exec, InVec v, Scalar init);
\end{itemdecl}

\begin{itemdescr}
\pnum
\begin{note}
These functions correspond to the BLAS function \tcode{xNRM2}\supercite{blas1}.
\end{note}

\pnum
\mandates
\tcode{InVec::value_type} and \tcode{Scalar} are either a floating-point type, or
a specialization of \tcode{complex}.
Let \tcode{a} be
\tcode{\exposid{abs-if-needed}(declval<typename InVec::value_type>())}.
Then, \tcode{decltype(\linebreak init + a * a} is convertible to \tcode{Scalar}.

\pnum
\returns
The square root of the sum of the square of \tcode{init} and the squares of the absolute values of the elements of \tcode{v}.
\begin{note}
For \tcode{init} equal to zero, this is the Euclidean norm
(also called 2-norm) of the vector \tcode{v}.
\end{note}

\pnum
\remarks
If \tcode{Scalar} has higher precision
than \tcode{InVec::value_type},
then intermediate terms in the sum use \tcode{Scalar}'s precision or greater.
\end{itemdescr}

\indexlibraryglobal{vector_two_norm}%
\begin{itemdecl}
template<@\exposconcept{in-vector}@ InVec>
  auto vector_two_norm(InVec v);
template<class ExecutionPolicy, @\exposconcept{in-vector}@ InVec>
  auto vector_two_norm(ExecutionPolicy&& exec, InVec v);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Let \tcode{a} be
\tcode{\exposid{abs-if-needed}(declval<typename InVec::value_type>())}.
Let \tcode{T} be \tcode{decltype(a * a)}.
Then,
\begin{itemize}
\item
the one-parameter overload is equivalent to:
\begin{codeblock}
return vector_two_norm(v, T{});
\end{codeblock}
and
\item
the two-parameter overload is equivalent to:
\begin{codeblock}
return vector_two_norm(std::forward<ExecutionPolicy>(exec), v, T{});
\end{codeblock}
\end{itemize}
\end{itemdescr}

\rSec3[linalg.algs.blas1.asum]{Sum of absolute values of vector elements}

\indexlibraryglobal{vector_abs_sum}%
\begin{itemdecl}
template<@\exposconcept{in-vector}@ InVec, @\exposconcept{scalar}@ Scalar>
  Scalar vector_abs_sum(InVec v, Scalar init);
template<class ExecutionPolicy, @\exposconcept{in-vector}@ InVec, @\exposconcept{scalar}@ Scalar>
  Scalar vector_abs_sum(ExecutionPolicy&& exec, InVec v, Scalar init);
\end{itemdecl}

\begin{itemdescr}
\pnum
\begin{note}
These functions correspond to the BLAS functions
\tcode{SASUM}, \tcode{DASUM}, \tcode{SCASUM}, and \tcode{DZASUM}\supercite{blas1}.
\end{note}

\pnum
\mandates
\begin{codeblock}
decltype(init + @\exposid{abs-if-needed}@(@\exposid{real-if-needed}@(declval<typename InVec::value_type>())) +
                @\exposid{abs-if-needed}@(@\exposid{imag-if-needed}@(declval<typename InVec::value_type>())))
\end{codeblock}
is convertible to \tcode{Scalar}.

\pnum
\returns
Let \tcode{N} be \tcode{v.extent(0)}.
\begin{itemize}
\item
\tcode{init} if \tcode{N} is zero;
\item
otherwise, if \tcode{InVec::value_type} is an arithmetic type,
\begin{codeblock}
@\placeholdernc{GENERALIZED_SUM}@(plus<>(), init, @\exposid{abs-if-needed}@(v[0]), @\ldots@, @\exposid{abs-if-needed}@(v[N-1]))
\end{codeblock}
\item
otherwise,
\begin{codeblock}
@\placeholdernc{GENERALIZED_SUM}@(plus<>(), init,
       @\exposid{abs-if-needed}@(@\exposid{real-if-needed}@(v[0])) + @\exposid{abs-if-needed}@(@\exposid{imag-if-needed}@(v[0])),
       @\ldots@,
       @\exposid{abs-if-needed}@(@\exposid{real-if-needed}@(v[N-1])) + @\exposid{abs-if-needed}@(@\exposid{imag-if-needed}@(v[N-1])))
\end{codeblock}
\end{itemize}

\pnum
\remarks
If \tcode{InVec::value_type} and \tcode{Scalar}
are all floating-point types or specializations of \tcode{complex},
and if \tcode{Scalar} has higher precision
than \tcode{InVec::value_type},
then intermediate terms in the sum use \tcode{Scalar}'s precision or greater.
\end{itemdescr}

\indexlibraryglobal{vector_abs_sum}%
\begin{itemdecl}
template<@\exposconcept{in-vector}@ InVec>
  auto vector_abs_sum(InVec v);
template<class ExecutionPolicy, @\exposconcept{in-vector}@ InVec>
  auto vector_abs_sum(ExecutionPolicy&& exec, InVec v);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Let \tcode{T} be \tcode{typename InVec::value_type}.
Then,
\begin{itemize}
\item
the one-parameter overload is equivalent to:
\begin{codeblock}
return vector_abs_sum(v, T{});
\end{codeblock}
and
\item
the two-parameter overload is equivalent to:
\begin{codeblock}
return vector_abs_sum(std::forward<ExecutionPolicy>(exec), v, T{});
\end{codeblock}
\end{itemize}
\end{itemdescr}

\rSec3[linalg.algs.blas1.iamax]{Index of maximum absolute value of vector elements}

\indexlibraryglobal{vector_idx_abs_max}%
\begin{itemdecl}
template<@\exposconcept{in-vector}@ InVec>
  typename InVec::extents_type vector_idx_abs_max(InVec v);
template<class ExecutionPolicy, @\exposconcept{in-vector}@ InVec>
  typename InVec::extents_type vector_idx_abs_max(ExecutionPolicy&& exec, InVec v);
\end{itemdecl}

\begin{itemdescr}
\pnum
\begin{note}
These functions correspond to the BLAS function \tcode{IxAMAX}\supercite{blas1}.
\end{note}

\pnum
Let \tcode{T} be
\begin{codeblock}
decltype(@\exposid{abs-if-needed}@(@\exposid{real-if-needed}@(declval<typename InVec::value_type>())) +
         @\exposid{abs-if-needed}@(@\exposid{imag-if-needed}@(declval<typename InVec::value_type>())))
\end{codeblock}

\pnum
\mandates
\tcode{declval<T>() < declval<T>()} is a valid expression.

\pnum
\returns
\begin{itemize}
\item
\tcode{numeric_limits<typename InVec::size_type>::max()}
      if \tcode{v} has zero elements;
\item
otherwise, the index of the first element of \tcode{v}
having largest absolute value,
if \tcode{InVec::value_type} is an arithmetic type;
\item
otherwise, the index of the first element $\tcode{v}_e$ of \tcode{v}
for which
\begin{codeblock}
@\exposid{abs-if-needed}@(@\exposid{real-if-needed}@(@$\tcode{v}_e$@)) + @\exposid{abs-if-needed}@(@\exposid{imag-if-needed}@(@$\tcode{v}_e$@))
\end{codeblock}
has the largest value.
\end{itemize}
\end{itemdescr}

\rSec3[linalg.algs.blas1.matfrobnorm]{Frobenius norm of a matrix}

\pnum
\begin{note}
These functions exist in the BLAS standard\supercite{blas-std}
but are not part of the reference implementation.
\end{note}

\indexlibraryglobal{matrix_frob_norm}%
\begin{itemdecl}
template<@\exposconcept{in-matrix}@ InMat, @\exposconcept{scalar}@ Scalar>
  Scalar matrix_frob_norm(InMat A, Scalar init);
template<class ExecutionPolicy, @\exposconcept{in-matrix}@ InMat, @\exposconcept{scalar}@ Scalar>
  Scalar matrix_frob_norm(ExecutionPolicy&& exec, InMat A, Scalar init);
\end{itemdecl}

\begin{itemdescr}

\pnum
\mandates
\tcode{InVec::value_type} and \tcode{Scalar} are either a floating-point type, or
a specialization of \tcode{complex}.
Let \tcode{a} be
\tcode{\exposid{abs-if-needed}(declval<typename InMat::value_type>())}.
Then, \tcode{decltype(\linebreak init + a * a)}
is convertible to \tcode{Scalar}.

\pnum
\returns
The square root of the sum of squares
of \tcode{init} and the absolute values of the elements of \tcode{A}.
\begin{note}
For \tcode{init} equal to zero,
this is the Frobenius norm of the matrix \tcode{A}.
\end{note}

\pnum
\remarks
If \tcode{Scalar} has higher precision
than \tcode{InMat::value_type},
then intermediate terms in the sum use \tcode{Scalar}'s precision or greater.
\end{itemdescr}

\indexlibraryglobal{matrix_frob_norm}%
\begin{itemdecl}
template<@\exposconcept{in-matrix}@ InMat>
  auto matrix_frob_norm(InMat A);
template<class ExecutionPolicy, @\exposconcept{in-matrix}@ InMat>
  auto matrix_frob_norm(ExecutionPolicy&& exec, InMat A);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Let \tcode{a} be
\tcode{\exposid{abs-if-needed}(declval<typename InMat::value_type>())}.
Let \tcode{T} be
\tcode{decltype(a * a)}.
Then,
\begin{itemize}
\item
the one-parameter overload is equivalent to:
\begin{codeblock}
return matrix_frob_norm(A, T{});
\end{codeblock}
and
\item
the two-parameter overload is equivalent to:
\begin{codeblock}
return matrix_frob_norm(std::forward<ExecutionPolicy>(exec), A, T{});
\end{codeblock}
\end{itemize}
\end{itemdescr}

\rSec3[linalg.algs.blas1.matonenorm]{One norm of a matrix}

\pnum
\begin{note}
These functions exist in the BLAS standard\supercite{blas-std}
but are not part of the reference implementation.
\end{note}

\indexlibraryglobal{matrix_one_norm}%
\begin{itemdecl}
template<@\exposconcept{in-matrix}@ InMat, @\exposconcept{scalar}@ Scalar>
  Scalar matrix_one_norm(InMat A, Scalar init);
template<class ExecutionPolicy, @\exposconcept{in-matrix}@ InMat, @\exposconcept{scalar}@ Scalar>
  Scalar matrix_one_norm(ExecutionPolicy&& exec, InMat A, Scalar init);
\end{itemdecl}

\begin{itemdescr}
\pnum
\mandates
\tcode{decltype(\exposid{abs-if-needed}(declval<typename InMat::value_type>()))}
is convertible to \tcode{Scalar}.

\pnum
\returns
\begin{itemize}
\item
\tcode{init} if \tcode{A.extent(1)} is zero;
\item
otherwise, the sum of \tcode{init} and the one norm of the matrix $A$.
\end{itemize}
\begin{note}
The one norm of the matrix \tcode{A}
is the maximum over all columns of \tcode{A},
of the sum of the absolute values of the elements of the column.
\end{note}

\pnum
\remarks
If \tcode{InMat::value_type} and \tcode{Scalar}
are all floating-point types or specializations of \tcode{complex},
and if \tcode{Scalar} has higher precision
than \tcode{InMat::value_type},
then intermediate terms in the sum use \tcode{Scalar}'s precision or greater.
\end{itemdescr}

\indexlibraryglobal{matrix_one_norm}%
\begin{itemdecl}
template<@\exposconcept{in-matrix}@ InMat>
  auto matrix_one_norm(InMat A);
template<class ExecutionPolicy, @\exposconcept{in-matrix}@ InMat>
  auto matrix_one_norm(ExecutionPolicy&& exec, InMat A);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Let \tcode{T} be
\tcode{decltype(\exposid{abs-if-needed}(declval<typename InMat::value_type>())}.
Then,
\begin{itemize}
\item
the one-parameter overload is equivalent to:
\begin{codeblock}
return matrix_one_norm(A, T{});
\end{codeblock}
and
\item
the two-parameter overload is equivalent to:
\begin{codeblock}
return matrix_one_norm(std::forward<ExecutionPolicy>(exec), A, T{});
\end{codeblock}
\end{itemize}
\end{itemdescr}

\rSec3[linalg.algs.blas1.matinfnorm]{Infinity norm of a matrix}

\pnum
\begin{note}
These functions exist in the BLAS standard\supercite{blas-std}
but are not part of the reference implementation.
\end{note}

\indexlibraryglobal{matrix_inf_norm}%
\begin{itemdecl}
template<@\exposconcept{in-matrix}@ InMat, @\exposconcept{scalar}@ Scalar>
  Scalar matrix_inf_norm(InMat A, Scalar init);
template<class ExecutionPolicy, @\exposconcept{in-matrix}@ InMat, @\exposconcept{scalar}@ Scalar>
  Scalar matrix_inf_norm(ExecutionPolicy&& exec, InMat A, Scalar init);
\end{itemdecl}

\begin{itemdescr}
\pnum
\mandates
\tcode{decltype(\exposid{abs-if-needed}(declval<typename InMat::value_type>()))}
is convertible to \tcode{Scalar}.

\pnum
\returns
\begin{itemize}
\item
\tcode{init} if \tcode{A.extent(0)} is zero;
\item
otherwise,
the sum of \tcode{init} and the infinity norm of the matrix \tcode{A}.
\end{itemize}
\begin{note}
The infinity norm of the matrix \tcode{A}
is the maximum over all rows of \tcode{A},
of the sum of the absolute values
of the elements of the row.
\end{note}

\pnum
\remarks
If \tcode{InMat::value_type} and \tcode{Scalar}
are all floating-point types or specializations of \tcode{complex},
and if \tcode{Scalar} has higher precision
than \tcode{InMat::value_type},
then intermediate terms in the sum use \tcode{Scalar}'s precision or greater.
\end{itemdescr}

\indexlibraryglobal{matrix_inf_norm}%
\begin{itemdecl}
template<@\exposconcept{in-matrix}@ InMat>
  auto matrix_inf_norm(InMat A);
template<class ExecutionPolicy, @\exposconcept{in-matrix}@ InMat>
  auto matrix_inf_norm(ExecutionPolicy&& exec, InMat A);
\end{itemdecl}

\begin{itemdescr}

\pnum
\effects
Let \tcode{T} be
\tcode{decltype(\exposid{abs-if-needed}(declval<typename InMat::value_type>())}.
Then,
\begin{itemize}
\item
the one-parameter overload is equivalent to:
\begin{codeblock}
return matrix_inf_norm(A, T{});
\end{codeblock}
and
\item
the two-parameter overload is equivalent to:
\begin{codeblock}
return matrix_inf_norm(std::forward<ExecutionPolicy>(exec), A, T{});
\end{codeblock}
\end{itemize}
\end{itemdescr}

\rSec2[linalg.algs.blas2]{BLAS 2 algorithms}

\rSec3[linalg.algs.blas2.gemv]{General matrix-vector product}

\pnum
\begin{note}
These functions correspond to the BLAS function \tcode{xGEMV}.
\end{note}

\pnum
The following elements apply to all functions in \ref{linalg.algs.blas2.gemv}.

\pnum
\mandates
\begin{itemize}
\item
\tcode{\exposid{possibly-multipliable}<decltype(A), decltype(x), decltype(y)>()}
is \tcode{true}, and
\item
\tcode{\exposid{possibly-addable}<decltype(y), decltype(y), decltype(z)>()}
is \tcode{true} for those overloads that take a \tcode{z} parameter.
\end{itemize}

\pnum
\expects
\begin{itemize}
\item
\tcode{\exposid{multipliable}(A,x,y)} is \tcode{true}, and
\item
\tcode{\exposid{addable}(y,y,z)} is \tcode{true} for those overloads that take a \tcode{z} parameter.
\end{itemize}

\pnum
\complexity
\bigoh{\tcode{A.extent(0)} \times \tcode{x.extent(0)}}.

\indexlibraryglobal{matrix_vector_product}%
\begin{itemdecl}
template<@\exposconcept{in-matrix}@ InMat, @\exposconcept{in-vector}@ InVec, @\exposconcept{out-vector}@ OutVec>
  void matrix_vector_product(InMat A, InVec x, OutVec y);
template<class ExecutionPolicy, @\exposconcept{in-matrix}@ InMat, @\exposconcept{in-vector}@ InVec, @\exposconcept{out-vector}@ OutVec>
  void matrix_vector_product(ExecutionPolicy&& exec, InMat A, InVec x, OutVec y);
\end{itemdecl}

\begin{itemdescr}
\pnum
These functions perform an overwriting matrix-vector product.

\pnum
\effects
Computes $y = A x$.
\end{itemdescr}

\begin{example}
\begin{codeblock}
constexpr size_t num_rows = 5;
constexpr size_t num_cols = 6;

// y = 3.0 * A * x
void scaled_matvec_1(mdspan<double, extents<size_t, num_rows, num_cols>> A,
  mdspan<double, extents<size_t, num_cols>> x, mdspan<double, extents<size_t, num_rows>> y) {
  matrix_vector_product(scaled(3.0, A), x, y);
}

// z = 7.0 times the transpose of A, times y
void scaled_transposed_matvec(mdspan<double, extents<size_t, num_rows, num_cols>> A,
  mdspan<double, extents<size_t, num_rows>> y, mdspan<double, extents<size_t, num_cols>> z) {
  matrix_vector_product(scaled(7.0, transposed(A)), y, z);
}
\end{codeblock}
\end{example}

\indexlibraryglobal{matrix_vector_product}%
\begin{itemdecl}
  template<@\exposconcept{in-matrix}@ InMat, @\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, @\exposconcept{out-vector}@ OutVec>
    void matrix_vector_product(InMat A, InVec1 x, InVec2 y, OutVec z);
  template<class ExecutionPolicy,
           @\exposconcept{in-matrix}@ InMat, @\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, @\exposconcept{out-vector}@ OutVec>
    void matrix_vector_product(ExecutionPolicy&& exec,
                               InMat A, InVec1 x, InVec2 y, OutVec z);
\end{itemdecl}

\begin{itemdescr}
\pnum
These functions perform an updating matrix-vector product.

\pnum
\effects
Computes $z = y + A x$.

\pnum
\remarks
\tcode{z} may alias \tcode{y}.
\end{itemdescr}

\begin{example}
\begin{codeblock}
// y = 3.0 * A * x + 2.0 * y
void scaled_matvec_2(mdspan<double, extents<size_t, num_rows, num_cols>> A,
  mdspan<double, extents<size_t, num_cols>> x, mdspan<double, extents<size_t, num_rows>> y) {
  matrix_vector_product(scaled(3.0, A), x, scaled(2.0, y), y);
}
\end{codeblock}
\end{example}

\rSec3[linalg.algs.blas2.symv]{Symmetric matrix-vector product}

\pnum
\begin{note}
These functions correspond to the BLAS functions
\tcode{xSYMV} and \tcode{xSPMV}\supercite{blas2}.
\end{note}

\pnum
The following elements apply to all functions in \ref{linalg.algs.blas2.symv}.

\pnum
\mandates
\begin{itemize}
\item
If \tcode{InMat} has \tcode{layout_blas_packed} layout,
then the layout's \tcode{Triangle} template argument has
the same type as the function's \tcode{Triangle} template argument;
\item
\tcode{\exposid{compatible-static-extents}<decltype(A), decltype(A)>(0, 1)} is \tcode{true};
\item
\tcode{\exposid{possibly-multipliable}<decltype(A), decltype(x), decltype(y)>()}
is \tcode{true}; and
\item
\tcode{\exposid{possibly-addable}<decltype(y), decltype(y), decltype(z)>()}
is \tcode{true} for those overloads that take a \tcode{z} parameter.
\end{itemize}

\pnum
\expects
\begin{itemize}
\item
\tcode{A.extent(0)} equals \tcode{A.extent(1)},
\item
\tcode{\exposid{multipliable}(A,x,y)} is \tcode{true}, and
\item
\tcode{\exposid{addable}(y,y,z)} is \tcode{true}
for those overloads that take a \tcode{z} parameter.
\end{itemize}

\pnum
\complexity
\bigoh{\tcode{A.extent(0)} \times \tcode{x.extent(0)}}.

\indexlibraryglobal{symmetric_matrix_vector_product}%
\begin{itemdecl}
template<@\exposconcept{in-matrix}@ InMat, class Triangle, @\exposconcept{in-vector}@ InVec, @\exposconcept{out-vector}@ OutVec>
  void symmetric_matrix_vector_product(InMat A, Triangle t, InVec x, OutVec y);
template<class ExecutionPolicy,
         @\exposconcept{in-matrix}@ InMat, class Triangle, @\exposconcept{in-vector}@ InVec, @\exposconcept{out-vector}@ OutVec>
  void symmetric_matrix_vector_product(ExecutionPolicy&& exec,
                                       InMat A, Triangle t, InVec x, OutVec y);
\end{itemdecl}

\begin{itemdescr}

\pnum
These functions perform an overwriting symmetric matrix-vector product,
taking into account the \tcode{Triangle} parameter
that applies to the symmetric matrix \tcode{A}\iref{linalg.general}.

\pnum
\effects
Computes $y = A x$.
\end{itemdescr}

\indexlibraryglobal{symmetric_matrix_vector_product}%
\begin{itemdecl}
template<@\exposconcept{in-matrix}@ InMat, class Triangle, @\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, @\exposconcept{out-vector}@ OutVec>
  void symmetric_matrix_vector_product(InMat A, Triangle t, InVec1 x, InVec2 y, OutVec z);
template<class ExecutionPolicy,
         @\exposconcept{in-matrix}@ InMat, class Triangle, @\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, @\exposconcept{out-vector}@ OutVec>
  void symmetric_matrix_vector_product(ExecutionPolicy&& exec,
                                       InMat A, Triangle t, InVec1 x, InVec2 y, OutVec z);
\end{itemdecl}

\begin{itemdescr}
\pnum
These functions perform an updating symmetric matrix-vector product,
taking into account the \tcode{Triangle} parameter
that applies to the symmetric matrix \tcode{A}\iref{linalg.general}.

\pnum
\effects
Computes $z = y + A x$.

\pnum
\remarks
\tcode{z} may alias \tcode{y}.
\end{itemdescr}

\rSec3[linalg.algs.blas2.hemv]{Hermitian matrix-vector product}

\pnum
\begin{note}
These functions correspond to the BLAS functions
\tcode{xHEMV} and \tcode{xHPMV}\supercite{blas2}.
\end{note}

\pnum
The following elements apply to all functions in \ref{linalg.algs.blas2.hemv}.

\pnum
\mandates
\begin{itemize}
\item
If \tcode{InMat} has \tcode{layout_blas_packed} layout,
then the layout's \tcode{Triangle} template argument
has the same type as the function's \tcode{Triangle} template argument;
\item
\tcode{\exposid{compatible-static-extents}<decltype(A), decltype(A)>(0, 1)}
is \tcode{true};
\item
\tcode{\exposid{possibly-multipliable}<decltype(A), decltype(x), decltype(y)>()}
is \tcode{true}; and
\item
\tcode{\exposid{possibly-addable}<decltype(y), decltype(y), decltype(z)>()}
is \tcode{true} for those overloads that take a \tcode{z} parameter.
\end{itemize}

\pnum
\expects
\begin{itemize}
\item
\tcode{A.extent(0)} equals \tcode{A.extent(1)},
\item
\tcode{\exposid{multipliable}(A, x, y)} is \tcode{true}, and
\item
\tcode{\exposid{addable}(y, y, z)} is \tcode{true} for those overloads that take a \tcode{z} parameter.
\end{itemize}

\pnum
\complexity
\bigoh{\tcode{A.extent(0)} \times \tcode{x.extent(0)}}.

\indexlibraryglobal{hermitian_matrix_vector_product}%
\begin{itemdecl}
template<@\exposconcept{in-matrix}@ InMat, class Triangle, @\exposconcept{in-vector}@ InVec, @\exposconcept{out-vector}@ OutVec>
  void hermitian_matrix_vector_product(InMat A, Triangle t, InVec x, OutVec y);
template<class ExecutionPolicy,
         @\exposconcept{in-matrix}@ InMat, class Triangle, @\exposconcept{in-vector}@ InVec, @\exposconcept{out-vector}@ OutVec>
  void hermitian_matrix_vector_product(ExecutionPolicy&& exec,
                                       InMat A, Triangle t, InVec x, OutVec y);
\end{itemdecl}

\begin{itemdescr}
\pnum
These functions perform an overwriting Hermitian matrix-vector product,
taking into account the \tcode{Triangle} parameter
that applies to the Hermitian matrix \tcode{A}\iref{linalg.general}.

\pnum
\effects
Computes $y = A x$.
\end{itemdescr}

\indexlibraryglobal{hermitian_matrix_vector_product}%
\begin{itemdecl}
template<@\exposconcept{in-matrix}@ InMat, class Triangle, @\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, @\exposconcept{out-vector}@ OutVec>
  void hermitian_matrix_vector_product(InMat A, Triangle t, InVec1 x, InVec2 y, OutVec z);
template<class ExecutionPolicy,
         @\exposconcept{in-matrix}@ InMat, class Triangle, @\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, @\exposconcept{out-vector}@ OutVec>
  void hermitian_matrix_vector_product(ExecutionPolicy&& exec,
                                       InMat A, Triangle t, InVec1 x, InVec2 y, OutVec z);
\end{itemdecl}

\begin{itemdescr}
\pnum
These functions perform an updating Hermitian matrix-vector product,
taking into account the \tcode{Triangle} parameter
that applies to the Hermitian matrix \tcode{A}\iref{linalg.general}.

\pnum
\effects
Computes $z = y + A x$.

\pnum
\remarks
\tcode{z} may alias \tcode{y}.
\end{itemdescr}

\rSec3[linalg.algs.blas2.trmv]{Triangular matrix-vector product}

\pnum
\begin{note}
These functions correspond to the BLAS functions
\tcode{xTRMV} and \tcode{xTPMV}\supercite{blas2}.
\end{note}

\pnum
The following elements apply to all functions in \ref{linalg.algs.blas2.trmv}.

\pnum
\mandates
\begin{itemize}
\item
If \tcode{InMat} has \tcode{layout_blas_packed} layout,
then the layout's \tcode{Triangle} template argument has
the same type as the function's \tcode{Triangle} template argument;
\item
\tcode{\exposid{compatible-static-extents}<decltype(A), decltype(A)>(0, 1)}
is \tcode{true};
\item
\tcode{\exposid{compatible-static-extents}<decltype(A), decltype(y)>(0, 0)}
is \tcode{true};
\item
\tcode{\exposid{compatible-static-extents}<decltype(A), decltype(x)>(0, 0)}
is \tcode{true} for those overloads that take an \tcode{x} parameter; and
\item
\tcode{\exposid{compatible-static-extents}<decltype(A), decltype(z)>(0, 0)}
is \tcode{true} for those overloads that take a \tcode{z} parameter.
\end{itemize}

\pnum
\expects
\begin{itemize}
\item
\tcode{A.extent(0)} equals \tcode{A.extent(1)},
\item
\tcode{A.extent(0)} equals \tcode{y.extent(0)},
\item
\tcode{A.extent(0)} equals \tcode{x.extent(0)} for those overloads that take an \tcode{x} parameter, and
\item
\tcode{A.extent(0)} equals \tcode{z.extent(0)} for those overloads that take a \tcode{z} parameter.
\end{itemize}

\indexlibraryglobal{triangular_matrix_vector_product}%
\begin{itemdecl}
template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, @\exposconcept{in-vector}@ InVec,
         @\exposconcept{out-vector}@ OutVec>
  void triangular_matrix_vector_product(InMat A, Triangle t, DiagonalStorage d, InVec x, OutVec y);
template<class ExecutionPolicy,
         @\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, @\exposconcept{in-vector}@ InVec,
         @\exposconcept{out-vector}@ OutVec>
  void triangular_matrix_vector_product(ExecutionPolicy&& exec,
                                        InMat A, Triangle t, DiagonalStorage d, InVec x, OutVec y);
\end{itemdecl}

\begin{itemdescr}

\pnum
These functions perform
an overwriting triangular matrix-vector product,
taking into account the \tcode{Triangle} and \tcode{DiagonalStorage} parameters
that apply to the triangular matrix \tcode{A}\iref{linalg.general}.

\pnum
\effects
Computes $y = A x$.

\pnum
\complexity
\bigoh{\tcode{A.extent(0)} \times \tcode{x.extent(0)}}.
\end{itemdescr}

\indexlibraryglobal{triangular_matrix_vector_product}%
\begin{itemdecl}
template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, @\exposconcept{inout-vector}@ InOutVec>
  void triangular_matrix_vector_product(InMat A, Triangle t, DiagonalStorage d, InOutVec y);
template<class ExecutionPolicy,
         @\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, @\exposconcept{inout-vector}@ InOutVec>
  void triangular_matrix_vector_product(ExecutionPolicy&& exec,
                                        InMat A, Triangle t, DiagonalStorage d, InOutVec y);
\end{itemdecl}

\begin{itemdescr}

\pnum
These functions perform an in-place triangular matrix-vector product,
taking into account the \tcode{Triangle} and \tcode{DiagonalStorage} parameters
that apply to the triangular matrix \tcode{A}\iref{linalg.general}.
\begin{note}
Performing this operation in place hinders parallelization.
However, other \tcode{ExecutionPolicy} specific optimizations,
such as vectorization, are still possible.
\end{note}

\pnum
\effects
Computes a vector $y'$ such that $y' = A y$,
and assigns each element of $y'$ to the corresponding element of $y$.

\pnum
\complexity
\bigoh{\tcode{A.extent(0)} \times \tcode{y.extent(0)}}.
\end{itemdescr}

\indexlibraryglobal{triangular_matrix_vector_product}%
\begin{itemdecl}
template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage,
         @\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, @\exposconcept{out-vector}@ OutVec>
  void triangular_matrix_vector_product(InMat A, Triangle t, DiagonalStorage d,
                                        InVec1 x, InVec2 y, OutVec z);
template<class ExecutionPolicy, @\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage,
         @\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, @\exposconcept{out-vector}@ OutVec>
  void triangular_matrix_vector_product(ExecutionPolicy&& exec,
                                        InMat A, Triangle t, DiagonalStorage d,
                                        InVec1 x, InVec2 y, OutVec z);
\end{itemdecl}

\begin{itemdescr}
\pnum
These functions perform an updating triangular matrix-vector product,
taking into account the \tcode{Triangle} and \tcode{DiagonalStorage} parameters
that apply to the triangular matrix \tcode{A}\iref{linalg.general}.

\pnum
\effects
Computes $z = y + A x$.

\pnum
\complexity
\bigoh{\tcode{A.extent(0)} \times \tcode{x.extent(0)}}.

\pnum
\remarks
\tcode{z} may alias \tcode{y}.
\end{itemdescr}

\rSec3[linalg.algs.blas2.trsv]{Solve a triangular linear system}

\pnum
\begin{note}
These functions correspond to the BLAS functions
\tcode{xTRSV} and \tcode{xTPSV}\supercite{blas2}.
\end{note}

\pnum
The following elements apply to all functions in \ref{linalg.algs.blas2.trsv}.

\pnum
\mandates
\begin{itemize}
\item
If \tcode{InMat} has \tcode{layout_blas_packed} layout,
then the layout's \tcode{Triangle} template argument has
the same type as the function's \tcode{Triangle} template argument;
\item
\tcode{\exposid{compatible-static-extents}<decltype(A), decltype(A)>(0, 1)}
is \tcode{true};
\item
\tcode{\exposid{compatible-static-extents}<decltype(A), decltype(b)>(0, 0)}
is \tcode{true}; and
\item
\tcode{\exposid{compatible-static-extents}<decltype(A), decltype(x)>(0, 0)}
is \tcode{true} for those overloads that take an \tcode{x} parameter.
\end{itemize}

\pnum
\expects
\begin{itemize}
\item
\tcode{A.extent(0)} equals \tcode{A.extent(1)},
\item
\tcode{A.extent(0)} equals \tcode{b.extent(0)}, and
\item
\tcode{A.extent(0)} equals \tcode{x.extent(0)}
for those overloads that take an \tcode{x} parameter.
\end{itemize}

\indexlibraryglobal{triangular_matrix_vector_solve}%
\begin{itemdecl}
  template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage,
           @\exposconcept{in-vector}@ InVec, @\exposconcept{out-vector}@ OutVec, class BinaryDivideOp>
    void triangular_matrix_vector_solve(InMat A, Triangle t, DiagonalStorage d,
                                        InVec b, OutVec x, BinaryDivideOp divide);
  template<class ExecutionPolicy, @\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage,
           @\exposconcept{in-vector}@ InVec, @\exposconcept{out-vector}@ OutVec, class BinaryDivideOp>
    void triangular_matrix_vector_solve(ExecutionPolicy&& exec,
                                        InMat A, Triangle t, DiagonalStorage d,
                                        InVec b, OutVec x, BinaryDivideOp divide);
\end{itemdecl}

\begin{itemdescr}

\pnum
These functions perform
a triangular solve,
taking into account the \tcode{Triangle} and \tcode{DiagonalStorage} parameters
that apply to the triangular matrix \tcode{A}\iref{linalg.general}.

\pnum
\effects
Computes a vector $x'$ such that $b = A x'$,
and assigns each element of $x'$ to the corresponding element of $x$.
If no such $x'$ exists,
then the elements of \tcode{x} are valid but unspecified.

\pnum
\complexity
\bigoh{\tcode{A.extent(1)} \times \tcode{b.extent(0)}}.
\end{itemdescr}

\indexlibraryglobal{triangular_matrix_vector_solve}%
\begin{itemdecl}
template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage,
         @\exposconcept{in-vector}@ InVec, @\exposconcept{out-vector}@ OutVec>
  void triangular_matrix_vector_solve(InMat A, Triangle t, DiagonalStorage d, InVec b, OutVec x);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
triangular_matrix_vector_solve(A, t, d, b, x, divides<void>{});
\end{codeblock}
\end{itemdescr}

\indexlibraryglobal{triangular_matrix_vector_solve}%
\begin{itemdecl}
template<class ExecutionPolicy, @\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage,
         @\exposconcept{in-vector}@ InVec, @\exposconcept{out-vector}@ OutVec>
  void triangular_matrix_vector_solve(ExecutionPolicy&& exec,
                                      InMat A, Triangle t, DiagonalStorage d, InVec b, OutVec x);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
triangular_matrix_vector_solve(std::forward<ExecutionPolicy>(exec),
                               A, t, d, b, x, divides<void>{});
\end{codeblock}
\end{itemdescr}

\indexlibraryglobal{triangular_matrix_vector_solve}%
\begin{itemdecl}
template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage,
         @\exposconcept{inout-vector}@ InOutVec, class BinaryDivideOp>
  void triangular_matrix_vector_solve(InMat A, Triangle t, DiagonalStorage d,
                                      InOutVec b, BinaryDivideOp divide);
template<class ExecutionPolicy, @\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage,
         @\exposconcept{inout-vector}@ InOutVec, class BinaryDivideOp>
  void triangular_matrix_vector_solve(ExecutionPolicy&& exec,
                                      InMat A, Triangle t, DiagonalStorage d,
                                      InOutVec b, BinaryDivideOp divide);
\end{itemdecl}

\begin{itemdescr}
\pnum
These functions perform an in-place triangular solve,
taking into account the \tcode{Triangle} and \tcode{Diagonal\-Storage} parameters
that apply to the triangular matrix \tcode{A}\iref{linalg.general}.
\begin{note}
Performing triangular solve in place hinders parallelization.
However, other \tcode{ExecutionPolicy} specific optimizations,
such as vectorization, are still possible.
\end{note}

\pnum
\effects
Computes a vector $x'$ such that $b = A x'$,
and assigns each element of $x'$ to the corresponding element of $b$.
If no such $x'$ exists,
then the elements of \tcode{b} are valid but unspecified.

\pnum
\complexity
\bigoh{\tcode{A.extent(1)} \times \tcode{b.extent(0)}}.
\end{itemdescr}

\indexlibraryglobal{triangular_matrix_vector_solve}%
\begin{itemdecl}
template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, @\exposconcept{inout-vector}@ InOutVec>
  void triangular_matrix_vector_solve(InMat A, Triangle t, DiagonalStorage d, InOutVec b);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
triangular_matrix_vector_solve(A, t, d, b, divides<void>{});
\end{codeblock}
\end{itemdescr}

\indexlibraryglobal{triangular_matrix_vector_solve}%
\begin{itemdecl}
template<class ExecutionPolicy,
         @\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, @\exposconcept{inout-vector}@ InOutVec>
  void triangular_matrix_vector_solve(ExecutionPolicy&& exec,
                                      InMat A, Triangle t, DiagonalStorage d, InOutVec b);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
triangular_matrix_vector_solve(std::forward<ExecutionPolicy>(exec),
                               A, t, d, b, divides<void>{});
\end{codeblock}
\end{itemdescr}

\rSec3[linalg.algs.blas2.rank1]{Rank-1 (outer product) update of a matrix}

\pnum
The following elements apply to all functions in~\ref{linalg.algs.blas2.rank1}.

\pnum
\mandates
\begin{itemize}
\item
\tcode{\exposid{possibly-multipliable}<OutMat, InVec2, InVec1>()}
is \tcode{true}, and
\item
\tcode{\exposid{possibly-addable}<OutMat, InMat, OutMat>()}
is \tcode{true} for those overloads with an \tcode{E} parameter.
\end{itemize}

\pnum
\expects
\begin{itemize}
\item
\tcode{\exposid{multipliable}(A, y, x)}
is \tcode{true}, and
\item
\tcode{\exposid{addable}(A, E, A)}
is \tcode{true} for those overloads with an \tcode{E} parameter.
\end{itemize}

\pnum
\complexity
\bigoh{\tcode{x.extent(0)} \times \tcode{y.extent(0)}}.

\indexlibraryglobal{matrix_rank_1_update}%
\begin{itemdecl}
template<@\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, @\exposconcept{out-matrix}@ OutMat>
  void matrix_rank_1_update(InVec1 x, InVec2 y, OutMat A);
template<class ExecutionPolicy, @\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, @\exposconcept{out-matrix}@ OutMat>
  void matrix_rank_1_update(ExecutionPolicy&& exec, InVec1 x, InVec2 y, OutMat A);
\end{itemdecl}

\begin{itemdescr}
\pnum
These functions perform an overwriting nonsymmetric nonconjugated rank-1 update.
\begin{note}
These functions correspond to the BLAS functions
\tcode{xGER} (for real element types) and
\tcode{xGERU} (for complex element types)\supercite{blas2}.
\end{note}

\pnum
\effects
Computes $A = x y^T$.
\end{itemdescr}

\indexlibraryglobal{matrix_rank_1_update}%
\begin{itemdecl}
template<@\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, @\exposconcept{in-matrix}@ InMat, @\exposconcept{out-matrix}@ OutMat>
  void matrix_rank_1_update(InVec1 x, InVec2 y, InMat E, OutMat A);
template<class ExecutionPolicy, @\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, @\exposconcept{in-matrix}@ InMat,
         @\exposconcept{out-matrix}@ OutMat>
  void matrix_rank_1_update(ExecutionPolicy&& exec, InVec1 x, InVec2 y, InMat E, OutMat A);
\end{itemdecl}

\begin{itemdescr}
\pnum
These functions perform an updating nonsymmetric nonconjugated rank-1 update.
\begin{note}
These functions correspond to the BLAS functions
\tcode{xGER} (for real element types) and
\tcode{xGERU} (for complex element types)\supercite{blas2}.
\end{note}

\pnum
\effects
Computes $A = E + x y^T$.

\pnum
\remarks
\tcode{A} may alias \tcode{E}.
\end{itemdescr}

\indexlibraryglobal{matrix_rank_1_update_c}%
\begin{itemdecl}
template<@\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, @\exposconcept{out-matrix}@ OutMat>
  void matrix_rank_1_update_c(InVec1 x, InVec2 y, OutMat A);
template<class ExecutionPolicy, @\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, @\exposconcept{out-matrix}@ OutMat>
  void matrix_rank_1_update_c(ExecutionPolicy&& exec, InVec1 x, InVec2 y, OutMat A);
\end{itemdecl}

\begin{itemdescr}
\pnum
These functions perform an overwriting nonsymmetric conjugated rank-1 update.
\begin{note}
These functions correspond to the BLAS functions
\tcode{xGER} (for real element types) and
\tcode{xGERC} (for complex element types)\supercite{blas2}.
\end{note}

\pnum
\effects
\begin{itemize}
\item
For the overloads without an \tcode{ExecutionPolicy} argument,
equivalent to:
\begin{codeblock}
matrix_rank_1_update(x, conjugated(y), A);
\end{codeblock}
\item
otherwise, equivalent to:
\begin{codeblock}
matrix_rank_1_update(std::forward<ExecutionPolicy>(exec), x, conjugated(y), A);
\end{codeblock}
\end{itemize}
\end{itemdescr}

\indexlibraryglobal{matrix_rank_1_update_c}%
\begin{itemdecl}
template<@\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, @\exposconcept{in-matrix}@ InMat, @\exposconcept{out-matrix}@ OutMat>
  void matrix_rank_1_update_c(InVec1 x, InVec2 y, InMat E, OutMat A);
template<class ExecutionPolicy, @\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, @\exposconcept{in-matrix}@ InMat,
         @\exposconcept{out-matrix}@ OutMat>
  void matrix_rank_1_update_c(ExecutionPolicy&& exec, InVec1 x, InVec2 y, InMat E, OutMat A);
\end{itemdecl}

\begin{itemdescr}
\pnum
These functions perform an updating nonsymmetric conjugated rank-1 update.
\begin{note}
These functions correspond to the BLAS functions
\tcode{xGER} (for real element types) and
\tcode{xGERC} (for complex element types)\supercite{blas2}.
\end{note}

\pnum
\effects
\begin{itemize}
\item
For the overloads without an \tcode{ExecutionPolicy} argument,
equivalent to:
\begin{codeblock}
matrix_rank_1_update(x, conjugated(y), A);
\end{codeblock}
\item
otherwise, equivalent to:
\begin{codeblock}
matrix_rank_1_update(std::forward<ExecutionPolicy>(exec), x, conjugated(y), E, A);
\end{codeblock}
\end{itemize}
\end{itemdescr}

\rSec3[linalg.algs.blas2.symherrank1]{Symmetric or Hermitian Rank-1 (outer product) update of a matrix}

\pnum
\begin{note}
These functions correspond to the BLAS functions
\tcode{xSYR}, \tcode{xSPR}, \tcode{xHER}, and \tcode{xHPR}\supercite{blas2}.
They have overloads taking a scaling factor \tcode{alpha},
because it would be impossible to express the update
$A = A - x x^T$ in noncomplex arithmetic otherwise.
\end{note}

\pnum
The following elements apply to all functions in \ref{linalg.algs.blas2.symherrank1}.

\pnum
For any function \tcode{F} in this subclause with
a parameter named \tcode{t},
an \tcode{InMat} template parameter, and
a function parameter \tcode{InMat E},
\tcode{t} applies to accesses done through the parameter \tcode{E}.
\tcode{F} only accesses the triangle of \tcode{E} specified by \tcode{t}.
For accesses of diagonal elements \tcode{E[i, i]},
\tcode{F} only uses the value \tcode{\exposid{real-if-needed}(E[i, i])}
if the name of \tcode{F} starts with \tcode{hermitian}.
For accesses \tcode{E[i, j]} outside the triangle specified by \tcode{t},
\tcode{F} only uses the value
\begin{itemize}
\item
\tcode{\exposid{conj-if-needed}(E[j, i])}
if the name of \tcode{F} starts with \tcode{hermitian}, or
\item
\tcode{E[j, i]}
if the name of \tcode{F} starts with \tcode{symmetric}.
\end{itemize}

\pnum
\mandates
\begin{itemize}
\item
If \tcode{OutMat} has \tcode{layout_blas_packed} layout,
then the layout's \tcode{Triangle} template argument has
the same type as the function's \tcode{Triangle} template argument;
\item
\tcode{\exposid{compatible-static-extents}<decltype(A), decltype(A)>(0, 1)}
is \tcode{true};
\item
\tcode{\exposid{compatible-static-extents}<decltype(A), decltype(x)>(0, 0)}
is \tcode{true}; and
\item
\tcode{\exposid{possibly-addable}<decltype(A), decltype(E), decltype(A)>()}
is \tcode{true} for those overloads with an \tcode{E} parameter.
\end{itemize}

\pnum
\expects
\begin{itemize}
\item
\tcode{A.extent(0)} equals \tcode{A.extent(1)},
\item
\tcode{A.extent(0)} equals \tcode{x.extent(0)}, and
\item
\tcode{\exposid{addable}(A, E, A)} is \tcode{true}
for those overloads with an \tcode{E} parameter.
\end{itemize}

\pnum
\complexity
\bigoh{\tcode{x.extent(0)} \times \tcode{x.extent(0)}}.

\indexlibraryglobal{symmetric_matrix_rank_1_update}%
\begin{itemdecl}
template<@\exposconcept{scalar}@ Scalar, @\exposconcept{in-vector}@ InVec, @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle>
  void symmetric_matrix_rank_1_update(Scalar alpha, InVec x, OutMat A, Triangle t);
template<class ExecutionPolicy,
         @\exposconcept{scalar}@ Scalar, @\exposconcept{in-vector}@ InVec, @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle>
  void symmetric_matrix_rank_1_update(ExecutionPolicy&& exec,
                                      Scalar alpha, InVec x, OutMat A, Triangle t);
\end{itemdecl}

\begin{itemdescr}
\pnum
These functions perform
an overwriting symmetric rank-1 update of the symmetric matrix \tcode{A},
taking into account the \tcode{Triangle} parameter
that applies to \tcode{A}\iref{linalg.general}.

\pnum
\effects
Computes a matrix $A = \alpha x x^T$,
where the scalar $\alpha$ is \tcode{alpha}.
\end{itemdescr}

\indexlibraryglobal{symmetric_matrix_rank_1_update}%
\begin{itemdecl}
template<@\exposconcept{scalar}@ Scalar, @\exposconcept{in-vector}@ InVec, @\exposconcept{in-matrix}@ InMat, @\exposconcept{possibly-packed-out-matrix}@ OutMat,
         class Triangle>
  void symmetric_matrix_rank_1_update(Scalar alpha, InVec x, InMat E, OutMat A, Triangle t);
template<class ExecutionPolicy, @\exposconcept{scalar}@ Scalar, @\exposconcept{in-vector}@ InVec, @\exposconcept{in-matrix}@ InMat,
         @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle>
  void symmetric_matrix_rank_1_update(ExecutionPolicy&& exec,
                                      Scalar alpha, InVec x, InMat E, OutMat A, Triangle t);
\end{itemdecl}

\begin{itemdescr}
\pnum
These functions perform
an updating symmetric rank-1 update of the symmetric matrix \tcode{A}
using the symmetric matrix \tcode{E},
taking into account the \tcode{Triangle} parameter
that applies to \tcode{A} and \tcode{E}\iref{linalg.general}.

\pnum
\effects
Computes $A = E + \alpha x x^T$,
where the scalar $\alpha$ is \tcode{alpha}.

\pnum
\remarks
\tcode{A} may alias \tcode{E}.
\end{itemdescr}

\indexlibraryglobal{hermitian_matrix_rank_1_update}%
\begin{itemdecl}
template<@\exposconcept{scalar}@ Scalar, @\exposconcept{in-vector}@ InVec, @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle>
  void hermitian_matrix_rank_1_update(Scalar alpha, InVec x, OutMat A, Triangle t);
template<class ExecutionPolicy,
         @\exposconcept{scalar}@ Scalar, @\exposconcept{in-vector}@ InVec, @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle>
  void hermitian_matrix_rank_1_update(ExecutionPolicy&& exec,
                                      Scalar alpha, InVec x, OutMat A, Triangle t);
\end{itemdecl}

\begin{itemdescr}
\pnum
These functions perform
an overwriting Hermitian rank-1 update of the Hermitian matrix \tcode{A},
taking into account the \tcode{Triangle} parameter
that applies to \tcode{A}\iref{linalg.general}.

\pnum
\effects
Computes $A = \alpha x x^H$,
where the scalar $\alpha$ is \tcode{\exposid{real-if-needed}(alpha)}.
\end{itemdescr}

\indexlibraryglobal{hermitian_matrix_rank_1_update}%
\begin{itemdecl}
template<@\exposconcept{scalar}@ Scalar, @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle>
  void hermitian_matrix_rank_1_update(InVec x, OutMat A, Triangle t);
template<class ExecutionPolicy,
         @\exposconcept{scalar}@ Scalar, @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle>
  void hermitian_matrix_rank_1_update(ExecutionPolicy&& exec, InVec x, OutMat A, Triangle t);
\end{itemdecl}

\begin{itemdescr}
\pnum
These functions perform
an updating Hermitian rank-1 update of the Hermitian matrix \tcode{A}
using the Hermitian matrix \tcode{E},
taking into account the \tcode{Triangle} parameter
that applies to \tcode{A} and \tcode{E}\iref{linalg.general}.

\pnum
\effects
Computes $A = E + \alpha x x^H$,
where the scalar $\alpha$ is \tcode{\exposid{real-if-needed}(alpha)}.

\pnum
\remarks
\tcode{A} may alias \tcode{E}.
\end{itemdescr}

\rSec3[linalg.algs.blas2.rank2]{Symmetric and Hermitian rank-2 matrix updates}

\pnum
\begin{note}
These functions correspond to the BLAS functions
\tcode{xSYR2}, \tcode{xSPR2}, \tcode{xHER2} and \tcode{xHPR2}\supercite{blas2}.
\end{note}

\pnum
The following elements apply to all functions in \ref{linalg.algs.blas2.rank2}.

\pnum
For any function \tcode{F} in this subclause with
a parameter named \tcode{t},
an \tcode{InMat} template parameter, and
a function parameter \tcode{InMat E},
\tcode{t} applies to accesses done through the parameter \tcode{E}.
\tcode{F} only accesses the triangle of \tcode{E} specified by \tcode{t}.
For accesses of diagonal elements \tcode{E[i, i]},
\tcode{F} only uses the value \tcode{\exposid{real-if-needed}(E[i, i])}
if the name of \tcode{F} starts with \tcode{hermitian}.
For accesses \tcode{E[i, j]} outside the triangle specified by \tcode{t},
\tcode{F} only uses the value
\begin{itemize}
\item
\tcode{\exposid{conj-if-needed}(E[j, i])}
if the name of \tcode{F} starts with \tcode{hermitian}, or
\item
\tcode{E[j, i]}
if the name of \tcode{F} starts with \tcode{symmetric}.
\end{itemize}

\pnum
\mandates
\begin{itemize}
\item
If \tcode{OutMat} has \tcode{layout_blas_packed} layout,
then the layout's \tcode{Triangle} template argument has
the same type as the function's \tcode{Triangle} template argument;
\item
If the function has an \tcode{InMat} template parameter and
\tcode{InMat} has \tcode{layout_blas_packed} layout,
then the layout's \tcode{Triangle} template argument has
the same type as the function's \tcode{Triangle} template argument;
\item
\tcode{\exposid{compatible-static-extents}<decltype(A), decltype(A)>(0, 1)}
is \tcode{true};
\item
\tcode{\exposid{possibly-multipliable}<decltype(A), decltype(x), decltype(y)>()}
is \tcode{true}; and
\item
\tcode{\exposid{possibly-addable}<decltype(A), decltype(E), decltype(A)>()}
is \tcode{true} for those overloads with an \tcode{E} parameter.
\end{itemize}

\pnum
\expects
\begin{itemize}
\item
\tcode{A.extent(0)} equals \tcode{A.extent(1)},
\item
\tcode{\exposid{multipliable}(A, x, y)} is \tcode{true}, and
\item
\tcode{\exposid{addable}(A, E, A)} is \tcode{true}
for those overloads with an \tcode{E} parameter.
\end{itemize}

\pnum
\complexity
\bigoh{\tcode{x.extent(0)} \times \tcode{y.extent(0)}}.

\indexlibraryglobal{symmetric_matrix_rank_2_update}%
\begin{itemdecl}
template<@\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2,
         @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle>
  void symmetric_matrix_rank_2_update(InVec1 x, InVec2 y, OutMat A, Triangle t);
template<class ExecutionPolicy, @\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2,
         @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle>
  void symmetric_matrix_rank_2_update(ExecutionPolicy&& exec,
                                      InVec1 x, InVec2 y, OutMat A, Triangle t);
\end{itemdecl}

\begin{itemdescr}
\pnum
These functions perform
an overwriting symmetric rank-2 update of the symmetric matrix \tcode{A},
taking into account the \tcode{Triangle} parameter
that applies to \tcode{A}\iref{linalg.general}.

\pnum
\effects
Computes $A = x y^T + y x^T$.
\end{itemdescr}

\indexlibraryglobal{symmetric_matrix_rank_2_update}%
\begin{itemdecl}
template<@\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, @\exposconcept{in-matrix}@ InMat,
         @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle>
  void symmetric_matrix_rank_2_update(InVec1 x, InVec2 y, InMat E, OutMat A, Triangle t);
template<class ExecutionPolicy, @\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, @\exposconcept{in-matrix}@ InMat,
         @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle>
  void symmetric_matrix_rank_2_update(ExecutionPolicy&& exec,
                                      InVec1 x, InVec2 y, InMat E, OutMat A, Triangle t);
\end{itemdecl}

\begin{itemdescr}
\pnum
These functions perform
an updating symmetric rank-2 update of the symmetric matrix \tcode{A}
using the symmetric matrix \tcode{E},
taking into account the \tcode{Triangle} parameter
that applies to \tcode{A} and \tcode{E}\iref{linalg.general}.

\pnum
\effects
Computes $A = E + x y^T + y x^T$.

\pnum
\remarks
\tcode{A} may alias \tcode{E}.
\end{itemdescr}

\indexlibraryglobal{hermitian_matrix_rank_2_update}%
\begin{itemdecl}
template<@\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2,
         @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle>
  void hermitian_matrix_rank_2_update(InVec1 x, InVec2 y, OutMat A, Triangle t);
template<class ExecutionPolicy, @\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2,
         @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle>
  void hermitian_matrix_rank_2_update(ExecutionPolicy&& exec,
                                      InVec1 x, InVec2 y, OutMat A, Triangle t);
\end{itemdecl}

\begin{itemdescr}
\pnum
These functions perform
an overwriting Hermitian rank-2 update of the Hermitian matrix \tcode{A},
taking into account the \tcode{Triangle} parameter
that applies to \tcode{A}\iref{linalg.general}.

\pnum
\effects
Computes $A = x y^H + y x^H$.
\end{itemdescr}

\indexlibraryglobal{hermitian_matrix_rank_2_update}%
\begin{itemdecl}
template<@\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, @\exposconcept{in-matrix}@ InMat,
         @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle>
  void hermitian_matrix_rank_2_update(InVec1 x, InVec2 y, InMat E, OutMat A, Triangle t);
template<class ExecutionPolicy, @\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, @\exposconcept{in-matrix}@ InMat,
         @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle>
  void hermitian_matrix_rank_2_update(ExecutionPolicy&& exec,
                                      InVec1 x, InVec2 y, InMat E, OutMat A, Triangle t);
\end{itemdecl}

\begin{itemdescr}
\pnum
These functions perform
an updating Hermitian rank-2 update of the Hermitian matrix \tcode{A}
using the Hermitian matrix \tcode{E},
taking into account the \tcode{Triangle} parameter
that applies to \tcode{A} and \tcode{E}\iref{linalg.general}.

\pnum
\effects
Computes $A = E + x y^H + y x^H$.

\pnum
\remarks
\tcode{A} may alias \tcode{E}.
\end{itemdescr}

\rSec2[linalg.algs.blas3]{BLAS 3 algorithms}

\rSec3[linalg.algs.blas3.gemm]{General matrix-matrix product}

\pnum
\begin{note}
These functions correspond to the BLAS function \tcode{xGEMM}\supercite{blas3}.
\end{note}

\pnum
The following elements apply
to all functions in \ref{linalg.algs.blas3.gemm}
in addition to function-specific elements.

\pnum
\mandates
\tcode{\exposid{possibly-multipliable}<decltype(A), decltype(B), decltype(C)>()}
is \tcode{true}.

\pnum
\expects
\tcode{\exposid{multipliable}(A, B, C)} is \tcode{true}.

\pnum
\complexity
\bigoh{\tcode{A.extent(0)} \times \tcode{A.extent(1)} \times \tcode{B.extent(1)}}.

\indexlibraryglobal{matrix_product}%
\begin{itemdecl}
  template<@\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, @\exposconcept{out-matrix}@ OutMat>
    void matrix_product(InMat1 A, InMat2 B, OutMat C);
  template<class ExecutionPolicy, @\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, @\exposconcept{out-matrix}@ OutMat>
    void matrix_product(ExecutionPolicy&& exec, InMat1 A, InMat2 B, OutMat C);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Computes $C = A B$.
\end{itemdescr}

\indexlibraryglobal{matrix_product}%
\begin{itemdecl}
template<@\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, @\exposconcept{in-matrix}@ InMat3, @\exposconcept{out-matrix}@ OutMat>
  void matrix_product(InMat1 A, InMat2 B, InMat3 E, OutMat C);
template<class ExecutionPolicy,
         @\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, @\exposconcept{in-matrix}@ InMat3, @\exposconcept{out-matrix}@ OutMat>
  void matrix_product(ExecutionPolicy&& exec, InMat1 A, InMat2 B, InMat3 E, OutMat C);
\end{itemdecl}

\begin{itemdescr}
\pnum
\mandates
\tcode{\exposid{possibly-addable}<InMat3, InMat3, OutMat>()} is \tcode{true}.

\pnum
\expects
\tcode{\exposid{addable}(E, E, C)} is \tcode{true}.

\pnum
\effects
Computes $C = E + A B$.

\pnum
\remarks
\tcode{C} may alias \tcode{E}.
\end{itemdescr}

\rSec3[linalg.algs.blas3.xxmm]{Symmetric, Hermitian, and triangular matrix-matrix product}

\pnum
\begin{note}
These functions correspond to the BLAS functions
\tcode{xSYMM}, \tcode{xHEMM}, and \tcode{xTRMM}\supercite{blas3}.
\end{note}

\pnum
The following elements apply to all functions in \ref{linalg.algs.blas3.xxmm}
in addition to function-specific elements.

\pnum
\mandates
\begin{itemize}
\item
\tcode{\exposid{possibly-multipliable}<decltype(A), decltype(B), decltype(C)>()}
is \tcode{true}, and
\item
\tcode{\exposid{possibly-addable}<decltype(E), decltype(E), decltype(C)>()}
is \tcode{true} for those overloads that take an \tcode{E} parameter.
\end{itemize}

\pnum
\expects
\begin{itemize}
\item
\tcode{\exposid{multipliable}(A, B, C)} is \tcode{true}, and
\item
\tcode{\exposid{addable}(E, E, C)}
is \tcode{true} for those overloads that take an \tcode{E} parameter.
\end{itemize}

\pnum
\complexity
\bigoh{\tcode{A.extent(0)} \times \tcode{A.extent(1)} \times \tcode{B.extent(1)}}.

\indexlibraryglobal{symmetric_matrix_product}%
\begin{itemdecl}
template<@\exposconcept{in-matrix}@ InMat1, class Triangle, @\exposconcept{in-matrix}@ InMat2, @\exposconcept{out-matrix}@ OutMat>
  void symmetric_matrix_product(InMat1 A, Triangle t, InMat2 B, OutMat C);
template<class ExecutionPolicy,
         @\exposconcept{in-matrix}@ InMat1, class Triangle, @\exposconcept{in-matrix}@ InMat2, @\exposconcept{out-matrix}@ OutMat>
  void symmetric_matrix_product(ExecutionPolicy&& exec, InMat1 A, Triangle t, InMat2 B, OutMat C);

template<@\exposconcept{in-matrix}@ InMat1, class Triangle, @\exposconcept{in-matrix}@ InMat2, @\exposconcept{out-matrix}@ OutMat>
  void hermitian_matrix_product(InMat1 A, Triangle t, InMat2 B, OutMat C);
template<class ExecutionPolicy,
         @\exposconcept{in-matrix}@ InMat1, class Triangle, @\exposconcept{in-matrix}@ InMat2, @\exposconcept{out-matrix}@ OutMat>
  void hermitian_matrix_product(ExecutionPolicy&& exec, InMat1 A, Triangle t, InMat2 B, OutMat C);

template<@\exposconcept{in-matrix}@ InMat1, class Triangle, class DiagonalStorage,
         @\exposconcept{in-matrix}@ InMat2, @\exposconcept{out-matrix}@ OutMat>
  void triangular_matrix_product(InMat1 A, Triangle t, DiagonalStorage d, InMat2 B, OutMat C);
template<class ExecutionPolicy, @\exposconcept{in-matrix}@ InMat1, class Triangle, class DiagonalStorage,
         @\exposconcept{in-matrix}@ InMat2, @\exposconcept{out-matrix}@ OutMat>
  void triangular_matrix_product(ExecutionPolicy&& exec,
                                 InMat1 A, Triangle t, DiagonalStorage d, InMat2 B, OutMat C);
\end{itemdecl}

\begin{itemdescr}
\pnum
These functions perform a matrix-matrix multiply,
taking into account
the \tcode{Triangle} and \tcode{Diagonal\-Storage} (if applicable) parameters
that apply to the symmetric, Hermitian, or triangular (respectively) matrix \tcode{A}\iref{linalg.general}.

\pnum
\mandates
\begin{itemize}
\item
If \tcode{InMat1} has \tcode{layout_blas_packed} layout,
then the layout's \tcode{Triangle} template argument has
the same type as the function's \tcode{Triangle} template argument; and
\item
\tcode{\exposid{compatible-static-extents}<InMat1, InMat1>(0, 1)} is \tcode{true}.
\end{itemize}

\pnum
\expects
\tcode{A.extent(0) == A.extent(1)} is \tcode{true}.

\pnum
\effects
Computes $C = A B$.
\end{itemdescr}

\indexlibraryglobal{symmetric_matrix_product}%
\begin{itemdecl}
  template<@\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, class Triangle, @\exposconcept{out-matrix}@ OutMat>
    void symmetric_matrix_product(InMat1 A, InMat2 B, Triangle t, OutMat C);
  template<class ExecutionPolicy,
           @\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, class Triangle, @\exposconcept{out-matrix}@ OutMat>
    void symmetric_matrix_product(ExecutionPolicy&& exec,
                                  InMat1 A, InMat2 B, Triangle t, OutMat C);

  template<@\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, class Triangle, @\exposconcept{out-matrix}@ OutMat>
    void hermitian_matrix_product(InMat1 A, InMat2 B, Triangle t, OutMat C);
  template<class ExecutionPolicy,
           @\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, class Triangle, @\exposconcept{out-matrix}@ OutMat>
    void hermitian_matrix_product(ExecutionPolicy&& exec,
                                  InMat1 A, InMat2 B, Triangle t, OutMat C);

  template<@\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, class Triangle, class DiagonalStorage,
           @\exposconcept{out-matrix}@ OutMat>
    void triangular_matrix_product(InMat1 A, InMat2 B, Triangle t, DiagonalStorage d, OutMat C);
  template<class ExecutionPolicy,
           @\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, class Triangle, class DiagonalStorage,
           @\exposconcept{out-matrix}@ OutMat>
    void triangular_matrix_product(ExecutionPolicy&& exec,
                                   InMat1 A, InMat2 B, Triangle t, DiagonalStorage d, OutMat C);
\end{itemdecl}

\begin{itemdescr}
\pnum
These functions perform a matrix-matrix multiply,
taking into account
the \tcode{Triangle} and \tcode{Diagonal\-Storage} (if applicable) parameters
that apply to the symmetric, Hermitian, or triangular (respectively) matrix \tcode{B}\iref{linalg.general}.

\pnum
\mandates
\begin{itemize}
\item
If \tcode{InMat2} has \tcode{layout_blas_packed} layout,
then the layout's \tcode{Triangle} template argument has
the same type as the function's \tcode{Triangle} template argument; and
\item
\tcode{\exposid{compatible-static-extents}<InMat2, InMat2>(0, 1)} is \tcode{true}.
\end{itemize}

\pnum
\expects
\tcode{B.extent(0) == B.extent(1)} is \tcode{true}.

\pnum
\effects
Computes $C = A B$.
\end{itemdescr}

\indexlibraryglobal{symmetric_matrix_product}%
\begin{itemdecl}
template<@\exposconcept{in-matrix}@ InMat1, class Triangle, @\exposconcept{in-matrix}@ InMat2, @\exposconcept{in-matrix}@ InMat3,
         @\exposconcept{out-matrix}@ OutMat>
  void symmetric_matrix_product(InMat1 A, Triangle t, InMat2 B, InMat3 E, OutMat C);
template<class ExecutionPolicy,
         @\exposconcept{in-matrix}@ InMat1, class Triangle, @\exposconcept{in-matrix}@ InMat2, @\exposconcept{in-matrix}@ InMat3,
         @\exposconcept{out-matrix}@ OutMat>
  void symmetric_matrix_product(ExecutionPolicy&& exec,
                                InMat1 A, Triangle t, InMat2 B, InMat3 E, OutMat C);

template<@\exposconcept{in-matrix}@ InMat1, class Triangle, @\exposconcept{in-matrix}@ InMat2, @\exposconcept{in-matrix}@ InMat3,
         @\exposconcept{out-matrix}@ OutMat>
  void hermitian_matrix_product(InMat1 A, Triangle t, InMat2 B, InMat3 E, OutMat C);
template<class ExecutionPolicy,
         @\exposconcept{in-matrix}@ InMat1, class Triangle, @\exposconcept{in-matrix}@ InMat2, @\exposconcept{in-matrix}@ InMat3,
         @\exposconcept{out-matrix}@ OutMat>
  void hermitian_matrix_product(ExecutionPolicy&& exec,
                                InMat1 A, Triangle t, InMat2 B, InMat3 E, OutMat C);

template<@\exposconcept{in-matrix}@ InMat1, class Triangle, class DiagonalStorage,
         @\exposconcept{in-matrix}@ InMat2, @\exposconcept{in-matrix}@ InMat3, @\exposconcept{out-matrix}@ OutMat>
  void triangular_matrix_product(InMat1 A, Triangle t, DiagonalStorage d, InMat2 B, InMat3 E,
                                 OutMat C);
template<class ExecutionPolicy,
         @\exposconcept{in-matrix}@ InMat1, class Triangle, class DiagonalStorage,
         @\exposconcept{in-matrix}@ InMat2, @\exposconcept{in-matrix}@ InMat3, @\exposconcept{out-matrix}@ OutMat>
  void triangular_matrix_product(ExecutionPolicy&& exec,
                                 InMat1 A, Triangle t, DiagonalStorage d, InMat2 B, InMat3 E,
                                 OutMat C);
\end{itemdecl}

\begin{itemdescr}
\pnum
These functions perform
a potentially overwriting matrix-matrix multiply-add,
taking into account the \tcode{Triangle} and \tcode{DiagonalStorage} (if applicable) parameters
that apply to the symmetric, Hermitian, or triangular (respectively) matrix \tcode{A}\iref{linalg.general}.

\pnum
\mandates
\begin{itemize}
\item
If \tcode{InMat1} has \tcode{layout_blas_packed} layout, then the
      layout's \tcode{Triangle} template argument has the same type as
      the function's \tcode{Triangle} template argument; and
\item
\tcode{\exposid{compatible-static-extents}<InMat1, InMat1>(0, 1)} is \tcode{true}.
\end{itemize}

\pnum
\expects
\tcode{A.extent(0) == A.extent(1)} is \tcode{true}.

\pnum
\effects
Computes $C = E + A B$.

\pnum
\remarks
\tcode{C} may alias \tcode{E}.
\end{itemdescr}

\indexlibraryglobal{symmetric_matrix_product}%
\begin{itemdecl}
template<@\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, class Triangle, @\exposconcept{in-matrix}@ InMat3,
         @\exposconcept{out-matrix}@ OutMat>
  void symmetric_matrix_product(InMat1 A, InMat2 B, Triangle t, InMat3 E, OutMat C);
template<class ExecutionPolicy,
         @\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, class Triangle, @\exposconcept{in-matrix}@ InMat3,
         @\exposconcept{out-matrix}@ OutMat>
  void symmetric_matrix_product(ExecutionPolicy&& exec,
                                InMat1 A, InMat2 B, Triangle t, InMat3 E, OutMat C);

template<@\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, class Triangle, @\exposconcept{in-matrix}@ InMat3,
         @\exposconcept{out-matrix}@ OutMat>
  void hermitian_matrix_product(InMat1 A, InMat2 B, Triangle t, InMat3 E, OutMat C);
template<class ExecutionPolicy,
         @\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, class Triangle, @\exposconcept{in-matrix}@ InMat3,
         @\exposconcept{out-matrix}@ OutMat>
  void hermitian_matrix_product(ExecutionPolicy&& exec,
                                InMat1 A, InMat2 B, Triangle t, InMat3 E, OutMat C);

template<@\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, class Triangle, class DiagonalStorage,
         @\exposconcept{in-matrix}@ InMat3, @\exposconcept{out-matrix}@ OutMat>
  void triangular_matrix_product(InMat1 A, InMat2 B, Triangle t, DiagonalStorage d, InMat3 E,
                                 OutMat C);
template<class ExecutionPolicy,
         @\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, class Triangle, class DiagonalStorage,
         @\exposconcept{in-matrix}@ InMat3, @\exposconcept{out-matrix}@ OutMat>
  void triangular_matrix_product(ExecutionPolicy&& exec,
                                 InMat1 A, InMat2 B, Triangle t, DiagonalStorage d, InMat3 E,
                                 OutMat C);
\end{itemdecl}

\begin{itemdescr}
\pnum
These functions perform
a potentially overwriting matrix-matrix multiply-add,
taking into account
the \tcode{Triangle} and \tcode{Diagonal\-Storage} (if applicable) parameters
that apply to the symmetric, Hermitian, or triangular (respectively) matrix \tcode{B}\iref{linalg.general}.

\pnum
\mandates
\begin{itemize}
\item
If \tcode{InMat2} has \tcode{layout_blas_packed} layout,
then the layout's \tcode{Triangle} template argument has
the same type as the function's \tcode{Triangle} template argument; and
\item
\tcode{\exposid{compatible-static-extents}<InMat2, InMat2>(0, 1)} is \tcode{true}.
\end{itemize}

\pnum
\expects
\tcode{B.extent(0) == B.extent(1)} is \tcode{true}.

\pnum
\effects
Computes $C = E + A B$.

\pnum
\remarks
\tcode{C} may alias \tcode{E}.
\end{itemdescr}

\rSec3[linalg.algs.blas3.trmm]{In-place triangular matrix-matrix product}

\pnum
These functions perform
an in-place matrix-matrix multiply,
taking into account
the \tcode{Triangle} and \tcode{Diagonal\-Storage} parameters
that apply to the triangular matrix \tcode{A}\iref{linalg.general}.
\begin{note}
These functions correspond to the BLAS function \tcode{xTRMM}\supercite{blas3}.
\end{note}

\indexlibraryglobal{triangular_matrix_product}%
\begin{itemdecl}
template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, @\exposconcept{inout-matrix}@ InOutMat>
  void triangular_matrix_left_product(InMat A, Triangle t, DiagonalStorage d, InOutMat C);
template<class ExecutionPolicy,
         @\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, @\exposconcept{inout-matrix}@ InOutMat>
  void triangular_matrix_left_product(ExecutionPolicy&& exec,
                                      InMat A, Triangle t, DiagonalStorage d, InOutMat C);
\end{itemdecl}

\begin{itemdescr}
\pnum
\mandates
\begin{itemize}
\item
If \tcode{InMat} has \tcode{layout_blas_packed} layout,
then the layout's \tcode{Triangle} template argument has
the same type as the function's \tcode{Triangle} template argument;
\item
\tcode{\exposid{possibly-multipliable}<InMat, InOutMat, InOutMat>()}
is \tcode{true}; and
\item
\tcode{\exposid{compatible-static-extents}<InMat, InMat>(0, 1)} is \tcode{true}.
\end{itemize}

\pnum
\expects
\begin{itemize}
\item
\tcode{\exposid{multipliable}(A, C, C)} is \tcode{true}, and
\item
\tcode{A.extent(0) == A.extent(1)} is \tcode{true}.
\end{itemize}

\pnum
\effects
Computes a matrix $C'$ such that $C' = A C$ and
assigns each element of $C'$ to the corresponding element of $C$.

\pnum
\complexity
\bigoh{\tcode{A.extent(0)} \times \tcode{A.extent(1)} \times \tcode{C.extent(0)}}.
\end{itemdescr}

\indexlibraryglobal{triangular_matrix_right_product}%
\begin{itemdecl}
template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, @\exposconcept{inout-matrix}@ InOutMat>
  void triangular_matrix_right_product(InMat A, Triangle t, DiagonalStorage d, InOutMat C);
template<class ExecutionPolicy,
         @\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, @\exposconcept{inout-matrix}@ InOutMat>
  void triangular_matrix_right_product(ExecutionPolicy&& exec,
                                       InMat A, Triangle t, DiagonalStorage d, InOutMat C);
\end{itemdecl}

\begin{itemdescr}
\pnum
\mandates
\begin{itemize}
\item
If \tcode{InMat} has \tcode{layout_blas_packed} layout,
then the layout's \tcode{Triangle} template argument has
the same type as the function's \tcode{Triangle} template argument;
\item
\tcode{\exposid{possibly-multipliable}<InOutMat, InMat, InOutMat>()}
is \tcode{true}; and
\item
\tcode{\exposid{compatible-static-extents}<InMat, InMat>(0, 1)} is \tcode{true}.
\end{itemize}

\pnum
\expects
\begin{itemize}
\item
\tcode{\exposid{multipliable}(C, A, C)} is \tcode{true}, and
\item
\tcode{A.extent(0) == A.extent(1)} is \tcode{true}.
\end{itemize}

\pnum
\effects
Computes a matrix $C'$ such that $C' = C A$ and
assigns each element of $C'$ to the corresponding element of $C$.

\pnum
\complexity
\bigoh{\tcode{A.extent(0)} \times \tcode{A.extent(1)} \times \tcode{C.extent(0)}}.
\end{itemdescr}

\rSec3[linalg.algs.blas3.rankk]{Rank-k update of a symmetric or Hermitian matrix}

\pnum
\begin{note}
These functions correspond to the BLAS functions
\tcode{xSYRK} and \tcode{xHERK}\supercite{blas3}.
\end{note}

\pnum
The following elements apply to all functions in \ref{linalg.algs.blas3.rankk}.

\pnum
For any function \tcode{F} in this subclause with
a parameter named \tcode{t},
an \tcode{InMat2} template parameter, and
a function parameter \tcode{InMat2 E},
\tcode{t} applies to accesses done through the parameter \tcode{E}.
\tcode{F} only accesses the triangle of \tcode{E} specified by \tcode{t}.
For accesses of diagonal elements \tcode{E[i, i]},
\tcode{F} only uses the value \tcode{\exposid{real-if-needed}(E[i, i])}
if the name of \tcode{F} starts with \tcode{hermitian}.
For accesses \tcode{E[i, j]} outside the triangle specified by \tcode{t},
\tcode{F} only uses the value
\begin{itemize}
\item
\tcode{\exposid{conj-if-needed}(E[j, i])}
if the name of \tcode{F} starts with \tcode{hermitian}, or
\item
\tcode{E[j, i]}
if the name of \tcode{F} starts with \tcode{symmetric}.
\end{itemize}

\pnum
\mandates
\begin{itemize}
\item
If \tcode{OutMat} has \tcode{layout_blas_packed} layout,
then the layout's \tcode{Triangle} template argument has
the same type as the function's \tcode{Triangle} template argument;
\item
If the function has an \tcode{InMat2} template parameter and
if \tcode{InMat2} has \tcode{layout_blas_packed} layout,
then the layout's \tcode{Triangle} template argument has
the same type as the function's \tcode{Triangle} template argument;
\item
\tcode{\exposid{possibly-multipliable}<decltype(A), decltype(transposed(A)), decltype(C)>()}
is \tcode{true}; and
\item
\tcode{\exposid{possibly-addable}<decltype(C), decltype(E), decltype(C)>()}
is \tcode{true} for those overloads with an \tcode{E} parameter.
\end{itemize}

\pnum
\expects
\begin{itemize}
\item
\tcode{\exposid{multipliable}(A, transposed(A), C)}
is \tcode{true}; and
\begin{note}
This implies that \tcode{C} is square.
\end{note}
\item
\tcode{\exposid{addable}(C, E, C)}
is \tcode{true} for those overloads with an \tcode{E} parameter.
\end{itemize}

\pnum
\complexity
\bigoh{\tcode{A.extent(0)} \times \tcode{A.extent(1)} \times \tcode{A.extent(0)}}.

\pnum
\remarks
\tcode{C} may alias \tcode{E} for those overloads with an \tcode{E} parameter.

\indexlibraryglobal{symmetric_matrix_rank_k_update}%
\begin{itemdecl}
  template<@\exposconcept{scalar}@ Scalar, @\exposconcept{in-matrix}@ InMat, @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle>
    void symmetric_matrix_rank_k_update(Scalar alpha, InMat A, OutMat C, Triangle t);
  template<class ExecutionPolicy, @\exposconcept{scalar}@ Scalar,
           @\exposconcept{in-matrix}@ InMat, @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle>
    void symmetric_matrix_rank_k_update(ExecutionPolicy&& exec,
                                        Scalar alpha, InMat A, OutMat C, Triangle t);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Computes $C = \alpha A A^T$,
where the scalar $\alpha$ is \tcode{alpha}.
\end{itemdescr}

\indexlibraryglobal{hermitian_matrix_rank_k_update}%
\begin{itemdecl}
template<@\exposconcept{scalar}@ Scalar, @\exposconcept{in-matrix}@ InMat, @\exposconcept{possibly-packed-out-matrix}@ OutMat,
         class Triangle>
void hermitian_matrix_rank_k_update(Scalar alpha, InMat A, OutMat C, Triangle t);
template<class ExecutionPolicy, @\exposconcept{scalar}@ Scalar, @\exposconcept{in-matrix}@ InMat,
         @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle>
void hermitian_matrix_rank_k_update(ExecutionPolicy&& exec, Scalar alpha, InMat A,
                                    OutMat C, Triangle t);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Computes $C = \alpha A A^H$,
where the scalar $\alpha$ is \tcode{\exposid{real-if-needed}(alpha)}.
\end{itemdescr}

\indexlibraryglobal{symmetric_matrix_rank_k_update}%
\begin{itemdecl}
template<@\exposconcept{scalar}@ Scalar, @\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, @\exposconcept{possibly-packed-out-matrix}@ OutMat,
         class Triangle>
void symmetric_matrix_rank_k_update(Scalar alpha, InMat1 A, InMat2 E, OutMat C, Triangle t);
template<class ExecutionPolicy, @\exposconcept{scalar}@ Scalar, @\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2,
         @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle>
void symmetric_matrix_rank_k_update(ExecutionPolicy&& exec, Scalar alpha, InMat1 A, InMat2 E,
                                    OutMat C, Triangle t);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Computes $C = E + \alpha A A^T$,
where the scalar $\alpha$ is \tcode{alpha}.
\end{itemdescr}

\indexlibraryglobal{hermitian_matrix_rank_k_update}%
\begin{itemdecl}
template<@\exposconcept{scalar}@ Scalar, @\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, @\exposconcept{possibly-packed-out-matrix}@ OutMat,
         class Triangle>
void hermitian_matrix_rank_k_update(Scalar alpha, InMat1 A, InMat2 E, OutMat C, Triangle t);
template<class ExecutionPolicy, @\exposconcept{scalar}@ Scalar, @\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2,
         @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle>
void hermitian_matrix_rank_k_update(ExecutionPolicy&& exec, Scalar alpha, InMat1 A, InMat2 E,
                                    OutMat C, Triangle t);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Computes $C = E + \alpha A A^H$,
where the scalar $\alpha$ is \tcode{\exposid{real-if-needed}(alpha)}.
\end{itemdescr}

\rSec3[linalg.algs.blas3.rank2k]{Rank-2k update of a symmetric or Hermitian matrix}

\pnum
\begin{note}
These functions correspond to the BLAS functions
\tcode{xSYR2K} and \tcode{xHER2K}\supercite{blas3}.
\end{note}

\pnum
The following elements apply to all functions in \ref{linalg.algs.blas3.rank2k}.

\pnum
For any function \tcode{F} in this subclause with
a parameter named \tcode{t},
an \tcode{InMat3} template parameter, and
a function parameter \tcode{InMat3 E},
\tcode{t} applies to accesses done through the parameter \tcode{E}.
\tcode{F} only accesses the triangle of \tcode{E} specified by \tcode{t}.
For accesses of diagonal elements \tcode{E[i, i]},
\tcode{F} only uses the value \tcode{\exposid{real-if-needed}(E[i, i])}
if the name of \tcode{F} starts with \tcode{hermitian}.
For accesses \tcode{E[i, j]} outside the triangle specified by \tcode{t},
\tcode{F} only uses the value
\begin{itemize}
\item
\tcode{\exposid{conj-if-needed}(E[j, i])}
if the name of \tcode{F} starts with \tcode{hermitian}, or
\item
\tcode{E[j, i]}
if the name of \tcode{F} starts with \tcode{symmetric}.
\end{itemize}

\pnum
\mandates
\begin{itemize}
\item
If \tcode{OutMat} has \tcode{layout_blas_packed} layout,
then the layout's \tcode{Triangle} template argument has
the same type as the function's \tcode{Triangle} template argument;
\item
If the function has an \tcode{InMat3} template parameter and
if \tcode{InMat3} has \tcode{layout_blas_packed} layout,
then the layout's \tcode{Triangle} template argument has
the same type as the function's \tcode{Triangle} template argument;
\item
\tcode{\exposid{possibly-multipliable}<decltype(A), decltype(transposed(B)), decltype(C)>()}
is \tcode{true};
\item
\tcode{\exposid{possibly-multipliable}<decltype(B), decltype(transposed(A)), decltype(C)>()}
is \tcode{true}; and
\item
\tcode{\exposid{possibly-addable}<decltype(C), decltype(E), decltype(C)>()}
is \tcode{true} for those overloads with an \tcode{E} parameter.
\end{itemize}

\pnum
\expects
\begin{itemize}
\item
\tcode{\exposid{multipliable}(A, transposed(B), C)}
is \tcode{true},
\item
\tcode{\exposid{multipliable}(B, transposed(A), C)}
is \tcode{true}, and
\begin{note}
This and the previous imply that \tcode{C} is square.
\end{note}
\item
\tcode{\exposid{addable}(C, E, C)}
is \tcode{true} for those overloads with an \tcode{E} parameter.
\end{itemize}

\pnum
\complexity
\bigoh{\tcode{A.extent(0)} \times \tcode{A.extent(1)} \times \tcode{B.extent(0)}}.

\pnum
\remarks
\tcode{C} may alias \tcode{E} for those overloads with an \tcode{E} parameter.

\indexlibraryglobal{symmetric_matrix_rank_2k_update}%
\begin{itemdecl}
template<@\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2,
         @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle>
  void symmetric_matrix_rank_2k_update(InMat1 A, InMat2 B, OutMat C, Triangle t);
template<class ExecutionPolicy, @\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2,
         @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle>
  void symmetric_matrix_rank_2k_update(ExecutionPolicy&& exec,
                                       InMat1 A, InMat2 B, OutMat C, Triangle t);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Computes $C = A B^T + B A^T$.
\end{itemdescr}

\indexlibraryglobal{hermitian_matrix_rank_2k_update}%
\begin{itemdecl}
template<@\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2,
         @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle>
  void hermitian_matrix_rank_2k_update(InMat1 A, InMat2 B, OutMat C, Triangle t);
template<class ExecutionPolicy,
         @\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2,
         @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle>
  void hermitian_matrix_rank_2k_update(ExecutionPolicy&& exec,
                                       InMat1 A, InMat2 B, OutMat C, Triangle t);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Computes $C = A B^H + B A^H$.
\end{itemdescr}

\indexlibraryglobal{symmetric_matrix_rank_2k_update}%
\begin{itemdecl}
template<@\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, @\exposconcept{in-matrix}@ InMat3,
         @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle>
void symmetric_matrix_rank_2k_update(InMat1 A, InMat2 B, InMat3 E, OutMat C, Triangle t);
template<class ExecutionPolicy, @\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, @\exposconcept{in-matrix}@ InMat3,
         @\exposconcept{possibly-packed-out-matrix}@ OutMat, class Triangle>
void symmetric_matrix_rank_2k_update(ExecutionPolicy&& exec,
                                     InMat1 A, InMat2 B, InMat3 E, OutMat C, Triangle t);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Computes $C = E + A B^T + B A^T$.
\end{itemdescr}

\indexlibraryglobal{hermitian_matrix_rank_2k_update}%
\begin{itemdecl}
template<@\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, @\exposconcept{in-matrix}@ InMat3, @\exposconcept{possibly-packed-out-matrix}@ OutMat,
         class Triangle>
void hermitian_matrix_rank_2k_update(InMat1 A, InMat2 B, InMat3 E, OutMat C, Triangle t);
template<class ExecutionPolicy, @\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, @\exposconcept{in-matrix}@ InMat3,
         @\exposconcept{possibly-packed-out-matrix}@ OutMat,
         class Triangle>
void hermitian_matrix_rank_2k_update(ExecutionPolicy&& exec, InMat1 A, InMat2 B, InMat3 E,
                                     OutMat C, Triangle t);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Computes $C = E + A B^H + B A^H$.
\end{itemdescr}

\rSec3[linalg.algs.blas3.trsm]{Solve multiple triangular linear systems}

\pnum
\begin{note}
These functions correspond to the BLAS function \tcode{xTRSM}\supercite{blas3}.
\end{note}

\indexlibraryglobal{triangular_matrix_matrix_left_solve}%
\begin{itemdecl}
template<@\exposconcept{in-matrix}@ InMat1, class Triangle, class DiagonalStorage,
         @\exposconcept{in-matrix}@ InMat2, @\exposconcept{out-matrix}@ OutMat, class BinaryDivideOp>
  void triangular_matrix_matrix_left_solve(InMat1 A, Triangle t, DiagonalStorage d,
                                           InMat2 B, OutMat X, BinaryDivideOp divide);
template<class ExecutionPolicy,
         @\exposconcept{in-matrix}@ InMat1, class Triangle, class DiagonalStorage,
         @\exposconcept{in-matrix}@ InMat2, @\exposconcept{out-matrix}@ OutMat, class BinaryDivideOp>
  void triangular_matrix_matrix_left_solve(ExecutionPolicy&& exec,
                                           InMat1 A, Triangle t, DiagonalStorage d,
                                           InMat2 B, OutMat X, BinaryDivideOp divide);
\end{itemdecl}

\begin{itemdescr}
\pnum
These functions perform multiple matrix solves,
taking into account the \tcode{Triangle} and \tcode{DiagonalStorage} parameters
that apply to the triangular matrix \tcode{A}\iref{linalg.general}.

\pnum
\mandates
\begin{itemize}
\item
If \tcode{InMat1} has \tcode{layout_blas_packed} layout, then the
      layout's \tcode{Triangle} template argument has the same type as
      the function's \tcode{Triangle} template argument;
\item
\tcode{\exposid{possibly-multipliable}<InMat1, OutMat, InMat2>()}
is \tcode{true}; and
\item
\tcode{\exposid{compatible-static-extents}<InMat1, InMat1>(0, 1)}
is \tcode{true}.
\end{itemize}

\pnum
\expects
\begin{itemize}
\item
\tcode{\exposid{multipliable}(A, X, B)} is \tcode{true}, and
\item
\tcode{A.extent(0) == A.extent(1)} is \tcode{true}.
\end{itemize}

\pnum
\effects
Computes $X'$ such that $AX' = B$,
and assigns each element of $X'$ to the corresponding element of $X$.
If no such $X'$ exists,
then the elements of \tcode{X} are valid but unspecified.

\pnum
\complexity
\bigoh{\tcode{A.extent(0)} \times \tcode{B.extent(1)} \times \tcode{B.extent(1)}}.
\end{itemdescr}

\pnum
\begin{note}
Since the triangular matrix is on the left,
the desired \tcode{divide} implementation
in the case of noncommutative multiplication
is mathematically equivalent to $y^{-1} x$,
where $x$ is the first argument and $y$ is the second argument,
and $y^{-1}$ denotes the multiplicative inverse of $y$.
\end{note}

\indexlibraryglobal{triangular_matrix_matrix_left_solve}%
\begin{itemdecl}
template<@\exposconcept{in-matrix}@ InMat1, class Triangle, class DiagonalStorage,
         @\exposconcept{in-matrix}@ InMat2, @\exposconcept{out-matrix}@ OutMat>
  void triangular_matrix_matrix_left_solve(InMat1 A, Triangle t, DiagonalStorage d,
                                           InMat2 B, OutMat X);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
triangular_matrix_matrix_left_solve(A, t, d, B, X, divides<void>{});
\end{codeblock}
\end{itemdescr}

\indexlibraryglobal{triangular_matrix_matrix_left_solve}%
\begin{itemdecl}
template<class ExecutionPolicy, @\exposconcept{in-matrix}@ InMat1, class Triangle, class DiagonalStorage,
         @\exposconcept{in-matrix}@ InMat2, @\exposconcept{out-matrix}@ OutMat>
  void triangular_matrix_matrix_left_solve(ExecutionPolicy&& exec,
                                           InMat1 A, Triangle t, DiagonalStorage d,
                                           InMat2 B, OutMat X);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
triangular_matrix_matrix_left_solve(std::forward<ExecutionPolicy>(exec),
                                    A, t, d, B, X, divides<void>{});
\end{codeblock}
\end{itemdescr}

\indexlibraryglobal{triangular_matrix_matrix_right_solve}%
\begin{itemdecl}
template<@\exposconcept{in-matrix}@ InMat1, class Triangle, class DiagonalStorage,
         @\exposconcept{in-matrix}@ InMat2, @\exposconcept{out-matrix}@ OutMat, class BinaryDivideOp>
  void triangular_matrix_matrix_right_solve(InMat1 A, Triangle t, DiagonalStorage d,
                                            InMat2 B, OutMat X, BinaryDivideOp divide);
template<class ExecutionPolicy,
         @\exposconcept{in-matrix}@ InMat1, class Triangle, class DiagonalStorage,
         @\exposconcept{in-matrix}@ InMat2, @\exposconcept{out-matrix}@ OutMat, class BinaryDivideOp>
  void triangular_matrix_matrix_right_solve(ExecutionPolicy&& exec,
                                            InMat1 A, Triangle t, DiagonalStorage d,
                                            InMat2 B, OutMat X, BinaryDivideOp divide);
\end{itemdecl}

\begin{itemdescr}

\pnum
These functions perform multiple matrix solves,
taking into account the \tcode{Triangle} and \tcode{DiagonalStorage} parameters
that apply to the triangular matrix \tcode{A}\iref{linalg.general}.

\pnum
\mandates
\begin{itemize}
\item
If \tcode{InMat1} has \tcode{layout_blas_packed} layout,
then the layout's \tcode{Triangle} template argument has
the same type as the function's \tcode{Triangle} template argument;
\item
\tcode{\exposid{possibly-multipliable}<OutMat, InMat1, InMat2>()} is \tcode{true}; and
\item
\tcode{\exposid{compatible-static-extents}<InMat1, InMat1>(0,1)} is \tcode{true}.
\end{itemize}

\pnum
\expects
\begin{itemize}
\item
\tcode{\exposid{multipliable}(X, A, B)} is \tcode{true}, and
\item
\tcode{A.extent(0) == A.extent(1)} is \tcode{true}.
\end{itemize}

\pnum
\effects
Computes $X'$ such that $X'A = B$,
and assigns each element of $X'$ to the corresponding element of $X$.
If no such $X'$ exists,
then the elements of \tcode{X} are valid but unspecified.

\pnum
\complexity
$O($ \tcode{B.extent(0)} $\cdot$ \tcode{B.extent(1)} $\cdot$ \tcode{A.extent(1)} $)$
\begin{note}
Since the triangular matrix is on the right,
the desired \tcode{divide} implementation
in the case of noncommutative multiplication
is mathematically equivalent to $x y^{-1}$,
where $x$ is the first argument and $y$ is the second argument,
and $y^{-1}$ denotes the multiplicative inverse of $y$.
\end{note}
\end{itemdescr}

\indexlibraryglobal{triangular_matrix_matrix_right_solve}%
\begin{itemdecl}
template<@\exposconcept{in-matrix}@ InMat1, class Triangle, class DiagonalStorage,
         @\exposconcept{in-matrix}@ InMat2, @\exposconcept{out-matrix}@ OutMat>
  void triangular_matrix_matrix_right_solve(InMat1 A, Triangle t, DiagonalStorage d,
                                            InMat2 B, OutMat X);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
triangular_matrix_matrix_right_solve(A, t, d, B, X, divides<void>{});
\end{codeblock}
\end{itemdescr}

\indexlibraryglobal{triangular_matrix_matrix_right_solve}%
\begin{itemdecl}
template<class ExecutionPolicy, @\exposconcept{in-matrix}@ InMat1, class Triangle, class DiagonalStorage,
         @\exposconcept{in-matrix}@ InMat2, @\exposconcept{out-matrix}@ OutMat>
  void triangular_matrix_matrix_right_solve(ExecutionPolicy&& exec,
                                            InMat1 A, Triangle t, DiagonalStorage d,
                                            InMat2 B, OutMat X);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
triangular_matrix_matrix_right_solve(std::forward<ExecutionPolicy>(exec),
                                     A, t, d, B, X, divides<void>{});
\end{codeblock}
\end{itemdescr}

\rSec3[linalg.algs.blas3.inplacetrsm]{Solve multiple triangular linear systems in-place}

\pnum
\begin{note}
These functions correspond to the BLAS function \tcode{xTRSM}\supercite{blas3}.
\end{note}

\indexlibraryglobal{triangular_matrix_matrix_left_solve}%
\begin{itemdecl}
template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage,
         @\exposconcept{inout-matrix}@ InOutMat, class BinaryDivideOp>
  void triangular_matrix_matrix_left_solve(InMat A, Triangle t, DiagonalStorage d,
                                           InOutMat B, BinaryDivideOp divide);
template<class ExecutionPolicy, @\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage,
         @\exposconcept{inout-matrix}@ InOutMat, class BinaryDivideOp>
  void triangular_matrix_matrix_left_solve(ExecutionPolicy&& exec,
                                           InMat A, Triangle t, DiagonalStorage d,
                                           InOutMat B, BinaryDivideOp divide);
\end{itemdecl}

\begin{itemdescr}
\pnum
These functions perform multiple in-place matrix solves,
taking into account the \tcode{Triangle} and \tcode{DiagonalStorage} parameters
that apply to the triangular matrix \tcode{A}\iref{linalg.general}.
\begin{note}
This algorithm makes it possible
to compute factorizations like Cholesky and LU in place.
Performing triangular solve in place hinders parallelization.
However, other \tcode{ExecutionPolicy} specific optimizations,
such as vectorization, are still possible.
\end{note}

\pnum
\mandates
\begin{itemize}
\item
If \tcode{InMat} has \tcode{layout_blas_packed} layout,
then the layout's \tcode{Triangle} template argument has
the same type as the function's \tcode{Triangle} template argument;
\item
\tcode{\exposid{possibly-multipliable}<InMat, InOutMat, InOutMat>()}
is \tcode{true}; and
\item
\tcode{\exposid{compatible-static-extents}<InMat, InMat>(0, 1)}
is \tcode{true}.
\end{itemize}

\pnum
\expects
\begin{itemize}
\item
\tcode{\exposid{multipliable}(A, B, B)} is \tcode{true}, and
\item
\tcode{A.extent(0) == A.extent(1)} is \tcode{true}.
\end{itemize}

\pnum
\effects
Computes $X'$ such that $AX' = B$,
and assigns each element of $X'$ to the corresponding element of $B$.
If so such $X'$ exists,
then the elements of \tcode{B} are valid but unspecified.

\pnum
\complexity
\bigoh{\tcode{B.extent(0)} \times \tcode{A.extent(0)} \times \tcode{A.extent(1)}}.
\end{itemdescr}

\indexlibraryglobal{triangular_matrix_matrix_left_solve}%
\begin{itemdecl}
template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, @\exposconcept{inout-matrix}@ InOutMat>
  void triangular_matrix_matrix_left_solve(InMat A, Triangle t, DiagonalStorage d,
                                           InOutMat B);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
triangular_matrix_matrix_left_solve(A, t, d, B, divides<void>{});
\end{codeblock}
\end{itemdescr}

\indexlibraryglobal{triangular_matrix_matrix_left_solve}%
\begin{itemdecl}
  template<class ExecutionPolicy,
           @\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, @\exposconcept{inout-matrix}@ InOutMat>
    void triangular_matrix_matrix_left_solve(ExecutionPolicy&& exec,
                                             InMat A, Triangle t, DiagonalStorage d,
                                             InOutMat B);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
triangular_matrix_matrix_left_solve(std::forward<ExecutionPolicy>(exec),
                                    A, t, d, B, divides<void>{});
\end{codeblock}
\end{itemdescr}

\indexlibraryglobal{triangular_matrix_matrix_right_solve}%
\begin{itemdecl}
template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage,
         @\exposconcept{inout-matrix}@ InOutMat, class BinaryDivideOp>
  void triangular_matrix_matrix_right_solve(InMat A, Triangle t, DiagonalStorage d,
                                            InOutMat B, BinaryDivideOp divide);
template<class ExecutionPolicy, @\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage,
         @\exposconcept{inout-matrix}@ InOutMat, class BinaryDivideOp>
  void triangular_matrix_matrix_right_solve(ExecutionPolicy&& exec,
                                            InMat A, Triangle t, DiagonalStorage d,
                                            InOutMat B, BinaryDivideOp divide);
\end{itemdecl}

\begin{itemdescr}
\pnum
These functions perform multiple in-place matrix solves,
taking into account the \tcode{Triangle} and \tcode{DiagonalStorage} parameters
that apply to the triangular matrix \tcode{A}\iref{linalg.general}.
\begin{note}
This algorithm makes it possible
to compute factorizations like Cholesky and LU in place.
Performing triangular solve in place hinders parallelization.
However, other \tcode{ExecutionPolicy} specific optimizations,
such as vectorization, are still possible.
\end{note}

\pnum
\mandates
\begin{itemize}
\item
If \tcode{InMat} has \tcode{layout_blas_packed} layout,
then the layout's \tcode{Triangle} template argument has
the same type as the function's \tcode{Triangle} template argument;
\item
\tcode{\exposid{possibly-multipliable}<InOutMat, InMat, InOutMat>()}
is \tcode{true}; and
\item
\tcode{\exposid{compatible-static-extents}<InMat, InMat>(0, 1)} is \tcode{true}.
\end{itemize}

\pnum
\expects
\begin{itemize}
\item
\tcode{\exposid{multipliable}(B, A, B)} is \tcode{true}, and
\item
\tcode{A.extent(0) == A.extent(1)} is \tcode{true}.
\end{itemize}

\pnum
\effects
Computes $X'$ such that $X'A = B$,
and assigns each element of $X'$ to the corresponding element of $B$.
If so such $X'$ exists,
then the elements of \tcode{B} are valid but unspecified.

\pnum
\complexity
\bigoh{\tcode{A.extent(0)} \times \tcode{A.extent(1)} \times \tcode{B.extent(1)}}.
\end{itemdescr}

\indexlibraryglobal{triangular_matrix_matrix_right_solve}%
\begin{itemdecl}
template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, @\exposconcept{inout-matrix}@ InOutMat>
  void triangular_matrix_matrix_right_solve(InMat A, Triangle t, DiagonalStorage d, InOutMat B);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
triangular_matrix_matrix_right_solve(A, t, d, B, divides<void>{});
\end{codeblock}
\end{itemdescr}

\indexlibraryglobal{triangular_matrix_matrix_right_solve}%
\begin{itemdecl}
template<class ExecutionPolicy,
         @\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, @\exposconcept{inout-matrix}@ InOutMat>
  void triangular_matrix_matrix_right_solve(ExecutionPolicy&& exec,
                                            InMat A, Triangle t, DiagonalStorage d,
                                            InOutMat B);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
triangular_matrix_matrix_right_solve(std::forward<ExecutionPolicy>(exec),
                                     A, t, d, B, divides<void>{});
\end{codeblock}
\end{itemdescr}

\rSec1[simd]{Data-parallel types}

\rSec2[simd.general]{General}

\pnum
Subclause \ref{simd} defines data-parallel types and operations on these types.
\begin{note}
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\supercite{flynn-taxonomy}.
\end{note}

\pnum
The set of \defnadjx{vectorizable}{types}{type} comprises
\begin{itemize}
 \item
   all standard integer types, character types, and the types \tcode{float} and
   \tcode{double}\iref{basic.fundamental};
 \item
   \tcode{std::float16_t}, \tcode{std::float32_t}, and \tcode{std::float64_t}
   if defined\iref{basic.extended.fp}; and
 \item
   \tcode{complex<T>} where \tcode{T} is a vectorizable floating-point type.
\end{itemize}

\pnum
The term \defnadj{data-parallel}{type} refers to all enabled specializations of
the \tcode{basic_vec} and \tcode{basic_mask} class templates.
A \defnadj{data-parallel}{object} is an object of data-parallel type.

\pnum
Each specialization of \tcode{basic_vec} or \tcode{basic_mask} is either
enabled or disabled, as described in \ref{simd.overview} and
\ref{simd.mask.overview}.

\pnum
A data-parallel type consists of one or more elements of an underlying
vectorizable type, called the \defnadj{element}{type}.
The number of elements is a constant for each data-parallel type and called the
\defn{width} of that type.
The elements in a data-parallel type are indexed from 0 to $\textrm{width} - 1$.

\pnum
An \defnadj{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 \defnadj{unary element-wise}{operation} is an element-wise operation that
applies a unary operation to each element of a data-parallel object.
A \defnadj{binary element-wise}{operation} is an element-wise operation that
applies a binary operation to corresponding elements of two data-parallel
objects.

\pnum
Given a \tcode{basic_mask<Bytes, Abi>} object \tcode{mask}, the
\defnadj{selected}{indices} signify the integers $i$ in the range
\range{0}{mask.size()} for which \tcode{mask[$i$]} is \tcode{true}.
Given a data-parallel object \tcode{data}, the \defnadj{selected}{elements}
signify the elements \tcode{data[$i$]} for all selected indices $i$.

\pnum
The conversion from an arithmetic type \tcode{U} to a vectorizable type
\tcode{T} is \defn{value-preserving} if all possible values of \tcode{U} can be
represented with type \tcode{T}.

\rSec2[simd.expos]{Exposition-only types, variables, and concepts}

\begin{codeblock}
using @\exposidnc{simd-size-type} = \seebelownc@;                                    // \expos
template<size_t Bytes> using @\exposidnc{integer-from} = \seebelownc@;               // \expos

template<class T, class Abi>
  constexpr @\exposidnc{simd-size-type} \exposidnc{simd-size-v} = \seebelownc@;                  // \expos
template<class T> constexpr size_t @\exposidnc{mask-element-size} = \seebelownc@;    // \expos

template<class T>
  concept @\defexposconceptnc{constexpr-wrapper-like}@ =                                   // \expos
    @\libconcept{convertible_to}@<T, decltype(T::value)> &&
    @\libconcept{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<class From, class To>
  concept @\defexposconceptnc{explicitly-convertible-to}@ =                                // \expos
    requires {
      static_cast<To>(declval<From>());
    };

template<class T> using @\exposidnc{deduced-vec-t} = \seebelownc@;                   // \expos

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

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

template<class V>
  concept @\defexposconceptnc{simd-mask-type}@ =                                           // \expos
    @\libconcept{same_as}@<V, basic_mask<@\exposid{mask-element-size}@<V>, typename V::abi_type>> &&
    is_default_constructible_v<V>;

template<class V>
  concept @\defexposconceptnc{simd-floating-point}@ =                                      // \expos
    @\exposconcept{simd-vec-type}@<V> && @\libconcept{floating_point}@<typename V::value_type>;

template<class V>
  concept @\defexposconceptnc{simd-integral}@ =                                            // \expos
    @\exposconcept{simd-vec-type}@<V> && @\libconcept{integral}@<typename V::value_type>;

template<class V>
  using @\exposidnc{simd-complex-value-type}@ = V::value_type::value_type; // \expos

template<class V>
  concept @\defexposconceptnc{simd-complex}@ =                                             // \expos
    @\exposconcept{simd-vec-type}@<V> && @\libconcept{same_as}@<typename V::value_type, complex<@\exposid{simd-complex-value-type}@<V>>>;

template<class... Ts>
  concept @\defexposconceptnc{math-floating-point}@ =                                      // \expos
    (@\exposconceptnc{simd-floating-point}<\exposidnc{deduced-vec-t}@<Ts>> || ...);

template<class... Ts>
  requires @\exposconceptnc{math-floating-point}@<Ts...>
    using @\exposidnc{math-common-simd-t} = \seebelownc@;                            // \expos

template<class BinaryOperation, class T>
  concept @\exposconceptnc{reduction-binary-operation} = \seebelownc@;                    // \expos

// \ref{simd.expos.abi}, \tcode{simd} ABI tags
template<class T> using @\exposidnc{native-abi} = \seebelownc@;                      // \expos
template<class T, @\exposidnc{simd-size-type}@ N> using @\exposidnc{deduce-abi-t} = \seebelownc@;  // \expos

// \ref{simd.flags}, load and store flags
struct @\exposidnc{convert-flag}@;                                                 // \expos
struct @\exposidnc{aligned-flag}@;                                                 // \expos
template<size_t N> struct @\exposidnc{overaligned-flag}@;                          // \expos
\end{codeblock}

\rSec3[simd.expos.defn]{Exposition-only helpers}

\begin{itemdecl}
using @\exposid{simd-size-type}@ = @\seebelow@;
\end{itemdecl}

\begin{itemdescr}
\pnum
\exposid{simd-size-type} is an alias for a signed integer type.
\end{itemdescr}

\begin{itemdecl}
template<size_t Bytes> using @\exposid{integer-from}@ = @\seebelow@;
\end{itemdecl}

\begin{itemdescr}
\pnum
\tcode{\exposid{integer-from}<Bytes>} is an alias for a signed integer type
\tcode{T} such that \tcode{sizeof(T)} equals \tcode{Bytes}.
\end{itemdescr}

\begin{itemdecl}
template<class T, class Abi>
  constexpr @\exposid{simd-size-type} \exposid{simd-size-v}@ = @\seebelow@;
\end{itemdecl}

\begin{itemdescr}
\pnum
\tcode{\exposid{simd-size-v}<T, Abi>} denotes the width of \tcode{basic_vec<T,
Abi>} if the specialization \tcode{basic_vec<T, Abi>} is enabled, or \tcode{0}
otherwise.
\end{itemdescr}

\begin{itemdecl}
template<class T> constexpr size_t @\exposid{mask-element-size}@ = @\seebelow@;
\end{itemdecl}

\begin{itemdescr}
\pnum
\tcode{\exposid{mask-element-size}<basic_mask<Bytes, Abi>>} has the value
\tcode{Bytes}.
\end{itemdescr}

\begin{itemdecl}
template<class T> using @\exposid{deduced-vec-t}@ = @\seebelow@;
\end{itemdecl}

\begin{itemdescr}
\pnum
Let \tcode{x} denote an lvalue of type \tcode{const T}.

\pnum
\tcode{\exposid{deduced-vec-t}<T>} is an alias for
\begin{itemize}
 \item
   \tcode{decltype(x + x)}, if the type of \tcode{x + x} is an enabled
   specialization of \tcode{basic_vec}; otherwise
 \item
   \tcode{void}.
\end{itemize}
\end{itemdescr}

\begin{itemdecl}
template<class V, class T> using @\exposid{make-compatible-simd-t}@ = @\seebelow@;
\end{itemdecl}

\begin{itemdescr}
\pnum
Let \tcode{x} denote an lvalue of type \tcode{const T}.

\pnum
\tcode{\exposid{make-compatible-simd-t}<V, T>} is an alias for
\begin{itemize}
 \item
   \tcode{\exposid{deduced-vec-t}<T>}, if that type is not \tcode{void},
   otherwise
 \item
   \tcode{vec<decltype(x + x), V::size()>}.
\end{itemize}
\end{itemdescr}

\begin{itemdecl}
template<class... Ts>
  requires @\exposconcept{math-floating-point}@<Ts...>
    using @\exposid{math-common-simd-t}@ = @\seebelow@;
\end{itemdecl}

\begin{itemdescr}
\pnum
Let \tcode{T0} denote \tcode{Ts...[0]}.
Let \tcode{T1} denote \tcode{Ts...[1]}.
Let \tcode{TRest} denote a pack such that \tcode{T0, T1, TRest...} is equivalent
to \tcode{Ts...}.

\pnum
Let \tcode{\exposid{math-common-simd-t}<Ts...>} be an alias for
\begin{itemize}
 \item
   \tcode{\exposid{deduced-vec-t}<T0>}, if \tcode{sizeof...(Ts)} equals $1$;
   otherwise
 \item
   \tcode{common_type_t<\exposid{deduced-vec-t}<T0>,
   \exposid{deduced-vec-t}<T1>>}, if \tcode{sizeof...(Ts)} equals $2$ and
   \tcode{\exposconcept{math-floating-point}<T0> \&\&
   \exposconcept{math-floating-point}<T1>} is \tcode{true}; otherwise
 \item
   \tcode{common_type_t<\exposid{deduced-vec-t}<T0>, T1>}, if
   \tcode{sizeof...(Ts)} equals $2$ and
   \tcode{\exposconceptx{math-floating-\brk{}point}{math-floating-point}<\brk{}T0>}
   is \tcode{true}; otherwise
 \item
   \tcode{common_type_t<T0, \exposid{deduced-vec-t}<T1>>}, if
   \tcode{sizeof...(Ts)} equals $2$; otherwise
 \item
   \tcode{common_type_t<\exposid{math-common-simd-t}<T0, T1>, TRest...>}, if
   \tcode{\exposid{math-common-simd-t}<T0, T1>} is valid and denotes a type;
   otherwise
 \item
   \tcode{common_type_t<\exposid{math-common-simd-t}<TRest...>, T0, T1>}.
\end{itemize}
\end{itemdescr}

\begin{itemdecl}
template<class BinaryOperation, class T>
  concept @\defexposconcept{reduction-binary-operation}@ =
    requires (const BinaryOperation binary_op, const vec<T, 1> v) {
      { binary_op(v, v) } -> @\libconcept{same_as}@<vec<T, 1>>;
    };
\end{itemdecl}

\begin{itemdescr}
\pnum
Types \tcode{BinaryOperation} and \tcode{T} model
\tcode{\exposconcept{reduction-binary-operation}<BinaryOperation, T>} only if:
\begin{itemize}
\item \tcode{BinaryOperation} is a binary element-wise operation and the
operation is commutative.

\item An object of type \tcode{BinaryOperation} can be invoked with two
arguments of type \tcode{basic_vec<T, Abi>}, with unspecified ABI tag
\tcode{Abi}, returning a \tcode{basic_vec<T, Abi>}.
\end{itemize}
\end{itemdescr}

\rSec3[simd.expos.abi]{\tcode{simd} ABI tags}

\begin{itemdecl}
template<class T> using @\exposid{native-abi}@ = @\seebelow@;
template<class T, @\exposid{simd-size-type}@ N> using @\exposid{deduce-abi-t}@ = @\seebelow@;
\end{itemdecl}

\begin{itemdescr}
\pnum
An \defn{ABI tag} is a type that indicates a choice of size and binary
representation for objects of data-parallel type.
\begin{note}
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}

\pnum
\begin{note}
The ABI tag is orthogonal to selecting the machine instruction set.
The selected machine instruction set limits the usable ABI tag types, though
(see \ref{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}

\pnum
An implementation defines ABI tag types as necessary for the following aliases.

\pnum
\tcode{\exposid{deduce-abi-t}<T, N>} is defined if
\begin{itemize}
\item \tcode{T} is a vectorizable type,
\item \tcode{N} is greater than zero, and
\item \tcode{N} is not larger than an implementation-defined maximum.
\end{itemize}
The \impldef{maximum width for \tcode{vec} and \tcode{mask}} maximum for
\tcode{N} is not smaller than 64 and can differ depending on \tcode{T}.

\pnum
Where present, \tcode{\exposid{deduce-abi-t}<T, N>} names an ABI tag type such
that
\begin{itemize}
 \item
   \tcode{\exposid{simd-size-v}<T, \exposid{deduce-abi-t}<T, N>>} equals
   \tcode{N}, \item \tcode{basic_vec<T, \exposid{deduce-abi-t}<T, N>>} is
   enabled\iref{simd.overview}, and
 \item
   \tcode{basic_mask<sizeof(T),
   \exposid{deduce-abi-t}<\exposid{integer-from}<sizeof(T)>, N>>} is enabled.
\end{itemize}

\pnum
\tcode{\exposid{native-abi}<T>} is an \impldef{default ABI tag for
\tcode{basic_vec} and \tcode{basic_mask}} alias for an ABI tag.
\tcode{basic_vec<T, \exposid{native-abi}<T>>} is an enabled specialization.
\begin{note}
The intent is to use the ABI tag producing the most efficient data-parallel
execution for the element type \tcode{T} on the currently targeted system.
For target architectures with ISA extensions, compiler flags can change the type
of the \tcode{\exposid{native-abi}<T>} alias.
\end{note}
\begin{example}
Consider a target architecture supporting the ABI tags \tcode{__simd128} and
\tcode{__simd256}, where hardware support for \tcode{__simd256} exists only for
floating-point types.
The implementation therefore defines \tcode{\exposid{native-abi}<T>} as an alias
for
\begin{itemize}
\item \tcode{__simd256} if \tcode{T} is a floating-point type, and
\item \tcode{__simd128} otherwise.
\end{itemize}
\end{example}
\end{itemdescr}

\rSec2[simd.syn]{Header \tcode{<simd>} synopsis}
\indexheader{simd}%
\begin{codeblock}
namespace std::simd {
  // \ref{simd.traits}, type traits
  template<class T, class U = typename T::value_type> struct alignment;
  template<class T, class U = typename T::value_type>
    constexpr size_t @\libmember{alignment_v}{simd}@ = alignment<T, U>::value;

  template<class T, class V> struct rebind { using type = @\seebelow@; };
  template<class T, class V> using @\libmember{rebind_t}{simd}@ = rebind<T, V>::type;
  template<@\exposid{simd-size-type}@ N, class V> struct resize { using type = @\seebelow@; };
  template<@\exposid{simd-size-type}@ N, class V> using @\libmember{resize_t}{simd}@ = resize<N, V>::type;

  // \ref{simd.flags}, load and store flags
  template<class... Flags> struct flags;
  inline constexpr flags<> @\libmember{flag_default}{simd}@{};
  inline constexpr flags<@\exposid{convert-flag}@> @\libmember{flag_convert}{simd}@{};
  inline constexpr flags<@\exposid{aligned-flag}@> @\libmember{flag_aligned}{simd}@{};
  template<size_t N> requires (has_single_bit(N))
    constexpr flags<@\exposid{overaligned-flag}<N>@> @\libmember{flag_overaligned}{simd}@{};

  // \ref{simd.iterator}, class template \exposid{simd-iterator}
  template<class V>
    class @\exposidnc{simd-iterator}@;                // \expos

  // \ref{simd.class}, class template \tcode{basic_vec}
  template<class T, class Abi = @\exposid{native-abi}@<T>> class basic_vec;
  template<class T, @\exposid{simd-size-type}@ N = @\exposid{simd-size-v}@<T, @\exposid{native-abi}@<T>>>
    using @\libmember{vec}{simd}@ = basic_vec<T, @\exposid{deduce-abi-t}@<T, N>>;

  // \ref{simd.reductions}, reductions
  template<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<T> identity_element = @\seebelow@);

  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;

  // \ref{simd.loadstore}, load and store functions
  template<class V = @\seebelow@, ranges::@\libconcept{contiguous_range}@ R, class... Flags>
    requires ranges::@\libconcept{sized_range}@<R>
    constexpr V unchecked_load(R&& r, flags<Flags...> f = {});
  template<class V = @\seebelow@, ranges::@\libconcept{contiguous_range}@ R, class... Flags>
    requires ranges::@\libconcept{sized_range}@<R>
    constexpr V unchecked_load(R&& r, const typename V::mask_type& k,
                               flags<Flags...> f = {});
  template<class V = @\seebelow@, @\libconcept{contiguous_iterator}@ I, class... Flags>
    constexpr V unchecked_load(I first, iter_difference_t<I> n,
                               flags<Flags...> f = {});
  template<class V = @\seebelow@, @\libconcept{contiguous_iterator}@ I, class... Flags>
    constexpr V unchecked_load(I first, iter_difference_t<I> n,
                               const typename V::mask_type& k, flags<Flags...> f = {});
  template<class V = @\seebelow@, @\libconcept{contiguous_iterator}@ I, @\libconcept{sized_sentinel_for}@<I> S, class... Flags>
    constexpr V unchecked_load(I first, S last, flags<Flags...> f = {});
  template<class V = @\seebelow@, @\libconcept{contiguous_iterator}@ I, @\libconcept{sized_sentinel_for}@<I> S, class... Flags>
    constexpr V unchecked_load(I first, S last, const typename V::mask_type& k,
                               flags<Flags...> f = {});

  template<class V = @\seebelow@, ranges::@\libconcept{contiguous_range}@ R, class... Flags>
    requires ranges::@\libconcept{sized_range}@<R>
    constexpr V partial_load(R&& r, flags<Flags...> f = {});
  template<class V = @\seebelow@, ranges::@\libconcept{contiguous_range}@ R, class... Flags>
    requires ranges::@\libconcept{sized_range}@<R>
    constexpr V partial_load(R&& r, const typename V::mask_type& k,
                             flags<Flags...> f = {});
  template<class V = @\seebelow@, @\libconcept{contiguous_iterator}@ I, class... Flags>
    constexpr V partial_load(I first, iter_difference_t<I> n, flags<Flags...> f = {});
  template<class V = @\seebelow@, @\libconcept{contiguous_iterator}@ I, class... Flags>
    constexpr V partial_load(I first, iter_difference_t<I> n,
                             const typename V::mask_type& k, flags<Flags...> f = {});
  template<class V = @\seebelow@, @\libconcept{contiguous_iterator}@ I, @\libconcept{sized_sentinel_for}@<I> S, class... Flags>
    constexpr V partial_load(I first, S last, flags<Flags...> f = {});
  template<class V = @\seebelow@, @\libconcept{contiguous_iterator}@ I, @\libconcept{sized_sentinel_for}@<I> 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::@\libconcept{contiguous_range}@ R, class... Flags>
    requires ranges::@\libconcept{sized_range}@<R>
    constexpr void unchecked_store(const basic_vec<T, Abi>& v, R&& r,
                                   flags<Flags...> f = {});
  template<class T, class Abi, ranges::@\libconcept{contiguous_range}@ R, class... Flags>
    requires ranges::@\libconcept{sized_range}@<R>
    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, @\libconcept{contiguous_iterator}@ I, class... Flags>
    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, @\libconcept{contiguous_iterator}@ I, class... Flags>
    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, @\libconcept{contiguous_iterator}@ I, @\libconcept{sized_sentinel_for}@<I> S, class... Flags>
    constexpr void unchecked_store(const basic_vec<T, Abi>& v, I first, S last,
                                   flags<Flags...> f = {});
  template<class T, class Abi, @\libconcept{contiguous_iterator}@ I, @\libconcept{sized_sentinel_for}@<I> S, class... Flags>
    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::@\libconcept{contiguous_range}@ R, class... Flags>
    requires ranges::@\libconcept{sized_range}@<R>
    constexpr void partial_store(const basic_vec<T, Abi>& v, R&& r,
                                 flags<Flags...> f = {});
  template<class T, class Abi, ranges::@\libconcept{contiguous_range}@ R, class... Flags>
    requires ranges::@\libconcept{sized_range}@<R>
    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, @\libconcept{contiguous_iterator}@ I, class... Flags>
    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, @\libconcept{contiguous_iterator}@ I, class... Flags>
    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, @\libconcept{contiguous_iterator}@ I, @\libconcept{sized_sentinel_for}@<I> S, class... Flags>
    constexpr void partial_store(const basic_vec<T, Abi>& v, I first, S last,
                                 flags<Flags...> f = {});
  template<class T, class Abi, @\libconcept{contiguous_iterator}@ I, @\libconcept{sized_sentinel_for}@<I> S, class... Flags>
    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 = {});

  // \ref{simd.permute.static}, static permute
  inline constexpr @\exposid{simd-size-type}@ @\libmember{zero_element}{simd}@   = @\impdefx{value of \tcode{simd::zero_element}}@;
  inline constexpr @\exposid{simd-size-type}@ @\libmember{uninit_element}{simd}@ = @\impdefx{value of \tcode{simd::uninit_element}}@;

  template<@\exposid{simd-size-type}@ N = @\seebelow@, @\exposconcept{simd-vec-type}@ V, class IdxMap>
    constexpr resize_t<N, V> permute(const V& v, IdxMap&& idxmap);
  template<@\exposid{simd-size-type}@ N = @\seebelow@, @\exposconcept{simd-mask-type}@ V, class IdxMap>
    constexpr resize_t<N, V> permute(const V& v, IdxMap&& idxmap);

  // \ref{simd.permute.dynamic}, dynamic permute
  template<@\exposconcept{simd-vec-type}@ V, @\exposconcept{simd-integral}@ I>
    constexpr resize_t<I::size(), V> permute(const V& v, const I& indices);
  template<@\exposconcept{simd-mask-type}@ V, @\exposconcept{simd-integral}@ I>
    constexpr resize_t<I::size(), V> permute(const V& v, const I& indices);

  // \ref{simd.permute.mask}, mask permute
  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<V>& 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<V>& 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<V>& selector,
                       const V& original = {});

  // \ref{simd.permute.memory}, memory permute
  template<class V = @\seebelow@, ranges::@\libconcept{contiguous_range}@ R, @\exposconcept{simd-integral}@ I, class... Flags>
    requires ranges::@\libconcept{sized_range}@<R>
    constexpr V unchecked_gather_from(R&& in, const I& indices, flags<Flags...> f = {});
  template<class V = @\seebelow@, ranges::@\libconcept{contiguous_range}@ R, @\exposconcept{simd-integral}@ I, class... Flags>
    requires ranges::@\libconcept{sized_range}@<R>
    constexpr V unchecked_gather_from(R&& in, const typename I::mask_type& mask,
                                      const I& indices, flags<Flags...> f = {});

  template<class V = @\seebelow@, ranges::@\libconcept{contiguous_range}@ R, @\exposconcept{simd-integral}@ I, class... Flags>
    requires ranges::@\libconcept{sized_range}@<R>
    constexpr V partial_gather_from(R&& in, const I& indices, flags<Flags...> f = {});
  template<class V = @\seebelow@, ranges::@\libconcept{contiguous_range}@ R, @\exposconcept{simd-integral}@ I, class... Flags>
    requires ranges::@\libconcept{sized_range}@<R>
    constexpr V partial_gather_from(R&& in, const typename I::mask_type& mask,
                                    const I& indices, flags<Flags...> f = {});

  template<@\exposconcept{simd-vec-type}@ V, ranges::@\libconcept{contiguous_range}@ R, @\exposconcept{simd-integral}@ I, class... Flags>
    requires ranges::@\libconcept{sized_range}@<R>
    constexpr void unchecked_scatter_to(const V& v, R&& out,
                                        const I& indices, flags<Flags...> f = {});
  template<@\exposconcept{simd-vec-type}@ V, ranges::@\libconcept{contiguous_range}@ R, @\exposconcept{simd-integral}@ I, class... Flags>
    requires ranges::@\libconcept{sized_range}@<R>
    constexpr void unchecked_scatter_to(const V& v, R&& out, const typename I::mask_type& mask,
                                        const I& indices, flags<Flags...> f = {});

  template<@\exposconcept{simd-vec-type}@ V, ranges::@\libconcept{contiguous_range}@ R, @\exposconcept{simd-integral}@ I, class... Flags>
    requires ranges::@\libconcept{sized_range}@<R>
    constexpr void partial_scatter_to(const V& v, R&& out,
                                      const I& indices, flags<Flags...> f = {});
  template<@\exposconcept{simd-vec-type}@ V, ranges::@\libconcept{contiguous_range}@ R, @\exposconcept{simd-integral}@ I, class... Flags>
    requires ranges::@\libconcept{sized_range}@<R>
    constexpr void partial_scatter_to(const V& v, R&& out, const typename I::mask_type& mask,
                                      const I& indices, flags<Flags...> f = {});

  // \ref{simd.creation}, 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<@\exposid{mask-element-size}@<T>, Abi>& x) noexcept;

  template<@\exposid{simd-size-type}@ N, class T, class Abi>
    constexpr auto chunk(const basic_vec<T, Abi>& x) noexcept;
  template<@\exposid{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, @\exposid{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, @\exposid{deduce-abi-t}@<@\exposid{integer-from}@<Bytes>,
                              (basic_mask<Bytes, Abis>::size() + ...)>>
      cat(const basic_mask<Bytes, Abis>&...) noexcept;

  // \ref{simd.alg}, algorithms
  template<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(@\exposid{simd-select-impl}@(c, a, b));

  // \ref{simd.math}, mathematical functions
  template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-vec-t}@<V> acos(const V& x);
  template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-vec-t}@<V> asin(const V& x);
  template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-vec-t}@<V> atan(const V& x);
  template<class V0, class V1>
    constexpr @\exposid{math-common-simd-t}@<V0, V1> atan2(const V0& y, const V1& x);
  template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-vec-t}@<V> cos(const V& x);
  template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-vec-t}@<V> sin(const V& x);
  template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-vec-t}@<V> tan(const V& x);
  template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-vec-t}@<V> acosh(const V& x);
  template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-vec-t}@<V> asinh(const V& x);
  template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-vec-t}@<V> atanh(const V& x);
  template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-vec-t}@<V> cosh(const V& x);
  template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-vec-t}@<V> sinh(const V& x);
  template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-vec-t}@<V> tanh(const V& x);
  template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-vec-t}@<V> exp(const V& x);
  template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-vec-t}@<V> exp2(const V& x);
  template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-vec-t}@<V> expm1(const V& x);
  template<@\exposconcept{math-floating-point}@ V>
    constexpr @\exposid{deduced-vec-t}@<V>
      frexp(const V& value, rebind_t<int, @\exposid{deduced-vec-t}@<V>>* exp);
  template<@\exposconcept{math-floating-point}@ V>
    constexpr rebind_t<int, @\exposid{deduced-vec-t}@<V>> ilogb(const V& x);
  template<@\exposconcept{math-floating-point}@ V>
    constexpr @\exposid{deduced-vec-t}@<V> ldexp(const V& x, const rebind_t<int, @\exposid{deduced-vec-t}@<V>>& exp);
  template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-vec-t}@<V> log(const V& x);
  template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-vec-t}@<V> log10(const V& x);
  template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-vec-t}@<V> log1p(const V& x);
  template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-vec-t}@<V> log2(const V& x);
  template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-vec-t}@<V> 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<@\exposconcept{math-floating-point}@ V>
    constexpr @\exposid{deduced-vec-t}@<V> scalbn(const V& x, const rebind_t<int, @\exposid{deduced-vec-t}@<V>>& n);
  template<@\exposconcept{math-floating-point}@ V>
    constexpr @\exposid{deduced-vec-t}@<V> scalbln(
      const V& x, const rebind_t<long int, @\exposid{deduced-vec-t}@<V>>& n);
  template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-vec-t}@<V> cbrt(const V& x);
  template<@\libconcept{signed_integral}@ T, class Abi>
    constexpr basic_vec<T, Abi> abs(const basic_vec<T, Abi>& j);
  template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-vec-t}@<V> abs(const V& j);
  template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-vec-t}@<V> fabs(const V& x);
  template<class V0, class V1>
    constexpr @\exposid{math-common-simd-t}@<V0, V1> hypot(const V0& x, const V1& y);
  template<class V0, class V1, class V2>
    constexpr @\exposid{math-common-simd-t}@<V0, V1, V2> hypot(const V0& x, const V1& y, const V2& z);
  template<class V0, class V1>
    constexpr @\exposid{math-common-simd-t}@<V0, V1> pow(const V0& x, const V1& y);
  template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-vec-t}@<V> sqrt(const V& x);
  template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-vec-t}@<V> erf(const V& x);
  template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-vec-t}@<V> erfc(const V& x);
  template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-vec-t}@<V> lgamma(const V& x);
  template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-vec-t}@<V> tgamma(const V& x);
  template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-vec-t}@<V> ceil(const V& x);
  template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-vec-t}@<V> floor(const V& x);
  template<@\exposconcept{math-floating-point}@ V> @\exposid{deduced-vec-t}@<V> nearbyint(const V& x);
  template<@\exposconcept{math-floating-point}@ V> @\exposid{deduced-vec-t}@<V> rint(const V& x);
  template<@\exposconcept{math-floating-point}@ V>
    rebind_t<long int, @\exposid{deduced-vec-t}@<V>> lrint(const V& x);
  template<@\exposconcept{math-floating-point}@ V>
    rebind_t<long long int, V> llrint(const @\exposid{deduced-vec-t}@<V>& x);
  template<@\exposconcept{math-floating-point}@ V>
    constexpr @\exposid{deduced-vec-t}@<V> round(const V& x);
  template<@\exposconcept{math-floating-point}@ V>
    constexpr rebind_t<long int, @\exposid{deduced-vec-t}@<V>> lround(const V& x);
  template<@\exposconcept{math-floating-point}@ V>
    constexpr rebind_t<long long int, @\exposid{deduced-vec-t}@<V>> llround(const V& x);
  template<@\exposconcept{math-floating-point}@ V>
    constexpr @\exposid{deduced-vec-t}@<V> trunc(const V& x);
  template<class V0, class V1>
    constexpr @\exposid{math-common-simd-t}@<V0, V1> fmod(const V0& x, const V1& y);
  template<class V0, class V1>
    constexpr @\exposid{math-common-simd-t}@<V0, V1> remainder(const V0& x, const V1& y);
  template<class V0, class V1>
    constexpr @\exposid{math-common-simd-t}@<V0, V1>
      remquo(const V0& x, const V1& y, rebind_t<int, @\exposid{math-common-simd-t}@<V0, V1>>* quo);
  template<class V0, class V1>
    constexpr @\exposid{math-common-simd-t}@<V0, V1> copysign(const V0& x, const V1& y);
  template<class V0, class V1>
    constexpr @\exposid{math-common-simd-t}@<V0, V1> nextafter(const V0& x, const V1& y);
  template<class V0, class V1>
    constexpr @\exposid{math-common-simd-t}@<V0, V1> fdim(const V0& x, const V1& y);
  template<class V0, class V1>
    constexpr @\exposid{math-common-simd-t}@<V0, V1> fmax(const V0& x, const V1& y);
  template<class V0, class V1>
    constexpr @\exposid{math-common-simd-t}@<V0, V1> fmin(const V0& x, const V1& y);
  template<class V0, class V1, class V2>
    constexpr @\exposid{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 @\exposid{math-common-simd-t}@<V0, V1, V2>
      lerp(const V0& a, const V1& b, const V2& t) noexcept;
  template<@\exposconcept{math-floating-point}@ V>
    constexpr rebind_t<int, @\exposid{deduced-vec-t}@<V>> fpclassify(const V& x);
  template<@\exposconcept{math-floating-point}@ V>
    constexpr typename @\exposid{deduced-vec-t}@<V>::mask_type isfinite(const V& x);
  template<@\exposconcept{math-floating-point}@ V>
    constexpr typename @\exposid{deduced-vec-t}@<V>::mask_type isinf(const V& x);
  template<@\exposconcept{math-floating-point}@ V>
    constexpr typename @\exposid{deduced-vec-t}@<V>::mask_type isnan(const V& x);
  template<@\exposconcept{math-floating-point}@ V>
    constexpr typename @\exposid{deduced-vec-t}@<V>::mask_type isnormal(const V& x);
  template<@\exposconcept{math-floating-point}@ V>
    constexpr typename @\exposid{deduced-vec-t}@<V>::mask_type signbit(const V& x);
  template<class V0, class V1>
    constexpr typename @\exposid{math-common-simd-t}@<V0, V1>::mask_type
      isgreater(const V0& x, const V1& y);
  template<class V0, class V1>
    constexpr typename @\exposid{math-common-simd-t}@<V0, V1>::mask_type
      isgreaterequal(const V0& x, const V1& y);
  template<class V0, class V1>
    constexpr typename @\exposid{math-common-simd-t}@<V0, V1>::mask_type
      isless(const V0& x, const V1& y);
  template<class V0, class V1>
    constexpr typename @\exposid{math-common-simd-t}@<V0, V1>::mask_type
      islessequal(const V0& x, const V1& y);
  template<class V0, class V1>
    constexpr typename @\exposid{math-common-simd-t}@<V0, V1>::mask_type
      islessgreater(const V0& x, const V1& y);
  template<class V0, class V1>
    constexpr typename @\exposid{math-common-simd-t}@<V0, V1>::mask_type
      isunordered(const V0& x, const V1& y);
  template<@\exposconcept{math-floating-point}@ V>
    @\exposid{deduced-vec-t}@<V> assoc_laguerre(const rebind_t<unsigned, @\exposid{deduced-vec-t}@<V>>& n,
                                    const rebind_t<unsigned, @\exposid{deduced-vec-t}@<V>>& m, const V& x);
  template<@\exposconcept{math-floating-point}@ V>
    @\exposid{deduced-vec-t}@<V> assoc_legendre(const rebind_t<unsigned, @\exposid{deduced-vec-t}@<V>>& l,
                                    const rebind_t<unsigned, @\exposid{deduced-vec-t}@<V>>& m, const V& x);
  template<class V0, class V1>
    @\exposid{math-common-simd-t}@<V0, V1> beta(const V0& x, const V1& y);
  template<@\exposconcept{math-floating-point}@ V> @\exposid{deduced-vec-t}@<V> comp_ellint_1(const V& k);
  template<@\exposconcept{math-floating-point}@ V> @\exposid{deduced-vec-t}@<V> comp_ellint_2(const V& k);
  template<class V0, class V1>
    @\exposid{math-common-simd-t}@<V0, V1> comp_ellint_3(const V0& k, const V1& nu);
  template<class V0, class V1>
    @\exposid{math-common-simd-t}@<V0, V1> cyl_bessel_i(const V0& nu, const V1& x);
  template<class V0, class V1>
    @\exposid{math-common-simd-t}@<V0, V1> cyl_bessel_j(const V0& nu, const V1& x);
  template<class V0, class V1>
    @\exposid{math-common-simd-t}@<V0, V1> cyl_bessel_k(const V0& nu, const V1& x);
  template<class V0, class V1>
    @\exposid{math-common-simd-t}@<V0, V1> cyl_neumann(const V0& nu, const V1& x);
  template<class V0, class V1>
    @\exposid{math-common-simd-t}@<V0, V1> ellint_1(const V0& k, const V1& phi);
  template<class V0, class V1>
    @\exposid{math-common-simd-t}@<V0, V1> ellint_2(const V0& k, const V1& phi);
  template<class V0, class V1, class V2>
    @\exposid{math-common-simd-t}@<V0, V1, V2> ellint_3(const V0& k, const V1& nu, const V2& phi);
  template<@\exposconcept{math-floating-point}@ V> @\exposid{deduced-vec-t}@<V> expint(const V& x);
  template<@\exposconcept{math-floating-point}@ V>
    @\exposid{deduced-vec-t}@<V> hermite(const rebind_t<unsigned, @\exposid{deduced-vec-t}@<V>>& n, const V& x);
  template<@\exposconcept{math-floating-point}@ V>
    @\exposid{deduced-vec-t}@<V> laguerre(const rebind_t<unsigned, @\exposid{deduced-vec-t}@<V>>& n, const V& x);
  template<@\exposconcept{math-floating-point}@ V>
    @\exposid{deduced-vec-t}@<V> legendre(const rebind_t<unsigned, @\exposid{deduced-vec-t}@<V>>& l, const V& x);
  template<@\exposconcept{math-floating-point}@ V>
    @\exposid{deduced-vec-t}@<V> riemann_zeta(const V& x);
  template<@\exposconcept{math-floating-point}@ V>
    @\exposid{deduced-vec-t}@<V> sph_bessel(
      const rebind_t<unsigned, @\exposid{deduced-vec-t}@<V>>& n, const V& x);
  template<@\exposconcept{math-floating-point}@ V>
    @\exposid{deduced-vec-t}@<V> sph_legendre(const rebind_t<unsigned, @\exposid{deduced-vec-t}@<V>>& l,
      const rebind_t<unsigned, @\exposid{deduced-vec-t}@<V>>& m, const V& theta);
  template<@\exposconcept{math-floating-point}@ V>
    @\exposid{deduced-vec-t}@<V>
      sph_neumann(const rebind_t<unsigned, @\exposid{deduced-vec-t}@<V>>& n, const V& x);

  // \ref{simd.bit}, bit manipulation
  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);
  template<@\exposconcept{simd-vec-type}@ V> constexpr V bit_floor(const V& v) noexcept;

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

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

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

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

  // \ref{simd.complex.math}, complex math
  template<@\exposconcept{simd-complex}@ V>
    constexpr rebind_t<@\exposid{simd-complex-value-type<V>}@, V> real(const V&) noexcept;

  template<@\exposconcept{simd-complex}@ V>
    constexpr rebind_t<@\exposid{simd-complex-value-type<V>}@, V> imag(const V&) noexcept;

  template<@\exposconcept{simd-complex}@ V>
    constexpr rebind_t<@\exposid{simd-complex-value-type<V>}@, V> abs(const V&);

  template<@\exposconcept{simd-complex}@ V>
    constexpr rebind_t<@\exposid{simd-complex-value-type<V>}@, V> arg(const V&);

  template<@\exposconcept{simd-complex}@ V>
    constexpr rebind_t<@\exposid{simd-complex-value-type<V>}@, V> norm(const V&);

  template<@\exposconcept{simd-complex}@ V> constexpr V conj(const V&);
  template<@\exposconcept{simd-complex}@ V> constexpr V proj(const V&);
  template<@\exposconcept{simd-complex}@ V> constexpr V exp(const V& v);
  template<@\exposconcept{simd-complex}@ V> constexpr V log(const V& v);
  template<@\exposconcept{simd-complex}@ V> constexpr V log10(const V& v);

  template<@\exposconcept{simd-complex}@ V> constexpr V sqrt(const V& v);
  template<@\exposconcept{simd-complex}@ V> constexpr V sin(const V& v);
  template<@\exposconcept{simd-complex}@ V> constexpr V asin(const V& v);
  template<@\exposconcept{simd-complex}@ V> constexpr V cos(const V& v);
  template<@\exposconcept{simd-complex}@ V> constexpr V acos(const V& v);
  template<@\exposconcept{simd-complex}@ V> constexpr V tan(const V& v);
  template<@\exposconcept{simd-complex}@ V> constexpr V atan(const V& v);
  template<@\exposconcept{simd-complex}@ V> constexpr V sinh(const V& v);
  template<@\exposconcept{simd-complex}@ V> constexpr V asinh(const V& v);
  template<@\exposconcept{simd-complex}@ V> constexpr V cosh(const V& v);
  template<@\exposconcept{simd-complex}@ V> constexpr V acosh(const V& v);
  template<@\exposconcept{simd-complex}@ V> constexpr V tanh(const V& v);
  template<@\exposconcept{simd-complex}@ V> constexpr V atanh(const V& v);

  template<@\exposconcept{simd-floating-point}@ V>
    rebind_t<complex<typename V::value_type>, V> polar(const V& x, const V& y = {});

  template<@\exposconcept{simd-complex}@ V> constexpr V pow(const V& x, const V& y);

  // \ref{simd.mask.class}, class template \tcode{basic_mask}
  template<size_t Bytes, class Abi = @\exposid{native-abi}@<@\exposid{integer-from}@<Bytes>>> class basic_mask;
  template<class T, @\exposid{simd-size-type}@ N = @\exposid{simd-size-v}@<T, @\exposid{native-abi}@<T>>>
    using @\libmember{mask}{simd}@ = basic_mask<sizeof(T), @\exposid{deduce-abi-t}@<T, N>>;

  // \ref{simd.mask.reductions}, reductions
  template<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 @\exposid{simd-size-type}@ reduce_count(const basic_mask<Bytes, Abi>&) noexcept;
  template<size_t Bytes, class Abi>
    constexpr @\exposid{simd-size-type}@ reduce_min_index(const basic_mask<Bytes, Abi>&);
  template<size_t Bytes, class Abi>
    constexpr @\exposid{simd-size-type}@ reduce_max_index(const basic_mask<Bytes, Abi>&);

  constexpr bool all_of(@\libconcept{same_as}@<bool> auto) noexcept;
  constexpr bool any_of(@\libconcept{same_as}@<bool> auto) noexcept;
  constexpr bool none_of(@\libconcept{same_as}@<bool> auto) noexcept;
  constexpr @\exposid{simd-size-type}@ reduce_count(@\libconcept{same_as}@<bool> auto) noexcept;
  constexpr @\exposid{simd-size-type}@ reduce_min_index(@\libconcept{same_as}@<bool> auto);
  constexpr @\exposid{simd-size-type}@ reduce_max_index(@\libconcept{same_as}@<bool> auto);
}

namespace std {
  // See \ref{simd.alg}, algorithms
  using simd::min;
  using simd::max;
  using simd::minmax;
  using simd::clamp;

  // See \ref{simd.math}, mathematical functions
  using 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 \ref{simd.bit}, bit manipulation
  using 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 \ref{simd.complex.math}, \tcode{vec} complex math
  using simd::real;
  using simd::imag;
  using simd::arg;
  using simd::norm;
  using simd::conj;
  using simd::proj;
  using simd::polar;
}
\end{codeblock}

\rSec2[simd.traits]{Type traits}

\indexlibrarymember{alignment}{simd}
\begin{itemdecl}
template<class T, class U = typename T::value_type> struct alignment { @\seebelow@ };
\end{itemdecl}

\begin{itemdescr}
\pnum
\tcode{alignment<T, U>} has a member \tcode{value} if and only if
\tcode{T} is a specialization of \tcode{basic_vec} and
\tcode{U} is a vectorizable type.

\pnum
If \tcode{value} is present, the type \tcode{alignment<T, U>} is a
\tcode{BinaryTypeTrait} with a base characteristic of
\tcode{integral_constant<size_t, N>} for some unspecified
\tcode{N}\iref{simd.ctor,simd.loadstore}.
\begin{note}
\tcode{value} identifies the alignment restrictions on pointers used for
(converting) loads and stores for the given type \tcode{T} on arrays of type
\tcode{U}.
\end{note}

\pnum
The behavior of a program that adds specializations for \tcode{alignment}
is undefined.
\end{itemdescr}

\indexlibrarymember{rebind}{simd}
\begin{itemdecl}
template<class T, class V> struct rebind { using type = @\seebelow@; };
\end{itemdecl}

\begin{itemdescr}
\pnum
The member \tcode{type} is present if and only if
\begin{itemize}
\item \tcode{V} is a data-parallel type,
\item \tcode{T} is a vectorizable type, and
\item \tcode{\exposid{deduce-abi-t}<T, V::size()>} has a member type
  \tcode{type}.
\end{itemize}

\pnum
If \tcode V is a specialization of \tcode{basic_vec}, let \tcode{Abi1} denote
an ABI tag such that \tcode{basic_vec<T, Abi1>::\brk{}size()} equals
\tcode{V::size()}.
If \tcode V is a specialization of \tcode{basic_mask}, let \tcode{Abi1}
denote an ABI tag such that \tcode{basic_mask<sizeof(T),
Abi1>::\brk{}size()} equals \tcode{V::size()}.

\pnum
Where present, the member typedef \tcode{type} names \tcode{basic_vec<T, Abi1>}
if \tcode V is a specialization of \tcode{basic_vec} or
\tcode{basic_mask<sizeof(T), Abi1>} if \tcode V is a specialization of
\tcode{basic_mask}.
\end{itemdescr}

\indexlibrarymember{resize}{simd}
\begin{itemdecl}
template<@\exposid{simd-size-type}@ N, class V> struct resize { using type = @\seebelow@; };
\end{itemdecl}

\begin{itemdescr}
\pnum
Let \tcode{T} denote
\begin{itemize}
 \item
   \tcode{typename V::value_type} if \tcode{V} is a specialization of
   \tcode{basic_vec},
 \item
   otherwise \tcode{\exposid{integer-from}<\exposid{mask-element-size}<V>>} if
   \tcode{V} is a specialization of \tcode{basic_mask}.
\end{itemize}

\pnum
The member \tcode{type} is present if and only if
\begin{itemize}
\item \tcode{V} is a data-parallel type, and
\item \tcode{\exposid{deduce-abi-t}<T, N>} has a member type \tcode{type}.
\end{itemize}

\pnum
If \tcode V is a specialization of \tcode{basic_vec}, let \tcode{Abi1} denote an
ABI tag such that \tcode{basic_vec<T, Abi1>::\brk{}size()} equals \tcode{N}.
If \tcode V is a specialization of \tcode{basic_mask}, let \tcode{Abi1}
denote an ABI tag such that \tcode{basic_mask<sizeof(T), Abi1>::size()} equals \tcode{N}.

\pnum
Where present, the member typedef \tcode{type} names \tcode{basic_vec<T, Abi1>}
if \tcode V is a specialization of \tcode{basic_vec} or
\tcode{basic_mask<sizeof(T), Abi1>} if \tcode V is a specialization of
\tcode{basic_mask}.
\end{itemdescr}

\rSec2[simd.flags]{Load and store flags}

\rSec3[simd.flags.overview]{Class template \tcode{flags} overview}

\indexlibrarymember{flags}{simd}
\begin{codeblock}
namespace std::simd {
  template<class... Flags> struct flags {
    // \ref{simd.flags.oper}, \tcode{flags} operators
    template<class... Other>
      friend consteval auto operator|(flags, flags<Other...>);
  };
}
\end{codeblock}

\pnum
\begin{note}
The class template \tcode{flags} acts like an integer bit-flag for types.
\end{note}

\pnum
\constraints
Every type in the parameter pack \tcode{Flags} is one of \tcode{\exposid{convert-flag}},
\tcode{\exposid{aligned-flag}}, or \tcode{\exposid{over\-aligned-\brk{}flag}<N>}.

\rSec3[simd.flags.oper]{\tcode{flags} operators}

\indexlibrarymember{operator"|}{simd::flags}
\begin{itemdecl}
template<class... Other>
  friend consteval auto operator|(flags a, flags<Other...> b);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
  A default-initialized object of type \tcode{flags<Flags2...>} for some
  \tcode{Flags2} where every type in \tcode{Flags2} is present either in template parameter pack
  \tcode{Flags} or in template parameter pack \tcode{Other}, and every type in template parameter
  packs \tcode{Flags} and \tcode{Other} is present in \tcode{Flags2}.
  If the packs \tcode{Flags} and \tcode{Other} contain two
  different specializations \tcode{\exposid{overaligned-flag}<N1>} and
  \tcode{\exposid{overaligned-flag}<N2>}, \tcode{Flags2} is not required to contain the
  specialization \tcode{\exposid{overaligned-flag}<std::min(N1, N2)>}.
\end{itemdescr}

\rSec2[simd.iterator]{Class template \exposid{simd-iterator}}

\indexlibrarymember{iterator}{basic_vec}%
\indexlibrarymember{iterator}{basic_mask}%
\indexlibrarymember{const_iterator}{basic_vec}%
\indexlibrarymember{const_iterator}{basic_mask}%
\begin{codeblock}
namespace std::simd {
  template<class V>
  class @\exposidnc{simd-iterator}@ {                                                 // \expos
    V* @\exposid{data_}@ = nullptr;                                                 // \expos
    @\exposid{simd-size-type}@ @\exposidnc{offset_}@ = 0;                                         // \expos

    constexpr @\exposidnc{simd-iterator}@(V& d, @\exposidnc{simd-size-type}@ off) noexcept;         // \expos

  public:
    using value_type = V::value_type;
    using iterator_category = input_iterator_tag;
    using iterator_concept = random_access_iterator_tag;
    using difference_type = @\exposid{simd-size-type}@;

    constexpr @\exposid{simd-iterator}@() = default;

    constexpr @\exposid{simd-iterator}@(const @\exposid{simd-iterator}@&) = default;
    constexpr @\exposid{simd-iterator}@& operator=(const @\exposid{simd-iterator}@&) = default;

    constexpr @\exposid{simd-iterator}@(const @\exposid{simd-iterator}@<remove_const_t<V>>&) requires is_const_v<V>;

    constexpr value_type operator*() const;

    constexpr @\exposid{simd-iterator}@& operator++();
    constexpr @\exposid{simd-iterator}@ operator++(int);
    constexpr @\exposid{simd-iterator}@& operator--();
    constexpr @\exposid{simd-iterator}@ operator--(int);

    constexpr @\exposid{simd-iterator}@& operator+=(difference_type n);
    constexpr @\exposid{simd-iterator}@& operator-=(difference_type n);

    constexpr value_type operator[](difference_type n) const;

    friend constexpr bool operator==(@\exposid{simd-iterator}@ a, @\exposid{simd-iterator}@ b) = default;
    friend constexpr bool operator==(@\exposid{simd-iterator}@ a, default_sentinel_t) noexcept;
    friend constexpr auto operator<=>(@\exposid{simd-iterator}@ a, @\exposid{simd-iterator}@ b);

    friend constexpr @\exposid{simd-iterator}@ operator+(@\exposid{simd-iterator}@ i, difference_type n);
    friend constexpr @\exposid{simd-iterator}@ operator+(difference_type n, @\exposid{simd-iterator}@ i);
    friend constexpr @\exposid{simd-iterator}@ operator-(@\exposid{simd-iterator}@ i, difference_type n);

    friend constexpr difference_type operator-(@\exposid{simd-iterator}@ a, @\exposid{simd-iterator}@ b);
    friend constexpr difference_type operator-(@\exposid{simd-iterator}@ i, default_sentinel_t) noexcept;
    friend constexpr difference_type operator-(default_sentinel_t, @\exposid{simd-iterator}@ i) noexcept;
  };
}
\end{codeblock}

\begin{itemdecl}
constexpr @\exposid{simd-iterator}@(V& d, @\exposid{simd-size-type}@ off) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{data_} with \tcode{addressof(d)} and \exposid{offset_} with \tcode{off}.
\end{itemdescr}

\begin{itemdecl}
constexpr @\exposid{simd-iterator}@(const @\exposid{simd-iterator}@<remove_const_t<V>>& i) requires is_const_v<V>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes \exposid{data_} with \tcode{i.\exposid{data_}} and \exposid{offset_} with \tcode{i.\exposid{offset_}}.
\end{itemdescr}

\begin{itemdecl}
constexpr value_type operator*() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return (*\exposid{data_})[\exposid{offset_}];}
\end{itemdescr}

\begin{itemdecl}
constexpr @\exposid{simd-iterator}@& operator++();
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return *this += 1;}
\end{itemdescr}

\begin{itemdecl}
constexpr @\exposid{simd-iterator}@ operator++(int);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
@\exposid{simd-iterator}@ tmp = *this;
*this += 1;
return tmp;
\end{codeblock}
\end{itemdescr}

\begin{itemdecl}
constexpr @\exposid{simd-iterator}@& operator--();
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return *this -= 1;}
\end{itemdescr}

\begin{itemdecl}
constexpr @\exposid{simd-iterator}@ operator--(int);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
@\exposid{simd-iterator}@ tmp = *this;
*this -= 1;
return tmp;
\end{codeblock}
\end{itemdescr}

\begin{itemdecl}
constexpr @\exposid{simd-iterator}@& operator+=(difference_type n);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{\exposid{offset_} + n} is in the range \crange{0}{V::size()}.

\pnum
\effects
Equivalent to:
\begin{codeblock}
@\exposid{offset_}@ += n;
return *this;
\end{codeblock}
\end{itemdescr}

\begin{itemdecl}
constexpr @\exposid{simd-iterator}@& operator-=(difference_type n);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{\exposid{offset_} - n} is in the range \crange{0}{V::size()}.

\pnum
\effects
Equivalent to:
\begin{codeblock}
@\exposid{offset_}@ -= n;
return *this;
\end{codeblock}
\end{itemdescr}

\begin{itemdecl}
constexpr value_type operator[](difference_type n) const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return (*\exposid{data_})[\exposid{offset_} + n];}
\end{itemdescr}

\begin{itemdecl}
friend constexpr bool operator==(@\exposid{simd-iterator}@ i, default_sentinel_t) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return i.\exposid{offset_} == V::size();}
\end{itemdescr}

\begin{itemdecl}
friend constexpr auto operator<=>(@\exposid{simd-iterator}@ a, @\exposid{simd-iterator}@ b);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{a.\exposid{data_} == b.\exposid{data_}} is \tcode{true}.

\pnum
\effects
Equivalent to: \tcode{return a.\exposid{offset_} <=> b.\exposid{offset_};}
\end{itemdescr}

\begin{itemdecl}
friend constexpr @\exposid{simd-iterator}@ operator+(@\exposid{simd-iterator}@ i, difference_type n);
friend constexpr @\exposid{simd-iterator}@ operator+(difference_type n, @\exposid{simd-iterator}@ i);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return i += n;}
\end{itemdescr}

\begin{itemdecl}
friend constexpr @\exposid{simd-iterator}@ operator-(@\exposid{simd-iterator}@ i, difference_type n);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return i -= n;}
\end{itemdescr}

\begin{itemdecl}
friend constexpr difference_type operator-(@\exposid{simd-iterator}@ a, @\exposid{simd-iterator}@ b);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{a.\exposid{data_} == b.\exposid{data_}} is \tcode{true}.

\pnum
\effects
Equivalent to: \tcode{return a.\exposid{offset_} - b.\exposid{offset_};}
\end{itemdescr}

\begin{itemdecl}
friend constexpr difference_type operator-(@\exposid{simd-iterator}@ i, default_sentinel_t) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return i.\exposid{offset_} - V::size();}
\end{itemdescr}


\begin{itemdecl}
friend constexpr difference_type operator-(default_sentinel_t, @\exposid{simd-iterator}@ i) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return V::size() - i.\exposid{offset_};}
\end{itemdescr}

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

\rSec3[simd.overview]{Overview}

\indexlibraryglobal{basic_vec}%
\begin{codeblock}
namespace std::simd {
  template<class T, class Abi> class basic_vec {
    using @\exposid{real-type}@ = @\seebelow@;                // \expos
  public:
    using @\libmember{value_type}{basic_vec}@ = T;
    using @\libmember{mask_type}{basic_vec}@ = basic_mask<sizeof(T), Abi>;
    using @\libmember{abi_type}{basic_vec}@ = Abi;
    using @\libmember{iterator}{basic_vec}@ = @\exposid{simd-iterator}@<basic_vec>;
    using @\libmember{const_iterator}{basic_vec}@ = @\exposid{simd-iterator}@<const basic_vec>;

    constexpr iterator @\libmember{begin}{basic_vec}@() noexcept { return {*this, 0}; }
    constexpr const_iterator @\libmember{begin}{basic_vec}@() const noexcept { return {*this, 0}; }
    constexpr const_iterator @\libmember{cbegin}{basic_vec}@() const noexcept { return {*this, 0}; }
    constexpr default_sentinel_t @\libmember{end}{basic_vec}@() const noexcept { return {}; }
    constexpr default_sentinel_t @\libmember{cend}{basic_vec}@() const noexcept { return {}; }

    static constexpr integral_constant<@\exposid{simd-size-type}@, @\exposid{simd-size-v}@<T, Abi>> @\libmember{size}{basic_vec}@ {};

    constexpr basic_vec() noexcept = default;

    // \ref{simd.ctor}, \tcode{basic_vec} constructors
    template<class U>
      constexpr explicit(@\seebelow@) basic_vec(U&& value) noexcept;
    template<class U, class UAbi>
      constexpr explicit(@\seebelow@) basic_vec(const basic_vec<U, UAbi>&) noexcept;
    template<class G>
      constexpr explicit basic_vec(G&& gen);
    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...> = {});
    constexpr basic_vec(const @\exposid{real-type}@& reals, const @\exposid{real-type}@& imags = {}) noexcept;

    // \ref{simd.subscr}, \tcode{basic_vec} subscript operators
    constexpr value_type operator[](@\exposid{simd-size-type}@) const;
    template<@\exposconcept{simd-integral}@ I>
      constexpr resize_t<I::size(), basic_vec> operator[](const I& indices) const;

    // \ref{simd.complex.access}, \tcode{basic_vec} complex accessors
    constexpr @\exposid{real-type}@ real() const noexcept;
    constexpr @\exposid{real-type}@ imag() const noexcept;
    constexpr void real(const @\exposid{real-type}@& v) noexcept;
    constexpr void imag(const @\exposid{real-type}@& v) noexcept;

    // \ref{simd.unary}, \tcode{basic_vec} unary operators
    constexpr 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;

    // \ref{simd.binary}, \tcode{basic_vec} binary operators
    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&, const basic_vec&) noexcept;
    friend constexpr basic_vec operator<<(const basic_vec&, @\exposid{simd-size-type}@) noexcept;
    friend constexpr basic_vec operator>>(const basic_vec&, @\exposid{simd-size-type}@) noexcept;

    // \ref{simd.cassign}, \tcode{basic_vec} compound assignment
    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&, const basic_vec&) noexcept;
    friend constexpr basic_vec& operator<<=(basic_vec&, @\exposid{simd-size-type}@) noexcept;
    friend constexpr basic_vec& operator>>=(basic_vec&, @\exposid{simd-size-type}@) noexcept;

    // \ref{simd.comparison}, \tcode{basic_vec} compare operators
    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;
    friend constexpr mask_type operator<(const basic_vec&, const basic_vec&) noexcept;

    // \ref{simd.cond}, \tcode{basic_vec} exposition only conditional operators
    friend constexpr basic_vec @\exposid{simd-select-impl}@( // \expos
      const mask_type&, const basic_vec&, const basic_vec&) noexcept;
  };

  template<class R, class... Ts>
    basic_vec(R&& r, Ts...) -> @\seebelow@;

  template<size_t Bytes, class Abi>
    basic_vec(basic_mask<Bytes, Abi>) -> @\seebelow@;
}
\end{codeblock}

\pnum
Every specialization of \tcode{basic_vec} is a complete type.
The specialization of \tcode{basic_vec<T, Abi>} is
\begin{itemize}
 \item
    enabled, if \tcode{T} is a vectorizable type, and there exists value
    \tcode{N} in the range \crange{1}{64}, such that \tcode{Abi} is
    \tcode{\exposid{deduce-abi-t}<T, N>},
 \item
   otherwise, disabled, if \tcode{T} is not a vectorizable type,
 \item
   otherwise, it is \impldef{set of enabled \tcode{basic_vec<T, Abi>}
   specializations} if such a specialization is enabled.
\end{itemize}

If \tcode{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 \tcode{value_type}, \tcode{abi_type}, and
\tcode{mask_type} members are present.

If \tcode{basic_vec<T, Abi>} is enabled, then \tcode{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\iref{dcl.init.general}.

\pnum
\recommended
Implementations should support implicit conversions between specializations of
\tcode{basic_vec} and appropriate \impldef{conversions of \tcode{basic_vec}
from/to implementation-specific vector types} types.
\begin{note}
Appropriate types are non-standard vector types which are available in the
implementation.
\end{note}

\pnum
If \tcode{T} is a specialization of \tcode{complex},
\exposid{real-type} denotes the same type as
\tcode{rebind_t<typename T::value_type, basic_vec<T, Abi>>},
otherwise an unspecified non-array object type.

\rSec3[simd.ctor]{Constructors}

\indexlibraryctor{basic_vec}
\begin{itemdecl}
template<class U> constexpr explicit(@\seebelow@) basic_vec(U&& value) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
Let \tcode{From} denote the type \tcode{remove_cvref_t<U>}.

\pnum
\constraints
\tcode{U} satisfies \tcode{\exposconcept{explicitly-convertible-to}<value_type>}.

\pnum
\effects
Initializes each element to the value of the argument after conversion to
\tcode{value_type}.

\pnum
\remarks
The expression inside \tcode{explicit} evaluates to \tcode{false} if and only if
\tcode{U} satisfies \tcode{\libconcept{convertible_to}<value_type>}, and either
\begin{itemize}
 \item
   \tcode{From} is not an arithmetic type and does not satisfy
   \exposconcept{constexpr-wrapper-like},
 \item
   \tcode{From} is an arithmetic type and the conversion from \tcode{From} to
   \tcode{value_type} is value-preserving\iref{simd.general}, or
 \item
   \tcode{From} satisfies \exposconcept{constexpr-wrapper-like},
   \tcode{remove_cvref_t<decltype(From::value)>} is an arithmetic type, and
   \tcode{From::value} is representable by \tcode{value_type}.
\end{itemize}
\end{itemdescr}

\indexlibraryctor{basic_vec}
\begin{itemdecl}
template<class U, class UAbi>
  constexpr explicit(@\seebelow@) basic_vec(const basic_vec<U, UAbi>& x) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\begin{itemize}
\item \tcode{\exposid{simd-size-v}<U, UAbi> == size()} is \tcode{true}, and
\item \tcode{U} satisfies \tcode{\exposconcept{explicitly-convertible-to}<T>}.
\end{itemize}

\pnum
\effects
Initializes the $i^\text{th}$ element with \tcode{static_cast<T>(x[$i$])} for
all $i$ in the range of \range{0}{size()}.

\pnum
\remarks
The expression inside \tcode{explicit} evaluates to \tcode{true} if either
\begin{itemize}
 \item
   the conversion from \tcode{U} to \tcode{value_type} is not value-preserving,
   or
 \item
   both \tcode{U} and \tcode{value_type} are integral types and the integer
   conversion rank\iref{conv.rank} of \tcode{U} is greater than the integer
   conversion rank of \tcode{value_type}, or
 \item
   both \tcode{U} and \tcode{value_type} are floating-point types and the
   floating-point conversion rank\iref{conv.rank} of \tcode{U} is greater than
   the floating-point conversion rank of \tcode{value_type}.
\end{itemize}
\end{itemdescr}

\indexlibraryctor{basic_vec}
\begin{itemdecl}
template<class G> constexpr explicit basic_vec(G&& gen);
\end{itemdecl}

\begin{itemdescr}
\pnum
Let \tcode{From}$_i$ denote the type
\tcode{decltype(gen(integral_constant<\exposid{simd-size-type}, $i$>()))}.

\pnum
\constraints
\tcode{From}$_i$ satisfies \tcode{\libconcept{convertible_to}<value_type>} for all $i$ in
the range of \range{0}{size()}.
In addition, for all $i$ in the range of \range{0}{size()}, if \tcode{From}$_i$
is an arithmetic type, conversion from \tcode{From}$_i$ to \tcode{value_type}
is value-preserving.

\pnum
\effects
Initializes the $i^\text{th}$ element with
\tcode{static_cast<value_type>(gen(integral_constant<\exposid{simd-\brk{}size-\brk{}type},
i>()))} for all $i$ in the range of \range{0}{size()}.

\pnum
\remarks
\tcode{gen} is invoked exactly once for each $i$, in increasing order of $i$.
\end{itemdescr}

\indexlibraryctor{basic_vec}
\begin{itemdecl}
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...> = {});
\end{itemdecl}

\begin{itemdescr}
\pnum
Let \tcode{mask} be \tcode{mask_type(true)} for the overload with no
\tcode{mask} parameter.

\pnum
\constraints
\begin{itemize}
\item \tcode{R} models \tcode{ranges::\libconcept{contiguous_range}} and
  \tcode{ranges::\libconcept{sized_range}},
\item \tcode{ranges::size(r)} is a constant expression,
\item \tcode{ranges::size(r)} is equal to \tcode{size()}, and
\item \tcode{ranges::range_value_t<R>} is a vectorizable type and
  satisfies \tcode{\exposconcept{explicitly-convertible-to}<T>}.
\end{itemize}

\pnum
\mandates
If the template parameter pack \tcode{Flags} does not contain
\tcode{\exposid{convert-flag}}, then the conversion from
\tcode{ranges::range_value_t<R>} to \tcode{value_type} is value-preserving.

\pnum
\expects
\begin{itemize}
 \item
   If the template parameter pack \tcode{Flags} contains
   \tcode{\exposid{aligned-flag}}, \tcode{ranges::data(r)} points to
   storage aligned by \tcode{alignment_v<basic_vec,
   ranges::range_value_t<R>>}.
 \item
   If the template parameter pack \tcode{Flags} contains
   \tcode{\exposid{overaligned-flag}<N>}, \tcode{ranges::data(r)} points to
   storage aligned by \tcode{N}.
\end{itemize}

\pnum
\effects
Initializes the $i^\text{th}$ element with \tcode{mask[$i$] ?
static_cast<T>(\brk{}ranges::\brk{}data(r)[$i$]) : T()} for all $i$ in the
range of \range{0}{size()}.
\end{itemdescr}

\begin{itemdecl}
template<class R, class... Ts>
  basic_vec(R&& r, Ts...) -> @\seebelow@;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\begin{itemize}
\item \tcode{R} models \tcode{ranges::\libconcept{contiguous_range}} and
  \tcode{ranges::\libconcept{sized_range}}, and
\item \tcode{ranges::size(r)} is a constant expression.
\end{itemize}

\pnum
\remarks
The deduced type is equivalent to
\begin{codeblock}
vec<ranges::range_value_t<R>, static_cast<@\exposid{simd-size-type}@>(ranges::size(r))>
\end{codeblock}
\end{itemdescr}

\begin{itemdecl}
template<size_t Bytes, class Abi>
  basic_vec(basic_mask<Bytes, Abi> k) -> @\seebelow@;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{basic_mask<Bytes, Abi>} is an enabled specialization of \tcode{basic_mask} and
\tcode{decltype(+k)} is a valid type.

\pnum
\remarks
The deduced type is equivalent to \tcode{decltype(+k)}.
\end{itemdescr}

\indexlibraryctor{basic_vec}
\begin{itemdecl}
constexpr basic_vec(const @\exposid{real-type}@& reals, const @\exposid{real-type}@& imags = {}) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{\exposconcept{simd-complex}<basic_vec>} is modeled.

\pnum
\effects
Initializes the $i^\text{th}$ element with \tcode{value_type(reals[$i$],
imags[$i$])} for all $i$ in the range \range{0}{size()}.
\end{itemdescr}

\rSec3[simd.subscr]{Subscript operator}

\indexlibrarymember{operator[]}{basic_vec}
\begin{itemdecl}
constexpr value_type operator[](@\exposid{simd-size-type}@ i) const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{i >= 0 \&\& i < size()} is \tcode{true}.

\pnum
\returns
The value of the $i^\text{th}$ element.

\pnum
\throws
Nothing.
\end{itemdescr}

\indexlibrarymember{operator[]}{basic_vec}
\begin{itemdecl}
template<@\exposconcept{simd-integral}@ I>
  constexpr resize_t<I::size(), basic_vec> operator[](const I& indices) const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return permute(*this, indices);}
\end{itemdescr}

\rSec3[simd.complex.access]{Complex accessors}

\indexlibrarymember{real}{basic_vec}
\indexlibrarymember{imag}{basic_vec}
\begin{itemdecl}
constexpr @\exposid{real-type}@ real() const noexcept;
constexpr @\exposid{real-type}@ imag() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{\exposconcept{simd-complex}<basic_vec>} is modeled.

\pnum
\returns
An object of type \exposid{real-type}
where the $i^\text{th}$ element is initialized to the result of
\tcode{\placeholder{cmplx-func}(\brk{}operator[]($i$))} for all $i$ in the range
\range{0}{size()}, where \tcode{\placeholder{cmplx-func}} is the corresponding function
from \libheader{complex}.
\end{itemdescr}

\indexlibrarymember{real}{basic_vec}
\indexlibrarymember{imag}{basic_vec}
\begin{itemdecl}
constexpr void real(const @\exposid{real-type}@& v) noexcept;
constexpr void imag(const @\exposid{real-type}@& v) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{\exposconcept{simd-complex}<basic_vec>} is modeled.

\pnum
\effects
Replaces each element of the \tcode{basic_vec} object such that the
$i^\text{th}$ element is replaced with \tcode{value_type(v[$i$],
operator[]($i$).imag())} or \tcode{value_type(operator[]($i$).real(), v[$i$])}
for \tcode{real} and \tcode{imag} respectively, for all $i$ in the range \range{0}{size()}.
\end{itemdescr}

\rSec3[simd.unary]{Unary operators}

\pnum
Effects in \ref{simd.unary} are applied as unary element-wise operations.

\indexlibrarymember{operator++}{basic_vec}
\begin{itemdecl}
constexpr basic_vec& operator++() noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{requires (value_type a) \{ ++a; \}} is \tcode{true}.

\pnum
\effects
Increments every element by one.

\pnum
\returns
\tcode{*this}.
\end{itemdescr}

\indexlibrarymember{operator++}{basic_vec}
\begin{itemdecl}
constexpr basic_vec operator++(int) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{requires (value_type a) \{ a++; \}} is \tcode{true}.

\pnum
\effects
Increments every element by one.

\pnum
\returns
A copy of \tcode{*this} before incrementing.
\end{itemdescr}

\indexlibrarymember{operator--}{basic_vec}
\begin{itemdecl}
constexpr basic_vec& operator--() noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{requires (value_type a) \{ --a; \}} is \tcode{true}.

\pnum
\effects
Decrements every element by one.

\pnum
\returns
\tcode{*this}.
\end{itemdescr}

\indexlibrarymember{operator--}{basic_vec}
\begin{itemdecl}
constexpr basic_vec operator--(int) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{requires (value_type a) \{ a--; \}} is \tcode{true}.

\pnum
\effects
Decrements every element by one.

\pnum
\returns
A copy of \tcode{*this} before decrementing.
\end{itemdescr}

\indexlibrarymember{operator"!}{basic_vec}
\begin{itemdecl}
constexpr mask_type operator!() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{requires (const value_type a) \{ !a; \}} is \tcode{true}.

\pnum
\returns
A \tcode{basic_mask} object with the $i^\text{th}$ element set to
\tcode{!operator[]($i$)} for all $i$ in the range of \range{0}{size()}.
\end{itemdescr}

\indexlibrarymember{operator\~{}}{basic_vec}
\begin{itemdecl}
constexpr basic_vec operator~() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{requires (const value_type a) \{ \~{}a; \}} is \tcode{true}.

\pnum
\returns
A \tcode{basic_vec} object with the $i^\text{th}$ element set to
\tcode{\~{}operator[]($i$)} for all $i$ in the range of \range{0}{size()}.
\end{itemdescr}

\indexlibrarymember{operator+}{basic_vec}
\begin{itemdecl}
constexpr basic_vec operator+() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{requires (const value_type a) \{ +a; \}} is \tcode{true}.

\pnum
\returns
\tcode{*this}.
\end{itemdescr}

\indexlibrarymember{operator-}{basic_vec}
\begin{itemdecl}
constexpr basic_vec operator-() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{requires (const value_type a) \{ -a; \}} is \tcode{true}.

\pnum
\returns
A \tcode{basic_vec} object where the $i^\text{th}$ element is initialized to
\tcode{-operator[]($i$)} for all $i$ in the range of \range{0}{size()}.
\end{itemdescr}

\rSec2[simd.nonmembers]{\tcode{basic_vec} non-member operations}

\rSec3[simd.binary]{Binary operators}

\indexlibrarymember{operator+}{basic_vec}
\indexlibrarymember{operator-}{basic_vec}
\indexlibrarymember{operator*}{basic_vec}
\indexlibrarymember{operator/}{basic_vec}
\indexlibrarymember{operator\%}{basic_vec}
\indexlibrarymember{operator\&}{basic_vec}
\indexlibrarymember{operator"|}{basic_vec}
\indexlibrarymember{operator\caret}{basic_vec}
\indexlibrarymember{operator<<}{basic_vec}
\indexlibrarymember{operator>>}{basic_vec}
\begin{itemdecl}
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;
\end{itemdecl}

\begin{itemdescr}
\pnum
Let \placeholder{op} be the operator.

\pnum
\constraints
\tcode{requires (value_type a, value_type b) \{ a \placeholder{op} b; \}} is
\tcode{true}.

\pnum
\returns
A \tcode{basic_vec} object initialized with the results of applying
\placeholder{op} to \tcode{lhs} and \tcode{rhs} as a binary element-wise
operation.
\end{itemdescr}

\indexlibrarymember{operator<<}{basic_vec}
\indexlibrarymember{operator>>}{basic_vec}
\begin{itemdecl}
friend constexpr basic_vec operator<<(const basic_vec& v, @\exposid{simd-size-type}@ n) noexcept;
friend constexpr basic_vec operator>>(const basic_vec& v, @\exposid{simd-size-type}@ n) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
Let \placeholder{op} be the operator.

\pnum
\constraints
\tcode{requires (value_type a, \exposid{simd-size-type} b) \{ a
\placeholder{op} b; \}} is \tcode{true}.

\pnum
\returns
A \tcode{basic_vec} object where the $i^\text{th}$ element is initialized to
the result of applying \placeholder{op} to \tcode{v[$i$]} and \tcode{n} for all
$i$ in the range of \range{0}{size()}.
\end{itemdescr}

\rSec3[simd.cassign]{Compound assignment}

\indexlibrarymember{operator+=}{basic_vec}
\indexlibrarymember{operator-=}{basic_vec}
\indexlibrarymember{operator*=}{basic_vec}
\indexlibrarymember{operator/=}{basic_vec}
\indexlibrarymember{operator\%=}{basic_vec}
\indexlibrarymember{operator\&=}{basic_vec}
\indexlibrarymember{operator"|=}{basic_vec}
\indexlibrarymember{operator\caret=}{basic_vec}
\indexlibrarymember{operator<<=}{basic_vec}
\indexlibrarymember{operator>>=}{basic_vec}
\begin{itemdecl}
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;
\end{itemdecl}

\begin{itemdescr}
\pnum
Let \placeholder{op} be the operator.

\pnum
\constraints
\tcode{requires (value_type a, value_type b) \{ a \placeholder{op} b; \}} is
\tcode{true}.

\pnum
\effects
These operators apply the indicated operator to \tcode{lhs} and \tcode{rhs} as
an element-wise operation.

\pnum
\returns
\tcode{lhs}.
\end{itemdescr}

\indexlibrarymember{operator<<=}{basic_vec}
\indexlibrarymember{operator>>=}{basic_vec}
\begin{itemdecl}
friend constexpr basic_vec& operator<<=(basic_vec& lhs, @\exposid{simd-size-type}@ n) noexcept;
friend constexpr basic_vec& operator>>=(basic_vec& lhs, @\exposid{simd-size-type}@ n) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
Let \placeholder{op} be the operator.

\pnum
\constraints
\tcode{requires (value_type a, \exposid{simd-size-type} b) \{ a
\placeholder{op} b; \}} is \tcode{true}.

\pnum
\effects
Equivalent to: \tcode{return operator \placeholder{op} (lhs, basic_vec(n));}
\end{itemdescr}

\rSec3[simd.comparison]{Comparison operators}

\indexlibrarymember{operator==}{basic_vec}
\indexlibrarymember{operator"!=}{basic_vec}
\indexlibrarymember{operator>=}{basic_vec}
\indexlibrarymember{operator<=}{basic_vec}
\indexlibrarymember{operator>}{basic_vec}
\indexlibrarymember{operator<}{basic_vec}
\begin{itemdecl}
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;
\end{itemdecl}

\begin{itemdescr}
\pnum
Let \placeholder{op} be the operator.

\pnum
\constraints
\tcode{requires (value_type a, value_type b) \{ a \placeholder{op} b; \}} is
\tcode{true}.

\pnum
\returns
A \tcode{basic_mask} object initialized with the results of applying
\placeholder{op} to \tcode{lhs} and \tcode{rhs} as a binary element-wise
operation.
\end{itemdescr}

\rSec3[simd.cond]{Exposition-only conditional operators}

\begin{itemdecl}
friend constexpr basic_vec
@\exposid{simd-select-impl}@(const mask_type& mask, const basic_vec& a, const basic_vec& b) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
A \tcode{basic_vec} object where the $i^\text{th}$ element equals
\tcode{mask[$i$] ? a[$i$] : b[$i$]} for all $i$ in the range of
\range{0}{size()}.
\end{itemdescr}

\rSec3[simd.reductions]{Reductions}

\indexlibrarymember{reduce}{simd}
\begin{itemdecl}
template<class T, class Abi, class BinaryOperation = plus<>>
  constexpr T reduce(const basic_vec<T, Abi>& x, BinaryOperation binary_op = {});
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{BinaryOperation} models
\tcode{\exposconcept{reduction-binary-operation}<T>}.

\pnum
\expects
\tcode{binary_op} does not modify \tcode{x}.

\pnum
\returns
\tcode{\placeholdernc{GENERALIZED_SUM}(binary_op, vec<T, 1>(x[0]), $\ldots$,
vec<T, 1>(x[x.size() - 1]))[\brk{}0]}\iref{numerics.defns}.

\pnum
\throws
Any exception thrown from \tcode{binary_op}.
\end{itemdescr}

\indexlibrarymember{reduce}{simd}
\begin{itemdecl}
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 = @\seebelow@);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\begin{itemize}
\item
  \tcode{BinaryOperation} models
  \tcode{\exposconcept{reduction-binary-operation}<T>}.
\item
  An argument for \tcode{identity_element} is provided for the invocation,
  unless \tcode{BinaryOperation} is one of \tcode{plus<>},
  \tcode{multiplies<>}, \tcode{bit_and<>}, \tcode{bit_or<>}, or
  \tcode{bit_xor<>}.
\end{itemize}

\pnum
\expects
\begin{itemize}
 \item
   \tcode{binary_op} does not modify \tcode{x}.
 \item
   For all finite values \tcode{y} representable by \tcode{T}, the results of
   \tcode{y == binary_op(vec<T, 1>(iden\-ti\-ty\-_\-element), vec<T,
   1>(y))[0]} and \tcode{y == binary_op(vec<T, 1>(y), vec<T,
   1>(iden\-ti\-ty\-_\-element))[0]} are \tcode{true}.
\end{itemize}

\pnum
\returns
If \tcode{none_of(mask)} is \tcode{true}, returns \tcode{identity_element}.
Otherwise, returns \tcode{\placeholdernc{GENERALIZED_SUM}(binary_op, vec<T,
1>(x[$k_0$]), $\ldots$, vec<T, 1>(x[$k_n$]))[0]} where $k_0, \ldots, k_n$ are
the selected indices of \tcode{mask}.

\pnum
\throws
Any exception thrown from \tcode{binary_op}.

\pnum
\remarks
The default argument for \tcode{identity_element} is equal to
\begin{itemize}
\item \tcode{T()} if \tcode{BinaryOperation} is \tcode{plus<>},
\item \tcode{T(1)} if \tcode{BinaryOperation} is \tcode{multiplies<>},
\item \tcode{T(\~{}T())} if \tcode{BinaryOperation} is \tcode{bit_and<>},
\item \tcode{T()} if \tcode{BinaryOperation} is \tcode{bit_or<>}, or
\item \tcode{T()} if \tcode{BinaryOperation} is \tcode{bit_xor<>}.
\end{itemize}
\end{itemdescr}

\indexlibrarymember{reduce_min}{simd}
\begin{itemdecl}
template<class T, class Abi> constexpr T reduce_min(const basic_vec<T, Abi>& x) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{T} models \libconcept{totally_ordered}.

\pnum
\returns
The value of an element \tcode{x[$j$]} for which \tcode{x[$i$] < x[$j$]} is
\tcode{false} for all $i$ in the range of \range{0}{basic_vec<T, Abi>::size()}.
\end{itemdescr}

\indexlibrarymember{reduce_min}{simd}
\begin{itemdecl}
template<class T, class Abi>
  constexpr T reduce_min(
    const basic_vec<T, Abi>&, const typename basic_vec<T, Abi>::mask_type&) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{T} models \libconcept{totally_ordered}.

\pnum
\returns
If \tcode{none_of(mask)} is \tcode{true}, returns
\tcode{numeric_limits<T>::max()}.
Otherwise, returns the value of a selected element \tcode{x[$j$]} for which
\tcode{x[$i$] < x[$j$]} is \tcode{false} for all selected indices $i$ of
\tcode{mask}.
\end{itemdescr}

\indexlibrarymember{reduce_max}{simd}
\begin{itemdecl}
template<class T, class Abi> constexpr T reduce_max(const basic_vec<T, Abi>& x) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{T} models \libconcept{totally_ordered}.

\pnum
\returns
The value of an element \tcode{x[$j$]} for which \tcode{x[$j$] < x[$i$]} is
\tcode{false} for all $i$ in the range of \range{0}{basic_vec<T, Abi>::size()}.
\end{itemdescr}

\indexlibrarymember{reduce_max}{simd}
\begin{itemdecl}
template<class T, class Abi>
  constexpr T reduce_max(
    const basic_vec<T, Abi>&, const typename basic_vec<T, Abi>::mask_type&) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{T} models \libconcept{totally_ordered}.

\pnum
\returns
If \tcode{none_of(mask)} is \tcode{true}, returns
\tcode{numeric_limits<V::value_type>::lowest()}.
Otherwise, returns the value of a selected element \tcode{x[$j$]} for which
\tcode{x[$j$] < x[$i$]} is \tcode{false} for all selected indices $i$ of
\tcode{mask}.
\end{itemdescr}

\rSec3[simd.loadstore]{Load and store functions}

\indexlibrarymember{unchecked_load}{simd}
\begin{itemdecl}
template<class V = @\seebelow@, ranges::@\libconcept{contiguous_range}@ R, class... Flags>
  requires ranges::@\libconcept{sized_range}@<R>
  constexpr V unchecked_load(R&& r, flags<Flags...> f = {});
template<class V = @\seebelow@, ranges::@\libconcept{contiguous_range}@ R, class... Flags>
  requires ranges::@\libconcept{sized_range}@<R>
  constexpr V unchecked_load(R&& r, const typename V::mask_type& mask, flags<Flags...> f = {});
template<class V = @\seebelow@, @\libconcept{contiguous_iterator}@ I, class... Flags>
  constexpr V unchecked_load(I first, iter_difference_t<I> n, flags<Flags...> f = {});
template<class V = @\seebelow@, @\libconcept{contiguous_iterator}@ 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 = @\seebelow@, @\libconcept{contiguous_iterator}@ I, @\libconcept{sized_sentinel_for}@<I> S, class... Flags>
  constexpr V unchecked_load(I first, S last, flags<Flags...> f = {});
template<class V = @\seebelow@, @\libconcept{contiguous_iterator}@ I, @\libconcept{sized_sentinel_for}@<I> S, class... Flags>
  constexpr V unchecked_load(I first, S last, const typename V::mask_type& mask,
                             flags<Flags...> f = {});
\end{itemdecl}

\begin{itemdescr}
\pnum
Let
\begin{itemize}
 \item
   \tcode{mask} be \tcode{V::mask_type(true)} for the overloads with no
   \tcode{mask} parameter;
 \item
   \tcode{R} be \tcode{span<const iter_value_t<I>>} for the overloads with no
   template parameter \tcode{R};
 \item
   \tcode{r} be \tcode{R(first, n)} for the overloads with an \tcode{n}
   parameter and \tcode{R(first, last)} for the overloads with a \tcode{last}
   parameter.
\end{itemize}

\pnum
\mandates
If \tcode{ranges::size(r)} is a constant expression then
\tcode{ranges::size(r)} $\ge$ \tcode{V::size()}.

\pnum
\expects
\begin{itemize}
\item \range{first}{first + n} is a valid range for the overloads with an
  \tcode{n} parameter.
\item \range{first}{last} is a valid range for the overloads with a
  \tcode{last} parameter.
\item \tcode{ranges::size(r)} $\ge$ \tcode{V::size()}
\end{itemize}

\pnum
\effects
Equivalent to: \tcode{return partial_load<V>(r, mask, f);}

\pnum
\remarks
The default argument for template parameter \tcode{V} is
\tcode{basic_vec<ranges::range_value_t<R>>}.
\end{itemdescr}

\indexlibrarymember{partial_load}{simd}
\begin{itemdecl}
template<class V = @\seebelow@, ranges::@\libconcept{contiguous_range}@ R, class... Flags>
  requires ranges::@\libconcept{sized_range}@<R>
  constexpr V partial_load(R&& r, flags<Flags...> f = {});
template<class V = @\seebelow@, ranges::@\libconcept{contiguous_range}@ R, class... Flags>
  requires ranges::@\libconcept{sized_range}@<R>
  constexpr V partial_load(R&& r, const typename V::mask_type& mask, flags<Flags...> f = {});
template<class V = @\seebelow@, @\libconcept{contiguous_iterator}@ I, class... Flags>
  constexpr V partial_load(I first, iter_difference_t<I> n, flags<Flags...> f = {});
template<class V = @\seebelow@, @\libconcept{contiguous_iterator}@ 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 = @\seebelow@, @\libconcept{contiguous_iterator}@ I, @\libconcept{sized_sentinel_for}@<I> S, class... Flags>
  constexpr V partial_load(I first, S last, flags<Flags...> f = {});
template<class V = @\seebelow@, @\libconcept{contiguous_iterator}@ I, @\libconcept{sized_sentinel_for}@<I> S, class... Flags>
  constexpr V partial_load(I first, S last, const typename V::mask_type& mask,
                           flags<Flags...> f = {});
\end{itemdecl}

\begin{itemdescr}
\pnum
Let
\begin{itemize}
 \item
   \tcode{mask} be \tcode{V::mask_type(true)} for the overloads with no
   \tcode{mask} parameter;
 \item
   \tcode{R} be \tcode{span<const iter_value_t<I>>} for the overloads with no
   template parameter \tcode{R};
 \item
   \tcode{r} be \tcode{R(first, n)} for the overloads with an \tcode{n}
   parameter and \tcode{R(first, last)} for the overloads with a \tcode{last}
   parameter;
 \item
  \tcode{T} be \tcode{typename V::value_type}.
\end{itemize}

\pnum
\mandates
\begin{itemize}
 \item
   \tcode{ranges::range_value_t<R>} is a vectorizable type and
   satisfies \tcode{\exposconcept{explicitly-convertible-to}<T>},
 \item
   \tcode{\libconcept{same_as}<remove_cvref_t<V>, V>} is \tcode{true},
 \item
   \tcode{V} is an enabled specialization of \tcode{basic_vec}, and
 \item
   if the template parameter pack \tcode{Flags} does not contain
   \tcode{\exposid{convert-flag}}, then the conversion from
   \tcode{ranges::range_value_t<R>} to \tcode{V::value_type} is
   value-preserving.
\end{itemize}

\pnum
\expects
\begin{itemize}
 \item
   \range{first}{first + n} is a valid range for the overloads with an
   \tcode{n} parameter.
 \item
   \range{first}{last} is a valid range for the overloads with a \tcode{last}
   parameter.
 \item
   If the template parameter pack \tcode{Flags} contains
   \tcode{\exposid{aligned-flag}}, \tcode{ranges::data(r)} points to storage
   aligned by \tcode{alignment_v<V, ranges::range_value_t<R>>}.
 \item
   If the template parameter pack \tcode{Flags} contains
   \tcode{\exposid{overaligned-flag}<N>}, \tcode{ranges::data(r)} points to
   storage aligned by \tcode{N}.
\end{itemize}

\pnum
\returns
A \tcode{basic_vec} object whose $i^\text{th}$ element is initialized with
\tcode{mask[$i$] \&\& $i$ < ranges::size(r) ?
static_cast<T>(\brk{}ranges::data(r)[$i$]) : T()} for all $i$ in the range of
\range{0}{V::size()},
where \tcode{T} is \tcode{V::value_type}.

\pnum
\remarks
The default argument for template parameter \tcode{V} is
\tcode{basic_vec<ranges::range_value_t<R>>}.
\end{itemdescr}

\indexlibrarymember{unchecked_store}{simd}
\begin{itemdecl}
template<class T, class Abi, ranges::@\libconcept{contiguous_range}@ R, class... Flags>
  requires ranges::@\libconcept{sized_range}@<R>
  constexpr void unchecked_store(const basic_vec<T, Abi>& v, R&& r, flags<Flags...> f = {});
template<class T, class Abi, ranges::@\libconcept{contiguous_range}@ R, class... Flags>
  requires ranges::@\libconcept{sized_range}@<R>
  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, @\libconcept{contiguous_iterator}@ I, class... Flags>
  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, @\libconcept{contiguous_iterator}@ I, class... Flags>
  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, @\libconcept{contiguous_iterator}@ I, @\libconcept{sized_sentinel_for}@<I> S, class... Flags>
  constexpr void unchecked_store(const basic_vec<T, Abi>& v, I first, S last,
                                 flags<Flags...> f = {});
template<class T, class Abi, @\libconcept{contiguous_iterator}@ I, @\libconcept{sized_sentinel_for}@<I> S, class... Flags>
  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 = {});
\end{itemdecl}

\begin{itemdescr}
\pnum
Let
\begin{itemize}
 \item
   \tcode{mask} be \tcode{basic_vec<T, Abi>::mask_type(true)} for the
   overloads with no \tcode{mask} parameter;
 \item
   \tcode{R} be \tcode{span<iter_value_t<I>>} for the overloads with no
   template parameter \tcode{R};
 \item
   \tcode{r} be \tcode{R(first, n)} for the overloads with an \tcode{n}
   parameter and \tcode{R(first, last)} for the overloads with a \tcode{last}
   parameter.
\end{itemize}

\pnum
\mandates
If \tcode{ranges::size(r)} is a constant expression then
\tcode{ranges::size(r)} $\ge$ \tcode{\exposid{simd-size-v}<T, Abi>}.

\pnum
\expects
\begin{itemize}
 \item
   \range{first}{first + n} is a valid range for the overloads with an
   \tcode{n} parameter.
 \item
   \range{first}{last} is a valid range for the overloads with a \tcode{last}
   parameter.
 \item
   \tcode{ranges::size(r)} $\ge$ \tcode{\exposid{simd-size-v}<T, Abi>}
\end{itemize}

\pnum
\effects
Equivalent to: \tcode{partial_store(v, r, mask, f)}.
\end{itemdescr}

\indexlibrarymember{partial_store}{simd}
\begin{itemdecl}
template<class T, class Abi, ranges::@\libconcept{contiguous_range}@ R, class... Flags>
  requires ranges::@\libconcept{sized_range}@<R>
  constexpr void partial_store(const basic_vec<T, Abi>& v, R&& r, flags<Flags...> f = {});
template<class T, class Abi, ranges::@\libconcept{contiguous_range}@ R, class... Flags>
  requires ranges::@\libconcept{sized_range}@<R>
  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, @\libconcept{contiguous_iterator}@ I, class... Flags>
  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, @\libconcept{contiguous_iterator}@ I, class... Flags>
  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, @\libconcept{contiguous_iterator}@ I, @\libconcept{sized_sentinel_for}@<I> S, class... Flags>
  constexpr void partial_store(const basic_vec<T, Abi>& v, I first, S last,
                               flags<Flags...> f = {});
template<class T, class Abi, @\libconcept{contiguous_iterator}@ I, @\libconcept{sized_sentinel_for}@<I> S, class... Flags>
  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 = {});
\end{itemdecl}

\begin{itemdescr}
\pnum
Let
\begin{itemize}
 \item
   \tcode{mask} be \tcode{basic_vec<T, Abi>::mask_type(true)} for the
   overloads with no \tcode{mask} parameter;
 \item
   \tcode{R} be \tcode{span<iter_value_t<I>>} for the overloads with no
   template parameter \tcode{R};
 \item
   \tcode{r} be \tcode{R(first, n)} for the overloads with an \tcode{n}
   parameter and \tcode{R(first, last)} for the overloads with a \tcode{last}
   parameter.
\end{itemize}

\pnum
\constraints
\begin{itemize}
 \item
   \tcode{ranges::iterator_t<R>} models
   \tcode{\libconcept{indirectly_writable}<ranges::range_value_t<R>>}, and
 \item
  \tcode{T} satisfies
  \tcode{\exposconcept{explicitly-convertible-to}<ranges::range_value_t<R>>}.
\end{itemize}

\pnum
\mandates
\begin{itemize}
 \item
   \tcode{ranges::range_value_t<R>} is a vectorizable type, and
 \item
   if the template parameter pack \tcode{Flags} does not contain
   \tcode{\exposid{convert-flag}}, then the conversion from \tcode{T} to
   \tcode{ranges::range_value_t<R>} is value-preserving.
\end{itemize}

\pnum
\expects
\begin{itemize}
 \item
   \range{first}{first + n} is a valid range for the overloads with an
   \tcode{n} parameter.
 \item
   \range{first}{last} is a valid range for the overloads with a \tcode{last}
   parameter.
 \item
   If the template parameter pack \tcode{Flags} contains
   \tcode{\exposid{aligned-flag}}, \tcode{ranges::data(r)} points to storage
   aligned by \tcode{alignment_v<basic_vec<T, Abi>,
   ranges::range_value_t<R>>}.
 \item
   If the template parameter pack \tcode{Flags} contains
   \tcode{\exposid{overaligned-flag}<N>}, \tcode{ranges::data(r)} points to
   storage aligned by \tcode{N}.
\end{itemize}

\pnum
\effects
For all $i$ in the range of \range{0}{basic_vec<T, Abi>::size()}, if
\tcode{mask[$i$] \&\& $i$ < ranges::\brk{}size(r)} is \tcode{true}, evaluates
\tcode{ranges::data(r)[$i$] = static_cast<ranges::range_value_t<R>>(v[\brk{}$i$])}.
\end{itemdescr}

\rSec3[simd.permute.static]{Static permute}

\indexlibrarymember{permute}{simd}
\begin{itemdecl}
template<@\exposid{simd-size-type}@ N = @\seebelow@, @\exposconcept{simd-vec-type}@ V, class IdxMap>
  constexpr resize_t<N, V> permute(const V& v, IdxMap&& idxmap);
template<@\exposid{simd-size-type}@ N = @\seebelow@, @\exposconcept{simd-mask-type}@ V, class IdxMap>
  constexpr resize_t<N, V> 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
At least one of
\tcode{invoke_result_t<IdxMap\&, \exposid{simd-size-type}>}
and
\tcode{invoke_result_t<IdxMap\&, \exposid{simd-size-type}, \exposid{simd-size-type}>}
satisfies \libconcept{integral}.

\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 data-parallel 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]{Dynamic permute}

\indexlibrarymember{permute}{simd}
\begin{itemdecl}
template<@\exposconcept{simd-vec-type}@ V, @\exposconcept{simd-integral}@ I>
  constexpr resize_t<I::size(), V> permute(const V& v, const I& indices);
template<@\exposconcept{simd-mask-type}@ V, @\exposconcept{simd-integral}@ I>
  constexpr resize_t<I::size(), V> 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 data-parallel 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]{Mask permute}

\indexlibrarymember{compress}{simd}
\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<V>& 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 data-parallel 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}

\indexlibrarymember{compress}{simd}
\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<V>& 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 data-parallel 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}

\indexlibrarymember{expand}{simd}
\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<V>& 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}, in ascending order.
\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 data-parallel 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]{Memory permute}

\indexlibrarymember{unchecked_gather_from}{simd}
\begin{itemdecl}
template<class V = @\seebelow@, ranges::@\libconcept{contiguous_range}@ R, @\exposconcept{simd-integral}@ I, class... Flags>
  requires ranges::@\libconcept{sized_range}@<R>
  constexpr V unchecked_gather_from(R&& in, const I& indices, flags<Flags...> f = {});
template<class V = @\seebelow@, ranges::@\libconcept{contiguous_range}@ R, @\exposconcept{simd-integral}@ I, class... Flags>
  requires ranges::@\libconcept{sized_range}@<R>
  constexpr V unchecked_gather_from(R&& in, const typename I::mask_type& mask,
                                    const I& indices, flags<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<V>(in, mask, indices, f);}

\pnum
\remarks
The default argument for template parameter \tcode{V} is
\tcode{vec<ranges::range_value_t<R>, I::\brk{}size()>}.
\end{itemdescr}

\indexlibrarymember{partial_gather_from}{simd}
\begin{itemdecl}
template<class V = @\seebelow@, ranges::@\libconcept{contiguous_range}@ R, @\exposconcept{simd-integral}@ I, class... Flags>
  requires ranges::@\libconcept{sized_range}@<R>
  constexpr V partial_gather_from(R&& in, const I& indices, flags<Flags...> f = {});
template<class V = @\seebelow@, ranges::@\libconcept{contiguous_range}@ R, @\exposconcept{simd-integral}@ I, class... Flags>
  requires ranges::@\libconcept{sized_range}@<R>
  constexpr V partial_gather_from(R&& in, const typename I::mask_type& mask,
                                  const I& indices, flags<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
\constraints
\tcode{ranges::range_value_t<R>} is a vectorizable type and satisfies
\tcode{\exposconceptx{explicitly-convert\-ible-to}{explicitly-convertible-to}<T>}.

\pnum
\mandates
\begin{itemize}
\item
\tcode{ranges::range_value_t<R>} is a vectorizable type,
\item
\tcode{\libconcept{same_as}<remove_cvref_t<V>, V>} is \tcode{true},
\item
\tcode{V} is an enabled specialization of \tcode{basic_vec},
\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<R>} 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<V, ranges::range_value_t<R>>}.
\item
If the template parameter pack \tcode{Flags} contains
\tcode{\exposid{overaligned-flag}<N>}, \tcode{ranges::data(in)} points to
storage aligned by \tcode{N}.
\end{itemize}

\pnum
\returns
A \tcode{basic_vec} object where the $i^\text{th}$
element is initialized to the result of
\begin{codeblock}
mask[@$i$@] && indices[@$i$@] < ranges::size(in) ? static_cast<T>(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{vec<ranges::range_value_t<R>, I::\brk{}size()>}.
\end{itemdescr}

\indexlibrarymember{unchecked_scatter_to}{simd}
\begin{itemdecl}
template<@\exposconcept{simd-vec-type}@ V, ranges::@\libconcept{contiguous_range}@ R, @\exposconcept{simd-integral}@ I, class... Flags>
  requires ranges::@\libconcept{sized_range}@<R>
  constexpr void unchecked_scatter_to(const V& v, R&& out, const I& indices,
                                      flags<Flags...> f = {});
template<@\exposconcept{simd-vec-type}@ V, ranges::@\libconcept{contiguous_range}@ R, @\exposconcept{simd-integral}@ I, class... Flags>
  requires ranges::@\libconcept{sized_range}@<R>
  constexpr void unchecked_scatter_to(const V& v, R&& out, const typename I::mask_type& mask,
                                      const I& indices, flags<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}

\indexlibrarymember{partial_scatter_to}{simd}
\begin{itemdecl}
template<@\exposconcept{simd-vec-type}@ V, ranges::@\libconcept{contiguous_range}@ R, @\exposconcept{simd-integral}@ I, class... Flags>
  requires ranges::@\libconcept{sized_range}@<R>
  constexpr void
  partial_scatter_to(const V& v, R&& out, const I& indices, flags<Flags...> f = {});
template<@\exposconcept{simd-vec-type}@ V, ranges::@\libconcept{contiguous_range}@ R, @\exposconcept{simd-integral}@ I, class... Flags>
  requires ranges::@\libconcept{sized_range}@<R>
  constexpr void partial_scatter_to(const V& v, R&& out, const typename I::mask_type& mask,
                                    const I& indices, flags<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
\begin{itemize}
\item
\tcode{V::size() == I::size()} is \tcode{true},
\item
\tcode{ranges::iterator_t<R>} models
\tcode{\libconcept{indirectly_writable}<ranges::range_value_t<R>>}, and
\item
\tcode{typename V::value_type} satisfies
\tcode{\exposconcept{explicitly-convertible-to}<ranges::range_value_t<R\linebreak{}>>}.
\end{itemize}

\pnum
\mandates
\begin{itemize}
\item
\tcode{ranges::range_value_t<R>} 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<R>} 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<V, ranges::range_value_t<R>>}.
\item
If the template parameter pack \tcode{Flags} contains
\tcode{\exposid{overaligned-flag}<N>},
\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$]] = static_cast<ranges::range_value_t<R>>(v[\brk{}$i$])}.
\end{itemdescr}

\rSec3[simd.creation]{Creation}

\indexlibrarymember{chunk}{simd}
\begin{itemdecl}
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<@\exposid{mask-element-size}@<T>, Abi>& x) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\begin{itemize}
 \item
   For the first overload,
   \tcode{T} is an enabled specialization of \tcode{basic_vec}.
   If \tcode{basic_vec<\brk{}typename T::\brk{}value_type, Abi>::size() \% T::size()}
   is not \tcode{0}, then
   \tcode{resize_t<basic_vec<\brk{}typename T::\brk{}value_type, Abi>::size()
   \% T::size(), T>} is valid and denotes a type.

 \item
   For the second overload,
   \tcode{T} is an enabled specialization of \tcode{basic_mask}.
   If \tcode{basic_mask<\exposid{mask-el\-e\-ment-size}<T>, Abi>::size() \% T::size()}
   is not \tcode{0}, then
   \tcode{resize_t<\brk{}basic_mask<\brk{}\exposid{mask-el\-e\-ment-size}<T>,
   Abi>::size() \% T::size(), T>} is valid and denotes a type.
\end{itemize}

\pnum
Let $N$ be \tcode{x.size() / T::size()}.

\pnum
\returns
\begin{itemize}
 \item
   If \tcode{x.size() \% T::size() == 0} is \tcode{true}, an \tcode{array<T,
   $N$>} with the $i^\text{th}$ \tcode{basic_vec} or \tcode{basic_mask}
   element of the $j^\text{th}$ \tcode{array} element initialized to the value
   of the element in \tcode{x} with index \tcode{$i$ + $j$ * T::size()}.

 \item
   Otherwise, a \tcode{tuple} of $N$ objects of type \tcode{T} and one object
   of type \tcode{resize_t<x.size() \% T::size(), T>}.
   The $i^\text{th}$ \tcode{basic_vec} or \tcode{basic_mask} element of
   the $j^\text{th}$ \tcode{tuple} element of type \tcode{T} is initialized to
   the value of the element in \tcode{x} with index \tcode{$i$ + $j$ *
   T::size()}.
   The $i^\text{th}$ \tcode{basic_vec} or \tcode{basic_mask} element of
   the $N^\text{th}$ \tcode{tuple} element is initialized to the value of the
   element in \tcode{x} with index \tcode{$i$ + $N$ * T::size()}.
\end{itemize}
\end{itemdescr}

\indexlibrarymember{chunk}{simd}
\begin{itemdecl}
template<@\exposid{simd-size-type}@ N, class T, class Abi>
  constexpr auto chunk(const basic_vec<T, Abi>& x) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return chunk<resize_t<N, basic_vec<T, Abi>>>(x);}
\end{itemdescr}

\indexlibrarymember{chunk}{simd}
\begin{itemdecl}
template<@\exposid{simd-size-type}@ N, size_t Bytes, class Abi>
  constexpr auto chunk(const basic_mask<Bytes, Abi>& x) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return chunk<resize_t<N, basic_mask<Bytes, Abi>>>(x);}
\end{itemdescr}

\indexlibrarymember{cat}{simd}
\begin{itemdecl}
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, @\exposid{deduce-abi-t}@<@\exposid{integer-from}@<Bytes>,
                            (basic_mask<Bytes, Abis>::size() + ...)>>
    cat(const basic_mask<Bytes, Abis>&... xs) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\begin{itemize}
 \item
   For the first overload \tcode{vec<T, (basic_vec<T, Abis>::size() + ...)>}
   is enabled.
 \item
   For the second overload
   \tcode{basic_mask<Bytes,
   \exposid{deduce-abi-t}<\exposid{integer-from}<Bytes>,
   (basic_mask<Bytes, Abis>::size() + ...)>>} is enabled.
\end{itemize}

\pnum
\returns
A data-parallel object initialized with the concatenated values in the
\tcode{xs} pack of data-parallel objects: The $i^\text{th}$
\tcode{basic_vec}/\tcode{basic_mask} element of the $j^\text{th}$
parameter in the \tcode{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 \tcode{xs}
pack.
\end{itemdescr}

\rSec3[simd.alg]{Algorithms}

\indexlibrarymember{min}{simd}
\begin{itemdecl}
template<class T, class Abi>
  constexpr basic_vec<T, Abi> min(const basic_vec<T, Abi>& a,
                                  const basic_vec<T, Abi>& b) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{T} models \libconcept{totally_ordered}.

\pnum
\returns
The result of the element-wise application of \tcode{min(a[$i$], b[$i$])} for
all $i$ in the range of \range{0}{basic_vec<T, Abi>::size()}.
\end{itemdescr}

\indexlibrarymember{max}{simd}
\begin{itemdecl}
template<class T, class Abi>
  constexpr basic_vec<T, Abi> max(const basic_vec<T, Abi>& a,
                                  const basic_vec<T, Abi>& b) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{T} models \libconcept{totally_ordered}.

\pnum
\returns
The result of the element-wise application of \tcode{max(a[$i$], b[$i$])} for
all $i$ in the range of \range{0}{basic_vec<T, Abi>::size()}.
\end{itemdescr}

\indexlibrarymember{minmax}{simd}
\begin{itemdecl}
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;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return pair\{min(a, b), max(a, b)\};}
\end{itemdescr}

\indexlibrarymember{clamp}{simd}
\begin{itemdecl}
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);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{T} models \libconcept{totally_ordered}.

\pnum
\expects
No element in \tcode{lo} is greater than the corresponding element in
\tcode{hi}.

\pnum
\returns
The result of element-wise application of \tcode{clamp(v[$i$], lo[$i$],
hi[$i$])} for all $i$ in the range of \range{0}{basic_vec<T, Abi>::size()}.
\end{itemdescr}

\indexlibrarymember{select}{simd}
\begin{itemdecl}
template<class T, class U>
  constexpr auto select(bool c, const T& a, const U& b)
  -> remove_cvref_t<decltype(c ? a : b)>;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return c ? a : b;}
\end{itemdescr}

\indexlibrarymember{select}{simd}
\begin{itemdecl}
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(@\exposid{simd-select-impl}@(c, a, b));
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
return @\exposid{simd-select-impl}@(c, a, b);
\end{codeblock}
where \tcode{\exposid{simd-select-impl}} is found by argument-dependent
lookup\iref{basic.lookup.argdep} contrary to \ref{contents}.
\end{itemdescr}

\rSec3[simd.math]{Mathematical functions}

\indexlibrarymember{ilogb}{simd}
\indexlibrarymember{ldexp}{simd}
\indexlibrarymember{scalbn}{simd}
\indexlibrarymember{scalbln}{simd}
\indexlibrarymember{abs}{simd}
\indexlibrarymember{abs}{simd}
\indexlibrarymember{fabs}{simd}
\indexlibrarymember{ceil}{simd}
\indexlibrarymember{floor}{simd}
\indexlibrarymember{nearbyint}{simd}
\indexlibrarymember{rint}{simd}
\indexlibrarymember{lrint}{simd}
\indexlibrarymember{llrint}{simd}
\indexlibrarymember{round}{simd}
\indexlibrarymember{lround}{simd}
\indexlibrarymember{llround}{simd}
\indexlibrarymember{fmod}{simd}
\indexlibrarymember{trunc}{simd}
\indexlibrarymember{remainder}{simd}
\indexlibrarymember{copysign}{simd}
\indexlibrarymember{nextafter}{simd}
\indexlibrarymember{fdim}{simd}
\indexlibrarymember{fmax}{simd}
\indexlibrarymember{fmin}{simd}
\indexlibrarymember{fma}{simd}
\indexlibrarymember{fpclassify}{simd}
\indexlibrarymember{isfinite}{simd}
\indexlibrarymember{isinf}{simd}
\indexlibrarymember{isnan}{simd}
\indexlibrarymember{isnormal}{simd}
\indexlibrarymember{signbit}{simd}
\indexlibrarymember{isgreater}{simd}
\indexlibrarymember{isgreaterequal}{simd}
\indexlibrarymember{isless}{simd}
\indexlibrarymember{islessequal}{simd}
\indexlibrarymember{islessgreater}{simd}
\indexlibrarymember{isunordered}{simd}
\begin{itemdecl}
template<@\exposconcept{math-floating-point}@ V>
  constexpr rebind_t<int, @\exposid{deduced-vec-t}@<V>> ilogb(const V& x);
template<@\exposconcept{math-floating-point}@ V>
  constexpr @\exposid{deduced-vec-t}@<V> ldexp(const V& x, const rebind_t<int, @\exposid{deduced-vec-t}@<V>>& exp);
template<@\exposconcept{math-floating-point}@ V>
  constexpr @\exposid{deduced-vec-t}@<V> scalbn(const V& x, const rebind_t<int, @\exposid{deduced-vec-t}@<V>>& n);
template<@\exposconcept{math-floating-point}@ V>
  constexpr @\exposid{deduced-vec-t}@<V>
    scalbln(const V& x, const rebind_t<long int, @\exposid{deduced-vec-t}@<V>>& n);
template<@\libconcept{signed_integral}@ T, class Abi>
  constexpr basic_vec<T, Abi> abs(const basic_vec<T, Abi>& j);
template<@\exposconcept{math-floating-point}@ V>
  constexpr @\exposid{deduced-vec-t}@<V> abs(const V& j);
template<@\exposconcept{math-floating-point}@ V>
  constexpr @\exposid{deduced-vec-t}@<V> fabs(const V& x);
template<@\exposconcept{math-floating-point}@ V>
  constexpr @\exposid{deduced-vec-t}@<V> ceil(const V& x);
template<@\exposconcept{math-floating-point}@ V>
  constexpr @\exposid{deduced-vec-t}@<V> floor(const V& x);
template<@\exposconcept{math-floating-point}@ V>
  @\exposid{deduced-vec-t}@<V> nearbyint(const V& x);
template<@\exposconcept{math-floating-point}@ V>
  @\exposid{deduced-vec-t}@<V> rint(const V& x);
template<@\exposconcept{math-floating-point}@ V>
  rebind_t<long int, @\exposid{deduced-vec-t}@<V>> lrint(const V& x);
template<@\exposconcept{math-floating-point}@ V>
  rebind_t<long long int, @\exposid{deduced-vec-t}@<V>> llrint(const V& x);
template<@\exposconcept{math-floating-point}@ V>
  constexpr @\exposid{deduced-vec-t}@<V> round(const V& x);
template<@\exposconcept{math-floating-point}@ V>
  constexpr rebind_t<long int, @\exposid{deduced-vec-t}@<V>> lround(const V& x);
template<@\exposconcept{math-floating-point}@ V>
  constexpr rebind_t<long long int, @\exposid{deduced-vec-t}@<V>> llround(const V& x);
template<class V0, class V1>
  constexpr @\exposid{math-common-simd-t}@<V0, V1> fmod(const V0& x, const V1& y);
template<@\exposconcept{math-floating-point}@ V>
  constexpr @\exposid{deduced-vec-t}@<V> trunc(const V& x);
template<class V0, class V1>
  constexpr @\exposid{math-common-simd-t}@<V0, V1> remainder(const V0& x, const V1& y);
template<class V0, class V1>
  constexpr @\exposid{math-common-simd-t}@<V0, V1> copysign(const V0& x, const V1& y);
template<class V0, class V1>
  constexpr @\exposid{math-common-simd-t}@<V0, V1> nextafter(const V0& x, const V1& y);
template<class V0, class V1>
  constexpr @\exposid{math-common-simd-t}@<V0, V1> fdim(const V0& x, const V1& y);
template<class V0, class V1>
  constexpr @\exposid{math-common-simd-t}@<V0, V1> fmax(const V0& x, const V1& y);
template<class V0, class V1>
  constexpr @\exposid{math-common-simd-t}@<V0, V1> fmin(const V0& x, const V1& y);
template<class V0, class V1, class V2>
  constexpr @\exposid{math-common-simd-t}@<V0, V1, V2> fma(const V0& x, const V1& y, const V2& z);
template<@\exposconcept{math-floating-point}@ V>
  constexpr rebind_t<int, @\exposid{deduced-vec-t}@<V>> fpclassify(const V& x);
template<@\exposconcept{math-floating-point}@ V>
  constexpr typename @\exposid{deduced-vec-t}@<V>::mask_type isfinite(const V& x);
template<@\exposconcept{math-floating-point}@ V>
  constexpr typename @\exposid{deduced-vec-t}@<V>::mask_type isinf(const V& x);
template<@\exposconcept{math-floating-point}@ V>
  constexpr typename @\exposid{deduced-vec-t}@<V>::mask_type isnan(const V& x);
template<@\exposconcept{math-floating-point}@ V>
  constexpr typename @\exposid{deduced-vec-t}@<V>::mask_type isnormal(const V& x);
template<@\exposconcept{math-floating-point}@ V>
  constexpr typename @\exposid{deduced-vec-t}@<V>::mask_type signbit(const V& x);
template<class V0, class V1>
  constexpr typename @\exposid{math-common-simd-t}@<V0, V1>::mask_type isgreater(const V0& x, const V1& y);
template<class V0, class V1>
  constexpr typename @\exposid{math-common-simd-t}@<V0, V1>::mask_type
    isgreaterequal(const V0& x, const V1& y);
template<class V0, class V1>
  constexpr typename @\exposid{math-common-simd-t}@<V0, V1>::mask_type isless(const V0& x, const V1& y);
template<class V0, class V1>
  constexpr typename @\exposid{math-common-simd-t}@<V0, V1>::mask_type islessequal(const V0& x, const V1& y);
template<class V0, class V1>
  constexpr typename @\exposid{math-common-simd-t}@<V0, V1>::mask_type islessgreater(const V0& x, const V1& y);
template<class V0, class V1>
  constexpr typename @\exposid{math-common-simd-t}@<V0, V1>::mask_type isunordered(const V0& x, const V1& y);
\end{itemdecl}

\begin{itemdescr}
\pnum
Let \tcode{Ret} denote the return type of the specialization of a function
template with the name \tcode{\placeholder{math-func}}.
Let \tcode{\placeholder{math-func-vec}} denote:
\begin{codeblock}
template<class... Args>
Ret @\placeholder{math-func-vec}@(Args... args) {
  return Ret([&](@\exposid{simd-size-type}@ i) {
    return @\placeholder{math-func}@(@\exposid{make-compatible-simd-t}@<Ret, Args>(args)[i]...);
  });
}
\end{codeblock}

\pnum
\returns
A value \tcode{ret} of type \tcode{Ret}, that is element-wise equal to the
result of calling \tcode{\placeholder{math-func-vec}} with the arguments of the above
functions.
If in an invocation of a scalar overload of \tcode{\placeholder{math-func}} for index
\tcode{i} in \tcode{\placeholder{math-func-vec}} a domain, pole, or range error would
occur, the value of \tcode{ret[i]} is unspecified.

\pnum
\remarks
It is unspecified whether \tcode{errno}\iref{errno} is accessed.
\end{itemdescr}

\indexlibrarymember{acos}{simd}
\indexlibrarymember{asin}{simd}
\indexlibrarymember{atan}{simd}
\indexlibrarymember{atan2}{simd}
\indexlibrarymember{cos}{simd}
\indexlibrarymember{sin}{simd}
\indexlibrarymember{tan}{simd}
\indexlibrarymember{acosh}{simd}
\indexlibrarymember{asinh}{simd}
\indexlibrarymember{atanh}{simd}
\indexlibrarymember{cosh}{simd}
\indexlibrarymember{sinh}{simd}
\indexlibrarymember{tanh}{simd}
\indexlibrarymember{exp}{simd}
\indexlibrarymember{exp2}{simd}
\indexlibrarymember{expm1}{simd}
\indexlibrarymember{log}{simd}
\indexlibrarymember{log10}{simd}
\indexlibrarymember{log1p}{simd}
\indexlibrarymember{log2}{simd}
\indexlibrarymember{logb}{simd}
\indexlibrarymember{cbrt}{simd}
\indexlibrarymember{hypot}{simd}
\indexlibrarymember{hypot}{simd}
\indexlibrarymember{pow}{simd}
\indexlibrarymember{sqrt}{simd}
\indexlibrarymember{erf}{simd}
\indexlibrarymember{erfc}{simd}
\indexlibrarymember{lgamma}{simd}
\indexlibrarymember{tgamma}{simd}
\indexlibrarymember{lerp}{simd}
\indexlibrarymember{assoc_laguerre}{simd}
\indexlibrarymember{assoc_legendre}{simd}
\indexlibrarymember{beta}{simd}
\indexlibrarymember{comp_ellint_1}{simd}
\indexlibrarymember{comp_ellint_2}{simd}
\indexlibrarymember{comp_ellint_3}{simd}
\indexlibrarymember{cyl_bessel_i}{simd}
\indexlibrarymember{cyl_bessel_j}{simd}
\indexlibrarymember{cyl_bessel_k}{simd}
\indexlibrarymember{cyl_neumann}{simd}
\indexlibrarymember{ellint_1}{simd}
\indexlibrarymember{ellint_2}{simd}
\indexlibrarymember{ellint_3}{simd}
\indexlibrarymember{expint}{simd}
\indexlibrarymember{hermite}{simd}
\indexlibrarymember{laguerre}{simd}
\indexlibrarymember{legendre}{simd}
\indexlibrarymember{riemann_zeta}{simd}
\indexlibrarymember{sph_bessel}{simd}
\indexlibrarymember{sph_legendre}{simd}
\indexlibrarymember{sph_neumann}{simd}
\begin{itemdecl}
template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-vec-t}@<V> acos(const V& x);
template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-vec-t}@<V> asin(const V& x);
template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-vec-t}@<V> atan(const V& x);
template<class V0, class V1>
  constexpr @\exposid{math-common-simd-t}@<V0, V1> atan2(const V0& y, const V1& x);
template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-vec-t}@<V> cos(const V& x);
template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-vec-t}@<V> sin(const V& x);
template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-vec-t}@<V> tan(const V& x);
template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-vec-t}@<V> acosh(const V& x);
template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-vec-t}@<V> asinh(const V& x);
template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-vec-t}@<V> atanh(const V& x);
template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-vec-t}@<V> cosh(const V& x);
template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-vec-t}@<V> sinh(const V& x);
template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-vec-t}@<V> tanh(const V& x);
template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-vec-t}@<V> exp(const V& x);
template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-vec-t}@<V> exp2(const V& x);
template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-vec-t}@<V> expm1(const V& x);
template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-vec-t}@<V> log(const V& x);
template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-vec-t}@<V> log10(const V& x);
template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-vec-t}@<V> log1p(const V& x);
template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-vec-t}@<V> log2(const V& x);
template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-vec-t}@<V> logb(const V& x);
template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-vec-t}@<V> cbrt(const V& x);
template<class V0, class V1>
  constexpr @\exposid{math-common-simd-t}@<V0, V1> hypot(const V0& x, const V1& y);
template<class V0, class V1, class V2>
  constexpr @\exposid{math-common-simd-t}@<V0, V1, V2> hypot(const V0& x, const V1& y, const V2& z);
template<class V0, class V1>
  constexpr @\exposid{math-common-simd-t}@<V0, V1> pow(const V0& x, const V1& y);
template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-vec-t}@<V> sqrt(const V& x);
template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-vec-t}@<V> erf(const V& x);
template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-vec-t}@<V> erfc(const V& x);
template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-vec-t}@<V> lgamma(const V& x);
template<@\exposconcept{math-floating-point}@ V> constexpr @\exposid{deduced-vec-t}@<V> tgamma(const V& x);
template<class V0, class V1, class V2>
  constexpr @\exposid{math-common-simd-t}@<V0, V1, V2> lerp(const V0& a, const V1& b, const V2& t) noexcept;
template<@\exposconcept{math-floating-point}@ V>
  @\exposid{deduced-vec-t}@<V> assoc_laguerre(const rebind_t<unsigned, @\exposid{deduced-vec-t}@<V>>& n, const
    rebind_t<unsigned, @\exposid{deduced-vec-t}@<V>>& m, const V& x);
template<@\exposconcept{math-floating-point}@ V>
  @\exposid{deduced-vec-t}@<V> assoc_legendre(const rebind_t<unsigned, @\exposid{deduced-vec-t}@<V>>& l, const
    rebind_t<unsigned, @\exposid{deduced-vec-t}@<V>>& m, const V& x);
template<class V0, class V1>
  @\exposid{math-common-simd-t}@<V0, V1> beta(const V0& x, const V1& y);
template<@\exposconcept{math-floating-point}@ V> @\exposid{deduced-vec-t}@<V> comp_ellint_1(const V& k);
template<@\exposconcept{math-floating-point}@ V> @\exposid{deduced-vec-t}@<V> comp_ellint_2(const V& k);
template<class V0, class V1>
  @\exposid{math-common-simd-t}@<V0, V1> comp_ellint_3(const V0& k, const V1& nu);
template<class V0, class V1>
  @\exposid{math-common-simd-t}@<V0, V1> cyl_bessel_i(const V0& nu, const V1& x);
template<class V0, class V1>
  @\exposid{math-common-simd-t}@<V0, V1> cyl_bessel_j(const V0& nu, const V1& x);
template<class V0, class V1>
  @\exposid{math-common-simd-t}@<V0, V1> cyl_bessel_k(const V0& nu, const V1& x);
template<class V0, class V1>
  @\exposid{math-common-simd-t}@<V0, V1> cyl_neumann(const V0& nu, const V1& x);
template<class V0, class V1>
  @\exposid{math-common-simd-t}@<V0, V1> ellint_1(const V0& k, const V1& phi);
template<class V0, class V1>
  @\exposid{math-common-simd-t}@<V0, V1> ellint_2(const V0& k, const V1& phi);
template<class V0, class V1, class V2>
  @\exposid{math-common-simd-t}@<V0, V1, V2> ellint_3(const V0& k, const V1& nu, const V2& phi);
template<@\exposconcept{math-floating-point}@ V> @\exposid{deduced-vec-t}@<V> expint(const V& x);
template<@\exposconcept{math-floating-point}@ V> @\exposid{deduced-vec-t}@<V> hermite(const rebind_t<unsigned,
@\exposid{deduced-vec-t}@<V>>& n, const V& x);
template<@\exposconcept{math-floating-point}@ V> @\exposid{deduced-vec-t}@<V> laguerre(const rebind_t<unsigned,
@\exposid{deduced-vec-t}@<V>>& n, const V& x);
template<@\exposconcept{math-floating-point}@ V> @\exposid{deduced-vec-t}@<V> legendre(const rebind_t<unsigned,
@\exposid{deduced-vec-t}@<V>>& l, const V& x);
template<@\exposconcept{math-floating-point}@ V> @\exposid{deduced-vec-t}@<V> riemann_zeta(const V& x);
template<@\exposconcept{math-floating-point}@ V> @\exposid{deduced-vec-t}@<V> sph_bessel(const rebind_t<unsigned,
@\exposid{deduced-vec-t}@<V>>& n, const V& x);
template<@\exposconcept{math-floating-point}@ V>
  @\exposid{deduced-vec-t}@<V> sph_legendre(const rebind_t<unsigned, @\exposid{deduced-vec-t}@<V>>& l,
                                 const rebind_t<unsigned, @\exposid{deduced-vec-t}@<V>>& m,
                                 const V& theta);
template<@\exposconcept{math-floating-point}@ V> @\exposid{deduced-vec-t}@<V> sph_neumann(const rebind_t<unsigned,
@\exposid{deduced-vec-t}@<V>>& n, const V& x);
\end{itemdecl}

\begin{itemdescr}
\pnum
Let \tcode{Ret} denote the return type of the specialization of a function
template with the name \tcode{\placeholder{math-func}}.
Let \tcode{\placeholder{math-func-vec}} denote:
\begin{codeblock}
template<class... Args>
Ret @\placeholder{math-func-vec}@(Args... args) {
  return Ret([&](@\exposid{simd-size-type}@ i) {
    return @\placeholder{math-func}@(@\exposid{make-compatible-simd-t}@<Ret, Args>(args)[i]...);
  });
}
\end{codeblock}

\pnum
\returns
A value \tcode{ret} of type \tcode{Ret}, that is element-wise approximately
equal to the result of calling \tcode{\placeholder{math-func-vec}} with the arguments
of the above functions.
If in an invocation of a scalar overload of \tcode{\placeholder{math-func}} for index
\tcode{i} in \tcode{\placeholder{math-func-vec}} a domain, pole, or range error would
occur, the value of \tcode{ret[i]} is unspecified.

\pnum
\remarks
It is unspecified whether \tcode{errno}\iref{errno} is accessed.
\end{itemdescr}

\indexlibrarymember{frexp}{simd}
\begin{itemdecl}
template<@\exposconcept{math-floating-point}@ V>
  constexpr @\exposid{deduced-vec-t}@<V> frexp(const V& value, rebind_t<int, @\exposid{deduced-vec-t}@<V>>* exp);
\end{itemdecl}

\begin{itemdescr}
\pnum
Let \tcode{Ret} be \tcode{\exposid{deduced-vec-t}<V>}.
Let \tcode{\placeholder{frexp-vec}} denote:
\begin{codeblock}
template<class V>
pair<Ret, rebind_t<int, Ret>> @\placeholder{frexp-vec}@(const V& x) {
  int r1[Ret::size()];
  Ret r0([&](@\exposid{simd-size-type}@ i) {
    return frexp(@\exposid{make-compatible-simd-t}@<Ret, V>(x)[i], &r1[i]);
  });
  return {r0, rebind_t<int, Ret>(r1)};
}
\end{codeblock}
Let \tcode{ret} be a value of type \tcode{pair<Ret, rebind_t<int, Ret>>}
that is the same value as the result of calling
\tcode{\placeholder{frexp-vec}(x)}.

\pnum
\effects
Sets \tcode{*exp} to \tcode{ret.second}.

\pnum
\returns
\tcode{ret.first}.
\end{itemdescr}

\indexlibrarymember{remquo}{simd}
\begin{itemdecl}
template<class V0, class V1>
  constexpr @\exposid{math-common-simd-t}@<V0, V1> remquo(const V0& x, const V1& y,
                                              rebind_t<int, @\exposid{math-common-simd-t}@<V0, V1>>* quo);
\end{itemdecl}

\begin{itemdescr}
\pnum
Let \tcode{Ret} be \tcode{\exposid{math-common-simd-t}<V0, V1>}.
Let \tcode{\placeholder{remquo-vec}} denote:
\begin{codeblock}
template<class V0, class V1>
pair<Ret, rebind_t<int, Ret>> @\placeholder{remquo-vec}@(const V0& x, const V1& y) {
  int r1[Ret::size()];
  Ret r0([&](@\exposid{simd-size-type}@ i) {
    return remquo(@\exposid{make-compatible-simd-t}@<Ret, V0>(x)[i],
                  @\exposid{make-compatible-simd-t}@<Ret, V1>(y)[i], &r1[i]);
  });
  return {r0, rebind_t<int, Ret>(r1)};
}
\end{codeblock}
Let \tcode{ret} be a value of type \tcode{pair<Ret, rebind_t<int, Ret>>}
that is the same value as the result of calling
\tcode{\placeholder{remquo-vec}(x, y)}.
If in an invocation of a scalar overload of \tcode{remquo} for index \tcode{i}
in \tcode{\placeholder{remquo-vec}} a domain, pole, or range error would occur, the
value of \tcode{ret[i]} is unspecified.

\pnum
\effects
Sets \tcode{*quo} to \tcode{ret.second}.

\pnum
\returns
\tcode{ret.first}.

\pnum
\remarks
It is unspecified whether \tcode{errno}\iref{errno} is accessed.
\end{itemdescr}

\indexlibrarymember{modf}{simd}
\begin{itemdecl}
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);
\end{itemdecl}

\begin{itemdescr}
\pnum
Let \tcode{V} be \tcode{basic_vec<T, Abi>}.
Let \tcode{\placeholder{modf-vec}} denote:
\begin{codeblock}
pair<V, V> @\placeholder{modf-vec}@(const V& x) {
  T r1[Ret::size()];
  V r0([&](@\exposid{simd-size-type}@ i) {
    return modf(V(x)[i], &r1[i]);
  });
  return {r0, V(r1)};
}
\end{codeblock}
Let \tcode{ret} be a value of type \tcode{pair<V, V>} that is the same value as
the result of calling \tcode{\placeholder{modf-vec}(value)}.

\pnum
\effects
Sets \tcode{*iptr} to \tcode{ret.second}.

\pnum
\returns
\tcode{ret.first}.
\end{itemdescr}

\rSec3[simd.bit]{Bit manipulation}

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

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

\pnum
\returns
A \tcode{basic_vec} 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}

\indexlibrarymember{bit_ceil}{simd}
\begin{itemdecl}
template<@\exposconcept{simd-vec-type}@ V> constexpr V bit_ceil(const V& v);
\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_vec} 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.core}.
\end{itemdescr}

\indexlibrarymember{bit_floor}{simd}
\begin{itemdecl}
template<@\exposconcept{simd-vec-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_vec} 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}

\indexlibrarymember{has_single_bit}{simd}
\begin{itemdecl}
template<@\exposconcept{simd-vec-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_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}

\indexlibrarymember{rotl}{simd}
\indexlibrarymember{rotr}{simd}
\begin{itemdecl}
template<@\exposconcept{simd-vec-type}@ V0, @\exposconcept{simd-vec-type}@ V1>
  constexpr V0 rotl(const V0& v0, const V1& v1) noexcept;
template<@\exposconcept{simd-vec-type}@ V0, @\exposconcept{simd-vec-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 \libconcept{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_vec} 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 \tcode{\placeholder{bit-func}} is the corresponding scalar function from \libheader{bit}.
\end{itemdescr}

\indexlibrarymember{rotl}{simd}
\indexlibrarymember{rotr}{simd}
\begin{itemdecl}
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}
\pnum
\constraints
The type \tcode{V::value_type} is an unsigned integer type\iref{basic.fundamental}.

\pnum
\returns
A \tcode{basic_vec} 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 \tcode{\placeholder{bit-func}} is the corresponding
scalar function from \libheader{bit}.
\end{itemdescr}

\indexlibrarymember{bit_width}{simd}
\indexlibrarymember{countl_zero}{simd}
\indexlibrarymember{countl_one}{simd}
\indexlibrarymember{countr_zero}{simd}
\indexlibrarymember{countr_one}{simd}
\indexlibrarymember{popcount}{simd}
\begin{itemdecl}
template<@\exposconcept{simd-vec-type}@ V>
  constexpr rebind_t<make_signed_t<typename V::value_type>, V> bit_width(const V& v) noexcept;
template<@\exposconcept{simd-vec-type}@ V>
  constexpr rebind_t<make_signed_t<typename V::value_type>, V> countl_zero(const V& v) noexcept;
template<@\exposconcept{simd-vec-type}@ V>
  constexpr rebind_t<make_signed_t<typename V::value_type>, V> countl_one(const V& v) noexcept;
template<@\exposconcept{simd-vec-type}@ V>
  constexpr rebind_t<make_signed_t<typename V::value_type>, V> countr_zero(const V& v) noexcept;
template<@\exposconcept{simd-vec-type}@ V>
  constexpr rebind_t<make_signed_t<typename V::value_type>, V> countr_one(const V& v) noexcept;
template<@\exposconcept{simd-vec-type}@ V>
  constexpr rebind_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_vec} 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 \tcode{\placeholder{bit-func}} is the corresponding scalar
function from \libheader{bit}.
\end{itemdescr}

\rSec3[simd.complex.math]{Complex math}

\indexlibrarymember{real}{simd}
\indexlibrarymember{imag}{simd}
\indexlibrarymember{abs}{simd}
\indexlibrarymember{arg}{simd}
\indexlibrarymember{norm}{simd}
\indexlibrarymember{conj}{simd}
\indexlibrarymember{proj}{simd}
\indexlibrarymember{exp}{simd}
\indexlibrarymember{log}{simd}
\indexlibrarymember{log10}{simd}
\indexlibrarymember{sqrt}{simd}
\indexlibrarymember{sin}{simd}
\indexlibrarymember{asin}{simd}
\indexlibrarymember{cos}{simd}
\indexlibrarymember{acos}{simd}
\indexlibrarymember{tan}{simd}
\indexlibrarymember{atan}{simd}
\indexlibrarymember{sinh}{simd}
\indexlibrarymember{asinh}{simd}
\indexlibrarymember{cosh}{simd}
\indexlibrarymember{acosh}{simd}
\indexlibrarymember{tanh}{simd}
\indexlibrarymember{atanh}{simd}
\begin{itemdecl}
template<@\exposconcept{simd-complex}@ V>
  constexpr rebind_t<@\exposid{simd-complex-value-type<V>}@, V> real(const V&) noexcept;
template<@\exposconcept{simd-complex}@ V>
  constexpr rebind_t<@\exposid{simd-complex-value-type<V>}@, V> imag(const V&) noexcept;

template<@\exposconcept{simd-complex}@ V>
  constexpr rebind_t<@\exposid{simd-complex-value-type<V>}@, V> abs(const V&);
template<@\exposconcept{simd-complex}@ V>
  constexpr rebind_t<@\exposid{simd-complex-value-type<V>}@, V> arg(const V&);
template<@\exposconcept{simd-complex}@ V>
  constexpr rebind_t<@\exposid{simd-complex-value-type<V>}@, V> norm(const V&);
template<@\exposconcept{simd-complex}@ V> constexpr V conj(const V&);
template<@\exposconcept{simd-complex}@ V> constexpr V proj(const V&);

template<@\exposconcept{simd-complex}@ V> constexpr V exp(const V& v);
template<@\exposconcept{simd-complex}@ V> constexpr V log(const V& v);
template<@\exposconcept{simd-complex}@ V> constexpr V log10(const V& v);

template<@\exposconcept{simd-complex}@ V> constexpr V sqrt(const V& v);
template<@\exposconcept{simd-complex}@ V> constexpr V sin(const V& v);
template<@\exposconcept{simd-complex}@ V> constexpr V asin(const V& v);
template<@\exposconcept{simd-complex}@ V> constexpr V cos(const V& v);
template<@\exposconcept{simd-complex}@ V> constexpr V acos(const V& v);
template<@\exposconcept{simd-complex}@ V> constexpr V tan(const V& v);
template<@\exposconcept{simd-complex}@ V> constexpr V atan(const V& v);
template<@\exposconcept{simd-complex}@ V> constexpr V sinh(const V& v);
template<@\exposconcept{simd-complex}@ V> constexpr V asinh(const V& v);
template<@\exposconcept{simd-complex}@ V> constexpr V cosh(const V& v);
template<@\exposconcept{simd-complex}@ V> constexpr V acosh(const V& v);
template<@\exposconcept{simd-complex}@ V> constexpr V tanh(const V& v);
template<@\exposconcept{simd-complex}@ V> constexpr V atanh(const V& v);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
A \tcode{basic_vec} object \tcode{ret} where the $i^\text{th}$ element is
initialized to the result of \tcode{\placeholder{cmplx-func}(v[$i$])} for all
$i$ in the range \range{0}{V::size()}, where \tcode{\placeholder{cmplx-func}} is the
corresponding function from \libheader{complex}. If in an invocation of
\tcode{\placeholder{cmplx-func}} for index $i$ a domain, pole, or range error would
occur, the value of \tcode{ret[$i$]} is unspecified.

\pnum
\remarks
It is unspecified whether \tcode{errno}\iref{errno} is accessed.
\end{itemdescr}

\indexlibrarymember{polar}{simd}
\indexlibrarymember{pow}{simd}
\begin{itemdecl}
template<@\exposconcept{simd-floating-point}@ V>
  rebind_t<complex<typename V::value_type>, V> polar(const V& x, const V& y = {});

template<@\exposconcept{simd-complex}@ V> constexpr V pow(const V& x, const V& y);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
A \tcode{basic_vec} object \tcode{ret} where the $i^\text{th}$ element is
initialized to the result of \tcode{\placeholder{cmplx-func}(x[$i$], y[$i$])}
for all $i$ in the range \range{0}{V::size()}, where \tcode{\placeholder{cmplx-func}}
is the corresponding function from \libheader{complex}. If in an invocation of
\tcode{\placeholder{cmplx-func}} for index $i$ a domain, pole, or range error would
occur, the value of \tcode{ret[$i$]} is unspecified.

\pnum
\remarks
It is unspecified whether \tcode{errno}\iref{errno} is accessed.
\end{itemdescr}

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

\rSec3[simd.mask.overview]{Overview}

\begin{codeblock}
namespace std::simd {
  template<size_t Bytes, class Abi> class basic_mask {
  public:
    using @\libmember{value_type}{basic_mask}@ = bool;
    using @\libmember{abi_type}{basic_mask}@ = Abi;
    using @\libmember{iterator}{basic_mask}@ = @\exposid{simd-iterator}@<basic_mask>;
    using @\libmember{const_iterator}{basic_mask}@ = @\exposid{simd-iterator}@<const basic_mask>;

    constexpr iterator @\libmember{begin}{basic_mask}@() noexcept { return {*this, 0}; }
    constexpr const_iterator @\libmember{begin}{basic_mask}@() const noexcept { return {*this, 0}; }
    constexpr const_iterator @\libmember{cbegin}{basic_mask}@() const noexcept { return {*this, 0}; }
    constexpr default_sentinel_t @\libmember{end}{basic_mask}@() const noexcept { return {}; }
    constexpr default_sentinel_t @\libmember{cend}{basic_mask}@() const noexcept { return {}; }

    static constexpr integral_constant<@\exposid{simd-size-type}@, @\exposid{simd-size-v}@<@\exposid{integer-from}@<Bytes>, Abi>>
      @\libmember{size}{basic_mask}@ {};

    constexpr basic_mask() noexcept = default;

    // \ref{simd.mask.ctor}, \tcode{basic_mask} constructors
    constexpr explicit basic_mask(@\libconcept{same_as}@<value_type> auto) noexcept;
    template<size_t UBytes, class UAbi>
      constexpr explicit basic_mask(const basic_mask<UBytes, UAbi>&) noexcept;
    template<class G>
      constexpr explicit basic_mask(G&& gen);
    template<@\libconcept{same_as}@<bitset<size()>> T>
      constexpr basic_mask(const T& b) noexcept;
    template<@\libconcept{unsigned_integral}@ T>
      requires (!@\libconcept{same_as}@<T, value_type>)
      constexpr explicit basic_mask(T val) noexcept;

    // \ref{simd.mask.subscr}, \tcode{basic_mask} subscript operators
    constexpr value_type operator[](@\exposid{simd-size-type}@) const;
    template<@\exposconcept{simd-integral}@ I>
      constexpr resize_t<I::size(), basic_mask> operator[](const I& indices) const;

    // \ref{simd.mask.unary}, \tcode{basic_mask} unary operators
    constexpr basic_mask operator!() const noexcept;
    constexpr @\seebelow@ operator+() const noexcept;
    constexpr @\seebelow@ operator-() const noexcept;
    constexpr @\seebelow@ operator~() const noexcept;

    // \ref{simd.mask.conv}, \tcode{basic_mask} conversions
    template<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;

    // \ref{simd.mask.binary}, \tcode{basic_mask} binary operators
    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;

    // \ref{simd.mask.cassign}, \tcode{basic_mask} compound assignment
    friend 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;

    // \ref{simd.mask.comparison}, \tcode{basic_mask} comparisons
    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;
    friend constexpr basic_mask
      operator<(const basic_mask&, const basic_mask&) noexcept;

    // \ref{simd.mask.cond}, \tcode{basic_mask} exposition only conditional operators
    friend constexpr basic_mask @\exposid{simd-select-impl}@( // \expos
      const basic_mask&, const basic_mask&, const basic_mask&) noexcept;
    friend constexpr basic_mask @\exposid{simd-select-impl}@( // \expos
      const basic_mask&, @\libconcept{same_as}@<bool> auto, @\libconcept{same_as}@<bool> auto) noexcept;
    template<class T0, class T1>
      friend constexpr vec<@\seebelow@, size()>
        @\exposid{simd-select-impl}@(const basic_mask&, const T0&, const T1&) noexcept; // \expos
  };
}
\end{codeblock}

\pnum
Every specialization of \tcode{basic_mask} is a complete type.
The specialization of \tcode{basic_mask<Bytes, Abi>} is:
\begin{itemize}
 \item
   disabled, if there is no vectorizable type \tcode{T} such that \tcode{Bytes}
   is equal to \tcode{sizeof(T)},
 \item
   otherwise, enabled, if there exists a vectorizable type \tcode{T} and a
   value \tcode{N} in the range \crange{1}{64} such that \tcode{Bytes} is equal
   to \tcode{sizeof(T)} and \tcode{Abi} is \tcode{\exposid{deduce-abi-t}<T,
   N>},
 \item
   otherwise, it is \impldef{set of enabled \tcode{basic_mask<Bytes, Abi>}
   specializations} if such a specialization is enabled.
\end{itemize}

If \tcode{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 \tcode{value_type} and \tcode{abi_type} members are
present.

If \tcode{basic_mask<Bytes, Abi>} is enabled,
\tcode{basic_mask<Bytes, Abi>} is trivially copyable.

\pnum
\recommended Implementations should support implicit conversions between
specializations of \tcode{basic_mask} and appropriate \impldef{conversions
of \tcode{basic_mask} from/to implementation-specific vector types} types.
\begin{note}
Appropriate types are non-standard vector types which are available in the
implementation.
\end{note}

\rSec3[simd.mask.ctor]{Constructors}

\indexlibraryctor{basic_mask}
\begin{itemdecl}
constexpr explicit basic_mask(@\libconcept{same_as}@<value_type> auto) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes each element with \tcode{x}.
\end{itemdescr}

\indexlibraryctor{basic_mask}
\begin{itemdecl}
template<size_t UBytes, class UAbi>
  constexpr explicit basic_mask(const basic_mask<UBytes, UAbi>& x) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{basic_mask<UBytes, UAbi>::size() == size()} is
\tcode{true}.

\pnum
\effects
Initializes the $i^\text{th}$ element with \tcode{x[$i$]} for all $i$ in the
range of \range{0}{size()}.
\end{itemdescr}

\indexlibraryctor{basic_mask}
\begin{itemdecl}
template<class G> constexpr explicit basic_mask(G&& gen);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
The expression \tcode{gen(integral_constant<\exposid{simd-size-type}, i>())} is
well-formed and its type is \tcode{bool} for all $i$ in the range of
\range{0}{size()}.

\pnum
\effects
Initializes the $i^\text{th}$ element with
\tcode{gen(integral_constant<\exposid{simd-size-type}, i>())} for all $i$ in
the range of \range{0}{size()}.

\pnum
\remarks
\tcode{gen} is invoked exactly once for each $i$, in increasing order of $i$.
\end{itemdescr}

\indexlibraryctor{basic_mask}
\begin{itemdecl}
template<@\libconcept{same_as}@<bitset<size()>> T>
  constexpr basic_mask(const T& b) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes the $i^\text{th}$ element with \tcode{b[$i$]} for all $i$ in the
range \range{0}{size()}.
\end{itemdescr}

\indexlibraryctor{basic_mask}
\begin{itemdecl}
template<@\libconcept{unsigned_integral}@ T>
  requires (!@\libconcept{same_as}@<T, value_type>)
  constexpr explicit basic_mask(T val) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Initializes the first $M$ elements to the corresponding bit values in
\tcode{val}, where $M$ is the smaller of \tcode{size()} and the number of bits in
the value representation\iref{basic.types.general} of the type of \tcode{val}. If
$M$ is less than \tcode{size()}, the remaining elements are initialized to
zero.
\end{itemdescr}

\rSec3[simd.mask.subscr]{Subscript operator}

\indexlibrarymember{operator[]}{basic_mask}
\begin{itemdecl}
constexpr value_type operator[](@\exposid{simd-size-type}@ i) const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{i >= 0 \&\& i < size()} is \tcode{true}.

\pnum
\returns
The value of the $i^\text{th}$ element.

\pnum
\throws
Nothing.
\end{itemdescr}

\indexlibrarymember{operator[]}{basic_mask}
\begin{itemdecl}
template<@\exposconcept{simd-integral}@ I>
  constexpr resize_t<I::size(), basic_mask> operator[](const I& indices) const;
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to: \tcode{return permute(*this, indices);}
\end{itemdescr}

\rSec3[simd.mask.unary]{Unary operators}

\indexlibrarymember{operator"!}{basic_mask}
\indexlibrarymember{operator+}{basic_mask}
\indexlibrarymember{operator-}{basic_mask}
\indexlibrarymember{operator\~{}}{basic_mask}
\begin{itemdecl}
constexpr basic_mask operator!() const noexcept;
constexpr @\seebelow@ operator+() const noexcept;
constexpr @\seebelow@ operator-() const noexcept;
constexpr @\seebelow@ operator~() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
Let \placeholder{op} be the operator.

\pnum
\returns
A data-parallel object where the $i^\text{th}$ element is initialized to the
results of applying \placeholder{op} to \tcode{operator[]($i$)} for all $i$ in
the range of \range{0}{size()}.

\pnum
\remarks
If there exists a vectorizable signed integer type \tcode{I} such that
\tcode{sizeof(I) == Bytes} is \tcode{true},
\tcode{operator+}, \tcode{operator-}, and \tcode{operator~}
return an enabled specialization \tcode{R} of \tcode{basic_vec} such that
\tcode{R::value_type} denotes \tcode{\exposid{integer-from}<Bytes>} and
\tcode{R::size() == size()} is \tcode{true}.
Otherwise,
these operators are defined as deleted and their return types are unspecified.
\end{itemdescr}

\rSec3[simd.mask.conv]{Conversions}

\indexlibrarymember{operator basic_vec}{basic_mask}
\begin{itemdecl}
template<class U, class A>
  constexpr explicit(sizeof(U) != Bytes) operator basic_vec<U, A>() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\tcode{\exposid{simd-size-v}<U, A> == \exposid{simd-size-v}<T, Abi>}.

\pnum
\returns
A data-parallel object where the $i^\text{th}$ element is initialized to
\tcode{static_cast<U>(operator[]($i$))}.
\end{itemdescr}

\indexlibrarymember{to_bitset}{basic_mask}
\begin{itemdecl}
constexpr bitset<size()> to_bitset() const noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
A \tcode{bitset<size()>} object where the $i^\text{th}$ element is initialized to
\tcode{operator[]($i$)} for all $i$ in the range \range{0}{size()}.
\end{itemdescr}

\indexlibrarymember{to_ullong}{basic_mask}
\begin{itemdecl}
constexpr unsigned long long to_ullong() const;
\end{itemdecl}

\begin{itemdescr}
\pnum
Let $N$ be the width of \tcode{unsigned long long}.

\pnum
\expects
\begin{itemize}
\item \tcode{size() <= $N$} is \tcode{true}, or
\item for all $i$ in the range \range{$N$}{size()}, \tcode{operator[]($i$)} returns \tcode{false}.
\end{itemize}

\pnum
\returns
The integral value corresponding to the bits in \tcode{*this}.

\pnum
\throws
Nothing.
\end{itemdescr}

\rSec2[simd.mask.nonmembers]{\tcode{basic_mask} non-member operations}

\rSec3[simd.mask.binary]{Binary operators}

\indexlibrarymember{operator\&\&}{basic_mask}
\indexlibrarymember{operator"|"|}{basic_mask}
\indexlibrarymember{operator\&}{basic_mask}
\indexlibrarymember{operator"|}{basic_mask}
\indexlibrarymember{operator\caret}{basic_mask}
\begin{itemdecl}
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;
\end{itemdecl}

\begin{itemdescr}
\pnum
Let \placeholder{op} be the operator.

\pnum
\returns
A \tcode{basic_mask} object initialized with the results of applying
\placeholder{op} to \tcode{lhs} and \tcode{rhs} as a binary element-wise
operation.
\end{itemdescr}

\rSec3[simd.mask.cassign]{Compound assignment}

\indexlibrarymember{operator\&=}{basic_mask}
\indexlibrarymember{operator"|=}{basic_mask}
\indexlibrarymember{operator\caret=}{basic_mask}
\begin{itemdecl}
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;
\end{itemdecl}

\begin{itemdescr}
\pnum
Let \placeholder{op} be the operator.

\pnum
\effects
These operators apply \placeholder{op} to \tcode{lhs} and \tcode{rhs} as a
binary element-wise operation.

\pnum
\returns
\tcode{lhs}.
\end{itemdescr}

\rSec3[simd.mask.comparison]{Comparisons}

\indexlibrarymember{operator==}{basic_mask}
\indexlibrarymember{operator"!=}{basic_mask}
\indexlibrarymember{operator>=}{basic_mask}
\indexlibrarymember{operator<=}{basic_mask}
\indexlibrarymember{operator<}{basic_mask}
\indexlibrarymember{operator>}{basic_mask}
\begin{itemdecl}
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;
\end{itemdecl}

\begin{itemdescr}
\pnum
Let \placeholder{op} be the operator.

\pnum
\returns
A \tcode{basic_mask} object initialized with the results of applying
\placeholder{op} to \tcode{lhs} and \tcode{rhs} as a binary element-wise
operation.
\end{itemdescr}

\rSec3[simd.mask.cond]{Exposition-only conditional operators}

\begin{itemdecl}
friend constexpr basic_mask @\exposid{simd-select-impl}@(
  const basic_mask& mask, const basic_mask& a, const basic_mask& b) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
A \tcode{basic_mask} object where the $i^\text{th}$ element equals
\tcode{mask[$i$] ? a[$i$] : b[$i$]} for all $i$ in the range of
\range{0}{size()}.
\end{itemdescr}

\begin{itemdecl}
friend constexpr basic_mask
@\exposid{simd-select-impl}@(const basic_mask& mask, @\libconcept{same_as}@<bool> auto a, @\libconcept{same_as}@<bool> auto b) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
A \tcode{basic_mask} object where the $i^\text{th}$ element equals
\tcode{mask[$i$] ? a : b} for all $i$ in the range of \range{0}{size()}.
\end{itemdescr}

\begin{itemdecl}
template<class T0, class T1>
  friend constexpr vec<@\seebelow@, size()>
    @\exposid{simd-select-impl}@(const basic_mask& mask, const T0& a, const T1& b) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\constraints
\begin{itemize}
 \item
   \tcode{\libconcept{same_as}<T0, T1>} is \tcode{true},
 \item
   \tcode{T0} is a vectorizable type, and
 \item
   \tcode{sizeof(T0) == Bytes}.
\end{itemize}

\pnum
\returns
A \tcode{vec<T0, size()>} object where the $i^\text{th}$ element equals
\tcode{mask[$i$] ? a : b} for all $i$ in the range of \range{0}{size()}.
\end{itemdescr}

\rSec3[simd.mask.reductions]{Reductions}

\indexlibrarymember{all_of}{simd}
\begin{itemdecl}
template<size_t Bytes, class Abi>
  constexpr bool all_of(const basic_mask<Bytes, Abi>& k) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{true} if all boolean elements in \tcode{k} are \tcode{true}, otherwise
\tcode{false}.
\end{itemdescr}

\indexlibrarymember{any_of}{simd}
\begin{itemdecl}
template<size_t Bytes, class Abi>
  constexpr bool any_of(const basic_mask<Bytes, Abi>& k) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{true} if at least one boolean element in \tcode{k} is \tcode{true},
otherwise \tcode{false}.
\end{itemdescr}

\indexlibrarymember{none_of}{simd}
\begin{itemdecl}
template<size_t Bytes, class Abi>
  constexpr bool none_of(const basic_mask<Bytes, Abi>& k) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{!any_of(k)}.
\end{itemdescr}

\indexlibrarymember{reduce_count}{simd}
\begin{itemdecl}
template<size_t Bytes, class Abi>
  constexpr @\exposid{simd-size-type}@ reduce_count(const basic_mask<Bytes, Abi>& k) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
The number of boolean elements in \tcode{k} that are \tcode{true}.
\end{itemdescr}

\indexlibrarymember{reduce_min_index}{simd}
\begin{itemdecl}
template<size_t Bytes, class Abi>
  constexpr @\exposid{simd-size-type}@ reduce_min_index(const basic_mask<Bytes, Abi>& k);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{any_of(k)} is \tcode{true}.

\pnum
\returns
The lowest element index $i$ where \tcode{k[$i$]} is \tcode{true}.
\end{itemdescr}

\indexlibrarymember{reduce_max_index}{simd}
\begin{itemdecl}
template<size_t Bytes, class Abi>
  constexpr @\exposid{simd-size-type}@ reduce_max_index(const basic_mask<Bytes, Abi>& k);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{any_of(k)} is \tcode{true}.

\pnum
\returns
The greatest element index $i$ where \tcode{k[$i$]} is \tcode{true}.
\end{itemdescr}

\indexlibrarymember{all_of}{simd}
\indexlibrarymember{any_of}{simd}
\indexlibrarymember{reduce_count}{simd}
\begin{itemdecl}
constexpr bool all_of(@\libconcept{same_as}@<bool> auto x) noexcept;
constexpr bool any_of(@\libconcept{same_as}@<bool> auto x) noexcept;
constexpr @\exposid{simd-size-type}@ reduce_count(@\libconcept{same_as}@<bool> auto x) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{x}.
\end{itemdescr}

\indexlibrarymember{none_of}{simd}
\begin{itemdecl}
constexpr bool none_of(@\libconcept{same_as}@<bool> auto x) noexcept;
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
\tcode{!x}.
\end{itemdescr}

\indexlibrarymember{reduce_min_index}{simd}
\indexlibrarymember{reduce_max_index}{simd}
\begin{itemdecl}
constexpr @\exposid{simd-size-type}@ reduce_min_index(@\libconcept{same_as}@<bool> auto x);
constexpr @\exposid{simd-size-type}@ reduce_max_index(@\libconcept{same_as}@<bool> auto x);
\end{itemdecl}

\begin{itemdescr}
\pnum
\expects
\tcode{x} is \tcode{true}.

\pnum
\returns
\tcode{0}.
\end{itemdescr}

\rSec1[numerics.c]{C compatibility}

\rSec2[stdckdint.h.syn]{Header \tcode{<stdckdint.h>} synopsis}

\indexheader{stdckdint.h}%
\begin{codeblock}
#define @\libmacro{__STDC_VERSION_STDCKDINT_H__}@ 202311L

template<class type1, class type2, class type3>
  bool ckd_add(type1* result, type2 a, type3 b);
template<class type1, class type2, class type3>
  bool ckd_sub(type1* result, type2 a, type3 b);
template<class type1, class type2, class type3>
  bool ckd_mul(type1* result, type2 a, type3 b);
\end{codeblock}

\pnum
\xrefc{7.20}

\rSec2[numerics.c.ckdint]{Checked integer operations}

\indexlibraryglobal{ckd_add}%
\indexlibraryglobal{ckd_sub}%
\indexlibraryglobal{ckd_mul}%
\begin{itemdecl}
template<class type1, class type2, class type3>
  bool ckd_add(type1* result, type2 a, type3 b);
template<class type1, class type2, class type3>
  bool ckd_sub(type1* result, type2 a, type3 b);
template<class type1, class type2, class type3>
  bool ckd_mul(type1* result, type2 a, type3 b);
\end{itemdecl}

\begin{itemdescr}
\pnum
\mandates
Each of the types \tcode{type1}, \tcode{type2}, and \tcode{type3} is a
signed or unsigned integer type\iref{basic.fundamental}.

\pnum
\remarks
Each function template has the same semantics as
the corresponding type-generic macro with the same name
specified in \xrefc{7.20}.
\end{itemdescr}
