/// Constructor takes matrix reference explicit diagonal(const Matrix& A) : inv_diag(num_rows(A)) { mtl::vampir_trace<5050> tracer; MTL_THROW_IF(num_rows(A) != num_cols(A), mtl::matrix_not_square()); using math::reciprocal; for (size_type i= 0; i < num_rows(A); ++i) inv_diag[i]= reciprocal(A[i][i]); }
// Undefined if matrix is not symmetric void factorize(const Matrix& A, mtl::tag::sparse) { using namespace mtl; using namespace mtl::tag; using mtl::traits::range_generator; using math::reciprocal; using mtl::matrix::upper; typedef typename range_generator<row, U_type>::type cur_type; typedef typename range_generator<nz, cur_type>::type icur_type; MTL_THROW_IF(num_rows(A) != num_cols(A), mtl::matrix_not_square()); U= upper(A); crop(U); U_type L(lower(A)); // needed to find non-zeros in column typename mtl::traits::col<U_type>::type col(U), col_l(L); typename mtl::traits::value<U_type>::type value(U); cur_type kc= begin<row>(U), kend= end<row>(U); for (size_type k= 0; kc != kend; ++kc, ++k) { icur_type ic= begin<nz>(kc), iend= end<nz>(kc); MTL_DEBUG_THROW_IF(col(*ic) != k, mtl::missing_diagonal()); // U[k][k]= 1.0 / sqrt(U[k][k]); value_type inv_dia= reciprocal(sqrt(value(*ic))); value(*ic, inv_dia); icur_type jbegin= ++ic; for (; ic != iend; ++ic) { // U[k][i] *= U[k][k] value_type d= value(*ic) * inv_dia; value(*ic, d); size_type i= col(*ic); // find non-zeros U[j][i] below U[k][i] for j in (k, i] // 1. Go to ith row in L (== ith column in U) cur_type irow= begin<row>(L); irow+= i; // 2. Find nonzeros with col() in (k, i] icur_type jc= begin<nz>(irow), jend= end<nz>(irow); while (col_l(*jc) <= k) ++jc; while (col_l(*--jend) > i); ++jend; for (; jc != jend; ++jc) { size_type j= col_l(*jc); U.lvalue(j, i)-= d * U[k][j]; } // std::cout << "U after eliminating U[" << i << "][" << k << "] =\n" << U; } } }
void factorize(const Matrix& A, L_type& L, U_type& U, boost::mpl::true_) { using namespace mtl; using namespace mtl::tag; using mtl::traits::range_generator; using math::reciprocal; MTL_THROW_IF(num_rows(A) != num_cols(A), mtl::matrix_not_square()); mtl::vampir_trace<5038> tracer; typedef typename mtl::Collection<Matrix>::value_type value_type; typedef typename mtl::Collection<Matrix>::size_type size_type; typedef mtl::mat::parameters<mtl::row_major, mtl::index::c_index, mtl::non_fixed::dimensions, false, size_type> para; typedef mtl::mat::compressed2D<value_type, para> LU_type; LU_type LU(A); typedef typename range_generator<row, LU_type>::type cur_type; typedef typename range_generator<nz, cur_type>::type icur_type; typename mtl::traits::col<LU_type>::type col(LU); typename mtl::traits::value<LU_type>::type value(LU); mtl::vec::dense_vector<value_type, mtl::vec::parameters<> > inv_dia(num_rows(A)); cur_type ic= begin<row>(LU), iend= end<row>(LU); for (size_type i= 0; ic != iend; ++ic, ++i) { for (icur_type kc= begin<nz>(ic), kend= end<nz>(ic); kc != kend; ++kc) { size_type k= col(*kc); if (k == i) break; value_type aik= value(*kc) * inv_dia[k]; value(*kc, aik); for (icur_type jc= kc + 1; jc != kend; ++jc) value(*jc, value(*jc) - aik * LU[k][col(*jc)]); // std::cout << "LU after eliminating A[" << i << "][" << k << "] =\n" << LU; } inv_dia[i]= reciprocal(LU[i][i]); } invert_diagonal(LU); L= strict_lower(LU); U= upper(LU); }