18#ifndef __B2MATRIX_COMPRESSED_H__
19#define __B2MATRIX_COMPRESSED_H__
26#include "b2linear_algebra_def.H"
27#include "b2sparse_solver.H"
28#include "b2vector_compressed.H"
29#include "b2vector_dense.H"
30#include "b2vector_index.H"
34namespace b2000::b2linalg {
36struct Mcompressed_col {
37 using base = Mcompressed_col_ref;
38 using const_base = Mcompressed_col_st_constref;
39 using copy = Mcompressed_col;
43class Matrix<T, Mcompressed_col> {
45 Matrix() : s1(0) { si.assign(1, 0); }
47 Matrix(
size_t s1_,
size_t s2_,
size_t snn_) : s1(s1_), si(s2_ + 1), m(snn_), index(snn_) {}
49 Matrix(
const Matrix& m_) : s1(m_.s1), si(m_.si), m(m_.m), index(m_.index) {}
51 template <
typename T1>
52 Matrix(
const Matrix<T1, Mcompressed_col>& m_,
bool set_zero_same_structure =
false)
53 : s1(m_.s1), si(m_.si), m(m_.m.begin(), m_.m.end()), index(m_.index) {}
55 template <
typename T1>
56 Matrix& operator=(
const Matrix<T1, Mcompressed_col>& m_) {
59 m.assign(m_.m.begin(), m_.m.end());
64 template <
typename T1>
65 Matrix& operator=(
const Matrix<T1, Msym_compressed_col_st_constref>& m_) {
69 const size_t* m_index = m_.index + m_.si[0];
70 size_t* si1 = &si[0] + 2;
71 for (
size_t j = 0; j != s1; ++j) {
72 const size_t* m_index_end = m_.index + m_.si[j + 1];
73 si1[j] += m_index_end - m_index;
74 if (m_index != m_index_end && *m_index == j) { ++m_index; }
75 for (; m_index < m_index_end; ++m_index) { ++si1[*m_index]; }
78 std::partial_sum(si1, si1 + s1, si1);
81 index.assign(si1[s1], 0);
82 m.assign(si1[s1], T(0));
84 for (
size_t j = 0; j != s1; ++j) {
85 const size_t i_end = m_.si[j + 1];
86 std::copy(m_.index + i, m_.index + i_end, index.begin() + si1[j]);
88 const T* b = m_.m + i;
89 const T* b_end = m_.m + i_end;
91 for (; b != b_end; ++b, ++bs) { *bs = m_.scale * *b; }
94 if (i != i_end && m_.index[i] == j) { ++i; }
95 for (; i < i_end; ++i) {
96 size_t& ii = si1[m_.index[i]];
98 m[ii] = m_.scale * m_.m[i];
107 Matrix(
const Matrix<T, Mcompressed_col_st_constref>& m_) { *
this = m_; }
109 Matrix(
const Matrix<T, Msym_compressed_col_st_constref>& m_,
const Index& index_) {
110 resize(m_.size1(), index_.size(), 0);
111 std::vector<size_t> ind(index_);
112 std::sort(ind.begin(), ind.end());
113 const size_t s2 = index_.size();
115 for (
size_t j = 0; j != m_.s1; ++j) {
116 size_t ii = m_.si[j];
117 const size_t ii_end = m_.si[j + 1];
118 if (ii == ii_end) {
continue; }
119 if (ij != s2 && j == ind[ij]) {
120 si[ij] += ii_end - ii;
123 if (m_.index[ii] == j) { ++ii; }
125 while (i != s2 && ii != ii_end) {
126 if (m_.index[ii] < ind[i]) {
128 }
else if (m_.index[ii] > ind[i]) {
137 for (
size_t i = 0; i != s2; ++i) { si[i + 1] += si[i]; }
138 index.assign(si[s2], 0);
140 for (
size_t i = s2; i > 1; --i) { si[i] = si[i - 2]; }
142 size_t* siptr = &si[1];
144 for (
size_t j = 0; j != m_.s1; ++j) {
145 size_t ii = m_.si[j];
146 const size_t ii_end = m_.si[j + 1];
147 if (ii == ii_end) {
continue; }
148 if (ij != s2 && j == ind[ij]) {
149 std::copy(m_.index + ii, m_.index + ii_end, &index[siptr[ij]]);
150 std::copy(m_.m + ii, m_.m + ii_end, &m[siptr[ij]]);
151 siptr[ij] += ii_end - ii;
154 if (m_.index[ii] == j) { ++ii; }
156 while (i != s2 && ii != ii_end) {
157 if (m_.index[ii] < ind[i]) {
159 }
else if (m_.index[ii] > ind[i]) {
163 m[siptr[i]] = m_.m[ii];
172 void this_prod_index(Index& i_index)
const {
173 const size_t* colind = &si[0];
174 const size_t* rowind = &index[0];
175 std::set<size_t> tmp_rowind;
176 const size_t*
const i_end = &i_index[0] + i_index.size();
177 const size_t i_max = si.size() - 1;
178 for (
const size_t* i = &i_index[0]; i != i_end; ++i) {
179 if (*i >= i_max) { Exception() <<
THROW; }
180 tmp_rowind.insert(rowind + colind[*i], rowind + colind[*i + 1]);
182 i_index.assign(tmp_rowind.begin(), tmp_rowind.end());
185 void remove_row(
const Index& index_row) {
186 std::vector<size_t> tmp_index(s1);
190 for (
size_t i = 0; i != s1; ++i) {
191 if (i_index != index_row.size() && i == index_row[i_index]) {
202 for (
size_t j = 1; j != si.size(); ++j) {
203 const size_t i_oe = si[j];
204 for (; i_o != i_oe; ++i_o) {
205 const size_t tmp_i = tmp_index[index[i_o]];
216 s1 -= index_row.size();
219 void remove_col(
const Index& index_col) {
220 size_t index_col_ptr = 0;
223 for (
size_t j = 0; j != si.size() - 1; ++j) {
224 if (index_col_ptr != index_col.size() && j == index_col[index_col_ptr]) {
229 index.begin() + si[j], index.begin() + si[j + 1], index.begin() + dest);
230 std::copy(m.begin() + si[j], m.begin() + si[j + 1], m.begin() + dest);
232 const size_t s = si[j + 1] - si[j];
233 si[si_dest++] = dest;
237 si[si_dest++] = dest;
243 void remove_nonzero_in_cols(
const Index& index_col) {
247 for (
size_t j = 0; j != index_col.size(); ++j) {
248 const size_t i_l = si[index_col[j]];
250 std::copy(index.begin() + i_o, index.begin() + i_l, index.begin() + i_n);
251 std::copy(m.begin() + i_o, m.begin() + i_l, m.begin() + i_n);
252 const size_t diff = i_o - i_n;
253 for (; jj != index_col[j]; ++jj) { si[jj] -= diff; }
256 i_o = si[index_col[j] + 1];
259 const size_t i_l = si.back();
260 std::copy(index.begin() + i_o, index.begin() + i_l, index.begin() + i_n);
261 std::copy(m.begin() + i_o, m.begin() + i_l, m.begin() + i_n);
262 const size_t diff = i_o - i_n;
263 for (; jj != si.size(); ++jj) { si[jj] -= diff; }
267 bool get_nonzero_unit_row_for_column(
const Index& index_col, Index& index_row) {
269 index_row.reserve(index_col.size());
270 for (
size_t j = 0; j != index_col.size(); ++j) {
271 size_t jj = index_col[j];
272 if (si[jj + 1] - si[jj] != 1 || m[si[jj]] != T(1)) {
return false; }
273 index_row.push_back(index[si[jj]]);
275 std::sort(index_row.begin(), index_row.end());
279 Matrix& operator=(
const Matrix<T, Mcompressed_col_st_constref>& m_) {
282 si.assign(m_.si, m_.si + m_.s2 + 1);
283 index.assign(m_.index, m_.index + m_.si[m_.s2]);
284 if (m_.scale == T(1)) {
285 m.assign(m_.m, m_.m + m_.si[m_.s2]);
287 m.reserve(m_.si[m_.s2]);
288 for (
const T* i = m_.m; i != m_.m + m_.si[m_.s2]; ++i) {
289 m.push_back(m_.scale * *i);
293 si.assign(m_.s1 + 1, 0);
294 m.assign(m_.si[m_.s2], 0);
295 index.assign(m_.si[m_.s2], 0);
297 size_t* tmp_col =
new size_t[m_.s1];
298 std::fill_n(tmp_col, m_.s1, 0);
300 const size_t* colind_begin = m_.si;
301 const size_t* rowind_begin = m_.index + *colind_begin;
302 const size_t*
const colind_end = colind_begin + s1;
303 while (colind_begin != colind_end) {
304 const size_t*
const rowind_end = m_.index + *++colind_begin;
305 while (rowind_begin != rowind_end) { ++(tmp_col[*rowind_begin++]); }
308 std::partial_sum(tmp_col, tmp_col + m_.s1, si.begin() + 1);
310 rowind_begin = m_.index + m_.si[0];
311 const T* value_begin = m_.m;
312 for (
size_t col = 0; col != s1; ++col) {
313 const size_t*
const rowind_end = m_.index + m_.si[col + 1];
314 while (rowind_begin != rowind_end) {
315 size_t i = (si[*rowind_begin++])++;
317 m[i] = m_.scale * *value_begin++;
322 std::partial_sum(tmp_col, tmp_col + m_.s1, si.begin() + 1);
328 Matrix(
const Matrix<T, MMProd<Mcompressed_col_st_constref, Mcompressed_col_st_constref>>& m_)
329 : s1(m_.size1()), si(m_.size2() + 1) {
334 const Matrix<T, MMProd<Mcompressed_col_st_constref, Mcompressed_col_st_constref>>& m_) {
338 si.resize(m_.size2() + 1);
340 const size_t end_list_flag = m_.m1.size1();
344 T scale = m_.scale * m_.m1.scale * m_.m2.scale;
347 const size_t* b_colind_begin = m_.m2.si;
348 const size_t*
const b_colind_end = b_colind_begin + m_.m2.size2();
349 size_t end_list = end_list_flag;
351 while (b_colind_begin != b_colind_end) {
352 const size_t* b_rowind_begin = &m_.m2.index[*b_colind_begin];
353 const T* b_value_begin = &m_.m2.m[*b_colind_begin];
354 const size_t*
const b_rowind_end = &m_.m2.index[*++b_colind_begin];
355 while (b_rowind_begin != b_rowind_end) {
356 const size_t* a_rowind_begin = m_.m1.index + m_.m1.si[*b_rowind_begin];
357 const size_t*
const a_rowind_end = m_.m1.index + m_.m1.si[*b_rowind_begin + 1];
358 const T* a_value_begin = m_.m1.m + m_.m1.si[*b_rowind_begin++];
359 const T b_value_begin_v = *b_value_begin++;
360 while (a_rowind_begin != a_rowind_end) {
361 tmp_value[*a_rowind_begin] += *a_value_begin++ * b_value_begin_v;
362 if (!(std::numeric_limits<size_t>::max() - tmp_index[*a_rowind_begin])) {
363 tmp_index[*a_rowind_begin] = end_list;
364 end_list = *a_rowind_begin;
369 std::vector<std::pair<size_t, T>> res_tmp;
370 while (end_list != end_list_flag) {
371 res_tmp.push_back(std::pair<size_t, T>(end_list, tmp_value[end_list]));
372 const size_t end_list_next = tmp_index[end_list];
373 tmp_index[end_list] = std::numeric_limits<size_t>::max();
374 tmp_value[end_list] = T(0);
375 end_list = end_list_next;
377 std::sort(res_tmp.begin(), res_tmp.end(), CompareFirstOfPair());
379 for (
typename std::vector<std::pair<size_t, T>>::iterator i = res_tmp.begin();
380 i != res_tmp.end(); ++i) {
381 index.push_back(i->first);
382 m.push_back(i->second * scale);
384 si[++col] = m.size();
392 T, Sum<Mcompressed_col_st_constref,
393 MMProd<Mcompressed_col_st_constref, Mcompressed_col_st_constref>>>& m_) {
394 if (m_.trans || m_.m1.trans || m_.m2.m1.trans || m_.m2.m2.trans) {
399 si.resize(m_.size2() + 1);
401 const size_t end_list_flag = m_.m2.m1.size1();
405 T scale_1 = m_.scale * m_.m1.scale;
406 T
scale_2 = m_.scale * m_.m2.scale * m_.m2.m1.scale * m_.m2.m2.scale;
409 const size_t* c_colind_begin = m_.m1.si;
410 const size_t* b_colind_begin = m_.m2.m2.si;
411 const size_t*
const b_colind_end = b_colind_begin + m_.m2.m2.size2();
412 size_t end_list = end_list_flag;
414 while (b_colind_begin != b_colind_end) {
415 const size_t* b_rowind_begin = &m_.m2.m2.index[*b_colind_begin];
416 const T* b_value_begin = &m_.m2.m2.m[*b_colind_begin];
417 const size_t* b_rowind_end = &m_.m2.m2.index[*++b_colind_begin];
418 while (b_rowind_begin != b_rowind_end) {
419 const size_t* a_rowind_begin = m_.m2.m1.index + m_.m2.m1.si[*b_rowind_begin];
420 const size_t*
const a_rowind_end =
421 m_.m2.m1.index + m_.m2.m1.si[*b_rowind_begin + 1];
422 const T* a_value_begin = m_.m2.m1.m + m_.m2.m1.si[*b_rowind_begin++];
423 const T b_value_begin_v = *b_value_begin++;
424 while (a_rowind_begin != a_rowind_end) {
425 tmp_value[*a_rowind_begin] +=
scale_2 * *a_value_begin++ * b_value_begin_v;
426 if (!(std::numeric_limits<size_t>::max() - tmp_index[*a_rowind_begin])) {
427 tmp_index[*a_rowind_begin] = end_list;
428 end_list = *a_rowind_begin;
434 b_rowind_begin = &m_.m1.index[*c_colind_begin];
435 b_value_begin = &m_.m1.m[*c_colind_begin];
436 b_rowind_end = &m_.m1.index[*++c_colind_begin];
437 while (b_rowind_begin != b_rowind_end) {
438 tmp_value[*b_rowind_begin] += scale_1 * *b_value_begin++;
439 if (!(std::numeric_limits<size_t>::max() - tmp_index[*b_rowind_begin])) {
440 tmp_index[*b_rowind_begin] = end_list;
441 end_list = *b_rowind_begin;
446 std::vector<std::pair<size_t, T>> res_tmp;
447 while (end_list != end_list_flag) {
448 res_tmp.push_back(std::pair<size_t, T>(end_list, tmp_value[end_list]));
449 const size_t end_list_next = tmp_index[end_list];
450 tmp_index[end_list] = std::numeric_limits<size_t>::max();
451 tmp_value[end_list] = T(0);
452 end_list = end_list_next;
454 std::sort(res_tmp.begin(), res_tmp.end(), CompareFirstOfPair());
456 for (
typename std::vector<std::pair<size_t, T>>::iterator i = res_tmp.begin();
457 i != res_tmp.end(); ++i) {
458 index.push_back(i->first);
459 m.push_back(i->second);
461 si[++col] = m.size();
467 bool is_null()
const {
return this == &null; }
470 std::fill(si.begin(), si.end(), 0);
482 void resize(
size_t s1_,
size_t s2_) {
485 si.insert(si.end(), s2_ - size2(), si.back());
491 void resize(
size_t s1_,
size_t s2_,
size_t snn) {
493 si.assign(s2_ + 1, 0);
498 void resize(
const Index& idx) {
501 for (std::vector<size_t>::iterator i = index.begin(); i != index.end(); ++i) {
505 for (
size_t j = 0; j != size2(); ++j) {
506 size_t* i_begin = &index[si[j]];
507 size_t* i_end = &index[si[j + 1]];
508 T* v_begin = &m[si[j]];
509 std::vector<std::pair<size_t, T>> tmp;
510 tmp.reserve(i_end - i_begin);
511 while (i_begin != i_end) {
512 tmp.push_back(std::pair<size_t, T>(idx[*i_begin++], *v_begin++));
514 std::sort(tmp.begin(), tmp.end(), CompareFirstOfPair());
515 i_begin = &index[si[j]];
517 for (
typename std::vector<std::pair<size_t, T>>::iterator i = tmp.begin();
518 i != tmp.end(); ++i) {
519 *i_begin++ = i->first;
520 *v_begin++ = i->second;
526 size_t get_nb_nonzero()
const {
return si.back(); }
528 size_t get_nb_nonzero(
size_t col)
const {
return si[col + 1] - si[col]; }
530 void push_back(
size_t row,
size_t col, T value) {
531 while (si.size() <= col + 1) { si.push_back(si.back()); }
532 index.push_back(row);
535 s1 = std::max(s1, row + 1);
538 void push_back(
size_t row,
size_t col,
const Vector<T, Vdense_constref>& v) {
539 while (si.size() <= col + 1) { si.push_back(si.back()); }
540 m.insert(m.end(), v.v, v.v + v.s);
541 for (
size_t i = 0; i != v.s; ++i) { index.push_back(row + i); }
542 si.back() = m.size();
543 s1 = std::max(s1, row + v.s);
546 void push_back(
size_t row,
size_t col,
const Index& ind,
const Vector<T, Vdense_constref>& v) {
547 while (si.size() <= col + 1) { si.push_back(si.back()); }
548 for (
size_t i = 0; i != v.size(); ++i) {
550 index.push_back(row + ind[i]);
552 si.back() = m.size();
553 s1 = std::max(s1, row + v.s);
556 void push_back(
size_t row,
size_t col,
const Vector<T, Vcompressed_scale_constref>& v) {
557 while (si.size() <= col + 1) { si.push_back(si.back()); }
558 for (
size_t i = 0; i != v.snn; ++i) {
559 m.push_back(v.scale * v.v[i]);
560 index.push_back(row + v.index[i]);
562 si.back() = m.size();
563 s1 = std::max(s1, row + v.s);
566 void push_back(
size_t i,
const Matrix<T, Mcompressed_col_st_constref>& m_) {
568 if (m_.size2() == 0) {
return; }
569 if (si.empty()) { si.push_back(0); }
570 std::size_t ii = index.size();
571 index.insert(index.end(), m_.index + m_.si[0], m_.index + m_.si[m_.s2]);
572 for (std::vector<size_t>::iterator iii = index.begin() + ii; iii != index.end(); ++iii) {
576 m.insert(m.end(), m_.m + m_.si[0], m_.m + m_.si[m_.s2]);
577 if (m_.scale != T(1)) {
578 for (; j != m.size(); ++j) { m[j] *= m_.scale; }
581 size_t is = si.size();
582 si.insert(si.end(), m_.si + 1, m_.si + m_.s2 + 1);
583 size_t iv = si[is - 1] - m_.si[0];
584 for (std::vector<size_t>::iterator iii = si.begin() + is; iii != si.end(); ++iii) {
587 s1 = std::max(s1, i + m_.size1());
591 size_t i1,
const Matrix<T, Mcompressed_col_constref>& m1,
size_t i2,
592 const Matrix<T, Mcompressed_col_constref>& m2) {
594 if (si.empty()) { si.push_back(0); }
595 for (
size_t j = 0; j != m1.size2(); ++j) {
596 size_t ii = index.size();
597 index.insert(index.end(), m1.index + m1.si[j], m1.index + m1.si[j + 1]);
598 for (std::vector<size_t>::iterator i = index.begin() + ii; i != index.end(); ++i) {
602 index.insert(index.end(), m2.index + m2.si[j], m2.index + m2.si[j + 1]);
603 for (std::vector<size_t>::iterator i = index.begin() + ii; i != index.end(); ++i) {
606 m.insert(m.end(), m1.m + m1.si[j], m1.m + m1.si[j + 1]);
607 m.insert(m.end(), m2.m + m2.si[j], m2.m + m2.si[j + 1]);
608 si.push_back(m.size());
610 s1 = std::max(s1, i2 + m2.size1());
613 void set_identity(
size_t i1,
size_t i2) {
617 const size_t s = std::min(i1, i2);
622 for (; i != index.size(); ++i) {
627 std::fill(si.begin() + i, si.end(), i);
630 void push_back_identity(
size_t i1,
size_t i2) {
632 index.reserve(std::min(i1, i2));
634 m.reserve(index.size());
637 while (si.size() < i1 + 1) { si.push_back(si.back()); }
641 si.push_back(m.size());
644 s1 = std::max(s1, i2);
647 void get_values(
size_t*& colind,
size_t*& rowind, T*& value) {
653 size_t get_col_value(
const size_t col,
size_t*& rowind, T*& value) {
654 rowind = &index[si[col]];
656 return si[col + 1] - si[col];
660 size_t s1_,
size_t s2_,
size_t snn,
const size_t* colind,
const size_t* rowind,
664 std::copy(colind, colind + s2_ + 1, si.begin());
666 std::copy(rowind, rowind + snn, index.begin());
668 std::copy(value, value + snn, m.begin());
671 std::pair<size_t, size_t> size()
const {
672 return std::pair<size_t, size_t>(s1, si.size() == 0 ? 0 : si.size() - 1);
675 size_t size1()
const {
return s1; }
677 size_t size2()
const {
return si.size() == 0 ? 0 : si.size() - 1; }
679 T operator()(
size_t i,
size_t j)
const {
680 std::vector<size_t>::const_iterator s = index.begin() + si[j];
681 std::vector<size_t>::const_iterator e = index.begin() + si[j + 1];
682 std::vector<size_t>::const_iterator ii = std::lower_bound(s, e, i);
683 if (ii < e && *ii == i) {
return m[ii - index.begin()]; }
687 Matrix<T, Msub_constref<Mcompressed_col_constref, Index, Index>> operator()(
688 const Index& i,
const Index& j)
const {
689 return Matrix<T, Msub_constref<Mcompressed_col_constref, Index, Index>>(
690 Matrix<T, Mcompressed_col_constref>(*
this), i, j);
693 Matrix<T, Mcompressed_col_constref> operator()(
const Interval& j)
const {
694 return Matrix<T, Mcompressed_col_constref>(
695 s1, j.size(), si[j.end] - si[j.start], &si[j.start], &index[0], &m[0]);
698 Vector<T, Vcompressed_scale_constref> operator[](
size_t i)
const {
699 if (i >= size2()) { Exception() <<
THROW; }
700 return Vector<T, Vcompressed_scale_constref>(
701 s1, si[i + 1] - si[i], &index[si[i]], &m[si[i]], 1);
704 Matrix& operator=(
const Matrix<T, Msub_constref<Mcompressed_col_constref, Index, Index>>& m_) {
706 si.reserve(m_.size2() + 1);
708 const size_t* jindex;
709 const size_t* jindex_end;
711 if (m_.index2.is_all()) {
712 index_tmp.resize(m_.m.size1());
713 for (
size_t i = 0; i != index_tmp.size(); ++i) { index_tmp[i] = i; }
714 jindex = &index_tmp[0];
715 jindex_end = jindex + index_tmp.size();
717 jindex = &m_.index2[0];
718 jindex_end = jindex + m_.index2.size();
720 if (m_.index1.is_all()) {
721 for (; jindex != jindex_end; ++jindex) {
722 size_t j = m_.m.si[*jindex];
723 size_t j_end = m_.m.si[*jindex + 1];
724 m.insert(m.end(), m_.m.m + j, m_.m.m + j_end);
725 index.insert(index.end(), m_.m.index + j, m_.m.index + j_end);
726 si.push_back(index.size());
729 if (m_.index1.sorted()) {
730 Index dual_iindex = m_.index1.make_dual();
731 for (; jindex != jindex_end; ++jindex) {
732 size_t j = m_.m.si[*jindex];
733 size_t j_end = m_.m.si[*jindex + 1];
734 for (; j != j_end; ++j) {
735 if (dual_iindex[m_.m.index[j]] != dual_iindex.size()) {
736 index.push_back(m_.m.index[j]);
737 m.push_back(m_.m.m[j]);
740 si.push_back(index.size());
743 Index dual_iindex = m_.index1.make_dual();
744 for (; jindex != jindex_end; ++jindex) {
745 size_t j = m_.m.si[*jindex];
746 size_t j_end = m_.m.si[*jindex + 1];
747 std::vector<std::pair<size_t, T>> tmp;
748 tmp.reserve(j_end - j);
749 for (; j != j_end; ++j) {
750 tmp.push_back(std::pair<size_t, T>(dual_iindex[m_.m.index[j]], m_.m.m[j]));
752 std::sort(tmp.begin(), tmp.end(), CompareFirstOfPair());
753 for (
typename std::vector<std::pair<size_t, T>>::iterator i = tmp.begin();
754 i != tmp.end(); ++i) {
755 index.push_back(i->first);
756 m.push_back(i->second);
758 si.push_back(index.size());
765 void swap(Matrix& m_) {
766 std::swap(s1, m_.s1);
769 index.swap(m_.index);
775 void LUFactorization(
776 Matrix<T, Mcompressed_col>& trans_L, Matrix<T, Mcompressed_col>& U, Index& P, Index& Q,
777 Vector<double, Vdense>& R) {
778 Matrix<T, Mcompressed_col_constref>(*this).LUFactorization(trans_L, U, P, Q, R);
790 size_t LUIFactorization(
791 Matrix<T, Mcompressed_col>& L, Matrix<T, Mcompressed_col>& trans_U, Index& P, Index& Q,
792 const bool compute_LU, Vector<double>& w = Vector<double>::null,
793 const bool rook_pivot =
false,
double tol_pivot = -1,
const double tol_drop = 3e-13,
794 const double tol_rank_abs = 3.7e-11,
const double tol_rank_rel = 3.7e-11,
795 const Index& col_to_remove = Index::null);
800 void LUIFactorization(
801 Matrix<T, Mcompressed_col>& L, Matrix<T, Mcompressed_col>& trans_U, Index& P, Index& Q,
802 const double tol_drop = 3e-13,
const double tol_pivot_rank_search = 4.0,
803 const double tol_pivot_LU_fact = 10.0,
const double tol_rank_abs = 3.7e-11,
804 const double tol_rank_rel = 3.7e-11) {
807 const size_t rank = LUIFactorization(
808 L, trans_U, Index::null, Index::null,
false, w,
true, tol_pivot_rank_search, tol_drop,
809 tol_rank_abs, tol_rank_rel);
811 col_to_remove.reserve(w.size() - rank);
812 for (
size_t i = 0; i != w.size(); ++i) {
813 if (w[i] <= 0) { col_to_remove.push_back(i); }
818 L, trans_U, P, Q,
true, Vector<double>::null,
false, tol_pivot_LU_fact, tol_drop,
819 tol_rank_abs, tol_rank_rel, col_to_remove);
825 void get_dep_columns(
826 Index& Q,
const double tol_drop = 3e-13,
const double tol_pivot = 4.0,
827 const double tol_rank_abs = 3.7e-11,
const double tol_rank_rel = 3.7e-11) {
829 Matrix<T, Mcompressed_col> L;
830 Matrix<T, Mcompressed_col> trans_U;
831 const size_t rank = LUIFactorization(
832 L, trans_U, Index::null, Index::null,
false, w,
true, tol_pivot, tol_drop,
833 tol_rank_abs, tol_rank_rel);
835 Q.reserve(w.size() - rank);
836 for (
size_t i = 0; i != w.size(); ++i) {
837 if (w[i] <= 0) { Q.push_back(i); }
841 Matrix& operator*=(
const double s) {
842 for (
size_t i = 0; i != m.size(); ++i) { m[i] *= s; }
849 MMProd<Minverse_constref<Mcompressed_col_constref>, Mcompressed_col_st_constref>>&
851 if (m_.scale != T(1) || m_.m2.scale != T(1) || m_.m2.trans) {
854 if (m_.m1.size1() != m_.m1.size2()) { Exception() <<
THROW; }
861 for (
size_t k = 0; k != m_.m2.size2(); ++k) {
862 if (m_.m2.si[k + 1] - m_.m2.si[k] > 0) {
863 std::list<std::pair<size_t, T>> tmp;
864 for (
size_t j = m_.m2.si[k]; j != m_.m2.si[k + 1]; ++j) {
865 tmp.push_back(std::pair<size_t, T>(m_.m2.index[j], m_.m2.m[j]));
867 for (
typename std::list<std::pair<size_t, T>>::reverse_iterator j = tmp.rbegin();
868 j != tmp.rend(); ++j) {
869 size_t jj_piv_p = m_.m1.m.si[j->first + 1] - 1;
870 if (m_.m1.m.index[jj_piv_p] != j->first) { Exception() <<
THROW; }
871 T piv = (j->second /= m_.m1.m.m[jj_piv_p]);
872 if (b2000::norm(piv) < 1e-15) {
continue; }
873 typename std::list<std::pair<size_t, T>>::iterator jc = tmp.begin();
874 for (
size_t jj = m_.m1.m.si[j->first]; jj < jj_piv_p; ++jj) {
875 size_t ii = m_.m1.m.index[jj];
876 T v = -m_.m1.m.m[jj] * piv;
877 while (jc != tmp.end() && jc->first < ii) { ++jc; }
878 if (jc != tmp.end() && jc->first == ii) {
881 tmp.insert(jc, std::pair<size_t, T>(ii, v));
885 for (
typename std::list<std::pair<size_t, T>>::iterator i = tmp.begin();
886 i != tmp.end(); ++i) {
887 if (b2000::norm(i->second) > 1e-15) {
888 index.push_back(i->first);
889 m.push_back(i->second);
893 si.push_back(index.size());
901 MMProd<Mcompressed_col_st_constref, Minverse_constref<Mcompressed_col_constref>>>&
903 if (m_.scale != T(1) || m_.m1.scale != T(1) || m_.m1.trans) {
906 if (m_.m2.size1() != m_.m2.size2()) { Exception() <<
THROW; }
914 const size_t end_list_flag = m_.m1.size1();
916 for (
size_t k = 0; k != m_.m2.m.size1(); ++k) {
917 size_t end_list = end_list_flag;
918 const size_t* rowind_begin = m_.m1.index + m_.m1.si[k];
919 const size_t* rowind_end = m_.m1.index + m_.m1.si[k + 1];
920 const T* value_begin = m_.m1.m + m_.m1.si[k];
921 while (rowind_begin != rowind_end) {
922 tmp_value[*rowind_begin] = *value_begin++;
923 tmp_index[*rowind_begin] = end_list;
924 end_list = *rowind_begin++;
926 rowind_begin = m_.m2.m.index + m_.m2.m.si[k];
927 value_begin = m_.m2.m.m + m_.m2.m.si[k];
928 while (*rowind_begin < k) {
929 const size_t* a_rowind_begin = &index[si[*rowind_begin]];
930 const T* a_value_begin = &m[si[*rowind_begin]];
931 const size_t* a_rowind_end = &index[si[*rowind_begin + 1]];
933 while (a_rowind_begin != a_rowind_end) {
934 tmp_value[*a_rowind_begin] -= *a_value_begin++ * *value_begin;
935 if (!(std::numeric_limits<size_t>::max() - tmp_index[*a_rowind_begin])) {
936 tmp_index[*a_rowind_begin] = end_list;
937 end_list = *a_rowind_begin;
943 T pivot = T(1) / *value_begin;
944 std::vector<std::pair<size_t, T>> res_tmp;
945 while (end_list != end_list_flag) {
946 res_tmp.push_back(std::pair<size_t, T>(end_list, pivot * tmp_value[end_list]));
947 const size_t end_list_next = tmp_index[end_list];
948 tmp_index[end_list] = std::numeric_limits<size_t>::max();
949 tmp_value[end_list] = T(0);
950 end_list = end_list_next;
952 std::sort(res_tmp.begin(), res_tmp.end(), CompareFirstOfPair());
954 for (
typename std::vector<std::pair<size_t, T>>::iterator i = res_tmp.begin();
955 i != res_tmp.end(); ++i) {
956 index.push_back(i->first);
957 m.push_back(i->second);
959 si.push_back(m.size());
965 template <
typename T1,
typename STORAGE>
966 void scale_row(
const Vector<T1, STORAGE>& v) {
967 for (
size_t i = 0; i != m.size(); ++i) { m[i] *= v[index[i]]; }
970 template <
typename T1,
typename STORAGE>
971 void scale_col(
const Vector<T1, STORAGE>& v) {
972 if (m.empty()) {
return; }
973 for (
size_t j = 0; j != size2(); ++j) {
975 T* i_end = &m[si[j + 1]];
977 while (i != i_end) { *i++ *= tmp; }
981 void scale_col_to_norminf(Vector<double, Vdense>& v) {
982 if (m.empty()) {
return; }
983 for (
size_t j = 0; j != size2(); ++j) {
984 T* i_end = &m[si[j + 1]];
986 for (T* i = &m[si[j]]; i != i_end; ++i) {
987 tmp = max_abs(tmp, *i);
989 if (tmp == T(0)) {
continue; }
991 v[j] = b2000::real(tmp);
992 for (T* i = &m[si[j]]; i != i_end; ++i) { *i *= tmp; }
996 template <
typename T1>
997 void scale_invert_col(
const Vector<T1, Vdense_constref>& v) {
998 if (m.empty()) {
return; }
1000 for (
size_t i = 0; i != v.size(); ++i) {
1001 T1 tmp = T1(1) / v[i];
1002 for (T
const* i_end = &m[si[i + 1]]; ii != i_end; ++ii) { *ii *= tmp; }
1006 bool is_null_value()
const {
1007 for (
size_t i = 0; i != m.size(); ++i) {
1008 if (m[i] != T(0)) {
return false; }
1013 void remove_zero(
const double tol = 0) {
1016 for (
size_t j = 1; j != si.size(); ++j) {
1017 for (; i != si[j]; ++i) {
1018 if (b2000::norm(m[i]) > tol) {
1020 index[i_out] = index[i];
1026 index.resize(i_out);
1030 void row_permute(
size_t new_s1,
const Index perm) {
1031 if (perm.size() != s1) { Exception() <<
THROW; }
1032 for (
size_t i = 0; i != index.size(); ++i) { index[i] = perm[index[i]]; }
1038 std::vector<T> m_tmp(s1 * size2());
1041 for (
size_t j = 1; j != si.size(); ++j, ptro += s1) {
1042 for (; ptri != si[j]; ++ptri) { m_tmp[ptro + index[ptri]] = m[ptri]; }
1046 index.resize(m.size());
1049 for (
size_t j = 1; j != si.size(); ++j) {
1050 si[j] = si[j - 1] + s1;
1051 for (
size_t i = 0; i != s1; ++i, ++ptr) { index[ptr] = i; }
1055 friend logging::Logger& operator<<(logging::Logger& l,
const Matrix& m) {
1056 l <<
"column compressed matrix of size (" << m.size1() <<
", " << m.size2() <<
") ";
1057 l.write(m.si.size(), &m.si[0], 1,
"colind");
1058 l.write(m.index.size(), &m.index[0], 1,
"rowind");
1059 l.write(m.m.size(), &m.m[0], 1,
"value");
1063 friend std::ostream& operator<<(std::ostream& out,
const Matrix& m) {
1071 std::vector<size_t> sii(m.si);
1072 const size_t s2 = sii.size() - 1;
1074 for (
size_t i = 0;;) {
1076 for (
size_t j = 0;;) {
1077 if (sii[j] == m.si[j + 1] || m.index[sii[j]] != i) {
1080 out << m.m[sii[j]++];
1090 out <<
"," << std::endl;
1103 std::vector<size_t> si;
1105 std::vector<size_t> index;
1109template <
typename T>
1110Matrix<T, Mcompressed_col> Matrix<T, Mcompressed_col>::null;
1117template <
typename T>
1118size_t Matrix<T, Mcompressed_col>::LUIFactorization(
1119 Matrix<T, Mcompressed_col>& L, Matrix<T, Mcompressed_col>& trans_U, Index& P, Index& Q,
1120 const bool compute_LU, Vector<double>& w,
const bool rook_pivot,
double tol_pivot,
1121 const double drop_tol,
const double tol_rank_abs,
const double tol_rank_rel,
1122 const Index& col_to_remove) {
1123 if (tol_pivot < 0) { tol_pivot = rook_pivot ? 4.0 : 10.0; }
1125 const size_t s2 = size2();
1126 const size_t min_mn = std::min(s1, s2);
1128 std::set<size_t> empty_row;
1129 std::set<size_t> empty_col;
1130 size_t* P_empty_row = 0;
1131 size_t* Q_empty_col = 0;
1134 P_empty_row = &P.back();
1136 Q_empty_col = &Q.back();
1147 trans_U.si.push_back(0);
1148 trans_U.index.clear();
1151 Vector<double> U_diag;
1159 std::vector<std::map<size_t, T>> col(s2);
1160 std::vector<std::map<size_t, T*>> row(s1);
1161 std::vector<double> col_max(s2);
1162 std::vector<double> row_max(s1);
1164 const size_t* col_to_remove_ptr = 0;
1165 const size_t* col_to_remove_ptr_end = 0;
1166 if (!col_to_remove.is_null() && !col_to_remove.empty()) {
1167 col_to_remove_ptr = &col_to_remove[0];
1168 col_to_remove_ptr_end = &col_to_remove.back() + 1;
1171 for (
size_t j = 0; j != s2; ++j) {
1172 if (col_to_remove_ptr && col_to_remove_ptr != col_to_remove_ptr_end
1173 && j == *col_to_remove_ptr) {
1174 ++col_to_remove_ptr;
1178 const size_t i_end = si[j + 1];
1179 for (; i != i_end; ++i) {
1180 const size_t ii = index[i];
1181 const double nm = b2000::norm(m[i]);
1182 if (nm > drop_tol) {
1185 typename std::map<size_t, T>& col_j = col[j];
1186 ptr = &(col_j.insert(col_j.end(), std::pair<size_t, T>(ii, m[i]))->second);
1189 typename std::map<size_t, T*>& row_i = row[ii];
1190 row_i.insert(row_i.end(), std::pair<size_t, T*>(j, ptr));
1192 if (nm > col_max[j]) { col_max[j] = nm; }
1193 if (nm > row_max[ii]) { row_max[ii] = nm; }
1200 using degree_t = std::multimap<size_t, size_t>;
1201 using degree_iter_t = std::vector<degree_t::iterator>;
1203 degree_t col_degree;
1204 degree_iter_t col_degree_iter(s2);
1205 degree_t row_degree;
1206 degree_iter_t row_degree_iter(s1);
1207 for (
size_t i = 0; i != s2; ++i) {
1208 if (!col[i].empty()) {
1209 col_degree_iter[i] = col_degree.insert(std::pair<size_t, size_t>(col[i].size(), i));
1211 if (Q_empty_col) { *Q_empty_col-- = i; }
1212 empty_col.insert(i);
1215 for (
size_t i = 0; i != s1; ++i) {
1216 if (!row[i].empty()) {
1217 row_degree_iter[i] = row_degree.insert(std::pair<size_t, size_t>(row[i].size(), i));
1219 if (P_empty_row) { *P_empty_row-- = i; }
1220 empty_row.insert(i);
1226 for (k = 0; k != min_mn; ++k) {
1227 size_t i_pivot = s1;
1228 size_t j_pivot = s2;
1234 degree_t::const_iterator j = col_degree.begin();
1235 degree_t::const_iterator i = row_degree.begin();
1236 if (j == col_degree.end() || i == row_degree.end()) {
break; }
1237 assert(col[j->second].size() == j->first);
1238 assert(row[i->second].size() == i->first);
1239 double min_tol = std::numeric_limits<double>::max();
1240 double min_degree = s1 * s2;
1241 const size_t min_degree_all = i->first * j->first;
1243 const size_t min_degree_all1 = i->first * j->first;
1244 if (j->first <= i->first) {
1245 typename std::map<size_t, T>::const_iterator i1 = col[j->second].begin();
1246 if (j->first == 1 && row_degree_iter[i1->first] != row_degree.end()
1247 && col_degree_iter[j->second] != col_degree.end()) {
1251 i_pivot = i1->first;
1252 j_pivot = j->second;
1253 assert(col[j_pivot].find(i_pivot) != col[j_pivot].end());
1256 const typename std::map<size_t, T>::const_iterator i1_end =
1257 col[j->second].end();
1258 for (; i1 != i1_end; ++i1) {
1259 const size_t d = j->first * row[i1->first].size();
1260 if (d <= min_degree) {
1261 const T iv = T(1) / i1->second;
1262 double vc = b2000::norm(col_max[j->second] * iv);
1264 vc = std::max(vc,
double(b2000::norm(row_max[i1->first] * iv)));
1266 if (vc < min_tol && vc < tol_pivot
1267 && row_degree_iter[i1->first] != row_degree.end()
1268 && col_degree_iter[j->second] != col_degree.end()) {
1271 i_pivot = i1->first;
1272 j_pivot = j->second;
1273 assert(col[j_pivot].find(i_pivot) != col[j_pivot].end());
1279 typename std::map<size_t, T*>::const_iterator j1 = row[i->second].begin();
1280 if (i->first == 1 && row_degree_iter[i->second] != row_degree.end()
1281 && col_degree_iter[j1->first] != col_degree.end()) {
1285 i_pivot = i->second;
1286 j_pivot = j1->first;
1287 assert(col[j_pivot].find(i_pivot) != col[j_pivot].end());
1290 const typename std::map<size_t, T*>::const_iterator j1_end =
1291 row[i->second].end();
1292 for (; j1 != j1_end; ++j1) {
1293 const size_t d = i->first * col[j1->first].size();
1294 if (d <= min_degree) {
1295 const T iv = T(1) / *(j1->second);
1296 double vc = b2000::norm(col_max[j1->first] * iv);
1298 vc = std::min(vc,
double(b2000::norm(row_max[i->second] * iv)));
1300 if (vc < min_tol && vc < tol_pivot
1301 && row_degree_iter[i->second] != row_degree.end()
1302 && col_degree_iter[j1->first] != col_degree.end()) {
1305 i_pivot = i->second;
1306 j_pivot = j1->first;
1307 assert(col[j_pivot].find(i_pivot) != col[j_pivot].end());
1313 if (min_tol < 1.0001 && min_degree == min_degree_all) {
break; }
1314 if (min_tol < tol_pivot && min_degree_all1 > min_degree_all) {
break; }
1315 if (j == col_degree.end() || i == row_degree.end()) {
break; }
1319 if (i_pivot == s1) { Exception() <<
THROW; }
1321 col_degree.erase(col_degree_iter[j_pivot]);
1322 col_degree_iter[j_pivot] = col_degree.end();
1323 row_degree.erase(row_degree_iter[i_pivot]);
1324 row_degree_iter[i_pivot] = row_degree.end();
1330 typename std::map<size_t, T>::iterator i = col[j_pivot].find(i_pivot);
1331 assert(i != col[j_pivot].end());
1332 T value_pivot = i->second;
1336 const T inv_value_pivot = T(1) / value_pivot;
1337 i = col[j_pivot].begin();
1338 const typename std::map<size_t, T>::const_iterator i_end = col[j_pivot].end();
1339 for (; i != i_end; ++i) {
1340 L.index.push_back(i->first);
1341 L.m.push_back(i->first == i_pivot ? T(1) : i->second * inv_value_pivot);
1342 row[i->first].erase(j_pivot);
1345 col[j_pivot].clear();
1348 trans_U.index.push_back(j_pivot);
1349 trans_U.m.push_back(value_pivot);
1351 typename std::map<size_t, T*>::const_iterator j = row[i_pivot].begin();
1352 const typename std::map<size_t, T*>::const_iterator j_end = row[i_pivot].end();
1353 for (; j != j_end; ++j) {
1354 typename std::map<size_t, T>& col_j = col[j->first];
1355 typename std::map<size_t, T>::iterator ii = col_j.find(i_pivot);
1356 assert(ii != col_j.end());
1357 trans_U.index.push_back(j->first);
1358 trans_U.m.push_back(ii->second);
1360 for (
size_t iii = L.si.back(); iii != L.index.size(); ++iii) {
1361 if (L.index[iii] != i_pivot) {
1362 const T v = -L.m[iii] * trans_U.m.back();
1363 ii = col_j.find(L.index[iii]);
1364 if (ii == col_j.end()) {
1365 T* ptr = &(col_j.insert(std::pair<size_t, T>(L.index[iii], v))
1367 row[L.index[iii]].insert(std::pair<size_t, T*>(j->first, ptr));
1370 if (b2000::norm(ii->second) <= drop_tol) {
1372 row[L.index[iii]].erase(j->first);
1379 row[i_pivot].clear();
1382 for (
size_t jj = trans_U.si.back(); jj != trans_U.index.size(); ++jj) {
1383 const size_t j = trans_U.index[jj];
1384 if (j == j_pivot) {
continue; }
1386 typename std::map<size_t, T>::const_iterator i = col[j].begin();
1387 const typename std::map<size_t, T>::const_iterator i_end = col[j].end();
1389 for (; i != i_end; ++i) { max = std::max(max,
double(b2000::norm(i->second))); }
1392 if (col_degree_iter[j] != col_degree.end()) { col_degree.erase(col_degree_iter[j]); }
1393 col_degree_iter[j] = col_degree.end();
1394 if (!col[j].empty()) {
1395 col_degree_iter[j] = col_degree.insert(std::pair<size_t, size_t>(col[j].size(), j));
1397 if (Q_empty_col && empty_col.find(j) == empty_col.end()) { *Q_empty_col-- = j; }
1398 empty_col.insert(j);
1403 for (
size_t ii = L.si.back(); ii != L.index.size(); ++ii) {
1404 const size_t i = L.index[ii];
1405 if (i == i_pivot) {
continue; }
1407 typename std::map<size_t, T*>::const_iterator j = row[i].begin();
1408 const typename std::map<size_t, T*>::const_iterator j_end = row[i].end();
1410 for (; j != j_end; ++j) { max = std::max(max,
double(b2000::norm(*(j->second)))); }
1413 if (row_degree_iter[i] != row_degree.end()) { row_degree.erase(row_degree_iter[i]); }
1414 row_degree_iter[i] = row_degree.end();
1415 if (!row[i].empty()) {
1416 row_degree_iter[i] = row_degree.insert(std::pair<size_t, size_t>(row[i].size(), i));
1418 if (P_empty_row && empty_row.find(i) == empty_row.end()) { *P_empty_row-- = i; }
1419 empty_row.insert(i);
1425 U_diag[j_pivot] = b2000::norm(value_pivot);
1426 for (
size_t jj = trans_U.si.back(); jj != trans_U.index.size(); ++jj) {
1427 const size_t j = trans_U.index[jj];
1428 w[j] = std::max(w[j],
double(b2000::norm(trans_U.m[jj])));
1433 L.si.push_back(L.index.size());
1434 trans_U.si.push_back(trans_U.index.size());
1438 trans_U.index.clear();
1446 for (degree_t::const_iterator i = row_degree.begin(); i != row_degree.end();
1450 std::sort(P.begin() + k, P.end());
1454 pair_iterator<std::vector<size_t>::iterator,
typename std::vector<T>::iterator>;
1456 Index inv_P = P.make_dual();
1458 for (Index::const_iterator j = L.si.begin() + 1; j != L.si.end(); ++j) {
1459 const size_t i_end = *j;
1460 p_iter ii_begin(L.index.begin() + i, L.m.begin() + i);
1461 for (; i != i_end; ++i) {
1462 size_t& ii = L.index[i];
1465 p_iter ii_end(L.index.begin() + i, L.m.begin() + i);
1466 std::sort(ii_begin, ii_end, CompareFirstOfPair());
1472 for (degree_t::const_iterator j = col_degree.begin(); j != col_degree.end();
1476 std::sort(Q.begin() + k, Q.end());
1479 Index inv_Q = Q.make_dual();
1480 size_t i = trans_U.si[0];
1481 for (Index::const_iterator j = trans_U.si.begin() + 1; j != trans_U.si.end(); ++j) {
1482 const size_t i_end = *j;
1483 p_iter ii_begin(trans_U.index.begin() + i, trans_U.m.begin() + i);
1484 for (; i != i_end; ++i) {
1485 size_t& ii = trans_U.index[i];
1488 p_iter ii_end(trans_U.index.begin() + i, trans_U.m.begin() + i);
1489 std::sort(ii_begin, ii_end, CompareFirstOfPair());
1497 for (
size_t j = 0; j != s2; ++j) {
1498 if (U_diag[j] < tol_rank_abs || U_diag[j] < tol_rank_rel * w[j]) {
1507struct Mcompressed_col_ref {
1508 using base = Mcompressed_col_ref;
1509 using const_base = Mcompressed_col_st_constref;
1510 using copy = Mcompressed_col;
1513template <
typename T>
1514class Matrix<T, Mcompressed_col_ref> {
1516 Matrix() : s1(0), s2(0), si(0), index(0), m(0) {}
1518 Matrix(
size_t s1_,
size_t s2_,
size_t snn_,
size_t* si_,
size_t* index_, T* m_)
1519 : s1(s1_), s2(s2_), si(si_), index(index_), m(m_) {}
1521 Matrix(
const Matrix& m_) : s1(m_.s1), s2(m_.s2), si(m_.si), index(m_.index), m(m_.m) {}
1523 Matrix(Matrix<T, Mcompressed_col>& m_)
1524 : s1(m_.s1), s2(m_.si.size() - 1), si(&m_.si[0]), index(&m_.index[0]), m(&m_.m[0]) {}
1526 bool is_null()
const {
return m == 0; }
1528 bool is_null_value()
const {
1529 for (
size_t i = si[0]; i != si[s2]; ++i) {
1530 if (m[i] != 0) {
return false; }
1535 std::pair<size_t, size_t> size()
const {
return std::pair<size_t, size_t>(s1, s2); }
1537 size_t size1()
const {
return s1; }
1539 size_t size2()
const {
return s2; }
1541 T operator()(
size_t i,
size_t j)
const {
1542 const size_t* s = index + si[j];
1543 const size_t* e = index + si[j + 1];
1544 const size_t* ii = std::lower_bound(s, e, i);
1545 if (ii < e && *ii == i) {
return m[ii - index]; }
1549 template <
typename T1>
1550 void scale_row(
const Vector<T1, Vdense_constref>& v) {
1551 for (
size_t i = si[0]; i != si[s2]; ++i) { m[i] *= v[index[i]]; }
1554 template <
typename T1>
1555 void scale_col(
const Vector<T1, Vdense_constref>& v) {
1556 if (si[s2] == 0) {
return; }
1557 for (
size_t j = 0; j != size2(); ++j) {
1559 T* i_end = m + si[j + 1];
1561 while (i != i_end) { *i *= tmp; }
1565 template <
typename T1>
1566 void scale_invert_col(
const Vector<T1, Vdense_constref>& v) {
1567 if (si[s2] == 0) {
return; }
1569 for (
size_t i = 0; i != v.size(); ++i) {
1570 T1 tmp = T1(1) / v[i];
1571 for (T
const* i_end = m + index[i + 1]; ii != i_end; ++ii) { *ii *= tmp; }
1575 friend logging::Logger& operator<<(logging::Logger& l,
const Matrix& m) {
1576 l <<
"column compressed matrix of size (" << m.size1() <<
", " << m.size2() <<
") ";
1577 l.write(m.s2 + 1, m.si, 1,
"colind");
1578 l.write(m.si[m.s2], m.index + m.si[0], 1,
"rowind");
1579 l.write(m.si[m.s2], m.m + m.si[0], 1,
"value");
1583 friend std::ostream& operator<<(std::ostream& out,
const Matrix& m) {
1585 for (
size_t j = 0; j != m.s2; ++j) {
1586 for (
size_t i_end = m.si[j + 1]; i != i_end; ++i) {
1587 out <<
"(" << m.index[i] <<
", " << j <<
") = " << m.m[i] << std::endl;
1604template <
typename T>
1605Matrix<T, Mcompressed_col_ref> Matrix<T, Mcompressed_col_ref>::null;
1607struct Mcompressed_col_constref {
1608 using base = Mcompressed_col_st_constref;
1609 using const_base = Mcompressed_col_st_constref;
1610 using copy = Mcompressed_col;
1613template <
typename T>
1614class Matrix<T, Mcompressed_col_constref> {
1616 Matrix() : s1(0), s2(0), si(0), index(0), m(0) {}
1619 size_t s1_,
size_t s2_,
size_t snn_,
const size_t* si_,
const size_t* index_,
const T* m_)
1620 : s1(s1_), s2(s2_), si(si_), index(index_), m(m_) {}
1622 Matrix(
const Matrix& m_) : s1(m_.s1), s2(m_.s2), si(m_.si), index(m_.index), m(m_.m) {}
1624 Matrix(
const Matrix<T, Mcompressed_col_ref>& m_)
1625 : s1(m_.s1), s2(m_.s2), si(m_.si), index(m_.index), m(m_.m) {}
1627 Matrix(
const Matrix<T, Mcompressed_col>& m_)
1628 : s1(m_.s1), s2(m_.si.size() - 1), si(&m_.si[0]), index(&m_.index[0]), m(&m_.m[0]) {}
1630 bool is_null()
const {
return m == 0; }
1632 bool is_null_value()
const {
1633 for (
size_t i = si[0]; i != si[s2]; ++i) {
1634 if (m[i] != T(0)) {
return false; }
1639 std::pair<size_t, size_t> size()
const {
return std::pair<size_t, size_t>(s1, s2); }
1641 size_t size1()
const {
return s1; }
1643 size_t size2()
const {
return s2; }
1645 T operator()(
size_t i,
size_t j)
const {
1646 const size_t* s = index + si[j];
1647 const size_t* e = index + si[j + 1];
1648 const size_t* ii = std::lower_bound(s, e, i);
1649 if (ii < e && *ii == i) {
return m[ii - index]; }
1653 friend logging::Logger& operator<<(logging::Logger& l,
const Matrix& m) {
1654 l <<
"column compressed matrix of size (" << m.size1() <<
", " << m.size2() <<
") ";
1655 l.write(m.s2 + 1, m.si, 1,
"colind");
1656 l.write(m.si[m.s2], m.index + m.si[0], 1,
"rowind");
1657 l.write(m.si[m.s2], m.m + m.si[0], 1,
"value");
1661 friend std::ostream& operator<<(std::ostream& out,
const Matrix& m) {
1663 for (
size_t j = 0; j != m.s2; ++j) {
1664 for (
size_t i_end = m.si[j + 1]; i != i_end; ++i) {
1665 out <<
"(" << m.index[i] <<
", " << j <<
") = " << m.m[i] << std::endl;
1674 void LUFactorization(
1675 Matrix<T, Mcompressed_col>& trans_L, Matrix<T, Mcompressed_col>& U, Index& P, Index& Q,
1676 Vector<double, Vdense>& R);
1681 static void UMFPACK_clean_incomplete_factorization(
1682 Matrix<T, Mcompressed_col>& trans_L, Matrix<T, Mcompressed_col>& U,
const size_t nb_udiag,
1683 Index& P, Index& Q, Vector<double, Vdense>& R);
1688 const size_t* index;
1694void Matrix<double, Mcompressed_col_constref>::LUFactorization(
1695 Matrix<double, Mcompressed_col>& trans_L, Matrix<double, Mcompressed_col>& U, Index& P,
1696 Index& Q, Vector<double, Vdense>& R);
1699void Matrix<b2000::csda<double>, Mcompressed_col_constref>::LUFactorization(
1700 Matrix<b2000::csda<double>, Mcompressed_col>& trans_L,
1701 Matrix<b2000::csda<double>, Mcompressed_col>& U, Index& P, Index& Q,
1702 Vector<double, Vdense>& R);
1705void Matrix<std::complex<double>, Mcompressed_col_constref>::LUFactorization(
1706 Matrix<std::complex<double>, Mcompressed_col>& trans_L,
1707 Matrix<std::complex<double>, Mcompressed_col>& U, Index& P, Index& Q,
1708 Vector<double, Vdense>& R);
1710template <
typename T>
1711Matrix<T, Mcompressed_col_constref> Matrix<T, Mcompressed_col_constref>::null;
1713struct Mcompressed_col_st_constref {
1714 using base = Mcompressed_col_st_constref;
1715 using const_base = Mcompressed_col_st_constref;
1716 using copy = Mcompressed_col;
1719template <
typename T>
1720class Matrix<T, Mcompressed_col_st_constref> {
1722 Matrix() : s1(0), s2(0), si(0), index(0), m(0), scale(0), trans(0) {}
1725 size_t s1_,
size_t s2_,
size_t snn_,
const size_t* si_,
const size_t* index_,
const T* m_,
1726 T scale_,
bool trans_)
1727 : s1(s1_), s2(s2_), si(si_), index(index_), m(m_), scale(scale_), trans(trans_) {}
1729 Matrix(
const Matrix& m_)
1738 Matrix(
const Matrix<T, Mcompressed_col_ref>& m_)
1739 : s1(m_.s1), s2(m_.s2), si(m_.si), index(m_.index), m(m_.m), scale(1), trans(false) {}
1741 Matrix(
const Matrix<T, Mcompressed_col_constref>& m_)
1742 : s1(m_.s1), s2(m_.s2), si(m_.si), index(m_.index), m(m_.m), scale(1), trans(false) {}
1744 Matrix(
const Matrix<T, Mcompressed_col>& m_)
1746 s2(m_.si.size() - 1),
1748 index(&m_.index[0]),
1753 bool is_null()
const {
return m == 0; }
1755 std::pair<size_t, size_t> size()
const {
1757 return std::pair<size_t, size_t>(s2, s1);
1759 return std::pair<size_t, size_t>(s1, s2);
1763 size_t size1()
const {
1771 size_t size2()
const {
1779 T operator()(
size_t i,
size_t j)
const {
1780 if (trans) { std::swap(i, j); }
1781 const size_t* s = index + si[j];
1782 const size_t* e = index + si[j + 1];
1783 const size_t* ii = std::lower_bound(s, e, i);
1784 if (ii < e && *ii == i) {
return scale * m[ii - index]; }
1788 Matrix& operator*(T scale_) {
1793 Matrix& transpose() {
1794 trans = trans ? false :
true;
1802 return s1 == m_.s1 && s2 == m_.s2 && si == m_.si && index == m_.index && m == m_.m
1803 && scale == m_.scale && trans == m_.trans;
1809 const size_t* index;
1816template <
typename T>
1817Matrix<T, Mcompressed_col_st_constref> Matrix<T, Mcompressed_col_st_constref>::null;
1819struct Mcompressed_col_update_inv {
1820 using base = Mcompressed_col_ref;
1821 using const_base = Mcompressed_col_st_constref;
1822 using copy = Mcompressed_col_update_inv;
1823 using inverse = Mcompressed_col_update_inv;
1826template <
typename T>
1827class Matrix<T, Mcompressed_col_update_inv> {
1831 SparseMatrixConnectivityType connectivity_ = sparse_matrix_connectivity_unknown,
1833 : s1(s1_), value(s1_), solver(0), connectivity(connectivity_), dictionary(&dictionary_) {}
1835 Matrix(
const Matrix& m_)
1842 connectivity(m_.connectivity),
1843 dictionary(m_.dictionary) {}
1845 virtual ~Matrix() {
delete solver; }
1848 size_t s, SparseMatrixConnectivityType connectivity_ = sparse_matrix_connectivity_unknown,
1856 if (connectivity_ != sparse_matrix_connectivity_unknown) { connectivity = connectivity_; }
1861 size_t s1_,
size_t s2,
1862 SparseMatrixConnectivityType connectivity_ = sparse_matrix_connectivity_unknown,
1870 if (connectivity_ != sparse_matrix_connectivity_unknown) { connectivity = connectivity_; }
1874 void set_same_structure(
const Matrix& m_) {
1878 m.resize(m_.m.size());
1879 std::fill(m.begin(), m.end(), 0);
1880 connectivity = m_.connectivity;
1881 dictionary = m_.dictionary;
1884 virtual void set_zero() {
1885 std::fill(si.begin(), si.end(), 0);
1892 virtual bool is_null()
const {
return this == &null; }
1894 virtual void set_zero_same_struct() {
1895 for (
typename std::vector<std::vector<std::pair<size_t, T>>>::iterator i = value.begin();
1896 i != value.end(); ++i) {
1899 std::fill(m.begin(), m.end(), 0);
1900 if (solver) { solver->update_value(); }
1903 std::pair<size_t, size_t> size()
const {
1910 return std::pair<size_t, size_t>(s1, s);
1913 size_t size1()
const {
return s1; }
1915 size_t size2()
const {
1916 if (si.empty()) {
return value.size(); }
1917 return si.size() - 1;
1926 void InitializeRow(
size_t row,
const std::map<size_t, T>& row_contributions) {
1927 value[row].reserve(row_contributions.size());
1928 auto pos{begin(row_contributions)};
1930 for (; pos != end(row_contributions); pos++) {
1931 value[row].push_back(std::make_pair(pos->first, pos->second));
1935 size_t get_nb_nonzero()
const {
1938 for (
size_t i = 0; i != value.size(); ++i) { r += value[i].size(); }
1940 return index.size();
1949 T operator()(
size_t i,
size_t j)
const {
1951 typename std::vector<std::pair<size_t, T>>::const_iterator ii = std::lower_bound(
1952 value[j].begin(), value[j].end(), std::pair<size_t, T>(i, 0),
1953 CompareFirstOfPair());
1955 if (ii != value[j].end() && ii->first == i) {
return ii->second; }
1957 std::vector<size_t>::const_iterator s = index.begin() + si[j];
1958 std::vector<size_t>::const_iterator e = index.begin() + si[j + 1];
1959 std::vector<size_t>::const_iterator ii = std::lower_bound(s, e, i);
1960 if (ii < e && *ii == i) {
return m[ii - index.begin()]; }
1971 T& operator()(
size_t i,
size_t j) {
1975 typename std::vector<std::pair<size_t, T>>::iterator ii = std::lower_bound(
1976 value[j].begin(), value[j].end(), std::pair<size_t, T>(i, 0),
1977 CompareFirstOfPair());
1979 if (ii != value[j].end() && ii->first == i) {
return ii->second; }
1981 std::vector<size_t>::const_iterator s = index.begin() + si[j];
1982 std::vector<size_t>::const_iterator e = index.begin() + si[j + 1];
1983 std::vector<size_t>::const_iterator ii = std::lower_bound(s, e, i);
1984 if (ii < e && *ii == i) {
return m[ii - index.begin()]; }
1991 const Matrix<T, Mstructured_constref<Mrectangle_increment_st_constref>>& m_) {
1992 if (size() != m_.size()) {
1993 Exception() <<
"The two matrix do not have the same size, " << size() <<
" and "
1994 << m_.size() <<
THROW;
1996 for (
size_t j = 0; j != m_.m.s2; ++j) {
1997 std::vector<std::pair<size_t, T>> tmp;
1998 tmp.reserve(m_.m.s1);
1999 for (
size_t i = 0; i != m_.m.s1; ++i) {
2000 tmp.push_back(std::pair<size_t, T>(m_.index[i], m_.m(i, j)));
2002 std::sort(tmp.begin(), tmp.end(), CompareFirstOfPair());
2004 add_colomn(m_.index2[j], tmp.begin(), tmp.end());
2006 add_colomn(m_.index[j], tmp.begin(), tmp.end());
2012 Matrix& operator+=(
const Matrix<
2015 Mcompressed_col_st_constref,
2016 Mstructured_constref<Mrectangle_increment_st_constref>>,
2017 Mcompressed_col_st_constref>>& m_) {
2018 if (size1() < m_.size1() || size2() < m_.size2()) {
2019 Exception() <<
"The two matrix do not have the same size, " << size() <<
" and "
2020 << m_.size() <<
THROW;
2022 if (m_.m1.m1.trans ==
true || m_.m1.m2.m.s1 != m_.m1.m2.m.s2 || m_.m2.trans ==
false
2023 || m_.m1.m1.si != m_.m2.si || m_.m1.m1.index != m_.m2.index || m_.m1.m1.m != m_.m2.m) {
2027 const size_t* colind = m_.m2.si;
2028 const size_t* rowind = m_.m2.index;
2029 const T* value_ = m_.m2.m;
2030 const size_t input_size = m_.m1.m2.m.s1;
2031 const size_t* input_dof_numbering = m_.m1.m2.index;
2033 bool new_output_matrix =
false;
2034 std::map<size_t, size_t> tmp_rowind;
2035 const size_t* input_dof_numbering_begin = input_dof_numbering;
2036 const size_t*
const input_dof_numbering_end = input_dof_numbering_begin + input_size;
2037 while (input_dof_numbering_begin != input_dof_numbering_end) {
2038 const size_t* rowind_begin = rowind + colind[*input_dof_numbering_begin];
2039 const size_t*
const rowind_end = rowind + colind[*input_dof_numbering_begin + 1];
2040 const T* value_begin = value_ + colind[*input_dof_numbering_begin];
2041 std::pair<size_t, size_t> tmp_rowind_insert(
2042 0, input_dof_numbering_begin - input_dof_numbering);
2043 while (rowind_begin != rowind_end) {
2044 tmp_rowind_insert.first = *rowind_begin;
2045 if (!tmp_rowind.insert(tmp_rowind_insert).second || *value_begin != T(1)) {
2046 new_output_matrix =
true;
2051 ++input_dof_numbering_begin;
2053 const size_t output_size = tmp_rowind.size();
2054 std::vector<std::pair<size_t, size_t>> output_dof_numbering(
2055 tmp_rowind.begin(), tmp_rowind.end());
2056 std::vector<std::pair<size_t, T>> output_col(output_size);
2057 for (
size_t i = 0; i != output_size; ++i) {
2058 output_col[i].first = output_dof_numbering[i].first;
2060 const Matrix<T, Mrectangle_increment_st_constref>& input_matrix = m_.m1.m2.m;
2061 const T scale_ = m_.scale * m_.m1.scale * m_.m1.m1.scale * m_.m2.scale;
2062 if (!new_output_matrix) {
2063 for (
size_t j = 0; j != output_size; ++j) {
2064 size_t jj = output_dof_numbering[j].second;
2065 for (
size_t i = 0; i != output_size; ++i) {
2066 output_col[i].second =
2067 scale_ * input_matrix(output_dof_numbering[i].second, jj);
2069 add_colomn(output_dof_numbering[j].first, output_col.begin(), output_col.end());
2072 for (
size_t i = 0; i != output_size; ++i) {
2073 tmp_rowind[output_dof_numbering[i].first] = i;
2076 T* output_value_l = output_value;
2077 for (
size_t j = 0; j != input_size; ++j, output_value_l += output_size) {
2078 for (
size_t i = 0; i != input_size; ++i) {
2079 const size_t* rowind_begin = rowind + colind[input_dof_numbering[i]];
2080 const size_t*
const rowind_end = rowind + colind[input_dof_numbering[i] + 1];
2081 const T* value_begin = value_ + colind[input_dof_numbering[i]];
2082 const T v = scale_ * input_matrix(j, i);
2083 while (rowind_begin != rowind_end) {
2084 output_value_l[tmp_rowind[*rowind_begin++]] += *value_begin++ * v;
2088 for (
size_t i = 0; i != output_size; ++i) {
2089 for (
size_t j = 0; j != output_size; ++j) { output_col[j].second = 0; }
2090 for (
size_t j = 0; j != input_size; ++j) {
2091 const size_t* rowind_begin = rowind + colind[input_dof_numbering[j]];
2092 const size_t*
const rowind_end = rowind + colind[input_dof_numbering[j] + 1];
2093 const T* value_begin = value_ + colind[input_dof_numbering[j]];
2094 const T v = output_value[i + j * output_size];
2095 while (rowind_begin != rowind_end) {
2096 output_col[tmp_rowind[*rowind_begin++]].second += *value_begin++ * v;
2099 add_colomn(output_dof_numbering[i].first, output_col.begin(), output_col.end());
2101 std::fill_n(output_value, output_size * input_size, 0);
2106 Matrix& operator+=(
const Matrix<
2108 MMProd<Mcompressed_col_st_constref, Mcompressed_col_st_constref>,
2109 Mcompressed_col_st_constref>>& m_) {
2115 const Matrix<T, MMProd<Mcompressed_col_st_constref, Mcompressed_col_st_constref>>& m_) {
2116 if (size1() < m_.size1() || size2() < m_.size2()) {
2117 Exception() <<
"The two matrix do not have the same size, " << size() <<
" and "
2118 << m_.size() <<
THROW;
2123 Matrix<T, Mcompressed_col> m_m2_tmp;
2124 if (m_.m2.trans) { m_m2_tmp = m_.m2; }
2126 Matrix<T, Mcompressed_col_st_constref> m_m2(
2127 m_.m2.trans ? Matrix<T, Mcompressed_col_st_constref>(m_m2_tmp) : m_.m2);
2130 const size_t end_list_flag = m_.m1.size1();
2133 T scale = m_.scale * m_.m1.scale * m_m2.scale;
2134 const size_t* b_colind_begin = m_m2.si;
2135 const size_t*
const b_colind_end = b_colind_begin + m_m2.size2();
2136 size_t end_list = end_list_flag;
2138 while (b_colind_begin != b_colind_end) {
2139 const size_t* b_rowind_begin = &m_m2.index[*b_colind_begin];
2140 const T* b_value_begin = &m_m2.m[*b_colind_begin];
2141 const size_t*
const b_rowind_end = &m_m2.index[*++b_colind_begin];
2142 while (b_rowind_begin != b_rowind_end) {
2143 const size_t* a_rowind_begin = m_.m1.index + m_.m1.si[*b_rowind_begin];
2144 const size_t*
const a_rowind_end = m_.m1.index + m_.m1.si[*b_rowind_begin + 1];
2145 const T* a_value_begin = m_.m1.m + m_.m1.si[*b_rowind_begin++];
2146 const T b_value_begin_v = *b_value_begin++;
2147 while (a_rowind_begin != a_rowind_end) {
2148 tmp_value[*a_rowind_begin] += *a_value_begin++ * b_value_begin_v;
2149 if (!(std::numeric_limits<size_t>::max() - tmp_index[*a_rowind_begin])) {
2150 tmp_index[*a_rowind_begin] = end_list;
2151 end_list = *a_rowind_begin;
2156 std::vector<std::pair<size_t, T>> res_tmp;
2157 while (end_list != end_list_flag) {
2158 res_tmp.push_back(std::pair<size_t, T>(end_list, scale * tmp_value[end_list]));
2159 const size_t end_list_next = tmp_index[end_list];
2160 tmp_index[end_list] = std::numeric_limits<size_t>::max();
2161 tmp_value[end_list] = T(0);
2162 end_list = end_list_next;
2165 std::sort(res_tmp.begin(), res_tmp.end(), CompareFirstOfPair());
2166 add_colomn(col++, res_tmp.begin(), res_tmp.end());
2171 Matrix& operator-=(
const Matrix& m_) {
2173 const_cast<Matrix&
>(m_).value_to_ccarray();
2174 blas::axpy(m.size(), -1, &m_.m[0], 1, &m[0], 1);
2178 Matrix& operator+=(
const Matrix& m_) {
2180 const_cast<Matrix&
>(m_).value_to_ccarray();
2181 blas::axpy(m.size(), 1, &m_.m[0], 1, &m[0], 1);
2185 Matrix& operator+=(
const Matrix<T, Mcompressed_col_st_constref>& m_) {
2189 if (!std::equal(si.begin(), si.end(), m_.si)
2191 index.begin() + si[0], index.begin() + si[size2()], m_.index + m_.si[0])) {
2192 if (si.back() == 0) {
2193 si.assign(m_.si, m_.si + m_.s2 + 1);
2194 index.assign(m_.index, m_.index + si.back());
2195 m.assign(m_.m, m_.m + si.back());
2196 blas::scal(m.size(), m_.scale, &m[0], 1);
2198 size_t s_i = m_.si[0];
2200 for (
size_t j = 1; j != m_.s2 + 1; ++j) {
2201 const size_t s_i_end = m_.si[j];
2202 const size_t d_i_end = si[j];
2203 for (; d_i != d_i_end && s_i != s_i_end; ++d_i) {
2204 if (m_.index[s_i] == index[d_i]) { m[d_i] += m_.scale * m_.m[s_i++]; }
2207 if (s_i != s_i_end) {
2208 if (s_i_end - s_i == 1 && m_.m[s_i] == T(0)) {
2211 Exception() <<
THROW;
2217 blas::axpy(m.size(), m_.scale, &m_.m[0], 1, &m[0], 1);
2223 const Matrix<T, Sum<Mcompressed_col_st_constref, Mcompressed_col_st_constref>>& m_) {
2225 if (m_.m1.trans || m_.m2.trans || !std::equal(m_.m1.si, m_.m1.si + m_.m1.s2 + 1, m_.m2.si)
2227 m_.m1.index + m_.m1.si[0], m_.m1.index + m_.m1.si[m_.m1.s2],
2228 m_.m2.index + m_.m2.si[0])) {
2232 si.insert(si.begin(), m_.m1.si, m_.m1.si + m_.m1.s2 + 1);
2234 index.insert(index.begin(), m_.m1.index + m_.m1.si[0], m_.m1.index + m_.m1.si[m_.m1.s2]);
2235 m.resize(index.size());
2236 for (
size_t i = 0; i != m.size(); ++i) {
2237 m[i] = m_.scale * (m_.m1.scale * m_.m1.m[i] + m_.m2.scale * m_.m2.m[i]);
2242 Matrix& operator*=(T s) {
2244 blas::scal(m.size(), s, &m[0], 1);
2248 template <
typename STORAGE>
2249 void scale(
const Vector<T, STORAGE>& v_) {
2252 for (
size_t j = 1; j != si.size(); ++j) {
2253 const size_t i_end = si[j];
2254 for (; i != i_end; ++i) { m[i] *= v_[j] * v_[index[i]]; }
2258 void remove_empty_column(Index& index) {
2260 std::vector<std::vector<std::pair<size_t, T>>> value_tmp;
2262 for (
size_t i = 0; i != value.size(); ++i) {
2263 if (!value[i].empty()) {
2264 value_tmp.push_back(std::vector<std::pair<size_t, T>>());
2265 value_tmp.back().swap(value[i]);
2269 value.swap(value_tmp);
2273 void remove_empty_column(Index& index,
const double tol) {
2275 std::vector<std::vector<std::pair<size_t, T>>> value_tmp;
2277 for (
size_t i = 0; i != value.size(); ++i) {
2278 for (
typename std::vector<std::pair<size_t, T>>::const_iterator j = value[i].begin();
2279 j != value[i].end(); ++j) {
2280 if (b2000::norm(j->second) > tol) {
2281 value_tmp.push_back(std::vector<std::pair<size_t, T>>());
2282 value_tmp.back().swap(value[i]);
2288 value.swap(value_tmp);
2292 void remove_zero(
const double tol = 0) {
2296 for (
size_t j = 1; j != si.size(); ++j) {
2297 for (; i != si[j]; ++i) {
2298 if (b2000::norm(m[i]) > tol) {
2300 index[i_out] = index[i];
2306 index.resize(i_out);
2310 Vector<T, Vindex1_constref> get_diagonal() {
2312 return Vector<T, Vindex1_constref>(
2313 diag_index.size(), &m[0], diag_index.back(), &diag_index[0]);
2316 void get_diagonal(Vector<T>& diag) {
2318 diag.resize(si.size() - 1);
2319 for (
size_t j = 0; j != diag.size(); ++j) { diag[j] = m[si[j]]; }
2322 Matrix<T, Mcompressed_col_update_sub_ref> operator()(
const Interval& i,
const Interval& j) {
2323 return Matrix<T, Mcompressed_col_update_sub_ref>(*
this, i, j);
2326 operator const Matrix<T, Mcompressed_col_st_constref>()
const {
2327 const_cast<Matrix*
>(
this)->value_to_ccarray();
2328 return Matrix<T, Mcompressed_col_st_constref>(
2329 s1, si.size() - 1, m.size(), &si[0], &index[0], &m[0], 1,
false);
2332 friend logging::Logger& operator<<(logging::Logger& l,
const Matrix& m) {
2333 const_cast<Matrix&
>(m).value_to_ccarray();
2334 l <<
"column compressed matrix of size (" << m.size1() <<
", " << m.size2() <<
") ";
2335 l.write(m.si.size(), &m.si[0], 1,
"colind");
2337 l.write(m.index.size(), &m.index[0], 1,
"rowind");
2339 l.write(m.m.size(), &m.m[0], 1,
"value");
2343 size_t get_null_space_size() {
2344 if (si.size() <= 1) {
return 0; }
2345 if (solver == 0) {
return 0; }
2346 Matrix* noconst_this =
const_cast<Matrix<T, Mcompressed_col_update_inv>*
>(
this);
2347 return noconst_this->solver->get_null_space_size();
2350 void get_null_space(Matrix<T, Mrectangle_ref> nks) {
2351 if (si.size() <= 1) {
return; }
2352 Matrix* noconst_this =
const_cast<Matrix<T, Mcompressed_col_update_inv>*
>(
this);
2353 noconst_this->value_to_ccarray();
2355 noconst_this->solver = LU_sparse_solver<T>::new_default(connectivity, *dictionary);
2356 noconst_this->solver->init(
2357 si.size() - 1, index.size(), &si[0], &index[0], &m[0], connectivity, *dictionary);
2359 noconst_this->solver->get_null_space(nks.size1(), nks.size2(), nks.m, nks.size1());
2365 void set_diag_index() {
2367 if (diag_index.empty()) {
2368 diag_index.resize(si.size() - 1);
2370 for (
size_t j = 0; j != diag_index.size(); ++j) {
2371 for (
const size_t i_end = si[j + 1]; i != i_end; ++i) {
2372 if (index[i] == j) { diag_index[j] = i; }
2378 bool value_to_ccarray() {
2379 if (value.empty()) {
2380 if (si.empty()) { si.push_back(0); }
2385 si.reserve(value.size() + 1);
2387 typename std::vector<std::vector<std::pair<size_t, T>>>::const_iterator begin =
2389 typename std::vector<std::vector<std::pair<size_t, T>>>::const_iterator end =
2392 for (; begin != end; ++begin) { nnz += begin->size(); }
2395 for (begin = value.begin(); begin != end; ++begin) {
2396 typename std::vector<std::pair<size_t, T>>::const_iterator i = begin->begin();
2397 typename std::vector<std::pair<size_t, T>>::const_iterator i_end = begin->end();
2398 for (; i != i_end; ++i) {
2399 index.push_back(i->first);
2400 m.push_back(i->second);
2402 si.push_back(m.size());
2406 for (
size_t j = 0; j != value.size(); ++j) {
2407 nnz += si[j + 1] - si[j] + value[j].size();
2409 std::vector<size_t> si_tmp;
2410 si_tmp.reserve(si.size());
2411 si_tmp.push_back(0);
2412 std::vector<size_t> index_tmp;
2413 index_tmp.reserve(nnz);
2414 std::vector<T> m_tmp;
2416 for (
size_t j = 0; j != value.size(); ++j) {
2418 const size_t i_end = si[j + 1];
2419 if (!value[j].empty()) {
2420 typename std::vector<std::pair<size_t, T>>::const_iterator iv =
2422 typename std::vector<std::pair<size_t, T>>::const_iterator iv_end =
2425 if (i == i_end || iv->first < index[i]) {
2426 index_tmp.push_back(iv->first);
2427 m_tmp.push_back(iv->second);
2428 if (++iv == iv_end) {
break; }
2430 index_tmp.push_back(index[i]);
2431 m_tmp.push_back(m[i]);
2436 index_tmp.insert(index_tmp.end(), index.begin() + i, index.begin() + i_end);
2437 m_tmp.insert(m_tmp.end(), m.begin() + i, m.begin() + i_end);
2438 si_tmp.push_back(m_tmp.size());
2441 index.swap(index_tmp);
2453 size_t s,
size_t nrhs,
const T* b,
size_t ldb, T* x,
size_t ldx,
char left_or_right,
2454 Matrix<T, Mrectangle>& null_space, ssize_t max_null_space_vector)
const {
2455 if (s == 0) {
return; }
2456 Matrix* noconst_this =
const_cast<Matrix<T, Mcompressed_col_update_inv>*
>(
this);
2457 noconst_this->value_to_ccarray();
2459 noconst_this->solver = LU_sparse_solver<T>::new_default(connectivity, *dictionary);
2460 noconst_this->solver->init(
2461 si.size() - 1, index.size(), &si[0], &index[0], &m[0], connectivity, *dictionary);
2463 noconst_this->solver->resolve(s, nrhs, b, ldb, x, ldx, left_or_right);
2467 size_t col,
typename std::vector<std::pair<size_t, T>>::const_iterator begin,
2468 typename std::vector<std::pair<size_t, T>>::const_iterator end) {
2469 if (begin == end) {
return; }
2472 std::vector<std::pair<size_t, T>>& vcol = value[col];
2473 if (vcol.empty() || begin->first > vcol.back().first) {
2474 vcol.insert(vcol.end(), begin, end);
2476 std::vector<std::pair<size_t, T>> tmp;
2477 tmp.reserve(vcol.size() + (end - begin));
2478 typename std::vector<std::pair<size_t, T>>::const_iterator vbegin = vcol.begin();
2479 typename std::vector<std::pair<size_t, T>>::const_iterator vend = vcol.end();
2480 while (vbegin != vend && begin != end) {
2481 if (vbegin->first < begin->first) {
2482 tmp.push_back(*vbegin++);
2483 }
else if (vbegin->first > begin->first) {
2484 tmp.push_back(*begin++);
2487 std::pair<size_t, T>(vbegin->first, vbegin->second + begin->second));
2492 tmp.insert(tmp.end(), vbegin, vend);
2493 tmp.insert(tmp.end(), begin, end);
2497 size_t colind = si[col];
2498 T* beginv = &m[colind];
2499 size_t* begini = &index[colind];
2500 size_t* begini_end = &index[si[col + 1]];
2501 while (begini != begini_end) {
2502 if (*begini == begin->first) {
2503 *beginv += begin->second;
2504 if (++begin == end) {
break; }
2509 if (begin == end) {
return; }
2511 if (value.empty()) { value.resize(si.size() - 1); }
2512 std::vector<std::pair<size_t, T>>& vcol = value[col];
2513 beginv = &m[colind];
2514 begini = &index[colind];
2515 if (vcol.empty() || begin->first > vcol.back().first) {
2516 while (begin != end) {
2517 if (begini == begini_end || *begini > begin->first) {
2518 vcol.push_back(*begin++);
2520 if (*begini == begin->first) { *beginv += (begin++)->second; }
2526 std::vector<std::pair<size_t, T>> tmp;
2527 tmp.reserve(vcol.size() + (end - begin));
2528 typename std::vector<std::pair<size_t, T>>::const_iterator vbegin =
2530 typename std::vector<std::pair<size_t, T>>::const_iterator vend = vcol.end();
2531 while (begin != end) {
2532 if (begini == begini_end || *begini > begin->first) {
2533 while (vbegin != vend && vbegin->first < begin->first) {
2534 tmp.push_back(*vbegin++);
2536 if (vbegin != vend) {
2537 if (vbegin->first > begin->first) {
2538 tmp.push_back(*begin);
2540 tmp.push_back(std::pair<size_t, T>(
2541 vbegin->first, vbegin->second + begin->second));
2545 tmp.push_back(*begin);
2549 if (*begini == begin->first) { *beginv += (begin++)->second; }
2554 tmp.insert(tmp.end(), vbegin, vend);
2562 std::vector<size_t> si;
2564 std::vector<size_t> index;
2565 std::vector<size_t> diag_index;
2566 std::vector<std::vector<std::pair<size_t, T>>>
2569 LU_sparse_solver<T>* solver;
2570 SparseMatrixConnectivityType connectivity;
2571 const Dictionary* dictionary;
2575template <
typename T>
2576Matrix<T, Mcompressed_col_update_inv> Matrix<T, Mcompressed_col_update_inv>::null;
2578struct Mcompressed_col_update_inv_ext {
2579 using copy = Mcompressed_col_update_inv;
2580 using inverse = Mcompressed_col_update_inv;
2589template <
typename T>
2590class Matrix<T, Mcompressed_col_update_inv_ext> :
public Matrix<T, Mcompressed_col_update_inv> {
2593 size_t s1_ = 0,
size_t size_ext_ = 0,
2594 SparseMatrixConnectivityType connectivity_ = sparse_matrix_connectivity_unknown,
2596 : Matrix<T, Mcompressed_col_update_inv>(s1_, connectivity_, dictionary_),
2597 size_ext(size_ext_),
2600 Matrix(
const Matrix& m_) : size_ext(m_.size_ext), solver(0) {}
2602 ~Matrix() {
delete solver; }
2604 std::pair<size_t, size_t> size()
const {
2605 return std::pair<size_t, size_t>(
2606 Matrix<T, Mcompressed_col_update_inv>::size1() + size_ext,
2607 Matrix<T, Mcompressed_col_update_inv>::size2() + size_ext);
2610 size_t size1()
const {
return Matrix<T, Mcompressed_col_update_inv>::size1() + size_ext; }
2612 size_t size2()
const {
return Matrix<T, Mcompressed_col_update_inv>::size2() + size_ext; }
2615 size_t s,
size_t s_ext,
2616 SparseMatrixConnectivityType connectivity_ = sparse_matrix_connectivity_unknown,
2618 Matrix<T, Mcompressed_col_update_inv>::resize(s, connectivity_, dictionary_);
2623 Matrix<T, Mcompressed_col_update_inv>::set_zero();
2628 void set_zero_same_struct() {
2629 Matrix<T, Mcompressed_col_update_inv>::set_zero_same_struct();
2630 if (solver) { solver->update_value(); }
2633 bool is_null()
const {
return this == &null; }
2635 T operator()(
size_t i,
size_t j)
const {
2636 if (i < Matrix<T, Mcompressed_col_update_inv>::size1()
2637 && j < Matrix<T, Mcompressed_col_update_inv>::size2()) {
2638 return Matrix<T, Mcompressed_col_update_inv>::operator()(i, j);
2643 Matrix<T, Mcompressed_col_update_sub_ref> operator()(
const Interval& i,
const Interval& j) {
2644 return Matrix<T, Mcompressed_col_update_sub_ref>(*
this, i, j);
2648 size_t s,
size_t nrhs,
const T* b,
size_t ldb, T* x,
size_t ldx,
const T* ma,
const T* mb,
2649 const T* mc,
char left_or_right, Matrix<T, Mrectangle>& null_space,
2650 ssize_t max_null_space_vector)
const {
2651 Matrix* noconst_this =
const_cast<Matrix<T, Mcompressed_col_update_inv_ext>*
>(
this);
2652 if (noconst_this->value_to_ccarray()) {
2653 delete noconst_this->solver;
2654 noconst_this->solver = 0;
2657 noconst_this->solver = LU_extension_sparse_solver<T>::new_default(
2658 Matrix<T, Mcompressed_col_update_inv>::connectivity,
2659 *Matrix<T, Mcompressed_col_update_inv>::dictionary);
2660 noconst_this->solver->init(
2661 Matrix<T, Mcompressed_col_update_inv>::si.size() - 1,
2662 Matrix<T, Mcompressed_col_update_inv>::index.size(),
2663 &Matrix<T, Mcompressed_col_update_inv>::si[0],
2664 &Matrix<T, Mcompressed_col_update_inv>::index[0],
2665 &Matrix<T, Mcompressed_col_update_inv>::m[0], size_ext,
2666 Matrix<T, Mcompressed_col_update_inv>::connectivity,
2667 *Matrix<T, Mcompressed_col_update_inv>::dictionary);
2669 noconst_this->solver->resolve(s, nrhs, b, ldb, x, ldx, ma, mb, mc, left_or_right);
2676 LU_extension_sparse_solver<T>* solver;
2680template <
typename T>
2681Matrix<T, Mcompressed_col_update_inv_ext> Matrix<T, Mcompressed_col_update_inv_ext>::null;
2683struct Mcompressed_col_update_sub_ref {
2684 using copy = Mrectangle;
2687template <
typename T>
2688class Matrix<T, Mcompressed_col_update_sub_ref> {
2690 Matrix(Matrix<T, Mcompressed_col_update_inv>& m_,
const Interval& i_,
const Interval& j_)
2691 : m(m_), i(i_), j(j_) {}
2693 std::pair<size_t, size_t> size()
const {
return std::pair<size_t, size_t>(i.size(), j.size()); }
2695 size_t size1()
const {
return i.size(); }
2697 size_t size2()
const {
return j.size(); }
2699 Matrix& operator+=(
const Matrix<T, Mcompressed_col_constref>& m_) {
2700 if (size() != m_.size()) {
2701 Exception() <<
"The two matrix do not have the same size, " << size() <<
" and "
2702 << m_.size() <<
"." <<
THROW;
2704 std::vector<std::pair<size_t, T>> res;
2705 size_t ii = m_.si[0];
2706 for (
size_t jj = 0; jj != m_.size2(); ++jj) {
2707 const size_t ii_end = m_.si[jj + 1];
2709 res.reserve(ii_end - ii);
2710 for (; ii != ii_end; ++ii) {
2711 res.push_back(std::pair<size_t, T>(i[0] + m_.index[ii], m_.m[ii]));
2713 m.add_colomn(j[0] + jj, res.begin(), res.end());
2719 const Matrix<T, MMProd<Mcompressed_col_st_constref, Mcompressed_col_st_constref>>& m_) {
2720 if (size() != m_.size()) {
2721 Exception() <<
"The two matrix do not have the same size, " << size() <<
" and "
2722 << m_.size() <<
"." <<
THROW;
2725 if (!(m_.trans || m_.m1.trans || m_.m2.trans)) {
2727 const size_t end_list_flag = m_.m1.size1();
2730 const size_t* b_colind_begin = m_.m2.si;
2731 const size_t*
const b_colind_end = b_colind_begin + m_.m2.size2();
2732 size_t end_list = end_list_flag;
2734 while (b_colind_begin != b_colind_end) {
2735 const size_t* b_rowind_begin = &m_.m2.index[*b_colind_begin];
2736 const T* b_value_begin = &m_.m2.m[*b_colind_begin];
2737 const size_t*
const b_rowind_end = &m_.m2.index[*++b_colind_begin];
2738 while (b_rowind_begin != b_rowind_end) {
2739 const size_t* a_rowind_begin = m_.m1.index + m_.m1.si[*b_rowind_begin];
2740 const size_t*
const a_rowind_end = m_.m1.index + m_.m1.si[*b_rowind_begin + 1];
2741 const T* a_value_begin = m_.m1.m + m_.m1.si[*b_rowind_begin++];
2742 const T b_value_begin_v = *b_value_begin++;
2743 while (a_rowind_begin != a_rowind_end) {
2744 tmp_value[*a_rowind_begin] += *a_value_begin++ * b_value_begin_v;
2745 if (!(std::numeric_limits<size_t>::max() - tmp_index[*a_rowind_begin])) {
2746 tmp_index[*a_rowind_begin] = end_list;
2747 end_list = *a_rowind_begin;
2752 std::vector<std::pair<size_t, T>> res_tmp;
2753 while (end_list != end_list_flag) {
2754 res_tmp.push_back(std::pair<size_t, T>(i[end_list], tmp_value[end_list]));
2755 const size_t end_list_next = tmp_index[end_list];
2756 tmp_index[end_list] = std::numeric_limits<size_t>::max();
2757 tmp_value[end_list] = T(0);
2758 end_list = end_list_next;
2760 std::sort(res_tmp.begin(), res_tmp.end(), CompareFirstOfPair());
2761 m.add_colomn(col++, res_tmp.begin(), res_tmp.end());
2763 }
else if (!m_.trans && m_.m1.trans && m_.m2.trans) {
2764 std::vector<std::vector<std::pair<size_t, T>>> res_tmp(j.size());
2767 const size_t end_list_flag = m_.m2.size2();
2770 const size_t* b_colind_begin = m_.m1.si;
2771 const size_t*
const b_colind_end = b_colind_begin + m_.m1.size1();
2772 size_t end_list = end_list_flag;
2774 while (b_colind_begin != b_colind_end) {
2775 const size_t* b_rowind_begin = &m_.m1.index[*b_colind_begin];
2776 const T* b_value_begin = &m_.m1.m[*b_colind_begin];
2777 const size_t*
const b_rowind_end = &m_.m1.index[*++b_colind_begin];
2778 while (b_rowind_begin != b_rowind_end) {
2779 const size_t* a_rowind_begin = m_.m2.index + m_.m2.si[*b_rowind_begin];
2780 const size_t*
const a_rowind_end = m_.m2.index + m_.m2.si[*b_rowind_begin + 1];
2781 const T* a_value_begin = m_.m2.m + m_.m2.si[*b_rowind_begin++];
2782 const T b_value_begin_v = *b_value_begin++;
2783 while (a_rowind_begin != a_rowind_end) {
2784 tmp_value[*a_rowind_begin] += *a_value_begin++ * b_value_begin_v;
2785 if (!(std::numeric_limits<size_t>::max() - tmp_index[*a_rowind_begin])) {
2786 tmp_index[*a_rowind_begin] = end_list;
2787 end_list = *a_rowind_begin;
2792 while (end_list != end_list_flag) {
2793 res_tmp[end_list + j[0]].push_back(
2794 std::pair<size_t, T>(i[col], tmp_value[end_list]));
2795 const size_t end_list_next = tmp_index[end_list];
2796 tmp_index[end_list] = std::numeric_limits<size_t>::max();
2797 tmp_value[end_list] = T(0);
2798 end_list = end_list_next;
2802 for (
size_t jj = 0; jj != res_tmp.size(); ++jj) {
2803 if (!res_tmp[jj].empty()) {
2804 std::sort(res_tmp[jj].begin(), res_tmp[jj].end(), CompareFirstOfPair());
2805 m.add_colomn(j[jj], res_tmp[jj].begin(), res_tmp[jj].end());
2808 }
else if (!m_.trans && !m_.m1.trans && m_.m2.trans) {
2809 Matrix<T, Mcompressed_col> m_m2;
2813 const size_t end_list_flag = m_.m1.size1();
2816 T scale = m_.scale * m_.m1.scale;
2817 const size_t* b_colind_begin = &m_m2.si[0];
2818 const size_t*
const b_colind_end = b_colind_begin + m_m2.size2();
2819 size_t end_list = end_list_flag;
2821 while (b_colind_begin != b_colind_end) {
2822 const size_t* b_rowind_begin = &m_m2.index[*b_colind_begin];
2823 const T* b_value_begin = &m_m2.m[*b_colind_begin];
2824 const size_t*
const b_rowind_end = &m_m2.index[*++b_colind_begin];
2825 while (b_rowind_begin != b_rowind_end) {
2826 const size_t* a_rowind_begin = m_.m1.index + m_.m1.si[*b_rowind_begin];
2827 const size_t*
const a_rowind_end =
2828 m_.m1.index + m_.m1.si[*b_rowind_begin++ + 1];
2829 while (a_rowind_begin != a_rowind_end && *a_rowind_begin < col) {
2832 const T* a_value_begin = m_.m1.m + (a_rowind_begin - m_.m1.index);
2833 const T b_value_begin_v = *b_value_begin++;
2834 while (a_rowind_begin != a_rowind_end) {
2835 tmp_value[*a_rowind_begin] += *a_value_begin++ * b_value_begin_v;
2836 if (!(std::numeric_limits<size_t>::max() - tmp_index[*a_rowind_begin])) {
2837 tmp_index[*a_rowind_begin] = end_list;
2838 end_list = *a_rowind_begin;
2843 std::vector<std::pair<size_t, T>> res_tmp;
2844 while (end_list != end_list_flag) {
2846 std::pair<size_t, T>(i[end_list], scale * tmp_value[end_list]));
2847 const size_t end_list_next = tmp_index[end_list];
2848 tmp_index[end_list] = std::numeric_limits<size_t>::max();
2849 tmp_value[end_list] = T(0);
2850 end_list = end_list_next;
2853 std::sort(res_tmp.begin(), res_tmp.end(), CompareFirstOfPair());
2854 m.add_colomn(j[col++], res_tmp.begin(), res_tmp.end());
2864 Matrix<T, Mcompressed_col_update_inv>& m;
bool operator==(const csda< T1 > &a, const csda< T2 > &b)
Comparison of two csda numbers is performed on the real part only.
Definition b2csda.H:226
#define THROW
Definition b2exception.H:198
Definition b2dictionary.H:48
static Dictionary & get_empty()
Definition b2dictionary.C:78
static T * get(size_t size)
Definition b2linear_algebra_utils.H:50
void scale_2(T1 v[2], const T2 s)
Definition b2tensor_calculus.H:297
GenericException< UnimplementedError_name > UnimplementedError
Definition b2exception.H:314