68 #ifndef GMM_DENSE_LU_H
69 #define GMM_DENSE_LU_H
75 #if defined(GMM_USES_BLAS) || defined(GMM_USES_LAPACK)
76 typedef std::vector<BLAS_INT> lapack_ipvt;
78 typedef std::vector<size_type> lapack_ipvt;
91 template <
typename DenseMatrix,
typename Pvector>
92 size_type lu_factor(DenseMatrix& A, Pvector& ipvt) {
93 typedef typename linalg_traits<DenseMatrix>::value_type T;
94 typedef typename linalg_traits<Pvector>::value_type INT;
95 typedef typename number_traits<T>::magnitude_type R;
96 size_type info(0), i, j, jp, M(mat_nrows(A)), N(mat_ncols(A));
99 size_type NN = std::min(M, N);
100 std::vector<T> c(M), r(N);
102 GMM_ASSERT2(ipvt.size()+1 >= NN,
"IPVT too small");
103 for (i = 0; i+1 < NN; ++i) ipvt[i] = INT(i);
106 for (j = 0; j+1 < NN; ++j) {
107 R max = gmm::abs(A(j,j)); jp = j;
108 for (i = j+1; i < M; ++i)
109 if (gmm::abs(A(i,j)) > max) { jp = i; max = gmm::abs(A(i,j)); }
110 ipvt[j] = INT(jp + 1);
112 if (max == R(0)) { info = j + 1;
break; }
113 if (jp != j)
for (i = 0; i < N; ++i) std::swap(A(jp, i), A(j, i));
115 for (i = j+1; i < M; ++i) { A(i, j) /= A(j,j); c[i-j-1] = -A(i, j); }
116 for (i = j+1; i < N; ++i) r[i-j-1] = A(j, i);
117 rank_one_update(sub_matrix(A, sub_interval(j+1, M-j-1),
120 ipvt[NN-1] = INT(NN);
127 template <
typename DenseMatrix,
typename VectorB,
typename VectorX,
129 void lu_solve(
const DenseMatrix &LU,
const Pvector& pvector,
130 VectorX &x,
const VectorB &b) {
131 typedef typename linalg_traits<DenseMatrix>::value_type T;
133 for(size_type i = 0; i < pvector.size(); ++i) {
134 size_type perm =
size_type(pvector[i]-1);
135 if (i != perm) { T aux = x[i]; x[i] = x[perm]; x[perm] = aux; }
138 lower_tri_solve(LU, x,
true);
139 upper_tri_solve(LU, x,
false);
142 template <
typename DenseMatrix,
typename VectorB,
typename VectorX>
143 void lu_solve(
const DenseMatrix &A, VectorX &x,
const VectorB &b) {
144 typedef typename linalg_traits<DenseMatrix>::value_type T;
145 const size_type M(mat_nrows(A)), N(mat_ncols(A));
146 if (M == 0 || N == 0)
148 dense_matrix<T> B(M, N);
152 GMM_ASSERT1(!info,
"Singular system, pivot = " << info);
153 lu_solve(B, ipvt, x, b);
156 template <
typename DenseMatrix,
typename VectorB,
typename VectorX,
158 void lu_solve_transposed(
const DenseMatrix &LU,
const Pvector& pvector,
159 VectorX &x,
const VectorB &b) {
160 typedef typename linalg_traits<DenseMatrix>::value_type T;
162 lower_tri_solve(transposed(LU), x,
false);
163 upper_tri_solve(transposed(LU), x,
true);
164 for (
size_type i = pvector.size(); i > 0; --i) {
176 template <
typename DenseMatrixLU,
typename DenseMatrix,
typename Pvector>
177 void lu_inverse(
const DenseMatrixLU& LU,
const Pvector& pvector,
178 DenseMatrix& AInv, col_major) {
179 typedef typename linalg_traits<DenseMatrixLU>::value_type T;
180 std::vector<T> tmp(pvector.size(), T(0));
181 std::vector<T> result(pvector.size());
182 for(
size_type i = 0; i < pvector.size(); ++i) {
185 copy(result, mat_col(AInv, i));
190 template <
typename DenseMatrixLU,
typename DenseMatrix,
typename Pvector>
191 void lu_inverse(
const DenseMatrixLU& LU,
const Pvector& pvector,
192 DenseMatrix& AInv, row_major) {
193 typedef typename linalg_traits<DenseMatrixLU>::value_type T;
194 std::vector<T> tmp(pvector.size(), T(0));
195 std::vector<T> result(pvector.size());
196 for(
size_type i = 0; i < pvector.size(); ++i) {
202 lu_solve_transposed(LU, pvector, result, tmp);
203 copy(result, mat_row(AInv, i));
210 template <
typename DenseMatrixLU,
typename DenseMatrix,
typename Pvector>
211 void lu_inverse(
const DenseMatrixLU& LU,
const Pvector& pvector,
212 const DenseMatrix& AInv_) {
213 DenseMatrix& AInv =
const_cast<DenseMatrix&
>(AInv_);
214 lu_inverse(LU, pvector, AInv,
typename principal_orientation_type<
typename
215 linalg_traits<DenseMatrix>::sub_orientation>::potype());
220 template <
typename DenseMatrix>
221 typename linalg_traits<DenseMatrix>::value_type
222 lu_inverse(
const DenseMatrix& A_,
bool doassert =
true) {
223 typedef typename linalg_traits<DenseMatrix>::value_type T;
224 DenseMatrix& A =
const_cast<DenseMatrix&
>(A_);
225 const size_type M(mat_nrows(A)), N(mat_ncols(A));
226 if (M == 0 || N == 0)
228 dense_matrix<T> B(M, N);
231 size_type info = lu_factor(B, ipvt);
232 if (doassert) GMM_ASSERT1(!info,
"Non invertible matrix, pivot = "<<info);
233 if (!info) lu_inverse(B, ipvt, A);
234 return lu_det(B, ipvt);
238 template <
typename DenseMatrixLU,
typename Pvector>
239 typename linalg_traits<DenseMatrixLU>::value_type
240 lu_det(
const DenseMatrixLU& LU,
const Pvector &pvector) {
241 typedef typename linalg_traits<DenseMatrixLU>::value_type T;
242 typedef typename linalg_traits<Pvector>::value_type INT;
244 const size_type J=std::min(mat_nrows(LU), mat_ncols(LU));
245 for (size_type j = 0; j < J; ++j)
247 for(INT i = 0; i < INT(pvector.size()); ++i)
248 if (i != pvector[i]-1) { det = -det; }
252 template <
typename DenseMatrix>
253 typename linalg_traits<DenseMatrix>::value_type
254 lu_det(
const DenseMatrix& A) {
255 typedef typename linalg_traits<DenseMatrix>::value_type T;
256 const size_type M(mat_nrows(A)), N(mat_ncols(A));
257 if (M == 0 || N == 0)
259 dense_matrix<T> B(M, N);
263 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