69 #ifndef GMM_DENSE_LU_H
70 #define GMM_DENSE_LU_H
84 class lapack_ipvt :
public std::vector<size_type> {
87 {
return std::vector<size_type>::operator[](i); }
89 {
return std::vector<size_type>::operator[](i); }
90 void begin(
void)
const {}
92 void end(
void)
const {}
96 void set_to_int32() { is_int64 =
false; }
98 {
return &(*(std::vector<size_type>::begin())); }
99 size_type *pfirst() {
return &(*(std::vector<size_type>::begin())); }
105 return is_int64 ? p[i] :
size_type(((
const int *)(p))[i]);
109 if (is_int64) p[i] = val;
else ((
int *)(p))[i] = int(val);
128 template <
typename DenseMatrix>
129 size_type lu_factor(DenseMatrix& A, lapack_ipvt& ipvt) {
130 typedef typename linalg_traits<DenseMatrix>::value_type T;
131 typedef typename number_traits<T>::magnitude_type R;
132 size_type info(0), i, j, jp, M(mat_nrows(A)), N(mat_ncols(A));
133 size_type NN = std::min(M, N);
134 std::vector<T> c(M), r(N);
136 GMM_ASSERT2(ipvt.size()+1 >= NN,
"IPVT too small");
137 for (i = 0; i+1 < NN; ++i) ipvt.set(i, i);
140 for (j = 0; j+1 < NN; ++j) {
141 R max = gmm::abs(A(j,j)); jp = j;
142 for (i = j+1; i < M; ++i)
143 if (gmm::abs(A(i,j)) > max) { jp = i; max = gmm::abs(A(i,j)); }
146 if (max == R(0)) { info = j + 1;
break; }
147 if (jp != j)
for (i = 0; i < N; ++i) std::swap(A(jp, i), A(j, i));
149 for (i = j+1; i < M; ++i) { A(i, j) /= A(j,j); c[i-j-1] = -A(i, j); }
150 for (i = j+1; i < N; ++i) r[i-j-1] = A(j, i);
151 rank_one_update(sub_matrix(A, sub_interval(j+1, M-j-1),
161 template <
typename DenseMatrix,
typename VectorB,
typename VectorX,
163 void lu_solve(
const DenseMatrix &LU,
const Pvector& pvector,
164 VectorX &x,
const VectorB &b) {
165 typedef typename linalg_traits<DenseMatrix>::value_type T;
167 for(size_type i = 0; i < pvector.size(); ++i) {
168 size_type perm = pvector.get(i)-1;
169 if(i != perm) { T aux = x[i]; x[i] = x[perm]; x[perm] = aux; }
172 lower_tri_solve(LU, x,
true);
173 upper_tri_solve(LU, x,
false);
176 template <
typename DenseMatrix,
typename VectorB,
typename VectorX>
177 void lu_solve(
const DenseMatrix &A, VectorX &x,
const VectorB &b) {
178 typedef typename linalg_traits<DenseMatrix>::value_type T;
179 dense_matrix<T> B(mat_nrows(A), mat_ncols(A));
180 lapack_ipvt ipvt(mat_nrows(A));
183 GMM_ASSERT1(!info,
"Singular system, pivot = " << info);
184 lu_solve(B, ipvt, x, b);
187 template <
typename DenseMatrix,
typename VectorB,
typename VectorX,
189 void lu_solve_transposed(
const DenseMatrix &LU,
const Pvector& pvector,
190 VectorX &x,
const VectorB &b) {
191 typedef typename linalg_traits<DenseMatrix>::value_type T;
193 lower_tri_solve(transposed(LU), x,
false);
194 upper_tri_solve(transposed(LU), x,
true);
195 for(
size_type i = pvector.size(); i > 0; --i) {
197 if(i-1 != perm) { T aux = x[i-1]; x[i-1] = x[perm]; x[perm] = aux; }
203 template <
typename DenseMatrixLU,
typename DenseMatrix,
typename Pvector>
204 void lu_inverse(
const DenseMatrixLU& LU,
const Pvector& pvector,
205 DenseMatrix& AInv, col_major) {
206 typedef typename linalg_traits<DenseMatrixLU>::value_type T;
207 std::vector<T> tmp(pvector.size(), T(0));
208 std::vector<T> result(pvector.size());
209 for(
size_type i = 0; i < pvector.size(); ++i) {
212 copy(result, mat_col(AInv, i));
217 template <
typename DenseMatrixLU,
typename DenseMatrix,
typename Pvector>
218 void lu_inverse(
const DenseMatrixLU& LU,
const Pvector& pvector,
219 DenseMatrix& AInv, row_major) {
220 typedef typename linalg_traits<DenseMatrixLU>::value_type T;
221 std::vector<T> tmp(pvector.size(), T(0));
222 std::vector<T> result(pvector.size());
223 for(
size_type i = 0; i < pvector.size(); ++i) {
229 lu_solve_transposed(LU, pvector, result, tmp);
230 copy(result, mat_row(AInv, i));
237 template <
typename DenseMatrixLU,
typename DenseMatrix,
typename Pvector>
238 void lu_inverse(
const DenseMatrixLU& LU,
const Pvector& pvector,
239 const DenseMatrix& AInv_) {
240 DenseMatrix& AInv =
const_cast<DenseMatrix&
>(AInv_);
241 lu_inverse(LU, pvector, AInv,
typename principal_orientation_type<
typename
242 linalg_traits<DenseMatrix>::sub_orientation>::potype());
247 template <
typename DenseMatrix>
248 typename linalg_traits<DenseMatrix>::value_type
249 lu_inverse(
const DenseMatrix& A_,
bool doassert =
true) {
250 typedef typename linalg_traits<DenseMatrix>::value_type T;
251 DenseMatrix& A =
const_cast<DenseMatrix&
>(A_);
252 dense_matrix<T> B(mat_nrows(A), mat_ncols(A));
253 lapack_ipvt ipvt(mat_nrows(A));
255 size_type info = lu_factor(B, ipvt);
256 if (doassert) GMM_ASSERT1(!info,
"Non invertible matrix, pivot = "<<info);
257 if (!info) lu_inverse(B, ipvt, A);
258 return lu_det(B, ipvt);
262 template <
typename DenseMatrixLU,
typename Pvector>
263 typename linalg_traits<DenseMatrixLU>::value_type
264 lu_det(
const DenseMatrixLU& LU,
const Pvector &pvector) {
265 typedef typename linalg_traits<DenseMatrixLU>::value_type T;
267 for (size_type j = 0; j < std::min(mat_nrows(LU), mat_ncols(LU)); ++j)
269 for(size_type i = 0; i < pvector.size(); ++i)
270 if (i !=
size_type(pvector.get(i)-1)) { det = -det; }
274 template <
typename DenseMatrix>
275 typename linalg_traits<DenseMatrix>::value_type
276 lu_det(
const DenseMatrix& A) {
277 typedef typename linalg_traits<DenseMatrix>::value_type T;
278 dense_matrix<T> B(mat_nrows(A), mat_ncols(A));
279 lapack_ipvt ipvt(mat_nrows(A));
282 return lu_det(B, ipvt);