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