21#ifndef __B2MATRIX_OPERATION_H__
22#define __B2MATRIX_OPERATION_H__
27#include "b2linear_algebra_def.H"
28#include "b2linear_algebra_utils.H"
30namespace b2000::b2linalg {
32template <
typename T,
typename STORAGE1,
typename STORAGE2>
33class Matrix<T, Sum<STORAGE1, STORAGE2> > {
35 Matrix(
const Matrix<T, STORAGE1>& m1_,
const Matrix<T, STORAGE2>& m2_, T scale_ = T(1))
36 : m1(m1_), m2(m2_), scale(scale_), trans(false) {
37 if (m1.size() != m2.size()) {
38 Exception() <<
"The two matrices do not have the same size." <<
THROW;
42 std::pair<size_t, size_t> size()
const {
44 return std::pair<size_t, size_t>(m1.size2(), m1.size1());
50 size_t size1()
const {
58 size_t size2()
const {
66 T operator()(
size_t i,
size_t j)
const {
68 return scale * (m1(j, i) + m2(j, i));
70 return scale * (m1(i, j) + m2(i, j));
74 Matrix& operator*(T t) {
80 trans = trans ? false :
true;
85 Matrix<T, STORAGE1> m1;
86 Matrix<T, STORAGE2> m2;
92template <
typename T1,
typename T2>
94 using const_base = MMProd;
97template <
typename T,
typename STORAGE1,
typename STORAGE2>
98class Matrix<T, MMProd<STORAGE1, STORAGE2> > {
100 Matrix(
const Matrix<T, STORAGE1>& m1_,
const Matrix<T, STORAGE2>& m2_, T scale_ = T(1))
101 : m1(m1_), m2(m2_), scale(scale_), trans(false) {
102 if (m1.size2() != m2.size1()) {
103 Exception() <<
"Matrix-matrix inner product: The number of columns of the "
105 << m1.size1() <<
" x " << m1.size2()
106 <<
") differs from the number of rows of the second matrix (" << m2.size1()
107 <<
" x " << m2.size2() <<
")." <<
THROW;
111 std::pair<size_t, size_t> size()
const {
112 return std::pair<size_t, size_t>(m1.size1(), m2.size2());
115 size_t size1()
const {
return m1.size1(); }
117 size_t size2()
const {
return m2.size2(); }
119 T operator()(
size_t i,
size_t j)
const {
121 return scale * transpose(m1)[i] * m2[j];
123 return scale * transpose(m1)[j] * m2[i];
127 Matrix& operator*(T t) {
132 Matrix& transpose() {
133 trans = trans ? false :
true;
138 Matrix<T, STORAGE1> m1;
139 Matrix<T, STORAGE2> m2;
145template <
typename T1,
typename S1,
typename T2,
typename S2>
146inline void copy_m(
const Matrix<T1, S1>& a, Matrix<T2, S2>& b) {
147 b.resize(a.size1(), a.size2());
148 for (
size_t i = 0; i != a.size1(); ++i) {
149 for (
size_t j = 0; j != a.size2(); ++j) { b(i, j) = a(i, j); }
153template <
typename T1,
typename S1,
typename T2,
typename S2>
154inline void copy_vm(
const std::vector<Matrix<T1, S1> >& a, std::vector<Matrix<T2, S2> >& b) {
156 for (
size_t i = 0; i != a.size(); ++i) { copy_m(a[i], b[i]); }
159template <
typename T,
typename STORAGE>
160Matrix<T, typename STORAGE::const_base> transposed(
const Matrix<T, STORAGE>& m) {
161 return Matrix<T, typename STORAGE::const_base>(m).transpose();
164template <
typename T,
typename STORAGE1,
typename STORAGE2>
165Matrix<T, Sum<typename STORAGE1::const_base, typename STORAGE2::const_base> > operator+(
166 const Matrix<T, STORAGE1>& m1,
const Matrix<T, STORAGE2>& m2) {
167 return Matrix<T, Sum<typename STORAGE1::const_base, typename STORAGE2::const_base> >(m1, m2);
170template <
typename T,
typename STORAGE1,
typename STORAGE2>
171Matrix<T, Sum<typename STORAGE1::const_base, typename STORAGE2::const_base> > operator-(
172 const Matrix<T, STORAGE1>& m1,
const Matrix<T, STORAGE2>& m2) {
173 return Matrix<T, Sum<typename STORAGE1::const_base, typename STORAGE2::const_base> >(m1, -m2);
176template <
typename T,
typename STORAGE1,
typename STORAGE2>
177Matrix<T, MMProd<typename STORAGE1::const_base, typename STORAGE2::const_base> > operator*(
178 const Matrix<T, STORAGE1>& m1,
const Matrix<T, STORAGE2>& m2) {
179 return Matrix<T, MMProd<typename STORAGE1::const_base, typename STORAGE2::const_base> >(m1, m2);
182template <
typename T,
typename STORAGE>
183Matrix<T, typename STORAGE::const_base> operator*(T t,
const Matrix<T, STORAGE>& m) {
184 return Matrix<T, typename STORAGE::const_base>(m) * t;
187template <
typename T,
typename STORAGE>
188Matrix<T, typename STORAGE::const_base> operator*(
const Matrix<T, STORAGE>& m, T t) {
189 return Matrix<T, typename STORAGE::const_base>(m) * t;
192template <
typename T,
typename STORAGE>
193Matrix<T, typename STORAGE::const_base> operator-(
const Matrix<T, STORAGE>& m) {
194 return Matrix<T, typename STORAGE::const_base>(m) * T(-1);
197template <
typename MTYPE,
typename INDEX1,
typename INDEX2>
198struct Msub_constref {
199 using base = Msub_constref;
200 using const_base = Msub_constref;
203template <
typename T,
typename MTYPE,
typename INDEX1,
typename INDEX2>
204class Matrix<T, Msub_constref<MTYPE, INDEX1, INDEX2> > {
206 Matrix(
const Matrix<T, MTYPE> m_,
const INDEX1& index1_,
const INDEX2& index2_)
207 : m(m_), index1(index1_), index2(index2_) {}
209 std::pair<size_t, size_t> size()
const {
210 return std::pair<size_t, size_t>(
211 index1.is_all() ? m.size1() : index1.size(),
212 index2.is_all() ? m.size2() : index2.size());
215 size_t size1()
const {
return index1.is_all() ? m.size1() : index1.size(); }
217 size_t size2()
const {
return index2.is_all() ? m.size2() : index2.size(); }
219 T operator()(
size_t i,
size_t j)
const {
220 return m(index1.is_all() ? i : index1[i], index2.is_all() ? j : index2[j]);
225 const Matrix<T, MTYPE> m;
226 const INDEX1& index1;
227 const INDEX2& index2;
230template <
typename MTYPE>
231struct Minverse_constref {
232 using base = Minverse_constref;
233 using const_base = Minverse_constref;
236template <
typename T,
typename MTYPE>
237class Matrix<T, Minverse_constref<MTYPE> > {
240 const Matrix<T, MTYPE>& m_, Matrix<T>& null_space_ = Matrix<T>::null,
241 ssize_t max_null_space_vector_ = 0)
242 : m(m_), null_space(null_space_), max_null_space_vector(max_null_space_vector_) {}
244 Matrix(
const Matrix& m_)
245 : m(m_.m), null_space(m_.null_space), max_null_space_vector(m_.max_null_space_vector) {}
247 std::pair<size_t, size_t> size()
const {
return m.size(); }
249 size_t size1()
const {
return m.size1(); }
251 size_t size2()
const {
return m.size2(); }
254 const Matrix<T, MTYPE>& m;
255 Matrix<T>& null_space;
256 ssize_t max_null_space_vector;
260template <
typename T,
typename MTYPE>
261Matrix<T, Minverse_constref<MTYPE> > inverse(
262 const Matrix<T, MTYPE>& m, Matrix<T, Mrectangle>& null_space = Matrix<T, Mrectangle>::null,
263 ssize_t max_null_space_vector = 0) {
264 return Matrix<T, Minverse_constref<MTYPE> >(m, null_space, max_null_space_vector);
267template <
typename MTYPE>
268struct Minverse_ext_constref {
269 using base = Minverse_ext_constref;
270 using const_base = Minverse_ext_constref;
273template <
typename T,
typename MTYPE>
274class Matrix<T, Minverse_ext_constref<MTYPE> > {
277 const Matrix<T, MTYPE>& m_,
const T* a_,
const T* b_,
const T* c_,
278 Matrix<T>& null_space_ = Matrix<T>::null, ssize_t max_null_space_vector_ = 0)
283 null_space(null_space_),
284 max_null_space_vector(max_null_space_vector_) {}
286 Matrix(
const Matrix& m_)
291 null_space(m_.null_space),
292 max_null_space_vector(m_.max_null_space_vector) {}
294 std::pair<size_t, size_t> size()
const {
return m.size(); }
296 size_t size1()
const {
return m.size1(); }
298 size_t size2()
const {
return m.size2(); }
301 const Matrix<T, MTYPE>& m;
305 Matrix<T>& null_space;
306 ssize_t max_null_space_vector;
310template <
typename T,
typename MTYPE,
typename MTYPEA,
typename MTYPEB,
typename MTYPEC>
311Matrix<T, Minverse_ext_constref<MTYPE> > update_extension_and_inverse(
312 const Matrix<T, MTYPE>& m,
const Matrix<T, MTYPEA>& a,
const Matrix<T, MTYPEB>& b,
313 const Matrix<T, MTYPEC>& c, Matrix<T, Mrectangle>& null_space = Matrix<T, Mrectangle>::null,
314 ssize_t max_null_space_vector = 0) {
315 return Matrix<T, Minverse_ext_constref<MTYPE> >(
316 m, &a(0, 0), &b(0, 0), &c(0, 0), null_space, max_null_space_vector);
319template <
typename T,
typename MTYPE,
typename MTYPEA,
typename MTYPEB>
320Matrix<T, Minverse_ext_constref<MTYPE> > update_extension_and_inverse(
321 const Matrix<T, MTYPE>& m,
const Vector<T, MTYPEA>& a,
const Vector<T, MTYPEB>& b,
const T& c,
322 Matrix<T, Mrectangle>& null_space = Matrix<T, Mrectangle>::null,
323 ssize_t max_null_space_vector = 0) {
324 return Matrix<T, Minverse_ext_constref<MTYPE> >(
325 m, &a[0], &b[0], &c, null_space, max_null_space_vector);
347template <
typename T,
typename TYPE>
349 const Matrix<T, TYPE>& m, std::ostream& out, std::string seperator =
", ",
350 std::string row_sep =
"\n",
351 std::pair<std::string, std::string> row_enclosure =
352 std::pair<std::string, std::string>(
"",
""),
353 std::pair<std::string, std::string> mat_enclosure =
354 std::pair<std::string, std::string>(
"",
"")) {
355 size_t n_rows = m.size1();
356 size_t n_cols = m.size2();
358 out << mat_enclosure.first;
359 for (
size_t i = 0; i < n_rows; ++i) {
360 out << row_enclosure.first;
361 for (
size_t j = 0; j < n_cols - 1; ++j) { out << m(i, j) << seperator; }
363 out << m(i, n_cols - 1) << row_enclosure.second;
365 if (i < n_rows - 1) { out << row_sep; }
367 out << mat_enclosure.second;
371template <
typename T,
typename TYPE>
372std::ostream& operator<<(std::ostream& out,
const Matrix<T, TYPE>& m) {
373 const auto closures = std::pair<std::string, std::string>(
"( ",
" )");
374 print(m, out,
", ",
",\n", closures, closures);
384template <
typename T,
typename TYPE>
386 const Matrix<T, TYPE>& m, std::string matrixname, std::filesystem::path filepath,
387 std::streamsize precision = 16) {
388 std::ofstream out(filepath);
389 out.precision(precision);
390 out <<
"# " << matrixname <<
" with (" << m.size1() <<
" x " << m.size2() <<
") DoF\n";
395template <
typename ATYPE,
typename BTYPE>
397 using base = Eigenvector;
398 using const_base = Eigenvector;
401template <
typename T,
typename ATYPE,
typename BTYPE>
402class Matrix<T, Eigenvector<ATYPE, BTYPE> > {
405 const Matrix<T, ATYPE>& a_,
const char type_a_,
const Matrix<T, BTYPE>& b_,
406 const char type_b_, Vector<T, Vdense_ref> eigenvalue_,
const char which_[2], T sigma_,
407 int ncv_,
double tol_,
int maxit_,
const Vector<T, Vdense_constref> starting_eigenvector_)
412 eigenvalue(eigenvalue_),
417 starting_eigenvector(starting_eigenvector_) {
418 if (!b.is_null() && a.size() != b.size()) {
419 Exception() <<
"Eigenvalue extraction: Matrix A and B do not have same size." <<
THROW;
421 if (!starting_eigenvector.is_null() && starting_eigenvector.size() != a.size1()) {
422 Exception() <<
"Eigenvalue extraction: Eigenvalue start vector size != matrix size."
425 strcpy(which, which_);
426 if (tol < 0) { tol = 0; }
429 std::pair<size_t, size_t> size()
const {
430 return std::pair<size_t, size_t>(a.size1(), eigenvalue.size());
433 size_t size1()
const {
return a.size1(); }
435 size_t size2()
const {
return eigenvalue.size(); }
437 void resolve(Matrix<T, Mrectangle_increment_ref>& eigenvector);
440 const Matrix<T, ATYPE>& a;
442 const Matrix<T, BTYPE>& b;
444 Vector<T, Vdense_ref> eigenvalue;
450 Vector<T, Vdense_constref> starting_eigenvector;
455 Vector<T, Vdense_ref> x, Vector<T, Vdense_ref> y, Vector<T, Vdense_constref> Bx) {}
456 virtual void prod_b(Vector<T, Vdense_constref> x, Vector<T, Vdense_ref> y) {}
458 Vector<T, Vdense_ref> eigenvalue, Matrix<T, Mrectangle_increment_ref> eigenvector) {}
461 struct OPS1 :
public OP {
462 OPS1(
const Matrix<T, ATYPE>& a_) : a(a_) {}
463 void op(Vector<T, Vdense_ref> x, Vector<T, Vdense_ref> y, Vector<T, Vdense_constref> Bx) {
466 const Matrix<T, ATYPE>& a;
469 struct OPS1i :
public OP {
470 OPS1i(
const Matrix<T, ATYPE>& a_) : a(a_) {}
471 void op(Vector<T, Vdense_ref> x, Vector<T, Vdense_ref> y, Vector<T, Vdense_constref> Bx) {
475 Vector<T, Vdense_ref> eigenvalue, Matrix<T, Mrectangle_increment_ref> eigenvector) {
476 for (
size_t i = 0; i != eigenvalue.size(); ++i) {
477 eigenvalue[i] = T(1) / eigenvalue[i];
480 const Matrix<T, ATYPE>& a;
483 struct OPS2 :
public OP {
484 OPS2(
const Matrix<T, ATYPE>& a_,
const Matrix<T, BTYPE>& b_) : a(a_), b(b_) {}
485 void op(Vector<T, Vdense_ref> x, Vector<T, Vdense_ref> y, Vector<T, Vdense_constref> Bx) {
489 void prod_b(Vector<T, Vdense_constref> x, Vector<T, Vdense_ref> y) { y = b * x; }
490 const Matrix<T, ATYPE>& a;
491 const Matrix<T, BTYPE>& b;
494 struct OPS2i :
public OP {
495 OPS2i(
const Matrix<T, ATYPE>& a_,
const Matrix<T, BTYPE>& b_) : a(a_), b(b_) {}
496 void op(Vector<T, Vdense_ref> x, Vector<T, Vdense_ref> y, Vector<T, Vdense_constref> Bx) {
500 void prod_b(Vector<T, Vdense_constref> x, Vector<T, Vdense_ref> y) { y = a * x; }
502 Vector<T, Vdense_ref> eigenvalue, Matrix<T, Mrectangle_increment_ref> eigenvector) {
503 for (
size_t i = 0; i != eigenvalue.size(); ++i) {
504 eigenvalue[i] = T(1) / eigenvalue[i];
507 const Matrix<T, ATYPE>& a;
508 const Matrix<T, BTYPE>& b;
511 struct OPS3_0 :
public OP {
512 OPS3_0(
const Matrix<T, ATYPE>& a_,
const Matrix<T, BTYPE>& b_) : a(a_), b(b_) {}
513 void op(Vector<T, Vdense_ref> x, Vector<T, Vdense_ref> y, Vector<T, Vdense_constref> Bx) {
521 void prod_b(Vector<T, Vdense_constref> x, Vector<T, Vdense_ref> y) { y = b * x; }
522 const Matrix<T, ATYPE>& a;
523 const Matrix<T, BTYPE>& b;
526 struct OPS3 :
public OP {
527 OPS3(
const Matrix<T, ATYPE>& a,
const Matrix<T, BTYPE>& b_, T sigma) : b(b_), m(a) {
529 for (
size_t i = 0; i != a.size1(); ++i) { m(i, i) -= sigma; }
534 void op(Vector<T, Vdense_ref> x, Vector<T, Vdense_ref> y, Vector<T, Vdense_constref> Bx) {
542 void prod_b(Vector<T, Vdense_constref> x, Vector<T, Vdense_ref> y) { y = b * x; }
543 const Matrix<T, BTYPE>& b;
544 Matrix<T, typename ATYPE::inverse> m;
547 struct OPS4 :
public OP {
548 OPS4(
const Matrix<T, ATYPE>& a_,
const Matrix<T, BTYPE>& b_, T sigma) : a(a_), b(b_), m(a) {
550 for (
size_t i = 0; i != a.size1(); ++i) { m(i, i) -= sigma; }
555 void op(Vector<T, Vdense_ref> x, Vector<T, Vdense_ref> y, Vector<T, Vdense_constref> Bx) {
563 void prod_b(Vector<T, Vdense_constref> x, Vector<T, Vdense_ref> y) { y = a * x; }
564 const Matrix<T, ATYPE>& a;
565 const Matrix<T, BTYPE>& b;
566 Matrix<T, typename ATYPE::inverse> m;
569 struct OPS5 :
public OP {
570 OPS5(
const Matrix<T, ATYPE>& a_,
const Matrix<T, BTYPE>& b_, T sigma_)
571 : sigma(sigma_), a(a_), b(b_), m(a) {
573 for (
size_t i = 0; i != a.size1(); ++i) { m(i, i) -= sigma; }
578 void op(Vector<T, Vdense_ref> x, Vector<T, Vdense_ref> y, Vector<T, Vdense_constref> Bx) {
587 void prod_b(Vector<T, Vdense_constref> x, Vector<T, Vdense_ref> y) { y = b * x; }
589 const Matrix<T, ATYPE>& a;
590 const Matrix<T, BTYPE>& b;
591 Matrix<T, typename ATYPE::inverse> m;
594 struct OPNN1 :
public OP {
595 OPNN1(
const Matrix<T, ATYPE>& a_,
const Matrix<T, BTYPE>& b_) : a(a_), b(b_) {}
596 void op(Vector<T, Vdense_ref> x, Vector<T, Vdense_ref> y, Vector<T, Vdense_constref> Bx) {
601 Vector<T, Vdense_ref> eigenvalue, Matrix<T, Mrectangle_increment_ref> eigenvector) {
602 for (
size_t i = 0; i != eigenvalue.size(); ++i) {
603 eigenvalue[i] = T(1) / eigenvalue[i];
606 const Matrix<T, ATYPE>& a;
607 const Matrix<T, BTYPE>& b;
610 struct OPNN1_shift :
public OP {
611 OPNN1_shift(
const Matrix<T, ATYPE>& a_,
const Matrix<T, BTYPE>& b_, T sigma_)
612 : sigma(sigma_), a(a_), b(b_), m(a) {
614 for (
size_t i = 0; i != a.size1(); ++i) { m(i, i) -= sigma; }
619 void op(Vector<T, Vdense_ref> x, Vector<T, Vdense_ref> y, Vector<T, Vdense_constref> Bx) {
624 Vector<T, Vdense_ref> eigenvalue, Matrix<T, Mrectangle_increment_ref> eigenvector) {
625 std::vector<std::pair<double, size_t> > tmp;
626 for (
size_t i = 0; i != eigenvalue.size(); ++i) {
627 eigenvalue[i] = sigma + T(1) / eigenvalue[i];
628 tmp.push_back(std::pair<double, size_t>(b2000::real(eigenvalue[i]), tmp.size()));
630 std::sort(tmp.begin(), tmp.end(), CompareFirstOfPair());
631 Vector<T, Vdense> eigenvalue_tmp(eigenvalue.size());
632 Matrix<T, Mrectangle> eigenvector_tmp(eigenvector.size1(), eigenvector.size2());
633 for (
size_t i = 0; i != eigenvalue.size(); ++i) {
634 eigenvalue_tmp[i] = eigenvalue[tmp[i].second];
635 eigenvector_tmp[i] = eigenvector[tmp[i].second];
637 eigenvalue = eigenvalue_tmp;
638 eigenvector = Matrix<T, Mrectangle_increment_constref>(eigenvector_tmp);
641 const Matrix<T, ATYPE>& a;
642 const Matrix<T, BTYPE>& b;
643 Matrix<T, typename ATYPE::inverse> m;
646 struct OPNN2 :
public OP {
647 OPNN2(
const Matrix<T, ATYPE>& a_,
const Matrix<T, BTYPE>& b_) : a(a_), b(b_) {}
648 void op(Vector<T, Vdense_ref> x, Vector<T, Vdense_ref> y, Vector<T, Vdense_constref> Bx) {
653 void prod_b(Vector<T, Vdense_constref> x, Vector<T, Vdense_ref> y) {
654 y = b * transposed(b) * x;
657 Vector<T, Vdense_ref> eigenvalue, Matrix<T, Mrectangle_increment_ref> eigenvector) {
658 Matrix<T, Mrectangle> tmp;
660 eigenvector = transposed(b) * tmp;
662 const Matrix<T, ATYPE>& a;
663 const Matrix<T, BTYPE>& b;
666 struct OPNN3 :
public OP {
667 OPNN3(
const Matrix<T, ATYPE>& a,
const Matrix<T, BTYPE>& b_, T sigma) : b(b_), m(a) {
669 for (
size_t i = 0; i != a.size1(); ++i) { m(i, i) -= sigma; }
674 void op(Vector<T, Vdense_ref> x, Vector<T, Vdense_ref> y, Vector<T, Vdense_constref> Bx) {
676 y = b * transposed(b) * x;
684 void prod_b(Vector<T, Vdense_constref> x, Vector<T, Vdense_ref> y) {
685 y = b * transposed(b) * x;
688 Vector<T, Vdense_ref> eigenvalue, Matrix<T, Mrectangle_increment_ref> eigenvector) {
689 Matrix<T, Mrectangle> tmp;
691 eigenvector = transposed(b) * tmp;
693 const Matrix<T, BTYPE>& b;
694 Matrix<T, typename ATYPE::inverse> m;
697 struct OPNN3_0 :
public OP {
698 OPNN3_0(
const Matrix<T, ATYPE>& a_,
const Matrix<T, BTYPE>& b_) : a(a_), b(b_) {}
699 void op(Vector<T, Vdense_ref> x, Vector<T, Vdense_ref> y, Vector<T, Vdense_constref> Bx) {
701 y = b * transposed(b) * x;
709 void prod_b(Vector<T, Vdense_constref> x, Vector<T, Vdense_ref> y) {
710 y = b * transposed(b) * x;
713 Vector<T, Vdense_ref> eigenvalue, Matrix<T, Mrectangle_increment_ref> eigenvector) {
714 Matrix<T, Mrectangle> tmp;
716 eigenvector = transposed(b) * tmp;
718 const Matrix<T, ATYPE>& a;
719 const Matrix<T, BTYPE>& b;
723template <
typename T,
typename ATYPE,
typename BTYPE>
724void Matrix<T, Eigenvector<ATYPE, BTYPE> >::resolve(
725 Matrix<T, Mrectangle_increment_ref>& eigenvector) {
726 size_t size_ = a.size1();
727 std::unique_ptr<OP> op;
732 eigenvector(0, 0) = 1;
733 eigenvalue[0] = a(0, 0);
737 if (strcmp(which,
"RA") == 0) {
742 op = std::unique_ptr<OP>(
new OPS1i(a));
748 op = std::unique_ptr<OP>(
new OPS3(a, Matrix<T, BTYPE>::null, sigma));
750 }
else if (strcmp(which,
"LA") == 0) {
755 op = std::unique_ptr<OP>(
new OPS1i(a));
761 op = std::unique_ptr<OP>(
new OPS3(a, Matrix<T, BTYPE>::null, sigma));
763 }
else if (strcmp(which,
"SM") == 0) {
768 op = std::unique_ptr<OP>(
new OPS1i(a));
774 op = std::unique_ptr<OP>(
new OPS3(a, Matrix<T, BTYPE>::null, sigma));
778 op = std::unique_ptr<OP>(
new OPS1(a));
782 eigenvector(0, 0) = 1.0 / b(0, 0);
783 eigenvalue[0] = a(0, 0) * eigenvector(0, 0);
787 if (strcmp(which,
"RA") == 0) {
790 if ((type_b ==
'S' || type_b ==
'P') && type_a !=
'N') {
792 op = std::unique_ptr<OP>(
new OPS3_0(a, b));
793 }
else if ((type_a ==
'S' || type_a ==
'P') && type_b !=
'N') {
795 op = std::unique_ptr<OP>(
new OPS2i(a, b));
796 }
else if (type_a ==
'N' && type_b ==
'N') {
800 op = std::unique_ptr<OP>(
new OPNN1(a, b));
805 if ((type_b ==
'S' || type_b ==
'P') && type_a !=
'N') {
807 op = std::unique_ptr<OP>(
new OPS3(a, b, sigma));
808 }
else if ((type_a ==
'S' || type_a ==
'P') && type_b !=
'N') {
810 op = std::unique_ptr<OP>(
new OPS4(a, b, sigma));
811 }
else if (type_a ==
'N' && type_b ==
'N') {
815 op = std::unique_ptr<OP>(
new OPNN1_shift(a, b, sigma));
820 }
else if (strcmp(which,
"LA") == 0) {
825 op = std::unique_ptr<OP>(
new OPS2i(a, b));
826 }
else if (type_a ==
'N' && type_b ==
'N') {
830 op = std::unique_ptr<OP>(
new OPNN1(a, b));
835 if (type_b ==
'S' || type_b ==
'P') {
837 op = std::unique_ptr<OP>(
new OPS3(a, b, sigma));
838 }
else if (type_a ==
'S' || type_a ==
'P') {
840 op = std::unique_ptr<OP>(
new OPS4(a, b, sigma));
841 }
else if (type_a ==
'N' && type_b ==
'N') {
845 op = std::unique_ptr<OP>(
new OPNN1_shift(a, b, sigma));
850 }
else if (strcmp(which,
"SM") == 0) {
853 if (type_b ==
'S' || type_b ==
'P') {
855 op = std::unique_ptr<OP>(
new OPS3_0(a, b));
856 }
else if (type_a ==
'S' || type_a ==
'P') {
858 }
else if (type_a ==
'N' && type_b ==
'N') {
861 op = std::unique_ptr<OP>(
new OPNN1(a, b));
866 if (type_b ==
'S' || type_b ==
'P') {
868 op = std::unique_ptr<OP>(
new OPS3(a, b, sigma));
869 }
else if (type_a ==
'S' || type_a ==
'P') {
871 op = std::unique_ptr<OP>(
new OPS4(a, b, sigma));
872 }
else if (type_a ==
'N' && type_b ==
'N') {
875 op = std::unique_ptr<OP>(
new OPNN1_shift(a, b, sigma));
883 op = std::unique_ptr<OP>(
new OPS2(a, b));
891 Vector<T, Vdense> resid(size_);
892 if (ncv == -1) { ncv = std::min(size_, eigenvalue.size() * 2 + 1); }
893 if (
int(eigenvalue.size()) >= ncv) {
894 Exception() <<
"Eigenvalue extraction: Number of required eigenvalues ("
895 << eigenvalue.size() <<
") must be < number of DOFs (" << size_
896 <<
") of reduced system." <<
THROW;
898 std::vector<T> vv(size_ * ncv);
899 int iparam[11] = {1, 0, 300, 0, 0, 0, 0, 0, 0, 0, 0};
900 if (maxit > 0) { iparam[2] = maxit; }
903 std::vector<T> workd(size_ * 3);
904 size_t lworkl = ncv * (3 * ncv + 8);
905 std::vector<T> workl(lworkl);
906 std::vector<T> rwork(ncv);
908 if (starting_eigenvector.is_null()) {
912 resid = starting_eigenvector;
917 ido, bmat, size_, which, eigenvalue.size(), tol, &resid[0], ncv, &vv[0], size_,
918 iparam, ipntr, &workd[0], &workl[0], lworkl, &rwork[0], info);
922 Vector<T, Vdense_ref>(size_, &workd[ipntr[0] - 1]),
923 Vector<T, Vdense_ref>(size_, &workd[ipntr[1] - 1]),
924 Vector<T, Vdense_constref>(size_, 0));
928 Vector<T, Vdense_ref>(size_, &workd[ipntr[0] - 1]),
929 Vector<T, Vdense_ref>(size_, &workd[ipntr[1] - 1]),
930 Vector<T, Vdense_constref>(size_, &workd[ipntr[2] - 1]));
934 Vector<T, Vdense_constref>(size_, &workd[ipntr[0] - 1]),
935 Vector<T, Vdense_ref>(size_, &workd[ipntr[1] - 1]));
948 <<
"Eigenvalue extraction: Maximum number of iterations reached.\n"
949 <<
"All possible eigenvalues (" << int(iparam[4]) <<
") have been found."
950 << logging::LOGFLUSH;
953 if (
size_t(ncv) == size_) {
954 Exception() <<
"Eigenvalue extraction: No shifts could be applied during a "
956 <<
"of the implicitly restarted Arnoldi iteration." <<
THROW;
959 <<
"Eigenvalue extraction: No shifts could be applied during a cycle\n"
960 <<
"of the implicitly restarted Arnoldi iteration. Retry by increasing "
962 << logging::LOGFLUSH;
963 ncv = std::min(size_, ncv + eigenvalue.size());
964 vv.resize(size_ * ncv);
965 lworkl = ncv * (3 * ncv + 8);
966 workl.resize(lworkl);
972 if (
size_t(iparam[4]) < eigenvalue.size() + 2) {
973 Exception() <<
"Eigenvalue extraction: Could not build an Arnoldi "
975 <<
"All possible eigenvalues (" << int(iparam[4])
976 <<
") have been found." <<
THROW;
979 <<
"Eigenvalue extraction: Could not build an Arnoldi factorization.\n"
980 "Retry by reducing the NCV"
981 << logging::LOGFLUSH;
982 ncv = std::min(
int(size_), iparam[4]);
983 vv.resize(size_ * ncv);
984 lworkl = ncv * (3 * ncv + 8);
985 workl.resize(lworkl);
991 Exception() <<
"Eigenvalue extraction: arpack eigenvalue extraction failed, "
993 <<
info <<
".\nPossible reason: B matrix is 0." <<
THROW;
998 std::vector<int> select(ncv);
999 std::vector<T> D(eigenvalue.size() + 1);
1001 eigenvector.is_null() ? 0 : 1,
"A", &select[0], &D[0], eigenvector.m, eigenvector.ldm,
1002 sigma, bmat, size_, which, eigenvalue.size(), tol, &resid[0], ncv, &vv[0], size_, iparam,
1003 ipntr, &workd[0], &workl[0], lworkl, &rwork[0],
info);
1004 std::copy(D.begin(), D.end() - 1, eigenvalue.v);
1006 Exception() <<
"Eigenvalue extraction: arpack eigenvalue extraction failed, eupd error="
1009 op->end(eigenvalue, eigenvector);
1012template <
typename T,
typename ATYPE,
typename VTYPE1>
1013Matrix<T, Eigenvector<ATYPE, ATYPE> > eigenvector(
1014 const Matrix<T, ATYPE>& a,
char type_a, Vector<T, VTYPE1>& eigenvalue,
1015 const char which[2] =
"SM", T sigma = 0,
int ncv = -1,
double tol = -1,
int maxit = -1) {
1016 return Matrix<T, Eigenvector<ATYPE, ATYPE> >(
1017 a, type_a, Matrix<T, ATYPE>::null,
' ', eigenvalue, which, sigma, ncv, tol, maxit,
1018 Vector<T, Vdense_constref>::null);
1021template <
typename T,
typename ATYPE,
typename VTYPE1,
typename VTYPE2>
1022Matrix<T, Eigenvector<ATYPE, ATYPE> > eigenvector(
1023 const Matrix<T, ATYPE>& a,
char type_a, Vector<T, VTYPE1>& eigenvalue,
1024 const char which[2] =
"SM", T sigma = 0,
int ncv = -1,
double tol = -1,
int maxit = -1,
1025 const Vector<T, VTYPE2>& starting_eigenvector = Vector<T, VTYPE2>::null) {
1026 return Matrix<T, Eigenvector<ATYPE, ATYPE> >(
1027 a, type_a, Matrix<T, ATYPE>::null,
' ', eigenvalue, which, sigma, ncv, tol, maxit,
1028 starting_eigenvector.is_null()
1029 ? Vector<T, Vdense_constref>::null
1030 :
static_cast<const Vector<T, Vdense_constref>&
>(starting_eigenvector));
1055template <
typename T,
typename ATYPE,
typename BTYPE,
typename VTYPE1>
1056Matrix<T, Eigenvector<ATYPE, BTYPE> > eigenvector(
1057 const Matrix<T, ATYPE>& a,
char type_a,
const Matrix<T, BTYPE>& b,
char type_b,
1058 Vector<T, VTYPE1>& eigenvalue,
const char which[2] =
"SM", T sigma = 0,
int ncv = -1,
1059 double tol = -1,
int maxit = -1) {
1060 return Matrix<T, Eigenvector<ATYPE, BTYPE> >(
1061 a, type_a, b, type_b, eigenvalue, which, sigma, ncv, tol, maxit,
1062 Vector<T, Vdense_constref>::null);
1065template <
typename T,
typename ATYPE,
typename BTYPE,
typename VTYPE1>
1066Matrix<T, Eigenvector<ATYPE, BTYPE> > eigenvector(
1067 const Matrix<T, ATYPE>& a,
char type_a,
const std::vector<Matrix<T, BTYPE> >& b,
char type_b,
1068 Vector<T, VTYPE1>& eigenvalue,
const char which[2] =
"SM", T sigma = 0,
int ncv = -1,
1069 double tol = -1,
int maxit = -1) {
1070 return Matrix<T, Eigenvector<ATYPE, BTYPE> >(
1071 a, type_a, b, type_b, eigenvalue, which, sigma, ncv, tol, maxit,
1072 Vector<T, Vdense_constref>::null);
1075template <
typename T,
typename ATYPE,
typename BTYPE,
typename VTYPE1,
typename VTYPE2>
1076Matrix<T, Eigenvector<ATYPE, BTYPE> > eigenvector(
1077 const Matrix<T, ATYPE>& a,
char type_a,
const Matrix<T, BTYPE>& b,
char type_b,
1078 Vector<T, VTYPE1>& eigenvalue,
const char which[2] =
"SM", T sigma = 0,
int ncv = -1,
1079 double tol = -1,
int maxit = -1,
1080 const Vector<T, VTYPE2>& starting_eigenvector = Vector<T, VTYPE2>::null) {
1081 return Matrix<T, Eigenvector<ATYPE, BTYPE> >(
1082 a, type_a, b, type_b, eigenvalue, which, sigma, ncv, tol, maxit,
1083 starting_eigenvector.is_null()
1084 ? Vector<T, Vdense_constref>::null
1085 :
static_cast<const Vector<T, Vdense_constref>&
>(starting_eigenvector));
1088template <
typename ATYPE,
typename BTYPE>
1089struct PolyEigenvector {
1090 using base = PolyEigenvector;
1091 using const_base = PolyEigenvector;
1094template <
typename T,
typename ATYPE,
typename BTYPE>
1095class Matrix<T, PolyEigenvector<ATYPE, BTYPE> > {
1098 const Matrix<T, ATYPE>& a_,
const char type_a_,
const std::vector<Matrix<T, BTYPE> >& b_,
1099 const char type_b_, Vector<T, Vdense_ref> eigenvalue_r,
1100 Vector<T, Vdense_ref> eigenvalue_i,
const char which_[2], T sigma_,
int ncv_,
double tol_,
1101 int maxit_,
const Vector<T, Vdense_constref> starting_eigenvector_)
1106 eigenvaluer(eigenvalue_r),
1107 eigenvaluei(eigenvalue_i),
1112 starting_eigenvector(starting_eigenvector_) {
1113 for (
size_t i = 0; i != b.size(); ++i) {
1114 if (a.size() != b[i].size()) {
1115 Exception() <<
"The two matrices are not of the same size." <<
THROW;
1118 if (!starting_eigenvector.is_null()
1119 && starting_eigenvector.size() != a.size1() * b.size()) {
1120 Exception() <<
"The starting eigenvalue vector is not of the same size than the matrix."
1123 strcpy(which, which_);
1124 if (tol < 0) { tol = 0; }
1127 std::pair<size_t, size_t> size()
const {
1128 return std::pair<size_t, size_t>(a.size1(), eigenvaluer.size());
1131 size_t size1()
const {
return a.size1(); }
1133 size_t size2()
const {
return eigenvaluer.size(); }
1135 void resolve(Matrix<T, Mrectangle_increment_ref>& eigenvector);
1138 const Matrix<T, ATYPE>& a;
1140 const std::vector<Matrix<T, BTYPE> >& b;
1142 Vector<T, Vdense_ref> eigenvaluer;
1143 Vector<T, Vdense_ref> eigenvaluei;
1149 Vector<T, Vdense_constref> starting_eigenvector;
1154 Vector<T, Vdense_ref> x, Vector<T, Vdense_ref> y, Vector<T, Vdense_constref> Bx) {}
1155 virtual void prod_b(Vector<T, Vdense_constref> x, Vector<T, Vdense_ref> y) {}
1157 Vector<T, Vdense_ref> eigenvaluer, Vector<T, Vdense_ref> eigenvaluei,
1158 Matrix<T, Mrectangle_increment_ref> eigenvector) {}
1161 struct OP1 :
public OP {
1162 OP1(
const Matrix<T, ATYPE>& a_,
const std::vector<Matrix<T, BTYPE> >& b_) : a(a_), b(b_) {}
1163 void op(Vector<T, Vdense_ref> x, Vector<T, Vdense_ref> y, Vector<T, Vdense_constref> Bx) {
1164 size_t s = a.size1();
1165 y(Interval(0, s)) = b[0] * x(Interval(0, s));
1166 for (
size_t i = 1; i < b.size(); ++i) {
1167 y(Interval(0, s)) += b[i] * x(Interval(i * s, (i + 1) * s));
1169 for (
size_t i = 1; i < b.size(); ++i) {
1170 y(Interval(i * s, (i + 1) * s)) = x(Interval((i - 1) * s, i * s));
1172 y(Interval(0, s)) = inverse(a) * y(Interval(0, s));
1174 void prod_b(Vector<T, Vdense_constref> x, Vector<T, Vdense_ref> y) {
1175 size_t s = a.size1();
1176 y(Interval(0, s)) = a * x(Interval(0, s));
1177 y(Interval(s, y.size())) = x(Interval(s, x.size()));
1179 const Matrix<T, ATYPE>& a;
1180 const std::vector<Matrix<T, BTYPE> >& b;
1184template <
typename T,
typename ATYPE,
typename BTYPE>
1185void Matrix<T, PolyEigenvector<ATYPE, BTYPE> >::resolve(
1186 Matrix<T, Mrectangle_increment_ref>& eigenvector) {
1187 size_t size_ = a.size1() * b.size();
1188 if (eigenvaluer.size() > size_ - 2) {
1191 << eigenvaluer.size() <<
" is too large for the size " << size_
1192 <<
" of problem." <<
THROW;
1194 std::unique_ptr<OP> op;
1199 if (sigma == T(0)) {
1200 if (type_a ==
'P') {
1203 op = std::unique_ptr<OP>(
new OP1(a, b));
1204 if (strcmp(which,
"SM") == 0) {
1205 strcpy(which,
"LM");
1206 }
else if (strcmp(which,
"RA") == 0) {
1207 strcpy(which,
"LR");
1219 Vector<T, Vdense> resid(size_);
1220 if (ncv == -1) { ncv = std::min(size_, eigenvaluer.size() * 2 + 1); }
1221 std::vector<T> vv(size_ * (ncv + 1));
1222 int iparam[11] = {1, 0, 300, 1, 0, 0, 0, 0, 0, 0, 0};
1223 if (maxit > 0) { iparam[2] = maxit; }
1226 std::vector<T> workd(size_ * 3);
1227 size_t lworkl = ncv * (3 * ncv + 8);
1228 std::vector<T> workl(lworkl);
1229 std::vector<T> rwork(ncv);
1231 if (starting_eigenvector.is_null()) {
1235 resid = starting_eigenvector;
1240 ido, bmat, size_, which, eigenvaluer.size(), tol, &resid[0], ncv, &vv[0], size_,
1241 iparam, ipntr, &workd[0], &workl[0], lworkl, &rwork[0], info);
1245 Vector<T, Vdense_ref>(size_, &workd[ipntr[0] - 1]),
1246 Vector<T, Vdense_ref>(size_, &workd[ipntr[1] - 1]),
1247 Vector<T, Vdense_constref>(size_, 0));
1251 Vector<T, Vdense_ref>(size_, &workd[ipntr[0] - 1]),
1252 Vector<T, Vdense_ref>(size_, &workd[ipntr[1] - 1]),
1253 Vector<T, Vdense_constref>(size_, &workd[ipntr[2] - 1]));
1257 Vector<T, Vdense_constref>(size_, &workd[ipntr[0] - 1]),
1258 Vector<T, Vdense_ref>(size_, &workd[ipntr[1] - 1]));
1271 <<
"Eigenvalue extraction: Maximum number of iterations reached\n."
1272 <<
"All possible eigenvalues (" << int(iparam[4]) <<
") have been found."
1273 << logging::LOGFLUSH;
1276 if (
size_t(ncv) == size_) {
1277 Exception() <<
"Eigenvalue extraction: No shifts could be applied during a "
1279 <<
"of the implicitly restarted Arnoldi iteration." <<
THROW;
1282 <<
"Eigenvalue extraction: No shifts could be applied during a cycle of "
1284 <<
"restarted Arnoldi iteration. Retry by increasing NCV."
1285 << logging::LOGFLUSH;
1286 ncv = std::min(size_, ncv + eigenvaluer.size());
1287 vv.resize(size_ * ncv);
1288 lworkl = ncv * (3 * ncv + 8);
1289 workl.resize(lworkl);
1295 if (
size_t(iparam[4]) < eigenvaluer.size() + 2) {
1296 Exception() <<
"Eigenvalue extraction: Could not build an Arnoldi "
1298 <<
"All possible eigenvalues (" << int(iparam[4])
1299 <<
") have been found." <<
THROW;
1302 <<
"Eigenvalue extraction: Could not build an Arnoldi factorization.\n"
1303 " Retry by reducing the NCV"
1304 << logging::LOGFLUSH;
1305 ncv = std::min(
int(size_), iparam[4]);
1306 vv.resize(size_ * ncv);
1307 lworkl = ncv * (3 * ncv + 8);
1308 workl.resize(lworkl);
1314 Exception() <<
"Eigenvalue extraction: arpack subroutine aupd error=" <<
info
1315 <<
".\nPossible reason: B matrix is 0." <<
THROW;
1319 }
while (ido != 99);
1320 std::vector<int> select(ncv);
1321 std::vector<T> Dr(eigenvaluer.size() + 1);
1322 std::vector<T> Di(eigenvaluei.size() + 1);
1323 std::vector<T> workev(3 * ncv);
1324 Matrix<T, Mrectangle> eigenvector_tmp(size_, eigenvaluer.size() + 1);
1326 eigenvector.is_null() ? 0 : 1,
"A", &select[0], &Dr[0], &Di[0], &eigenvector_tmp.m[0],
1327 size_, sigma, 0, &workev[0], bmat, size_, which, eigenvaluer.size(), tol, &resid[0], ncv,
1328 &vv[0], size_, iparam, ipntr, &workd[0], &workl[0], lworkl, &rwork[0],
info);
1331 eigenvector_tmp(Interval(0, eigenvector.size1()), Interval(0, eigenvector.size2()));
1333 for (
size_t i = 0; i != eigenvaluer.size(); ++i) {
1334 const double d = 1 / (Dr[i] * Dr[i] + Di[i] * Di[i]);
1335 eigenvaluer[i] = Dr[i] * d;
1336 eigenvaluei[i] = -Di[i] * d;
1339 std::copy(Dr.begin(), Dr.end() - 1, eigenvaluer.v);
1340 std::copy(Di.begin(), Di.end() - 1, eigenvaluei.v);
1343 Exception() <<
"Eigenvalue extraction: Error with the arpack subroutine eupd, info = "
1346 op->end(eigenvaluer, eigenvaluei, eigenvector);
1371template <
typename T,
typename ATYPE,
typename BTYPE,
typename VTYPE1>
1372Matrix<T, PolyEigenvector<ATYPE, BTYPE> > eigenvector(
1373 const Matrix<T, ATYPE>& a,
char type_a,
const std::vector<Matrix<T, BTYPE> >& b,
char type_b,
1374 Vector<T, VTYPE1>& eigenvalue_r, Vector<T, VTYPE1>& eigenvalue_i,
const char which[2] =
"SM",
1375 T sigma = 0,
int ncv = -1,
double tol = -1,
int maxit = -1) {
1376 return Matrix<T, PolyEigenvector<ATYPE, BTYPE> >(
1377 a, type_a, b, type_b, eigenvalue_r, eigenvalue_i, which, sigma, ncv, tol, maxit,
1378 Vector<T, Vdense_constref>::null);
1381template <
typename T>
1382void copy_real(
const Matrix<b2000::csda<T>, Mrectangle_constref>& in, Matrix<T, Mrectangle>& out) {
1383 out.resize(in.size());
1384 const b2000::csda<T>* pin = &in(0, 0);
1385 T* pout = &out(0, 0);
1386 const T* pout_end = pout + out.size1() * out.size2();
1387 for (; pout != pout_end; ++pin, ++pout) { *pout = real(*pin); }
1390template <
typename T>
1391void copy_real(
const Matrix<std::complex<T>, Mrectangle_constref>& in, Matrix<T, Mrectangle>& out) {
1392 out.resize(in.size());
1393 const std::complex<T>* pin = &in(0, 0);
1394 T* pout = &out(0, 0);
1395 const T* pout_end = pout + out.size1() * out.size2();
1396 for (; pout != pout_end; ++pin, ++pout) { *pout = real(*pin); }
1399template <
typename T>
1400void copy_imag(
const Matrix<b2000::csda<T>, Mrectangle_constref>& in, Matrix<T, Mrectangle>& out) {
1401 out.resize(in.size());
1402 const b2000::csda<T>* pin = &in(0, 0);
1403 T* pout = &out(0, 0);
1404 const T* pout_end = pout + out.size1() * out.size2();
1405 for (; pout != pout_end; ++pin, ++pout) { *pout = imag(*pin); }
1408template <
typename T>
1409void copy_imag(
const Matrix<std::complex<T>, Mrectangle_constref>& in, Matrix<T, Mrectangle>& out) {
1410 out.resize(in.size());
1411 const std::complex<T>* pin = &in(0, 0);
1412 T* pout = &out(0, 0);
1413 const T* pout_end = pout + out.size1() * out.size2();
1414 for (; pout != pout_end; ++pin, ++pout) { *pout = imag(*pin); }
1417template <
typename T>
1418void copy(
const Matrix<b2000::csda<T>, Mrectangle_constref>& in, Matrix<T, Mrectangle>& out) {
1419 out.resize(in.size());
1420 const b2000::csda<T>* pin = &in(0, 0);
1421 T* pout = &out(0, 0);
1422 const T* pout_end = pout + out.size1() * out.size2();
1423 for (; pout != pout_end; ++pin, ++pout) { *pout = real(*pin); }
1426template <
typename T>
1427void copy(
const Matrix<std::complex<T>, Mrectangle_constref>& in, Matrix<T, Mrectangle>& out) {
1428 out.resize(in.size());
1429 const std::complex<T>* pin = &in(0, 0);
1430 T* pout = &out(0, 0);
1431 const T* pout_end = pout + out.size1() * out.size2();
1432 for (; pout != pout_end; ++pin, ++pout) { *pout = real(*pin); }
1435template <
typename T>
1436void copy(
const Matrix<T, Mrectangle_constref>& in, Matrix<b2000::csda<T>, Mrectangle>& out) {
1437 out.resize(in.size());
1438 const T* pin = &in(0, 0);
1439 b2000::csda<T>* pout = &out(0, 0);
1440 const b2000::csda<T>* pout_end = pout + out.size1() * out.size2();
1441 for (; pout != pout_end; ++pin, ++pout) { *pout = b2000::csda<T>(*pin); }
1444template <
typename T>
1445void copy(
const Matrix<T, Mrectangle_constref>& in, Matrix<std::complex<T>, Mrectangle>& out) {
1446 out.resize(in.size());
1447 const T* pin = &in(0, 0);
1448 std::complex<T>* pout = &out(0, 0);
1449 const std::complex<T>* pout_end = pout + out.size1() * out.size2();
1450 for (; pout != pout_end; ++pin, ++pout) { *pout = std::complex<T>(*pin); }
1453template <
typename T>
1454void copy(
const Matrix<T, Mrectangle_constref>& in, Matrix<T, Mrectangle>& out) {
#define THROW
Definition b2exception.H:198
Logger & get_logger(const std::string &logger_name="")
Definition b2logging.H:829
GenericException< UnimplementedError_name > UnimplementedError
Definition b2exception.H:314