18#ifndef B2MATRIX_SYM_COMPRESSED_H_
19#define B2MATRIX_SYM_COMPRESSED_H_
22#include <unordered_map>
24#include "b2linear_algebra_def.H"
25#include "b2sparse_solver.H"
26#include "b2vector_index.H"
28namespace b2000::b2linalg {
30struct Msym_compressed_col {
31 typedef Msym_compressed_col_ref base;
32 typedef Msym_compressed_col_st_constref const_base;
33 typedef Msym_compressed_col copy;
34 typedef Msym_compressed_col_update_inv inverse;
38class Matrix<T, Msym_compressed_col> {
40 Matrix(
size_t s1_ = 0,
size_t s2_ = 0,
size_t snn_ = 0)
41 : s1(s1_), si(s2_ + 1), m(snn_), index(snn_) {}
43 Matrix(
const Matrix& m_) : s1(m_.s1), si(m_.si), m(m_.m), index(m_.index) {}
45 template <
typename T1>
46 Matrix& operator=(
const Matrix<T1, Msym_compressed_col>& m_) {
49 m.assign(m_.m.begin(), m_.m.end());
54 template <
typename T1>
55 Matrix(
const Matrix<T1, Msym_compressed_col>& m_)
57 si(m_.si.begin(), m_.si.end()),
58 m(m_.m.begin(), m_.m.end()),
59 index(m_.index.begin(), m_.index.end()) {}
61 bool is_null()
const {
return this == &null; }
64 std::fill(si.begin(), si.end(), 0);
69 void resize(
size_t s1_,
size_t s2_) {
72 si.insert(si.end(), s2_ - size2(), si.back());
78 void resize(
size_t s1_,
size_t s2_,
size_t snn = 0) {
85 void swap(std::vector<size_t>& colind, std::vector<size_t>& rowind, std::vector<T>& value) {
86 s1 = colind.size() - 1;
92 void get_values(
size_t*& colind,
size_t*& rowind, T*& value) {
98 std::pair<size_t, size_t> size()
const {
99 return std::pair<size_t, size_t>(s1, si.size() == 0 ? 0 : si.size() - 1);
102 size_t size1()
const {
return s1; }
104 size_t size2()
const {
return si.size() == 0 ? 0 : si.size() - 1; }
106 size_t nb_nonzero()
const {
return si.back(); }
108 T operator()(
size_t i,
size_t j)
const {
109 if (i < j) { std::swap(i, j); }
110 std::vector<size_t>::const_iterator s = index.begin() + si[j];
111 std::vector<size_t>::const_iterator e = index.begin() + si[j + 1];
112 std::vector<size_t>::const_iterator ii = std::lower_bound(s, e, i);
113 if (ii < e && *ii == i) {
return m[ii - index.begin()]; }
117 friend logging::Logger& operator<<(logging::Logger& l,
const Matrix& m) {
118 l <<
"symmetric column compressed matrix of size (" << m.s1 <<
", " << m.s1 <<
") ";
119 l.write(m.si.size(), &m.si[0], 1,
"colind");
120 l.write(m.index.size(), &m.index[0], 1,
"rowind");
121 l.write(m.m.size(), &m.m[0], 1,
"value");
129 std::vector<size_t> si;
131 std::vector<size_t> index;
136Matrix<T, Msym_compressed_col> Matrix<T, Msym_compressed_col>::null;
138struct Msym_compressed_col_ref {
139 typedef Msym_compressed_col_ref base;
140 typedef Msym_compressed_col_st_constref const_base;
141 typedef Msym_compressed_col copy;
142 typedef Msym_compressed_col_update_inv inverse;
146class Matrix<T, Msym_compressed_col_ref> {
148 Matrix() : s1(0), s2(0), si(0), index(0), m(0) {}
150 Matrix(
size_t s1_,
size_t s2_,
size_t snn_,
size_t* si_,
size_t* index_, T* m_)
151 : s1(s1_), s2(s2_), si(si_), index(index_), m(m_) {}
153 Matrix(
const Matrix& m_) : s1(m_.s1), s2(m_.s2), si(m_.si), index(m_.index), m(m_.m) {}
155 Matrix(Matrix<T, Msym_compressed_col>& m_)
156 : s1(m_.s1), s2(m_.si.size() - 1), si(&m_.si[0]), index(&m_.index[0]), m(&m_.m[0]) {}
158 bool is_null()
const {
return m == 0; }
160 std::pair<size_t, size_t> size()
const {
return std::pair<size_t, size_t>(s1, s2); }
162 size_t size1()
const {
return s1; }
164 size_t size2()
const {
return s2; }
166 T operator()(
size_t i,
size_t j)
const {
167 if (i < j) { std::swap(i, j); }
168 const size_t* s = index + si[j];
169 const size_t* e = index + si[j + 1];
170 const size_t* ii = std::lower_bound(s, e, i);
171 if (ii < e && *ii == i) {
return m[ii - index]; }
175 friend logging::Logger& operator<<(logging::Logger& l,
const Matrix& m) {
176 l <<
"symmetric column compressed matrix of size (" << m.s1 <<
", " << m.s1 <<
") ";
177 l.write(m.s2 + 1, m.si, 1,
"colind");
178 l.write(m.si[m.s2], m.index, 1,
"rowind");
179 l.write(m.si[m.s2], m.m, 1,
"value");
195Matrix<T, Msym_compressed_col_ref> Matrix<T, Msym_compressed_col_ref>::null;
197struct Msym_compressed_col_constref {
198 typedef Msym_compressed_col_st_constref base;
199 typedef Msym_compressed_col_st_constref const_base;
200 typedef Msym_compressed_col copy;
201 typedef Msym_compressed_col_update_inv inverse;
205class Matrix<T, Msym_compressed_col_constref> {
207 Matrix() : s1(0), s2(0), si(0), index(0), m(0) {}
210 size_t s1_,
size_t s2_,
size_t snn_,
const size_t* si_,
const size_t* index_,
const T* m_)
211 : s1(s1_), s2(s2_), si(si_), index(index_), m(m_) {}
213 Matrix(
const Matrix& m_) : s1(m_.s1), s2(m_.s2), si(m_.si), index(m_.index), m(m_.m) {}
215 Matrix(
const Matrix<T, Msym_compressed_col_ref>& m_)
216 : s1(m_.s1), s2(m_.s2), si(m_.si), index(m_.index), m(m_.m) {}
218 Matrix(
const Matrix<T, Msym_compressed_col>& m_)
219 : s1(m_.s1), s2(m_.si.size() - 1), si(&m_.si[0]), index(&m_.index[0]), m(&m_.m[0]) {}
221 bool is_null()
const {
return m == 0; }
223 std::pair<size_t, size_t> size()
const {
return std::pair<size_t, size_t>(s1, s2); }
225 size_t size1()
const {
return s1; }
227 size_t size2()
const {
return s2; }
229 T operator()(
size_t i,
size_t j)
const {
230 if (i < j) { std::swap(i, j); }
231 const size_t* s = index + si[j];
232 const size_t* e = index + si[j + 1];
233 const size_t* ii = std::lower_bound(s, e, i);
234 if (ii < e && *ii == i) {
return m[ii - index]; }
238 friend logging::Logger& operator<<(logging::Logger& l,
const Matrix& m) {
239 l <<
"symmetric column compressed matrix of size (" << m.s1 <<
", " << m.s1 <<
") ";
240 l.write(m.s2 + 1, m.si, 1,
"colind");
241 l.write(m.si[m.s2], m.index, 1,
"rowind");
242 l.write(m.si[m.s2], m.m, 1,
"value");
258Matrix<T, Msym_compressed_col_constref> Matrix<T, Msym_compressed_col_constref>::null;
260struct Msym_compressed_col_st_constref {
261 typedef Msym_compressed_col_st_constref base;
262 typedef Msym_compressed_col_st_constref const_base;
263 typedef Msym_compressed_col copy;
264 typedef Msym_compressed_col_update_inv inverse;
268class Matrix<T, Msym_compressed_col_st_constref> {
270 Matrix() : s1(0), s2(0), si(0), index(0), m(0), scale(0) {}
273 size_t s1_,
size_t s2_,
size_t snn_,
const size_t* si_,
const size_t* index_,
const T* m_,
275 : s1(s1_), s2(s2_), si(si_), index(index_), m(m_), scale(scale_) {}
277 Matrix(
const Matrix& m_)
278 : s1(m_.s1), s2(m_.s2), si(m_.si), index(m_.index), m(m_.m), scale(m_.scale) {}
280 Matrix(
const Matrix<T, Msym_compressed_col_ref>& m_)
281 : s1(m_.s1), s2(m_.s2), si(m_.si), index(m_.index), m(m_.m), scale(1) {}
283 Matrix(
const Matrix<T, Msym_compressed_col_constref>& m_)
284 : s1(m_.s1), s2(m_.s2), si(m_.si), index(m_.index), m(m_.m), scale(1) {}
286 Matrix(
const Matrix<T, Msym_compressed_col>& m_)
288 s2(m_.si.size() - 1),
294 Matrix(Matrix<T, Msym_compressed_col_update_inv>& m_) : scale(1) {
295 m_.value_to_ccarray();
296 s1 = m_.si.size() - 1;
299 index = &m_.index[0];
303 bool is_null()
const {
return m == 0; }
305 std::pair<size_t, size_t> size()
const {
return std::pair<size_t, size_t>(s1, s2); }
307 size_t size1()
const {
return s1; }
309 size_t size2()
const {
return s2; }
311 T operator()(
size_t i,
size_t j)
const {
312 if (i < j) { std::swap(i, j); }
313 const size_t* s = index + si[j];
314 const size_t* e = index + si[j + 1];
315 const size_t* ii = std::lower_bound(s, e, i);
316 if (ii < e && *ii == i) {
return scale * m[ii - index]; }
320 Matrix& operator*(T scale_) {
338Matrix<T, Msym_compressed_col_st_constref> Matrix<T, Msym_compressed_col_st_constref>::null;
340struct Msym_compressed_col_update_inv {
341 typedef Msym_compressed_col_ref base;
342 typedef Msym_compressed_col_st_constref const_base;
343 typedef Msym_compressed_col_update_inv copy;
344 typedef Msym_compressed_col_update_inv inverse;
348class Matrix<T, Msym_compressed_col_update_inv> {
352 SparseMatrixConnectivityType connectivity_ = sparse_matrix_connectivity_unknown,
354 : value(s1_), solver(0), connectivity(connectivity_), dictionary(&dictionary_) {}
356 Matrix(
const Matrix& m_)
362 connectivity(m_.connectivity),
363 dictionary(m_.dictionary) {}
365 virtual ~Matrix() {
delete solver; }
368 size_t s, SparseMatrixConnectivityType connectivity_ = sparse_matrix_connectivity_unknown,
375 if (connectivity_ != sparse_matrix_connectivity_unknown) { connectivity = connectivity_; }
380 size_t s1,
size_t s2,
381 SparseMatrixConnectivityType connectivity_ = sparse_matrix_connectivity_unknown,
383 if (s1 != s2) { Exception() <<
THROW; }
385 if (connectivity_ != sparse_matrix_connectivity_unknown) { connectivity = connectivity_; }
389 void set_same_structure(
const Matrix& m_) {
390 const_cast<Matrix&
>(m_).value_to_ccarray();
393 m.resize(m_.m.size());
394 std::fill(m.begin(), m.end(), 0);
395 connectivity = m_.connectivity;
396 dictionary = m_.dictionary;
399 virtual void set_zero() {
408 virtual bool is_null()
const {
return this == &null; }
410 virtual void set_zero_same_struct() {
411 for (
typename std::vector<std::vector<std::pair<size_t, T>>>::iterator i = value.begin();
412 i != value.end(); ++i) {
415 std::fill(m.begin(), m.end(), 0);
416 if (solver) { solver->update_value(); }
419 std::pair<size_t, size_t> size()
const {
426 return std::pair<size_t, size_t>(s, s);
429 size_t get_nb_nonzero()
const {
432 for (
size_t i = 0; i != value.size(); ++i) { r += value[i].size(); }
437 size_t size1()
const {
438 if (si.empty()) {
return value.size(); }
439 return si.size() - 1;
442 size_t size2()
const {
443 if (si.empty()) {
return value.size(); }
444 return si.size() - 1;
453 void InitializeRow(
size_t row,
const std::map<size_t, T>& row_contributions) {
454 value[row].reserve(row_contributions.size());
455 auto pos{begin(row_contributions)};
457 for (; pos != end(row_contributions); pos++) {
458 value[row].push_back(std::make_pair(pos->first, pos->second));
467 T operator()(
size_t i,
size_t j)
const {
468 if (i < j) { std::swap(i, j); }
470 typename std::vector<std::pair<size_t, T>>::const_iterator ii = std::lower_bound(
471 value[j].begin(), value[j].end(), std::pair<size_t, T>(i, 0),
472 CompareFirstOfPair());
474 if (ii != value[j].end() && ii->first == i) {
return ii->second; }
477 std::vector<size_t>::const_iterator s = index.begin() + si[j];
478 std::vector<size_t>::const_iterator e = index.begin() + si[j + 1];
479 std::vector<size_t>::const_iterator ii = std::lower_bound(s, e, i);
480 if (ii < e && *ii == i) {
return m[ii - index.begin()]; }
491 T& operator()(
size_t i,
size_t j) {
494 if (i < j) { std::swap(i, j); }
497 typename std::vector<std::pair<size_t, T>>::iterator ii = std::lower_bound(
498 value[j].begin(), value[j].end(), std::pair<size_t, T>(i, T{}),
499 CompareFirstOfPair());
500 if (ii != value[j].end() && ii->first == i) {
return ii->second; }
502 std::vector<size_t>::const_iterator s = index.begin() + si[j];
503 std::vector<size_t>::const_iterator e = index.begin() + si[j + 1];
504 std::vector<size_t>::const_iterator ii = std::lower_bound(s, e, i);
505 if (ii < e && *ii == i) {
return m[ii - index.begin()]; }
512 Matrix& operator+=(
const Matrix<T, Mstructured_constref<Mpacked_st_constref>>& m_) {
513 if (size() != m_.size()) {
514 Exception() <<
"The two matrix do not have the same size, " << size() <<
" and "
515 << m_.size() <<
THROW;
517 std::vector<std::pair<size_t, T>> tmp;
519 for (
size_t j = 0; j != m_.m.s; ++j) {
521 size_t index_j = m_.index[j];
522 for (
size_t i = 0; i != m_.m.s; ++i) {
523 size_t index_i = m_.index[i];
524 if (index_i >= index_j) {
525 tmp.push_back(std::pair<size_t, T>(index_i, m_.m(i, j)));
528 std::sort(tmp.begin(), tmp.end(), CompareFirstOfPair());
529 add_colomn(index_j, tmp.begin(), tmp.end());
539 Mcompressed_col_st_constref, Mstructured_constref<Mpacked_st_constref>>,
540 Mcompressed_col_st_constref>>& m_) {
541 if (size1() < m_.size1()) {
542 Exception() <<
"The two matrix do not have the same size, " << size() <<
" and "
543 << m_.size() <<
THROW;
545 if (m_.m1.m1.trans ==
true || m_.m2.trans ==
false || m_.m1.m1.si != m_.m2.si
546 || m_.m1.m1.index != m_.m2.index || m_.m1.m1.m != m_.m2.m) {
550 const size_t* colind = m_.m2.si;
551 const size_t* rowind = m_.m2.index;
552 const T* value_ = m_.m2.m;
553 const size_t input_size = m_.m1.m2.m.s;
554 const size_t* input_dof_numbering = m_.m1.m2.index;
556 bool new_output_matrix =
false;
557 std::map<size_t, size_t> tmp_rowind;
558 const size_t* input_dof_numbering_begin = input_dof_numbering;
559 const size_t*
const input_dof_numbering_end = input_dof_numbering_begin + input_size;
560 while (input_dof_numbering_begin != input_dof_numbering_end) {
561 const size_t* rowind_begin = rowind + colind[*input_dof_numbering_begin];
562 const size_t*
const rowind_end = rowind + colind[*input_dof_numbering_begin + 1];
563 const T* value_begin = value_ + colind[*input_dof_numbering_begin];
564 std::pair<size_t, size_t> tmp_rowind_insert(
565 0, input_dof_numbering_begin - input_dof_numbering);
566 while (rowind_begin != rowind_end) {
567 tmp_rowind_insert.first = *rowind_begin;
568 if (!tmp_rowind.insert(tmp_rowind_insert).second || *value_begin != T(1)) {
569 new_output_matrix =
true;
574 ++input_dof_numbering_begin;
576 const size_t output_size = tmp_rowind.size();
577 std::vector<std::pair<size_t, size_t>> output_dof_numbering(
578 tmp_rowind.begin(), tmp_rowind.end());
579 std::vector<std::pair<size_t, T>> output_col(output_size);
580 for (
size_t i = 0; i != output_size; ++i) {
581 output_col[i].first = output_dof_numbering[i].first;
583 const Matrix<T, Mpacked_st_constref>& input_matrix = m_.m1.m2.m;
584 const T scale_ = m_.scale * m_.m1.scale * m_.m1.m1.scale * m_.m2.scale;
585 if (!new_output_matrix) {
586 for (
size_t j = 0; j != output_size; ++j) {
587 size_t jj = output_dof_numbering[j].second;
588 for (
size_t i = j; i != output_size; ++i) {
589 output_col[i].second =
590 scale_ * input_matrix(output_dof_numbering[i].second, jj);
592 add_colomn(output_dof_numbering[j].first, output_col.begin() + j, output_col.end());
596 std::map<size_t, size_t>::iterator ii = tmp_rowind.begin();
597 for (
size_t i = 0; i != output_size; ++i, ++ii) { ii->second = i; }
600 T* output_value_l = output_value;
601 for (
size_t j = 0; j != input_size; ++j, output_value_l += output_size) {
602 for (
size_t i = 0; i != input_size; ++i) {
603 const size_t* rowind_begin = rowind + colind[input_dof_numbering[i]];
604 const size_t*
const rowind_end = rowind + colind[input_dof_numbering[i] + 1];
605 const T* value_begin = value_ + colind[input_dof_numbering[i]];
606 const T v = scale_ * input_matrix(j, i);
607 while (rowind_begin != rowind_end) {
608 output_value_l[tmp_rowind[*rowind_begin++]] += *value_begin++ * v;
612 for (
size_t i = 0; i != output_size; ++i) {
613 for (
size_t j = 0; j != output_size; ++j) { output_col[j].second = 0; }
614 for (
size_t j = 0; j != input_size; ++j) {
615 const size_t* rowind_begin = rowind + colind[input_dof_numbering[j]];
616 const size_t*
const rowind_end = rowind + colind[input_dof_numbering[j] + 1];
617 const T* value_begin = value_ + colind[input_dof_numbering[j]];
618 const T v = output_value[i + j * output_size];
619 while (rowind_begin != rowind_end) {
620 output_col[tmp_rowind[*rowind_begin++]].second += *value_begin++ * v;
623 add_colomn(output_dof_numbering[i].first, output_col.begin() + i, output_col.end());
625 std::fill_n(output_value, output_size * input_size, 0);
633 MMProd<Mcompressed_col_st_constref, Msym_compressed_col_st_constref>,
634 Mcompressed_col_st_constref>>& m_) {
635 if (size() < m_.size()) {
636 Exception() <<
"The two matrix do not have the same size, " << size() <<
" and "
637 << m_.size() <<
THROW;
639 if (m_.m1.m1.trans ==
true || m_.m2.trans ==
false || m_.m1.m1.si != m_.m2.si
640 || m_.m1.m1.index != m_.m2.index || m_.m1.m1.m != m_.m2.m) {
644 Matrix<T, Mcompressed_col> M2;
646 Matrix<T, Mcompressed_col> M12;
647 M12 = m_.m1.scale * (m_.m1.m1 * M2);
649 Matrix<T, Mcompressed_col> M123;
650 M123 = m_.scale * (M12 * M2);
652 std::vector<std::pair<size_t, T>> res_tmp;
653 size_t mi = M123.si[0];
654 for (
size_t j = 0; j != M123.s1; ++j) {
655 const size_t mi_end = M123.si[j + 1];
656 for (; mi != mi_end && M123.index[mi] < j; ++mi) { ; }
658 res_tmp.resize(mi_end - mi);
659 for (
size_t i = 0; mi != mi_end; ++i, ++mi) {
660 res_tmp[i].first = M123.index[mi];
661 res_tmp[i].second = M123.m[mi];
663 add_colomn(j, res_tmp.begin(), res_tmp.end());
670 const Matrix<T, MMProd<Mcompressed_col_st_constref, Mcompressed_col_st_constref>>& m_) {
671 if (size1() < m_.size1() || size2() < m_.size2()) {
672 Exception() <<
"The two matrix do not have the same size, " << size() <<
" and "
673 << m_.size() <<
THROW;
677 if (m_.m1.m != m_.m2.m) { Exception() <<
THROW; }
679 Matrix<T, Mcompressed_col> m_m2;
683 const size_t end_list_flag = m_.m1.size1();
686 T scale = m_.scale * m_.m1.scale;
687 const size_t* b_colind_begin = &m_m2.si[0];
688 const size_t*
const b_colind_end = b_colind_begin + m_m2.size2();
689 size_t end_list = end_list_flag;
691 while (b_colind_begin != b_colind_end) {
692 const size_t* b_rowind_begin = &m_m2.index[*b_colind_begin];
693 const T* b_value_begin = &m_m2.m[*b_colind_begin];
694 const size_t*
const b_rowind_end = &m_m2.index[*++b_colind_begin];
695 while (b_rowind_begin != b_rowind_end) {
696 const size_t* a_rowind_begin = m_.m1.index + m_.m1.si[*b_rowind_begin];
697 const size_t*
const a_rowind_end = m_.m1.index + m_.m1.si[*b_rowind_begin++ + 1];
698 while (a_rowind_begin != a_rowind_end && *a_rowind_begin < col) {
701 const T* a_value_begin = m_.m1.m + (a_rowind_begin - m_.m1.index);
702 const T b_value_begin_v = *b_value_begin++;
703 while (a_rowind_begin != a_rowind_end) {
704 tmp_value[*a_rowind_begin] += *a_value_begin++ * b_value_begin_v;
705 if (!(std::numeric_limits<size_t>::max() - tmp_index[*a_rowind_begin])) {
706 tmp_index[*a_rowind_begin] = end_list;
707 end_list = *a_rowind_begin;
712 std::vector<std::pair<size_t, T>> res_tmp;
713 while (end_list != end_list_flag) {
714 res_tmp.push_back(std::pair<size_t, T>(end_list, scale * tmp_value[end_list]));
715 const size_t end_list_next = tmp_index[end_list];
716 tmp_index[end_list] = std::numeric_limits<size_t>::max();
717 tmp_value[end_list] = T(0);
718 end_list = end_list_next;
721 std::sort(res_tmp.begin(), res_tmp.end(), CompareFirstOfPair());
722 add_colomn(col++, res_tmp.begin(), res_tmp.end());
727 Matrix& operator+=(
const Matrix& m_) {
729 const_cast<Matrix&
>(m_).value_to_ccarray();
730 if (size1() != m_.size1()) {
731 Exception() <<
"The two matrices do not have the same size." <<
THROW;
733 if (!std::equal(si.begin(), si.end(), m_.si.begin())
735 index.begin() + si.front(), index.begin() + si.back(),
736 m_.index.begin() + m_.si.front())) {
739 blas::axpy(m.size(), 1, &m_.m[0], 1, &m[0], 1);
743 Matrix& operator-=(
const Matrix& m_) {
744 if (size1() != m_.size1()) {
745 Exception() <<
"The two matrices do not have the same size." <<
THROW;
748 const_cast<Matrix&
>(m_).value_to_ccarray();
749 if (!std::equal(si.begin(), si.end(), m_.si.begin())
751 index.begin() + si.front(), index.begin() + si.back(),
752 m_.index.begin() + m_.si.front())) {
753 if (si.back() == 0) {
757 blas::scal(m.size(), -1, &m[0], 1);
762 blas::axpy(m.size(), -1, &m_.m[0], 1, &m[0], 1);
767 Matrix& operator+=(
const Matrix<T, Msym_compressed_col_st_constref>& m_) {
770 if (!std::equal(si.begin(), si.end(), m_.si)
772 index.begin() + si[0], index.begin() + si[size2()], m_.index + m_.si[0])) {
773 if (si.back() == 0) {
774 si.assign(m_.si, m_.si + m_.s2 + 1);
775 index.assign(m_.index, m_.index + si.back());
776 m.assign(m_.m, m_.m + si.back());
777 blas::scal(m.size(), m_.scale, &m[0], 1);
779 size_t s_i = m_.si[0];
781 for (
size_t j = 1; j != m_.s2 + 1; ++j) {
782 const size_t s_i_end = m_.si[j];
783 const size_t d_i_end = si[j];
784 for (; d_i != d_i_end && s_i != s_i_end; ++d_i) {
785 if (m_.index[s_i] == index[d_i]) { m[d_i] += m_.scale * m_.m[s_i++]; }
788 if (s_i != s_i_end) {
789 if (s_i_end - s_i == 1 && m_.m[s_i] == T(0)) {
792 Exception() <<
THROW;
798 blas::axpy(m.size(), m_.scale, &m_.m[0], 1, &m[0], 1);
804 const Matrix<T, Sum<Msym_compressed_col_st_constref, Msym_compressed_col_st_constref>>&
807 if (!std::equal(m_.m1.si, m_.m1.si + m_.m1.s2 + 1, m_.m2.si)
809 m_.m1.index + m_.m1.si[0], m_.m1.index + m_.m1.si[m_.m1.s2],
810 m_.m2.index + m_.m2.si[0])) {
815 si.insert(si.begin(), m_.m1.si, m_.m1.si + m_.m1.s2 + 1);
817 index.insert(index.begin(), m_.m1.index + m_.m1.si[0], m_.m1.index + m_.m1.si[m_.m1.s2]);
818 m.resize(index.size());
819 for (
size_t i = 0; i != m.size(); ++i) {
820 m[i] = m_.scale * (m_.m1.scale * m_.m1.m[i] + m_.m2.scale * m_.m2.m[i]);
825 Matrix& operator*=(T s) {
827 blas::scal(m.size(), s, &m[0], 1);
831 template <
typename STORAGE>
832 void scale(
const Vector<T, STORAGE>& v_) {
835 for (
size_t j = 1; j != si.size(); ++j) {
836 const size_t i_end = si[j];
837 for (; i != i_end; ++i) { m[i] *= v_[j] * v_[index[i]]; }
841 Vector<T, Vindex1_constref> get_diagonal() {
843 return Vector<T, Vindex1_constref>(si.size() - 1, &m[0], si.back(), &si[0]);
846 void get_diagonal(Vector<T>& diag) {
848 diag.resize(si.size() - 1);
849 for (
size_t j = 0; j != diag.size(); ++j) { diag[j] = m[si[j]]; }
852 Matrix<T, Msym_compressed_col_update_sub_ref> operator()(
const Interval& i,
const Interval& j) {
853 return Matrix<T, Msym_compressed_col_update_sub_ref>(*
this, i, j);
856 operator const Matrix<T, Msym_compressed_col_st_constref>()
const {
857 const_cast<Matrix*
>(
this)->value_to_ccarray();
858 return Matrix<T, Msym_compressed_col_st_constref>(
859 si.size() - 1, si.size() - 1, m.size(), &si[0], &index[0], &m[0], 1);
862 friend logging::Logger& operator<<(logging::Logger& l,
const Matrix& m) {
863 const_cast<Matrix&
>(m).value_to_ccarray();
864 l <<
"symmetric column compressed matrix of size (" << m.size1() <<
", " << m.size2()
866 l.write(m.si.size(), &m.si[0], 1,
"colind");
868 l.write(m.index.size(), &m.index[0], 1,
"rowind");
870 l.write(m.m.size(), &m.m[0], 1,
"value");
874 friend std::ostream& operator<<(std::ostream& out,
const Matrix& m) {
875 const_cast<Matrix&
>(m).value_to_ccarray();
876 out <<
"{" << std::setprecision(15);
878 for (
size_t j = 0; j != m.si.size() - 1; ++j) {
879 for (
size_t i_end = m.si[j + 1]; i != i_end; ++i) {
880 if (m.m[i] != 0) { out <<
"(" << m.index[i] <<
", " << j <<
"):" << m.m[i] <<
","; }
912 size_t get_null_space_size() {
913 if (si.size() <= 1) {
return 0; }
914 if (solver == 0) {
return 0; }
915 Matrix* noconst_this =
const_cast<Matrix<T, Msym_compressed_col_update_inv>*
>(
this);
916 return noconst_this->solver->get_null_space_size();
919 void get_null_space(Matrix<T, Mrectangle_ref> nks) {
920 if (si.size() <= 1) {
return; }
921 if (solver == 0) {
return; }
922 Matrix* noconst_this =
const_cast<Matrix<T, Msym_compressed_col_update_inv>*
>(
this);
923 noconst_this->solver->get_null_space(nks.size1(), nks.size2(), nks.m, nks.size1());
926 void remove_zero(
const double tol = 0) {
930 for (
size_t j = 1; j != si.size(); ++j) {
931 for (; i != si[j]; ++i) {
932 if (b2000::norm(m[i]) > tol) {
934 index[i_out] = index[i];
947 bool value_to_ccarray() {
949 if (si.empty()) { si.push_back(0); }
953 si.reserve(value.size() + 1);
955 typename std::vector<std::vector<std::pair<size_t, T>>>::const_iterator begin =
957 typename std::vector<std::vector<std::pair<size_t, T>>>::const_iterator end =
960 for (; begin != end; ++begin) {
961 nnz += begin->size();
962 if (begin->empty()) { ++nnz; }
966 for (begin = value.begin(); begin != end; ++begin) {
967 if (begin->empty()) {
968 index.push_back(begin - value.begin());
971 typename std::vector<std::pair<size_t, T>>::const_iterator i = begin->begin();
972 typename std::vector<std::pair<size_t, T>>::const_iterator i_end = begin->end();
973 for (; i != i_end; ++i) {
974 index.push_back(i->first);
975 m.push_back(i->second);
978 si.push_back(m.size());
982 for (
size_t j = 0; j != value.size(); ++j) {
983 nnz += si[j + 1] - si[j] + value[j].size();
985 std::vector<size_t> si_tmp;
986 si_tmp.reserve(si.size());
988 std::vector<size_t> index_tmp;
989 index_tmp.reserve(nnz);
990 std::vector<T> m_tmp;
992 for (
size_t j = 0; j != value.size(); ++j) {
994 const size_t i_end = si[j + 1];
995 if (!value[j].empty()) {
996 typename std::vector<std::pair<size_t, T>>::const_iterator iv =
998 typename std::vector<std::pair<size_t, T>>::const_iterator iv_end =
1001 if (i == i_end || iv->first < index[i]) {
1002 index_tmp.push_back(iv->first);
1003 m_tmp.push_back(iv->second);
1004 if (++iv == iv_end) {
break; }
1006 index_tmp.push_back(index[i]);
1007 m_tmp.push_back(m[i]);
1012 index_tmp.insert(index_tmp.end(), index.begin() + i, index.begin() + i_end);
1013 m_tmp.insert(m_tmp.end(), m.begin() + i, m.begin() + i_end);
1014 si_tmp.push_back(m_tmp.size());
1017 index.swap(index_tmp);
1029 size_t s,
size_t nrhs,
const T* b,
size_t ldb, T* x,
size_t ldx,
char left_or_right,
1030 Matrix<T, Mrectangle>& null_space, ssize_t max_null_space_vector)
const {
1031 if (s == 0) {
return; }
1032 Matrix* noconst_this =
const_cast<Matrix<T, Msym_compressed_col_update_inv>*
>(
this);
1033 noconst_this->value_to_ccarray();
1036 noconst_this->solver =
1037 LDLt_sparse_solver<T>::new_default(connectivity, *dictionary);
1038 noconst_this->solver->init(
1039 si.size() - 1, index.size(), &si[0], &index[0], &m[0], connectivity,
1042 noconst_this->solver->resolve(s, nrhs, b, ldb, x, ldx, left_or_right);
1043 }
catch (SingularMatrixError& e) {
1044 if (max_null_space_vector != 0) {
1046 max_null_space_vector > 0
1047 && ssize_t(e.null_space_size) > max_null_space_vector
1048 ? max_null_space_vector
1049 : e.null_space_size;
1050 null_space.resize(s, nbnv);
1051 noconst_this->solver->get_null_space(s, nbnv, &null_space(0, 0), s);
1055 const size_t nss = noconst_this->solver->get_null_space_size();
1056 if (max_null_space_vector != 0 && nss > 0) {
1057 const size_t nbnv = max_null_space_vector > 0 && ssize_t(nss) > max_null_space_vector
1058 ? max_null_space_vector
1060 null_space.resize(s, nbnv);
1061 noconst_this->solver->get_null_space(s, nbnv, &null_space(0, 0), s);
1066 size_t col,
typename std::vector<std::pair<size_t, T>>::const_iterator begin,
1067 typename std::vector<std::pair<size_t, T>>::const_iterator end) {
1068 if (begin == end) {
return; }
1071 std::vector<std::pair<size_t, T>>& vcol = value[col];
1072 if (vcol.empty() || begin->first > vcol.back().first) {
1073 vcol.insert(vcol.end(), begin, end);
1075 std::vector<std::pair<size_t, T>> tmp;
1076 tmp.reserve(vcol.size() + (end - begin));
1077 typename std::vector<std::pair<size_t, T>>::const_iterator vbegin = vcol.begin();
1078 typename std::vector<std::pair<size_t, T>>::const_iterator vend = vcol.end();
1079 while (vbegin != vend && begin != end) {
1080 if (vbegin->first < begin->first) {
1081 tmp.push_back(*vbegin++);
1082 }
else if (vbegin->first > begin->first) {
1083 tmp.push_back(*begin++);
1086 std::pair<size_t, T>(vbegin->first, vbegin->second + begin->second));
1091 tmp.insert(tmp.end(), vbegin, vend);
1092 tmp.insert(tmp.end(), begin, end);
1096 size_t colind = si[col];
1097 T* beginv = &m[colind];
1098 size_t* begini = &index[colind];
1099 size_t* begini_end = &index[si[col + 1]];
1100 while (begini != begini_end) {
1101 if (*begini == begin->first) {
1102 *beginv += begin->second;
1103 if (++begin == end) {
break; }
1108 if (begin == end) {
return; }
1110 if (value.empty()) { value.resize(si.size() - 1); }
1111 std::vector<std::pair<size_t, T>>& vcol = value[col];
1112 beginv = &m[colind];
1113 begini = &index[colind];
1114 if (vcol.empty() || begin->first > vcol.back().first) {
1115 while (begin != end) {
1116 if (begini == begini_end || *begini > begin->first) {
1117 vcol.push_back(*begin++);
1119 if (*begini == begin->first) { *beginv += (begin++)->second; }
1125 std::vector<std::pair<size_t, T>> tmp;
1126 tmp.reserve(vcol.size() + (end - begin));
1127 typename std::vector<std::pair<size_t, T>>::const_iterator vbegin =
1129 typename std::vector<std::pair<size_t, T>>::const_iterator vend = vcol.end();
1130 while (begin != end) {
1131 if (begini == begini_end || *begini > begin->first) {
1132 while (vbegin != vend && vbegin->first < begin->first) {
1133 tmp.push_back(*vbegin++);
1135 if (vbegin != vend) {
1136 if (vbegin->first > begin->first) {
1137 tmp.push_back(*begin);
1139 tmp.push_back(std::pair<size_t, T>(
1140 vbegin->first, vbegin->second + begin->second));
1144 tmp.push_back(*begin);
1148 if (*begini == begin->first) { *beginv += (begin++)->second; }
1153 tmp.insert(tmp.end(), vbegin, vend);
1160 std::vector<size_t> si;
1162 std::vector<size_t> index;
1163 std::vector<std::vector<std::pair<size_t, T>>>
1167 LDLt_sparse_solver<T>* solver;
1168 SparseMatrixConnectivityType connectivity;
1169 const Dictionary* dictionary;
1173template <
typename T>
1174Matrix<T, Msym_compressed_col_update_inv> Matrix<T, Msym_compressed_col_update_inv>::null;
1176struct Msym_compressed_col_update_inv_ext {
1177 typedef Msym_compressed_col_update_inv_ext const_base;
1178 typedef Msym_compressed_col_update_inv_ext copy;
1179 typedef Msym_compressed_col_update_inv_ext inverse;
1188template <
typename T>
1189class Matrix<T, Msym_compressed_col_update_inv_ext>
1190 :
public Matrix<T, Msym_compressed_col_update_inv> {
1193 size_t s1_ = 0,
size_t size_ext_ = 0,
1194 SparseMatrixConnectivityType connectivity_ = sparse_matrix_connectivity_unknown,
1196 : Matrix<T, Msym_compressed_col_update_inv>(s1_, connectivity_, dictionary_),
1197 size_ext(size_ext_),
1198 m_ab(2 * s1_ * size_ext_) {
1202 Matrix(
const Matrix& m_) : size_ext(m_.size_ext) {}
1204 std::pair<size_t, size_t> size()
const {
1205 return std::pair<size_t, size_t>(
1206 Matrix<T, Msym_compressed_col_update_inv>::size1() + size_ext,
1207 Matrix<T, Msym_compressed_col_update_inv>::size2() + size_ext);
1210 size_t size1()
const {
return Matrix<T, Msym_compressed_col_update_inv>::size1() + size_ext; }
1212 size_t size2()
const {
return Matrix<T, Msym_compressed_col_update_inv>::size2() + size_ext; }
1215 size_t s,
size_t s_ext,
1216 SparseMatrixConnectivityType connectivity_ = sparse_matrix_connectivity_unknown,
1218 Matrix<T, Msym_compressed_col_update_inv>::resize(s, connectivity_, dictionary_);
1220 m_ab.resize(s * 2 * size_ext);
1224 void set_zero() { Matrix<T, Msym_compressed_col_update_inv>::set_zero(); }
1226 void set_zero_same_struct() {
1227 Matrix<T, Msym_compressed_col_update_inv>::set_zero_same_struct();
1230 bool is_null()
const {
return this == &null; }
1232 T operator()(
size_t i,
size_t j)
const {
1233 if (i < Matrix<T, Msym_compressed_col_update_inv>::size1()
1234 && j < Matrix<T, Msym_compressed_col_update_inv>::size2()) {
1235 return Matrix<T, Msym_compressed_col_update_inv>::operator()(i, j);
1240 Matrix<T, Msym_compressed_col_update_sub_ref> operator()(
const Interval& i,
const Interval& j) {
1241 return Matrix<T, Msym_compressed_col_update_sub_ref>(*
this, i, j);
1245 size_t s,
size_t nrhs,
const T* b,
size_t ldb, T* x,
size_t ldx,
const T* ma,
const T* mb,
1246 const T* mc,
char left_or_right, Matrix<T, Mrectangle>& null_space,
1247 ssize_t max_null_space_vector)
const {
1248 Matrix* noconst_this =
const_cast<Matrix<T, Msym_compressed_col_update_inv_ext>*
>(
this);
1249 if (noconst_this->value_to_ccarray()) {
1250 delete noconst_this->solver;
1251 noconst_this->solver = 0;
1254 if (this->solver == 0) {
1255 noconst_this->solver = LDLt_sparse_solver<T>::new_default(
1256 Matrix<T, Msym_compressed_col_update_inv>::connectivity,
1257 *Matrix<T, Msym_compressed_col_update_inv>::dictionary);
1258 noconst_this->solver->init(
1259 Matrix<T, Msym_compressed_col_update_inv>::si.size() - 1,
1260 Matrix<T, Msym_compressed_col_update_inv>::index.size(),
1261 &Matrix<T, Msym_compressed_col_update_inv>::si[0],
1262 &Matrix<T, Msym_compressed_col_update_inv>::index[0],
1263 &Matrix<T, Msym_compressed_col_update_inv>::m[0],
1264 Matrix<T, Msym_compressed_col_update_inv>::connectivity,
1265 *Matrix<T, Msym_compressed_col_update_inv>::dictionary);
1269 std::copy(ma, ma + s - 1,
const_cast<T*
>(&m_ab[0]));
1270 std::copy(mb, mb + s - 1,
const_cast<T*
>(&m_ab[s - 1]));
1271 noconst_this->solver->resolve(
1272 s - 1, 2, &m_ab[0], s - 1,
const_cast<T*
>(&m_ab[0]), s - 1);
1273 const_cast<T&
>(div) = 1 / (*mc - blas::dot(s - 1, ma, 1, &m_ab[s - 1], 1));
1276 for (
size_t i = 0; i != nrhs; ++i) {
1277 const double x2 = x[ldx * i + s - 1] =
1279 * (b[ldb * i + s - 1] - blas::dot(s - 1, b + ldb * i, 1, &m_ab[s - 1], 1));
1280 noconst_this->solver->resolve(s - 1, 1, b + ldb * i, ldb, x + ldx * i, ldx);
1281 blas::axpy(s - 1, -x2, &m_ab[0], 1, x + ldx * i, 1);
1286 }
catch (SingularMatrixError& e) {
1287 if (max_null_space_vector != 0) {
1289 max_null_space_vector > 0
1290 && ssize_t(e.null_space_size) > max_null_space_vector
1291 ? max_null_space_vector
1292 : e.null_space_size;
1293 null_space.resize(s, nbnv);
1294 noconst_this->solver->get_null_space(s, nbnv, &null_space(0, 0), s);
1298 const size_t nss = noconst_this->solver->get_null_space_size();
1299 if (max_null_space_vector != 0 && nss > 0) {
1300 const size_t nbnv = max_null_space_vector > 0 && ssize_t(nss) > max_null_space_vector
1301 ? max_null_space_vector
1303 null_space.resize(s, nbnv);
1304 noconst_this->solver->get_null_space(s, nbnv, &null_space(0, 0), s);
1308 size_t get_null_space_size() {
1309 if (Matrix<T, Msym_compressed_col_update_inv>::si.size() <= 1) {
return 0; }
1310 if (this->solver == 0) {
return 0; }
1311 Matrix* noconst_this =
const_cast<Matrix<T, Msym_compressed_col_update_inv_ext>*
>(
this);
1312 return noconst_this->solver->get_null_space_size();
1315 void get_null_space(Matrix<T, Mrectangle_ref> nks) {
1316 if (Matrix<T, Msym_compressed_col_update_inv>::si.size() <= 1) {
return; }
1317 if (this->solver == 0) {
return; }
1318 Matrix* noconst_this =
const_cast<Matrix<T, Msym_compressed_col_update_inv_ext>*
>(
this);
1319 noconst_this->solver->get_null_space(nks.size1(), nks.size2(), nks.m, nks.size1());
1326 std::vector<double> m_ab;
1331template <
typename T>
1332Matrix<T, Msym_compressed_col_update_inv_ext> Matrix<T, Msym_compressed_col_update_inv_ext>::null;
1334struct Msym_compressed_col_update_sub_ref {
1335 typedef Mlower_packed copy;
1338template <
typename T>
1339class Matrix<T, Msym_compressed_col_update_sub_ref> {
1341 Matrix(Matrix<T, Msym_compressed_col_update_inv>& m_,
const Interval& i_,
const Interval& j_)
1342 : m(m_), i(i_), j(j_) {}
1344 std::pair<size_t, size_t> size()
const {
return std::pair<size_t, size_t>(i.size(), j.size()); }
1346 size_t size1()
const {
return i.size(); }
1348 size_t size2()
const {
return j.size(); }
1350 Matrix& operator+=(
const Matrix<T, Mcompressed_col_constref>& m_) {
1351 if (size() != m_.size()) {
1352 Exception() <<
"The two matrix do not have the same size, " << size() <<
" and "
1353 << m_.size() <<
"." <<
THROW;
1356 if (i.end <= j.start) {
1361 std::vector<std::pair<size_t, T>> res;
1362 size_t ii = m_.si[0];
1363 for (
size_t jj = 0; jj != m_.size2(); ++jj) {
1364 const size_t ii_end = m_.si[jj + 1];
1366 res.reserve(ii_end - ii);
1367 for (; ii != ii_end; ++ii) {
1368 if (i[0] + m_.index[ii] >= j[0] + jj) {
1369 res.push_back(std::pair<size_t, T>(i[0] + m_.index[ii], m_.m[ii]));
1372 m.add_colomn(j[0] + jj, res.begin(), res.end());
1378 const Matrix<T, MMProd<Mcompressed_col_st_constref, Mcompressed_col_st_constref>>& m_) {
1379 if (size() != m_.size()) {
1380 Exception() <<
"The two matrix do not have the same size, " << size() <<
" and "
1381 << m_.size() <<
"." <<
THROW;
1384 if (i.end < j.start) {
1389 if (!(m_.trans || m_.m1.trans || m_.m2.trans)) {
1391 const size_t end_list_flag = m_.m1.size1();
1394 const size_t* b_colind_begin = m_.m2.si;
1395 const size_t*
const b_colind_end = b_colind_begin + m_.m2.size2();
1396 size_t end_list = end_list_flag;
1398 while (b_colind_begin != b_colind_end) {
1399 const size_t* b_rowind_begin = &m_.m2.index[*b_colind_begin];
1400 const T* b_value_begin = &m_.m2.m[*b_colind_begin];
1401 const size_t*
const b_rowind_end = &m_.m2.index[*++b_colind_begin];
1402 while (b_rowind_begin != b_rowind_end) {
1403 const size_t* a_rowind_begin = m_.m1.index + m_.m1.si[*b_rowind_begin];
1404 const size_t*
const a_rowind_end = m_.m1.index + m_.m1.si[*b_rowind_begin + 1];
1405 const T* a_value_begin = m_.m1.m + m_.m1.si[*b_rowind_begin++];
1406 const T b_value_begin_v = *b_value_begin++;
1407 while (a_rowind_begin != a_rowind_end) {
1408 tmp_value[*a_rowind_begin] += *a_value_begin++ * b_value_begin_v;
1409 if (!(std::numeric_limits<size_t>::max() - tmp_index[*a_rowind_begin])) {
1410 tmp_index[*a_rowind_begin] = end_list;
1411 end_list = *a_rowind_begin;
1416 std::vector<std::pair<size_t, T>> res_tmp;
1417 while (end_list != end_list_flag) {
1418 res_tmp.push_back(std::pair<size_t, T>(i[end_list], tmp_value[end_list]));
1419 const size_t end_list_next = tmp_index[end_list];
1420 tmp_index[end_list] = std::numeric_limits<size_t>::max();
1421 tmp_value[end_list] = T(0);
1422 end_list = end_list_next;
1424 std::sort(res_tmp.begin(), res_tmp.end(), CompareFirstOfPair());
1425 m.add_colomn(col++, res_tmp.begin(), res_tmp.end());
1427 }
else if (!m_.trans && m_.m1.trans && m_.m2.trans) {
1428 std::vector<std::vector<std::pair<size_t, T>>> res_tmp(j.size());
1431 const size_t end_list_flag = m_.m2.size2();
1434 const size_t* b_colind_begin = m_.m1.si;
1435 const size_t*
const b_colind_end = b_colind_begin + m_.m1.size1();
1436 size_t end_list = end_list_flag;
1438 while (b_colind_begin != b_colind_end) {
1439 const size_t* b_rowind_begin = &m_.m1.index[*b_colind_begin];
1440 const T* b_value_begin = &m_.m1.m[*b_colind_begin];
1441 const size_t*
const b_rowind_end = &m_.m1.index[*++b_colind_begin];
1442 while (b_rowind_begin != b_rowind_end) {
1443 const size_t* a_rowind_begin = m_.m2.index + m_.m2.si[*b_rowind_begin];
1444 const size_t*
const a_rowind_end = m_.m2.index + m_.m2.si[*b_rowind_begin + 1];
1445 const T* a_value_begin = m_.m2.m + m_.m2.si[*b_rowind_begin++];
1446 const T b_value_begin_v = *b_value_begin++;
1447 while (a_rowind_begin != a_rowind_end) {
1448 tmp_value[*a_rowind_begin] += *a_value_begin++ * b_value_begin_v;
1449 if (!(std::numeric_limits<size_t>::max() - tmp_index[*a_rowind_begin])) {
1450 tmp_index[*a_rowind_begin] = end_list;
1451 end_list = *a_rowind_begin;
1456 while (end_list != end_list_flag) {
1457 res_tmp[end_list].push_back(std::pair<size_t, T>(i[col], tmp_value[end_list]));
1458 const size_t end_list_next = tmp_index[end_list];
1459 tmp_index[end_list] = std::numeric_limits<size_t>::max();
1460 tmp_value[end_list] = T(0);
1461 end_list = end_list_next;
1465 for (
size_t jj = 0; jj != res_tmp.size(); ++jj) {
1466 if (!res_tmp[jj].empty()) {
1467 std::sort(res_tmp[jj].begin(), res_tmp[jj].end(), CompareFirstOfPair());
1468 m.add_colomn(j[jj], res_tmp[jj].begin(), res_tmp[jj].end());
1471 }
else if (!m_.trans && !m_.m1.trans && m_.m2.trans && m_.m1.m == m_.m2.m) {
1472 Matrix<T, Mcompressed_col> m_m2;
1476 const size_t end_list_flag = m_.m1.size1();
1479 T scale = m_.scale * m_.m1.scale;
1480 const size_t* b_colind_begin = &m_m2.si[0];
1481 const size_t*
const b_colind_end = b_colind_begin + m_m2.size2();
1482 size_t end_list = end_list_flag;
1484 while (b_colind_begin != b_colind_end) {
1485 const size_t* b_rowind_begin = &m_m2.index[*b_colind_begin];
1486 const T* b_value_begin = &m_m2.m[*b_colind_begin];
1487 const size_t*
const b_rowind_end = &m_m2.index[*++b_colind_begin];
1488 while (b_rowind_begin != b_rowind_end) {
1489 const size_t* a_rowind_begin = m_.m1.index + m_.m1.si[*b_rowind_begin];
1490 const size_t*
const a_rowind_end =
1491 m_.m1.index + m_.m1.si[*b_rowind_begin++ + 1];
1492 while (a_rowind_begin != a_rowind_end && *a_rowind_begin < col) {
1495 const T* a_value_begin = m_.m1.m + (a_rowind_begin - m_.m1.index);
1496 const T b_value_begin_v = *b_value_begin++;
1497 while (a_rowind_begin != a_rowind_end) {
1498 tmp_value[*a_rowind_begin] += *a_value_begin++ * b_value_begin_v;
1499 if (!(std::numeric_limits<size_t>::max() - tmp_index[*a_rowind_begin])) {
1500 tmp_index[*a_rowind_begin] = end_list;
1501 end_list = *a_rowind_begin;
1506 std::vector<std::pair<size_t, T>> res_tmp;
1507 while (end_list != end_list_flag) {
1509 std::pair<size_t, T>(i[end_list], scale * tmp_value[end_list]));
1510 const size_t end_list_next = tmp_index[end_list];
1511 tmp_index[end_list] = std::numeric_limits<size_t>::max();
1512 tmp_value[end_list] = T(0);
1513 end_list = end_list_next;
1516 std::sort(res_tmp.begin(), res_tmp.end(), CompareFirstOfPair());
1517 m.add_colomn(j[col++], res_tmp.begin(), res_tmp.end());
1527 Matrix<T, Msym_compressed_col_update_inv>& m;
#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
GenericException< UnimplementedError_name > UnimplementedError
Definition b2exception.H:314