# 28 Numerics library [numerics]

## 28.9 Basic linear algebra algorithms [linalg]

### 28.9.15 BLAS 3 algorithms [linalg.algs.blas3]

#### 28.9.15.6 Solve multiple triangular linear systems [linalg.algs.blas3.trsm]

[Note 1:
These functions correspond to the BLAS function xTRSM[bib].
— end note]
```template<in-matrix InMat1, class Triangle, class DiagonalStorage, in-matrix InMat2, out-matrix OutMat, class BinaryDivideOp> void triangular_matrix_matrix_left_solve(InMat1 A, Triangle t, DiagonalStorage d, InMat2 B, OutMat X, BinaryDivideOp divide); template<class ExecutionPolicy, in-matrix InMat1, class Triangle, class DiagonalStorage, in-matrix InMat2, out-matrix OutMat, class BinaryDivideOp> void triangular_matrix_matrix_left_solve(ExecutionPolicy&& exec, InMat1 A, Triangle t, DiagonalStorage d, InMat2 B, OutMat X, BinaryDivideOp divide); ```
These functions perform multiple matrix solves, taking into account the Triangle and DiagonalStorage parameters that apply to the triangular matrix A ([linalg.general]).
Mandates:
• 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;
• possibly-multipliable<InMat1, OutMat, InMat2>() is true; and
• compatible-static-extents<InMat1, InMat1>(0, 1) is true.
Preconditions:
• multipliable(A, X, B) is true, and
• A.extent(0) == A.extent(1) is true.
Effects: Computes such that , and assigns each element of to the corresponding element of X.
If no such exists, then the elements of X are valid but unspecified.
Complexity: .
[Note 2:
Since the triangular matrix is on the left, the desired divide implementation in the case of noncommutative multiplication is mathematically equivalent to , where x is the first argument and y is the second argument, and denotes the multiplicative inverse of y.
— end note]
```template<in-matrix InMat1, class Triangle, class DiagonalStorage, in-matrix InMat2, out-matrix OutMat> void triangular_matrix_matrix_left_solve(InMat1 A, Triangle t, DiagonalStorage d, InMat2 B, OutMat X); ```
Effects: Equivalent to: triangular_matrix_matrix_left_solve(A, t, d, B, X, divides<void>{});
```template<class ExecutionPolicy, in-matrix InMat1, class Triangle, class DiagonalStorage, in-matrix InMat2, out-matrix OutMat> void triangular_matrix_matrix_left_solve(ExecutionPolicy&& exec, InMat1 A, Triangle t, DiagonalStorage d, InMat2 B, OutMat X); ```
Effects: Equivalent to: triangular_matrix_matrix_left_solve(std::forward<ExecutionPolicy>(exec), A, t, d, B, X, divides<void>{});
```template<in-matrix InMat1, class Triangle, class DiagonalStorage, in-matrix InMat2, out-matrix OutMat, class BinaryDivideOp> void triangular_matrix_matrix_right_solve(InMat1 A, Triangle t, DiagonalStorage d, InMat2 B, OutMat X, BinaryDivideOp divide); template<class ExecutionPolicy, in-matrix InMat1, class Triangle, class DiagonalStorage, in-matrix InMat2, out-matrix OutMat, class BinaryDivideOp> void triangular_matrix_matrix_right_solve(ExecutionPolicy&& exec, InMat1 A, Triangle t, DiagonalStorage d, InMat2 B, OutMat X, BinaryDivideOp divide); ```
These functions perform multiple matrix solves, taking into account the Triangle and DiagonalStorage parameters that apply to the triangular matrix A ([linalg.general]).
Mandates:
• 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;
• possibly-multipliable<OutMat, InMat1, InMat2>() is true; and
• compatible-static-extents<InMat1, InMat1>(0,1) is true.
Preconditions:
• multipliable(X, A, B) is true, and
• A.extent(0) == A.extent(1) is true.
Effects: Computes such that , and assigns each element of to the corresponding element of X.
If no such exists, then the elements of X are valid but unspecified.
Complexity: O( B.extent(0) B.extent(1) A.extent(1) )
[Note 3:
Since the triangular matrix is on the right, the desired divide implementation in the case of noncommutative multiplication is mathematically equivalent to , where x is the first argument and y is the second argument, and denotes the multiplicative inverse of y.
— end note]
```template<in-matrix InMat1, class Triangle, class DiagonalStorage, in-matrix InMat2, out-matrix OutMat> void triangular_matrix_matrix_right_solve(InMat1 A, Triangle t, DiagonalStorage d, InMat2 B, OutMat X); ```
Effects: Equivalent to: triangular_matrix_matrix_right_solve(A, t, d, B, X, divides<void>{});
```template<class ExecutionPolicy, in-matrix InMat1, class Triangle, class DiagonalStorage, in-matrix InMat2, out-matrix OutMat> void triangular_matrix_matrix_right_solve(ExecutionPolicy&& exec, InMat1 A, Triangle t, DiagonalStorage d, InMat2 B, OutMat X); ```
Effects: Equivalent to: triangular_matrix_matrix_right_solve(std::forward<ExecutionPolicy>(exec), A, t, d, B, X, divides<void>{});