21#ifndef __B2MATRIX_RECTANGLE_H__ 
   22#define __B2MATRIX_RECTANGLE_H__ 
   27#include "b2linear_algebra_def.H" 
   29namespace b2000::b2linalg {
 
   32    using base = Mrectangle_increment_ref;
 
   33    using const_base = Mrectangle_increment_st_constref;
 
   34    using copy = Mrectangle;
 
   38class Matrix<T, Mrectangle> {
 
   42    explicit Matrix(
size_t s1_, 
size_t s2_) : s1(s1_), s2(s2_), m(s1_ * s2_) {}
 
   44    Matrix(
size_t s1_, 
size_t s2_, 
const T& t) : s1(s1_), s2(s2_), m(s1_ * s2_, t) {}
 
   46    Matrix(
const Matrix& m_) : s1(m_.s1), s2(m_.s2), m(m_.m) {}
 
   48    template <
typename T1>
 
   49    Matrix(
const Matrix<T1, Mrectangle>& m_)
 
   50        : s1(m_.s1.begin(), m_.s1.end()),
 
   51          s2(m_.s2.begin(), m_.s2.end()),
 
   52          m(m_.m.begin(), m_.m.end()) {}
 
   54    template <
typename T1>
 
   55    Matrix& operator=(
const Matrix<T1, Mrectangle>& m_) {
 
   58        m.assign(m_.m.begin(), m_.m.end());
 
   62    template <
typename STORAGE>
 
   63    Matrix(
const Matrix<T, STORAGE>& m_)
 
   64        : s1(m_.size1()), s2(m_.size2()), m(m_.size1() * m_.size2()) {
 
   65        Matrix<T, Mrectangle_increment_ref>(*
this) = m_;
 
   68    template <
typename T1, 
typename STORAGE>
 
   69    Matrix& operator=(
const Matrix<T1, STORAGE>& m_) {
 
   72        m.resize(m_.size1() * m_.size2());
 
   73        for (
size_t j = 0; j != size2(); ++j) {
 
   74            for (
size_t i = 0; i != size1(); ++i) { (*this)(i, j) = m_(i, j); }
 
   79    double norm_inf()
 const {
 
   81        for (
typename std::vector<T>::const_iterator i = m.begin(); i != m.end(); ++i) {
 
   82            res = std::max(res, 
norm(*i));
 
   87    void copy_real(
const Matrix<b2000::csda<T>, Mrectangle_constref>& m_) {
 
   90        m.resize(m_.size1() * m_.size2());
 
   91        for (
size_t i = 0; i != m.size(); ++i) { m[i] = std::real(m_.m[i]); }
 
   94    void copy_real(
const Matrix<std::complex<T>, Mrectangle_constref>& m_) {
 
   97        m.resize(m_.size1() * m_.size2());
 
   98        for (
size_t i = 0; i != m.size(); ++i) { m[i] = std::real(m_.m[i]); }
 
  101    void copy_imag(
const Matrix<b2000::csda<T>, Mrectangle_constref>& m_) {
 
  104        m.resize(m_.size1() * m_.size2());
 
  105        for (
size_t i = 0; i != m.size(); ++i) { m[i] = std::imag(m_.m[i]); }
 
  108    void copy_imag(
const Matrix<std::complex<T>, Mrectangle_constref>& m_) {
 
  111        m.resize(m_.size1() * m_.size2());
 
  112        for (
size_t i = 0; i != m.size(); ++i) { m[i] = std::imag(m_.m[i]); }
 
  115    bool is_null()
 const { 
return this == &null; }
 
  117    void set_zero() { std::fill(m.begin(), m.end(), 0); }
 
  119    void swap(Matrix& m_) {
 
  120        std::swap(s1, m_.s1);
 
  121        std::swap(s2, m_.s2);
 
  125    Matrix& operator=(
const Matrix& m_) {
 
  132    template <
typename STORAGE>
 
  133    Matrix& operator=(
const Matrix<T, STORAGE>& m_) {
 
  135        Matrix<T, Mrectangle_increment_ref>(*
this) = m_;
 
  139    template <
typename STORAGE>
 
  140    Matrix& operator+=(
const Matrix<T, STORAGE>& m_) {
 
  145    template <
typename STORAGE>
 
  146    Matrix& operator-=(
const Matrix<T, STORAGE>& m_) {
 
  151    Matrix& operator*=(
const T& scalar) {
 
  152        blas::scal(m.size(), scalar, &m[0], 1);
 
  156    std::pair<size_t, size_t> size()
 const { 
return std::pair<size_t, size_t>(s1, s2); }
 
  158    size_t size1()
 const { 
return s1; }
 
  160    size_t size2()
 const { 
return s2; }
 
  162    size_t esize()
 const { 
return s1 * s2; }
 
  164    void resize(std::pair<size_t, size_t> s) {
 
  170    void resize(
size_t s1_, 
size_t s2_) {
 
  176    const T& operator()(
size_t i, 
size_t j)
 const { 
return m[i + j * s1]; }
 
  178    T& operator()(
size_t i, 
size_t j) { 
return m[i + j * s1]; }
 
  180    Vector<T, Vdense_ref> operator[](
size_t i) { 
return Vector<T, Vdense_ref>(s1, &m[i * s1]); }
 
  182    Vector<T, Vdense_constref> operator[](
size_t i)
 const {
 
  183        return Vector<T, Vdense_constref>(s1, &m[i * s1]);
 
  186    Matrix<T, Mrectangle_ref> operator()(
const Interval& i) {
 
  187        return Matrix<T, Mrectangle_ref>(s1, i.size(), &m[i[0] * s1]);
 
  190    Matrix<T, Mrectangle_constref> operator()(
const Interval& i)
 const {
 
  191        return Matrix<T, Mrectangle_constref>(s1, i.size(), &m[i[0] * s1]);
 
  194    Matrix<T, Mrectangle_increment_ref> operator()(
const Interval& i1, 
const Interval& i2) {
 
  195        return Matrix<T, Mrectangle_increment_ref>(
 
  196              i1.size(), i2.size(), &m[i1[0] + i2[0] * s1], s1);
 
  199    Matrix<T, Mrectangle_increment_constref> operator()(
 
  200          const Interval& i1, 
const Interval& i2)
 const {
 
  201        return Matrix<T, Mrectangle_increment_constref>(
 
  202              i1.size(), i2.size(), &m[i1[0] + i2[0] * s1], s1);
 
  205    Vector<T, Vdense_ref> operator()(
const Interval& i1, 
size_t i2) {
 
  206        return Vector<T, Vdense_ref>(i1.size(), &m[i1[0] + i2 * s1]);
 
  209    Vector<T, Vdense_constref> operator()(
const Interval& i1, 
size_t i2)
 const {
 
  210        return Vector<T, Vdense_constref>(i1.size(), &m[i1[0] + i2 * s1]);
 
  222    Matrix& operator=(
const Matrix<T, Mpacked>& m_) {
 
  227        std::vector<T> cache(s2);
 
  230            auto it1e{std::end(m)};
 
  231            auto it2b{std::next(std::cend(m_.m), -s1)};
 
  232            auto it2e{std::cend(m_.m)};
 
  235            for (
size_t j = 0; j < s2; ++j) {
 
  237                it1e = m.insert(it1e, std::begin(cache), std::next(std::begin(cache), j));
 
  238                it1e = m.insert(it1e, it2b, it2e);
 
  241                it2b = it2b - (s1 - j - 1);
 
  245                    for (
size_t i = 0; i <= j; ++i) { cache[j - i] = m_(s1 - j - 2, s2 - i - 1); }
 
  249            auto it1e{std::end(m)};
 
  250            auto it2b{std::cbegin(m_.m)};
 
  251            auto it2e{std::next(std::cbegin(m_.m), s1)};
 
  254            for (
size_t j = 0; j < s2; ++j) {
 
  256                m.insert(it1e, std::begin(cache), std::next(std::begin(cache), j));
 
  258                m.insert(it1e, it2b, it2e);
 
  262                it2e = it2e + (s1 - j - 1);
 
  266                    for (
size_t i = 0; i <= j; ++i) { cache[i] = m_(j + 1, i); }
 
  274    Matrix& operator=(
const Matrix<
 
  276                               Minverse_constref<Msym_compressed_col_update_inv>,
 
  277                               Mrectangle_increment_st_constref> >& m_) {
 
  278        if (size() != m_.size()) { resize(m_.size()); }
 
  281              s1, s2, m_.m2.m, m_.m2.ldm, &m[0], s1, 
' ', m_.m1.null_space,
 
  282              m_.m1.max_null_space_vector);
 
  286    Matrix& operator=(
const Matrix<
 
  288                               Minverse_constref<Mcompressed_col_update_inv>,
 
  289                               Mrectangle_increment_st_constref> >& m_) {
 
  290        if (size() != m_.size()) { resize(m_.size()); }
 
  293              s1, s2, m_.m2.m, m_.m2.ldm, &m[0], s1, 
' ', m_.m1.null_space,
 
  294              m_.m1.max_null_space_vector);
 
  298    friend logging::Logger& operator<<(logging::Logger& l, 
const Matrix& m) {
 
  299        l << 
"rectangular matrix ";
 
  300        l.write(m.s1, m.s2, &m.m[0], m.s1);
 
  308            for (
size_t j = 0; j != s2; ++j) {
 
  309                for (
size_t i = 0; i != j; ++i) { std::swap((*
this)(i, j), (*
this)(j, i)); }
 
  311        } 
else if (s1 * s2 > 0) {
 
  313            mt.reserve(m.size());
 
  314            const size_t nm1 = s1 * s2 - 1;
 
  315            for (
size_t a = 0; a != s1 * s2; ++a) {
 
  316                const size_t pa = (a == nm1 ? nm1 : s1 * a % nm1);
 
  334Matrix<T, Mrectangle> Matrix<T, Mrectangle>::null;
 
  336struct Mrectangle_ref {
 
  337    using base = Mrectangle_ref;
 
  338    using const_base = Mrectangle_increment_st_constref;
 
  339    using copy = Mrectangle;
 
  343class Matrix<T, Mrectangle_ref> {
 
  347    Matrix(
size_t s1_, 
size_t s2_, T* m_) : s1(s1_), s2(s2_), m(m_) {}
 
  349    Matrix(
const Matrix& m_) : s1(m_.s1), s2(m_.s2), m(m_.m) {}
 
  351    Matrix(Matrix<T, Mrectangle>& m_) : s1(m_.s1), s2(m_.s2), m(&m_.m[0]) {}
 
  353    explicit Matrix(Vector<T, Vdense_ref> v) : s1(v.s), s2(1), m(v.v) {}
 
  355    Matrix(
size_t s1_, 
size_t s2_, Vector<T, Vdense_ref> v) : s1(s1_), s2(s2_), m(v.v) {
 
  356        if (v.s != s1_ * s2_) { Exception() << 
THROW; }
 
  359    bool is_null()
 const { 
return m == 0; }
 
  361    void set_zero() { std::fill_n(m, s1 * s2, 0); }
 
  363    template <
typename STORAGE>
 
  364    Matrix& operator+=(
const Matrix<T, STORAGE>& m_) {
 
  369    template <
typename STORAGE>
 
  370    Matrix& operator-=(
const Matrix<T, STORAGE>& m_) {
 
  375    Matrix& operator=(
const Matrix& m_) {
 
  376        if (size() != m_.size()) {
 
  377            Exception() << 
"The two matrices do not have the same size." << 
THROW;
 
  379        std::copy(m_.m, m_.m + s1 * s2, m);
 
  383    template <
typename STORAGE>
 
  384    Matrix& operator=(
const Matrix<T, STORAGE>& m_) {
 
  385        Matrix<T, Mrectangle_increment_ref>(*
this) = m_;
 
  389    std::pair<size_t, size_t> size()
 const { 
return std::pair<size_t, size_t>(s1, s2); }
 
  391    size_t size1()
 const { 
return s1; }
 
  393    size_t size2()
 const { 
return s2; }
 
  395    size_t esize()
 const { 
return s1 * s2; }
 
  397    const T& operator()(
size_t i, 
size_t j)
 const { 
return m[i + j * s1]; }
 
  399    T& operator()(
size_t i, 
size_t j) { 
return m[i + j * s1]; }
 
  401    Vector<T, Vdense_ref> operator[](
size_t i) { 
return Vector<T, Vdense_ref>(s1, m + i * s1); }
 
  403    Vector<T, Vdense_constref> operator[](
size_t i)
 const {
 
  404        return Vector<T, Vdense_constref>(s1, m + i * s1);
 
  407    Matrix<T, Mrectangle_ref> operator()(
const Interval& i) {
 
  408        return Matrix<T, Mrectangle_ref>(s1, i.size(), m + (i[0] * s1));
 
  411    Matrix<T, Mrectangle_constref> operator()(
const Interval& i)
 const {
 
  412        return Matrix<T, Mrectangle_constref>(s1, i.size(), m + (i[0] * s1));
 
  415    Matrix<T, Mrectangle_increment_ref> operator()(
const Interval& i1, 
const Interval& i2) {
 
  416        return Matrix<T, Mrectangle_increment_ref>(
 
  417              i1.size(), i2.size(), m + i1[0] + i2[0] * s1, s1);
 
  420    Matrix<T, Mrectangle_increment_constref> operator()(
 
  421          const Interval& i1, 
const Interval& i2)
 const {
 
  422        return Matrix<T, Mrectangle_increment_constref>(
 
  423              i1.size(), i2.size(), m + i1[0] + i2[0] * s1, s1);
 
  428    friend logging::Logger& operator<<(logging::Logger& l, 
const Matrix& m) {
 
  429        l << 
"rectangular matrix ";
 
  430        l.write(m.s1, m.s2, m.m, m.s1);
 
  442Matrix<T, Mrectangle_ref> Matrix<T, Mrectangle_ref>::null;
 
  444struct Mrectangle_constref {
 
  445    using base = Mrectangle_constref;
 
  446    using const_base = Mrectangle_increment_st_constref;
 
  447    using copy = Mrectangle;
 
  451class Matrix<T, Mrectangle_constref> {
 
  455    Matrix(
size_t s1_, 
size_t s2_, 
const T* m_) : s1(s1_), s2(s2_), m(m_) {}
 
  457    Matrix(
const Matrix& m_) : s1(m_.s1), s2(m_.s2), m(m_.m) {}
 
  459    Matrix(
const Matrix<T, Mrectangle>& m_) : s1(m_.s1), s2(m_.s2), m(&m_.m[0]) {}
 
  461    Matrix(
const Matrix<T, Mrectangle_ref>& m_) : s1(m_.s1), s2(m_.s2), m(m_.m) {}
 
  463    explicit Matrix(
const Vector<T, Vdense_constref>& v) : s1(v.s), s2(1), m(v.v) {}
 
  465    Matrix(
size_t s1_, 
size_t s2_, 
const Vector<T, Vdense_constref>& v) : s1(s1_), s2(s2_), m(v.v) {
 
  466        if (v.s != s1_ * s2_) { Exception() << 
THROW; }
 
  469    bool is_null()
 const { 
return m == 0; }
 
  471    std::pair<size_t, size_t> size()
 const { 
return std::pair<size_t, size_t>(s1, s2); }
 
  473    size_t size1()
 const { 
return s1; }
 
  475    size_t size2()
 const { 
return s2; }
 
  477    size_t esize()
 const { 
return s1 * s2; }
 
  479    const T& operator()(
size_t i, 
size_t j)
 const { 
return m[i + j * s1]; }
 
  481    Vector<T, Vdense_constref> operator[](
size_t i)
 const {
 
  482        return Vector<T, Vdense_constref>(s1, m + i * s1);
 
  485    Matrix<T, Mrectangle_constref> operator()(
const Interval& i)
 const {
 
  486        return Matrix<T, Mrectangle_constref>(s1, i.size(), m + (i[0] * s1));
 
  489    Matrix<T, Mrectangle_increment_constref> operator()(
 
  490          const Interval& i1, 
const Interval& i2)
 const {
 
  491        return Matrix<T, Mrectangle_increment_constref>(
 
  492              i1.size(), i2.size(), m + i1[0] + i2[0] * s1, s1);
 
  497    friend logging::Logger& operator<<(logging::Logger& l, 
const Matrix& m) {
 
  498        l << 
"rectangular matrix ";
 
  499        l.write(m.s1, m.s2, m.m, m.s1);
 
  511Matrix<T, Mrectangle_constref> Matrix<T, Mrectangle_constref>::null;
 
  513struct Mrectangle_increment_ref {
 
  514    using base = Mrectangle_increment_ref;
 
  515    using const_base = Mrectangle_increment_st_constref;
 
  516    using copy = Mrectangle;
 
  520class Matrix<T, Mrectangle_increment_ref> {
 
  524    Matrix(
size_t s1_, 
size_t s2_, T* m_, 
size_t ldm_) : s1(s1_), s2(s2_), m(m_), ldm(ldm_) {}
 
  526    Matrix(
const Matrix& m_) : s1(m_.s1), s2(m_.s2), m(m_.m), ldm(m_.ldm) {}
 
  528    Matrix(Matrix<T, Mrectangle>& m_) : s1(m_.s1), s2(m_.s2), m(&m_.m[0]), ldm(m_.s1) {}
 
  530    Matrix(Matrix<T, Mrectangle_ref> m_) : s1(m_.s1), s2(m_.s2), m(m_.m), ldm(m_.s1) {}
 
  532    Matrix(
size_t s1_, 
size_t s2_, Vector<T, Vincrement_ref> v)
 
  533        : s1(s1_), s2(s2_), m(v.v), ldm(s1_) {
 
  534        if (v.s != s1_ * s2_) { Exception() << 
THROW; }
 
  537    bool is_null()
 const { 
return m == 0; }
 
  541        for (
size_t j = 0; j != s2; ++j, ptr += ldm) { std::fill_n(ptr, s1, 0.0); }
 
  544    std::pair<size_t, size_t> size()
 const { 
return std::pair<size_t, size_t>(s1, s2); }
 
  546    size_t size1()
 const { 
return s1; }
 
  548    size_t size2()
 const { 
return s2; }
 
  550    size_t esize()
 const { 
return s1 * s2; }
 
  552    const T& operator()(
size_t i, 
size_t j)
 const { 
return m[i + j * ldm]; }
 
  554    T& operator()(
size_t i, 
size_t j) { 
return m[i + j * ldm]; }
 
  556    Vector<T, Vdense_ref> operator[](
size_t i) { 
return Vector<T, Vdense_ref>(s1, m + i * ldm); }
 
  558    Vector<T, Vdense_constref> operator[](
size_t i)
 const {
 
  559        return Vector<T, Vdense_constref>(s1, m + i * ldm);
 
  562    Matrix operator()(
const Interval& i1, 
const Interval& i2) {
 
  563        return Matrix(i1.size(), i2.size(), m + i1[0] + i2[0] * ldm, s1);
 
  566    Matrix<T, Mrectangle_increment_constref> operator()(
 
  567          const Interval& i1, 
const Interval& i2)
 const {
 
  568        return Matrix<T, Mrectangle_increment_constref>(
 
  569              i1.size(), i2.size(), m + i1[0] + i2[0] * ldm, s1);
 
  572    Matrix& operator*=(T s) {
 
  574        for (
size_t j = 0; j != s2; ++j) {
 
  575            T* ptr_end = ptr + s1;
 
  576            for (; ptr != ptr_end; ++ptr) { *ptr *= s; }
 
  582    template <
typename STORAGE>
 
  583    Matrix& operator+=(
const Matrix<T, STORAGE>& m_) {
 
  588    template <
typename STORAGE>
 
  589    Matrix& operator-=(
const Matrix<T, STORAGE>& m_) {
 
  594    Matrix& operator=(
const Matrix& m_) {
 
  595        if (size() != m_.size()) {
 
  596            Exception() << 
"The two matrices do not have the same size." << 
THROW;
 
  598        if (m == m_.m && ldm == m_.ldm) { 
return *
this; }
 
  599        if (ldm == s1 && m_.ldm == m_.s1) {
 
  602            const T* m2_end = m2 + s1 * s2;
 
  603            while (m2 != m2_end) { *(m1++) = *(m2++); }
 
  605            for (
size_t i = 0; i != s2; ++i) { (*this)[i] = m_[i]; }
 
  610    Matrix& operator=(
const Matrix<T, Mrectangle_constref>& m_) {
 
  611        if (size1() != m_.size1() || size2() != m_.size2()) {
 
  612            Exception() << 
"The two matrices do not have the same size." << 
THROW;
 
  614        const T* ptrin = m_.m;
 
  616        for (
size_t j = 0; j != s2; ++j, ptrout += ldm - s1) {
 
  617            for (
size_t i = 0; i != s1; ++i, ++ptrout, ++ptrin) { *ptrout = *ptrin; }
 
  622    Matrix& operator=(
const Matrix<T, Mpacked_st_constref>& m_) {
 
  623        if (size1() != m_.size1() || size2() != m_.size2()) {
 
  624            Exception() << 
"The two matrices do not have the same size." << 
THROW;
 
  626        for (
size_t j = 0; j != size2(); ++j) {
 
  627            for (
size_t i = 0; i != size1(); ++i) { (*this)(i, j) = m_(i, j); }
 
  632    Matrix& operator=(
const Matrix<T, Mrectangle_increment_st_constref>& m_) {
 
  633        if (size() != m_.size()) {
 
  634            Exception() << 
"The two matrices do not have the same size." << 
THROW;
 
  636        if (m == m_.m && ldm == m_.ldm && m_.trans == 
false && m_.scale == T(1)) { 
return *
this; }
 
  637        if (m_.trans == 
false && ldm == s1 && m_.ldm == m_.s1) {
 
  640            const T* m2_end = m2 + s1 * s2;
 
  641            while (m2 != m2_end) { *(m1++) = m_.scale * *(m2++); }
 
  643            for (
size_t i = 0; i != s2; ++i) { (*this)[i] = m_[i]; }
 
  649          const Matrix<T, Sum<Mrectangle_increment_st_constref, Mrectangle_increment_st_constref> >&
 
  651        if (size() != m_.size()) {
 
  652            Exception() << 
"The two matrices do not have the same size." << 
THROW;
 
  654        if (!m_.m1.trans && !m_.m2.trans && ldm == s1 && m_.m1.ldm == s1 && m_.m2.ldm == s1
 
  655            && m_.m1.scale == T(1) && m_.m2.scale == T(1)) {
 
  656            const size_t i_end = s1 * s2;
 
  657            for (
size_t i = 0; i != i_end; ++i) { m[i] = m_.m1.m[i] + m_.m2.m[i]; }
 
  659            for (
size_t i = 0; i != s2; ++i) { (*this)[i] = m_.scale * (m_.m1[i] + m_.m2[i]); }
 
  666                T, MMProd<Mrectangle_increment_st_constref, Mrectangle_increment_st_constref> >&
 
  668        if (size() != m_.size()) {
 
  669            Exception() << 
"The two matrices do not have the same size." << 
THROW;
 
  673                  m_.m2.trans ? 
'n' : 
't', m_.m1.trans ? 
'n' : 
't', s1, s2, m_.m2.size1(),
 
  674                  m_.scale * m_.m1.scale * m_.m2.scale, m_.m2.m, m_.m2.ldm, m_.m1.m, m_.m1.ldm, 0,
 
  678                  m_.m1.trans ? 
't' : 
'n', m_.m2.trans ? 
't' : 
'n', s1, s2, m_.m1.size2(),
 
  679                  m_.scale * m_.m1.scale * m_.m2.scale, m_.m1.m, m_.m1.ldm, m_.m2.m, m_.m2.ldm, 0,
 
  688                Sum<Mrectangle_increment_st_constref,
 
  689                    MMProd<Mrectangle_increment_st_constref, Mrectangle_increment_st_constref> > >&
 
  691        if (size() != m_.size()) {
 
  692            Exception() << 
"The two matrices do not have the same size." << 
THROW;
 
  695            (*this) = transposed(m_.scale * m_.m1);
 
  697            (*this) = m_.scale * m_.m1;
 
  699        if (m_.m2.trans ^ m_.trans) {
 
  701                  m_.m2.m2.trans ? 
'n' : 
't', m_.m2.m1.trans ? 
'n' : 
't', s1, s2, m_.m2.m2.size1(),
 
  702                  m_.scale * m_.m2.scale * m_.m2.m1.scale * m_.m2.m2.scale, m_.m2.m2.m,
 
  703                  m_.m2.m2.ldm, m_.m2.m1.m, m_.m2.m1.ldm, m_.scale * m_.m1.scale, m, ldm);
 
  706                  m_.m2.m1.trans ? 
't' : 
'n', m_.m2.m2.trans ? 
't' : 
'n', s1, s2, m_.m2.m1.size2(),
 
  707                  m_.scale * m_.m2.scale * m_.m2.m1.scale * m_.m2.m2.scale, m_.m2.m1.m,
 
  708                  m_.m2.m1.ldm, m_.m2.m2.m, m_.m2.m2.ldm, m_.scale * m_.m1.scale, m, ldm);
 
  714          const Matrix<T, MMProd<Mcompressed_col_st_constref, Mrectangle_increment_st_constref> >&
 
  716        if (size() != m_.size()) {
 
  717            Exception() << 
"The two matrices do not have the same size." << 
THROW;
 
  719        for (
size_t j = 0; j != s2; ++j) { (*this)[j] = m_.m1 * m_.m2[j]; }
 
  725                T, Sum<Mrectangle_increment_st_constref,
 
  726                       MMProd<Mcompressed_col_st_constref, Mrectangle_increment_st_constref> > >&
 
  728        if (size() != m_.size()) {
 
  729            Exception() << 
"The two matrices do not have the same size." << 
THROW;
 
  732        for (
size_t i = 0; i != s2; ++i) {
 
  733            (*this)[i] = m_.scale * m_.m1[i] + (m_.scale * m_.m2.scale) * (m_.m2.m1 * m_.m2.m2[i]);
 
  738    template <
typename ATYPE, 
typename BTYPE>
 
  739    Matrix& operator=(
const Matrix<T, Eigenvector<ATYPE, BTYPE> >& eigenvector) {
 
  740        if (size() != eigenvector.size()) {
 
  741            Exception() << 
"The two matrices do not have the same size." << 
THROW;
 
  743        const_cast<Matrix<T, Eigenvector<ATYPE, BTYPE> 
>&>(eigenvector).resolve(*
this);
 
  747    template <
typename ATYPE, 
typename BTYPE>
 
  748    Matrix& operator=(
const Matrix<T, PolyEigenvector<ATYPE, BTYPE> >& eigenvector) {
 
  749        if (size() != eigenvector.size()) {
 
  750            Exception() << 
"The two matrices do not have the same size." << 
THROW;
 
  752        const_cast<Matrix<T, PolyEigenvector<ATYPE, BTYPE> 
>&>(eigenvector).resolve(*
this);
 
  758                T, MMProd<Msym_compressed_col_st_constref, Mrectangle_increment_st_constref> >&
 
  760        if (size() != m_.size()) {
 
  761            Exception() << 
"The two matrices do not have the same size." << 
THROW;
 
  764        for (
size_t i = 0; i != s2; ++i) { (*this)[i] = m_.scale * (m_.m1 * m_.m2[i]); }
 
  771                Sum<Mrectangle_increment_st_constref,
 
  772                    MMProd<Msym_compressed_col_st_constref, Mrectangle_increment_st_constref> > >&
 
  774        if (size() != m_.size()) {
 
  775            Exception() << 
"The two matrices do not have the same size." << 
THROW;
 
  778        for (
size_t i = 0; i != s2; ++i) {
 
  779            (*this)[i] = m_.scale * m_.m1[i] + (m_.scale * m_.m2.scale) * (m_.m2.m1 * m_.m2.m2[i]);
 
  784    template <
typename M_FORMAT>
 
  787                T, MMProd<Mstructured_constref<M_FORMAT>, Mrectangle_increment_st_constref> >& m_) {
 
  788        if (size() != m_.size()) {
 
  789            Exception() << 
"The two matrices do not have the same size." << 
THROW;
 
  792        if (m_.scale == T(1) && m_.trans == 
false && m_.m2.trans == 
false) {
 
  793            for (
size_t k = 0; k != s2; ++k) {
 
  794                Vector<T, Vindex_scale_constref> tmp1(
 
  795                      m_.m1.m.size1(), m_.m2.m + k * m_.m2.ldm, m_.m1.index, m_.m2.scale);
 
  796                Vector<T, Vindex_ref> tmp2(m_.m1.m.size1(), &(*
this)(0, k), m_.m1.index);
 
  797                tmp2 += m_.m1.m * tmp1;
 
  805    template <
typename M_FORMAT>
 
  808                T, Sum<Mrectangle_increment_st_constref,
 
  809                       MMProd<Mstructured_constref<M_FORMAT>, Mrectangle_increment_st_constref> > >&
 
  811        if (size() != m_.size()) {
 
  812            Exception() << 
"The two matrices do not have the same size." << 
THROW;
 
  815        if (m_.m1.m == m && m_.m1.ldm == ldm && m_.m1.scale == T(1) && m_.m1.trans == 
false 
  816            && m_.scale == T(1) && m_.trans == 
false && m_.m2.m2.trans == 
false) {
 
  817            for (
size_t k = 0; k != s2; ++k) {
 
  818                Vector<T, Vindex_scale_constref> tmp1(
 
  819                      m_.m2.m1.m.size1(), m_.m2.m2.m + k * m_.m2.m2.ldm, m_.m2.m1.index,
 
  821                Vector<T, Vindex_ref> tmp2(m_.m2.m1.m.size1(), &(*
this)(0, k), m_.m2.m1.index);
 
  822                tmp2 = Vector<T, Vindex_scale_constref>(tmp2) + m_.m2.m1.m * tmp1;
 
  830    template <
typename M_FORMAT>
 
  832          const Matrix<T, Sum<Mrectangle_increment_st_constref, Mstructured_constref<M_FORMAT> > >&
 
  834        if (size() != m_.size()) {
 
  835            Exception() << 
"The two matrices do not have the same size." << 
THROW;
 
  839            (*this) = m_.scale * m_.m1;
 
  840        } 
else if (m_.m1.ldm != ldm) {
 
  842        } 
else if (m_.scale != T(1)) {
 
  845        for (
size_t j = 0; j != m_.m2.m.size2(); ++j) {
 
  846            const size_t jj = (m_.m2.index2 ? m_.m2.index2 : m_.m2.index)[j];
 
  847            for (
size_t i = 0; i != m_.m2.m.size1(); ++i) {
 
  848                (*this)(m_.m2.index[i], jj) += m_.m2.m(i, j) * m_.scale;
 
  855          const Matrix<T, MMProd<Mrectangle_inv, Mrectangle_increment_st_constref> >& m_) {
 
  858        m_.m1.resolve(*
this);
 
  863          const Matrix<T, MMProd<Mpacked_st_constref, Mrectangle_increment_st_constref> >& m_) {
 
  864        if (size() != m_.size()) {
 
  865            Exception() << 
"The two matrices do not have the same size." << 
THROW;
 
  867        const T alpha = m_.m1.scale * m_.m2.scale * m_.scale;
 
  868        const char m1_up = m_.m1.upper ? 
'U' : 
'L';
 
  870            for (
size_t i = 0; i != s1; ++i) {
 
  872                      m1_up, m_.m1.s, alpha, m_.m1.m, &m_.m2.m[i], m_.m2.ldm, 0, &m[i * ldm], 1);
 
  875            for (
size_t j = 0; j != s2; ++j) {
 
  877                      m1_up, m_.m1.s, alpha, m_.m1.m, &m_.m2.m[j * m_.m2.ldm], 1, 0, &m[j * ldm],
 
  885          const Matrix<T, MMProd<Mcompressed_col_st_constref, Mcompressed_col_st_constref> >& m_) {
 
  886        if (size() != m_.size()) {
 
  887            Exception() << 
"The two matrices do not have the same size." << 
THROW;
 
  890        const T scale = m_.scale * m_.m1.scale * m_.m2.scale;
 
  892        for (
size_t j = 0; j != s2; ++j, ptr += ldm) {
 
  893            std::fill_n(ptr, s1, T(0));
 
  894            size_t k = m_.m2.si[j];
 
  895            const size_t k_end = m_.m2.si[j + 1];
 
  896            for (; k != k_end; ++k) {
 
  897                const size_t kk = m_.m2.index[k];
 
  898                const T kv = scale * m_.m2.m[k];
 
  899                size_t i = m_.m1.si[kk];
 
  900                const size_t i_end = m_.m1.si[kk + 1];
 
  901                for (; i != i_end; ++i) { ptr[m_.m1.index[i]] += kv * m_.m1.m[i]; }
 
  907    void in_place_invert() {
 
  908        if (s1 != s2) { Exception() << 
THROW; }
 
  911        lapack::getrf(s1, s1, m, ldm, ipiv, info);
 
  912        if (info != 0) { Exception() << 
THROW; }
 
  914        if (info != 0) { Exception() << 
THROW; }
 
  917    size_t diagonalise_base_vector_on_observation_matrix(
 
  918          const Index& observation_matrix, 
const double tol = 1e-13) {
 
  919        if (observation_matrix.size() > s2) { Exception() << 
THROW; }
 
  920        Matrix<T, Mrectangle> u(observation_matrix.size(), s2);
 
  924            for (
size_t j = 0; j != s2; ++j, orig += ldm) {
 
  925                for (
size_t i = 0; i != observation_matrix.size(); ++i, ++dest) {
 
  926                    *dest = orig[observation_matrix[i]];
 
  930        Vector<T, Vdense> sv(u.size1());
 
  931        Matrix<T, Mrectangle> vt(s2, s2);
 
  937                  'O', 
'A', u.size1(), s2, &u(0, 0), u.size1(), &sv[0], NULL, 1, &vt(0, 0), s2,
 
  938                  &lwork_tmp, -1, info);
 
  939            lwork = int(lwork_tmp);
 
  941        if (info != 0) { Exception() << 
THROW; }
 
  943            std::vector<T> work(lwork);
 
  945                  'O', 
'A', u.size1(), s2, &u(0, 0), u.size1(), &sv[0], NULL, 1, &vt(0, 0), s2,
 
  946                  &work[0], lwork, info);
 
  947            if (info < 0) { Exception() << 
THROW; }
 
  949                Exception() << 
"could not compute the svd decomposition of the matrix." << 
THROW;
 
  951            u.resize(u.size1(), u.size1());
 
  954        Matrix<T, Mrectangle> tmp;
 
  955        tmp = (*this) * transposed(vt);
 
  957        for (rank = 0; rank != sv.size(); ++rank) {
 
  958            if (std::abs(sv[rank]) < tol) { 
break; }
 
  959            tmp[rank] *= 1.0 / sv[rank];
 
  961        Interval inter(0, u.size1());
 
  962        (*this)(Interval(0, s1), inter) = tmp(Interval(0, s1), inter) * transposed(u(inter, inter));
 
  963        (*this)(Interval(0, s1), Interval(u.size1(), s2)) =
 
  964              tmp(Interval(0, s1), Interval(u.size1(), s2));
 
  966        return s2 + rank - observation_matrix.size();
 
  971    friend logging::Logger& operator<<(logging::Logger& l, 
const Matrix& m) {
 
  972        l << 
"rectangular matrix ";
 
  973        l.write(m.s1, m.s2, m.m, m.ldm);
 
  986Matrix<T, Mrectangle_increment_ref> Matrix<T, Mrectangle_increment_ref>::null;
 
  988struct Mrectangle_increment_constref {
 
  989    using base = Mrectangle_increment_constref;
 
  990    using const_base = Mrectangle_increment_st_constref;
 
  991    using copy = Mrectangle;
 
  995class Matrix<T, Mrectangle_increment_constref> {
 
  999    Matrix(
size_t s1_, 
size_t s2_, 
const T* m_, 
size_t ldm_)
 
 1000        : s1(s1_), s2(s2_), m(m_), ldm(std::max(size_t(1), ldm_)) {}
 
 1002    Matrix(
const Matrix& m_) : s1(m_.s1), s2(m_.s2), m(m_.m), ldm(m_.ldm) {}
 
 1004    Matrix(
const Matrix<T, Mrectangle>& m_)
 
 1005        : s1(m_.s1), s2(m_.s2), m(&m_.m[0]), ldm(std::max(size_t(1), m_.s1)) {}
 
 1007    Matrix(
const Matrix<T, Mrectangle_ref>& m_)
 
 1008        : s1(m_.s1), s2(m_.s2), m(m_.m), ldm(std::max(size_t(1), m_.s1)) {}
 
 1010    Matrix(
const Matrix<T, Mrectangle_constref>& m_)
 
 1011        : s1(m_.s1), s2(m_.s2), m(m_.m), ldm(std::max(size_t(1), m_.s1)) {}
 
 1013    Matrix(
const Matrix<T, Mrectangle_increment_ref>& m_)
 
 1014        : s1(m_.s1), s2(m_.s2), m(m_.m), ldm(m_.ldm) {}
 
 1016    Matrix(
size_t s1_, 
size_t s2_, 
const Vector<T, Vincrement_constref>& v)
 
 1017        : s1(s1_), s2(s2_), m(v.v), ldm(std::max(size_t(1), s1_)) {
 
 1018        if (v.s != s1 * s2) { Exception() << 
THROW; }
 
 1021    bool is_null()
 const { 
return m == 0; }
 
 1023    std::pair<size_t, size_t> size()
 const { 
return std::pair<size_t, size_t>(s1, s2); }
 
 1025    size_t size1()
 const { 
return s1; }
 
 1027    size_t size2()
 const { 
return s2; }
 
 1029    size_t esize()
 const { 
return s1 * s2; }
 
 1031    const T& operator()(
size_t i, 
size_t j)
 const { 
return m[i + j * ldm]; }
 
 1033    Vector<T, Vdense_constref> operator[](
size_t i)
 const {
 
 1034        return Vector<T, Vdense_constref>(s1, m + i * ldm);
 
 1037    Matrix<T, Mrectangle_increment_constref> operator()(
 
 1038          const Interval& i1, 
const Interval& i2)
 const {
 
 1039        return Matrix<T, Mrectangle_increment_constref>(
 
 1040              i1.size(), i2.size(), m + i1[0] + i2[0] * ldm, ldm);
 
 1045    friend logging::Logger& operator<<(logging::Logger& l, 
const Matrix& m) {
 
 1046        l << 
"rectangular matrix ";
 
 1047        l.write(m.s1, m.s2, m.m, m.ldm);
 
 1059template <
typename T>
 
 1060Matrix<T, Mrectangle_increment_constref> Matrix<T, Mrectangle_increment_constref>::null;
 
 1062struct Mrectangle_increment_st_constref {
 
 1063    using base = Mrectangle_increment_st_constref;
 
 1064    using const_base = Mrectangle_increment_st_constref;
 
 1065    using copy = Mrectangle;
 
 1068template <
typename T>
 
 1069class Matrix<T, Mrectangle_increment_st_constref> {
 
 1073    Matrix(
size_t s1_, 
size_t s2_, 
const T* m_, 
size_t ldm_, T scale_, 
bool transpose_ = 
false)
 
 1077          ldm(std::max(size_t(1), ldm_)),
 
 1079          trans(transpose_) {}
 
 1081    Matrix(
const Matrix& m_)
 
 1082        : s1(m_.s1), s2(m_.s2), m(m_.m), ldm(m_.ldm), scale(m_.scale), trans(m_.trans) {}
 
 1084    Matrix(
const Matrix<T, Mrectangle>& m_)
 
 1088          ldm(std::max(size_t(1), m_.s1)),
 
 1092    Matrix(
const Matrix<T, Mrectangle_ref>& m_)
 
 1093        : s1(m_.s1), s2(m_.s2), m(m_.m), ldm(std::max(size_t(1), m_.s1)), scale(1), trans(false) {}
 
 1095    Matrix(
const Matrix<T, Mrectangle_constref>& m_)
 
 1096        : s1(m_.s1), s2(m_.s2), m(m_.m), ldm(std::max(size_t(1), m_.s1)), scale(1), trans(false) {}
 
 1098    Matrix(
const Matrix<T, Mrectangle_increment_ref>& m_)
 
 1099        : s1(m_.s1), s2(m_.s2), m(m_.m), ldm(m_.ldm), scale(1), trans(false) {}
 
 1101    Matrix(
const Matrix<T, Mrectangle_increment_constref>& m_)
 
 1102        : s1(m_.s1), s2(m_.s2), m(m_.m), ldm(m_.ldm), scale(1), trans(false) {}
 
 1104    Matrix(
size_t s1_, 
size_t s2_, 
const Vector<T, Vincrement_scale_constref>& v)
 
 1105        : s1(s1_), s2(s2_), m(v.v), ldm(std::max(size_t(1), s1_)), scale(v.scale), trans(false) {
 
 1106        if (v.s != s1 * s2) { Exception() << 
THROW; }
 
 1109    bool is_null()
 const { 
return m == 0; }
 
 1111    std::pair<size_t, size_t> size()
 const {
 
 1113            return std::pair<size_t, size_t>(s2, s1);
 
 1115            return std::pair<size_t, size_t>(s1, s2);
 
 1119    size_t size1()
 const {
 
 1127    size_t size2()
 const {
 
 1135    size_t esize()
 const { 
return s1 * s2; }
 
 1137    T operator()(
size_t i, 
size_t j)
 const {
 
 1139            return scale * m[j + i * ldm];
 
 1141            return scale * m[i + j * ldm];
 
 1145    Vector<T, Vincrement_scale_constref> operator[](
size_t i)
 const {
 
 1147            return Vector<T, Vincrement_scale_constref>(s2, m + i, ldm, scale);
 
 1149            return Vector<T, Vincrement_scale_constref>(s1, m + i * ldm, 1, scale);
 
 1153    Matrix<T, Mrectangle_increment_st_constref> operator()(
 
 1154          const Interval& i1, 
const Interval& i2)
 const {
 
 1156            return Matrix<T, Mrectangle_increment_st_constref>(
 
 1157                  i2.size(), i1.size(), m + i2[0] + i1[0] * ldm, ldm, scale, trans);
 
 1159            return Matrix<T, Mrectangle_increment_st_constref>(
 
 1160                  i1.size(), i2.size(), m + i1[0] + i2[0] * ldm, ldm, scale, trans);
 
 1164    Matrix& operator*(T s) {
 
 1169    Matrix& transpose() {
 
 1170        trans = trans ? false : 
true;
 
 1186template <
typename T>
 
 1187Matrix<T, Mrectangle_increment_st_constref> Matrix<T, Mrectangle_increment_st_constref>::null;
 
 1189struct Mrectangle_inv {
 
 1190    using base = Mrectangle_inv;
 
 1191    using const_base = Mrectangle_inv;
 
 1192    using copy = Mrectangle_inv;
 
 1195template <
typename T>
 
 1196class Matrix<T, Mrectangle_inv> {
 
 1198    Matrix(
const Matrix<T, Mrectangle>& m_) : s(m_.s1), m(m_.m), ipiv(m_.s1) {
 
 1201        lapack::getrf(s, s, &m[0], s, &ipiv[0], info);
 
 1202        if (info < 0) { Exception() << 
THROW; }
 
 1203        if (info > 0) { Exception() << 
"The matrix is singular." << 
THROW; }
 
 1206    size_t size1()
 const { 
return s; }
 
 1208    size_t size2()
 const { 
return s; }
 
 1210    std::pair<size_t, size_t> size()
 const { 
return std::pair<size_t, size_t>(s, s); }
 
 1212    void resolve(Vector<T, Vincrement_ref> v_)
 const {
 
 1215        lapack::getrs(
'N', s, 1, &m[0], s, &ipiv[0], v_.v, s, info);
 
 1216        if (info < 0) { Exception() << 
THROW; }
 
 1219    void resolve(Matrix<T, Mrectangle_increment_ref> m_)
 const {
 
 1221        lapack::getrs(
'N', s, m_.size2(), &m[0], s, &ipiv[0], m_.m, m_.ldm, info);
 
 1222        if (info < 0) { Exception() << 
THROW; }
 
 1228    std::vector<int> ipiv;
 
csda< T > norm(const csda< T > &a)
Definition b2csda.H:343
 
#define THROW
Definition b2exception.H:198
 
static T * get(size_t size)
Definition b2linear_algebra_utils.H:50
 
GenericException< UnimplementedError_name > UnimplementedError
Definition b2exception.H:314