[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.3 Multidimensional access"))[.](#overview-1.sentence-2) ### [29.9.2](#syn) Header synopsis [[linalg.syn]](linalg.syn) [🔗](#header:%3clinalg%3e) namespace std::linalg {// [[linalg.tags.order]](#tags.order "29.9.5.1 Storage 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.2 Triangle 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.3 Diagonal 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.6 Layouts for packed matrix types"), class template layout_blas_packedtemplateclass layout_blas_packed; // [[linalg.helpers]](#helpers "29.9.7 Exposition-only helpers"), exposition-only helpers// [[linalg.helpers.concepts]](#helpers.concepts "29.9.7.5 Argument concepts"), linear algebra argument conceptstemplateconstexpr bool *is-mdspan* = *see below*; // *exposition only*templateconcept [*in-vector*](#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") = *see below*; // *exposition only*templateconcept [*out-vector*](#concept:out-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") = *see below*; // *exposition only*templateconcept [*inout-vector*](#concept:inout-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") = *see below*; // *exposition only*templateconcept [*in-matrix*](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") = *see below*; // *exposition only*templateconcept [*out-matrix*](#concept:out-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") = *see below*; // *exposition only*templateconcept [*inout-matrix*](#concept:inout-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") = *see below*; // *exposition only*templateconcept [*possibly-packed-inout-matrix*](#concept:possibly-packed-inout-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") = *see below*; // *exposition only*templateconcept [*in-object*](#concept:in-object "29.9.7.5 Argument concepts [linalg.helpers.concepts]") = *see below*; // *exposition only*templateconcept [*out-object*](#concept:out-object "29.9.7.5 Argument concepts [linalg.helpers.concepts]") = *see below*; // *exposition only*templateconcept [*inout-object*](#concept:inout-object "29.9.7.5 Argument concepts [linalg.helpers.concepts]") = *see below*; // *exposition only*// [[linalg.scaled]](#scaled "29.9.8 Scaled in-place transformation"), scaled in-place transformation// [[linalg.scaled.scaledaccessor]](#scaled.scaledaccessor "29.9.8.2 Class template scaled_­accessor"), class template scaled_accessortemplateclass scaled_accessor; // [[linalg.scaled.scaled]](#scaled.scaled "29.9.8.3 Function template scaled"), function template scaledtemplateconstexpr auto scaled(ScalingFactor alpha, mdspan x); // [[linalg.conj]](#conj "29.9.9 Conjugated in-place transformation"), conjugated in-place transformation// [[linalg.conj.conjugatedaccessor]](#conj.conjugatedaccessor "29.9.9.2 Class template conjugated_­accessor"), class template conjugated_accessortemplateclass conjugated_accessor; // [[linalg.conj.conjugated]](#conj.conjugated "29.9.9.3 Function template conjugated"), function template conjugatedtemplateconstexpr auto conjugated(mdspan a); // [[linalg.transp]](#transp "29.9.10 Transpose in-place transformation"), transpose in-place transformation// [[linalg.transp.layout.transpose]](#transp.layout.transpose "29.9.10.3 Class template layout_­transpose"), class template layout_transposetemplateclass layout_transpose; // [[linalg.transp.transposed]](#transp.transposed "29.9.10.4 Function template transposed"), function template transposedtemplateconstexpr auto transposed(mdspan a); // [[linalg.conjtransposed]](#conjtransposed "29.9.11 Conjugate transpose in-place transform"), conjugated transpose in-place transformationtemplateconstexpr auto conjugate_transposed(mdspan a); // [[linalg.algs.blas1]](#algs.blas1 "29.9.13 BLAS 1 algorithms"), BLAS 1 algorithms// [[linalg.algs.blas1.givens]](#algs.blas1.givens "29.9.13.2 Givens rotations"), Givens rotations// [[linalg.algs.blas1.givens.lartg]](#algs.blas1.givens.lartg "29.9.13.2.1 Compute Givens rotation"), compute Givens rotationtemplatestruct setup_givens_rotation_result { Real c; Real s; Real r; }; templatestruct setup_givens_rotation_result> { Real c; complex s; complex r; }; template setup_givens_rotation_result setup_givens_rotation(Real a, Real b) noexcept; template setup_givens_rotation_result> setup_givens_rotation(complex a, complex b) noexcept; // [[linalg.algs.blas1.givens.rot]](#algs.blas1.givens.rot "29.9.13.2.2 Apply a computed Givens rotation to vectors"), apply computed Givens rotationtemplate<[*inout-vector*](#concept:inout-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InOutVec1, [*inout-vector*](#concept:inout-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InOutVec2, class Real>void apply_givens_rotation(InOutVec1 x, InOutVec2 y, Real c, Real s); templatevoid apply_givens_rotation(ExecutionPolicy&& exec, InOutVec1 x, InOutVec2 y, Real c, Real s); template<[*inout-vector*](#concept:inout-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InOutVec1, [*inout-vector*](#concept:inout-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InOutVec2, class Real>void apply_givens_rotation(InOutVec1 x, InOutVec2 y, Real c, complex s); templatevoid apply_givens_rotation(ExecutionPolicy&& exec, InOutVec1 x, InOutVec2 y, Real c, complex s); // [[linalg.algs.blas1.swap]](#algs.blas1.swap "29.9.13.3 Swap matrix or vector elements"), swap elementstemplate<[*inout-object*](#concept:inout-object "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InOutObj1, [*inout-object*](#concept:inout-object "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InOutObj2>void swap_elements(InOutObj1 x, InOutObj2 y); templatevoid swap_elements(ExecutionPolicy&& exec, InOutObj1 x, InOutObj2 y); // [[linalg.algs.blas1.scal]](#algs.blas1.scal "29.9.13.4 Multiply the elements of an object in place by a scalar"), multiply elements by scalartemplatevoid scale(Scalar alpha, InOutObj x); templatevoid scale(ExecutionPolicy&& exec, Scalar alpha, InOutObj x); // [[linalg.algs.blas1.copy]](#algs.blas1.copy "29.9.13.5 Copy elements of one matrix or vector into another"), copy elementstemplate<[*in-object*](#concept:in-object "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InObj, [*out-object*](#concept:out-object "29.9.7.5 Argument concepts [linalg.helpers.concepts]") OutObj>void copy(InObj x, OutObj y); templatevoid copy(ExecutionPolicy&& exec, InObj x, OutObj y); // [[linalg.algs.blas1.add]](#algs.blas1.add "29.9.13.6 Add vectors or matrices elementwise"), add elementwisetemplate<[*in-object*](#concept:in-object "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InObj1, [*in-object*](#concept:in-object "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InObj2, [*out-object*](#concept:out-object "29.9.7.5 Argument concepts [linalg.helpers.concepts]") OutObj>void add(InObj1 x, InObj2 y, OutObj z); templatevoid add(ExecutionPolicy&& exec, InObj1 x, InObj2 y, OutObj z); // [[linalg.algs.blas1.dot]](#algs.blas1.dot "29.9.13.7 Dot product of two vectors"), dot product of two vectorstemplate<[*in-vector*](#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec1, [*in-vector*](#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec2, class Scalar> Scalar dot(InVec1 v1, InVec2 v2, Scalar init); template Scalar dot(ExecutionPolicy&& exec, InVec1 v1, InVec2 v2, Scalar init); template<[*in-vector*](#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec1, [*in-vector*](#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec2>auto dot(InVec1 v1, InVec2 v2); templateauto dot(ExecutionPolicy&& exec, InVec1 v1, InVec2 v2); template<[*in-vector*](#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec1, [*in-vector*](#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec2, class Scalar> Scalar dotc(InVec1 v1, InVec2 v2, Scalar init); template Scalar dotc(ExecutionPolicy&& exec, InVec1 v1, InVec2 v2, Scalar init); template<[*in-vector*](#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec1, [*in-vector*](#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec2>auto dotc(InVec1 v1, InVec2 v2); templateauto dotc(ExecutionPolicy&& exec, InVec1 v1, InVec2 v2); // [[linalg.algs.blas1.ssq]](#algs.blas1.ssq "29.9.13.8 Scaled sum of squares of a vector"), scaled sum of squares of a vector's elementstemplatestruct sum_of_squares_result { Scalar scaling_factor; Scalar scaled_sum_of_squares; }; template<[*in-vector*](#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec, class Scalar> sum_of_squares_result vector_sum_of_squares(InVec v, sum_of_squares_result init); template sum_of_squares_result vector_sum_of_squares(ExecutionPolicy&& exec, InVec v, sum_of_squares_result init); // [[linalg.algs.blas1.nrm2]](#algs.blas1.nrm2 "29.9.13.9 Euclidean norm of a vector"), Euclidean norm of a vectortemplate<[*in-vector*](#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec, class Scalar> Scalar vector_two_norm(InVec v, Scalar init); template Scalar vector_two_norm(ExecutionPolicy&& exec, InVec v, Scalar init); template<[*in-vector*](#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec>auto vector_two_norm(InVec v); templateauto vector_two_norm(ExecutionPolicy&& exec, InVec v); // [[linalg.algs.blas1.asum]](#algs.blas1.asum "29.9.13.10 Sum of absolute values of vector elements"), sum of absolute values of vector elementstemplate<[*in-vector*](#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec, class Scalar> Scalar vector_abs_sum(InVec v, Scalar init); template Scalar vector_abs_sum(ExecutionPolicy&& exec, InVec v, Scalar init); template<[*in-vector*](#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec>auto vector_abs_sum(InVec v); templateauto vector_abs_sum(ExecutionPolicy&& exec, InVec v); // [[linalg.algs.blas1.iamax]](#algs.blas1.iamax "29.9.13.11 Index of maximum absolute value of vector elements"), index of maximum absolute value of vector elementstemplate<[*in-vector*](#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec>typename InVec::extents_type vector_idx_abs_max(InVec v); templatetypename InVec::extents_type vector_idx_abs_max(ExecutionPolicy&& exec, InVec v); // [[linalg.algs.blas1.matfrobnorm]](#algs.blas1.matfrobnorm "29.9.13.12 Frobenius norm of a matrix"), Frobenius norm of a matrixtemplate<[*in-matrix*](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat, class Scalar> Scalar matrix_frob_norm(InMat A, Scalar init); template Scalar matrix_frob_norm(ExecutionPolicy&& exec, InMat A, Scalar init); template<[*in-matrix*](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat>auto matrix_frob_norm(InMat A); templateauto matrix_frob_norm(ExecutionPolicy&& exec, InMat A); // [[linalg.algs.blas1.matonenorm]](#algs.blas1.matonenorm "29.9.13.13 One norm of a matrix"), one norm of a matrixtemplate<[*in-matrix*](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat, class Scalar> Scalar matrix_one_norm(InMat A, Scalar init); template Scalar matrix_one_norm(ExecutionPolicy&& exec, InMat A, Scalar init); template<[*in-matrix*](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat>auto matrix_one_norm(InMat A); templateauto matrix_one_norm(ExecutionPolicy&& exec, InMat A); // [[linalg.algs.blas1.matinfnorm]](#algs.blas1.matinfnorm "29.9.13.14 Infinity norm of a matrix"), infinity norm of a matrixtemplate<[*in-matrix*](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat, class Scalar> Scalar matrix_inf_norm(InMat A, Scalar init); template Scalar matrix_inf_norm(ExecutionPolicy&& exec, InMat A, Scalar init); template<[*in-matrix*](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat>auto matrix_inf_norm(InMat A); templateauto matrix_inf_norm(ExecutionPolicy&& exec, InMat A); // [[linalg.algs.blas2]](#algs.blas2 "29.9.14 BLAS 2 algorithms"), BLAS 2 algorithms// [[linalg.algs.blas2.gemv]](#algs.blas2.gemv "29.9.14.1 General matrix-vector product"), general matrix-vector producttemplate<[*in-matrix*](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat, [*in-vector*](#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec, [*out-vector*](#concept:out-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") OutVec>void matrix_vector_product(InMat A, InVec x, OutVec y); templatevoid matrix_vector_product(ExecutionPolicy&& exec, InMat A, InVec x, OutVec y); template<[*in-matrix*](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat, [*in-vector*](#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec1, [*in-vector*](#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec2, [*out-vector*](#concept:out-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") OutVec>void matrix_vector_product(InMat A, InVec1 x, InVec2 y, OutVec z); templatevoid matrix_vector_product(ExecutionPolicy&& exec, InMat A, InVec1 x, InVec2 y, OutVec z); // [[linalg.algs.blas2.symv]](#algs.blas2.symv "29.9.14.2 Symmetric matrix-vector product"), symmetric matrix-vector producttemplate<[*in-matrix*](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat, class Triangle, [*in-vector*](#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec, [*out-vector*](#concept:out-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") OutVec>void symmetric_matrix_vector_product(InMat A, Triangle t, InVec x, OutVec y); templatevoid symmetric_matrix_vector_product(ExecutionPolicy&& exec, InMat A, Triangle t, InVec x, OutVec y); template<[*in-matrix*](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat, class Triangle, [*in-vector*](#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec1, [*in-vector*](#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec2, [*out-vector*](#concept:out-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") OutVec>void symmetric_matrix_vector_product(InMat A, Triangle t, InVec1 x, InVec2 y, OutVec z); templatevoid 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.3 Hermitian matrix-vector product"), Hermitian matrix-vector producttemplate<[*in-matrix*](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat, class Triangle, [*in-vector*](#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec, [*out-vector*](#concept:out-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") OutVec>void hermitian_matrix_vector_product(InMat A, Triangle t, InVec x, OutVec y); templatevoid hermitian_matrix_vector_product(ExecutionPolicy&& exec, InMat A, Triangle t, InVec x, OutVec y); template<[*in-matrix*](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat, class Triangle, [*in-vector*](#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec1, [*in-vector*](#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec2, [*out-vector*](#concept:out-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") OutVec>void hermitian_matrix_vector_product(InMat A, Triangle t, InVec1 x, InVec2 y, OutVec z); templatevoid 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.4 Triangular matrix-vector product"), triangular matrix-vector product// Overwriting triangular matrix-vector producttemplate<[*in-matrix*](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage, [*in-vector*](#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec, [*out-vector*](#concept:out-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") OutVec>void triangular_matrix_vector_product(InMat A, Triangle t, DiagonalStorage d, InVec x, OutVec y); templatevoid 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.5 Argument concepts [linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage, [*inout-vector*](#concept:inout-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InOutVec>void triangular_matrix_vector_product(InMat A, Triangle t, DiagonalStorage d, InOutVec y); templatevoid 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.5 Argument concepts [linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage, [*in-vector*](#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec1, [*in-vector*](#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec2, [*out-vector*](#concept:out-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") OutVec>void triangular_matrix_vector_product(InMat A, Triangle t, DiagonalStorage d, InVec1 x, InVec2 y, OutVec z); templatevoid 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.5 Solve 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.5 Argument concepts [linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage, [*in-vector*](#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec, [*out-vector*](#concept:out-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") OutVec, class BinaryDivideOp>void triangular_matrix_vector_solve(InMat A, Triangle t, DiagonalStorage d, InVec b, OutVec x, BinaryDivideOp divide); templatevoid 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.5 Argument concepts [linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage, [*in-vector*](#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec, [*out-vector*](#concept:out-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") OutVec>void triangular_matrix_vector_solve(InMat A, Triangle t, DiagonalStorage d, InVec b, OutVec x); templatevoid 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.5 Argument concepts [linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage, [*inout-vector*](#concept:inout-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InOutVec, class BinaryDivideOp>void triangular_matrix_vector_solve(InMat A, Triangle t, DiagonalStorage d, InOutVec b, BinaryDivideOp divide); templatevoid 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.5 Argument concepts [linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage, [*inout-vector*](#concept:inout-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InOutVec>void triangular_matrix_vector_solve(InMat A, Triangle t, DiagonalStorage d, InOutVec b); templatevoid triangular_matrix_vector_solve(ExecutionPolicy&& exec, InMat A, Triangle t, DiagonalStorage d, InOutVec b); // [[linalg.algs.blas2.rank1]](#algs.blas2.rank1 "29.9.14.6 Rank-1 (outer product) update of a matrix"), nonsymmetric rank-1 matrix updatetemplate<[*in-vector*](#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec1, [*in-vector*](#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec2, [*inout-matrix*](#concept:inout-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InOutMat>void matrix_rank_1_update(InVec1 x, InVec2 y, InOutMat A); templatevoid matrix_rank_1_update(ExecutionPolicy&& exec, InVec1 x, InVec2 y, InOutMat A); template<[*in-vector*](#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec1, [*in-vector*](#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec2, [*inout-matrix*](#concept:inout-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InOutMat>void matrix_rank_1_update_c(InVec1 x, InVec2 y, InOutMat A); templatevoid matrix_rank_1_update_c(ExecutionPolicy&& exec, InVec1 x, InVec2 y, InOutMat A); // [[linalg.algs.blas2.symherrank1]](#algs.blas2.symherrank1 "29.9.14.7 Symmetric or Hermitian Rank-1 (outer product) update of a matrix"), symmetric or Hermitian rank-1 matrix updatetemplatevoid symmetric_matrix_rank_1_update(Scalar alpha, InVec x, InOutMat A, Triangle t); templatevoid symmetric_matrix_rank_1_update(ExecutionPolicy&& exec, Scalar alpha, InVec x, InOutMat A, Triangle t); template<[*in-vector*](#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec, [*possibly-packed-inout-matrix*](#concept:possibly-packed-inout-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InOutMat, class Triangle>void symmetric_matrix_rank_1_update(InVec x, InOutMat A, Triangle t); templatevoid symmetric_matrix_rank_1_update(ExecutionPolicy&& exec, InVec x, InOutMat A, Triangle t); templatevoid hermitian_matrix_rank_1_update(Scalar alpha, InVec x, InOutMat A, Triangle t); templatevoid hermitian_matrix_rank_1_update(ExecutionPolicy&& exec, Scalar alpha, InVec x, InOutMat A, Triangle t); template<[*in-vector*](#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec, [*possibly-packed-inout-matrix*](#concept:possibly-packed-inout-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InOutMat, class Triangle>void hermitian_matrix_rank_1_update(InVec x, InOutMat A, Triangle t); templatevoid hermitian_matrix_rank_1_update(ExecutionPolicy&& exec, InVec x, InOutMat A, Triangle t); // [[linalg.algs.blas2.rank2]](#algs.blas2.rank2 "29.9.14.8 Symmetric 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.5 Argument concepts [linalg.helpers.concepts]") InVec1, [*in-vector*](#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec2, [*possibly-packed-inout-matrix*](#concept:possibly-packed-inout-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InOutMat, class Triangle>void symmetric_matrix_rank_2_update(InVec1 x, InVec2 y, InOutMat A, Triangle t); templatevoid 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.5 Argument concepts [linalg.helpers.concepts]") InVec1, [*in-vector*](#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec2, [*possibly-packed-inout-matrix*](#concept:possibly-packed-inout-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InOutMat, class Triangle>void hermitian_matrix_rank_2_update(InVec1 x, InVec2 y, InOutMat A, Triangle t); templatevoid hermitian_matrix_rank_2_update(ExecutionPolicy&& exec, InVec1 x, InVec2 y, InOutMat A, Triangle t); // [[linalg.algs.blas3]](#algs.blas3 "29.9.15 BLAS 3 algorithms"), BLAS 3 algorithms// [[linalg.algs.blas3.gemm]](#algs.blas3.gemm "29.9.15.1 General matrix-matrix product"), general matrix-matrix producttemplate<[*in-matrix*](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat1, [*in-matrix*](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat2, [*out-matrix*](#concept:out-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") OutMat>void matrix_product(InMat1 A, InMat2 B, OutMat C); templatevoid matrix_product(ExecutionPolicy&& exec, InMat1 A, InMat2 B, OutMat C); template<[*in-matrix*](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat1, [*in-matrix*](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat2, [*in-matrix*](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat3, [*out-matrix*](#concept:out-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") OutMat>void matrix_product(InMat1 A, InMat2 B, InMat3 E, OutMat C); templatevoid matrix_product(ExecutionPolicy&& exec, InMat1 A, InMat2 B, InMat3 E, OutMat C); // [[linalg.algs.blas3.xxmm]](#algs.blas3.xxmm "29.9.15.2 Symmetric, Hermitian, and triangular matrix-matrix product"), symmetric, Hermitian, and triangular matrix-matrix producttemplate<[*in-matrix*](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat1, class Triangle, [*in-matrix*](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat2, [*out-matrix*](#concept:out-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") OutMat>void symmetric_matrix_product(InMat1 A, Triangle t, InMat2 B, OutMat C); templatevoid symmetric_matrix_product(ExecutionPolicy&& exec, InMat1 A, Triangle t, InMat2 B, OutMat C); template<[*in-matrix*](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat1, class Triangle, [*in-matrix*](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat2, [*out-matrix*](#concept:out-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") OutMat>void hermitian_matrix_product(InMat1 A, Triangle t, InMat2 B, OutMat C); templatevoid hermitian_matrix_product(ExecutionPolicy&& exec, InMat1 A, Triangle t, InMat2 B, OutMat C); template<[*in-matrix*](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat1, class Triangle, class DiagonalStorage, [*in-matrix*](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat2, [*out-matrix*](#concept:out-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") OutMat>void triangular_matrix_product(InMat1 A, Triangle t, DiagonalStorage d, InMat2 B, OutMat C); templatevoid triangular_matrix_product(ExecutionPolicy&& exec, InMat1 A, Triangle t, DiagonalStorage d, InMat2 B, OutMat C); template<[*in-matrix*](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat1, [*in-matrix*](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat2, class Triangle, [*out-matrix*](#concept:out-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") OutMat>void symmetric_matrix_product(InMat1 A, InMat2 B, Triangle t, OutMat C); templatevoid symmetric_matrix_product(ExecutionPolicy&& exec, InMat1 A, InMat2 B, Triangle t, OutMat C); template<[*in-matrix*](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat1, [*in-matrix*](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat2, class Triangle, [*out-matrix*](#concept:out-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") OutMat>void hermitian_matrix_product(InMat1 A, InMat2 B, Triangle t, OutMat C); templatevoid hermitian_matrix_product(ExecutionPolicy&& exec, InMat1 A, InMat2 B, Triangle t, OutMat C); template<[*in-matrix*](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat1, [*in-matrix*](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat2, class Triangle, class DiagonalStorage, [*out-matrix*](#concept:out-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") OutMat>void triangular_matrix_product(InMat1 A, InMat2 B, Triangle t, DiagonalStorage d, OutMat C); templatevoid triangular_matrix_product(ExecutionPolicy&& exec, InMat1 A, InMat2 B, Triangle t, DiagonalStorage d, OutMat C); template<[*in-matrix*](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat1, class Triangle, [*in-matrix*](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat2, [*in-matrix*](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat3, [*out-matrix*](#concept:out-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") OutMat>void symmetric_matrix_product(InMat1 A, Triangle t, InMat2 B, InMat3 E, OutMat C); templatevoid symmetric_matrix_product(ExecutionPolicy&& exec, InMat1 A, Triangle t, InMat2 B, InMat3 E, OutMat C); template<[*in-matrix*](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat1, class Triangle, [*in-matrix*](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat2, [*in-matrix*](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat3, [*out-matrix*](#concept:out-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") OutMat>void hermitian_matrix_product(InMat1 A, Triangle t, InMat2 B, InMat3 E, OutMat C); templatevoid hermitian_matrix_product(ExecutionPolicy&& exec, InMat1 A, Triangle t, InMat2 B, InMat3 E, OutMat C); template<[*in-matrix*](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat1, class Triangle, class DiagonalStorage, [*in-matrix*](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat2, [*in-matrix*](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat3, [*out-matrix*](#concept:out-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") OutMat>void triangular_matrix_product(InMat1 A, Triangle t, DiagonalStorage d, InMat2 B, InMat3 E, OutMat C); templatevoid 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.5 Argument concepts [linalg.helpers.concepts]") InMat1, [*in-matrix*](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat2, class Triangle, [*in-matrix*](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat3, [*out-matrix*](#concept:out-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") OutMat>void symmetric_matrix_product(InMat1 A, InMat2 B, Triangle t, InMat3 E, OutMat C); templatevoid symmetric_matrix_product(ExecutionPolicy&& exec, InMat1 A, InMat2 B, Triangle t, InMat3 E, OutMat C); template<[*in-matrix*](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat1, [*in-matrix*](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat2, class Triangle, [*in-matrix*](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat3, [*out-matrix*](#concept:out-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") OutMat>void hermitian_matrix_product(InMat1 A, InMat2 B, Triangle t, InMat3 E, OutMat C); templatevoid hermitian_matrix_product(ExecutionPolicy&& exec, InMat1 A, InMat2 B, Triangle t, InMat3 E, OutMat C); template<[*in-matrix*](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat1, [*in-matrix*](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat2, class Triangle, class DiagonalStorage, [*in-matrix*](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat3, [*out-matrix*](#concept:out-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") OutMat>void triangular_matrix_product(InMat1 A, InMat2 B, Triangle t, DiagonalStorage d, InMat3 E, OutMat C); templatevoid 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.3 In-place triangular matrix-matrix product"), in-place triangular matrix-matrix producttemplate<[*in-matrix*](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage, [*inout-matrix*](#concept:inout-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InOutMat>void triangular_matrix_left_product(InMat A, Triangle t, DiagonalStorage d, InOutMat C); templatevoid triangular_matrix_left_product(ExecutionPolicy&& exec, InMat A, Triangle t, DiagonalStorage d, InOutMat C); template<[*in-matrix*](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage, [*inout-matrix*](#concept:inout-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InOutMat>void triangular_matrix_right_product(InMat A, Triangle t, DiagonalStorage d, InOutMat C); templatevoid triangular_matrix_right_product(ExecutionPolicy&& exec, InMat A, Triangle t, DiagonalStorage d, InOutMat C); // [[linalg.algs.blas3.rankk]](#algs.blas3.rankk "29.9.15.4 Rank-k update of a symmetric or Hermitian matrix"), rank-k update of a symmetric or Hermitian matrix// rank-k symmetric matrix updatetemplatevoid symmetric_matrix_rank_k_update(Scalar alpha, InMat A, InOutMat C, Triangle t); templatevoid symmetric_matrix_rank_k_update(ExecutionPolicy&& exec, Scalar alpha, InMat A, InOutMat C, Triangle t); template<[*in-matrix*](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat, [*possibly-packed-inout-matrix*](#concept:possibly-packed-inout-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InOutMat, class Triangle>void symmetric_matrix_rank_k_update(InMat A, InOutMat C, Triangle t); templatevoid symmetric_matrix_rank_k_update(ExecutionPolicy&& exec, InMat A, InOutMat C, Triangle t); // rank-k Hermitian matrix updatetemplatevoid hermitian_matrix_rank_k_update(Scalar alpha, InMat A, InOutMat C, Triangle t); templatevoid hermitian_matrix_rank_k_update(ExecutionPolicy&& exec, Scalar alpha, InMat A, InOutMat C, Triangle t); template<[*in-matrix*](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat, [*possibly-packed-inout-matrix*](#concept:possibly-packed-inout-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InOutMat, class Triangle>void hermitian_matrix_rank_k_update(InMat A, InOutMat C, Triangle t); templatevoid hermitian_matrix_rank_k_update(ExecutionPolicy&& exec, InMat A, InOutMat C, Triangle t); // [[linalg.algs.blas3.rank2k]](#algs.blas3.rank2k "29.9.15.5 Rank-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.5 Argument concepts [linalg.helpers.concepts]") InMat1, [*in-matrix*](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat2, [*possibly-packed-inout-matrix*](#concept:possibly-packed-inout-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InOutMat, class Triangle>void symmetric_matrix_rank_2k_update(InMat1 A, InMat2 B, InOutMat C, Triangle t); templatevoid 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.5 Argument concepts [linalg.helpers.concepts]") InMat1, [*in-matrix*](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat2, [*possibly-packed-inout-matrix*](#concept:possibly-packed-inout-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InOutMat, class Triangle>void hermitian_matrix_rank_2k_update(InMat1 A, InMat2 B, InOutMat C, Triangle t); templatevoid 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.6 Solve 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.5 Argument concepts [linalg.helpers.concepts]") InMat1, class Triangle, class DiagonalStorage, [*in-matrix*](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat2, [*out-matrix*](#concept:out-matrix "29.9.7.5 Argument 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); templatevoid 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.5 Argument concepts [linalg.helpers.concepts]") InMat1, class Triangle, class DiagonalStorage, [*in-matrix*](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat2, [*out-matrix*](#concept:out-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") OutMat>void triangular_matrix_matrix_left_solve(InMat1 A, Triangle t, DiagonalStorage d, InMat2 B, OutMat X); templatevoid 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.5 Argument concepts [linalg.helpers.concepts]") InMat1, class Triangle, class DiagonalStorage, [*in-matrix*](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat2, [*out-matrix*](#concept:out-matrix "29.9.7.5 Argument 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); templatevoid 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.5 Argument concepts [linalg.helpers.concepts]") InMat1, class Triangle, class DiagonalStorage, [*in-matrix*](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat2, [*out-matrix*](#concept:out-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") OutMat>void triangular_matrix_matrix_right_solve(InMat1 A, Triangle t, DiagonalStorage d, InMat2 B, OutMat X); templatevoid 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.5 Argument concepts [linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage, [*inout-matrix*](#concept:inout-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InOutMat, class BinaryDivideOp>void triangular_matrix_matrix_left_solve(InMat A, Triangle t, DiagonalStorage d, InOutMat B, BinaryDivideOp divide); templatevoid 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.5 Argument concepts [linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage, [*inout-matrix*](#concept:inout-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InOutMat>void triangular_matrix_matrix_left_solve(InMat A, Triangle t, DiagonalStorage d, InOutMat B); templatevoid 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.5 Argument concepts [linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage, [*inout-matrix*](#concept:inout-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InOutMat, class BinaryDivideOp>void triangular_matrix_matrix_right_solve(InMat A, Triangle t, DiagonalStorage d, InOutMat B, BinaryDivideOp divide); templatevoid 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.5 Argument concepts [linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage, [*inout-matrix*](#concept:inout-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InOutMat>void triangular_matrix_matrix_right_solve(InMat A, Triangle t, DiagonalStorage d, InOutMat B); templatevoid 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.3 General [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.3 General [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.3 General [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) templatevoid triangular_matrix_vector_2x2_product( mdspan> m, Triangle t, mdspan> x, mdspan> y) {static_assert(is_same_v || is_same_v); if constexpr (is_same_v) { 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.1 Linear 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.6 Object 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.2 Algorithm 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.5 Solve a triangular linear system"),[[linalg.algs.blas3.trmm]](#algs.blas3.trmm "29.9.15.3 In-place triangular matrix-matrix product"),[[linalg.algs.blas3.trsm]](#algs.blas3.trsm "29.9.15.6 Solve multiple triangular linear systems"), and[[linalg.algs.blas3.inplacetrsm]](#algs.blas3.inplacetrsm "29.9.15.7 Solve multiple triangular linear systems in-place") either have a BinaryDivideOp template parameter (see [[linalg.algs.reqs]](#algs.reqs "29.9.12 Algorithm 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.13 BLAS 1 algorithms"), [[linalg.algs.blas2]](#algs.blas2 "29.9.14 BLAS 2 algorithms"), and [[linalg.algs.blas3]](#algs.blas3 "29.9.15 BLAS 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.2 Algorithm 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.6 Layouts 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.1 Storage order tags [linalg.tags.order]") { explicit column_major_t() = default; }; inline constexpr column_major_t [column_major](#lib:column_major "29.9.5.1 Storage order tags [linalg.tags.order]"){}; struct [row_major_t](#lib:row_major_t "29.9.5.1 Storage order tags [linalg.tags.order]") { explicit row_major_t() = default; }; inline constexpr row_major_t [row_major](#lib:row_major "29.9.5.1 Storage 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.2 Triangle tags [linalg.tags.triangle]") { explicit upper_triangle_t() = default; }; inline constexpr upper_triangle_t [upper_triangle](#lib:upper_triangle "29.9.5.2 Triangle tags [linalg.tags.triangle]"){}; struct [lower_triangle_t](#lib:lower_triangle_t "29.9.5.2 Triangle tags [linalg.tags.triangle]") { explicit lower_triangle_t() = default; }; inline constexpr lower_triangle_t [lower_triangle](#lib:lower_triangle "29.9.5.2 Triangle 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.3 General"))[.](#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.3 Diagonal 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.3 Diagonal tags [linalg.tags.diagonal]"){}; struct [explicit_diagonal_t](#lib:explicit_diagonal_t "29.9.5.3 Diagonal tags [linalg.tags.diagonal]") { explicit explicit_diagonal_t() = default; }; inline constexpr explicit_diagonal_t [explicit_diagonal](#lib:explicit_diagonal "29.9.5.3 Diagonal 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.3 General"))[.](#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.3 General"))[.](#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 {templateclass [layout_blas_packed](#lib:layout_blas_packed "29.9.6.1 Overview [linalg.layout.packed.overview]") {public:using triangle_type = Triangle; using storage_order_type = StorageOrder; templatestruct 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.2 Constructors"), constructorsconstexpr mapping() noexcept = default; constexpr mapping(const mapping&) noexcept = default; constexpr mapping(const extents_type&) noexcept; templateconstexpr explicit(!is_convertible_v) mapping(const mapping& other) noexcept; constexpr mapping& operator=(const mapping&) noexcept = default; // [[linalg.layout.packed.obs]](#layout.packed.obs "29.9.6.3 Observers"), observersconstexpr const extents_type& extents() const noexcept { return *extents_*; }constexpr index_type required_span_size() const noexcept; templateconstexpr 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; templatefriend constexpr bool operator==(const mapping&, const mapping&) 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​::​mapping is a trivially copyable type that models [regular](concepts.object#concept:regular "18.6 Object 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.2 Fundamental 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 explicit(!is_convertible_v) constexpr mapping(const mapping& other) noexcept; ` [3](#layout.packed.cons-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12175) *Constraints*: is_constructible_v 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.2 Fundamental 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 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 is true, - [(2.2)](#layout.packed.obs-2.2) is_convertible_v is true, - [(2.3)](#layout.packed.obs-2.3) is_nothrow_constructible_v is true, and - [(2.4)](#layout.packed.obs-2.4) is_nothrow_constructible_v 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.1 Overview"))[.](#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 && is_same_v is true oris_same_v && is_same_v 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 friend constexpr bool operator==(const mapping& x, const mapping& 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 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 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 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 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) templateconstexpr bool *is-mdspan* = false; templateconstexpr bool *is-mdspan*> = true; templateconcept [*in-vector*](#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") =*is-mdspan* && T::rank() == 1; templateconcept [*out-vector*](#concept:out-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") =*is-mdspan* && T::rank() == 1 && is_assignable_v && T::is_always_unique(); templateconcept [*inout-vector*](#concept:inout-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") =*is-mdspan* && T::rank() == 1 && is_assignable_v && T::is_always_unique(); templateconcept [*in-matrix*](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") =*is-mdspan* && T::rank() == 2; templateconcept [*out-matrix*](#concept:out-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") =*is-mdspan* && T::rank() == 2 && is_assignable_v && T::is_always_unique(); templateconcept [*inout-matrix*](#concept:inout-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") =*is-mdspan* && T::rank() == 2 && is_assignable_v && T::is_always_unique(); templateconstexpr bool *is-layout-blas-packed* = false; // *exposition only*templateconstexpr bool *is-layout-blas-packed*> = true; templateconcept [*possibly-packed-inout-matrix*](#concept:possibly-packed-inout-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") =*is-mdspan* && T::rank() == 2 && is_assignable_v &&(T::is_always_unique() || *is-layout-blas-packed*); templateconcept [*in-object*](#concept:in-object "29.9.7.5 Argument concepts [linalg.helpers.concepts]") =*is-mdspan* && (T::rank() == 1 || T::rank() == 2); templateconcept [*out-object*](#concept:out-object "29.9.7.5 Argument concepts [linalg.helpers.concepts]") =*is-mdspan* && (T::rank() == 1 || T::rank() == 2) && is_assignable_v && T::is_always_unique(); templateconcept [*inout-object*](#concept:inout-object "29.9.7.5 Argument concepts [linalg.helpers.concepts]") =*is-mdspan* && (T::rank() == 1 || T::rank() == 2) && is_assignable_v && 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.5 Argument concepts [linalg.helpers.concepts]"),[*in-matrix*](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]"), or[*in-object*](#concept:in-object "29.9.7.5 Argument 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.5 Argument concepts [linalg.helpers.concepts]"),[*inout-matrix*](#concept:inout-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]"),[*inout-object*](#concept:inout-object "29.9.7.5 Argument concepts [linalg.helpers.concepts]"),[*out-vector*](#concept:out-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]"),[*out-matrix*](#concept:out-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]"),[*out-object*](#concept:out-object "29.9.7.5 Argument concepts [linalg.helpers.concepts]"), or[*possibly-packed-inout-matrix*](#concept:possibly-packed-inout-matrix "29.9.7.5 Argument 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*] templaterequires(*is-mdspan* && *is-mdspan*)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.5 Argument concepts [linalg.helpers.concepts]") In1, [*in-vector*](#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") In2, [*in-vector*](#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") Out>constexpr bool *possibly-addable*() { // *exposition only*return *compatible-static-extents*(0, 0) &&*compatible-static-extents*(0, 0) &&*compatible-static-extents*(0, 0); }template<[*in-matrix*](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") In1, [*in-matrix*](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") In2, [*in-matrix*](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") Out>constexpr bool *possibly-addable*() { // *exposition only*return *compatible-static-extents*(0, 0) &&*compatible-static-extents*(1, 1) &&*compatible-static-extents*(0, 0) &&*compatible-static-extents*(1, 1) &&*compatible-static-extents*(0, 0) &&*compatible-static-extents*(1, 1); }template<[*in-matrix*](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat, [*in-vector*](#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec, [*in-vector*](#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") OutVec>constexpr bool *possibly-multipliable*() { // *exposition only*return *compatible-static-extents*(0, 0) &&*compatible-static-extents*(1, 0); }template<[*in-vector*](#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec, [*in-matrix*](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat, [*in-vector*](#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") OutVec>constexpr bool *possibly-multipliable*() { // *exposition only*return *compatible-static-extents*(0, 1) &&*compatible-static-extents*(0, 0); }template<[*in-matrix*](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat1, [*in-matrix*](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat2, [*in-matrix*](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") OutMat>constexpr bool *possibly-multipliable*() { // *exposition only*return *compatible-static-extents*(0, 0) &&*compatible-static-extents*(1, 1) &&*compatible-static-extents*(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.5 Argument concepts [linalg.helpers.concepts]") auto& in1, const [*in-vector*](#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") auto& in2, const [*in-vector*](#concept:in-vector "29.9.7.5 Argument 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.5 Argument concepts [linalg.helpers.concepts]") auto& in1, const [*in-matrix*](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") auto& in2, const [*in-matrix*](#concept:in-matrix "29.9.7.5 Argument 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.5 Argument concepts [linalg.helpers.concepts]") auto& in_mat, const [*in-vector*](#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") auto& in_vec, const [*in-vector*](#concept:in-vector "29.9.7.5 Argument 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.5 Argument concepts [linalg.helpers.concepts]") auto& in_vec, const [*in-matrix*](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") auto& in_mat, const [*in-vector*](#concept:in-vector "29.9.7.5 Argument 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.5 Argument concepts [linalg.helpers.concepts]") auto& in_mat1, const [*in-matrix*](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") auto& in_mat2, const [*in-matrix*](#concept:in-matrix "29.9.7.5 Argument 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>; // 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.3 Function template scaled"))[.](#scaled.scaledaccessor-1.sentence-2) namespace std::linalg {templateclass [scaled_accessor](#lib:scaled_accessor "29.9.8.2 Class template scaled_­accessor [linalg.scaled.scaledaccessor]") {public:using element_type = add_const_t() * declval())>; using reference = remove_const_t; using data_handle_type = NestedAccessor::data_handle_type; using offset_policy = scaled_accessor; constexpr scaled_accessor() = default; templateexplicit(!is_convertible_v)constexpr scaled_accessor(const scaled_accessor& 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 is true, - [(2.3)](#scaled.scaledaccessor-2.3) is_reference_v is false, - [(2.4)](#scaled.scaledaccessor-2.4) ScalingFactor models [semiregular](concepts.object#concept:semiregular "18.6 Object 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.2 Requirements"))[.](#scaled.scaledaccessor-2.sentence-1) [🔗](#lib:scaled_accessor,constructor) `template explicit(!is_convertible_v) constexpr scaled_accessor(const scaled_accessor& other); ` [3](#scaled.scaledaccessor-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12654) *Constraints*: is_constructible_v 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 constexpr auto scaled(ScalingFactor alpha, mdspan x); ` [2](#scaled.scaled-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12728) Let SA be scaled_accessor[.](#scaled.scaled-2.sentence-1) [3](#scaled.scaled-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12731) *Returns*: mdspan(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> 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.3 Function template conjugated"))[.](#conj.conjugatedaccessor-1.sentence-2) namespace std::linalg {templateclass [conjugated_accessor](#lib:conjugated_accessor "29.9.9.2 Class template conjugated_­accessor [linalg.conj.conjugatedaccessor]") {public:using element_type = add_const_t()))>; using reference = remove_const_t; using data_handle_type = typename NestedAccessor::data_handle_type; using offset_policy = conjugated_accessor; constexpr conjugated_accessor() = default; templateexplicit(!is_convertible_v>)constexpr conjugated_accessor(const conjugated_accessor& 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 is true, - [(2.3)](#conj.conjugatedaccessor-2.3) is_reference_v 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.2 Requirements"))[.](#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 explicit(!is_convertible_v>) constexpr conjugated_accessor(const conjugated_accessor& other); ` [4](#conj.conjugatedaccessor-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12834) *Constraints*: is_constructible_v 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 constexpr auto [conjugated](#lib:conjugated "29.9.9.3 Function template conjugated [linalg.conj.conjugated]")(mdspan 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 if Accessor is a specialization of conjugated_accessor; - [(1.2)](#conj.conjugated-1.2) otherwise,Accessor if remove_cvref_t is an arithmetic type; - [(1.3)](#conj.conjugated-1.3) otherwise,conjugated_accessor if the expression conj(E) is valid for any subexpression E whose type is remove_cvref_t with overload resolution performed in a context that includes the declarationtemplate 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[.](#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 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, extents> 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> 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* 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 constexpr extents transpose-extents(const extents& in); // exposition only ` [3](#transp.helpers-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12973) *Returns*: extents(in.extent(1), in.extent(0)) templateusing *transpose-extents-t* =decltype(*transpose-extents*(declval())); // *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 {templateclass [layout_transpose](#lib:layout_transpose "29.9.10.3 Class template layout_­transpose [linalg.transp.layout.transpose]") {public:using nested_layout_type = Layout; templatestruct mapping {private:using *nested-mapping-type* =typename Layout::template mapping<*transpose-extents-t*>; // *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(); templateconstexpr 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; templatefriend constexpr bool operator==(const mapping& x, const mapping& 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.3 Layout 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 friend constexpr bool operator==(const mapping& x, const mapping& 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 constexpr auto transposed(mdspan 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*[.](#transp.transposed-3.sentence-1) Let R bemdspan, 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 if Layout is layout_left_padded for some size_t value PaddingValue; - [(3.4)](#transp.transposed-3.4) otherwise, layout_left_padded if Layout is layout_right_padded 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, if Layout is layout_blas_packed for some Triangle and StorageOrder, where * [(3.6.1)](#transp.transposed-3.6.1) OppositeTriangle isconditional_t, lower_triangle_t, upper_triangle_t> and * [(3.6.2)](#transp.transposed-3.6.2) OppositeStorageOrder isconditional_t, row_major_t, column_major_t> - [(3.7)](#transp.transposed-3.7) otherwise, NestedLayout if Layout is layout_transpose for some NestedLayout; - [(3.8)](#transp.transposed-3.8) otherwise, layout_transpose[.](#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: - [(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 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 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> 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 constexpr auto conjugate_transposed(mdspan 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, extents> 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.13 BLAS 1 algorithms"), [[linalg.algs.blas2]](#algs.blas2 "29.9.14 BLAS 2 algorithms"), and [[linalg.algs.blas3]](#algs.blas3 "29.9.15 BLAS 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​::​value is true ([[execpol.type]](execpol.type "26.3.6.2 Execution policy type trait"))[.](#algs.reqs-1.1.sentence-1) - [(1.2)](#algs.reqs-1.2) Real is any type such that complex is specified ([[complex.numbers.general]](complex.numbers.general "29.4.1 General"))[.](#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.1 Preamble"))[.](#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.13 BLAS 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 setup_givens_rotation_result setup_givens_rotation(Real a, Real b) noexcept; template setup_givens_rotation_result> setup_givens_rotation(complex a, complex 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.5 Argument concepts [linalg.helpers.concepts]") InOutVec1, [inout-vector](#concept:inout-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InOutVec2, class Real> void apply_givens_rotation(InOutVec1 x, InOutVec2 y, Real c, Real s); template void apply_givens_rotation(ExecutionPolicy&& exec, InOutVec1 x, InOutVec2 y, Real c, Real s); template<[inout-vector](#concept:inout-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InOutVec1, [inout-vector](#concept:inout-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InOutVec2, class Real> void apply_givens_rotation(InOutVec1 x, InOutVec2 y, Real c, complex s); template void apply_givens_rotation(ExecutionPolicy&& exec, InOutVec1 x, InOutVec2 y, Real c, complex 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*(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.5 Argument concepts [linalg.helpers.concepts]") InOutObj1, [inout-object](#concept:inout-object "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InOutObj2> void swap_elements(InOutObj1 x, InOutObj2 y); template 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*(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 void scale(Scalar alpha, InOutObj x); template 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.5 Argument concepts [linalg.helpers.concepts]") InObj, [out-object](#concept:out-object "29.9.7.5 Argument concepts [linalg.helpers.concepts]") OutObj> void copy(InObj x, OutObj y); template 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*(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.5 Argument concepts [linalg.helpers.concepts]") InObj1, [in-object](#concept:in-object "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InObj2, [out-object](#concept:out-object "29.9.7.5 Argument concepts [linalg.helpers.concepts]") OutObj> void add(InObj1 x, InObj2 y, OutObj z); template 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*() 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.7 Dot 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*(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.5 Argument concepts [linalg.helpers.concepts]") InVec1, [in-vector](#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec2, class Scalar> Scalar dot(InVec1 v1, InVec2 v2, Scalar init); template 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.5 Argument concepts [linalg.helpers.concepts]") InVec1, [in-vector](#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec2> auto dot(InVec1 v1, InVec2 v2); template 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() * declval())[.](#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(exec), v1, v2, T{}); [🔗](#lib:dotc) `template<[in-vector](#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec1, [in-vector](#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec2, class Scalar> Scalar dotc(InVec1 v1, InVec2 v2, Scalar init); template 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(exec), conjugated(v1), v2, init); [🔗](#lib:dotc_) `template<[in-vector](#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec1, [in-vector](#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec2> auto dotc(InVec1 v1, InVec2 v2); template 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()) * declval())[.](#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(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.5 Argument concepts [linalg.helpers.concepts]") InVec, class Scalar> sum_of_squares_result vector_sum_of_squares(InVec v, sum_of_squares_result init); template sum_of_squares_result vector_sum_of_squares(ExecutionPolicy&& exec, InVec v, sum_of_squares_result 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())) 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.5 Argument concepts [linalg.helpers.concepts]") InVec, class Scalar> Scalar vector_two_norm(InVec v, Scalar init); template 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())[.](#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.5 Argument concepts [linalg.helpers.concepts]") InVec> auto vector_two_norm(InVec v); template 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())[.](#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(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.5 Argument concepts [linalg.helpers.concepts]") InVec, class Scalar> Scalar vector_abs_sum(InVec v, Scalar init); template 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())) +*abs-if-needed*(*imag-if-needed*(declval()))) 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.5 Argument concepts [linalg.helpers.concepts]") InVec> auto vector_abs_sum(InVec v); template 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(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.5 Argument concepts [linalg.helpers.concepts]") InVec> typename InVec::extents_type vector_idx_abs_max(InVec v); template 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())) +*abs-if-needed*(*imag-if-needed*(declval()))) [3](#algs.blas1.iamax-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13965) *Mandates*: declval() < declval() 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​::​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.5 Argument concepts [linalg.helpers.concepts]") InMat, class Scalar> Scalar matrix_frob_norm(InMat A, Scalar init); template 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())[.](#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.5 Argument concepts [linalg.helpers.concepts]") InMat> auto matrix_frob_norm(InMat A); template 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())[.](#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(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.5 Argument concepts [linalg.helpers.concepts]") InMat, class Scalar> Scalar matrix_one_norm(InMat A, Scalar init); template 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())) 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.5 Argument concepts [linalg.helpers.concepts]") InMat> auto matrix_one_norm(InMat A); template 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())[.](#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(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.5 Argument concepts [linalg.helpers.concepts]") InMat, class Scalar> Scalar matrix_inf_norm(InMat A, Scalar init); template 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())) 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.5 Argument concepts [linalg.helpers.concepts]") InMat> auto matrix_inf_norm(InMat A); template 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())[.](#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(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.1 General 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*() is true, and - [(3.2)](#algs.blas2.gemv-3.2) *possibly-addable*() 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.5 Argument concepts [linalg.helpers.concepts]") InMat, [in-vector](#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec, [out-vector](#concept:out-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") OutVec> void matrix_vector_product(InMat A, InVec x, OutVec y); template 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> A, mdspan> x, mdspan> y) { matrix_vector_product(scaled(3.0, A), x, y);}// z = 7.0 times the transpose of A, times yvoid scaled_transposed_matvec(mdspan> A, mdspan> y, mdspan> 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.5 Argument concepts [linalg.helpers.concepts]") InMat, [in-vector](#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec1, [in-vector](#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec2, [out-vector](#concept:out-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") OutVec> void matrix_vector_product(InMat A, InVec1 x, InVec2 y, OutVec z); template 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> A, mdspan> x, mdspan> 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.2 Symmetric 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*(0, 1) is true; - [(3.3)](#algs.blas2.symv-3.3) *possibly-multipliable*() is true; and - [(3.4)](#algs.blas2.symv-3.4) *possibly-addable*() 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.5 Argument concepts [linalg.helpers.concepts]") InMat, class Triangle, [in-vector](#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec, [out-vector](#concept:out-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") OutVec> void symmetric_matrix_vector_product(InMat A, Triangle t, InVec x, OutVec y); template 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.3 General"))[.](#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.5 Argument concepts [linalg.helpers.concepts]") InMat, class Triangle, [in-vector](#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec1, [in-vector](#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec2, [out-vector](#concept:out-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") OutVec> void symmetric_matrix_vector_product(InMat A, Triangle t, InVec1 x, InVec2 y, OutVec z); template 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.3 General"))[.](#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.3 Hermitian 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*(0, 1) is true; - [(3.3)](#algs.blas2.hemv-3.3) *possibly-multipliable*() is true; and - [(3.4)](#algs.blas2.hemv-3.4) *possibly-addable*() 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.5 Argument concepts [linalg.helpers.concepts]") InMat, class Triangle, [in-vector](#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec, [out-vector](#concept:out-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") OutVec> void hermitian_matrix_vector_product(InMat A, Triangle t, InVec x, OutVec y); template 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.3 General"))[.](#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.5 Argument concepts [linalg.helpers.concepts]") InMat, class Triangle, [in-vector](#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec1, [in-vector](#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec2, [out-vector](#concept:out-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") OutVec> void hermitian_matrix_vector_product(InMat A, Triangle t, InVec1 x, InVec2 y, OutVec z); template 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.3 General"))[.](#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.4 Triangular 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*(0, 1) is true; - [(3.3)](#algs.blas2.trmv-3.3) *compatible-static-extents*(0, 0) is true; - [(3.4)](#algs.blas2.trmv-3.4) *compatible-static-extents*(0, 0) is true for those overloads that take an x parameter; and - [(3.5)](#algs.blas2.trmv-3.5) *compatible-static-extents*(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.5 Argument concepts [linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage, [in-vector](#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec, [out-vector](#concept:out-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") OutVec> void triangular_matrix_vector_product(InMat A, Triangle t, DiagonalStorage d, InVec x, OutVec y); template 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.3 General"))[.](#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.5 Argument concepts [linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage, [inout-vector](#concept:inout-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InOutVec> void triangular_matrix_vector_product(InMat A, Triangle t, DiagonalStorage d, InOutVec y); template 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.3 General"))[.](#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.5 Argument concepts [linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage, [in-vector](#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec1, [in-vector](#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec2, [out-vector](#concept:out-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") OutVec> void triangular_matrix_vector_product(InMat A, Triangle t, DiagonalStorage d, InVec1 x, InVec2 y, OutVec z); template 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.3 General"))[.](#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.5 Solve 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*(0, 1) is true; - [(3.3)](#algs.blas2.trsv-3.3) *compatible-static-extents*(0, 0) is true; and - [(3.4)](#algs.blas2.trsv-3.4) *compatible-static-extents*(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.5 Argument concepts [linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage, [in-vector](#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec, [out-vector](#concept:out-vector "29.9.7.5 Argument 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 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.3 General"))[.](#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.5 Argument concepts [linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage, [in-vector](#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec, [out-vector](#concept:out-vector "29.9.7.5 Argument 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{}); [🔗](#lib:triangular_matrix_vector_solve__) `template 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(exec), A, t, d, b, x, divides{}); [🔗](#lib:triangular_matrix_vector_solve___) `template<[in-matrix](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage, [inout-vector](#concept:inout-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InOutVec, class BinaryDivideOp> void triangular_matrix_vector_solve(InMat A, Triangle t, DiagonalStorage d, InOutVec b, BinaryDivideOp divide); template 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.3 General"))[.](#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.5 Argument concepts [linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage, [inout-vector](#concept:inout-vector "29.9.7.5 Argument 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{}); [🔗](#lib:triangular_matrix_vector_solve_____) `template 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(exec), A, t, d, b, divides{}); #### [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.5 Argument concepts [linalg.helpers.concepts]") InVec1, [in-vector](#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec2, [inout-matrix](#concept:inout-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InOutMat> void matrix_rank_1_update(InVec1 x, InVec2 y, InOutMat A); template 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*() 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.5 Argument concepts [linalg.helpers.concepts]") InVec1, [in-vector](#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec2, [inout-matrix](#concept:inout-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InOutMat> void matrix_rank_1_update_c(InVec1 x, InVec2 y, InOutMat A); template 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(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.7 Symmetric 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*(0, 1) is true; and - [(3.3)](#algs.blas2.symherrank1-3.3) *compatible-static-extents*(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 void symmetric_matrix_rank_1_update(Scalar alpha, InVec x, InOutMat A, Triangle t); template 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.3 General"))[.](#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.5 Argument concepts [linalg.helpers.concepts]") InVec, [possibly-packed-inout-matrix](#concept:possibly-packed-inout-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InOutMat, class Triangle> void symmetric_matrix_rank_1_update(InVec x, InOutMat A, Triangle t); template 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.3 General"))[.](#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 void hermitian_matrix_rank_1_update(Scalar alpha, InVec x, InOutMat A, Triangle t); template 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.3 General"))[.](#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.5 Argument concepts [linalg.helpers.concepts]") InVec, [possibly-packed-inout-matrix](#concept:possibly-packed-inout-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InOutMat, class Triangle> void hermitian_matrix_rank_1_update(InVec x, InOutMat A, Triangle t); template 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.3 General"))[.](#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.8 Symmetric 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*(0, 1) is true; and - [(3.3)](#algs.blas2.rank2-3.3) *possibly-multipliable*() 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.5 Argument concepts [linalg.helpers.concepts]") InVec1, [in-vector](#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec2, [possibly-packed-inout-matrix](#concept:possibly-packed-inout-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InOutMat, class Triangle> void symmetric_matrix_rank_2_update(InVec1 x, InVec2 y, InOutMat A, Triangle t); template 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.3 General"))[.](#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.5 Argument concepts [linalg.helpers.concepts]") InVec1, [in-vector](#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec2, [possibly-packed-inout-matrix](#concept:possibly-packed-inout-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InOutMat, class Triangle> void hermitian_matrix_rank_2_update(InVec1 x, InVec2 y, InOutMat A, Triangle t); template 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.3 General"))[.](#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.1 General 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*() 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.5 Argument concepts [linalg.helpers.concepts]") InMat1, [in-matrix](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat2, [out-matrix](#concept:out-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") OutMat> void matrix_product(InMat1 A, InMat2 B, OutMat C); template 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.5 Argument concepts [linalg.helpers.concepts]") InMat1, [in-matrix](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat2, [in-matrix](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat3, [out-matrix](#concept:out-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") OutMat> void matrix_product(InMat1 A, InMat2 B, InMat3 E, OutMat C); template 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*() 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.2 Symmetric, 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*() is true, and - [(3.2)](#algs.blas3.xxmm-3.2) *possibly-addable*() 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.5 Argument concepts [linalg.helpers.concepts]") InMat1, class Triangle, [in-matrix](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat2, [out-matrix](#concept:out-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") OutMat> void symmetric_matrix_product(InMat1 A, Triangle t, InMat2 B, OutMat C); template void symmetric_matrix_product(ExecutionPolicy&& exec, InMat1 A, Triangle t, InMat2 B, OutMat C); template<[in-matrix](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat1, class Triangle, [in-matrix](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat2, [out-matrix](#concept:out-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") OutMat> void hermitian_matrix_product(InMat1 A, Triangle t, InMat2 B, OutMat C); template void hermitian_matrix_product(ExecutionPolicy&& exec, InMat1 A, Triangle t, InMat2 B, OutMat C); template<[in-matrix](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat1, class Triangle, class DiagonalStorage, [in-matrix](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat2, [out-matrix](#concept:out-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") OutMat> void triangular_matrix_product(InMat1 A, Triangle t, DiagonalStorage d, InMat2 B, OutMat C); template 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.3 General"))[.](#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*(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.5 Argument concepts [linalg.helpers.concepts]") InMat1, [in-matrix](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat2, class Triangle, [out-matrix](#concept:out-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") OutMat> void symmetric_matrix_product(InMat1 A, InMat2 B, Triangle t, OutMat C); template void symmetric_matrix_product(ExecutionPolicy&& exec, InMat1 A, InMat2 B, Triangle t, OutMat C); template<[in-matrix](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat1, [in-matrix](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat2, class Triangle, [out-matrix](#concept:out-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") OutMat> void hermitian_matrix_product(InMat1 A, InMat2 B, Triangle t, OutMat C); template void hermitian_matrix_product(ExecutionPolicy&& exec, InMat1 A, InMat2 B, Triangle t, OutMat C); template<[in-matrix](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat1, [in-matrix](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat2, class Triangle, class DiagonalStorage, [out-matrix](#concept:out-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") OutMat> void triangular_matrix_product(InMat1 A, InMat2 B, Triangle t, DiagonalStorage d, OutMat C); template 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.3 General"))[.](#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*(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.5 Argument concepts [linalg.helpers.concepts]") InMat1, class Triangle, [in-matrix](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat2, [in-matrix](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat3, [out-matrix](#concept:out-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") OutMat> void symmetric_matrix_product(InMat1 A, Triangle t, InMat2 B, InMat3 E, OutMat C); template 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.5 Argument concepts [linalg.helpers.concepts]") InMat1, class Triangle, [in-matrix](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat2, [in-matrix](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat3, [out-matrix](#concept:out-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") OutMat> void hermitian_matrix_product(InMat1 A, Triangle t, InMat2 B, InMat3 E, OutMat C); template 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.5 Argument concepts [linalg.helpers.concepts]") InMat1, class Triangle, class DiagonalStorage, [in-matrix](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat2, [in-matrix](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat3, [out-matrix](#concept:out-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") OutMat> void triangular_matrix_product(InMat1 A, Triangle t, DiagonalStorage d, InMat2 B, InMat3 E, OutMat C); template 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.3 General"))[.](#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*(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.5 Argument concepts [linalg.helpers.concepts]") InMat1, [in-matrix](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat2, class Triangle, [in-matrix](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat3, [out-matrix](#concept:out-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") OutMat> void symmetric_matrix_product(InMat1 A, InMat2 B, Triangle t, InMat3 E, OutMat C); template 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.5 Argument concepts [linalg.helpers.concepts]") InMat1, [in-matrix](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat2, class Triangle, [in-matrix](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat3, [out-matrix](#concept:out-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") OutMat> void hermitian_matrix_product(InMat1 A, InMat2 B, Triangle t, InMat3 E, OutMat C); template 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.5 Argument concepts [linalg.helpers.concepts]") InMat1, [in-matrix](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat2, class Triangle, class DiagonalStorage, [in-matrix](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat3, [out-matrix](#concept:out-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") OutMat> void triangular_matrix_product(InMat1 A, InMat2 B, Triangle t, DiagonalStorage d, InMat3 E, OutMat C); template 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.3 General"))[.](#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*(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.3 General"))[.](#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.5 Argument concepts [linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage, [inout-matrix](#concept:inout-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InOutMat> void triangular_matrix_left_product(InMat A, Triangle t, DiagonalStorage d, InOutMat C); template 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*() is true; and - [(2.3)](#algs.blas3.trmm-2.3) *compatible-static-extents*(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.5 Argument concepts [linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage, [inout-matrix](#concept:inout-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InOutMat> void triangular_matrix_right_product(InMat A, Triangle t, DiagonalStorage d, InOutMat C); template 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*() is true; and - [(6.3)](#algs.blas3.trmm-6.3) *compatible-static-extents*(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.4 Rank-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*(0, 1) is true; - [(3.3)](#algs.blas3.rankk-3.3) *compatible-static-extents*(0, 1) is true; and - [(3.4)](#algs.blas3.rankk-3.4) *compatible-static-extents*(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 void symmetric_matrix_rank_k_update(Scalar alpha, InMat A, InOutMat C, Triangle t); template 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.5 Argument concepts [linalg.helpers.concepts]") InMat, [possibly-packed-inout-matrix](#concept:possibly-packed-inout-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InOutMat, class Triangle> void symmetric_matrix_rank_k_update(InMat A, InOutMat C, Triangle t); template 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 void hermitian_matrix_rank_k_update(Scalar alpha, InMat A, InOutMat C, Triangle t); template 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.5 Argument concepts [linalg.helpers.concepts]") InMat, [possibly-packed-inout-matrix](#concept:possibly-packed-inout-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InOutMat, class Triangle> void hermitian_matrix_rank_k_update(InMat A, InOutMat C, Triangle t); template 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.5 Rank-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*() is true; and - [(3.3)](#algs.blas3.rank2k-3.3) *compatible-static-extents*(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.5 Argument concepts [linalg.helpers.concepts]") InMat1, [in-matrix](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat2, [possibly-packed-inout-matrix](#concept:possibly-packed-inout-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InOutMat, class Triangle> void symmetric_matrix_rank_2k_update(InMat1 A, InMat2 B, InOutMat C, Triangle t); template 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.5 Argument concepts [linalg.helpers.concepts]") InMat1, [in-matrix](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat2, [possibly-packed-inout-matrix](#concept:possibly-packed-inout-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InOutMat, class Triangle> void hermitian_matrix_rank_2k_update(InMat1 A, InMat2 B, InOutMat C, Triangle t); template 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.5 Argument concepts [linalg.helpers.concepts]") InMat1, class Triangle, class DiagonalStorage, [in-matrix](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat2, [out-matrix](#concept:out-matrix "29.9.7.5 Argument 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 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.3 General"))[.](#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*() is true; and - [(3.3)](#algs.blas3.trsm-3.3) *compatible-static-extents*(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.5 Argument concepts [linalg.helpers.concepts]") InMat1, class Triangle, class DiagonalStorage, [in-matrix](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat2, [out-matrix](#concept:out-matrix "29.9.7.5 Argument 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{}); [🔗](#lib:triangular_matrix_matrix_left_solve__) `template 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(exec), A, t, d, B, X, divides{}); [🔗](#lib:triangular_matrix_matrix_right_solve) `template<[in-matrix](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat1, class Triangle, class DiagonalStorage, [in-matrix](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat2, [out-matrix](#concept:out-matrix "29.9.7.5 Argument 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 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.3 General"))[.](#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*() is true; and - [(11.3)](#algs.blas3.trsm-11.3) *compatible-static-extents*(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.5 Argument concepts [linalg.helpers.concepts]") InMat1, class Triangle, class DiagonalStorage, [in-matrix](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat2, [out-matrix](#concept:out-matrix "29.9.7.5 Argument 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{}); [🔗](#lib:triangular_matrix_matrix_right_solve__) `template 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(exec), A, t, d, B, X, divides{}); #### [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.5 Argument concepts [linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage, [inout-matrix](#concept:inout-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InOutMat, class BinaryDivideOp> void triangular_matrix_matrix_left_solve(InMat A, Triangle t, DiagonalStorage d, InOutMat B, BinaryDivideOp divide); template 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.3 General"))[.](#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*() is true; and - [(3.3)](#algs.blas3.inplacetrsm-3.3) *compatible-static-extents*(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.5 Argument concepts [linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage, [inout-matrix](#concept:inout-matrix "29.9.7.5 Argument 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{}); [🔗](#lib:triangular_matrix_matrix_left_solve_____) ` template 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(exec), A, t, d, B, divides{}); [🔗](#lib:triangular_matrix_matrix_right_solve___) `template<[in-matrix](#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage, [inout-matrix](#concept:inout-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InOutMat, class BinaryDivideOp> void triangular_matrix_matrix_right_solve(InMat A, Triangle t, DiagonalStorage d, InOutMat B, BinaryDivideOp divide); template 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.3 General"))[.](#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*() is true; and - [(10.3)](#algs.blas3.inplacetrsm-10.3) *compatible-static-extents*(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.5 Argument concepts [linalg.helpers.concepts]") InMat, class Triangle, class DiagonalStorage, [inout-matrix](#concept:inout-matrix "29.9.7.5 Argument 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{}); [🔗](#lib:triangular_matrix_matrix_right_solve_____) `template 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(exec), A, t, d, B, divides{});