FLAMES 0.1.0
Matrix-Empowered HLS Library
core.hpp
Go to the documentation of this file.
1
12#ifndef _FLAMES_CORE_HPP_
13#define _FLAMES_CORE_HPP_
14
15#include <ap_fixed.h>
16#include <ap_int.h>
17#include <cassert>
18#include <complex>
19#include <cstddef>
20#include <fstream>
21#include <hls_vector.h>
22#include <initializer_list>
23#include <iostream>
24#include <type_traits>
25#include <vector>
26
27#ifndef __VITIS_HLS__
28# error "FLAMES library can only be used for Vitis HLS."
29#endif
30
31/*
32 * There are some unwanted warning messages, including:
33 * WARNING: [HLS 207-1462] template template parameter using 'typename' is a C++17 extension
34 * WARNING: [HLS 207-5292] unused parameter '...'
35 * They are safe to ignore, so all warnings of the FLAMES library are suppressed.
36 * You can restore them by defining `FLAMES_PRESERVE_WARNING`
37 */
38#ifndef FLAMES_KEEP_WARNING
39# ifdef __SYNTHESIS__
40# pragma GCC diagnostic push
41# pragma GCC diagnostic ignored "-Weverything"
42# endif
43#endif
44
45#ifndef PRAGMA_SUB
46# define PRAGMA_SUB(x) _Pragma(# x)
47#endif
48#ifndef FLAMES_PRAGMA
49// Alias for #pragma HLS with support for macro expansion.
50# define FLAMES_PRAGMA(x) PRAGMA_SUB(HLS x)
51#endif
52
53#ifndef FLAMES_MAT_PLUS_UNROLL_FACTOR
54# ifdef FLAMES_UNROLL_FACTOR
55# define FLAMES_MAT_PLUS_UNROLL_FACTOR FLAMES_UNROLL_FACTOR
56# else
57# define FLAMES_MAT_PLUS_UNROLL_FACTOR 32
58# endif
59#endif
60#ifndef FLAMES_MAT_MINUS_UNROLL_FACTOR
61# ifdef FLAMES_UNROLL_FACTOR
62# define FLAMES_MAT_MINUS_UNROLL_FACTOR FLAMES_UNROLL_FACTOR
63# else
64# define FLAMES_MAT_MINUS_UNROLL_FACTOR 32
65# endif
66#endif
67#ifndef FLAMES_MAT_SET_VALUE_UNROLL_FACTOR
68# ifdef FLAMES_UNROLL_FACTOR
69# define FLAMES_MAT_SET_VALUE_UNROLL_FACTOR FLAMES_UNROLL_FACTOR
70# else
71# define FLAMES_MAT_SET_VALUE_UNROLL_FACTOR 32
72# endif
73#endif
74#ifndef FLAMES_MAT_POWER_UNROLL_FACTOR
75# ifdef FLAMES_UNROLL_FACTOR
76# define FLAMES_MAT_POWER_UNROLL_FACTOR FLAMES_UNROLL_FACTOR
77# else
78# define FLAMES_MAT_POWER_UNROLL_FACTOR 32
79# endif
80#endif
81#ifndef FLAMES_MAT_COPY_UNROLL_FACTOR
82# ifdef FLAMES_UNROLL_FACTOR
83# define FLAMES_MAT_COPY_UNROLL_FACTOR FLAMES_UNROLL_FACTOR
84# else
85# define FLAMES_MAT_COPY_UNROLL_FACTOR 32
86# endif
87#endif
88#ifndef FLAMES_MAT_SCALAR_TIMES_UNROLL_FACTOR
89# ifdef FLAMES_MAT_TIMES_UNROLL_FACTOR
90# define FLAMES_MAT_SCALAR_TIMES_UNROLL_FACTOR FLAMES_MAT_TIMES_UNROLL_FACTOR
91# else
92# ifdef FLAMES_UNROLL_FACTOR
93# define FLAMES_MAT_SCALAR_TIMES_UNROLL_FACTOR FLAMES_UNROLL_FACTOR
94# else
95# define FLAMES_MAT_SCALAR_TIMES_UNROLL_FACTOR 32
96# endif
97# endif
98#endif
99#ifndef FLAMES_MAT_TIMES_UNROLL_FACTOR
100# ifdef FLAMES_UNROLL_FACTOR
101# define FLAMES_MAT_TIMES_UNROLL_FACTOR FLAMES_UNROLL_FACTOR
102# else
103# define FLAMES_MAT_TIMES_UNROLL_FACTOR 32
104# endif
105#endif
106#ifndef FLAMES_MAT_EMUL_UNROLL_FACTOR
107# ifdef FLAMES_UNROLL_FACTOR
108# define FLAMES_MAT_EMUL_UNROLL_FACTOR FLAMES_UNROLL_FACTOR
109# else
110# define FLAMES_MAT_EMUL_UNROLL_FACTOR 32
111# endif
112#endif
113#ifndef FLAMES_MAT_BOOL_OPER_UNROLL_FACTOR
114# ifdef FLAMES_UNROLL_FACTOR
115# define FLAMES_MAT_BOOL_OPER_UNROLL_FACTOR FLAMES_UNROLL_FACTOR
116# else
117# define FLAMES_MAT_BOOL_OPER_UNROLL_FACTOR 32
118# endif
119#endif
120#ifndef FLAMES_MAT_ABS_UNROLL_FACTOR
121# ifdef FLAMES_UNROLL_FACTOR
122# define FLAMES_MAT_ABS_UNROLL_FACTOR FLAMES_UNROLL_FACTOR
123# else
124# define FLAMES_MAT_ABS_UNROLL_FACTOR 32
125# endif
126#endif
127#ifndef FLAMES_MAT_TRANSPOSE_UNROLL_FACTOR
128# ifdef FLAMES_UNROLL_FACTOR
129# define FLAMES_MAT_TRANSPOSE_UNROLL_FACTOR FLAMES_UNROLL_FACTOR
130# else
131# define FLAMES_MAT_TRANSPOSE_UNROLL_FACTOR 32
132# endif
133#endif
134#ifndef FLAMES_MAT_INV_UNROLL_FACTOR
135# ifdef FLAMES_UNROLL_FACTOR
136# define FLAMES_MAT_INV_UNROLL_FACTOR FLAMES_UNROLL_FACTOR
137# else
138# define FLAMES_MAT_INV_UNROLL_FACTOR 32
139# endif
140#endif
141#ifndef FLAMES_MAT_PARTITION_COMPLETE
142# ifndef FLAMES_MAT_PARTITION_FACTOR
143# define FLAMES_MAT_PARTITION_FACTOR 8
144# endif
145#endif
146#ifndef FLAMES_SORT_PARTITION_COMPLETE
147# ifndef FLAMES_SORT_PARTITION_FACTOR
148# define FLAMES_SORT_PARTITION_FACTOR 32
149# endif
150#endif
151
152#if defined __SYNTHESIS__ && defined FLAMES_PRINT_PER_MAT_COPY
153# undef FLAMES_PRINT_PER_MAT_COPY
154#endif
155
156#ifdef INLINE
157# define DEFINED_INLINE
158# undef INLINE
159#endif
160
166namespace flames {
167
181 ASYM
183
185using MATTYPE_NORMAL = std::integral_constant<int, MatType::NORMAL>;
187using MATTYPE_DIAGONAL = std::integral_constant<int, MatType::DIAGONAL>;
189using MATTYPE_SCALAR = std::integral_constant<int, MatType::SCALAR>;
191using MATTYPE_UPPER = std::integral_constant<int, MatType::UPPER>;
193using MATTYPE_LOWER = std::integral_constant<int, MatType::LOWER>;
195using MATTYPE_SUPPER = std::integral_constant<int, MatType::SUPPER>;
197using MATTYPE_SLOWER = std::integral_constant<int, MatType::SLOWER>;
199using MATTYPE_SYM = std::integral_constant<int, MatType::SYM>;
201using MATTYPE_ASYM = std::integral_constant<int, MatType::ASYM>;
202
209template <typename T>
210inline constexpr MatType matType() {
211 return MatType(T::value);
212}
213
219template <int type>
220using MType = std::integral_constant<int, type>;
221
229inline constexpr MatType sumType(MatType type1, MatType type2) noexcept {
230 if (type1 == type2) return type1;
231 else if ((type1 == MatType::DIAGONAL && type2 == MatType::SCALAR) ||
232 (type1 == MatType::SCALAR && type2 == MatType::DIAGONAL))
233 return MatType::DIAGONAL;
234 else if ((type1 == MatType::DIAGONAL && type2 == MatType::UPPER) ||
235 (type1 == MatType::UPPER && type2 == MatType::DIAGONAL))
236 return MatType::UPPER;
237 else if ((type1 == MatType::DIAGONAL && type2 == MatType::LOWER) ||
238 (type1 == MatType::LOWER && type2 == MatType::DIAGONAL))
239 return MatType::LOWER;
240 else if ((type1 == MatType::DIAGONAL && type2 == MatType::SUPPER) ||
241 (type1 == MatType::SUPPER && type2 == MatType::DIAGONAL))
242 return MatType::UPPER;
243 else if ((type1 == MatType::DIAGONAL && type2 == MatType::SLOWER) ||
244 (type1 == MatType::SLOWER && type2 == MatType::DIAGONAL))
245 return MatType::LOWER;
246 else if ((type1 == MatType::SCALAR && type2 == MatType::SUPPER) ||
247 (type1 == MatType::SUPPER && type2 == MatType::SCALAR))
248 return MatType::UPPER;
249 else if ((type1 == MatType::SCALAR && type2 == MatType::SLOWER) ||
250 (type1 == MatType::SLOWER && type2 == MatType::SCALAR))
251 return MatType::LOWER;
252 else if ((type1 == MatType::SUPPER && type2 == MatType::UPPER) ||
253 (type1 == MatType::UPPER && type2 == MatType::SUPPER))
254 return MatType::UPPER;
255 else if ((type1 == MatType::SLOWER && type2 == MatType::LOWER) ||
256 (type1 == MatType::LOWER && type2 == MatType::SLOWER))
257 return MatType::LOWER;
258 else if ((type1 == MatType::DIAGONAL && type2 == MatType::SYM) ||
259 (type1 == MatType::SYM && type2 == MatType::DIAGONAL))
260 return MatType::SYM;
261 else if ((type1 == MatType::SCALAR && type2 == MatType::SYM) || (type1 == MatType::SYM && type2 == MatType::SCALAR))
262 return MatType::SYM;
263 else return MatType::NORMAL;
264}
265
276inline constexpr MatType mulType(MatType type1, MatType type2, size_t n_rows, size_t comm, size_t n_cols) noexcept {
277 if (n_rows == comm && comm == n_cols) {
278 if (type1 == type2) {
279 if (type1 != SYM && type1 != ASYM) return type1;
280 }
281 if (type1 == MatType::SCALAR) return type2;
282 else if (type2 == MatType::SCALAR) return type1;
283 else if (type1 == MatType::DIAGONAL && (type2 == MatType::SUPPER || type2 == MatType::UPPER ||
284 type2 == MatType::SLOWER || type2 == MatType::LOWER))
285 return type2;
286 else if (type2 == MatType::DIAGONAL && (type1 == MatType::SUPPER || type1 == MatType::UPPER ||
287 type1 == MatType::SLOWER || type1 == MatType::LOWER))
288 return type1;
289 else if (type1 == MatType::SUPPER && type2 == MatType::UPPER) return type1;
290 else if (type1 == MatType::SLOWER && type2 == MatType::LOWER) return type1;
291 else if (type1 == MatType::UPPER && type2 == MatType::SUPPER) return type2;
292 else if (type1 == MatType::LOWER && type2 == MatType::SLOWER) return type2;
293 }
294 return MatType::NORMAL;
295}
296
303inline constexpr MatType tType(MatType type) noexcept {
304 if (type == MatType::SUPPER) return MatType::SLOWER;
305 else if (type == MatType::SLOWER) return MatType::SUPPER;
306 else if (type == MatType::UPPER) return MatType::LOWER;
307 else if (type == MatType::LOWER) return MatType::UPPER;
308 else return type;
309}
310
318inline constexpr size_t upperRow(size_t index, size_t N) {
319 size_t r = 0;
320 while (index >= N - r) {
321 index -= N - r;
322 ++r;
323 }
324 return r;
325}
326
334inline constexpr size_t lowerRow(size_t index, size_t N) {
335 size_t r = 0;
336 while (index >= r + 1) {
337 index -= r + 1;
338 ++r;
339 }
340 return r;
341}
342
350inline constexpr size_t supperRow(size_t index, size_t N) {
351 size_t r = 0;
352 while (index >= N - 1 - r) {
353 index -= N - 1 - r;
354 ++r;
355 }
356 return r;
357}
358
366inline constexpr size_t slowerRow(size_t index, size_t N) {
367 size_t r = 0;
368 while (index >= r) {
369 index -= r;
370 ++r;
371 }
372 return r;
373}
374
388template <typename T, size_t n_rows, size_t n_cols, MatType type = MatType::NORMAL>
389class Mat;
390
391template <typename T, size_t n_rows, size_t n_cols, size_t n_slices, MatType type = MatType::NORMAL>
392class Tensor;
393
401template <typename T, size_t N>
403
411template <typename T, size_t N>
413
422template <typename T, size_t n_rows, size_t n_cols, MatType type = MatType::NORMAL>
423class MatView;
424
425template <typename T, size_t n_rows, size_t n_cols, MatType type = MatType::NORMAL>
426class MatRef;
427
436template <typename T, size_t n_rows, size_t n_cols, MatType type>
437class MatViewOpp;
438
447template <typename T, size_t n_rows, size_t n_cols, MatType type>
448class MatViewT;
449
459template <typename T, size_t N, size_t N_, MatType type, typename type_parent = MATTYPE_NORMAL>
460class MatViewDiagMat;
461
471template <typename T, size_t N, size_t N_, MatType type, typename type_parent = MATTYPE_NORMAL>
472class MatViewDiagVec;
473
483template <typename T, size_t N, size_t N_, MatType type, typename type_parent = MATTYPE_NORMAL>
485
495template <typename T, size_t N, size_t N_, MatType type, typename type_parent = MATTYPE_NORMAL>
496class MatViewOffDiag;
497
507template <typename T, size_t n_rows, size_t n_cols, MatType type, typename type_parent = MATTYPE_NORMAL>
508class MatViewCol;
509
510template <typename T, size_t n_rows, size_t n_cols, MatType type, typename type_parent = MATTYPE_NORMAL>
511class MatRefCol;
512
522template <typename T, size_t n_rows, size_t n_cols, MatType type, typename type_parent = MATTYPE_NORMAL>
523class MatViewRow;
524
534template <size_t first_col, size_t last_col, typename T, size_t n_rows, size_t n_cols, MatType type,
535 typename type_parent = MATTYPE_NORMAL>
536class MatViewCols;
537
547template <size_t first_row, size_t last_row, typename T, size_t n_rows, size_t n_cols, MatType type,
548 typename type_parent = MATTYPE_NORMAL>
549class MatViewRows;
550
556enum class InitAfterwards {
557 NONE,
558 OPP,
559 TR
560};
561
562enum class Init { NONE, ZEROS, ONES };
563
564template <typename T, size_t n_rows, size_t n_cols, MatType type>
565class Mat {
566 friend class MatView<T, n_rows, n_cols, type>;
567 friend class MatViewOpp<T, n_rows, n_cols, type>;
568 friend class MatViewT<T, n_cols, n_rows, type>;
569 friend class MatViewT<T, n_rows, n_cols, type>;
570 template <typename View_T, size_t View_N, size_t View_N_, MatType View_type, typename type_parent>
571 friend class MatViewDiagMat;
572 template <typename View_T, size_t View_N, size_t View_N_, MatType View_type, typename type_parent>
573 friend class MatViewDiagVec;
574 template <typename View_T, size_t View_N, size_t View_N_, MatType View_type, typename type_parent>
575 friend class MatViewDiagRowVec;
576 template <typename View_T, size_t View_N, size_t View_N_, MatType View_type, typename type_parent>
577 friend class MatViewOffDiag;
578 template <typename View_T, size_t View_n_rows, size_t View_n_cols, MatType View_type, typename type_parent>
579 friend class MatViewCol;
580 template <typename View_T, size_t View_n_rows, size_t View_n_cols, MatType View_type, typename type_parent>
581 friend class MatViewRow;
582 template <size_t first_col, size_t last_col, typename View_T, size_t View_n_rows, size_t View_n_cols,
583 MatType View_type, typename type_parent>
584 friend class MatViewCols;
585 template <size_t first_row, size_t last_row, typename View_T, size_t View_n_rows, size_t View_n_cols,
586 MatType View_type, typename type_parent>
587 friend class MatViewRows;
588 template <typename View_T_T, size_t T_n_rows, size_t T_n_cols, size_t T_n_slices, MatType T_type>
589 friend class Tensor;
590
591 public:
592 using element_type = T;
593 using value_type = T;
594
604 Mat() {
605 static_assert(n_rows != 0, "'rows' should be no smaller than 1.");
606 static_assert(n_cols != 0, "'n_cols' should be no smaller than 1.");
607 static_assert(type == MatType::NORMAL || n_rows == n_cols, "Square matrix 'rows' should be equal to 'n_cols'.");
608#ifdef FLAMES_MAT_PARTITION_COMPLETE
609 FLAMES_PRAGMA(ARRAY_PARTITION variable = _data type = complete)
610#else
611 FLAMES_PRAGMA(ARRAY_PARTITION variable = _data type = block factor = FLAMES_MAT_PARTITION_FACTOR)
612#endif
613 }
614
623 Mat(T val) {
624 static_assert(n_rows != 0, "'n_rows' should be no smaller than 1.");
625 static_assert(n_cols != 0, "'n_cols' should be no smaller than 1.");
626 static_assert(type == MatType::NORMAL || n_rows == n_cols, "Square matrix 'rows' should be equal to 'n_cols'.");
627#ifdef FLAMES_MAT_PARTITION_COMPLETE
628 FLAMES_PRAGMA(ARRAY_PARTITION variable = _data type = complete)
629#else
630 FLAMES_PRAGMA(ARRAY_PARTITION variable = _data type = block factor = FLAMES_MAT_PARTITION_FACTOR)
631#endif
632 setValue(val);
633 }
634
644 Mat(const Mat& mat) {
645 MAT_COPY:
646 for (size_t i = 0; i != size(); ++i) {
648 _data[i] = mat[i];
649 }
650#ifdef FLAMES_MAT_PARTITION_COMPLETE
651 FLAMES_PRAGMA(ARRAY_PARTITION variable = _data type = complete)
652#else
653 FLAMES_PRAGMA(ARRAY_PARTITION variable = _data type = block factor = FLAMES_MAT_PARTITION_FACTOR)
654#endif
655#ifdef FLAMES_PRINT_PER_MAT_COPY
656 std::cout << "Mat copy!" << std::endl;
657#endif
658 }
659
660 template <typename T2, size_t _rows, size_t _cols, MatType _type,
661 std::enable_if_t<!std::is_same<T, T2>::value && type == _type && n_rows == _rows && n_cols == _cols,
662 bool> = true>
664 MAT_COPY:
665 for (size_t i = 0; i != size(); ++i) {
667 _data[i] = mat[i];
668 }
669#ifdef FLAMES_MAT_PARTITION_COMPLETE
670 FLAMES_PRAGMA(ARRAY_PARTITION variable = _data type = complete)
671#else
672 FLAMES_PRAGMA(ARRAY_PARTITION variable = _data type = block factor = FLAMES_MAT_PARTITION_FACTOR)
673#endif
674#ifdef FLAMES_PRINT_PER_MAT_COPY
675 std::cout << "Mat copy!" << std::endl;
676#endif
677 }
678
679 template <typename T2, size_t _rows, size_t _cols, MatType _type,
680 std::enable_if_t<type != _type && n_rows == _rows && n_cols == _cols, bool> = true>
682 MAT_COPY:
683 for (size_t r = 0; r != n_rows; ++r) {
685 for (size_t c = 0; c != n_cols; ++c) {
686 FLAMES_PRAGMA(LOOP_FLATTEN)
687 _tryAssign(r, c, mat(r, c));
688 }
689 }
690#ifdef FLAMES_MAT_PARTITION_COMPLETE
691 FLAMES_PRAGMA(ARRAY_PARTITION variable = _data type = complete)
692#else
693 FLAMES_PRAGMA(ARRAY_PARTITION variable = _data type = block factor = FLAMES_MAT_PARTITION_FACTOR)
694#endif
695#ifdef FLAMES_PRINT_PER_MAT_COPY
696 std::cout << "Mat copy!" << std::endl;
697#endif
698 }
699
708 Mat(const std::vector<T>& vec) {
709 assert(vec.size() == size() && "Initialization vector size disagrees.");
710 MAT_COPY_FROM_STD_VEC:
711 for (size_t i = 0; i != size(); ++i) {
713 _data[i] = vec[i];
714 }
715#ifdef FLAMES_MAT_PARTITION_COMPLETE
716 FLAMES_PRAGMA(ARRAY_PARTITION variable = _data type = complete)
717#else
718 FLAMES_PRAGMA(ARRAY_PARTITION variable = _data type = block factor = FLAMES_MAT_PARTITION_FACTOR)
719#endif
720#ifdef FLAMES_PRINT_PER_MAT_COPY
721 std::cout << "Mat copy!" << std::endl;
722#endif
723 }
724
725 template <typename T2>
726 Mat(std::initializer_list<T2> list) {
727 auto list_size = list.size();
728 assert(list_size <= size() && "Initializer list size should not exceed size().");
729 MAT_COPY_FROM_INIT_LIST:
730 for (size_t i = 0; i != list_size; ++i) {
732 _data[i] = *(list.begin() + i);
733 }
734#ifdef FLAMES_MAT_PARTITION_COMPLETE
735 FLAMES_PRAGMA(ARRAY_PARTITION variable = _data type = complete)
736#else
737 FLAMES_PRAGMA(ARRAY_PARTITION variable = _data type = block factor = FLAMES_MAT_PARTITION_FACTOR)
738#endif
739#ifdef FLAMES_PRINT_PER_MAT_COPY
740 std::cout << "Mat copy!" << std::endl;
741#endif
742 }
743
744 Mat(Init init) {}
745
746 // public: // original private
747 public:
755 explicit Mat(const T* ptr, InitAfterwards opt = InitAfterwards::NONE) {
756 if (opt == InitAfterwards::NONE) {
757 MAT_COPY:
758 for (size_t i = 0; i != size(); ++i) {
760 _data[i] = ptr[i];
761 }
762 } else if (opt == InitAfterwards::OPP) {
763 MAT_COPY_OPP:
764 for (size_t i = 0; i != size(); ++i) {
766 _data[i] = -ptr[i];
767 }
768 } else if (opt == InitAfterwards::TR) {
770 this->t(tmp);
771 }
772#ifdef FLAMES_MAT_PARTITION_COMPLETE
773 FLAMES_PRAGMA(ARRAY_PARTITION variable = _data type = complete)
774#else
775 FLAMES_PRAGMA(ARRAY_PARTITION variable = _data type = block factor = FLAMES_MAT_PARTITION_FACTOR)
776#endif
777#ifdef FLAMES_PRINT_PER_MAT_COPY
778 std::cout << "Mat copy!" << std::endl;
779#endif
780 }
781
782 explicit Mat(T* const ptr, InitAfterwards opt = InitAfterwards::NONE) {
783 if (opt == InitAfterwards::NONE) {
784 MAT_COPY:
785 for (size_t i = 0; i != size(); ++i) {
787 _data[i] = ptr[i];
788 }
789 } else if (opt == InitAfterwards::OPP) {
790 MAT_COPY_OPP:
791 for (size_t i = 0; i != size(); ++i) {
793 _data[i] = -ptr[i];
794 }
795 } else if (opt == InitAfterwards::TR) {
797 this->t(tmp);
798 }
799#ifdef FLAMES_MAT_PARTITION_COMPLETE
800 FLAMES_PRAGMA(ARRAY_PARTITION variable = _data type = complete)
801#else
802 FLAMES_PRAGMA(ARRAY_PARTITION variable = _data type = block factor = FLAMES_MAT_PARTITION_FACTOR)
803#endif
804#ifdef FLAMES_PRINT_PER_MAT_COPY
805 std::cout << "Mat copy!" << std::endl;
806#endif
807 }
808
809 public:
816 // so far nothing to do
817 }
818
819 // template <typename... _unused, MatType _type = type,
820 // typename std::enable_if_t<_type == MatType::NORMAL, bool> = true>
821 // inline constexpr size_t size_const() noexcept {
822 // static_assert(sizeof...(_unused) == 0, "Do not specify template arguments for Mat::size()!");
823 // return n_rows * n_cols;
824 // }
825
832 inline static constexpr size_t size() noexcept {
833 return type == MatType::NORMAL ? n_rows * n_cols
834 : type == MatType::DIAGONAL ? n_rows
835 : type == MatType::SCALAR ? 1
836 : type == MatType::SUPPER ? (n_rows - 1) * n_rows / 2
837 : type == MatType::SLOWER ? (n_rows - 1) * n_rows / 2
838 : type == MatType::ASYM ? (n_rows - 1) * n_rows / 2
839 : (1 + n_rows) * n_rows / 2;
840 }
841
850 T operator[](size_t index) const {
851 FLAMES_PRAGMA(INLINE)
852 assert(index < size() && "Matrix index should be within range");
853 return _data[index];
854 }
855
864 T& operator[](size_t index) {
865 FLAMES_PRAGMA(INLINE)
866 assert(index < size() && "Matrix index should be within range");
867 return _data[index];
868 }
869
877 T operator()(size_t r, size_t c) const {
878 FLAMES_PRAGMA(INLINE)
879 assert(r < n_rows && "Matrix row index should be within range");
880 assert(c < n_cols && "Matrix col index should be within range");
881 if (type == MatType::NORMAL) {
882 return _data[r * n_cols + c];
883 } else if (type == MatType::DIAGONAL) {
884 if (r == c) return _data[r];
885 else return T(0);
886 } else if (type == MatType::SCALAR) {
887 if (r == c) return _data[0];
888 else return T(0);
889 } else if (type == MatType::UPPER) {
890 if (r <= c) return _data[(2 * n_cols + 1 - r) * r / 2 + c - r];
891 else return T(0);
892 } else if (type == MatType::LOWER) {
893 if (r >= c) return _data[(1 + r) * r / 2 + c];
894 else return T(0);
895 } else if (type == MatType::SUPPER) {
896 if (r < c) return _data[(2 * n_cols + 1 - r) * r / 2 + c - 1 - 2 * r];
897 else return T(0);
898 } else if (type == MatType::SLOWER) {
899 if (r > c) return _data[(1 + r) * r / 2 + c - r];
900 else return T(0);
901 } else if (type == MatType::SYM) {
902 if (r <= c) return _data[(2 * n_cols + 1 - r) * r / 2 + c - r];
903 else return _data[(2 * n_cols + 1 - c) * c / 2 + r - c];
904 } else if (type == MatType::ASYM) {
905 if (r < c) return _data[(2 * n_cols + 1 - r) * r / 2 + c - 1 - 2 * r];
906 else if (r > c) return -_data[(2 * n_cols + 1 - c) * c / 2 + r - 1 - 2 * c];
907 else return T(0);
908 } else {
909 // Normally it is impossible to reach here.
910 assert(!"Impossible! Unknown MatType!");
911 }
912 }
913
921 T& operator()(size_t r, size_t c) {
922 FLAMES_PRAGMA(INLINE)
923 assert(r < n_rows && "Matrix row index should be within range");
924 assert(c < n_cols && "Matrix col index should be within range");
925 if (type == MatType::NORMAL) {
926 return _data[r * n_cols + c];
927 } else if (type == MatType::DIAGONAL) {
928 if (r == c) return _data[r];
929 else assert(!"This element cannot be modified (DIAGONAL).");
930 } else if (type == MatType::SCALAR) {
931 assert(!"This element cannot be modified (SCALAR).");
932 } else if (type == MatType::UPPER) {
933 if (r <= c) return _data[(2 * n_cols + 1 - r) * r / 2 + c - r];
934 else assert(!"This element cannot be modified (UPPER).");
935 } else if (type == MatType::LOWER) {
936 if (r >= c) return _data[(1 + r) * r / 2 + c];
937 else assert(!"This element cannot be modified (LOWER).");
938 } else if (type == MatType::SUPPER) {
939 if (r < c) return _data[(2 * n_cols + 1 - r) * r / 2 + c - 1 - 2 * r];
940 else assert(!"This element cannot be modified (SUPPER).");
941 } else if (type == MatType::SLOWER) {
942 if (r > c) return _data[(1 + r) * r / 2 + c - r];
943 else assert(!"This element cannot be modified (SLOWER).");
944 } else if (type == MatType::SYM) {
945 if (r <= c) return _data[(2 * n_cols + 1 - r) * r / 2 + c - r];
946 else return _data[(2 * n_cols + 1 - c) * c / 2 + r - c];
947 } else if (type == MatType::ASYM) {
948 if (r < c) return _data[(2 * n_cols + 1 - r) * r / 2 + c - 1 - 2 * r];
949 else if (r > c) return _data[(2 * n_cols + 1 - c) * c / 2 + r - 1 - 2 * c];
950
951 // ATTENTION This part needs to be perfected , missing a minus sign.
952 // Because a minus sign will result in a error about reference.
953
954 else assert(!"This element cannot be modified (ASYM).");
955 } else {
956 // Normally it is impossible to reach here.
957 assert(!"Impossible! Unknown MatType!");
958 }
959 // Just to make the compiler happy.
960 return _data[0];
961 }
962
968 void setValue(T val) {
969 for (size_t i = 0; i != size(); ++i) {
971 _data[i] = val;
972 }
973 }
974
979 void setZero() { setValue(static_cast<T>(0)); }
980
981 bool read(const std::string& file_name) {
982#ifndef __SYNTHESIS__
983 std::ifstream f(file_name);
984 if (f.is_open()) {
985 size_t in_rows, in_cols;
986 f >> in_rows >> in_cols;
987 if (n_rows != in_rows || n_cols != in_cols) return false; // dimension does not match
988 std::string complex_real, mat_type;
989 f >> complex_real >> mat_type;
990 if (type == MatType::NORMAL && mat_type != "normal") return false;
991 if (type == MatType::DIAGONAL && mat_type != "diagonal") return false;
992 if (type == MatType::SCALAR && mat_type != "scalar") return false;
993 if (type == MatType::UPPER && mat_type != "upper") return false;
994 if (type == MatType::LOWER && mat_type != "lower") return false;
995 if (type == MatType::SUPPER && mat_type != "supper") return false;
996 if (type == MatType::SYM && mat_type != "sym") return false;
997 if (type == MatType::ASYM && mat_type != "asym") return false;
998 if (complex_real == "complex") {
999 // std::string real_part, imag_part;
1000 // for (size_t i = 0; i != size(); ++i) {
1001 // std::getline(f, real_part, ',');
1002 // std::getline(f, imag_part, ',');
1003 // _data[i].real(std::stod(real_part));
1004 // _data[i].imag(std::stod(imag_part));
1005 // }
1006 assert(!"Read from a complex matrix is not currently supported.");
1007 return false;
1008 } else {
1009 std::string buf;
1010 for (size_t i = 0; i != size(); ++i) {
1011 std::getline(f, buf, ',');
1012 _data[i] = std::stod(buf);
1013 }
1014 return true;
1015 }
1016 } else {
1017 return false;
1018 }
1019#else
1020 return true;
1021#endif
1022 }
1023
1040 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
1041 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
1042 typename T2>
1043 Mat& add(const M1<T1, n_rows, n_cols, type, _unused1...>& mat_L,
1044 const M2<T2, n_rows, n_cols, type, _unused2...>& mat_R) {
1045 MAT_PLUS_MAT_SAME:
1046 for (size_t i = 0; i != size(); ++i) {
1048 this->_data[i] = mat_L[i] + mat_R[i];
1049 }
1050 return *this;
1051 }
1052
1071 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
1072 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
1073 typename T2, MatType type1, MatType type2,
1074 std::enable_if_t<type == MatType::NORMAL && (type1 != MatType::NORMAL || type2 != MatType::NORMAL),
1075 bool> = true>
1076 Mat& add(const M1<T1, n_rows, n_cols, type1, _unused1...>& mat_L,
1077 const M2<T2, n_rows, n_cols, type2, _unused2...>& mat_R) {
1078 MAT_PLUS_MAT_NORMAL:
1079 for (size_t i = 0; i != n_rows; ++i) {
1081 for (size_t j = 0; j != n_cols; ++j) {
1082 FLAMES_PRAGMA(LOOP_FLATTEN)
1083 this->_data[i * n_cols + j] = mat_L(i, j) + mat_R(i, j);
1084 }
1085 }
1086 return *this;
1087 }
1088
1107 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
1108 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
1109 typename T2, MatType type1, MatType type2,
1110 std::enable_if_t<type == MatType::DIAGONAL && (type1 != MatType::DIAGONAL || type2 != MatType::DIAGONAL),
1111 bool> = true>
1112 Mat& add(const M1<T1, n_rows, n_cols, type1, _unused1...>& mat_L,
1113 const M2<T2, n_rows, n_cols, type2, _unused2...>& mat_R) {
1114 MAT_PLUS_MAT_LOWER:
1115 for (size_t i = 0; i != n_rows; ++i) {
1117 this->_data[i] = mat_L(i, i) + mat_R(i, i);
1118 }
1119 return *this;
1120 }
1121
1138 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
1139 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
1140 typename T2, MatType type1, MatType type2,
1141 std::enable_if_t<type == MatType::SCALAR && (type1 != MatType::SCALAR || type2 != MatType::SCALAR),
1142 bool> = true>
1143 Mat& add(const M1<T1, n_rows, n_cols, type1, _unused1...>& mat_L,
1144 const M2<T2, n_rows, n_cols, type2, _unused2...>& mat_R) {
1145 MAT_PLUS_MAT_SCALAR:
1146 this->_data[0] = mat_L(0, 0) + mat_R(0, 0);
1147 return *this;
1148 }
1149
1168 template <
1169 template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
1170 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1, typename T2,
1171 MatType type1, MatType type2,
1172 std::enable_if_t<type == MatType::UPPER && (type1 != MatType::UPPER || type2 != MatType::UPPER), bool> = true>
1173 Mat& add(const M1<T1, n_rows, n_cols, type1, _unused1...>& mat_L,
1174 const M2<T2, n_rows, n_cols, type2, _unused2...>& mat_R) {
1175 MAT_PLUS_MAT_UPPER:
1176 for (size_t i = 0; i != n_rows; ++i) {
1178 for (size_t j = i; j != n_cols; ++j) {
1179 FLAMES_PRAGMA(LOOP_FLATTEN)
1180 this->_data[(2 * n_cols + 1 - i) * i / 2 + j - i] = mat_L(i, j) + mat_R(i, j);
1181 }
1182 }
1183 return *this;
1184 }
1185
1204 template <
1205 template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
1206 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1, typename T2,
1207 MatType type1, MatType type2,
1208 std::enable_if_t<type == MatType::LOWER && (type1 != MatType::LOWER || type2 != MatType::LOWER), bool> = true>
1209 Mat& add(const M1<T1, n_rows, n_cols, type1, _unused1...>& mat_L,
1210 const M2<T2, n_rows, n_cols, type2, _unused2...>& mat_R) {
1211 MAT_PLUS_MAT_LOWER:
1212 for (size_t i = 0; i != n_rows; ++i) {
1214 for (size_t j = i; j != n_cols; ++j) {
1215 FLAMES_PRAGMA(LOOP_FLATTEN)
1216 this->_data[(1 + i) * i / 2 + j] = mat_L(i, j) + mat_R(i, j);
1217 }
1218 }
1219 return *this;
1220 }
1221
1240 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
1241 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
1242 typename T2, MatType type1, MatType type2,
1243 std::enable_if_t<type == MatType::SUPPER && (type1 != MatType::SUPPER || type2 != MatType::SUPPER),
1244 bool> = true>
1245 Mat& add(const M1<T1, n_rows, n_cols, type1, _unused1...>& mat_L,
1246 const M2<T2, n_rows, n_cols, type2, _unused2...>& mat_R) {
1247 MAT_PLUS_MAT_SUPPER:
1248 for (size_t i = 0; i != n_rows - 1; ++i) {
1250 for (size_t j = i + 1; j != n_cols; ++j) {
1251 FLAMES_PRAGMA(LOOP_FLATTEN)
1252 this->_data[(2 * n_cols + 1 - i) * i / 2 + j - 2 * i - 1] = mat_L(i, j) + mat_R(i, j);
1253 }
1254 }
1255 return *this;
1256 }
1257
1276 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
1277 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
1278 typename T2, MatType type1, MatType type2,
1279 std::enable_if_t<type == MatType::SLOWER && (type1 != MatType::SLOWER || type2 != MatType::SLOWER),
1280 bool> = true>
1281 Mat& add(const M1<T1, n_rows, n_cols, type1, _unused1...>& mat_L,
1282 const M2<T2, n_rows, n_cols, type2, _unused2...>& mat_R) {
1283 MAT_PLUS_MAT_SLOWER:
1284 for (size_t i = 1; i != n_rows; ++i) {
1286 for (size_t j = 0; j != n_cols - 1; ++j) {
1287 FLAMES_PRAGMA(LOOP_FLATTEN)
1288 this->_data[(1 + i) * i / 2 + j - i] = mat_L(i, j) + mat_R(i, j);
1289 }
1290 }
1291 return *this;
1292 }
1293
1312 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
1313 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
1314 typename T2, MatType type1, MatType type2,
1315 std::enable_if_t<type == MatType::SYM && (type1 != MatType::SYM || type2 != MatType::SYM), bool> = true>
1316 Mat& add(const M1<T1, n_rows, n_cols, type1, _unused1...>& mat_L,
1317 const M2<T2, n_rows, n_cols, type2, _unused2...>& mat_R) {
1318 MAT_PLUS_MAT_SYM:
1319 for (size_t i = 0; i != n_rows; ++i) {
1321 for (size_t j = i; j != n_cols; ++j) {
1322 FLAMES_PRAGMA(LOOP_FLATTEN)
1323 this->_data[(2 * n_cols + 1 - i) * i / 2 + j - i] = mat_L(i, j) + mat_R(i, j);
1324 }
1325 }
1326 return *this;
1327 }
1328
1347 template <
1348 template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
1349 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1, typename T2,
1350 MatType type1, MatType type2,
1351 std::enable_if_t<type == MatType::ASYM && (type1 != MatType::ASYM || type2 != MatType::ASYM), bool> = true>
1352 Mat& add(const M1<T1, n_rows, n_cols, type1, _unused1...>& mat_L,
1353 const M2<T2, n_rows, n_cols, type2, _unused2...>& mat_R) {
1354 MAT_PLUS_MAT_ASYM:
1355 for (size_t i = 0; i != n_rows; ++i) {
1357 for (size_t j = i + 1; j != n_cols; ++j) {
1358 FLAMES_PRAGMA(LOOP_FLATTEN)
1359 this->_data[(2 * n_cols + 1 - i) * i / 2 + j - i * 2 - 1] = mat_L(i, j) + mat_R(i, j);
1360 }
1361 }
1362 return *this;
1363 }
1364
1375 template <template <class, size_t, size_t, MatType, class...> typename M, typename... _unused, typename T2,
1376 MatType type2>
1378 FLAMES_PRAGMA(INLINE)
1379 return this->add(*this, mat_R);
1380 }
1381
1398 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
1399 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
1400 typename T2>
1401 Mat& sub(const M1<T1, n_rows, n_cols, type, _unused1...>& mat_L,
1402 const M2<T2, n_rows, n_cols, type, _unused2...>& mat_R) {
1403 MAT_MINUS_MAT_SAME:
1404 for (size_t i = 0; i != size(); ++i) {
1406 this->_data[i] = mat_L[i] - mat_R[i];
1407 }
1408 return *this;
1409 }
1410
1429 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
1430 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
1431 typename T2, MatType type1, MatType type2,
1432 std::enable_if_t<type == MatType::NORMAL && (type1 != MatType::NORMAL || type2 != MatType::NORMAL),
1433 bool> = true>
1434 Mat& sub(const M1<T1, n_rows, n_cols, type1, _unused1...>& mat_L,
1435 const M2<T2, n_rows, n_cols, type2, _unused2...>& mat_R) {
1436 MAT_MINUS_MAT_NORMAL:
1437 for (size_t i = 0; i != n_rows; ++i) {
1439 for (size_t j = 0; j != n_cols; ++j) {
1440 FLAMES_PRAGMA(LOOP_FLATTEN)
1441 this->_data[i * n_cols + j] = mat_L(i, j) - mat_R(i, j);
1442 }
1443 }
1444 return *this;
1445 }
1446
1465 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
1466 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
1467 typename T2, MatType type1, MatType type2,
1468 std::enable_if_t<type == MatType::DIAGONAL && (type1 != MatType::DIAGONAL || type2 != MatType::DIAGONAL),
1469 bool> = true>
1470 Mat& sub(const M1<T1, n_rows, n_cols, type1, _unused1...>& mat_L,
1471 const M2<T2, n_rows, n_cols, type2, _unused2...>& mat_R) {
1472 MAT_MINUS_MAT_DIAGONAL:
1473 for (size_t i = 0; i != n_rows; ++i) {
1475 this->_data[i] = mat_L(i, i) - mat_R(i, i);
1476 }
1477 return *this;
1478 }
1497 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
1498 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
1499 typename T2, MatType type1, MatType type2,
1500 std::enable_if_t<type == MatType::SCALAR && (type1 != MatType::SCALAR || type2 != MatType::SCALAR),
1501 bool> = true>
1502 Mat& sub(const M1<T1, n_rows, n_cols, type1, _unused1...>& mat_L,
1503 const M2<T2, n_rows, n_cols, type2, _unused2...>& mat_R) {
1504 MAT_MINUS_MAT_SCALAR:
1505 this->_data[0] = mat_L(0, 0) - mat_R(0, 0);
1506 return *this;
1507 }
1508
1527 template <
1528 template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
1529 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1, typename T2,
1530 MatType type1, MatType type2,
1531 std::enable_if_t<type == MatType::UPPER && (type1 != MatType::UPPER || type2 != MatType::UPPER), bool> = true>
1532 Mat& sub(const M1<T1, n_rows, n_cols, type1, _unused1...>& mat_L,
1533 const M2<T2, n_rows, n_cols, type2, _unused2...>& mat_R) {
1534 MAT_MINUS_MAT_UPPER:
1535 for (size_t i = 0; i != n_rows; ++i) {
1537 for (size_t j = i; j != n_cols; ++j) {
1538 FLAMES_PRAGMA(LOOP_FLATTEN)
1539 this->_data[(2 * n_cols + 1 - i) * i / 2 + j - i] = mat_L(i, j) - mat_R(i, j);
1540 }
1541 }
1542 return *this;
1543 }
1544
1563 template <
1564 template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
1565 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1, typename T2,
1566 MatType type1, MatType type2,
1567 std::enable_if_t<type == MatType::LOWER && (type1 != MatType::LOWER || type2 != MatType::LOWER), bool> = true>
1568 Mat& sub(const M1<T1, n_rows, n_cols, type1, _unused1...>& mat_L,
1569 const M2<T2, n_rows, n_cols, type2, _unused2...>& mat_R) {
1570 MAT_MINUS_MAT_LOWER:
1571 for (size_t i = 0; i != n_rows; ++i) {
1573 for (size_t j = i; j != n_cols; ++j) {
1574 FLAMES_PRAGMA(LOOP_FLATTEN)
1575 this->_data[(1 + i) * i / 2 + j] = mat_L(i, j) - mat_R(i, j);
1576 }
1577 }
1578 return *this;
1579 }
1580
1599 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
1600 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
1601 typename T2, MatType type1, MatType type2,
1602 std::enable_if_t<type == MatType::SUPPER && (type1 != MatType::SUPPER || type2 != MatType::SUPPER),
1603 bool> = true>
1604 Mat& sub(const M1<T1, n_rows, n_cols, type1, _unused1...>& mat_L,
1605 const M2<T2, n_rows, n_cols, type2, _unused2...>& mat_R) {
1606 MAT_MINUS_MAT_SUPPER:
1607 for (size_t i = 0; i != n_rows - 1; ++i) {
1609 for (size_t j = i + 1; j != n_cols; ++j) {
1610 FLAMES_PRAGMA(LOOP_FLATTEN)
1611 this->_data[(2 * n_cols + 1 - i) * i / 2 + j - 2 * i - 1] = mat_L(i, j) - mat_R(i, j);
1612 }
1613 }
1614 return *this;
1615 }
1616
1635 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
1636 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
1637 typename T2, MatType type1, MatType type2,
1638 std::enable_if_t<type == MatType::SLOWER && (type1 != MatType::SLOWER || type2 != MatType::SLOWER),
1639 bool> = true>
1640 Mat& sub(const M1<T1, n_rows, n_cols, type1, _unused1...>& mat_L,
1641 const M2<T2, n_rows, n_cols, type2, _unused2...>& mat_R) {
1642 MAT_MINUS_MAT_SLOWER:
1643 for (size_t i = 1; i != n_rows; ++i) {
1645 for (size_t j = 0; j != n_cols - 1; ++j) {
1646 FLAMES_PRAGMA(LOOP_FLATTEN)
1647 this->_data[(1 + i) * i / 2 + j - i] = mat_L(i, j) - mat_R(i, j);
1648 }
1649 }
1650 return *this;
1651 }
1652
1671 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
1672 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
1673 typename T2, MatType type1, MatType type2,
1674 std::enable_if_t<type == MatType::SYM && (type1 != MatType::SYM || type2 != MatType::SYM), bool> = true>
1675 Mat& sub(const M1<T1, n_rows, n_cols, type1, _unused1...>& mat_L,
1676 const M2<T2, n_rows, n_cols, type2, _unused2...>& mat_R) {
1677 MAT_MINUS_MAT_SYM:
1678 for (size_t i = 0; i != n_rows; ++i) {
1680 for (size_t j = i; j != n_cols; ++j) {
1681 FLAMES_PRAGMA(LOOP_FLATTEN)
1682 this->_data[(2 * n_cols + 1 - i) * i / 2 + j - i] = mat_L(i, j) - mat_R(i, j);
1683 }
1684 }
1685 return *this;
1686 }
1687
1706 template <
1707 template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
1708 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1, typename T2,
1709 MatType type1, MatType type2,
1710 std::enable_if_t<type == MatType::ASYM && (type1 != MatType::ASYM || type2 != MatType::ASYM), bool> = true>
1711 Mat& sub(const M1<T1, n_rows, n_cols, type1, _unused1...>& mat_L,
1712 const M2<T2, n_rows, n_cols, type2, _unused2...>& mat_R) {
1713 MAT_MINUS_MAT_ASYM:
1714 for (size_t i = 0; i != n_rows; ++i) {
1716 for (size_t j = i + 1; j != n_cols; ++j) {
1717 FLAMES_PRAGMA(LOOP_FLATTEN)
1718 this->_data[(2 * n_cols + 1 - i) * i / 2 + j - i * 2 - 1] = mat_L(i, j) - mat_R(i, j);
1719 }
1720 }
1721 return *this;
1722 }
1723
1737 template <template <class, size_t, size_t, MatType, class...> typename M, typename... _unused, typename T2,
1738 MatType type2>
1740 FLAMES_PRAGMA(INLINE)
1741 // return this->sub(*this, mat_R);
1742 for (size_t i = 0; i != size(); ++i) {
1744 _data[i] -= mat_R[i];
1745 }
1746 return *this;
1747 }
1748
1765 template <
1766 template <class, size_t, size_t, MatType, class...> typename M, typename... _unused, typename ScalarT,
1767 typename T2,
1768 std::enable_if_t<std::is_arithmetic<std::remove_cv_t<std::remove_reference_t<ScalarT>>>::value, bool> = true>
1770 MAT_SCALAR_TIMES:
1771 for (size_t i = 0; i != size(); ++i) {
1773 _data[i] = mat[i] * s;
1774 }
1775 return *this;
1776 }
1777
1793 template <
1794 template <class, size_t, size_t, MatType, class...> typename M, typename... _unused, typename ScalarT,
1795 typename T2,
1796 std::enable_if_t<std::is_arithmetic<std::remove_cv_t<std::remove_reference_t<ScalarT>>>::value, bool> = true>
1797 Mat& mul(const M<T2, n_rows, n_cols, type, _unused...>& mat, std::complex<ScalarT> s) {
1798 MAT_SCALAR_TIMES:
1799 for (size_t i = 0; i != size(); ++i) {
1801 _data[i] = mat[i] * s;
1802 }
1803 return *this;
1804 }
1805
1820 template <template <class, size_t, size_t, MatType, class...> typename M, typename... _unused, int AP_W,
1821 typename T2>
1822 Mat& mul(const M<T2, n_rows, n_cols, type, _unused...>& mat, ap_int<AP_W> s) {
1823 MAT_SCALAR_TIMES:
1824 for (size_t i = 0; i != size(); ++i) {
1826 _data[i] = mat[i] * s;
1827 }
1828 return *this;
1829 }
1830
1849 template <template <class, size_t, size_t, MatType, class...> typename M, typename... _unused, int AP_W, int AP_I,
1850 ap_q_mode AP_Q, ap_o_mode AP_O, int AP_N, typename T2>
1851 Mat& mul(const M<T2, n_rows, n_cols, type, _unused...>& mat, ap_fixed<AP_W, AP_I, AP_Q, AP_O, AP_N> s) {
1852 MAT_SCALAR_TIMES:
1853 for (size_t i = 0; i != size(); ++i) {
1855 _data[i] = mat[i] * s;
1856 }
1857 return *this;
1858 }
1859
1871 template <
1872 typename ScalarT,
1873 std::enable_if_t<std::is_arithmetic<std::remove_cv_t<std::remove_reference_t<ScalarT>>>::value, bool> = true>
1874 Mat& mul(ScalarT s) {
1875 MAT_SCALAR_TIMES_SELF:
1876 for (size_t i = 0; i != size(); ++i) {
1878 _data[i] *= s;
1879 }
1880 return *this;
1881 }
1882
1893 template <
1894 typename ScalarT,
1895 std::enable_if_t<std::is_arithmetic<std::remove_cv_t<std::remove_reference_t<ScalarT>>>::value, bool> = true>
1896 Mat& mul(std::complex<ScalarT> s) {
1897 MAT_SCALAR_TIMES_SELF:
1898 for (size_t i = 0; i != size(); ++i) {
1900 _data[i] *= s;
1901 }
1902 return *this;
1903 }
1904
1915 template <int AP_W>
1916 Mat& mul(ap_int<AP_W> s) {
1917 MAT_SCALAR_TIMES_SELF:
1918 for (size_t i = 0; i != size(); ++i) {
1920 _data[i] *= s;
1921 }
1922 return *this;
1923 }
1924
1939 template <int AP_W, int AP_I, ap_q_mode AP_Q, ap_o_mode AP_O, int AP_N>
1940 Mat& mul(ap_fixed<AP_W, AP_I, AP_Q, AP_O, AP_N> s) {
1941 MAT_SCALAR_TIMES_SELF:
1942 for (size_t i = 0; i != size(); ++i) {
1944 _data[i] *= s;
1945 }
1946 return *this;
1947 }
1948
1971 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
1972 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
1973 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
1974 std::enable_if_t<(!(std::is_same<T1, bool>::value) && !(std::is_same<T2, bool>::value)) &&
1975 ((type1 == MatType::NORMAL && type2 == MatType::NORMAL) ||
1976 (type1 == MatType::NORMAL && type2 == MatType::SYM) ||
1977 (type1 == MatType::SYM && type2 == MatType::NORMAL) ||
1978 (type1 == MatType::SYM && type2 == MatType::SYM)),
1979 bool> = true>
1980 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
1981 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
1982 FLAMES_PRAGMA(INLINE off)
1983 static_assert(n_rows == rows_, "Matrix dimension should meet.");
1984 static_assert(n_cols == cols_, "Matrix dimension should meet.");
1985 GEMM:
1986 for (size_t i = 0; i != comm; ++i) {
1987 GEMM_r:
1988 for (size_t r = 0; r != n_rows; ++r) {
1990 // FLAMES_PRAGMA(DEPENDENCE variable=mat_L inter false)
1991 // FLAMES_PRAGMA(DEPENDENCE variable=mat_L intra false)
1992 // FLAMES_PRAGMA(DEPENDENCE variable=mat_R inter false)
1993 // FLAMES_PRAGMA(DEPENDENCE variable=mat_R intra false
1994 GEMM_c:
1995 for (size_t c = 0; c != n_cols; ++c) {
1996 FLAMES_PRAGMA(LOOP_FLATTEN)
1997 if (i == 0) (*this)(r, c) = T(0); // initialize
1998 (*this)(r, c) += mat_L(r, i) * mat_R(i, c);
1999 }
2000 }
2001 }
2002 return *this;
2003 }
2004
2026 template <
2027 template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
2028 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1, typename T2,
2029 MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
2030 std::enable_if_t<((type1 == MatType::NORMAL || type1 == MatType::SYM) && type2 == MatType::ASYM), bool> = true>
2031 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
2032 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
2033 FLAMES_PRAGMA(INLINE off)
2034 static_assert(n_rows == rows_, "Matrix dimension should meet.");
2035 static_assert(n_cols == cols_, "Matrix dimension should meet.");
2036 MAT_NORAML_OR_SYM_TIMES_MAT_ASYM:
2037 for (size_t i = 0; i != comm; ++i) {
2038 GEMM_r:
2039 for (size_t r = 0; r != n_rows; ++r) {
2041 GEMM_c:
2042 for (size_t c = 0; c != n_cols; ++c) {
2043 FLAMES_PRAGMA(LOOP_FLATTEN)
2044 if (i == 0) (*this)(r, c) = T(0); // initialize
2045 if (i != c) (*this)(r, c) += mat_L(r, i) * mat_R(i, c);
2046 }
2047 }
2048 }
2049 return *this;
2050 }
2051
2073 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
2074 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
2075 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
2076 std::enable_if_t<((type1 == MatType::NORMAL || type1 == MatType::SYM) && type2 == MatType::DIAGONAL),
2077 bool> = true>
2078 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
2079 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
2080 static_assert(n_rows == rows_, "Matrix dimension should meet.");
2081 static_assert(n_cols == cols_, "Matrix dimension should meet.");
2082 MAT_NORAML_OR_SYM_TIMES_DIAG:
2083 for (size_t i = 0; i != n_rows; ++i) {
2085 for (size_t j = 0; j != n_cols; ++j) {
2086 FLAMES_PRAGMA(LOOP_FLATTEN)
2087 (*this)(i, j) = mat_L(i, j) * mat_R[j];
2088 }
2089 }
2090 return *this;
2091 }
2092
2114 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
2115 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
2116 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
2117 std::enable_if_t<((type1 == MatType::NORMAL || type1 == MatType::SYM) && type2 == MatType::SCALAR),
2118 bool> = true>
2119 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
2120 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
2121 static_assert(n_rows == rows_, "Matrix dimension should meet.");
2122 static_assert(n_cols == cols_, "Matrix dimension should meet.");
2123 MAT_NORAML_OR_MAT_SYM_TIMES_SCAL:
2124 for (size_t i = 0; i != n_rows; ++i) {
2126 for (size_t j = 0; j != n_rows; ++j) {
2127 FLAMES_PRAGMA(LOOP_FLATTEN)
2128 (*this)(i, j) = mat_L(i, j) * mat_R[0];
2129 }
2130 }
2131 return *this;
2132 }
2133
2155 template <
2156 template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
2157 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1, typename T2,
2158 MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
2159 std::enable_if_t<((type1 == MatType::NORMAL || type1 == MatType::SYM) && type2 == MatType::UPPER), bool> = true>
2160 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
2161 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
2162 static_assert(n_rows == rows_, "Matrix dimension should meet.");
2163 static_assert(n_cols == cols_, "Matrix dimension should meet.");
2164 static const size_t r[288] = {
2165 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2166 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2167 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2168 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
2169 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
2170 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
2171 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
2172 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
2173 };
2174 static const size_t i[288] = {
2175 0, 0, 1, 0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 7,
2176 0, 0, 1, 0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 7,
2177 0, 0, 1, 0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 7,
2178 0, 0, 1, 0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 7,
2179 0, 0, 1, 0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 7,
2180 0, 0, 1, 0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 7,
2181 0, 0, 1, 0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 7,
2182 0, 0, 1, 0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 7
2183 };
2184 static const size_t c[288] = {
2185 0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7,
2186 0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7,
2187 0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7,
2188 0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7,
2189 0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7,
2190 0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7,
2191 0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7,
2192 0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7
2193 };
2194 MAT_NORAML_OR_MAT_SYM_TIMES_UPPER:
2195 for (size_t n = 0; n != n_rows * n_rows * (n_rows + 1) / 2; n++) {
2197 if (i[n] == 0) (*this)(r[n], c[n]) = 0; // initialize
2198 (*this)(r[n], c[n]) += mat_L(r[n], i[n]) * mat_R(i[n], c[n]);
2199 }
2200 return *this;
2201 }
2202
2224 template <
2225 template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
2226 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1, typename T2,
2227 MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
2228 std::enable_if_t<((type1 == MatType::NORMAL || type1 == MatType::SYM) && type2 == MatType::LOWER), bool> = true>
2229 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
2230 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
2231 static_assert(n_rows == rows_, "Matrix dimension should meet.");
2232 static_assert(n_cols == cols_, "Matrix dimension should meet.");
2233 static const size_t r[288] = {
2234 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2235 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2236 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2237 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
2238 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
2239 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
2240 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
2241 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
2242 };
2243 static const size_t i[288] = {
2244 7, 6, 7, 5, 6, 7, 4, 5, 6, 7, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7,
2245 7, 6, 7, 5, 6, 7, 4, 5, 6, 7, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7,
2246 7, 6, 7, 5, 6, 7, 4, 5, 6, 7, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7,
2247 7, 6, 7, 5, 6, 7, 4, 5, 6, 7, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7,
2248 7, 6, 7, 5, 6, 7, 4, 5, 6, 7, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7,
2249 7, 6, 7, 5, 6, 7, 4, 5, 6, 7, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7,
2250 7, 6, 7, 5, 6, 7, 4, 5, 6, 7, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7,
2251 7, 6, 7, 5, 6, 7, 4, 5, 6, 7, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7
2252 };
2253 static const size_t c[288] = {
2254 7, 6, 6, 5, 5, 5, 4, 4, 4, 4, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
2255 7, 6, 6, 5, 5, 5, 4, 4, 4, 4, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
2256 7, 6, 6, 5, 5, 5, 4, 4, 4, 4, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
2257 7, 6, 6, 5, 5, 5, 4, 4, 4, 4, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
2258 7, 6, 6, 5, 5, 5, 4, 4, 4, 4, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
2259 7, 6, 6, 5, 5, 5, 4, 4, 4, 4, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
2260 7, 6, 6, 5, 5, 5, 4, 4, 4, 4, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
2261 7, 6, 6, 5, 5, 5, 4, 4, 4, 4, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0
2262 };
2263 MAT_NORAML_OR_MAT_SYM_TIMES_LOWER:
2264 for (size_t n = 0; n != n_rows * n_rows * (n_rows + 1) / 2; n++) {
2266 if (i[n] == c[n]) (*this)(r[n], c[n]) = 0; // initialize
2267 (*this)(r[n], c[n]) += mat_L(r[n], i[n]) * mat_R(i[n], c[n]);
2268 }
2269 return *this;
2270 }
2271
2293 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
2294 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
2295 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
2296 std::enable_if_t<((type1 == MatType::NORMAL || type1 == MatType::SYM) && type2 == MatType::SUPPER),
2297 bool> = true>
2298 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
2299 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
2300 static_assert(n_rows == rows_, "Matrix dimension should meet.");
2301 static_assert(n_cols == cols_, "Matrix dimension should meet.");
2302 static const size_t r[224] = {
2303 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
2304 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2,
2305 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
2306 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
2307 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
2308 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
2309 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
2310 };
2311 static const size_t i[224] = {
2312 0, 0, 1, 0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6, 0, 0, 1, 0,
2313 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6, 0, 0, 1, 0, 1, 2, 0, 1,
2314 2, 3, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6, 0, 0, 1, 0, 1, 2, 0, 1, 2, 3, 0, 1,
2315 2, 3, 4, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6, 0, 0, 1, 0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4, 0,
2316 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6, 0, 0, 1, 0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4,
2317 5, 0, 1, 2, 3, 4, 5, 6, 0, 0, 1, 0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 0, 1, 2,
2318 3, 4, 5, 6, 0, 0, 1, 0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6,
2319 };
2320 static const size_t c[224] = {
2321 1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 1, 2, 2, 3,
2322 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 1, 2, 2, 3, 3, 3, 4, 4,
2323 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5,
2324 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6,
2325 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6,
2326 6, 7, 7, 7, 7, 7, 7, 7, 1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7,
2327 7, 7, 7, 7, 1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7,
2328 };
2329 MAT_NORAML_OR_MAT_SYM_TIMES_SUPPER:
2330 for (size_t n = 0; n != n_rows * n_rows * (n_rows - 1) / 2; n++) {
2332 if (i[n] == 0) (*this)(r[n], c[n]) = 0; // initialize
2333 (*this)(r[n], c[n]) += mat_L(r[n], i[n]) * mat_R(i[n], c[n]);
2334 }
2335 for (size_t i = 0; i != n_rows; i++) { (*this)(i, 0) = 0; }
2336 return *this;
2337 }
2338
2360 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
2361 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
2362 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
2363 std::enable_if_t<((type1 == MatType::NORMAL || type1 == MatType::SYM) && type2 == MatType::SLOWER),
2364 bool> = true>
2365 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
2366 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
2367 static_assert(n_rows == rows_, "Matrix dimension should meet.");
2368 static_assert(n_cols == cols_, "Matrix dimension should meet.");
2369 static const size_t r[224] = {
2370 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
2371 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2,
2372 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
2373 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
2374 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
2375 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
2376 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
2377 };
2378 static const size_t i[224] = {
2379 7, 6, 7, 5, 6, 7, 4, 5, 6, 7, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 7, 6, 7, 5,
2380 6, 7, 4, 5, 6, 7, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 7, 6, 7, 5, 6, 7, 4, 5,
2381 6, 7, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 7, 6, 7, 5, 6, 7, 4, 5, 6, 7, 3, 4,
2382 5, 6, 7, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 7, 6, 7, 5, 6, 7, 4, 5, 6, 7, 3, 4, 5, 6, 7, 2,
2383 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 7, 6, 7, 5, 6, 7, 4, 5, 6, 7, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6,
2384 7, 1, 2, 3, 4, 5, 6, 7, 7, 6, 7, 5, 6, 7, 4, 5, 6, 7, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 1, 2, 3,
2385 4, 5, 6, 7, 7, 6, 7, 5, 6, 7, 4, 5, 6, 7, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7,
2386 };
2387 static const size_t c[224] = {
2388 6, 5, 5, 4, 4, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 6, 5, 5, 4,
2389 4, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 6, 5, 5, 4, 4, 4, 3, 3,
2390 3, 3, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 6, 5, 5, 4, 4, 4, 3, 3, 3, 3, 2, 2,
2391 2, 2, 2, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 6, 5, 5, 4, 4, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 1,
2392 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 6, 5, 5, 4, 4, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1,
2393 1, 0, 0, 0, 0, 0, 0, 0, 6, 5, 5, 4, 4, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 0, 0, 0,
2394 0, 0, 0, 0, 6, 5, 5, 4, 4, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
2395 };
2396 MAT_NORAML_OR_MAT_SYM_TIMES_SLOWER:
2397 for (size_t n = 0; n != n_rows * n_rows * (n_rows - 1) / 2; n++) {
2399 if (i[n] == c[n] + 1) (*this)(r[n], c[n]) = 0; // initialize
2400 (*this)(r[n], c[n]) += mat_L(r[n], i[n]) * mat_R(i[n], c[n]);
2401 }
2402 for (size_t i = 0; i != n_rows; i++) { (*this)(i, n_rows - 1) = 0; }
2403 return *this;
2404 }
2426 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
2427 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
2428 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
2429 std::enable_if_t<(type1 == MatType::DIAGONAL && type2 == MatType::DIAGONAL), bool> = true>
2430 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
2431 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
2432 static_assert(n_rows == rows_, "Matrix dimension should meet.");
2433 static_assert(n_cols == cols_, "Matrix dimension should meet.");
2434 MAT_DIAG_TIMES_MAT_DIAG:
2435 for (size_t i = 0; i != n_rows; ++i) {
2437 (*this)(i, i) = mat_L[i] * mat_R[i];
2438 }
2439 return *this;
2440 }
2441
2463 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
2464 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
2465 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
2466 std::enable_if_t<(type1 == MatType::DIAGONAL && type2 == MatType::SCALAR), bool> = true>
2467 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
2468 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
2469 static_assert(n_rows == rows_, "Matrix dimension should meet.");
2470 static_assert(n_cols == cols_, "Matrix dimension should meet.");
2471 MAT_DIAG_TIMES_MAT_SCAL:
2472 for (size_t i = 0; i != n_cols; ++i) {
2474 _data[i] = mat_L[i] * mat_R[0];
2475 }
2476 return *this;
2477 }
2478
2500 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
2501 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
2502 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
2503 std::enable_if_t<(type1 == MatType::DIAGONAL && type2 == MatType::UPPER), bool> = true>
2504 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
2505 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
2506 static_assert(n_rows == rows_, "Matrix dimension should meet.");
2507 static_assert(n_cols == cols_, "Matrix dimension should meet.");
2508 static const size_t r[36] = {
2509 0, 0, 1, 0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 7,
2510 };
2511 static const size_t i[36] = {
2512 0, 0, 1, 0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 7,
2513 };
2514 static const size_t c[36] = {
2515 0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7,
2516 };
2517 MAT_DIAG_TIMES_UPPER:
2518 for (size_t n = 0; n != n_rows * (n_rows + 1) / 2; n++) {
2520 (*this)(r[n], c[n]) = mat_L(r[n], i[n]) * mat_R(i[n], c[n]);
2521 }
2522 return *this;
2523 }
2524
2546 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
2547 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
2548 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
2549 std::enable_if_t<(type1 == MatType::DIAGONAL && type2 == MatType::LOWER), bool> = true>
2550 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
2551 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
2552 static_assert(n_rows == rows_, "Matrix dimension should meet.");
2553 static_assert(n_cols == cols_, "Matrix dimension should meet.");
2554 static const size_t r[36] = {
2555 0, 1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 3, 4, 5, 6, 7, 4, 5, 6, 7, 5, 6, 7, 6, 7, 7,
2556 };
2557 static const size_t i[36] = {
2558 0, 1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 3, 4, 5, 6, 7, 4, 5, 6, 7, 5, 6, 7, 6, 7, 7,
2559 };
2560 static const size_t c[36] = {
2561 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 6, 6, 7,
2562 };
2563 MAT_DIAG_TIMES_LOWER:
2564 for (size_t n = 0; n != n_rows * (n_rows + 1) / 2; n++) {
2566 (*this)(r[n], c[n]) = mat_L(r[n], i[n]) * mat_R(i[n], c[n]);
2567 }
2568 return *this;
2569 }
2570
2592 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
2593 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
2594 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
2595 std::enable_if_t<(type1 == MatType::DIAGONAL && type2 == MatType::SUPPER), bool> = true>
2596 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
2597 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
2598 static_assert(n_rows == rows_, "Matrix dimension should meet.");
2599 static_assert(n_cols == cols_, "Matrix dimension should meet.");
2600 static const size_t r[28] = {
2601 0, 0, 1, 0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6
2602 };
2603 static const size_t i[28] = {
2604 0, 0, 1, 0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6
2605 };
2606 static const size_t c[28] = {
2607 1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7
2608 };
2609 MAT_DIAG_TIMES_SUPPER:
2610 for (size_t n = 0; n != n_rows * (n_rows - 1) / 2; n++) {
2612 (*this)(r[n], c[n]) = mat_L(r[n], i[n]) * mat_R(i[n], c[n]);
2613 }
2614 return *this;
2615 }
2616
2638 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
2639 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
2640 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
2641 std::enable_if_t<(type1 == MatType::DIAGONAL && type2 == MatType::SLOWER), bool> = true>
2642 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
2643 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
2644 static_assert(n_rows == rows_, "Matrix dimension should meet.");
2645 static_assert(n_cols == cols_, "Matrix dimension should meet.");
2646 static const size_t r[28] = {
2647 1, 2, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 3, 4, 5, 6, 7, 4, 5, 6, 7, 5, 6, 7, 6, 7, 7
2648 };
2649 static const size_t i[28] = {
2650 1, 2, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 3, 4, 5, 6, 7, 4, 5, 6, 7, 5, 6, 7, 6, 7, 7
2651 };
2652 static const size_t c[28] = {
2653 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 5, 5, 6
2654 };
2655 MAT_DIAG_TIMES_SLOWER:
2656 for (size_t n = 0; n != n_rows * (n_rows - 1) / 2; n++) {
2658 (*this)(r[n], c[n]) = mat_L(r[n], i[n]) * mat_R(i[n], c[n]);
2659 }
2660 return *this;
2661 }
2662
2684 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
2685 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
2686 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
2687 std::enable_if_t<(type1 == MatType::DIAGONAL && (type2 == MatType::NORMAL || type2 == MatType::SYM)),
2688 bool> = true>
2689 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
2690 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
2691 static_assert(n_rows == rows_, "Matrix dimension should meet.");
2692 static_assert(n_cols == cols_, "Matrix dimension should meet.");
2693 MAT_DIAG_TIMES_MAT_NORMAL_or_SYM:
2694 for (size_t j = 0; j != n_cols; ++j) {
2696 for (size_t i = 0; i != n_rows; ++i) {
2697 FLAMES_PRAGMA(LOOP_FLATTEN)
2698 (*this)(i, j) = mat_L(i, i) * mat_R(i, j);
2699 }
2700 }
2701 return *this;
2702 }
2703
2725 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
2726 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
2727 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
2728 std::enable_if_t<(type1 == MatType::DIAGONAL && type2 == MatType::ASYM), bool> = true>
2729 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
2730 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
2731 static_assert(n_rows == rows_, "Matrix dimension should meet.");
2732 static_assert(n_cols == cols_, "Matrix dimension should meet.");
2733 MAT_DIAG_TIMES_MAT_ASYM:
2734 for (size_t j = 0; j != n_cols; ++j) {
2736 for (size_t i = 0; i != n_rows; ++i) {
2737 FLAMES_PRAGMA(LOOP_FLATTEN)
2738 if (i != j) (*this)(i, j) = mat_L(i, i) * mat_R(i, j);
2739 else (*this)(i, j) = T(0);
2740 }
2741 }
2742 return *this;
2743 }
2744
2764 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
2765 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
2766 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
2767 std::enable_if_t<(type1 == MatType::SCALAR && type2 == MatType::SCALAR), bool> = true>
2768 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
2769 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
2770 static_assert(n_rows == rows_, "Matrix dimension should meet.");
2771 static_assert(n_cols == cols_, "Matrix dimension should meet.");
2772 MAT_SCAL_TIMES_MAT_SCAL:
2773 _data[0] = mat_L[0] * mat_R[0];
2774 return *this;
2775 }
2776
2798 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
2799 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
2800 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
2801 std::enable_if_t<(type1 == MatType::SCALAR && type2 == MatType::DIAGONAL), bool> = true>
2802 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
2803 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
2804 static_assert(n_rows == rows_, "Matrix dimension should meet.");
2805 static_assert(n_cols == cols_, "Matrix dimension should meet.");
2806 MAT_SCAL_TIMES_MAT_DIAG:
2807 for (size_t i = 0; i != n_cols; ++i) {
2809 _data[i] = mat_L[0] * mat_R[i];
2810 }
2811 return *this;
2812 }
2813
2835 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
2836 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
2837 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
2838 std::enable_if_t<(type2 == MatType::UPPER && type1 == MatType::SCALAR), bool> = true>
2839 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
2840 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
2841 static_assert(n_rows == rows_, "Matrix dimension should meet.");
2842 static_assert(n_cols == cols_, "Matrix dimension should meet.");
2843 MAT_SCAL_TIMES_MAT_UPPER:
2844 for (size_t i = 0; i != (1 + n_rows) * n_rows / 2; ++i) {
2846 _data[i] = mat_L[0] * mat_R[i];
2847 }
2848 return *this;
2849 }
2850
2872 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
2873 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
2874 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
2875 std::enable_if_t<(type2 == MatType::LOWER && type1 == MatType::SCALAR), bool> = true>
2876 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
2877 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
2878 static_assert(n_rows == rows_, "Matrix dimension should meet.");
2879 static_assert(n_cols == cols_, "Matrix dimension should meet.");
2880 MAT_SCAL_TIMES_MAT_LOWER:
2881 for (size_t i = 0; i != (1 + n_rows) * n_rows / 2; ++i) {
2883 _data[i] = mat_L[0] * mat_R[i];
2884 }
2885 return *this;
2886 }
2887
2909 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
2910 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
2911 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
2912 std::enable_if_t<(type2 == MatType::SUPPER && type1 == MatType::SCALAR), bool> = true>
2913 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
2914 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
2915 static_assert(n_rows == rows_, "Matrix dimension should meet.");
2916 static_assert(n_cols == cols_, "Matrix dimension should meet.");
2917 MAT_SCAL_TIMES_MAT_SUPPER:
2918 for (size_t i = 0; i != (n_rows - 1) * n_rows / 2; ++i) {
2920 _data[i] = mat_L[0] * mat_R[i];
2921 }
2922 return *this;
2923 }
2924
2946 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
2947 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
2948 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
2949 std::enable_if_t<(type2 == MatType::SLOWER && type1 == MatType::SCALAR), bool> = true>
2950 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
2951 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
2952 static_assert(n_rows == rows_, "Matrix dimension should meet.");
2953 static_assert(n_cols == cols_, "Matrix dimension should meet.");
2954 MAT_SCAL_TIMES_MAT_SLOWER:
2955 for (size_t i = 0; i != (n_rows - 1) * n_rows / 2; ++i) {
2957 _data[i] = mat_L[0] * mat_R[i];
2958 }
2959 return *this;
2960 }
2961
2983 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
2984 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
2985 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
2986 std::enable_if_t<(type2 == MatType::ASYM && type1 == MatType::SCALAR), bool> = true>
2987 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
2988 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
2989 static_assert(n_rows == rows_, "Matrix dimension should meet.");
2990 static_assert(n_cols == cols_, "Matrix dimension should meet.");
2991 MAT_SCAL_TIMES_MAT_SLOWER:
2992 for (size_t i = 1; i != n_rows; ++i) {
2994 for (size_t j = 0; j != n_cols; ++j) {
2995 FLAMES_PRAGMA(LOOP_FLATTEN)
2996 if (i != j) (*this)(i, j) = mat_L[0] * mat_R(i, j);
2997 else (*this)(i, j) = T(0);
2998 }
2999 }
3000 return *this;
3001 }
3002
3024 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
3025 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
3026 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
3027 std::enable_if_t<((type2 == MatType::SYM || type2 == NORMAL) && type1 == MatType::SCALAR), bool> = true>
3028 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
3029 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
3030 static_assert(n_rows == rows_, "Matrix dimension should meet.");
3031 static_assert(n_cols == cols_, "Matrix dimension should meet.");
3032 MAT_SCAL_TIMES_MAT_NORMAL_OR_MAT_SYM:
3033 for (size_t i = 0; i != n_rows; ++i) {
3035 for (size_t j = 0; j != n_cols; ++j) {
3036 FLAMES_PRAGMA(LOOP_FLATTEN)
3037 (*this)(i, j) = mat_L[0] * mat_R(i, j);
3038 }
3039 }
3040 return *this;
3041 }
3042
3064 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
3065 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
3066 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
3067 std::enable_if_t<(type1 == MatType::UPPER && type2 == MatType::SCALAR), bool> = true>
3068 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
3069 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
3070 static_assert(n_rows == rows_, "Matrix dimension should meet.");
3071 static_assert(n_cols == cols_, "Matrix dimension should meet.");
3072 MAT_UPPER_TIMES_MAT_SCALAR:
3073 for (size_t i = 0; i != (n_rows + 1) * n_rows / 2; ++i) {
3075 _data[i] = mat_L[i] * mat_R[0];
3076 }
3077 return *this;
3078 }
3079
3101 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
3102 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
3103 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
3104 std::enable_if_t<(type1 == MatType::UPPER && type2 == MatType::DIAGONAL), bool> = true>
3105 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
3106 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
3107 static_assert(n_rows == rows_, "Matrix dimension should meet.");
3108 static_assert(n_cols == cols_, "Matrix dimension should meet.");
3109 static const size_t r[36] = { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2,
3110 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 6, 6, 7 };
3111 static const size_t i[36] = { 0, 1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 2, 3, 4,
3112 5, 6, 7, 3, 4, 5, 6, 7, 4, 5, 6, 7, 5, 6, 7, 6, 7, 7 };
3113 static const size_t c[36] = { 0, 1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 2, 3, 4,
3114 5, 6, 7, 3, 4, 5, 6, 7, 4, 5, 6, 7, 5, 6, 7, 6, 7, 7 };
3115 MAT_UPPER_TIMES_DIAG:
3116 for (size_t n = 0; n != n_rows * (n_rows + 1) / 2; n++) {
3118 (*this)(r[n], c[n]) = mat_L(r[n], i[n]) * mat_R(i[n], c[n]);
3119 }
3120 return *this;
3121 }
3122
3144 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
3145 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
3146 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
3147 std::enable_if_t<(type1 == MatType::UPPER && type2 == MatType::UPPER), bool> = true>
3148 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
3149 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
3150 FLAMES_PRAGMA(INLINE off)
3151 static_assert(n_rows == rows_, "Matrix dimension should meet.");
3152 static_assert(n_cols == cols_, "Matrix dimension should meet.");
3153 static const size_t r[120] = { 0, 1, 2, 3, 4, 5, 6, 7, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 0, 0,
3154 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 0, 0, 0, 0, 1, 1, 1, 1,
3155 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2,
3156 2, 2, 2, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2,
3157 2, 2, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 };
3158 static const size_t i[120] = { 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 0, 1,
3159 2, 1, 2, 3, 2, 3, 4, 3, 4, 5, 4, 5, 6, 5, 6, 7, 0, 1, 2, 3, 1, 2, 3, 4,
3160 2, 3, 4, 5, 3, 4, 5, 6, 4, 5, 6, 7, 0, 1, 2, 3, 4, 1, 2, 3, 4, 5, 2, 3,
3161 4, 5, 6, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 6, 2, 3, 4, 5,
3162 6, 7, 0, 1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7 };
3163 static const size_t c[120] = { 0, 1, 2, 3, 4, 5, 6, 7, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 2, 2,
3164 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, 3, 3, 3, 3, 4, 4, 4, 4,
3165 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6,
3166 6, 6, 6, 7, 7, 7, 7, 7, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7,
3167 7, 7, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 };
3168 MAT_UPPER_TIMES_UPPER:
3169 for (size_t n = 0; n != n_rows * (n_rows + 1) * (n_rows + 2) / 6; n++) {
3171 if (i[n] == r[n]) (*this)(r[n], c[n]) = 0; // initialize
3172 (*this)(r[n], c[n]) += mat_L(r[n], i[n]) * mat_R(i[n], c[n]);
3173 }
3174 return *this;
3175 }
3176
3198 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
3199 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
3200 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
3201 std::enable_if_t<(type1 == MatType::UPPER && type2 == MatType::LOWER), bool> = true>
3202 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
3203 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
3204 FLAMES_PRAGMA(INLINE off)
3205 static_assert(n_rows == rows_, "Matrix dimension should meet.");
3206 static_assert(n_cols == cols_, "Matrix dimension should meet.");
3207 static const size_t r[120] = {
3208 0, 1, 2, 3, 4, 5, 6, 7, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 0, 0, 0, 1, 1, 1, 2, 2,
3209 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4,
3210 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
3211 1, 1, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
3212 };
3213 static const size_t i[120] = {
3214 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 0, 1, 2, 1, 2, 3, 2, 3,
3215 4, 3, 4, 5, 4, 5, 6, 5, 6, 7, 0, 1, 2, 3, 1, 2, 3, 4, 2, 3, 4, 5, 3, 4, 5, 6, 4, 5, 6, 7,
3216 0, 1, 2, 3, 4, 1, 2, 3, 4, 5, 2, 3, 4, 5, 6, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 1, 2, 3, 4,
3217 5, 6, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7,
3218 };
3219 static const size_t c[120] = {
3220 0, 1, 2, 3, 4, 5, 6, 7, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 2, 2, 2, 3, 3, 3, 4, 4,
3221 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7,
3222 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6,
3223 6, 6, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
3224 };
3225 MAT_UPPER_TIMES_MAT_LOWER:
3226 for (size_t n = 0; n != n_rows * (n_rows + 1) * (n_rows + 2) / 6; n++) {
3228 if (i[n] == r[n]) (*this)(r[n], c[n]) = 0; // initialize
3229 (*this)(r[n], c[n]) += mat_L(r[n], i[n]) * mat_R(i[n], c[n]);
3230 }
3231 return *this;
3232 }
3233
3255 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
3256 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
3257 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
3258 std::enable_if_t<(type1 == MatType::UPPER && type2 == MatType::SUPPER), bool> = true>
3259 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
3260 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
3261 FLAMES_PRAGMA(INLINE off)
3262 static_assert(n_rows == rows_, "Matrix dimension should meet.");
3263 static_assert(n_cols == cols_, "Matrix dimension should meet.");
3264 static const size_t c[84] = {
3265 0, 1, 2, 3, 4, 5, 6, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 0, 0, 0, 1, 1, 1, 2, 2, 2,
3266 3, 3, 3, 4, 4, 4, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 0, 0, 0, 0, 0, 1,
3267 1, 1, 1, 1, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
3268 };
3269 static const size_t i[84] = {
3270 0, 1, 2, 3, 4, 5, 6, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 0, 1, 2, 1, 2, 3, 2, 3, 4,
3271 3, 4, 5, 4, 5, 6, 0, 1, 2, 3, 1, 2, 3, 4, 2, 3, 4, 5, 3, 4, 5, 6, 0, 1, 2, 3, 4, 1,
3272 2, 3, 4, 5, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6,
3273 };
3274 static const size_t r[84] = {
3275 1, 2, 3, 4, 5, 6, 7, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 3, 3, 3, 4, 4, 4, 5, 5, 5,
3276 6, 6, 6, 7, 7, 7, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 5, 5, 5, 5, 5, 6,
3277 6, 6, 6, 6, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
3278 };
3279 MAT_UPPER_TIMES_MAT_SUPPER:
3280 for (size_t n = 0; n != (n_rows * n_rows * n_rows - n_rows) / 6; n++) {
3282 if (i[n] == r[n]) (*this)(r[n], c[n]) = 0; // initialize
3283 (*this)(r[n], c[n]) += mat_L(r[n], i[n]) * mat_R(i[n], c[n]);
3284 }
3285 return *this;
3286 }
3287
3309 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
3310 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
3311 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
3312 std::enable_if_t<(type1 == MatType::UPPER && type2 == MatType::SLOWER), bool> = true>
3313 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
3314 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
3315 FLAMES_PRAGMA(INLINE off)
3316 static_assert(n_rows == rows_, "Matrix dimension should meet.");
3317 static_assert(n_cols == cols_, "Matrix dimension should meet.");
3318 static const size_t r[168] = {
3319 7, 7, 7, 7, 7, 7, 7, 6, 5, 4, 3, 2, 1, 0, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2,
3320 1, 1, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 1, 1, 1, 0, 0, 0,
3321 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 3, 3,
3322 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2,
3323 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
3324 };
3325 static const size_t i[168] = {
3326 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7,
3327 6, 7, 6, 7, 5, 6, 7, 5, 6, 7, 5, 6, 7, 5, 6, 7, 5, 6, 7, 5, 6, 7, 5, 6, 7, 5, 6, 7, 5, 6, 7, 5, 6, 7,
3328 4, 5, 6, 7, 4, 5, 6, 7, 4, 5, 6, 7, 4, 5, 6, 7, 4, 5, 6, 7, 4, 5, 6, 7, 4, 5, 6, 7, 4, 5, 6, 7, 3, 4,
3329 5, 6, 7, 3, 4, 5, 6, 7, 3, 4, 5, 6, 7, 3, 4, 5, 6, 7, 3, 4, 5, 6, 7, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7,
3330 2, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7,
3331 };
3332 static const size_t c[168] = {
3333 0, 1, 2, 3, 4, 5, 6, 6, 6, 6, 6, 6, 6, 6, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
3334 5, 5, 5, 5, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
3335 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0,
3336 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0,
3337 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3338 };
3339 MAT_UPPER_TIMES_MAT_SLOWER:
3340 for (size_t n = 0; n != (n_rows * n_rows * n_rows - n_rows) / 3; n++) {
3342 if (i[n] == r[n] || i[n] == (c[n] + 1)) (*this)(r[n], c[n]) = 0; // initialize
3343 (*this)(r[n], c[n]) += mat_L(r[n], i[n]) * mat_R(i[n], c[n]);
3344 }
3345 return *this;
3346 }
3347
3369 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
3370 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
3371 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
3372 std::enable_if_t<(type1 == MatType::UPPER && type2 == MatType::ASYM), bool> = true>
3373 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
3374 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
3375 FLAMES_PRAGMA(INLINE off)
3376 static_assert(n_rows == rows_, "Matrix dimension should meet.");
3377 static_assert(n_cols == cols_, "Matrix dimension should meet.");
3378 static const size_t r[288] = {
3379 7, 6, 6, 5, 5, 5, 4, 4, 4, 4, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
3380 7, 6, 6, 5, 5, 5, 4, 4, 4, 4, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
3381 7, 6, 6, 5, 5, 5, 4, 4, 4, 4, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
3382 7, 6, 6, 5, 5, 5, 4, 4, 4, 4, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
3383 7, 6, 6, 5, 5, 5, 4, 4, 4, 4, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
3384 7, 6, 6, 5, 5, 5, 4, 4, 4, 4, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
3385 7, 6, 6, 5, 5, 5, 4, 4, 4, 4, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
3386 7, 6, 6, 5, 5, 5, 4, 4, 4, 4, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
3387 };
3388 static const size_t c[288] = {
3389 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3390 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3391 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
3392 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3393 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
3394 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
3395 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
3396 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
3397 };
3398 static const size_t i[288] = {
3399 7, 6, 7, 5, 6, 7, 4, 5, 6, 7, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7,
3400 7, 6, 7, 5, 6, 7, 4, 5, 6, 7, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7,
3401 7, 6, 7, 5, 6, 7, 4, 5, 6, 7, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7,
3402 7, 6, 7, 5, 6, 7, 4, 5, 6, 7, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7,
3403 7, 6, 7, 5, 6, 7, 4, 5, 6, 7, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7,
3404 7, 6, 7, 5, 6, 7, 4, 5, 6, 7, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7,
3405 7, 6, 7, 5, 6, 7, 4, 5, 6, 7, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7,
3406 7, 6, 7, 5, 6, 7, 4, 5, 6, 7, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7,
3407 };
3408 MAT_UPPER_TIMES_MAT_ASYM:
3409 for (size_t n = 0; n != n_rows * n_rows * (n_rows + 1) / 2; n++) {
3411 if (i[n] == r[n]) (*this)(r[n], c[n]) = 0; // initialize
3412 if (i[n] != c[n]) (*this)(r[n], c[n]) += mat_L(r[n], i[n]) * mat_R(i[n], c[n]);
3413 }
3414 return *this;
3415 }
3416
3438 template <
3439 template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
3440 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1, typename T2,
3441 MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
3442 std::enable_if_t<(type1 == MatType::UPPER && (type2 == MatType::SYM || type2 == MatType::NORMAL)), bool> = true>
3443 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
3444 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
3445 FLAMES_PRAGMA(INLINE off)
3446 static_assert(n_rows == rows_, "Matrix dimension should meet.");
3447 static_assert(n_cols == cols_, "Matrix dimension should meet.");
3448 static const size_t r[288] = {
3449 7, 6, 6, 5, 5, 5, 4, 4, 4, 4, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
3450 7, 6, 6, 5, 5, 5, 4, 4, 4, 4, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
3451 7, 6, 6, 5, 5, 5, 4, 4, 4, 4, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
3452 7, 6, 6, 5, 5, 5, 4, 4, 4, 4, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
3453 7, 6, 6, 5, 5, 5, 4, 4, 4, 4, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
3454 7, 6, 6, 5, 5, 5, 4, 4, 4, 4, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
3455 7, 6, 6, 5, 5, 5, 4, 4, 4, 4, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
3456 7, 6, 6, 5, 5, 5, 4, 4, 4, 4, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
3457 };
3458 static const size_t c[288] = {
3459 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3460 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3461 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
3462 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3463 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
3464 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
3465 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
3466 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
3467 };
3468 static const size_t i[288] = {
3469 7, 6, 7, 5, 6, 7, 4, 5, 6, 7, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7,
3470 7, 6, 7, 5, 6, 7, 4, 5, 6, 7, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7,
3471 7, 6, 7, 5, 6, 7, 4, 5, 6, 7, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7,
3472 7, 6, 7, 5, 6, 7, 4, 5, 6, 7, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7,
3473 7, 6, 7, 5, 6, 7, 4, 5, 6, 7, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7,
3474 7, 6, 7, 5, 6, 7, 4, 5, 6, 7, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7,
3475 7, 6, 7, 5, 6, 7, 4, 5, 6, 7, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7,
3476 7, 6, 7, 5, 6, 7, 4, 5, 6, 7, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7,
3477 };
3478 MAT_LOWER_TIMES_NORAML_OR_MAT_SYM:
3479 for (size_t n = 0; n != n_rows * n_rows * (n_rows + 1) / 2; n++) {
3481 if (i[n] == r[n]) (*this)(r[n], c[n]) = 0; // initialize
3482 (*this)(r[n], c[n]) += mat_L(r[n], i[n]) * mat_R(i[n], c[n]);
3483 }
3484 return *this;
3485 }
3486
3508 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
3509 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
3510 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
3511 std::enable_if_t<(type1 == MatType::LOWER && type2 == MatType::SCALAR), bool> = true>
3512 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
3513 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
3514 static_assert(n_rows == rows_, "Matrix dimension should meet.");
3515 static_assert(n_cols == cols_, "Matrix dimension should meet.");
3516 MAT_LOWER_TIMES_MAT_SCALAR:
3517 for (size_t i = 0; i != (n_rows + 1) * n_rows / 2; ++i) {
3519 _data[i] = mat_L[i] * mat_R[0];
3520 }
3521 return *this;
3522 }
3523
3545 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
3546 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
3547 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
3548 std::enable_if_t<(type1 == MatType::LOWER && type2 == MatType::DIAGONAL), bool> = true>
3549 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
3550 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
3551 static_assert(n_rows == rows_, "Matrix dimension should meet.");
3552 static_assert(n_cols == cols_, "Matrix dimension should meet.");
3553 static const size_t r[36] = {
3554 0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7,
3555 };
3556 static const size_t i[36] = {
3557 0, 0, 1, 0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 7,
3558 };
3559 static const size_t c[36] = {
3560 0, 0, 1, 0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 7,
3561 };
3562 MAT_LOWER_TIMES_DIAG:
3563 for (size_t n = 0; n != n_rows * (n_rows + 1) / 2; n++) {
3565 (*this)(r[n], c[n]) = mat_L(r[n], i[n]) * mat_R(i[n], c[n]);
3566 }
3567 return *this;
3568 }
3569
3591 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
3592 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
3593 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
3594 std::enable_if_t<(type1 == MatType::LOWER && type2 == MatType::UPPER), bool> = true>
3595 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
3596 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
3597 FLAMES_PRAGMA(INLINE off)
3598 static_assert(n_rows == rows_, "Matrix dimension should meet.");
3599 static_assert(n_cols == cols_, "Matrix dimension should meet.");
3600 static const size_t r[204] = {
3601 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1,
3602 1, 1, 1, 1, 1, 1, 1, 7, 7, 7, 6, 6, 6, 5, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
3603 2, 2, 2, 2, 2, 2, 7, 7, 7, 7, 6, 6, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3604 3, 3, 3, 3, 3, 3, 3, 3, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
3605 4, 4, 4, 4, 4, 4, 4, 4, 4, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
3606 5, 5, 5, 5, 5, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7,
3607 };
3608 static const size_t i[204] = {
3609 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
3610 1, 0, 1, 0, 1, 0, 1, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2,
3611 0, 1, 2, 0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
3612 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0,
3613 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0,
3614 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 7,
3615 };
3616 static const size_t c[204] = {
3617 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4,
3618 4, 5, 5, 6, 6, 7, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5,
3619 6, 6, 6, 7, 7, 7, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5,
3620 6, 6, 6, 6, 7, 7, 7, 7, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6,
3621 6, 6, 6, 6, 7, 7, 7, 7, 7, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7,
3622 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
3623 };
3624 MAT_LOWER_TIMES_MAT_UPPER:
3625 for (size_t n = 0; n != (2 * n_rows * n_rows * n_rows + 3 * n_rows * n_rows + n_rows) / 6; n++) {
3627 if (i[n] == 0) (*this)(r[n], c[n]) = 0; // initialize
3628 (*this)(r[n], c[n]) += mat_L(r[n], i[n]) * mat_R(i[n], c[n]);
3629 }
3630 return *this;
3631 }
3632
3654 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
3655 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
3656 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
3657 std::enable_if_t<(type1 == MatType::LOWER && type2 == MatType::LOWER), bool> = true>
3658 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
3659 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
3660 FLAMES_PRAGMA(INLINE off)
3661 static_assert(n_rows == rows_, "Matrix dimension should meet.");
3662 static_assert(n_cols == cols_, "Matrix dimension should meet.");
3663 static const size_t c[120] = {
3664 0, 1, 2, 3, 4, 5, 6, 7, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 0, 0, 0, 1, 1, 1, 2, 2,
3665 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4,
3666 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
3667 1, 1, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
3668 };
3669 static const size_t i[120] = {
3670 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 0, 1, 2, 1, 2, 3, 2, 3,
3671 4, 3, 4, 5, 4, 5, 6, 5, 6, 7, 0, 1, 2, 3, 1, 2, 3, 4, 2, 3, 4, 5, 3, 4, 5, 6, 4, 5, 6, 7,
3672 0, 1, 2, 3, 4, 1, 2, 3, 4, 5, 2, 3, 4, 5, 6, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 1, 2, 3, 4,
3673 5, 6, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7,
3674 };
3675 static const size_t r[120] = {
3676 0, 1, 2, 3, 4, 5, 6, 7, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 2, 2, 2, 3, 3, 3, 4, 4,
3677 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7,
3678 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6,
3679 6, 6, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
3680 };
3681 MAT_LOWER_TIMES_MAT_LOWER:
3682 for (size_t n = 0; n != n_rows * (n_rows + 1) * (n_rows + 2) / 6; n++) {
3684 if (i[n] == c[n]) (*this)(r[n], c[n]) = 0; // initialize
3685 (*this)(r[n], c[n]) += mat_L(r[n], i[n]) * mat_R(i[n], c[n]);
3686 }
3687 return *this;
3688 }
3689
3711 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
3712 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
3713 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
3714 std::enable_if_t<(type1 == MatType::LOWER && type2 == MatType::SUPPER), bool> = true>
3715 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
3716 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
3717 FLAMES_PRAGMA(INLINE off)
3718 static_assert(n_rows == rows_, "Matrix dimension should meet.");
3719 static_assert(n_cols == cols_, "Matrix dimension should meet.");
3720 static const size_t r[168] = {
3721 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5,
3722 6, 6, 7, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7,
3723 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 4, 4,
3724 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 5, 5, 5, 5, 5, 5,
3725 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7,
3726 };
3727 static const size_t i[168] = {
3728 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
3729 0, 1, 0, 1, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2,
3730 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1,
3731 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5,
3732 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6,
3733 };
3734 static const size_t c[168] = {
3735 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
3736 2, 2, 2, 2, 7, 7, 7, 6, 6, 6, 5, 5, 5, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3737 7, 7, 7, 7, 6, 6, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 7, 7,
3738 7, 7, 7, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 7, 7, 7, 7, 7, 7,
3739 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
3740 };
3741 MAT_LOWER_TIMES_MAT_SUPPER:
3742 for (size_t n = 0; n != (n_rows * n_rows * n_rows - n_rows) / 3; n++) {
3744 if (i[n] == 0) (*this)(r[n], c[n]) = 0; // initialize
3745 (*this)(r[n], c[n]) += mat_L(r[n], i[n]) * mat_R(i[n], c[n]);
3746 }
3747 for (size_t r = 0; r != n_cols; r++) { (*this)(r, 0) = T(0); }
3748 return *this;
3749 }
3750
3773 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
3774 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
3775 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
3776 std::enable_if_t<(type1 == MatType::LOWER && type2 == MatType::SLOWER), bool> = true>
3777 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
3778 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
3779 FLAMES_PRAGMA(INLINE off)
3780 static_assert(n_rows == rows_, "Matrix dimension should meet.");
3781 static_assert(n_cols == cols_, "Matrix dimension should meet.");
3782 static const size_t c[84] = {
3783 0, 1, 2, 3, 4, 5, 6, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 0, 0, 0, 1, 1, 1, 2, 2, 2,
3784 3, 3, 3, 4, 4, 4, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 0, 0, 0, 0, 0, 1,
3785 1, 1, 1, 1, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
3786 };
3787 static const size_t i[84] = {
3788 1, 2, 3, 4, 5, 6, 7, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 1, 2, 3, 2, 3, 4, 3, 4, 5,
3789 4, 5, 6, 5, 6, 7, 1, 2, 3, 4, 2, 3, 4, 5, 3, 4, 5, 6, 4, 5, 6, 7, 1, 2, 3, 4, 5, 2,
3790 3, 4, 5, 6, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7,
3791 };
3792 static const size_t r[84] = {
3793 1, 2, 3, 4, 5, 6, 7, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 3, 3, 3, 4, 4, 4, 5, 5, 5,
3794 6, 6, 6, 7, 7, 7, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 5, 5, 5, 5, 5, 6,
3795 6, 6, 6, 6, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
3796 };
3797 MAT_LOWER_TIMES_MAT_SLOWER:
3798 for (size_t n = 0; n != (n_rows * n_rows * n_rows - n_rows) / 6; n++) {
3800 if (i[n] == c[n] + 1) (*this)(r[n], c[n]) = 0; // initialize
3801 (*this)(r[n], c[n]) += mat_L(r[n], i[n]) * mat_R(i[n], c[n]);
3802 }
3803 return *this;
3804 }
3805
3827 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
3828 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
3829 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
3830 std::enable_if_t<(type1 == MatType::LOWER && type2 == MatType::ASYM), bool> = true>
3831 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
3832 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
3833 FLAMES_PRAGMA(INLINE off)
3834 static_assert(n_rows == rows_, "Matrix dimension should meet.");
3835 static_assert(n_cols == cols_, "Matrix dimension should meet.");
3836 static const size_t c[288] = {
3837 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3838 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3839 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
3840 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3841 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
3842 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
3843 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
3844 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
3845 };
3846 static const size_t i[288] = {
3847 0, 0, 1, 0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 7,
3848 0, 0, 1, 0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 7,
3849 0, 0, 1, 0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 7,
3850 0, 0, 1, 0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 7,
3851 0, 0, 1, 0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 7,
3852 0, 0, 1, 0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 7,
3853 0, 0, 1, 0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 7,
3854 0, 0, 1, 0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 7,
3855 };
3856 static const size_t r[288] = {
3857 0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7,
3858 0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7,
3859 0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7,
3860 0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7,
3861 0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7,
3862 0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7,
3863 0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7,
3864 0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7,
3865 };
3866 MAT_LOWER_TIMES_MAT_ASYM:
3867 for (size_t n = 0; n != n_rows * n_rows * (n_rows + 1) / 2; n++) {
3869 if (i[n] == 0) (*this)(r[n], c[n]) = 0; // initialize
3870 if (i[n] != c[n]) (*this)(r[n], c[n]) += mat_L(r[n], i[n]) * mat_R(i[n], c[n]);
3871 }
3872 return *this;
3873 }
3874
3896 template <
3897 template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
3898 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1, typename T2,
3899 MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
3900 std::enable_if_t<(type1 == MatType::LOWER && (type2 == MatType::SYM || type2 == MatType::NORMAL)), bool> = true>
3901 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
3902 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
3903 FLAMES_PRAGMA(INLINE off)
3904 static_assert(n_rows == rows_, "Matrix dimension should meet.");
3905 static_assert(n_cols == cols_, "Matrix dimension should meet.");
3906 static const size_t c[288] = {
3907 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3908 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3909 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
3910 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3911 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
3912 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
3913 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
3914 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
3915 };
3916 static const size_t i[288] = {
3917 0, 0, 1, 0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 7,
3918 0, 0, 1, 0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 7,
3919 0, 0, 1, 0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 7,
3920 0, 0, 1, 0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 7,
3921 0, 0, 1, 0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 7,
3922 0, 0, 1, 0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 7,
3923 0, 0, 1, 0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 7,
3924 0, 0, 1, 0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 7,
3925 };
3926 static const size_t r[288] = {
3927 0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7,
3928 0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7,
3929 0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7,
3930 0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7,
3931 0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7,
3932 0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7,
3933 0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7,
3934 0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7,
3935 };
3936 MAT_LOWER_TIMES_MAT_NORMAL_OR_MAT_SYM:
3937 for (size_t n = 0; n != n_rows * n_rows * (n_rows + 1) / 2; n++) {
3939 if (i[n] == 0) (*this)(r[n], c[n]) = 0; // initialize
3940 (*this)(r[n], c[n]) += mat_L(r[n], i[n]) * mat_R(i[n], c[n]);
3941 }
3942 return *this;
3943 }
3944
3966 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
3967 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
3968 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
3969 std::enable_if_t<(type1 == MatType::SUPPER && type2 == MatType::SCALAR), bool> = true>
3970 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
3971 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
3972 static_assert(n_rows == rows_, "Matrix dimension should meet.");
3973 static_assert(n_cols == cols_, "Matrix dimension should meet.");
3974 MAT_SUPPER_TIMES_MAT_SCALAR:
3975 for (size_t i = 0; i != (n_rows - 1) * n_rows / 2; ++i) {
3977 _data[i] = mat_L[i] * mat_R[0];
3978 }
3979 return *this;
3980 }
3981
4003 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
4004 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
4005 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
4006 std::enable_if_t<(type1 == MatType::SUPPER && type2 == MatType::DIAGONAL), bool> = true>
4007 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
4008 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
4009 static_assert(n_rows == rows_, "Matrix dimension should meet.");
4010 static_assert(n_cols == cols_, "Matrix dimension should meet.");
4011 static const size_t c[28] = {
4012 1, 2, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 3, 4, 5, 6, 7, 4, 5, 6, 7, 5, 6, 7, 6, 7, 7,
4013 };
4014 static const size_t i[28] = {
4015 1, 2, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 3, 4, 5, 6, 7, 4, 5, 6, 7, 5, 6, 7, 6, 7, 7,
4016 };
4017 static const size_t r[28] = {
4018 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 5, 5, 6,
4019 };
4020 MAT_SUPPER_TIMES_MAT_DIAG:
4021 for (size_t n = 0; n != n_rows * (n_rows - 1) / 2; n++) {
4023 (*this)(r[n], c[n]) = mat_L(r[n], i[n]) * mat_R(i[n], c[n]);
4024 }
4025 return *this;
4026 }
4027
4049 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
4050 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
4051 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
4052 std::enable_if_t<(type1 == MatType::SUPPER && type2 == MatType::UPPER), bool> = true>
4053 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
4054 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
4055 FLAMES_PRAGMA(INLINE off)
4056 static_assert(n_rows == rows_, "Matrix dimension should meet.");
4057 static_assert(n_cols == cols_, "Matrix dimension should meet.");
4058 static const size_t r[84] = {
4059 0, 1, 2, 3, 4, 5, 6, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 0, 0, 0, 1, 1, 1, 2, 2, 2,
4060 3, 3, 3, 4, 4, 4, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 0, 0, 0, 0, 0, 1,
4061 1, 1, 1, 1, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
4062 };
4063 static const size_t i[84] = {
4064 1, 2, 3, 4, 5, 6, 7, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 1, 2, 3, 2, 3, 4, 3, 4, 5,
4065 4, 5, 6, 5, 6, 7, 1, 2, 3, 4, 2, 3, 4, 5, 3, 4, 5, 6, 4, 5, 6, 7, 1, 2, 3, 4, 5, 2,
4066 3, 4, 5, 6, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7,
4067 };
4068 static const size_t c[84] = {
4069 1, 2, 3, 4, 5, 6, 7, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 3, 3, 3, 4, 4, 4, 5, 5, 5,
4070 6, 6, 6, 7, 7, 7, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 5, 5, 5, 5, 5, 6,
4071 6, 6, 6, 6, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
4072 };
4073 MAT_SUPPER_TIMES_MAT_UPPER:
4074 for (size_t n = 0; n != (n_rows * n_rows * n_rows - n_rows) / 6; n++) {
4076 if (i[n] == r[n] + 1) (*this)(r[n], c[n]) = 0; // initialize
4077 (*this)(r[n], c[n]) += mat_L(r[n], i[n]) * mat_R(i[n], c[n]);
4078 }
4079 return *this;
4080 }
4081
4103 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
4104 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
4105 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
4106 std::enable_if_t<(type1 == MatType::SUPPER && type2 == MatType::LOWER), bool> = true>
4107 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
4108 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
4109 FLAMES_PRAGMA(INLINE off)
4110 static_assert(n_rows == rows_, "Matrix dimension should meet.");
4111 static_assert(n_cols == cols_, "Matrix dimension should meet.");
4112 static const size_t c[168] = {
4113 7, 7, 7, 7, 7, 7, 7, 6, 5, 4, 3, 2, 1, 0, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2,
4114 1, 1, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 1, 1, 1, 0, 0, 0,
4115 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 3, 3,
4116 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2,
4117 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
4118 };
4119 static const size_t i[168] = {
4120 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7,
4121 6, 7, 6, 7, 5, 6, 7, 5, 6, 7, 5, 6, 7, 5, 6, 7, 5, 6, 7, 5, 6, 7, 5, 6, 7, 5, 6, 7, 5, 6, 7, 5, 6, 7,
4122 4, 5, 6, 7, 4, 5, 6, 7, 4, 5, 6, 7, 4, 5, 6, 7, 4, 5, 6, 7, 4, 5, 6, 7, 4, 5, 6, 7, 4, 5, 6, 7, 3, 4,
4123 5, 6, 7, 3, 4, 5, 6, 7, 3, 4, 5, 6, 7, 3, 4, 5, 6, 7, 3, 4, 5, 6, 7, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7,
4124 2, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7,
4125 };
4126 static const size_t r[168] = {
4127 0, 1, 2, 3, 4, 5, 6, 6, 6, 6, 6, 6, 6, 6, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
4128 5, 5, 5, 5, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4129 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0,
4130 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0,
4131 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
4132 };
4133 MAT_UPPER_TIMES_MAT_SLOWER:
4134 for (size_t n = 0; n != (n_rows * n_rows * n_rows - n_rows) / 3; n++) {
4136 if (i[n] == c[n] || i[n] == (r[n] + 1)) (*this)(r[n], c[n]) = 0; // initialize
4137 (*this)(r[n], c[n]) += mat_L(r[n], i[n]) * mat_R(i[n], c[n]);
4138 }
4139 for (size_t c = 0; c != n_cols; c++) { (*this)(n_rows - 1, c) = T(0); }
4140
4141 return *this;
4142 }
4143
4165 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
4166 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
4167 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
4168 std::enable_if_t<(type1 == MatType::SUPPER && type2 == MatType::SUPPER), bool> = true>
4169 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
4170 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
4171 FLAMES_PRAGMA(INLINE off)
4172 static_assert(n_rows == rows_, "Matrix dimension should meet.");
4173 static_assert(n_cols == cols_, "Matrix dimension should meet.");
4174 static const size_t r[56] = {
4175 0, 1, 2, 3, 4, 5, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3,
4176 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
4177 };
4178 static const size_t i[56] = {
4179 1, 2, 3, 4, 5, 6, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 1, 2, 3, 2, 3, 4, 3, 4, 5, 4, 5, 6,
4180 1, 2, 3, 4, 2, 3, 4, 5, 3, 4, 5, 6, 1, 2, 3, 4, 5, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6,
4181 };
4182 static const size_t c[56] = {
4183 2, 3, 4, 5, 6, 7, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7,
4184 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
4185 };
4186 MAT_SUPPER_TIMES_MAT_SUPPER:
4187 for (size_t n = 0; n != ((n_rows - 1) * (n_rows - 1) * (n_rows - 1) - (n_rows - 1)) / 6; n++) {
4189 if (i[n] == 1 + r[n]) (*this)(r[n], c[n]) = 0; // initialize
4190 (*this)(r[n], c[n]) += mat_L(r[n], i[n]) * mat_R(i[n], c[n]);
4191 }
4192 for (size_t i = 0; i != n_rows - 1; i++) { (*this)(i, i + 1) = T(0); }
4193 return *this;
4194 }
4195
4217 template <
4218 template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
4219 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1, typename T2,
4220 MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
4221 std::enable_if_t<!(type1 == MatType::SUPPER && n_rows == 1) && !(type2 == MatType::SLOWER && cols_ == 1) &&
4222 (type1 == MatType::SUPPER && type2 == MatType::SLOWER),
4223 bool> = true>
4224 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
4225 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
4226 FLAMES_PRAGMA(INLINE off)
4227 static_assert(n_rows == rows_, "Matrix dimension should meet.");
4228 static_assert(n_cols == cols_, "Matrix dimension should meet.");
4229 static const size_t c[140] = {
4230 6, 6, 6, 6, 6, 6, 6, 5, 4, 3, 2, 1, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 0, 0,
4231 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 2, 2, 2, 1, 1, 1, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3,
4232 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
4233 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
4234 };
4235 static const size_t i[140] = {
4236 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7,
4237 5, 6, 7, 5, 6, 7, 5, 6, 7, 5, 6, 7, 5, 6, 7, 5, 6, 7, 5, 6, 7, 5, 6, 7, 5, 6, 7, 4, 5, 6, 7, 4, 5, 6, 7,
4238 4, 5, 6, 7, 4, 5, 6, 7, 4, 5, 6, 7, 4, 5, 6, 7, 4, 5, 6, 7, 3, 4, 5, 6, 7, 3, 4, 5, 6, 7, 3, 4, 5, 6, 7,
4239 3, 4, 5, 6, 7, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7,
4240 };
4241 static const size_t r[140] = {
4242 0, 1, 2, 3, 4, 5, 6, 6, 6, 6, 6, 6, 6, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
4243 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 1, 1, 1, 1,
4244 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2,
4245 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
4246 };
4247 MAT_SUPPER_TIMES_MAT_SLOWER:
4248 for (size_t n = 0;
4249 n != (2 * (n_rows - 1) * (n_rows - 1) * (n_rows - 1) + 3 * (n_rows - 1) * (n_rows - 1) + (n_rows - 1)) / 6;
4250 n++) {
4252 if (i[n] == r[n] + 1 || i[n] == c[n] + 1) (*this)(r[n], c[n]) = T(0); // initialize
4253 (*this)(r[n], c[n]) += mat_L(r[n], i[n]) * mat_R(i[n], c[n]);
4254 }
4255 for (size_t r = 0; r != n_rows; r++) { (*this)(r, n_cols - 1) = T(0); }
4256 for (size_t c = 0; c != n_cols - 1; c++) { (*this)(n_rows - 1, c) = T(0); }
4257
4258 return *this;
4259 }
4260
4282 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
4283 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
4284 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
4285 std::enable_if_t<(type1 == MatType::SUPPER && type2 == MatType::ASYM), bool> = true>
4286 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
4287 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
4288 FLAMES_PRAGMA(INLINE off)
4289 static_assert(n_rows == rows_, "Matrix dimension should meet.");
4290 static_assert(n_cols == cols_, "Matrix dimension should meet.");
4291 static const size_t c[224] = {
4292 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
4293 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2,
4294 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
4295 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4296 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
4297 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
4298 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
4299 };
4300 static const size_t i[224] = {
4301 7, 6, 7, 5, 6, 7, 4, 5, 6, 7, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 7, 6, 7, 5,
4302 6, 7, 4, 5, 6, 7, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 7, 6, 7, 5, 6, 7, 4, 5,
4303 6, 7, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 7, 6, 7, 5, 6, 7, 4, 5, 6, 7, 3, 4,
4304 5, 6, 7, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 7, 6, 7, 5, 6, 7, 4, 5, 6, 7, 3, 4, 5, 6, 7, 2,
4305 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 7, 6, 7, 5, 6, 7, 4, 5, 6, 7, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6,
4306 7, 1, 2, 3, 4, 5, 6, 7, 7, 6, 7, 5, 6, 7, 4, 5, 6, 7, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 1, 2, 3,
4307 4, 5, 6, 7, 7, 6, 7, 5, 6, 7, 4, 5, 6, 7, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7,
4308 };
4309 static const size_t r[224] = {
4310 6, 5, 5, 4, 4, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 6, 5, 5, 4,
4311 4, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 6, 5, 5, 4, 4, 4, 3, 3,
4312 3, 3, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 6, 5, 5, 4, 4, 4, 3, 3, 3, 3, 2, 2,
4313 2, 2, 2, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 6, 5, 5, 4, 4, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 1,
4314 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 6, 5, 5, 4, 4, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1,
4315 1, 0, 0, 0, 0, 0, 0, 0, 6, 5, 5, 4, 4, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 0, 0, 0,
4316 0, 0, 0, 0, 6, 5, 5, 4, 4, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
4317 };
4318 MAT_SUPPER_TIMES_MAT_ASYM:
4319 for (size_t n = 0; n != n_rows * n_rows * (n_rows - 1) / 2; n++) {
4321 if (i[n] == r[n] + 1) (*this)(r[n], c[n]) = T(0); // initialize
4322 if (i[n] != c[n]) (*this)(r[n], c[n]) += mat_L(r[n], i[n]) * mat_R(i[n], c[n]);
4323 }
4324 for (size_t c = 0; c != n_cols; c++) { (*this)(n_rows - 1, c) = T(0); }
4325
4326 return *this;
4327 }
4328
4350 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
4351 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
4352 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
4353 std::enable_if_t<(type1 == MatType::SUPPER && (type2 == MatType::SYM || type2 == MatType::NORMAL)),
4354 bool> = true>
4355 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
4356 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
4357 FLAMES_PRAGMA(INLINE off)
4358 static_assert(n_rows == rows_, "Matrix dimension should meet.");
4359 static_assert(n_cols == cols_, "Matrix dimension should meet.");
4360 static const size_t c[224] = {
4361 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
4362 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2,
4363 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
4364 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4365 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
4366 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
4367 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
4368 };
4369 static const size_t i[224] = {
4370 7, 6, 7, 5, 6, 7, 4, 5, 6, 7, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 7, 6, 7, 5,
4371 6, 7, 4, 5, 6, 7, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 7, 6, 7, 5, 6, 7, 4, 5,
4372 6, 7, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 7, 6, 7, 5, 6, 7, 4, 5, 6, 7, 3, 4,
4373 5, 6, 7, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 7, 6, 7, 5, 6, 7, 4, 5, 6, 7, 3, 4, 5, 6, 7, 2,
4374 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 7, 6, 7, 5, 6, 7, 4, 5, 6, 7, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6,
4375 7, 1, 2, 3, 4, 5, 6, 7, 7, 6, 7, 5, 6, 7, 4, 5, 6, 7, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 1, 2, 3,
4376 4, 5, 6, 7, 7, 6, 7, 5, 6, 7, 4, 5, 6, 7, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7,
4377 };
4378 static const size_t r[224] = {
4379 6, 5, 5, 4, 4, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 6, 5, 5, 4,
4380 4, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 6, 5, 5, 4, 4, 4, 3, 3,
4381 3, 3, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 6, 5, 5, 4, 4, 4, 3, 3, 3, 3, 2, 2,
4382 2, 2, 2, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 6, 5, 5, 4, 4, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 1,
4383 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 6, 5, 5, 4, 4, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1,
4384 1, 0, 0, 0, 0, 0, 0, 0, 6, 5, 5, 4, 4, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 0, 0, 0,
4385 0, 0, 0, 0, 6, 5, 5, 4, 4, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
4386 };
4387 MAT_SUPPER_TIMES_MAT_NORMAL_OR_SYM:
4388 for (size_t n = 0; n != n_rows * n_rows * (n_rows - 1) / 2; n++) {
4390 if (i[n] == r[n] + 1) (*this)(r[n], c[n]) = T(0); // initialize
4391 (*this)(r[n], c[n]) += mat_L(r[n], i[n]) * mat_R(i[n], c[n]);
4392 }
4393 for (size_t c = 0; c != n_cols; c++) { (*this)(n_rows - 1, c) = T(0); }
4394 return *this;
4395 }
4396
4418 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
4419 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
4420 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
4421 std::enable_if_t<(type1 == MatType::SLOWER && type2 == MatType::SCALAR), bool> = true>
4422 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
4423 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
4424 static_assert(n_rows == rows_, "Matrix dimension should meet.");
4425 static_assert(n_cols == cols_, "Matrix dimension should meet.");
4426 MAT_SLOWER_TIMES_MAT_SCALAR:
4427 for (size_t i = 0; i != (n_rows - 1) * n_rows / 2; ++i) {
4429 _data[i] = mat_L[i] * mat_R[0];
4430 }
4431 return *this;
4432 }
4433
4455 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
4456 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
4457 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
4458 std::enable_if_t<(type1 == MatType::SLOWER && type2 == MatType::DIAGONAL), bool> = true>
4459 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
4460 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
4461 static_assert(n_rows == rows_, "Matrix dimension should meet.");
4462 static_assert(n_cols == cols_, "Matrix dimension should meet.");
4463 static const size_t c[28] = {
4464 0, 0, 1, 0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6,
4465 };
4466 static const size_t i[28] = {
4467 0, 0, 1, 0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6,
4468 };
4469 static const size_t r[28] = {
4470 1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7,
4471 };
4472 MAT_SLOWER_TIMES_MAT_DIAG:
4473 for (size_t n = 0; n != n_rows * (n_rows - 1) / 2; n++) {
4475 (*this)(r[n], c[n]) = mat_L(r[n], i[n]) * mat_R(i[n], c[n]);
4476 }
4477 return *this;
4478 }
4479
4501 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
4502 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
4503 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
4504 std::enable_if_t<(type1 == MatType::SLOWER && type2 == MatType::UPPER), bool> = true>
4505 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
4506 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
4507 FLAMES_PRAGMA(INLINE off)
4508 static_assert(n_rows == rows_, "Matrix dimension should meet.");
4509 static_assert(n_cols == cols_, "Matrix dimension should meet.");
4510 static const size_t c[168] = {
4511 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5,
4512 6, 6, 7, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7,
4513 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 4, 4,
4514 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 5, 5, 5, 5, 5, 5,
4515 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7,
4516 };
4517 static const size_t i[168] = {
4518 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
4519 0, 1, 0, 1, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2,
4520 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1,
4521 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5,
4522 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6,
4523 };
4524 static const size_t r[168] = {
4525 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
4526 2, 2, 2, 2, 7, 7, 7, 6, 6, 6, 5, 5, 5, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
4527 7, 7, 7, 7, 6, 6, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 7, 7,
4528 7, 7, 7, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 7, 7, 7, 7, 7, 7,
4529 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
4530 };
4531 MAT_SLOWER_TIMES_MAT_UPPER:
4532 for (size_t n = 0; n != (n_rows * n_rows * n_rows - n_rows) / 3; n++) {
4534 if (i[n] == 0) (*this)(r[n], c[n]) = 0; // initialize
4535 (*this)(r[n], c[n]) += mat_L(r[n], i[n]) * mat_R(i[n], c[n]);
4536 }
4537 for (size_t c = 0; c != n_cols; c++) { (*this)(0, c) = T(0); }
4538
4539 return *this;
4540 }
4541
4563 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
4564 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
4565 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
4566 std::enable_if_t<(type1 == MatType::SLOWER && type2 == MatType::LOWER), bool> = true>
4567 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
4568 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
4569 FLAMES_PRAGMA(INLINE off)
4570 static_assert(n_rows == rows_, "Matrix dimension should meet.");
4571 static_assert(n_cols == cols_, "Matrix dimension should meet.");
4572 static const size_t c[84] = {
4573 0, 1, 2, 3, 4, 5, 6, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 0, 0, 0, 1, 1, 1, 2, 2, 2,
4574 3, 3, 3, 4, 4, 4, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 0, 0, 0, 0, 0, 1,
4575 1, 1, 1, 1, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
4576 };
4577 static const size_t i[84] = {
4578 0, 1, 2, 3, 4, 5, 6, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 0, 1, 2, 1, 2, 3, 2, 3, 4,
4579 3, 4, 5, 4, 5, 6, 0, 1, 2, 3, 1, 2, 3, 4, 2, 3, 4, 5, 3, 4, 5, 6, 0, 1, 2, 3, 4, 1,
4580 2, 3, 4, 5, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6,
4581 };
4582 static const size_t r[84] = {
4583 1, 2, 3, 4, 5, 6, 7, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 3, 3, 3, 4, 4, 4, 5, 5, 5,
4584 6, 6, 6, 7, 7, 7, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 5, 5, 5, 5, 5, 6,
4585 6, 6, 6, 6, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
4586 };
4587 MAT_SLOWER_TIMES_MAT_LOWER:
4588 for (size_t n = 0; n != (n_rows * n_rows * n_rows - n_rows) / 6; n++) {
4590 if (i[n] == c[n]) (*this)(r[n], c[n]) = 0; // initialize
4591 (*this)(r[n], c[n]) += mat_L(r[n], i[n]) * mat_R(i[n], c[n]);
4592 }
4593 return *this;
4594 }
4595
4617 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
4618 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
4619 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
4620 std::enable_if_t<(type1 == MatType::SLOWER && type2 == MatType::SUPPER), bool> = true>
4621 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
4622 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
4623 FLAMES_PRAGMA(INLINE off)
4624 static_assert(n_rows == rows_, "Matrix dimension should meet.");
4625 static_assert(n_cols == cols_, "Matrix dimension should meet.");
4626 static const size_t c[140] = {
4627 1, 1, 1, 1, 1, 1, 1, 2, 3, 4, 5, 6, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7,
4628 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, 4, 4, 4, 4, 4, 4, 4, 4,
4629 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
4630 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
4631 };
4632 static const size_t i[140] = {
4633 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
4634 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3,
4635 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4,
4636 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6,
4637 };
4638 static const size_t r[140] = {
4639 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
4640 7, 7, 7, 6, 6, 6, 5, 5, 5, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 7, 7, 7, 7, 6, 6, 6, 6,
4641 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5,
4642 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7,
4643 };
4644 MAT_SLOWER_TIMES_MAT_SUPPER:
4645 for (size_t n = 0;
4646 n != (2 * (n_rows - 1) * (n_rows - 1) * (n_rows - 1) + 3 * (n_rows - 1) * (n_rows - 1) + (n_rows - 1)) / 6;
4647 n++) {
4649 if (i[n] == 0) (*this)(r[n], c[n]) = 0; // initialize
4650 (*this)(r[n], c[n]) += mat_L(r[n], i[n]) * mat_R(i[n], c[n]);
4651 }
4652 for (size_t r = 0; r != n_rows; r++) { (*this)(r, 0) = T(0); }
4653 for (size_t c = 1; c != n_cols; c++) { (*this)(0, c) = T(0); }
4654
4655 return *this;
4656 }
4657
4680 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
4681 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
4682 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
4683 std::enable_if_t<(type1 == MatType::SLOWER && type2 == MatType::SLOWER), bool> = true>
4684 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
4685 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
4686 FLAMES_PRAGMA(INLINE off)
4687 static_assert(n_rows == rows_, "Matrix dimension should meet.");
4688 static_assert(n_cols == cols_, "Matrix dimension should meet.");
4689 static const size_t c[56] = {
4690 0, 1, 2, 3, 4, 5, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3,
4691 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
4692 };
4693 static const size_t i[56] = {
4694 1, 2, 3, 4, 5, 6, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 1, 2, 3, 2, 3, 4, 3, 4, 5, 4, 5, 6,
4695 1, 2, 3, 4, 2, 3, 4, 5, 3, 4, 5, 6, 1, 2, 3, 4, 5, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6,
4696 };
4697 static const size_t r[56] = {
4698 2, 3, 4, 5, 6, 7, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7,
4699 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
4700 };
4701 MAT_SLOWER_TIMES_MAT_SLOWER:
4702 for (size_t n = 0; n != ((n_rows - 1) * (n_rows - 1) * (n_rows - 1) - (n_rows - 1)) / 6; n++) {
4704 if (i[n] == 1 + c[n]) (*this)(r[n], c[n]) = 0; // initialize
4705 (*this)(r[n], c[n]) += mat_L(r[n], i[n]) * mat_R(i[n], c[n]);
4706 }
4707 for (size_t i = 0; i != n_rows - 1; i++) { (*this)(i, i - 1) = T(0); }
4708
4709 return *this;
4710 }
4711
4733 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
4734 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
4735 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
4736 std::enable_if_t<(type1 == MatType::SLOWER && type2 == MatType::ASYM), bool> = true>
4737 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
4738 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
4739 FLAMES_PRAGMA(INLINE off)
4740 static_assert(n_rows == rows_, "Matrix dimension should meet.");
4741 static_assert(n_cols == cols_, "Matrix dimension should meet.");
4742 static const size_t c[224] = {
4743 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
4744 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2,
4745 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
4746 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4747 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
4748 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
4749 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
4750 };
4751 static const size_t i[224] = {
4752 0, 0, 1, 0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6, 0, 0, 1, 0,
4753 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6, 0, 0, 1, 0, 1, 2, 0, 1,
4754 2, 3, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6, 0, 0, 1, 0, 1, 2, 0, 1, 2, 3, 0, 1,
4755 2, 3, 4, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6, 0, 0, 1, 0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4, 0,
4756 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6, 0, 0, 1, 0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4,
4757 5, 0, 1, 2, 3, 4, 5, 6, 0, 0, 1, 0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 0, 1, 2,
4758 3, 4, 5, 6, 0, 0, 1, 0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6,
4759 };
4760 static const size_t r[224] = {
4761 1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 1, 2, 2, 3,
4762 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 1, 2, 2, 3, 3, 3, 4, 4,
4763 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5,
4764 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6,
4765 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6,
4766 6, 7, 7, 7, 7, 7, 7, 7, 1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7,
4767 7, 7, 7, 7, 1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7,
4768 };
4769 MAT_SLOWER_TIMES_MAT_ASYM:
4770 for (size_t n = 0; n != n_rows * n_rows * (n_rows - 1) / 2; n++) {
4772 if (i[n] == 0) (*this)(r[n], c[n]) = 0; // initialize
4773 if (i[n] != c[n]) (*this)(r[n], c[n]) += mat_L(r[n], i[n]) * mat_R(i[n], c[n]);
4774 }
4775 for (size_t c = 0; c != n_cols; ++c) { (*this)(0, c) = T(0); }
4776 return *this;
4777 }
4778
4800 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
4801 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
4802 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
4803 std::enable_if_t<(type1 == MatType::SLOWER && (type2 == MatType::SYM || type2 == MatType::NORMAL)),
4804 bool> = true>
4805 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
4806 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
4807 FLAMES_PRAGMA(INLINE off)
4808 static_assert(n_rows == rows_, "Matrix dimension should meet.");
4809 static_assert(n_cols == cols_, "Matrix dimension should meet.");
4810 static const size_t c[224] = {
4811 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
4812 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2,
4813 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
4814 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4815 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
4816 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
4817 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
4818 };
4819 static const size_t i[224] = {
4820 0, 0, 1, 0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6, 0, 0, 1, 0,
4821 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6, 0, 0, 1, 0, 1, 2, 0, 1,
4822 2, 3, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6, 0, 0, 1, 0, 1, 2, 0, 1, 2, 3, 0, 1,
4823 2, 3, 4, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6, 0, 0, 1, 0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4, 0,
4824 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6, 0, 0, 1, 0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4,
4825 5, 0, 1, 2, 3, 4, 5, 6, 0, 0, 1, 0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 0, 1, 2,
4826 3, 4, 5, 6, 0, 0, 1, 0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6,
4827 };
4828 static const size_t r[224] = {
4829 1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 1, 2, 2, 3,
4830 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 1, 2, 2, 3, 3, 3, 4, 4,
4831 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5,
4832 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6,
4833 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6,
4834 6, 7, 7, 7, 7, 7, 7, 7, 1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7,
4835 7, 7, 7, 7, 1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7,
4836 };
4837 MAT_SLOWER_TIMES_MAT_NORMAL_OR_MAT_SYM:
4838 for (size_t n = 0; n != n_rows * n_rows * (n_rows - 1) / 2; n++) {
4840 if (i[n] == 0) (*this)(r[n], c[n]) = 0; // initialize
4841 (*this)(r[n], c[n]) += mat_L(r[n], i[n]) * mat_R(i[n], c[n]);
4842 }
4843 for (size_t c = 0; c != n_cols; ++c) { (*this)(0, c) = T(0); }
4844 return *this;
4845 }
4846
4868 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
4869 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
4870 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
4871 std::enable_if_t<(type1 == MatType::ASYM && type2 == MatType::DIAGONAL), bool> = true>
4872 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
4873 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
4874 static_assert(n_rows == rows_, "Matrix dimension should meet.");
4875 static_assert(n_cols == cols_, "Matrix dimension should meet.");
4876 MAT_ASYM_TIMES_MAT_DIAG:
4877 for (size_t i = 0; i != n_rows; ++i) {
4879 for (size_t j = 0; j != n_rows; ++j) {
4880 FLAMES_PRAGMA(LOOP_FLATTEN)
4881 if (i != j) (*this)(i, j) = mat_L(i, j) * mat_R[j];
4882 }
4883 }
4884 for (size_t c = 0; c != n_cols; ++c) { (*this)(c, c) = T(0); }
4885 return *this;
4886 }
4887
4909 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
4910 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
4911 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
4912 std::enable_if_t<(type1 == MatType::ASYM && type2 == MatType::SCALAR), bool> = true>
4913 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
4914 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
4915 static_assert(n_rows == rows_, "Matrix dimension should meet.");
4916 static_assert(n_cols == cols_, "Matrix dimension should meet.");
4917 MAT_ASYM_TIMES_MAT_SCAL:
4918 for (size_t i = 0; i != n_rows; ++i) {
4920 for (size_t j = i + 1; j != n_rows; ++j) {
4921 FLAMES_PRAGMA(LOOP_FLATTEN)
4922 if (i != j) (*this)(i, j) = mat_L(i, j) * mat_R[0];
4923 }
4924 }
4925 return *this;
4926 }
4927
4949 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
4950 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
4951 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
4952 std::enable_if_t<(type1 == MatType::ASYM && type2 == MatType::UPPER), bool> = true>
4953 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
4954 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
4955 static_assert(n_rows == rows_, "Matrix dimension should meet.");
4956 static_assert(n_cols == cols_, "Matrix dimension should meet.");
4957 static const size_t r[288] = {
4958 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
4959 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
4960 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
4961 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
4962 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4963 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
4964 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
4965 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
4966 };
4967 static const size_t i[288] = {
4968 0, 0, 1, 0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 7,
4969 0, 0, 1, 0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 7,
4970 0, 0, 1, 0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 7,
4971 0, 0, 1, 0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 7,
4972 0, 0, 1, 0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 7,
4973 0, 0, 1, 0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 7,
4974 0, 0, 1, 0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 7,
4975 0, 0, 1, 0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 7,
4976 };
4977 static const size_t c[288] = {
4978 0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7,
4979 0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7,
4980 0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7,
4981 0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7,
4982 0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7,
4983 0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7,
4984 0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7,
4985 0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7,
4986 };
4987 MAT_ASYM_TIMES_MAT_UPPER:
4988 for (size_t n = 0; n != n_rows * n_rows * (n_rows + 1) / 2; n++) {
4990 if (i[n] == 0) (*this)(r[n], c[n]) = 0; // initialize
4991 if (r[n] != i[n]) (*this)(r[n], c[n]) += mat_L(r[n], i[n]) * mat_R(i[n], c[n]);
4992 }
4993 return *this;
4994 }
4995
5017 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
5018 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
5019 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
5020 std::enable_if_t<(type1 == MatType::ASYM && type2 == MatType::LOWER), bool> = true>
5021 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
5022 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
5023 static_assert(n_rows == rows_, "Matrix dimension should meet.");
5024 static_assert(n_cols == cols_, "Matrix dimension should meet.");
5025 static const size_t r[288] = {
5026 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5027 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5028 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
5029 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
5030 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
5031 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5032 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
5033 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
5034 };
5035 static const size_t i[288] = {
5036 7, 6, 7, 5, 6, 7, 4, 5, 6, 7, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7,
5037 7, 6, 7, 5, 6, 7, 4, 5, 6, 7, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7,
5038 7, 6, 7, 5, 6, 7, 4, 5, 6, 7, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7,
5039 7, 6, 7, 5, 6, 7, 4, 5, 6, 7, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7,
5040 7, 6, 7, 5, 6, 7, 4, 5, 6, 7, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7,
5041 7, 6, 7, 5, 6, 7, 4, 5, 6, 7, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7,
5042 7, 6, 7, 5, 6, 7, 4, 5, 6, 7, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7,
5043 7, 6, 7, 5, 6, 7, 4, 5, 6, 7, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7,
5044 };
5045 static const size_t c[288] = {
5046 7, 6, 6, 5, 5, 5, 4, 4, 4, 4, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
5047 7, 6, 6, 5, 5, 5, 4, 4, 4, 4, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
5048 7, 6, 6, 5, 5, 5, 4, 4, 4, 4, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
5049 7, 6, 6, 5, 5, 5, 4, 4, 4, 4, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
5050 7, 6, 6, 5, 5, 5, 4, 4, 4, 4, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
5051 7, 6, 6, 5, 5, 5, 4, 4, 4, 4, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
5052 7, 6, 6, 5, 5, 5, 4, 4, 4, 4, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
5053 7, 6, 6, 5, 5, 5, 4, 4, 4, 4, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
5054 };
5055 MAT_ASYM_TIMES_MAT_LOWER:
5056 for (size_t n = 0; n != n_rows * n_rows * (n_rows + 1) / 2; n++) {
5058 if (i[n] == c[n]) (*this)(r[n], c[n]) = 0; // initialize
5059 if (r[n] != i[n]) (*this)(r[n], c[n]) += mat_L(r[n], i[n]) * mat_R(i[n], c[n]);
5060 }
5061 return *this;
5062 }
5063
5085 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
5086 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
5087 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
5088 std::enable_if_t<(type1 == MatType::ASYM && type2 == MatType::SUPPER), bool> = true>
5089 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
5090 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
5091 static_assert(n_rows == rows_, "Matrix dimension should meet.");
5092 static_assert(n_cols == cols_, "Matrix dimension should meet.");
5093 static const size_t r[224] = {
5094 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
5095 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2,
5096 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
5097 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
5098 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5099 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
5100 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
5101 };
5102 static const size_t i[224] = {
5103 0, 0, 1, 0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6, 0, 0, 1, 0,
5104 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6, 0, 0, 1, 0, 1, 2, 0, 1,
5105 2, 3, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6, 0, 0, 1, 0, 1, 2, 0, 1, 2, 3, 0, 1,
5106 2, 3, 4, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6, 0, 0, 1, 0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4, 0,
5107 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6, 0, 0, 1, 0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4,
5108 5, 0, 1, 2, 3, 4, 5, 6, 0, 0, 1, 0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 0, 1, 2,
5109 3, 4, 5, 6, 0, 0, 1, 0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6,
5110 };
5111 static const size_t c[224] = {
5112 1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 1, 2, 2, 3,
5113 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 1, 2, 2, 3, 3, 3, 4, 4,
5114 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5,
5115 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6,
5116 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6,
5117 6, 7, 7, 7, 7, 7, 7, 7, 1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7,
5118 7, 7, 7, 7, 1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7,
5119 };
5120 MAT_ASYM_TIMES_SUPPER:
5121 for (size_t n = 0; n != n_rows * n_rows * (n_rows - 1) / 2; n++) {
5123 if (i[n] == 0) (*this)(r[n], c[n]) = 0; // initialize
5124 if (r[n] != i[n]) (*this)(r[n], c[n]) += mat_L(r[n], i[n]) * mat_R(i[n], c[n]);
5125 }
5126 for (size_t r = 0; r != n_rows; r++) { (*this)(r, 0) = T(0); }
5127
5128 return *this;
5129 }
5130
5152 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
5153 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
5154 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
5155 std::enable_if_t<(type1 == MatType::ASYM && type2 == MatType::SLOWER), bool> = true>
5156 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
5157 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
5158 static_assert(n_rows == rows_, "Matrix dimension should meet.");
5159 static_assert(n_cols == cols_, "Matrix dimension should meet.");
5160 static const size_t r[224] = {
5161 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
5162 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2,
5163 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
5164 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
5165 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5166 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
5167 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
5168 };
5169 static const size_t i[224] = {
5170 7, 6, 7, 5, 6, 7, 4, 5, 6, 7, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 7, 6, 7, 5,
5171 6, 7, 4, 5, 6, 7, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 7, 6, 7, 5, 6, 7, 4, 5,
5172 6, 7, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 7, 6, 7, 5, 6, 7, 4, 5, 6, 7, 3, 4,
5173 5, 6, 7, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 7, 6, 7, 5, 6, 7, 4, 5, 6, 7, 3, 4, 5, 6, 7, 2,
5174 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 7, 6, 7, 5, 6, 7, 4, 5, 6, 7, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6,
5175 7, 1, 2, 3, 4, 5, 6, 7, 7, 6, 7, 5, 6, 7, 4, 5, 6, 7, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 1, 2, 3,
5176 4, 5, 6, 7, 7, 6, 7, 5, 6, 7, 4, 5, 6, 7, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7,
5177 };
5178 static const size_t c[224] = {
5179 6, 5, 5, 4, 4, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 6, 5, 5, 4,
5180 4, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 6, 5, 5, 4, 4, 4, 3, 3,
5181 3, 3, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 6, 5, 5, 4, 4, 4, 3, 3, 3, 3, 2, 2,
5182 2, 2, 2, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 6, 5, 5, 4, 4, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 1,
5183 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 6, 5, 5, 4, 4, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1,
5184 1, 0, 0, 0, 0, 0, 0, 0, 6, 5, 5, 4, 4, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 0, 0, 0,
5185 0, 0, 0, 0, 6, 5, 5, 4, 4, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
5186 };
5187 MAT_ASYM_TIMES_SLOWER:
5188 for (size_t n = 0; n != n_rows * n_rows * (n_rows - 1) / 2; n++) {
5190 if (i[n] == c[n] + 1) (*this)(r[n], c[n]) = 0; // initialize
5191 if (r[n] != i[n]) (*this)(r[n], c[n]) += mat_L(r[n], i[n]) * mat_R(i[n], c[n]);
5192 }
5193 for (size_t r = 0; r != n_rows; r++) { (*this)(r, n_cols - 1) = T(0); }
5194
5195 return *this;
5196 }
5197
5220 template <
5221 template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
5222 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1, typename T2,
5223 MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
5224 std::enable_if_t<(type1 == MatType::ASYM && (type2 == MatType::NORMAL || type2 == MatType::SYM)), bool> = true>
5225 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
5226 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
5227 FLAMES_PRAGMA(INLINE off)
5228 static_assert(n_rows == rows_, "Matrix dimension should meet.");
5229 static_assert(n_cols == cols_, "Matrix dimension should meet.");
5230 MAT_ASYM_TIMES_MAT_NORMAL:
5231 for (size_t i = 0; i != comm; ++i) {
5232 GEMM_r:
5233 for (size_t r = 0; r != n_rows; ++r) {
5235 GEMM_c:
5236 for (size_t c = 0; c != n_cols; ++c) {
5237 FLAMES_PRAGMA(LOOP_FLATTEN)
5238 if (i == 0) (*this)(r, c) = T(0); // initialize
5239 if (r != i) (*this)(r, c) += mat_L(r, i) * mat_R(i, c);
5240 }
5241 }
5242 }
5243 return *this;
5244 }
5245
5267 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
5268 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
5269 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
5270 std::enable_if_t<(type1 == MatType::ASYM && type2 == MatType::ASYM), bool> = true>
5271 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
5272 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
5273 FLAMES_PRAGMA(INLINE off)
5274 static_assert(n_rows == rows_, "Matrix dimension should meet.");
5275 static_assert(n_cols == cols_, "Matrix dimension should meet.");
5276 MAT_ASYM_TIMES_MAT_ASYM:
5277 GEMM_r:
5278 for (size_t r = 0; r != n_rows; ++r) {
5280 GEMM_c:
5281 for (size_t c = 0; c != n_cols; ++c) {
5282 for (size_t i = 0; i != comm; ++i) {
5283 FLAMES_PRAGMA(LOOP_FLATTEN)
5284 if (i == 0) (*this)(r, c) = T(0); // initialize
5285 if (i != c && i != r) (*this)(r, c) += mat_L(r, i) * mat_R(i, c);
5286 }
5287 }
5288 }
5289 return *this;
5290 }
5291
5314 template <
5315 template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
5316 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1, typename T2,
5317 MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
5318 std::enable_if_t<(std::is_same<T1, bool>::value) && ((type1 == MatType::NORMAL && type2 == MatType::NORMAL) ||
5319 (type1 == MatType::NORMAL && type2 == MatType::SYM) ||
5320 (type1 == MatType::SYM && type2 == MatType::NORMAL) ||
5321 (type1 == MatType::SYM && type2 == MatType::SYM)),
5322 bool> = true>
5323 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
5324 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
5325 FLAMES_PRAGMA(INLINE off)
5326 static_assert(n_rows == rows_, "Matrix dimension should meet.");
5327 static_assert(n_cols == cols_, "Matrix dimension should meet.");
5328 this->setZero();
5329 for (size_t c = 0; c < n_cols; ++c) {
5330 for (size_t i = 0; i < comm; ++i) {
5332 for (size_t r = 0; r < n_rows; ++r) {
5333 FLAMES_PRAGMA(UNROLL)
5334 (*this)(r, c) += mat_L(r, i) * mat_R(i, c);
5335 }
5336 }
5337 }
5338
5339 return *this;
5340 }
5341
5364 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
5365 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
5366 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
5367 std::enable_if_t<(std::is_same<T2, bool>::value && !std::is_same<T1, bool>::value) &&
5368 ((type1 == MatType::NORMAL && type2 == MatType::NORMAL) ||
5369 (type1 == MatType::NORMAL && type2 == MatType::SYM) ||
5370 (type1 == MatType::SYM && type2 == MatType::NORMAL) ||
5371 (type1 == MatType::SYM && type2 == MatType::SYM)),
5372 bool> = true>
5373 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
5374 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
5375 FLAMES_PRAGMA(INLINE off)
5376 static_assert(n_rows == rows_, "Matrix dimension should meet.");
5377 static_assert(n_cols == cols_, "Matrix dimension should meet.");
5378 GEMM_r:
5379 for (size_t r = 0; r != n_rows; ++r) {
5381 GEMM_c:
5382 for (size_t c = 0; c != n_cols; ++c) {
5383 GEMM:
5384 for (size_t i = 0; i != comm; ++i) {
5385 FLAMES_PRAGMA(LOOP_FLATTEN)
5386 if (i == 0) (*this)(r, c) = T(0); // initialize
5387 if (mat_R(i, c) != 0) (*this)(r, c) += mat_L(r, i);
5388 }
5389 }
5390 }
5391 return *this;
5392 }
5393
5413 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
5414 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
5415 typename T2, size_t rows_, size_t cols_, MatType type1, MatType type2,
5416 std::enable_if_t<rows_ == n_rows && cols_ == n_cols && type1 == type && type2 == type, bool> = true>
5417 Mat& emul(const M1<T1, rows_, cols_, type1, _unused1...>& mat_L,
5418 const M2<T2, rows_, cols_, type2, _unused2...>& mat_R) {
5419 for (size_t i = 0; i != size(); ++i) {
5421 _data[i] = mat_L[i] * mat_R[i];
5422 }
5423 return *this;
5424 }
5425
5440 template <template <class, size_t, size_t, MatType, class...> typename M, typename... _unused, typename T2,
5441 MatType type2, size_t rows_, size_t cols_>
5443 assert(c < n_cols && "Take the specific col by index requires 'The index should be smaller than the number of "
5444 "the matrix's columns.'.");
5445 static_assert(size() == rows_, "Element number should be rows_ in Mat::col(mat, index).");
5446 for (size_t i = 0; i != size(); ++i) {
5448 _data[i] = mat(i, c);
5449 }
5450 return *this;
5451 }
5452
5453 template <template <class, size_t, size_t, MatType, class...> typename M, typename... _unused, typename T2,
5454 MatType type2, size_t rows_, size_t cols_>
5455 [[deprecated("Use .col_ to create a MatRefCol to write a column instead.")]] void
5457 assert(c < n_cols && "Take the specific col by index requires 'The index should be smaller than the number of "
5458 "the matrix's columns.'.");
5459 assert(mat.size() == n_rows && "Element number should be n_rows in Mat::col(index, mat).");
5460 for (int i = 0; i != mat.size(); ++i) {
5462 (*this)(i, c) = mat[i];
5463 }
5464 }
5465
5481 assert(c < n_cols && "Take the specific col by index requires 'The index should be smaller than the number of "
5482 "the matrix's columns.'.");
5484 for (size_t i = 0; i != n_rows; ++i) {
5486 mat(i, 0) = (*this)(i, c);
5487 }
5488 return mat;
5489 }
5490
5497 assert(index < n_cols && "Take the specific col by index requires 'The index should be smaller than the number "
5498 "of the matrix's columns.'.");
5499 return { *this, index };
5500 }
5501
5503 assert(index < n_cols && "Take the specific col by index requires 'The index should be smaller than the number "
5504 "of the matrix's columns.'.");
5505 return { *this, index };
5506 }
5507
5523 template <template <class, size_t, size_t, MatType, class...> typename M, typename... _unused, typename T2,
5524 MatType type2, size_t rows_, size_t cols_>
5526 assert(r < rows_ && "row should be smaller than rows_ of mat in Mat::row.");
5527 static_assert(size() == cols_, "The number of the Matrices' n_cols should meet.");
5528 for (size_t j = 0; j != size(); ++j) {
5530 _data[j] = mat(r, j);
5531 }
5532 return *this;
5533 }
5534
5550 assert(r < n_rows && "Take the specific row by index requires 'The index should be smaller than the number of "
5551 "the matrix's rows.'.");
5553 for (size_t j = 0; j != n_cols; ++j) {
5555 mat(0, j) = (*this)(r, j);
5556 }
5557 return mat;
5558 }
5559
5560 // /**
5561 // * @brief Take a row of a matrix by index as a read only view.
5562 // *
5563 // * @return (MatViewRow<Index, T, n_rows, n_cols, MatType::NORMAL, MType<type>>) The read only a row vector view.
5564 // */
5565 // MatViewRow<T, n_rows, n_cols, MatType::NORMAL, MType<type>> Row_() const {
5566 // static_assert(Index > int(0), "Take the specific row by index requires 'The index can't be smaller than
5567 // 0'."); static_assert(Index < n_rows, "Take the specific row by index requires 'The index should be smaller
5568 // than the "
5569 // "number of the matrix's rows.'.");
5570 // return *this;
5571 // }
5572
5589 template <template <class, size_t, size_t, MatType, class...> typename M, typename... _unused, typename T2,
5590 MatType type2, size_t rows_, size_t cols_>
5591 Mat& cols(const M<T2, rows_, cols_, type2, _unused...>& mat, size_t first_col) {
5592 assert(first_col < n_cols && "Take the successive n_cols by index requires 'The indexes should be smaller than "
5593 "the number of the matrix's columns.'.");
5594 assert(first_col > int(0) &&
5595 "Take the successive n_cols by index requires 'The indexes can't be smaller than 0'.");
5596 static_assert(n_rows == rows_, "The number of the Matrices' rows should meet.");
5597 for (size_t j = 0; j != n_cols; ++j) {
5599 for (size_t i = 0; i != n_rows; ++i) {
5600 FLAMES_PRAGMA(LOOP_FLATTEN)
5601 (*this)(i, j) = mat(i, j + first_col);
5602 }
5603 }
5604 return *this;
5605 }
5606
5626 template <size_t _cols>
5628 assert(first_col < n_cols && "Take the successive n_cols by index requires 'The indexes should be smaller than "
5629 "the number of the matrix's columns.'.");
5630 assert(first_col > int(0) &&
5631 "Take the successive n_cols by index requires 'The indexes can't be smaller than 0'.");
5632 static_assert(_cols > int(1),
5633 "Take the successive n_cols by index requires 'The total number can't be smaller than 1'.");
5634
5636 for (size_t j = 0; j != _cols; ++j) {
5638 for (size_t i = 0; i != n_rows; ++i) {
5639 FLAMES_PRAGMA(LOOP_FLATTEN)
5640 mat(i, j) = (*this)(i, j + first_col);
5641 }
5642 }
5643 return mat;
5644 }
5651 template <size_t first_col, size_t last_col>
5653 static_assert(first_col > int(0),
5654 "Take the successive cols by index requires 'The first index can't be smaller than 0'.");
5655 static_assert(
5656 first_col < last_col,
5657 "Take the successive cols by index requires 'The first index should be smaller than the last index'.");
5658 static_assert(last_col < n_cols, "Take the successive cols by index requires 'The last index should be smaller "
5659 "than the number of the matrix's cols.'.");
5660 return *this;
5661 }
5662
5679 template <template <class, size_t, size_t, MatType, class...> typename M, typename... _unused, typename T2,
5680 MatType type2, size_t rows_, size_t cols_>
5681 Mat& rows(const M<T2, rows_, cols_, type2, _unused...>& mat, size_t first_row) {
5682 assert(first_row < n_rows && "Take the successive n_rows by index requires 'The indexes should be smaller than "
5683 "the number of the matrix's rows.'.");
5684 assert(first_row > int(0) &&
5685 "Take the successive n_rows by index requires 'The indexes can't be smaller than 0'.");
5686 static_assert(n_cols == cols_, "The number of the Matrices' cols should meet.");
5687 for (size_t i = 0; i != n_rows; ++i) {
5689 for (size_t j = 0; j != n_cols; ++j) {
5690 FLAMES_PRAGMA(LOOP_FLATTEN)
5691 (*this)(i, j) = mat(i + first_row, j);
5692 }
5693 }
5694 return *this;
5695 }
5696
5717 template <size_t _rows>
5719 assert(first_row < n_rows && "Take the successive n_rows by index requires 'The indexes should be smaller than "
5720 "the number of the matrix's rows.'.");
5721 assert(first_row > int(0) &&
5722 "Take the successive n_rows by index requires 'The indexes can't be smaller than 0'.");
5723 static_assert(_rows > int(1),
5724 "Take the successive n_rows by index requires 'The total number can't be smaller than 1'.");
5725
5727 for (size_t i = 0; i != _rows; ++i) {
5729 for (size_t j = 0; j != n_cols; ++j) {
5730 FLAMES_PRAGMA(LOOP_FLATTEN)
5731 mat(i, j) = (*this)(i + first_row, j);
5732 }
5733 }
5734 return mat;
5735 }
5736
5743 template <size_t first_row, size_t last_row>
5745 static_assert(
5746 first_row < last_row,
5747 "Take the successive rows by index requires 'The first index should be smaller than the last index'.");
5748 static_assert(last_row < n_rows, "Take the successive rows by index requires 'The last index should be smaller "
5749 "than the number of the matrix's rows.'.");
5750 return *this;
5751 }
5752
5771 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1, typename M2,
5772 typename T1, MatType type1, size_t rows_, size_t cols_>
5773 Mat& rows(const M1<T1, rows_, cols_, type1, _unused1...>& mat, M2 vector) {
5774 static_assert(n_cols == cols_, "The number of the Matrices' cols should meet.");
5775 for (size_t i = 0; i != n_rows; ++i) {
5777 assert(vector[i] > int(0) &&
5778 "Take the discrete n_rows by index requires 'The indexes can't be smaller than 0'.");
5779 assert(vector[i] < n_rows && "Take the discrete n_rows by index requires 'The indexes should be smaller "
5780 "than the number of the matrix's rows.'.");
5781 for (size_t j = 0; j != n_cols; ++j) {
5782 FLAMES_PRAGMA(LOOP_FLATTEN)
5783 (*this)(i, j) = mat(vector[i], j);
5784 }
5785 }
5786 return *this;
5787 }
5788
5808 template <size_t _rows, typename M2>
5811 for (size_t i = 0; i != _rows; ++i) {
5813 assert(vector[i] >= int(0) &&
5814 "Take the discrete n_rows by index requires 'The indexes can't be smaller than 0'.");
5815 assert(vector[i] < n_rows && "Take the discrete n_rows by index requires 'The indexes should be smaller "
5816 "than the number of the matrix's rows.'.");
5817 for (size_t j = 0; j != n_cols; ++j) {
5818 FLAMES_PRAGMA(LOOP_FLATTEN)
5819 mat(i, j) = (*this)(vector[i], j);
5820 }
5821 }
5822 return mat;
5823 }
5824
5843 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1, typename M2,
5844 typename T1, MatType type1, size_t rows_, size_t cols_>
5845 Mat& cols(const M1<T1, rows_, cols_, type1, _unused1...>& mat, M2 vector) {
5846 static_assert(n_rows == rows_, "The number of the Matrices' rows should meet.");
5847 for (size_t j = 0; j != n_cols; ++j) {
5849 assert(vector[j] >= int(0) &&
5850 "Take the discrete n_cols by index requires 'The indexes can't be smaller than 0'.");
5851 assert(vector[j] < n_cols && "Take the discrete n_cols by index requires 'The indexes should be smaller "
5852 "than the number of the matrix's cols.'.");
5853 for (size_t i = 0; i != n_rows; ++i) {
5854 FLAMES_PRAGMA(LOOP_FLATTEN)
5855 (*this)(i, j) = mat(i, vector[j]);
5856 }
5857 }
5858 return *this;
5859 }
5860
5880 template <size_t _cols, typename M2>
5883 for (size_t j = 0; j != _cols; ++j) {
5885 assert(vector[j] >= int(0) &&
5886 "Take the discrete n_cols by index requires 'The indexes can't be smaller than 0'.");
5887 assert(vector[j] < n_cols && "Take the discrete n_cols by index requires 'The indexes should be smaller "
5888 "than the number of the matrix's cols.'.");
5889 for (size_t i = 0; i != n_cols; ++i) {
5890 FLAMES_PRAGMA(LOOP_FLATTEN)
5891 mat(i, j) = (*this)(i, vector[j]);
5892 }
5893 }
5894 return mat;
5895 }
5896
5904 for (size_t i = 0; i != size(); ++i) {
5906 if (_data[i] < 0) _data[i] = -_data[i];
5907 }
5908 return *this;
5909 }
5910
5925 template <template <class, size_t, size_t, MatType, class...> typename M, typename... _unused, typename T2,
5926 MatType type2>
5928 if (type == MatType::DIAGONAL || type == MatType::SCALAR || type == MatType::SYM) {
5929 // do nothing
5930 } else if (type == MatType::NORMAL) {
5931 MAT_TRANSPOSE_NORMAL:
5932 for (size_t i = 0; i != n_cols; ++i) {
5934 for (size_t j = 0; j != n_rows; ++j) {
5935 FLAMES_PRAGMA(LOOP_FLATTEN)
5936 _data[n_rows * i + j] = mat._data[n_rows * j + i];
5937 }
5938 }
5939 } else if (type == MatType::UPPER) {
5940 MAT_TRANSPOSE_UPPER:
5941 for (size_t i = 0; i != n_cols; ++i) {
5943 for (size_t j = i; j != n_rows; ++j) {
5944 FLAMES_PRAGMA(LOOP_FLATTEN)
5945 (*this)(i, j) = mat(j, i);
5946 }
5947 }
5948 } else if (type == MatType::LOWER) {
5949 MAT_TRANSPOSE_LOWER:
5950 for (size_t i = 0; i != n_cols; ++i) {
5952 for (size_t j = 0; j <= i; ++j) {
5953 FLAMES_PRAGMA(LOOP_FLATTEN)
5954 (*this)(i, j) = mat(j, i);
5955 }
5956 }
5957 } else if (type == MatType::SUPPER) {
5958 MAT_TRANSPOSE_SUPPER:
5959 for (size_t i = 0; i != n_cols; ++i) {
5961 for (size_t j = i; j != n_rows; ++j) {
5962 FLAMES_PRAGMA(LOOP_FLATTEN)
5963 (*this)(i, j) = mat(j, i);
5964 }
5965 }
5966 } else if (type == MatType::SLOWER) {
5967 MAT_TRANSPOSE_SLOWER:
5968 for (size_t i = 0; i != n_cols; ++i) {
5970 for (size_t j = i; j != n_rows; ++j) {
5971 FLAMES_PRAGMA(LOOP_FLATTEN)
5972 (*this)(i, j) = mat(j, i);
5973 }
5974 }
5975 } else if (type == MatType::ASYM) {
5976 MAT_TRANSPOSE_ASYM:
5977 for (size_t i = 0; i != n_cols; ++i) {
5979 for (size_t j = i + 1; j != n_rows; ++j) {
5980 FLAMES_PRAGMA(LOOP_FLATTEN)
5981 (*this)(i, j) = mat(j, i);
5982 }
5983 }
5984 } else {
5985 assert(!"Impossible");
5986 }
5987 return *this;
5988 }
5989
6004 template <typename... _unused, MatType _type = type,
6005 typename std::enable_if_t<_type == MatType::NORMAL, bool> = true>
6007 // Ref: https://stackoverflow.com/a/13401982/15080514
6008 static_assert(sizeof...(_unused) == 0, "Do not specify template arguments for Mat::t()!");
6009 static_assert(n_cols > 0 && n_rows > 0, "The matrix should have size when transposing.");
6011 MAT_TRANSPOSE_NORMAL:
6012 for (size_t i = 0; i != n_cols; ++i) {
6014 for (size_t j = 0; j != n_rows; ++j) {
6015 FLAMES_PRAGMA(LOOP_FLATTEN)
6016 mat(i, j) = (*this)(j, i);
6017 }
6018 }
6019 return mat;
6020 }
6021
6034 template <typename... _unused, MatType _type = type,
6035 typename std::enable_if_t<
6036 (_type == MatType::DIAGONAL || _type == MatType::SCALAR || _type == MatType::SYM), bool> = true>
6037 Mat t() const {
6038 static_assert(sizeof...(_unused) == 0, "Do not specify template arguments for Mat::t()!");
6039 return *this;
6040 }
6041
6056 template <typename... _unused, MatType _type = type,
6057 typename std::enable_if_t<_type == MatType::UPPER, bool> = true>
6059 static_assert(sizeof...(_unused) == 0, "Do not specify template arguments for Mat::t()!");
6060 static_assert(n_cols > 0 && n_rows > 0, "The matrix should have size when transposing.");
6062 MAT_TRANSPOSE_NORMAL:
6063 for (size_t i = 0; i != n_cols; ++i) {
6065 for (size_t j = 0; j != n_rows; ++j) {
6066 FLAMES_PRAGMA(LOOP_FLATTEN)
6067 mat(i, j) = (*this)(j, i);
6068 }
6069 }
6070 return mat;
6071 }
6072
6087 template <typename... _unused, MatType _type = type,
6088 typename std::enable_if_t<_type == MatType::LOWER, bool> = true>
6090 static_assert(sizeof...(_unused) == 0, "Do not specify template arguments for Mat::t()!");
6091 static_assert(n_cols > 0 && n_rows > 0, "The matrix should have size when transposing.");
6093 MAT_TRANSPOSE_LOWER:
6094 for (size_t i = 0; i != n_cols; ++i) {
6096 for (size_t j = i; j <= i; ++j) {
6097 FLAMES_PRAGMA(LOOP_FLATTEN)
6098 mat(j, i) = (*this)(i, j);
6099 }
6100 }
6101 return mat;
6102 }
6103
6118 template <typename... _unused, MatType _type = type,
6119 typename std::enable_if_t<_type == MatType::SUPPER, bool> = true>
6121 static_assert(sizeof...(_unused) == 0, "Do not specify template arguments for Mat::t()!");
6122 static_assert(n_cols > 0 && n_rows > 0, "The matrix should have size when transposing.");
6124 MAT_TRANSPOSE_SUPPER:
6125 for (size_t i = 0; i != n_cols - 1; ++i) {
6127 for (size_t j = i + 1; j != n_rows; ++j) {
6128 FLAMES_PRAGMA(LOOP_FLATTEN)
6129 mat(j, i) = (*this)(i, j);
6130 }
6131 }
6132 return mat;
6133 }
6134
6149 template <typename... _unused, MatType _type = type,
6150 typename std::enable_if_t<_type == MatType::SLOWER, bool> = true>
6152 static_assert(sizeof...(_unused) == 0, "Do not specify template arguments for Mat::t()!");
6153 static_assert(n_cols > 0 && n_rows > 0, "The matrix should have size when transposing.");
6155 MAT_TRANSPOSE_SLOWER:
6156 for (size_t i = 1; i != n_cols; ++i) {
6158 for (size_t j = i + 1; j != n_rows - 1; ++j) {
6159 FLAMES_PRAGMA(LOOP_FLATTEN)
6160 mat(j, i) = (*this)(i, j);
6161 }
6162 }
6163 return mat;
6164 }
6165
6180 template <typename... _unused, MatType _type = type, typename std::enable_if_t<_type == MatType::ASYM, bool> = true>
6181 Mat t() const {
6182 static_assert(n_cols > 0 && n_rows > 0, "The matrix should have size when transposing.");
6183 Mat mat;
6184 MAT_TRANSPOSE_ASYM:
6185 for (size_t i = 1; i != n_cols; ++i) {
6187 for (size_t j = i + 1; j != n_rows - 1; ++j) {
6188 FLAMES_PRAGMA(LOOP_FLATTEN)
6189 mat(j, i) = (*this)(i, j);
6190 }
6191 }
6192 return mat;
6193 }
6194
6200 MatViewT<T, n_cols, n_rows, tType(type)> t_() { return const_cast<T*>(_data); }
6201
6202 MatViewT<T, n_cols, n_rows, tType(type)> t_() const { return const_cast<T*>(_data); }
6203
6214 static_assert(type != MatType::UPPER, "Upper matrix cannot perform in place transpose.");
6215 static_assert(type != MatType::LOWER, "Lower matrix cannot perform in place transpose.");
6216 static_assert(type != MatType::SUPPER, "Strict upper matrix cannot perform in place transpose.");
6217 static_assert(type != MatType::SLOWER, "Strict lower matrix cannot perform in place transpose.");
6218 static_assert(n_rows == n_cols, "In-place transpose requires a square matrix.");
6219 if (type == MatType::NORMAL) {
6220 MAT_NORMAL_TRANSPOSE_SELF:
6221 for (size_t i = 0; i != n_cols; ++i) {
6223 for (size_t j = i; j != n_cols; ++j) {
6224 FLAMES_PRAGMA(LOOP_FLATTEN)
6225 std::swap(_data[n_cols * i + j], _data[n_cols * j + i]);
6226 }
6227 }
6228 } else if (type == MatType::ASYM) {
6229 MAT_AYSM_TRANSPOSE_SELF:
6230 for (size_t i = 0; i != n_cols * (n_cols - 1) / 2; ++i) {
6232 _data[i] = -_data[i];
6233 }
6234 }
6235 return *this;
6236 }
6237
6251 template <template <class, size_t, size_t, MatType, class...> typename M, typename... _unused, typename T2>
6253 MAT_OPP:
6254 for (size_t i = 0; i != size(); ++i) {
6256 _data[i] = -mat[i];
6257 }
6258 return *this;
6259 }
6260
6275 Mat opp() const {
6276 Mat mat;
6277 MAT_OPP:
6278 for (size_t i = 0; i != size(); ++i) {
6280 mat[i] = -_data[i];
6281 }
6282 return mat;
6283 }
6284
6291 FLAMES_PRAGMA(INLINE)
6292 return *this;
6293 }
6294
6305 MAT_OPP_SELF:
6306 for (size_t i = 0; i != size(); ++i) {
6308 _data[i] = -_data[i];
6309 }
6310 }
6311
6325 template <template <class, size_t, size_t, MatType, class...> typename M, typename... _unused, typename T2,
6326 MatType type2>
6328 static_assert(n_rows == n_cols, "Take the diagonal requires 'n_rows == n_cols'.");
6329 for (size_t i = 0; i != n_rows; ++i) {
6331 (*this)(i, i) = mat(i, i);
6332 }
6333 return *this;
6334 }
6335
6352 for (size_t i = 0; i != n_rows; ++i) {
6354 mat(i, i) = (*this)(i, i);
6355 }
6356 return mat;
6357 }
6358
6365 static_assert(n_rows == n_cols, "Take the diagonal requires 'n_rows == n_cols'.");
6366 return *this;
6367 }
6368
6382 template <template <class, size_t, size_t, MatType, class...> typename M, typename... _unused, typename T2,
6383 MatType type2>
6385 static_assert(n_cols == 1, "Diagonal vector has column number as 1.");
6386 for (size_t i = 0; i != n_rows; ++i) {
6388 _data[i] = mat(i, i);
6389 }
6390 return *this;
6391 }
6392
6408 static_assert(n_rows == n_cols, "Take the diagonal requires 'n_rows == n_cols'.");
6409 Vec<T, n_rows> mat;
6410 for (size_t i = 0; i != n_rows; ++i) {
6412 mat._data[i] = (*this)(i, i);
6413 }
6414 return mat;
6415 }
6416
6423 static_assert(n_rows == n_cols, "Take the diagonal requires 'n_rows == n_cols'.");
6424 return *this;
6425 }
6426
6440 template <template <class, size_t, size_t, MatType, class...> typename M, typename... _unused, typename T2,
6441 MatType type2>
6443 static_assert(n_rows == 1, "Diagonal vector has column number as 1.");
6444 for (size_t i = 0; i != n_cols; ++i) {
6446 _data[i] = mat(i, i);
6447 }
6448 return *this;
6449 }
6450
6466 static_assert(n_rows == n_cols, "Take the diagonal requires 'n_rows == n_cols'.");
6468 for (size_t i = 0; i != n_cols; ++i) {
6470 mat._data[i] = (*this)(i, i);
6471 }
6472 return mat;
6473 }
6474
6481 static_assert(n_rows == n_cols, "Take the diagonal requires 'n_rows == n_cols'.");
6482 return *this;
6483 }
6484
6498 template <template <class, size_t, size_t, MatType, class...> typename M, typename... _unused, typename T2,
6499 MatType type2>
6501 static_assert(n_rows == n_cols, "Take the off diagonal requires 'n_rows == n_cols'.");
6502 static_assert(type == MatType::NORMAL, "Take the off diagonal requires the matrix to be NORMAL.");
6503 for (size_t i = 0; i != n_rows; ++i) {
6505 for (size_t j = 0; j != n_cols; ++j) {
6506 FLAMES_PRAGMA(LOOP_FLATTEN)
6507 if (i != j) (*this)(i, j) = mat(i, j);
6508 else (*this)(i, j) = T(0);
6509 }
6510 }
6511 return *this;
6512 }
6513
6529 static_assert(n_rows == n_cols, "Take the off diagonal requires 'n_rows == n_cols'.");
6530 static_assert(type == MatType::NORMAL, "Take the off diagonal requires the matrix to be NORMAL.");
6532 for (size_t i = 0; i != n_rows; ++i) {
6534 for (size_t j = 0; j != n_cols; ++j) {
6535 FLAMES_PRAGMA(LOOP_FLATTEN)
6536 if (i != j) mat(i, j) = (*this)(i, j);
6537 else mat(i, j) = T(0);
6538 }
6539 }
6540 return mat;
6541 }
6542
6549 static_assert(n_rows == n_cols, "Take the off diagonal requires 'n_rows == n_cols'.");
6550 return *this;
6551 }
6552
6569 template <template <class, size_t, size_t, MatType, class...> typename M, typename... _unused, typename T2,
6570 MatType type2>
6572 static_assert(type == MatType::DIAGONAL, "'invDiag' is only used for diagonal matrix.");
6573 for (size_t i = 0; i != n_rows; ++i) {
6575 _data[i] = T(1.0) / mat(i, i);
6576 }
6577 return *this;
6578 }
6579
6586 Mat invDiag() const {
6587 static_assert(type == MatType::DIAGONAL, "'invDiag' is only used for diagonal matrix.");
6588 Mat mat;
6589 for (size_t i = 0; i != n_rows; ++i) {
6591 mat._data[i] = T(1.0) / _data[i];
6592 }
6593 }
6594
6606 template <template <class, size_t, size_t, MatType, class...> typename M, typename... _unused, typename T2,
6607 MatType type2>
6609 static_assert(n_rows == n_cols, "Calculate inverse needs to be a square matrix.");
6610 assert(iter >= 1 && "At least one iteration is needed.");
6611 const auto D = mat.diagMat_(); // diagonal part
6612 const auto E = mat.offDiag_(); // off-diagonal part
6614 D_inv.invDiag(D); // inverse of diagonal part
6615 // D_inv.print("D_inv:\n");
6616 // E.asMat().print("E:\n");
6617 auto D_inv_opp = -D_inv;
6618 Mat<T, n_rows, n_cols, MatType::NORMAL> product = D_inv_opp * E;
6619 Mat<T, n_rows, n_cols, MatType::NORMAL> sum_tmp = *this = product; // the first iteration
6621 MAT_INV_NSA:
6622 for (size_t i = 1; i < iter; ++i) {
6623 tmp.mul(*this, product);
6624 *this = tmp;
6625 sum_tmp += tmp;
6626 }
6627 this->mul(sum_tmp, D_inv);
6628 return *this += D_inv;
6629 }
6630
6641 Mat invNSA(size_t iter = 4) const {
6642 static_assert(n_rows == n_cols, "Calculate inverse needs to be a square matrix.");
6643 Mat mat;
6644 mat.invNSA(*this, iter);
6645 return mat;
6646 }
6647
6663 template <template <class, size_t, size_t, MatType, class...> typename M, typename... _unused, typename T2,
6664 MatType type2, typename coeff_type>
6665 Mat& invINSA(const M<T2, n_rows, n_cols, type2, _unused...>& mat, size_t iter = 3, coeff_type beta = 2) {
6666 static_assert(n_rows == n_cols, "Calculate inverse needs to be a square matrix.");
6667 assert(iter >= 1 && "At least one iteration is needed.");
6668 return *this;
6669 }
6670
6679 template <typename coeff_type>
6680 Mat invINSA(size_t iter = 3, coeff_type beta = 1.0) const {
6681 static_assert(n_rows == n_cols, "Calculate inverse needs to be a square matrix.");
6682 Mat mat;
6683 mat.invINSA(*this, iter);
6684 return mat;
6685 }
6686
6687 // Does not support complex number now.
6688 template <typename Tp = T>
6689 Tp power() const {
6690 Tp p = 0;
6691 for (size_t i = 0; i != size(); ++i) {
6693 p += static_cast<Tp>(_data[i] * _data[i]);
6694 }
6695 return p;
6696 }
6697
6703 T value() const {
6704 static_assert(n_rows == 1 && n_cols == 1, "This only applies to matrix of size 1x1.");
6705 return _data[0];
6706 }
6707
6713 T& value() {
6714 static_assert(n_rows == 1 && n_cols == 1, "This only applies to matrix of size 1x1.");
6715 return _data[0];
6716 }
6717
6724 void print(const std::string& str = "", std::ostream& os = std::cout) const {
6725#ifndef __SYNTHESIS__
6726 static_assert(n_rows > 0 && n_cols > 0, "Print requires this matrix be of valid size.");
6727 os << str << "[";
6728 for (size_t i = 0; i + 1 < n_rows; ++i) {
6729 os << "[";
6730 for (size_t j = 0; j + 1 < n_cols; ++j) os << static_cast<T>((*this)(i, j)) << ", ";
6731 os << static_cast<T>((*this)(i, n_cols - 1)) << "]," << std::endl;
6732 }
6733 os << "[";
6734 for (size_t j = 0; j + 1 < n_cols; ++j) os << static_cast<T>((*this)(n_rows - 1, j)) << ", ";
6735 os << static_cast<T>((*this)(n_rows - 1, n_cols - 1)) << "]]" << std::endl;
6736#endif
6737 }
6738
6745 FLAMES_PRAGMA(INLINE)
6746 return *this;
6747 }
6748
6756 FLAMES_PRAGMA(INLINE)
6757 return *this;
6758 }
6759
6760 // public: // original private
6761 public:
6769 T* rawDataPtr() { return _data; }
6770
6771 const T* rawDataPtr() const { return _data; }
6772
6783 inline void _tryAssign(size_t r, size_t c, T value) {
6784 FLAMES_PRAGMA(INLINE)
6785 if (type == MatType::DIAGONAL) {
6786 if (r == c) (*this)(r, c) = value;
6787 } else if (type == MatType::UPPER) {
6788 if (r <= c) (*this)(r, c) = value;
6789 } else if (type == MatType::LOWER) {
6790 if (r >= c) (*this)(r, c) = value;
6791 } else if (type == MatType::SUPPER) {
6792 if (r < c) (*this)(r, c) = value;
6793 } else if (type == MatType::SLOWER) {
6794 if (r > c) (*this)(r, c) = value;
6795 } else if (type == MatType::SYM) {
6796 if (r <= c) (*this)(r, c) = value;
6797 } else if (type == MatType::ASYM) {
6798 if (r < c) (*this)(r, c) = value;
6799 } else if (type == MatType::NORMAL) {
6800 (*this)(r, c) = value;
6801 } else {
6802 assert(!"Impossible! Unknown type!");
6803 }
6804 }
6805
6814 inline void _tryAssignOutRange(size_t r, size_t c, T value) {
6815 FLAMES_PRAGMA(INLINE)
6816 if (r >= n_rows || c >= n_cols) return;
6817 else _tryAssign(r, c, value);
6818 }
6819
6829 inline void _tryPlus(size_t r, size_t c, T value) {
6830 FLAMES_PRAGMA(INLINE)
6831 if (type == MatType::DIAGONAL) {
6832 if (r == c) (*this)(r, c) += value;
6833 } else if (type == MatType::UPPER) {
6834 if (r <= c) (*this)(r, c) += value;
6835 } else if (type == MatType::LOWER) {
6836 if (r >= c) (*this)(r, c) += value;
6837 } else if (type == MatType::SUPPER) {
6838 if (r < c) (*this)(r, c) += value;
6839 } else if (type == MatType::SLOWER) {
6840 if (r > c) (*this)(r, c) += value;
6841 } else if (type == MatType::ASYM) {
6842 if (r != c) (*this)(r, c) += value;
6843 } else if (type == MatType::SYM) {
6844 (*this)(r, c) += value;
6845 } else if (type == MatType::NORMAL) {
6846 (*this)(r, c) += value;
6847 } else {
6848 assert(!"Impossible! Unknown type!");
6849 }
6850 }
6851
6865 template <typename Tmp, typename M, typename Comm, typename Zero>
6866 inline void _sa_read_first_col_L(size_t i, Tmp& tmp_L, const M& mat_L, size_t begin_shift,
6867 Comm __attribute__((unused)) _comm_foo, Zero zero) const {
6868 FLAMES_PRAGMA(INLINE)
6869 constexpr size_t comm = Comm::value;
6870 read_first_col_L:
6871 for (size_t j = 0; j < n_rows; ++j) {
6873 tmp_L[j][0] = ((j <= i + begin_shift) && (i + begin_shift - j < comm))
6874 ? mat_L(j, comm - 1 - (i + begin_shift - j))
6875 : zero;
6876 }
6877 }
6878
6892 template <typename Tmp, typename M, typename Comm, typename Zero>
6893 inline void _sa_read_first_row_R(size_t i, Tmp& tmp_R, const M& mat_R, size_t begin_shift,
6894 Comm __attribute__((unused)) _comm_foo, Zero zero) const {
6895 FLAMES_PRAGMA(INLINE)
6896 constexpr size_t comm = Comm::value;
6897 read_first_row_R:
6898 for (size_t j = 0; j < n_cols; ++j) {
6900 tmp_R[0][j] = ((j <= i + begin_shift) && (i + begin_shift - j < comm))
6901 ? mat_R(comm - 1 - (i + begin_shift - j), j)
6902 : zero;
6903 }
6904 }
6905
6916 template <typename T1, typename T2, typename HLSVec>
6917 inline void _sa_multiply(const T1& tmp_L, const T2& tmp_R, const HLSVec& use_assign) {
6918 FLAMES_PRAGMA(INLINE)
6919 multiply:
6920 for (size_t r = 0; r != n_rows; ++r) {
6922 for (size_t c = 0; c != n_cols; ++c) {
6923 FLAMES_PRAGMA(LOOP_FLATTEN)
6924 T result = tmp_L[r][c] * tmp_R[r][c];
6925 if (use_assign[r * n_cols + c]) {
6926 _tryAssign(r, c, result);
6927 // std::cout << "assign " << r << ' ' << c << " (" << tmp_L[r][c] << "x" << tmp_R[r][c] << "=" <<
6928 // result << ")\n";
6929 } else {
6930 _tryPlus(r, c, result);
6931 // std::cout << "plus " << r << ' ' << c << " (" << tmp_L[r][c] << "x" << tmp_R[r][c] << "=" <<
6932 // result << ")\n";
6933 }
6934 }
6935 }
6936 };
6937
6956 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
6957 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
6958 typename T2, MatType type1, MatType type2, size_t comm>
6959 Mat& _systolicArrayMul(const M1<T1, n_rows, comm, type1, _unused1...>& mat_L,
6960 const M2<T2, comm, n_cols, type2, _unused2...>& mat_R, size_t begin_shift = 0,
6961 size_t end_shift = 0) {
6962 // constexpr size_t begin_shift = BeginShift::value;
6963 // constexpr size_t end_shift = EndShift::value;
6964 T1 tmp_L[n_rows][n_cols];
6965 T2 tmp_R[n_rows][n_cols];
6966 std::vector<bool> use_assign(n_rows * n_cols, true);
6967// hls::vector<bool, n_rows * n_cols> use_assign = true;
6968#ifdef FLAMES_MAT_PARTITION_COMPLETE
6969 FLAMES_PRAGMA(ARRAY_PARTITION variable = tmp_L type = complete)
6970 FLAMES_PRAGMA(ARRAY_PARTITION variable = tmp_R type = complete)
6971#else
6972 FLAMES_PRAGMA(ARRAY_PARTITION variable = tmp_L type = block factor = FLAMES_MAT_PARTITION_FACTOR)
6973 FLAMES_PRAGMA(ARRAY_PARTITION variable = tmp_R type = block factor = FLAMES_MAT_PARTITION_FACTOR)
6974#endif
6975 auto write_L = [&](size_t i) {
6976 if (i + 1 != n_rows + comm + n_cols - 2 - begin_shift - end_shift) {
6977 write_L:
6978 for (size_t c = n_cols; c > 1; --c) {
6980 for (size_t r = 0; r < n_rows; ++r) {
6981 FLAMES_PRAGMA(LOOP_FLATTEN)
6982 if (c <= i + 2 && r + c <= i + begin_shift + 2 && r <= i) { tmp_L[r][c - 1] = tmp_L[r][c - 2]; }
6983 }
6984 }
6985 }
6986 };
6987 // systolic array passes data down (data from the right matrix)
6988 auto write_R = [&](size_t i) {
6989 if (i + 1 != n_rows + comm + n_cols - 2 - begin_shift - end_shift) {
6990 write_R:
6991 for (size_t r = n_rows; r > 1; --r) {
6993 for (size_t c = 0; c < n_cols; ++c) {
6994 FLAMES_PRAGMA(LOOP_FLATTEN)
6995 if (r <= i + 2 && c + r <= i + begin_shift + 2 && c <= i) { tmp_R[r - 1][c] = tmp_R[r - 2][c]; }
6996 }
6997 }
6998 }
6999 };
7000 // systolic array passes data right (data from the left matrix)
7001 auto set_assign_ctl = [&](size_t i) {
7002 FLAMES_PRAGMA(LATENCY max = 0)
7003 set_assign_ctl:
7004 for (size_t r = 0; r < n_rows; ++r) {
7006 size_t c = i - r; // note this is unsigned so there can be overflow
7007 if (c < n_cols) { use_assign[r * n_cols + c] = false; }
7008 }
7009 };
7010 std::integral_constant<int, comm> _comm_foo = {};
7011 SYSTOLIC_ARRAY_MAT_MUL:
7012 for (size_t i = 0; i < n_rows + comm + n_cols - 2 - begin_shift - end_shift; ++i) {
7013 FLAMES_PRAGMA(PIPELINE)
7014 // std::cout << "ITER " << i << "\n";
7015 // read
7016 _sa_read_first_col_L(i, tmp_L, mat_L, begin_shift, _comm_foo, T1(0));
7017 _sa_read_first_row_R(i, tmp_R, mat_R, begin_shift, _comm_foo, T2(0));
7018 // multiply
7019 _sa_multiply(tmp_L, tmp_R, use_assign);
7020 set_assign_ctl(i);
7021 // write
7022 write_L(i);
7023 write_R(i);
7024 }
7025 return *this;
7026 }
7027
7028 public: // original private
7037 T _data[type == MatType::NORMAL ? n_rows * n_cols
7038 : type == MatType::DIAGONAL ? n_rows
7039 : type == MatType::SCALAR ? 1
7040 : type == MatType::SUPPER ? (n_rows - 1) * n_rows / 2
7041 : type == MatType::SLOWER ? (n_rows - 1) * n_rows / 2
7042 : type == MatType::ASYM ? (n_rows - 1) * n_rows / 2
7043 : (1 + n_rows) * n_rows / 2];
7044};
7045
7046template <typename T, size_t n_rows, size_t n_cols, MatType type>
7047class MatView {
7048 public:
7054 MatView(const Mat<T, n_rows, n_cols, type>& m) : _data(m.rawDataPtr()) {}
7056
7057 MatView(const T* const ptr) : _data(ptr) {}
7058
7064 MatView(const MatView& m) : _data(m._data) {}
7065
7071 inline static constexpr size_t size() noexcept {
7072 return type == MatType::NORMAL ? n_rows * n_cols
7073 : type == MatType::DIAGONAL ? n_rows
7074 : type == MatType::SCALAR ? 1
7075 : type == MatType::SUPPER ? (n_rows - 1) * n_rows / 2
7076 : type == MatType::SLOWER ? (n_rows - 1) * n_rows / 2
7077 : type == MatType::ASYM ? (n_rows - 1) * n_rows / 2
7078 : (1 + n_rows) * n_rows / 2;
7079 }
7080
7082 for (size_t i = 0; i != size(); ++i) {
7084 _data[i] = m[i];
7085 }
7086 return *this;
7087 }
7088
7089 template <typename M>
7090 void assign(M m) {
7091 for (size_t i = 0; i != size(); ++i) {
7093 _data[i] = m[i];
7094 }
7095 }
7096
7104 T operator()(size_t r, size_t c) const {
7105 FLAMES_PRAGMA(INLINE)
7106 assert(r < n_rows && "Matrix row index should be within range");
7107 assert(c < n_cols && "Matrix col index should be within range");
7108 if (type == MatType::NORMAL) {
7109 return _data[r * n_cols + c];
7110 } else if (type == MatType::DIAGONAL) {
7111 if (r == c) return _data[r];
7112 else return T(0);
7113 } else if (type == MatType::SCALAR) {
7114 if (r == c) return _data[0];
7115 else return T(0);
7116 } else if (type == MatType::UPPER) {
7117 if (r <= c) return _data[(2 * n_cols + 1 - r) * r / 2 + c - r];
7118 else return T(0);
7119 } else if (type == MatType::LOWER) {
7120 if (r >= c) return _data[(1 + r) * r / 2 + c];
7121 else return T(0);
7122 } else if (type == MatType::SUPPER) {
7123 if (r < c) return _data[(2 * n_cols + 1 - r) * r / 2 + c - 2 * r - 1];
7124 else return T(0);
7125 } else if (type == MatType::SLOWER) {
7126 if (r >= c) return _data[(1 + r) * r / 2 + c - r];
7127 else return T(0);
7128 } else if (type == MatType::SYM) {
7129 if (r <= c) return _data[(2 * n_cols + 1 - r) * r / 2 + c - r];
7130 else return _data[(2 * n_cols + 1 - c) * c / 2 + r - c];
7131 } else if (type == MatType::ASYM) {
7132 if (r < c) return _data[(2 * n_cols + 1 - r) * r / 2 + c - r * 2 - 1];
7133 else if (r > c) return -_data[(2 * n_cols + 1 - c) * c / 2 + r - c * 2 - 1];
7134 else return T(0);
7135 } else {
7136 // Normally it is impossible to reach here.
7137 assert(!"Impossible! Unknown MatType!");
7138 return T(0);
7139 }
7140 }
7141
7148 T operator[](size_t index) const {
7149 FLAMES_PRAGMA(INLINE)
7150 assert(index < size() && "[index] should be in range in MatView");
7151 return _data[index];
7152 }
7153
7168 template <template <class, size_t, size_t, MatType, class...> typename M, typename... _unused, typename T2,
7169 MatType type2, size_t rows_, size_t cols_>
7171 assert(c < n_cols && "Take the specific col by index requires 'The index should be smaller than the number of "
7172 "the matrix's columns.'.");
7173 static_assert(size() == rows_, "Element number should be rows_ in Mat::col(mat, index).");
7174 for (size_t i = 0; i != size(); ++i) {
7176 _data[i] = mat(i, c);
7177 }
7178 return *this;
7179 }
7180
7181 template <template <class, size_t, size_t, MatType, class...> typename M, typename... _unused, typename T2,
7182 MatType type2, size_t rows_, size_t cols_>
7183 void col(size_t c, const M<T2, rows_, cols_, type2, _unused...>& mat) {
7184 assert(c < n_cols && "Take the specific col by index requires 'The index should be smaller than the number of "
7185 "the matrix's columns.'.");
7186 assert(mat.size() == n_rows && "Element number should be n_rows in Mat::col(index, mat).");
7187 for (int i = 0; i != mat.size(); ++i) {
7189 (*this)(i, c) = mat[i];
7190 }
7191 }
7192
7208 assert(c < n_cols && "Take the specific col by index requires 'The index should be smaller than the number of "
7209 "the matrix's columns.'.");
7211 for (size_t i = 0; i != n_rows; ++i) {
7213 mat(i, 0) = (*this)(i, c);
7214 }
7215 return mat;
7216 }
7217
7218 template <template <class, size_t, size_t, MatType, class...> typename M, typename... _unused, typename T2,
7219 MatType type2>
7221 FLAMES_PRAGMA(INLINE)
7222 // return this->sub(*this, mat_R);
7223 for (size_t i = 0; i != size(); ++i) {
7225 _data[i] += mat_R[i];
7226 }
7227 return *this;
7228 }
7229
7230 template <template <class, size_t, size_t, MatType, class...> typename M, typename... _unused, typename T2,
7231 MatType type2>
7233 FLAMES_PRAGMA(INLINE)
7234 // return this->sub(*this, mat_R);
7235 for (size_t i = 0; i != size(); ++i) {
7237 _data[i] -= mat_R[i];
7238 }
7239 return *this;
7240 }
7241
7243
7244 template <typename Tp = T>
7245 Tp power() const {
7246 Tp p = 0;
7247 for (size_t i = 0; i != size(); ++i) {
7249 p += static_cast<Tp>(_data[i] * _data[i]);
7250 }
7251 return p;
7252 }
7253
7254 template <typename Tp = T>
7255 Tp abssum() const {
7256 Tp p = 0;
7257 for (size_t i = 0; i != size(); ++i) {
7259 auto d = _data[i];
7260 if (d > 0) p += static_cast<Tp>(d);
7261 }
7262 return p;
7263 }
7264
7271 FLAMES_PRAGMA(INLINE);
7272 return Mat<T, n_rows, n_cols, type>(const_cast<const T*>(_data), InitAfterwards::NONE);
7273 }
7274
7281 FLAMES_PRAGMA(INLINE);
7282 return static_cast<Mat<T, n_rows, n_cols, type>>(*this);
7283 }
7284
7285 void print(const std::string& str = "", std::ostream& os = std::cout) const { this->asMat().print(str, os); }
7286
7287 // public: // original private
7288 public:
7289 const T* const _data;
7290};
7291
7292template <typename T, size_t n_rows, size_t n_cols, MatType type>
7293class MatRef {
7294 public:
7301
7302 MatRef(const T* const ptr) : _data(ptr) {}
7303
7309 MatRef(const MatRef& m) : _data(m._data) {}
7310
7316 inline static constexpr size_t size() noexcept {
7317 return type == MatType::NORMAL ? n_rows * n_cols
7318 : type == MatType::DIAGONAL ? n_rows
7319 : type == MatType::SCALAR ? 1
7320 : type == MatType::SUPPER ? (n_rows - 1) * n_rows / 2
7321 : type == MatType::SLOWER ? (n_rows - 1) * n_rows / 2
7322 : type == MatType::ASYM ? (n_rows - 1) * n_rows / 2
7323 : (1 + n_rows) * n_rows / 2;
7324 }
7325
7327 for (size_t i = 0; i != size(); ++i) {
7329 _data[i] = m[i];
7330 }
7331 return *this;
7332 }
7333
7334 template <typename M>
7335 void assign(M m) {
7336 for (size_t i = 0; i != size(); ++i) {
7338 _data[i] = m[i];
7339 }
7340 }
7341
7349 T operator()(size_t r, size_t c) const {
7350 FLAMES_PRAGMA(INLINE)
7351 assert(r < n_rows && "Matrix row index should be within range");
7352 assert(c < n_cols && "Matrix col index should be within range");
7353 if (type == MatType::NORMAL) {
7354 return _data[r * n_cols + c];
7355 } else if (type == MatType::DIAGONAL) {
7356 if (r == c) return _data[r];
7357 else return T(0);
7358 } else if (type == MatType::SCALAR) {
7359 if (r == c) return _data[0];
7360 else return T(0);
7361 } else if (type == MatType::UPPER) {
7362 if (r <= c) return _data[(2 * n_cols + 1 - r) * r / 2 + c - r];
7363 else return T(0);
7364 } else if (type == MatType::LOWER) {
7365 if (r >= c) return _data[(1 + r) * r / 2 + c];
7366 else return T(0);
7367 } else if (type == MatType::SUPPER) {
7368 if (r < c) return _data[(2 * n_cols + 1 - r) * r / 2 + c - 2 * r - 1];
7369 else return T(0);
7370 } else if (type == MatType::SLOWER) {
7371 if (r >= c) return _data[(1 + r) * r / 2 + c - r];
7372 else return T(0);
7373 } else if (type == MatType::SYM) {
7374 if (r <= c) return _data[(2 * n_cols + 1 - r) * r / 2 + c - r];
7375 else return _data[(2 * n_cols + 1 - c) * c / 2 + r - c];
7376 } else if (type == MatType::ASYM) {
7377 if (r < c) return _data[(2 * n_cols + 1 - r) * r / 2 + c - r * 2 - 1];
7378 else if (r > c) return -_data[(2 * n_cols + 1 - c) * c / 2 + r - c * 2 - 1];
7379 else return T(0);
7380 } else {
7381 // Normally it is impossible to reach here.
7382 assert(!"Impossible! Unknown MatType!");
7383 return T(0);
7384 }
7385 }
7386
7394 T& operator()(size_t r, size_t c) {
7395 FLAMES_PRAGMA(INLINE)
7396 assert(r < n_rows && "Matrix row index should be within range");
7397 assert(c < n_cols && "Matrix col index should be within range");
7398 if (type == MatType::NORMAL) {
7399 return _data[r * n_cols + c];
7400 } else if (type == MatType::DIAGONAL) {
7401 if (r == c) return _data[r];
7402 else assert(!"This element cannot be modified (DIAGONAL).");
7403 } else if (type == MatType::SCALAR) {
7404 assert(!"This element cannot be modified (SCALAR).");
7405 } else if (type == MatType::UPPER) {
7406 if (r <= c) return _data[(2 * n_cols + 1 - r) * r / 2 + c - r];
7407 else assert(!"This element cannot be modified (UPPER).");
7408 } else if (type == MatType::LOWER) {
7409 if (r >= c) return _data[(1 + r) * r / 2 + c];
7410 else assert(!"This element cannot be modified (LOWER).");
7411 } else if (type == MatType::SUPPER) {
7412 if (r < c) return _data[(2 * n_cols + 1 - r) * r / 2 + c - 1 - 2 * r];
7413 else assert(!"This element cannot be modified (SUPPER).");
7414 } else if (type == MatType::SLOWER) {
7415 if (r > c) return _data[(1 + r) * r / 2 + c - r];
7416 else assert(!"This element cannot be modified (SLOWER).");
7417 } else if (type == MatType::SYM) {
7418 if (r <= c) return _data[(2 * n_cols + 1 - r) * r / 2 + c - r];
7419 else return _data[(2 * n_cols + 1 - c) * c / 2 + r - c];
7420 } else if (type == MatType::ASYM) {
7421 if (r < c) return _data[(2 * n_cols + 1 - r) * r / 2 + c - 1 - 2 * r];
7422 else if (r > c) return _data[(2 * n_cols + 1 - c) * c / 2 + r - 1 - 2 * c];
7423
7424 // ATTENTION This part needs to be perfected , missing a minus sign.
7425 // Because a minus sign will result in a error about reference.
7426
7427 else assert(!"This element cannot be modified (ASYM).");
7428 } else {
7429 // Normally it is impossible to reach here.
7430 assert(!"Impossible! Unknown MatType!");
7431 }
7432 // Just to make the compiler happy.
7433 return _data[0];
7434 }
7435
7442 T operator[](size_t index) const {
7443 FLAMES_PRAGMA(INLINE)
7444 assert(index < size() && "[index] should be in range in MatView");
7445 return _data[index];
7446 }
7447
7454 T& operator[](size_t index) {
7455 FLAMES_PRAGMA(INLINE)
7456 assert(index < size() && "[index] should be in range in MatView");
7457 return _data[index];
7458 }
7459
7465 void setValue(T val) {
7466 for (size_t i = 0; i != size(); ++i) {
7468 _data[i] = val;
7469 }
7470 }
7471
7476 void setZero() { setValue(static_cast<T>(0)); }
7477
7492 template <template <class, size_t, size_t, MatType, class...> typename M, typename... _unused, typename T2,
7493 MatType type2, size_t rows_, size_t cols_>
7495 assert(c < n_cols && "Take the specific col by index requires 'The index should be smaller than the number of "
7496 "the matrix's columns.'.");
7497 static_assert(size() == rows_, "Element number should be rows_ in Mat::col(mat, index).");
7498 for (size_t i = 0; i != size(); ++i) {
7500 _data[i] = mat(i, c);
7501 }
7502 return *this;
7503 }
7504
7505 template <template <class, size_t, size_t, MatType, class...> typename M, typename... _unused, typename T2,
7506 MatType type2, size_t rows_, size_t cols_>
7507 void col(size_t c, const M<T2, rows_, cols_, type2, _unused...>& mat) {
7508 assert(c < n_cols && "Take the specific col by index requires 'The index should be smaller than the number of "
7509 "the matrix's columns.'.");
7510 assert(mat.size() == n_rows && "Element number should be n_rows in Mat::col(index, mat).");
7511 for (int i = 0; i != mat.size(); ++i) {
7513 (*this)(i, c) = mat[i];
7514 }
7515 }
7516
7532 assert(c < n_cols && "Take the specific col by index requires 'The index should be smaller than the number of "
7533 "the matrix's columns.'.");
7535 for (size_t i = 0; i != n_rows; ++i) {
7537 mat(i, 0) = (*this)(i, c);
7538 }
7539 return mat;
7540 }
7541
7542 template <template <class, size_t, size_t, MatType, class...> typename M, typename... _unused, typename T2,
7543 MatType type2>
7545 FLAMES_PRAGMA(INLINE)
7546 // return this->sub(*this, mat_R);
7547 for (size_t i = 0; i != size(); ++i) {
7549 _data[i] += mat_R[i];
7550 }
7551 return *this;
7552 }
7553
7554 template <template <class, size_t, size_t, MatType, class...> typename M, typename... _unused, typename T2,
7555 MatType type2>
7557 FLAMES_PRAGMA(INLINE)
7558 // return this->sub(*this, mat_R);
7559 for (size_t i = 0; i != size(); ++i) {
7561 _data[i] -= mat_R[i];
7562 }
7563 return *this;
7564 }
7565
7567
7568 template <typename Tp = T>
7569 Tp power() const {
7570 Tp p = 0;
7571 for (size_t i = 0; i != size(); ++i) {
7573 p += static_cast<Tp>(_data[i] * _data[i]);
7574 }
7575 return p;
7576 }
7577
7578 template <typename Tp = T>
7579 Tp abssum() const {
7580 Tp p = 0;
7581 for (size_t i = 0; i != size(); ++i) {
7583 auto d = _data[i];
7584 if (d > 0) p += static_cast<Tp>(d);
7585 }
7586 return p;
7587 }
7588
7595 FLAMES_PRAGMA(INLINE);
7596 return Mat<T, n_rows, n_cols, type>(const_cast<const T*>(_data), InitAfterwards::NONE);
7597 }
7598
7605 FLAMES_PRAGMA(INLINE);
7606 return static_cast<Mat<T, n_rows, n_cols, type>>(*this);
7607 }
7608
7609 void print(const std::string& str = "", std::ostream& os = std::cout) const { this->asMat().print(str, os); }
7610
7611 // public: // original private
7612 public:
7613 T* const _data;
7614};
7615
7616template <typename T, size_t n_rows, size_t n_cols, MatType type>
7618 public:
7624 MatViewOpp(const Mat<T, n_cols, n_rows, type>& m) : _data(m.rawDataPtr()) {}
7625
7632
7638 inline static constexpr size_t size() noexcept {
7639 return type == MatType::NORMAL ? n_rows * n_cols
7640 : type == MatType::DIAGONAL ? n_rows
7641 : type == MatType::SCALAR ? 1
7642 : type == MatType::SUPPER ? (n_rows - 1) * n_rows / 2
7643 : type == MatType::SLOWER ? (n_rows - 1) * n_rows / 2
7644 : type == MatType::ASYM ? (n_rows - 1) * n_rows / 2
7645 : (1 + n_rows) * n_rows / 2;
7646 }
7647
7655 T operator()(size_t r, size_t c) const {
7656 FLAMES_PRAGMA(INLINE)
7657 assert(r < n_rows && "Matrix row index should be within range");
7658 assert(c < n_cols && "Matrix col index should be within range");
7659 if (type == MatType::NORMAL) {
7660 return -_data[r * n_cols + c];
7661 } else if (type == MatType::DIAGONAL) {
7662 if (r == c) return -_data[r];
7663 else return T(0);
7664 } else if (type == MatType::SCALAR) {
7665 if (r == c) return -_data[0];
7666 else return T(0);
7667 } else if (type == MatType::UPPER) {
7668 if (r <= c) return -_data[(2 * n_cols + 1 - r) * r / 2 + c - r];
7669 else return T(0);
7670 } else if (type == MatType::LOWER) {
7671 if (r >= c) return -_data[(1 + r) * r / 2 + c];
7672 else return T(0);
7673 } else if (type == MatType::SUPPER) {
7674 if (r < c) return -_data[(2 * n_cols + 1 - r) * r / 2 + c - 2 * r - 1];
7675 else return T(0);
7676 } else if (type == MatType::SLOWER) {
7677 if (r >= c) return -_data[(1 + r) * r / 2 + c - r];
7678 else return T(0);
7679 } else if (type == MatType::SYM) {
7680 if (r <= c) return -_data[(2 * n_cols + 1 - r) * r / 2 + c - r];
7681 else return -_data[(2 * n_cols + 1 - c) * c / 2 + r - c];
7682 } else if (type == MatType::ASYM) {
7683 if (r < c) return -_data[(2 * n_cols + 1 - r) * r / 2 + c - r * 2 - 1];
7684 else if (r > c) return _data[(2 * n_cols + 1 - c) * c / 2 + r - c * 2 - 1];
7685 else return T(0);
7686 } else {
7687 // Normally it is impossible to reach here.
7688 assert(!"Impossible! Unknown MatType!");
7689 }
7690 }
7691
7698 T operator[](size_t index) const {
7699 FLAMES_PRAGMA(INLINE)
7700 assert(index < size() && "[index] should be in range in MatViewOpp");
7701 return -_data[index];
7702 }
7703
7710 FLAMES_PRAGMA(INLINE);
7712 }
7713
7720 FLAMES_PRAGMA(INLINE);
7721 return static_cast<Mat<T, n_rows, n_cols, type>>(*this);
7722 }
7723
7724 public: // original private
7725 const T* _data;
7726};
7727
7728template <typename T, size_t n_rows, size_t n_cols, MatType type>
7730 public:
7736 MatViewT(const Mat<T, n_cols, n_rows, tType(type)>& m) : _data(m.rawDataPtr()) {}
7737 MatViewT(Mat<T, n_cols, n_rows, tType(type)>& m) : _data(m.rawDataPtr()) {}
7738
7744 MatViewT(const MatViewT& m) : _data(m._data) {}
7745
7746 // MatViewT(T* const ptr) : _data(ptr) {}
7747
7748 MatViewT(T* ptr) : _data(ptr) {}
7749
7755 inline static constexpr size_t size() noexcept {
7756 return type == MatType::NORMAL ? n_rows * n_cols
7757 : type == MatType::DIAGONAL ? n_rows
7758 : type == MatType::SCALAR ? 1
7759 : type == MatType::SUPPER ? (n_rows - 1) * n_rows / 2
7760 : type == MatType::SLOWER ? (n_rows - 1) * n_rows / 2
7761 : type == MatType::ASYM ? (n_rows - 1) * n_rows / 2
7762 : (1 + n_rows) * n_rows / 2;
7763 }
7764
7772 T operator()(size_t r, size_t c) const {
7773 FLAMES_PRAGMA(INLINE)
7774 assert(r < n_rows && "Matrix row index should be within range");
7775 assert(c < n_cols && "Matrix col index should be within range");
7776 if (type == MatType::NORMAL) {
7777 return _data[c * n_rows + r];
7778 } else if (type == MatType::DIAGONAL) {
7779 if (r == c) return _data[r];
7780 else return T(0);
7781 } else if (type == MatType::SCALAR) {
7782 if (r == c) return _data[0];
7783 else return T(0);
7784 } else if (type == MatType::UPPER) {
7785 if (r <= c) return _data[(2 * n_cols + 1 - c) * c / 2 + r - c];
7786 else return T(0);
7787 } else if (type == MatType::LOWER) {
7788 if (r >= c) return _data[(1 + c) * c / 2 + r];
7789 else return T(0);
7790 } else if (type == MatType::SUPPER) {
7791 if (r < c) return _data[(2 * n_cols + 1 - c) * c / 2 + r - 2 * c - 1];
7792 else return T(0);
7793 } else if (type == MatType::SLOWER) {
7794 if (r >= c) return _data[(1 + c) * c / 2 + r - c];
7795 else return T(0);
7796 } else if (type == MatType::SYM) {
7797 if (r <= c) return _data[(2 * n_cols + 1 - c) * c / 2 + r - c];
7798 else return _data[(2 * n_cols + 1 - r) * r / 2 + c - r];
7799 } else if (type == MatType::ASYM) {
7800 if (r < c) return -_data[(2 * n_cols + 1 - r) * r / 2 + c - r * 2 - 1];
7801 else if (r > c) return _data[(2 * n_cols + 1 - c) * c / 2 + r - c * 2 - 1];
7802 else return T(0);
7803 } else {
7804 // Normally it is impossible to reach here.
7805 assert(!"Impossible! Unknown MatType!");
7806 }
7807 }
7808
7815 T operator[](size_t index) const {
7816 FLAMES_PRAGMA(INLINE)
7817 size_t r, c; // of the original matrix
7818 if (type == MatType::DIAGONAL) {
7819 r = c = index;
7820 } else if (type == MatType::SCALAR) {
7821 r = c = index;
7822 } else if (type == MatType::NORMAL) {
7823 r = index / n_cols;
7824 c = index % n_cols;
7825 } else if (type == MatType::UPPER) {
7826 r = upperRow(index, n_cols);
7827 c = r + index - (2 * n_cols + 1 - r) * r / 2;
7828 } else if (type == MatType::LOWER) {
7829 r = lowerRow(index, n_cols);
7830 c = index - (r + 1) * r / 2;
7831 } else if (type == MatType::SUPPER) {
7832 r = supperRow(index, n_cols);
7833 c = 2 * r + 1 + index - c - (2 * n_cols + 1 - r) * r / 2;
7834 } else if (type == MatType::SLOWER) {
7835 r = slowerRow(index, n_cols);
7836 c = index - (1 + r) * r / 2 + r;
7837 } else if (type == MatType::SYM) {
7838 r = upperRow(index, n_cols);
7839 c = r + index - (2 * n_cols + 1 - r) * r / 2;
7840 } else if (type == MatType::ASYM) {
7841 r = supperRow(index, n_cols);
7842 c = 2 * r + 1 + index - c - (2 * n_cols + 1 - r) * r / 2;
7843 }
7844 return (*this)(r, c);
7845 }
7846
7853 FLAMES_PRAGMA(INLINE);
7854 return Mat<T, n_rows, n_cols, type>(const_cast<const T*>(_data), InitAfterwards::TR);
7855 }
7856
7863 FLAMES_PRAGMA(INLINE);
7864 return static_cast<Mat<T, n_rows, n_cols, type>>(*this);
7865 }
7866
7867 // public: // original private
7868 public:
7874 T* const _data;
7875};
7876
7877template <typename T, size_t N, size_t N_, MatType type, typename type_parent>
7879 public:
7885 MatViewDiagMat(const Mat<T, N, N, matType<type_parent>()>& m) : _data(m.rawDataPtr()) {
7886 static_assert(type == MatType::DIAGONAL && N == N_, "DiagMat is and comes from a square matrix.");
7887 }
7888
7895
7903 MATVIEWDIAGMAT_INV:
7904 for (size_t i = 0; i != N; ++i) {
7906 mat[i] = static_cast<T>(1) / (*this)[i];
7907 }
7908 return mat;
7909 }
7910
7916 inline static constexpr size_t size() noexcept {
7917 return type == MatType::NORMAL ? N * N
7918 : type == MatType::DIAGONAL ? N
7919 : type == MatType::SCALAR ? 1
7920 : type == MatType::SUPPER ? (N - 1) * N / 2
7921 : type == MatType::SLOWER ? (N - 1) * N / 2
7922 : type == MatType::ASYM ? (N - 1) * N / 2
7923 : (1 + N) * N / 2;
7924 }
7925
7931 inline static constexpr MatType pType() noexcept { return matType<type_parent>(); }
7932
7940 T operator()(size_t r, size_t c) const {
7941 if (r != c) return T(0);
7942 constexpr MatType p_type = pType();
7943 if (p_type == MatType::NORMAL) {
7944 return _data[r * N + c];
7945 } else if (p_type == MatType::DIAGONAL) {
7946 return _data[r];
7947 } else if (p_type == MatType::SCALAR) {
7948 return _data[0];
7949 } else if (p_type == MatType::UPPER) {
7950 return _data[(2 * N + 1 - r) * r / 2];
7951 } else if (p_type == MatType::LOWER) {
7952 return _data[(1 + r) * r / 2 + r];
7953 } else if (p_type == MatType::SUPPER) {
7954 return T(0);
7955 } else if (p_type == MatType::SLOWER) {
7956 return T(0);
7957 } else if (p_type == MatType::SYM) {
7958 return _data[(2 * N + 1 - r) * r / 2];
7959 } else if (p_type == MatType::ASYM) {
7960 return T(0);
7961 } else {
7962 // Normally it is impossible to reach here.
7963 assert(!"Impossible! Unknown MatType!");
7964 }
7965 }
7966
7973 T operator[](size_t index) const { return (*this)(index, index); }
7974
7981 if (pType() == MatType::DIAGONAL) {
7982 return this->_data;
7983 } else {
7985 MAT_COPY_DIAG:
7986 for (size_t i = 0; i != N; ++i) {
7988 mat[i] = (*this)[i];
7989 }
7990 return mat;
7991 }
7992 }
7993
8000 FLAMES_PRAGMA(INLINE);
8001 return static_cast<Mat<T, N, N, MatType::DIAGONAL>>(*this);
8002 }
8003
8004 public: // original private
8010 const T* _data;
8011};
8012
8013template <typename T, size_t N, size_t n_cols, MatType type, typename type_parent>
8015 public:
8021 MatViewDiagVec(const Mat<T, N, N, matType<type_parent>()>& m) : _data(m.rawDataPtr()) {
8022 static_assert(n_cols == 1, "DiagVec is a column vector.");
8023 }
8024
8031
8037 inline static constexpr size_t size() noexcept {
8038 return type == MatType::NORMAL ? N * N
8039 : type == MatType::DIAGONAL ? N
8040 : type == MatType::SCALAR ? 1
8041 : type == MatType::SUPPER ? (N - 1) * N / 2
8042 : type == MatType::SLOWER ? (N - 1) * N / 2
8043 : type == MatType::ASYM ? (N - 1) * N / 2
8044 : (1 + N) * N / 2;
8045 }
8046
8052 Vec<T, N> inv() const {
8053 Vec<T, N> mat;
8054 MATVIEWDIAGVEC_INV:
8055 for (size_t i = 0; i != N; ++i) {
8057 mat[i] = static_cast<T>(1) / (*this)[i];
8058 }
8059 return mat;
8060 }
8061
8067 inline static constexpr MatType pType() noexcept { return matType<type_parent>(); }
8068
8076 T operator()(size_t r, size_t c) const {
8077 assert(c == 0 && "Column vector's column index should always be 0.");
8078 constexpr MatType p_type = pType();
8079 if (p_type == MatType::NORMAL) {
8080 return _data[r * N + r];
8081 } else if (p_type == MatType::DIAGONAL) {
8082 return _data[r];
8083 } else if (p_type == MatType::SCALAR) {
8084 return _data[0];
8085 } else if (p_type == MatType::UPPER) {
8086 return _data[(2 * N + 1 - r) * r / 2];
8087 } else if (p_type == MatType::LOWER) {
8088 return _data[(1 + r) * r / 2 + r];
8089 } else if (p_type == MatType::SUPPER) {
8090 return T(0);
8091 } else if (p_type == MatType::SLOWER) {
8092 return T(0);
8093 } else if (p_type == MatType::SYM) {
8094 return _data[(2 * N + 1 - r) * r / 2];
8095 } else if (p_type == MatType::ASYM) {
8096 return T(0);
8097 } else {
8098 // Normally it is impossible to reach here.
8099 assert(!"Impossible! Unknown MatType!");
8100 }
8101 }
8102
8109 T operator[](size_t index) const { return (*this)(index, 0); }
8110
8116 operator Vec<T, N>() const {
8117 Vec<T, N> mat;
8118 MAT_COPY_DIAG:
8119 for (size_t i = 0; i != N; ++i) {
8121 mat[i] = (*this)[i];
8122 }
8123 return mat;
8124 }
8125
8132 FLAMES_PRAGMA(INLINE);
8133 return static_cast<Vec<T, N>>(*this);
8134 }
8135
8142 FLAMES_PRAGMA(INLINE);
8143 return static_cast<Vec<T, N>>(*this);
8144 }
8145
8146 public: // original private
8152 const T* _data;
8153};
8154
8155template <typename T, size_t n_rows, size_t N, MatType type, typename type_parent>
8157 public:
8163 MatViewDiagRowVec(const Mat<T, N, N, matType<type_parent>()>& m) : _data(m.rawDataPtr()) {
8164 static_assert(n_rows == 1, "DiagRowVec is a row vector.");
8165 }
8166
8173
8179 inline static constexpr size_t size() noexcept {
8180 return type == MatType::NORMAL ? N * N
8181 : type == MatType::DIAGONAL ? N
8182 : type == MatType::SCALAR ? 1
8183 : type == MatType::SUPPER ? (N - 1) * N / 2
8184 : type == MatType::SLOWER ? (N - 1) * N / 2
8185 : type == MatType::ASYM ? (N - 1) * N / 2
8186 : (1 + N) * N / 2;
8187 }
8188
8194 inline static constexpr MatType pType() noexcept { return matType<type_parent>(); }
8195
8203 T operator()(size_t r, size_t c) const {
8204 assert(r == 0 && "Row vector's row index should always be 0.");
8205 constexpr MatType p_type = pType();
8206 if (p_type == MatType::NORMAL) {
8207 return _data[c * N + c];
8208 } else if (p_type == MatType::DIAGONAL) {
8209 return _data[c];
8210 } else if (p_type == MatType::SCALAR) {
8211 return _data[0];
8212 } else if (p_type == MatType::UPPER) {
8213 return _data[(2 * N + 1 - c) * c / 2];
8214 } else if (p_type == MatType::LOWER) {
8215 return _data[(1 + c) * c / 2 + c];
8216 } else if (p_type == MatType::SUPPER) {
8217 return T(0);
8218 } else if (p_type == MatType::SLOWER) {
8219 return T(0);
8220 } else if (p_type == MatType::SYM) {
8221 return _data[(2 * N + 1 - c) * c / 2];
8222 } else if (p_type == MatType::ASYM) {
8223 return T(0);
8224 } else {
8225 // Normally it is impossible to reach here.
8226 assert(!"Impossible! Unknown MatType!");
8227 }
8228 }
8229
8236 T operator[](size_t index) const { return (*this)(0, index); }
8237
8243 operator RowVec<T, N>() const {
8244 RowVec<T, N> mat;
8245 MAT_COPY_DIAG:
8246 for (size_t i = 0; i != N; ++i) {
8248 mat[i] = (*this)[i];
8249 }
8250 return mat;
8251 }
8252
8259 FLAMES_PRAGMA(INLINE);
8260 return static_cast<RowVec<T, N>>(*this);
8261 }
8262
8269 FLAMES_PRAGMA(INLINE);
8270 return static_cast<RowVec<T, N>>(*this);
8271 }
8272
8273 public: // original private
8279 const T* _data;
8280};
8281
8282template <typename T, size_t N, size_t N_, MatType type, typename type_parent>
8284 public:
8290 MatViewOffDiag(const Mat<T, N, N, matType<type_parent>()>& m) : _data(m.rawDataPtr()) {
8291 static_assert(type == MatType::NORMAL && N == N_, "OffDiag is and comes from a square and normal matrix.");
8292 }
8293
8300
8306 inline static constexpr size_t size() noexcept {
8307 return type == MatType::NORMAL ? N * N
8308 : type == MatType::DIAGONAL ? N
8309 : type == MatType::SCALAR ? 1
8310 : type == MatType::SUPPER ? (N - 1) * N / 2
8311 : type == MatType::SLOWER ? (N - 1) * N / 2
8312 : type == MatType::ASYM ? (N - 1) * N / 2
8313 : (1 + N) * N / 2;
8314 }
8315
8321 inline static constexpr MatType pType() noexcept { return matType<type_parent>(); }
8322
8330 T operator()(size_t r, size_t c) const {
8331 if (r == c) return T(0);
8332 constexpr MatType p_type = pType();
8333 if (type == MatType::NORMAL) {
8334 return _data[r * N + c];
8335 } else if (type == MatType::DIAGONAL) {
8336 if (r == c) return _data[r];
8337 else return T(0);
8338 } else if (type == MatType::SCALAR) {
8339 if (r == c) return _data[0];
8340 else return T(0);
8341 } else if (type == MatType::UPPER) {
8342 if (r <= c) return _data[(2 * N + 1 - r) * r / 2 + c - r];
8343 else return T(0);
8344 } else if (type == MatType::LOWER) {
8345 if (r >= c) return _data[(1 + r) * r / 2 + c];
8346 else return T(0);
8347 } else if (type == MatType::SUPPER) {
8348 if (r < c) return _data[(2 * N + 1 - r) * r / 2 + c - 2 * r - 1];
8349 else return T(0);
8350 } else if (type == MatType::SLOWER) {
8351 if (r >= c) return _data[(1 + r) * r / 2 + c - r];
8352 else return T(0);
8353 } else if (type == MatType::SYM) {
8354 if (r <= c) return _data[(2 * N + 1 - r) * r / 2 + c - r];
8355 else return _data[(2 * N + 1 - c) * c / 2 + r - c];
8356 } else if (type == MatType::ASYM) {
8357 if (r < c) return _data[(2 * N + 1 - r) * r / 2 + c - r * 2 - 1];
8358 else if (r > c) return -_data[(2 * N + 1 - c) * c / 2 + r - c * 2 - 1];
8359 else return T(0);
8360 } else {
8361 // Normally it is impossible to reach here.
8362 assert(!"Impossible! Unknown MatType!");
8363 return T(0);
8364 }
8365 }
8366
8373 T operator[](size_t index) const {
8374 if (index % (N + 1) == 0) return T(0);
8375 else return this->_data[index];
8376 }
8377
8385 MAT_COPY_OFFDIAG:
8386 for (size_t i = 0; i != N * N; ++i) {
8388 if (i % (N + 1) == 0) mat[i] = 0;
8389 else mat[i] = this->_data[i];
8390 }
8391 return mat;
8392 }
8393
8400 FLAMES_PRAGMA(INLINE)
8401 return static_cast<Mat<T, N, N, MatType::NORMAL>>(*this);
8402 }
8403
8404 public: // original private
8410 const T* _data;
8411};
8412
8413template <typename T, size_t n_rows, size_t n_cols, MatType type, typename type_parent>
8415 public:
8421 MatViewCol(const Mat<T, n_rows, n_cols, matType<type_parent>()>& m, size_t index) : _data(m.rawDataPtr() + index) {
8422 static_assert(type == MatType::NORMAL, "We only support limited matType.");
8423 assert(index < n_cols && "Take the specific col by index requires 'The index should be smaller than the number "
8424 "of the matrix's cols.'");
8425 }
8426
8433
8439 inline static constexpr size_t size() noexcept { return n_rows; }
8440
8446 inline static constexpr MatType pType() noexcept { return matType<type_parent>(); }
8447
8455 T operator()(size_t r, size_t c) const {
8456 assert(c == 0 && "Column vector's column index should always be 0.");
8457 assert(r < n_rows && "Matrix row index should be within range");
8458 constexpr MatType p_type = pType();
8459 if (p_type == MatType::NORMAL) {
8460 return _data[r * n_cols];
8461 } else {
8462 // Normally it is impossible to reach here.
8463 assert(!"Impossible! Unknown MatType!");
8464 }
8465 return _data[0];
8466 }
8467
8474 T operator[](size_t index) const { return (*this)(index, 0); }
8475
8480 operator Vec<T, n_rows>() const {
8481 Vec<T, n_rows> mat;
8482 MAT_COPY_COL:
8483 for (size_t i = 0; i != n_rows; ++i) {
8485 mat[i] = (*this)[i];
8486 }
8487 return mat;
8488 }
8489
8496 FLAMES_PRAGMA(INLINE);
8497 return static_cast<Vec<T, n_rows>>(*this);
8498 }
8499
8506 FLAMES_PRAGMA(INLINE);
8507 return static_cast<Vec<T, n_rows>>(*this);
8508 }
8509
8510 void print(const std::string& str = "", std::ostream& os = std::cout) const { this->asMat().print(str, os); }
8511
8512 public: // original private
8518 const T* const _data;
8519};
8520
8521template <typename T, size_t n_rows, size_t n_cols, MatType type, typename type_parent>
8523 public:
8529 MatViewRow(const Mat<T, n_rows, n_cols, matType<type_parent>()>& m, size_t index)
8530 : _data(m.rawDataPtr() + index * n_cols) {
8531 static_assert(type == MatType::NORMAL, "We only support limited matType.");
8532 assert(index < n_rows && "Take the specific row by index requires 'The index should be smaller than the number "
8533 "of the matrix's rows.'");
8534 }
8535
8542
8548 inline static constexpr size_t size() noexcept { return n_cols; }
8549
8555 inline static constexpr MatType pType() noexcept { return matType<type_parent>(); }
8556
8564 T operator()(size_t r, size_t c) const {
8565 assert(r == 0 && "Row vector's row index should always be 0.");
8566 assert(c < n_cols && "Matrix column index should be within range");
8567 constexpr MatType p_type = pType();
8568 if (p_type == MatType::NORMAL) {
8569 return _data[c];
8570 } else {
8571 // Normally it is impossible to reach here.
8572 assert(!"Impossible! Unknown MatType!");
8573 }
8574 return _data[0];
8575 }
8576
8583 T operator[](size_t index) const { return (*this)(0, index); }
8584
8589 operator RowVec<T, n_rows>() const {
8591 MAT_COPY_ROW:
8592 for (size_t i = 0; i != n_cols; ++i) {
8594 mat[i] = (*this)[i];
8595 }
8596 return mat;
8597 }
8598
8605 FLAMES_PRAGMA(INLINE);
8606 return static_cast<RowVec<T, n_cols>>(*this);
8607 }
8608
8615 FLAMES_PRAGMA(INLINE);
8616 return static_cast<Vec<T, n_cols>>(*this);
8617 }
8618
8619 void print(const std::string& str = "", std::ostream& os = std::cout) const { this->asMat().print(str, os); }
8620
8621 public: // original private
8627 const T* const _data;
8628};
8629
8630template <typename T, size_t n_rows, size_t n_cols, MatType type, typename type_parent>
8632 public:
8638 MatRefCol(Mat<T, n_rows, n_cols, matType<type_parent>()>& m, size_t index) : _data(m.rawDataPtr() + index) {
8639 static_assert(type == MatType::NORMAL, "We only support limited matType.");
8640 assert(index < n_cols && "Take the specific col by index requires 'The index should be smaller than the number "
8641 "of the matrix's cols.'");
8642 }
8643
8650 MatRefCol(const MatRefCol& m) : _data(m._data) {}
8651
8652 template <typename T_, size_t n_rows_, size_t n_cols_, MatType type_>
8654 for (size_t i = 0; i != size(); ++i) {
8656 _data[i * n_rows] = m[i];
8657 }
8658 return *this;
8659 }
8660
8661 template <typename M>
8662 void assign(M m) {
8663 for (size_t i = 0; i != size(); ++i) {
8665 _data[i * n_rows] = m[i];
8666 }
8667 }
8668
8674 inline static constexpr size_t size() noexcept { return n_rows; }
8675
8681 inline static constexpr MatType pType() noexcept { return matType<type_parent>(); }
8682
8690 T operator()(size_t r, size_t c) const {
8691 assert(c == 0 && "Column vector's column index should always be 0.");
8692 assert(r < n_rows && "Matrix row index should be within range");
8693 constexpr MatType p_type = pType();
8694 if (p_type == MatType::NORMAL) {
8695 return _data[r * n_cols];
8696 } else {
8697 // Normally it is impossible to reach here.
8698 assert(!"Impossible! Unknown MatType!");
8699 }
8700 return _data[0];
8701 }
8702
8703 T& operator()(size_t r, size_t c) {
8704 assert(c == 0 && "Column vector's column index should always be 0.");
8705 assert(r < n_rows && "Matrix row index should be within range");
8706 constexpr MatType p_type = pType();
8707 if (p_type == MatType::NORMAL) {
8708 return _data[r * n_cols];
8709 } else {
8710 // Normally it is impossible to reach here.
8711 assert(!"Impossible! Unknown MatType!");
8712 }
8713 return _data[0];
8714 }
8715
8722 T operator[](size_t index) const { return (*this)(index, 0); }
8723
8724 T& operator[](size_t index) { return (*this)(index, 0); }
8725
8730 operator Vec<T, n_rows>() const {
8731 Vec<T, n_rows> mat;
8732 MAT_COPY_COL:
8733 for (size_t i = 0; i != n_rows; ++i) {
8735 mat[i] = (*this)[i];
8736 }
8737 return mat;
8738 }
8739
8746 FLAMES_PRAGMA(INLINE);
8747 return static_cast<Vec<T, n_rows>>(*this);
8748 }
8749
8756 FLAMES_PRAGMA(INLINE);
8757 return static_cast<Vec<T, n_rows>>(*this);
8758 }
8759
8760 void print(const std::string& str = "", std::ostream& os = std::cout) const { this->asMat().print(str, os); }
8761
8762 public: // original private
8768 T* const _data;
8769};
8770
8771template <typename T, size_t n_rows, size_t n_cols, MatType type, typename type_parent>
8773 public:
8779 MatRefRow(Mat<T, n_rows, n_cols, matType<type_parent>()>& m, size_t index)
8780 : _data(m.rawDataPtr() + index * n_cols) {
8781 static_assert(type == MatType::NORMAL, "We only support limited matType.");
8782 assert(index < n_rows && "Take the specific row by index requires 'The index should be smaller than the number "
8783 "of the matrix's rows.'");
8784 }
8785
8792 MatRefRow(const MatRefRow& m) : _data(m._data) {}
8793
8794 template <typename T_, size_t n_rows_, size_t n_cols_, MatType type_>
8796 for (size_t i = 0; i != size(); ++i) {
8798 _data[i] = m[i];
8799 }
8800 return *this;
8801 }
8802
8803 template <typename M>
8804 void assign(M m) {
8805 for (size_t i = 0; i != size(); ++i) {
8807 _data[i] = m[i];
8808 }
8809 }
8810
8816 inline static constexpr size_t size() noexcept { return n_cols; }
8817
8823 inline static constexpr MatType pType() noexcept { return matType<type_parent>(); }
8824
8832 T operator()(size_t r, size_t c) const {
8833 assert(r == 0 && "Row vector's row index should always be 0.");
8834 assert(c < n_cols && "Matrix column index should be within range");
8835 constexpr MatType p_type = pType();
8836 if (p_type == MatType::NORMAL) {
8837 return _data[c];
8838 } else {
8839 // Normally it is impossible to reach here.
8840 assert(!"Impossible! Unknown MatType!");
8841 }
8842 return _data[0];
8843 }
8844
8845 T& operator()(size_t r, size_t c) {
8846 assert(r == 0 && "Row vector's row index should always be 0.");
8847 assert(c < n_cols && "Matrix column index should be within range");
8848 constexpr MatType p_type = pType();
8849 if (p_type == MatType::NORMAL) {
8850 return _data[c];
8851 } else {
8852 // Normally it is impossible to reach here.
8853 assert(!"Impossible! Unknown MatType!");
8854 }
8855 return _data[0];
8856 }
8857
8864 T operator[](size_t index) const { return (*this)(0, index); }
8865
8866 T& operator[](size_t index) { return (*this)(0, index); }
8867
8872 operator RowVec<T, n_cols>() const {
8874 MAT_COPY_ROW:
8875 for (size_t i = 0; i != n_cols; ++i) {
8877 mat[i] = (*this)[i];
8878 }
8879 return mat;
8880 }
8881
8888 FLAMES_PRAGMA(INLINE);
8889 return static_cast<RowVec<T, n_cols>>(*this);
8890 }
8891
8898 FLAMES_PRAGMA(INLINE);
8899 return static_cast<RowVec<T, n_cols>>(*this);
8900 }
8901
8902 void print(const std::string& str = "", std::ostream& os = std::cout) const { this->asMat().print(str, os); }
8903
8904 public: // original private
8910 T* const _data;
8911};
8912
8913template <size_t first_col, size_t last_col, typename T, size_t n_rows, size_t n_cols, MatType type,
8914 typename type_parent>
8916 public:
8922 MatViewCols(const Mat<T, n_rows, n_cols, matType<type_parent>()>& m) : _data(m.rawDataPtr()) {
8923 static_assert(last_col < n_cols, "Take the successive cols by indexes requires 'The indexes should be smaller "
8924 "than the number of the matrix's cols.'");
8925 static_assert(first_col > 0, "Take the specific col by index requires 'The indexes can't be smaller than 0.'");
8926 static_assert(first_col <= last_col, "The first index should be smaller than the second one.");
8927 }
8928
8935
8941 inline static constexpr size_t size() noexcept {
8942 return type == MatType::NORMAL ? n_rows * n_cols
8943 : type == MatType::DIAGONAL ? n_rows
8944 : type == MatType::SCALAR ? 1
8945 : type == MatType::SUPPER ? (n_rows - 1) * n_rows / 2
8946 : type == MatType::SLOWER ? (n_rows - 1) * n_rows / 2
8947 : type == MatType::ASYM ? (n_rows - 1) * n_rows / 2
8948 : (1 + n_rows) * n_rows / 2;
8949 }
8950
8956 inline static constexpr MatType pType() noexcept { return matType<type_parent>(); }
8957
8965 T operator()(size_t r, size_t c) const {
8966 assert(c < (last_col - first_col + 1) &&
8967 "The col index must be small than the number of the successive columns .");
8968 assert(r > 0 && "The row index can't be smaller than 0.");
8969 constexpr MatType p_type = pType();
8970 if (p_type == MatType::NORMAL) {
8971 return _data[r * n_cols + c + first_col];
8972 } else if (p_type == MatType::DIAGONAL) {
8973 if (r == (c + first_col)) return _data[r];
8974 else return T(0);
8975 } else if (p_type == MatType::SCALAR) {
8976 if (r == (c + first_col)) return _data[0];
8977 else return T(0);
8978 } else if (p_type == MatType::UPPER) {
8979 if (r <= (c + first_col)) return _data[(2 * n_cols + 1 - r) * r / 2 + c + first_col - r];
8980 else return T(0);
8981 } else if (p_type == MatType::LOWER) {
8982 if (r >= (c + first_col)) return _data[(1 + r) * r / 2 + c + first_col - r];
8983 else return T(0);
8984 } else if (p_type == MatType::SUPPER) {
8985 if (r < (c + first_col)) return _data[(2 * n_cols + 1 - r) * r / 2 + c + first_col - 2 * r - 1];
8986 else return T(0);
8987 } else if (p_type == MatType::SLOWER) {
8988 if (r >= (c + first_col)) return _data[(1 + r) * r / 2 + c + first_col - r];
8989 else return T(0);
8990 } else if (p_type == MatType::SYM) {
8991 if (r <= (c + first_col)) return _data[(2 * n_cols + 1 - r) * r / 2 + c + first_col - r];
8992 else return _data[(2 * n_cols + 1 - (c + first_col)) * (c + first_col) / 2 + r - (c + first_col)];
8993 } else if (p_type == MatType::ASYM) {
8994 if (r < (c + first_col)) return -_data[(2 * n_cols + 1 - r) * r / 2 + (c + first_col) - r * 2 - 1];
8995 else if (r > (c + first_col))
8996 return _data[(2 * n_cols + 1 - (c + first_col)) * (c + first_col) / 2 + r - (c + first_col) * 2 - 1];
8997 else return T(0);
8998 } else {
8999 // Normally it is impossible to reach here.
9000 assert(!"Impossible! Unknown MatType!");
9001 }
9002 }
9003
9010 T operator[](size_t index) const {
9011 return (*this)(index / (last_col - first_col + 1), index % (last_col - first_col + 1));
9012 }
9013
9018 operator Mat<T, n_rows, last_col - first_col + 1, MatType::NORMAL>() const {
9019 Mat<T, n_rows, last_col - first_col + 1, MatType::NORMAL> mat;
9020 MAT_COPY_COLS:
9021 for (size_t i = 0; i != n_rows * (last_col - first_col + 1); ++i) {
9023 mat[i] = (*this)[i];
9024 }
9025 return mat;
9026 }
9027
9033 Mat<T, n_rows, last_col - first_col + 1, MatType::NORMAL> asMat() const {
9034 FLAMES_PRAGMA(INLINE);
9035 return static_cast<Mat<T, n_rows, last_col - first_col + 1, MatType::NORMAL>>(*this);
9036 }
9037
9038 public: // original private
9044 const T* _data;
9045};
9046
9047template <size_t first_row, size_t last_row, typename T, size_t n_rows, size_t n_cols, MatType type,
9048 typename type_parent>
9050 public:
9056 MatViewRows(const Mat<T, n_cols, n_rows, matType<type_parent>()>& m) : _data(m.rawDataPtr()) {
9057 static_assert(last_row < n_rows, "Take the successive rows by indexes requires 'The indexes should be smaller "
9058 "than the number of the matrix's rows.'");
9059 static_assert(first_row > 0, "Take the specific row by index requires 'The indexes can't be smaller than 0.'");
9060 static_assert(first_row <= last_row, "The first index should be smaller than the second one.");
9061 }
9062
9069
9075 inline static constexpr size_t size() noexcept {
9076 return type == MatType::NORMAL ? n_rows * n_cols
9077 : type == MatType::DIAGONAL ? n_rows
9078 : type == MatType::SCALAR ? 1
9079 : type == MatType::SUPPER ? (n_rows - 1) * n_rows / 2
9080 : type == MatType::SLOWER ? (n_rows - 1) * n_rows / 2
9081 : type == MatType::ASYM ? (n_rows - 1) * n_rows / 2
9082 : (1 + n_rows) * n_rows / 2;
9083 }
9084
9090 inline static constexpr MatType pType() noexcept { return matType<type_parent>(); }
9091
9099 T operator()(size_t r, size_t c) const {
9100 assert(r < last_row - first_row && "The row index must be small than the number of the successive rows .");
9101 assert(c > 0 && "The row index can't be smaller than 0.");
9102 constexpr MatType p_type = pType();
9103 if (p_type == MatType::NORMAL) {
9104 return _data[(r + first_row) * n_cols + c];
9105 } else if (p_type == MatType::DIAGONAL) {
9106 if ((r + first_row) == c) return _data[r];
9107 else return T(0);
9108 } else if (p_type == MatType::SCALAR) {
9109 if ((r + first_row) == c) return _data[0];
9110 else return T(0);
9111 } else if (p_type == MatType::UPPER) {
9112 if ((r + first_row) <= c)
9113 return _data[(2 * n_cols + 1 - (r + first_row)) * (r + first_row) / 2 + c - (r + first_row)];
9114 else return T(0);
9115 } else if (p_type == MatType::LOWER) {
9116 if ((r + first_row) >= c) return _data[(1 + (r + first_row)) * (r + first_row) / 2 + c];
9117 else return T(0);
9118 } else if (p_type == MatType::SUPPER) {
9119 if ((r + first_row) < c)
9120 return _data[(2 * n_cols + 1 - (r + first_row)) * (r + first_row) / 2 + c - 2 * (r + first_row) - 1];
9121 else return T(0);
9122 } else if (p_type == MatType::SLOWER) {
9123 if ((r + first_row) >= c) return _data[(1 + (r + first_row)) * (r + first_row) / 2 + c - (r + first_row)];
9124 else return T(0);
9125 } else if (p_type == MatType::SYM) {
9126 if ((r + first_row) <= c)
9127 return _data[(2 * n_cols + 1 - (r + first_row)) * (r + first_row) / 2 + c - (r + first_row)];
9128 else return _data[(2 * n_cols + 1 - c) * c / 2 + (r + first_row) - c];
9129 } else if (p_type == MatType::ASYM) {
9130 if ((r + first_row) < c)
9131 return -_data[(2 * n_cols + 1 - (r + first_row)) * (r + first_row) / 2 + c - (r + first_row) * 2 - 1];
9132 else if ((r + first_row) > c) return _data[(2 * n_cols + 1 - c) * c / 2 + r - c * 2 - 1];
9133 else return T(0);
9134 } else {
9135 // Normally it is impossible to reach here.
9136 assert(!"Impossible! Unknown MatType!");
9137 }
9138 }
9139
9146 T operator[](size_t index) const { return (*this)(index / n_cols, index % n_cols); }
9147
9152 operator Mat<T, last_row - first_row + 1, n_cols, MatType::NORMAL>() const {
9153 Mat<T, last_row - first_row + 1, n_cols, MatType::NORMAL> mat;
9154 MAT_COPY_ROWS:
9155 for (size_t i = 0; i != n_rows * (last_row - first_row + 1); ++i) {
9157 mat[i] = (*this)[i];
9158 }
9159 return mat;
9160 }
9161
9167 Mat<T, last_row - first_row + 1, n_cols, MatType::NORMAL> asMat() const {
9168 FLAMES_PRAGMA(INLINE);
9169 return static_cast<Mat<T, last_row - first_row + 1, n_cols, MatType::NORMAL>>(*this);
9170 }
9171
9177 Mat<T, last_row - first_row + 1, n_cols, MatType::NORMAL> asVec() const {
9178 FLAMES_PRAGMA(INLINE);
9179 return static_cast<Mat<T, last_row - first_row + 1, n_cols, MatType::NORMAL>>(*this);
9180 }
9181
9182 public: // original private
9188 const T* _data;
9189};
9190
9209template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
9210 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
9211 typename T2, size_t n_rows, size_t n_cols, MatType type1, MatType type2>
9212static inline Mat<T1, n_rows, n_cols, sumType(type1, type2)>
9213operator+(const M1<T1, n_rows, n_cols, type1, _unused1...>& mat_L,
9214 const M2<T2, n_rows, n_cols, type2, _unused2...>& mat_R) {
9215 FLAMES_PRAGMA(INLINE)
9217 return mat.add(mat_L, mat_R);
9218}
9219
9235template <template <class, size_t, size_t, MatType, class...> typename M, typename... _unused, typename T1, typename T2,
9236 size_t n_rows, size_t n_cols, MatType type1, MatType type2>
9239 FLAMES_PRAGMA(INLINE)
9240 return mat_L.add(mat_R);
9241}
9242
9261template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
9262 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
9263 typename T2, size_t n_rows, size_t n_cols, MatType type1, MatType type2>
9264static inline Mat<T1, n_rows, n_cols, sumType(type1, type2)>
9265operator-(const M1<T1, n_rows, n_cols, type1, _unused1...>& mat_L,
9266 const M2<T2, n_rows, n_cols, type2, _unused2...>& mat_R) {
9267 FLAMES_PRAGMA(INLINE)
9269 return mat.sub(mat_L, mat_R);
9270}
9271
9287template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
9288 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
9289 typename T2, size_t n_rows, size_t n_cols, MatType type1, MatType type2>
9290static inline M1<T1, n_rows, n_cols, type1>& operator-=(M1<T1, n_rows, n_cols, type1, _unused1...>& mat_L,
9291 const M2<T2, n_rows, n_cols, type2, _unused2...>& mat_R) {
9292 FLAMES_PRAGMA(INLINE)
9293 return mat_L.sub(mat_R);
9294}
9295
9314template <template <class, size_t, size_t, MatType, class...> typename M, typename... _unused, typename T1, typename T2,
9315 size_t n_rows, size_t n_cols, MatType type1, MatType type2,
9316 std::enable_if_t<(std::is_same<T1, bool>::value), bool> = true>
9317static inline Mat<T1, n_rows, n_cols, mulType(type1, type2, n_rows, n_cols, n_cols)>
9319 FLAMES_PRAGMA(INLINE)
9320 Mat<T2, n_rows, n_cols, mulType(type1, type2, n_rows, n_cols, n_cols)> tmp;
9321 tmp.mul(mat, mat_R);
9322 return mat = tmp;
9323}
9324
9340template <template <class, size_t, size_t, MatType, class...> typename M, typename... _unused, typename T1, typename T2,
9341 size_t n_rows, size_t n_cols, MatType type1, MatType type2,
9342 std::enable_if_t<!(std::is_same<T1, bool>::value), bool> = true>
9343static inline Mat<T1, n_rows, n_cols, mulType(type1, type2, n_rows, n_cols, n_cols)>
9344operator*=(Mat<T1, n_rows, n_cols, type1>& mat, const M<T2, n_cols, n_cols, type2, _unused...>& mat_R) {
9345 FLAMES_PRAGMA(INLINE)
9346 Mat<T1, n_rows, n_cols, mulType(type1, type2, n_rows, n_cols, n_cols)> tmp;
9347 tmp.mul(mat, mat_R);
9348 return mat = tmp;
9349}
9350
9366template <template <class, size_t, size_t, MatType, class...> typename M, typename... _unused, typename T,
9367 typename ScalarT, size_t n_rows, size_t n_cols, MatType type,
9368 std::enable_if_t<std::is_arithmetic<std::remove_reference_t<ScalarT>>::value, bool> = true>
9370 FLAMES_PRAGMA(INLINE)
9371 return mat.mul(s);
9372}
9373
9391template <template <class, size_t, size_t, MatType, class...> typename M, typename... _unused, typename T,
9392 typename ScalarT, size_t n_rows, size_t n_cols, MatType type,
9393 std::enable_if_t<std::is_arithmetic<std::remove_reference_t<ScalarT>>::value, bool> = true>
9395 FLAMES_PRAGMA(INLINE)
9397 return mat.mul(mat_L, s);
9398}
9399
9418template <template <class, size_t, size_t, MatType, class...> typename M, typename... _unused, typename T,
9419 size_t n_rows, size_t n_cols, MatType type, int AP_W, int AP_I, ap_q_mode AP_Q, ap_o_mode AP_O, int AP_N>
9421 ap_fixed<AP_W, AP_I, AP_Q, AP_O, AP_N> s) {
9422 FLAMES_PRAGMA(INLINE)
9424 return mat.mul(mat_L, s);
9425}
9426
9444template <template <class, size_t, size_t, MatType, class...> typename M, typename... _unused, typename T,
9445 typename ScalarT, size_t n_rows, size_t n_cols, MatType type,
9446 std::enable_if_t<std::is_arithmetic<std::remove_reference_t<ScalarT>>::value, bool> = true>
9448 FLAMES_PRAGMA(INLINE)
9450 return mat.mul(mat_R, s);
9451}
9452
9471template <template <class, size_t, size_t, MatType, class...> typename M, typename... _unused, typename T,
9472 size_t n_rows, size_t n_cols, MatType type, int AP_W, int AP_I, ap_q_mode AP_Q, ap_o_mode AP_O, int AP_N>
9473static inline Mat<T, n_rows, n_cols, type> operator*(ap_fixed<AP_W, AP_I, AP_Q, AP_O, AP_N> s,
9475 FLAMES_PRAGMA(INLINE)
9477 return mat.mul(mat_R, s);
9478}
9479
9503template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
9504 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
9505 typename T2, size_t n_rows, size_t comm, size_t n_cols, MatType type1, MatType type2,
9506 std::enable_if_t<(std::is_same<T1, bool>::value), bool> = true>
9507static inline Mat<T2, n_rows, n_cols, mulType(type1, type2, n_rows, comm, n_cols)>
9508operator*(const M1<T1, n_rows, comm, type1, _unused1...>& mat_L,
9509 const M2<T2, comm, n_cols, type2, _unused2...>& mat_R) {
9510 Mat<T2, n_rows, n_cols, mulType(type1, type2, n_rows, comm, n_cols)> mat;
9511 mat.mul(mat_L, mat_R);
9512 return mat;
9513 // if "return mat.mul(mat_L, mat_R);" , then there will be a error. But I don't know why.
9514}
9515
9516template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
9517 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
9518 typename T2, size_t n_rows, size_t comm, size_t n_cols, MatType type1, MatType type2,
9519 std::enable_if_t<!(std::is_same<T1, bool>::value), bool> = true>
9520static inline Mat<T1, n_rows, n_cols, mulType(type1, type2, n_rows, comm, n_cols)>
9521operator*(const M1<T1, n_rows, comm, type1, _unused1...>& mat_L,
9522 const M2<T2, comm, n_cols, type2, _unused2...>& mat_R) {
9523 Mat<T1, n_rows, n_cols, mulType(type1, type2, n_rows, comm, n_cols)> mat;
9524 mat.mul(mat_L, mat_R);
9525 return mat;
9526 // if "return mat.mul(mat_L, mat_R);" , then there will be a error. But I don't know why.
9527}
9528
9550template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
9551 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
9552 typename T2, size_t n_rows, size_t n_cols, MatType type>
9553Mat<T1, n_rows, n_cols, type> operator%(const M1<T1, n_rows, n_cols, type, _unused1...>& mat_L,
9554 const M2<T2, n_rows, n_cols, type, _unused2...>& mat_R) {
9556 return mat.emul(mat_L, mat_R);
9557}
9558
9577template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
9578 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
9579 typename T2, size_t n_rows, size_t n_cols, MatType type>
9580Mat<bool, n_rows, n_cols, type> operator==(const M1<T1, n_rows, n_cols, type, _unused1...>& mat_L,
9581 const M2<T2, n_rows, n_cols, type, _unused2...>& mat_R) {
9583OPERATOR_EQUAL:
9584 for (size_t i = 0; i != mat_L.size(); ++i) {
9586 mat[i] = mat_L[i] == mat_R[i];
9587 }
9588 return mat;
9589}
9590
9609template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
9610 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
9611 typename T2, size_t n_rows, size_t n_cols, MatType type>
9612Mat<bool, n_rows, n_cols, type> operator!=(const M1<T1, n_rows, n_cols, type, _unused1...>& mat_L,
9613 const M2<T2, n_rows, n_cols, type, _unused2...>& mat_R) {
9615OPERATOR_UNEQUAL:
9616 for (size_t i = 0; i != mat_L.size(); ++i) {
9618 mat[i] = mat_L[i] != mat_R[i];
9619 }
9620 return mat;
9621}
9622
9641template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
9642 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
9643 typename T2, size_t n_rows, size_t n_cols, MatType type>
9644Mat<bool, n_rows, n_cols, type> operator>(const M1<T1, n_rows, n_cols, type, _unused1...>& mat_L,
9645 const M2<T2, n_rows, n_cols, type, _unused2...>& mat_R) {
9647OPERATOR_GREATER:
9648 for (size_t i = 0; i != mat_L.size(); ++i) {
9650 mat[i] = mat_L[i] > mat_R[i];
9651 }
9652 return mat;
9653}
9654
9673template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
9674 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
9675 typename T2, size_t n_rows, size_t n_cols, MatType type>
9676Mat<bool, n_rows, n_cols, type> operator<(const M1<T1, n_rows, n_cols, type, _unused1...>& mat_L,
9677 const M2<T2, n_rows, n_cols, type, _unused2...>& mat_R) {
9678 Mat<bool, n_rows, n_cols, type> mat;
9679OPERATOR_LESS:
9680 for (size_t i = 0; i != mat_L.size(); ++i) {
9682 mat[i] = mat_L[i] < mat_R[i];
9683 }
9684 return mat;
9685}
9686
9705template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
9706 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
9707 typename T2, size_t n_rows, size_t n_cols, MatType type>
9708Mat<bool, n_rows, n_cols, type> operator>=(const M1<T1, n_rows, n_cols, type, _unused1...>& mat_L,
9709 const M2<T2, n_rows, n_cols, type, _unused2...>& mat_R) {
9711OPERATOR_GEQ:
9712 for (size_t i = 0; i != mat_L.size(); ++i) {
9714 mat[i] = mat_L[i] >= mat_R[i];
9715 }
9716 return mat;
9717}
9718
9737template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
9738 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
9739 typename T2, size_t n_rows, size_t n_cols, MatType type>
9740Mat<bool, n_rows, n_cols, type> operator<=(const M1<T1, n_rows, n_cols, type, _unused1...>& mat_L,
9741 const M2<T2, n_rows, n_cols, type, _unused2...>& mat_R) {
9742 Mat<bool, n_rows, n_cols, type> mat;
9743OPERATOR_LEQ:
9744 for (size_t i = 0; i != mat_L.size(); ++i) {
9746 mat[i] = mat_L[i] <= mat_R[i];
9747 }
9748 return mat;
9749}
9750
9769template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
9770 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
9771 typename T2, size_t n_rows, size_t n_cols, MatType type>
9772Mat<T1, n_rows, n_cols, type> mod(const M1<T1, n_rows, n_cols, type, _unused1...>& mat_L,
9773 const M2<T2, n_rows, n_cols, type, _unused2...>& mat_R) {
9775OPERATOR_LEQ:
9776 for (size_t i = 0; i != mat_L.size(); ++i) {
9778 mat[i] = mat_L[i] % mat_R[i]; // Operator % Should be defined, otherwise compilation error.
9779 }
9780 return mat;
9781}
9782
9783template <typename Tp = double, template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
9784 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
9785 typename T2, size_t L_rows, size_t L_cols, size_t R_rows, size_t R_cols, MatType type,
9786 std::enable_if_t<L_rows * L_cols == R_rows * R_cols, bool> = true>
9787Tp innerProd(const M1<T1, L_rows, L_cols, type, _unused1...>& mat_L,
9788 const M2<T2, R_rows, R_cols, type, _unused2...>& mat_R) {
9789 assert(mat_L.size() == mat_R.size() && "Dimension should meet for innerProd.");
9790 Tp result = 0;
9791INNER_PROD:
9792 for (size_t i = 0; i != mat_L.size(); ++i) {
9794 result += static_cast<Tp>(mat_L[i] * mat_R[i]);
9795 }
9796 return result;
9797}
9798
9811template <typename T, size_t n_rows, size_t n_cols, MatType type>
9812static inline std::ostream& operator<<(std::ostream& os, const Mat<T, n_rows, n_cols, type>& mat) {
9813 mat.print("", os);
9814 return os;
9815}
9816
9817} // namespace flames
9818
9819#ifndef FLAMES_PRESERVE_WARNING
9820# ifdef __SYNTHESIS__
9821# pragma GCC diagnostic pop
9822# endif
9823#endif
9824
9825#ifdef DEFINED_INLINE
9826# define INLINE inline
9827# undef DEFINED_INLINE
9828#endif
9829
9830#endif
Matrix.
Definition: core.hpp:565
Mat & sub(const M< T2, n_rows, n_cols, type2, _unused... > &mat_R)
Matrix self minus a matrix.
Definition: core.hpp:1739
MatViewOpp< T, n_rows, n_cols, type > opp_() const
Matrix opposite as a read only view.
Definition: core.hpp:6290
Mat< T, _rows, n_cols, MatType::NORMAL > rows(M2 vector)
Take discrete rows of a matrix by container and make a copy.
Definition: core.hpp:5809
T operator[](size_t index) const
Get read only element by row major index from the data array.
Definition: core.hpp:850
Mat & mul(ap_int< AP_W > s)
Matrix self multiply ap_int integer.
Definition: core.hpp:1916
Mat & rows(const M< T2, rows_, cols_, type2, _unused... > &mat, size_t first_row)
Take successive rows of a matrix by index.
Definition: core.hpp:5681
Vec< T, n_rows > diagVec() const
Take the diagonal vector of a matrix and make a copy.
Definition: core.hpp:6407
void _sa_read_first_col_L(size_t i, Tmp &tmp_L, const M &mat_L, size_t begin_shift, Comm __attribute__((unused)) _comm_foo, Zero zero) const
Systolic array read the first column from the left matrix.
Definition: core.hpp:6866
T * rawDataPtr()
Get the raw data array pointer.
Definition: core.hpp:6769
MatRefCol< T, n_rows, n_cols, MatType::NORMAL, MType< type > > col_(size_t index)
Definition: core.hpp:5502
Mat< T, n_rows, _cols, MatType::NORMAL > cols(M2 vector)
Take discrete cols of a matrix by container and make a copy.
Definition: core.hpp:5881
T & operator()(size_t r, size_t c)
Get writeable data element by row index and column index.
Definition: core.hpp:921
void _tryAssign(size_t r, size_t c, T value)
Try to assign a value to a specific position.
Definition: core.hpp:6783
Mat & t(const M< T2, n_cols, n_rows, type2, _unused... > &mat)
Transpose.
Definition: core.hpp:5927
Mat< T, n_rows, n_cols, MatType::NORMAL > offDiag() const
Take the off diagonal of a matrix and make a copy.
Definition: core.hpp:6528
Mat< T, 1, n_cols, MatType::NORMAL > row(size_t r) const
Take a row of a matrix by index and make a copy.
Definition: core.hpp:5549
Mat & invNSA(const M< T2, n_rows, n_cols, type2, _unused... > &mat, size_t iter=4)
Matrix inverse using Newton-Schulz iterative method (NSA).
Definition: core.hpp:6608
Mat & diagMat(const M< T2, n_rows, n_cols, type2, _unused... > &mat)
Take the diagonal of a matrix.
Definition: core.hpp:6327
Mat & diagVec(const M< T2, n_rows, n_rows, type2, _unused... > &mat)
Take the diagonal vector of a matrix.
Definition: core.hpp:6384
Mat(Init init)
Definition: core.hpp:744
Mat & oppSelf()
In-place matrix opposite.
Definition: core.hpp:6304
void _sa_read_first_row_R(size_t i, Tmp &tmp_R, const M &mat_R, size_t begin_shift, Comm __attribute__((unused)) _comm_foo, Zero zero) const
Systolic array read the first column from the right matrix.
Definition: core.hpp:6893
void _tryAssignOutRange(size_t r, size_t c, T value)
Try to assign a value to a specific position that may have out-of-range index.
Definition: core.hpp:6814
Mat & tSelf()
In-place transpose.
Definition: core.hpp:6213
Mat(T *const ptr, InitAfterwards opt=InitAfterwards::NONE)
Definition: core.hpp:782
Mat & diagRowVec(const M< T2, n_cols, n_cols, type2, _unused... > &mat)
Take the diagonal row vector of a matrix.
Definition: core.hpp:6442
~Mat()
Destroy the Mat object.
Definition: core.hpp:815
Mat & invINSA(const M< T2, n_rows, n_cols, type2, _unused... > &mat, size_t iter=3, coeff_type beta=2)
Matrix inverse using improved Newton-Schulz iterative method (INSA).
Definition: core.hpp:6665
Mat & invDiag(const M< T2, n_cols, n_rows, type2, _unused... > &mat)
Inverse the diagonal matrix.
Definition: core.hpp:6571
Mat & rows(const M1< T1, rows_, cols_, type1, _unused1... > &mat, M2 vector)
Take discrete rows of a matrix by container.
Definition: core.hpp:5773
T & operator[](size_t index)
Get writeable element by row major index from the data array.
Definition: core.hpp:864
void setZero()
Set all elements of the matrix to zero.
Definition: core.hpp:979
Mat< T, _rows, n_cols, MatType::NORMAL > rows(size_t first_row)
Take successive rows of a matrix by index and make a copy.
Definition: core.hpp:5718
Mat & opp(const M< T2, n_rows, n_cols, type, _unused... > &mat)
Calculate the opposite of a matrix.
Definition: core.hpp:6252
Mat & mul(const M< T2, n_rows, n_cols, type, _unused... > &mat, ScalarT s)
Matrix times a scalar.
Definition: core.hpp:1769
const T * rawDataPtr() const
Definition: core.hpp:6771
MatViewOffDiag< T, n_rows, n_cols, MatType::NORMAL, MType< type > > offDiag_() const
Take the diagonal of a matrix as a read only view.
Definition: core.hpp:6548
MatViewOpp< T, n_rows, n_cols, type > operator-() const
The unary minus operator.
Definition: core.hpp:6755
MatViewT< T, n_cols, n_rows, tType(type)> t_()
Transpose as a read only view.
Definition: core.hpp:6200
MatViewRows< first_row, last_row, T, n_rows, n_cols, MatType::NORMAL, MType< type > > Rows_() const
Take successive rows of a matrix by indexes as a read only view.
Definition: core.hpp:5744
Mat invNSA(size_t iter=4) const
Matrix inverse using Newton-Schulz iterative method (NSA) as a copy.
Definition: core.hpp:6641
Mat & cols(const M1< T1, rows_, cols_, type1, _unused1... > &mat, M2 vector)
Take discrete cols of a matrix by container.
Definition: core.hpp:5845
MatViewCol< T, n_rows, n_cols, MatType::NORMAL, MType< type > > col_(size_t index) const
Take a column of a matrix by index as a read only view.
Definition: core.hpp:5496
Mat & mul(ScalarT s)
Matrix self multiply a scalar.
Definition: core.hpp:1874
Mat & add(const M1< T1, n_rows, n_cols, type1, _unused1... > &mat_L, const M2< T2, n_rows, n_cols, type2, _unused2... > &mat_R)
Matrix plus matrix into NORMAL.
Definition: core.hpp:1076
Mat< T, n_rows, 1, MatType::NORMAL > col(size_t c) const
Take a column of a matrix by index and make a copy.
Definition: core.hpp:5480
Mat & mul(const M< T2, n_rows, n_cols, type, _unused... > &mat, ap_int< AP_W > s)
Matrix times ap_int integer.
Definition: core.hpp:1822
Mat & mul(ap_fixed< AP_W, AP_I, AP_Q, AP_O, AP_N > s)
Matrix self multiply ap_fixed float.
Definition: core.hpp:1940
Mat< T, n_rows, _cols, MatType::NORMAL > cols(size_t first_col)
Take successive columns of a matrix by index and make a copy.
Definition: core.hpp:5627
Mat & mul(std::complex< ScalarT > s)
Matrix self multiply a complex number.
Definition: core.hpp:1896
void col(size_t c, const M< T2, rows_, cols_, type2, _unused... > &mat)
Definition: core.hpp:5456
Mat()
Construct a new Mat object.
Definition: core.hpp:604
MatViewDiagVec< T, n_rows, 1, MatType::NORMAL, MType< type > > diagVec_() const
Take the diagonal vector of a matrix as a read only view.
Definition: core.hpp:6422
T & value()
Get the writeable value from 1x1 matrix.
Definition: core.hpp:6713
MatViewDiagMat< T, n_rows, n_cols, MatType::DIAGONAL, MType< type > > diagMat_() const
Take the diagonal of a matrix as a read only view.
Definition: core.hpp:6364
T _data[type==MatType::NORMAL ? n_rows *n_cols :type==MatType::DIAGONAL ? n_rows :type==MatType::SCALAR ? 1 :type==MatType::SUPPER ?(n_rows - 1) *n_rows/2 :type==MatType::SLOWER ?(n_rows - 1) *n_rows/2 :type==MatType::ASYM ?(n_rows - 1) *n_rows/2 :(1+n_rows) *n_rows/2]
The raw data array in row major.
Definition: core.hpp:7043
Mat & _systolicArrayMul(const M1< T1, n_rows, comm, type1, _unused1... > &mat_L, const M2< T2, comm, n_cols, type2, _unused2... > &mat_R, size_t begin_shift=0, size_t end_shift=0)
The systolic array multiplication.
Definition: core.hpp:6959
static constexpr size_t size() noexcept
Get the matrix size of storage.
Definition: core.hpp:832
Mat & mul(const M< T2, n_rows, n_cols, type, _unused... > &mat, std::complex< ScalarT > s)
Matrix times a complex number.
Definition: core.hpp:1797
Mat< T, n_rows, n_cols, MatType::SLOWER > t() const
Transpose SUPPER matrix as a copy.
Definition: core.hpp:6120
Tp power() const
Definition: core.hpp:6689
Mat & cols(const M< T2, rows_, cols_, type2, _unused... > &mat, size_t first_col)
Take successive columns of a matrix by index.
Definition: core.hpp:5591
Mat & row(const M< T2, rows_, cols_, type2, _unused... > &mat, size_t r)
Take a row of a matrix by index.
Definition: core.hpp:5525
Mat & sub(const M1< T1, n_rows, n_cols, type1, _unused1... > &mat_L, const M2< T2, n_rows, n_cols, type2, _unused2... > &mat_R)
Matrix minus matrix into NORMAL.
Definition: core.hpp:1434
Mat & abs_()
Apply 'abs' (absolute value) to itself.
Definition: core.hpp:5903
Mat(const T *ptr, InitAfterwards opt=InitAfterwards::NONE)
Construct a new Mat object from raw data pointer.
Definition: core.hpp:755
bool read(const std::string &file_name)
Definition: core.hpp:981
Mat< T, n_rows, n_cols, MatType::UPPER > t() const
Transpose LOWER matrix as a copy.
Definition: core.hpp:6089
Mat t() const
Transpose DIAGONAL/SCALAR/SYM matrix as a copy.
Definition: core.hpp:6037
T element_type
Definition: core.hpp:592
Mat< T, n_rows, n_cols, MatType::LOWER > t() const
Transpose UPPER matrix as a copy.
Definition: core.hpp:6058
void _sa_multiply(const T1 &tmp_L, const T2 &tmp_R, const HLSVec &use_assign)
Systolic array multiplication.
Definition: core.hpp:6917
Mat(T val)
Construct a new Mat object with initial value.
Definition: core.hpp:623
MatViewCols< first_col, last_col, T, n_rows, n_cols, MatType::NORMAL, MType< type > > Cols_() const
Take seccessive columns of a matrix by indexes as a read only view.
Definition: core.hpp:5652
void setValue(T val)
Set all elements of the matrix to a value.
Definition: core.hpp:968
Mat invINSA(size_t iter=3, coeff_type beta=1.0) const
Matrix inverse using improved Newton-Schulz iterative method (INSA) as a copy.
Definition: core.hpp:6680
Mat< T, n_cols, n_rows, type > t() const
Transpose NORMAL matrix as a copy.
Definition: core.hpp:6006
Mat & col(const M< T2, rows_, cols_, type2, _unused... > &mat, size_t c)
Take a column of a matrix by index.
Definition: core.hpp:5442
Mat & offDiag(const M< T2, n_cols, n_rows, type2, _unused... > &mat)
Take the off diagonal of a matrix.
Definition: core.hpp:6500
Mat invDiag() const
Inverse the diagonal matrix and makes a copy.
Definition: core.hpp:6586
void print(const std::string &str="", std::ostream &os=std::cout) const
Print the matrix.
Definition: core.hpp:6724
Mat opp() const
Calculate the opposite of a matrix and make a copy.
Definition: core.hpp:6275
T value() const
Get the value from 1x1 matrix.
Definition: core.hpp:6703
Mat(std::initializer_list< T2 > list)
Definition: core.hpp:726
MatViewT< T, n_cols, n_rows, tType(type)> t_() const
Definition: core.hpp:6202
RowVec< T, n_cols > diagRowVec() const
Take the diagonal row vector of a matrix and make a copy.
Definition: core.hpp:6465
Mat & mul(const M< T2, n_rows, n_cols, type, _unused... > &mat, ap_fixed< AP_W, AP_I, AP_Q, AP_O, AP_N > s)
Matrix times ap_fixed float.
Definition: core.hpp:1851
Mat(const Mat &mat)
Copy constructor from a Mat object.
Definition: core.hpp:644
Mat & mul(const M1< T1, rows_, comm, type1, _unused1... > &mat_L, const M2< T2, comm, cols_, type2, _unused2... > &mat_R)
General matrix matrix multiplication.(Including SYM or NORMAL matrix times a SYM or NORMAL matrix )
Definition: core.hpp:1980
Mat & add(const M< T2, n_rows, n_cols, type2, _unused... > &mat_R)
Matrix self plus a matrix.
Definition: core.hpp:1377
MatViewDiagRowVec< T, 1, n_cols, MatType::NORMAL, MType< type > > diagRowVec_() const
Take the diagonal row vector of a matrix as a read only view.
Definition: core.hpp:6480
Mat & emul(const M1< T1, rows_, cols_, type1, _unused1... > &mat_L, const M2< T2, rows_, cols_, type2, _unused2... > &mat_R)
Element-wise product of two matrices.
Definition: core.hpp:5417
MatView< T, n_rows, n_cols, type > operator+() const
The unary plus operator.
Definition: core.hpp:6744
T operator()(size_t r, size_t c) const
Get read only data element by row index and column index.
Definition: core.hpp:877
Mat(const Mat< T2, _rows, _cols, _type > &mat)
Definition: core.hpp:663
Mat & add(const M1< T1, n_rows, n_cols, type, _unused1... > &mat_L, const M2< T2, n_rows, n_cols, type, _unused2... > &mat_R)
Matrix plus matrix with same MatType.
Definition: core.hpp:1043
Mat(const std::vector< T > &vec)
Construct a new Mat object from std::vector.
Definition: core.hpp:708
Mat< T, n_rows, n_cols, MatType::DIAGONAL > diagMat() const
Take the diagonal of a matrix and make a copy.
Definition: core.hpp:6350
Mat & sub(const M1< T1, n_rows, n_cols, type, _unused1... > &mat_L, const M2< T2, n_rows, n_cols, type, _unused2... > &mat_R)
Matrix minus matrix with same MatType.
Definition: core.hpp:1401
T value_type
Definition: core.hpp:593
void _tryPlus(size_t r, size_t c, T value)
Try to plus a value to a specific position.
Definition: core.hpp:6829
Definition: core.hpp:8631
void assign(M m)
Definition: core.hpp:8662
T operator[](size_t index) const
Get the read only element by array row major index.
Definition: core.hpp:8722
T operator()(size_t r, size_t c) const
Get the read only data element from row and column index.
Definition: core.hpp:8690
T & operator()(size_t r, size_t c)
Definition: core.hpp:8703
Vec< T, n_rows > asMat() const
Explicitly make a Mat copy.
Definition: core.hpp:8745
T *const _data
Raw data pointer.
Definition: core.hpp:8768
MatRefCol(Mat< T, n_rows, n_cols, matType< type_parent >()> &m, size_t index)
Construct a new MatRefCol object from raw data pointer.
Definition: core.hpp:8638
T & operator[](size_t index)
Definition: core.hpp:8724
static constexpr size_t size() noexcept
The data element number.
Definition: core.hpp:8674
MatRefCol(const MatRefCol &m)
Copy constructor.
Definition: core.hpp:8650
Vec< T, n_rows > asVec() const
Explicitly make a Mat (Vec) copy.
Definition: core.hpp:8755
void print(const std::string &str="", std::ostream &os=std::cout) const
Definition: core.hpp:8760
MatRefCol & operator=(const Mat< T_, n_rows_, n_cols_, type_ > &m)
Definition: core.hpp:8653
static constexpr MatType pType() noexcept
Parent matrix as MatType.
Definition: core.hpp:8681
Definition: core.hpp:7293
T operator[](size_t index) const
Get the read only element by array row major index.
Definition: core.hpp:7442
T operator()(size_t r, size_t c) const
Get the read only data element from row and column index.
Definition: core.hpp:7349
void col(size_t c, const M< T2, rows_, cols_, type2, _unused... > &mat)
Definition: core.hpp:7507
T *const _data
Definition: core.hpp:7613
MatRef & operator=(const Mat< T, n_rows, n_cols, type > &m)
Definition: core.hpp:7326
Mat< T, n_rows, n_cols, type > asMat() const
Explicitly make a Mat copy.
Definition: core.hpp:7604
T & operator[](size_t index)
Get the writeable element by array row major index.
Definition: core.hpp:7454
static constexpr size_t size() noexcept
The data element number.
Definition: core.hpp:7316
void assign(M m)
Definition: core.hpp:7335
MatViewT< T, n_cols, n_rows, type > t_() const
Definition: core.hpp:7566
void setValue(T val)
Set all elements of the matrix to a value.
Definition: core.hpp:7465
MatRef & col(const M< T2, rows_, cols_, type2, _unused... > &mat, size_t c)
Take a column of a matrix by index.
Definition: core.hpp:7494
void print(const std::string &str="", std::ostream &os=std::cout) const
Definition: core.hpp:7609
MatRef & add(const M< T2, n_rows, n_cols, type2, _unused... > &mat_R)
Definition: core.hpp:7544
MatRef & sub(const M< T2, n_rows, n_cols, type2, _unused... > &mat_R)
Definition: core.hpp:7556
T & operator()(size_t r, size_t c)
Get writeable data element by row index and column index.
Definition: core.hpp:7394
Tp abssum() const
Definition: core.hpp:7579
MatRef(Mat< T, n_rows, n_cols, type > &m)
Construct a new MatView object from raw data pointer.
Definition: core.hpp:7300
void setZero()
Set all elements of the matrix to zero.
Definition: core.hpp:7476
MatRef(const T *const ptr)
Definition: core.hpp:7302
Mat< T, n_rows, 1, MatType::NORMAL > col(size_t c) const
Take a column of a matrix by index and make a copy.
Definition: core.hpp:7531
Tp power() const
Definition: core.hpp:7569
MatRef(const MatRef &m)
Copy constructor.
Definition: core.hpp:7309
Definition: core.hpp:8772
T *const _data
Raw data pointer.
Definition: core.hpp:8910
T operator()(size_t r, size_t c) const
Get the read only data element from row and column index.
Definition: core.hpp:8832
void assign(M m)
Definition: core.hpp:8804
static constexpr size_t size() noexcept
The data element number.
Definition: core.hpp:8816
static constexpr MatType pType() noexcept
Parent matrix as MatType.
Definition: core.hpp:8823
MatRefRow(Mat< T, n_rows, n_cols, matType< type_parent >()> &m, size_t index)
Construct a new MatRefRow object from raw data pointer.
Definition: core.hpp:8779
T & operator[](size_t index)
Definition: core.hpp:8866
RowVec< T, n_cols > asMat() const
Explicitly make a Mat copy.
Definition: core.hpp:8887
void print(const std::string &str="", std::ostream &os=std::cout) const
Definition: core.hpp:8902
T operator[](size_t index) const
Get the read only element by array row major index.
Definition: core.hpp:8864
MatRefRow & operator=(const Mat< T_, n_rows_, n_cols_, type_ > &m)
Definition: core.hpp:8795
MatRefRow(const MatRefRow &m)
Copy constructor.
Definition: core.hpp:8792
T & operator()(size_t r, size_t c)
Definition: core.hpp:8845
RowVec< T, n_cols > asVec() const
Explicitly make a Mat (RowVec) copy.
Definition: core.hpp:8897
Read only view version of a certain column as colunm vector.
Definition: core.hpp:8414
T operator[](size_t index) const
Get the read only element by array row major index.
Definition: core.hpp:8474
MatViewCol(const MatViewCol &m)
Copy constructor.
Definition: core.hpp:8432
Vec< T, n_rows > asMat() const
Explicitly make a Mat copy.
Definition: core.hpp:8495
MatViewCol(const Mat< T, n_rows, n_cols, matType< type_parent >()> &m, size_t index)
Construct a new MatViewCol object from raw data pointer.
Definition: core.hpp:8421
Vec< T, n_rows > asVec() const
Explicitly make a Mat (Vec) copy.
Definition: core.hpp:8505
void print(const std::string &str="", std::ostream &os=std::cout) const
Definition: core.hpp:8510
static constexpr size_t size() noexcept
The data element number.
Definition: core.hpp:8439
T operator()(size_t r, size_t c) const
Get the read only data element from row and column index.
Definition: core.hpp:8455
static constexpr MatType pType() noexcept
Parent matrix as MatType.
Definition: core.hpp:8446
const T *const _data
Raw data pointer.
Definition: core.hpp:8518
Read only view version of successive columns.
Definition: core.hpp:8915
static constexpr size_t size() noexcept
The data element number.
Definition: core.hpp:8941
MatViewCols(const Mat< T, n_rows, n_cols, matType< type_parent >()> &m)
Construct a new MatViewCols object from raw data pointer.
Definition: core.hpp:8922
MatViewCols(const MatViewCols &m)
Copy constructor.
Definition: core.hpp:8934
const T * _data
Raw data pointer.
Definition: core.hpp:9044
T operator()(size_t r, size_t c) const
Get the read only data element from row and column index.
Definition: core.hpp:8965
T operator[](size_t index) const
Get the read only element by array row major index.
Definition: core.hpp:9010
Mat< T, n_rows, last_col - first_col+1, MatType::NORMAL > asMat() const
Explicitly make a Mat copy.
Definition: core.hpp:9033
static constexpr MatType pType() noexcept
Parent matrix as MatType.
Definition: core.hpp:8956
Read only view version of a diagonal matrix.
Definition: core.hpp:7878
MatViewDiagMat(const Mat< T, N, N, matType< type_parent >()> &m)
Construct a new MatViewDiagMat object from a raw data pointer.
Definition: core.hpp:7885
T operator()(size_t r, size_t c) const
Get the read only data element from row and column index.
Definition: core.hpp:7940
static constexpr size_t size() noexcept
The data element number.
Definition: core.hpp:7916
Mat< T, N, N, MatType::DIAGONAL > inv() const
Return a inverse matrix.
Definition: core.hpp:7901
static constexpr MatType pType() noexcept
Parent matrix as MatType.
Definition: core.hpp:7931
T operator[](size_t index) const
Get the read only element by array row major index.
Definition: core.hpp:7973
Mat< T, N, N, MatType::DIAGONAL > asMat() const
Explicitly make a Mat copy.
Definition: core.hpp:7999
MatViewDiagMat(const MatViewDiagMat &m)
Copy constructor.
Definition: core.hpp:7894
const T * _data
Raw data pointer.
Definition: core.hpp:8010
Read only view version of a diagonal matrix as row vector.
Definition: core.hpp:8156
MatViewDiagRowVec(const MatViewDiagRowVec &m)
Copy constructor.
Definition: core.hpp:8172
static constexpr MatType pType() noexcept
Parent matrix as MatType.
Definition: core.hpp:8194
T operator[](size_t index) const
Get the read only element by array row major index.
Definition: core.hpp:8236
MatViewDiagRowVec(const Mat< T, N, N, matType< type_parent >()> &m)
Construct a new MatViewDiagRowVec object from raw data pointer.
Definition: core.hpp:8163
RowVec< T, N > asRowVec() const
Explicitly make a Mat (RowVec) copy.
Definition: core.hpp:8268
const T * _data
Raw data pointer.
Definition: core.hpp:8279
RowVec< T, N > asMat() const
Explicitly make a Mat copy.
Definition: core.hpp:8258
T operator()(size_t r, size_t c) const
Get the read only data element from row and column index.
Definition: core.hpp:8203
static constexpr size_t size() noexcept
The data element number.
Definition: core.hpp:8179
Read only view version of a diagonal matrix as vector.
Definition: core.hpp:8014
Vec< T, N > inv() const
Return a inverse matrix.
Definition: core.hpp:8052
T operator[](size_t index) const
Get the read only element by array row major index.
Definition: core.hpp:8109
MatViewDiagVec(const Mat< T, N, N, matType< type_parent >()> &m)
Construct a new MatViewDiagVec object from raw data pointer.
Definition: core.hpp:8021
Vec< T, N > asVec() const
Explicitly make a Mat (Vec) copy.
Definition: core.hpp:8141
static constexpr size_t size() noexcept
The data element number.
Definition: core.hpp:8037
static constexpr MatType pType() noexcept
Parent matrix as MatType.
Definition: core.hpp:8067
const T * _data
Raw data pointer.
Definition: core.hpp:8152
T operator()(size_t r, size_t c) const
Get the read only data element from row and column index.
Definition: core.hpp:8076
MatViewDiagVec(const MatViewDiagVec &m)
Copy constructor.
Definition: core.hpp:8030
Vec< T, N > asMat() const
Explicitly make a Mat copy.
Definition: core.hpp:8131
Read only view version of a matrix.
Definition: core.hpp:7047
static constexpr size_t size() noexcept
The data element number.
Definition: core.hpp:7071
Mat< T, n_rows, 1, MatType::NORMAL > col(size_t c) const
Take a column of a matrix by index and make a copy.
Definition: core.hpp:7207
void assign(M m)
Definition: core.hpp:7090
MatView(const T *const ptr)
Definition: core.hpp:7057
MatView(Mat< T, n_rows, n_cols, type > &m)
Definition: core.hpp:7055
T operator()(size_t r, size_t c) const
Get the read only data element from row and column index.
Definition: core.hpp:7104
MatView & operator=(const Mat< T, n_rows, n_cols, type > &m)
Definition: core.hpp:7081
void print(const std::string &str="", std::ostream &os=std::cout) const
Definition: core.hpp:7285
MatView & sub(const M< T2, n_rows, n_cols, type2, _unused... > &mat_R)
Definition: core.hpp:7232
const T *const _data
Definition: core.hpp:7289
MatViewT< T, n_cols, n_rows, type > t_() const
Definition: core.hpp:7242
T operator[](size_t index) const
Get the read only element by array row major index.
Definition: core.hpp:7148
MatView(const Mat< T, n_rows, n_cols, type > &m)
Construct a new MatView object from raw data pointer.
Definition: core.hpp:7054
Tp abssum() const
Definition: core.hpp:7255
Tp power() const
Definition: core.hpp:7245
MatView & col(const M< T2, rows_, cols_, type2, _unused... > &mat, size_t c)
Take a column of a matrix by index.
Definition: core.hpp:7170
MatView(const MatView &m)
Copy constructor.
Definition: core.hpp:7064
void col(size_t c, const M< T2, rows_, cols_, type2, _unused... > &mat)
Definition: core.hpp:7183
Mat< T, n_rows, n_cols, type > asMat() const
Explicitly make a Mat copy.
Definition: core.hpp:7280
MatView & add(const M< T2, n_rows, n_cols, type2, _unused... > &mat_R)
Definition: core.hpp:7220
Read only view version of a off diagonal.
Definition: core.hpp:8283
T operator()(size_t r, size_t c) const
Get the read only data element from row and column index.
Definition: core.hpp:8330
static constexpr size_t size() noexcept
The data element number.
Definition: core.hpp:8306
MatViewOffDiag(const MatViewOffDiag &m)
Copy constructor.
Definition: core.hpp:8299
const T * _data
Raw data pointer.
Definition: core.hpp:8410
T operator[](size_t index) const
Get the read only element by array row major index.
Definition: core.hpp:8373
Mat< T, N, N, MatType::NORMAL > asMat() const
Explicitly make a Mat copy.
Definition: core.hpp:8399
static constexpr MatType pType() noexcept
Parent matrix as MatType.
Definition: core.hpp:8321
MatViewOffDiag(const Mat< T, N, N, matType< type_parent >()> &m)
Construct a new MatViewOffDiag object from raw data pointer.
Definition: core.hpp:8290
Read only view version of the opposite of a matrix.
Definition: core.hpp:7617
MatViewOpp(const Mat< T, n_cols, n_rows, type > &m)
Construct a new MatViewOpp object from raw data pointer.
Definition: core.hpp:7624
T operator()(size_t r, size_t c) const
Get the read only data element from row and column index.
Definition: core.hpp:7655
const T * _data
Definition: core.hpp:7725
MatViewOpp(const MatViewOpp &m)
Copy constructor.
Definition: core.hpp:7631
static constexpr size_t size() noexcept
The data element number.
Definition: core.hpp:7638
Mat< T, n_rows, n_cols, type > asMat() const
Explicitly make a Mat copy.
Definition: core.hpp:7719
T operator[](size_t index) const
Get the read only element by array row major index.
Definition: core.hpp:7698
Read only view version of a certain row as row vector.
Definition: core.hpp:8522
Vec< T, n_rows > asRowVec() const
Explicitly make a Mat (RowVec) copy.
Definition: core.hpp:8614
T operator()(size_t r, size_t c) const
Get the read only data element from row and column index.
Definition: core.hpp:8564
T operator[](size_t index) const
Get the read only element by array row major index.
Definition: core.hpp:8583
MatViewRow(const Mat< T, n_rows, n_cols, matType< type_parent >()> &m, size_t index)
Construct a new MatViewRow object from raw data pointer.
Definition: core.hpp:8529
static constexpr MatType pType() noexcept
Parent matrix as MatType.
Definition: core.hpp:8555
RowVec< T, n_cols > asMat() const
Explicitly make a Mat copy.
Definition: core.hpp:8604
const T *const _data
Raw data pointer.
Definition: core.hpp:8627
static constexpr size_t size() noexcept
The data element number.
Definition: core.hpp:8548
MatViewRow(const MatViewRow &m)
Copy constructor.
Definition: core.hpp:8541
void print(const std::string &str="", std::ostream &os=std::cout) const
Definition: core.hpp:8619
Read only view version of successive rows.
Definition: core.hpp:9049
static constexpr size_t size() noexcept
The data element number.
Definition: core.hpp:9075
Mat< T, last_row - first_row+1, n_cols, MatType::NORMAL > asMat() const
Explicitly make a Mat copy.
Definition: core.hpp:9167
static constexpr MatType pType() noexcept
Parent matrix as MatType.last_col.
Definition: core.hpp:9090
const T * _data
Raw data pointer.
Definition: core.hpp:9188
T operator[](size_t index) const
Get the read only element by array row major index.
Definition: core.hpp:9146
Mat< T, last_row - first_row+1, n_cols, MatType::NORMAL > asVec() const
Explicitly make a Mat (Vec) copy.
Definition: core.hpp:9177
MatViewRows(const Mat< T, n_cols, n_rows, matType< type_parent >()> &m)
Construct a new MatViewRows object from raw data pointer.
Definition: core.hpp:9056
T operator()(size_t r, size_t c) const
Get the read only data element from row and column index.
Definition: core.hpp:9099
MatViewRows(const MatViewRows &m)
Copy constructor.
Definition: core.hpp:9068
Read only view version of a transposed matrix.
Definition: core.hpp:7729
MatViewT(const Mat< T, n_cols, n_rows, tType(type)> &m)
Construct a new MatViewT object from raw data pointer.
Definition: core.hpp:7736
T operator()(size_t r, size_t c) const
Get the read only data element from row and column index.
Definition: core.hpp:7772
static constexpr size_t size() noexcept
The data element number.
Definition: core.hpp:7755
MatViewT(T *ptr)
Definition: core.hpp:7748
T *const _data
Raw data pointer.
Definition: core.hpp:7874
MatViewT(Mat< T, n_cols, n_rows, tType(type)> &m)
Definition: core.hpp:7737
T operator[](size_t index) const
Get the read only element by array row major index.
Definition: core.hpp:7815
Mat< T, n_rows, n_cols, type > asMat() const
Explicitly make a Mat copy.
Definition: core.hpp:7862
MatViewT(const MatViewT &m)
Copy constructor.
Definition: core.hpp:7744
Definition: tensor.hpp:27
#define FLAMES_MAT_EMUL_UNROLL_FACTOR
Definition: core.hpp:110
#define FLAMES_MAT_POWER_UNROLL_FACTOR
Definition: core.hpp:78
#define FLAMES_MAT_MINUS_UNROLL_FACTOR
Definition: core.hpp:64
#define FLAMES_MAT_SCALAR_TIMES_UNROLL_FACTOR
Definition: core.hpp:95
#define FLAMES_PRAGMA(x)
Definition: core.hpp:50
#define FLAMES_MAT_PARTITION_FACTOR
Definition: core.hpp:143
#define FLAMES_MAT_INV_UNROLL_FACTOR
Definition: core.hpp:138
#define FLAMES_MAT_ABS_UNROLL_FACTOR
Definition: core.hpp:124
#define FLAMES_MAT_TIMES_UNROLL_FACTOR
Definition: core.hpp:103
#define FLAMES_MAT_SET_VALUE_UNROLL_FACTOR
Definition: core.hpp:71
#define FLAMES_MAT_PLUS_UNROLL_FACTOR
Definition: core.hpp:57
#define FLAMES_MAT_COPY_UNROLL_FACTOR
Definition: core.hpp:85
#define FLAMES_MAT_TRANSPOSE_UNROLL_FACTOR
Definition: core.hpp:131
#define FLAMES_MAT_BOOL_OPER_UNROLL_FACTOR
Definition: core.hpp:117
Mat< dtype, 4, 4 > M
Definition: mat-inv-nsa-expanded.cpp:4
Namespace for the FLAMES library.
Definition: core.hpp:166
InitAfterwards
Afterwards action with initialization.
Definition: core.hpp:556
std::integral_constant< int, MatType::UPPER > MATTYPE_UPPER
Upper triangular matrix as a class type.
Definition: core.hpp:191
constexpr MatType mulType(MatType type1, MatType type2, size_t n_rows, size_t comm, size_t n_cols) noexcept
Multiplication type of two matrices.
Definition: core.hpp:276
std::integral_constant< int, MatType::SLOWER > MATTYPE_SLOWER
Strict lower triangular matrix as a class type.
Definition: core.hpp:197
static Mat< T, n_rows, n_cols, type > operator*(const M< T, n_rows, n_cols, type, _unused... > &mat_L, ScalarT s)
Matrix times a scalar.
Definition: core.hpp:9394
constexpr size_t lowerRow(size_t index, size_t N)
Calculate the row index of a lower triangular matrix.
Definition: core.hpp:334
static Mat< T1, n_rows, n_cols, type1 > & operator+=(Mat< T1, n_rows, n_cols, type1 > &mat_L, const M< T2, n_rows, n_cols, type2, _unused... > &mat_R)
Matrix self plus a matrix.
Definition: core.hpp:9237
constexpr MatType sumType(MatType type1, MatType type2) noexcept
Summation type of two matrices.
Definition: core.hpp:229
std::integral_constant< int, MatType::SYM > MATTYPE_SYM
Symmetrical matrix as a class type.
Definition: core.hpp:199
std::integral_constant< int, MatType::ASYM > MATTYPE_ASYM
Antisymmetrical matrix as a class type.
Definition: core.hpp:201
constexpr size_t upperRow(size_t index, size_t N)
Calculate the row index of a upper triangular matrix.
Definition: core.hpp:318
std::integral_constant< int, MatType::LOWER > MATTYPE_LOWER
Lower triangular matrix as a class type.
Definition: core.hpp:193
Mat< bool, n_rows, n_cols, type > operator<=(const M1< T1, n_rows, n_cols, type, _unused1... > &mat_L, const M2< T2, n_rows, n_cols, type, _unused2... > &mat_R)
Element-wise less or equal comparison.
Definition: core.hpp:9740
constexpr size_t supperRow(size_t index, size_t N)
Calculate the row index of a strict upper triangular matrix.
Definition: core.hpp:350
Mat< bool, n_rows, n_cols, type > operator>=(const M1< T1, n_rows, n_cols, type, _unused1... > &mat_L, const M2< T2, n_rows, n_cols, type, _unused2... > &mat_R)
Element-wise greater or equal comparison.
Definition: core.hpp:9708
Mat< T1, n_rows, n_cols, type > mod(const M1< T1, n_rows, n_cols, type, _unused1... > &mat_L, const M2< T2, n_rows, n_cols, type, _unused2... > &mat_R)
Element-wise modulus.
Definition: core.hpp:9772
std::integral_constant< int, MatType::SUPPER > MATTYPE_SUPPER
Strict upper triangular matrix as a class type.
Definition: core.hpp:195
Init
Definition: core.hpp:562
std::integral_constant< int, type > MType
Get the class form of MatType.
Definition: core.hpp:220
std::integral_constant< int, MatType::SCALAR > MATTYPE_SCALAR
Scalar matrix matrix as a class type.
Definition: core.hpp:189
Mat< bool, n_rows, n_cols, type > operator==(const M1< T1, n_rows, n_cols, type, _unused1... > &mat_L, const M2< T2, n_rows, n_cols, type, _unused2... > &mat_R)
Element-wise equal comparison.
Definition: core.hpp:9580
static Mat< T1, n_rows, n_cols, sumType(type1, type2)> operator-(const M1< T1, n_rows, n_cols, type1, _unused1... > &mat_L, const M2< T2, n_rows, n_cols, type2, _unused2... > &mat_R)
Minus two matrices and make a copy.
Definition: core.hpp:9265
static Mat< T1, n_rows, n_cols, mulType(type1, type2, n_rows, n_cols, n_cols)> operator*=(Mat< T1, n_rows, n_cols, type1 > &mat, const M< T2, n_cols, n_cols, type2, _unused... > &mat_R)
Matrix self times a matrix.
Definition: core.hpp:9318
constexpr size_t slowerRow(size_t index, size_t N)
Calculate the row index of a strict lower triangular matrix.
Definition: core.hpp:366
Mat< T1, n_rows, n_cols, type > operator%(const M1< T1, n_rows, n_cols, type, _unused1... > &mat_L, const M2< T2, n_rows, n_cols, type, _unused2... > &mat_R)
Element-wise product of two matrices.
Definition: core.hpp:9553
constexpr MatType tType(MatType type) noexcept
Transpose type of a matrix.
Definition: core.hpp:303
Mat< bool, n_rows, n_cols, type > operator>(const M1< T1, n_rows, n_cols, type, _unused1... > &mat_L, const M2< T2, n_rows, n_cols, type, _unused2... > &mat_R)
Element-wise greater comparison.
Definition: core.hpp:9644
static std::ostream & operator<<(std::ostream &os, const Mat< T, n_rows, n_cols, type > &mat)
Print matrix in a out stream.
Definition: core.hpp:9812
static M1< T1, n_rows, n_cols, type1 > & operator-=(M1< T1, n_rows, n_cols, type1, _unused1... > &mat_L, const M2< T2, n_rows, n_cols, type2, _unused2... > &mat_R)
Matrix self minus a matrix.
Definition: core.hpp:9290
Mat< bool, n_rows, n_cols, type > operator!=(const M1< T1, n_rows, n_cols, type, _unused1... > &mat_L, const M2< T2, n_rows, n_cols, type, _unused2... > &mat_R)
Element-wise unequal comparison.
Definition: core.hpp:9612
Mat< bool, n_rows, n_cols, type > operator<(const M1< T1, n_rows, n_cols, type, _unused1... > &mat_L, const M2< T2, n_rows, n_cols, type, _unused2... > &mat_R)
Element-wise less comparison.
Definition: core.hpp:9676
std::integral_constant< int, MatType::NORMAL > MATTYPE_NORMAL
Normal matrix as a class type.
Definition: core.hpp:185
std::integral_constant< int, MatType::DIAGONAL > MATTYPE_DIAGONAL
Diagonal matrix as a class type.
Definition: core.hpp:187
Tp innerProd(const M1< T1, L_rows, L_cols, type, _unused1... > &mat_L, const M2< T2, R_rows, R_cols, type, _unused2... > &mat_R)
Definition: core.hpp:9787
MatType
Matrix type for storage.
Definition: core.hpp:172
@ SCALAR
Definition: core.hpp:175
@ SLOWER
Definition: core.hpp:179
@ DIAGONAL
Definition: core.hpp:174
@ NORMAL
Definition: core.hpp:173
@ UPPER
Definition: core.hpp:176
@ ASYM
Definition: core.hpp:181
@ LOWER
Definition: core.hpp:177
@ SUPPER
Definition: core.hpp:178
@ SYM
Definition: core.hpp:180
static Mat< T1, n_rows, n_cols, sumType(type1, type2)> operator+(const M1< T1, n_rows, n_cols, type1, _unused1... > &mat_L, const M2< T2, n_rows, n_cols, type2, _unused2... > &mat_R)
Add two matrices and make a copy.
Definition: core.hpp:9213
constexpr MatType matType()
Get the MatType value from the class form.
Definition: core.hpp:210