<T>LAPACK 0.1.1
C++ Template Linear Algebra PACKage
Loading...
Searching...
No Matches
getrf_recursive.hpp
Go to the documentation of this file.
1
3//
4// Copyright (c) 2021-2023, University of Colorado Denver. All rights reserved.
5//
6// This file is part of <T>LAPACK.
7// <T>LAPACK is free software: you can redistribute it and/or modify it under
8// the terms of the BSD 3-Clause license. See the accompanying LICENSE file.
9
10#ifndef TLAPACK_GETRF_RECURSIVE_HH
11#define TLAPACK_GETRF_RECURSIVE_HH
12
14#include "tlapack/blas/gemm.hpp"
16#include "tlapack/blas/swap.hpp"
17#include "tlapack/blas/trsm.hpp"
19
20namespace tlapack {
21
55template <TLAPACK_SMATRIX matrix_t, TLAPACK_SVECTOR piv_t>
57{
58 using idx_t = size_type<matrix_t>;
59 using T = type_t<matrix_t>;
60 using real_t = real_type<T>;
62
63 // Using the following lines to pass the abs function to iamax
64 IamaxOpts optsIamax([](const T& x) -> real_t { return abs(x); });
65
66 // constants
67 const idx_t m = nrows(A);
68 const idx_t n = ncols(A);
69 const idx_t k = min(m, n);
70
71 // check arguments
72 tlapack_check((idx_t)size(piv) >= k);
73
74 // quick return
75 if (m <= 0 || n <= 0) return 0;
76
77 // base case of recursion; one column matrices or one row matrices
78 // one-row matrices
79 if (m == 1) {
80 // piv has one element
81 piv[0] = idx_t(0);
82 if (A(piv[0], 0) == real_t(0)) {
83 // in case which A(0,0) is zero, then we return 1 since in the first
84 // iteration we stopped
85 return 1;
86 }
87
88 return 0;
89 }
90
91 // one-column matrices
92 else if (n == 1) {
93 // when n==1, piv has one element, piv[0] needs to be swapped by the
94 // first row
95 piv[0] = iamax(col(A, 0), optsIamax);
96
97 // in the following case all elements are zero, and we return 1
98 if (A(piv[0], 0) == real_t(0)) return 1;
99
100 // in this case, we can safely swap since A(piv[0],0) is not zero
101 if (piv[0] != 0) {
102 const T aux = A(piv[0], 0);
103 A(piv[0], 0) = A(0, 0);
104 A(0, 0) = aux;
105 }
106
107 // by the previous comment, we can safely scale all elements of 0th
108 // column by 1/A(0,0)
109 auto l = slice(A, range(1, m), 0);
110 rscl((T)A(0, 0), l);
111
112 return 0;
113 }
114
115 // the case where m<n, we simply slice A into two parts, A0, a square matrix
116 // and A1 where A=[A0 , A1]
117 else if (m < n) {
118 auto A0 = tlapack::cols(A, range(0, m));
119 auto A1 = tlapack::cols(A, range(m, n));
120
121 int info = getrf_recursive(A0, piv);
122 if (info != 0) return info;
123
124 // swap the rows of A1 according to piv
125 for (idx_t j = 0; j < k; j++) {
126 if ((idx_t)piv[j] != j) {
127 auto vect1 = tlapack::row(A1, j);
128 auto vect2 = tlapack::row(A1, piv[j]);
130 }
131 }
132
133 // Solve triangular system A0 X = A1 and update A1
135
136 return 0;
137 }
138 else {
139 // Dimensions for the submatrices
140 idx_t k0 = k / 2;
141
142 // in this step, we break A into two matrices, A=[A0 , A1]
143 auto A0 = tlapack::cols(A, range(0, k0));
144 auto A1 = tlapack::cols(A, range(k0, n));
145
146 // piv0 is the first k0 elements of piv
147 auto piv0 = tlapack::slice(piv, range(0, k0));
148
149 // Apply getrf on the left of half of the matrix
150 int info = getrf_recursive(A0, piv0);
151 if (info != 0) return info;
152
153 // swap the rows of A1
154 for (idx_t j = 0; j < k0; j++) {
155 if ((idx_t)piv0[j] != j) {
156 auto vect1 = tlapack::row(A1, j);
157 auto vect2 = tlapack::row(A1, piv0[j]);
159 }
160 }
161
162 // partition A into the following four blocks:
163 auto A00 = tlapack::slice(A, range(0, k0), range(0, k0));
164 auto A01 = tlapack::slice(A, range(0, k0), range(k0, n));
165 auto A10 = tlapack::slice(A, range(k0, m), range(0, k0));
166 auto A11 = tlapack::slice(A, range(k0, m), range(k0, n));
167
168 // Take piv1 to be the second slice of of piv, meaning piv= [piv0, piv1]
169 auto piv1 = tlapack::slice(piv, range(k0, k));
170
171 // Solve the triangular system of equations given by A00 X = A01
173
174 // A11 <---- A11 - (A10 * A01)
176
177 // Finding LU factorization of A11 in place
179 if (info != 0) return info + k0;
180
181 // swap the rows of A10 according to the swapped rows of A11 by refering
182 // to piv1
183 for (idx_t j = 0; j < k - k0; j++) {
184 if ((idx_t)piv1[j] != j) {
185 auto vect1 = tlapack::row(A10, j);
186 auto vect2 = tlapack::row(A10, piv1[j]);
188 }
189 }
190
191 // Shift piv1, so piv will have the accurate representation of overall
192 // pivots
193 for (idx_t i = 0; i < k - k0; i++) {
194 piv1[i] += k0;
195 }
196
197 return 0;
198 }
199
200} // getrf_recursive
201
202} // namespace tlapack
203
204#endif // TLAPACK_GETRF_RECURSIVE_HH
constexpr internal::LowerTriangle LOWER_TRIANGLE
Lower Triangle access.
Definition types.hpp:183
constexpr internal::UnitDiagonal UNIT_DIAG
The main diagonal is assumed to consist of 1's.
Definition types.hpp:217
constexpr internal::NoTranspose NO_TRANS
no transpose
Definition types.hpp:255
constexpr internal::LeftSide LEFT_SIDE
left side
Definition types.hpp:289
void rscl(const alpha_t &alpha, vector_t &x)
Scale vector by the reciprocal of a constant, .
Definition rscl.hpp:22
void swap(vectorX_t &x, vectorY_t &y)
Swap vectors, .
Definition swap.hpp:31
size_type< vector_t > iamax(const vector_t &x, const IamaxOpts< abs_f > &opts)
Return .
Definition iamax.hpp:234
void gemm(Op transA, Op transB, const alpha_t &alpha, const matrixA_t &A, const matrixB_t &B, const beta_t &beta, matrixC_t &C)
General matrix-matrix multiply:
Definition gemm.hpp:61
void trsm(Side side, Uplo uplo, Op trans, Diag diag, const alpha_t &alpha, const matrixA_t &A, matrixB_t &B)
Solve the triangular matrix-vector equation.
Definition trsm.hpp:76
int getrf_recursive(matrix_t &A, piv_t &piv)
getrf_recursive computes an LU factorization of a general m-by-n matrix A using partial pivoting with...
Definition getrf_recursive.hpp:56
#define tlapack_check(cond)
Throw an error if cond is false.
Definition exceptionHandling.hpp:98
typename traits::real_type_traits< Types..., int >::type real_type
The common real type of the list of types.
Definition scalar_type_traits.hpp:113
Options for iamax.
Definition iamax.hpp:37