Files
2025-10-25 03:02:53 +03:00

4961 lines
291 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

[linalg]
# 29 Numerics library [[numerics]](./#numerics)
## 29.9 Basic linear algebra algorithms [linalg]
### [29.9.1](#overview) Overview [[linalg.overview]](linalg.overview)
[1](#overview-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L10920)
Subclause [linalg] defines basic linear algebra algorithms[.](#overview-1.sentence-1)
The algorithms that access the elements of arrays
view those elements through mdspan ([[views.multidim]](views.multidim "23.7.3Multidimensional access"))[.](#overview-1.sentence-2)
### [29.9.2](#syn) Header <linalg> synopsis [[linalg.syn]](linalg.syn)
[🔗](#header:%3clinalg%3e)
namespace std::linalg {// [[linalg.tags.order]](#tags.order "29.9.5.1Storage order tags"), storage order tagsstruct column_major_t; inline constexpr column_major_t column_major; struct row_major_t; inline constexpr row_major_t row_major; // [[linalg.tags.triangle]](#tags.triangle "29.9.5.2Triangle tags"), triangle tagsstruct upper_triangle_t; inline constexpr upper_triangle_t upper_triangle; struct lower_triangle_t; inline constexpr lower_triangle_t lower_triangle; // [[linalg.tags.diagonal]](#tags.diagonal "29.9.5.3Diagonal tags"), diagonal tagsstruct implicit_unit_diagonal_t; inline constexpr implicit_unit_diagonal_t implicit_unit_diagonal; struct explicit_diagonal_t; inline constexpr explicit_diagonal_t explicit_diagonal; // [[linalg.layout.packed]](#layout.packed "29.9.6Layouts for packed matrix types"), class template layout_blas_packedtemplate<class Triangle, class StorageOrder>class layout_blas_packed; // [[linalg.helpers]](#helpers "29.9.7Exposition-only helpers"), exposition-only helpers// [[linalg.helpers.concepts]](#helpers.concepts "29.9.7.5Argument concepts"), linear algebra argument conceptstemplate<class T>constexpr bool *is-mdspan* = *see below*; // *exposition only*template<class T>concept [*in-vector*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") = *see below*; // *exposition only*template<class T>concept [*out-vector*](#concept:out-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") = *see below*; // *exposition only*template<class T>concept [*inout-vector*](#concept:inout-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") = *see below*; // *exposition only*template<class T>concept [*in-matrix*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") = *see below*; // *exposition only*template<class T>concept [*out-matrix*](#concept:out-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") = *see below*; // *exposition only*template<class T>concept [*inout-matrix*](#concept:inout-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") = *see below*; // *exposition only*template<class T>concept [*possibly-packed-inout-matrix*](#concept:possibly-packed-inout-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") = *see below*; // *exposition only*template<class T>concept [*in-object*](#concept:in-object "29.9.7.5Argument concepts[linalg.helpers.concepts]") = *see below*; // *exposition only*template<class T>concept [*out-object*](#concept:out-object "29.9.7.5Argument concepts[linalg.helpers.concepts]") = *see below*; // *exposition only*template<class T>concept [*inout-object*](#concept:inout-object "29.9.7.5Argument concepts[linalg.helpers.concepts]") = *see below*; // *exposition only*// [[linalg.scaled]](#scaled "29.9.8Scaled in-place transformation"), scaled in-place transformation// [[linalg.scaled.scaledaccessor]](#scaled.scaledaccessor "29.9.8.2Class template scaled_­accessor"), class template scaled_accessortemplate<class ScalingFactor, class NestedAccessor>class scaled_accessor; // [[linalg.scaled.scaled]](#scaled.scaled "29.9.8.3Function template scaled"), function template scaledtemplate<class ScalingFactor, class ElementType, class Extents, class Layout, class Accessor>constexpr auto scaled(ScalingFactor alpha, mdspan<ElementType, Extents, Layout, Accessor> x); // [[linalg.conj]](#conj "29.9.9Conjugated in-place transformation"), conjugated in-place transformation// [[linalg.conj.conjugatedaccessor]](#conj.conjugatedaccessor "29.9.9.2Class template conjugated_­accessor"), class template conjugated_accessortemplate<class NestedAccessor>class conjugated_accessor; // [[linalg.conj.conjugated]](#conj.conjugated "29.9.9.3Function template conjugated"), function template conjugatedtemplate<class ElementType, class Extents, class Layout, class Accessor>constexpr auto conjugated(mdspan<ElementType, Extents, Layout, Accessor> a); // [[linalg.transp]](#transp "29.9.10Transpose in-place transformation"), transpose in-place transformation// [[linalg.transp.layout.transpose]](#transp.layout.transpose "29.9.10.3Class template layout_­transpose"), class template layout_transposetemplate<class Layout>class layout_transpose; // [[linalg.transp.transposed]](#transp.transposed "29.9.10.4Function template transposed"), function template transposedtemplate<class ElementType, class Extents, class Layout, class Accessor>constexpr auto transposed(mdspan<ElementType, Extents, Layout, Accessor> a); // [[linalg.conjtransposed]](#conjtransposed "29.9.11Conjugate transpose in-place transform"), conjugated transpose in-place transformationtemplate<class ElementType, class Extents, class Layout, class Accessor>constexpr auto conjugate_transposed(mdspan<ElementType, Extents, Layout, Accessor> a); // [[linalg.algs.blas1]](#algs.blas1 "29.9.13BLAS 1 algorithms"), BLAS 1 algorithms// [[linalg.algs.blas1.givens]](#algs.blas1.givens "29.9.13.2Givens rotations"), Givens rotations// [[linalg.algs.blas1.givens.lartg]](#algs.blas1.givens.lartg "29.9.13.2.1Compute Givens rotation"), compute Givens rotationtemplate<class Real>struct setup_givens_rotation_result { Real c;
Real s;
Real r; }; template<class Real>struct setup_givens_rotation_result<complex<Real>> { Real c;
complex<Real> s;
complex<Real> r; }; template<class Real> setup_givens_rotation_result<Real> setup_givens_rotation(Real a, Real b) noexcept; template<class Real> setup_givens_rotation_result<complex<Real>> setup_givens_rotation(complex<Real> a, complex<Real> b) noexcept; // [[linalg.algs.blas1.givens.rot]](#algs.blas1.givens.rot "29.9.13.2.2Apply a computed Givens rotation to vectors"), apply computed Givens rotationtemplate<[*inout-vector*](#concept:inout-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutVec1, [*inout-vector*](#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*](#concept:inout-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutVec1, [*inout-vector*](#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*](#concept:inout-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutVec1, [*inout-vector*](#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*](#concept:inout-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutVec1, [*inout-vector*](#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); // [[linalg.algs.blas1.swap]](#algs.blas1.swap "29.9.13.3Swap matrix or vector elements"), swap elementstemplate<[*inout-object*](#concept:inout-object "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutObj1, [*inout-object*](#concept:inout-object "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutObj2>void swap_elements(InOutObj1 x, InOutObj2 y); template<class ExecutionPolicy, [*inout-object*](#concept:inout-object "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutObj1, [*inout-object*](#concept:inout-object "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutObj2>void swap_elements(ExecutionPolicy&& exec,
InOutObj1 x, InOutObj2 y); // [[linalg.algs.blas1.scal]](#algs.blas1.scal "29.9.13.4Multiply the elements of an object in place by a scalar"), multiply elements by scalartemplate<class Scalar, [*inout-object*](#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*](#concept:inout-object "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutObj>void scale(ExecutionPolicy&& exec,
Scalar alpha, InOutObj x); // [[linalg.algs.blas1.copy]](#algs.blas1.copy "29.9.13.5Copy elements of one matrix or vector into another"), copy elementstemplate<[*in-object*](#concept:in-object "29.9.7.5Argument concepts[linalg.helpers.concepts]") InObj, [*out-object*](#concept:out-object "29.9.7.5Argument concepts[linalg.helpers.concepts]") OutObj>void copy(InObj x, OutObj y); template<class ExecutionPolicy, [*in-object*](#concept:in-object "29.9.7.5Argument concepts[linalg.helpers.concepts]") InObj, [*out-object*](#concept:out-object "29.9.7.5Argument concepts[linalg.helpers.concepts]") OutObj>void copy(ExecutionPolicy&& exec,
InObj x, OutObj y); // [[linalg.algs.blas1.add]](#algs.blas1.add "29.9.13.6Add vectors or matrices elementwise"), add elementwisetemplate<[*in-object*](#concept:in-object "29.9.7.5Argument concepts[linalg.helpers.concepts]") InObj1, [*in-object*](#concept:in-object "29.9.7.5Argument concepts[linalg.helpers.concepts]") InObj2, [*out-object*](#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*](#concept:in-object "29.9.7.5Argument concepts[linalg.helpers.concepts]") InObj1, [*in-object*](#concept:in-object "29.9.7.5Argument concepts[linalg.helpers.concepts]") InObj2, [*out-object*](#concept:out-object "29.9.7.5Argument concepts[linalg.helpers.concepts]") OutObj>void add(ExecutionPolicy&& exec,
InObj1 x, InObj2 y, OutObj z); // [[linalg.algs.blas1.dot]](#algs.blas1.dot "29.9.13.7Dot product of two vectors"), dot product of two vectorstemplate<[*in-vector*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec1, [*in-vector*](#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*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec1, [*in-vector*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec2, class Scalar> Scalar dot(ExecutionPolicy&& exec,
InVec1 v1, InVec2 v2, Scalar init); template<[*in-vector*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec1, [*in-vector*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec2>auto dot(InVec1 v1, InVec2 v2); template<class ExecutionPolicy, [*in-vector*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec1, [*in-vector*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec2>auto dot(ExecutionPolicy&& exec,
InVec1 v1, InVec2 v2); template<[*in-vector*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec1, [*in-vector*](#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*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec1, [*in-vector*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec2, class Scalar> Scalar dotc(ExecutionPolicy&& exec,
InVec1 v1, InVec2 v2, Scalar init); template<[*in-vector*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec1, [*in-vector*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec2>auto dotc(InVec1 v1, InVec2 v2); template<class ExecutionPolicy, [*in-vector*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec1, [*in-vector*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec2>auto dotc(ExecutionPolicy&& exec,
InVec1 v1, InVec2 v2); // [[linalg.algs.blas1.ssq]](#algs.blas1.ssq "29.9.13.8Scaled sum of squares of a vector"), scaled sum of squares of a vector's elementstemplate<class Scalar>struct sum_of_squares_result { Scalar scaling_factor;
Scalar scaled_sum_of_squares; }; template<[*in-vector*](#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*](#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); // [[linalg.algs.blas1.nrm2]](#algs.blas1.nrm2 "29.9.13.9Euclidean norm of a vector"), Euclidean norm of a vectortemplate<[*in-vector*](#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*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec, class Scalar> Scalar vector_two_norm(ExecutionPolicy&& exec, InVec v, Scalar init); template<[*in-vector*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec>auto vector_two_norm(InVec v); template<class ExecutionPolicy, [*in-vector*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec>auto vector_two_norm(ExecutionPolicy&& exec, InVec v); // [[linalg.algs.blas1.asum]](#algs.blas1.asum "29.9.13.10Sum of absolute values of vector elements"), sum of absolute values of vector elementstemplate<[*in-vector*](#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*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec, class Scalar> Scalar vector_abs_sum(ExecutionPolicy&& exec, InVec v, Scalar init); template<[*in-vector*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec>auto vector_abs_sum(InVec v); template<class ExecutionPolicy, [*in-vector*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec>auto vector_abs_sum(ExecutionPolicy&& exec, InVec v); // [[linalg.algs.blas1.iamax]](#algs.blas1.iamax "29.9.13.11Index of maximum absolute value of vector elements"), index of maximum absolute value of vector elementstemplate<[*in-vector*](#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*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec>typename InVec::extents_type vector_idx_abs_max(ExecutionPolicy&& exec, InVec v); // [[linalg.algs.blas1.matfrobnorm]](#algs.blas1.matfrobnorm "29.9.13.12Frobenius norm of a matrix"), Frobenius norm of a matrixtemplate<[*in-matrix*](#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*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Scalar> Scalar matrix_frob_norm(ExecutionPolicy&& exec, InMat A, Scalar init); template<[*in-matrix*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat>auto matrix_frob_norm(InMat A); template<class ExecutionPolicy, [*in-matrix*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat>auto matrix_frob_norm(ExecutionPolicy&& exec, InMat A); // [[linalg.algs.blas1.matonenorm]](#algs.blas1.matonenorm "29.9.13.13One norm of a matrix"), one norm of a matrixtemplate<[*in-matrix*](#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*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Scalar> Scalar matrix_one_norm(ExecutionPolicy&& exec, InMat A, Scalar init); template<[*in-matrix*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat>auto matrix_one_norm(InMat A); template<class ExecutionPolicy, [*in-matrix*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat>auto matrix_one_norm(ExecutionPolicy&& exec, InMat A); // [[linalg.algs.blas1.matinfnorm]](#algs.blas1.matinfnorm "29.9.13.14Infinity norm of a matrix"), infinity norm of a matrixtemplate<[*in-matrix*](#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*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Scalar> Scalar matrix_inf_norm(ExecutionPolicy&& exec, InMat A, Scalar init); template<[*in-matrix*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat>auto matrix_inf_norm(InMat A); template<class ExecutionPolicy, [*in-matrix*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat>auto matrix_inf_norm(ExecutionPolicy&& exec, InMat A); // [[linalg.algs.blas2]](#algs.blas2 "29.9.14BLAS 2 algorithms"), BLAS 2 algorithms// [[linalg.algs.blas2.gemv]](#algs.blas2.gemv "29.9.14.1General matrix-vector product"), general matrix-vector producttemplate<[*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, [*out-vector*](#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*](#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, [*out-vector*](#concept:out-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") OutVec>void matrix_vector_product(ExecutionPolicy&& exec,
InMat A, InVec x, OutVec y); 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]") InVec1, [*in-vector*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec2, [*out-vector*](#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*](#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]") InVec1, [*in-vector*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec2, [*out-vector*](#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); // [[linalg.algs.blas2.symv]](#algs.blas2.symv "29.9.14.2Symmetric matrix-vector product"), symmetric matrix-vector producttemplate<[*in-matrix*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, [*in-vector*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec, [*out-vector*](#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*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, [*in-vector*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec, [*out-vector*](#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); template<[*in-matrix*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, [*in-vector*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec1, [*in-vector*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec2, [*out-vector*](#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*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, [*in-vector*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec1, [*in-vector*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec2, [*out-vector*](#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); // [[linalg.algs.blas2.hemv]](#algs.blas2.hemv "29.9.14.3Hermitian matrix-vector product"), Hermitian matrix-vector producttemplate<[*in-matrix*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, [*in-vector*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec, [*out-vector*](#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*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, [*in-vector*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec, [*out-vector*](#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); template<[*in-matrix*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, [*in-vector*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec1, [*in-vector*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec2, [*out-vector*](#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*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, [*in-vector*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec1, [*in-vector*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec2, [*out-vector*](#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); // [[linalg.algs.blas2.trmv]](#algs.blas2.trmv "29.9.14.4Triangular matrix-vector product"), triangular matrix-vector product// Overwriting triangular matrix-vector producttemplate<[*in-matrix*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage, [*in-vector*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec, [*out-vector*](#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*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage, [*in-vector*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec, [*out-vector*](#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); // In-place triangular matrix-vector producttemplate<[*in-matrix*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage, [*inout-vector*](#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*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage, [*inout-vector*](#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); // Updating triangular matrix-vector producttemplate<[*in-matrix*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage, [*in-vector*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec1, [*in-vector*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec2, [*out-vector*](#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*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage, [*in-vector*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec1, [*in-vector*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec2, [*out-vector*](#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); // [[linalg.algs.blas2.trsv]](#algs.blas2.trsv "29.9.14.5Solve a triangular linear system"), solve a triangular linear system// Solve a triangular linear system, not in placetemplate<[*in-matrix*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage, [*in-vector*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec, [*out-vector*](#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*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage, [*in-vector*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec, [*out-vector*](#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); template<[*in-matrix*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage, [*in-vector*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec, [*out-vector*](#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); template<class ExecutionPolicy, [*in-matrix*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage, [*in-vector*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec, [*out-vector*](#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); // Solve a triangular linear system, in placetemplate<[*in-matrix*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage, [*inout-vector*](#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*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage, [*inout-vector*](#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); template<[*in-matrix*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage, [*inout-vector*](#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); template<class ExecutionPolicy, [*in-matrix*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage, [*inout-vector*](#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); // [[linalg.algs.blas2.rank1]](#algs.blas2.rank1 "29.9.14.6Rank-1 (outer product) update of a matrix"), nonsymmetric rank-1 matrix updatetemplate<[*in-vector*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec1, [*in-vector*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec2, [*inout-matrix*](#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*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec1, [*in-vector*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec2, [*inout-matrix*](#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); template<[*in-vector*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec1, [*in-vector*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec2, [*inout-matrix*](#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*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec1, [*in-vector*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec2, [*inout-matrix*](#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); // [[linalg.algs.blas2.symherrank1]](#algs.blas2.symherrank1 "29.9.14.7Symmetric or Hermitian Rank-1 (outer product) update of a matrix"), symmetric or Hermitian rank-1 matrix updatetemplate<class Scalar, [*in-vector*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec, [*possibly-packed-inout-matrix*](#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*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec, [*possibly-packed-inout-matrix*](#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); template<[*in-vector*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec, [*possibly-packed-inout-matrix*](#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*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec, [*possibly-packed-inout-matrix*](#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); template<class Scalar, [*in-vector*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec, [*possibly-packed-inout-matrix*](#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*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec, [*possibly-packed-inout-matrix*](#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); template<[*in-vector*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec, [*possibly-packed-inout-matrix*](#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*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec, [*possibly-packed-inout-matrix*](#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); // [[linalg.algs.blas2.rank2]](#algs.blas2.rank2 "29.9.14.8Symmetric and Hermitian rank-2 matrix updates"), symmetric and Hermitian rank-2 matrix updates// symmetric rank-2 matrix updatetemplate<[*in-vector*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec1, [*in-vector*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec2, [*possibly-packed-inout-matrix*](#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*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec1, [*in-vector*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec2, [*possibly-packed-inout-matrix*](#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); // Hermitian rank-2 matrix updatetemplate<[*in-vector*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec1, [*in-vector*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec2, [*possibly-packed-inout-matrix*](#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*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec1, [*in-vector*](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec2, [*possibly-packed-inout-matrix*](#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); // [[linalg.algs.blas3]](#algs.blas3 "29.9.15BLAS 3 algorithms"), BLAS 3 algorithms// [[linalg.algs.blas3.gemm]](#algs.blas3.gemm "29.9.15.1General matrix-matrix product"), general matrix-matrix producttemplate<[*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, [*out-matrix*](#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*](#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, [*out-matrix*](#concept:out-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") OutMat>void matrix_product(ExecutionPolicy&& exec,
InMat1 A, InMat2 B, OutMat C); 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]") InMat3, [*out-matrix*](#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*](#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]") InMat3, [*out-matrix*](#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); // [[linalg.algs.blas3.xxmm]](#algs.blas3.xxmm "29.9.15.2Symmetric, Hermitian, and triangular matrix-matrix product"), symmetric, Hermitian, and triangular matrix-matrix producttemplate<[*in-matrix*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat1, class Triangle, [*in-matrix*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat2, [*out-matrix*](#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*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat1, class Triangle, [*in-matrix*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat2, [*out-matrix*](#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*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat1, class Triangle, [*in-matrix*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat2, [*out-matrix*](#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*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat1, class Triangle, [*in-matrix*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat2, [*out-matrix*](#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*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat1, class Triangle, class DiagonalStorage, [*in-matrix*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat2, [*out-matrix*](#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*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat1, class Triangle, class DiagonalStorage, [*in-matrix*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat2, [*out-matrix*](#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); 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, class Triangle, [*out-matrix*](#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*](#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, class Triangle, [*out-matrix*](#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*](#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, class Triangle, [*out-matrix*](#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*](#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, class Triangle, [*out-matrix*](#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*](#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, class Triangle, class DiagonalStorage, [*out-matrix*](#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*](#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, class Triangle, class DiagonalStorage, [*out-matrix*](#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); template<[*in-matrix*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat1, class Triangle, [*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]") InMat3, [*out-matrix*](#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*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat1, class Triangle, [*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]") InMat3, [*out-matrix*](#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*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat1, class Triangle, [*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]") InMat3, [*out-matrix*](#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*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat1, class Triangle, [*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]") InMat3, [*out-matrix*](#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*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat1, class Triangle, class DiagonalStorage, [*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]") InMat3, [*out-matrix*](#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*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat1, class Triangle, class DiagonalStorage, [*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]") InMat3, [*out-matrix*](#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); 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, class Triangle, [*in-matrix*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat3, [*out-matrix*](#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*](#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, class Triangle, [*in-matrix*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat3, [*out-matrix*](#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*](#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, class Triangle, [*in-matrix*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat3, [*out-matrix*](#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*](#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, class Triangle, [*in-matrix*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat3, [*out-matrix*](#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*](#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, class Triangle, class DiagonalStorage, [*in-matrix*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat3, [*out-matrix*](#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*](#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, class Triangle, class DiagonalStorage, [*in-matrix*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat3, [*out-matrix*](#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); // [[linalg.algs.blas3.trmm]](#algs.blas3.trmm "29.9.15.3In-place triangular matrix-matrix product"), in-place triangular matrix-matrix producttemplate<[*in-matrix*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage, [*inout-matrix*](#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*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage, [*inout-matrix*](#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); template<[*in-matrix*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage, [*inout-matrix*](#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*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage, [*inout-matrix*](#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); // [[linalg.algs.blas3.rankk]](#algs.blas3.rankk "29.9.15.4Rank-k update of a symmetric or Hermitian matrix"), rank-k update of a symmetric or Hermitian matrix// rank-k symmetric matrix updatetemplate<class Scalar, [*in-matrix*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, [*possibly-packed-inout-matrix*](#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*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, [*possibly-packed-inout-matrix*](#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); template<[*in-matrix*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, [*possibly-packed-inout-matrix*](#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*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, [*possibly-packed-inout-matrix*](#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); // rank-k Hermitian matrix updatetemplate<class Scalar, [*in-matrix*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, [*possibly-packed-inout-matrix*](#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*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, [*possibly-packed-inout-matrix*](#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); template<[*in-matrix*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, [*possibly-packed-inout-matrix*](#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*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, [*possibly-packed-inout-matrix*](#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); // [[linalg.algs.blas3.rank2k]](#algs.blas3.rank2k "29.9.15.5Rank-2k update of a symmetric or Hermitian matrix"), rank-2k update of a symmetric or Hermitian matrix// rank-2k symmetric matrix updatetemplate<[*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, [*possibly-packed-inout-matrix*](#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*](#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, [*possibly-packed-inout-matrix*](#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); // rank-2k Hermitian matrix updatetemplate<[*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, [*possibly-packed-inout-matrix*](#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*](#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, [*possibly-packed-inout-matrix*](#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); // [[linalg.algs.blas3.trsm]](#algs.blas3.trsm "29.9.15.6Solve multiple triangular linear systems"), solve multiple triangular linear systems// solve multiple triangular systems on the left, not-in-placetemplate<[*in-matrix*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat1, class Triangle, class DiagonalStorage, [*in-matrix*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat2, [*out-matrix*](#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*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat1, class Triangle, class DiagonalStorage, [*in-matrix*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat2, [*out-matrix*](#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); template<[*in-matrix*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat1, class Triangle, class DiagonalStorage, [*in-matrix*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat2, [*out-matrix*](#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); template<class ExecutionPolicy, [*in-matrix*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat1, class Triangle, class DiagonalStorage, [*in-matrix*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat2, [*out-matrix*](#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); // solve multiple triangular systems on the right, not-in-placetemplate<[*in-matrix*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat1, class Triangle, class DiagonalStorage, [*in-matrix*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat2, [*out-matrix*](#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*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat1, class Triangle, class DiagonalStorage, [*in-matrix*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat2, [*out-matrix*](#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); template<[*in-matrix*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat1, class Triangle, class DiagonalStorage, [*in-matrix*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat2, [*out-matrix*](#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); template<class ExecutionPolicy, [*in-matrix*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat1, class Triangle, class DiagonalStorage, [*in-matrix*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat2, [*out-matrix*](#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); // solve multiple triangular systems on the left, in-placetemplate<[*in-matrix*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage, [*inout-matrix*](#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*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage, [*inout-matrix*](#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); template<[*in-matrix*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage, [*inout-matrix*](#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); template<class ExecutionPolicy, [*in-matrix*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage, [*inout-matrix*](#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); // solve multiple triangular systems on the right, in-placetemplate<[*in-matrix*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage, [*inout-matrix*](#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*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage, [*inout-matrix*](#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); template<[*in-matrix*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage, [*inout-matrix*](#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); template<class ExecutionPolicy, [*in-matrix*](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage, [*inout-matrix*](#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);}
### [29.9.3](#general) General [[linalg.general]](linalg.general)
[1](#general-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L11642)
For the effects of all functions in [linalg],
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)](#general-1.1)
E has
the conventional mathematical meaning as written[.](#general-1.1.sentence-1)
- [(1.2)](#general-1.2)
The pattern xT should be read as
“the transpose of x[.](#general-1.2.sentence-1)”
- [(1.3)](#general-1.3)
The pattern xH should be read as
“the conjugate transpose of x[.](#general-1.3.sentence-1)”
- [(1.4)](#general-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[.](#general-1.4.sentence-1)
[2](#general-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L11665)
Some of the functions and types in [linalg] distinguish between
the “rows” and the “columns” of a matrix[.](#general-2.sentence-1)
For a matrix A and a multidimensional index i, j in A.extents(),
- [(2.1)](#general-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)](#general-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()[.](#general-2.sentence-2)
[3](#general-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L11678)
Some of the functions in [linalg] distinguish between
the “upper triangle,” “lower triangle,” and “diagonal” of a matrix[.](#general-3.sentence-1)
- [(3.1)](#general-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))[.](#general-3.1.sentence-1)
- [(3.2)](#general-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[.](#general-3.2.sentence-1)
It includes the diagonal[.](#general-3.2.sentence-2)
- [(3.3)](#general-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[.](#general-3.3.sentence-1)
It includes the diagonal[.](#general-3.3.sentence-2)
[4](#general-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[.](#general-4.sentence-1)
Let m be such an access-modified function parameter[.](#general-4.sentence-2)
F will only access the triangle of m specified by t[.](#general-4.sentence-3)
For accesses m[i, j] outside the triangle specified by t,F will use the value
- [(4.1)](#general-4.1)
*conj-if-needed*(m[j, i]) if the name of F starts with hermitian,
- [(4.2)](#general-4.2)
m[j, i] if the name of F starts with symmetric, or
- [(4.3)](#general-4.3)
the additive identity if the name of F starts with triangular[.](#general-4.sentence-4)
[*Example [1](#general-example-1)*:
Small vector product accessing only specified triangle[.](#general-4.sentence-5)
It would not be a precondition violation for the non-accessed
matrix element to be non-zero[.](#general-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](#general-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[.](#general-5.sentence-1)
Let m be such an access-modified function parameter[.](#general-5.sentence-2)
If d specifies that an implicit unit diagonal is to be assumed, then
- [(5.1)](#general-5.1)
F will not access the diagonal of m; and
- [(5.2)](#general-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)[.](#general-5.sentence-3)
Otherwise,
if d specifies that an explicit diagonal is to be assumed,
then F will access the diagonal of m[.](#general-5.sentence-4)
[6](#general-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L11755)
Within all the functions in [linalg],
any calls to abs, conj, imag, and real are unqualified[.](#general-6.sentence-1)
[7](#general-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[.](#general-7.sentence-1)
[*Note [1](#general-note-1)*:
This means thatx and y view the same elements in the same order[.](#general-7.sentence-2)
— *end note*]
[8](#general-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[.](#general-8.sentence-1)
[*Note [2](#general-note-2)*:
Aliasing is a special case of overlapping[.](#general-8.sentence-2)
If x and y do not overlap,
then they also do not alias each other[.](#general-8.sentence-3)
— *end note*]
### [29.9.4](#reqs) Requirements [[linalg.reqs]](linalg.reqs)
#### [29.9.4.1](#reqs.val) Linear algebra value types [[linalg.reqs.val]](linalg.reqs.val)
[1](#reqs.val-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L11788)
Throughout [linalg],
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)](#reqs.val-1.1)
the value_type type alias of
any input or output mdspan parameter(s) of
any function in [linalg]; and
- [(1.2)](#reqs.val-1.2)
the Scalar template parameter (if any) of
any function or class in [linalg][.](#reqs.val-1.sentence-1)
[2](#reqs.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]")[.](#reqs.val-2.sentence-1)
[3](#reqs.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[.](#reqs.val-3.sentence-1)
#### [29.9.4.2](#reqs.alg) Algorithm and class requirements [[linalg.reqs.alg]](linalg.reqs.alg)
[1](#reqs.alg-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L11811)
[[linalg.reqs.alg]](#reqs.alg "29.9.4.2Algorithm and class requirements") lists common requirements for
all algorithms and classes in [linalg][.](#reqs.alg-1.sentence-1)
[2](#reqs.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[.](#reqs.alg-2.sentence-1)
- [(2.1)](#reqs.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[.](#reqs.alg-2.1.sentence-1)
- [(2.2)](#reqs.alg-2.2)
The [*triangular solve algorithms*](#def:triangular_solve_algorithms) in[[linalg.algs.blas2.trsv]](#algs.blas2.trsv "29.9.14.5Solve a triangular linear system"),[[linalg.algs.blas3.trmm]](#algs.blas3.trmm "29.9.15.3In-place triangular matrix-matrix product"),[[linalg.algs.blas3.trsm]](#algs.blas3.trsm "29.9.15.6Solve multiple triangular linear systems"), and[[linalg.algs.blas3.inplacetrsm]](#algs.blas3.inplacetrsm "29.9.15.7Solve multiple triangular linear systems in-place") either have
a BinaryDivideOp template parameter (see [[linalg.algs.reqs]](#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[.](#reqs.alg-2.2.sentence-1)
Triangular solve algorithms interpret divide(a, b) asa times the multiplicative inverse of b[.](#reqs.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[.](#reqs.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[.](#reqs.alg-2.2.sentence-4)
- [(2.3)](#reqs.alg-2.3)
Each function in[[linalg.algs.blas1]](#algs.blas1 "29.9.13BLAS 1 algorithms"), [[linalg.algs.blas2]](#algs.blas2 "29.9.14BLAS 2 algorithms"), and [[linalg.algs.blas3]](#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[.](#reqs.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[.](#reqs.alg-2.3.sentence-2)
- [(2.4)](#reqs.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[.](#reqs.alg-2.4.sentence-1)
- [(2.5)](#reqs.alg-2.5)
The function may reorder addends and partial sums arbitrarily[.](#reqs.alg-2.5.sentence-1)
[*Note [1](#reqs.alg-note-1)*:
Factors in each product are not reordered;
multiplication is not necessarily commutative[.](#reqs.alg-2.5.sentence-2)
— *end note*]
[*Note [2](#reqs.alg-note-2)*:
The above requirements do not prohibit
implementation approaches and optimization techniques
which are not user-observable[.](#reqs.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[.](#reqs.alg-2.sentence-3)
— *end note*]
[3](#reqs.alg-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L11896)
[*Note [3](#reqs.alg-note-3)*:
For all functions in [linalg],
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[.](#reqs.alg-3.sentence-1)
Then, functions can do all of the following:
- [(3.1)](#reqs.alg-3.1)
compute floating-point sums in any way
that improves their accuracy for arbitrary input;
- [(3.2)](#reqs.alg-3.2)
perform additional arithmetic operations
(other than those specified by the function's wording and [[linalg.reqs.alg]](#reqs.alg "29.9.4.2Algorithm and class requirements"))
in order to improve performance or accuracy; and
- [(3.3)](#reqs.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)](#reqs.alg-3.4)
the function satisfies the complexity requirements; and
- [(3.5)](#reqs.alg-3.5)
the function is logarithmically stable,
as defined in Demmel 2007[[bib]](bibliography#bib:linalg-stable "Bibliography")[.](#reqs.alg-3.sentence-2)
Strassen's algorithm for matrix-matrix multiply
is an example of a logarithmically stable algorithm[.](#reqs.alg-3.5.sentence-2)
— *end note*]
### [29.9.5](#tags) Tag classes [[linalg.tags]](linalg.tags)
#### [29.9.5.1](#tags.order) Storage order tags [[linalg.tags.order]](linalg.tags.order)
[1](#tags.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]](#layout.packed "29.9.6Layouts for packed matrix types")) layout[.](#tags.order-1.sentence-1)
[🔗](#tags.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](#tags.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[.](#tags.order-2.sentence-1)
#### [29.9.5.2](#tags.triangle) Triangle tags [[linalg.tags.triangle]](linalg.tags.triangle)
[🔗](#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](#tags.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]](#general "29.9.3General"))[.](#tags.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[.](#tags.triangle-1.sentence-2)
#### [29.9.5.3](#tags.diagonal) Diagonal tags [[linalg.tags.diagonal]](linalg.tags.diagonal)
[🔗](#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](#tags.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[.](#tags.diagonal-1.sentence-1)
[2](#tags.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]](#general "29.9.3General"))[.](#tags.diagonal-2.sentence-1)
[3](#tags.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]](#general "29.9.3General"))[.](#tags.diagonal-3.sentence-1)
### [29.9.6](#layout.packed) Layouts for packed matrix types [[linalg.layout.packed]](linalg.layout.packed)
#### [29.9.6.1](#layout.packed.overview) Overview [[linalg.layout.packed.overview]](linalg.layout.packed.overview)
[1](#layout.packed.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[.](#layout.packed.overview-1.sentence-1)
Its Triangle template parameter determines
whether an mdspan with this layout
stores the upper or lower triangle of the matrix[.](#layout.packed.overview-1.sentence-2)
Its StorageOrder template parameter determines
whether the layout packs the matrix's elements
in column-major or row-major order[.](#layout.packed.overview-1.sentence-3)
[2](#layout.packed.overview-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12026)
A StorageOrder of column_major_t indicates column-major ordering[.](#layout.packed.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)[.](#layout.packed.overview-2.sentence-2)
[3](#layout.packed.overview-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12033)
A StorageOrder of row_major_t indicates row-major ordering[.](#layout.packed.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[.](#layout.packed.overview-3.sentence-2)
[4](#layout.packed.overview-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12040)
[*Note [1](#layout.packed.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[.](#layout.packed.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]](#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]](#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](#layout.packed.overview-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12113)
*Mandates*:
- [(5.1)](#layout.packed.overview-5.1)
Triangle is either upper_triangle_t or lower_triangle_t,
- [(5.2)](#layout.packed.overview-5.2)
StorageOrder is either column_major_t or row_major_t,
- [(5.3)](#layout.packed.overview-5.3)
Extents is a specialization of std::extents,
- [(5.4)](#layout.packed.overview-5.4)
Extents::rank() equals 2,
- [(5.5)](#layout.packed.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)](#layout.packed.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[.](#layout.packed.overview-5.sentence-1)
[6](#layout.packed.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[.](#layout.packed.overview-6.sentence-1)
#### [29.9.6.2](#layout.packed.cons) Constructors [[linalg.layout.packed.cons]](linalg.layout.packed.cons)
[🔗](#lib:layout_blas_packed::mapping,constructor)
`constexpr mapping(const extents_type& e) noexcept;
`
[1](#layout.packed.cons-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12151)
*Preconditions*:
- [(1.1)](#layout.packed.cons-1.1)
Let N be equal to e.extent(0)[.](#layout.packed.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"))[.](#layout.packed.cons-1.1.sentence-2)
- [(1.2)](#layout.packed.cons-1.2)
e.extent(0) equals e.extent(1)[.](#layout.packed.cons-1.2.sentence-1)
[2](#layout.packed.cons-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12162)
*Effects*: Direct-non-list-initializes *extents_* with e[.](#layout.packed.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](#layout.packed.cons-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12175)
*Constraints*: is_constructible_v<extents_type, OtherExtents> is true[.](#layout.packed.cons-3.sentence-1)
[4](#layout.packed.cons-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12179)
*Preconditions*: Let N be other.extents().extent(0)[.](#layout.packed.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"))[.](#layout.packed.cons-4.sentence-2)
[5](#layout.packed.cons-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12185)
*Effects*: Direct-non-list-initializes *extents_* with other.extents()[.](#layout.packed.cons-5.sentence-1)
#### [29.9.6.3](#layout.packed.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](#layout.packed.obs-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12198)
*Returns*: *extents_*.extent(0) * (*extents_*.extent(0) + 1)/2[.](#layout.packed.obs-1.sentence-1)
[*Note [1](#layout.packed.obs-note-1)*:
For example, a 5 x 5 packed matrix
only stores 15 matrix elements[.](#layout.packed.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](#layout.packed.obs-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12214)
*Constraints*:
- [(2.1)](#layout.packed.obs-2.1)
is_convertible_v<Index0, index_type> is true,
- [(2.2)](#layout.packed.obs-2.2)
is_convertible_v<Index1, index_type> is true,
- [(2.3)](#layout.packed.obs-2.3)
is_nothrow_constructible_v<index_type, Index0> is true, and
- [(2.4)](#layout.packed.obs-2.4)
is_nothrow_constructible_v<index_type, Index1> is true[.](#layout.packed.obs-2.sentence-1)
[3](#layout.packed.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)[.](#layout.packed.obs-3.sentence-1)
[4](#layout.packed.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"))[.](#layout.packed.obs-4.sentence-1)
[5](#layout.packed.obs-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12236)
*Returns*: Let N be *extents_*.extent(0)[.](#layout.packed.obs-5.sentence-1)
Then
- [(5.1)](#layout.packed.obs-5.1)
(*this)(j, i) if i > j is true; otherwise
- [(5.2)](#layout.packed.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)](#layout.packed.obs-5.3)
j + N * i - i * (i + 1)/2[.](#layout.packed.obs-5.sentence-2)
[🔗](#lib:layout_blas_packed::mapping,stride)
`constexpr index_type stride(rank_type r) const noexcept;
`
[6](#layout.packed.obs-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12264)
*Preconditions*:
- [(6.1)](#layout.packed.obs-6.1)
is_strided() is true, and
- [(6.2)](#layout.packed.obs-6.2)
r < extents_type::rank() is true[.](#layout.packed.obs-6.sentence-1)
[7](#layout.packed.obs-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12273)
*Returns*: 1[.](#layout.packed.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](#layout.packed.obs-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12285)
*Effects*: Equivalent to: return x.extents() == y.extents();
### [29.9.7](#helpers) Exposition-only helpers [[linalg.helpers]](linalg.helpers)
#### [29.9.7.1](#helpers.abs) *abs-if-needed* [[linalg.helpers.abs]](linalg.helpers.abs)
[1](#helpers.abs-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12294)
The name *abs-if-needed* denotes an exposition-only function object[.](#helpers.abs-1.sentence-1)
The expression *abs-if-needed*(E) for a subexpression E whose type is T is expression-equivalent to:
- [(1.1)](#helpers.abs-1.1)
E if T is an unsigned integer;
- [(1.2)](#helpers.abs-1.2)
otherwise, std::abs(E) if T is an arithmetic type,
- [(1.3)](#helpers.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[.](#helpers.abs-1.3.sentence-2)
#### [29.9.7.2](#helpers.conj) *conj-if-needed* [[linalg.helpers.conj]](linalg.helpers.conj)
[1](#helpers.conj-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12317)
The name *conj-if-needed* denotes an exposition-only function object[.](#helpers.conj-1.sentence-1)
The expression *conj-if-needed*(E) for a subexpression E whose type is T is expression-equivalent to:
- [(1.1)](#helpers.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)](#helpers.conj-1.2)
otherwise, E[.](#helpers.conj-1.sentence-2)
#### [29.9.7.3](#helpers.real) *real-if-needed* [[linalg.helpers.real]](linalg.helpers.real)
[1](#helpers.real-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12339)
The name *real-if-needed* denotes an exposition-only function object[.](#helpers.real-1.sentence-1)
The expression *real-if-needed*(E) for a subexpression E whose type is T is expression-equivalent to:
- [(1.1)](#helpers.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)](#helpers.real-1.2)
otherwise, E[.](#helpers.real-1.sentence-2)
#### [29.9.7.4](#helpers.imag) *imag-if-needed* [[linalg.helpers.imag]](linalg.helpers.imag)
[1](#helpers.imag-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12361)
The name *imag-if-needed* denotes an exposition-only function object[.](#helpers.imag-1.sentence-1)
The expression *imag-if-needed*(E) for a subexpression E whose type is T is expression-equivalent to:
- [(1.1)](#helpers.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)](#helpers.imag-1.2)
otherwise, ((void)E, T{})[.](#helpers.imag-1.sentence-2)
#### [29.9.7.5](#helpers.concepts) Argument concepts [[linalg.helpers.concepts]](linalg.helpers.concepts)
[1](#helpers.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][.](#helpers.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](#helpers.concepts-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12448)
If a function in [linalg] 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[.](#helpers.concepts-2.sentence-1)
[3](#helpers.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]
shall not overlap any other mdspan parameter of the function[.](#helpers.concepts-3.sentence-1)
#### [29.9.7.6](#helpers.mandates) Mandates [[linalg.helpers.mandates]](linalg.helpers.mandates)
[1](#helpers.mandates-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12470)
[*Note [1](#helpers.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[.](#helpers.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](#helpers.precond) Preconditions [[linalg.helpers.precond]](linalg.helpers.precond)
[1](#helpers.precond-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12529)
[*Note [1](#helpers.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[.](#helpers.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);}
### [29.9.8](#scaled) Scaled in-place transformation [[linalg.scaled]](linalg.scaled)
#### [29.9.8.1](#scaled.intro) Introduction [[linalg.scaled.intro]](linalg.scaled.intro)
[1](#scaled.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[.](#scaled.intro-1.sentence-1)
[*Example [1](#scaled.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](#scaled.scaledaccessor) Class template scaled_accessor [[linalg.scaled.scaledaccessor]](linalg.scaled.scaledaccessor)
[1](#scaled.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[.](#scaled.scaledaccessor-1.sentence-1)
It is part of the implementation of scaled ([[linalg.scaled.scaled]](#scaled.scaled "29.9.8.3Function template scaled"))[.](#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](#scaled.scaledaccessor-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12631)
*Mandates*:
- [(2.1)](#scaled.scaledaccessor-2.1)
element_type is valid and denotes a type,
- [(2.2)](#scaled.scaledaccessor-2.2)
is_copy_constructible_v<reference> is true,
- [(2.3)](#scaled.scaledaccessor-2.3)
is_reference_v<element_type> is false,
- [(2.4)](#scaled.scaledaccessor-2.4)
ScalingFactor models [semiregular](concepts.object#concept:semiregular "18.6Object concepts[concepts.object]"), and
- [(2.5)](#scaled.scaledaccessor-2.5)
NestedAccessor meets the accessor policy requirements ([[mdspan.accessor.reqmts]](mdspan.accessor.reqmts "23.7.3.5.2Requirements"))[.](#scaled.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](#scaled.scaledaccessor-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12654)
*Constraints*: is_constructible_v<NestedAccessor, const OtherNestedAccessor&> is true[.](#scaled.scaledaccessor-3.sentence-1)
[4](#scaled.scaledaccessor-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12658)
*Effects*:
- [(4.1)](#scaled.scaledaccessor-4.1)
Direct-non-list-initializes *scaling-factor* with other.scaling_factor(), and
- [(4.2)](#scaled.scaledaccessor-4.2)
direct-non-list-initializes *nested-accessor* with other.nested_accessor()[.](#scaled.scaledaccessor-4.sentence-1)
[🔗](#lib:scaled_accessor,constructor_)
`constexpr scaled_accessor(const ScalingFactor& s, const NestedAccessor& a);
`
[5](#scaled.scaledaccessor-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12676)
*Effects*:
- [(5.1)](#scaled.scaledaccessor-5.1)
Direct-non-list-initializes *scaling-factor* with s, and
- [(5.2)](#scaled.scaledaccessor-5.2)
direct-non-list-initializes *nested-accessor* with a[.](#scaled.scaledaccessor-5.sentence-1)
[🔗](#lib:scaled_accessor,access)
`constexpr reference access(data_handle_type p, size_t i) const;
`
[6](#scaled.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](#scaled.scaledaccessor-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12705)
*Returns*: *nested-accessor*.offset(p, i)
#### [29.9.8.3](#scaled.scaled) Function template scaled [[linalg.scaled.scaled]](linalg.scaled.scaled)
[1](#scaled.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.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.scaled-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12728)
Let SA be scaled_accessor<ScalingFactor, Accessor>[.](#scaled.scaled-2.sentence-1)
[3](#scaled.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.scaled-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12739)
[*Example [1](#scaled.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*]
### [29.9.9](#conj) Conjugated in-place transformation [[linalg.conj]](linalg.conj)
#### [29.9.9.1](#conj.intro) Introduction [[linalg.conj.intro]](linalg.conj.intro)
[1](#conj.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[.](#conj.intro-1.sentence-1)
#### [29.9.9.2](#conj.conjugatedaccessor) Class template conjugated_accessor [[linalg.conj.conjugatedaccessor]](linalg.conj.conjugatedaccessor)
[1](#conj.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[.](#conj.conjugatedaccessor-1.sentence-1)
It is part of the implementation ofconjugated ([[linalg.conj.conjugated]](#conj.conjugated "29.9.9.3Function template conjugated"))[.](#conj.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](#conj.conjugatedaccessor-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12801)
*Mandates*:
- [(2.1)](#conj.conjugatedaccessor-2.1)
element_type is valid and denotes a type,
- [(2.2)](#conj.conjugatedaccessor-2.2)
is_copy_constructible_v<reference> is true,
- [(2.3)](#conj.conjugatedaccessor-2.3)
is_reference_v<element_type> is false, and
- [(2.4)](#conj.conjugatedaccessor-2.4)
NestedAccessor meets the accessor policy requirements ([[mdspan.accessor.reqmts]](mdspan.accessor.reqmts "23.7.3.5.2Requirements"))[.](#conj.conjugatedaccessor-2.sentence-1)
[🔗](#lib:conjugated_accessor,constructor)
`constexpr conjugated_accessor(const NestedAccessor& acc);
`
[3](#conj.conjugatedaccessor-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12820)
*Effects*: Direct-non-list-initializes*nested-accessor_* with acc[.](#conj.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](#conj.conjugatedaccessor-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12834)
*Constraints*: is_constructible_v<NestedAccessor, const OtherNestedAccessor&> is true[.](#conj.conjugatedaccessor-4.sentence-1)
[5](#conj.conjugatedaccessor-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12839)
*Effects*: Direct-non-list-initializes *nested-accessor_* with other.nested_accessor()[.](#conj.conjugatedaccessor-5.sentence-1)
[🔗](#lib:conjugated_accessor,access)
`constexpr reference access(data_handle_type p, size_t i) const;
`
[6](#conj.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](#conj.conjugatedaccessor-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12862)
*Returns*: *nested-accessor_*.offset(p, i)
#### [29.9.9.3](#conj.conjugated) Function template conjugated [[linalg.conj.conjugated]](linalg.conj.conjugated)
[🔗](#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](#conj.conjugated-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12875)
Let A be
- [(1.1)](#conj.conjugated-1.1)
remove_cvref_t<decltype(a.accessor().nested_accessor())> if Accessor is a specialization of conjugated_accessor;
- [(1.2)](#conj.conjugated-1.2)
otherwise,Accessor if remove_cvref_t<ElementType> is an arithmetic type;
- [(1.3)](#conj.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)](#conj.conjugated-1.4)
otherwise,Accessor[.](#conj.conjugated-1.sentence-1)
[2](#conj.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>[.](#conj.conjugated-2.sentence-1)
- [(2.1)](#conj.conjugated-2.1)
MD(a.data_handle(), a.mapping(), a.accessor().nested_accessor()) if Accessor is a
specialization of conjugated_accessor;
- [(2.2)](#conj.conjugated-2.2)
otherwise,a, if is_same_v<A, Accessor> is true;
- [(2.3)](#conj.conjugated-2.3)
otherwise,MD(a.data_handle(), a.mapping(), conjugated_accessor(a.accessor())).
[3](#conj.conjugated-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12912)
[*Example [1](#conj.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*]
### [29.9.10](#transp) Transpose in-place transformation [[linalg.transp]](linalg.transp)
#### [29.9.10.1](#transp.intro) Introduction [[linalg.transp.intro]](linalg.transp.intro)
[1](#transp.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[.](#transp.intro-1.sentence-1)
[2](#transp.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[.](#transp.intro-2.sentence-1)
#### [29.9.10.2](#transp.helpers) Exposition-only helpers for layout_transpose and transposed [[linalg.transp.helpers]](linalg.transp.helpers)
[1](#transp.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[.](#transp.helpers-1.sentence-1)
[2](#transp.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[.](#transp.helpers-2.sentence-1)
[🔗](#transp.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](#transp.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](#transp.layout.transpose) Class template layout_transpose [[linalg.transp.layout.transpose]](linalg.transp.layout.transpose)
[1](#transp.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[.](#transp.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](#transp.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"))[.](#transp.layout.transpose-2.sentence-1)
[3](#transp.layout.transpose-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13053)
*Mandates*:
- [(3.1)](#transp.layout.transpose-3.1)
Extents is a specialization of std::extents, and
- [(3.2)](#transp.layout.transpose-3.2)
Extents::rank() equals 2[.](#transp.layout.transpose-3.sentence-1)
[🔗](#lib:layout_transpose::mapping,constructor)
`constexpr explicit mapping(const nested-mapping-type& map);
`
[4](#transp.layout.transpose-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13068)
*Effects*:
- [(4.1)](#transp.layout.transpose-4.1)
Initializes *nested-mapping_* with map, and
- [(4.2)](#transp.layout.transpose-4.2)
initializes *extents_* with *transpose-extents*(map.extents())[.](#transp.layout.transpose-4.sentence-1)
[🔗](#lib:layout_transpose::mapping,stride)
`constexpr index_type stride(size_t r) const;
`
[5](#transp.layout.transpose-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13085)
*Preconditions*:
- [(5.1)](#transp.layout.transpose-5.1)
is_strided() is true, and
- [(5.2)](#transp.layout.transpose-5.2)
r < 2 is true[.](#transp.layout.transpose-5.sentence-1)
[6](#transp.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](#transp.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[.](#transp.layout.transpose-7.sentence-1)
[8](#transp.layout.transpose-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13112)
*Returns*: x.*nested-mapping_* == y.*nested-mapping_*[.](#transp.layout.transpose-8.sentence-1)
#### [29.9.10.4](#transp.transposed) Function template transposed [[linalg.transp.transposed]](linalg.transp.transposed)
[1](#transp.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[.](#transp.transposed-1.sentence-1)
The input matrix's data are not modified, and
the returned mdspan accesses the input matrix's data in place[.](#transp.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](#transp.transposed-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13132)
*Mandates*: Extents::rank() == 2 is true[.](#transp.transposed-2.sentence-1)
[3](#transp.transposed-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13136)
Let ReturnExtents be*transpose-extents-t*<Extents>[.](#transp.transposed-3.sentence-1)
Let R bemdspan<ElementType, ReturnExtents, ReturnLayout, Accessor>,
where ReturnLayout is:
- [(3.1)](#transp.transposed-3.1)
layout_right if Layout is layout_left;
- [(3.2)](#transp.transposed-3.2)
otherwise, layout_left if Layout is layout_right;
- [(3.3)](#transp.transposed-3.3)
otherwise, layout_right_padded<PaddingValue> if Layout is
layout_left_padded<PaddingValue> for some size_t value PaddingValue;
- [(3.4)](#transp.transposed-3.4)
otherwise, layout_left_padded<PaddingValue> if Layout is
layout_right_padded<PaddingValue> for some size_t value PaddingValue;
- [(3.5)](#transp.transposed-3.5)
otherwise, layout_stride if Layout is layout_stride;
- [(3.6)](#transp.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)](#transp.transposed-3.6.1)
OppositeTriangle isconditional_t<is_same_v<Triangle, upper_triangle_t>,
lower_triangle_t, upper_triangle_t> and
* [(3.6.2)](#transp.transposed-3.6.2)
OppositeStorageOrder isconditional_t<is_same_v<StorageOrder, column_major_t>, row_major_t, column_major_t>
- [(3.7)](#transp.transposed-3.7)
otherwise, NestedLayout if Layout is layout_transpose<NestedLayout> for some NestedLayout;
- [(3.8)](#transp.transposed-3.8)
otherwise, layout_transpose<Layout>[.](#transp.transposed-3.sentence-2)
[4](#transp.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)](#transp.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)](#transp.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)](#transp.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)](#transp.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)](#transp.transposed-4.5)
otherwise, if Layout is a specialization of layout_transpose,R(a.data_handle(), a.mapping().nested_mapping(), a.accessor())
- [(4.6)](#transp.transposed-4.6)
otherwise,R(a.data_handle(), ReturnMapping(a.mapping()), a.accessor())
[5](#transp.transposed-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13232)
[*Example [1](#transp.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*]
### [29.9.11](#conjtransposed) Conjugate transpose in-place transform [[linalg.conjtransposed]](linalg.conjtransposed)
[1](#conjtransposed-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13268)
The conjugate_transposed function
returns a conjugate transpose view of an object[.](#conjtransposed-1.sentence-1)
This combines the effects of transposed and conjugated[.](#conjtransposed-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](#conjtransposed-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13279)
*Effects*: Equivalent to: return conjugated(transposed(a));
[3](#conjtransposed-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13284)
[*Example [1](#conjtransposed-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*]
### [29.9.12](#algs.reqs) Algorithm requirements based on template parameter name [[linalg.algs.reqs]](linalg.algs.reqs)
[1](#algs.reqs-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13321)
Throughout[[linalg.algs.blas1]](#algs.blas1 "29.9.13BLAS 1 algorithms"), [[linalg.algs.blas2]](#algs.blas2 "29.9.14BLAS 2 algorithms"), and [[linalg.algs.blas3]](#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[.](#algs.reqs-1.sentence-1)
- [(1.1)](#algs.reqs-1.1)
is_execution_policy<ExecutionPolicy>::value is true ([[execpol.type]](execpol.type "26.3.6.2Execution policy type trait"))[.](#algs.reqs-1.1.sentence-1)
- [(1.2)](#algs.reqs-1.2)
Real is any type such that complex<Real> is
specified ([[complex.numbers.general]](complex.numbers.general "29.4.1General"))[.](#algs.reqs-1.2.sentence-1)
- [(1.3)](#algs.reqs-1.3)
Triangle is either upper_triangle_t or lower_triangle_t[.](#algs.reqs-1.3.sentence-1)
- [(1.4)](#algs.reqs-1.4)
DiagonalStorage is
either implicit_unit_diagonal_t or explicit_diagonal_t[.](#algs.reqs-1.4.sentence-1)
[*Note [1](#algs.reqs-note-1)*:
Function templates that have a template parameter named ExecutionPolicy are parallel algorithms ([[algorithms.parallel.defns]](algorithms.parallel.defns "26.3.1Preamble"))[.](#algs.reqs-1.sentence-2)
— *end note*]
### [29.9.13](#algs.blas1) BLAS 1 algorithms [[linalg.algs.blas1]](linalg.algs.blas1)
#### [29.9.13.1](#algs.blas1.complexity) Complexity [[linalg.algs.blas1.complexity]](linalg.algs.blas1.complexity)
[1](#algs.blas1.complexity-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13348)
*Complexity*: All algorithms in [[linalg.algs.blas1]](#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[.](#algs.blas1.complexity-1.sentence-1)
#### [29.9.13.2](#algs.blas1.givens) Givens rotations [[linalg.algs.blas1.givens]](linalg.algs.blas1.givens)
#### [29.9.13.2.1](#algs.blas1.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](#algs.blas1.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[.](#algs.blas1.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[.](#algs.blas1.givens.lartg-1.sentence-3)
[*Note [1](#algs.blas1.givens.lartg-note-1)*:
These functions correspond to the LAPACK function xLARTG[[bib]](bibliography#bib:lapack "Bibliography")[.](#algs.blas1.givens.lartg-1.sentence-4)
— *end note*]
[2](#algs.blas1.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[.](#algs.blas1.givens.lartg-2.sentence-1)
#### [29.9.13.2.2](#algs.blas1.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](#concept:inout-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutVec1, [inout-vector](#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](#concept:inout-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutVec1, [inout-vector](#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](#concept:inout-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutVec1, [inout-vector](#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](#concept:inout-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutVec1, [inout-vector](#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](#algs.blas1.givens.rot-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13428)
[*Note [1](#algs.blas1.givens.rot-note-1)*:
These functions correspond to the BLAS function xROT[[bib]](bibliography#bib:blas1 "Bibliography")[.](#algs.blas1.givens.rot-1.sentence-1)
— *end note*]
[2](#algs.blas1.givens.rot-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13433)
*Mandates*: *compatible-static-extents*<InOutVec1, InOutVec2>(0, 0) is true[.](#algs.blas1.givens.rot-2.sentence-1)
[3](#algs.blas1.givens.rot-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13437)
*Preconditions*: x.extent(0) equals y.extent(0)[.](#algs.blas1.givens.rot-3.sentence-1)
[4](#algs.blas1.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[.](#algs.blas1.givens.rot-4.sentence-1)
#### [29.9.13.3](#algs.blas1.swap) Swap matrix or vector elements [[linalg.algs.blas1.swap]](linalg.algs.blas1.swap)
[🔗](#lib:swap_elements)
`template<[inout-object](#concept:inout-object "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutObj1, [inout-object](#concept:inout-object "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutObj2>
void swap_elements(InOutObj1 x, InOutObj2 y);
template<class ExecutionPolicy, [inout-object](#concept:inout-object "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutObj1, [inout-object](#concept:inout-object "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutObj2>
void swap_elements(ExecutionPolicy&& exec, InOutObj1 x, InOutObj2 y);
`
[1](#algs.blas1.swap-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13461)
[*Note [1](#algs.blas1.swap-note-1)*:
These functions correspond to the BLAS function xSWAP[[bib]](bibliography#bib:blas1 "Bibliography")[.](#algs.blas1.swap-1.sentence-1)
— *end note*]
[2](#algs.blas1.swap-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13466)
*Constraints*: x.rank() equals y.rank()[.](#algs.blas1.swap-2.sentence-1)
[3](#algs.blas1.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[.](#algs.blas1.swap-3.sentence-1)
[4](#algs.blas1.swap-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13478)
*Preconditions*: x.extents() equals y.extents()[.](#algs.blas1.swap-4.sentence-1)
[5](#algs.blas1.swap-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13482)
*Effects*: Swaps all corresponding elements of x and y[.](#algs.blas1.swap-5.sentence-1)
#### [29.9.13.4](#algs.blas1.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](#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](#concept:inout-object "29.9.7.5Argument concepts[linalg.helpers.concepts]") InOutObj>
void scale(ExecutionPolicy&& exec, Scalar alpha, InOutObj x);
`
[1](#algs.blas1.scal-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13498)
[*Note [1](#algs.blas1.scal-note-1)*:
These functions correspond to the BLAS function xSCAL[[bib]](bibliography#bib:blas1 "Bibliography")[.](#algs.blas1.scal-1.sentence-1)
— *end note*]
[2](#algs.blas1.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[.](#algs.blas1.scal-2.sentence-1)
#### [29.9.13.5](#algs.blas1.copy) Copy elements of one matrix or vector into another [[linalg.algs.blas1.copy]](linalg.algs.blas1.copy)
[🔗](#lib:copy)
`template<[in-object](#concept:in-object "29.9.7.5Argument concepts[linalg.helpers.concepts]") InObj, [out-object](#concept:out-object "29.9.7.5Argument concepts[linalg.helpers.concepts]") OutObj>
void copy(InObj x, OutObj y);
template<class ExecutionPolicy, [in-object](#concept:in-object "29.9.7.5Argument concepts[linalg.helpers.concepts]") InObj, [out-object](#concept:out-object "29.9.7.5Argument concepts[linalg.helpers.concepts]") OutObj>
void copy(ExecutionPolicy&& exec, InObj x, OutObj y);
`
[1](#algs.blas1.copy-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13521)
[*Note [1](#algs.blas1.copy-note-1)*:
These functions correspond to the BLAS function xCOPY[[bib]](bibliography#bib:blas1 "Bibliography")[.](#algs.blas1.copy-1.sentence-1)
— *end note*]
[2](#algs.blas1.copy-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13526)
*Constraints*: x.rank() equals y.rank()[.](#algs.blas1.copy-2.sentence-1)
[3](#algs.blas1.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[.](#algs.blas1.copy-3.sentence-1)
[4](#algs.blas1.copy-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13538)
*Preconditions*: x.extents() equals y.extents()[.](#algs.blas1.copy-4.sentence-1)
[5](#algs.blas1.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[.](#algs.blas1.copy-5.sentence-1)
#### [29.9.13.6](#algs.blas1.add) Add vectors or matrices elementwise [[linalg.algs.blas1.add]](linalg.algs.blas1.add)
[🔗](#lib:add)
`template<[in-object](#concept:in-object "29.9.7.5Argument concepts[linalg.helpers.concepts]") InObj1, [in-object](#concept:in-object "29.9.7.5Argument concepts[linalg.helpers.concepts]") InObj2, [out-object](#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](#concept:in-object "29.9.7.5Argument concepts[linalg.helpers.concepts]") InObj1, [in-object](#concept:in-object "29.9.7.5Argument concepts[linalg.helpers.concepts]") InObj2, [out-object](#concept:out-object "29.9.7.5Argument concepts[linalg.helpers.concepts]") OutObj>
void add(ExecutionPolicy&& exec,
InObj1 x, InObj2 y, OutObj z);
`
[1](#algs.blas1.add-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13559)
[*Note [1](#algs.blas1.add-note-1)*:
These functions correspond to the BLAS function xAXPY[[bib]](bibliography#bib:blas1 "Bibliography")[.](#algs.blas1.add-1.sentence-1)
— *end note*]
[2](#algs.blas1.add-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13564)
*Constraints*: x.rank(), y.rank(), and z.rank() are all equal[.](#algs.blas1.add-2.sentence-1)
[3](#algs.blas1.add-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13568)
*Mandates*: *possibly-addable*<InObj1, InObj2, OutObj>() is true[.](#algs.blas1.add-3.sentence-1)
[4](#algs.blas1.add-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13572)
*Preconditions*: *addable*(x,y,z) is true[.](#algs.blas1.add-4.sentence-1)
[5](#algs.blas1.add-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13576)
*Effects*: Computes z=x+y[.](#algs.blas1.add-5.sentence-1)
[6](#algs.blas1.add-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13580)
*Remarks*: z may alias x or y[.](#algs.blas1.add-6.sentence-1)
#### [29.9.13.7](#algs.blas1.dot) Dot product of two vectors [[linalg.algs.blas1.dot]](linalg.algs.blas1.dot)
[1](#algs.blas1.dot-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13587)
[*Note [1](#algs.blas1.dot-note-1)*:
The functions in this section correspond to the BLAS
functions xDOT, xDOTU, and xDOTC[[bib]](bibliography#bib:blas1 "Bibliography")[.](#algs.blas1.dot-1.sentence-1)
— *end note*]
[2](#algs.blas1.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]](#algs.blas1.dot "29.9.13.7Dot product of two vectors")[.](#algs.blas1.dot-2.sentence-1)
[3](#algs.blas1.dot-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13596)
*Mandates*: *compatible-static-extents*<InVec1, InVec2>(0, 0) is true[.](#algs.blas1.dot-3.sentence-1)
[4](#algs.blas1.dot-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13600)
*Preconditions*: v1.extent(0) equals v2.extent(0)[.](#algs.blas1.dot-4.sentence-1)
[🔗](#lib:dot)
`template<[in-vector](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec1, [in-vector](#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](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec1, [in-vector](#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](#algs.blas1.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[.](#algs.blas1.dot-5.sentence-1)
[6](#algs.blas1.dot-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13618)
*Returns*: Let N be v1.extent(0)[.](#algs.blas1.dot-6.sentence-1)
- [(6.1)](#algs.blas1.dot-6.1)
init if N is zero;
- [(6.2)](#algs.blas1.dot-6.2)
otherwise,*GENERALIZED_SUM*(plus<>(), init, v1[0]*v2[0], …, v1[N-1]*v2[N-1]).
[7](#algs.blas1.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[.](#algs.blas1.dot-7.sentence-1)
[🔗](#lib:dot_)
` template<[in-vector](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec1, [in-vector](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec2>
auto dot(InVec1 v1, InVec2 v2);
template<class ExecutionPolicy, [in-vector](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec1, [in-vector](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec2>
auto dot(ExecutionPolicy&& exec,
InVec1 v1, InVec2 v2);
`
[8](#algs.blas1.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[.](#algs.blas1.dot-8.sentence-1)
[9](#algs.blas1.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>())[.](#algs.blas1.dot-9.sentence-1)
Then,
- [(9.1)](#algs.blas1.dot-9.1)
the two-parameter overload is equivalent to:return dot(v1, v2, T{}); and
- [(9.2)](#algs.blas1.dot-9.2)
the three-parameter overload is equivalent to:return dot(std::forward<ExecutionPolicy>(exec), v1, v2, T{});
[🔗](#lib:dotc)
`template<[in-vector](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec1, [in-vector](#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](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec1, [in-vector](#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](#algs.blas1.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[.](#algs.blas1.dot-10.sentence-1)
[11](#algs.blas1.dot-11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13686)
*Effects*:
- [(11.1)](#algs.blas1.dot-11.1)
The three-parameter overload is equivalent to:return dot(conjugated(v1), v2, init); and
- [(11.2)](#algs.blas1.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](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec1, [in-vector](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec2>
auto dotc(InVec1 v1, InVec2 v2);
template<class ExecutionPolicy, [in-vector](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec1, [in-vector](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec2>
auto dotc(ExecutionPolicy&& exec,
InVec1 v1, InVec2 v2);
`
[12](#algs.blas1.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[.](#algs.blas1.dot-12.sentence-1)
[13](#algs.blas1.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>())[.](#algs.blas1.dot-13.sentence-1)
Then,
- [(13.1)](#algs.blas1.dot-13.1)
the two-parameter overload is equivalent to:return dotc(v1, v2, T{}); and
- [(13.2)](#algs.blas1.dot-13.2)
the three-parameter overload is equivalent toreturn dotc(std::forward<ExecutionPolicy>(exec), v1, v2, T{});
#### [29.9.13.8](#algs.blas1.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](#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](#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](#algs.blas1.ssq-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13748)
[*Note [1](#algs.blas1.ssq-note-1)*:
These functions correspond to the LAPACK function xLASSQ[[bib]](bibliography#bib:lapack "Bibliography")[.](#algs.blas1.ssq-1.sentence-1)
— *end note*]
[2](#algs.blas1.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[.](#algs.blas1.ssq-2.sentence-1)
[3](#algs.blas1.ssq-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13757)
*Effects*: Returns a value result such that
- [(3.1)](#algs.blas1.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)](#algs.blas1.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[.](#algs.blas1.ssq-3.sentence-1)
[4](#algs.blas1.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[.](#algs.blas1.ssq-4.sentence-1)
#### [29.9.13.9](#algs.blas1.nrm2) Euclidean norm of a vector [[linalg.algs.blas1.nrm2]](linalg.algs.blas1.nrm2)
[🔗](#lib:vector_two_norm)
`template<[in-vector](#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](#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](#algs.blas1.nrm2-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13796)
[*Note [1](#algs.blas1.nrm2-note-1)*:
These functions correspond to the BLAS function xNRM2[[bib]](bibliography#bib:blas1 "Bibliography")[.](#algs.blas1.nrm2-1.sentence-1)
— *end note*]
[2](#algs.blas1.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>())[.](#algs.blas1.nrm2-2.sentence-1)
Then, decltype(init + a * a is convertible to Scalar[.](#algs.blas1.nrm2-2.sentence-2)
[3](#algs.blas1.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[.](#algs.blas1.nrm2-3.sentence-1)
[*Note [2](#algs.blas1.nrm2-note-2)*:
For init equal to zero, this is the Euclidean norm
(also called 2-norm) of the vector v[.](#algs.blas1.nrm2-3.sentence-2)
— *end note*]
[4](#algs.blas1.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[.](#algs.blas1.nrm2-4.sentence-1)
[*Note [3](#algs.blas1.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})[.](#algs.blas1.nrm2-4.sentence-2)
— *end note*]
[🔗](#lib:vector_two_norm_)
`template<[in-vector](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec>
auto vector_two_norm(InVec v);
template<class ExecutionPolicy, [in-vector](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec>
auto vector_two_norm(ExecutionPolicy&& exec, InVec v);
`
[5](#algs.blas1.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>())[.](#algs.blas1.nrm2-5.sentence-1)
Let T be decltype(a * a)[.](#algs.blas1.nrm2-5.sentence-2)
Then,
- [(5.1)](#algs.blas1.nrm2-5.1)
the one-parameter overload is equivalent to:return vector_two_norm(v, T{}); and
- [(5.2)](#algs.blas1.nrm2-5.2)
the two-parameter overload is equivalent to:return vector_two_norm(std::forward<ExecutionPolicy>(exec), v, T{});
#### [29.9.13.10](#algs.blas1.asum) Sum of absolute values of vector elements [[linalg.algs.blas1.asum]](linalg.algs.blas1.asum)
[🔗](#lib:vector_abs_sum)
`template<[in-vector](#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](#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](#algs.blas1.asum-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13870)
[*Note [1](#algs.blas1.asum-note-1)*:
These functions correspond to the BLAS functionsSASUM, DASUM, SCASUM, and DZASUM[[bib]](bibliography#bib:blas1 "Bibliography")[.](#algs.blas1.asum-1.sentence-1)
— *end note*]
[2](#algs.blas1.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[.](#algs.blas1.asum-2.sentence-1)
[3](#algs.blas1.asum-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13884)
*Returns*: Let N be v.extent(0)[.](#algs.blas1.asum-3.sentence-1)
- [(3.1)](#algs.blas1.asum-3.1)
init if N is zero;
- [(3.2)](#algs.blas1.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)](#algs.blas1.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](#algs.blas1.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[.](#algs.blas1.asum-4.sentence-1)
[🔗](#lib:vector_abs_sum_)
`template<[in-vector](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec>
auto vector_abs_sum(InVec v);
template<class ExecutionPolicy, [in-vector](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec>
auto vector_abs_sum(ExecutionPolicy&& exec, InVec v);
`
[5](#algs.blas1.asum-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13923)
*Effects*: Let T be typename InVec::value_type[.](#algs.blas1.asum-5.sentence-1)
Then,
- [(5.1)](#algs.blas1.asum-5.1)
the one-parameter overload is equivalent to:return vector_abs_sum(v, T{}); and
- [(5.2)](#algs.blas1.asum-5.2)
the two-parameter overload is equivalent to:return vector_abs_sum(std::forward<ExecutionPolicy>(exec), v, T{});
#### [29.9.13.11](#algs.blas1.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](#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](#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](#algs.blas1.iamax-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13953)
[*Note [1](#algs.blas1.iamax-note-1)*:
These functions correspond to the BLAS function IxAMAX[[bib]](bibliography#bib:blas1 "Bibliography")[.](#algs.blas1.iamax-1.sentence-1)
— *end note*]
[2](#algs.blas1.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](#algs.blas1.iamax-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13965)
*Mandates*: declval<T>() < declval<T>() is a valid expression[.](#algs.blas1.iamax-3.sentence-1)
[4](#algs.blas1.iamax-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13969)
*Returns*:
- [(4.1)](#algs.blas1.iamax-4.1)
numeric_limits<typename InVec::size_type>::max() if v has zero elements;
- [(4.2)](#algs.blas1.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)](#algs.blas1.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[.](#algs.blas1.iamax-4.sentence-1)
#### [29.9.13.12](#algs.blas1.matfrobnorm) Frobenius norm of a matrix [[linalg.algs.blas1.matfrobnorm]](linalg.algs.blas1.matfrobnorm)
[1](#algs.blas1.matfrobnorm-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13991)
[*Note [1](#algs.blas1.matfrobnorm-note-1)*:
These functions exist in the BLAS standard[[bib]](bibliography#bib:blas-std "Bibliography") but are not part of the reference implementation[.](#algs.blas1.matfrobnorm-1.sentence-1)
— *end note*]
[🔗](#lib:matrix_frob_norm)
`template<[in-matrix](#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](#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](#algs.blas1.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>())[.](#algs.blas1.matfrobnorm-2.sentence-1)
Then, decltype(init + a * a) is convertible to Scalar[.](#algs.blas1.matfrobnorm-2.sentence-2)
[3](#algs.blas1.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[.](#algs.blas1.matfrobnorm-3.sentence-1)
[*Note [2](#algs.blas1.matfrobnorm-note-2)*:
For init equal to zero,
this is the Frobenius norm of the matrix A[.](#algs.blas1.matfrobnorm-3.sentence-2)
— *end note*]
[4](#algs.blas1.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[.](#algs.blas1.matfrobnorm-4.sentence-1)
[🔗](#lib:matrix_frob_norm_)
`template<[in-matrix](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat>
auto matrix_frob_norm(InMat A);
template<class ExecutionPolicy, [in-matrix](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat>
auto matrix_frob_norm(ExecutionPolicy&& exec, InMat A);
`
[5](#algs.blas1.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>())[.](#algs.blas1.matfrobnorm-5.sentence-1)
Let T bedecltype(a * a)[.](#algs.blas1.matfrobnorm-5.sentence-2)
Then,
- [(5.1)](#algs.blas1.matfrobnorm-5.1)
the one-parameter overload is equivalent to:return matrix_frob_norm(A, T{}); and
- [(5.2)](#algs.blas1.matfrobnorm-5.2)
the two-parameter overload is equivalent to:return matrix_frob_norm(std::forward<ExecutionPolicy>(exec), A, T{});
#### [29.9.13.13](#algs.blas1.matonenorm) One norm of a matrix [[linalg.algs.blas1.matonenorm]](linalg.algs.blas1.matonenorm)
[1](#algs.blas1.matonenorm-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14065)
[*Note [1](#algs.blas1.matonenorm-note-1)*:
These functions exist in the BLAS standard[[bib]](bibliography#bib:blas-std "Bibliography") but are not part of the reference implementation[.](#algs.blas1.matonenorm-1.sentence-1)
— *end note*]
[🔗](#lib:matrix_one_norm)
`template<[in-matrix](#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](#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](#algs.blas1.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[.](#algs.blas1.matonenorm-2.sentence-1)
[3](#algs.blas1.matonenorm-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14085)
*Returns*:
- [(3.1)](#algs.blas1.matonenorm-3.1)
init if A.extent(1) is zero;
- [(3.2)](#algs.blas1.matonenorm-3.2)
otherwise, the sum of init and the one norm of the matrix A[.](#algs.blas1.matonenorm-3.sentence-1)
[*Note [2](#algs.blas1.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[.](#algs.blas1.matonenorm-3.sentence-2)
— *end note*]
[4](#algs.blas1.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[.](#algs.blas1.matonenorm-4.sentence-1)
[🔗](#lib:matrix_one_norm_)
`template<[in-matrix](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat>
auto matrix_one_norm(InMat A);
template<class ExecutionPolicy, [in-matrix](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat>
auto matrix_one_norm(ExecutionPolicy&& exec, InMat A);
`
[5](#algs.blas1.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>())[.](#algs.blas1.matonenorm-5.sentence-1)
Then,
- [(5.1)](#algs.blas1.matonenorm-5.1)
the one-parameter overload is equivalent to:return matrix_one_norm(A, T{}); and
- [(5.2)](#algs.blas1.matonenorm-5.2)
the two-parameter overload is equivalent to:return matrix_one_norm(std::forward<ExecutionPolicy>(exec), A, T{});
#### [29.9.13.14](#algs.blas1.matinfnorm) Infinity norm of a matrix [[linalg.algs.blas1.matinfnorm]](linalg.algs.blas1.matinfnorm)
[1](#algs.blas1.matinfnorm-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14139)
[*Note [1](#algs.blas1.matinfnorm-note-1)*:
These functions exist in the BLAS standard[[bib]](bibliography#bib:blas-std "Bibliography") but are not part of the reference implementation[.](#algs.blas1.matinfnorm-1.sentence-1)
— *end note*]
[🔗](#lib:matrix_inf_norm)
`template<[in-matrix](#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](#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](#algs.blas1.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[.](#algs.blas1.matinfnorm-2.sentence-1)
[3](#algs.blas1.matinfnorm-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14159)
*Returns*:
- [(3.1)](#algs.blas1.matinfnorm-3.1)
init if A.extent(0) is zero;
- [(3.2)](#algs.blas1.matinfnorm-3.2)
otherwise,
the sum of init and the infinity norm of the matrix A[.](#algs.blas1.matinfnorm-3.sentence-1)
[*Note [2](#algs.blas1.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[.](#algs.blas1.matinfnorm-3.sentence-2)
— *end note*]
[4](#algs.blas1.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[.](#algs.blas1.matinfnorm-4.sentence-1)
[🔗](#lib:matrix_inf_norm_)
`template<[in-matrix](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat>
auto matrix_inf_norm(InMat A);
template<class ExecutionPolicy, [in-matrix](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat>
auto matrix_inf_norm(ExecutionPolicy&& exec, InMat A);
`
[5](#algs.blas1.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>())[.](#algs.blas1.matinfnorm-5.sentence-1)
Then,
- [(5.1)](#algs.blas1.matinfnorm-5.1)
the one-parameter overload is equivalent to:return matrix_inf_norm(A, T{}); and
- [(5.2)](#algs.blas1.matinfnorm-5.2)
the two-parameter overload is equivalent to:return matrix_inf_norm(std::forward<ExecutionPolicy>(exec), A, T{});
### [29.9.14](#algs.blas2) BLAS 2 algorithms [[linalg.algs.blas2]](linalg.algs.blas2)
#### [29.9.14.1](#algs.blas2.gemv) General matrix-vector product [[linalg.algs.blas2.gemv]](linalg.algs.blas2.gemv)
[1](#algs.blas2.gemv-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14218)
[*Note [1](#algs.blas2.gemv-note-1)*:
These functions correspond to the BLAS function xGEMV[.](#algs.blas2.gemv-1.sentence-1)
— *end note*]
[2](#algs.blas2.gemv-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14223)
The following elements apply to all functions in [[linalg.algs.blas2.gemv]](#algs.blas2.gemv "29.9.14.1General matrix-vector product")[.](#algs.blas2.gemv-2.sentence-1)
[3](#algs.blas2.gemv-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14226)
*Mandates*:
- [(3.1)](#algs.blas2.gemv-3.1)
*possibly-multipliable*<decltype(A), decltype(x), decltype(y)>() is true, and
- [(3.2)](#algs.blas2.gemv-3.2)
*possibly-addable*<decltype(x), decltype(y), decltype(z)>() is true for those overloads that take a z parameter[.](#algs.blas2.gemv-3.sentence-1)
[4](#algs.blas2.gemv-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14237)
*Preconditions*:
- [(4.1)](#algs.blas2.gemv-4.1)
*multipliable*(A,x,y) is true, and
- [(4.2)](#algs.blas2.gemv-4.2)
*addable*(x,y,z) is true for those overloads that take a z parameter[.](#algs.blas2.gemv-4.sentence-1)
[5](#algs.blas2.gemv-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14246)
*Complexity*: O(x.extent(0)×A.extent(1))[.](#algs.blas2.gemv-5.sentence-1)
[🔗](#lib:matrix_vector_product)
`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, [out-vector](#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](#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, [out-vector](#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](#algs.blas2.gemv-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14259)
These functions perform an overwriting matrix-vector product[.](#algs.blas2.gemv-6.sentence-1)
[7](#algs.blas2.gemv-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14262)
*Effects*: Computes y=Ax[.](#algs.blas2.gemv-7.sentence-1)
[*Example [1](#algs.blas2.gemv-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](#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]") InVec1, [in-vector](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec2, [out-vector](#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](#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]") InVec1, [in-vector](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec2, [out-vector](#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](#algs.blas2.gemv-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14297)
These functions perform an updating matrix-vector product[.](#algs.blas2.gemv-8.sentence-1)
[9](#algs.blas2.gemv-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14300)
*Effects*: Computes z=y+Ax[.](#algs.blas2.gemv-9.sentence-1)
[10](#algs.blas2.gemv-10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14304)
*Remarks*: z may alias y[.](#algs.blas2.gemv-10.sentence-1)
[*Example [2](#algs.blas2.gemv-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*]
#### [29.9.14.2](#algs.blas2.symv) Symmetric matrix-vector product [[linalg.algs.blas2.symv]](linalg.algs.blas2.symv)
[1](#algs.blas2.symv-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14321)
[*Note [1](#algs.blas2.symv-note-1)*:
These functions correspond to the BLAS functionsxSYMV and xSPMV[[bib]](bibliography#bib:blas2 "Bibliography")[.](#algs.blas2.symv-1.sentence-1)
— *end note*]
[2](#algs.blas2.symv-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14327)
The following elements apply to all functions in [[linalg.algs.blas2.symv]](#algs.blas2.symv "29.9.14.2Symmetric matrix-vector product")[.](#algs.blas2.symv-2.sentence-1)
[3](#algs.blas2.symv-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14330)
*Mandates*:
- [(3.1)](#algs.blas2.symv-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)](#algs.blas2.symv-3.2)
*compatible-static-extents*<decltype(A), decltype(A)>(0, 1) is true;
- [(3.3)](#algs.blas2.symv-3.3)
*possibly-multipliable*<decltype(A), decltype(x), decltype(y)>() is true; and
- [(3.4)](#algs.blas2.symv-3.4)
*possibly-addable*<decltype(x), decltype(y), decltype(z)>() is true for those overloads that take a z parameter[.](#algs.blas2.symv-3.sentence-1)
[4](#algs.blas2.symv-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14347)
*Preconditions*:
- [(4.1)](#algs.blas2.symv-4.1)
A.extent(0) equals A.extent(1),
- [(4.2)](#algs.blas2.symv-4.2)
*multipliable*(A,x,y) is true, and
- [(4.3)](#algs.blas2.symv-4.3)
*addable*(x,y,z) is true for those overloads that take a z parameter[.](#algs.blas2.symv-4.sentence-1)
[5](#algs.blas2.symv-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14359)
*Complexity*: O(x.extent(0)×A.extent(1))[.](#algs.blas2.symv-5.sentence-1)
[🔗](#lib:symmetric_matrix_vector_product)
`template<[in-matrix](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, [in-vector](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec, [out-vector](#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](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, [in-vector](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec, [out-vector](#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](#algs.blas2.symv-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]](#general "29.9.3General"))[.](#algs.blas2.symv-6.sentence-1)
[7](#algs.blas2.symv-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14380)
*Effects*: Computes y=Ax[.](#algs.blas2.symv-7.sentence-1)
[🔗](#lib:symmetric_matrix_vector_product_)
`template<[in-matrix](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, [in-vector](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec1, [in-vector](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec2, [out-vector](#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](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, [in-vector](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec1, [in-vector](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec2, [out-vector](#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](#algs.blas2.symv-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]](#general "29.9.3General"))[.](#algs.blas2.symv-8.sentence-1)
[9](#algs.blas2.symv-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14401)
*Effects*: Computes z=y+Ax[.](#algs.blas2.symv-9.sentence-1)
[10](#algs.blas2.symv-10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14405)
*Remarks*: z may alias y[.](#algs.blas2.symv-10.sentence-1)
#### [29.9.14.3](#algs.blas2.hemv) Hermitian matrix-vector product [[linalg.algs.blas2.hemv]](linalg.algs.blas2.hemv)
[1](#algs.blas2.hemv-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14412)
[*Note [1](#algs.blas2.hemv-note-1)*:
These functions correspond to the BLAS functionsxHEMV and xHPMV[[bib]](bibliography#bib:blas2 "Bibliography")[.](#algs.blas2.hemv-1.sentence-1)
— *end note*]
[2](#algs.blas2.hemv-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14418)
The following elements apply to all functions in [[linalg.algs.blas2.hemv]](#algs.blas2.hemv "29.9.14.3Hermitian matrix-vector product")[.](#algs.blas2.hemv-2.sentence-1)
[3](#algs.blas2.hemv-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14421)
*Mandates*:
- [(3.1)](#algs.blas2.hemv-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)](#algs.blas2.hemv-3.2)
*compatible-static-extents*<decltype(A), decltype(A)>(0, 1) is true;
- [(3.3)](#algs.blas2.hemv-3.3)
*possibly-multipliable*<decltype(A), decltype(x), decltype(y)>() is true; and
- [(3.4)](#algs.blas2.hemv-3.4)
*possibly-addable*<decltype(x), decltype(y), decltype(z)>() is true for those overloads that take a z parameter[.](#algs.blas2.hemv-3.sentence-1)
[4](#algs.blas2.hemv-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14439)
*Preconditions*:
- [(4.1)](#algs.blas2.hemv-4.1)
A.extent(0) equals A.extent(1),
- [(4.2)](#algs.blas2.hemv-4.2)
*multipliable*(A, x, y) is true, and
- [(4.3)](#algs.blas2.hemv-4.3)
*addable*(x, y, z) is true for those overloads that take a z parameter[.](#algs.blas2.hemv-4.sentence-1)
[5](#algs.blas2.hemv-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14450)
*Complexity*: O(x.extent(0)×A.extent(1))[.](#algs.blas2.hemv-5.sentence-1)
[🔗](#lib:hermitian_matrix_vector_product)
`template<[in-matrix](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, [in-vector](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec, [out-vector](#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](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, [in-vector](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec, [out-vector](#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](#algs.blas2.hemv-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]](#general "29.9.3General"))[.](#algs.blas2.hemv-6.sentence-1)
[7](#algs.blas2.hemv-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14470)
*Effects*: Computes y=Ax[.](#algs.blas2.hemv-7.sentence-1)
[🔗](#lib:hermitian_matrix_vector_product_)
`template<[in-matrix](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, [in-vector](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec1, [in-vector](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec2, [out-vector](#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](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, [in-vector](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec1, [in-vector](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec2, [out-vector](#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](#algs.blas2.hemv-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]](#general "29.9.3General"))[.](#algs.blas2.hemv-8.sentence-1)
[9](#algs.blas2.hemv-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14491)
*Effects*: Computes z=y+Ax[.](#algs.blas2.hemv-9.sentence-1)
[10](#algs.blas2.hemv-10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14495)
*Remarks*: z may alias y[.](#algs.blas2.hemv-10.sentence-1)
#### [29.9.14.4](#algs.blas2.trmv) Triangular matrix-vector product [[linalg.algs.blas2.trmv]](linalg.algs.blas2.trmv)
[1](#algs.blas2.trmv-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14502)
[*Note [1](#algs.blas2.trmv-note-1)*:
These functions correspond to the BLAS functionsxTRMV and xTPMV[[bib]](bibliography#bib:blas2 "Bibliography")[.](#algs.blas2.trmv-1.sentence-1)
— *end note*]
[2](#algs.blas2.trmv-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14508)
The following elements apply to all functions in [[linalg.algs.blas2.trmv]](#algs.blas2.trmv "29.9.14.4Triangular matrix-vector product")[.](#algs.blas2.trmv-2.sentence-1)
[3](#algs.blas2.trmv-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14511)
*Mandates*:
- [(3.1)](#algs.blas2.trmv-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)](#algs.blas2.trmv-3.2)
*compatible-static-extents*<decltype(A), decltype(A)>(0, 1) is true;
- [(3.3)](#algs.blas2.trmv-3.3)
*compatible-static-extents*<decltype(A), decltype(y)>(0, 0) is true;
- [(3.4)](#algs.blas2.trmv-3.4)
*compatible-static-extents*<decltype(A), decltype(x)>(0, 0) is true for those overloads that take an x parameter; and
- [(3.5)](#algs.blas2.trmv-3.5)
*compatible-static-extents*<decltype(A), decltype(z)>(0, 0) is true for those overloads that take a z parameter[.](#algs.blas2.trmv-3.sentence-1)
[4](#algs.blas2.trmv-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14532)
*Preconditions*:
- [(4.1)](#algs.blas2.trmv-4.1)
A.extent(0) equals A.extent(1),
- [(4.2)](#algs.blas2.trmv-4.2)
A.extent(0) equals y.extent(0),
- [(4.3)](#algs.blas2.trmv-4.3)
A.extent(0) equals x.extent(0) for those overloads that take an x parameter, and
- [(4.4)](#algs.blas2.trmv-4.4)
A.extent(0) equals z.extent(0) for those overloads that take a z parameter[.](#algs.blas2.trmv-4.sentence-1)
[🔗](#lib:triangular_matrix_vector_product)
`template<[in-matrix](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage, [in-vector](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec,
[out-vector](#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](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage, [in-vector](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec,
[out-vector](#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](#algs.blas2.trmv-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]](#general "29.9.3General"))[.](#algs.blas2.trmv-5.sentence-1)
[6](#algs.blas2.trmv-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14565)
*Effects*: Computes y=Ax[.](#algs.blas2.trmv-6.sentence-1)
[7](#algs.blas2.trmv-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14569)
*Complexity*: O(x.extent(0)×A.extent(1))[.](#algs.blas2.trmv-7.sentence-1)
[🔗](#lib:triangular_matrix_vector_product_)
`template<[in-matrix](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage, [inout-vector](#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](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage, [inout-vector](#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](#algs.blas2.trmv-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]](#general "29.9.3General"))[.](#algs.blas2.trmv-8.sentence-1)
[*Note [2](#algs.blas2.trmv-note-2)*:
Performing this operation in place hinders parallelization[.](#algs.blas2.trmv-8.sentence-2)
However, other ExecutionPolicy specific optimizations,
such as vectorization, are still possible[.](#algs.blas2.trmv-8.sentence-3)
— *end note*]
[9](#algs.blas2.trmv-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[.](#algs.blas2.trmv-9.sentence-1)
[10](#algs.blas2.trmv-10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14601)
*Complexity*: O(y.extent(0)×A.extent(1))[.](#algs.blas2.trmv-10.sentence-1)
[🔗](#lib:triangular_matrix_vector_product__)
`template<[in-matrix](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage,
[in-vector](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec1, [in-vector](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec2, [out-vector](#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](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage,
[in-vector](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec1, [in-vector](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec2, [out-vector](#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](#algs.blas2.trmv-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]](#general "29.9.3General"))[.](#algs.blas2.trmv-11.sentence-1)
[12](#algs.blas2.trmv-12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14625)
*Effects*: Computes z=y+Ax[.](#algs.blas2.trmv-12.sentence-1)
[13](#algs.blas2.trmv-13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14629)
*Complexity*: O(x.extent(0)×A.extent(1))[.](#algs.blas2.trmv-13.sentence-1)
[14](#algs.blas2.trmv-14)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14633)
*Remarks*: z may alias y[.](#algs.blas2.trmv-14.sentence-1)
#### [29.9.14.5](#algs.blas2.trsv) Solve a triangular linear system [[linalg.algs.blas2.trsv]](linalg.algs.blas2.trsv)
[1](#algs.blas2.trsv-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14640)
[*Note [1](#algs.blas2.trsv-note-1)*:
These functions correspond to the BLAS functionsxTRSV and xTPSV[[bib]](bibliography#bib:blas2 "Bibliography")[.](#algs.blas2.trsv-1.sentence-1)
— *end note*]
[2](#algs.blas2.trsv-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14646)
The following elements apply to all functions in [[linalg.algs.blas2.trsv]](#algs.blas2.trsv "29.9.14.5Solve a triangular linear system")[.](#algs.blas2.trsv-2.sentence-1)
[3](#algs.blas2.trsv-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14649)
*Mandates*:
- [(3.1)](#algs.blas2.trsv-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)](#algs.blas2.trsv-3.2)
*compatible-static-extents*<decltype(A), decltype(A)>(0, 1) is true;
- [(3.3)](#algs.blas2.trsv-3.3)
*compatible-static-extents*<decltype(A), decltype(b)>(0, 0) is true; and
- [(3.4)](#algs.blas2.trsv-3.4)
*compatible-static-extents*<decltype(A), decltype(x)>(0, 0) is true for those overloads that take an x parameter[.](#algs.blas2.trsv-3.sentence-1)
[4](#algs.blas2.trsv-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14667)
*Preconditions*:
- [(4.1)](#algs.blas2.trsv-4.1)
A.extent(0) equals A.extent(1),
- [(4.2)](#algs.blas2.trsv-4.2)
A.extent(0) equals b.extent(0), and
- [(4.3)](#algs.blas2.trsv-4.3)
A.extent(0) equals x.extent(0) for those overloads that take an x parameter[.](#algs.blas2.trsv-4.sentence-1)
[🔗](#lib:triangular_matrix_vector_solve)
` template<[in-matrix](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage,
[in-vector](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec, [out-vector](#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](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage,
[in-vector](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec, [out-vector](#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](#algs.blas2.trsv-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]](#general "29.9.3General"))[.](#algs.blas2.trsv-5.sentence-1)
[6](#algs.blas2.trsv-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[.](#algs.blas2.trsv-6.sentence-1)
If no such x′ exists,
then the elements of x are valid but unspecified[.](#algs.blas2.trsv-6.sentence-2)
[7](#algs.blas2.trsv-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14707)
*Complexity*: O(A.extent(1)×b.extent(0))[.](#algs.blas2.trsv-7.sentence-1)
[🔗](#lib:triangular_matrix_vector_solve_)
`template<[in-matrix](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage,
[in-vector](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec, [out-vector](#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](#algs.blas2.trsv-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](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage,
[in-vector](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec, [out-vector](#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](#algs.blas2.trsv-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](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage,
[inout-vector](#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](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage,
[inout-vector](#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](#algs.blas2.trsv-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]](#general "29.9.3General"))[.](#algs.blas2.trsv-10.sentence-1)
[*Note [2](#algs.blas2.trsv-note-2)*:
Performing triangular solve in place hinders parallelization[.](#algs.blas2.trsv-10.sentence-2)
However, other ExecutionPolicy specific optimizations,
such as vectorization, are still possible[.](#algs.blas2.trsv-10.sentence-3)
— *end note*]
[11](#algs.blas2.trsv-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[.](#algs.blas2.trsv-11.sentence-1)
If no such x′ exists,
then the elements of b are valid but unspecified[.](#algs.blas2.trsv-11.sentence-2)
[12](#algs.blas2.trsv-12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14777)
*Complexity*: O(A.extent(1)×b.extent(0))[.](#algs.blas2.trsv-12.sentence-1)
[🔗](#lib:triangular_matrix_vector_solve____)
`template<[in-matrix](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage, [inout-vector](#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](#algs.blas2.trsv-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](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage, [inout-vector](#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](#algs.blas2.trsv-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>{});
#### [29.9.14.6](#algs.blas2.rank1) Rank-1 (outer product) update of a matrix [[linalg.algs.blas2.rank1]](linalg.algs.blas2.rank1)
[🔗](#lib:matrix_rank_1_update)
`template<[in-vector](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec1, [in-vector](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec2, [inout-matrix](#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](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec1, [in-vector](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec2, [inout-matrix](#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](#algs.blas2.rank1-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14826)
These functions perform a nonsymmetric nonconjugated rank-1 update[.](#algs.blas2.rank1-1.sentence-1)
[*Note [1](#algs.blas2.rank1-note-1)*:
These functions correspond to the BLAS functionsxGER (for real element types) andxGERU (for complex element types)[[bib]](bibliography#bib:blas2 "Bibliography")[.](#algs.blas2.rank1-1.sentence-2)
— *end note*]
[2](#algs.blas2.rank1-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14834)
*Mandates*: *possibly-multipliable*<InOutMat, InVec2, InVec1>() is true[.](#algs.blas2.rank1-2.sentence-1)
[3](#algs.blas2.rank1-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14839)
*Preconditions*: *multipliable*(A, y, x) is true[.](#algs.blas2.rank1-3.sentence-1)
[4](#algs.blas2.rank1-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[.](#algs.blas2.rank1-4.sentence-1)
[5](#algs.blas2.rank1-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14848)
*Complexity*: O(x.extent(0)×y.extent(0))[.](#algs.blas2.rank1-5.sentence-1)
[🔗](#lib:matrix_rank_1_update_)
`template<[in-vector](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec1, [in-vector](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec2, [inout-matrix](#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](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec1, [in-vector](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec2, [inout-matrix](#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](#algs.blas2.rank1-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14862)
These functions perform a nonsymmetric conjugated rank-1 update[.](#algs.blas2.rank1-6.sentence-1)
[*Note [2](#algs.blas2.rank1-note-2)*:
These functions correspond to the BLAS functionsxGER (for real element types) andxGERC (for complex element types)[[bib]](bibliography#bib:blas2 "Bibliography")[.](#algs.blas2.rank1-6.sentence-2)
— *end note*]
[7](#algs.blas2.rank1-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14870)
*Effects*:
- [(7.1)](#algs.blas2.rank1-7.1)
For the overloads without an ExecutionPolicy argument,
equivalent to:matrix_rank_1_update(x, conjugated(y), A);
- [(7.2)](#algs.blas2.rank1-7.2)
otherwise, equivalent to:matrix_rank_1_update(std::forward<ExecutionPolicy>(exec), x, conjugated(y), A);
#### [29.9.14.7](#algs.blas2.symherrank1) Symmetric or Hermitian Rank-1 (outer product) update of a matrix [[linalg.algs.blas2.symherrank1]](linalg.algs.blas2.symherrank1)
[1](#algs.blas2.symherrank1-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14889)
[*Note [1](#algs.blas2.symherrank1-note-1)*:
These functions correspond to the BLAS functionsxSYR, xSPR, xHER, and xHPR[[bib]](bibliography#bib:blas2 "Bibliography")[.](#algs.blas2.symherrank1-1.sentence-1)
They have overloads taking a scaling factor alpha,
because it would be impossible to express the updateA=A−xxT otherwise[.](#algs.blas2.symherrank1-1.sentence-2)
— *end note*]
[2](#algs.blas2.symherrank1-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14898)
The following elements apply to all functions in [[linalg.algs.blas2.symherrank1]](#algs.blas2.symherrank1 "29.9.14.7Symmetric or Hermitian Rank-1 (outer product) update of a matrix")[.](#algs.blas2.symherrank1-2.sentence-1)
[3](#algs.blas2.symherrank1-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14901)
*Mandates*:
- [(3.1)](#algs.blas2.symherrank1-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)](#algs.blas2.symherrank1-3.2)
*compatible-static-extents*<decltype(A), decltype(A)>(0, 1) is true; and
- [(3.3)](#algs.blas2.symherrank1-3.3)
*compatible-static-extents*<decltype(A), decltype(x)>(0, 0) is true[.](#algs.blas2.symherrank1-3.sentence-1)
[4](#algs.blas2.symherrank1-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14916)
*Preconditions*:
- [(4.1)](#algs.blas2.symherrank1-4.1)
A.extent(0) equals A.extent(1), and
- [(4.2)](#algs.blas2.symherrank1-4.2)
A.extent(0) equals x.extent(0)[.](#algs.blas2.symherrank1-4.sentence-1)
[5](#algs.blas2.symherrank1-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L14925)
*Complexity*: O(x.extent(0)×x.extent(0))[.](#algs.blas2.symherrank1-5.sentence-1)
[🔗](#lib:symmetric_matrix_rank_1_update)
`template<class Scalar, [in-vector](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec, [possibly-packed-inout-matrix](#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](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec, [possibly-packed-inout-matrix](#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](#algs.blas2.symherrank1-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]](#general "29.9.3General"))[.](#algs.blas2.symherrank1-6.sentence-1)
[7](#algs.blas2.symherrank1-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[.](#algs.blas2.symherrank1-7.sentence-1)
[🔗](#lib:symmetric_matrix_rank_1_update_)
`template<[in-vector](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec, [possibly-packed-inout-matrix](#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](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec, [possibly-packed-inout-matrix](#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](#algs.blas2.symherrank1-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]](#general "29.9.3General"))[.](#algs.blas2.symherrank1-8.sentence-1)
[9](#algs.blas2.symherrank1-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[.](#algs.blas2.symherrank1-9.sentence-1)
[🔗](#lib:hermitian_matrix_rank_1_update)
`template<class Scalar, [in-vector](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec, [possibly-packed-inout-matrix](#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](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec, [possibly-packed-inout-matrix](#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](#algs.blas2.symherrank1-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]](#general "29.9.3General"))[.](#algs.blas2.symherrank1-10.sentence-1)
[11](#algs.blas2.symherrank1-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[.](#algs.blas2.symherrank1-11.sentence-1)
[🔗](#lib:hermitian_matrix_rank_1_update_)
`template<[in-vector](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec, [possibly-packed-inout-matrix](#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](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec, [possibly-packed-inout-matrix](#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](#algs.blas2.symherrank1-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]](#general "29.9.3General"))[.](#algs.blas2.symherrank1-12.sentence-1)
[13](#algs.blas2.symherrank1-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[.](#algs.blas2.symherrank1-13.sentence-1)
#### [29.9.14.8](#algs.blas2.rank2) Symmetric and Hermitian rank-2 matrix updates [[linalg.algs.blas2.rank2]](linalg.algs.blas2.rank2)
[1](#algs.blas2.rank2-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15023)
[*Note [1](#algs.blas2.rank2-note-1)*:
These functions correspond to the BLAS functionsxSYR2,xSPR2, xHER2 and xHPR2[[bib]](bibliography#bib:blas2 "Bibliography")[.](#algs.blas2.rank2-1.sentence-1)
— *end note*]
[2](#algs.blas2.rank2-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15029)
The following elements apply to all functions in [[linalg.algs.blas2.rank2]](#algs.blas2.rank2 "29.9.14.8Symmetric and Hermitian rank-2 matrix updates")[.](#algs.blas2.rank2-2.sentence-1)
[3](#algs.blas2.rank2-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15032)
*Mandates*:
- [(3.1)](#algs.blas2.rank2-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)](#algs.blas2.rank2-3.2)
*compatible-static-extents*<decltype(A), decltype(A)>(0, 1) is true; and
- [(3.3)](#algs.blas2.rank2-3.3)
*possibly-multipliable*<decltype(A), decltype(x), decltype(y)>() is true[.](#algs.blas2.rank2-3.sentence-1)
[4](#algs.blas2.rank2-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15047)
*Preconditions*:
- [(4.1)](#algs.blas2.rank2-4.1)
A.extent(0) equals A.extent(1), and
- [(4.2)](#algs.blas2.rank2-4.2)
*multipliable*(A, x, y) is true[.](#algs.blas2.rank2-4.sentence-1)
[5](#algs.blas2.rank2-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15056)
*Complexity*: O(x.extent(0)×y.extent(0))[.](#algs.blas2.rank2-5.sentence-1)
[🔗](#lib:symmetric_matrix_rank_2_update)
`template<[in-vector](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec1, [in-vector](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec2,
[possibly-packed-inout-matrix](#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](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec1, [in-vector](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec2,
[possibly-packed-inout-matrix](#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](#algs.blas2.rank2-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]](#general "29.9.3General"))[.](#algs.blas2.rank2-6.sentence-1)
[7](#algs.blas2.rank2-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[.](#algs.blas2.rank2-7.sentence-1)
[🔗](#lib:hermitian_matrix_rank_2_update)
`template<[in-vector](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec1, [in-vector](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec2,
[possibly-packed-inout-matrix](#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](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec1, [in-vector](#concept:in-vector "29.9.7.5Argument concepts[linalg.helpers.concepts]") InVec2,
[possibly-packed-inout-matrix](#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](#algs.blas2.rank2-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]](#general "29.9.3General"))[.](#algs.blas2.rank2-8.sentence-1)
[9](#algs.blas2.rank2-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[.](#algs.blas2.rank2-9.sentence-1)
### [29.9.15](#algs.blas3) BLAS 3 algorithms [[linalg.algs.blas3]](linalg.algs.blas3)
#### [29.9.15.1](#algs.blas3.gemm) General matrix-matrix product [[linalg.algs.blas3.gemm]](linalg.algs.blas3.gemm)
[1](#algs.blas3.gemm-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15112)
[*Note [1](#algs.blas3.gemm-note-1)*:
These functions correspond to the BLAS function xGEMM[[bib]](bibliography#bib:blas3 "Bibliography")[.](#algs.blas3.gemm-1.sentence-1)
— *end note*]
[2](#algs.blas3.gemm-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15117)
The following elements apply
to all functions in [[linalg.algs.blas3.gemm]](#algs.blas3.gemm "29.9.15.1General matrix-matrix product") in addition to function-specific elements[.](#algs.blas3.gemm-2.sentence-1)
[3](#algs.blas3.gemm-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15122)
*Mandates*: *possibly-multipliable*<decltype(A), decltype(B), decltype(C)>() is true[.](#algs.blas3.gemm-3.sentence-1)
[4](#algs.blas3.gemm-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15127)
*Preconditions*: *multipliable*(A, B, C) is true[.](#algs.blas3.gemm-4.sentence-1)
[5](#algs.blas3.gemm-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15131)
*Complexity*: O(A.extent(0)×A.extent(1)×B.extent(1))[.](#algs.blas3.gemm-5.sentence-1)
[🔗](#lib:matrix_product)
` 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, [out-matrix](#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](#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, [out-matrix](#concept:out-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") OutMat>
void matrix_product(ExecutionPolicy&& exec, InMat1 A, InMat2 B, OutMat C);
`
[6](#algs.blas3.gemm-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15144)
*Effects*: Computes C=AB[.](#algs.blas3.gemm-6.sentence-1)
[🔗](#lib:matrix_product_)
`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]") InMat3, [out-matrix](#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](#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]") InMat3, [out-matrix](#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](#algs.blas3.gemm-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15159)
*Mandates*: *possibly-addable*<InMat3, InMat3, OutMat>() is true[.](#algs.blas3.gemm-7.sentence-1)
[8](#algs.blas3.gemm-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15163)
*Preconditions*: *addable*(E, E, C) is true[.](#algs.blas3.gemm-8.sentence-1)
[9](#algs.blas3.gemm-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15167)
*Effects*: Computes C=E+AB[.](#algs.blas3.gemm-9.sentence-1)
[10](#algs.blas3.gemm-10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15171)
*Remarks*: C may alias E[.](#algs.blas3.gemm-10.sentence-1)
#### [29.9.15.2](#algs.blas3.xxmm) Symmetric, Hermitian, and triangular matrix-matrix product [[linalg.algs.blas3.xxmm]](linalg.algs.blas3.xxmm)
[1](#algs.blas3.xxmm-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15178)
[*Note [1](#algs.blas3.xxmm-note-1)*:
These functions correspond to the BLAS functionsxSYMM, xHEMM, and xTRMM[[bib]](bibliography#bib:blas3 "Bibliography")[.](#algs.blas3.xxmm-1.sentence-1)
— *end note*]
[2](#algs.blas3.xxmm-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15184)
The following elements apply to all functions in [[linalg.algs.blas3.xxmm]](#algs.blas3.xxmm "29.9.15.2Symmetric, Hermitian, and triangular matrix-matrix product") in addition to function-specific elements[.](#algs.blas3.xxmm-2.sentence-1)
[3](#algs.blas3.xxmm-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15188)
*Mandates*:
- [(3.1)](#algs.blas3.xxmm-3.1)
*possibly-multipliable*<decltype(A), decltype(B), decltype(C)>() is true, and
- [(3.2)](#algs.blas3.xxmm-3.2)
*possibly-addable*<decltype(E), decltype(E), decltype(C)>() is true for those overloads that take an E parameter[.](#algs.blas3.xxmm-3.sentence-1)
[4](#algs.blas3.xxmm-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15199)
*Preconditions*:
- [(4.1)](#algs.blas3.xxmm-4.1)
*multipliable*(A, B, C) is true, and
- [(4.2)](#algs.blas3.xxmm-4.2)
*addable*(E, E, C) is true for those overloads that take an E parameter[.](#algs.blas3.xxmm-4.sentence-1)
[5](#algs.blas3.xxmm-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15209)
*Complexity*: O(A.extent(0)×A.extent(1)×B.extent(1))[.](#algs.blas3.xxmm-5.sentence-1)
[🔗](#lib:symmetric_matrix_product)
`template<[in-matrix](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat1, class Triangle, [in-matrix](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat2, [out-matrix](#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](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat1, class Triangle, [in-matrix](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat2, [out-matrix](#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](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat1, class Triangle, [in-matrix](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat2, [out-matrix](#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](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat1, class Triangle, [in-matrix](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat2, [out-matrix](#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](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat1, class Triangle, class DiagonalStorage,
[in-matrix](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat2, [out-matrix](#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](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat1, class Triangle, class DiagonalStorage,
[in-matrix](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat2, [out-matrix](#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](#algs.blas3.xxmm-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]](#general "29.9.3General"))[.](#algs.blas3.xxmm-6.sentence-1)
[7](#algs.blas3.xxmm-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15243)
*Mandates*:
- [(7.1)](#algs.blas3.xxmm-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)](#algs.blas3.xxmm-7.2)
*compatible-static-extents*<InMat1, InMat1>(0, 1) is true[.](#algs.blas3.xxmm-7.sentence-1)
[8](#algs.blas3.xxmm-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15254)
*Preconditions*: A.extent(0) == A.extent(1) is true[.](#algs.blas3.xxmm-8.sentence-1)
[9](#algs.blas3.xxmm-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15258)
*Effects*: Computes C=AB[.](#algs.blas3.xxmm-9.sentence-1)
[🔗](#lib:symmetric_matrix_product_)
` 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, class Triangle, [out-matrix](#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](#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, class Triangle, [out-matrix](#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](#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, class Triangle, [out-matrix](#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](#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, class Triangle, [out-matrix](#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](#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, class Triangle, class DiagonalStorage,
[out-matrix](#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](#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, class Triangle, class DiagonalStorage,
[out-matrix](#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](#algs.blas3.xxmm-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]](#general "29.9.3General"))[.](#algs.blas3.xxmm-10.sentence-1)
[11](#algs.blas3.xxmm-11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15296)
*Mandates*:
- [(11.1)](#algs.blas3.xxmm-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)](#algs.blas3.xxmm-11.2)
*compatible-static-extents*<InMat2, InMat2>(0, 1) is true[.](#algs.blas3.xxmm-11.sentence-1)
[12](#algs.blas3.xxmm-12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15307)
*Preconditions*: B.extent(0) == B.extent(1) is true[.](#algs.blas3.xxmm-12.sentence-1)
[13](#algs.blas3.xxmm-13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15311)
*Effects*: Computes C=AB[.](#algs.blas3.xxmm-13.sentence-1)
[🔗](#lib:symmetric_matrix_product__)
`template<[in-matrix](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat1, class Triangle, [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]") InMat3,
[out-matrix](#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](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat1, class Triangle, [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]") InMat3,
[out-matrix](#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](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat1, class Triangle, [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]") InMat3,
[out-matrix](#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](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat1, class Triangle, [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]") InMat3,
[out-matrix](#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](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat1, class Triangle, class DiagonalStorage,
[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]") InMat3, [out-matrix](#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](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat1, class Triangle, class DiagonalStorage,
[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]") InMat3, [out-matrix](#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](#algs.blas3.xxmm-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]](#general "29.9.3General"))[.](#algs.blas3.xxmm-14.sentence-1)
[15](#algs.blas3.xxmm-15)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15355)
*Mandates*:
- [(15.1)](#algs.blas3.xxmm-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)](#algs.blas3.xxmm-15.2)
*compatible-static-extents*<InMat1, InMat1>(0, 1) is true[.](#algs.blas3.xxmm-15.sentence-1)
[16](#algs.blas3.xxmm-16)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15366)
*Preconditions*: A.extent(0) == A.extent(1) is true[.](#algs.blas3.xxmm-16.sentence-1)
[17](#algs.blas3.xxmm-17)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15370)
*Effects*: Computes C=E+AB[.](#algs.blas3.xxmm-17.sentence-1)
[18](#algs.blas3.xxmm-18)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15374)
*Remarks*: C may alias E[.](#algs.blas3.xxmm-18.sentence-1)
[🔗](#lib:symmetric_matrix_product___)
`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, class Triangle, [in-matrix](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat3,
[out-matrix](#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](#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, class Triangle, [in-matrix](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat3,
[out-matrix](#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](#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, class Triangle, [in-matrix](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat3,
[out-matrix](#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](#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, class Triangle, [in-matrix](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat3,
[out-matrix](#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](#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, class Triangle, class DiagonalStorage,
[in-matrix](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat3, [out-matrix](#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](#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, class Triangle, class DiagonalStorage,
[in-matrix](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat3, [out-matrix](#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](#algs.blas3.xxmm-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]](#general "29.9.3General"))[.](#algs.blas3.xxmm-19.sentence-1)
[20](#algs.blas3.xxmm-20)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15419)
*Mandates*:
- [(20.1)](#algs.blas3.xxmm-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)](#algs.blas3.xxmm-20.2)
*compatible-static-extents*<InMat2, InMat2>(0, 1) is true[.](#algs.blas3.xxmm-20.sentence-1)
[21](#algs.blas3.xxmm-21)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15430)
*Preconditions*: B.extent(0) == B.extent(1) is true[.](#algs.blas3.xxmm-21.sentence-1)
[22](#algs.blas3.xxmm-22)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15434)
*Effects*: Computes C=E+AB[.](#algs.blas3.xxmm-22.sentence-1)
[23](#algs.blas3.xxmm-23)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15438)
*Remarks*: C may alias E[.](#algs.blas3.xxmm-23.sentence-1)
#### [29.9.15.3](#algs.blas3.trmm) In-place triangular matrix-matrix product [[linalg.algs.blas3.trmm]](linalg.algs.blas3.trmm)
[1](#algs.blas3.trmm-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]](#general "29.9.3General"))[.](#algs.blas3.trmm-1.sentence-1)
[*Note [1](#algs.blas3.trmm-note-1)*:
These functions correspond to the BLAS function xTRMM[[bib]](bibliography#bib:blas3 "Bibliography")[.](#algs.blas3.trmm-1.sentence-2)
— *end note*]
[🔗](#lib:triangular_matrix_product)
`template<[in-matrix](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage, [inout-matrix](#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](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage, [inout-matrix](#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](#algs.blas3.trmm-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15466)
*Mandates*:
- [(2.1)](#algs.blas3.trmm-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)](#algs.blas3.trmm-2.2)
*possibly-multipliable*<InMat, InOutMat, InOutMat>() is true; and
- [(2.3)](#algs.blas3.trmm-2.3)
*compatible-static-extents*<InMat, InMat>(0, 1) is true[.](#algs.blas3.trmm-2.sentence-1)
[3](#algs.blas3.trmm-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15480)
*Preconditions*:
- [(3.1)](#algs.blas3.trmm-3.1)
*multipliable*(A, C, C) is true, and
- [(3.2)](#algs.blas3.trmm-3.2)
A.extent(0) == A.extent(1) is true[.](#algs.blas3.trmm-3.sentence-1)
[4](#algs.blas3.trmm-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[.](#algs.blas3.trmm-4.sentence-1)
[5](#algs.blas3.trmm-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15494)
*Complexity*: O(A.extent(0)×A.extent(1)×C.extent(0))[.](#algs.blas3.trmm-5.sentence-1)
[🔗](#lib:triangular_matrix_right_product)
`template<[in-matrix](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage, [inout-matrix](#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](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage, [inout-matrix](#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](#algs.blas3.trmm-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15510)
*Mandates*:
- [(6.1)](#algs.blas3.trmm-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)](#algs.blas3.trmm-6.2)
*possibly-multipliable*<InOutMat, InMat, InOutMat>() is true; and
- [(6.3)](#algs.blas3.trmm-6.3)
*compatible-static-extents*<InMat, InMat>(0, 1) is true[.](#algs.blas3.trmm-6.sentence-1)
[7](#algs.blas3.trmm-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15524)
*Preconditions*:
- [(7.1)](#algs.blas3.trmm-7.1)
*multipliable*(C, A, C) is true, and
- [(7.2)](#algs.blas3.trmm-7.2)
A.extent(0) == A.extent(1) is true[.](#algs.blas3.trmm-7.sentence-1)
[8](#algs.blas3.trmm-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[.](#algs.blas3.trmm-8.sentence-1)
[9](#algs.blas3.trmm-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15538)
*Complexity*: O(A.extent(0)×A.extent(1)×C.extent(0))[.](#algs.blas3.trmm-9.sentence-1)
#### [29.9.15.4](#algs.blas3.rankk) Rank-k update of a symmetric or Hermitian matrix [[linalg.algs.blas3.rankk]](linalg.algs.blas3.rankk)
[1](#algs.blas3.rankk-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15545)
[*Note [1](#algs.blas3.rankk-note-1)*:
These functions correspond to the BLAS functionsxSYRK and xHERK[[bib]](bibliography#bib:blas3 "Bibliography")[.](#algs.blas3.rankk-1.sentence-1)
— *end note*]
[2](#algs.blas3.rankk-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15551)
The following elements apply to all functions in [[linalg.algs.blas3.rankk]](#algs.blas3.rankk "29.9.15.4Rank-k update of a symmetric or Hermitian matrix")[.](#algs.blas3.rankk-2.sentence-1)
[3](#algs.blas3.rankk-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15554)
*Mandates*:
- [(3.1)](#algs.blas3.rankk-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)](#algs.blas3.rankk-3.2)
*compatible-static-extents*<decltype(A), decltype(A)>(0, 1) is true;
- [(3.3)](#algs.blas3.rankk-3.3)
*compatible-static-extents*<decltype(C), decltype(C)>(0, 1) is true; and
- [(3.4)](#algs.blas3.rankk-3.4)
*compatible-static-extents*<decltype(A), decltype(C)>(0, 0) is true[.](#algs.blas3.rankk-3.sentence-1)
[4](#algs.blas3.rankk-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15572)
*Preconditions*:
- [(4.1)](#algs.blas3.rankk-4.1)
A.extent(0) equals A.extent(1),
- [(4.2)](#algs.blas3.rankk-4.2)
C.extent(0) equals C.extent(1), and
- [(4.3)](#algs.blas3.rankk-4.3)
A.extent(0) equals C.extent(0)[.](#algs.blas3.rankk-4.sentence-1)
[5](#algs.blas3.rankk-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15583)
*Complexity*: O(A.extent(0)×A.extent(1)×C.extent(0))[.](#algs.blas3.rankk-5.sentence-1)
[🔗](#lib:symmetric_matrix_rank_k_update)
` template<class Scalar, [in-matrix](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, [possibly-packed-inout-matrix](#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](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, [possibly-packed-inout-matrix](#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](#algs.blas3.rankk-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[.](#algs.blas3.rankk-6.sentence-1)
[🔗](#lib:symmetric_matrix_rank_k_update_)
`template<[in-matrix](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, [possibly-packed-inout-matrix](#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](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, [possibly-packed-inout-matrix](#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](#algs.blas3.rankk-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[.](#algs.blas3.rankk-7.sentence-1)
[🔗](#lib:hermitian_matrix_rank_k_update)
`template<class Scalar, [in-matrix](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, [possibly-packed-inout-matrix](#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](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, [possibly-packed-inout-matrix](#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](#algs.blas3.rankk-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[.](#algs.blas3.rankk-8.sentence-1)
[🔗](#lib:hermitian_matrix_rank_k_update_)
`template<[in-matrix](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, [possibly-packed-inout-matrix](#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](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, [possibly-packed-inout-matrix](#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](#algs.blas3.rankk-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[.](#algs.blas3.rankk-9.sentence-1)
#### [29.9.15.5](#algs.blas3.rank2k) Rank-2k update of a symmetric or Hermitian matrix [[linalg.algs.blas3.rank2k]](linalg.algs.blas3.rank2k)
[1](#algs.blas3.rank2k-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15659)
[*Note [1](#algs.blas3.rank2k-note-1)*:
These functions correspond to the BLAS functionsxSYR2K and xHER2K[[bib]](bibliography#bib:blas3 "Bibliography")[.](#algs.blas3.rank2k-1.sentence-1)
— *end note*]
[2](#algs.blas3.rank2k-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15665)
The following elements apply to all functions in [[linalg.algs.blas3.rank2k]](#algs.blas3.rank2k "29.9.15.5Rank-2k update of a symmetric or Hermitian matrix")[.](#algs.blas3.rank2k-2.sentence-1)
[3](#algs.blas3.rank2k-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15668)
*Mandates*:
- [(3.1)](#algs.blas3.rank2k-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)](#algs.blas3.rank2k-3.2)
*possibly-addable*<decltype(A), decltype(B), decltype(C)>() is true; and
- [(3.3)](#algs.blas3.rank2k-3.3)
*compatible-static-extents*<decltype(A), decltype(A)>(0, 1) is true[.](#algs.blas3.rank2k-3.sentence-1)
[4](#algs.blas3.rank2k-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15683)
*Preconditions*:
- [(4.1)](#algs.blas3.rank2k-4.1)
*addable*(A, B, C) is true, and
- [(4.2)](#algs.blas3.rank2k-4.2)
A.extent(0) equals A.extent(1)[.](#algs.blas3.rank2k-4.sentence-1)
[5](#algs.blas3.rank2k-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15692)
*Complexity*: O(A.extent(0)×A.extent(1)×C.extent(0))[.](#algs.blas3.rank2k-5.sentence-1)
[🔗](#lib:symmetric_matrix_rank_2k_update)
`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,
[possibly-packed-inout-matrix](#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](#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,
[possibly-packed-inout-matrix](#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](#algs.blas3.rank2k-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[.](#algs.blas3.rank2k-6.sentence-1)
[🔗](#lib:hermitian_matrix_rank_2k_update)
`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,
[possibly-packed-inout-matrix](#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](#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,
[possibly-packed-inout-matrix](#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](#algs.blas3.rank2k-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[.](#algs.blas3.rank2k-7.sentence-1)
#### [29.9.15.6](#algs.blas3.trsm) Solve multiple triangular linear systems [[linalg.algs.blas3.trsm]](linalg.algs.blas3.trsm)
[1](#algs.blas3.trsm-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15735)
[*Note [1](#algs.blas3.trsm-note-1)*:
These functions correspond to the BLAS function xTRSM[[bib]](bibliography#bib:blas3 "Bibliography")[.](#algs.blas3.trsm-1.sentence-1)
— *end note*]
[🔗](#lib:triangular_matrix_matrix_left_solve)
`template<[in-matrix](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat1, class Triangle, class DiagonalStorage,
[in-matrix](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat2, [out-matrix](#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](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat1, class Triangle, class DiagonalStorage,
[in-matrix](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat2, [out-matrix](#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](#algs.blas3.trsm-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]](#general "29.9.3General"))[.](#algs.blas3.trsm-2.sentence-1)
[3](#algs.blas3.trsm-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15760)
*Mandates*:
- [(3.1)](#algs.blas3.trsm-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)](#algs.blas3.trsm-3.2)
*possibly-multipliable*<InMat1, OutMat, InMat2>() is true; and
- [(3.3)](#algs.blas3.trsm-3.3)
*compatible-static-extents*<InMat1, InMat1>(0, 1) is true[.](#algs.blas3.trsm-3.sentence-1)
[4](#algs.blas3.trsm-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15775)
*Preconditions*:
- [(4.1)](#algs.blas3.trsm-4.1)
*multipliable*(A, X, B) is true, and
- [(4.2)](#algs.blas3.trsm-4.2)
A.extent(0) == A.extent(1) is true[.](#algs.blas3.trsm-4.sentence-1)
[5](#algs.blas3.trsm-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[.](#algs.blas3.trsm-5.sentence-1)
If no such X′ exists,
then the elements of X are valid but unspecified[.](#algs.blas3.trsm-5.sentence-2)
[6](#algs.blas3.trsm-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15791)
*Complexity*: O(A.extent(0)×X.extent(1)×X.extent(1))[.](#algs.blas3.trsm-6.sentence-1)
[7](#algs.blas3.trsm-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15796)
[*Note [2](#algs.blas3.trsm-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[.](#algs.blas3.trsm-7.sentence-1)
— *end note*]
[🔗](#lib:triangular_matrix_matrix_left_solve_)
`template<[in-matrix](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat1, class Triangle, class DiagonalStorage,
[in-matrix](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat2, [out-matrix](#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](#algs.blas3.trsm-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](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat1, class Triangle, class DiagonalStorage,
[in-matrix](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat2, [out-matrix](#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](#algs.blas3.trsm-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](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat1, class Triangle, class DiagonalStorage,
[in-matrix](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat2, [out-matrix](#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](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat1, class Triangle, class DiagonalStorage,
[in-matrix](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat2, [out-matrix](#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](#algs.blas3.trsm-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]](#general "29.9.3General"))[.](#algs.blas3.trsm-10.sentence-1)
[11](#algs.blas3.trsm-11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15863)
*Mandates*:
- [(11.1)](#algs.blas3.trsm-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)](#algs.blas3.trsm-11.2)
*possibly-multipliable*<OutMat, InMat1, InMat2>() is true; and
- [(11.3)](#algs.blas3.trsm-11.3)
*compatible-static-extents*<InMat1, InMat1>(0,1) is true[.](#algs.blas3.trsm-11.sentence-1)
[12](#algs.blas3.trsm-12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15876)
*Preconditions*:
- [(12.1)](#algs.blas3.trsm-12.1)
*multipliable*(X, A, B) is true, and
- [(12.2)](#algs.blas3.trsm-12.2)
A.extent(0) == A.extent(1) is true[.](#algs.blas3.trsm-12.sentence-1)
[13](#algs.blas3.trsm-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[.](#algs.blas3.trsm-13.sentence-1)
If no such X′ exists,
then the elements of X are valid but unspecified[.](#algs.blas3.trsm-13.sentence-2)
[14](#algs.blas3.trsm-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](#algs.blas3.trsm-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[.](#algs.blas3.trsm-14.sentence-1)
— *end note*]
[🔗](#lib:triangular_matrix_matrix_right_solve_)
`template<[in-matrix](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat1, class Triangle, class DiagonalStorage,
[in-matrix](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat2, [out-matrix](#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](#algs.blas3.trsm-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](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat1, class Triangle, class DiagonalStorage,
[in-matrix](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat2, [out-matrix](#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](#algs.blas3.trsm-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>{});
#### [29.9.15.7](#algs.blas3.inplacetrsm) Solve multiple triangular linear systems in-place [[linalg.algs.blas3.inplacetrsm]](linalg.algs.blas3.inplacetrsm)
[1](#algs.blas3.inplacetrsm-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15943)
[*Note [1](#algs.blas3.inplacetrsm-note-1)*:
These functions correspond to the BLAS function xTRSM[[bib]](bibliography#bib:blas3 "Bibliography")[.](#algs.blas3.inplacetrsm-1.sentence-1)
— *end note*]
[🔗](#lib:triangular_matrix_matrix_left_solve___)
`template<[in-matrix](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage,
[inout-matrix](#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](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage,
[inout-matrix](#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](#algs.blas3.inplacetrsm-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]](#general "29.9.3General"))[.](#algs.blas3.inplacetrsm-2.sentence-1)
[*Note [2](#algs.blas3.inplacetrsm-note-2)*:
This algorithm makes it possible
to compute factorizations like Cholesky and LU in place[.](#algs.blas3.inplacetrsm-2.sentence-2)
Performing triangular solve in place hinders parallelization[.](#algs.blas3.inplacetrsm-2.sentence-3)
However, other ExecutionPolicy specific optimizations,
such as vectorization, are still possible[.](#algs.blas3.inplacetrsm-2.sentence-4)
— *end note*]
[3](#algs.blas3.inplacetrsm-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15974)
*Mandates*:
- [(3.1)](#algs.blas3.inplacetrsm-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)](#algs.blas3.inplacetrsm-3.2)
*possibly-multipliable*<InMat, InOutMat, InOutMat>() is true; and
- [(3.3)](#algs.blas3.inplacetrsm-3.3)
*compatible-static-extents*<InMat, InMat>(0, 1) is true[.](#algs.blas3.inplacetrsm-3.sentence-1)
[4](#algs.blas3.inplacetrsm-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L15989)
*Preconditions*:
- [(4.1)](#algs.blas3.inplacetrsm-4.1)
*multipliable*(A, B, B) is true, and
- [(4.2)](#algs.blas3.inplacetrsm-4.2)
A.extent(0) == A.extent(1) is true[.](#algs.blas3.inplacetrsm-4.sentence-1)
[5](#algs.blas3.inplacetrsm-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[.](#algs.blas3.inplacetrsm-5.sentence-1)
If so such X′ exists,
then the elements of B are valid but unspecified[.](#algs.blas3.inplacetrsm-5.sentence-2)
[6](#algs.blas3.inplacetrsm-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L16005)
*Complexity*: O(A.extent(0)×A.extent(1)×B.extent(1))[.](#algs.blas3.inplacetrsm-6.sentence-1)
[🔗](#lib:triangular_matrix_matrix_left_solve____)
`template<[in-matrix](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage, [inout-matrix](#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](#algs.blas3.inplacetrsm-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](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage, [inout-matrix](#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](#algs.blas3.inplacetrsm-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](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage,
[inout-matrix](#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](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage,
[inout-matrix](#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](#algs.blas3.inplacetrsm-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]](#general "29.9.3General"))[.](#algs.blas3.inplacetrsm-9.sentence-1)
[*Note [3](#algs.blas3.inplacetrsm-note-3)*:
This algorithm makes it possible
to compute factorizations like Cholesky and LU in place[.](#algs.blas3.inplacetrsm-9.sentence-2)
Performing triangular solve in place hinders parallelization[.](#algs.blas3.inplacetrsm-9.sentence-3)
However, other ExecutionPolicy specific optimizations,
such as vectorization, are still possible[.](#algs.blas3.inplacetrsm-9.sentence-4)
— *end note*]
[10](#algs.blas3.inplacetrsm-10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L16071)
*Mandates*:
- [(10.1)](#algs.blas3.inplacetrsm-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)](#algs.blas3.inplacetrsm-10.2)
*possibly-multipliable*<InOutMat, InMat, InOutMat>() is true; and
- [(10.3)](#algs.blas3.inplacetrsm-10.3)
*compatible-static-extents*<InMat, InMat>(0, 1) is true[.](#algs.blas3.inplacetrsm-10.sentence-1)
[11](#algs.blas3.inplacetrsm-11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L16085)
*Preconditions*:
- [(11.1)](#algs.blas3.inplacetrsm-11.1)
*multipliable*(B, A, B) is true, and
- [(11.2)](#algs.blas3.inplacetrsm-11.2)
A.extent(0) == A.extent(1) is true[.](#algs.blas3.inplacetrsm-11.sentence-1)
[12](#algs.blas3.inplacetrsm-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[.](#algs.blas3.inplacetrsm-12.sentence-1)
If so such X′ exists,
then the elements of B are valid but unspecified[.](#algs.blas3.inplacetrsm-12.sentence-2)
[13](#algs.blas3.inplacetrsm-13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L16101)
*Complexity*: O(A.extent(0)×A.extent(1)×B.extent(1))[.](#algs.blas3.inplacetrsm-13.sentence-1)
[🔗](#lib:triangular_matrix_matrix_right_solve____)
`template<[in-matrix](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage, [inout-matrix](#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](#algs.blas3.inplacetrsm-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](#concept:in-matrix "29.9.7.5Argument concepts[linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage, [inout-matrix](#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](#algs.blas3.inplacetrsm-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>{});