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