This commit is contained in:
2025-10-25 03:02:53 +03:00
commit 043225d523
3416 changed files with 681196 additions and 0 deletions

View File

@@ -0,0 +1,943 @@
[linalg.algs.blas1]
# 29 Numerics library [[numerics]](./#numerics)
## 29.9 Basic linear algebra algorithms [[linalg]](linalg#algs.blas1)
### 29.9.13 BLAS 1 algorithms [linalg.algs.blas1]
#### [29.9.13.1](#complexity) Complexity [[linalg.algs.blas1.complexity]](linalg.algs.blas1.complexity)
[1](#complexity-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13348)
*Complexity*: All algorithms in [linalg.algs.blas1] with mdspan parameters
perform a count of mdspan array accesses
and arithmetic operations that is linear in
the maximum product of extents of any mdspan parameter[.](#complexity-1.sentence-1)
#### [29.9.13.2](#givens) Givens rotations [[linalg.algs.blas1.givens]](linalg.algs.blas1.givens)
#### [29.9.13.2.1](#givens.lartg) Compute Givens rotation [[linalg.algs.blas1.givens.lartg]](linalg.algs.blas1.givens.lartg)
[🔗](#lib:setup_givens_rotation)
`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;
`
[1](#givens.lartg-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13370)
These functions compute the Givens plane rotation
represented by the two values c and s such that the 2 x 2 system of equations
[cs−¯¯¯sc]â‹[ab]=[r0]
holds, where c is always a real scalar, and c2+|s|2=1[.](#givens.lartg-1.sentence-2)
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[.](#givens.lartg-1.sentence-3)
[*Note [1](#givens.lartg-note-1)*:
These functions correspond to the LAPACK function xLARTG[[bib]](bibliography#bib:lapack "Bibliography")[.](#givens.lartg-1.sentence-4)
— *end note*]
[2](#givens.lartg-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13402)
*Returns*: c, s, r,
where c and s form the Givens plane rotation
corresponding to the input a and b,
and r is the Euclidean norm of the two-component vector
formed by a and b[.](#givens.lartg-2.sentence-1)
#### [29.9.13.2.2](#givens.rot) Apply a computed Givens rotation to vectors [[linalg.algs.blas1.givens.rot]](linalg.algs.blas1.givens.rot)
[🔗](#lib:apply_givens_rotation)
`template<[inout-vector](linalg.helpers.concepts#concept:inout-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutVec1, [inout-vector](linalg.helpers.concepts#concept:inout-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutVec2, class Real>
void apply_givens_rotation(InOutVec1 x, InOutVec2 y, Real c, Real s);
template<class ExecutionPolicy, [inout-vector](linalg.helpers.concepts#concept:inout-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutVec1, [inout-vector](linalg.helpers.concepts#concept:inout-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutVec2, class Real>
void apply_givens_rotation(ExecutionPolicy&& exec,
InOutVec1 x, InOutVec2 y, Real c, Real s);
template<[inout-vector](linalg.helpers.concepts#concept:inout-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutVec1, [inout-vector](linalg.helpers.concepts#concept:inout-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutVec2, class Real>
void apply_givens_rotation(InOutVec1 x, InOutVec2 y, Real c, complex<Real> s);
template<class ExecutionPolicy, [inout-vector](linalg.helpers.concepts#concept:inout-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutVec1, [inout-vector](linalg.helpers.concepts#concept:inout-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutVec2, class Real>
void apply_givens_rotation(ExecutionPolicy&& exec,
InOutVec1 x, InOutVec2 y, Real c, complex<Real> s);
`
[1](#givens.rot-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13428)
[*Note [1](#givens.rot-note-1)*:
These functions correspond to the BLAS function xROT[[bib]](bibliography#bib:blas1 "Bibliography")[.](#givens.rot-1.sentence-1)
— *end note*]
[2](#givens.rot-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13433)
*Mandates*: *compatible-static-extents*<InOutVec1, InOutVec2>(0, 0) is true[.](#givens.rot-2.sentence-1)
[3](#givens.rot-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13437)
*Preconditions*: x.extent(0) equals y.extent(0)[.](#givens.rot-3.sentence-1)
[4](#givens.rot-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13441)
*Effects*: Applies the plane rotation
specified by c and s to
the input vectors x and y,
as if the rotation were a 2 x 2 matrix and
the input vectors were successive rows of a matrix with two rows[.](#givens.rot-4.sentence-1)
#### [29.9.13.3](#swap) Swap matrix or vector elements [[linalg.algs.blas1.swap]](linalg.algs.blas1.swap)
[🔗](#lib:swap_elements)
`template<[inout-object](linalg.helpers.concepts#concept:inout-object "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutObj1, [inout-object](linalg.helpers.concepts#concept:inout-object "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutObj2>
void swap_elements(InOutObj1 x, InOutObj2 y);
template<class ExecutionPolicy, [inout-object](linalg.helpers.concepts#concept:inout-object "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutObj1, [inout-object](linalg.helpers.concepts#concept:inout-object "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutObj2>
void swap_elements(ExecutionPolicy&& exec, InOutObj1 x, InOutObj2 y);
`
[1](#swap-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13461)
[*Note [1](#swap-note-1)*:
These functions correspond to the BLAS function xSWAP[[bib]](bibliography#bib:blas1 "Bibliography")[.](#swap-1.sentence-1)
— *end note*]
[2](#swap-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13466)
*Constraints*: x.rank() equals y.rank()[.](#swap-2.sentence-1)
[3](#swap-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13470)
*Mandates*: For all r in the range [0, x.rank()),*compatible-static-extents*<InOutObj1, InOutObj2>(r, r) is true[.](#swap-3.sentence-1)
[4](#swap-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13478)
*Preconditions*: x.extents() equals y.extents()[.](#swap-4.sentence-1)
[5](#swap-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13482)
*Effects*: Swaps all corresponding elements of x and y[.](#swap-5.sentence-1)
#### [29.9.13.4](#scal) Multiply the elements of an object in place by a scalar [[linalg.algs.blas1.scal]](linalg.algs.blas1.scal)
[🔗](#lib:scale)
`template<class Scalar, [inout-object](linalg.helpers.concepts#concept:inout-object "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutObj>
void scale(Scalar alpha, InOutObj x);
template<class ExecutionPolicy, class Scalar, [inout-object](linalg.helpers.concepts#concept:inout-object "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutObj>
void scale(ExecutionPolicy&& exec, Scalar alpha, InOutObj x);
`
[1](#scal-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13498)
[*Note [1](#scal-note-1)*:
These functions correspond to the BLAS function xSCAL[[bib]](bibliography#bib:blas1 "Bibliography")[.](#scal-1.sentence-1)
— *end note*]
[2](#scal-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13503)
*Effects*: Overwrites x with the result of
computing the elementwise multiplication αx,
where the scalar α is alpha[.](#scal-2.sentence-1)
#### [29.9.13.5](#copy) Copy elements of one matrix or vector into another [[linalg.algs.blas1.copy]](linalg.algs.blas1.copy)
[🔗](#lib:copy)
`template<[in-object](linalg.helpers.concepts#concept:in-object "29.9.7.5Argument concepts[linalg.helpers.concepts]") InObj, [out-object](linalg.helpers.concepts#concept:out-object "29.9.7.5Argument concepts[linalg.helpers.concepts]") OutObj>
void copy(InObj x, OutObj y);
template<class ExecutionPolicy, [in-object](linalg.helpers.concepts#concept:in-object "29.9.7.5Argument concepts[linalg.helpers.concepts]") InObj, [out-object](linalg.helpers.concepts#concept:out-object "29.9.7.5Argument concepts[linalg.helpers.concepts]") OutObj>
void copy(ExecutionPolicy&& exec, InObj x, OutObj y);
`
[1](#copy-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13521)
[*Note [1](#copy-note-1)*:
These functions correspond to the BLAS function xCOPY[[bib]](bibliography#bib:blas1 "Bibliography")[.](#copy-1.sentence-1)
— *end note*]
[2](#copy-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13526)
*Constraints*: x.rank() equals y.rank()[.](#copy-2.sentence-1)
[3](#copy-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13530)
*Mandates*: For all r in the range [0,x.rank()),*compatible-static-extents*<InObj, OutObj>(r, r) is true[.](#copy-3.sentence-1)
[4](#copy-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13538)
*Preconditions*: x.extents() equals y.extents()[.](#copy-4.sentence-1)
[5](#copy-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13542)
*Effects*: Assigns each element of x to the corresponding element of y[.](#copy-5.sentence-1)
#### [29.9.13.6](#add) Add vectors or matrices elementwise [[linalg.algs.blas1.add]](linalg.algs.blas1.add)
[🔗](#lib:add)
`template<[in-object](linalg.helpers.concepts#concept:in-object "29.9.7.5Argument concepts[linalg.helpers.concepts]") InObj1, [in-object](linalg.helpers.concepts#concept:in-object "29.9.7.5Argument concepts[linalg.helpers.concepts]") InObj2, [out-object](linalg.helpers.concepts#concept:out-object "29.9.7.5Argument concepts[linalg.helpers.concepts]") OutObj>
void add(InObj1 x, InObj2 y, OutObj z);
template<class ExecutionPolicy, [in-object](linalg.helpers.concepts#concept:in-object "29.9.7.5Argument concepts[linalg.helpers.concepts]") InObj1, [in-object](linalg.helpers.concepts#concept:in-object "29.9.7.5Argument concepts[linalg.helpers.concepts]") InObj2, [out-object](linalg.helpers.concepts#concept:out-object "29.9.7.5Argument concepts[linalg.helpers.concepts]") OutObj>
void add(ExecutionPolicy&& exec,
InObj1 x, InObj2 y, OutObj z);
`
[1](#add-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13559)
[*Note [1](#add-note-1)*:
These functions correspond to the BLAS function xAXPY[[bib]](bibliography#bib:blas1 "Bibliography")[.](#add-1.sentence-1)
— *end note*]
[2](#add-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13564)
*Constraints*: x.rank(), y.rank(), and z.rank() are all equal[.](#add-2.sentence-1)
[3](#add-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13568)
*Mandates*: *possibly-addable*<InObj1, InObj2, OutObj>() is true[.](#add-3.sentence-1)
[4](#add-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13572)
*Preconditions*: *addable*(x,y,z) is true[.](#add-4.sentence-1)
[5](#add-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13576)
*Effects*: Computes z=x+y[.](#add-5.sentence-1)
[6](#add-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13580)
*Remarks*: z may alias x or y[.](#add-6.sentence-1)
#### [29.9.13.7](#dot) Dot product of two vectors [[linalg.algs.blas1.dot]](linalg.algs.blas1.dot)
[1](#dot-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13587)
[*Note [1](#dot-note-1)*:
The functions in this section correspond to the BLAS
functions xDOT, xDOTU, and xDOTC[[bib]](bibliography#bib:blas1 "Bibliography")[.](#dot-1.sentence-1)
— *end note*]
[2](#dot-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13593)
The following elements apply to all functions in [[linalg.algs.blas1.dot]](#dot "29.9.13.7Dot product of two vectors")[.](#dot-2.sentence-1)
[3](#dot-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13596)
*Mandates*: *compatible-static-extents*<InVec1, InVec2>(0, 0) is true[.](#dot-3.sentence-1)
[4](#dot-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13600)
*Preconditions*: v1.extent(0) equals v2.extent(0)[.](#dot-4.sentence-1)
[🔗](#lib:dot)
`template<[in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec1, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec2, class Scalar>
Scalar dot(InVec1 v1, InVec2 v2, Scalar init);
template<class ExecutionPolicy, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec1, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec2, class Scalar>
Scalar dot(ExecutionPolicy&& exec,
InVec1 v1, InVec2 v2, Scalar init);
`
[5](#dot-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13614)
These functions compute a non-conjugated dot product
with an explicitly specified result type[.](#dot-5.sentence-1)
[6](#dot-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13618)
*Returns*: Let N be v1.extent(0)[.](#dot-6.sentence-1)
- [(6.1)](#dot-6.1)
init if N is zero;
- [(6.2)](#dot-6.2)
otherwise,*GENERALIZED_SUM*(plus<>(), init, v1[0]*v2[0], …, v1[N-1]*v2[N-1]).
[7](#dot-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13629)
*Remarks*: If InVec1::value_type, InVec2::value_type, and Scalar are all floating-point types or specializations of complex,
and if Scalar has higher precision
than InVec1::value_type or InVec2::value_type,
then intermediate terms in the sum use Scalar's precision or greater[.](#dot-7.sentence-1)
[🔗](#lib:dot_)
` template<[in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec1, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec2>
auto dot(InVec1 v1, InVec2 v2);
template<class ExecutionPolicy, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec1, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec2>
auto dot(ExecutionPolicy&& exec,
InVec1 v1, InVec2 v2);
`
[8](#dot-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13648)
These functions compute a non-conjugated dot product with a default result type[.](#dot-8.sentence-1)
[9](#dot-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13651)
*Effects*: Let T bedecltype(declval<typename InVec1::value_type>() * declval<typename InVec2::value_type>())[.](#dot-9.sentence-1)
Then,
- [(9.1)](#dot-9.1)
the two-parameter overload is equivalent to:return dot(v1, v2, T{}); and
- [(9.2)](#dot-9.2)
the three-parameter overload is equivalent to:return dot(std::forward<ExecutionPolicy>(exec), v1, v2, T{});
[🔗](#lib:dotc)
`template<[in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec1, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec2, class Scalar>
Scalar dotc(InVec1 v1, InVec2 v2, Scalar init);
template<class ExecutionPolicy, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec1, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec2, class Scalar>
Scalar dotc(ExecutionPolicy&& exec,
InVec1 v1, InVec2 v2, Scalar init);
`
[10](#dot-10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13682)
These functions compute a conjugated dot product
with an explicitly specified result type[.](#dot-10.sentence-1)
[11](#dot-11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13686)
*Effects*:
- [(11.1)](#dot-11.1)
The three-parameter overload is equivalent to:return dot(conjugated(v1), v2, init); and
- [(11.2)](#dot-11.2)
the four-parameter overload is equivalent to:return dot(std::forward<ExecutionPolicy>(exec), conjugated(v1), v2, init);
[🔗](#lib:dotc_)
`template<[in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec1, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec2>
auto dotc(InVec1 v1, InVec2 v2);
template<class ExecutionPolicy, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec1, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec2>
auto dotc(ExecutionPolicy&& exec,
InVec1 v1, InVec2 v2);
`
[12](#dot-12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13714)
These functions compute a conjugated dot product with a default result type[.](#dot-12.sentence-1)
[13](#dot-13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13717)
*Effects*: Let T be decltype(*conj-if-needed*(declval<typename InVec1::value_type>()) * declval<typename InVec2::value_type>())[.](#dot-13.sentence-1)
Then,
- [(13.1)](#dot-13.1)
the two-parameter overload is equivalent to:return dotc(v1, v2, T{}); and
- [(13.2)](#dot-13.2)
the three-parameter overload is equivalent toreturn dotc(std::forward<ExecutionPolicy>(exec), v1, v2, T{});
#### [29.9.13.8](#ssq) Scaled sum of squares of a vector's elements [[linalg.algs.blas1.ssq]](linalg.algs.blas1.ssq)
[🔗](#lib:vector_sum_of_squares)
`template<[in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec, class Scalar>
sum_of_squares_result<Scalar> vector_sum_of_squares(InVec v, sum_of_squares_result<Scalar> init);
template<class ExecutionPolicy, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec, class Scalar>
sum_of_squares_result<Scalar> vector_sum_of_squares(ExecutionPolicy&& exec,
InVec v, sum_of_squares_result<Scalar> init);
`
[1](#ssq-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13748)
[*Note [1](#ssq-note-1)*:
These functions correspond to the LAPACK function xLASSQ[[bib]](bibliography#bib:lapack "Bibliography")[.](#ssq-1.sentence-1)
— *end note*]
[2](#ssq-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13753)
*Mandates*: decltype(*abs-if-needed*(declval<typename InVec::value_type>())) is convertible to Scalar[.](#ssq-2.sentence-1)
[3](#ssq-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13757)
*Effects*: Returns a value result such that
- [(3.1)](#ssq-3.1)
result.scaling_factor is the maximum of init.scaling_factor and*abs-if-needed*(x[i]) for all i in the domain of v; and
- [(3.2)](#ssq-3.2)
let s2init beinit.scaling_factor * init.scaling_factor * init.scaled_sum_of_squares then result.scaling_factor * result.scaling_factor * result.scaled_sum_of_squares equals the sum of s2init and
the squares of *abs-if-needed*(x[i]) for all i in the domain of v[.](#ssq-3.sentence-1)
[4](#ssq-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13776)
*Remarks*: If InVec::value_type, and Scalar are all floating-point types or specializations of complex,
and if Scalar has higher precision
than InVec::value_type,
then intermediate terms in the sum use Scalar's precision or greater[.](#ssq-4.sentence-1)
#### [29.9.13.9](#nrm2) Euclidean norm of a vector [[linalg.algs.blas1.nrm2]](linalg.algs.blas1.nrm2)
[🔗](#lib:vector_two_norm)
`template<[in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec, class Scalar>
Scalar vector_two_norm(InVec v, Scalar init);
template<class ExecutionPolicy, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec, class Scalar>
Scalar vector_two_norm(ExecutionPolicy&& exec, InVec v, Scalar init);
`
[1](#nrm2-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13796)
[*Note [1](#nrm2-note-1)*:
These functions correspond to the BLAS function xNRM2[[bib]](bibliography#bib:blas1 "Bibliography")[.](#nrm2-1.sentence-1)
— *end note*]
[2](#nrm2-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13801)
*Mandates*: Let a be*abs-if-needed*(declval<typename InVec::value_type>())[.](#nrm2-2.sentence-1)
Then, decltype(init + a * a is convertible to Scalar[.](#nrm2-2.sentence-2)
[3](#nrm2-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13807)
*Returns*: The square root of the sum of the square of init and the squares of the absolute values of the elements of v[.](#nrm2-3.sentence-1)
[*Note [2](#nrm2-note-2)*:
For init equal to zero, this is the Euclidean norm
(also called 2-norm) of the vector v[.](#nrm2-3.sentence-2)
— *end note*]
[4](#nrm2-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13815)
*Remarks*: If InVec::value_type, and Scalar are all floating-point types or specializations of complex,
and if Scalar has higher precision
than InVec::value_type,
then intermediate terms in the sum use Scalar's precision or greater[.](#nrm2-4.sentence-1)
[*Note [3](#nrm2-note-3)*:
An implementation of this function for floating-point types T can use the scaled_sum_of_squares result fromvector_sum_of_squares(x, {.scaling_factor=1.0, .scaled_sum_of_squares=init})[.](#nrm2-4.sentence-2)
— *end note*]
[🔗](#lib:vector_two_norm_)
`template<[in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec>
auto vector_two_norm(InVec v);
template<class ExecutionPolicy, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec>
auto vector_two_norm(ExecutionPolicy&& exec, InVec v);
`
[5](#nrm2-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13838)
*Effects*: Let a be*abs-if-needed*(declval<typename InVec::value_type>())[.](#nrm2-5.sentence-1)
Let T be decltype(a * a)[.](#nrm2-5.sentence-2)
Then,
- [(5.1)](#nrm2-5.1)
the one-parameter overload is equivalent to:return vector_two_norm(v, T{}); and
- [(5.2)](#nrm2-5.2)
the two-parameter overload is equivalent to:return vector_two_norm(std::forward<ExecutionPolicy>(exec), v, T{});
#### [29.9.13.10](#asum) Sum of absolute values of vector elements [[linalg.algs.blas1.asum]](linalg.algs.blas1.asum)
[🔗](#lib:vector_abs_sum)
`template<[in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec, class Scalar>
Scalar vector_abs_sum(InVec v, Scalar init);
template<class ExecutionPolicy, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec, class Scalar>
Scalar vector_abs_sum(ExecutionPolicy&& exec, InVec v, Scalar init);
`
[1](#asum-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13870)
[*Note [1](#asum-note-1)*:
These functions correspond to the BLAS functionsSASUM, DASUM, SCASUM, and DZASUM[[bib]](bibliography#bib:blas1 "Bibliography")[.](#asum-1.sentence-1)
— *end note*]
[2](#asum-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13876)
*Mandates*: decltype(init + *abs-if-needed*(*real-if-needed*(declval<typename InVec::value_type>())) +*abs-if-needed*(*imag-if-needed*(declval<typename InVec::value_type>()))) is convertible to Scalar[.](#asum-2.sentence-1)
[3](#asum-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13884)
*Returns*: Let N be v.extent(0)[.](#asum-3.sentence-1)
- [(3.1)](#asum-3.1)
init if N is zero;
- [(3.2)](#asum-3.2)
otherwise, if InVec::value_type is an arithmetic type,*GENERALIZED_SUM*(plus<>(), init, *abs-if-needed*(v[0]), …, *abs-if-needed*(v[N-1]))
- [(3.3)](#asum-3.3)
otherwise,*GENERALIZED_SUM*(plus<>(), init, *abs-if-needed*(*real-if-needed*(v[0])) + *abs-if-needed*(*imag-if-needed*(v[0])),
…, *abs-if-needed*(*real-if-needed*(v[N-1])) + *abs-if-needed*(*imag-if-needed*(v[N-1])))
[4](#asum-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13905)
*Remarks*: If InVec::value_type and Scalar are all floating-point types or specializations of complex,
and if Scalar has higher precision
than InVec::value_type,
then intermediate terms in the sum use Scalar's precision or greater[.](#asum-4.sentence-1)
[🔗](#lib:vector_abs_sum_)
`template<[in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec>
auto vector_abs_sum(InVec v);
template<class ExecutionPolicy, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec>
auto vector_abs_sum(ExecutionPolicy&& exec, InVec v);
`
[5](#asum-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13923)
*Effects*: Let T be typename InVec::value_type[.](#asum-5.sentence-1)
Then,
- [(5.1)](#asum-5.1)
the one-parameter overload is equivalent to:return vector_abs_sum(v, T{}); and
- [(5.2)](#asum-5.2)
the two-parameter overload is equivalent to:return vector_abs_sum(std::forward<ExecutionPolicy>(exec), v, T{});
#### [29.9.13.11](#iamax) Index of maximum absolute value of vector elements [[linalg.algs.blas1.iamax]](linalg.algs.blas1.iamax)
[🔗](#lib:vector_idx_abs_max)
`template<[in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec>
typename InVec::extents_type vector_idx_abs_max(InVec v);
template<class ExecutionPolicy, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec>
typename InVec::extents_type vector_idx_abs_max(ExecutionPolicy&& exec, InVec v);
`
[1](#iamax-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13953)
[*Note [1](#iamax-note-1)*:
These functions correspond to the BLAS function IxAMAX[[bib]](bibliography#bib:blas1 "Bibliography")[.](#iamax-1.sentence-1)
— *end note*]
[2](#iamax-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13958)
Let T bedecltype(*abs-if-needed*(*real-if-needed*(declval<typename InVec::value_type>())) +*abs-if-needed*(*imag-if-needed*(declval<typename InVec::value_type>())))
[3](#iamax-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13965)
*Mandates*: declval<T>() < declval<T>() is a valid expression[.](#iamax-3.sentence-1)
[4](#iamax-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13969)
*Returns*:
- [(4.1)](#iamax-4.1)
numeric_limits<typename InVec::size_type>::max() if v has zero elements;
- [(4.2)](#iamax-4.2)
otherwise, the index of the first element of v having largest absolute value,
if InVec::value_type is an arithmetic type;
- [(4.3)](#iamax-4.3)
otherwise, the index of the first element ve of v for which*abs-if-needed*(*real-if-needed*(ve)) + *abs-if-needed*(*imag-if-needed*(ve)) has the largest value[.](#iamax-4.sentence-1)
#### [29.9.13.12](#matfrobnorm) Frobenius norm of a matrix [[linalg.algs.blas1.matfrobnorm]](linalg.algs.blas1.matfrobnorm)
[1](#matfrobnorm-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13991)
[*Note [1](#matfrobnorm-note-1)*:
These functions exist in the BLAS standard[[bib]](bibliography#bib:blas-std "Bibliography") but are not part of the reference implementation[.](#matfrobnorm-1.sentence-1)
— *end note*]
[🔗](#lib:matrix_frob_norm)
`template<[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Scalar>
Scalar matrix_frob_norm(InMat A, Scalar init);
template<class ExecutionPolicy, [in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Scalar>
Scalar matrix_frob_norm(ExecutionPolicy&& exec, InMat A, Scalar init);
`
[2](#matfrobnorm-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14007)
*Mandates*: Let a be*abs-if-needed*(declval<typename InMat::value_type>())[.](#matfrobnorm-2.sentence-1)
Then, decltype(init + a * a) is convertible to Scalar[.](#matfrobnorm-2.sentence-2)
[3](#matfrobnorm-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14014)
*Returns*: The square root of the sum of squares
of init and the absolute values of the elements of A[.](#matfrobnorm-3.sentence-1)
[*Note [2](#matfrobnorm-note-2)*:
For init equal to zero,
this is the Frobenius norm of the matrix A[.](#matfrobnorm-3.sentence-2)
— *end note*]
[4](#matfrobnorm-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14023)
*Remarks*: If InMat::value_type and Scalar are all floating-point types or specializations of complex,
and if Scalar has higher precision
than InMat::value_type,
then intermediate terms in the sum use Scalar's precision or greater[.](#matfrobnorm-4.sentence-1)
[🔗](#lib:matrix_frob_norm_)
`template<[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat>
auto matrix_frob_norm(InMat A);
template<class ExecutionPolicy, [in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat>
auto matrix_frob_norm(ExecutionPolicy&& exec, InMat A);
`
[5](#matfrobnorm-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14041)
*Effects*: Let a be*abs-if-needed*(declval<typename InMat::value_type>())[.](#matfrobnorm-5.sentence-1)
Let T bedecltype(a * a)[.](#matfrobnorm-5.sentence-2)
Then,
- [(5.1)](#matfrobnorm-5.1)
the one-parameter overload is equivalent to:return matrix_frob_norm(A, T{}); and
- [(5.2)](#matfrobnorm-5.2)
the two-parameter overload is equivalent to:return matrix_frob_norm(std::forward<ExecutionPolicy>(exec), A, T{});
#### [29.9.13.13](#matonenorm) One norm of a matrix [[linalg.algs.blas1.matonenorm]](linalg.algs.blas1.matonenorm)
[1](#matonenorm-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14065)
[*Note [1](#matonenorm-note-1)*:
These functions exist in the BLAS standard[[bib]](bibliography#bib:blas-std "Bibliography") but are not part of the reference implementation[.](#matonenorm-1.sentence-1)
— *end note*]
[🔗](#lib:matrix_one_norm)
`template<[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Scalar>
Scalar matrix_one_norm(InMat A, Scalar init);
template<class ExecutionPolicy, [in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Scalar>
Scalar matrix_one_norm(ExecutionPolicy&& exec, InMat A, Scalar init);
`
[2](#matonenorm-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14080)
*Mandates*: decltype(*abs-if-needed*(declval<typename InMat::value_type>())) is convertible to Scalar[.](#matonenorm-2.sentence-1)
[3](#matonenorm-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14085)
*Returns*:
- [(3.1)](#matonenorm-3.1)
init if A.extent(1) is zero;
- [(3.2)](#matonenorm-3.2)
otherwise, the sum of init and the one norm of the matrix A[.](#matonenorm-3.sentence-1)
[*Note [2](#matonenorm-note-2)*:
The one norm of the matrix A is the maximum over all columns of A,
of the sum of the absolute values of the elements of the column[.](#matonenorm-3.sentence-2)
— *end note*]
[4](#matonenorm-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14099)
*Remarks*: If InMat::value_type and Scalar are all floating-point types or specializations of complex,
and if Scalar has higher precision
than InMat::value_type,
then intermediate terms in the sum use Scalar's precision or greater[.](#matonenorm-4.sentence-1)
[🔗](#lib:matrix_one_norm_)
`template<[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat>
auto matrix_one_norm(InMat A);
template<class ExecutionPolicy, [in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat>
auto matrix_one_norm(ExecutionPolicy&& exec, InMat A);
`
[5](#matonenorm-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14117)
*Effects*: Let T bedecltype(*abs-if-needed*(declval<typename InMat::value_type>())[.](#matonenorm-5.sentence-1)
Then,
- [(5.1)](#matonenorm-5.1)
the one-parameter overload is equivalent to:return matrix_one_norm(A, T{}); and
- [(5.2)](#matonenorm-5.2)
the two-parameter overload is equivalent to:return matrix_one_norm(std::forward<ExecutionPolicy>(exec), A, T{});
#### [29.9.13.14](#matinfnorm) Infinity norm of a matrix [[linalg.algs.blas1.matinfnorm]](linalg.algs.blas1.matinfnorm)
[1](#matinfnorm-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14139)
[*Note [1](#matinfnorm-note-1)*:
These functions exist in the BLAS standard[[bib]](bibliography#bib:blas-std "Bibliography") but are not part of the reference implementation[.](#matinfnorm-1.sentence-1)
— *end note*]
[🔗](#lib:matrix_inf_norm)
`template<[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Scalar>
Scalar matrix_inf_norm(InMat A, Scalar init);
template<class ExecutionPolicy, [in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Scalar>
Scalar matrix_inf_norm(ExecutionPolicy&& exec, InMat A, Scalar init);
`
[2](#matinfnorm-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14154)
*Mandates*: decltype(*abs-if-needed*(declval<typename InMat::value_type>())) is convertible to Scalar[.](#matinfnorm-2.sentence-1)
[3](#matinfnorm-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14159)
*Returns*:
- [(3.1)](#matinfnorm-3.1)
init if A.extent(0) is zero;
- [(3.2)](#matinfnorm-3.2)
otherwise,
the sum of init and the infinity norm of the matrix A[.](#matinfnorm-3.sentence-1)
[*Note [2](#matinfnorm-note-2)*:
The infinity norm of the matrix A is the maximum over all rows of A,
of the sum of the absolute values
of the elements of the row[.](#matinfnorm-3.sentence-2)
— *end note*]
[4](#matinfnorm-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14175)
*Remarks*: If InMat::value_type and Scalar are all floating-point types or specializations of complex,
and if Scalar has higher precision
than InMat::value_type,
then intermediate terms in the sum use Scalar's precision or greater[.](#matinfnorm-4.sentence-1)
[🔗](#lib:matrix_inf_norm_)
`template<[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat>
auto matrix_inf_norm(InMat A);
template<class ExecutionPolicy, [in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat>
auto matrix_inf_norm(ExecutionPolicy&& exec, InMat A);
`
[5](#matinfnorm-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14194)
*Effects*: Let T bedecltype(*abs-if-needed*(declval<typename InMat::value_type>())[.](#matinfnorm-5.sentence-1)
Then,
- [(5.1)](#matinfnorm-5.1)
the one-parameter overload is equivalent to:return matrix_inf_norm(A, T{}); and
- [(5.2)](#matinfnorm-5.2)
the two-parameter overload is equivalent to:return matrix_inf_norm(std::forward<ExecutionPolicy>(exec), A, T{});

View File

@@ -0,0 +1,58 @@
[linalg.algs.blas1.add]
# 29 Numerics library [[numerics]](./#numerics)
## 29.9 Basic linear algebra algorithms [[linalg]](linalg#algs.blas1.add)
### 29.9.13 BLAS 1 algorithms [[linalg.algs.blas1]](linalg.algs.blas1#add)
#### 29.9.13.6 Add vectors or matrices elementwise [linalg.algs.blas1.add]
[🔗](#lib:add)
`template<[in-object](linalg.helpers.concepts#concept:in-object "29.9.7.5Argument concepts[linalg.helpers.concepts]") InObj1, [in-object](linalg.helpers.concepts#concept:in-object "29.9.7.5Argument concepts[linalg.helpers.concepts]") InObj2, [out-object](linalg.helpers.concepts#concept:out-object "29.9.7.5Argument concepts[linalg.helpers.concepts]") OutObj>
void add(InObj1 x, InObj2 y, OutObj z);
template<class ExecutionPolicy, [in-object](linalg.helpers.concepts#concept:in-object "29.9.7.5Argument concepts[linalg.helpers.concepts]") InObj1, [in-object](linalg.helpers.concepts#concept:in-object "29.9.7.5Argument concepts[linalg.helpers.concepts]") InObj2, [out-object](linalg.helpers.concepts#concept:out-object "29.9.7.5Argument concepts[linalg.helpers.concepts]") OutObj>
void add(ExecutionPolicy&& exec,
InObj1 x, InObj2 y, OutObj z);
`
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13559)
[*Note [1](#note-1)*:
These functions correspond to the BLAS function xAXPY[[bib]](bibliography#bib:blas1 "Bibliography")[.](#1.sentence-1)
— *end note*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13564)
*Constraints*: x.rank(), y.rank(), and z.rank() are all equal[.](#2.sentence-1)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13568)
*Mandates*: *possibly-addable*<InObj1, InObj2, OutObj>() is true[.](#3.sentence-1)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13572)
*Preconditions*: *addable*(x,y,z) is true[.](#4.sentence-1)
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13576)
*Effects*: Computes z=x+y[.](#5.sentence-1)
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13580)
*Remarks*: z may alias x or y[.](#6.sentence-1)

View File

@@ -0,0 +1,85 @@
[linalg.algs.blas1.asum]
# 29 Numerics library [[numerics]](./#numerics)
## 29.9 Basic linear algebra algorithms [[linalg]](linalg#algs.blas1.asum)
### 29.9.13 BLAS 1 algorithms [[linalg.algs.blas1]](linalg.algs.blas1#asum)
#### 29.9.13.10 Sum of absolute values of vector elements [linalg.algs.blas1.asum]
[🔗](#lib:vector_abs_sum)
`template<[in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec, class Scalar>
Scalar vector_abs_sum(InVec v, Scalar init);
template<class ExecutionPolicy, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec, class Scalar>
Scalar vector_abs_sum(ExecutionPolicy&& exec, InVec v, Scalar init);
`
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13870)
[*Note [1](#note-1)*:
These functions correspond to the BLAS functionsSASUM, DASUM, SCASUM, and DZASUM[[bib]](bibliography#bib:blas1 "Bibliography")[.](#1.sentence-1)
— *end note*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13876)
*Mandates*: decltype(init + *abs-if-needed*(*real-if-needed*(declval<typename InVec::value_type>())) +*abs-if-needed*(*imag-if-needed*(declval<typename InVec::value_type>()))) is convertible to Scalar[.](#2.sentence-1)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13884)
*Returns*: Let N be v.extent(0)[.](#3.sentence-1)
- [(3.1)](#3.1)
init if N is zero;
- [(3.2)](#3.2)
otherwise, if InVec::value_type is an arithmetic type,*GENERALIZED_SUM*(plus<>(), init, *abs-if-needed*(v[0]), …, *abs-if-needed*(v[N-1]))
- [(3.3)](#3.3)
otherwise,*GENERALIZED_SUM*(plus<>(), init, *abs-if-needed*(*real-if-needed*(v[0])) + *abs-if-needed*(*imag-if-needed*(v[0])),
…, *abs-if-needed*(*real-if-needed*(v[N-1])) + *abs-if-needed*(*imag-if-needed*(v[N-1])))
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13905)
*Remarks*: If InVec::value_type and Scalar are all floating-point types or specializations of complex,
and if Scalar has higher precision
than InVec::value_type,
then intermediate terms in the sum use Scalar's precision or greater[.](#4.sentence-1)
[🔗](#lib:vector_abs_sum_)
`template<[in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec>
auto vector_abs_sum(InVec v);
template<class ExecutionPolicy, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec>
auto vector_abs_sum(ExecutionPolicy&& exec, InVec v);
`
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13923)
*Effects*: Let T be typename InVec::value_type[.](#5.sentence-1)
Then,
- [(5.1)](#5.1)
the one-parameter overload is equivalent to:return vector_abs_sum(v, T{}); and
- [(5.2)](#5.2)
the two-parameter overload is equivalent to:return vector_abs_sum(std::forward<ExecutionPolicy>(exec), v, T{});

View File

@@ -0,0 +1,18 @@
[linalg.algs.blas1.complexity]
# 29 Numerics library [[numerics]](./#numerics)
## 29.9 Basic linear algebra algorithms [[linalg]](linalg#algs.blas1.complexity)
### 29.9.13 BLAS 1 algorithms [[linalg.algs.blas1]](linalg.algs.blas1#complexity)
#### 29.9.13.1 Complexity [linalg.algs.blas1.complexity]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13348)
*Complexity*: All algorithms in [[linalg.algs.blas1]](linalg.algs.blas1 "29.9.13BLAS 1 algorithms") with mdspan parameters
perform a count of mdspan array accesses
and arithmetic operations that is linear in
the maximum product of extents of any mdspan parameter[.](#1.sentence-1)

View File

@@ -0,0 +1,51 @@
[linalg.algs.blas1.copy]
# 29 Numerics library [[numerics]](./#numerics)
## 29.9 Basic linear algebra algorithms [[linalg]](linalg#algs.blas1.copy)
### 29.9.13 BLAS 1 algorithms [[linalg.algs.blas1]](linalg.algs.blas1#copy)
#### 29.9.13.5 Copy elements of one matrix or vector into another [linalg.algs.blas1.copy]
[🔗](#lib:copy)
`template<[in-object](linalg.helpers.concepts#concept:in-object "29.9.7.5Argument concepts[linalg.helpers.concepts]") InObj, [out-object](linalg.helpers.concepts#concept:out-object "29.9.7.5Argument concepts[linalg.helpers.concepts]") OutObj>
void copy(InObj x, OutObj y);
template<class ExecutionPolicy, [in-object](linalg.helpers.concepts#concept:in-object "29.9.7.5Argument concepts[linalg.helpers.concepts]") InObj, [out-object](linalg.helpers.concepts#concept:out-object "29.9.7.5Argument concepts[linalg.helpers.concepts]") OutObj>
void copy(ExecutionPolicy&& exec, InObj x, OutObj y);
`
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13521)
[*Note [1](#note-1)*:
These functions correspond to the BLAS function xCOPY[[bib]](bibliography#bib:blas1 "Bibliography")[.](#1.sentence-1)
— *end note*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13526)
*Constraints*: x.rank() equals y.rank()[.](#2.sentence-1)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13530)
*Mandates*: For all r in the range [0,x.rank()),*compatible-static-extents*<InObj, OutObj>(r, r) is true[.](#3.sentence-1)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13538)
*Preconditions*: x.extents() equals y.extents()[.](#4.sentence-1)
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13542)
*Effects*: Assigns each element of x to the corresponding element of y[.](#5.sentence-1)

View File

@@ -0,0 +1,169 @@
[linalg.algs.blas1.dot]
# 29 Numerics library [[numerics]](./#numerics)
## 29.9 Basic linear algebra algorithms [[linalg]](linalg#algs.blas1.dot)
### 29.9.13 BLAS 1 algorithms [[linalg.algs.blas1]](linalg.algs.blas1#dot)
#### 29.9.13.7 Dot product of two vectors [linalg.algs.blas1.dot]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13587)
[*Note [1](#note-1)*:
The functions in this section correspond to the BLAS
functions xDOT, xDOTU, and xDOTC[[bib]](bibliography#bib:blas1 "Bibliography")[.](#1.sentence-1)
— *end note*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13593)
The following elements apply to all functions in [linalg.algs.blas1.dot][.](#2.sentence-1)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13596)
*Mandates*: *compatible-static-extents*<InVec1, InVec2>(0, 0) is true[.](#3.sentence-1)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13600)
*Preconditions*: v1.extent(0) equals v2.extent(0)[.](#4.sentence-1)
[🔗](#lib:dot)
`template<[in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec1, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec2, class Scalar>
Scalar dot(InVec1 v1, InVec2 v2, Scalar init);
template<class ExecutionPolicy, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec1, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec2, class Scalar>
Scalar dot(ExecutionPolicy&& exec,
InVec1 v1, InVec2 v2, Scalar init);
`
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13614)
These functions compute a non-conjugated dot product
with an explicitly specified result type[.](#5.sentence-1)
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13618)
*Returns*: Let N be v1.extent(0)[.](#6.sentence-1)
- [(6.1)](#6.1)
init if N is zero;
- [(6.2)](#6.2)
otherwise,*GENERALIZED_SUM*(plus<>(), init, v1[0]*v2[0], …, v1[N-1]*v2[N-1]).
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13629)
*Remarks*: If InVec1::value_type, InVec2::value_type, and Scalar are all floating-point types or specializations of complex,
and if Scalar has higher precision
than InVec1::value_type or InVec2::value_type,
then intermediate terms in the sum use Scalar's precision or greater[.](#7.sentence-1)
[🔗](#lib:dot_)
` template<[in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec1, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec2>
auto dot(InVec1 v1, InVec2 v2);
template<class ExecutionPolicy, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec1, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec2>
auto dot(ExecutionPolicy&& exec,
InVec1 v1, InVec2 v2);
`
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13648)
These functions compute a non-conjugated dot product with a default result type[.](#8.sentence-1)
[9](#9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13651)
*Effects*: Let T bedecltype(declval<typename InVec1::value_type>() * declval<typename InVec2::value_type>())[.](#9.sentence-1)
Then,
- [(9.1)](#9.1)
the two-parameter overload is equivalent to:return dot(v1, v2, T{}); and
- [(9.2)](#9.2)
the three-parameter overload is equivalent to:return dot(std::forward<ExecutionPolicy>(exec), v1, v2, T{});
[🔗](#lib:dotc)
`template<[in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec1, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec2, class Scalar>
Scalar dotc(InVec1 v1, InVec2 v2, Scalar init);
template<class ExecutionPolicy, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec1, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec2, class Scalar>
Scalar dotc(ExecutionPolicy&& exec,
InVec1 v1, InVec2 v2, Scalar init);
`
[10](#10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13682)
These functions compute a conjugated dot product
with an explicitly specified result type[.](#10.sentence-1)
[11](#11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13686)
*Effects*:
- [(11.1)](#11.1)
The three-parameter overload is equivalent to:return dot(conjugated(v1), v2, init); and
- [(11.2)](#11.2)
the four-parameter overload is equivalent to:return dot(std::forward<ExecutionPolicy>(exec), conjugated(v1), v2, init);
[🔗](#lib:dotc_)
`template<[in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec1, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec2>
auto dotc(InVec1 v1, InVec2 v2);
template<class ExecutionPolicy, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec1, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec2>
auto dotc(ExecutionPolicy&& exec,
InVec1 v1, InVec2 v2);
`
[12](#12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13714)
These functions compute a conjugated dot product with a default result type[.](#12.sentence-1)
[13](#13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13717)
*Effects*: Let T be decltype(*conj-if-needed*(declval<typename InVec1::value_type>()) * declval<typename InVec2::value_type>())[.](#13.sentence-1)
Then,
- [(13.1)](#13.1)
the two-parameter overload is equivalent to:return dotc(v1, v2, T{}); and
- [(13.2)](#13.2)
the three-parameter overload is equivalent toreturn dotc(std::forward<ExecutionPolicy>(exec), v1, v2, T{});

View File

@@ -0,0 +1,102 @@
[linalg.algs.blas1.givens]
# 29 Numerics library [[numerics]](./#numerics)
## 29.9 Basic linear algebra algorithms [[linalg]](linalg#algs.blas1.givens)
### 29.9.13 BLAS 1 algorithms [[linalg.algs.blas1]](linalg.algs.blas1#givens)
#### 29.9.13.2 Givens rotations [linalg.algs.blas1.givens]
#### [29.9.13.2.1](#lartg) Compute Givens rotation [[linalg.algs.blas1.givens.lartg]](linalg.algs.blas1.givens.lartg)
[🔗](#lib:setup_givens_rotation)
`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;
`
[1](#lartg-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13370)
These functions compute the Givens plane rotation
represented by the two values c and s such that the 2 x 2 system of equations
[cs−¯¯¯sc]â‹[ab]=[r0]
holds, where c is always a real scalar, and c2+|s|2=1[.](#lartg-1.sentence-2)
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[.](#lartg-1.sentence-3)
[*Note [1](#lartg-note-1)*:
These functions correspond to the LAPACK function xLARTG[[bib]](bibliography#bib:lapack "Bibliography")[.](#lartg-1.sentence-4)
— *end note*]
[2](#lartg-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13402)
*Returns*: c, s, r,
where c and s form the Givens plane rotation
corresponding to the input a and b,
and r is the Euclidean norm of the two-component vector
formed by a and b[.](#lartg-2.sentence-1)
#### [29.9.13.2.2](#rot) Apply a computed Givens rotation to vectors [[linalg.algs.blas1.givens.rot]](linalg.algs.blas1.givens.rot)
[🔗](#lib:apply_givens_rotation)
`template<[inout-vector](linalg.helpers.concepts#concept:inout-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutVec1, [inout-vector](linalg.helpers.concepts#concept:inout-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutVec2, class Real>
void apply_givens_rotation(InOutVec1 x, InOutVec2 y, Real c, Real s);
template<class ExecutionPolicy, [inout-vector](linalg.helpers.concepts#concept:inout-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutVec1, [inout-vector](linalg.helpers.concepts#concept:inout-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutVec2, class Real>
void apply_givens_rotation(ExecutionPolicy&& exec,
InOutVec1 x, InOutVec2 y, Real c, Real s);
template<[inout-vector](linalg.helpers.concepts#concept:inout-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutVec1, [inout-vector](linalg.helpers.concepts#concept:inout-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutVec2, class Real>
void apply_givens_rotation(InOutVec1 x, InOutVec2 y, Real c, complex<Real> s);
template<class ExecutionPolicy, [inout-vector](linalg.helpers.concepts#concept:inout-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutVec1, [inout-vector](linalg.helpers.concepts#concept:inout-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutVec2, class Real>
void apply_givens_rotation(ExecutionPolicy&& exec,
InOutVec1 x, InOutVec2 y, Real c, complex<Real> s);
`
[1](#rot-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13428)
[*Note [1](#rot-note-1)*:
These functions correspond to the BLAS function xROT[[bib]](bibliography#bib:blas1 "Bibliography")[.](#rot-1.sentence-1)
— *end note*]
[2](#rot-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13433)
*Mandates*: *compatible-static-extents*<InOutVec1, InOutVec2>(0, 0) is true[.](#rot-2.sentence-1)
[3](#rot-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13437)
*Preconditions*: x.extent(0) equals y.extent(0)[.](#rot-3.sentence-1)
[4](#rot-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13441)
*Effects*: Applies the plane rotation
specified by c and s to
the input vectors x and y,
as if the rotation were a 2 x 2 matrix and
the input vectors were successive rows of a matrix with two rows[.](#rot-4.sentence-1)

View File

@@ -0,0 +1,54 @@
[linalg.algs.blas1.givens.lartg]
# 29 Numerics library [[numerics]](./#numerics)
## 29.9 Basic linear algebra algorithms [[linalg]](linalg#algs.blas1.givens.lartg)
### 29.9.13 BLAS 1 algorithms [[linalg.algs.blas1]](linalg.algs.blas1#givens.lartg)
#### 29.9.13.2 Givens rotations [[linalg.algs.blas1.givens]](linalg.algs.blas1.givens#lartg)
#### 29.9.13.2.1 Compute Givens rotation [linalg.algs.blas1.givens.lartg]
[🔗](#lib:setup_givens_rotation)
`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;
`
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13370)
These functions compute the Givens plane rotation
represented by the two values c and s such that the 2 x 2 system of equations
[cs−¯¯¯sc]â‹[ab]=[r0]
holds, where c is always a real scalar, and c2+|s|2=1[.](#1.sentence-2)
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[.](#1.sentence-3)
[*Note [1](#note-1)*:
These functions correspond to the LAPACK function xLARTG[[bib]](bibliography#bib:lapack "Bibliography")[.](#1.sentence-4)
— *end note*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13402)
*Returns*: c, s, r,
where c and s form the Givens plane rotation
corresponding to the input a and b,
and r is the Euclidean norm of the two-component vector
formed by a and b[.](#2.sentence-1)

View File

@@ -0,0 +1,57 @@
[linalg.algs.blas1.givens.rot]
# 29 Numerics library [[numerics]](./#numerics)
## 29.9 Basic linear algebra algorithms [[linalg]](linalg#algs.blas1.givens.rot)
### 29.9.13 BLAS 1 algorithms [[linalg.algs.blas1]](linalg.algs.blas1#givens.rot)
#### 29.9.13.2 Givens rotations [[linalg.algs.blas1.givens]](linalg.algs.blas1.givens#rot)
#### 29.9.13.2.2 Apply a computed Givens rotation to vectors [linalg.algs.blas1.givens.rot]
[🔗](#lib:apply_givens_rotation)
`template<[inout-vector](linalg.helpers.concepts#concept:inout-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutVec1, [inout-vector](linalg.helpers.concepts#concept:inout-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutVec2, class Real>
void apply_givens_rotation(InOutVec1 x, InOutVec2 y, Real c, Real s);
template<class ExecutionPolicy, [inout-vector](linalg.helpers.concepts#concept:inout-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutVec1, [inout-vector](linalg.helpers.concepts#concept:inout-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutVec2, class Real>
void apply_givens_rotation(ExecutionPolicy&& exec,
InOutVec1 x, InOutVec2 y, Real c, Real s);
template<[inout-vector](linalg.helpers.concepts#concept:inout-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutVec1, [inout-vector](linalg.helpers.concepts#concept:inout-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutVec2, class Real>
void apply_givens_rotation(InOutVec1 x, InOutVec2 y, Real c, complex<Real> s);
template<class ExecutionPolicy, [inout-vector](linalg.helpers.concepts#concept:inout-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutVec1, [inout-vector](linalg.helpers.concepts#concept:inout-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutVec2, class Real>
void apply_givens_rotation(ExecutionPolicy&& exec,
InOutVec1 x, InOutVec2 y, Real c, complex<Real> s);
`
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13428)
[*Note [1](#note-1)*:
These functions correspond to the BLAS function xROT[[bib]](bibliography#bib:blas1 "Bibliography")[.](#1.sentence-1)
— *end note*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13433)
*Mandates*: *compatible-static-extents*<InOutVec1, InOutVec2>(0, 0) is true[.](#2.sentence-1)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13437)
*Preconditions*: x.extent(0) equals y.extent(0)[.](#3.sentence-1)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13441)
*Effects*: Applies the plane rotation
specified by c and s to
the input vectors x and y,
as if the rotation were a 2 x 2 matrix and
the input vectors were successive rows of a matrix with two rows[.](#4.sentence-1)

View File

@@ -0,0 +1,58 @@
[linalg.algs.blas1.iamax]
# 29 Numerics library [[numerics]](./#numerics)
## 29.9 Basic linear algebra algorithms [[linalg]](linalg#algs.blas1.iamax)
### 29.9.13 BLAS 1 algorithms [[linalg.algs.blas1]](linalg.algs.blas1#iamax)
#### 29.9.13.11 Index of maximum absolute value of vector elements [linalg.algs.blas1.iamax]
[🔗](#lib:vector_idx_abs_max)
`template<[in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec>
typename InVec::extents_type vector_idx_abs_max(InVec v);
template<class ExecutionPolicy, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec>
typename InVec::extents_type vector_idx_abs_max(ExecutionPolicy&& exec, InVec v);
`
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13953)
[*Note [1](#note-1)*:
These functions correspond to the BLAS function IxAMAX[[bib]](bibliography#bib:blas1 "Bibliography")[.](#1.sentence-1)
— *end note*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13958)
Let T bedecltype(*abs-if-needed*(*real-if-needed*(declval<typename InVec::value_type>())) +*abs-if-needed*(*imag-if-needed*(declval<typename InVec::value_type>())))
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13965)
*Mandates*: declval<T>() < declval<T>() is a valid expression[.](#3.sentence-1)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13969)
*Returns*:
- [(4.1)](#4.1)
numeric_limits<typename InVec::size_type>::max() if v has zero elements;
- [(4.2)](#4.2)
otherwise, the index of the first element of v having largest absolute value,
if InVec::value_type is an arithmetic type;
- [(4.3)](#4.3)
otherwise, the index of the first element ve of v for which*abs-if-needed*(*real-if-needed*(ve)) + *abs-if-needed*(*imag-if-needed*(ve)) has the largest value[.](#4.sentence-1)

View File

@@ -0,0 +1,84 @@
[linalg.algs.blas1.matfrobnorm]
# 29 Numerics library [[numerics]](./#numerics)
## 29.9 Basic linear algebra algorithms [[linalg]](linalg#algs.blas1.matfrobnorm)
### 29.9.13 BLAS 1 algorithms [[linalg.algs.blas1]](linalg.algs.blas1#matfrobnorm)
#### 29.9.13.12 Frobenius norm of a matrix [linalg.algs.blas1.matfrobnorm]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13991)
[*Note [1](#note-1)*:
These functions exist in the BLAS standard[[bib]](bibliography#bib:blas-std "Bibliography") but are not part of the reference implementation[.](#1.sentence-1)
— *end note*]
[🔗](#lib:matrix_frob_norm)
`template<[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Scalar>
Scalar matrix_frob_norm(InMat A, Scalar init);
template<class ExecutionPolicy, [in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Scalar>
Scalar matrix_frob_norm(ExecutionPolicy&& exec, InMat A, Scalar init);
`
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14007)
*Mandates*: Let a be*abs-if-needed*(declval<typename InMat::value_type>())[.](#2.sentence-1)
Then, decltype(init + a * a) is convertible to Scalar[.](#2.sentence-2)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14014)
*Returns*: The square root of the sum of squares
of init and the absolute values of the elements of A[.](#3.sentence-1)
[*Note [2](#note-2)*:
For init equal to zero,
this is the Frobenius norm of the matrix A[.](#3.sentence-2)
— *end note*]
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14023)
*Remarks*: If InMat::value_type and Scalar are all floating-point types or specializations of complex,
and if Scalar has higher precision
than InMat::value_type,
then intermediate terms in the sum use Scalar's precision or greater[.](#4.sentence-1)
[🔗](#lib:matrix_frob_norm_)
`template<[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat>
auto matrix_frob_norm(InMat A);
template<class ExecutionPolicy, [in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat>
auto matrix_frob_norm(ExecutionPolicy&& exec, InMat A);
`
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14041)
*Effects*: Let a be*abs-if-needed*(declval<typename InMat::value_type>())[.](#5.sentence-1)
Let T bedecltype(a * a)[.](#5.sentence-2)
Then,
- [(5.1)](#5.1)
the one-parameter overload is equivalent to:return matrix_frob_norm(A, T{}); and
- [(5.2)](#5.2)
the two-parameter overload is equivalent to:return matrix_frob_norm(std::forward<ExecutionPolicy>(exec), A, T{});

View File

@@ -0,0 +1,89 @@
[linalg.algs.blas1.matinfnorm]
# 29 Numerics library [[numerics]](./#numerics)
## 29.9 Basic linear algebra algorithms [[linalg]](linalg#algs.blas1.matinfnorm)
### 29.9.13 BLAS 1 algorithms [[linalg.algs.blas1]](linalg.algs.blas1#matinfnorm)
#### 29.9.13.14 Infinity norm of a matrix [linalg.algs.blas1.matinfnorm]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14139)
[*Note [1](#note-1)*:
These functions exist in the BLAS standard[[bib]](bibliography#bib:blas-std "Bibliography") but are not part of the reference implementation[.](#1.sentence-1)
— *end note*]
[🔗](#lib:matrix_inf_norm)
`template<[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Scalar>
Scalar matrix_inf_norm(InMat A, Scalar init);
template<class ExecutionPolicy, [in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Scalar>
Scalar matrix_inf_norm(ExecutionPolicy&& exec, InMat A, Scalar init);
`
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14154)
*Mandates*: decltype(*abs-if-needed*(declval<typename InMat::value_type>())) is convertible to Scalar[.](#2.sentence-1)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14159)
*Returns*:
- [(3.1)](#3.1)
init if A.extent(0) is zero;
- [(3.2)](#3.2)
otherwise,
the sum of init and the infinity norm of the matrix A[.](#3.sentence-1)
[*Note [2](#note-2)*:
The infinity norm of the matrix A is the maximum over all rows of A,
of the sum of the absolute values
of the elements of the row[.](#3.sentence-2)
— *end note*]
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14175)
*Remarks*: If InMat::value_type and Scalar are all floating-point types or specializations of complex,
and if Scalar has higher precision
than InMat::value_type,
then intermediate terms in the sum use Scalar's precision or greater[.](#4.sentence-1)
[🔗](#lib:matrix_inf_norm_)
`template<[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat>
auto matrix_inf_norm(InMat A);
template<class ExecutionPolicy, [in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat>
auto matrix_inf_norm(ExecutionPolicy&& exec, InMat A);
`
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14194)
*Effects*: Let T bedecltype(*abs-if-needed*(declval<typename InMat::value_type>())[.](#5.sentence-1)
Then,
- [(5.1)](#5.1)
the one-parameter overload is equivalent to:return matrix_inf_norm(A, T{}); and
- [(5.2)](#5.2)
the two-parameter overload is equivalent to:return matrix_inf_norm(std::forward<ExecutionPolicy>(exec), A, T{});

View File

@@ -0,0 +1,87 @@
[linalg.algs.blas1.matonenorm]
# 29 Numerics library [[numerics]](./#numerics)
## 29.9 Basic linear algebra algorithms [[linalg]](linalg#algs.blas1.matonenorm)
### 29.9.13 BLAS 1 algorithms [[linalg.algs.blas1]](linalg.algs.blas1#matonenorm)
#### 29.9.13.13 One norm of a matrix [linalg.algs.blas1.matonenorm]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14065)
[*Note [1](#note-1)*:
These functions exist in the BLAS standard[[bib]](bibliography#bib:blas-std "Bibliography") but are not part of the reference implementation[.](#1.sentence-1)
— *end note*]
[🔗](#lib:matrix_one_norm)
`template<[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Scalar>
Scalar matrix_one_norm(InMat A, Scalar init);
template<class ExecutionPolicy, [in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Scalar>
Scalar matrix_one_norm(ExecutionPolicy&& exec, InMat A, Scalar init);
`
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14080)
*Mandates*: decltype(*abs-if-needed*(declval<typename InMat::value_type>())) is convertible to Scalar[.](#2.sentence-1)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14085)
*Returns*:
- [(3.1)](#3.1)
init if A.extent(1) is zero;
- [(3.2)](#3.2)
otherwise, the sum of init and the one norm of the matrix A[.](#3.sentence-1)
[*Note [2](#note-2)*:
The one norm of the matrix A is the maximum over all columns of A,
of the sum of the absolute values of the elements of the column[.](#3.sentence-2)
— *end note*]
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14099)
*Remarks*: If InMat::value_type and Scalar are all floating-point types or specializations of complex,
and if Scalar has higher precision
than InMat::value_type,
then intermediate terms in the sum use Scalar's precision or greater[.](#4.sentence-1)
[🔗](#lib:matrix_one_norm_)
`template<[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat>
auto matrix_one_norm(InMat A);
template<class ExecutionPolicy, [in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat>
auto matrix_one_norm(ExecutionPolicy&& exec, InMat A);
`
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14117)
*Effects*: Let T bedecltype(*abs-if-needed*(declval<typename InMat::value_type>())[.](#5.sentence-1)
Then,
- [(5.1)](#5.1)
the one-parameter overload is equivalent to:return matrix_one_norm(A, T{}); and
- [(5.2)](#5.2)
the two-parameter overload is equivalent to:return matrix_one_norm(std::forward<ExecutionPolicy>(exec), A, T{});

View File

@@ -0,0 +1,89 @@
[linalg.algs.blas1.nrm2]
# 29 Numerics library [[numerics]](./#numerics)
## 29.9 Basic linear algebra algorithms [[linalg]](linalg#algs.blas1.nrm2)
### 29.9.13 BLAS 1 algorithms [[linalg.algs.blas1]](linalg.algs.blas1#nrm2)
#### 29.9.13.9 Euclidean norm of a vector [linalg.algs.blas1.nrm2]
[🔗](#lib:vector_two_norm)
`template<[in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec, class Scalar>
Scalar vector_two_norm(InVec v, Scalar init);
template<class ExecutionPolicy, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec, class Scalar>
Scalar vector_two_norm(ExecutionPolicy&& exec, InVec v, Scalar init);
`
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13796)
[*Note [1](#note-1)*:
These functions correspond to the BLAS function xNRM2[[bib]](bibliography#bib:blas1 "Bibliography")[.](#1.sentence-1)
— *end note*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13801)
*Mandates*: Let a be*abs-if-needed*(declval<typename InVec::value_type>())[.](#2.sentence-1)
Then, decltype(init + a * a is convertible to Scalar[.](#2.sentence-2)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13807)
*Returns*: The square root of the sum of the square of init and the squares of the absolute values of the elements of v[.](#3.sentence-1)
[*Note [2](#note-2)*:
For init equal to zero, this is the Euclidean norm
(also called 2-norm) of the vector v[.](#3.sentence-2)
— *end note*]
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13815)
*Remarks*: If InVec::value_type, and Scalar are all floating-point types or specializations of complex,
and if Scalar has higher precision
than InVec::value_type,
then intermediate terms in the sum use Scalar's precision or greater[.](#4.sentence-1)
[*Note [3](#note-3)*:
An implementation of this function for floating-point types T can use the scaled_sum_of_squares result fromvector_sum_of_squares(x, {.scaling_factor=1.0, .scaled_sum_of_squares=init})[.](#4.sentence-2)
— *end note*]
[🔗](#lib:vector_two_norm_)
`template<[in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec>
auto vector_two_norm(InVec v);
template<class ExecutionPolicy, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec>
auto vector_two_norm(ExecutionPolicy&& exec, InVec v);
`
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13838)
*Effects*: Let a be*abs-if-needed*(declval<typename InVec::value_type>())[.](#5.sentence-1)
Let T be decltype(a * a)[.](#5.sentence-2)
Then,
- [(5.1)](#5.1)
the one-parameter overload is equivalent to:return vector_two_norm(v, T{}); and
- [(5.2)](#5.2)
the two-parameter overload is equivalent to:return vector_two_norm(std::forward<ExecutionPolicy>(exec), v, T{});

View File

@@ -0,0 +1,35 @@
[linalg.algs.blas1.scal]
# 29 Numerics library [[numerics]](./#numerics)
## 29.9 Basic linear algebra algorithms [[linalg]](linalg#algs.blas1.scal)
### 29.9.13 BLAS 1 algorithms [[linalg.algs.blas1]](linalg.algs.blas1#scal)
#### 29.9.13.4 Multiply the elements of an object in place by a scalar [linalg.algs.blas1.scal]
[🔗](#lib:scale)
`template<class Scalar, [inout-object](linalg.helpers.concepts#concept:inout-object "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutObj>
void scale(Scalar alpha, InOutObj x);
template<class ExecutionPolicy, class Scalar, [inout-object](linalg.helpers.concepts#concept:inout-object "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutObj>
void scale(ExecutionPolicy&& exec, Scalar alpha, InOutObj x);
`
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13498)
[*Note [1](#note-1)*:
These functions correspond to the BLAS function xSCAL[[bib]](bibliography#bib:blas1 "Bibliography")[.](#1.sentence-1)
— *end note*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13503)
*Effects*: Overwrites x with the result of
computing the elementwise multiplication αx,
where the scalar α is alpha[.](#2.sentence-1)

View File

@@ -0,0 +1,58 @@
[linalg.algs.blas1.ssq]
# 29 Numerics library [[numerics]](./#numerics)
## 29.9 Basic linear algebra algorithms [[linalg]](linalg#algs.blas1.ssq)
### 29.9.13 BLAS 1 algorithms [[linalg.algs.blas1]](linalg.algs.blas1#ssq)
#### 29.9.13.8 Scaled sum of squares of a vector's elements [linalg.algs.blas1.ssq]
[🔗](#lib:vector_sum_of_squares)
`template<[in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec, class Scalar>
sum_of_squares_result<Scalar> vector_sum_of_squares(InVec v, sum_of_squares_result<Scalar> init);
template<class ExecutionPolicy, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec, class Scalar>
sum_of_squares_result<Scalar> vector_sum_of_squares(ExecutionPolicy&& exec,
InVec v, sum_of_squares_result<Scalar> init);
`
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13748)
[*Note [1](#note-1)*:
These functions correspond to the LAPACK function xLASSQ[[bib]](bibliography#bib:lapack "Bibliography")[.](#1.sentence-1)
— *end note*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13753)
*Mandates*: decltype(*abs-if-needed*(declval<typename InVec::value_type>())) is convertible to Scalar[.](#2.sentence-1)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13757)
*Effects*: Returns a value result such that
- [(3.1)](#3.1)
result.scaling_factor is the maximum of init.scaling_factor and*abs-if-needed*(x[i]) for all i in the domain of v; and
- [(3.2)](#3.2)
let s2init beinit.scaling_factor * init.scaling_factor * init.scaled_sum_of_squares then result.scaling_factor * result.scaling_factor * result.scaled_sum_of_squares equals the sum of s2init and
the squares of *abs-if-needed*(x[i]) for all i in the domain of v[.](#3.sentence-1)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13776)
*Remarks*: If InVec::value_type, and Scalar are all floating-point types or specializations of complex,
and if Scalar has higher precision
than InVec::value_type,
then intermediate terms in the sum use Scalar's precision or greater[.](#4.sentence-1)

View File

@@ -0,0 +1,51 @@
[linalg.algs.blas1.swap]
# 29 Numerics library [[numerics]](./#numerics)
## 29.9 Basic linear algebra algorithms [[linalg]](linalg#algs.blas1.swap)
### 29.9.13 BLAS 1 algorithms [[linalg.algs.blas1]](linalg.algs.blas1#swap)
#### 29.9.13.3 Swap matrix or vector elements [linalg.algs.blas1.swap]
[🔗](#lib:swap_elements)
`template<[inout-object](linalg.helpers.concepts#concept:inout-object "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutObj1, [inout-object](linalg.helpers.concepts#concept:inout-object "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutObj2>
void swap_elements(InOutObj1 x, InOutObj2 y);
template<class ExecutionPolicy, [inout-object](linalg.helpers.concepts#concept:inout-object "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutObj1, [inout-object](linalg.helpers.concepts#concept:inout-object "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutObj2>
void swap_elements(ExecutionPolicy&& exec, InOutObj1 x, InOutObj2 y);
`
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13461)
[*Note [1](#note-1)*:
These functions correspond to the BLAS function xSWAP[[bib]](bibliography#bib:blas1 "Bibliography")[.](#1.sentence-1)
— *end note*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13466)
*Constraints*: x.rank() equals y.rank()[.](#2.sentence-1)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13470)
*Mandates*: For all r in the range [0, x.rank()),*compatible-static-extents*<InOutObj1, InOutObj2>(r, r) is true[.](#3.sentence-1)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13478)
*Preconditions*: x.extents() equals y.extents()[.](#4.sentence-1)
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13482)
*Effects*: Swaps all corresponding elements of x and y[.](#5.sentence-1)

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,116 @@
[linalg.algs.blas2.gemv]
# 29 Numerics library [[numerics]](./#numerics)
## 29.9 Basic linear algebra algorithms [[linalg]](linalg#algs.blas2.gemv)
### 29.9.14 BLAS 2 algorithms [[linalg.algs.blas2]](linalg.algs.blas2#gemv)
#### 29.9.14.1 General matrix-vector product [linalg.algs.blas2.gemv]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14218)
[*Note [1](#note-1)*:
These functions correspond to the BLAS function xGEMV[.](#1.sentence-1)
— *end note*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14223)
The following elements apply to all functions in [linalg.algs.blas2.gemv][.](#2.sentence-1)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14226)
*Mandates*:
- [(3.1)](#3.1)
*possibly-multipliable*<decltype(A), decltype(x), decltype(y)>() is true, and
- [(3.2)](#3.2)
*possibly-addable*<decltype(x), decltype(y), decltype(z)>() is true for those overloads that take a z parameter[.](#3.sentence-1)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14237)
*Preconditions*:
- [(4.1)](#4.1)
*multipliable*(A,x,y) is true, and
- [(4.2)](#4.2)
*addable*(x,y,z) is true for those overloads that take a z parameter[.](#4.sentence-1)
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14246)
*Complexity*: O(x.extent(0)×A.extent(1))[.](#5.sentence-1)
[🔗](#lib:matrix_vector_product)
`template<[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec, [out-vector](linalg.helpers.concepts#concept:out-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") OutVec>
void matrix_vector_product(InMat A, InVec x, OutVec y);
template<class ExecutionPolicy, [in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec, [out-vector](linalg.helpers.concepts#concept:out-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") OutVec>
void matrix_vector_product(ExecutionPolicy&& exec, InMat A, InVec x, OutVec y);
`
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14259)
These functions perform an overwriting matrix-vector product[.](#6.sentence-1)
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14262)
*Effects*: Computes y=Ax[.](#7.sentence-1)
[*Example [1](#example-1)*: constexpr size_t num_rows = 5;constexpr size_t num_cols = 6;
// y = 3.0 * A * xvoid 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 yvoid 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 example*]
[🔗](#lib:matrix_vector_product_)
` template<[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec1, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec2, [out-vector](linalg.helpers.concepts#concept:out-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") OutVec>
void matrix_vector_product(InMat A, InVec1 x, InVec2 y, OutVec z);
template<class ExecutionPolicy,
[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec1, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec2, [out-vector](linalg.helpers.concepts#concept:out-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") OutVec>
void matrix_vector_product(ExecutionPolicy&& exec,
InMat A, InVec1 x, InVec2 y, OutVec z);
`
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14297)
These functions perform an updating matrix-vector product[.](#8.sentence-1)
[9](#9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14300)
*Effects*: Computes z=y+Ax[.](#9.sentence-1)
[10](#10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14304)
*Remarks*: z may alias y[.](#10.sentence-1)
[*Example [2](#example-2)*: // y = 3.0 * A * x + 2.0 * yvoid 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 example*]

View File

@@ -0,0 +1,127 @@
[linalg.algs.blas2.hemv]
# 29 Numerics library [[numerics]](./#numerics)
## 29.9 Basic linear algebra algorithms [[linalg]](linalg#algs.blas2.hemv)
### 29.9.14 BLAS 2 algorithms [[linalg.algs.blas2]](linalg.algs.blas2#hemv)
#### 29.9.14.3 Hermitian matrix-vector product [linalg.algs.blas2.hemv]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14412)
[*Note [1](#note-1)*:
These functions correspond to the BLAS functionsxHEMV and xHPMV[[bib]](bibliography#bib:blas2 "Bibliography")[.](#1.sentence-1)
— *end note*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14418)
The following elements apply to all functions in [linalg.algs.blas2.hemv][.](#2.sentence-1)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14421)
*Mandates*:
- [(3.1)](#3.1)
If InMat has layout_blas_packed layout,
then the layout's Triangle template argument
has the same type as the function's Triangle template argument;
- [(3.2)](#3.2)
*compatible-static-extents*<decltype(A), decltype(A)>(0, 1) is true;
- [(3.3)](#3.3)
*possibly-multipliable*<decltype(A), decltype(x), decltype(y)>() is true; and
- [(3.4)](#3.4)
*possibly-addable*<decltype(x), decltype(y), decltype(z)>() is true for those overloads that take a z parameter[.](#3.sentence-1)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14439)
*Preconditions*:
- [(4.1)](#4.1)
A.extent(0) equals A.extent(1),
- [(4.2)](#4.2)
*multipliable*(A, x, y) is true, and
- [(4.3)](#4.3)
*addable*(x, y, z) is true for those overloads that take a z parameter[.](#4.sentence-1)
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14450)
*Complexity*: O(x.extent(0)×A.extent(1))[.](#5.sentence-1)
[🔗](#lib:hermitian_matrix_vector_product)
`template<[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec, [out-vector](linalg.helpers.concepts#concept:out-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") OutVec>
void hermitian_matrix_vector_product(InMat A, Triangle t, InVec x, OutVec y);
template<class ExecutionPolicy,
[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec, [out-vector](linalg.helpers.concepts#concept:out-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") OutVec>
void hermitian_matrix_vector_product(ExecutionPolicy&& exec,
InMat A, Triangle t, InVec x, OutVec y);
`
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14465)
These functions perform an overwriting Hermitian matrix-vector product,
taking into account the Triangle parameter
that applies to the Hermitian matrix A ([[linalg.general]](linalg.general "29.9.3General"))[.](#6.sentence-1)
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14470)
*Effects*: Computes y=Ax[.](#7.sentence-1)
[🔗](#lib:hermitian_matrix_vector_product_)
`template<[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec1, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec2, [out-vector](linalg.helpers.concepts#concept:out-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") OutVec>
void hermitian_matrix_vector_product(InMat A, Triangle t, InVec1 x, InVec2 y, OutVec z);
template<class ExecutionPolicy,
[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec1, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec2, [out-vector](linalg.helpers.concepts#concept:out-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") OutVec>
void hermitian_matrix_vector_product(ExecutionPolicy&& exec,
InMat A, Triangle t, InVec1 x, InVec2 y, OutVec z);
`
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14486)
These functions perform an updating Hermitian matrix-vector product,
taking into account the Triangle parameter
that applies to the Hermitian matrix A ([[linalg.general]](linalg.general "29.9.3General"))[.](#8.sentence-1)
[9](#9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14491)
*Effects*: Computes z=y+Ax[.](#9.sentence-1)
[10](#10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14495)
*Remarks*: z may alias y[.](#10.sentence-1)

View File

@@ -0,0 +1,89 @@
[linalg.algs.blas2.rank1]
# 29 Numerics library [[numerics]](./#numerics)
## 29.9 Basic linear algebra algorithms [[linalg]](linalg#algs.blas2.rank1)
### 29.9.14 BLAS 2 algorithms [[linalg.algs.blas2]](linalg.algs.blas2#rank1)
#### 29.9.14.6 Rank-1 (outer product) update of a matrix [linalg.algs.blas2.rank1]
[🔗](#lib:matrix_rank_1_update)
`template<[in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec1, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec2, [inout-matrix](linalg.helpers.concepts#concept:inout-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutMat>
void matrix_rank_1_update(InVec1 x, InVec2 y, InOutMat A);
template<class ExecutionPolicy, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec1, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec2, [inout-matrix](linalg.helpers.concepts#concept:inout-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutMat>
void matrix_rank_1_update(ExecutionPolicy&& exec, InVec1 x, InVec2 y, InOutMat A);
`
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14826)
These functions perform a nonsymmetric nonconjugated rank-1 update[.](#1.sentence-1)
[*Note [1](#note-1)*:
These functions correspond to the BLAS functionsxGER (for real element types) andxGERU (for complex element types)[[bib]](bibliography#bib:blas2 "Bibliography")[.](#1.sentence-2)
— *end note*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14834)
*Mandates*: *possibly-multipliable*<InOutMat, InVec2, InVec1>() is true[.](#2.sentence-1)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14839)
*Preconditions*: *multipliable*(A, y, x) is true[.](#3.sentence-1)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14843)
*Effects*: Computes a matrix A′ such that A′=A+xyT,
and assigns each element of A′ to the corresponding element of A[.](#4.sentence-1)
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14848)
*Complexity*: O(x.extent(0)×y.extent(0))[.](#5.sentence-1)
[🔗](#lib:matrix_rank_1_update_)
`template<[in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec1, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec2, [inout-matrix](linalg.helpers.concepts#concept:inout-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutMat>
void matrix_rank_1_update_c(InVec1 x, InVec2 y, InOutMat A);
template<class ExecutionPolicy, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec1, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec2, [inout-matrix](linalg.helpers.concepts#concept:inout-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutMat>
void matrix_rank_1_update_c(ExecutionPolicy&& exec, InVec1 x, InVec2 y, InOutMat A);
`
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14862)
These functions perform a nonsymmetric conjugated rank-1 update[.](#6.sentence-1)
[*Note [2](#note-2)*:
These functions correspond to the BLAS functionsxGER (for real element types) andxGERC (for complex element types)[[bib]](bibliography#bib:blas2 "Bibliography")[.](#6.sentence-2)
— *end note*]
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14870)
*Effects*:
- [(7.1)](#7.1)
For the overloads without an ExecutionPolicy argument,
equivalent to:matrix_rank_1_update(x, conjugated(y), A);
- [(7.2)](#7.2)
otherwise, equivalent to:matrix_rank_1_update(std::forward<ExecutionPolicy>(exec), x, conjugated(y), A);

View File

@@ -0,0 +1,119 @@
[linalg.algs.blas2.rank2]
# 29 Numerics library [[numerics]](./#numerics)
## 29.9 Basic linear algebra algorithms [[linalg]](linalg#algs.blas2.rank2)
### 29.9.14 BLAS 2 algorithms [[linalg.algs.blas2]](linalg.algs.blas2#rank2)
#### 29.9.14.8 Symmetric and Hermitian rank-2 matrix updates [linalg.algs.blas2.rank2]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15023)
[*Note [1](#note-1)*:
These functions correspond to the BLAS functionsxSYR2,xSPR2, xHER2 and xHPR2[[bib]](bibliography#bib:blas2 "Bibliography")[.](#1.sentence-1)
— *end note*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15029)
The following elements apply to all functions in [linalg.algs.blas2.rank2][.](#2.sentence-1)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15032)
*Mandates*:
- [(3.1)](#3.1)
If InOutMat has layout_blas_packed layout,
then the layout's Triangle template argument has
the same type as the function's Triangle template argument;
- [(3.2)](#3.2)
*compatible-static-extents*<decltype(A), decltype(A)>(0, 1) is true; and
- [(3.3)](#3.3)
*possibly-multipliable*<decltype(A), decltype(x), decltype(y)>() is true[.](#3.sentence-1)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15047)
*Preconditions*:
- [(4.1)](#4.1)
A.extent(0) equals A.extent(1), and
- [(4.2)](#4.2)
*multipliable*(A, x, y) is true[.](#4.sentence-1)
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15056)
*Complexity*: O(x.extent(0)×y.extent(0))[.](#5.sentence-1)
[🔗](#lib:symmetric_matrix_rank_2_update)
`template<[in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec1, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec2,
[possibly-packed-inout-matrix](linalg.helpers.concepts#concept:possibly-packed-inout-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutMat, class Triangle>
void symmetric_matrix_rank_2_update(InVec1 x, InVec2 y, InOutMat A, Triangle t);
template<class ExecutionPolicy, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec1, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec2,
[possibly-packed-inout-matrix](linalg.helpers.concepts#concept:possibly-packed-inout-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutMat, class Triangle>
void symmetric_matrix_rank_2_update(ExecutionPolicy&& exec,
InVec1 x, InVec2 y, InOutMat A, Triangle t);
`
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15072)
These functions perform
a symmetric rank-2 update of the symmetric matrix A,
taking into account the Triangle parameter
that applies to A ([[linalg.general]](linalg.general "29.9.3General"))[.](#6.sentence-1)
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15078)
*Effects*: Computes A′ such that A′=A+xyT+yxT and
assigns each element of A′ to the corresponding element of A[.](#7.sentence-1)
[🔗](#lib:hermitian_matrix_rank_2_update)
`template<[in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec1, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec2,
[possibly-packed-inout-matrix](linalg.helpers.concepts#concept:possibly-packed-inout-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutMat, class Triangle>
void hermitian_matrix_rank_2_update(InVec1 x, InVec2 y, InOutMat A, Triangle t);
template<class ExecutionPolicy, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec1, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec2,
[possibly-packed-inout-matrix](linalg.helpers.concepts#concept:possibly-packed-inout-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutMat, class Triangle>
void hermitian_matrix_rank_2_update(ExecutionPolicy&& exec,
InVec1 x, InVec2 y, InOutMat A, Triangle t);
`
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15096)
These functions perform
a Hermitian rank-2 update of the Hermitian matrix A,
taking into account the Triangle parameter
that applies to A ([[linalg.general]](linalg.general "29.9.3General"))[.](#8.sentence-1)
[9](#9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15102)
*Effects*: Computes A′ such that A′=A+xyH+yxH and
assigns each element of A′ to the corresponding element of A[.](#9.sentence-1)

View File

@@ -0,0 +1,169 @@
[linalg.algs.blas2.symherrank1]
# 29 Numerics library [[numerics]](./#numerics)
## 29.9 Basic linear algebra algorithms [[linalg]](linalg#algs.blas2.symherrank1)
### 29.9.14 BLAS 2 algorithms [[linalg.algs.blas2]](linalg.algs.blas2#symherrank1)
#### 29.9.14.7 Symmetric or Hermitian Rank-1 (outer product) update of a matrix [linalg.algs.blas2.symherrank1]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14889)
[*Note [1](#note-1)*:
These functions correspond to the BLAS functionsxSYR, xSPR, xHER, and xHPR[[bib]](bibliography#bib:blas2 "Bibliography")[.](#1.sentence-1)
They have overloads taking a scaling factor alpha,
because it would be impossible to express the updateA=A−xxT otherwise[.](#1.sentence-2)
— *end note*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14898)
The following elements apply to all functions in [linalg.algs.blas2.symherrank1][.](#2.sentence-1)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14901)
*Mandates*:
- [(3.1)](#3.1)
If InOutMat has layout_blas_packed layout,
then the layout's Triangle template argument has
the same type as the function's Triangle template argument;
- [(3.2)](#3.2)
*compatible-static-extents*<decltype(A), decltype(A)>(0, 1) is true; and
- [(3.3)](#3.3)
*compatible-static-extents*<decltype(A), decltype(x)>(0, 0) is true[.](#3.sentence-1)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14916)
*Preconditions*:
- [(4.1)](#4.1)
A.extent(0) equals A.extent(1), and
- [(4.2)](#4.2)
A.extent(0) equals x.extent(0)[.](#4.sentence-1)
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14925)
*Complexity*: O(x.extent(0)×x.extent(0))[.](#5.sentence-1)
[🔗](#lib:symmetric_matrix_rank_1_update)
`template<class Scalar, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec, [possibly-packed-inout-matrix](linalg.helpers.concepts#concept:possibly-packed-inout-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutMat, class Triangle>
void symmetric_matrix_rank_1_update(Scalar alpha, InVec x, InOutMat A, Triangle t);
template<class ExecutionPolicy,
class Scalar, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec, [possibly-packed-inout-matrix](linalg.helpers.concepts#concept:possibly-packed-inout-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutMat, class Triangle>
void symmetric_matrix_rank_1_update(ExecutionPolicy&& exec,
Scalar alpha, InVec x, InOutMat A, Triangle t);
`
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14940)
These functions perform
a symmetric rank-1 update of the symmetric matrix A,
taking into account the Triangle parameter
that applies to A ([[linalg.general]](linalg.general "29.9.3General"))[.](#6.sentence-1)
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14946)
*Effects*: Computes a matrix A′ such thatA′=A+αxxT, where the scalar α is alpha,
and assigns each element of A′ to the corresponding element of A[.](#7.sentence-1)
[🔗](#lib:symmetric_matrix_rank_1_update_)
`template<[in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec, [possibly-packed-inout-matrix](linalg.helpers.concepts#concept:possibly-packed-inout-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutMat, class Triangle>
void symmetric_matrix_rank_1_update(InVec x, InOutMat A, Triangle t);
template<class ExecutionPolicy,
[in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec, [possibly-packed-inout-matrix](linalg.helpers.concepts#concept:possibly-packed-inout-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutMat, class Triangle>
void symmetric_matrix_rank_1_update(ExecutionPolicy&& exec, InVec x, InOutMat A, Triangle t);
`
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14963)
These functions perform
a symmetric rank-1 update of the symmetric matrix A,
taking into account the Triangle parameter
that applies to A ([[linalg.general]](linalg.general "29.9.3General"))[.](#8.sentence-1)
[9](#9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14969)
*Effects*: Computes a matrix A′ such that A′=A+xxT and assigns each element of A′ to the corresponding element of A[.](#9.sentence-1)
[🔗](#lib:hermitian_matrix_rank_1_update)
`template<class Scalar, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec, [possibly-packed-inout-matrix](linalg.helpers.concepts#concept:possibly-packed-inout-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutMat, class Triangle>
void hermitian_matrix_rank_1_update(Scalar alpha, InVec x, InOutMat A, Triangle t);
template<class ExecutionPolicy,
class Scalar, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec, [possibly-packed-inout-matrix](linalg.helpers.concepts#concept:possibly-packed-inout-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutMat, class Triangle>
void hermitian_matrix_rank_1_update(ExecutionPolicy&& exec,
Scalar alpha, InVec x, InOutMat A, Triangle t);
`
[10](#10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14986)
These functions perform
a Hermitian rank-1 update of the Hermitian matrix A,
taking into account the Triangle parameter
that applies to A ([[linalg.general]](linalg.general "29.9.3General"))[.](#10.sentence-1)
[11](#11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14992)
*Effects*: Computes A′ such thatA′=A+αxxH, where the scalar α is alpha,
and assigns each element of A′ to the corresponding element of A[.](#11.sentence-1)
[🔗](#lib:hermitian_matrix_rank_1_update_)
`template<[in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec, [possibly-packed-inout-matrix](linalg.helpers.concepts#concept:possibly-packed-inout-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutMat, class Triangle>
void hermitian_matrix_rank_1_update(InVec x, InOutMat A, Triangle t);
template<class ExecutionPolicy,
[in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec, [possibly-packed-inout-matrix](linalg.helpers.concepts#concept:possibly-packed-inout-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutMat, class Triangle>
void hermitian_matrix_rank_1_update(ExecutionPolicy&& exec, InVec x, InOutMat A, Triangle t);
`
[12](#12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15009)
These functions perform
a Hermitian rank-1 update of the Hermitian matrix A,
taking into account the Triangle parameter
that applies to A ([[linalg.general]](linalg.general "29.9.3General"))[.](#12.sentence-1)
[13](#13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15015)
*Effects*: Computes a matrix A′ such that A′=A+xxH and
assigns each element of A′ to the corresponding element of A[.](#13.sentence-1)

View File

@@ -0,0 +1,127 @@
[linalg.algs.blas2.symv]
# 29 Numerics library [[numerics]](./#numerics)
## 29.9 Basic linear algebra algorithms [[linalg]](linalg#algs.blas2.symv)
### 29.9.14 BLAS 2 algorithms [[linalg.algs.blas2]](linalg.algs.blas2#symv)
#### 29.9.14.2 Symmetric matrix-vector product [linalg.algs.blas2.symv]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14321)
[*Note [1](#note-1)*:
These functions correspond to the BLAS functionsxSYMV and xSPMV[[bib]](bibliography#bib:blas2 "Bibliography")[.](#1.sentence-1)
— *end note*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14327)
The following elements apply to all functions in [linalg.algs.blas2.symv][.](#2.sentence-1)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14330)
*Mandates*:
- [(3.1)](#3.1)
If InMat has layout_blas_packed layout,
then the layout's Triangle template argument has
the same type as the function's Triangle template argument;
- [(3.2)](#3.2)
*compatible-static-extents*<decltype(A), decltype(A)>(0, 1) is true;
- [(3.3)](#3.3)
*possibly-multipliable*<decltype(A), decltype(x), decltype(y)>() is true; and
- [(3.4)](#3.4)
*possibly-addable*<decltype(x), decltype(y), decltype(z)>() is true for those overloads that take a z parameter[.](#3.sentence-1)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14347)
*Preconditions*:
- [(4.1)](#4.1)
A.extent(0) equals A.extent(1),
- [(4.2)](#4.2)
*multipliable*(A,x,y) is true, and
- [(4.3)](#4.3)
*addable*(x,y,z) is true for those overloads that take a z parameter[.](#4.sentence-1)
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14359)
*Complexity*: O(x.extent(0)×A.extent(1))[.](#5.sentence-1)
[🔗](#lib:symmetric_matrix_vector_product)
`template<[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec, [out-vector](linalg.helpers.concepts#concept:out-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") OutVec>
void symmetric_matrix_vector_product(InMat A, Triangle t, InVec x, OutVec y);
template<class ExecutionPolicy,
[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec, [out-vector](linalg.helpers.concepts#concept:out-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") OutVec>
void symmetric_matrix_vector_product(ExecutionPolicy&& exec,
InMat A, Triangle t, InVec x, OutVec y);
`
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14375)
These functions perform an overwriting symmetric matrix-vector product,
taking into account the Triangle parameter
that applies to the symmetric matrix A ([[linalg.general]](linalg.general "29.9.3General"))[.](#6.sentence-1)
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14380)
*Effects*: Computes y=Ax[.](#7.sentence-1)
[🔗](#lib:symmetric_matrix_vector_product_)
`template<[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec1, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec2, [out-vector](linalg.helpers.concepts#concept:out-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") OutVec>
void symmetric_matrix_vector_product(InMat A, Triangle t, InVec1 x, InVec2 y, OutVec z);
template<class ExecutionPolicy,
[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec1, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec2, [out-vector](linalg.helpers.concepts#concept:out-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") OutVec>
void symmetric_matrix_vector_product(ExecutionPolicy&& exec,
InMat A, Triangle t, InVec1 x, InVec2 y, OutVec z);
`
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14396)
These functions perform an updating symmetric matrix-vector product,
taking into account the Triangle parameter
that applies to the symmetric matrix A ([[linalg.general]](linalg.general "29.9.3General"))[.](#8.sentence-1)
[9](#9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14401)
*Effects*: Computes z=y+Ax[.](#9.sentence-1)
[10](#10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14405)
*Remarks*: z may alias y[.](#10.sentence-1)

View File

@@ -0,0 +1,187 @@
[linalg.algs.blas2.trmv]
# 29 Numerics library [[numerics]](./#numerics)
## 29.9 Basic linear algebra algorithms [[linalg]](linalg#algs.blas2.trmv)
### 29.9.14 BLAS 2 algorithms [[linalg.algs.blas2]](linalg.algs.blas2#trmv)
#### 29.9.14.4 Triangular matrix-vector product [linalg.algs.blas2.trmv]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14502)
[*Note [1](#note-1)*:
These functions correspond to the BLAS functionsxTRMV and xTPMV[[bib]](bibliography#bib:blas2 "Bibliography")[.](#1.sentence-1)
— *end note*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14508)
The following elements apply to all functions in [linalg.algs.blas2.trmv][.](#2.sentence-1)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14511)
*Mandates*:
- [(3.1)](#3.1)
If InMat has layout_blas_packed layout,
then the layout's Triangle template argument has
the same type as the function's Triangle template argument;
- [(3.2)](#3.2)
*compatible-static-extents*<decltype(A), decltype(A)>(0, 1) is true;
- [(3.3)](#3.3)
*compatible-static-extents*<decltype(A), decltype(y)>(0, 0) is true;
- [(3.4)](#3.4)
*compatible-static-extents*<decltype(A), decltype(x)>(0, 0) is true for those overloads that take an x parameter; and
- [(3.5)](#3.5)
*compatible-static-extents*<decltype(A), decltype(z)>(0, 0) is true for those overloads that take a z parameter[.](#3.sentence-1)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14532)
*Preconditions*:
- [(4.1)](#4.1)
A.extent(0) equals A.extent(1),
- [(4.2)](#4.2)
A.extent(0) equals y.extent(0),
- [(4.3)](#4.3)
A.extent(0) equals x.extent(0) for those overloads that take an x parameter, and
- [(4.4)](#4.4)
A.extent(0) equals z.extent(0) for those overloads that take a z parameter[.](#4.sentence-1)
[🔗](#lib:triangular_matrix_vector_product)
`template<[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec,
[out-vector](linalg.helpers.concepts#concept:out-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") OutVec>
void triangular_matrix_vector_product(InMat A, Triangle t, DiagonalStorage d, InVec x, OutVec y);
template<class ExecutionPolicy,
[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec,
[out-vector](linalg.helpers.concepts#concept:out-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") OutVec>
void triangular_matrix_vector_product(ExecutionPolicy&& exec,
InMat A, Triangle t, DiagonalStorage d, InVec x, OutVec y);
`
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14559)
These functions perform
an overwriting triangular matrix-vector product,
taking into account the Triangle and DiagonalStorage parameters
that apply to the triangular matrix A ([[linalg.general]](linalg.general "29.9.3General"))[.](#5.sentence-1)
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14565)
*Effects*: Computes y=Ax[.](#6.sentence-1)
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14569)
*Complexity*: O(x.extent(0)×A.extent(1))[.](#7.sentence-1)
[🔗](#lib:triangular_matrix_vector_product_)
`template<[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage, [inout-vector](linalg.helpers.concepts#concept:inout-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutVec>
void triangular_matrix_vector_product(InMat A, Triangle t, DiagonalStorage d, InOutVec y);
template<class ExecutionPolicy,
[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage, [inout-vector](linalg.helpers.concepts#concept:inout-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutVec>
void triangular_matrix_vector_product(ExecutionPolicy&& exec,
InMat A, Triangle t, DiagonalStorage d, InOutVec y);
`
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14586)
These functions perform an in-place triangular matrix-vector product,
taking into account the Triangle and DiagonalStorage parameters
that apply to the triangular matrix A ([[linalg.general]](linalg.general "29.9.3General"))[.](#8.sentence-1)
[*Note [2](#note-2)*:
Performing this operation in place hinders parallelization[.](#8.sentence-2)
However, other ExecutionPolicy specific optimizations,
such as vectorization, are still possible[.](#8.sentence-3)
— *end note*]
[9](#9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14596)
*Effects*: Computes a vector y′ such that y′=Ay,
and assigns each element of y′ to the corresponding element of y[.](#9.sentence-1)
[10](#10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14601)
*Complexity*: O(y.extent(0)×A.extent(1))[.](#10.sentence-1)
[🔗](#lib:triangular_matrix_vector_product__)
`template<[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage,
[in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec1, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec2, [out-vector](linalg.helpers.concepts#concept:out-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") OutVec>
void triangular_matrix_vector_product(InMat A, Triangle t, DiagonalStorage d,
InVec1 x, InVec2 y, OutVec z);
template<class ExecutionPolicy, [in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage,
[in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec1, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec2, [out-vector](linalg.helpers.concepts#concept:out-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") OutVec>
void triangular_matrix_vector_product(ExecutionPolicy&& exec,
InMat A, Triangle t, DiagonalStorage d,
InVec1 x, InVec2 y, OutVec z);
`
[11](#11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14620)
These functions perform an updating triangular matrix-vector product,
taking into account the Triangle and DiagonalStorage parameters
that apply to the triangular matrix A ([[linalg.general]](linalg.general "29.9.3General"))[.](#11.sentence-1)
[12](#12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14625)
*Effects*: Computes z=y+Ax[.](#12.sentence-1)
[13](#13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14629)
*Complexity*: O(x.extent(0)×A.extent(1))[.](#13.sentence-1)
[14](#14)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14633)
*Remarks*: z may alias y[.](#14.sentence-1)

View File

@@ -0,0 +1,206 @@
[linalg.algs.blas2.trsv]
# 29 Numerics library [[numerics]](./#numerics)
## 29.9 Basic linear algebra algorithms [[linalg]](linalg#algs.blas2.trsv)
### 29.9.14 BLAS 2 algorithms [[linalg.algs.blas2]](linalg.algs.blas2#trsv)
#### 29.9.14.5 Solve a triangular linear system [linalg.algs.blas2.trsv]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14640)
[*Note [1](#note-1)*:
These functions correspond to the BLAS functionsxTRSV and xTPSV[[bib]](bibliography#bib:blas2 "Bibliography")[.](#1.sentence-1)
— *end note*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14646)
The following elements apply to all functions in [linalg.algs.blas2.trsv][.](#2.sentence-1)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14649)
*Mandates*:
- [(3.1)](#3.1)
If InMat has layout_blas_packed layout,
then the layout's Triangle template argument has
the same type as the function's Triangle template argument;
- [(3.2)](#3.2)
*compatible-static-extents*<decltype(A), decltype(A)>(0, 1) is true;
- [(3.3)](#3.3)
*compatible-static-extents*<decltype(A), decltype(b)>(0, 0) is true; and
- [(3.4)](#3.4)
*compatible-static-extents*<decltype(A), decltype(x)>(0, 0) is true for those overloads that take an x parameter[.](#3.sentence-1)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14667)
*Preconditions*:
- [(4.1)](#4.1)
A.extent(0) equals A.extent(1),
- [(4.2)](#4.2)
A.extent(0) equals b.extent(0), and
- [(4.3)](#4.3)
A.extent(0) equals x.extent(0) for those overloads that take an x parameter[.](#4.sentence-1)
[🔗](#lib:triangular_matrix_vector_solve)
` template<[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage,
[in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec, [out-vector](linalg.helpers.concepts#concept:out-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") OutVec, class BinaryDivideOp>
void triangular_matrix_vector_solve(InMat A, Triangle t, DiagonalStorage d,
InVec b, OutVec x, BinaryDivideOp divide);
template<class ExecutionPolicy, [in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage,
[in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec, [out-vector](linalg.helpers.concepts#concept:out-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") OutVec, class BinaryDivideOp>
void triangular_matrix_vector_solve(ExecutionPolicy&& exec,
InMat A, Triangle t, DiagonalStorage d,
InVec b, OutVec x, BinaryDivideOp divide);
`
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14694)
These functions perform
a triangular solve,
taking into account the Triangle and DiagonalStorage parameters
that apply to the triangular matrix A ([[linalg.general]](linalg.general "29.9.3General"))[.](#5.sentence-1)
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14700)
*Effects*: Computes a vector x′ such that b=Ax′,
and assigns each element of x′ to the corresponding element of x[.](#6.sentence-1)
If no such x′ exists,
then the elements of x are valid but unspecified[.](#6.sentence-2)
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14707)
*Complexity*: O(A.extent(1)×b.extent(0))[.](#7.sentence-1)
[🔗](#lib:triangular_matrix_vector_solve_)
`template<[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage,
[in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec, [out-vector](linalg.helpers.concepts#concept:out-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") OutVec>
void triangular_matrix_vector_solve(InMat A, Triangle t, DiagonalStorage d, InVec b, OutVec x);
`
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14720)
*Effects*: Equivalent to:triangular_matrix_vector_solve(A, t, d, b, x, divides<void>{});
[🔗](#lib:triangular_matrix_vector_solve__)
`template<class ExecutionPolicy, [in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage,
[in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec, [out-vector](linalg.helpers.concepts#concept:out-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") OutVec>
void triangular_matrix_vector_solve(ExecutionPolicy&& exec,
InMat A, Triangle t, DiagonalStorage d, InVec b, OutVec x);
`
[9](#9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14737)
*Effects*: Equivalent to:triangular_matrix_vector_solve(std::forward<ExecutionPolicy>(exec),
A, t, d, b, x, divides<void>{});
[🔗](#lib:triangular_matrix_vector_solve___)
`template<[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage,
[inout-vector](linalg.helpers.concepts#concept:inout-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutVec, class BinaryDivideOp>
void triangular_matrix_vector_solve(InMat A, Triangle t, DiagonalStorage d,
InOutVec b, BinaryDivideOp divide);
template<class ExecutionPolicy, [in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage,
[inout-vector](linalg.helpers.concepts#concept:inout-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutVec, class BinaryDivideOp>
void triangular_matrix_vector_solve(ExecutionPolicy&& exec,
InMat A, Triangle t, DiagonalStorage d,
InOutVec b, BinaryDivideOp divide);
`
[10](#10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14760)
These functions perform an in-place triangular solve,
taking into account the Triangle and DiagonalStorage parameters
that apply to the triangular matrix A ([[linalg.general]](linalg.general "29.9.3General"))[.](#10.sentence-1)
[*Note [2](#note-2)*:
Performing triangular solve in place hinders parallelization[.](#10.sentence-2)
However, other ExecutionPolicy specific optimizations,
such as vectorization, are still possible[.](#10.sentence-3)
— *end note*]
[11](#11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14770)
*Effects*: Computes a vector x′ such that b=Ax′,
and assigns each element of x′ to the corresponding element of b[.](#11.sentence-1)
If no such x′ exists,
then the elements of b are valid but unspecified[.](#11.sentence-2)
[12](#12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14777)
*Complexity*: O(A.extent(1)×b.extent(0))[.](#12.sentence-1)
[🔗](#lib:triangular_matrix_vector_solve____)
`template<[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage, [inout-vector](linalg.helpers.concepts#concept:inout-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutVec>
void triangular_matrix_vector_solve(InMat A, Triangle t, DiagonalStorage d, InOutVec b);
`
[13](#13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14789)
*Effects*: Equivalent to:triangular_matrix_vector_solve(A, t, d, b, divides<void>{});
[🔗](#lib:triangular_matrix_vector_solve_____)
`template<class ExecutionPolicy,
[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage, [inout-vector](linalg.helpers.concepts#concept:inout-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutVec>
void triangular_matrix_vector_solve(ExecutionPolicy&& exec,
InMat A, Triangle t, DiagonalStorage d, InOutVec b);
`
[14](#14)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14806)
*Effects*: Equivalent to:triangular_matrix_vector_solve(std::forward<ExecutionPolicy>(exec),
A, t, d, b, divides<void>{});

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,92 @@
[linalg.algs.blas3.gemm]
# 29 Numerics library [[numerics]](./#numerics)
## 29.9 Basic linear algebra algorithms [[linalg]](linalg#algs.blas3.gemm)
### 29.9.15 BLAS 3 algorithms [[linalg.algs.blas3]](linalg.algs.blas3#gemm)
#### 29.9.15.1 General matrix-matrix product [linalg.algs.blas3.gemm]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15112)
[*Note [1](#note-1)*:
These functions correspond to the BLAS function xGEMM[[bib]](bibliography#bib:blas3 "Bibliography")[.](#1.sentence-1)
— *end note*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15117)
The following elements apply
to all functions in [linalg.algs.blas3.gemm]
in addition to function-specific elements[.](#2.sentence-1)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15122)
*Mandates*: *possibly-multipliable*<decltype(A), decltype(B), decltype(C)>() is true[.](#3.sentence-1)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15127)
*Preconditions*: *multipliable*(A, B, C) is true[.](#4.sentence-1)
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15131)
*Complexity*: O(A.extent(0)×A.extent(1)×B.extent(1))[.](#5.sentence-1)
[🔗](#lib:matrix_product)
` template<[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat1, [in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat2, [out-matrix](linalg.helpers.concepts#concept:out-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") OutMat>
void matrix_product(InMat1 A, InMat2 B, OutMat C);
template<class ExecutionPolicy, [in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat1, [in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat2, [out-matrix](linalg.helpers.concepts#concept:out-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") OutMat>
void matrix_product(ExecutionPolicy&& exec, InMat1 A, InMat2 B, OutMat C);
`
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15144)
*Effects*: Computes C=AB[.](#6.sentence-1)
[🔗](#lib:matrix_product_)
`template<[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat1, [in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat2, [in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat3, [out-matrix](linalg.helpers.concepts#concept:out-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") OutMat>
void matrix_product(InMat1 A, InMat2 B, InMat3 E, OutMat C);
template<class ExecutionPolicy,
[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat1, [in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat2, [in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat3, [out-matrix](linalg.helpers.concepts#concept:out-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") OutMat>
void matrix_product(ExecutionPolicy&& exec, InMat1 A, InMat2 B, InMat3 E, OutMat C);
`
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15159)
*Mandates*: *possibly-addable*<InMat3, InMat3, OutMat>() is true[.](#7.sentence-1)
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15163)
*Preconditions*: *addable*(E, E, C) is true[.](#8.sentence-1)
[9](#9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15167)
*Effects*: Computes C=E+AB[.](#9.sentence-1)
[10](#10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15171)
*Remarks*: C may alias E[.](#10.sentence-1)

View File

@@ -0,0 +1,242 @@
[linalg.algs.blas3.inplacetrsm]
# 29 Numerics library [[numerics]](./#numerics)
## 29.9 Basic linear algebra algorithms [[linalg]](linalg#algs.blas3.inplacetrsm)
### 29.9.15 BLAS 3 algorithms [[linalg.algs.blas3]](linalg.algs.blas3#inplacetrsm)
#### 29.9.15.7 Solve multiple triangular linear systems in-place [linalg.algs.blas3.inplacetrsm]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15943)
[*Note [1](#note-1)*:
These functions correspond to the BLAS function xTRSM[[bib]](bibliography#bib:blas3 "Bibliography")[.](#1.sentence-1)
— *end note*]
[🔗](#lib:triangular_matrix_matrix_left_solve)
`template<[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage,
[inout-matrix](linalg.helpers.concepts#concept:inout-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutMat, class BinaryDivideOp>
void triangular_matrix_matrix_left_solve(InMat A, Triangle t, DiagonalStorage d,
InOutMat B, BinaryDivideOp divide);
template<class ExecutionPolicy, [in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage,
[inout-matrix](linalg.helpers.concepts#concept:inout-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutMat, class BinaryDivideOp>
void triangular_matrix_matrix_left_solve(ExecutionPolicy&& exec,
InMat A, Triangle t, DiagonalStorage d,
InOutMat B, BinaryDivideOp divide);
`
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15962)
These functions perform multiple in-place matrix solves,
taking into account the Triangle and DiagonalStorage parameters
that apply to the triangular matrix A ([[linalg.general]](linalg.general "29.9.3General"))[.](#2.sentence-1)
[*Note [2](#note-2)*:
This algorithm makes it possible
to compute factorizations like Cholesky and LU in place[.](#2.sentence-2)
Performing triangular solve in place hinders parallelization[.](#2.sentence-3)
However, other ExecutionPolicy specific optimizations,
such as vectorization, are still possible[.](#2.sentence-4)
— *end note*]
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15974)
*Mandates*:
- [(3.1)](#3.1)
If InMat has layout_blas_packed layout,
then the layout's Triangle template argument has
the same type as the function's Triangle template argument;
- [(3.2)](#3.2)
*possibly-multipliable*<InMat, InOutMat, InOutMat>() is true; and
- [(3.3)](#3.3)
*compatible-static-extents*<InMat, InMat>(0, 1) is true[.](#3.sentence-1)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15989)
*Preconditions*:
- [(4.1)](#4.1)
*multipliable*(A, B, B) is true, and
- [(4.2)](#4.2)
A.extent(0) == A.extent(1) is true[.](#4.sentence-1)
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15998)
*Effects*: Computes X′ such that AX′=B,
and assigns each element of X′ to the corresponding element of B[.](#5.sentence-1)
If so such X′ exists,
then the elements of B are valid but unspecified[.](#5.sentence-2)
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L16005)
*Complexity*: O(A.extent(0)×A.extent(1)×B.extent(1))[.](#6.sentence-1)
[🔗](#lib:triangular_matrix_matrix_left_solve_)
`template<[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage, [inout-matrix](linalg.helpers.concepts#concept:inout-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutMat>
void triangular_matrix_matrix_left_solve(InMat A, Triangle t, DiagonalStorage d,
InOutMat B);
`
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L16018)
*Effects*: Equivalent to:triangular_matrix_matrix_left_solve(A, t, d, B, divides<void>{});
[🔗](#lib:triangular_matrix_matrix_left_solve__)
` template<class ExecutionPolicy,
[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage, [inout-matrix](linalg.helpers.concepts#concept:inout-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutMat>
void triangular_matrix_matrix_left_solve(ExecutionPolicy&& exec,
InMat A, Triangle t, DiagonalStorage d,
InOutMat B);
`
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L16036)
*Effects*: Equivalent to:triangular_matrix_matrix_left_solve(std::forward<ExecutionPolicy>(exec),
A, t, d, B, divides<void>{});
[🔗](#lib:triangular_matrix_matrix_right_solve)
`template<[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage,
[inout-matrix](linalg.helpers.concepts#concept:inout-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutMat, class BinaryDivideOp>
void triangular_matrix_matrix_right_solve(InMat A, Triangle t, DiagonalStorage d,
InOutMat B, BinaryDivideOp divide);
template<class ExecutionPolicy, [in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage,
[inout-matrix](linalg.helpers.concepts#concept:inout-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutMat, class BinaryDivideOp>
void triangular_matrix_matrix_right_solve(ExecutionPolicy&& exec,
InMat A, Triangle t, DiagonalStorage d,
InOutMat B, BinaryDivideOp divide);
`
[9](#9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L16059)
These functions perform multiple in-place matrix solves,
taking into account the Triangle and DiagonalStorage parameters
that apply to the triangular matrix A ([[linalg.general]](linalg.general "29.9.3General"))[.](#9.sentence-1)
[*Note [3](#note-3)*:
This algorithm makes it possible
to compute factorizations like Cholesky and LU in place[.](#9.sentence-2)
Performing triangular solve in place hinders parallelization[.](#9.sentence-3)
However, other ExecutionPolicy specific optimizations,
such as vectorization, are still possible[.](#9.sentence-4)
— *end note*]
[10](#10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L16071)
*Mandates*:
- [(10.1)](#10.1)
If InMat has layout_blas_packed layout,
then the layout's Triangle template argument has
the same type as the function's Triangle template argument;
- [(10.2)](#10.2)
*possibly-multipliable*<InOutMat, InMat, InOutMat>() is true; and
- [(10.3)](#10.3)
*compatible-static-extents*<InMat, InMat>(0, 1) is true[.](#10.sentence-1)
[11](#11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L16085)
*Preconditions*:
- [(11.1)](#11.1)
*multipliable*(B, A, B) is true, and
- [(11.2)](#11.2)
A.extent(0) == A.extent(1) is true[.](#11.sentence-1)
[12](#12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L16094)
*Effects*: Computes X′ such that X′A=B,
and assigns each element of X′ to the corresponding element of B[.](#12.sentence-1)
If so such X′ exists,
then the elements of B are valid but unspecified[.](#12.sentence-2)
[13](#13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L16101)
*Complexity*: O(A.extent(0)×A.extent(1)×B.extent(1))[.](#13.sentence-1)
[🔗](#lib:triangular_matrix_matrix_right_solve_)
`template<[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage, [inout-matrix](linalg.helpers.concepts#concept:inout-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutMat>
void triangular_matrix_matrix_right_solve(InMat A, Triangle t, DiagonalStorage d, InOutMat B);
`
[14](#14)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L16113)
*Effects*: Equivalent to:triangular_matrix_matrix_right_solve(A, t, d, B, divides<void>{});
[🔗](#lib:triangular_matrix_matrix_right_solve__)
`template<class ExecutionPolicy,
[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage, [inout-matrix](linalg.helpers.concepts#concept:inout-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutMat>
void triangular_matrix_matrix_right_solve(ExecutionPolicy&& exec,
InMat A, Triangle t, DiagonalStorage d,
InOutMat B);
`
[15](#15)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L16131)
*Effects*: Equivalent to:triangular_matrix_matrix_right_solve(std::forward<ExecutionPolicy>(exec),
A, t, d, B, divides<void>{});

View File

@@ -0,0 +1,102 @@
[linalg.algs.blas3.rank2k]
# 29 Numerics library [[numerics]](./#numerics)
## 29.9 Basic linear algebra algorithms [[linalg]](linalg#algs.blas3.rank2k)
### 29.9.15 BLAS 3 algorithms [[linalg.algs.blas3]](linalg.algs.blas3#rank2k)
#### 29.9.15.5 Rank-2k update of a symmetric or Hermitian matrix [linalg.algs.blas3.rank2k]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15659)
[*Note [1](#note-1)*:
These functions correspond to the BLAS functionsxSYR2K and xHER2K[[bib]](bibliography#bib:blas3 "Bibliography")[.](#1.sentence-1)
— *end note*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15665)
The following elements apply to all functions in [linalg.algs.blas3.rank2k][.](#2.sentence-1)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15668)
*Mandates*:
- [(3.1)](#3.1)
If InOutMat has layout_blas_packed layout,
then the layout's Triangle template argument has
the same type as the function's Triangle template argument;
- [(3.2)](#3.2)
*possibly-addable*<decltype(A), decltype(B), decltype(C)>() is true; and
- [(3.3)](#3.3)
*compatible-static-extents*<decltype(A), decltype(A)>(0, 1) is true[.](#3.sentence-1)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15683)
*Preconditions*:
- [(4.1)](#4.1)
*addable*(A, B, C) is true, and
- [(4.2)](#4.2)
A.extent(0) equals A.extent(1)[.](#4.sentence-1)
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15692)
*Complexity*: O(A.extent(0)×A.extent(1)×C.extent(0))[.](#5.sentence-1)
[🔗](#lib:symmetric_matrix_rank_2k_update)
`template<[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat1, [in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat2,
[possibly-packed-inout-matrix](linalg.helpers.concepts#concept:possibly-packed-inout-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutMat, class Triangle>
void symmetric_matrix_rank_2k_update(InMat1 A, InMat2 B, InOutMat C, Triangle t);
template<class ExecutionPolicy, [in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat1, [in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat2,
[possibly-packed-inout-matrix](linalg.helpers.concepts#concept:possibly-packed-inout-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutMat, class Triangle>
void symmetric_matrix_rank_2k_update(ExecutionPolicy&& exec,
InMat1 A, InMat2 B, InOutMat C, Triangle t);
`
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15708)
*Effects*: Computes a matrix C′ such that C′=C+ABT+BAT,
and assigns each element of C′ to the corresponding element of C[.](#6.sentence-1)
[🔗](#lib:hermitian_matrix_rank_2k_update)
`template<[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat1, [in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat2,
[possibly-packed-inout-matrix](linalg.helpers.concepts#concept:possibly-packed-inout-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutMat, class Triangle>
void hermitian_matrix_rank_2k_update(InMat1 A, InMat2 B, InOutMat C, Triangle t);
template<class ExecutionPolicy,
[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat1, [in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat2,
[possibly-packed-inout-matrix](linalg.helpers.concepts#concept:possibly-packed-inout-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutMat, class Triangle>
void hermitian_matrix_rank_2k_update(ExecutionPolicy&& exec,
InMat1 A, InMat2 B, InOutMat C, Triangle t);
`
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15727)
*Effects*: Computes a matrix C′ such that C′=C+ABH+BAH,
and assigns each element of C′ to the corresponding element of C[.](#7.sentence-1)

View File

@@ -0,0 +1,143 @@
[linalg.algs.blas3.rankk]
# 29 Numerics library [[numerics]](./#numerics)
## 29.9 Basic linear algebra algorithms [[linalg]](linalg#algs.blas3.rankk)
### 29.9.15 BLAS 3 algorithms [[linalg.algs.blas3]](linalg.algs.blas3#rankk)
#### 29.9.15.4 Rank-k update of a symmetric or Hermitian matrix [linalg.algs.blas3.rankk]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15545)
[*Note [1](#note-1)*:
These functions correspond to the BLAS functionsxSYRK and xHERK[[bib]](bibliography#bib:blas3 "Bibliography")[.](#1.sentence-1)
— *end note*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15551)
The following elements apply to all functions in [linalg.algs.blas3.rankk][.](#2.sentence-1)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15554)
*Mandates*:
- [(3.1)](#3.1)
If InOutMat has layout_blas_packed layout,
then the layout's Triangle template argument has
the same type as the function's Triangle template argument;
- [(3.2)](#3.2)
*compatible-static-extents*<decltype(A), decltype(A)>(0, 1) is true;
- [(3.3)](#3.3)
*compatible-static-extents*<decltype(C), decltype(C)>(0, 1) is true; and
- [(3.4)](#3.4)
*compatible-static-extents*<decltype(A), decltype(C)>(0, 0) is true[.](#3.sentence-1)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15572)
*Preconditions*:
- [(4.1)](#4.1)
A.extent(0) equals A.extent(1),
- [(4.2)](#4.2)
C.extent(0) equals C.extent(1), and
- [(4.3)](#4.3)
A.extent(0) equals C.extent(0)[.](#4.sentence-1)
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15583)
*Complexity*: O(A.extent(0)×A.extent(1)×C.extent(0))[.](#5.sentence-1)
[🔗](#lib:symmetric_matrix_rank_k_update)
` template<class Scalar, [in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, [possibly-packed-inout-matrix](linalg.helpers.concepts#concept:possibly-packed-inout-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutMat, class Triangle>
void symmetric_matrix_rank_k_update(Scalar alpha, InMat A, InOutMat C, Triangle t);
template<class ExecutionPolicy, class Scalar,
[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, [possibly-packed-inout-matrix](linalg.helpers.concepts#concept:possibly-packed-inout-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutMat, class Triangle>
void symmetric_matrix_rank_k_update(ExecutionPolicy&& exec,
Scalar alpha, InMat A, InOutMat C, Triangle t);
`
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15598)
*Effects*: Computes a matrix C′ such that C′=C+αAAT,
where the scalar α is alpha,
and assigns each element of C′ to the corresponding element of C[.](#6.sentence-1)
[🔗](#lib:symmetric_matrix_rank_k_update_)
`template<[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, [possibly-packed-inout-matrix](linalg.helpers.concepts#concept:possibly-packed-inout-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutMat, class Triangle>
void symmetric_matrix_rank_k_update(InMat A, InOutMat C, Triangle t);
template<class ExecutionPolicy,
[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, [possibly-packed-inout-matrix](linalg.helpers.concepts#concept:possibly-packed-inout-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutMat, class Triangle>
void symmetric_matrix_rank_k_update(ExecutionPolicy&& exec,
InMat A, InOutMat C, Triangle t);
`
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15616)
*Effects*: Computes a matrix C′ such that C′=C+AAT, and
assigns each element of C′ to the corresponding element of C[.](#7.sentence-1)
[🔗](#lib:hermitian_matrix_rank_k_update)
`template<class Scalar, [in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, [possibly-packed-inout-matrix](linalg.helpers.concepts#concept:possibly-packed-inout-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutMat, class Triangle>
void hermitian_matrix_rank_k_update(Scalar alpha, InMat A, InOutMat C, Triangle t);
template<class ExecutionPolicy,
class Scalar, [in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, [possibly-packed-inout-matrix](linalg.helpers.concepts#concept:possibly-packed-inout-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutMat, class Triangle>
void hermitian_matrix_rank_k_update(ExecutionPolicy&& exec,
Scalar alpha, InMat A, InOutMat C, Triangle t);
`
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15633)
*Effects*: Computes a matrix C′ such that C′=C+αAAH,
where the scalar α is alpha,
and assigns each element of C′ to the corresponding element of C[.](#8.sentence-1)
[🔗](#lib:hermitian_matrix_rank_k_update_)
`template<[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, [possibly-packed-inout-matrix](linalg.helpers.concepts#concept:possibly-packed-inout-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutMat, class Triangle>
void hermitian_matrix_rank_k_update(InMat A, InOutMat C, Triangle t);
template<class ExecutionPolicy,
[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, [possibly-packed-inout-matrix](linalg.helpers.concepts#concept:possibly-packed-inout-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutMat, class Triangle>
void hermitian_matrix_rank_k_update(ExecutionPolicy&& exec,
InMat A, InOutMat C, Triangle t);
`
[9](#9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15651)
*Effects*: Computes a matrix C′ such that C′=C+AAH, and
assigns each element of C′ to the corresponding element of C[.](#9.sentence-1)

View File

@@ -0,0 +1,139 @@
[linalg.algs.blas3.trmm]
# 29 Numerics library [[numerics]](./#numerics)
## 29.9 Basic linear algebra algorithms [[linalg]](linalg#algs.blas3.trmm)
### 29.9.15 BLAS 3 algorithms [[linalg.algs.blas3]](linalg.algs.blas3#trmm)
#### 29.9.15.3 In-place triangular matrix-matrix product [linalg.algs.blas3.trmm]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15445)
These functions perform
an in-place matrix-matrix multiply,
taking into account
the Triangle and DiagonalStorage parameters
that apply to the triangular matrix A ([[linalg.general]](linalg.general "29.9.3General"))[.](#1.sentence-1)
[*Note [1](#note-1)*:
These functions correspond to the BLAS function xTRMM[[bib]](bibliography#bib:blas3 "Bibliography")[.](#1.sentence-2)
— *end note*]
[🔗](#lib:triangular_matrix_product)
`template<[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage, [inout-matrix](linalg.helpers.concepts#concept:inout-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutMat>
void triangular_matrix_left_product(InMat A, Triangle t, DiagonalStorage d, InOutMat C);
template<class ExecutionPolicy,
[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage, [inout-matrix](linalg.helpers.concepts#concept:inout-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutMat>
void triangular_matrix_left_product(ExecutionPolicy&& exec,
InMat A, Triangle t, DiagonalStorage d, InOutMat C);
`
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15466)
*Mandates*:
- [(2.1)](#2.1)
If InMat has layout_blas_packed layout,
then the layout's Triangle template argument has
the same type as the function's Triangle template argument;
- [(2.2)](#2.2)
*possibly-multipliable*<InMat, InOutMat, InOutMat>() is true; and
- [(2.3)](#2.3)
*compatible-static-extents*<InMat, InMat>(0, 1) is true[.](#2.sentence-1)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15480)
*Preconditions*:
- [(3.1)](#3.1)
*multipliable*(A, C, C) is true, and
- [(3.2)](#3.2)
A.extent(0) == A.extent(1) is true[.](#3.sentence-1)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15489)
*Effects*: Computes a matrix C′ such that C′=AC and
assigns each element of C′ to the corresponding element of C[.](#4.sentence-1)
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15494)
*Complexity*: O(A.extent(0)×A.extent(1)×C.extent(0))[.](#5.sentence-1)
[🔗](#lib:triangular_matrix_right_product)
`template<[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage, [inout-matrix](linalg.helpers.concepts#concept:inout-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutMat>
void triangular_matrix_right_product(InMat A, Triangle t, DiagonalStorage d, InOutMat C);
template<class ExecutionPolicy,
[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage, [inout-matrix](linalg.helpers.concepts#concept:inout-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutMat>
void triangular_matrix_right_product(ExecutionPolicy&& exec,
InMat A, Triangle t, DiagonalStorage d, InOutMat C);
`
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15510)
*Mandates*:
- [(6.1)](#6.1)
If InMat has layout_blas_packed layout,
then the layout's Triangle template argument has
the same type as the function's Triangle template argument;
- [(6.2)](#6.2)
*possibly-multipliable*<InOutMat, InMat, InOutMat>() is true; and
- [(6.3)](#6.3)
*compatible-static-extents*<InMat, InMat>(0, 1) is true[.](#6.sentence-1)
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15524)
*Preconditions*:
- [(7.1)](#7.1)
*multipliable*(C, A, C) is true, and
- [(7.2)](#7.2)
A.extent(0) == A.extent(1) is true[.](#7.sentence-1)
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15533)
*Effects*: Computes a matrix C′ such that C′=CA and
assigns each element of C′ to the corresponding element of C[.](#8.sentence-1)
[9](#9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15538)
*Complexity*: O(A.extent(0)×A.extent(1)×C.extent(0))[.](#9.sentence-1)

View File

@@ -0,0 +1,249 @@
[linalg.algs.blas3.trsm]
# 29 Numerics library [[numerics]](./#numerics)
## 29.9 Basic linear algebra algorithms [[linalg]](linalg#algs.blas3.trsm)
### 29.9.15 BLAS 3 algorithms [[linalg.algs.blas3]](linalg.algs.blas3#trsm)
#### 29.9.15.6 Solve multiple triangular linear systems [linalg.algs.blas3.trsm]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15735)
[*Note [1](#note-1)*:
These functions correspond to the BLAS function xTRSM[[bib]](bibliography#bib:blas3 "Bibliography")[.](#1.sentence-1)
— *end note*]
[🔗](#lib:triangular_matrix_matrix_left_solve)
`template<[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat1, class Triangle, class DiagonalStorage,
[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat2, [out-matrix](linalg.helpers.concepts#concept:out-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") OutMat, class BinaryDivideOp>
void triangular_matrix_matrix_left_solve(InMat1 A, Triangle t, DiagonalStorage d,
InMat2 B, OutMat X, BinaryDivideOp divide);
template<class ExecutionPolicy,
[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat1, class Triangle, class DiagonalStorage,
[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat2, [out-matrix](linalg.helpers.concepts#concept:out-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") OutMat, class BinaryDivideOp>
void triangular_matrix_matrix_left_solve(ExecutionPolicy&& exec,
InMat1 A, Triangle t, DiagonalStorage d,
InMat2 B, OutMat X, BinaryDivideOp divide);
`
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15755)
These functions perform multiple matrix solves,
taking into account the Triangle and DiagonalStorage parameters
that apply to the triangular matrix A ([[linalg.general]](linalg.general "29.9.3General"))[.](#2.sentence-1)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15760)
*Mandates*:
- [(3.1)](#3.1)
If InMat1 has layout_blas_packed layout, then the
layout's Triangle template argument has the same type as
the function's Triangle template argument;
- [(3.2)](#3.2)
*possibly-multipliable*<InMat1, OutMat, InMat2>() is true; and
- [(3.3)](#3.3)
*compatible-static-extents*<InMat1, InMat1>(0, 1) is true[.](#3.sentence-1)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15775)
*Preconditions*:
- [(4.1)](#4.1)
*multipliable*(A, X, B) is true, and
- [(4.2)](#4.2)
A.extent(0) == A.extent(1) is true[.](#4.sentence-1)
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15784)
*Effects*: Computes X′ such that AX′=B,
and assigns each element of X′ to the corresponding element of X[.](#5.sentence-1)
If no such X′ exists,
then the elements of X are valid but unspecified[.](#5.sentence-2)
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15791)
*Complexity*: O(A.extent(0)×X.extent(1)×X.extent(1))[.](#6.sentence-1)
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15796)
[*Note [2](#note-2)*:
Since the triangular matrix is on the left,
the desired divide implementation
in the case of noncommutative multiplication
is mathematically equivalent to y−1x,
where x is the first argument and y is the second argument,
and y−1 denotes the multiplicative inverse of y[.](#7.sentence-1)
— *end note*]
[🔗](#lib:triangular_matrix_matrix_left_solve_)
`template<[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat1, class Triangle, class DiagonalStorage,
[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat2, [out-matrix](linalg.helpers.concepts#concept:out-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") OutMat>
void triangular_matrix_matrix_left_solve(InMat1 A, Triangle t, DiagonalStorage d,
InMat2 B, OutMat X);
`
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15815)
*Effects*: Equivalent to:triangular_matrix_matrix_left_solve(A, t, d, B, X, divides<void>{});
[🔗](#lib:triangular_matrix_matrix_left_solve__)
`template<class ExecutionPolicy, [in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat1, class Triangle, class DiagonalStorage,
[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat2, [out-matrix](linalg.helpers.concepts#concept:out-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") OutMat>
void triangular_matrix_matrix_left_solve(ExecutionPolicy&& exec,
InMat1 A, Triangle t, DiagonalStorage d,
InMat2 B, OutMat X);
`
[9](#9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15833)
*Effects*: Equivalent to:triangular_matrix_matrix_left_solve(std::forward<ExecutionPolicy>(exec),
A, t, d, B, X, divides<void>{});
[🔗](#lib:triangular_matrix_matrix_right_solve)
`template<[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat1, class Triangle, class DiagonalStorage,
[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat2, [out-matrix](linalg.helpers.concepts#concept:out-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") OutMat, class BinaryDivideOp>
void triangular_matrix_matrix_right_solve(InMat1 A, Triangle t, DiagonalStorage d,
InMat2 B, OutMat X, BinaryDivideOp divide);
template<class ExecutionPolicy,
[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat1, class Triangle, class DiagonalStorage,
[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat2, [out-matrix](linalg.helpers.concepts#concept:out-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") OutMat, class BinaryDivideOp>
void triangular_matrix_matrix_right_solve(ExecutionPolicy&& exec,
InMat1 A, Triangle t, DiagonalStorage d,
InMat2 B, OutMat X, BinaryDivideOp divide);
`
[10](#10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15858)
These functions perform multiple matrix solves,
taking into account the Triangle and DiagonalStorage parameters
that apply to the triangular matrix A ([[linalg.general]](linalg.general "29.9.3General"))[.](#10.sentence-1)
[11](#11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15863)
*Mandates*:
- [(11.1)](#11.1)
If InMat1 has layout_blas_packed layout,
then the layout's Triangle template argument has
the same type as the function's Triangle template argument;
- [(11.2)](#11.2)
*possibly-multipliable*<OutMat, InMat1, InMat2>() is true; and
- [(11.3)](#11.3)
*compatible-static-extents*<InMat1, InMat1>(0,1) is true[.](#11.sentence-1)
[12](#12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15876)
*Preconditions*:
- [(12.1)](#12.1)
*multipliable*(X, A, B) is true, and
- [(12.2)](#12.2)
A.extent(0) == A.extent(1) is true[.](#12.sentence-1)
[13](#13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15885)
*Effects*: Computes X′ such that X′A=B,
and assigns each element of X′ to the corresponding element of X[.](#13.sentence-1)
If no such X′ exists,
then the elements of X are valid but unspecified[.](#13.sentence-2)
[14](#14)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15892)
*Complexity*: O( B.extent(0) ⋠B.extent(1) ⋠A.extent(1) )
[*Note [3](#note-3)*:
Since the triangular matrix is on the right,
the desired divide implementation
in the case of noncommutative multiplication
is mathematically equivalent to xy−1,
where x is the first argument and y is the second argument,
and y−1 denotes the multiplicative inverse of y[.](#14.sentence-1)
— *end note*]
[🔗](#lib:triangular_matrix_matrix_right_solve_)
`template<[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat1, class Triangle, class DiagonalStorage,
[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat2, [out-matrix](linalg.helpers.concepts#concept:out-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") OutMat>
void triangular_matrix_matrix_right_solve(InMat1 A, Triangle t, DiagonalStorage d,
InMat2 B, OutMat X);
`
[15](#15)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15914)
*Effects*: Equivalent to:triangular_matrix_matrix_right_solve(A, t, d, B, X, divides<void>{});
[🔗](#lib:triangular_matrix_matrix_right_solve__)
`template<class ExecutionPolicy, [in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat1, class Triangle, class DiagonalStorage,
[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat2, [out-matrix](linalg.helpers.concepts#concept:out-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") OutMat>
void triangular_matrix_matrix_right_solve(ExecutionPolicy&& exec,
InMat1 A, Triangle t, DiagonalStorage d,
InMat2 B, OutMat X);
`
[16](#16)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15932)
*Effects*: Equivalent to:triangular_matrix_matrix_right_solve(std::forward<ExecutionPolicy>(exec),
A, t, d, B, X, divides<void>{});

View File

@@ -0,0 +1,334 @@
[linalg.algs.blas3.xxmm]
# 29 Numerics library [[numerics]](./#numerics)
## 29.9 Basic linear algebra algorithms [[linalg]](linalg#algs.blas3.xxmm)
### 29.9.15 BLAS 3 algorithms [[linalg.algs.blas3]](linalg.algs.blas3#xxmm)
#### 29.9.15.2 Symmetric, Hermitian, and triangular matrix-matrix product [linalg.algs.blas3.xxmm]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15178)
[*Note [1](#note-1)*:
These functions correspond to the BLAS functionsxSYMM, xHEMM, and xTRMM[[bib]](bibliography#bib:blas3 "Bibliography")[.](#1.sentence-1)
— *end note*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15184)
The following elements apply to all functions in [linalg.algs.blas3.xxmm]
in addition to function-specific elements[.](#2.sentence-1)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15188)
*Mandates*:
- [(3.1)](#3.1)
*possibly-multipliable*<decltype(A), decltype(B), decltype(C)>() is true, and
- [(3.2)](#3.2)
*possibly-addable*<decltype(E), decltype(E), decltype(C)>() is true for those overloads that take an E parameter[.](#3.sentence-1)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15199)
*Preconditions*:
- [(4.1)](#4.1)
*multipliable*(A, B, C) is true, and
- [(4.2)](#4.2)
*addable*(E, E, C) is true for those overloads that take an E parameter[.](#4.sentence-1)
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15209)
*Complexity*: O(A.extent(0)×A.extent(1)×B.extent(1))[.](#5.sentence-1)
[🔗](#lib:symmetric_matrix_product)
`template<[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat1, class Triangle, [in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat2, [out-matrix](linalg.helpers.concepts#concept:out-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") OutMat>
void symmetric_matrix_product(InMat1 A, Triangle t, InMat2 B, OutMat C);
template<class ExecutionPolicy,
[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat1, class Triangle, [in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat2, [out-matrix](linalg.helpers.concepts#concept:out-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") OutMat>
void symmetric_matrix_product(ExecutionPolicy&& exec, InMat1 A, Triangle t, InMat2 B, OutMat C);
template<[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat1, class Triangle, [in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat2, [out-matrix](linalg.helpers.concepts#concept:out-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") OutMat>
void hermitian_matrix_product(InMat1 A, Triangle t, InMat2 B, OutMat C);
template<class ExecutionPolicy,
[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat1, class Triangle, [in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat2, [out-matrix](linalg.helpers.concepts#concept:out-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") OutMat>
void hermitian_matrix_product(ExecutionPolicy&& exec, InMat1 A, Triangle t, InMat2 B, OutMat C);
template<[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat1, class Triangle, class DiagonalStorage,
[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat2, [out-matrix](linalg.helpers.concepts#concept:out-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") OutMat>
void triangular_matrix_product(InMat1 A, Triangle t, DiagonalStorage d, InMat2 B, OutMat C);
template<class ExecutionPolicy, [in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat1, class Triangle, class DiagonalStorage,
[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat2, [out-matrix](linalg.helpers.concepts#concept:out-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") OutMat>
void triangular_matrix_product(ExecutionPolicy&& exec,
InMat1 A, Triangle t, DiagonalStorage d, InMat2 B, OutMat C);
`
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15237)
These functions perform a matrix-matrix multiply,
taking into account
the Triangle and DiagonalStorage (if applicable) parameters
that apply to the symmetric, Hermitian, or triangular (respectively) matrix A ([[linalg.general]](linalg.general "29.9.3General"))[.](#6.sentence-1)
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15243)
*Mandates*:
- [(7.1)](#7.1)
If InMat1 has layout_blas_packed layout,
then the layout's Triangle template argument has
the same type as the function's Triangle template argument; and
- [(7.2)](#7.2)
*compatible-static-extents*<InMat1, InMat1>(0, 1) is true[.](#7.sentence-1)
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15254)
*Preconditions*: A.extent(0) == A.extent(1) is true[.](#8.sentence-1)
[9](#9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15258)
*Effects*: Computes C=AB[.](#9.sentence-1)
[🔗](#lib:symmetric_matrix_product_)
` template<[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat1, [in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat2, class Triangle, [out-matrix](linalg.helpers.concepts#concept:out-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") OutMat>
void symmetric_matrix_product(InMat1 A, InMat2 B, Triangle t, OutMat C);
template<class ExecutionPolicy,
[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat1, [in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat2, class Triangle, [out-matrix](linalg.helpers.concepts#concept:out-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") OutMat>
void symmetric_matrix_product(ExecutionPolicy&& exec,
InMat1 A, InMat2 B, Triangle t, OutMat C);
template<[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat1, [in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat2, class Triangle, [out-matrix](linalg.helpers.concepts#concept:out-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") OutMat>
void hermitian_matrix_product(InMat1 A, InMat2 B, Triangle t, OutMat C);
template<class ExecutionPolicy,
[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat1, [in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat2, class Triangle, [out-matrix](linalg.helpers.concepts#concept:out-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") OutMat>
void hermitian_matrix_product(ExecutionPolicy&& exec,
InMat1 A, InMat2 B, Triangle t, OutMat C);
template<[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat1, [in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat2, class Triangle, class DiagonalStorage,
[out-matrix](linalg.helpers.concepts#concept:out-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") OutMat>
void triangular_matrix_product(InMat1 A, InMat2 B, Triangle t, DiagonalStorage d, OutMat C);
template<class ExecutionPolicy,
[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat1, [in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat2, class Triangle, class DiagonalStorage,
[out-matrix](linalg.helpers.concepts#concept:out-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") OutMat>
void triangular_matrix_product(ExecutionPolicy&& exec,
InMat1 A, InMat2 B, Triangle t, DiagonalStorage d, OutMat C);
`
[10](#10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15290)
These functions perform a matrix-matrix multiply,
taking into account
the Triangle and DiagonalStorage (if applicable) parameters
that apply to the symmetric, Hermitian, or triangular (respectively) matrix B ([[linalg.general]](linalg.general "29.9.3General"))[.](#10.sentence-1)
[11](#11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15296)
*Mandates*:
- [(11.1)](#11.1)
If InMat2 has layout_blas_packed layout,
then the layout's Triangle template argument has
the same type as the function's Triangle template argument; and
- [(11.2)](#11.2)
*compatible-static-extents*<InMat2, InMat2>(0, 1) is true[.](#11.sentence-1)
[12](#12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15307)
*Preconditions*: B.extent(0) == B.extent(1) is true[.](#12.sentence-1)
[13](#13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15311)
*Effects*: Computes C=AB[.](#13.sentence-1)
[🔗](#lib:symmetric_matrix_product__)
`template<[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat1, class Triangle, [in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat2, [in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat3,
[out-matrix](linalg.helpers.concepts#concept:out-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") OutMat>
void symmetric_matrix_product(InMat1 A, Triangle t, InMat2 B, InMat3 E, OutMat C);
template<class ExecutionPolicy,
[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat1, class Triangle, [in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat2, [in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat3,
[out-matrix](linalg.helpers.concepts#concept:out-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") OutMat>
void symmetric_matrix_product(ExecutionPolicy&& exec,
InMat1 A, Triangle t, InMat2 B, InMat3 E, OutMat C);
template<[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat1, class Triangle, [in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat2, [in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat3,
[out-matrix](linalg.helpers.concepts#concept:out-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") OutMat>
void hermitian_matrix_product(InMat1 A, Triangle t, InMat2 B, InMat3 E, OutMat C);
template<class ExecutionPolicy,
[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat1, class Triangle, [in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat2, [in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat3,
[out-matrix](linalg.helpers.concepts#concept:out-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") OutMat>
void hermitian_matrix_product(ExecutionPolicy&& exec,
InMat1 A, Triangle t, InMat2 B, InMat3 E, OutMat C);
template<[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat1, class Triangle, class DiagonalStorage,
[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat2, [in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat3, [out-matrix](linalg.helpers.concepts#concept:out-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") OutMat>
void triangular_matrix_product(InMat1 A, Triangle t, DiagonalStorage d, InMat2 B, InMat3 E,
OutMat C);
template<class ExecutionPolicy,
[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat1, class Triangle, class DiagonalStorage,
[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat2, [in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat3, [out-matrix](linalg.helpers.concepts#concept:out-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") OutMat>
void triangular_matrix_product(ExecutionPolicy&& exec,
InMat1 A, Triangle t, DiagonalStorage d, InMat2 B, InMat3 E,
OutMat C);
`
[14](#14)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15349)
These functions perform
a potentially overwriting matrix-matrix multiply-add,
taking into account the Triangle and DiagonalStorage (if applicable) parameters
that apply to the symmetric, Hermitian, or triangular (respectively) matrix A ([[linalg.general]](linalg.general "29.9.3General"))[.](#14.sentence-1)
[15](#15)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15355)
*Mandates*:
- [(15.1)](#15.1)
If InMat1 has layout_blas_packed layout, then the
layout's Triangle template argument has the same type as
the function's Triangle template argument; and
- [(15.2)](#15.2)
*compatible-static-extents*<InMat1, InMat1>(0, 1) is true[.](#15.sentence-1)
[16](#16)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15366)
*Preconditions*: A.extent(0) == A.extent(1) is true[.](#16.sentence-1)
[17](#17)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15370)
*Effects*: Computes C=E+AB[.](#17.sentence-1)
[18](#18)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15374)
*Remarks*: C may alias E[.](#18.sentence-1)
[🔗](#lib:symmetric_matrix_product___)
`template<[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat1, [in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat2, class Triangle, [in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat3,
[out-matrix](linalg.helpers.concepts#concept:out-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") OutMat>
void symmetric_matrix_product(InMat1 A, InMat2 B, Triangle t, InMat3 E, OutMat C);
template<class ExecutionPolicy,
[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat1, [in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat2, class Triangle, [in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat3,
[out-matrix](linalg.helpers.concepts#concept:out-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") OutMat>
void symmetric_matrix_product(ExecutionPolicy&& exec,
InMat1 A, InMat2 B, Triangle t, InMat3 E, OutMat C);
template<[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat1, [in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat2, class Triangle, [in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat3,
[out-matrix](linalg.helpers.concepts#concept:out-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") OutMat>
void hermitian_matrix_product(InMat1 A, InMat2 B, Triangle t, InMat3 E, OutMat C);
template<class ExecutionPolicy,
[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat1, [in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat2, class Triangle, [in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat3,
[out-matrix](linalg.helpers.concepts#concept:out-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") OutMat>
void hermitian_matrix_product(ExecutionPolicy&& exec,
InMat1 A, InMat2 B, Triangle t, InMat3 E, OutMat C);
template<[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat1, [in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat2, class Triangle, class DiagonalStorage,
[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat3, [out-matrix](linalg.helpers.concepts#concept:out-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") OutMat>
void triangular_matrix_product(InMat1 A, InMat2 B, Triangle t, DiagonalStorage d, InMat3 E,
OutMat C);
template<class ExecutionPolicy,
[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat1, [in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat2, class Triangle, class DiagonalStorage,
[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat3, [out-matrix](linalg.helpers.concepts#concept:out-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") OutMat>
void triangular_matrix_product(ExecutionPolicy&& exec,
InMat1 A, InMat2 B, Triangle t, DiagonalStorage d, InMat3 E,
OutMat C);
`
[19](#19)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15412)
These functions perform
a potentially overwriting matrix-matrix multiply-add,
taking into account
the Triangle and DiagonalStorage (if applicable) parameters
that apply to the symmetric, Hermitian, or triangular (respectively) matrix B ([[linalg.general]](linalg.general "29.9.3General"))[.](#19.sentence-1)
[20](#20)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15419)
*Mandates*:
- [(20.1)](#20.1)
If InMat2 has layout_blas_packed layout,
then the layout's Triangle template argument has
the same type as the function's Triangle template argument; and
- [(20.2)](#20.2)
*compatible-static-extents*<InMat2, InMat2>(0, 1) is true[.](#20.sentence-1)
[21](#21)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15430)
*Preconditions*: B.extent(0) == B.extent(1) is true[.](#21.sentence-1)
[22](#22)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15434)
*Effects*: Computes C=E+AB[.](#22.sentence-1)
[23](#23)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15438)
*Remarks*: C may alias E[.](#23.sentence-1)

View File

@@ -0,0 +1,39 @@
[linalg.algs.reqs]
# 29 Numerics library [[numerics]](./#numerics)
## 29.9 Basic linear algebra algorithms [[linalg]](linalg#algs.reqs)
### 29.9.12 Algorithm requirements based on template parameter name [linalg.algs.reqs]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13321)
Throughout[[linalg.algs.blas1]](linalg.algs.blas1 "29.9.13BLAS 1 algorithms"), [[linalg.algs.blas2]](linalg.algs.blas2 "29.9.14BLAS 2 algorithms"), and [[linalg.algs.blas3]](linalg.algs.blas3 "29.9.15BLAS 3 algorithms"),
where the template parameters are not constrained,
the names of template parameters are used to express the following constraints[.](#1.sentence-1)
- [(1.1)](#1.1)
is_execution_policy<ExecutionPolicy>::value is true ([[execpol.type]](execpol.type "26.3.6.2Execution policy type trait"))[.](#1.1.sentence-1)
- [(1.2)](#1.2)
Real is any type such that complex<Real> is
specified ([[complex.numbers.general]](complex.numbers.general "29.4.1General"))[.](#1.2.sentence-1)
- [(1.3)](#1.3)
Triangle is either upper_triangle_t or lower_triangle_t[.](#1.3.sentence-1)
- [(1.4)](#1.4)
DiagonalStorage is
either implicit_unit_diagonal_t or explicit_diagonal_t[.](#1.4.sentence-1)
[*Note [1](#note-1)*:
Function templates that have a template parameter named ExecutionPolicy are parallel algorithms ([[algorithms.parallel.defns]](algorithms.parallel.defns "26.3.1Preamble"))[.](#1.sentence-2)
— *end note*]

161
cppdraft/linalg/conj.md Normal file
View File

@@ -0,0 +1,161 @@
[linalg.conj]
# 29 Numerics library [[numerics]](./#numerics)
## 29.9 Basic linear algebra algorithms [[linalg]](linalg#conj)
### 29.9.9 Conjugated in-place transformation [linalg.conj]
#### [29.9.9.1](#intro) Introduction [[linalg.conj.intro]](linalg.conj.intro)
[1](#intro-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12756)
The conjugated function takes an mdspan x,
and returns a new read-only mdspan y with the same domain as x,
whose elements are the complex conjugates
of the corresponding elements of x[.](#intro-1.sentence-1)
#### [29.9.9.2](#conjugatedaccessor) Class template conjugated_accessor [[linalg.conj.conjugatedaccessor]](linalg.conj.conjugatedaccessor)
[1](#conjugatedaccessor-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12765)
The class template conjugated_accessor is an mdspan accessor policy
which upon access produces conjugate elements[.](#conjugatedaccessor-1.sentence-1)
It is part of the implementation ofconjugated ([[linalg.conj.conjugated]](#conjugated "29.9.9.3Function template conjugated"))[.](#conjugatedaccessor-1.sentence-2)
namespace std::linalg {template<class NestedAccessor>class [conjugated_accessor](#lib:conjugated_accessor "29.9.9.2Class template conjugated_­accessor[linalg.conj.conjugatedaccessor]") {public:using element_type = add_const_t<decltype(*conj-if-needed*(declval<NestedAccessor::element_type>()))>; using reference = remove_const_t<element_type>; using data_handle_type = typename NestedAccessor::data_handle_type; using offset_policy = conjugated_accessor<NestedAccessor::offset_policy>; constexpr conjugated_accessor() = default; 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& nested_accessor() const noexcept { return *nested-accessor_*; }private: NestedAccessor *nested-accessor_*{}; // *exposition only*};}
[2](#conjugatedaccessor-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12801)
*Mandates*:
- [(2.1)](#conjugatedaccessor-2.1)
element_type is valid and denotes a type,
- [(2.2)](#conjugatedaccessor-2.2)
is_copy_constructible_v<reference> is true,
- [(2.3)](#conjugatedaccessor-2.3)
is_reference_v<element_type> is false, and
- [(2.4)](#conjugatedaccessor-2.4)
NestedAccessor meets the accessor policy requirements ([[mdspan.accessor.reqmts]](mdspan.accessor.reqmts "23.7.3.5.2Requirements"))[.](#conjugatedaccessor-2.sentence-1)
[🔗](#lib:conjugated_accessor,constructor)
`constexpr conjugated_accessor(const NestedAccessor& acc);
`
[3](#conjugatedaccessor-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12820)
*Effects*: Direct-non-list-initializes*nested-accessor_* with acc[.](#conjugatedaccessor-3.sentence-1)
[🔗](#lib:conjugated_accessor,constructor_)
`template<class OtherNestedAccessor>
explicit(!is_convertible_v<OtherNestedAccessor, NestedAccessor>>)
constexpr conjugated_accessor(const conjugated_accessor<OtherNestedAccessor>& other);
`
[4](#conjugatedaccessor-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12834)
*Constraints*: is_constructible_v<NestedAccessor, const OtherNestedAccessor&> is true[.](#conjugatedaccessor-4.sentence-1)
[5](#conjugatedaccessor-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12839)
*Effects*: Direct-non-list-initializes *nested-accessor_* with other.nested_accessor()[.](#conjugatedaccessor-5.sentence-1)
[🔗](#lib:conjugated_accessor,access)
`constexpr reference access(data_handle_type p, size_t i) const;
`
[6](#conjugatedaccessor-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12851)
*Returns*: *conj-if-needed*(NestedAccessor::element_type(*nested-accessor_*.access(p, i)))
[🔗](#lib:conjugated_accessor,offset)
`constexpr typename offset_policy::data_handle_type offset(data_handle_type p, size_t i) const;
`
[7](#conjugatedaccessor-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12862)
*Returns*: *nested-accessor_*.offset(p, i)
#### [29.9.9.3](#conjugated) Function template conjugated [[linalg.conj.conjugated]](linalg.conj.conjugated)
[🔗](#conjugated-itemdecl:1)
` template<class ElementType, class Extents, class Layout, class Accessor>
constexpr auto [conjugated](#lib:conjugated "29.9.9.3Function template conjugated[linalg.conj.conjugated]")(mdspan<ElementType, Extents, Layout, Accessor> a);
`
[1](#conjugated-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12875)
Let A be
- [(1.1)](#conjugated-1.1)
remove_cvref_t<decltype(a.accessor().nested_accessor())> if Accessor is a specialization of conjugated_accessor;
- [(1.2)](#conjugated-1.2)
otherwise,Accessor if remove_cvref_t<ElementType> is an arithmetic type;
- [(1.3)](#conjugated-1.3)
otherwise,conjugated_accessor<Accessor> if the expression conj(E) is valid for any subexpression E whose type is remove_cvref_t<ElementType> with overload resolution performed in a context that includes the declarationtemplate<class U> U conj(const U&) = delete;;
- [(1.4)](#conjugated-1.4)
otherwise,Accessor[.](#conjugated-1.sentence-1)
[2](#conjugated-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12896)
*Returns*: Let MD be mdspan<typename A::element_type, Extents, Layout, A>[.](#conjugated-2.sentence-1)
- [(2.1)](#conjugated-2.1)
MD(a.data_handle(), a.mapping(), a.accessor().nested_accessor()) if Accessor is a
specialization of conjugated_accessor;
- [(2.2)](#conjugated-2.2)
otherwise,a, if is_same_v<A, Accessor> is true;
- [(2.3)](#conjugated-2.3)
otherwise,MD(a.data_handle(), a.mapping(), conjugated_accessor(a.accessor())).
[3](#conjugated-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12912)
[*Example [1](#conjugated-example-1)*: 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 example*]

View File

@@ -0,0 +1,62 @@
[linalg.conj.conjugated]
# 29 Numerics library [[numerics]](./#numerics)
## 29.9 Basic linear algebra algorithms [[linalg]](linalg#conj.conjugated)
### 29.9.9 Conjugated in-place transformation [[linalg.conj]](linalg.conj#conjugated)
#### 29.9.9.3 Function template conjugated [linalg.conj.conjugated]
[🔗](#itemdecl:1)
` template<class ElementType, class Extents, class Layout, class Accessor>
constexpr auto [conjugated](#lib:conjugated "29.9.9.3Function template conjugated[linalg.conj.conjugated]")(mdspan<ElementType, Extents, Layout, Accessor> a);
`
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12875)
Let A be
- [(1.1)](#1.1)
remove_cvref_t<decltype(a.accessor().nested_accessor())> if Accessor is a specialization of conjugated_accessor;
- [(1.2)](#1.2)
otherwise,Accessor if remove_cvref_t<ElementType> is an arithmetic type;
- [(1.3)](#1.3)
otherwise,conjugated_accessor<Accessor> if the expression conj(E) is valid for any subexpression E whose type is remove_cvref_t<ElementType> with overload resolution performed in a context that includes the declarationtemplate<class U> U conj(const U&) = delete;;
- [(1.4)](#1.4)
otherwise,Accessor[.](#1.sentence-1)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12896)
*Returns*: Let MD be mdspan<typename A::element_type, Extents, Layout, A>[.](#2.sentence-1)
- [(2.1)](#2.1)
MD(a.data_handle(), a.mapping(), a.accessor().nested_accessor()) if Accessor is a
specialization of conjugated_accessor;
- [(2.2)](#2.2)
otherwise,a, if is_same_v<A, Accessor> is true;
- [(2.3)](#2.3)
otherwise,MD(a.data_handle(), a.mapping(), conjugated_accessor(a.accessor())).
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12912)
[*Example [1](#example-1)*: 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 example*]

View File

@@ -0,0 +1,95 @@
[linalg.conj.conjugatedaccessor]
# 29 Numerics library [[numerics]](./#numerics)
## 29.9 Basic linear algebra algorithms [[linalg]](linalg#conj.conjugatedaccessor)
### 29.9.9 Conjugated in-place transformation [[linalg.conj]](linalg.conj#conjugatedaccessor)
#### 29.9.9.2 Class template conjugated_accessor [linalg.conj.conjugatedaccessor]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12765)
The class template conjugated_accessor is an mdspan accessor policy
which upon access produces conjugate elements[.](#1.sentence-1)
It is part of the implementation ofconjugated ([[linalg.conj.conjugated]](linalg.conj.conjugated "29.9.9.3Function template conjugated"))[.](#1.sentence-2)
namespace std::linalg {template<class NestedAccessor>class [conjugated_accessor](#lib:conjugated_accessor "29.9.9.2Class template conjugated_­accessor[linalg.conj.conjugatedaccessor]") {public:using element_type = add_const_t<decltype(*conj-if-needed*(declval<NestedAccessor::element_type>()))>; using reference = remove_const_t<element_type>; using data_handle_type = typename NestedAccessor::data_handle_type; using offset_policy = conjugated_accessor<NestedAccessor::offset_policy>; constexpr conjugated_accessor() = default; 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& nested_accessor() const noexcept { return *nested-accessor_*; }private: NestedAccessor *nested-accessor_*{}; // *exposition only*};}
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12801)
*Mandates*:
- [(2.1)](#2.1)
element_type is valid and denotes a type,
- [(2.2)](#2.2)
is_copy_constructible_v<reference> is true,
- [(2.3)](#2.3)
is_reference_v<element_type> is false, and
- [(2.4)](#2.4)
NestedAccessor meets the accessor policy requirements ([[mdspan.accessor.reqmts]](mdspan.accessor.reqmts "23.7.3.5.2Requirements"))[.](#2.sentence-1)
[🔗](#lib:conjugated_accessor,constructor)
`constexpr conjugated_accessor(const NestedAccessor& acc);
`
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12820)
*Effects*: Direct-non-list-initializes*nested-accessor_* with acc[.](#3.sentence-1)
[🔗](#lib:conjugated_accessor,constructor_)
`template<class OtherNestedAccessor>
explicit(!is_convertible_v<OtherNestedAccessor, NestedAccessor>>)
constexpr conjugated_accessor(const conjugated_accessor<OtherNestedAccessor>& other);
`
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12834)
*Constraints*: is_constructible_v<NestedAccessor, const OtherNestedAccessor&> is true[.](#4.sentence-1)
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12839)
*Effects*: Direct-non-list-initializes *nested-accessor_* with other.nested_accessor()[.](#5.sentence-1)
[🔗](#lib:conjugated_accessor,access)
`constexpr reference access(data_handle_type p, size_t i) const;
`
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12851)
*Returns*: *conj-if-needed*(NestedAccessor::element_type(*nested-accessor_*.access(p, i)))
[🔗](#lib:conjugated_accessor,offset)
`constexpr typename offset_policy::data_handle_type offset(data_handle_type p, size_t i) const;
`
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12862)
*Returns*: *nested-accessor_*.offset(p, i)

View File

@@ -0,0 +1,18 @@
[linalg.conj.intro]
# 29 Numerics library [[numerics]](./#numerics)
## 29.9 Basic linear algebra algorithms [[linalg]](linalg#conj.intro)
### 29.9.9 Conjugated in-place transformation [[linalg.conj]](linalg.conj#intro)
#### 29.9.9.1 Introduction [linalg.conj.intro]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12756)
The conjugated function takes an mdspan x,
and returns a new read-only mdspan y with the same domain as x,
whose elements are the complex conjugates
of the corresponding elements of x[.](#1.sentence-1)

View File

@@ -0,0 +1,43 @@
[linalg.conjtransposed]
# 29 Numerics library [[numerics]](./#numerics)
## 29.9 Basic linear algebra algorithms [[linalg]](linalg#conjtransposed)
### 29.9.11 Conjugate transpose in-place transform [linalg.conjtransposed]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13268)
The conjugate_transposed function
returns a conjugate transpose view of an object[.](#1.sentence-1)
This combines the effects of transposed and conjugated[.](#1.sentence-2)
[🔗](#lib:conjugate_transposed)
` template<class ElementType, class Extents, class Layout, class Accessor>
constexpr auto conjugate_transposed(mdspan<ElementType, Extents, Layout, Accessor> a);
`
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13279)
*Effects*: Equivalent to: return conjugated(transposed(a));
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13284)
[*Example [1](#example-1)*: 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 example*]

180
cppdraft/linalg/general.md Normal file
View File

@@ -0,0 +1,180 @@
[linalg.general]
# 29 Numerics library [[numerics]](./#numerics)
## 29.9 Basic linear algebra algorithms [[linalg]](linalg#general)
### 29.9.3 General [linalg.general]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L11642)
For the effects of all functions in [[linalg]](linalg "29.9Basic linear algebra algorithms"),
when the effects are described as
“computes R=E” or “compute R=E”
(for some R and mathematical expression E),
the following apply:
- [(1.1)](#1.1)
E has
the conventional mathematical meaning as written[.](#1.1.sentence-1)
- [(1.2)](#1.2)
The pattern xT should be read as
“the transpose of x[.](#1.2.sentence-1)”
- [(1.3)](#1.3)
The pattern xH should be read as
“the conjugate transpose of x[.](#1.3.sentence-1)”
- [(1.4)](#1.4)
When R is the same name as a function parameter
whose type is a template parameter with Out in its name,
the intent is that the result of the computation
is written to the elements of the function parameter R[.](#1.4.sentence-1)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L11665)
Some of the functions and types in [[linalg]](linalg "29.9Basic linear algebra algorithms") distinguish between
the “rows” and the “columns” of a matrix[.](#2.sentence-1)
For a matrix A and a multidimensional index i, j in A.extents(),
- [(2.1)](#2.1)
[*row*](#def:row) i of A is the set of elements A[i, k1] for all k1 such that i, k1 is in A.extents(); and
- [(2.2)](#2.2)
[*column*](#def:column) j of A is the set of elements A[k0, j] for all k0 such that k0, j is in A.extents()[.](#2.sentence-2)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L11678)
Some of the functions in [[linalg]](linalg "29.9Basic linear algebra algorithms") distinguish between
the “upper triangle,” “lower triangle,” and “diagonal” of a matrix[.](#3.sentence-1)
- [(3.1)](#3.1)
The [*diagonal*](#def:diagonal "29.9.3General[linalg.general]") is the set of all elements of A accessed by A[i,i] for 0 ≤ i < min(A.extent(0), A.extent(1))[.](#3.1.sentence-1)
- [(3.2)](#3.2)
The [*upper triangle*](#def:triangle,upper "29.9.3General[linalg.general]") of a matrix A is the set of all elements of A accessed by A[i,j] with i ≤ j[.](#3.2.sentence-1)
It includes the diagonal[.](#3.2.sentence-2)
- [(3.3)](#3.3)
The [*lower triangle*](#def:triangle,lower "29.9.3General[linalg.general]") of A is the set of all elements of A accessed by A[i,j] with i ≥ j[.](#3.3.sentence-1)
It includes the diagonal[.](#3.3.sentence-2)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L11693)
For any function F that takes
a parameter named t,t applies to accesses done through the parameter preceding t in the parameter list of F[.](#4.sentence-1)
Let m be such an access-modified function parameter[.](#4.sentence-2)
F will only access the triangle of m specified by t[.](#4.sentence-3)
For accesses m[i, j] outside the triangle specified by t,F will use the value
- [(4.1)](#4.1)
*conj-if-needed*(m[j, i]) if the name of F starts with hermitian,
- [(4.2)](#4.2)
m[j, i] if the name of F starts with symmetric, or
- [(4.3)](#4.3)
the additive identity if the name of F starts with triangular[.](#4.sentence-4)
[*Example [1](#example-1)*:
Small vector product accessing only specified triangle[.](#4.sentence-5)
It would not be a precondition violation for the non-accessed
matrix element to be non-zero[.](#4.sentence-6)
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]; // + 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 example*]
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L11735)
For any function F that takes a parameter named d,d applies to accesses done through
the previous-of-the-previous parameter of d in the parameter list of F[.](#5.sentence-1)
Let m be such an access-modified function parameter[.](#5.sentence-2)
If d specifies that an implicit unit diagonal is to be assumed, then
- [(5.1)](#5.1)
F will not access the diagonal of m; and
- [(5.2)](#5.2)
the algorithm will interpret 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 m's value type does not have
a two-sided multiplicative identity)[.](#5.sentence-3)
Otherwise,
if d specifies that an explicit diagonal is to be assumed,
then F will access the diagonal of m[.](#5.sentence-4)
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L11755)
Within all the functions in [[linalg]](linalg "29.9Basic linear algebra algorithms"),
any calls to abs, conj, imag, and real are unqualified[.](#6.sentence-1)
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L11760)
Two mdspan objects x and y [*alias*](#def:alias) each other,
if they have the same extents e, and
for every pack of integers i which is a multidimensional index in e,x[i...] and y[i...] refer to the same element[.](#7.sentence-1)
[*Note [1](#note-1)*:
This means thatx and y view the same elements in the same order[.](#7.sentence-2)
— *end note*]
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L11771)
Two mdspan objects x and y [*overlap*](#def:overlap) each other,
if for some pack of integers i that is a multidimensional index in x.extents(),
there exists a pack of integers j that is a multidimensional index in y.extents(),
such that x[i...] and y[j...] refer to the same element[.](#8.sentence-1)
[*Note [2](#note-2)*:
Aliasing is a special case of overlapping[.](#8.sentence-2)
If x and y do not overlap,
then they also do not alias each other[.](#8.sentence-3)
— *end note*]

192
cppdraft/linalg/helpers.md Normal file
View File

@@ -0,0 +1,192 @@
[linalg.helpers]
# 29 Numerics library [[numerics]](./#numerics)
## 29.9 Basic linear algebra algorithms [[linalg]](linalg#helpers)
### 29.9.7 Exposition-only helpers [linalg.helpers]
#### [29.9.7.1](#abs) *abs-if-needed* [[linalg.helpers.abs]](linalg.helpers.abs)
[1](#abs-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12294)
The name *abs-if-needed* denotes an exposition-only function object[.](#abs-1.sentence-1)
The expression *abs-if-needed*(E) for a subexpression E whose type is T is expression-equivalent to:
- [(1.1)](#abs-1.1)
E if T is an unsigned integer;
- [(1.2)](#abs-1.2)
otherwise, std::abs(E) if T is an arithmetic type,
- [(1.3)](#abs-1.3)
otherwise, abs(E),
if that expression is valid,
with overload resolution performed in a context that includes the declarationtemplate<class U> U abs(U) = delete;
If the function selected by overload resolution
does not return the absolute value of its input,
the program is ill-formed, no diagnostic required[.](#abs-1.3.sentence-2)
#### [29.9.7.2](#conj) *conj-if-needed* [[linalg.helpers.conj]](linalg.helpers.conj)
[1](#conj-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12317)
The name *conj-if-needed* denotes an exposition-only function object[.](#conj-1.sentence-1)
The expression *conj-if-needed*(E) for a subexpression E whose type is T is expression-equivalent to:
- [(1.1)](#conj-1.1)
conj(E),
if T is not an arithmetic type and
the expression conj(E) is valid,
with overload resolution performed in a context that includes the declarationtemplate<class U> U conj(const U&) = delete;
If the function selected by overload resolution
does not return the complex conjugate of its input,
the program is ill-formed, no diagnostic required;
- [(1.2)](#conj-1.2)
otherwise, E[.](#conj-1.sentence-2)
#### [29.9.7.3](#real) *real-if-needed* [[linalg.helpers.real]](linalg.helpers.real)
[1](#real-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12339)
The name *real-if-needed* denotes an exposition-only function object[.](#real-1.sentence-1)
The expression *real-if-needed*(E) for a subexpression E whose type is T is expression-equivalent to:
- [(1.1)](#real-1.1)
real(E),
if T is not an arithmetic type and
the expression real(E) is valid,
with overload resolution performed in a context that includes the declarationtemplate<class U> U real(const U&) = delete;
If the function selected by overload resolution
does not return the real part of its input,
the program is ill-formed, no diagnostic required;
- [(1.2)](#real-1.2)
otherwise, E[.](#real-1.sentence-2)
#### [29.9.7.4](#imag) *imag-if-needed* [[linalg.helpers.imag]](linalg.helpers.imag)
[1](#imag-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12361)
The name *imag-if-needed* denotes an exposition-only function object[.](#imag-1.sentence-1)
The expression *imag-if-needed*(E) for a subexpression E whose type is T is expression-equivalent to:
- [(1.1)](#imag-1.1)
imag(E),
if T is not an arithmetic type and the expression imag(E) is valid, with overload resolution performed in a context
that includes the declarationtemplate<class U> U imag(const U&) = delete;
If the function selected by overload resolution
does not return the imaginary part of its input,
the program is ill-formed, no diagnostic required;
- [(1.2)](#imag-1.2)
otherwise, ((void)E, T{})[.](#imag-1.sentence-2)
#### [29.9.7.5](#concepts) Argument concepts [[linalg.helpers.concepts]](linalg.helpers.concepts)
[1](#concepts-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12383)
The exposition-only concepts defined in this section
constrain the algorithms in [[linalg]](linalg "29.9Basic linear algebra algorithms")[.](#concepts-1.sentence-1)
template<class T>constexpr bool *is-mdspan* = false;
template<class ElementType, class Extents, class Layout, class Accessor>constexpr bool *is-mdspan*<mdspan<ElementType, Extents, Layout, Accessor>> = true;
template<class T>concept [*in-vector*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") =*is-mdspan*<T> && T::rank() == 1;
template<class T>concept [*out-vector*](#concept:out-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") =*is-mdspan*<T> && T::rank() == 1 && is_assignable_v<typename T::reference, typename T::element_type> && T::is_always_unique();
template<class T>concept [*inout-vector*](#concept:inout-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") =*is-mdspan*<T> && T::rank() == 1 && is_assignable_v<typename T::reference, typename T::element_type> && T::is_always_unique();
template<class T>concept [*in-matrix*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") =*is-mdspan*<T> && T::rank() == 2;
template<class T>concept [*out-matrix*](#concept:out-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") =*is-mdspan*<T> && T::rank() == 2 && is_assignable_v<typename T::reference, typename T::element_type> && T::is_always_unique();
template<class T>concept [*inout-matrix*](#concept:inout-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") =*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 *is-layout-blas-packed* = false; // *exposition only*template<class Triangle, class StorageOrder>constexpr bool *is-layout-blas-packed*<layout_blas_packed<Triangle, StorageOrder>> = true;
template<class T>concept [*possibly-packed-inout-matrix*](#concept:possibly-packed-inout-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") =*is-mdspan*<T> && T::rank() == 2 && is_assignable_v<typename T::reference, typename T::element_type> &&(T::is_always_unique() || *is-layout-blas-packed*<typename T::layout_type>);
template<class T>concept [*in-object*](#concept:in-object "29.9.7.5Argument concepts[linalg.helpers.concepts]") =*is-mdspan*<T> && (T::rank() == 1 || T::rank() == 2);
template<class T>concept [*out-object*](#concept:out-object "29.9.7.5Argument concepts[linalg.helpers.concepts]") =*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 [*inout-object*](#concept:inout-object "29.9.7.5Argument concepts[linalg.helpers.concepts]") =*is-mdspan*<T> && (T::rank() == 1 || T::rank() == 2) && is_assignable_v<typename T::reference, typename T::element_type> && T::is_always_unique();
[2](#concepts-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12448)
If a function in [[linalg]](linalg "29.9Basic linear algebra algorithms") accesses the elements
of a parameter constrained by[*in-vector*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]"),[*in-matrix*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]"), or[*in-object*](#concept:in-object "29.9.7.5Argument concepts[linalg.helpers.concepts]"),
those accesses will not modify the elements[.](#concepts-2.sentence-1)
[3](#concepts-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12456)
Unless explicitly permitted, any[*inout-vector*](#concept:inout-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]"),[*inout-matrix*](#concept:inout-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]"),[*inout-object*](#concept:inout-object "29.9.7.5Argument concepts[linalg.helpers.concepts]"),[*out-vector*](#concept:out-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]"),[*out-matrix*](#concept:out-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]"),[*out-object*](#concept:out-object "29.9.7.5Argument concepts[linalg.helpers.concepts]"), or[*possibly-packed-inout-matrix*](#concept:possibly-packed-inout-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") parameter of a function in [[linalg]](linalg "29.9Basic linear algebra algorithms") shall not overlap any other mdspan parameter of the function[.](#concepts-3.sentence-1)
#### [29.9.7.6](#mandates) Mandates [[linalg.helpers.mandates]](linalg.helpers.mandates)
[1](#mandates-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12470)
[*Note [1](#mandates-note-1)*:
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[.](#mandates-1.sentence-1)
— *end note*]
template<class MDS1, class MDS2>requires(*is-mdspan*<MDS1> && *is-mdspan*<MDS2>)constexprbool *compatible-static-extents*(size_t r1, size_t r2) { // *exposition only*return MDS1::static_extent(r1) == dynamic_extent || MDS2::static_extent(r2) == dynamic_extent || MDS1::static_extent(r1) == MDS2::static_extent(r2); }template<[*in-vector*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") In1, [*in-vector*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") In2, [*in-vector*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") Out>constexpr bool *possibly-addable*() { // *exposition only*return *compatible-static-extents*<Out, In1>(0, 0) &&*compatible-static-extents*<Out, In2>(0, 0) &&*compatible-static-extents*<In1, In2>(0, 0); }template<[*in-matrix*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") In1, [*in-matrix*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") In2, [*in-matrix*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") Out>constexpr bool *possibly-addable*() { // *exposition only*return *compatible-static-extents*<Out, In1>(0, 0) &&*compatible-static-extents*<Out, In1>(1, 1) &&*compatible-static-extents*<Out, In2>(0, 0) &&*compatible-static-extents*<Out, In2>(1, 1) &&*compatible-static-extents*<In1, In2>(0, 0) &&*compatible-static-extents*<In1, In2>(1, 1); }template<[*in-matrix*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, [*in-vector*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec, [*in-vector*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") OutVec>constexpr bool *possibly-multipliable*() { // *exposition only*return *compatible-static-extents*<OutVec, InMat>(0, 0) &&*compatible-static-extents*<InMat, InVec>(1, 0); }template<[*in-vector*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec, [*in-matrix*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, [*in-vector*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") OutVec>constexpr bool *possibly-multipliable*() { // *exposition only*return *compatible-static-extents*<OutVec, InMat>(0, 1) &&*compatible-static-extents*<InMat, InVec>(0, 0); }template<[*in-matrix*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat1, [*in-matrix*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat2, [*in-matrix*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") OutMat>constexpr bool *possibly-multipliable*() { // *exposition only*return *compatible-static-extents*<OutMat, InMat1>(0, 0) &&*compatible-static-extents*<OutMat, InMat2>(1, 1) &&*compatible-static-extents*<InMat1, InMat2>(1, 0); }
#### [29.9.7.7](#precond) Preconditions [[linalg.helpers.precond]](linalg.helpers.precond)
[1](#precond-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12529)
[*Note [1](#precond-note-1)*:
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[.](#precond-1.sentence-1)
— *end note*]
constexpr bool *addable*( // *exposition only*const [*in-vector*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") auto& in1, const [*in-vector*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") auto& in2, const [*in-vector*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") auto& out) {return out.extent(0) == in1.extent(0) && out.extent(0) == in2.extent(0);}constexpr bool *addable*( // *exposition only*const [*in-matrix*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") auto& in1, const [*in-matrix*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") auto& in2, const [*in-matrix*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") 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 *multipliable*( // *exposition only*const [*in-matrix*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") auto& in_mat, const [*in-vector*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") auto& in_vec, const [*in-vector*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") auto& out_vec) {return out_vec.extent(0) == in_mat.extent(0) && in_mat.extent(1) == in_vec.extent(0);}constexpr bool *multipliable*( // *exposition only*const [*in-vector*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") auto& in_vec, const [*in-matrix*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") auto& in_mat, const [*in-vector*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") auto& out_vec) {return out_vec.extent(0) == in_mat.extent(1) && in_mat.extent(0) == in_vec.extent(0);}constexpr bool *multipliable*( // *exposition only*const [*in-matrix*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") auto& in_mat1, const [*in-matrix*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") auto& in_mat2, const [*in-matrix*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") 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);}

View File

@@ -0,0 +1,34 @@
[linalg.helpers.abs]
# 29 Numerics library [[numerics]](./#numerics)
## 29.9 Basic linear algebra algorithms [[linalg]](linalg#helpers.abs)
### 29.9.7 Exposition-only helpers [[linalg.helpers]](linalg.helpers#abs)
#### 29.9.7.1 *abs-if-needed* [linalg.helpers.abs]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12294)
The name *abs-if-needed* denotes an exposition-only function object[.](#1.sentence-1)
The expression *abs-if-needed*(E) for a subexpression E whose type is T is expression-equivalent to:
- [(1.1)](#1.1)
E if T is an unsigned integer;
- [(1.2)](#1.2)
otherwise, std::abs(E) if T is an arithmetic type,
- [(1.3)](#1.3)
otherwise, abs(E),
if that expression is valid,
with overload resolution performed in a context that includes the declarationtemplate<class U> U abs(U) = delete;
If the function selected by overload resolution
does not return the absolute value of its input,
the program is ill-formed, no diagnostic required[.](#1.3.sentence-2)

View File

@@ -0,0 +1,56 @@
[linalg.helpers.concepts]
# 29 Numerics library [[numerics]](./#numerics)
## 29.9 Basic linear algebra algorithms [[linalg]](linalg#helpers.concepts)
### 29.9.7 Exposition-only helpers [[linalg.helpers]](linalg.helpers#concepts)
#### 29.9.7.5 Argument concepts [linalg.helpers.concepts]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12383)
The exposition-only concepts defined in this section
constrain the algorithms in [[linalg]](linalg "29.9Basic linear algebra algorithms")[.](#1.sentence-1)
template<class T>constexpr bool *is-mdspan* = false;
template<class ElementType, class Extents, class Layout, class Accessor>constexpr bool *is-mdspan*<mdspan<ElementType, Extents, Layout, Accessor>> = true;
template<class T>concept [*in-vector*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") =*is-mdspan*<T> && T::rank() == 1;
template<class T>concept [*out-vector*](#concept:out-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") =*is-mdspan*<T> && T::rank() == 1 && is_assignable_v<typename T::reference, typename T::element_type> && T::is_always_unique();
template<class T>concept [*inout-vector*](#concept:inout-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") =*is-mdspan*<T> && T::rank() == 1 && is_assignable_v<typename T::reference, typename T::element_type> && T::is_always_unique();
template<class T>concept [*in-matrix*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") =*is-mdspan*<T> && T::rank() == 2;
template<class T>concept [*out-matrix*](#concept:out-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") =*is-mdspan*<T> && T::rank() == 2 && is_assignable_v<typename T::reference, typename T::element_type> && T::is_always_unique();
template<class T>concept [*inout-matrix*](#concept:inout-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") =*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 *is-layout-blas-packed* = false; // *exposition only*template<class Triangle, class StorageOrder>constexpr bool *is-layout-blas-packed*<layout_blas_packed<Triangle, StorageOrder>> = true;
template<class T>concept [*possibly-packed-inout-matrix*](#concept:possibly-packed-inout-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") =*is-mdspan*<T> && T::rank() == 2 && is_assignable_v<typename T::reference, typename T::element_type> &&(T::is_always_unique() || *is-layout-blas-packed*<typename T::layout_type>);
template<class T>concept [*in-object*](#concept:in-object "29.9.7.5Argument concepts[linalg.helpers.concepts]") =*is-mdspan*<T> && (T::rank() == 1 || T::rank() == 2);
template<class T>concept [*out-object*](#concept:out-object "29.9.7.5Argument concepts[linalg.helpers.concepts]") =*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 [*inout-object*](#concept:inout-object "29.9.7.5Argument concepts[linalg.helpers.concepts]") =*is-mdspan*<T> && (T::rank() == 1 || T::rank() == 2) && is_assignable_v<typename T::reference, typename T::element_type> && T::is_always_unique();
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12448)
If a function in [[linalg]](linalg "29.9Basic linear algebra algorithms") accesses the elements
of a parameter constrained by[*in-vector*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]"),[*in-matrix*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]"), or[*in-object*](#concept:in-object "29.9.7.5Argument concepts[linalg.helpers.concepts]"),
those accesses will not modify the elements[.](#2.sentence-1)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12456)
Unless explicitly permitted, any[*inout-vector*](#concept:inout-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]"),[*inout-matrix*](#concept:inout-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]"),[*inout-object*](#concept:inout-object "29.9.7.5Argument concepts[linalg.helpers.concepts]"),[*out-vector*](#concept:out-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]"),[*out-matrix*](#concept:out-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]"),[*out-object*](#concept:out-object "29.9.7.5Argument concepts[linalg.helpers.concepts]"), or[*possibly-packed-inout-matrix*](#concept:possibly-packed-inout-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") parameter of a function in [[linalg]](linalg "29.9Basic linear algebra algorithms") shall not overlap any other mdspan parameter of the function[.](#3.sentence-1)

View File

@@ -0,0 +1,31 @@
[linalg.helpers.conj]
# 29 Numerics library [[numerics]](./#numerics)
## 29.9 Basic linear algebra algorithms [[linalg]](linalg#helpers.conj)
### 29.9.7 Exposition-only helpers [[linalg.helpers]](linalg.helpers#conj)
#### 29.9.7.2 *conj-if-needed* [linalg.helpers.conj]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12317)
The name *conj-if-needed* denotes an exposition-only function object[.](#1.sentence-1)
The expression *conj-if-needed*(E) for a subexpression E whose type is T is expression-equivalent to:
- [(1.1)](#1.1)
conj(E),
if T is not an arithmetic type and
the expression conj(E) is valid,
with overload resolution performed in a context that includes the declarationtemplate<class U> U conj(const U&) = delete;
If the function selected by overload resolution
does not return the complex conjugate of its input,
the program is ill-formed, no diagnostic required;
- [(1.2)](#1.2)
otherwise, E[.](#1.sentence-2)

View File

@@ -0,0 +1,30 @@
[linalg.helpers.imag]
# 29 Numerics library [[numerics]](./#numerics)
## 29.9 Basic linear algebra algorithms [[linalg]](linalg#helpers.imag)
### 29.9.7 Exposition-only helpers [[linalg.helpers]](linalg.helpers#imag)
#### 29.9.7.4 *imag-if-needed* [linalg.helpers.imag]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12361)
The name *imag-if-needed* denotes an exposition-only function object[.](#1.sentence-1)
The expression *imag-if-needed*(E) for a subexpression E whose type is T is expression-equivalent to:
- [(1.1)](#1.1)
imag(E),
if T is not an arithmetic type and the expression imag(E) is valid, with overload resolution performed in a context
that includes the declarationtemplate<class U> U imag(const U&) = delete;
If the function selected by overload resolution
does not return the imaginary part of its input,
the program is ill-formed, no diagnostic required;
- [(1.2)](#1.2)
otherwise, ((void)E, T{})[.](#1.sentence-2)

View File

@@ -0,0 +1,26 @@
[linalg.helpers.mandates]
# 29 Numerics library [[numerics]](./#numerics)
## 29.9 Basic linear algebra algorithms [[linalg]](linalg#helpers.mandates)
### 29.9.7 Exposition-only helpers [[linalg.helpers]](linalg.helpers#mandates)
#### 29.9.7.6 Mandates [linalg.helpers.mandates]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12470)
[*Note [1](#note-1)*:
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[.](#1.sentence-1)
— *end note*]
template<class MDS1, class MDS2>requires(*is-mdspan*<MDS1> && *is-mdspan*<MDS2>)constexprbool *compatible-static-extents*(size_t r1, size_t r2) { // *exposition only*return MDS1::static_extent(r1) == dynamic_extent || MDS2::static_extent(r2) == dynamic_extent || MDS1::static_extent(r1) == MDS2::static_extent(r2); }template<[*in-vector*](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") In1, [*in-vector*](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") In2, [*in-vector*](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") Out>constexpr bool *possibly-addable*() { // *exposition only*return *compatible-static-extents*<Out, In1>(0, 0) &&*compatible-static-extents*<Out, In2>(0, 0) &&*compatible-static-extents*<In1, In2>(0, 0); }template<[*in-matrix*](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") In1, [*in-matrix*](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") In2, [*in-matrix*](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") Out>constexpr bool *possibly-addable*() { // *exposition only*return *compatible-static-extents*<Out, In1>(0, 0) &&*compatible-static-extents*<Out, In1>(1, 1) &&*compatible-static-extents*<Out, In2>(0, 0) &&*compatible-static-extents*<Out, In2>(1, 1) &&*compatible-static-extents*<In1, In2>(0, 0) &&*compatible-static-extents*<In1, In2>(1, 1); }template<[*in-matrix*](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, [*in-vector*](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec, [*in-vector*](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") OutVec>constexpr bool *possibly-multipliable*() { // *exposition only*return *compatible-static-extents*<OutVec, InMat>(0, 0) &&*compatible-static-extents*<InMat, InVec>(1, 0); }template<[*in-vector*](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec, [*in-matrix*](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, [*in-vector*](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") OutVec>constexpr bool *possibly-multipliable*() { // *exposition only*return *compatible-static-extents*<OutVec, InMat>(0, 1) &&*compatible-static-extents*<InMat, InVec>(0, 0); }template<[*in-matrix*](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat1, [*in-matrix*](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat2, [*in-matrix*](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") OutMat>constexpr bool *possibly-multipliable*() { // *exposition only*return *compatible-static-extents*<OutMat, InMat1>(0, 0) &&*compatible-static-extents*<OutMat, InMat2>(1, 1) &&*compatible-static-extents*<InMat1, InMat2>(1, 0); }

View File

@@ -0,0 +1,26 @@
[linalg.helpers.precond]
# 29 Numerics library [[numerics]](./#numerics)
## 29.9 Basic linear algebra algorithms [[linalg]](linalg#helpers.precond)
### 29.9.7 Exposition-only helpers [[linalg.helpers]](linalg.helpers#precond)
#### 29.9.7.7 Preconditions [linalg.helpers.precond]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12529)
[*Note [1](#note-1)*:
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[.](#1.sentence-1)
— *end note*]
constexpr bool *addable*( // *exposition only*const [*in-vector*](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") auto& in1, const [*in-vector*](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") auto& in2, const [*in-vector*](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") auto& out) {return out.extent(0) == in1.extent(0) && out.extent(0) == in2.extent(0);}constexpr bool *addable*( // *exposition only*const [*in-matrix*](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") auto& in1, const [*in-matrix*](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") auto& in2, const [*in-matrix*](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") 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 *multipliable*( // *exposition only*const [*in-matrix*](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") auto& in_mat, const [*in-vector*](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") auto& in_vec, const [*in-vector*](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") auto& out_vec) {return out_vec.extent(0) == in_mat.extent(0) && in_mat.extent(1) == in_vec.extent(0);}constexpr bool *multipliable*( // *exposition only*const [*in-vector*](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") auto& in_vec, const [*in-matrix*](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") auto& in_mat, const [*in-vector*](linalg.helpers.concepts#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") auto& out_vec) {return out_vec.extent(0) == in_mat.extent(1) && in_mat.extent(0) == in_vec.extent(0);}constexpr bool *multipliable*( // *exposition only*const [*in-matrix*](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") auto& in_mat1, const [*in-matrix*](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") auto& in_mat2, const [*in-matrix*](linalg.helpers.concepts#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") 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);}

View File

@@ -0,0 +1,31 @@
[linalg.helpers.real]
# 29 Numerics library [[numerics]](./#numerics)
## 29.9 Basic linear algebra algorithms [[linalg]](linalg#helpers.real)
### 29.9.7 Exposition-only helpers [[linalg.helpers]](linalg.helpers#real)
#### 29.9.7.3 *real-if-needed* [linalg.helpers.real]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12339)
The name *real-if-needed* denotes an exposition-only function object[.](#1.sentence-1)
The expression *real-if-needed*(E) for a subexpression E whose type is T is expression-equivalent to:
- [(1.1)](#1.1)
real(E),
if T is not an arithmetic type and
the expression real(E) is valid,
with overload resolution performed in a context that includes the declarationtemplate<class U> U real(const U&) = delete;
If the function selected by overload resolution
does not return the real part of its input,
the program is ill-formed, no diagnostic required;
- [(1.2)](#1.2)
otherwise, E[.](#1.sentence-2)

View File

@@ -0,0 +1,273 @@
[linalg.layout.packed]
# 29 Numerics library [[numerics]](./#numerics)
## 29.9 Basic linear algebra algorithms [[linalg]](linalg#layout.packed)
### 29.9.6 Layouts for packed matrix types [linalg.layout.packed]
#### [29.9.6.1](#overview) Overview [[linalg.layout.packed.overview]](linalg.layout.packed.overview)
[1](#overview-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12015)
layout_blas_packed is an mdspan layout mapping policy
that represents a square matrix that stores only the entries in one
triangle, in a packed contiguous format[.](#overview-1.sentence-1)
Its Triangle template parameter determines
whether an mdspan with this layout
stores the upper or lower triangle of the matrix[.](#overview-1.sentence-2)
Its StorageOrder template parameter determines
whether the layout packs the matrix's elements
in column-major or row-major order[.](#overview-1.sentence-3)
[2](#overview-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12026)
A StorageOrder of column_major_t indicates column-major ordering[.](#overview-2.sentence-1)
This packs matrix elements
starting with the leftmost (least column index) column, and
proceeding column by column, from the top entry (least row index)[.](#overview-2.sentence-2)
[3](#overview-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12033)
A StorageOrder of row_major_t indicates row-major ordering[.](#overview-3.sentence-1)
This packs matrix elements
starting with the topmost (least row index) row, and
proceeding row by row, from the leftmost (least column index) entry[.](#overview-3.sentence-2)
[4](#overview-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12040)
[*Note [1](#overview-note-1)*:
layout_blas_packed describes the data layout used by
the BLAS'
Symmetric Packed (SP), Hermitian Packed (HP), and Triangular Packed (TP)
matrix types[.](#overview-4.sentence-1)
— *end note*]
namespace std::linalg {template<class Triangle, class StorageOrder>class [layout_blas_packed](#lib:layout_blas_packed "29.9.6.1Overview[linalg.layout.packed.overview]") {public:using triangle_type = Triangle; using storage_order_type = StorageOrder; template<class Extents>struct mapping {public:using extents_type = Extents; using index_type = typename extents_type::index_type; using size_type = typename extents_type::size_type; using rank_type = typename extents_type::rank_type; using layout_type = layout_blas_packed; // [[linalg.layout.packed.cons]](#cons "29.9.6.2Constructors"), constructorsconstexpr 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; // [[linalg.layout.packed.obs]](#obs "29.9.6.3Observers"), observersconstexpr const extents_type& extents() const noexcept { return *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 is_always_unique() 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 is_always_exhaustive() noexcept { return true; }static constexpr bool is_always_strided() noexcept{ return is_always_unique(); }constexpr bool is_unique() const noexcept {return *extents_*.extent(0) < 2; }constexpr bool is_exhaustive() const noexcept { return true; }constexpr bool is_strided() const noexcept {return *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 *extents_*{}; // *exposition only*}; };}
[5](#overview-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12113)
*Mandates*:
- [(5.1)](#overview-5.1)
Triangle is either upper_triangle_t or lower_triangle_t,
- [(5.2)](#overview-5.2)
StorageOrder is either column_major_t or row_major_t,
- [(5.3)](#overview-5.3)
Extents is a specialization of std::extents,
- [(5.4)](#overview-5.4)
Extents::rank() equals 2,
- [(5.5)](#overview-5.5)
one ofextents_type::static_extent(0) == dynamic_extent, extents_type::static_extent(1) == dynamic_extent, or extents_type::static_extent(0) == extents_type::static_extent(1) is true, and
- [(5.6)](#overview-5.6)
if Extents::rank_dynamic() == 0 is true,
let Ns be equal to Extents::static_extent(0); then,Ns×(Ns+1) is representable as a value of type index_type[.](#overview-5.sentence-1)
[6](#overview-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12138)
layout_blas_packed<T, SO>::mapping<E> is a trivially copyable type
that models [regular](concepts.object#concept:regular "18.6Object concepts[concepts.object]") for each T, SO, and E[.](#overview-6.sentence-1)
#### [29.9.6.2](#cons) Constructors [[linalg.layout.packed.cons]](linalg.layout.packed.cons)
[🔗](#lib:layout_blas_packed::mapping,constructor)
`constexpr mapping(const extents_type& e) noexcept;
`
[1](#cons-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12151)
*Preconditions*:
- [(1.1)](#cons-1.1)
Let N be equal to e.extent(0)[.](#cons-1.1.sentence-1)
Then, N×(N+1) is representable as
a value of type index_type ([[basic.fundamental]](basic.fundamental "6.9.2Fundamental types"))[.](#cons-1.1.sentence-2)
- [(1.2)](#cons-1.2)
e.extent(0) equals e.extent(1)[.](#cons-1.2.sentence-1)
[2](#cons-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12162)
*Effects*: Direct-non-list-initializes *extents_* with e[.](#cons-2.sentence-1)
[🔗](#lib:layout_blas_packed::mapping,constructor_)
`template<class OtherExtents>
explicit(!is_convertible_v<OtherExtents, extents_type>)
constexpr mapping(const mapping<OtherExtents>& other) noexcept;
`
[3](#cons-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12175)
*Constraints*: is_constructible_v<extents_type, OtherExtents> is true[.](#cons-3.sentence-1)
[4](#cons-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12179)
*Preconditions*: Let N be other.extents().extent(0)[.](#cons-4.sentence-1)
Then, N×(N+1) is representable as
a value of type index_type ([[basic.fundamental]](basic.fundamental "6.9.2Fundamental types"))[.](#cons-4.sentence-2)
[5](#cons-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12185)
*Effects*: Direct-non-list-initializes *extents_* with other.extents()[.](#cons-5.sentence-1)
#### [29.9.6.3](#obs) Observers [[linalg.layout.packed.obs]](linalg.layout.packed.obs)
[🔗](#lib:layout_blas_packed::mapping,required_span_size)
`constexpr index_type required_span_size() const noexcept;
`
[1](#obs-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12198)
*Returns*: *extents_*.extent(0) * (*extents_*.extent(0) + 1)/2[.](#obs-1.sentence-1)
[*Note [1](#obs-note-1)*:
For example, a 5 x 5 packed matrix
only stores 15 matrix elements[.](#obs-1.sentence-2)
— *end note*]
[🔗](#lib:layout_blas_packed::mapping,operator())
`template<class Index0, class Index1>
constexpr index_type operator() (Index0 ind0, Index1 ind1) const noexcept;
`
[2](#obs-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12214)
*Constraints*:
- [(2.1)](#obs-2.1)
is_convertible_v<Index0, index_type> is true,
- [(2.2)](#obs-2.2)
is_convertible_v<Index1, index_type> is true,
- [(2.3)](#obs-2.3)
is_nothrow_constructible_v<index_type, Index0> is true, and
- [(2.4)](#obs-2.4)
is_nothrow_constructible_v<index_type, Index1> is true[.](#obs-2.sentence-1)
[3](#obs-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12227)
Let i be extents_type::*index-cast*(ind0), and
let j be extents_type::*index-cast*(ind1)[.](#obs-3.sentence-1)
[4](#obs-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12231)
*Preconditions*: i, j is a multidimensional index in *extents_* ([[mdspan.overview]](mdspan.overview "23.7.3.1Overview"))[.](#obs-4.sentence-1)
[5](#obs-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12236)
*Returns*: Let N be *extents_*.extent(0)[.](#obs-5.sentence-1)
Then
- [(5.1)](#obs-5.1)
(*this)(j, i) if i > j is true; otherwise
- [(5.2)](#obs-5.2)
i + j * (j + 1)/2 ifis_same_v<StorageOrder, column_major_t> && is_same_v<Triangle, upper_triangle_t> is true oris_same_v<StorageOrder, row_major_t> && is_same_v<Triangle, lower_triangle_t> is true; otherwise
- [(5.3)](#obs-5.3)
j + N * i - i * (i + 1)/2[.](#obs-5.sentence-2)
[🔗](#lib:layout_blas_packed::mapping,stride)
`constexpr index_type stride(rank_type r) const noexcept;
`
[6](#obs-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12264)
*Preconditions*:
- [(6.1)](#obs-6.1)
is_strided() is true, and
- [(6.2)](#obs-6.2)
r < extents_type::rank() is true[.](#obs-6.sentence-1)
[7](#obs-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12273)
*Returns*: 1[.](#obs-7.sentence-1)
[🔗](#lib:layout_blas_packed::mapping,operator==)
`template<class OtherExtents>
friend constexpr bool operator==(const mapping& x, const mapping<OtherExtents>& y) noexcept;
`
[8](#obs-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12285)
*Effects*: Equivalent to: return x.extents() == y.extents();

View File

@@ -0,0 +1,64 @@
[linalg.layout.packed.cons]
# 29 Numerics library [[numerics]](./#numerics)
## 29.9 Basic linear algebra algorithms [[linalg]](linalg#layout.packed.cons)
### 29.9.6 Layouts for packed matrix types [[linalg.layout.packed]](linalg.layout.packed#cons)
#### 29.9.6.2 Constructors [linalg.layout.packed.cons]
[🔗](#lib:layout_blas_packed::mapping,constructor)
`constexpr mapping(const extents_type& e) noexcept;
`
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12151)
*Preconditions*:
- [(1.1)](#1.1)
Let N be equal to e.extent(0)[.](#1.1.sentence-1)
Then, N×(N+1) is representable as
a value of type index_type ([[basic.fundamental]](basic.fundamental "6.9.2Fundamental types"))[.](#1.1.sentence-2)
- [(1.2)](#1.2)
e.extent(0) equals e.extent(1)[.](#1.2.sentence-1)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12162)
*Effects*: Direct-non-list-initializes *extents_* with e[.](#2.sentence-1)
[🔗](#lib:layout_blas_packed::mapping,constructor_)
`template<class OtherExtents>
explicit(!is_convertible_v<OtherExtents, extents_type>)
constexpr mapping(const mapping<OtherExtents>& other) noexcept;
`
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12175)
*Constraints*: is_constructible_v<extents_type, OtherExtents> is true[.](#3.sentence-1)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12179)
*Preconditions*: Let N be other.extents().extent(0)[.](#4.sentence-1)
Then, N×(N+1) is representable as
a value of type index_type ([[basic.fundamental]](basic.fundamental "6.9.2Fundamental types"))[.](#4.sentence-2)
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12185)
*Effects*: Direct-non-list-initializes *extents_* with other.extents()[.](#5.sentence-1)

View File

@@ -0,0 +1,125 @@
[linalg.layout.packed.obs]
# 29 Numerics library [[numerics]](./#numerics)
## 29.9 Basic linear algebra algorithms [[linalg]](linalg#layout.packed.obs)
### 29.9.6 Layouts for packed matrix types [[linalg.layout.packed]](linalg.layout.packed#obs)
#### 29.9.6.3 Observers [linalg.layout.packed.obs]
[🔗](#lib:layout_blas_packed::mapping,required_span_size)
`constexpr index_type required_span_size() const noexcept;
`
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12198)
*Returns*: *extents_*.extent(0) * (*extents_*.extent(0) + 1)/2[.](#1.sentence-1)
[*Note [1](#note-1)*:
For example, a 5 x 5 packed matrix
only stores 15 matrix elements[.](#1.sentence-2)
— *end note*]
[🔗](#lib:layout_blas_packed::mapping,operator())
`template<class Index0, class Index1>
constexpr index_type operator() (Index0 ind0, Index1 ind1) const noexcept;
`
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12214)
*Constraints*:
- [(2.1)](#2.1)
is_convertible_v<Index0, index_type> is true,
- [(2.2)](#2.2)
is_convertible_v<Index1, index_type> is true,
- [(2.3)](#2.3)
is_nothrow_constructible_v<index_type, Index0> is true, and
- [(2.4)](#2.4)
is_nothrow_constructible_v<index_type, Index1> is true[.](#2.sentence-1)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12227)
Let i be extents_type::*index-cast*(ind0), and
let j be extents_type::*index-cast*(ind1)[.](#3.sentence-1)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12231)
*Preconditions*: i, j is a multidimensional index in *extents_* ([[mdspan.overview]](mdspan.overview "23.7.3.1Overview"))[.](#4.sentence-1)
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12236)
*Returns*: Let N be *extents_*.extent(0)[.](#5.sentence-1)
Then
- [(5.1)](#5.1)
(*this)(j, i) if i > j is true; otherwise
- [(5.2)](#5.2)
i + j * (j + 1)/2 ifis_same_v<StorageOrder, column_major_t> && is_same_v<Triangle, upper_triangle_t> is true oris_same_v<StorageOrder, row_major_t> && is_same_v<Triangle, lower_triangle_t> is true; otherwise
- [(5.3)](#5.3)
j + N * i - i * (i + 1)/2[.](#5.sentence-2)
[🔗](#lib:layout_blas_packed::mapping,stride)
`constexpr index_type stride(rank_type r) const noexcept;
`
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12264)
*Preconditions*:
- [(6.1)](#6.1)
is_strided() is true, and
- [(6.2)](#6.2)
r < extents_type::rank() is true[.](#6.sentence-1)
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12273)
*Returns*: 1[.](#7.sentence-1)
[🔗](#lib:layout_blas_packed::mapping,operator==)
`template<class OtherExtents>
friend constexpr bool operator==(const mapping& x, const mapping<OtherExtents>& y) noexcept;
`
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12285)
*Effects*: Equivalent to: return x.extents() == y.extents();

View File

@@ -0,0 +1,98 @@
[linalg.layout.packed.overview]
# 29 Numerics library [[numerics]](./#numerics)
## 29.9 Basic linear algebra algorithms [[linalg]](linalg#layout.packed.overview)
### 29.9.6 Layouts for packed matrix types [[linalg.layout.packed]](linalg.layout.packed#overview)
#### 29.9.6.1 Overview [linalg.layout.packed.overview]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12015)
layout_blas_packed is an mdspan layout mapping policy
that represents a square matrix that stores only the entries in one
triangle, in a packed contiguous format[.](#1.sentence-1)
Its Triangle template parameter determines
whether an mdspan with this layout
stores the upper or lower triangle of the matrix[.](#1.sentence-2)
Its StorageOrder template parameter determines
whether the layout packs the matrix's elements
in column-major or row-major order[.](#1.sentence-3)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12026)
A StorageOrder of column_major_t indicates column-major ordering[.](#2.sentence-1)
This packs matrix elements
starting with the leftmost (least column index) column, and
proceeding column by column, from the top entry (least row index)[.](#2.sentence-2)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12033)
A StorageOrder of row_major_t indicates row-major ordering[.](#3.sentence-1)
This packs matrix elements
starting with the topmost (least row index) row, and
proceeding row by row, from the leftmost (least column index) entry[.](#3.sentence-2)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12040)
[*Note [1](#note-1)*:
layout_blas_packed describes the data layout used by
the BLAS'
Symmetric Packed (SP), Hermitian Packed (HP), and Triangular Packed (TP)
matrix types[.](#4.sentence-1)
— *end note*]
namespace std::linalg {template<class Triangle, class StorageOrder>class [layout_blas_packed](#lib:layout_blas_packed "29.9.6.1Overview[linalg.layout.packed.overview]") {public:using triangle_type = Triangle; using storage_order_type = StorageOrder; template<class Extents>struct mapping {public:using extents_type = Extents; using index_type = typename extents_type::index_type; using size_type = typename extents_type::size_type; using rank_type = typename extents_type::rank_type; using layout_type = layout_blas_packed; // [[linalg.layout.packed.cons]](linalg.layout.packed.cons "29.9.6.2Constructors"), constructorsconstexpr 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; // [[linalg.layout.packed.obs]](linalg.layout.packed.obs "29.9.6.3Observers"), observersconstexpr const extents_type& extents() const noexcept { return *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 is_always_unique() 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 is_always_exhaustive() noexcept { return true; }static constexpr bool is_always_strided() noexcept{ return is_always_unique(); }constexpr bool is_unique() const noexcept {return *extents_*.extent(0) < 2; }constexpr bool is_exhaustive() const noexcept { return true; }constexpr bool is_strided() const noexcept {return *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 *extents_*{}; // *exposition only*}; };}
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12113)
*Mandates*:
- [(5.1)](#5.1)
Triangle is either upper_triangle_t or lower_triangle_t,
- [(5.2)](#5.2)
StorageOrder is either column_major_t or row_major_t,
- [(5.3)](#5.3)
Extents is a specialization of std::extents,
- [(5.4)](#5.4)
Extents::rank() equals 2,
- [(5.5)](#5.5)
one ofextents_type::static_extent(0) == dynamic_extent, extents_type::static_extent(1) == dynamic_extent, or extents_type::static_extent(0) == extents_type::static_extent(1) is true, and
- [(5.6)](#5.6)
if Extents::rank_dynamic() == 0 is true,
let Ns be equal to Extents::static_extent(0); then,Ns×(Ns+1) is representable as a value of type index_type[.](#5.sentence-1)
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12138)
layout_blas_packed<T, SO>::mapping<E> is a trivially copyable type
that models [regular](concepts.object#concept:regular "18.6Object concepts[concepts.object]") for each T, SO, and E[.](#6.sentence-1)

View File

@@ -0,0 +1,16 @@
[linalg.overview]
# 29 Numerics library [[numerics]](./#numerics)
## 29.9 Basic linear algebra algorithms [[linalg]](linalg#overview)
### 29.9.1 Overview [linalg.overview]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L10920)
Subclause [[linalg]](linalg "29.9Basic linear algebra algorithms") defines basic linear algebra algorithms[.](#1.sentence-1)
The algorithms that access the elements of arrays
view those elements through mdspan ([[views.multidim]](views.multidim "23.7.3Multidimensional access"))[.](#1.sentence-2)

178
cppdraft/linalg/reqs.md Normal file
View File

@@ -0,0 +1,178 @@
[linalg.reqs]
# 29 Numerics library [[numerics]](./#numerics)
## 29.9 Basic linear algebra algorithms [[linalg]](linalg#reqs)
### 29.9.4 Requirements [linalg.reqs]
#### [29.9.4.1](#val) Linear algebra value types [[linalg.reqs.val]](linalg.reqs.val)
[1](#val-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L11788)
Throughout [[linalg]](linalg "29.9Basic linear algebra algorithms"),
the following types are[*linear algebra value types*](#def:value_type,linear_algebra "29.9.4.1Linear algebra value types[linalg.reqs.val]"):
- [(1.1)](#val-1.1)
the value_type type alias of
any input or output mdspan parameter(s) of
any function in [[linalg]](linalg "29.9Basic linear algebra algorithms"); and
- [(1.2)](#val-1.2)
the Scalar template parameter (if any) of
any function or class in [[linalg]](linalg "29.9Basic linear algebra algorithms")[.](#val-1.sentence-1)
[2](#val-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L11802)
Linear algebra value types shall model [semiregular](concepts.object#concept:semiregular "18.6Object concepts[concepts.object]")[.](#val-2.sentence-1)
[3](#val-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L11805)
A value-initialized object of linear algebra value type
shall act as the additive identity[.](#val-3.sentence-1)
#### [29.9.4.2](#alg) Algorithm and class requirements [[linalg.reqs.alg]](linalg.reqs.alg)
[1](#alg-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L11811)
[[linalg.reqs.alg]](#alg "29.9.4.2Algorithm and class requirements") lists common requirements for
all algorithms and classes in [[linalg]](linalg "29.9Basic linear algebra algorithms")[.](#alg-1.sentence-1)
[2](#alg-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L11815)
All of the following statements presume
that the algorithm's asymptotic complexity requirements, if any, are satisfied[.](#alg-2.sentence-1)
- [(2.1)](#alg-2.1)
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[.](#alg-2.1.sentence-1)
- [(2.2)](#alg-2.2)
The [*triangular solve algorithms*](#def:triangular_solve_algorithms) in[[linalg.algs.blas2.trsv]](linalg.algs.blas2.trsv "29.9.14.5Solve a triangular linear system"),[[linalg.algs.blas3.trmm]](linalg.algs.blas3.trmm "29.9.15.3In-place triangular matrix-matrix product"),[[linalg.algs.blas3.trsm]](linalg.algs.blas3.trsm "29.9.15.6Solve multiple triangular linear systems"), and[[linalg.algs.blas3.inplacetrsm]](linalg.algs.blas3.inplacetrsm "29.9.15.7Solve multiple triangular linear systems in-place") either have
a BinaryDivideOp template parameter (see [[linalg.algs.reqs]](linalg.algs.reqs "29.9.12Algorithm requirements based on template parameter name")) and
a binary function object parameter divide of that type,
or they have effects equivalent to invoking such an algorithm[.](#alg-2.2.sentence-1)
Triangular solve algorithms interpret divide(a, b) asa times the multiplicative inverse of b[.](#alg-2.2.sentence-2)
Each triangular solve algorithm uses a sequence of evaluations of*, *=, divide,
unary +, binary +, +=,
unary -, binary -, -=,
and = operators
that would produce the result
specified by the algorithm's *Effects* and *Remarks* when operating on elements of a field with noncommutative multiplication[.](#alg-2.2.sentence-3)
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 divide),
any denominator (second argument of divide),
and any assignment
is a well-formed expression[.](#alg-2.2.sentence-4)
- [(2.3)](#alg-2.3)
Each function in[[linalg.algs.blas1]](linalg.algs.blas1 "29.9.13BLAS 1 algorithms"), [[linalg.algs.blas2]](linalg.algs.blas2 "29.9.14BLAS 2 algorithms"), and [[linalg.algs.blas3]](linalg.algs.blas3 "29.9.15BLAS 3 algorithms") that is not a triangular solve algorithm
will use a sequence of evaluations of*, *=, +, +=, and = operators
that would produce the result
specified by the algorithm's *Effects* and *Remarks* when operating on elements of a semiring with noncommutative multiplication[.](#alg-2.3.sentence-1)
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[.](#alg-2.3.sentence-2)
- [(2.4)](#alg-2.4)
If the function has an output mdspan,
then all addends,
subtrahends (for the triangular solve algorithms),
or results of the divide parameter on intermediate terms
(if the function takes a divide parameter)
are assignable and convertible to
the output mdspan's value_type[.](#alg-2.4.sentence-1)
- [(2.5)](#alg-2.5)
The function may reorder addends and partial sums arbitrarily[.](#alg-2.5.sentence-1)
[*Note [1](#alg-note-1)*:
Factors in each product are not reordered;
multiplication is not necessarily commutative[.](#alg-2.5.sentence-2)
— *end note*]
[*Note [2](#alg-note-2)*:
The above requirements do not prohibit
implementation approaches and optimization techniques
which are not user-observable[.](#alg-2.sentence-2)
In particular, if for all input and output arguments
the 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[.](#alg-2.sentence-3)
— *end note*]
[3](#alg-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L11896)
[*Note [3](#alg-note-3)*:
For all functions in [[linalg]](linalg "29.9Basic linear algebra algorithms"),
suppose that all input and output mdspan have as value_type a floating-point type, and
any Scalar template argument has a floating-point type[.](#alg-3.sentence-1)
Then, functions can do all of the following:
- [(3.1)](#alg-3.1)
compute floating-point sums in any way
that improves their accuracy for arbitrary input;
- [(3.2)](#alg-3.2)
perform additional arithmetic operations
(other than those specified by the function's wording and [[linalg.reqs.alg]](#alg "29.9.4.2Algorithm and class requirements"))
in order to improve performance or accuracy; and
- [(3.3)](#alg-3.3)
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;
as long as
- [(3.4)](#alg-3.4)
the function satisfies the complexity requirements; and
- [(3.5)](#alg-3.5)
the function is logarithmically stable,
as defined in Demmel 2007[[bib]](bibliography#bib:linalg-stable "Bibliography")[.](#alg-3.sentence-2)
Strassen's algorithm for matrix-matrix multiply
is an example of a logarithmically stable algorithm[.](#alg-3.5.sentence-2)
— *end note*]

145
cppdraft/linalg/reqs/alg.md Normal file
View File

@@ -0,0 +1,145 @@
[linalg.reqs.alg]
# 29 Numerics library [[numerics]](./#numerics)
## 29.9 Basic linear algebra algorithms [[linalg]](linalg#reqs.alg)
### 29.9.4 Requirements [[linalg.reqs]](linalg.reqs#alg)
#### 29.9.4.2 Algorithm and class requirements [linalg.reqs.alg]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L11811)
[linalg.reqs.alg] lists common requirements for
all algorithms and classes in [[linalg]](linalg "29.9Basic linear algebra algorithms")[.](#1.sentence-1)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L11815)
All of the following statements presume
that the algorithm's asymptotic complexity requirements, if any, are satisfied[.](#2.sentence-1)
- [(2.1)](#2.1)
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[.](#2.1.sentence-1)
- [(2.2)](#2.2)
The [*triangular solve algorithms*](#def:triangular_solve_algorithms) in[[linalg.algs.blas2.trsv]](linalg.algs.blas2.trsv "29.9.14.5Solve a triangular linear system"),[[linalg.algs.blas3.trmm]](linalg.algs.blas3.trmm "29.9.15.3In-place triangular matrix-matrix product"),[[linalg.algs.blas3.trsm]](linalg.algs.blas3.trsm "29.9.15.6Solve multiple triangular linear systems"), and[[linalg.algs.blas3.inplacetrsm]](linalg.algs.blas3.inplacetrsm "29.9.15.7Solve multiple triangular linear systems in-place") either have
a BinaryDivideOp template parameter (see [[linalg.algs.reqs]](linalg.algs.reqs "29.9.12Algorithm requirements based on template parameter name")) and
a binary function object parameter divide of that type,
or they have effects equivalent to invoking such an algorithm[.](#2.2.sentence-1)
Triangular solve algorithms interpret divide(a, b) asa times the multiplicative inverse of b[.](#2.2.sentence-2)
Each triangular solve algorithm uses a sequence of evaluations of*, *=, divide,
unary +, binary +, +=,
unary -, binary -, -=,
and = operators
that would produce the result
specified by the algorithm's *Effects* and *Remarks* when operating on elements of a field with noncommutative multiplication[.](#2.2.sentence-3)
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 divide),
any denominator (second argument of divide),
and any assignment
is a well-formed expression[.](#2.2.sentence-4)
- [(2.3)](#2.3)
Each function in[[linalg.algs.blas1]](linalg.algs.blas1 "29.9.13BLAS 1 algorithms"), [[linalg.algs.blas2]](linalg.algs.blas2 "29.9.14BLAS 2 algorithms"), and [[linalg.algs.blas3]](linalg.algs.blas3 "29.9.15BLAS 3 algorithms") that is not a triangular solve algorithm
will use a sequence of evaluations of*, *=, +, +=, and = operators
that would produce the result
specified by the algorithm's *Effects* and *Remarks* when operating on elements of a semiring with noncommutative multiplication[.](#2.3.sentence-1)
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[.](#2.3.sentence-2)
- [(2.4)](#2.4)
If the function has an output mdspan,
then all addends,
subtrahends (for the triangular solve algorithms),
or results of the divide parameter on intermediate terms
(if the function takes a divide parameter)
are assignable and convertible to
the output mdspan's value_type[.](#2.4.sentence-1)
- [(2.5)](#2.5)
The function may reorder addends and partial sums arbitrarily[.](#2.5.sentence-1)
[*Note [1](#note-1)*:
Factors in each product are not reordered;
multiplication is not necessarily commutative[.](#2.5.sentence-2)
— *end note*]
[*Note [2](#note-2)*:
The above requirements do not prohibit
implementation approaches and optimization techniques
which are not user-observable[.](#2.sentence-2)
In particular, if for all input and output arguments
the 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[.](#2.sentence-3)
— *end note*]
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L11896)
[*Note [3](#note-3)*:
For all functions in [[linalg]](linalg "29.9Basic linear algebra algorithms"),
suppose that all input and output mdspan have as value_type a floating-point type, and
any Scalar template argument has a floating-point type[.](#3.sentence-1)
Then, functions can do all of the following:
- [(3.1)](#3.1)
compute floating-point sums in any way
that improves their accuracy for arbitrary input;
- [(3.2)](#3.2)
perform additional arithmetic operations
(other than those specified by the function's wording and [linalg.reqs.alg])
in order to improve performance or accuracy; and
- [(3.3)](#3.3)
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;
as long as
- [(3.4)](#3.4)
the function satisfies the complexity requirements; and
- [(3.5)](#3.5)
the function is logarithmically stable,
as defined in Demmel 2007[[bib]](bibliography#bib:linalg-stable "Bibliography")[.](#3.sentence-2)
Strassen's algorithm for matrix-matrix multiply
is an example of a logarithmically stable algorithm[.](#3.5.sentence-2)
— *end note*]

View File

@@ -0,0 +1,40 @@
[linalg.reqs.val]
# 29 Numerics library [[numerics]](./#numerics)
## 29.9 Basic linear algebra algorithms [[linalg]](linalg#reqs.val)
### 29.9.4 Requirements [[linalg.reqs]](linalg.reqs#val)
#### 29.9.4.1 Linear algebra value types [linalg.reqs.val]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L11788)
Throughout [[linalg]](linalg "29.9Basic linear algebra algorithms"),
the following types are[*linear algebra value types*](#def:value_type,linear_algebra "29.9.4.1Linear algebra value types[linalg.reqs.val]"):
- [(1.1)](#1.1)
the value_type type alias of
any input or output mdspan parameter(s) of
any function in [[linalg]](linalg "29.9Basic linear algebra algorithms"); and
- [(1.2)](#1.2)
the Scalar template parameter (if any) of
any function or class in [[linalg]](linalg "29.9Basic linear algebra algorithms")[.](#1.sentence-1)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L11802)
Linear algebra value types shall model [semiregular](concepts.object#concept:semiregular "18.6Object concepts[concepts.object]")[.](#2.sentence-1)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L11805)
A value-initialized object of linear algebra value type
shall act as the additive identity[.](#3.sentence-1)

168
cppdraft/linalg/scaled.md Normal file
View File

@@ -0,0 +1,168 @@
[linalg.scaled]
# 29 Numerics library [[numerics]](./#numerics)
## 29.9 Basic linear algebra algorithms [[linalg]](linalg#scaled)
### 29.9.8 Scaled in-place transformation [linalg.scaled]
#### [29.9.8.1](#intro) Introduction [[linalg.scaled.intro]](linalg.scaled.intro)
[1](#intro-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12572)
The scaled function
takes a value alpha and an mdspan x, and
returns a new read-only mdspan that represents
the elementwise product of alpha with each element of x[.](#intro-1.sentence-1)
[*Example [1](#intro-example-1)*: using Vec = mdspan<double, dextents<size_t, 1>>;
// z = alpha * x + yvoid 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 * yvoid 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 example*]
#### [29.9.8.2](#scaledaccessor) Class template scaled_accessor [[linalg.scaled.scaledaccessor]](linalg.scaled.scaledaccessor)
[1](#scaledaccessor-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12596)
The class template scaled_accessor is an mdspan accessor policy
which upon access produces scaled elements[.](#scaledaccessor-1.sentence-1)
It is part of the implementation of scaled ([[linalg.scaled.scaled]](#scaled "29.9.8.3Function template scaled"))[.](#scaledaccessor-1.sentence-2)
namespace std::linalg {template<class ScalingFactor, class NestedAccessor>class [scaled_accessor](#lib:scaled_accessor "29.9.8.2Class template scaled_­accessor[linalg.scaled.scaledaccessor]") {public:using element_type = add_const_t<decltype(declval<ScalingFactor>() * declval<NestedAccessor::element_type>())>; using reference = remove_const_t<element_type>; using data_handle_type = NestedAccessor::data_handle_type; using offset_policy = 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& scaling_factor() const noexcept { return *scaling-factor*; }constexpr const NestedAccessor& nested_accessor() const noexcept { return *nested-accessor*; }private: ScalingFactor *scaling-factor*{}; // *exposition only* NestedAccessor *nested-accessor*{}; // *exposition only*};}
[2](#scaledaccessor-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12631)
*Mandates*:
- [(2.1)](#scaledaccessor-2.1)
element_type is valid and denotes a type,
- [(2.2)](#scaledaccessor-2.2)
is_copy_constructible_v<reference> is true,
- [(2.3)](#scaledaccessor-2.3)
is_reference_v<element_type> is false,
- [(2.4)](#scaledaccessor-2.4)
ScalingFactor models [semiregular](concepts.object#concept:semiregular "18.6Object concepts[concepts.object]"), and
- [(2.5)](#scaledaccessor-2.5)
NestedAccessor meets the accessor policy requirements ([[mdspan.accessor.reqmts]](mdspan.accessor.reqmts "23.7.3.5.2Requirements"))[.](#scaledaccessor-2.sentence-1)
[🔗](#lib:scaled_accessor,constructor)
`template<class OtherNestedAccessor>
explicit(!is_convertible_v<OtherNestedAccessor, NestedAccessor>)
constexpr scaled_accessor(const scaled_accessor<ScalingFactor, OtherNestedAccessor>& other);
`
[3](#scaledaccessor-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12654)
*Constraints*: is_constructible_v<NestedAccessor, const OtherNestedAccessor&> is true[.](#scaledaccessor-3.sentence-1)
[4](#scaledaccessor-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12658)
*Effects*:
- [(4.1)](#scaledaccessor-4.1)
Direct-non-list-initializes *scaling-factor* with other.scaling_factor(), and
- [(4.2)](#scaledaccessor-4.2)
direct-non-list-initializes *nested-accessor* with other.nested_accessor()[.](#scaledaccessor-4.sentence-1)
[🔗](#lib:scaled_accessor,constructor_)
`constexpr scaled_accessor(const ScalingFactor& s, const NestedAccessor& a);
`
[5](#scaledaccessor-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12676)
*Effects*:
- [(5.1)](#scaledaccessor-5.1)
Direct-non-list-initializes *scaling-factor* with s, and
- [(5.2)](#scaledaccessor-5.2)
direct-non-list-initializes *nested-accessor* with a[.](#scaledaccessor-5.sentence-1)
[🔗](#lib:scaled_accessor,access)
`constexpr reference access(data_handle_type p, size_t i) const;
`
[6](#scaledaccessor-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12692)
*Returns*: scaling_factor() * NestedAccessor::element_type(*nested-accessor*.access(p, i))
[🔗](#lib:scaled_accessor,offset)
`constexpr offset_policy::data_handle_type offset(data_handle_type p, size_t i) const;
`
[7](#scaledaccessor-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12705)
*Returns*: *nested-accessor*.offset(p, i)
#### [29.9.8.3](#scaled) Function template scaled [[linalg.scaled.scaled]](linalg.scaled.scaled)
[1](#scaled-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12712)
The scaled function template takes
a scaling factor alpha and
an mdspan x, and
returns a new read-only mdspan with the same domain as x,
that represents the elementwise product of alpha with each element of x[.](#scaled-1.sentence-1)
[🔗](#lib:scaled)
` template<class ScalingFactor,
class ElementType, class Extents, class Layout, class Accessor>
constexpr auto scaled(ScalingFactor alpha, mdspan<ElementType, Extents, Layout, Accessor> x);
`
[2](#scaled-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12728)
Let SA be scaled_accessor<ScalingFactor, Accessor>[.](#scaled-2.sentence-1)
[3](#scaled-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12731)
*Returns*: mdspan<typename SA::element_type, Extents, Layout, SA>(x.data_handle(), x.mapping(),
SA(alpha, x.accessor()))
[4](#scaled-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12739)
[*Example [1](#scaled-example-1)*: 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 example*]

View File

@@ -0,0 +1,22 @@
[linalg.scaled.intro]
# 29 Numerics library [[numerics]](./#numerics)
## 29.9 Basic linear algebra algorithms [[linalg]](linalg#scaled.intro)
### 29.9.8 Scaled in-place transformation [[linalg.scaled]](linalg.scaled#intro)
#### 29.9.8.1 Introduction [linalg.scaled.intro]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12572)
The scaled function
takes a value alpha and an mdspan x, and
returns a new read-only mdspan that represents
the elementwise product of alpha with each element of x[.](#1.sentence-1)
[*Example [1](#example-1)*: using Vec = mdspan<double, dextents<size_t, 1>>;
// z = alpha * x + yvoid 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 * yvoid 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 example*]

View File

@@ -0,0 +1,45 @@
[linalg.scaled.scaled]
# 29 Numerics library [[numerics]](./#numerics)
## 29.9 Basic linear algebra algorithms [[linalg]](linalg#scaled.scaled)
### 29.9.8 Scaled in-place transformation [[linalg.scaled]](linalg.scaled#scaled)
#### 29.9.8.3 Function template scaled [linalg.scaled.scaled]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12712)
The scaled function template takes
a scaling factor alpha and
an mdspan x, and
returns a new read-only mdspan with the same domain as x,
that represents the elementwise product of alpha with each element of x[.](#1.sentence-1)
[🔗](#lib:scaled)
` template<class ScalingFactor,
class ElementType, class Extents, class Layout, class Accessor>
constexpr auto scaled(ScalingFactor alpha, mdspan<ElementType, Extents, Layout, Accessor> x);
`
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12728)
Let SA be scaled_accessor<ScalingFactor, Accessor>[.](#2.sentence-1)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12731)
*Returns*: mdspan<typename SA::element_type, Extents, Layout, SA>(x.data_handle(), x.mapping(),
SA(alpha, x.accessor()))
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12739)
[*Example [1](#example-1)*: 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 example*]

View File

@@ -0,0 +1,115 @@
[linalg.scaled.scaledaccessor]
# 29 Numerics library [[numerics]](./#numerics)
## 29.9 Basic linear algebra algorithms [[linalg]](linalg#scaled.scaledaccessor)
### 29.9.8 Scaled in-place transformation [[linalg.scaled]](linalg.scaled#scaledaccessor)
#### 29.9.8.2 Class template scaled_accessor [linalg.scaled.scaledaccessor]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12596)
The class template scaled_accessor is an mdspan accessor policy
which upon access produces scaled elements[.](#1.sentence-1)
It is part of the implementation of scaled ([[linalg.scaled.scaled]](linalg.scaled.scaled "29.9.8.3Function template scaled"))[.](#1.sentence-2)
namespace std::linalg {template<class ScalingFactor, class NestedAccessor>class [scaled_accessor](#lib:scaled_accessor "29.9.8.2Class template scaled_­accessor[linalg.scaled.scaledaccessor]") {public:using element_type = add_const_t<decltype(declval<ScalingFactor>() * declval<NestedAccessor::element_type>())>; using reference = remove_const_t<element_type>; using data_handle_type = NestedAccessor::data_handle_type; using offset_policy = 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& scaling_factor() const noexcept { return *scaling-factor*; }constexpr const NestedAccessor& nested_accessor() const noexcept { return *nested-accessor*; }private: ScalingFactor *scaling-factor*{}; // *exposition only* NestedAccessor *nested-accessor*{}; // *exposition only*};}
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12631)
*Mandates*:
- [(2.1)](#2.1)
element_type is valid and denotes a type,
- [(2.2)](#2.2)
is_copy_constructible_v<reference> is true,
- [(2.3)](#2.3)
is_reference_v<element_type> is false,
- [(2.4)](#2.4)
ScalingFactor models [semiregular](concepts.object#concept:semiregular "18.6Object concepts[concepts.object]"), and
- [(2.5)](#2.5)
NestedAccessor meets the accessor policy requirements ([[mdspan.accessor.reqmts]](mdspan.accessor.reqmts "23.7.3.5.2Requirements"))[.](#2.sentence-1)
[🔗](#lib:scaled_accessor,constructor)
`template<class OtherNestedAccessor>
explicit(!is_convertible_v<OtherNestedAccessor, NestedAccessor>)
constexpr scaled_accessor(const scaled_accessor<ScalingFactor, OtherNestedAccessor>& other);
`
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12654)
*Constraints*: is_constructible_v<NestedAccessor, const OtherNestedAccessor&> is true[.](#3.sentence-1)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12658)
*Effects*:
- [(4.1)](#4.1)
Direct-non-list-initializes *scaling-factor* with other.scaling_factor(), and
- [(4.2)](#4.2)
direct-non-list-initializes *nested-accessor* with other.nested_accessor()[.](#4.sentence-1)
[🔗](#lib:scaled_accessor,constructor_)
`constexpr scaled_accessor(const ScalingFactor& s, const NestedAccessor& a);
`
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12676)
*Effects*:
- [(5.1)](#5.1)
Direct-non-list-initializes *scaling-factor* with s, and
- [(5.2)](#5.2)
direct-non-list-initializes *nested-accessor* with a[.](#5.sentence-1)
[🔗](#lib:scaled_accessor,access)
`constexpr reference access(data_handle_type p, size_t i) const;
`
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12692)
*Returns*: scaling_factor() * NestedAccessor::element_type(*nested-accessor*.access(p, i))
[🔗](#lib:scaled_accessor,offset)
`constexpr offset_policy::data_handle_type offset(data_handle_type p, size_t i) const;
`
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12705)
*Returns*: *nested-accessor*.offset(p, i)

108
cppdraft/linalg/syn.md Normal file

File diff suppressed because one or more lines are too long

102
cppdraft/linalg/tags.md Normal file
View File

@@ -0,0 +1,102 @@
[linalg.tags]
# 29 Numerics library [[numerics]](./#numerics)
## 29.9 Basic linear algebra algorithms [[linalg]](linalg#tags)
### 29.9.5 Tag classes [linalg.tags]
#### [29.9.5.1](#order) Storage order tags [[linalg.tags.order]](linalg.tags.order)
[1](#order-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L11933)
The storage order tags describe
the order of elements in an mdspan withlayout_blas_packed ([[linalg.layout.packed]](linalg.layout.packed "29.9.6Layouts for packed matrix types")) layout[.](#order-1.sentence-1)
[🔗](#order-itemdecl:1)
`struct [column_major_t](#lib:column_major_t "29.9.5.1Storage order tags[linalg.tags.order]") {
explicit column_major_t() = default;
};
inline constexpr column_major_t [column_major](#lib:column_major "29.9.5.1Storage order tags[linalg.tags.order]"){};
struct [row_major_t](#lib:row_major_t "29.9.5.1Storage order tags[linalg.tags.order]") {
explicit row_major_t() = default;
};
inline constexpr row_major_t [row_major](#lib:row_major "29.9.5.1Storage order tags[linalg.tags.order]"){};
`
[2](#order-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L11950)
column_major_t indicates a column-major order,
and row_major_t indicates a row-major order[.](#order-2.sentence-1)
#### [29.9.5.2](#triangle) Triangle tags [[linalg.tags.triangle]](linalg.tags.triangle)
[🔗](#triangle-itemdecl:1)
`struct [upper_triangle_t](#lib:upper_triangle_t "29.9.5.2Triangle tags[linalg.tags.triangle]") {
explicit upper_triangle_t() = default;
};
inline constexpr upper_triangle_t [upper_triangle](#lib:upper_triangle "29.9.5.2Triangle tags[linalg.tags.triangle]"){};
struct [lower_triangle_t](#lib:lower_triangle_t "29.9.5.2Triangle tags[linalg.tags.triangle]") {
explicit lower_triangle_t() = default;
};
inline constexpr lower_triangle_t [lower_triangle](#lib:lower_triangle "29.9.5.2Triangle tags[linalg.tags.triangle]"){};
`
[1](#triangle-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L11970)
These tag classes specify whether
algorithms and other users of a matrix (represented as an mdspan)
access the
upper triangle (upper_triangle_t) or
lower triangle (lower_triangle_t)
of the matrix (see also [[linalg.general]](linalg.general "29.9.3General"))[.](#triangle-1.sentence-1)
This is also subject to the restrictions of implicit_unit_diagonal_t if that tag is also used as a function argument; see below[.](#triangle-1.sentence-2)
#### [29.9.5.3](#diagonal) Diagonal tags [[linalg.tags.diagonal]](linalg.tags.diagonal)
[🔗](#diagonal-itemdecl:1)
`struct [implicit_unit_diagonal_t](#lib:implicit_unit_diagonal_t "29.9.5.3Diagonal tags[linalg.tags.diagonal]") {
explicit implicit_unit_diagonal_t() = default;
};
inline constexpr implicit_unit_diagonal_t [implicit_unit_diagonal](#lib:implicit_unit_diagonal "29.9.5.3Diagonal tags[linalg.tags.diagonal]"){};
struct [explicit_diagonal_t](#lib:explicit_diagonal_t "29.9.5.3Diagonal tags[linalg.tags.diagonal]") {
explicit explicit_diagonal_t() = default;
};
inline constexpr explicit_diagonal_t [explicit_diagonal](#lib:explicit_diagonal "29.9.5.3Diagonal tags[linalg.tags.diagonal]"){};
`
[1](#diagonal-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L11996)
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[.](#diagonal-1.sentence-1)
[2](#diagonal-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12002)
The implicit_unit_diagonal_t tag indicates that
an implicit unit diagonal is to be assumed ([[linalg.general]](linalg.general "29.9.3General"))[.](#diagonal-2.sentence-1)
[3](#diagonal-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12006)
The explicit_diagonal_t tag indicates that
an explicit diagonal is used ([[linalg.general]](linalg.general "29.9.3General"))[.](#diagonal-3.sentence-1)

View File

@@ -0,0 +1,45 @@
[linalg.tags.diagonal]
# 29 Numerics library [[numerics]](./#numerics)
## 29.9 Basic linear algebra algorithms [[linalg]](linalg#tags.diagonal)
### 29.9.5 Tag classes [[linalg.tags]](linalg.tags#diagonal)
#### 29.9.5.3 Diagonal tags [linalg.tags.diagonal]
[🔗](#itemdecl:1)
`struct [implicit_unit_diagonal_t](#lib:implicit_unit_diagonal_t "29.9.5.3Diagonal tags[linalg.tags.diagonal]") {
explicit implicit_unit_diagonal_t() = default;
};
inline constexpr implicit_unit_diagonal_t [implicit_unit_diagonal](#lib:implicit_unit_diagonal "29.9.5.3Diagonal tags[linalg.tags.diagonal]"){};
struct [explicit_diagonal_t](#lib:explicit_diagonal_t "29.9.5.3Diagonal tags[linalg.tags.diagonal]") {
explicit explicit_diagonal_t() = default;
};
inline constexpr explicit_diagonal_t [explicit_diagonal](#lib:explicit_diagonal "29.9.5.3Diagonal tags[linalg.tags.diagonal]"){};
`
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L11996)
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[.](#1.sentence-1)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12002)
The implicit_unit_diagonal_t tag indicates that
an implicit unit diagonal is to be assumed ([[linalg.general]](linalg.general "29.9.3General"))[.](#2.sentence-1)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12006)
The explicit_diagonal_t tag indicates that
an explicit diagonal is used ([[linalg.general]](linalg.general "29.9.3General"))[.](#3.sentence-1)

View File

@@ -0,0 +1,36 @@
[linalg.tags.order]
# 29 Numerics library [[numerics]](./#numerics)
## 29.9 Basic linear algebra algorithms [[linalg]](linalg#tags.order)
### 29.9.5 Tag classes [[linalg.tags]](linalg.tags#order)
#### 29.9.5.1 Storage order tags [linalg.tags.order]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L11933)
The storage order tags describe
the order of elements in an mdspan withlayout_blas_packed ([[linalg.layout.packed]](linalg.layout.packed "29.9.6Layouts for packed matrix types")) layout[.](#1.sentence-1)
[🔗](#itemdecl:1)
`struct [column_major_t](#lib:column_major_t "29.9.5.1Storage order tags[linalg.tags.order]") {
explicit column_major_t() = default;
};
inline constexpr column_major_t [column_major](#lib:column_major "29.9.5.1Storage order tags[linalg.tags.order]"){};
struct [row_major_t](#lib:row_major_t "29.9.5.1Storage order tags[linalg.tags.order]") {
explicit row_major_t() = default;
};
inline constexpr row_major_t [row_major](#lib:row_major "29.9.5.1Storage order tags[linalg.tags.order]"){};
`
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L11950)
column_major_t indicates a column-major order,
and row_major_t indicates a row-major order[.](#2.sentence-1)

View File

@@ -0,0 +1,35 @@
[linalg.tags.triangle]
# 29 Numerics library [[numerics]](./#numerics)
## 29.9 Basic linear algebra algorithms [[linalg]](linalg#tags.triangle)
### 29.9.5 Tag classes [[linalg.tags]](linalg.tags#triangle)
#### 29.9.5.2 Triangle tags [linalg.tags.triangle]
[🔗](#itemdecl:1)
`struct [upper_triangle_t](#lib:upper_triangle_t "29.9.5.2Triangle tags[linalg.tags.triangle]") {
explicit upper_triangle_t() = default;
};
inline constexpr upper_triangle_t [upper_triangle](#lib:upper_triangle "29.9.5.2Triangle tags[linalg.tags.triangle]"){};
struct [lower_triangle_t](#lib:lower_triangle_t "29.9.5.2Triangle tags[linalg.tags.triangle]") {
explicit lower_triangle_t() = default;
};
inline constexpr lower_triangle_t [lower_triangle](#lib:lower_triangle "29.9.5.2Triangle tags[linalg.tags.triangle]"){};
`
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L11970)
These tag classes specify whether
algorithms and other users of a matrix (represented as an mdspan)
access the
upper triangle (upper_triangle_t) or
lower triangle (lower_triangle_t)
of the matrix (see also [[linalg.general]](linalg.general "29.9.3General"))[.](#1.sentence-1)
This is also subject to the restrictions of implicit_unit_diagonal_t if that tag is also used as a function argument; see below[.](#1.sentence-2)

278
cppdraft/linalg/transp.md Normal file
View File

@@ -0,0 +1,278 @@
[linalg.transp]
# 29 Numerics library [[numerics]](./#numerics)
## 29.9 Basic linear algebra algorithms [[linalg]](linalg#transp)
### 29.9.10 Transpose in-place transformation [linalg.transp]
#### [29.9.10.1](#intro) Introduction [[linalg.transp.intro]](linalg.transp.intro)
[1](#intro-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12943)
layout_transpose is an mdspan layout mapping policy
that swaps the two indices, extents, and strides
of any unique mdspan layout mapping policy[.](#intro-1.sentence-1)
[2](#intro-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12948)
The transposed function takes an mdspan representing a matrix, and returns a new mdspan representing the transpose of the input matrix[.](#intro-2.sentence-1)
#### [29.9.10.2](#helpers) Exposition-only helpers for layout_transpose and transposed [[linalg.transp.helpers]](linalg.transp.helpers)
[1](#helpers-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12955)
The exposition-only *transpose-extents* function
takes an extents object representing the extents of a matrix,
and returns a new extents object
representing the extents of the transpose of the matrix[.](#helpers-1.sentence-1)
[2](#helpers-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12961)
The exposition-only alias template*transpose-extents-t*<InputExtents> gives the type of *transpose-extents*(e) for a given extents object e of type InputExtents[.](#helpers-2.sentence-1)
[🔗](#helpers-itemdecl:1)
`template<class IndexType, size_t InputExtent0, size_t InputExtent1>
constexpr extents<IndexType, InputExtent1, InputExtent0>
transpose-extents(const extents<IndexType, InputExtent0, InputExtent1>& in); // exposition only
`
[3](#helpers-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12973)
*Returns*: extents<IndexType, InputExtent1, InputExtent0>(in.extent(1), in.extent(0))
template<class InputExtents>using *transpose-extents-t* =decltype(*transpose-extents*(declval<InputExtents>())); // *exposition only*
#### [29.9.10.3](#layout.transpose) Class template layout_transpose [[linalg.transp.layout.transpose]](linalg.transp.layout.transpose)
[1](#layout.transpose-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12986)
layout_transpose is an mdspan layout mapping policy
that swaps the two indices, extents, and strides
of any mdspan layout mapping policy[.](#layout.transpose-1.sentence-1)
namespace std::linalg {template<class Layout>class [layout_transpose](#lib:layout_transpose "29.9.10.3Class template layout_­transpose[linalg.transp.layout.transpose]") {public:using nested_layout_type = Layout; template<class Extents>struct mapping {private:using *nested-mapping-type* =typename Layout::template mapping<*transpose-extents-t*<Extents>>; // *exposition only*public:using extents_type = Extents; using index_type = typename extents_type::index_type; using size_type = typename extents_type::size_type; using rank_type = typename extents_type::rank_type; using layout_type = layout_transpose; constexpr explicit mapping(const *nested-mapping-type*&); constexpr const extents_type& extents() const noexcept { return *extents_*; }constexpr index_type required_span_size() const{ return *nested-mapping_*.required_span_size(); template<class Index0, class Index1>constexpr index_type operator()(Index0 ind0, Index1 ind1) const{ return *nested-mapping_*(ind1, ind0); }constexpr const *nested-mapping-type*& nested_mapping() const noexcept{ return *nested-mapping_*; }static constexpr bool is_always_unique() noexcept{ return *nested-mapping-type*::is_always_unique(); }static constexpr bool is_always_exhaustive() noexcept{ return *nested-mapping-type*::is_always_exhaustive(); }static constexpr bool is_always_strided() noexcept{ return *nested-mapping-type*::is_always_strided(); }constexpr bool is_unique() const { return *nested-mapping_*.is_unique(); }constexpr bool is_exhaustive() const { return *nested-mapping_*.is_exhaustive(); }constexpr bool is_strided() const { return *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:*nested-mapping-type* *nested-mapping_*; // *exposition only* extents_type *extents_*; // *exposition only*};}
[2](#layout.transpose-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13049)
Layout shall meet
the layout mapping policy requirements ([[mdspan.layout.policy.reqmts]](mdspan.layout.policy.reqmts "23.7.3.4.3Layout mapping policy requirements"))[.](#layout.transpose-2.sentence-1)
[3](#layout.transpose-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13053)
*Mandates*:
- [(3.1)](#layout.transpose-3.1)
Extents is a specialization of std::extents, and
- [(3.2)](#layout.transpose-3.2)
Extents::rank() equals 2[.](#layout.transpose-3.sentence-1)
[🔗](#lib:layout_transpose::mapping,constructor)
`constexpr explicit mapping(const nested-mapping-type& map);
`
[4](#layout.transpose-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13068)
*Effects*:
- [(4.1)](#layout.transpose-4.1)
Initializes *nested-mapping_* with map, and
- [(4.2)](#layout.transpose-4.2)
initializes *extents_* with *transpose-extents*(map.extents())[.](#layout.transpose-4.sentence-1)
[🔗](#lib:layout_transpose::mapping,stride)
`constexpr index_type stride(size_t r) const;
`
[5](#layout.transpose-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13085)
*Preconditions*:
- [(5.1)](#layout.transpose-5.1)
is_strided() is true, and
- [(5.2)](#layout.transpose-5.2)
r < 2 is true[.](#layout.transpose-5.sentence-1)
[6](#layout.transpose-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13094)
*Returns*: *nested-mapping_*.stride(r == 0 ? 1 : 0)
[🔗](#lib:layout_transpose::mapping,operator==)
`template<class OtherExtents>
friend constexpr bool operator==(const mapping& x, const mapping<OtherExtents>& y);
`
[7](#layout.transpose-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13106)
*Constraints*: The expressionx.*nested-mapping_* == y.*nested-mapping_* is well-formed and its result is convertible to bool[.](#layout.transpose-7.sentence-1)
[8](#layout.transpose-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13112)
*Returns*: x.*nested-mapping_* == y.*nested-mapping_*[.](#layout.transpose-8.sentence-1)
#### [29.9.10.4](#transposed) Function template transposed [[linalg.transp.transposed]](linalg.transp.transposed)
[1](#transposed-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13119)
The transposed function
takes a rank-2 mdspan representing a matrix, and
returns a new mdspan representing the input matrix's transpose[.](#transposed-1.sentence-1)
The input matrix's data are not modified, and
the returned mdspan accesses the input matrix's data in place[.](#transposed-1.sentence-2)
[🔗](#lib:transposed)
` template<class ElementType, class Extents, class Layout, class Accessor>
constexpr auto transposed(mdspan<ElementType, Extents, Layout, Accessor> a);
`
[2](#transposed-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13132)
*Mandates*: Extents::rank() == 2 is true[.](#transposed-2.sentence-1)
[3](#transposed-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13136)
Let ReturnExtents be*transpose-extents-t*<Extents>[.](#transposed-3.sentence-1)
Let R bemdspan<ElementType, ReturnExtents, ReturnLayout, Accessor>,
where ReturnLayout is:
- [(3.1)](#transposed-3.1)
layout_right if Layout is layout_left;
- [(3.2)](#transposed-3.2)
otherwise, layout_left if Layout is layout_right;
- [(3.3)](#transposed-3.3)
otherwise, layout_right_padded<PaddingValue> if Layout is
layout_left_padded<PaddingValue> for some size_t value PaddingValue;
- [(3.4)](#transposed-3.4)
otherwise, layout_left_padded<PaddingValue> if Layout is
layout_right_padded<PaddingValue> for some size_t value PaddingValue;
- [(3.5)](#transposed-3.5)
otherwise, layout_stride if Layout is layout_stride;
- [(3.6)](#transposed-3.6)
otherwise,layout_blas_packed<OppositeTriangle, OppositeStorageOrder>,
if Layout is
layout_blas_packed<Triangle, StorageOrder> for some Triangle and StorageOrder, where
* [(3.6.1)](#transposed-3.6.1)
OppositeTriangle isconditional_t<is_same_v<Triangle, upper_triangle_t>,
lower_triangle_t, upper_triangle_t> and
* [(3.6.2)](#transposed-3.6.2)
OppositeStorageOrder isconditional_t<is_same_v<StorageOrder, column_major_t>, row_major_t, column_major_t>
- [(3.7)](#transposed-3.7)
otherwise, NestedLayout if Layout is layout_transpose<NestedLayout> for some NestedLayout;
- [(3.8)](#transposed-3.8)
otherwise, layout_transpose<Layout>[.](#transposed-3.sentence-2)
[4](#transposed-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13185)
*Returns*: With ReturnMapping being
the type typename ReturnLayout::template mapping<ReturnExtents>:
- [(4.1)](#transposed-4.1)
if Layout is layout_left, layout_right, or
a specialization of layout_blas_packed,R(a.data_handle(), ReturnMapping(*transpose-extents*(a.mapping().extents())),
a.accessor())
- [(4.2)](#transposed-4.2)
otherwise,R(a.data_handle(), ReturnMapping(*transpose-extents*(a.mapping().extents()),
a.mapping().stride(1)), a.accessor()) if Layout is layout_left_padded<PaddingValue> for some size_t value PaddingValue;
- [(4.3)](#transposed-4.3)
otherwise,R(a.data_handle(), ReturnMapping(*transpose-extents*(a.mapping().extents()),
a.mapping().stride(0)), a.accessor()) if Layout is layout_right_padded<PaddingValue> for some size_t value PaddingValue;
- [(4.4)](#transposed-4.4)
otherwise, if Layout is layout_stride,R(a.data_handle(), ReturnMapping(*transpose-extents*(a.mapping().extents()),
array{a.mapping().stride(1), a.mapping().stride(0)}), a.accessor())
- [(4.5)](#transposed-4.5)
otherwise, if Layout is a specialization of layout_transpose,R(a.data_handle(), a.mapping().nested_mapping(), a.accessor())
- [(4.6)](#transposed-4.6)
otherwise,R(a.data_handle(), ReturnMapping(a.mapping()), a.accessor())
[5](#transposed-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13232)
[*Example [1](#transposed-example-1)*: 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 example*]

View File

@@ -0,0 +1,39 @@
[linalg.transp.helpers]
# 29 Numerics library [[numerics]](./#numerics)
## 29.9 Basic linear algebra algorithms [[linalg]](linalg#transp.helpers)
### 29.9.10 Transpose in-place transformation [[linalg.transp]](linalg.transp#helpers)
#### 29.9.10.2 Exposition-only helpers for layout_transpose and transposed [linalg.transp.helpers]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12955)
The exposition-only *transpose-extents* function
takes an extents object representing the extents of a matrix,
and returns a new extents object
representing the extents of the transpose of the matrix[.](#1.sentence-1)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12961)
The exposition-only alias template*transpose-extents-t*<InputExtents> gives the type of *transpose-extents*(e) for a given extents object e of type InputExtents[.](#2.sentence-1)
[🔗](#itemdecl:1)
`template<class IndexType, size_t InputExtent0, size_t InputExtent1>
constexpr extents<IndexType, InputExtent1, InputExtent0>
transpose-extents(const extents<IndexType, InputExtent0, InputExtent1>& in); // exposition only
`
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12973)
*Returns*: extents<IndexType, InputExtent1, InputExtent0>(in.extent(1), in.extent(0))
template<class InputExtents>using *transpose-extents-t* =decltype(*transpose-extents*(declval<InputExtents>())); // *exposition only*

View File

@@ -0,0 +1,23 @@
[linalg.transp.intro]
# 29 Numerics library [[numerics]](./#numerics)
## 29.9 Basic linear algebra algorithms [[linalg]](linalg#transp.intro)
### 29.9.10 Transpose in-place transformation [[linalg.transp]](linalg.transp#intro)
#### 29.9.10.1 Introduction [linalg.transp.intro]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12943)
layout_transpose is an mdspan layout mapping policy
that swaps the two indices, extents, and strides
of any unique mdspan layout mapping policy[.](#1.sentence-1)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12948)
The transposed function takes an mdspan representing a matrix, and returns a new mdspan representing the transpose of the input matrix[.](#2.sentence-1)

View File

@@ -0,0 +1,102 @@
[linalg.transp.layout.transpose]
# 29 Numerics library [[numerics]](./#numerics)
## 29.9 Basic linear algebra algorithms [[linalg]](linalg#transp.layout.transpose)
### 29.9.10 Transpose in-place transformation [[linalg.transp]](linalg.transp#layout.transpose)
#### 29.9.10.3 Class template layout_transpose [linalg.transp.layout.transpose]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12986)
layout_transpose is an mdspan layout mapping policy
that swaps the two indices, extents, and strides
of any mdspan layout mapping policy[.](#1.sentence-1)
namespace std::linalg {template<class Layout>class [layout_transpose](#lib:layout_transpose "29.9.10.3Class template layout_­transpose[linalg.transp.layout.transpose]") {public:using nested_layout_type = Layout; template<class Extents>struct mapping {private:using *nested-mapping-type* =typename Layout::template mapping<*transpose-extents-t*<Extents>>; // *exposition only*public:using extents_type = Extents; using index_type = typename extents_type::index_type; using size_type = typename extents_type::size_type; using rank_type = typename extents_type::rank_type; using layout_type = layout_transpose; constexpr explicit mapping(const *nested-mapping-type*&); constexpr const extents_type& extents() const noexcept { return *extents_*; }constexpr index_type required_span_size() const{ return *nested-mapping_*.required_span_size(); template<class Index0, class Index1>constexpr index_type operator()(Index0 ind0, Index1 ind1) const{ return *nested-mapping_*(ind1, ind0); }constexpr const *nested-mapping-type*& nested_mapping() const noexcept{ return *nested-mapping_*; }static constexpr bool is_always_unique() noexcept{ return *nested-mapping-type*::is_always_unique(); }static constexpr bool is_always_exhaustive() noexcept{ return *nested-mapping-type*::is_always_exhaustive(); }static constexpr bool is_always_strided() noexcept{ return *nested-mapping-type*::is_always_strided(); }constexpr bool is_unique() const { return *nested-mapping_*.is_unique(); }constexpr bool is_exhaustive() const { return *nested-mapping_*.is_exhaustive(); }constexpr bool is_strided() const { return *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:*nested-mapping-type* *nested-mapping_*; // *exposition only* extents_type *extents_*; // *exposition only*};}
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13049)
Layout shall meet
the layout mapping policy requirements ([[mdspan.layout.policy.reqmts]](mdspan.layout.policy.reqmts "23.7.3.4.3Layout mapping policy requirements"))[.](#2.sentence-1)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13053)
*Mandates*:
- [(3.1)](#3.1)
Extents is a specialization of std::extents, and
- [(3.2)](#3.2)
Extents::rank() equals 2[.](#3.sentence-1)
[🔗](#lib:layout_transpose::mapping,constructor)
`constexpr explicit mapping(const nested-mapping-type& map);
`
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13068)
*Effects*:
- [(4.1)](#4.1)
Initializes *nested-mapping_* with map, and
- [(4.2)](#4.2)
initializes *extents_* with *transpose-extents*(map.extents())[.](#4.sentence-1)
[🔗](#lib:layout_transpose::mapping,stride)
`constexpr index_type stride(size_t r) const;
`
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13085)
*Preconditions*:
- [(5.1)](#5.1)
is_strided() is true, and
- [(5.2)](#5.2)
r < 2 is true[.](#5.sentence-1)
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13094)
*Returns*: *nested-mapping_*.stride(r == 0 ? 1 : 0)
[🔗](#lib:layout_transpose::mapping,operator==)
`template<class OtherExtents>
friend constexpr bool operator==(const mapping& x, const mapping<OtherExtents>& y);
`
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13106)
*Constraints*: The expressionx.*nested-mapping_* == y.*nested-mapping_* is well-formed and its result is convertible to bool[.](#7.sentence-1)
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13112)
*Returns*: x.*nested-mapping_* == y.*nested-mapping_*[.](#8.sentence-1)

View File

@@ -0,0 +1,135 @@
[linalg.transp.transposed]
# 29 Numerics library [[numerics]](./#numerics)
## 29.9 Basic linear algebra algorithms [[linalg]](linalg#transp.transposed)
### 29.9.10 Transpose in-place transformation [[linalg.transp]](linalg.transp#transposed)
#### 29.9.10.4 Function template transposed [linalg.transp.transposed]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13119)
The transposed function
takes a rank-2 mdspan representing a matrix, and
returns a new mdspan representing the input matrix's transpose[.](#1.sentence-1)
The input matrix's data are not modified, and
the returned mdspan accesses the input matrix's data in place[.](#1.sentence-2)
[🔗](#lib:transposed)
` template<class ElementType, class Extents, class Layout, class Accessor>
constexpr auto transposed(mdspan<ElementType, Extents, Layout, Accessor> a);
`
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13132)
*Mandates*: Extents::rank() == 2 is true[.](#2.sentence-1)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13136)
Let ReturnExtents be*transpose-extents-t*<Extents>[.](#3.sentence-1)
Let R bemdspan<ElementType, ReturnExtents, ReturnLayout, Accessor>,
where ReturnLayout is:
- [(3.1)](#3.1)
layout_right if Layout is layout_left;
- [(3.2)](#3.2)
otherwise, layout_left if Layout is layout_right;
- [(3.3)](#3.3)
otherwise, layout_right_padded<PaddingValue> if Layout is
layout_left_padded<PaddingValue> for some size_t value PaddingValue;
- [(3.4)](#3.4)
otherwise, layout_left_padded<PaddingValue> if Layout is
layout_right_padded<PaddingValue> for some size_t value PaddingValue;
- [(3.5)](#3.5)
otherwise, layout_stride if Layout is layout_stride;
- [(3.6)](#3.6)
otherwise,layout_blas_packed<OppositeTriangle, OppositeStorageOrder>,
if Layout is
layout_blas_packed<Triangle, StorageOrder> for some Triangle and StorageOrder, where
* [(3.6.1)](#3.6.1)
OppositeTriangle isconditional_t<is_same_v<Triangle, upper_triangle_t>,
lower_triangle_t, upper_triangle_t> and
* [(3.6.2)](#3.6.2)
OppositeStorageOrder isconditional_t<is_same_v<StorageOrder, column_major_t>, row_major_t, column_major_t>
- [(3.7)](#3.7)
otherwise, NestedLayout if Layout is layout_transpose<NestedLayout> for some NestedLayout;
- [(3.8)](#3.8)
otherwise, layout_transpose<Layout>[.](#3.sentence-2)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13185)
*Returns*: With ReturnMapping being
the type typename ReturnLayout::template mapping<ReturnExtents>:
- [(4.1)](#4.1)
if Layout is layout_left, layout_right, or
a specialization of layout_blas_packed,R(a.data_handle(), ReturnMapping(*transpose-extents*(a.mapping().extents())),
a.accessor())
- [(4.2)](#4.2)
otherwise,R(a.data_handle(), ReturnMapping(*transpose-extents*(a.mapping().extents()),
a.mapping().stride(1)), a.accessor()) if Layout is layout_left_padded<PaddingValue> for some size_t value PaddingValue;
- [(4.3)](#4.3)
otherwise,R(a.data_handle(), ReturnMapping(*transpose-extents*(a.mapping().extents()),
a.mapping().stride(0)), a.accessor()) if Layout is layout_right_padded<PaddingValue> for some size_t value PaddingValue;
- [(4.4)](#4.4)
otherwise, if Layout is layout_stride,R(a.data_handle(), ReturnMapping(*transpose-extents*(a.mapping().extents()),
array{a.mapping().stride(1), a.mapping().stride(0)}), a.accessor())
- [(4.5)](#4.5)
otherwise, if Layout is a specialization of layout_transpose,R(a.data_handle(), a.mapping().nested_mapping(), a.accessor())
- [(4.6)](#4.6)
otherwise,R(a.data_handle(), ReturnMapping(a.mapping()), a.accessor())
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13232)
[*Example [1](#example-1)*: 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 example*]