69 #ifndef GMM_DENSE_LU_H
70 #define GMM_DENSE_LU_H
76 #if defined(GMM_USES_BLAS) || defined(GMM_USES_LAPACK)
77 typedef std::vector<BLAS_INT> lapack_ipvt;
79 typedef std::vector<size_type> lapack_ipvt;
92 template <
typename DenseMatrix,
typename Pvector>
93 size_type lu_factor(DenseMatrix& A, Pvector& ipvt) {
94 typedef typename linalg_traits<DenseMatrix>::value_type T;
95 typedef typename linalg_traits<Pvector>::value_type INT;
96 typedef typename number_traits<T>::magnitude_type R;
97 size_type info(0), i, j, jp, M(mat_nrows(A)), N(mat_ncols(A));
100 size_type NN = std::min(M, N);
101 std::vector<T> c(M), r(N);
103 GMM_ASSERT2(ipvt.size()+1 >= NN,
"IPVT too small");
104 for (i = 0; i+1 < NN; ++i) ipvt[i] = INT(i);
107 for (j = 0; j+1 < NN; ++j) {
108 R max = gmm::abs(A(j,j)); jp = j;
109 for (i = j+1; i < M; ++i)
110 if (gmm::abs(A(i,j)) > max) { jp = i; max = gmm::abs(A(i,j)); }
111 ipvt[j] = INT(jp + 1);
113 if (max == R(0)) { info = j + 1;
break; }
114 if (jp != j)
for (i = 0; i < N; ++i) std::swap(A(jp, i), A(j, i));
116 for (i = j+1; i < M; ++i) { A(i, j) /= A(j,j); c[i-j-1] = -A(i, j); }
117 for (i = j+1; i < N; ++i) r[i-j-1] = A(j, i);
118 rank_one_update(sub_matrix(A, sub_interval(j+1, M-j-1),
121 ipvt[NN-1] = INT(NN);
128 template <
typename DenseMatrix,
typename VectorB,
typename VectorX,
130 void lu_solve(
const DenseMatrix &LU,
const Pvector& pvector,
131 VectorX &x,
const VectorB &b) {
132 typedef typename linalg_traits<DenseMatrix>::value_type T;
134 for(size_type i = 0; i < pvector.size(); ++i) {
135 size_type perm =
size_type(pvector[i]-1);
136 if (i != perm) { T aux = x[i]; x[i] = x[perm]; x[perm] = aux; }
139 lower_tri_solve(LU, x,
true);
140 upper_tri_solve(LU, x,
false);
143 template <
typename DenseMatrix,
typename VectorB,
typename VectorX>
144 void lu_solve(
const DenseMatrix &A, VectorX &x,
const VectorB &b) {
145 typedef typename linalg_traits<DenseMatrix>::value_type T;
146 const size_type M(mat_nrows(A)), N(mat_ncols(A));
147 if (M == 0 || N == 0)
149 dense_matrix<T> B(M, N);
153 GMM_ASSERT1(!info,
"Singular system, pivot = " << info);
154 lu_solve(B, ipvt, x, b);
157 template <
typename DenseMatrix,
typename VectorB,
typename VectorX,
159 void lu_solve_transposed(
const DenseMatrix &LU,
const Pvector& pvector,
160 VectorX &x,
const VectorB &b) {
161 typedef typename linalg_traits<DenseMatrix>::value_type T;
163 lower_tri_solve(transposed(LU), x,
false);
164 upper_tri_solve(transposed(LU), x,
true);
165 for (
size_type i = pvector.size(); i > 0; --i) {
177 template <
typename DenseMatrixLU,
typename DenseMatrix,
typename Pvector>
178 void lu_inverse(
const DenseMatrixLU& LU,
const Pvector& pvector,
179 DenseMatrix& AInv, col_major) {
180 typedef typename linalg_traits<DenseMatrixLU>::value_type T;
181 std::vector<T> tmp(pvector.size(), T(0));
182 std::vector<T> result(pvector.size());
183 for(
size_type i = 0; i < pvector.size(); ++i) {
186 copy(result, mat_col(AInv, i));
191 template <
typename DenseMatrixLU,
typename DenseMatrix,
typename Pvector>
192 void lu_inverse(
const DenseMatrixLU& LU,
const Pvector& pvector,
193 DenseMatrix& AInv, row_major) {
194 typedef typename linalg_traits<DenseMatrixLU>::value_type T;
195 std::vector<T> tmp(pvector.size(), T(0));
196 std::vector<T> result(pvector.size());
197 for(
size_type i = 0; i < pvector.size(); ++i) {
203 lu_solve_transposed(LU, pvector, result, tmp);
204 copy(result, mat_row(AInv, i));
211 template <
typename DenseMatrixLU,
typename DenseMatrix,
typename Pvector>
212 void lu_inverse(
const DenseMatrixLU& LU,
const Pvector& pvector,
213 const DenseMatrix& AInv_) {
214 DenseMatrix& AInv =
const_cast<DenseMatrix&
>(AInv_);
215 lu_inverse(LU, pvector, AInv,
typename principal_orientation_type<
typename
216 linalg_traits<DenseMatrix>::sub_orientation>::potype());
221 template <
typename DenseMatrix>
222 typename linalg_traits<DenseMatrix>::value_type
223 lu_inverse(
const DenseMatrix& A_,
bool doassert =
true) {
224 typedef typename linalg_traits<DenseMatrix>::value_type T;
225 DenseMatrix& A =
const_cast<DenseMatrix&
>(A_);
226 const size_type M(mat_nrows(A)), N(mat_ncols(A));
227 if (M == 0 || N == 0)
229 dense_matrix<T> B(M, N);
232 size_type info = lu_factor(B, ipvt);
233 if (doassert) GMM_ASSERT1(!info,
"Non invertible matrix, pivot = "<<info);
234 if (!info) lu_inverse(B, ipvt, A);
235 return lu_det(B, ipvt);
239 template <
typename DenseMatrixLU,
typename Pvector>
240 typename linalg_traits<DenseMatrixLU>::value_type
241 lu_det(
const DenseMatrixLU& LU,
const Pvector &pvector) {
242 typedef typename linalg_traits<DenseMatrixLU>::value_type T;
243 typedef typename linalg_traits<Pvector>::value_type INT;
245 const size_type J=std::min(mat_nrows(LU), mat_ncols(LU));
246 for (size_type j = 0; j < J; ++j)
248 for(INT i = 0; i < INT(pvector.size()); ++i)
249 if (i != pvector[i]-1) { det = -det; }
253 template <
typename DenseMatrix>
254 typename linalg_traits<DenseMatrix>::value_type
255 lu_det(
const DenseMatrix& A) {
256 typedef typename linalg_traits<DenseMatrix>::value_type T;
257 const size_type M(mat_nrows(A)), N(mat_ncols(A));
258 if (M == 0 || N == 0)
260 dense_matrix<T> B(M, N);
264 return lu_det(B, ipvt);
void copy(const L1 &l1, L2 &l2)
*/
conjugated_return< L >::return_type conjugated(const L &v)
return a conjugated view of the input matrix or vector.
Householder for dense matrices.
void lu_solve(const DenseMatrix &LU, const Pvector &pvector, VectorX &x, const VectorB &b)
LU Solve : Solve equation Ax=b, given an LU factored matrix.
Optimization for some small cases (inversion of 2x2 matrices etc.)
size_t size_type
used as the common size type in the library