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