1 #ifndef _LILC_MATRIX_ILDL_INPLACE_H_ 2 #define _LILC_MATRIX_ILDL_INPLACE_H_ 9 template <
class el_type>
14 const int ncols = n_cols();
17 if (fill_factor > 1e4) lfil = ncols;
18 else lfil = 2*fill_factor*nnz()/ncols;
20 const el_type alpha = (1.0+sqrt(17.0))/8.0;
21 el_type w1(-1), wr(-1), d1(-1), dr(-1);
22 el_type det_D, D_inv11, D_inv22, D_inv12;
25 vector<bool> in_set(ncols,
false);
28 elt_vector_type work(ncols, 0), temp(ncols, 0);
29 idx_vector_type curr_nnzs, temp_nnzs;
30 curr_nnzs.reserve(ncols);
33 int i, j, k, r, offset, col_size, col_size2(-1);
34 bool size_two_piv =
false;
40 for (k = 0; k < ncols; k++) {
43 curr_nnzs.assign (m_idx[k].begin(), m_idx[k].end());
46 for (j = 0; j < (int) curr_nnzs.size(); j++) {
47 work[curr_nnzs[j]] = m_x[k][j];
49 sort(curr_nnzs.begin(), curr_nnzs.end());
55 update(k, work, curr_nnzs, *
this, D, in_set);
63 w1 = max(work, curr_nnzs, r);
65 if (piv_type == pivot_type::BKP) {
71 for (i = 0; i < (int) curr_nnzs.size(); i++) {
72 if (abs(work[curr_nnzs[i]])-pp_tol*w1 > eps ) {
84 }
else if ( (alpha * w1 - abs(d1)) < eps ) {
93 offset = row_first[r];
96 for (j = offset; j < (int) list[r].size(); j++) {
97 temp_nnzs.push_back(list[r][j]);
98 temp[list[r][j]] = coeff(r, list[r][j]);
102 temp_nnzs.insert(temp_nnzs.end(), m_idx[r].begin(), m_idx[r].end());
105 for (j = 0; j < (int) m_idx[r].size(); j++) {
106 temp[m_idx[r][j]] = m_x[r][j];
111 update(r, temp, temp_nnzs, *
this, D, in_set);
117 wr = max(temp, temp_nnzs, j);
119 if ((alpha*w1*w1 - abs(d1)*wr) < eps) {
122 }
else if ( (alpha * wr - abs(dr)) < eps) {
129 pivotA(s, in_set, k, r);
135 std::swap(perm[k], perm[r]);
138 std::swap(work[k], work[r]);
140 curr_nnzs.swap(temp_nnzs);
142 safe_swap(curr_nnzs, k, r);
150 for (
int i = 0; i < m_idx[k].size(); i++) {
152 if (l == k)
continue;
153 for (
int j = row_first[l]; j < list[l].size(); j++) {
154 if (list[l][j] == k) {
155 std::swap(list[l][j], list[l][list[l].size()-1]);
174 pivotA(s, in_set, k+1, r);
179 std::swap(perm[k+1], perm[r]);
182 std::swap(work[k+1], work[r]);
183 std::swap(temp[k+1], temp[r]);
186 safe_swap(curr_nnzs, k+1, r);
187 safe_swap(temp_nnzs, k+1, r);
192 }
else if (piv_type == pivot_type::ROOK) {
197 if (alpha * w1 <= abs(d1) + eps) {
202 for (idx_it it = temp_nnzs.begin(); it != temp_nnzs.end(); it++) {
207 offset = row_first[r];
210 for (j = offset; j < (int) list[r].size(); j++) {
211 temp_nnzs.push_back(list[r][j]);
212 temp[list[r][j]] = coeff(r, list[r][j]);
216 temp_nnzs.insert(temp_nnzs.end(), m_idx[r].begin(), m_idx[r].end());
219 for (j = 0; j < (int) m_idx[r].size(); j++) {
220 temp[m_idx[r][j]] = m_x[r][j];
225 update(r, temp, temp_nnzs, *
this, D, in_set);
231 wr = max(temp, temp_nnzs, j);
234 if (alpha * wr <= abs(dr) + eps) {
236 this->pivotA(s, in_set, k, r);
238 std::swap(perm[k], perm[r]);
240 std::swap(temp[k], temp[r]);
243 safe_swap(temp_nnzs, k, r);
244 curr_nnzs.swap(temp_nnzs);
248 }
else if (abs(w1 - wr) < eps) {
252 this->pivotA(s, in_set, k, i);
254 std::swap(perm[k], perm[i]);
256 std::swap(work[k], work[i]);
257 std::swap(temp[k], temp[i]);
259 safe_swap(curr_nnzs, k, i);
260 safe_swap(temp_nnzs, k, i);
266 this->pivotA(s, in_set, k+1, r);
268 std::swap(perm[k+1], perm[r]);
270 std::swap(work[k+1], work[r]);
271 std::swap(temp[k+1], temp[r]);
273 safe_swap(curr_nnzs, k+1, r);
274 safe_swap(temp_nnzs, k+1, r);
284 curr_nnzs.swap(temp_nnzs);
292 curr_nnzs.erase(std::remove(curr_nnzs.begin(), curr_nnzs.end(), k), curr_nnzs.end());
297 drop_tol(work, curr_nnzs, lfil, tol);
301 temp_nnzs.erase(std::remove(temp_nnzs.begin(), temp_nnzs.end(), k), temp_nnzs.end());
302 curr_nnzs.erase(std::remove(curr_nnzs.begin(), curr_nnzs.end(), k+1), curr_nnzs.end());
303 temp_nnzs.erase(std::remove(temp_nnzs.begin(), temp_nnzs.end(), k+1), temp_nnzs.end());
306 det_D = d1*dr - work[k+1]*work[k+1];
307 if ( abs(det_D) < eps) det_D = 1e-6;
310 D_inv12 = -work[k+1]/det_D;
317 unordered_inplace_union(curr_nnzs, temp_nnzs.begin(), temp_nnzs.end(), in_set);
321 for (idx_it it = curr_nnzs.begin(); it != curr_nnzs.end(); it++) {
322 l_11 = work[*it]*D_inv11 + temp[*it]*D_inv12;
323 l_12 = work[*it]*D_inv12 + temp[*it]*D_inv22;
332 temp_nnzs.assign(curr_nnzs.begin(), curr_nnzs.end());
335 drop_tol(temp, temp_nnzs, lfil, tol);
336 drop_tol(work, curr_nnzs, lfil, tol);
340 for (i = 0; i < m_idx[k].size(); i++) {
342 if (r == k)
continue;
343 for (j = row_first[r]; j < list[r].size(); j++) {
344 if (list[r][j] == k) {
345 std::swap(list[r][j], list[r][list[r].size()-1]);
353 m_idx[k].resize(curr_nnzs.size()+1);
354 m_x[k].resize(curr_nnzs.size()+1);
365 if ( abs(D[k]) < eps) D[k] = 1e-6;
368 for (idx_it it = curr_nnzs.begin(); it != curr_nnzs.end(); it++) {
369 if ( abs(work[*it]) > eps) {
371 m_x[k][i] = work[*it]/D[k];
373 list[*it].push_back(k);
382 for (i = 0; i < m_idx[k+1].size(); i++) {
384 if (r == k+1)
continue;
385 for (j = row_first[r]; j < list[r].size(); j++) {
386 if (list[r][j] == k+1) {
387 std::swap(list[r][j], list[r][list[r].size()-1]);
395 for (idx_it it = curr_nnzs.begin(); it != curr_nnzs.end(); it++) {
396 if ( abs(work[*it]) > eps) {
397 m_x[k][i] = work[*it];
400 list[*it].push_back(k);
408 m_idx[k+1].resize(temp_nnzs.size()+1);
409 m_x[k+1].resize(temp_nnzs.size()+1);
417 for (idx_it it = temp_nnzs.begin(); it != temp_nnzs.end(); it++) {
418 if ( abs(temp[*it]) > eps) {
419 m_x[k+1][j] = temp[*it];
422 list[*it].push_back(k+1);
442 for (idx_it it = curr_nnzs.begin(); it != curr_nnzs.end(); it++) {
447 for (idx_it it = temp_nnzs.begin(); it != temp_nnzs.end(); it++) {
455 m_x[k].resize(col_size);
456 m_idx[k].resize(col_size);
464 m_x[k+1].resize(col_size2);
465 m_idx[k+1].resize(col_size2);
473 size_two_piv =
false;
478 this->nnz_count = count;
el_type & off_diagonal(int i)
Definition: block_diag_matrix.h:114
void ildl_inplace(block_diag_matrix< el_type > &D, idx_vector_type &perm, const double &fill_factor, const double &tol, const double &pp_tol, int piv_type=pivot_type::BKP)
Performs an inplace LDL' factorization of this matrix.
Definition: lilc_matrix_ildl_inplace.h:10
void resize(int n, el_type default_value)
Resizes this matrix to an n*n matrix with default_value on the main diagonal.
Definition: block_diag_matrix.h:70
A quick implementation of a diagonal matrix with 1x1 and 2x2 blocks.
Definition: block_diag_matrix.h:39
A structure containing variables used in pivoting a LIL-C matrix.
Definition: swap_struct.h:6