FLAMES 0.1.0
Matrix-Empowered HLS Library
Loading...
Searching...
No Matches
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
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
401template <typename T, size_t n_rows, size_t n_cols, size_t n_slices, MatType type = MatType::NORMAL>
402class Tensor;
403
411template <typename T, size_t N>
413
421template <typename T, size_t N>
423
432template <typename T, size_t n_rows, size_t n_cols, MatType type = MatType::NORMAL>
433class MatView;
434
435template <typename T, size_t n_rows, size_t n_cols, MatType type = MatType::NORMAL>
436class MatRef;
437
446template <typename T, size_t n_rows, size_t n_cols, MatType type>
447class MatViewOpp;
448
457template <typename T, size_t n_rows, size_t n_cols, MatType type>
458class MatViewT;
459
469template <typename T, size_t N, size_t N_, MatType type, typename type_parent = MATTYPE_NORMAL>
470class MatViewDiagMat;
471
481template <typename T, size_t N, size_t N_, MatType type, typename type_parent = MATTYPE_NORMAL>
482class MatViewDiagVec;
483
493template <typename T, size_t N, size_t N_, MatType type, typename type_parent = MATTYPE_NORMAL>
495
505template <typename T, size_t N, size_t N_, MatType type, typename type_parent = MATTYPE_NORMAL>
506class MatViewOffDiag;
507
517template <typename T, size_t n_rows, size_t n_cols, MatType type, typename type_parent = MATTYPE_NORMAL>
518class MatViewCol;
519
520template <typename T, size_t n_rows, size_t n_cols, MatType type, typename type_parent = MATTYPE_NORMAL>
521class MatRefCol;
522
532template <typename T, size_t n_rows, size_t n_cols, MatType type, typename type_parent = MATTYPE_NORMAL>
533class MatViewRow;
534
544template <size_t first_col, size_t last_col, typename T, size_t n_rows, size_t n_cols, MatType type,
545 typename type_parent = MATTYPE_NORMAL>
546class MatViewCols;
547
557template <size_t first_row, size_t last_row, typename T, size_t n_rows, size_t n_cols, MatType type,
558 typename type_parent = MATTYPE_NORMAL>
559class MatViewRows;
560
566enum class InitAfterwards {
567 NONE,
568 OPP,
569 TR
570};
571
572enum class Init { NONE, ZEROS, ONES };
573
574template <typename T, size_t n_rows, size_t n_cols, MatType type>
575class Mat {
576 friend class MatView<T, n_rows, n_cols, type>;
577 friend class MatViewOpp<T, n_rows, n_cols, type>;
578 friend class MatViewT<T, n_cols, n_rows, type>;
579 friend class MatViewT<T, n_rows, n_cols, type>;
580 template <typename View_T, size_t View_N, size_t View_N_, MatType View_type, typename type_parent>
581 friend class MatViewDiagMat;
582 template <typename View_T, size_t View_N, size_t View_N_, MatType View_type, typename type_parent>
583 friend class MatViewDiagVec;
584 template <typename View_T, size_t View_N, size_t View_N_, MatType View_type, typename type_parent>
585 friend class MatViewDiagRowVec;
586 template <typename View_T, size_t View_N, size_t View_N_, MatType View_type, typename type_parent>
587 friend class MatViewOffDiag;
588 template <typename View_T, size_t View_n_rows, size_t View_n_cols, MatType View_type, typename type_parent>
589 friend class MatViewCol;
590 template <typename View_T, size_t View_n_rows, size_t View_n_cols, MatType View_type, typename type_parent>
591 friend class MatViewRow;
592 template <size_t first_col, size_t last_col, typename View_T, size_t View_n_rows, size_t View_n_cols,
593 MatType View_type, typename type_parent>
594 friend class MatViewCols;
595 template <size_t first_row, size_t last_row, typename View_T, size_t View_n_rows, size_t View_n_cols,
596 MatType View_type, typename type_parent>
597 friend class MatViewRows;
598 template <typename View_T_T, size_t T_n_rows, size_t T_n_cols, size_t T_n_slices, MatType T_type>
599 friend class Tensor;
600
601 public:
602 using element_type = T;
603 using value_type = T;
604
614 Mat() {
615 static_assert(n_rows != 0, "'rows' should be no smaller than 1.");
616 static_assert(n_cols != 0, "'n_cols' should be no smaller than 1.");
617 static_assert(type == MatType::NORMAL || n_rows == n_cols, "Square matrix 'rows' should be equal to 'n_cols'.");
618#ifdef FLAMES_MAT_PARTITION_COMPLETE
619 FLAMES_PRAGMA(ARRAY_PARTITION variable = _data type = complete)
620#else
621 FLAMES_PRAGMA(ARRAY_PARTITION variable = _data type = block factor = FLAMES_MAT_PARTITION_FACTOR)
622#endif
623 }
624
633 Mat(T val) {
634 static_assert(n_rows != 0, "'n_rows' should be no smaller than 1.");
635 static_assert(n_cols != 0, "'n_cols' should be no smaller than 1.");
636 static_assert(type == MatType::NORMAL || n_rows == n_cols, "Square matrix 'rows' should be equal to 'n_cols'.");
637#ifdef FLAMES_MAT_PARTITION_COMPLETE
638 FLAMES_PRAGMA(ARRAY_PARTITION variable = _data type = complete)
639#else
640 FLAMES_PRAGMA(ARRAY_PARTITION variable = _data type = block factor = FLAMES_MAT_PARTITION_FACTOR)
641#endif
642 setValue(val);
643 }
644
654 Mat(const Mat& mat) {
655 MAT_COPY:
656 for (size_t i = 0; i != size(); ++i) {
658 _data[i] = mat[i];
659 }
660#ifdef FLAMES_MAT_PARTITION_COMPLETE
661 FLAMES_PRAGMA(ARRAY_PARTITION variable = _data type = complete)
662#else
663 FLAMES_PRAGMA(ARRAY_PARTITION variable = _data type = block factor = FLAMES_MAT_PARTITION_FACTOR)
664#endif
665#ifdef FLAMES_PRINT_PER_MAT_COPY
666 std::cout << "Mat copy!" << std::endl;
667#endif
668 }
669
670 template <typename T2, size_t _rows, size_t _cols, MatType _type,
671 std::enable_if_t<!std::is_same<T, T2>::value && type == _type && n_rows == _rows && n_cols == _cols,
672 bool> = true>
674 MAT_COPY:
675 for (size_t i = 0; i != size(); ++i) {
677 _data[i] = mat[i];
678 }
679#ifdef FLAMES_MAT_PARTITION_COMPLETE
680 FLAMES_PRAGMA(ARRAY_PARTITION variable = _data type = complete)
681#else
682 FLAMES_PRAGMA(ARRAY_PARTITION variable = _data type = block factor = FLAMES_MAT_PARTITION_FACTOR)
683#endif
684#ifdef FLAMES_PRINT_PER_MAT_COPY
685 std::cout << "Mat copy!" << std::endl;
686#endif
687 }
688
689 template <typename T2, size_t _rows, size_t _cols, MatType _type,
690 std::enable_if_t<type != _type && n_rows == _rows && n_cols == _cols, bool> = true>
692 MAT_COPY:
693 for (size_t r = 0; r != n_rows; ++r) {
695 for (size_t c = 0; c != n_cols; ++c) {
696 FLAMES_PRAGMA(LOOP_FLATTEN)
697 _tryAssign(r, c, mat(r, c));
698 }
699 }
700#ifdef FLAMES_MAT_PARTITION_COMPLETE
701 FLAMES_PRAGMA(ARRAY_PARTITION variable = _data type = complete)
702#else
703 FLAMES_PRAGMA(ARRAY_PARTITION variable = _data type = block factor = FLAMES_MAT_PARTITION_FACTOR)
704#endif
705#ifdef FLAMES_PRINT_PER_MAT_COPY
706 std::cout << "Mat copy!" << std::endl;
707#endif
708 }
709
718 Mat(const std::vector<T>& vec) {
719 assert(vec.size() == size() && "Initialization vector size disagrees.");
720 MAT_COPY_FROM_STD_VEC:
721 for (size_t i = 0; i != size(); ++i) {
723 _data[i] = vec[i];
724 }
725#ifdef FLAMES_MAT_PARTITION_COMPLETE
726 FLAMES_PRAGMA(ARRAY_PARTITION variable = _data type = complete)
727#else
728 FLAMES_PRAGMA(ARRAY_PARTITION variable = _data type = block factor = FLAMES_MAT_PARTITION_FACTOR)
729#endif
730#ifdef FLAMES_PRINT_PER_MAT_COPY
731 std::cout << "Mat copy!" << std::endl;
732#endif
733 }
734
735 template <typename T2>
736 Mat(std::initializer_list<T2> list) {
737 auto list_size = list.size();
738 assert(list_size <= size() && "Initializer list size should not exceed size().");
739 MAT_COPY_FROM_INIT_LIST:
740 for (size_t i = 0; i != list_size; ++i) {
742 _data[i] = *(list.begin() + i);
743 }
744#ifdef FLAMES_MAT_PARTITION_COMPLETE
745 FLAMES_PRAGMA(ARRAY_PARTITION variable = _data type = complete)
746#else
747 FLAMES_PRAGMA(ARRAY_PARTITION variable = _data type = block factor = FLAMES_MAT_PARTITION_FACTOR)
748#endif
749#ifdef FLAMES_PRINT_PER_MAT_COPY
750 std::cout << "Mat copy!" << std::endl;
751#endif
752 }
753
754 Mat(Init init) {}
755
756 // public: // original private
757 public:
765 explicit Mat(const T* ptr, InitAfterwards opt = InitAfterwards::NONE) {
766 if (opt == InitAfterwards::NONE) {
767 MAT_COPY:
768 for (size_t i = 0; i != size(); ++i) {
770 _data[i] = ptr[i];
771 }
772 } else if (opt == InitAfterwards::OPP) {
773 MAT_COPY_OPP:
774 for (size_t i = 0; i != size(); ++i) {
776 _data[i] = -ptr[i];
777 }
778 } else if (opt == InitAfterwards::TR) {
780 this->t(tmp);
781 }
782#ifdef FLAMES_MAT_PARTITION_COMPLETE
783 FLAMES_PRAGMA(ARRAY_PARTITION variable = _data type = complete)
784#else
785 FLAMES_PRAGMA(ARRAY_PARTITION variable = _data type = block factor = FLAMES_MAT_PARTITION_FACTOR)
786#endif
787#ifdef FLAMES_PRINT_PER_MAT_COPY
788 std::cout << "Mat copy!" << std::endl;
789#endif
790 }
791
792 explicit Mat(T* const ptr, InitAfterwards opt = InitAfterwards::NONE) {
793 if (opt == InitAfterwards::NONE) {
794 MAT_COPY:
795 for (size_t i = 0; i != size(); ++i) {
797 _data[i] = ptr[i];
798 }
799 } else if (opt == InitAfterwards::OPP) {
800 MAT_COPY_OPP:
801 for (size_t i = 0; i != size(); ++i) {
803 _data[i] = -ptr[i];
804 }
805 } else if (opt == InitAfterwards::TR) {
807 this->t(tmp);
808 }
809#ifdef FLAMES_MAT_PARTITION_COMPLETE
810 FLAMES_PRAGMA(ARRAY_PARTITION variable = _data type = complete)
811#else
812 FLAMES_PRAGMA(ARRAY_PARTITION variable = _data type = block factor = FLAMES_MAT_PARTITION_FACTOR)
813#endif
814#ifdef FLAMES_PRINT_PER_MAT_COPY
815 std::cout << "Mat copy!" << std::endl;
816#endif
817 }
818
819 public:
826 // so far nothing to do
827 }
828
829 // template <typename... _unused, MatType _type = type,
830 // typename std::enable_if_t<_type == MatType::NORMAL, bool> = true>
831 // inline constexpr size_t size_const() noexcept {
832 // static_assert(sizeof...(_unused) == 0, "Do not specify template arguments for Mat::size()!");
833 // return n_rows * n_cols;
834 // }
835
842 inline static constexpr size_t size() noexcept {
843 return type == MatType::NORMAL ? n_rows * n_cols
844 : type == MatType::DIAGONAL ? n_rows
845 : type == MatType::SCALAR ? 1
846 : type == MatType::SUPPER ? (n_rows - 1) * n_rows / 2
847 : type == MatType::SLOWER ? (n_rows - 1) * n_rows / 2
848 : type == MatType::ASYM ? (n_rows - 1) * n_rows / 2
849 : (1 + n_rows) * n_rows / 2;
850 }
851
860 T operator[](size_t index) const {
861 FLAMES_PRAGMA(INLINE)
862 assert(index < size() && "Matrix index should be within range");
863 return _data[index];
864 }
865
874 T& operator[](size_t index) {
875 FLAMES_PRAGMA(INLINE)
876 assert(index < size() && "Matrix index should be within range");
877 return _data[index];
878 }
879
887 T operator()(size_t r, size_t c) const {
888 FLAMES_PRAGMA(INLINE)
889 assert(r < n_rows && "Matrix row index should be within range");
890 assert(c < n_cols && "Matrix col index should be within range");
891 if (type == MatType::NORMAL) {
892 return _data[r * n_cols + c];
893 } else if (type == MatType::DIAGONAL) {
894 if (r == c) return _data[r];
895 else return T(0);
896 } else if (type == MatType::SCALAR) {
897 if (r == c) return _data[0];
898 else return T(0);
899 } else if (type == MatType::UPPER) {
900 if (r <= c) return _data[(2 * n_cols + 1 - r) * r / 2 + c - r];
901 else return T(0);
902 } else if (type == MatType::LOWER) {
903 if (r >= c) return _data[(1 + r) * r / 2 + c];
904 else return T(0);
905 } else if (type == MatType::SUPPER) {
906 if (r < c) return _data[(2 * n_cols + 1 - r) * r / 2 + c - 1 - 2 * r];
907 else return T(0);
908 } else if (type == MatType::SLOWER) {
909 if (r > c) return _data[(1 + r) * r / 2 + c - r];
910 else return T(0);
911 } else if (type == MatType::SYM) {
912 if (r <= c) return _data[(2 * n_cols + 1 - r) * r / 2 + c - r];
913 else return _data[(2 * n_cols + 1 - c) * c / 2 + r - c];
914 } else if (type == MatType::ASYM) {
915 if (r < c) return _data[(2 * n_cols + 1 - r) * r / 2 + c - 1 - 2 * r];
916 else if (r > c) return -_data[(2 * n_cols + 1 - c) * c / 2 + r - 1 - 2 * c];
917 else return T(0);
918 } else {
919 // Normally it is impossible to reach here.
920 assert(!"Impossible! Unknown MatType!");
921 }
922 }
923
931 T& operator()(size_t r, size_t c) {
932 FLAMES_PRAGMA(INLINE)
933 assert(r < n_rows && "Matrix row index should be within range");
934 assert(c < n_cols && "Matrix col index should be within range");
935 if (type == MatType::NORMAL) {
936 return _data[r * n_cols + c];
937 } else if (type == MatType::DIAGONAL) {
938 if (r == c) return _data[r];
939 else assert(!"This element cannot be modified (DIAGONAL).");
940 } else if (type == MatType::SCALAR) {
941 assert(!"This element cannot be modified (SCALAR).");
942 } else if (type == MatType::UPPER) {
943 if (r <= c) return _data[(2 * n_cols + 1 - r) * r / 2 + c - r];
944 else assert(!"This element cannot be modified (UPPER).");
945 } else if (type == MatType::LOWER) {
946 if (r >= c) return _data[(1 + r) * r / 2 + c];
947 else assert(!"This element cannot be modified (LOWER).");
948 } else if (type == MatType::SUPPER) {
949 if (r < c) return _data[(2 * n_cols + 1 - r) * r / 2 + c - 1 - 2 * r];
950 else assert(!"This element cannot be modified (SUPPER).");
951 } else if (type == MatType::SLOWER) {
952 if (r > c) return _data[(1 + r) * r / 2 + c - r];
953 else assert(!"This element cannot be modified (SLOWER).");
954 } else if (type == MatType::SYM) {
955 if (r <= c) return _data[(2 * n_cols + 1 - r) * r / 2 + c - r];
956 else return _data[(2 * n_cols + 1 - c) * c / 2 + r - c];
957 } else if (type == MatType::ASYM) {
958 if (r < c) return _data[(2 * n_cols + 1 - r) * r / 2 + c - 1 - 2 * r];
959 else if (r > c) return _data[(2 * n_cols + 1 - c) * c / 2 + r - 1 - 2 * c];
960
961 // ATTENTION This part needs to be perfected , missing a minus sign.
962 // Because a minus sign will result in a error about reference.
963
964 else assert(!"This element cannot be modified (ASYM).");
965 } else {
966 // Normally it is impossible to reach here.
967 assert(!"Impossible! Unknown MatType!");
968 }
969 // Just to make the compiler happy.
970 return _data[0];
971 }
972
978 void setValue(T val) {
979 for (size_t i = 0; i != size(); ++i) {
981 _data[i] = val;
982 }
983 }
984
989 void setZero() { setValue(static_cast<T>(0)); }
990
991 bool read(const std::string& file_name) {
992#ifndef __SYNTHESIS__
993 std::ifstream f(file_name);
994 if (f.is_open()) {
995 size_t in_rows, in_cols;
996 f >> in_rows >> in_cols;
997 if (n_rows != in_rows || n_cols != in_cols) return false; // dimension does not match
998 std::string complex_real, mat_type;
999 f >> complex_real >> mat_type;
1000 if (type == MatType::NORMAL && mat_type != "normal") return false;
1001 if (type == MatType::DIAGONAL && mat_type != "diagonal") return false;
1002 if (type == MatType::SCALAR && mat_type != "scalar") return false;
1003 if (type == MatType::UPPER && mat_type != "upper") return false;
1004 if (type == MatType::LOWER && mat_type != "lower") return false;
1005 if (type == MatType::SUPPER && mat_type != "supper") return false;
1006 if (type == MatType::SYM && mat_type != "sym") return false;
1007 if (type == MatType::ASYM && mat_type != "asym") return false;
1008 if (complex_real == "complex") {
1009 // std::string real_part, imag_part;
1010 // for (size_t i = 0; i != size(); ++i) {
1011 // std::getline(f, real_part, ',');
1012 // std::getline(f, imag_part, ',');
1013 // _data[i].real(std::stod(real_part));
1014 // _data[i].imag(std::stod(imag_part));
1015 // }
1016 assert(!"Read from a complex matrix is not currently supported.");
1017 return false;
1018 } else {
1019 std::string buf;
1020 for (size_t i = 0; i != size(); ++i) {
1021 std::getline(f, buf, ',');
1022 _data[i] = std::stod(buf);
1023 }
1024 return true;
1025 }
1026 } else {
1027 return false;
1028 }
1029#else
1030 return true;
1031#endif
1032 }
1033
1050 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
1051 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
1052 typename T2>
1053 Mat& add(const M1<T1, n_rows, n_cols, type, _unused1...>& mat_L,
1054 const M2<T2, n_rows, n_cols, type, _unused2...>& mat_R) {
1055 MAT_PLUS_MAT_SAME:
1056 for (size_t i = 0; i != size(); ++i) {
1058 this->_data[i] = mat_L[i] + mat_R[i];
1059 }
1060 return *this;
1061 }
1062
1081 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
1082 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
1083 typename T2, MatType type1, MatType type2,
1084 std::enable_if_t<type == MatType::NORMAL && (type1 != MatType::NORMAL || type2 != MatType::NORMAL),
1085 bool> = true>
1086 Mat& add(const M1<T1, n_rows, n_cols, type1, _unused1...>& mat_L,
1087 const M2<T2, n_rows, n_cols, type2, _unused2...>& mat_R) {
1088 MAT_PLUS_MAT_NORMAL:
1089 for (size_t i = 0; i != n_rows; ++i) {
1091 for (size_t j = 0; j != n_cols; ++j) {
1092 FLAMES_PRAGMA(LOOP_FLATTEN)
1093 this->_data[i * n_cols + j] = mat_L(i, j) + mat_R(i, j);
1094 }
1095 }
1096 return *this;
1097 }
1098
1117 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
1118 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
1119 typename T2, MatType type1, MatType type2,
1120 std::enable_if_t<type == MatType::DIAGONAL && (type1 != MatType::DIAGONAL || type2 != MatType::DIAGONAL),
1121 bool> = true>
1122 Mat& add(const M1<T1, n_rows, n_cols, type1, _unused1...>& mat_L,
1123 const M2<T2, n_rows, n_cols, type2, _unused2...>& mat_R) {
1124 MAT_PLUS_MAT_LOWER:
1125 for (size_t i = 0; i != n_rows; ++i) {
1127 this->_data[i] = mat_L(i, i) + mat_R(i, i);
1128 }
1129 return *this;
1130 }
1131
1148 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
1149 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
1150 typename T2, MatType type1, MatType type2,
1151 std::enable_if_t<type == MatType::SCALAR && (type1 != MatType::SCALAR || type2 != MatType::SCALAR),
1152 bool> = true>
1153 Mat& add(const M1<T1, n_rows, n_cols, type1, _unused1...>& mat_L,
1154 const M2<T2, n_rows, n_cols, type2, _unused2...>& mat_R) {
1155 MAT_PLUS_MAT_SCALAR:
1156 this->_data[0] = mat_L(0, 0) + mat_R(0, 0);
1157 return *this;
1158 }
1159
1178 template <
1179 template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
1180 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1, typename T2,
1181 MatType type1, MatType type2,
1182 std::enable_if_t<type == MatType::UPPER && (type1 != MatType::UPPER || type2 != MatType::UPPER), bool> = true>
1183 Mat& add(const M1<T1, n_rows, n_cols, type1, _unused1...>& mat_L,
1184 const M2<T2, n_rows, n_cols, type2, _unused2...>& mat_R) {
1185 MAT_PLUS_MAT_UPPER:
1186 for (size_t i = 0; i != n_rows; ++i) {
1188 for (size_t j = i; j != n_cols; ++j) {
1189 FLAMES_PRAGMA(LOOP_FLATTEN)
1190 this->_data[(2 * n_cols + 1 - i) * i / 2 + j - i] = mat_L(i, j) + mat_R(i, j);
1191 }
1192 }
1193 return *this;
1194 }
1195
1214 template <
1215 template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
1216 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1, typename T2,
1217 MatType type1, MatType type2,
1218 std::enable_if_t<type == MatType::LOWER && (type1 != MatType::LOWER || type2 != MatType::LOWER), bool> = true>
1219 Mat& add(const M1<T1, n_rows, n_cols, type1, _unused1...>& mat_L,
1220 const M2<T2, n_rows, n_cols, type2, _unused2...>& mat_R) {
1221 MAT_PLUS_MAT_LOWER:
1222 for (size_t i = 0; i != n_rows; ++i) {
1224 for (size_t j = i; j != n_cols; ++j) {
1225 FLAMES_PRAGMA(LOOP_FLATTEN)
1226 this->_data[(1 + i) * i / 2 + j] = mat_L(i, j) + mat_R(i, j);
1227 }
1228 }
1229 return *this;
1230 }
1231
1250 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
1251 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
1252 typename T2, MatType type1, MatType type2,
1253 std::enable_if_t<type == MatType::SUPPER && (type1 != MatType::SUPPER || type2 != MatType::SUPPER),
1254 bool> = true>
1255 Mat& add(const M1<T1, n_rows, n_cols, type1, _unused1...>& mat_L,
1256 const M2<T2, n_rows, n_cols, type2, _unused2...>& mat_R) {
1257 MAT_PLUS_MAT_SUPPER:
1258 for (size_t i = 0; i != n_rows - 1; ++i) {
1260 for (size_t j = i + 1; j != n_cols; ++j) {
1261 FLAMES_PRAGMA(LOOP_FLATTEN)
1262 this->_data[(2 * n_cols + 1 - i) * i / 2 + j - 2 * i - 1] = mat_L(i, j) + mat_R(i, j);
1263 }
1264 }
1265 return *this;
1266 }
1267
1286 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
1287 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
1288 typename T2, MatType type1, MatType type2,
1289 std::enable_if_t<type == MatType::SLOWER && (type1 != MatType::SLOWER || type2 != MatType::SLOWER),
1290 bool> = true>
1291 Mat& add(const M1<T1, n_rows, n_cols, type1, _unused1...>& mat_L,
1292 const M2<T2, n_rows, n_cols, type2, _unused2...>& mat_R) {
1293 MAT_PLUS_MAT_SLOWER:
1294 for (size_t i = 1; i != n_rows; ++i) {
1296 for (size_t j = 0; j != n_cols - 1; ++j) {
1297 FLAMES_PRAGMA(LOOP_FLATTEN)
1298 this->_data[(1 + i) * i / 2 + j - i] = mat_L(i, j) + mat_R(i, j);
1299 }
1300 }
1301 return *this;
1302 }
1303
1322 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
1323 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
1324 typename T2, MatType type1, MatType type2,
1325 std::enable_if_t<type == MatType::SYM && (type1 != MatType::SYM || type2 != MatType::SYM), bool> = true>
1326 Mat& add(const M1<T1, n_rows, n_cols, type1, _unused1...>& mat_L,
1327 const M2<T2, n_rows, n_cols, type2, _unused2...>& mat_R) {
1328 MAT_PLUS_MAT_SYM:
1329 for (size_t i = 0; i != n_rows; ++i) {
1331 for (size_t j = i; j != n_cols; ++j) {
1332 FLAMES_PRAGMA(LOOP_FLATTEN)
1333 this->_data[(2 * n_cols + 1 - i) * i / 2 + j - i] = mat_L(i, j) + mat_R(i, j);
1334 }
1335 }
1336 return *this;
1337 }
1338
1357 template <
1358 template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
1359 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1, typename T2,
1360 MatType type1, MatType type2,
1361 std::enable_if_t<type == MatType::ASYM && (type1 != MatType::ASYM || type2 != MatType::ASYM), bool> = true>
1362 Mat& add(const M1<T1, n_rows, n_cols, type1, _unused1...>& mat_L,
1363 const M2<T2, n_rows, n_cols, type2, _unused2...>& mat_R) {
1364 MAT_PLUS_MAT_ASYM:
1365 for (size_t i = 0; i != n_rows; ++i) {
1367 for (size_t j = i + 1; j != n_cols; ++j) {
1368 FLAMES_PRAGMA(LOOP_FLATTEN)
1369 this->_data[(2 * n_cols + 1 - i) * i / 2 + j - i * 2 - 1] = mat_L(i, j) + mat_R(i, j);
1370 }
1371 }
1372 return *this;
1373 }
1374
1385 template <template <class, size_t, size_t, MatType, class...> typename M, typename... _unused, typename T2,
1386 MatType type2>
1388 FLAMES_PRAGMA(INLINE)
1389 return this->add(*this, mat_R);
1390 }
1391
1408 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
1409 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
1410 typename T2>
1411 Mat& sub(const M1<T1, n_rows, n_cols, type, _unused1...>& mat_L,
1412 const M2<T2, n_rows, n_cols, type, _unused2...>& mat_R) {
1413 MAT_MINUS_MAT_SAME:
1414 for (size_t i = 0; i != size(); ++i) {
1416 this->_data[i] = mat_L[i] - mat_R[i];
1417 }
1418 return *this;
1419 }
1420
1439 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
1440 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
1441 typename T2, MatType type1, MatType type2,
1442 std::enable_if_t<type == MatType::NORMAL && (type1 != MatType::NORMAL || type2 != MatType::NORMAL),
1443 bool> = true>
1444 Mat& sub(const M1<T1, n_rows, n_cols, type1, _unused1...>& mat_L,
1445 const M2<T2, n_rows, n_cols, type2, _unused2...>& mat_R) {
1446 MAT_MINUS_MAT_NORMAL:
1447 for (size_t i = 0; i != n_rows; ++i) {
1449 for (size_t j = 0; j != n_cols; ++j) {
1450 FLAMES_PRAGMA(LOOP_FLATTEN)
1451 this->_data[i * n_cols + j] = mat_L(i, j) - mat_R(i, j);
1452 }
1453 }
1454 return *this;
1455 }
1456
1475 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
1476 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
1477 typename T2, MatType type1, MatType type2,
1478 std::enable_if_t<type == MatType::DIAGONAL && (type1 != MatType::DIAGONAL || type2 != MatType::DIAGONAL),
1479 bool> = true>
1480 Mat& sub(const M1<T1, n_rows, n_cols, type1, _unused1...>& mat_L,
1481 const M2<T2, n_rows, n_cols, type2, _unused2...>& mat_R) {
1482 MAT_MINUS_MAT_DIAGONAL:
1483 for (size_t i = 0; i != n_rows; ++i) {
1485 this->_data[i] = mat_L(i, i) - mat_R(i, i);
1486 }
1487 return *this;
1488 }
1507 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
1508 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
1509 typename T2, MatType type1, MatType type2,
1510 std::enable_if_t<type == MatType::SCALAR && (type1 != MatType::SCALAR || type2 != MatType::SCALAR),
1511 bool> = true>
1512 Mat& sub(const M1<T1, n_rows, n_cols, type1, _unused1...>& mat_L,
1513 const M2<T2, n_rows, n_cols, type2, _unused2...>& mat_R) {
1514 MAT_MINUS_MAT_SCALAR:
1515 this->_data[0] = mat_L(0, 0) - mat_R(0, 0);
1516 return *this;
1517 }
1518
1537 template <
1538 template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
1539 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1, typename T2,
1540 MatType type1, MatType type2,
1541 std::enable_if_t<type == MatType::UPPER && (type1 != MatType::UPPER || type2 != MatType::UPPER), bool> = true>
1542 Mat& sub(const M1<T1, n_rows, n_cols, type1, _unused1...>& mat_L,
1543 const M2<T2, n_rows, n_cols, type2, _unused2...>& mat_R) {
1544 MAT_MINUS_MAT_UPPER:
1545 for (size_t i = 0; i != n_rows; ++i) {
1547 for (size_t j = i; j != n_cols; ++j) {
1548 FLAMES_PRAGMA(LOOP_FLATTEN)
1549 this->_data[(2 * n_cols + 1 - i) * i / 2 + j - i] = mat_L(i, j) - mat_R(i, j);
1550 }
1551 }
1552 return *this;
1553 }
1554
1573 template <
1574 template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
1575 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1, typename T2,
1576 MatType type1, MatType type2,
1577 std::enable_if_t<type == MatType::LOWER && (type1 != MatType::LOWER || type2 != MatType::LOWER), bool> = true>
1578 Mat& sub(const M1<T1, n_rows, n_cols, type1, _unused1...>& mat_L,
1579 const M2<T2, n_rows, n_cols, type2, _unused2...>& mat_R) {
1580 MAT_MINUS_MAT_LOWER:
1581 for (size_t i = 0; i != n_rows; ++i) {
1583 for (size_t j = i; j != n_cols; ++j) {
1584 FLAMES_PRAGMA(LOOP_FLATTEN)
1585 this->_data[(1 + i) * i / 2 + j] = mat_L(i, j) - mat_R(i, j);
1586 }
1587 }
1588 return *this;
1589 }
1590
1609 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
1610 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
1611 typename T2, MatType type1, MatType type2,
1612 std::enable_if_t<type == MatType::SUPPER && (type1 != MatType::SUPPER || type2 != MatType::SUPPER),
1613 bool> = true>
1614 Mat& sub(const M1<T1, n_rows, n_cols, type1, _unused1...>& mat_L,
1615 const M2<T2, n_rows, n_cols, type2, _unused2...>& mat_R) {
1616 MAT_MINUS_MAT_SUPPER:
1617 for (size_t i = 0; i != n_rows - 1; ++i) {
1619 for (size_t j = i + 1; j != n_cols; ++j) {
1620 FLAMES_PRAGMA(LOOP_FLATTEN)
1621 this->_data[(2 * n_cols + 1 - i) * i / 2 + j - 2 * i - 1] = mat_L(i, j) - mat_R(i, j);
1622 }
1623 }
1624 return *this;
1625 }
1626
1645 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
1646 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
1647 typename T2, MatType type1, MatType type2,
1648 std::enable_if_t<type == MatType::SLOWER && (type1 != MatType::SLOWER || type2 != MatType::SLOWER),
1649 bool> = true>
1650 Mat& sub(const M1<T1, n_rows, n_cols, type1, _unused1...>& mat_L,
1651 const M2<T2, n_rows, n_cols, type2, _unused2...>& mat_R) {
1652 MAT_MINUS_MAT_SLOWER:
1653 for (size_t i = 1; i != n_rows; ++i) {
1655 for (size_t j = 0; j != n_cols - 1; ++j) {
1656 FLAMES_PRAGMA(LOOP_FLATTEN)
1657 this->_data[(1 + i) * i / 2 + j - i] = mat_L(i, j) - mat_R(i, j);
1658 }
1659 }
1660 return *this;
1661 }
1662
1681 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
1682 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
1683 typename T2, MatType type1, MatType type2,
1684 std::enable_if_t<type == MatType::SYM && (type1 != MatType::SYM || type2 != MatType::SYM), bool> = true>
1685 Mat& sub(const M1<T1, n_rows, n_cols, type1, _unused1...>& mat_L,
1686 const M2<T2, n_rows, n_cols, type2, _unused2...>& mat_R) {
1687 MAT_MINUS_MAT_SYM:
1688 for (size_t i = 0; i != n_rows; ++i) {
1690 for (size_t j = i; j != n_cols; ++j) {
1691 FLAMES_PRAGMA(LOOP_FLATTEN)
1692 this->_data[(2 * n_cols + 1 - i) * i / 2 + j - i] = mat_L(i, j) - mat_R(i, j);
1693 }
1694 }
1695 return *this;
1696 }
1697
1716 template <
1717 template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
1718 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1, typename T2,
1719 MatType type1, MatType type2,
1720 std::enable_if_t<type == MatType::ASYM && (type1 != MatType::ASYM || type2 != MatType::ASYM), bool> = true>
1721 Mat& sub(const M1<T1, n_rows, n_cols, type1, _unused1...>& mat_L,
1722 const M2<T2, n_rows, n_cols, type2, _unused2...>& mat_R) {
1723 MAT_MINUS_MAT_ASYM:
1724 for (size_t i = 0; i != n_rows; ++i) {
1726 for (size_t j = i + 1; j != n_cols; ++j) {
1727 FLAMES_PRAGMA(LOOP_FLATTEN)
1728 this->_data[(2 * n_cols + 1 - i) * i / 2 + j - i * 2 - 1] = mat_L(i, j) - mat_R(i, j);
1729 }
1730 }
1731 return *this;
1732 }
1733
1747 template <template <class, size_t, size_t, MatType, class...> typename M, typename... _unused, typename T2,
1748 MatType type2>
1750 FLAMES_PRAGMA(INLINE)
1751 // return this->sub(*this, mat_R);
1752 for (size_t i = 0; i != size(); ++i) {
1754 _data[i] -= mat_R[i];
1755 }
1756 return *this;
1757 }
1758
1775 template <
1776 template <class, size_t, size_t, MatType, class...> typename M, typename... _unused, typename ScalarT,
1777 typename T2,
1778 std::enable_if_t<std::is_arithmetic<std::remove_cv_t<std::remove_reference_t<ScalarT>>>::value, bool> = true>
1780 MAT_SCALAR_TIMES:
1781 for (size_t i = 0; i != size(); ++i) {
1783 _data[i] = mat[i] * s;
1784 }
1785 return *this;
1786 }
1787
1803 template <
1804 template <class, size_t, size_t, MatType, class...> typename M, typename... _unused, typename ScalarT,
1805 typename T2,
1806 std::enable_if_t<std::is_arithmetic<std::remove_cv_t<std::remove_reference_t<ScalarT>>>::value, bool> = true>
1807 Mat& mul(const M<T2, n_rows, n_cols, type, _unused...>& mat, std::complex<ScalarT> s) {
1808 MAT_SCALAR_TIMES:
1809 for (size_t i = 0; i != size(); ++i) {
1811 _data[i] = mat[i] * s;
1812 }
1813 return *this;
1814 }
1815
1830 template <template <class, size_t, size_t, MatType, class...> typename M, typename... _unused, int AP_W,
1831 typename T2>
1832 Mat& mul(const M<T2, n_rows, n_cols, type, _unused...>& mat, ap_int<AP_W> s) {
1833 MAT_SCALAR_TIMES:
1834 for (size_t i = 0; i != size(); ++i) {
1836 _data[i] = mat[i] * s;
1837 }
1838 return *this;
1839 }
1840
1859 template <template <class, size_t, size_t, MatType, class...> typename M, typename... _unused, int AP_W, int AP_I,
1860 ap_q_mode AP_Q, ap_o_mode AP_O, int AP_N, typename T2>
1861 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) {
1862 MAT_SCALAR_TIMES:
1863 for (size_t i = 0; i != size(); ++i) {
1865 _data[i] = mat[i] * s;
1866 }
1867 return *this;
1868 }
1869
1881 template <
1882 typename ScalarT,
1883 std::enable_if_t<std::is_arithmetic<std::remove_cv_t<std::remove_reference_t<ScalarT>>>::value, bool> = true>
1884 Mat& mul(ScalarT s) {
1885 MAT_SCALAR_TIMES_SELF:
1886 for (size_t i = 0; i != size(); ++i) {
1888 _data[i] *= s;
1889 }
1890 return *this;
1891 }
1892
1903 template <
1904 typename ScalarT,
1905 std::enable_if_t<std::is_arithmetic<std::remove_cv_t<std::remove_reference_t<ScalarT>>>::value, bool> = true>
1906 Mat& mul(std::complex<ScalarT> s) {
1907 MAT_SCALAR_TIMES_SELF:
1908 for (size_t i = 0; i != size(); ++i) {
1910 _data[i] *= s;
1911 }
1912 return *this;
1913 }
1914
1925 template <int AP_W>
1926 Mat& mul(ap_int<AP_W> s) {
1927 MAT_SCALAR_TIMES_SELF:
1928 for (size_t i = 0; i != size(); ++i) {
1930 _data[i] *= s;
1931 }
1932 return *this;
1933 }
1934
1949 template <int AP_W, int AP_I, ap_q_mode AP_Q, ap_o_mode AP_O, int AP_N>
1950 Mat& mul(ap_fixed<AP_W, AP_I, AP_Q, AP_O, AP_N> s) {
1951 MAT_SCALAR_TIMES_SELF:
1952 for (size_t i = 0; i != size(); ++i) {
1954 _data[i] *= s;
1955 }
1956 return *this;
1957 }
1958
1981 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
1982 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
1983 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
1984 std::enable_if_t<(!(std::is_same<T1, bool>::value) && !(std::is_same<T2, bool>::value)) &&
1985 ((type1 == MatType::NORMAL && type2 == MatType::NORMAL) ||
1986 (type1 == MatType::NORMAL && type2 == MatType::SYM) ||
1987 (type1 == MatType::SYM && type2 == MatType::NORMAL) ||
1988 (type1 == MatType::SYM && type2 == MatType::SYM)),
1989 bool> = true>
1990 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
1991 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
1992 FLAMES_PRAGMA(INLINE off)
1993 static_assert(n_rows == rows_, "Matrix dimension should meet.");
1994 static_assert(n_cols == cols_, "Matrix dimension should meet.");
1995 GEMM:
1996 for (size_t i = 0; i != comm; ++i) {
1997 GEMM_r:
1998 for (size_t r = 0; r != n_rows; ++r) {
2000 // FLAMES_PRAGMA(DEPENDENCE variable=mat_L inter false)
2001 // FLAMES_PRAGMA(DEPENDENCE variable=mat_L intra false)
2002 // FLAMES_PRAGMA(DEPENDENCE variable=mat_R inter false)
2003 // FLAMES_PRAGMA(DEPENDENCE variable=mat_R intra false
2004 GEMM_c:
2005 for (size_t c = 0; c != n_cols; ++c) {
2006 FLAMES_PRAGMA(LOOP_FLATTEN)
2007 if (i == 0) (*this)(r, c) = T(0); // initialize
2008 (*this)(r, c) += mat_L(r, i) * mat_R(i, c);
2009 }
2010 }
2011 }
2012 return *this;
2013 }
2014
2036 template <
2037 template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
2038 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1, typename T2,
2039 MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
2040 std::enable_if_t<((type1 == MatType::NORMAL || type1 == MatType::SYM) && type2 == MatType::ASYM), bool> = true>
2041 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
2042 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
2043 FLAMES_PRAGMA(INLINE off)
2044 static_assert(n_rows == rows_, "Matrix dimension should meet.");
2045 static_assert(n_cols == cols_, "Matrix dimension should meet.");
2046 MAT_NORAML_OR_SYM_TIMES_MAT_ASYM:
2047 for (size_t i = 0; i != comm; ++i) {
2048 GEMM_r:
2049 for (size_t r = 0; r != n_rows; ++r) {
2051 GEMM_c:
2052 for (size_t c = 0; c != n_cols; ++c) {
2053 FLAMES_PRAGMA(LOOP_FLATTEN)
2054 if (i == 0) (*this)(r, c) = T(0); // initialize
2055 if (i != c) (*this)(r, c) += mat_L(r, i) * mat_R(i, c);
2056 }
2057 }
2058 }
2059 return *this;
2060 }
2061
2083 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
2084 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
2085 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
2086 std::enable_if_t<((type1 == MatType::NORMAL || type1 == MatType::SYM) && type2 == MatType::DIAGONAL),
2087 bool> = true>
2088 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
2089 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
2090 static_assert(n_rows == rows_, "Matrix dimension should meet.");
2091 static_assert(n_cols == cols_, "Matrix dimension should meet.");
2092 MAT_NORAML_OR_SYM_TIMES_DIAG:
2093 for (size_t i = 0; i != n_rows; ++i) {
2095 for (size_t j = 0; j != n_cols; ++j) {
2096 FLAMES_PRAGMA(LOOP_FLATTEN)
2097 (*this)(i, j) = mat_L(i, j) * mat_R[j];
2098 }
2099 }
2100 return *this;
2101 }
2102
2124 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
2125 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
2126 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
2127 std::enable_if_t<((type1 == MatType::NORMAL || type1 == MatType::SYM) && type2 == MatType::SCALAR),
2128 bool> = true>
2129 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
2130 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
2131 static_assert(n_rows == rows_, "Matrix dimension should meet.");
2132 static_assert(n_cols == cols_, "Matrix dimension should meet.");
2133 MAT_NORAML_OR_MAT_SYM_TIMES_SCAL:
2134 for (size_t i = 0; i != n_rows; ++i) {
2136 for (size_t j = 0; j != n_rows; ++j) {
2137 FLAMES_PRAGMA(LOOP_FLATTEN)
2138 (*this)(i, j) = mat_L(i, j) * mat_R[0];
2139 }
2140 }
2141 return *this;
2142 }
2143
2165 template <
2166 template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
2167 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1, typename T2,
2168 MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
2169 std::enable_if_t<((type1 == MatType::NORMAL || type1 == MatType::SYM) && type2 == MatType::UPPER), bool> = true>
2170 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
2171 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
2172 static_assert(n_rows == rows_, "Matrix dimension should meet.");
2173 static_assert(n_cols == cols_, "Matrix dimension should meet.");
2174 static const size_t r[288] = {
2175 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,
2176 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,
2177 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,
2178 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,
2179 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,
2180 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,
2181 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,
2182 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
2183 };
2184 static const size_t i[288] = {
2185 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,
2186 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,
2187 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,
2188 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,
2189 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,
2190 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,
2191 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,
2192 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
2193 };
2194 static const size_t c[288] = {
2195 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,
2196 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,
2197 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,
2198 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,
2199 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,
2200 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,
2201 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,
2202 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
2203 };
2204 MAT_NORAML_OR_MAT_SYM_TIMES_UPPER:
2205 for (size_t n = 0; n != n_rows * n_rows * (n_rows + 1) / 2; n++) {
2207 if (i[n] == 0) (*this)(r[n], c[n]) = 0; // initialize
2208 (*this)(r[n], c[n]) += mat_L(r[n], i[n]) * mat_R(i[n], c[n]);
2209 }
2210 return *this;
2211 }
2212
2234 template <
2235 template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
2236 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1, typename T2,
2237 MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
2238 std::enable_if_t<((type1 == MatType::NORMAL || type1 == MatType::SYM) && type2 == MatType::LOWER), bool> = true>
2239 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
2240 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
2241 static_assert(n_rows == rows_, "Matrix dimension should meet.");
2242 static_assert(n_cols == cols_, "Matrix dimension should meet.");
2243 static const size_t r[288] = {
2244 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,
2245 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,
2246 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,
2247 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,
2248 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,
2249 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,
2250 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,
2251 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
2252 };
2253 static const size_t i[288] = {
2254 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,
2255 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,
2256 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,
2257 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,
2258 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,
2259 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,
2260 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,
2261 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
2262 };
2263 static const size_t c[288] = {
2264 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,
2265 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,
2266 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,
2267 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,
2268 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,
2269 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,
2270 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,
2271 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
2272 };
2273 MAT_NORAML_OR_MAT_SYM_TIMES_LOWER:
2274 for (size_t n = 0; n != n_rows * n_rows * (n_rows + 1) / 2; n++) {
2276 if (i[n] == c[n]) (*this)(r[n], c[n]) = 0; // initialize
2277 (*this)(r[n], c[n]) += mat_L(r[n], i[n]) * mat_R(i[n], c[n]);
2278 }
2279 return *this;
2280 }
2281
2303 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
2304 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
2305 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
2306 std::enable_if_t<((type1 == MatType::NORMAL || type1 == MatType::SYM) && type2 == MatType::SUPPER),
2307 bool> = true>
2308 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
2309 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
2310 static_assert(n_rows == rows_, "Matrix dimension should meet.");
2311 static_assert(n_cols == cols_, "Matrix dimension should meet.");
2312 static const size_t r[224] = {
2313 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,
2314 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,
2315 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,
2316 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,
2317 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,
2318 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,
2319 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,
2320 };
2321 static const size_t i[224] = {
2322 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,
2323 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,
2324 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,
2325 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,
2326 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,
2327 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,
2328 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,
2329 };
2330 static const size_t c[224] = {
2331 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,
2332 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,
2333 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,
2334 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,
2335 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,
2336 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,
2337 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,
2338 };
2339 MAT_NORAML_OR_MAT_SYM_TIMES_SUPPER:
2340 for (size_t n = 0; n != n_rows * n_rows * (n_rows - 1) / 2; n++) {
2342 if (i[n] == 0) (*this)(r[n], c[n]) = 0; // initialize
2343 (*this)(r[n], c[n]) += mat_L(r[n], i[n]) * mat_R(i[n], c[n]);
2344 }
2345 for (size_t i = 0; i != n_rows; i++) { (*this)(i, 0) = 0; }
2346 return *this;
2347 }
2348
2370 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
2371 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
2372 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
2373 std::enable_if_t<((type1 == MatType::NORMAL || type1 == MatType::SYM) && type2 == MatType::SLOWER),
2374 bool> = true>
2375 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
2376 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
2377 static_assert(n_rows == rows_, "Matrix dimension should meet.");
2378 static_assert(n_cols == cols_, "Matrix dimension should meet.");
2379 static const size_t r[224] = {
2380 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,
2381 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,
2382 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,
2383 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,
2384 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,
2385 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,
2386 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,
2387 };
2388 static const size_t i[224] = {
2389 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,
2390 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,
2391 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,
2392 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,
2393 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,
2394 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,
2395 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,
2396 };
2397 static const size_t c[224] = {
2398 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,
2399 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,
2400 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,
2401 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,
2402 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,
2403 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,
2404 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,
2405 };
2406 MAT_NORAML_OR_MAT_SYM_TIMES_SLOWER:
2407 for (size_t n = 0; n != n_rows * n_rows * (n_rows - 1) / 2; n++) {
2409 if (i[n] == c[n] + 1) (*this)(r[n], c[n]) = 0; // initialize
2410 (*this)(r[n], c[n]) += mat_L(r[n], i[n]) * mat_R(i[n], c[n]);
2411 }
2412 for (size_t i = 0; i != n_rows; i++) { (*this)(i, n_rows - 1) = 0; }
2413 return *this;
2414 }
2436 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
2437 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
2438 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
2439 std::enable_if_t<(type1 == MatType::DIAGONAL && type2 == MatType::DIAGONAL), bool> = true>
2440 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
2441 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
2442 static_assert(n_rows == rows_, "Matrix dimension should meet.");
2443 static_assert(n_cols == cols_, "Matrix dimension should meet.");
2444 MAT_DIAG_TIMES_MAT_DIAG:
2445 for (size_t i = 0; i != n_rows; ++i) {
2447 (*this)(i, i) = mat_L[i] * mat_R[i];
2448 }
2449 return *this;
2450 }
2451
2473 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
2474 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
2475 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
2476 std::enable_if_t<(type1 == MatType::DIAGONAL && type2 == MatType::SCALAR), bool> = true>
2477 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
2478 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
2479 static_assert(n_rows == rows_, "Matrix dimension should meet.");
2480 static_assert(n_cols == cols_, "Matrix dimension should meet.");
2481 MAT_DIAG_TIMES_MAT_SCAL:
2482 for (size_t i = 0; i != n_cols; ++i) {
2484 _data[i] = mat_L[i] * mat_R[0];
2485 }
2486 return *this;
2487 }
2488
2510 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
2511 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
2512 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
2513 std::enable_if_t<(type1 == MatType::DIAGONAL && type2 == MatType::UPPER), bool> = true>
2514 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
2515 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
2516 static_assert(n_rows == rows_, "Matrix dimension should meet.");
2517 static_assert(n_cols == cols_, "Matrix dimension should meet.");
2518 static const size_t r[36] = {
2519 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,
2520 };
2521 static const size_t i[36] = {
2522 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,
2523 };
2524 static const size_t c[36] = {
2525 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,
2526 };
2527 MAT_DIAG_TIMES_UPPER:
2528 for (size_t n = 0; n != n_rows * (n_rows + 1) / 2; n++) {
2530 (*this)(r[n], c[n]) = mat_L(r[n], i[n]) * mat_R(i[n], c[n]);
2531 }
2532 return *this;
2533 }
2534
2556 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
2557 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
2558 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
2559 std::enable_if_t<(type1 == MatType::DIAGONAL && type2 == MatType::LOWER), bool> = true>
2560 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
2561 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
2562 static_assert(n_rows == rows_, "Matrix dimension should meet.");
2563 static_assert(n_cols == cols_, "Matrix dimension should meet.");
2564 static const size_t r[36] = {
2565 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,
2566 };
2567 static const size_t i[36] = {
2568 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,
2569 };
2570 static const size_t c[36] = {
2571 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,
2572 };
2573 MAT_DIAG_TIMES_LOWER:
2574 for (size_t n = 0; n != n_rows * (n_rows + 1) / 2; n++) {
2576 (*this)(r[n], c[n]) = mat_L(r[n], i[n]) * mat_R(i[n], c[n]);
2577 }
2578 return *this;
2579 }
2580
2602 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
2603 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
2604 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
2605 std::enable_if_t<(type1 == MatType::DIAGONAL && type2 == MatType::SUPPER), bool> = true>
2606 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
2607 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
2608 static_assert(n_rows == rows_, "Matrix dimension should meet.");
2609 static_assert(n_cols == cols_, "Matrix dimension should meet.");
2610 static const size_t r[28] = {
2611 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
2612 };
2613 static const size_t i[28] = {
2614 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
2615 };
2616 static const size_t c[28] = {
2617 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
2618 };
2619 MAT_DIAG_TIMES_SUPPER:
2620 for (size_t n = 0; n != n_rows * (n_rows - 1) / 2; n++) {
2622 (*this)(r[n], c[n]) = mat_L(r[n], i[n]) * mat_R(i[n], c[n]);
2623 }
2624 return *this;
2625 }
2626
2648 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
2649 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
2650 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
2651 std::enable_if_t<(type1 == MatType::DIAGONAL && type2 == MatType::SLOWER), bool> = true>
2652 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
2653 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
2654 static_assert(n_rows == rows_, "Matrix dimension should meet.");
2655 static_assert(n_cols == cols_, "Matrix dimension should meet.");
2656 static const size_t r[28] = {
2657 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
2658 };
2659 static const size_t i[28] = {
2660 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
2661 };
2662 static const size_t c[28] = {
2663 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
2664 };
2665 MAT_DIAG_TIMES_SLOWER:
2666 for (size_t n = 0; n != n_rows * (n_rows - 1) / 2; n++) {
2668 (*this)(r[n], c[n]) = mat_L(r[n], i[n]) * mat_R(i[n], c[n]);
2669 }
2670 return *this;
2671 }
2672
2694 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
2695 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
2696 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
2697 std::enable_if_t<(type1 == MatType::DIAGONAL && (type2 == MatType::NORMAL || type2 == MatType::SYM)),
2698 bool> = true>
2699 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
2700 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
2701 static_assert(n_rows == rows_, "Matrix dimension should meet.");
2702 static_assert(n_cols == cols_, "Matrix dimension should meet.");
2703 MAT_DIAG_TIMES_MAT_NORMAL_or_SYM:
2704 for (size_t j = 0; j != n_cols; ++j) {
2706 for (size_t i = 0; i != n_rows; ++i) {
2707 FLAMES_PRAGMA(LOOP_FLATTEN)
2708 (*this)(i, j) = mat_L(i, i) * mat_R(i, j);
2709 }
2710 }
2711 return *this;
2712 }
2713
2735 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
2736 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
2737 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
2738 std::enable_if_t<(type1 == MatType::DIAGONAL && type2 == MatType::ASYM), bool> = true>
2739 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
2740 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
2741 static_assert(n_rows == rows_, "Matrix dimension should meet.");
2742 static_assert(n_cols == cols_, "Matrix dimension should meet.");
2743 MAT_DIAG_TIMES_MAT_ASYM:
2744 for (size_t j = 0; j != n_cols; ++j) {
2746 for (size_t i = 0; i != n_rows; ++i) {
2747 FLAMES_PRAGMA(LOOP_FLATTEN)
2748 if (i != j) (*this)(i, j) = mat_L(i, i) * mat_R(i, j);
2749 else (*this)(i, j) = T(0);
2750 }
2751 }
2752 return *this;
2753 }
2754
2774 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
2775 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
2776 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
2777 std::enable_if_t<(type1 == MatType::SCALAR && type2 == MatType::SCALAR), bool> = true>
2778 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
2779 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
2780 static_assert(n_rows == rows_, "Matrix dimension should meet.");
2781 static_assert(n_cols == cols_, "Matrix dimension should meet.");
2782 MAT_SCAL_TIMES_MAT_SCAL:
2783 _data[0] = mat_L[0] * mat_R[0];
2784 return *this;
2785 }
2786
2808 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
2809 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
2810 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
2811 std::enable_if_t<(type1 == MatType::SCALAR && type2 == MatType::DIAGONAL), bool> = true>
2812 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
2813 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
2814 static_assert(n_rows == rows_, "Matrix dimension should meet.");
2815 static_assert(n_cols == cols_, "Matrix dimension should meet.");
2816 MAT_SCAL_TIMES_MAT_DIAG:
2817 for (size_t i = 0; i != n_cols; ++i) {
2819 _data[i] = mat_L[0] * mat_R[i];
2820 }
2821 return *this;
2822 }
2823
2845 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
2846 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
2847 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
2848 std::enable_if_t<(type2 == MatType::UPPER && type1 == MatType::SCALAR), bool> = true>
2849 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
2850 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
2851 static_assert(n_rows == rows_, "Matrix dimension should meet.");
2852 static_assert(n_cols == cols_, "Matrix dimension should meet.");
2853 MAT_SCAL_TIMES_MAT_UPPER:
2854 for (size_t i = 0; i != (1 + n_rows) * n_rows / 2; ++i) {
2856 _data[i] = mat_L[0] * mat_R[i];
2857 }
2858 return *this;
2859 }
2860
2882 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
2883 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
2884 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
2885 std::enable_if_t<(type2 == MatType::LOWER && type1 == MatType::SCALAR), bool> = true>
2886 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
2887 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
2888 static_assert(n_rows == rows_, "Matrix dimension should meet.");
2889 static_assert(n_cols == cols_, "Matrix dimension should meet.");
2890 MAT_SCAL_TIMES_MAT_LOWER:
2891 for (size_t i = 0; i != (1 + n_rows) * n_rows / 2; ++i) {
2893 _data[i] = mat_L[0] * mat_R[i];
2894 }
2895 return *this;
2896 }
2897
2919 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
2920 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
2921 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
2922 std::enable_if_t<(type2 == MatType::SUPPER && type1 == MatType::SCALAR), bool> = true>
2923 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
2924 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
2925 static_assert(n_rows == rows_, "Matrix dimension should meet.");
2926 static_assert(n_cols == cols_, "Matrix dimension should meet.");
2927 MAT_SCAL_TIMES_MAT_SUPPER:
2928 for (size_t i = 0; i != (n_rows - 1) * n_rows / 2; ++i) {
2930 _data[i] = mat_L[0] * mat_R[i];
2931 }
2932 return *this;
2933 }
2934
2956 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
2957 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
2958 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
2959 std::enable_if_t<(type2 == MatType::SLOWER && type1 == MatType::SCALAR), bool> = true>
2960 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
2961 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
2962 static_assert(n_rows == rows_, "Matrix dimension should meet.");
2963 static_assert(n_cols == cols_, "Matrix dimension should meet.");
2964 MAT_SCAL_TIMES_MAT_SLOWER:
2965 for (size_t i = 0; i != (n_rows - 1) * n_rows / 2; ++i) {
2967 _data[i] = mat_L[0] * mat_R[i];
2968 }
2969 return *this;
2970 }
2971
2993 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
2994 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
2995 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
2996 std::enable_if_t<(type2 == MatType::ASYM && type1 == MatType::SCALAR), bool> = true>
2997 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
2998 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
2999 static_assert(n_rows == rows_, "Matrix dimension should meet.");
3000 static_assert(n_cols == cols_, "Matrix dimension should meet.");
3001 MAT_SCAL_TIMES_MAT_SLOWER:
3002 for (size_t i = 1; i != n_rows; ++i) {
3004 for (size_t j = 0; j != n_cols; ++j) {
3005 FLAMES_PRAGMA(LOOP_FLATTEN)
3006 if (i != j) (*this)(i, j) = mat_L[0] * mat_R(i, j);
3007 else (*this)(i, j) = T(0);
3008 }
3009 }
3010 return *this;
3011 }
3012
3034 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
3035 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
3036 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
3037 std::enable_if_t<((type2 == MatType::SYM || type2 == NORMAL) && type1 == MatType::SCALAR), bool> = true>
3038 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
3039 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
3040 static_assert(n_rows == rows_, "Matrix dimension should meet.");
3041 static_assert(n_cols == cols_, "Matrix dimension should meet.");
3042 MAT_SCAL_TIMES_MAT_NORMAL_OR_MAT_SYM:
3043 for (size_t i = 0; i != n_rows; ++i) {
3045 for (size_t j = 0; j != n_cols; ++j) {
3046 FLAMES_PRAGMA(LOOP_FLATTEN)
3047 (*this)(i, j) = mat_L[0] * mat_R(i, j);
3048 }
3049 }
3050 return *this;
3051 }
3052
3074 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
3075 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
3076 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
3077 std::enable_if_t<(type1 == MatType::UPPER && type2 == MatType::SCALAR), bool> = true>
3078 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
3079 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
3080 static_assert(n_rows == rows_, "Matrix dimension should meet.");
3081 static_assert(n_cols == cols_, "Matrix dimension should meet.");
3082 MAT_UPPER_TIMES_MAT_SCALAR:
3083 for (size_t i = 0; i != (n_rows + 1) * n_rows / 2; ++i) {
3085 _data[i] = mat_L[i] * mat_R[0];
3086 }
3087 return *this;
3088 }
3089
3111 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
3112 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
3113 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
3114 std::enable_if_t<(type1 == MatType::UPPER && type2 == MatType::DIAGONAL), bool> = true>
3115 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
3116 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
3117 static_assert(n_rows == rows_, "Matrix dimension should meet.");
3118 static_assert(n_cols == cols_, "Matrix dimension should meet.");
3119 static const size_t r[36] = { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2,
3120 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 6, 6, 7 };
3121 static const size_t i[36] = { 0, 1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 2, 3, 4,
3122 5, 6, 7, 3, 4, 5, 6, 7, 4, 5, 6, 7, 5, 6, 7, 6, 7, 7 };
3123 static const size_t c[36] = { 0, 1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 2, 3, 4,
3124 5, 6, 7, 3, 4, 5, 6, 7, 4, 5, 6, 7, 5, 6, 7, 6, 7, 7 };
3125 MAT_UPPER_TIMES_DIAG:
3126 for (size_t n = 0; n != n_rows * (n_rows + 1) / 2; n++) {
3128 (*this)(r[n], c[n]) = mat_L(r[n], i[n]) * mat_R(i[n], c[n]);
3129 }
3130 return *this;
3131 }
3132
3154 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
3155 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
3156 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
3157 std::enable_if_t<(type1 == MatType::UPPER && type2 == MatType::UPPER), bool> = true>
3158 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
3159 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
3160 FLAMES_PRAGMA(INLINE off)
3161 static_assert(n_rows == rows_, "Matrix dimension should meet.");
3162 static_assert(n_cols == cols_, "Matrix dimension should meet.");
3163 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,
3164 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 0, 0, 0, 0, 1, 1, 1, 1,
3165 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2,
3166 2, 2, 2, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2,
3167 2, 2, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 };
3168 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,
3169 2, 1, 2, 3, 2, 3, 4, 3, 4, 5, 4, 5, 6, 5, 6, 7, 0, 1, 2, 3, 1, 2, 3, 4,
3170 2, 3, 4, 5, 3, 4, 5, 6, 4, 5, 6, 7, 0, 1, 2, 3, 4, 1, 2, 3, 4, 5, 2, 3,
3171 4, 5, 6, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 6, 2, 3, 4, 5,
3172 6, 7, 0, 1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7 };
3173 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,
3174 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, 3, 3, 3, 3, 4, 4, 4, 4,
3175 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6,
3176 6, 6, 6, 7, 7, 7, 7, 7, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7,
3177 7, 7, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 };
3178 MAT_UPPER_TIMES_UPPER:
3179 for (size_t n = 0; n != n_rows * (n_rows + 1) * (n_rows + 2) / 6; n++) {
3181 if (i[n] == r[n]) (*this)(r[n], c[n]) = 0; // initialize
3182 (*this)(r[n], c[n]) += mat_L(r[n], i[n]) * mat_R(i[n], c[n]);
3183 }
3184 return *this;
3185 }
3186
3208 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
3209 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
3210 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
3211 std::enable_if_t<(type1 == MatType::UPPER && type2 == MatType::LOWER), bool> = true>
3212 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
3213 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
3214 FLAMES_PRAGMA(INLINE off)
3215 static_assert(n_rows == rows_, "Matrix dimension should meet.");
3216 static_assert(n_cols == cols_, "Matrix dimension should meet.");
3217 static const size_t r[120] = {
3218 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,
3219 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,
3220 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,
3221 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,
3222 };
3223 static const size_t i[120] = {
3224 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,
3225 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,
3226 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,
3227 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,
3228 };
3229 static const size_t c[120] = {
3230 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,
3231 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,
3232 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,
3233 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,
3234 };
3235 MAT_UPPER_TIMES_MAT_LOWER:
3236 for (size_t n = 0; n != n_rows * (n_rows + 1) * (n_rows + 2) / 6; n++) {
3238 if (i[n] == r[n]) (*this)(r[n], c[n]) = 0; // initialize
3239 (*this)(r[n], c[n]) += mat_L(r[n], i[n]) * mat_R(i[n], c[n]);
3240 }
3241 return *this;
3242 }
3243
3265 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
3266 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
3267 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
3268 std::enable_if_t<(type1 == MatType::UPPER && type2 == MatType::SUPPER), bool> = true>
3269 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
3270 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
3271 FLAMES_PRAGMA(INLINE off)
3272 static_assert(n_rows == rows_, "Matrix dimension should meet.");
3273 static_assert(n_cols == cols_, "Matrix dimension should meet.");
3274 static const size_t c[84] = {
3275 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,
3276 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,
3277 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,
3278 };
3279 static const size_t i[84] = {
3280 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,
3281 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,
3282 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,
3283 };
3284 static const size_t r[84] = {
3285 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,
3286 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,
3287 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,
3288 };
3289 MAT_UPPER_TIMES_MAT_SUPPER:
3290 for (size_t n = 0; n != (n_rows * n_rows * n_rows - n_rows) / 6; n++) {
3292 if (i[n] == r[n]) (*this)(r[n], c[n]) = 0; // initialize
3293 (*this)(r[n], c[n]) += mat_L(r[n], i[n]) * mat_R(i[n], c[n]);
3294 }
3295 return *this;
3296 }
3297
3319 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
3320 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
3321 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
3322 std::enable_if_t<(type1 == MatType::UPPER && type2 == MatType::SLOWER), bool> = true>
3323 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
3324 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
3325 FLAMES_PRAGMA(INLINE off)
3326 static_assert(n_rows == rows_, "Matrix dimension should meet.");
3327 static_assert(n_cols == cols_, "Matrix dimension should meet.");
3328 static const size_t r[168] = {
3329 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,
3330 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,
3331 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,
3332 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,
3333 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,
3334 };
3335 static const size_t i[168] = {
3336 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,
3337 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,
3338 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,
3339 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,
3340 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,
3341 };
3342 static const size_t c[168] = {
3343 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,
3344 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,
3345 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,
3346 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,
3347 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,
3348 };
3349 MAT_UPPER_TIMES_MAT_SLOWER:
3350 for (size_t n = 0; n != (n_rows * n_rows * n_rows - n_rows) / 3; n++) {
3352 if (i[n] == r[n] || i[n] == (c[n] + 1)) (*this)(r[n], c[n]) = 0; // initialize
3353 (*this)(r[n], c[n]) += mat_L(r[n], i[n]) * mat_R(i[n], c[n]);
3354 }
3355 return *this;
3356 }
3357
3379 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
3380 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
3381 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
3382 std::enable_if_t<(type1 == MatType::UPPER && type2 == MatType::ASYM), bool> = true>
3383 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
3384 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
3385 FLAMES_PRAGMA(INLINE off)
3386 static_assert(n_rows == rows_, "Matrix dimension should meet.");
3387 static_assert(n_cols == cols_, "Matrix dimension should meet.");
3388 static const size_t r[288] = {
3389 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,
3390 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,
3391 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,
3392 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,
3393 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,
3394 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,
3395 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,
3396 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,
3397 };
3398 static const size_t c[288] = {
3399 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,
3400 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,
3401 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,
3402 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,
3403 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,
3404 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,
3405 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,
3406 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,
3407 };
3408 static const size_t i[288] = {
3409 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,
3410 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,
3411 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,
3412 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,
3413 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,
3414 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,
3415 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,
3416 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,
3417 };
3418 MAT_UPPER_TIMES_MAT_ASYM:
3419 for (size_t n = 0; n != n_rows * n_rows * (n_rows + 1) / 2; n++) {
3421 if (i[n] == r[n]) (*this)(r[n], c[n]) = 0; // initialize
3422 if (i[n] != c[n]) (*this)(r[n], c[n]) += mat_L(r[n], i[n]) * mat_R(i[n], c[n]);
3423 }
3424 return *this;
3425 }
3426
3448 template <
3449 template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
3450 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1, typename T2,
3451 MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
3452 std::enable_if_t<(type1 == MatType::UPPER && (type2 == MatType::SYM || type2 == MatType::NORMAL)), bool> = true>
3453 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
3454 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
3455 FLAMES_PRAGMA(INLINE off)
3456 static_assert(n_rows == rows_, "Matrix dimension should meet.");
3457 static_assert(n_cols == cols_, "Matrix dimension should meet.");
3458 static const size_t r[288] = {
3459 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,
3460 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,
3461 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,
3462 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,
3463 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,
3464 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,
3465 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,
3466 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,
3467 };
3468 static const size_t c[288] = {
3469 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,
3470 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,
3471 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,
3472 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,
3473 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,
3474 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,
3475 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,
3476 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,
3477 };
3478 static const size_t i[288] = {
3479 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,
3480 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,
3481 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,
3482 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,
3483 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,
3484 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,
3485 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,
3486 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,
3487 };
3488 MAT_LOWER_TIMES_NORAML_OR_MAT_SYM:
3489 for (size_t n = 0; n != n_rows * n_rows * (n_rows + 1) / 2; n++) {
3491 if (i[n] == r[n]) (*this)(r[n], c[n]) = 0; // initialize
3492 (*this)(r[n], c[n]) += mat_L(r[n], i[n]) * mat_R(i[n], c[n]);
3493 }
3494 return *this;
3495 }
3496
3518 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
3519 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
3520 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
3521 std::enable_if_t<(type1 == MatType::LOWER && type2 == MatType::SCALAR), bool> = true>
3522 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
3523 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
3524 static_assert(n_rows == rows_, "Matrix dimension should meet.");
3525 static_assert(n_cols == cols_, "Matrix dimension should meet.");
3526 MAT_LOWER_TIMES_MAT_SCALAR:
3527 for (size_t i = 0; i != (n_rows + 1) * n_rows / 2; ++i) {
3529 _data[i] = mat_L[i] * mat_R[0];
3530 }
3531 return *this;
3532 }
3533
3555 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
3556 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
3557 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
3558 std::enable_if_t<(type1 == MatType::LOWER && type2 == MatType::DIAGONAL), bool> = true>
3559 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
3560 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
3561 static_assert(n_rows == rows_, "Matrix dimension should meet.");
3562 static_assert(n_cols == cols_, "Matrix dimension should meet.");
3563 static const size_t r[36] = {
3564 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,
3565 };
3566 static const size_t i[36] = {
3567 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,
3568 };
3569 static const size_t c[36] = {
3570 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,
3571 };
3572 MAT_LOWER_TIMES_DIAG:
3573 for (size_t n = 0; n != n_rows * (n_rows + 1) / 2; n++) {
3575 (*this)(r[n], c[n]) = mat_L(r[n], i[n]) * mat_R(i[n], c[n]);
3576 }
3577 return *this;
3578 }
3579
3601 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
3602 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
3603 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
3604 std::enable_if_t<(type1 == MatType::LOWER && type2 == MatType::UPPER), bool> = true>
3605 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
3606 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
3607 FLAMES_PRAGMA(INLINE off)
3608 static_assert(n_rows == rows_, "Matrix dimension should meet.");
3609 static_assert(n_cols == cols_, "Matrix dimension should meet.");
3610 static const size_t r[204] = {
3611 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,
3612 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,
3613 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,
3614 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,
3615 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,
3616 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,
3617 };
3618 static const size_t i[204] = {
3619 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,
3620 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,
3621 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,
3622 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,
3623 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,
3624 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,
3625 };
3626 static const size_t c[204] = {
3627 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,
3628 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,
3629 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,
3630 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,
3631 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,
3632 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,
3633 };
3634 MAT_LOWER_TIMES_MAT_UPPER:
3635 for (size_t n = 0; n != (2 * n_rows * n_rows * n_rows + 3 * n_rows * n_rows + n_rows) / 6; n++) {
3637 if (i[n] == 0) (*this)(r[n], c[n]) = 0; // initialize
3638 (*this)(r[n], c[n]) += mat_L(r[n], i[n]) * mat_R(i[n], c[n]);
3639 }
3640 return *this;
3641 }
3642
3664 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
3665 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
3666 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
3667 std::enable_if_t<(type1 == MatType::LOWER && type2 == MatType::LOWER), bool> = true>
3668 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
3669 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
3670 FLAMES_PRAGMA(INLINE off)
3671 static_assert(n_rows == rows_, "Matrix dimension should meet.");
3672 static_assert(n_cols == cols_, "Matrix dimension should meet.");
3673 static const size_t c[120] = {
3674 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,
3675 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,
3676 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,
3677 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,
3678 };
3679 static const size_t i[120] = {
3680 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,
3681 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,
3682 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,
3683 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,
3684 };
3685 static const size_t r[120] = {
3686 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,
3687 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,
3688 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,
3689 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,
3690 };
3691 MAT_LOWER_TIMES_MAT_LOWER:
3692 for (size_t n = 0; n != n_rows * (n_rows + 1) * (n_rows + 2) / 6; n++) {
3694 if (i[n] == c[n]) (*this)(r[n], c[n]) = 0; // initialize
3695 (*this)(r[n], c[n]) += mat_L(r[n], i[n]) * mat_R(i[n], c[n]);
3696 }
3697 return *this;
3698 }
3699
3721 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
3722 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
3723 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
3724 std::enable_if_t<(type1 == MatType::LOWER && type2 == MatType::SUPPER), bool> = true>
3725 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
3726 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
3727 FLAMES_PRAGMA(INLINE off)
3728 static_assert(n_rows == rows_, "Matrix dimension should meet.");
3729 static_assert(n_cols == cols_, "Matrix dimension should meet.");
3730 static const size_t r[168] = {
3731 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,
3732 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,
3733 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,
3734 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,
3735 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,
3736 };
3737 static const size_t i[168] = {
3738 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,
3739 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,
3740 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,
3741 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,
3742 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,
3743 };
3744 static const size_t c[168] = {
3745 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,
3746 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,
3747 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,
3748 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,
3749 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,
3750 };
3751 MAT_LOWER_TIMES_MAT_SUPPER:
3752 for (size_t n = 0; n != (n_rows * n_rows * n_rows - n_rows) / 3; n++) {
3754 if (i[n] == 0) (*this)(r[n], c[n]) = 0; // initialize
3755 (*this)(r[n], c[n]) += mat_L(r[n], i[n]) * mat_R(i[n], c[n]);
3756 }
3757 for (size_t r = 0; r != n_cols; r++) { (*this)(r, 0) = T(0); }
3758 return *this;
3759 }
3760
3783 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
3784 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
3785 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
3786 std::enable_if_t<(type1 == MatType::LOWER && type2 == MatType::SLOWER), bool> = true>
3787 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
3788 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
3789 FLAMES_PRAGMA(INLINE off)
3790 static_assert(n_rows == rows_, "Matrix dimension should meet.");
3791 static_assert(n_cols == cols_, "Matrix dimension should meet.");
3792 static const size_t c[84] = {
3793 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,
3794 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,
3795 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,
3796 };
3797 static const size_t i[84] = {
3798 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,
3799 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,
3800 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,
3801 };
3802 static const size_t r[84] = {
3803 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,
3804 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,
3805 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,
3806 };
3807 MAT_LOWER_TIMES_MAT_SLOWER:
3808 for (size_t n = 0; n != (n_rows * n_rows * n_rows - n_rows) / 6; n++) {
3810 if (i[n] == c[n] + 1) (*this)(r[n], c[n]) = 0; // initialize
3811 (*this)(r[n], c[n]) += mat_L(r[n], i[n]) * mat_R(i[n], c[n]);
3812 }
3813 return *this;
3814 }
3815
3837 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
3838 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
3839 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
3840 std::enable_if_t<(type1 == MatType::LOWER && type2 == MatType::ASYM), bool> = true>
3841 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
3842 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
3843 FLAMES_PRAGMA(INLINE off)
3844 static_assert(n_rows == rows_, "Matrix dimension should meet.");
3845 static_assert(n_cols == cols_, "Matrix dimension should meet.");
3846 static const size_t c[288] = {
3847 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,
3848 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,
3849 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,
3850 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,
3851 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,
3852 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,
3853 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,
3854 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,
3855 };
3856 static const size_t i[288] = {
3857 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,
3858 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,
3859 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,
3860 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,
3861 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,
3862 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,
3863 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,
3864 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,
3865 };
3866 static const size_t r[288] = {
3867 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,
3868 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,
3869 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,
3870 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,
3871 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,
3872 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,
3873 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,
3874 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,
3875 };
3876 MAT_LOWER_TIMES_MAT_ASYM:
3877 for (size_t n = 0; n != n_rows * n_rows * (n_rows + 1) / 2; n++) {
3879 if (i[n] == 0) (*this)(r[n], c[n]) = 0; // initialize
3880 if (i[n] != c[n]) (*this)(r[n], c[n]) += mat_L(r[n], i[n]) * mat_R(i[n], c[n]);
3881 }
3882 return *this;
3883 }
3884
3906 template <
3907 template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
3908 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1, typename T2,
3909 MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
3910 std::enable_if_t<(type1 == MatType::LOWER && (type2 == MatType::SYM || type2 == MatType::NORMAL)), bool> = true>
3911 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
3912 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
3913 FLAMES_PRAGMA(INLINE off)
3914 static_assert(n_rows == rows_, "Matrix dimension should meet.");
3915 static_assert(n_cols == cols_, "Matrix dimension should meet.");
3916 static const size_t c[288] = {
3917 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,
3918 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,
3919 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,
3920 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,
3921 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,
3922 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,
3923 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,
3924 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,
3925 };
3926 static const size_t i[288] = {
3927 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,
3928 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,
3929 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,
3930 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,
3931 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,
3932 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,
3933 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,
3934 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,
3935 };
3936 static const size_t r[288] = {
3937 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,
3938 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,
3939 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,
3940 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,
3941 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,
3942 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,
3943 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,
3944 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,
3945 };
3946 MAT_LOWER_TIMES_MAT_NORMAL_OR_MAT_SYM:
3947 for (size_t n = 0; n != n_rows * n_rows * (n_rows + 1) / 2; n++) {
3949 if (i[n] == 0) (*this)(r[n], c[n]) = 0; // initialize
3950 (*this)(r[n], c[n]) += mat_L(r[n], i[n]) * mat_R(i[n], c[n]);
3951 }
3952 return *this;
3953 }
3954
3976 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
3977 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
3978 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
3979 std::enable_if_t<(type1 == MatType::SUPPER && type2 == MatType::SCALAR), bool> = true>
3980 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
3981 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
3982 static_assert(n_rows == rows_, "Matrix dimension should meet.");
3983 static_assert(n_cols == cols_, "Matrix dimension should meet.");
3984 MAT_SUPPER_TIMES_MAT_SCALAR:
3985 for (size_t i = 0; i != (n_rows - 1) * n_rows / 2; ++i) {
3987 _data[i] = mat_L[i] * mat_R[0];
3988 }
3989 return *this;
3990 }
3991
4013 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
4014 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
4015 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
4016 std::enable_if_t<(type1 == MatType::SUPPER && type2 == MatType::DIAGONAL), bool> = true>
4017 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
4018 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
4019 static_assert(n_rows == rows_, "Matrix dimension should meet.");
4020 static_assert(n_cols == cols_, "Matrix dimension should meet.");
4021 static const size_t c[28] = {
4022 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,
4023 };
4024 static const size_t i[28] = {
4025 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,
4026 };
4027 static const size_t r[28] = {
4028 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,
4029 };
4030 MAT_SUPPER_TIMES_MAT_DIAG:
4031 for (size_t n = 0; n != n_rows * (n_rows - 1) / 2; n++) {
4033 (*this)(r[n], c[n]) = mat_L(r[n], i[n]) * mat_R(i[n], c[n]);
4034 }
4035 return *this;
4036 }
4037
4059 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
4060 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
4061 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
4062 std::enable_if_t<(type1 == MatType::SUPPER && type2 == MatType::UPPER), bool> = true>
4063 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
4064 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
4065 FLAMES_PRAGMA(INLINE off)
4066 static_assert(n_rows == rows_, "Matrix dimension should meet.");
4067 static_assert(n_cols == cols_, "Matrix dimension should meet.");
4068 static const size_t r[84] = {
4069 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,
4070 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,
4071 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,
4072 };
4073 static const size_t i[84] = {
4074 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,
4075 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,
4076 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,
4077 };
4078 static const size_t c[84] = {
4079 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,
4080 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,
4081 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,
4082 };
4083 MAT_SUPPER_TIMES_MAT_UPPER:
4084 for (size_t n = 0; n != (n_rows * n_rows * n_rows - n_rows) / 6; n++) {
4086 if (i[n] == r[n] + 1) (*this)(r[n], c[n]) = 0; // initialize
4087 (*this)(r[n], c[n]) += mat_L(r[n], i[n]) * mat_R(i[n], c[n]);
4088 }
4089 return *this;
4090 }
4091
4113 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
4114 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
4115 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
4116 std::enable_if_t<(type1 == MatType::SUPPER && type2 == MatType::LOWER), bool> = true>
4117 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
4118 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
4119 FLAMES_PRAGMA(INLINE off)
4120 static_assert(n_rows == rows_, "Matrix dimension should meet.");
4121 static_assert(n_cols == cols_, "Matrix dimension should meet.");
4122 static const size_t c[168] = {
4123 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,
4124 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,
4125 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,
4126 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,
4127 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,
4128 };
4129 static const size_t i[168] = {
4130 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,
4131 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,
4132 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,
4133 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,
4134 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,
4135 };
4136 static const size_t r[168] = {
4137 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,
4138 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,
4139 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,
4140 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,
4141 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,
4142 };
4143 MAT_UPPER_TIMES_MAT_SLOWER:
4144 for (size_t n = 0; n != (n_rows * n_rows * n_rows - n_rows) / 3; n++) {
4146 if (i[n] == c[n] || i[n] == (r[n] + 1)) (*this)(r[n], c[n]) = 0; // initialize
4147 (*this)(r[n], c[n]) += mat_L(r[n], i[n]) * mat_R(i[n], c[n]);
4148 }
4149 for (size_t c = 0; c != n_cols; c++) { (*this)(n_rows - 1, c) = T(0); }
4150
4151 return *this;
4152 }
4153
4175 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
4176 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
4177 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
4178 std::enable_if_t<(type1 == MatType::SUPPER && type2 == MatType::SUPPER), bool> = true>
4179 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
4180 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
4181 FLAMES_PRAGMA(INLINE off)
4182 static_assert(n_rows == rows_, "Matrix dimension should meet.");
4183 static_assert(n_cols == cols_, "Matrix dimension should meet.");
4184 static const size_t r[56] = {
4185 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,
4186 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,
4187 };
4188 static const size_t i[56] = {
4189 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,
4190 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,
4191 };
4192 static const size_t c[56] = {
4193 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,
4194 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,
4195 };
4196 MAT_SUPPER_TIMES_MAT_SUPPER:
4197 for (size_t n = 0; n != ((n_rows - 1) * (n_rows - 1) * (n_rows - 1) - (n_rows - 1)) / 6; n++) {
4199 if (i[n] == 1 + r[n]) (*this)(r[n], c[n]) = 0; // initialize
4200 (*this)(r[n], c[n]) += mat_L(r[n], i[n]) * mat_R(i[n], c[n]);
4201 }
4202 for (size_t i = 0; i != n_rows - 1; i++) { (*this)(i, i + 1) = T(0); }
4203 return *this;
4204 }
4205
4227 template <
4228 template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
4229 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1, typename T2,
4230 MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
4231 std::enable_if_t<!(type1 == MatType::SUPPER && n_rows == 1) && !(type2 == MatType::SLOWER && cols_ == 1) &&
4232 (type1 == MatType::SUPPER && type2 == MatType::SLOWER),
4233 bool> = true>
4234 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
4235 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
4236 FLAMES_PRAGMA(INLINE off)
4237 static_assert(n_rows == rows_, "Matrix dimension should meet.");
4238 static_assert(n_cols == cols_, "Matrix dimension should meet.");
4239 static const size_t c[140] = {
4240 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,
4241 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,
4242 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,
4243 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,
4244 };
4245 static const size_t i[140] = {
4246 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,
4247 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,
4248 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,
4249 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,
4250 };
4251 static const size_t r[140] = {
4252 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,
4253 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,
4254 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,
4255 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,
4256 };
4257 MAT_SUPPER_TIMES_MAT_SLOWER:
4258 for (size_t n = 0;
4259 n != (2 * (n_rows - 1) * (n_rows - 1) * (n_rows - 1) + 3 * (n_rows - 1) * (n_rows - 1) + (n_rows - 1)) / 6;
4260 n++) {
4262 if (i[n] == r[n] + 1 || i[n] == c[n] + 1) (*this)(r[n], c[n]) = T(0); // initialize
4263 (*this)(r[n], c[n]) += mat_L(r[n], i[n]) * mat_R(i[n], c[n]);
4264 }
4265 for (size_t r = 0; r != n_rows; r++) { (*this)(r, n_cols - 1) = T(0); }
4266 for (size_t c = 0; c != n_cols - 1; c++) { (*this)(n_rows - 1, c) = T(0); }
4267
4268 return *this;
4269 }
4270
4292 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
4293 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
4294 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
4295 std::enable_if_t<(type1 == MatType::SUPPER && type2 == MatType::ASYM), bool> = true>
4296 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
4297 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
4298 FLAMES_PRAGMA(INLINE off)
4299 static_assert(n_rows == rows_, "Matrix dimension should meet.");
4300 static_assert(n_cols == cols_, "Matrix dimension should meet.");
4301 static const size_t c[224] = {
4302 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,
4303 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,
4304 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,
4305 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,
4306 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,
4307 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,
4308 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,
4309 };
4310 static const size_t i[224] = {
4311 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,
4312 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,
4313 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,
4314 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,
4315 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,
4316 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,
4317 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,
4318 };
4319 static const size_t r[224] = {
4320 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,
4321 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,
4322 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,
4323 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,
4324 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,
4325 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,
4326 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,
4327 };
4328 MAT_SUPPER_TIMES_MAT_ASYM:
4329 for (size_t n = 0; n != n_rows * n_rows * (n_rows - 1) / 2; n++) {
4331 if (i[n] == r[n] + 1) (*this)(r[n], c[n]) = T(0); // initialize
4332 if (i[n] != c[n]) (*this)(r[n], c[n]) += mat_L(r[n], i[n]) * mat_R(i[n], c[n]);
4333 }
4334 for (size_t c = 0; c != n_cols; c++) { (*this)(n_rows - 1, c) = T(0); }
4335
4336 return *this;
4337 }
4338
4360 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
4361 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
4362 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
4363 std::enable_if_t<(type1 == MatType::SUPPER && (type2 == MatType::SYM || type2 == MatType::NORMAL)),
4364 bool> = true>
4365 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
4366 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
4367 FLAMES_PRAGMA(INLINE off)
4368 static_assert(n_rows == rows_, "Matrix dimension should meet.");
4369 static_assert(n_cols == cols_, "Matrix dimension should meet.");
4370 static const size_t c[224] = {
4371 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,
4372 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,
4373 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,
4374 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,
4375 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,
4376 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,
4377 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,
4378 };
4379 static const size_t i[224] = {
4380 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,
4381 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,
4382 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,
4383 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,
4384 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,
4385 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,
4386 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,
4387 };
4388 static const size_t r[224] = {
4389 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,
4390 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,
4391 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,
4392 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,
4393 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,
4394 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,
4395 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,
4396 };
4397 MAT_SUPPER_TIMES_MAT_NORMAL_OR_SYM:
4398 for (size_t n = 0; n != n_rows * n_rows * (n_rows - 1) / 2; n++) {
4400 if (i[n] == r[n] + 1) (*this)(r[n], c[n]) = T(0); // initialize
4401 (*this)(r[n], c[n]) += mat_L(r[n], i[n]) * mat_R(i[n], c[n]);
4402 }
4403 for (size_t c = 0; c != n_cols; c++) { (*this)(n_rows - 1, c) = T(0); }
4404 return *this;
4405 }
4406
4428 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
4429 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
4430 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
4431 std::enable_if_t<(type1 == MatType::SLOWER && type2 == MatType::SCALAR), bool> = true>
4432 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
4433 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
4434 static_assert(n_rows == rows_, "Matrix dimension should meet.");
4435 static_assert(n_cols == cols_, "Matrix dimension should meet.");
4436 MAT_SLOWER_TIMES_MAT_SCALAR:
4437 for (size_t i = 0; i != (n_rows - 1) * n_rows / 2; ++i) {
4439 _data[i] = mat_L[i] * mat_R[0];
4440 }
4441 return *this;
4442 }
4443
4465 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
4466 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
4467 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
4468 std::enable_if_t<(type1 == MatType::SLOWER && type2 == MatType::DIAGONAL), bool> = true>
4469 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
4470 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
4471 static_assert(n_rows == rows_, "Matrix dimension should meet.");
4472 static_assert(n_cols == cols_, "Matrix dimension should meet.");
4473 static const size_t c[28] = {
4474 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,
4475 };
4476 static const size_t i[28] = {
4477 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,
4478 };
4479 static const size_t r[28] = {
4480 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,
4481 };
4482 MAT_SLOWER_TIMES_MAT_DIAG:
4483 for (size_t n = 0; n != n_rows * (n_rows - 1) / 2; n++) {
4485 (*this)(r[n], c[n]) = mat_L(r[n], i[n]) * mat_R(i[n], c[n]);
4486 }
4487 return *this;
4488 }
4489
4511 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
4512 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
4513 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
4514 std::enable_if_t<(type1 == MatType::SLOWER && type2 == MatType::UPPER), bool> = true>
4515 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
4516 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
4517 FLAMES_PRAGMA(INLINE off)
4518 static_assert(n_rows == rows_, "Matrix dimension should meet.");
4519 static_assert(n_cols == cols_, "Matrix dimension should meet.");
4520 static const size_t c[168] = {
4521 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,
4522 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,
4523 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,
4524 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,
4525 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,
4526 };
4527 static const size_t i[168] = {
4528 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,
4529 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,
4530 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,
4531 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,
4532 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,
4533 };
4534 static const size_t r[168] = {
4535 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,
4536 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,
4537 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,
4538 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,
4539 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,
4540 };
4541 MAT_SLOWER_TIMES_MAT_UPPER:
4542 for (size_t n = 0; n != (n_rows * n_rows * n_rows - n_rows) / 3; n++) {
4544 if (i[n] == 0) (*this)(r[n], c[n]) = 0; // initialize
4545 (*this)(r[n], c[n]) += mat_L(r[n], i[n]) * mat_R(i[n], c[n]);
4546 }
4547 for (size_t c = 0; c != n_cols; c++) { (*this)(0, c) = T(0); }
4548
4549 return *this;
4550 }
4551
4573 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
4574 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
4575 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
4576 std::enable_if_t<(type1 == MatType::SLOWER && type2 == MatType::LOWER), bool> = true>
4577 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
4578 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
4579 FLAMES_PRAGMA(INLINE off)
4580 static_assert(n_rows == rows_, "Matrix dimension should meet.");
4581 static_assert(n_cols == cols_, "Matrix dimension should meet.");
4582 static const size_t c[84] = {
4583 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,
4584 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,
4585 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,
4586 };
4587 static const size_t i[84] = {
4588 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,
4589 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,
4590 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,
4591 };
4592 static const size_t r[84] = {
4593 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,
4594 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,
4595 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,
4596 };
4597 MAT_SLOWER_TIMES_MAT_LOWER:
4598 for (size_t n = 0; n != (n_rows * n_rows * n_rows - n_rows) / 6; n++) {
4600 if (i[n] == c[n]) (*this)(r[n], c[n]) = 0; // initialize
4601 (*this)(r[n], c[n]) += mat_L(r[n], i[n]) * mat_R(i[n], c[n]);
4602 }
4603 return *this;
4604 }
4605
4627 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
4628 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
4629 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
4630 std::enable_if_t<(type1 == MatType::SLOWER && type2 == MatType::SUPPER), bool> = true>
4631 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
4632 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
4633 FLAMES_PRAGMA(INLINE off)
4634 static_assert(n_rows == rows_, "Matrix dimension should meet.");
4635 static_assert(n_cols == cols_, "Matrix dimension should meet.");
4636 static const size_t c[140] = {
4637 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,
4638 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,
4639 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,
4640 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,
4641 };
4642 static const size_t i[140] = {
4643 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,
4644 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,
4645 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,
4646 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,
4647 };
4648 static const size_t r[140] = {
4649 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,
4650 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,
4651 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,
4652 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,
4653 };
4654 MAT_SLOWER_TIMES_MAT_SUPPER:
4655 for (size_t n = 0;
4656 n != (2 * (n_rows - 1) * (n_rows - 1) * (n_rows - 1) + 3 * (n_rows - 1) * (n_rows - 1) + (n_rows - 1)) / 6;
4657 n++) {
4659 if (i[n] == 0) (*this)(r[n], c[n]) = 0; // initialize
4660 (*this)(r[n], c[n]) += mat_L(r[n], i[n]) * mat_R(i[n], c[n]);
4661 }
4662 for (size_t r = 0; r != n_rows; r++) { (*this)(r, 0) = T(0); }
4663 for (size_t c = 1; c != n_cols; c++) { (*this)(0, c) = T(0); }
4664
4665 return *this;
4666 }
4667
4690 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
4691 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
4692 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
4693 std::enable_if_t<(type1 == MatType::SLOWER && type2 == MatType::SLOWER), bool> = true>
4694 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
4695 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
4696 FLAMES_PRAGMA(INLINE off)
4697 static_assert(n_rows == rows_, "Matrix dimension should meet.");
4698 static_assert(n_cols == cols_, "Matrix dimension should meet.");
4699 static const size_t c[56] = {
4700 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,
4701 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,
4702 };
4703 static const size_t i[56] = {
4704 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,
4705 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,
4706 };
4707 static const size_t r[56] = {
4708 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,
4709 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,
4710 };
4711 MAT_SLOWER_TIMES_MAT_SLOWER:
4712 for (size_t n = 0; n != ((n_rows - 1) * (n_rows - 1) * (n_rows - 1) - (n_rows - 1)) / 6; n++) {
4714 if (i[n] == 1 + c[n]) (*this)(r[n], c[n]) = 0; // initialize
4715 (*this)(r[n], c[n]) += mat_L(r[n], i[n]) * mat_R(i[n], c[n]);
4716 }
4717 for (size_t i = 0; i != n_rows - 1; i++) { (*this)(i, i - 1) = T(0); }
4718
4719 return *this;
4720 }
4721
4743 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
4744 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
4745 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
4746 std::enable_if_t<(type1 == MatType::SLOWER && type2 == MatType::ASYM), bool> = true>
4747 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
4748 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
4749 FLAMES_PRAGMA(INLINE off)
4750 static_assert(n_rows == rows_, "Matrix dimension should meet.");
4751 static_assert(n_cols == cols_, "Matrix dimension should meet.");
4752 static const size_t c[224] = {
4753 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,
4754 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,
4755 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,
4756 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,
4757 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,
4758 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,
4759 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,
4760 };
4761 static const size_t i[224] = {
4762 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,
4763 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,
4764 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,
4765 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,
4766 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,
4767 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,
4768 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,
4769 };
4770 static const size_t r[224] = {
4771 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,
4772 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,
4773 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,
4774 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,
4775 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,
4776 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,
4777 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,
4778 };
4779 MAT_SLOWER_TIMES_MAT_ASYM:
4780 for (size_t n = 0; n != n_rows * n_rows * (n_rows - 1) / 2; n++) {
4782 if (i[n] == 0) (*this)(r[n], c[n]) = 0; // initialize
4783 if (i[n] != c[n]) (*this)(r[n], c[n]) += mat_L(r[n], i[n]) * mat_R(i[n], c[n]);
4784 }
4785 for (size_t c = 0; c != n_cols; ++c) { (*this)(0, c) = T(0); }
4786 return *this;
4787 }
4788
4810 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
4811 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
4812 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
4813 std::enable_if_t<(type1 == MatType::SLOWER && (type2 == MatType::SYM || type2 == MatType::NORMAL)),
4814 bool> = true>
4815 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
4816 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
4817 FLAMES_PRAGMA(INLINE off)
4818 static_assert(n_rows == rows_, "Matrix dimension should meet.");
4819 static_assert(n_cols == cols_, "Matrix dimension should meet.");
4820 static const size_t c[224] = {
4821 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,
4822 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,
4823 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,
4824 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,
4825 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,
4826 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,
4827 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,
4828 };
4829 static const size_t i[224] = {
4830 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,
4831 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,
4832 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,
4833 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,
4834 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,
4835 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,
4836 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,
4837 };
4838 static const size_t r[224] = {
4839 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,
4840 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,
4841 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,
4842 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,
4843 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,
4844 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,
4845 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,
4846 };
4847 MAT_SLOWER_TIMES_MAT_NORMAL_OR_MAT_SYM:
4848 for (size_t n = 0; n != n_rows * n_rows * (n_rows - 1) / 2; n++) {
4850 if (i[n] == 0) (*this)(r[n], c[n]) = 0; // initialize
4851 (*this)(r[n], c[n]) += mat_L(r[n], i[n]) * mat_R(i[n], c[n]);
4852 }
4853 for (size_t c = 0; c != n_cols; ++c) { (*this)(0, c) = T(0); }
4854 return *this;
4855 }
4856
4878 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
4879 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
4880 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
4881 std::enable_if_t<(type1 == MatType::ASYM && type2 == MatType::DIAGONAL), bool> = true>
4882 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
4883 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
4884 static_assert(n_rows == rows_, "Matrix dimension should meet.");
4885 static_assert(n_cols == cols_, "Matrix dimension should meet.");
4886 MAT_ASYM_TIMES_MAT_DIAG:
4887 for (size_t i = 0; i != n_rows; ++i) {
4889 for (size_t j = 0; j != n_rows; ++j) {
4890 FLAMES_PRAGMA(LOOP_FLATTEN)
4891 if (i != j) (*this)(i, j) = mat_L(i, j) * mat_R[j];
4892 }
4893 }
4894 for (size_t c = 0; c != n_cols; ++c) { (*this)(c, c) = T(0); }
4895 return *this;
4896 }
4897
4919 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
4920 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
4921 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
4922 std::enable_if_t<(type1 == MatType::ASYM && type2 == MatType::SCALAR), bool> = true>
4923 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
4924 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
4925 static_assert(n_rows == rows_, "Matrix dimension should meet.");
4926 static_assert(n_cols == cols_, "Matrix dimension should meet.");
4927 MAT_ASYM_TIMES_MAT_SCAL:
4928 for (size_t i = 0; i != n_rows; ++i) {
4930 for (size_t j = i + 1; j != n_rows; ++j) {
4931 FLAMES_PRAGMA(LOOP_FLATTEN)
4932 if (i != j) (*this)(i, j) = mat_L(i, j) * mat_R[0];
4933 }
4934 }
4935 return *this;
4936 }
4937
4959 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
4960 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
4961 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
4962 std::enable_if_t<(type1 == MatType::ASYM && type2 == MatType::UPPER), bool> = true>
4963 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
4964 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
4965 static_assert(n_rows == rows_, "Matrix dimension should meet.");
4966 static_assert(n_cols == cols_, "Matrix dimension should meet.");
4967 static const size_t r[288] = {
4968 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,
4969 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,
4970 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,
4971 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,
4972 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,
4973 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,
4974 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,
4975 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,
4976 };
4977 static const size_t i[288] = {
4978 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,
4979 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,
4980 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,
4981 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,
4982 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,
4983 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,
4984 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,
4985 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,
4986 };
4987 static const size_t c[288] = {
4988 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,
4989 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,
4990 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,
4991 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,
4992 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,
4993 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,
4994 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,
4995 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,
4996 };
4997 MAT_ASYM_TIMES_MAT_UPPER:
4998 for (size_t n = 0; n != n_rows * n_rows * (n_rows + 1) / 2; n++) {
5000 if (i[n] == 0) (*this)(r[n], c[n]) = 0; // initialize
5001 if (r[n] != i[n]) (*this)(r[n], c[n]) += mat_L(r[n], i[n]) * mat_R(i[n], c[n]);
5002 }
5003 return *this;
5004 }
5005
5027 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
5028 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
5029 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
5030 std::enable_if_t<(type1 == MatType::ASYM && type2 == MatType::LOWER), bool> = true>
5031 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
5032 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
5033 static_assert(n_rows == rows_, "Matrix dimension should meet.");
5034 static_assert(n_cols == cols_, "Matrix dimension should meet.");
5035 static const size_t r[288] = {
5036 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,
5037 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,
5038 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,
5039 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,
5040 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,
5041 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,
5042 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,
5043 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,
5044 };
5045 static const size_t i[288] = {
5046 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,
5047 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,
5048 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,
5049 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,
5050 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,
5051 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,
5052 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,
5053 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,
5054 };
5055 static const size_t c[288] = {
5056 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,
5057 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,
5058 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,
5059 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,
5060 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,
5061 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,
5062 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,
5063 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,
5064 };
5065 MAT_ASYM_TIMES_MAT_LOWER:
5066 for (size_t n = 0; n != n_rows * n_rows * (n_rows + 1) / 2; n++) {
5068 if (i[n] == c[n]) (*this)(r[n], c[n]) = 0; // initialize
5069 if (r[n] != i[n]) (*this)(r[n], c[n]) += mat_L(r[n], i[n]) * mat_R(i[n], c[n]);
5070 }
5071 return *this;
5072 }
5073
5095 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
5096 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
5097 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
5098 std::enable_if_t<(type1 == MatType::ASYM && type2 == MatType::SUPPER), bool> = true>
5099 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
5100 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
5101 static_assert(n_rows == rows_, "Matrix dimension should meet.");
5102 static_assert(n_cols == cols_, "Matrix dimension should meet.");
5103 static const size_t r[224] = {
5104 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,
5105 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,
5106 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,
5107 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,
5108 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,
5109 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,
5110 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,
5111 };
5112 static const size_t i[224] = {
5113 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,
5114 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,
5115 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,
5116 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,
5117 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,
5118 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,
5119 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,
5120 };
5121 static const size_t c[224] = {
5122 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,
5123 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,
5124 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,
5125 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,
5126 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,
5127 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,
5128 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,
5129 };
5130 MAT_ASYM_TIMES_SUPPER:
5131 for (size_t n = 0; n != n_rows * n_rows * (n_rows - 1) / 2; n++) {
5133 if (i[n] == 0) (*this)(r[n], c[n]) = 0; // initialize
5134 if (r[n] != i[n]) (*this)(r[n], c[n]) += mat_L(r[n], i[n]) * mat_R(i[n], c[n]);
5135 }
5136 for (size_t r = 0; r != n_rows; r++) { (*this)(r, 0) = T(0); }
5137
5138 return *this;
5139 }
5140
5162 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
5163 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
5164 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
5165 std::enable_if_t<(type1 == MatType::ASYM && type2 == MatType::SLOWER), bool> = true>
5166 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
5167 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
5168 static_assert(n_rows == rows_, "Matrix dimension should meet.");
5169 static_assert(n_cols == cols_, "Matrix dimension should meet.");
5170 static const size_t r[224] = {
5171 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,
5172 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,
5173 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,
5174 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,
5175 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,
5176 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,
5177 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,
5178 };
5179 static const size_t i[224] = {
5180 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,
5181 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,
5182 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,
5183 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,
5184 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,
5185 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,
5186 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,
5187 };
5188 static const size_t c[224] = {
5189 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,
5190 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,
5191 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,
5192 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,
5193 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,
5194 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,
5195 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,
5196 };
5197 MAT_ASYM_TIMES_SLOWER:
5198 for (size_t n = 0; n != n_rows * n_rows * (n_rows - 1) / 2; n++) {
5200 if (i[n] == c[n] + 1) (*this)(r[n], c[n]) = 0; // initialize
5201 if (r[n] != i[n]) (*this)(r[n], c[n]) += mat_L(r[n], i[n]) * mat_R(i[n], c[n]);
5202 }
5203 for (size_t r = 0; r != n_rows; r++) { (*this)(r, n_cols - 1) = T(0); }
5204
5205 return *this;
5206 }
5207
5230 template <
5231 template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
5232 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1, typename T2,
5233 MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
5234 std::enable_if_t<(type1 == MatType::ASYM && (type2 == MatType::NORMAL || type2 == MatType::SYM)), bool> = true>
5235 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
5236 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
5237 FLAMES_PRAGMA(INLINE off)
5238 static_assert(n_rows == rows_, "Matrix dimension should meet.");
5239 static_assert(n_cols == cols_, "Matrix dimension should meet.");
5240 MAT_ASYM_TIMES_MAT_NORMAL:
5241 for (size_t i = 0; i != comm; ++i) {
5242 GEMM_r:
5243 for (size_t r = 0; r != n_rows; ++r) {
5245 GEMM_c:
5246 for (size_t c = 0; c != n_cols; ++c) {
5247 FLAMES_PRAGMA(LOOP_FLATTEN)
5248 if (i == 0) (*this)(r, c) = T(0); // initialize
5249 if (r != i) (*this)(r, c) += mat_L(r, i) * mat_R(i, c);
5250 }
5251 }
5252 }
5253 return *this;
5254 }
5255
5277 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
5278 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
5279 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
5280 std::enable_if_t<(type1 == MatType::ASYM && type2 == MatType::ASYM), bool> = true>
5281 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
5282 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
5283 FLAMES_PRAGMA(INLINE off)
5284 static_assert(n_rows == rows_, "Matrix dimension should meet.");
5285 static_assert(n_cols == cols_, "Matrix dimension should meet.");
5286 MAT_ASYM_TIMES_MAT_ASYM:
5287 GEMM_r:
5288 for (size_t r = 0; r != n_rows; ++r) {
5290 GEMM_c:
5291 for (size_t c = 0; c != n_cols; ++c) {
5292 for (size_t i = 0; i != comm; ++i) {
5293 FLAMES_PRAGMA(LOOP_FLATTEN)
5294 if (i == 0) (*this)(r, c) = T(0); // initialize
5295 if (i != c && i != r) (*this)(r, c) += mat_L(r, i) * mat_R(i, c);
5296 }
5297 }
5298 }
5299 return *this;
5300 }
5301
5324 template <
5325 template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
5326 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1, typename T2,
5327 MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
5328 std::enable_if_t<(std::is_same<T1, bool>::value) && ((type1 == MatType::NORMAL && type2 == MatType::NORMAL) ||
5329 (type1 == MatType::NORMAL && type2 == MatType::SYM) ||
5330 (type1 == MatType::SYM && type2 == MatType::NORMAL) ||
5331 (type1 == MatType::SYM && type2 == MatType::SYM)),
5332 bool> = true>
5333 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
5334 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
5335 FLAMES_PRAGMA(INLINE off)
5336 static_assert(n_rows == rows_, "Matrix dimension should meet.");
5337 static_assert(n_cols == cols_, "Matrix dimension should meet.");
5338 this->setZero();
5339 for (size_t c = 0; c < n_cols; ++c) {
5340 for (size_t i = 0; i < comm; ++i) {
5342 for (size_t r = 0; r < n_rows; ++r) {
5343 FLAMES_PRAGMA(UNROLL)
5344 (*this)(r, c) += mat_L(r, i) * mat_R(i, c);
5345 }
5346 }
5347 }
5348
5349 return *this;
5350 }
5351
5374 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
5375 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
5376 typename T2, MatType type1, MatType type2, size_t rows_, size_t cols_, size_t comm,
5377 std::enable_if_t<(std::is_same<T2, bool>::value && !std::is_same<T1, bool>::value) &&
5378 ((type1 == MatType::NORMAL && type2 == MatType::NORMAL) ||
5379 (type1 == MatType::NORMAL && type2 == MatType::SYM) ||
5380 (type1 == MatType::SYM && type2 == MatType::NORMAL) ||
5381 (type1 == MatType::SYM && type2 == MatType::SYM)),
5382 bool> = true>
5383 Mat& mul(const M1<T1, rows_, comm, type1, _unused1...>& mat_L,
5384 const M2<T2, comm, cols_, type2, _unused2...>& mat_R) {
5385 FLAMES_PRAGMA(INLINE off)
5386 static_assert(n_rows == rows_, "Matrix dimension should meet.");
5387 static_assert(n_cols == cols_, "Matrix dimension should meet.");
5388 GEMM_r:
5389 for (size_t r = 0; r != n_rows; ++r) {
5391 GEMM_c:
5392 for (size_t c = 0; c != n_cols; ++c) {
5393 GEMM:
5394 for (size_t i = 0; i != comm; ++i) {
5395 FLAMES_PRAGMA(LOOP_FLATTEN)
5396 if (i == 0) (*this)(r, c) = T(0); // initialize
5397 if (mat_R(i, c) != 0) (*this)(r, c) += mat_L(r, i);
5398 }
5399 }
5400 }
5401 return *this;
5402 }
5403
5423 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
5424 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
5425 typename T2, size_t rows_, size_t cols_, MatType type1, MatType type2,
5426 std::enable_if_t<rows_ == n_rows && cols_ == n_cols && type1 == type && type2 == type, bool> = true>
5427 Mat& emul(const M1<T1, rows_, cols_, type1, _unused1...>& mat_L,
5428 const M2<T2, rows_, cols_, type2, _unused2...>& mat_R) {
5429 for (size_t i = 0; i != size(); ++i) {
5431 _data[i] = mat_L[i] * mat_R[i];
5432 }
5433 return *this;
5434 }
5435
5450 template <template <class, size_t, size_t, MatType, class...> typename M, typename... _unused, typename T2,
5451 MatType type2, size_t rows_, size_t cols_>
5453 assert(c < n_cols && "Take the specific col by index requires 'The index should be smaller than the number of "
5454 "the matrix's columns.'.");
5455 static_assert(size() == rows_, "Element number should be rows_ in Mat::col(mat, index).");
5456 for (size_t i = 0; i != size(); ++i) {
5458 _data[i] = mat(i, c);
5459 }
5460 return *this;
5461 }
5462
5463 template <template <class, size_t, size_t, MatType, class...> typename M, typename... _unused, typename T2,
5464 MatType type2, size_t rows_, size_t cols_>
5465 [[deprecated("Use .col_ to create a MatRefCol to write a column instead.")]] void
5467 assert(c < n_cols && "Take the specific col by index requires 'The index should be smaller than the number of "
5468 "the matrix's columns.'.");
5469 assert(mat.size() == n_rows && "Element number should be n_rows in Mat::col(index, mat).");
5470 for (int i = 0; i != mat.size(); ++i) {
5472 (*this)(i, c) = mat[i];
5473 }
5474 }
5475
5491 assert(c < n_cols && "Take the specific col by index requires 'The index should be smaller than the number of "
5492 "the matrix's columns.'.");
5494 for (size_t i = 0; i != n_rows; ++i) {
5496 mat(i, 0) = (*this)(i, c);
5497 }
5498 return mat;
5499 }
5500
5507 assert(index < n_cols && "Take the specific col by index requires 'The index should be smaller than the number "
5508 "of the matrix's columns.'.");
5509 return { *this, index };
5510 }
5511
5513 assert(index < n_cols && "Take the specific col by index requires 'The index should be smaller than the number "
5514 "of the matrix's columns.'.");
5515 return { *this, index };
5516 }
5517
5533 template <template <class, size_t, size_t, MatType, class...> typename M, typename... _unused, typename T2,
5534 MatType type2, size_t rows_, size_t cols_>
5536 assert(r < rows_ && "row should be smaller than rows_ of mat in Mat::row.");
5537 static_assert(size() == cols_, "The number of the Matrices' n_cols should meet.");
5538 for (size_t j = 0; j != size(); ++j) {
5540 _data[j] = mat(r, j);
5541 }
5542 return *this;
5543 }
5544
5560 assert(r < n_rows && "Take the specific row by index requires 'The index should be smaller than the number of "
5561 "the matrix's rows.'.");
5563 for (size_t j = 0; j != n_cols; ++j) {
5565 mat(0, j) = (*this)(r, j);
5566 }
5567 return mat;
5568 }
5569
5570 // /**
5571 // * @brief Take a row of a matrix by index as a read only view.
5572 // *
5573 // * @return (MatViewRow<Index, T, n_rows, n_cols, MatType::NORMAL, MType<type>>) The read only a row vector view.
5574 // */
5575 // MatViewRow<T, n_rows, n_cols, MatType::NORMAL, MType<type>> Row_() const {
5576 // static_assert(Index > int(0), "Take the specific row by index requires 'The index can't be smaller than
5577 // 0'."); static_assert(Index < n_rows, "Take the specific row by index requires 'The index should be smaller
5578 // than the "
5579 // "number of the matrix's rows.'.");
5580 // return *this;
5581 // }
5582
5599 template <template <class, size_t, size_t, MatType, class...> typename M, typename... _unused, typename T2,
5600 MatType type2, size_t rows_, size_t cols_>
5601 Mat& cols(const M<T2, rows_, cols_, type2, _unused...>& mat, size_t first_col) {
5602 assert(first_col < n_cols && "Take the successive n_cols by index requires 'The indexes should be smaller than "
5603 "the number of the matrix's columns.'.");
5604 assert(first_col > int(0) &&
5605 "Take the successive n_cols by index requires 'The indexes can't be smaller than 0'.");
5606 static_assert(n_rows == rows_, "The number of the Matrices' rows should meet.");
5607 for (size_t j = 0; j != n_cols; ++j) {
5609 for (size_t i = 0; i != n_rows; ++i) {
5610 FLAMES_PRAGMA(LOOP_FLATTEN)
5611 (*this)(i, j) = mat(i, j + first_col);
5612 }
5613 }
5614 return *this;
5615 }
5616
5636 template <size_t _cols>
5638 assert(first_col < n_cols && "Take the successive n_cols by index requires 'The indexes should be smaller than "
5639 "the number of the matrix's columns.'.");
5640 assert(first_col > int(0) &&
5641 "Take the successive n_cols by index requires 'The indexes can't be smaller than 0'.");
5642 static_assert(_cols > int(1),
5643 "Take the successive n_cols by index requires 'The total number can't be smaller than 1'.");
5644
5646 for (size_t j = 0; j != _cols; ++j) {
5648 for (size_t i = 0; i != n_rows; ++i) {
5649 FLAMES_PRAGMA(LOOP_FLATTEN)
5650 mat(i, j) = (*this)(i, j + first_col);
5651 }
5652 }
5653 return mat;
5654 }
5661 template <size_t first_col, size_t last_col>
5663 static_assert(first_col > int(0),
5664 "Take the successive cols by index requires 'The first index can't be smaller than 0'.");
5665 static_assert(
5666 first_col < last_col,
5667 "Take the successive cols by index requires 'The first index should be smaller than the last index'.");
5668 static_assert(last_col < n_cols, "Take the successive cols by index requires 'The last index should be smaller "
5669 "than the number of the matrix's cols.'.");
5670 return *this;
5671 }
5672
5689 template <template <class, size_t, size_t, MatType, class...> typename M, typename... _unused, typename T2,
5690 MatType type2, size_t rows_, size_t cols_>
5691 Mat& rows(const M<T2, rows_, cols_, type2, _unused...>& mat, size_t first_row) {
5692 assert(first_row < n_rows && "Take the successive n_rows by index requires 'The indexes should be smaller than "
5693 "the number of the matrix's rows.'.");
5694 assert(first_row > int(0) &&
5695 "Take the successive n_rows by index requires 'The indexes can't be smaller than 0'.");
5696 static_assert(n_cols == cols_, "The number of the Matrices' cols should meet.");
5697 for (size_t i = 0; i != n_rows; ++i) {
5699 for (size_t j = 0; j != n_cols; ++j) {
5700 FLAMES_PRAGMA(LOOP_FLATTEN)
5701 (*this)(i, j) = mat(i + first_row, j);
5702 }
5703 }
5704 return *this;
5705 }
5706
5727 template <size_t _rows>
5729 assert(first_row < n_rows && "Take the successive n_rows by index requires 'The indexes should be smaller than "
5730 "the number of the matrix's rows.'.");
5731 assert(first_row > int(0) &&
5732 "Take the successive n_rows by index requires 'The indexes can't be smaller than 0'.");
5733 static_assert(_rows > int(1),
5734 "Take the successive n_rows by index requires 'The total number can't be smaller than 1'.");
5735
5737 for (size_t i = 0; i != _rows; ++i) {
5739 for (size_t j = 0; j != n_cols; ++j) {
5740 FLAMES_PRAGMA(LOOP_FLATTEN)
5741 mat(i, j) = (*this)(i + first_row, j);
5742 }
5743 }
5744 return mat;
5745 }
5746
5753 template <size_t first_row, size_t last_row>
5755 static_assert(
5756 first_row < last_row,
5757 "Take the successive rows by index requires 'The first index should be smaller than the last index'.");
5758 static_assert(last_row < n_rows, "Take the successive rows by index requires 'The last index should be smaller "
5759 "than the number of the matrix's rows.'.");
5760 return *this;
5761 }
5762
5781 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1, typename M2,
5782 typename T1, MatType type1, size_t rows_, size_t cols_>
5783 Mat& rows(const M1<T1, rows_, cols_, type1, _unused1...>& mat, M2 vector) {
5784 static_assert(n_cols == cols_, "The number of the Matrices' cols should meet.");
5785 for (size_t i = 0; i != n_rows; ++i) {
5787 assert(vector[i] > int(0) &&
5788 "Take the discrete n_rows by index requires 'The indexes can't be smaller than 0'.");
5789 assert(vector[i] < n_rows && "Take the discrete n_rows by index requires 'The indexes should be smaller "
5790 "than the number of the matrix's rows.'.");
5791 for (size_t j = 0; j != n_cols; ++j) {
5792 FLAMES_PRAGMA(LOOP_FLATTEN)
5793 (*this)(i, j) = mat(vector[i], j);
5794 }
5795 }
5796 return *this;
5797 }
5798
5818 template <size_t _rows, typename M2>
5821 for (size_t i = 0; i != _rows; ++i) {
5823 assert(vector[i] >= int(0) &&
5824 "Take the discrete n_rows by index requires 'The indexes can't be smaller than 0'.");
5825 assert(vector[i] < n_rows && "Take the discrete n_rows by index requires 'The indexes should be smaller "
5826 "than the number of the matrix's rows.'.");
5827 for (size_t j = 0; j != n_cols; ++j) {
5828 FLAMES_PRAGMA(LOOP_FLATTEN)
5829 mat(i, j) = (*this)(vector[i], j);
5830 }
5831 }
5832 return mat;
5833 }
5834
5853 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1, typename M2,
5854 typename T1, MatType type1, size_t rows_, size_t cols_>
5855 Mat& cols(const M1<T1, rows_, cols_, type1, _unused1...>& mat, M2 vector) {
5856 static_assert(n_rows == rows_, "The number of the Matrices' rows should meet.");
5857 for (size_t j = 0; j != n_cols; ++j) {
5859 assert(vector[j] >= int(0) &&
5860 "Take the discrete n_cols by index requires 'The indexes can't be smaller than 0'.");
5861 assert(vector[j] < n_cols && "Take the discrete n_cols by index requires 'The indexes should be smaller "
5862 "than the number of the matrix's cols.'.");
5863 for (size_t i = 0; i != n_rows; ++i) {
5864 FLAMES_PRAGMA(LOOP_FLATTEN)
5865 (*this)(i, j) = mat(i, vector[j]);
5866 }
5867 }
5868 return *this;
5869 }
5870
5890 template <size_t _cols, typename M2>
5893 for (size_t j = 0; j != _cols; ++j) {
5895 assert(vector[j] >= int(0) &&
5896 "Take the discrete n_cols by index requires 'The indexes can't be smaller than 0'.");
5897 assert(vector[j] < n_cols && "Take the discrete n_cols by index requires 'The indexes should be smaller "
5898 "than the number of the matrix's cols.'.");
5899 for (size_t i = 0; i != n_cols; ++i) {
5900 FLAMES_PRAGMA(LOOP_FLATTEN)
5901 mat(i, j) = (*this)(i, vector[j]);
5902 }
5903 }
5904 return mat;
5905 }
5906
5914 for (size_t i = 0; i != size(); ++i) {
5916 if (_data[i] < 0) _data[i] = -_data[i];
5917 }
5918 return *this;
5919 }
5920
5935 template <template <class, size_t, size_t, MatType, class...> typename M, typename... _unused, typename T2,
5936 MatType type2>
5938 if (type == MatType::DIAGONAL || type == MatType::SCALAR || type == MatType::SYM) {
5939 // do nothing
5940 } else if (type == MatType::NORMAL) {
5941 MAT_TRANSPOSE_NORMAL:
5942 for (size_t i = 0; i != n_cols; ++i) {
5944 for (size_t j = 0; j != n_rows; ++j) {
5945 FLAMES_PRAGMA(LOOP_FLATTEN)
5946 _data[n_rows * i + j] = mat._data[n_rows * j + i];
5947 }
5948 }
5949 } else if (type == MatType::UPPER) {
5950 MAT_TRANSPOSE_UPPER:
5951 for (size_t i = 0; i != n_cols; ++i) {
5953 for (size_t j = i; j != n_rows; ++j) {
5954 FLAMES_PRAGMA(LOOP_FLATTEN)
5955 (*this)(i, j) = mat(j, i);
5956 }
5957 }
5958 } else if (type == MatType::LOWER) {
5959 MAT_TRANSPOSE_LOWER:
5960 for (size_t i = 0; i != n_cols; ++i) {
5962 for (size_t j = 0; j <= i; ++j) {
5963 FLAMES_PRAGMA(LOOP_FLATTEN)
5964 (*this)(i, j) = mat(j, i);
5965 }
5966 }
5967 } else if (type == MatType::SUPPER) {
5968 MAT_TRANSPOSE_SUPPER:
5969 for (size_t i = 0; i != n_cols; ++i) {
5971 for (size_t j = i; j != n_rows; ++j) {
5972 FLAMES_PRAGMA(LOOP_FLATTEN)
5973 (*this)(i, j) = mat(j, i);
5974 }
5975 }
5976 } else if (type == MatType::SLOWER) {
5977 MAT_TRANSPOSE_SLOWER:
5978 for (size_t i = 0; i != n_cols; ++i) {
5980 for (size_t j = i; j != n_rows; ++j) {
5981 FLAMES_PRAGMA(LOOP_FLATTEN)
5982 (*this)(i, j) = mat(j, i);
5983 }
5984 }
5985 } else if (type == MatType::ASYM) {
5986 MAT_TRANSPOSE_ASYM:
5987 for (size_t i = 0; i != n_cols; ++i) {
5989 for (size_t j = i + 1; j != n_rows; ++j) {
5990 FLAMES_PRAGMA(LOOP_FLATTEN)
5991 (*this)(i, j) = mat(j, i);
5992 }
5993 }
5994 } else {
5995 assert(!"Impossible");
5996 }
5997 return *this;
5998 }
5999
6014 template <typename... _unused, MatType _type = type,
6015 typename std::enable_if_t<_type == MatType::NORMAL, bool> = true>
6017 // Ref: https://stackoverflow.com/a/13401982/15080514
6018 static_assert(sizeof...(_unused) == 0, "Do not specify template arguments for Mat::t()!");
6019 static_assert(n_cols > 0 && n_rows > 0, "The matrix should have size when transposing.");
6021 MAT_TRANSPOSE_NORMAL:
6022 for (size_t i = 0; i != n_cols; ++i) {
6024 for (size_t j = 0; j != n_rows; ++j) {
6025 FLAMES_PRAGMA(LOOP_FLATTEN)
6026 mat(i, j) = (*this)(j, i);
6027 }
6028 }
6029 return mat;
6030 }
6031
6044 template <typename... _unused, MatType _type = type,
6045 typename std::enable_if_t<
6046 (_type == MatType::DIAGONAL || _type == MatType::SCALAR || _type == MatType::SYM), bool> = true>
6047 Mat t() const {
6048 static_assert(sizeof...(_unused) == 0, "Do not specify template arguments for Mat::t()!");
6049 return *this;
6050 }
6051
6066 template <typename... _unused, MatType _type = type,
6067 typename std::enable_if_t<_type == MatType::UPPER, bool> = true>
6069 static_assert(sizeof...(_unused) == 0, "Do not specify template arguments for Mat::t()!");
6070 static_assert(n_cols > 0 && n_rows > 0, "The matrix should have size when transposing.");
6072 MAT_TRANSPOSE_NORMAL:
6073 for (size_t i = 0; i != n_cols; ++i) {
6075 for (size_t j = 0; j != n_rows; ++j) {
6076 FLAMES_PRAGMA(LOOP_FLATTEN)
6077 mat(i, j) = (*this)(j, i);
6078 }
6079 }
6080 return mat;
6081 }
6082
6097 template <typename... _unused, MatType _type = type,
6098 typename std::enable_if_t<_type == MatType::LOWER, bool> = true>
6100 static_assert(sizeof...(_unused) == 0, "Do not specify template arguments for Mat::t()!");
6101 static_assert(n_cols > 0 && n_rows > 0, "The matrix should have size when transposing.");
6103 MAT_TRANSPOSE_LOWER:
6104 for (size_t i = 0; i != n_cols; ++i) {
6106 for (size_t j = i; j <= i; ++j) {
6107 FLAMES_PRAGMA(LOOP_FLATTEN)
6108 mat(j, i) = (*this)(i, j);
6109 }
6110 }
6111 return mat;
6112 }
6113
6128 template <typename... _unused, MatType _type = type,
6129 typename std::enable_if_t<_type == MatType::SUPPER, bool> = true>
6131 static_assert(sizeof...(_unused) == 0, "Do not specify template arguments for Mat::t()!");
6132 static_assert(n_cols > 0 && n_rows > 0, "The matrix should have size when transposing.");
6134 MAT_TRANSPOSE_SUPPER:
6135 for (size_t i = 0; i != n_cols - 1; ++i) {
6137 for (size_t j = i + 1; j != n_rows; ++j) {
6138 FLAMES_PRAGMA(LOOP_FLATTEN)
6139 mat(j, i) = (*this)(i, j);
6140 }
6141 }
6142 return mat;
6143 }
6144
6159 template <typename... _unused, MatType _type = type,
6160 typename std::enable_if_t<_type == MatType::SLOWER, bool> = true>
6162 static_assert(sizeof...(_unused) == 0, "Do not specify template arguments for Mat::t()!");
6163 static_assert(n_cols > 0 && n_rows > 0, "The matrix should have size when transposing.");
6165 MAT_TRANSPOSE_SLOWER:
6166 for (size_t i = 1; i != n_cols; ++i) {
6168 for (size_t j = i + 1; j != n_rows - 1; ++j) {
6169 FLAMES_PRAGMA(LOOP_FLATTEN)
6170 mat(j, i) = (*this)(i, j);
6171 }
6172 }
6173 return mat;
6174 }
6175
6190 template <typename... _unused, MatType _type = type, typename std::enable_if_t<_type == MatType::ASYM, bool> = true>
6191 Mat t() const {
6192 static_assert(n_cols > 0 && n_rows > 0, "The matrix should have size when transposing.");
6193 Mat mat;
6194 MAT_TRANSPOSE_ASYM:
6195 for (size_t i = 1; i != n_cols; ++i) {
6197 for (size_t j = i + 1; j != n_rows - 1; ++j) {
6198 FLAMES_PRAGMA(LOOP_FLATTEN)
6199 mat(j, i) = (*this)(i, j);
6200 }
6201 }
6202 return mat;
6203 }
6204
6210 MatViewT<T, n_cols, n_rows, tType(type)> t_() { return const_cast<T*>(_data); }
6211
6212 MatViewT<T, n_cols, n_rows, tType(type)> t_() const { return const_cast<T*>(_data); }
6213
6224 static_assert(type != MatType::UPPER, "Upper matrix cannot perform in place transpose.");
6225 static_assert(type != MatType::LOWER, "Lower matrix cannot perform in place transpose.");
6226 static_assert(type != MatType::SUPPER, "Strict upper matrix cannot perform in place transpose.");
6227 static_assert(type != MatType::SLOWER, "Strict lower matrix cannot perform in place transpose.");
6228 static_assert(n_rows == n_cols, "In-place transpose requires a square matrix.");
6229 if (type == MatType::NORMAL) {
6230 MAT_NORMAL_TRANSPOSE_SELF:
6231 for (size_t i = 0; i != n_cols; ++i) {
6233 for (size_t j = i; j != n_cols; ++j) {
6234 FLAMES_PRAGMA(LOOP_FLATTEN)
6235 std::swap(_data[n_cols * i + j], _data[n_cols * j + i]);
6236 }
6237 }
6238 } else if (type == MatType::ASYM) {
6239 MAT_AYSM_TRANSPOSE_SELF:
6240 for (size_t i = 0; i != n_cols * (n_cols - 1) / 2; ++i) {
6242 _data[i] = -_data[i];
6243 }
6244 }
6245 return *this;
6246 }
6247
6261 template <template <class, size_t, size_t, MatType, class...> typename M, typename... _unused, typename T2>
6263 MAT_OPP:
6264 for (size_t i = 0; i != size(); ++i) {
6266 _data[i] = -mat[i];
6267 }
6268 return *this;
6269 }
6270
6285 Mat opp() const {
6286 Mat mat;
6287 MAT_OPP:
6288 for (size_t i = 0; i != size(); ++i) {
6290 mat[i] = -_data[i];
6291 }
6292 return mat;
6293 }
6294
6301 FLAMES_PRAGMA(INLINE)
6302 return *this;
6303 }
6304
6315 MAT_OPP_SELF:
6316 for (size_t i = 0; i != size(); ++i) {
6318 _data[i] = -_data[i];
6319 }
6320 }
6321
6335 template <template <class, size_t, size_t, MatType, class...> typename M, typename... _unused, typename T2,
6336 MatType type2>
6338 static_assert(n_rows == n_cols, "Take the diagonal requires 'n_rows == n_cols'.");
6339 for (size_t i = 0; i != n_rows; ++i) {
6341 (*this)(i, i) = mat(i, i);
6342 }
6343 return *this;
6344 }
6345
6362 for (size_t i = 0; i != n_rows; ++i) {
6364 mat(i, i) = (*this)(i, i);
6365 }
6366 return mat;
6367 }
6368
6375 static_assert(n_rows == n_cols, "Take the diagonal requires 'n_rows == n_cols'.");
6376 return *this;
6377 }
6378
6392 template <template <class, size_t, size_t, MatType, class...> typename M, typename... _unused, typename T2,
6393 MatType type2>
6395 static_assert(n_cols == 1, "Diagonal vector has column number as 1.");
6396 for (size_t i = 0; i != n_rows; ++i) {
6398 _data[i] = mat(i, i);
6399 }
6400 return *this;
6401 }
6402
6418 static_assert(n_rows == n_cols, "Take the diagonal requires 'n_rows == n_cols'.");
6419 Vec<T, n_rows> mat;
6420 for (size_t i = 0; i != n_rows; ++i) {
6422 mat._data[i] = (*this)(i, i);
6423 }
6424 return mat;
6425 }
6426
6433 static_assert(n_rows == n_cols, "Take the diagonal requires 'n_rows == n_cols'.");
6434 return *this;
6435 }
6436
6450 template <template <class, size_t, size_t, MatType, class...> typename M, typename... _unused, typename T2,
6451 MatType type2>
6453 static_assert(n_rows == 1, "Diagonal vector has column number as 1.");
6454 for (size_t i = 0; i != n_cols; ++i) {
6456 _data[i] = mat(i, i);
6457 }
6458 return *this;
6459 }
6460
6476 static_assert(n_rows == n_cols, "Take the diagonal requires 'n_rows == n_cols'.");
6478 for (size_t i = 0; i != n_cols; ++i) {
6480 mat._data[i] = (*this)(i, i);
6481 }
6482 return mat;
6483 }
6484
6491 static_assert(n_rows == n_cols, "Take the diagonal requires 'n_rows == n_cols'.");
6492 return *this;
6493 }
6494
6508 template <template <class, size_t, size_t, MatType, class...> typename M, typename... _unused, typename T2,
6509 MatType type2>
6511 static_assert(n_rows == n_cols, "Take the off diagonal requires 'n_rows == n_cols'.");
6512 static_assert(type == MatType::NORMAL, "Take the off diagonal requires the matrix to be NORMAL.");
6513 for (size_t i = 0; i != n_rows; ++i) {
6515 for (size_t j = 0; j != n_cols; ++j) {
6516 FLAMES_PRAGMA(LOOP_FLATTEN)
6517 if (i != j) (*this)(i, j) = mat(i, j);
6518 else (*this)(i, j) = T(0);
6519 }
6520 }
6521 return *this;
6522 }
6523
6539 static_assert(n_rows == n_cols, "Take the off diagonal requires 'n_rows == n_cols'.");
6540 static_assert(type == MatType::NORMAL, "Take the off diagonal requires the matrix to be NORMAL.");
6542 for (size_t i = 0; i != n_rows; ++i) {
6544 for (size_t j = 0; j != n_cols; ++j) {
6545 FLAMES_PRAGMA(LOOP_FLATTEN)
6546 if (i != j) mat(i, j) = (*this)(i, j);
6547 else mat(i, j) = T(0);
6548 }
6549 }
6550 return mat;
6551 }
6552
6559 static_assert(n_rows == n_cols, "Take the off diagonal requires 'n_rows == n_cols'.");
6560 return *this;
6561 }
6562
6579 template <template <class, size_t, size_t, MatType, class...> typename M, typename... _unused, typename T2,
6580 MatType type2>
6582 static_assert(type == MatType::DIAGONAL, "'invDiag' is only used for diagonal matrix.");
6583 for (size_t i = 0; i != n_rows; ++i) {
6585 _data[i] = T(1.0) / mat(i, i);
6586 }
6587 return *this;
6588 }
6589
6596 Mat invDiag() const {
6597 static_assert(type == MatType::DIAGONAL, "'invDiag' is only used for diagonal matrix.");
6598 Mat mat;
6599 for (size_t i = 0; i != n_rows; ++i) {
6601 mat._data[i] = T(1.0) / _data[i];
6602 }
6603 }
6604
6616 template <template <class, size_t, size_t, MatType, class...> typename M, typename... _unused, typename T2,
6617 MatType type2>
6619 static_assert(n_rows == n_cols, "Calculate inverse needs to be a square matrix.");
6620 assert(iter >= 1 && "At least one iteration is needed.");
6621 const auto D = mat.diagMat_(); // diagonal part
6622 const auto E = mat.offDiag_(); // off-diagonal part
6624 D_inv.invDiag(D); // inverse of diagonal part
6625 // D_inv.print("D_inv:\n");
6626 // E.asMat().print("E:\n");
6627 auto D_inv_opp = -D_inv;
6628 Mat<T, n_rows, n_cols, MatType::NORMAL> product = D_inv_opp * E;
6629 Mat<T, n_rows, n_cols, MatType::NORMAL> sum_tmp = *this = product; // the first iteration
6631 MAT_INV_NSA:
6632 for (size_t i = 1; i < iter; ++i) {
6633 tmp.mul(*this, product);
6634 *this = tmp;
6635 sum_tmp += tmp;
6636 }
6637 this->mul(sum_tmp, D_inv);
6638 return *this += D_inv;
6639 }
6640
6651 Mat invNSA(size_t iter = 4) const {
6652 static_assert(n_rows == n_cols, "Calculate inverse needs to be a square matrix.");
6653 Mat mat;
6654 mat.invNSA(*this, iter);
6655 return mat;
6656 }
6657
6673 template <template <class, size_t, size_t, MatType, class...> typename M, typename... _unused, typename T2,
6674 MatType type2, typename coeff_type>
6675 Mat& invINSA(const M<T2, n_rows, n_cols, type2, _unused...>& mat, size_t iter = 3, coeff_type beta = 2) {
6676 static_assert(n_rows == n_cols, "Calculate inverse needs to be a square matrix.");
6677 assert(iter >= 1 && "At least one iteration is needed.");
6678 return *this;
6679 }
6680
6689 template <typename coeff_type>
6690 Mat invINSA(size_t iter = 3, coeff_type beta = 1.0) const {
6691 static_assert(n_rows == n_cols, "Calculate inverse needs to be a square matrix.");
6692 Mat mat;
6693 mat.invINSA(*this, iter);
6694 return mat;
6695 }
6696
6697 // Does not support complex number now.
6698 template <typename Tp = T>
6699 Tp power() const {
6700 Tp p = 0;
6701 for (size_t i = 0; i != size(); ++i) {
6703 p += static_cast<Tp>(_data[i] * _data[i]);
6704 }
6705 return p;
6706 }
6707
6713 T value() const {
6714 static_assert(n_rows == 1 && n_cols == 1, "This only applies to matrix of size 1x1.");
6715 return _data[0];
6716 }
6717
6723 T& value() {
6724 static_assert(n_rows == 1 && n_cols == 1, "This only applies to matrix of size 1x1.");
6725 return _data[0];
6726 }
6727
6734 void print(const std::string& str = "", std::ostream& os = std::cout) const {
6735#ifndef __SYNTHESIS__
6736 static_assert(n_rows > 0 && n_cols > 0, "Print requires this matrix be of valid size.");
6737 os << str << "[";
6738 for (size_t i = 0; i + 1 < n_rows; ++i) {
6739 os << "[";
6740 for (size_t j = 0; j + 1 < n_cols; ++j) os << static_cast<T>((*this)(i, j)) << ", ";
6741 os << static_cast<T>((*this)(i, n_cols - 1)) << "]," << std::endl;
6742 }
6743 os << "[";
6744 for (size_t j = 0; j + 1 < n_cols; ++j) os << static_cast<T>((*this)(n_rows - 1, j)) << ", ";
6745 os << static_cast<T>((*this)(n_rows - 1, n_cols - 1)) << "]]" << std::endl;
6746#endif
6747 }
6748
6755 FLAMES_PRAGMA(INLINE)
6756 return *this;
6757 }
6758
6766 FLAMES_PRAGMA(INLINE)
6767 return *this;
6768 }
6769
6770 // public: // original private
6771 public:
6779 T* rawDataPtr() { return _data; }
6780
6781 const T* rawDataPtr() const { return _data; }
6782
6793 inline void _tryAssign(size_t r, size_t c, T value) {
6794 FLAMES_PRAGMA(INLINE)
6795 if (type == MatType::DIAGONAL) {
6796 if (r == c) (*this)(r, c) = value;
6797 } else if (type == MatType::UPPER) {
6798 if (r <= c) (*this)(r, c) = value;
6799 } else if (type == MatType::LOWER) {
6800 if (r >= c) (*this)(r, c) = value;
6801 } else if (type == MatType::SUPPER) {
6802 if (r < c) (*this)(r, c) = value;
6803 } else if (type == MatType::SLOWER) {
6804 if (r > c) (*this)(r, c) = value;
6805 } else if (type == MatType::SYM) {
6806 if (r <= c) (*this)(r, c) = value;
6807 } else if (type == MatType::ASYM) {
6808 if (r < c) (*this)(r, c) = value;
6809 } else if (type == MatType::NORMAL) {
6810 (*this)(r, c) = value;
6811 } else {
6812 assert(!"Impossible! Unknown type!");
6813 }
6814 }
6815
6824 inline void _tryAssignOutRange(size_t r, size_t c, T value) {
6825 FLAMES_PRAGMA(INLINE)
6826 if (r >= n_rows || c >= n_cols) return;
6827 else _tryAssign(r, c, value);
6828 }
6829
6839 inline void _tryPlus(size_t r, size_t c, T value) {
6840 FLAMES_PRAGMA(INLINE)
6841 if (type == MatType::DIAGONAL) {
6842 if (r == c) (*this)(r, c) += value;
6843 } else if (type == MatType::UPPER) {
6844 if (r <= c) (*this)(r, c) += value;
6845 } else if (type == MatType::LOWER) {
6846 if (r >= c) (*this)(r, c) += value;
6847 } else if (type == MatType::SUPPER) {
6848 if (r < c) (*this)(r, c) += value;
6849 } else if (type == MatType::SLOWER) {
6850 if (r > c) (*this)(r, c) += value;
6851 } else if (type == MatType::ASYM) {
6852 if (r != c) (*this)(r, c) += value;
6853 } else if (type == MatType::SYM) {
6854 (*this)(r, c) += value;
6855 } else if (type == MatType::NORMAL) {
6856 (*this)(r, c) += value;
6857 } else {
6858 assert(!"Impossible! Unknown type!");
6859 }
6860 }
6861
6875 template <typename Tmp, typename M, typename Comm, typename Zero>
6876 inline void _sa_read_first_col_L(size_t i, Tmp& tmp_L, const M& mat_L, size_t begin_shift,
6877 Comm __attribute__((unused)) _comm_foo, Zero zero) const {
6878 FLAMES_PRAGMA(INLINE)
6879 constexpr size_t comm = Comm::value;
6880 read_first_col_L:
6881 for (size_t j = 0; j < n_rows; ++j) {
6883 tmp_L[j][0] = ((j <= i + begin_shift) && (i + begin_shift - j < comm))
6884 ? mat_L(j, comm - 1 - (i + begin_shift - j))
6885 : zero;
6886 }
6887 }
6888
6902 template <typename Tmp, typename M, typename Comm, typename Zero>
6903 inline void _sa_read_first_row_R(size_t i, Tmp& tmp_R, const M& mat_R, size_t begin_shift,
6904 Comm __attribute__((unused)) _comm_foo, Zero zero) const {
6905 FLAMES_PRAGMA(INLINE)
6906 constexpr size_t comm = Comm::value;
6907 read_first_row_R:
6908 for (size_t j = 0; j < n_cols; ++j) {
6910 tmp_R[0][j] = ((j <= i + begin_shift) && (i + begin_shift - j < comm))
6911 ? mat_R(comm - 1 - (i + begin_shift - j), j)
6912 : zero;
6913 }
6914 }
6915
6926 template <typename T1, typename T2, typename HLSVec>
6927 inline void _sa_multiply(const T1& tmp_L, const T2& tmp_R, const HLSVec& use_assign) {
6928 FLAMES_PRAGMA(INLINE)
6929 multiply:
6930 for (size_t r = 0; r != n_rows; ++r) {
6932 for (size_t c = 0; c != n_cols; ++c) {
6933 FLAMES_PRAGMA(LOOP_FLATTEN)
6934 T result = tmp_L[r][c] * tmp_R[r][c];
6935 if (use_assign[r * n_cols + c]) {
6936 _tryAssign(r, c, result);
6937 // std::cout << "assign " << r << ' ' << c << " (" << tmp_L[r][c] << "x" << tmp_R[r][c] << "=" <<
6938 // result << ")\n";
6939 } else {
6940 _tryPlus(r, c, result);
6941 // std::cout << "plus " << r << ' ' << c << " (" << tmp_L[r][c] << "x" << tmp_R[r][c] << "=" <<
6942 // result << ")\n";
6943 }
6944 }
6945 }
6946 };
6947
6966 template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
6967 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
6968 typename T2, MatType type1, MatType type2, size_t comm>
6969 Mat& _systolicArrayMul(const M1<T1, n_rows, comm, type1, _unused1...>& mat_L,
6970 const M2<T2, comm, n_cols, type2, _unused2...>& mat_R, size_t begin_shift = 0,
6971 size_t end_shift = 0) {
6972 // constexpr size_t begin_shift = BeginShift::value;
6973 // constexpr size_t end_shift = EndShift::value;
6974 T1 tmp_L[n_rows][n_cols];
6975 T2 tmp_R[n_rows][n_cols];
6976 std::vector<bool> use_assign(n_rows * n_cols, true);
6977// hls::vector<bool, n_rows * n_cols> use_assign = true;
6978#ifdef FLAMES_MAT_PARTITION_COMPLETE
6979 FLAMES_PRAGMA(ARRAY_PARTITION variable = tmp_L type = complete)
6980 FLAMES_PRAGMA(ARRAY_PARTITION variable = tmp_R type = complete)
6981#else
6982 FLAMES_PRAGMA(ARRAY_PARTITION variable = tmp_L type = block factor = FLAMES_MAT_PARTITION_FACTOR)
6983 FLAMES_PRAGMA(ARRAY_PARTITION variable = tmp_R type = block factor = FLAMES_MAT_PARTITION_FACTOR)
6984#endif
6985 auto write_L = [&](size_t i) {
6986 if (i + 1 != n_rows + comm + n_cols - 2 - begin_shift - end_shift) {
6987 write_L:
6988 for (size_t c = n_cols; c > 1; --c) {
6990 for (size_t r = 0; r < n_rows; ++r) {
6991 FLAMES_PRAGMA(LOOP_FLATTEN)
6992 if (c <= i + 2 && r + c <= i + begin_shift + 2 && r <= i) { tmp_L[r][c - 1] = tmp_L[r][c - 2]; }
6993 }
6994 }
6995 }
6996 };
6997 // systolic array passes data down (data from the right matrix)
6998 auto write_R = [&](size_t i) {
6999 if (i + 1 != n_rows + comm + n_cols - 2 - begin_shift - end_shift) {
7000 write_R:
7001 for (size_t r = n_rows; r > 1; --r) {
7003 for (size_t c = 0; c < n_cols; ++c) {
7004 FLAMES_PRAGMA(LOOP_FLATTEN)
7005 if (r <= i + 2 && c + r <= i + begin_shift + 2 && c <= i) { tmp_R[r - 1][c] = tmp_R[r - 2][c]; }
7006 }
7007 }
7008 }
7009 };
7010 // systolic array passes data right (data from the left matrix)
7011 auto set_assign_ctl = [&](size_t i) {
7012 FLAMES_PRAGMA(LATENCY max = 0)
7013 set_assign_ctl:
7014 for (size_t r = 0; r < n_rows; ++r) {
7016 size_t c = i - r; // note this is unsigned so there can be overflow
7017 if (c < n_cols) { use_assign[r * n_cols + c] = false; }
7018 }
7019 };
7020 std::integral_constant<int, comm> _comm_foo = {};
7021 SYSTOLIC_ARRAY_MAT_MUL:
7022 for (size_t i = 0; i < n_rows + comm + n_cols - 2 - begin_shift - end_shift; ++i) {
7023 FLAMES_PRAGMA(PIPELINE)
7024 // std::cout << "ITER " << i << "\n";
7025 // read
7026 _sa_read_first_col_L(i, tmp_L, mat_L, begin_shift, _comm_foo, T1(0));
7027 _sa_read_first_row_R(i, tmp_R, mat_R, begin_shift, _comm_foo, T2(0));
7028 // multiply
7029 _sa_multiply(tmp_L, tmp_R, use_assign);
7030 set_assign_ctl(i);
7031 // write
7032 write_L(i);
7033 write_R(i);
7034 }
7035 return *this;
7036 }
7037
7038 public: // original private
7047 T _data[type == MatType::NORMAL ? n_rows * n_cols
7048 : type == MatType::DIAGONAL ? n_rows
7049 : type == MatType::SCALAR ? 1
7050 : type == MatType::SUPPER ? (n_rows - 1) * n_rows / 2
7051 : type == MatType::SLOWER ? (n_rows - 1) * n_rows / 2
7052 : type == MatType::ASYM ? (n_rows - 1) * n_rows / 2
7053 : (1 + n_rows) * n_rows / 2];
7054};
7055
7056template <typename T, size_t n_rows, size_t n_cols, MatType type>
7057class MatView {
7058 public:
7064 MatView(const Mat<T, n_rows, n_cols, type>& m) : _data(m.rawDataPtr()) {}
7066
7067 MatView(const T* const ptr) : _data(ptr) {}
7068
7074 MatView(const MatView& m) : _data(m._data) {}
7075
7081 inline static constexpr size_t size() noexcept {
7082 return type == MatType::NORMAL ? n_rows * n_cols
7083 : type == MatType::DIAGONAL ? n_rows
7084 : type == MatType::SCALAR ? 1
7085 : type == MatType::SUPPER ? (n_rows - 1) * n_rows / 2
7086 : type == MatType::SLOWER ? (n_rows - 1) * n_rows / 2
7087 : type == MatType::ASYM ? (n_rows - 1) * n_rows / 2
7088 : (1 + n_rows) * n_rows / 2;
7089 }
7090
7092 for (size_t i = 0; i != size(); ++i) {
7094 _data[i] = m[i];
7095 }
7096 return *this;
7097 }
7098
7099 template <typename M>
7100 void assign(M m) {
7101 for (size_t i = 0; i != size(); ++i) {
7103 _data[i] = m[i];
7104 }
7105 }
7106
7114 T operator()(size_t r, size_t c) const {
7115 FLAMES_PRAGMA(INLINE)
7116 assert(r < n_rows && "Matrix row index should be within range");
7117 assert(c < n_cols && "Matrix col index should be within range");
7118 if (type == MatType::NORMAL) {
7119 return _data[r * n_cols + c];
7120 } else if (type == MatType::DIAGONAL) {
7121 if (r == c) return _data[r];
7122 else return T(0);
7123 } else if (type == MatType::SCALAR) {
7124 if (r == c) return _data[0];
7125 else return T(0);
7126 } else if (type == MatType::UPPER) {
7127 if (r <= c) return _data[(2 * n_cols + 1 - r) * r / 2 + c - r];
7128 else return T(0);
7129 } else if (type == MatType::LOWER) {
7130 if (r >= c) return _data[(1 + r) * r / 2 + c];
7131 else return T(0);
7132 } else if (type == MatType::SUPPER) {
7133 if (r < c) return _data[(2 * n_cols + 1 - r) * r / 2 + c - 2 * r - 1];
7134 else return T(0);
7135 } else if (type == MatType::SLOWER) {
7136 if (r >= c) return _data[(1 + r) * r / 2 + c - r];
7137 else return T(0);
7138 } else if (type == MatType::SYM) {
7139 if (r <= c) return _data[(2 * n_cols + 1 - r) * r / 2 + c - r];
7140 else return _data[(2 * n_cols + 1 - c) * c / 2 + r - c];
7141 } else if (type == MatType::ASYM) {
7142 if (r < c) return _data[(2 * n_cols + 1 - r) * r / 2 + c - r * 2 - 1];
7143 else if (r > c) return -_data[(2 * n_cols + 1 - c) * c / 2 + r - c * 2 - 1];
7144 else return T(0);
7145 } else {
7146 // Normally it is impossible to reach here.
7147 assert(!"Impossible! Unknown MatType!");
7148 return T(0);
7149 }
7150 }
7151
7158 T operator[](size_t index) const {
7159 FLAMES_PRAGMA(INLINE)
7160 assert(index < size() && "[index] should be in range in MatView");
7161 return _data[index];
7162 }
7163
7178 template <template <class, size_t, size_t, MatType, class...> typename M, typename... _unused, typename T2,
7179 MatType type2, size_t rows_, size_t cols_>
7181 assert(c < n_cols && "Take the specific col by index requires 'The index should be smaller than the number of "
7182 "the matrix's columns.'.");
7183 static_assert(size() == rows_, "Element number should be rows_ in Mat::col(mat, index).");
7184 for (size_t i = 0; i != size(); ++i) {
7186 _data[i] = mat(i, c);
7187 }
7188 return *this;
7189 }
7190
7191 template <template <class, size_t, size_t, MatType, class...> typename M, typename... _unused, typename T2,
7192 MatType type2, size_t rows_, size_t cols_>
7193 void col(size_t c, const M<T2, rows_, cols_, type2, _unused...>& mat) {
7194 assert(c < n_cols && "Take the specific col by index requires 'The index should be smaller than the number of "
7195 "the matrix's columns.'.");
7196 assert(mat.size() == n_rows && "Element number should be n_rows in Mat::col(index, mat).");
7197 for (int i = 0; i != mat.size(); ++i) {
7199 (*this)(i, c) = mat[i];
7200 }
7201 }
7202
7218 assert(c < n_cols && "Take the specific col by index requires 'The index should be smaller than the number of "
7219 "the matrix's columns.'.");
7221 for (size_t i = 0; i != n_rows; ++i) {
7223 mat(i, 0) = (*this)(i, c);
7224 }
7225 return mat;
7226 }
7227
7228 template <template <class, size_t, size_t, MatType, class...> typename M, typename... _unused, typename T2,
7229 MatType type2>
7231 FLAMES_PRAGMA(INLINE)
7232 // return this->sub(*this, mat_R);
7233 for (size_t i = 0; i != size(); ++i) {
7235 _data[i] += mat_R[i];
7236 }
7237 return *this;
7238 }
7239
7240 template <template <class, size_t, size_t, MatType, class...> typename M, typename... _unused, typename T2,
7241 MatType type2>
7243 FLAMES_PRAGMA(INLINE)
7244 // return this->sub(*this, mat_R);
7245 for (size_t i = 0; i != size(); ++i) {
7247 _data[i] -= mat_R[i];
7248 }
7249 return *this;
7250 }
7251
7253
7254 template <typename Tp = T>
7255 Tp power() const {
7256 Tp p = 0;
7257 for (size_t i = 0; i != size(); ++i) {
7259 p += static_cast<Tp>(_data[i] * _data[i]);
7260 }
7261 return p;
7262 }
7263
7264 template <typename Tp = T>
7265 Tp abssum() const {
7266 Tp p = 0;
7267 for (size_t i = 0; i != size(); ++i) {
7269 auto d = _data[i];
7270 if (d > 0) p += static_cast<Tp>(d);
7271 }
7272 return p;
7273 }
7274
7281 FLAMES_PRAGMA(INLINE);
7282 return Mat<T, n_rows, n_cols, type>(const_cast<const T*>(_data), InitAfterwards::NONE);
7283 }
7284
7291 FLAMES_PRAGMA(INLINE);
7292 return static_cast<Mat<T, n_rows, n_cols, type>>(*this);
7293 }
7294
7295 void print(const std::string& str = "", std::ostream& os = std::cout) const { this->asMat().print(str, os); }
7296
7297 // public: // original private
7298 public:
7299 const T* const _data;
7300};
7301
7302template <typename T, size_t n_rows, size_t n_cols, MatType type>
7303class MatRef {
7304 public:
7311
7312 MatRef(const T* const ptr) : _data(ptr) {}
7313
7319 MatRef(const MatRef& m) : _data(m._data) {}
7320
7326 inline static constexpr size_t size() noexcept {
7327 return type == MatType::NORMAL ? n_rows * n_cols
7328 : type == MatType::DIAGONAL ? n_rows
7329 : type == MatType::SCALAR ? 1
7330 : type == MatType::SUPPER ? (n_rows - 1) * n_rows / 2
7331 : type == MatType::SLOWER ? (n_rows - 1) * n_rows / 2
7332 : type == MatType::ASYM ? (n_rows - 1) * n_rows / 2
7333 : (1 + n_rows) * n_rows / 2;
7334 }
7335
7337 for (size_t i = 0; i != size(); ++i) {
7339 _data[i] = m[i];
7340 }
7341 return *this;
7342 }
7343
7344 template <typename M>
7345 void assign(M m) {
7346 for (size_t i = 0; i != size(); ++i) {
7348 _data[i] = m[i];
7349 }
7350 }
7351
7359 T operator()(size_t r, size_t c) const {
7360 FLAMES_PRAGMA(INLINE)
7361 assert(r < n_rows && "Matrix row index should be within range");
7362 assert(c < n_cols && "Matrix col index should be within range");
7363 if (type == MatType::NORMAL) {
7364 return _data[r * n_cols + c];
7365 } else if (type == MatType::DIAGONAL) {
7366 if (r == c) return _data[r];
7367 else return T(0);
7368 } else if (type == MatType::SCALAR) {
7369 if (r == c) return _data[0];
7370 else return T(0);
7371 } else if (type == MatType::UPPER) {
7372 if (r <= c) return _data[(2 * n_cols + 1 - r) * r / 2 + c - r];
7373 else return T(0);
7374 } else if (type == MatType::LOWER) {
7375 if (r >= c) return _data[(1 + r) * r / 2 + c];
7376 else return T(0);
7377 } else if (type == MatType::SUPPER) {
7378 if (r < c) return _data[(2 * n_cols + 1 - r) * r / 2 + c - 2 * r - 1];
7379 else return T(0);
7380 } else if (type == MatType::SLOWER) {
7381 if (r >= c) return _data[(1 + r) * r / 2 + c - r];
7382 else return T(0);
7383 } else if (type == MatType::SYM) {
7384 if (r <= c) return _data[(2 * n_cols + 1 - r) * r / 2 + c - r];
7385 else return _data[(2 * n_cols + 1 - c) * c / 2 + r - c];
7386 } else if (type == MatType::ASYM) {
7387 if (r < c) return _data[(2 * n_cols + 1 - r) * r / 2 + c - r * 2 - 1];
7388 else if (r > c) return -_data[(2 * n_cols + 1 - c) * c / 2 + r - c * 2 - 1];
7389 else return T(0);
7390 } else {
7391 // Normally it is impossible to reach here.
7392 assert(!"Impossible! Unknown MatType!");
7393 return T(0);
7394 }
7395 }
7396
7404 T& operator()(size_t r, size_t c) {
7405 FLAMES_PRAGMA(INLINE)
7406 assert(r < n_rows && "Matrix row index should be within range");
7407 assert(c < n_cols && "Matrix col index should be within range");
7408 if (type == MatType::NORMAL) {
7409 return _data[r * n_cols + c];
7410 } else if (type == MatType::DIAGONAL) {
7411 if (r == c) return _data[r];
7412 else assert(!"This element cannot be modified (DIAGONAL).");
7413 } else if (type == MatType::SCALAR) {
7414 assert(!"This element cannot be modified (SCALAR).");
7415 } else if (type == MatType::UPPER) {
7416 if (r <= c) return _data[(2 * n_cols + 1 - r) * r / 2 + c - r];
7417 else assert(!"This element cannot be modified (UPPER).");
7418 } else if (type == MatType::LOWER) {
7419 if (r >= c) return _data[(1 + r) * r / 2 + c];
7420 else assert(!"This element cannot be modified (LOWER).");
7421 } else if (type == MatType::SUPPER) {
7422 if (r < c) return _data[(2 * n_cols + 1 - r) * r / 2 + c - 1 - 2 * r];
7423 else assert(!"This element cannot be modified (SUPPER).");
7424 } else if (type == MatType::SLOWER) {
7425 if (r > c) return _data[(1 + r) * r / 2 + c - r];
7426 else assert(!"This element cannot be modified (SLOWER).");
7427 } else if (type == MatType::SYM) {
7428 if (r <= c) return _data[(2 * n_cols + 1 - r) * r / 2 + c - r];
7429 else return _data[(2 * n_cols + 1 - c) * c / 2 + r - c];
7430 } else if (type == MatType::ASYM) {
7431 if (r < c) return _data[(2 * n_cols + 1 - r) * r / 2 + c - 1 - 2 * r];
7432 else if (r > c) return _data[(2 * n_cols + 1 - c) * c / 2 + r - 1 - 2 * c];
7433
7434 // ATTENTION This part needs to be perfected , missing a minus sign.
7435 // Because a minus sign will result in a error about reference.
7436
7437 else assert(!"This element cannot be modified (ASYM).");
7438 } else {
7439 // Normally it is impossible to reach here.
7440 assert(!"Impossible! Unknown MatType!");
7441 }
7442 // Just to make the compiler happy.
7443 return _data[0];
7444 }
7445
7452 T operator[](size_t index) const {
7453 FLAMES_PRAGMA(INLINE)
7454 assert(index < size() && "[index] should be in range in MatView");
7455 return _data[index];
7456 }
7457
7464 T& operator[](size_t index) {
7465 FLAMES_PRAGMA(INLINE)
7466 assert(index < size() && "[index] should be in range in MatView");
7467 return _data[index];
7468 }
7469
7475 void setValue(T val) {
7476 for (size_t i = 0; i != size(); ++i) {
7478 _data[i] = val;
7479 }
7480 }
7481
7486 void setZero() { setValue(static_cast<T>(0)); }
7487
7502 template <template <class, size_t, size_t, MatType, class...> typename M, typename... _unused, typename T2,
7503 MatType type2, size_t rows_, size_t cols_>
7505 assert(c < n_cols && "Take the specific col by index requires 'The index should be smaller than the number of "
7506 "the matrix's columns.'.");
7507 static_assert(size() == rows_, "Element number should be rows_ in Mat::col(mat, index).");
7508 for (size_t i = 0; i != size(); ++i) {
7510 _data[i] = mat(i, c);
7511 }
7512 return *this;
7513 }
7514
7515 template <template <class, size_t, size_t, MatType, class...> typename M, typename... _unused, typename T2,
7516 MatType type2, size_t rows_, size_t cols_>
7517 void col(size_t c, const M<T2, rows_, cols_, type2, _unused...>& mat) {
7518 assert(c < n_cols && "Take the specific col by index requires 'The index should be smaller than the number of "
7519 "the matrix's columns.'.");
7520 assert(mat.size() == n_rows && "Element number should be n_rows in Mat::col(index, mat).");
7521 for (int i = 0; i != mat.size(); ++i) {
7523 (*this)(i, c) = mat[i];
7524 }
7525 }
7526
7542 assert(c < n_cols && "Take the specific col by index requires 'The index should be smaller than the number of "
7543 "the matrix's columns.'.");
7545 for (size_t i = 0; i != n_rows; ++i) {
7547 mat(i, 0) = (*this)(i, c);
7548 }
7549 return mat;
7550 }
7551
7552 template <template <class, size_t, size_t, MatType, class...> typename M, typename... _unused, typename T2,
7553 MatType type2>
7555 FLAMES_PRAGMA(INLINE)
7556 // return this->sub(*this, mat_R);
7557 for (size_t i = 0; i != size(); ++i) {
7559 _data[i] += mat_R[i];
7560 }
7561 return *this;
7562 }
7563
7564 template <template <class, size_t, size_t, MatType, class...> typename M, typename... _unused, typename T2,
7565 MatType type2>
7567 FLAMES_PRAGMA(INLINE)
7568 // return this->sub(*this, mat_R);
7569 for (size_t i = 0; i != size(); ++i) {
7571 _data[i] -= mat_R[i];
7572 }
7573 return *this;
7574 }
7575
7577
7578 template <typename Tp = T>
7579 Tp power() const {
7580 Tp p = 0;
7581 for (size_t i = 0; i != size(); ++i) {
7583 p += static_cast<Tp>(_data[i] * _data[i]);
7584 }
7585 return p;
7586 }
7587
7588 template <typename Tp = T>
7589 Tp abssum() const {
7590 Tp p = 0;
7591 for (size_t i = 0; i != size(); ++i) {
7593 auto d = _data[i];
7594 if (d > 0) p += static_cast<Tp>(d);
7595 }
7596 return p;
7597 }
7598
7605 FLAMES_PRAGMA(INLINE);
7606 return Mat<T, n_rows, n_cols, type>(const_cast<const T*>(_data), InitAfterwards::NONE);
7607 }
7608
7615 FLAMES_PRAGMA(INLINE);
7616 return static_cast<Mat<T, n_rows, n_cols, type>>(*this);
7617 }
7618
7619 void print(const std::string& str = "", std::ostream& os = std::cout) const { this->asMat().print(str, os); }
7620
7621 // public: // original private
7622 public:
7623 T* const _data;
7624};
7625
7626template <typename T, size_t n_rows, size_t n_cols, MatType type>
7628 public:
7634 MatViewOpp(const Mat<T, n_cols, n_rows, type>& m) : _data(m.rawDataPtr()) {}
7635
7642
7648 inline static constexpr size_t size() noexcept {
7649 return type == MatType::NORMAL ? n_rows * n_cols
7650 : type == MatType::DIAGONAL ? n_rows
7651 : type == MatType::SCALAR ? 1
7652 : type == MatType::SUPPER ? (n_rows - 1) * n_rows / 2
7653 : type == MatType::SLOWER ? (n_rows - 1) * n_rows / 2
7654 : type == MatType::ASYM ? (n_rows - 1) * n_rows / 2
7655 : (1 + n_rows) * n_rows / 2;
7656 }
7657
7665 T operator()(size_t r, size_t c) const {
7666 FLAMES_PRAGMA(INLINE)
7667 assert(r < n_rows && "Matrix row index should be within range");
7668 assert(c < n_cols && "Matrix col index should be within range");
7669 if (type == MatType::NORMAL) {
7670 return -_data[r * n_cols + c];
7671 } else if (type == MatType::DIAGONAL) {
7672 if (r == c) return -_data[r];
7673 else return T(0);
7674 } else if (type == MatType::SCALAR) {
7675 if (r == c) return -_data[0];
7676 else return T(0);
7677 } else if (type == MatType::UPPER) {
7678 if (r <= c) return -_data[(2 * n_cols + 1 - r) * r / 2 + c - r];
7679 else return T(0);
7680 } else if (type == MatType::LOWER) {
7681 if (r >= c) return -_data[(1 + r) * r / 2 + c];
7682 else return T(0);
7683 } else if (type == MatType::SUPPER) {
7684 if (r < c) return -_data[(2 * n_cols + 1 - r) * r / 2 + c - 2 * r - 1];
7685 else return T(0);
7686 } else if (type == MatType::SLOWER) {
7687 if (r >= c) return -_data[(1 + r) * r / 2 + c - r];
7688 else return T(0);
7689 } else if (type == MatType::SYM) {
7690 if (r <= c) return -_data[(2 * n_cols + 1 - r) * r / 2 + c - r];
7691 else return -_data[(2 * n_cols + 1 - c) * c / 2 + r - c];
7692 } else if (type == MatType::ASYM) {
7693 if (r < c) return -_data[(2 * n_cols + 1 - r) * r / 2 + c - r * 2 - 1];
7694 else if (r > c) return _data[(2 * n_cols + 1 - c) * c / 2 + r - c * 2 - 1];
7695 else return T(0);
7696 } else {
7697 // Normally it is impossible to reach here.
7698 assert(!"Impossible! Unknown MatType!");
7699 }
7700 }
7701
7708 T operator[](size_t index) const {
7709 FLAMES_PRAGMA(INLINE)
7710 assert(index < size() && "[index] should be in range in MatViewOpp");
7711 return -_data[index];
7712 }
7713
7723
7730 FLAMES_PRAGMA(INLINE);
7731 return static_cast<Mat<T, n_rows, n_cols, type>>(*this);
7732 }
7733
7734 public: // original private
7735 const T* _data;
7736};
7737
7738template <typename T, size_t n_rows, size_t n_cols, MatType type>
7740 public:
7746 MatViewT(const Mat<T, n_cols, n_rows, tType(type)>& m) : _data(m.rawDataPtr()) {}
7747 MatViewT(Mat<T, n_cols, n_rows, tType(type)>& m) : _data(m.rawDataPtr()) {}
7748
7754 MatViewT(const MatViewT& m) : _data(m._data) {}
7755
7756 // MatViewT(T* const ptr) : _data(ptr) {}
7757
7758 MatViewT(T* ptr) : _data(ptr) {}
7759
7765 inline static constexpr size_t size() noexcept {
7766 return type == MatType::NORMAL ? n_rows * n_cols
7767 : type == MatType::DIAGONAL ? n_rows
7768 : type == MatType::SCALAR ? 1
7769 : type == MatType::SUPPER ? (n_rows - 1) * n_rows / 2
7770 : type == MatType::SLOWER ? (n_rows - 1) * n_rows / 2
7771 : type == MatType::ASYM ? (n_rows - 1) * n_rows / 2
7772 : (1 + n_rows) * n_rows / 2;
7773 }
7774
7782 T operator()(size_t r, size_t c) const {
7783 FLAMES_PRAGMA(INLINE)
7784 assert(r < n_rows && "Matrix row index should be within range");
7785 assert(c < n_cols && "Matrix col index should be within range");
7786 if (type == MatType::NORMAL) {
7787 return _data[c * n_rows + r];
7788 } else if (type == MatType::DIAGONAL) {
7789 if (r == c) return _data[r];
7790 else return T(0);
7791 } else if (type == MatType::SCALAR) {
7792 if (r == c) return _data[0];
7793 else return T(0);
7794 } else if (type == MatType::UPPER) {
7795 if (r <= c) return _data[(2 * n_cols + 1 - c) * c / 2 + r - c];
7796 else return T(0);
7797 } else if (type == MatType::LOWER) {
7798 if (r >= c) return _data[(1 + c) * c / 2 + r];
7799 else return T(0);
7800 } else if (type == MatType::SUPPER) {
7801 if (r < c) return _data[(2 * n_cols + 1 - c) * c / 2 + r - 2 * c - 1];
7802 else return T(0);
7803 } else if (type == MatType::SLOWER) {
7804 if (r >= c) return _data[(1 + c) * c / 2 + r - c];
7805 else return T(0);
7806 } else if (type == MatType::SYM) {
7807 if (r <= c) return _data[(2 * n_cols + 1 - c) * c / 2 + r - c];
7808 else return _data[(2 * n_cols + 1 - r) * r / 2 + c - r];
7809 } else if (type == MatType::ASYM) {
7810 if (r < c) return -_data[(2 * n_cols + 1 - r) * r / 2 + c - r * 2 - 1];
7811 else if (r > c) return _data[(2 * n_cols + 1 - c) * c / 2 + r - c * 2 - 1];
7812 else return T(0);
7813 } else {
7814 // Normally it is impossible to reach here.
7815 assert(!"Impossible! Unknown MatType!");
7816 }
7817 }
7818
7825 T operator[](size_t index) const {
7826 FLAMES_PRAGMA(INLINE)
7827 size_t r, c; // of the original matrix
7828 if (type == MatType::DIAGONAL) {
7829 r = c = index;
7830 } else if (type == MatType::SCALAR) {
7831 r = c = index;
7832 } else if (type == MatType::NORMAL) {
7833 r = index / n_cols;
7834 c = index % n_cols;
7835 } else if (type == MatType::UPPER) {
7836 r = upperRow(index, n_cols);
7837 c = r + index - (2 * n_cols + 1 - r) * r / 2;
7838 } else if (type == MatType::LOWER) {
7839 r = lowerRow(index, n_cols);
7840 c = index - (r + 1) * r / 2;
7841 } else if (type == MatType::SUPPER) {
7842 r = supperRow(index, n_cols);
7843 c = 2 * r + 1 + index - c - (2 * n_cols + 1 - r) * r / 2;
7844 } else if (type == MatType::SLOWER) {
7845 r = slowerRow(index, n_cols);
7846 c = index - (1 + r) * r / 2 + r;
7847 } else if (type == MatType::SYM) {
7848 r = upperRow(index, n_cols);
7849 c = r + index - (2 * n_cols + 1 - r) * r / 2;
7850 } else if (type == MatType::ASYM) {
7851 r = supperRow(index, n_cols);
7852 c = 2 * r + 1 + index - c - (2 * n_cols + 1 - r) * r / 2;
7853 }
7854 return (*this)(r, c);
7855 }
7856
7863 FLAMES_PRAGMA(INLINE);
7864 return Mat<T, n_rows, n_cols, type>(const_cast<const T*>(_data), InitAfterwards::TR);
7865 }
7866
7873 FLAMES_PRAGMA(INLINE);
7874 return static_cast<Mat<T, n_rows, n_cols, type>>(*this);
7875 }
7876
7877 // public: // original private
7878 public:
7884 T* const _data;
7885};
7886
7887template <typename T, size_t N, size_t N_, MatType type, typename type_parent>
7889 public:
7895 MatViewDiagMat(const Mat<T, N, N, matType<type_parent>()>& m) : _data(m.rawDataPtr()) {
7896 static_assert(type == MatType::DIAGONAL && N == N_, "DiagMat is and comes from a square matrix.");
7897 }
7898
7905
7913 MATVIEWDIAGMAT_INV:
7914 for (size_t i = 0; i != N; ++i) {
7916 mat[i] = static_cast<T>(1) / (*this)[i];
7917 }
7918 return mat;
7919 }
7920
7926 inline static constexpr size_t size() noexcept {
7927 return type == MatType::NORMAL ? N * N
7928 : type == MatType::DIAGONAL ? N
7929 : type == MatType::SCALAR ? 1
7930 : type == MatType::SUPPER ? (N - 1) * N / 2
7931 : type == MatType::SLOWER ? (N - 1) * N / 2
7932 : type == MatType::ASYM ? (N - 1) * N / 2
7933 : (1 + N) * N / 2;
7934 }
7935
7941 inline static constexpr MatType pType() noexcept { return matType<type_parent>(); }
7942
7950 T operator()(size_t r, size_t c) const {
7951 if (r != c) return T(0);
7952 constexpr MatType p_type = pType();
7953 if (p_type == MatType::NORMAL) {
7954 return _data[r * N + c];
7955 } else if (p_type == MatType::DIAGONAL) {
7956 return _data[r];
7957 } else if (p_type == MatType::SCALAR) {
7958 return _data[0];
7959 } else if (p_type == MatType::UPPER) {
7960 return _data[(2 * N + 1 - r) * r / 2];
7961 } else if (p_type == MatType::LOWER) {
7962 return _data[(1 + r) * r / 2 + r];
7963 } else if (p_type == MatType::SUPPER) {
7964 return T(0);
7965 } else if (p_type == MatType::SLOWER) {
7966 return T(0);
7967 } else if (p_type == MatType::SYM) {
7968 return _data[(2 * N + 1 - r) * r / 2];
7969 } else if (p_type == MatType::ASYM) {
7970 return T(0);
7971 } else {
7972 // Normally it is impossible to reach here.
7973 assert(!"Impossible! Unknown MatType!");
7974 }
7975 }
7976
7983 T operator[](size_t index) const { return (*this)(index, index); }
7984
7991 if (pType() == MatType::DIAGONAL) {
7992 return this->_data;
7993 } else {
7995 MAT_COPY_DIAG:
7996 for (size_t i = 0; i != N; ++i) {
7998 mat[i] = (*this)[i];
7999 }
8000 return mat;
8001 }
8002 }
8003
8010 FLAMES_PRAGMA(INLINE);
8011 return static_cast<Mat<T, N, N, MatType::DIAGONAL>>(*this);
8012 }
8013
8014 public: // original private
8020 const T* _data;
8021};
8022
8023template <typename T, size_t N, size_t n_cols, MatType type, typename type_parent>
8025 public:
8031 MatViewDiagVec(const Mat<T, N, N, matType<type_parent>()>& m) : _data(m.rawDataPtr()) {
8032 static_assert(n_cols == 1, "DiagVec is a column vector.");
8033 }
8034
8041
8047 inline static constexpr size_t size() noexcept {
8048 return type == MatType::NORMAL ? N * N
8049 : type == MatType::DIAGONAL ? N
8050 : type == MatType::SCALAR ? 1
8051 : type == MatType::SUPPER ? (N - 1) * N / 2
8052 : type == MatType::SLOWER ? (N - 1) * N / 2
8053 : type == MatType::ASYM ? (N - 1) * N / 2
8054 : (1 + N) * N / 2;
8055 }
8056
8062 Vec<T, N> inv() const {
8063 Vec<T, N> mat;
8064 MATVIEWDIAGVEC_INV:
8065 for (size_t i = 0; i != N; ++i) {
8067 mat[i] = static_cast<T>(1) / (*this)[i];
8068 }
8069 return mat;
8070 }
8071
8077 inline static constexpr MatType pType() noexcept { return matType<type_parent>(); }
8078
8086 T operator()(size_t r, size_t c) const {
8087 assert(c == 0 && "Column vector's column index should always be 0.");
8088 constexpr MatType p_type = pType();
8089 if (p_type == MatType::NORMAL) {
8090 return _data[r * N + r];
8091 } else if (p_type == MatType::DIAGONAL) {
8092 return _data[r];
8093 } else if (p_type == MatType::SCALAR) {
8094 return _data[0];
8095 } else if (p_type == MatType::UPPER) {
8096 return _data[(2 * N + 1 - r) * r / 2];
8097 } else if (p_type == MatType::LOWER) {
8098 return _data[(1 + r) * r / 2 + r];
8099 } else if (p_type == MatType::SUPPER) {
8100 return T(0);
8101 } else if (p_type == MatType::SLOWER) {
8102 return T(0);
8103 } else if (p_type == MatType::SYM) {
8104 return _data[(2 * N + 1 - r) * r / 2];
8105 } else if (p_type == MatType::ASYM) {
8106 return T(0);
8107 } else {
8108 // Normally it is impossible to reach here.
8109 assert(!"Impossible! Unknown MatType!");
8110 }
8111 }
8112
8119 T operator[](size_t index) const { return (*this)(index, 0); }
8120
8126 operator Vec<T, N>() const {
8127 Vec<T, N> mat;
8128 MAT_COPY_DIAG:
8129 for (size_t i = 0; i != N; ++i) {
8131 mat[i] = (*this)[i];
8132 }
8133 return mat;
8134 }
8135
8142 FLAMES_PRAGMA(INLINE);
8143 return static_cast<Vec<T, N>>(*this);
8144 }
8145
8152 FLAMES_PRAGMA(INLINE);
8153 return static_cast<Vec<T, N>>(*this);
8154 }
8155
8156 public: // original private
8162 const T* _data;
8163};
8164
8165template <typename T, size_t n_rows, size_t N, MatType type, typename type_parent>
8167 public:
8173 MatViewDiagRowVec(const Mat<T, N, N, matType<type_parent>()>& m) : _data(m.rawDataPtr()) {
8174 static_assert(n_rows == 1, "DiagRowVec is a row vector.");
8175 }
8176
8183
8189 inline static constexpr size_t size() noexcept {
8190 return type == MatType::NORMAL ? N * N
8191 : type == MatType::DIAGONAL ? N
8192 : type == MatType::SCALAR ? 1
8193 : type == MatType::SUPPER ? (N - 1) * N / 2
8194 : type == MatType::SLOWER ? (N - 1) * N / 2
8195 : type == MatType::ASYM ? (N - 1) * N / 2
8196 : (1 + N) * N / 2;
8197 }
8198
8204 inline static constexpr MatType pType() noexcept { return matType<type_parent>(); }
8205
8213 T operator()(size_t r, size_t c) const {
8214 assert(r == 0 && "Row vector's row index should always be 0.");
8215 constexpr MatType p_type = pType();
8216 if (p_type == MatType::NORMAL) {
8217 return _data[c * N + c];
8218 } else if (p_type == MatType::DIAGONAL) {
8219 return _data[c];
8220 } else if (p_type == MatType::SCALAR) {
8221 return _data[0];
8222 } else if (p_type == MatType::UPPER) {
8223 return _data[(2 * N + 1 - c) * c / 2];
8224 } else if (p_type == MatType::LOWER) {
8225 return _data[(1 + c) * c / 2 + c];
8226 } else if (p_type == MatType::SUPPER) {
8227 return T(0);
8228 } else if (p_type == MatType::SLOWER) {
8229 return T(0);
8230 } else if (p_type == MatType::SYM) {
8231 return _data[(2 * N + 1 - c) * c / 2];
8232 } else if (p_type == MatType::ASYM) {
8233 return T(0);
8234 } else {
8235 // Normally it is impossible to reach here.
8236 assert(!"Impossible! Unknown MatType!");
8237 }
8238 }
8239
8246 T operator[](size_t index) const { return (*this)(0, index); }
8247
8253 operator RowVec<T, N>() const {
8254 RowVec<T, N> mat;
8255 MAT_COPY_DIAG:
8256 for (size_t i = 0; i != N; ++i) {
8258 mat[i] = (*this)[i];
8259 }
8260 return mat;
8261 }
8262
8269 FLAMES_PRAGMA(INLINE);
8270 return static_cast<RowVec<T, N>>(*this);
8271 }
8272
8279 FLAMES_PRAGMA(INLINE);
8280 return static_cast<RowVec<T, N>>(*this);
8281 }
8282
8283 public: // original private
8289 const T* _data;
8290};
8291
8292template <typename T, size_t N, size_t N_, MatType type, typename type_parent>
8294 public:
8300 MatViewOffDiag(const Mat<T, N, N, matType<type_parent>()>& m) : _data(m.rawDataPtr()) {
8301 static_assert(type == MatType::NORMAL && N == N_, "OffDiag is and comes from a square and normal matrix.");
8302 }
8303
8310
8316 inline static constexpr size_t size() noexcept {
8317 return type == MatType::NORMAL ? N * N
8318 : type == MatType::DIAGONAL ? N
8319 : type == MatType::SCALAR ? 1
8320 : type == MatType::SUPPER ? (N - 1) * N / 2
8321 : type == MatType::SLOWER ? (N - 1) * N / 2
8322 : type == MatType::ASYM ? (N - 1) * N / 2
8323 : (1 + N) * N / 2;
8324 }
8325
8331 inline static constexpr MatType pType() noexcept { return matType<type_parent>(); }
8332
8340 T operator()(size_t r, size_t c) const {
8341 if (r == c) return T(0);
8342 constexpr MatType p_type = pType();
8343 if (type == MatType::NORMAL) {
8344 return _data[r * N + c];
8345 } else if (type == MatType::DIAGONAL) {
8346 if (r == c) return _data[r];
8347 else return T(0);
8348 } else if (type == MatType::SCALAR) {
8349 if (r == c) return _data[0];
8350 else return T(0);
8351 } else if (type == MatType::UPPER) {
8352 if (r <= c) return _data[(2 * N + 1 - r) * r / 2 + c - r];
8353 else return T(0);
8354 } else if (type == MatType::LOWER) {
8355 if (r >= c) return _data[(1 + r) * r / 2 + c];
8356 else return T(0);
8357 } else if (type == MatType::SUPPER) {
8358 if (r < c) return _data[(2 * N + 1 - r) * r / 2 + c - 2 * r - 1];
8359 else return T(0);
8360 } else if (type == MatType::SLOWER) {
8361 if (r >= c) return _data[(1 + r) * r / 2 + c - r];
8362 else return T(0);
8363 } else if (type == MatType::SYM) {
8364 if (r <= c) return _data[(2 * N + 1 - r) * r / 2 + c - r];
8365 else return _data[(2 * N + 1 - c) * c / 2 + r - c];
8366 } else if (type == MatType::ASYM) {
8367 if (r < c) return _data[(2 * N + 1 - r) * r / 2 + c - r * 2 - 1];
8368 else if (r > c) return -_data[(2 * N + 1 - c) * c / 2 + r - c * 2 - 1];
8369 else return T(0);
8370 } else {
8371 // Normally it is impossible to reach here.
8372 assert(!"Impossible! Unknown MatType!");
8373 return T(0);
8374 }
8375 }
8376
8383 T operator[](size_t index) const {
8384 if (index % (N + 1) == 0) return T(0);
8385 else return this->_data[index];
8386 }
8387
8395 MAT_COPY_OFFDIAG:
8396 for (size_t i = 0; i != N * N; ++i) {
8398 if (i % (N + 1) == 0) mat[i] = 0;
8399 else mat[i] = this->_data[i];
8400 }
8401 return mat;
8402 }
8403
8410 FLAMES_PRAGMA(INLINE)
8411 return static_cast<Mat<T, N, N, MatType::NORMAL>>(*this);
8412 }
8413
8414 public: // original private
8420 const T* _data;
8421};
8422
8423template <typename T, size_t n_rows, size_t n_cols, MatType type, typename type_parent>
8425 public:
8431 MatViewCol(const Mat<T, n_rows, n_cols, matType<type_parent>()>& m, size_t index) : _data(m.rawDataPtr() + index) {
8432 static_assert(type == MatType::NORMAL, "We only support limited matType.");
8433 assert(index < n_cols && "Take the specific col by index requires 'The index should be smaller than the number "
8434 "of the matrix's cols.'");
8435 }
8436
8443
8449 inline static constexpr size_t size() noexcept { return n_rows; }
8450
8456 inline static constexpr MatType pType() noexcept { return matType<type_parent>(); }
8457
8465 T operator()(size_t r, size_t c) const {
8466 assert(c == 0 && "Column vector's column index should always be 0.");
8467 assert(r < n_rows && "Matrix row index should be within range");
8468 constexpr MatType p_type = pType();
8469 if (p_type == MatType::NORMAL) {
8470 return _data[r * n_cols];
8471 } else {
8472 // Normally it is impossible to reach here.
8473 assert(!"Impossible! Unknown MatType!");
8474 }
8475 return _data[0];
8476 }
8477
8484 T operator[](size_t index) const { return (*this)(index, 0); }
8485
8490 operator Vec<T, n_rows>() const {
8491 Vec<T, n_rows> mat;
8492 MAT_COPY_COL:
8493 for (size_t i = 0; i != n_rows; ++i) {
8495 mat[i] = (*this)[i];
8496 }
8497 return mat;
8498 }
8499
8506 FLAMES_PRAGMA(INLINE);
8507 return static_cast<Vec<T, n_rows>>(*this);
8508 }
8509
8516 FLAMES_PRAGMA(INLINE);
8517 return static_cast<Vec<T, n_rows>>(*this);
8518 }
8519
8520 void print(const std::string& str = "", std::ostream& os = std::cout) const { this->asMat().print(str, os); }
8521
8522 public: // original private
8528 const T* const _data;
8529};
8530
8531template <typename T, size_t n_rows, size_t n_cols, MatType type, typename type_parent>
8533 public:
8539 MatViewRow(const Mat<T, n_rows, n_cols, matType<type_parent>()>& m, size_t index)
8540 : _data(m.rawDataPtr() + index * n_cols) {
8541 static_assert(type == MatType::NORMAL, "We only support limited matType.");
8542 assert(index < n_rows && "Take the specific row by index requires 'The index should be smaller than the number "
8543 "of the matrix's rows.'");
8544 }
8545
8552
8558 inline static constexpr size_t size() noexcept { return n_cols; }
8559
8565 inline static constexpr MatType pType() noexcept { return matType<type_parent>(); }
8566
8574 T operator()(size_t r, size_t c) const {
8575 assert(r == 0 && "Row vector's row index should always be 0.");
8576 assert(c < n_cols && "Matrix column index should be within range");
8577 constexpr MatType p_type = pType();
8578 if (p_type == MatType::NORMAL) {
8579 return _data[c];
8580 } else {
8581 // Normally it is impossible to reach here.
8582 assert(!"Impossible! Unknown MatType!");
8583 }
8584 return _data[0];
8585 }
8586
8593 T operator[](size_t index) const { return (*this)(0, index); }
8594
8599 operator RowVec<T, n_rows>() const {
8601 MAT_COPY_ROW:
8602 for (size_t i = 0; i != n_cols; ++i) {
8604 mat[i] = (*this)[i];
8605 }
8606 return mat;
8607 }
8608
8615 FLAMES_PRAGMA(INLINE);
8616 return static_cast<RowVec<T, n_cols>>(*this);
8617 }
8618
8625 FLAMES_PRAGMA(INLINE);
8626 return static_cast<Vec<T, n_cols>>(*this);
8627 }
8628
8629 void print(const std::string& str = "", std::ostream& os = std::cout) const { this->asMat().print(str, os); }
8630
8631 public: // original private
8637 const T* const _data;
8638};
8639
8640template <typename T, size_t n_rows, size_t n_cols, MatType type, typename type_parent>
8642 public:
8648 MatRefCol(Mat<T, n_rows, n_cols, matType<type_parent>()>& m, size_t index) : _data(m.rawDataPtr() + index) {
8649 static_assert(type == MatType::NORMAL, "We only support limited matType.");
8650 assert(index < n_cols && "Take the specific col by index requires 'The index should be smaller than the number "
8651 "of the matrix's cols.'");
8652 }
8653
8660 MatRefCol(const MatRefCol& m) : _data(m._data) {}
8661
8662 template <typename T_, size_t n_rows_, size_t n_cols_, MatType type_>
8664 for (size_t i = 0; i != size(); ++i) {
8666 _data[i * n_rows] = m[i];
8667 }
8668 return *this;
8669 }
8670
8671 template <typename M>
8672 void assign(M m) {
8673 for (size_t i = 0; i != size(); ++i) {
8675 _data[i * n_rows] = m[i];
8676 }
8677 }
8678
8684 inline static constexpr size_t size() noexcept { return n_rows; }
8685
8691 inline static constexpr MatType pType() noexcept { return matType<type_parent>(); }
8692
8700 T operator()(size_t r, size_t c) const {
8701 assert(c == 0 && "Column vector's column index should always be 0.");
8702 assert(r < n_rows && "Matrix row index should be within range");
8703 constexpr MatType p_type = pType();
8704 if (p_type == MatType::NORMAL) {
8705 return _data[r * n_cols];
8706 } else {
8707 // Normally it is impossible to reach here.
8708 assert(!"Impossible! Unknown MatType!");
8709 }
8710 return _data[0];
8711 }
8712
8713 T& operator()(size_t r, size_t c) {
8714 assert(c == 0 && "Column vector's column index should always be 0.");
8715 assert(r < n_rows && "Matrix row index should be within range");
8716 constexpr MatType p_type = pType();
8717 if (p_type == MatType::NORMAL) {
8718 return _data[r * n_cols];
8719 } else {
8720 // Normally it is impossible to reach here.
8721 assert(!"Impossible! Unknown MatType!");
8722 }
8723 return _data[0];
8724 }
8725
8732 T operator[](size_t index) const { return (*this)(index, 0); }
8733
8734 T& operator[](size_t index) { return (*this)(index, 0); }
8735
8740 operator Vec<T, n_rows>() const {
8741 Vec<T, n_rows> mat;
8742 MAT_COPY_COL:
8743 for (size_t i = 0; i != n_rows; ++i) {
8745 mat[i] = (*this)[i];
8746 }
8747 return mat;
8748 }
8749
8756 FLAMES_PRAGMA(INLINE);
8757 return static_cast<Vec<T, n_rows>>(*this);
8758 }
8759
8766 FLAMES_PRAGMA(INLINE);
8767 return static_cast<Vec<T, n_rows>>(*this);
8768 }
8769
8770 void print(const std::string& str = "", std::ostream& os = std::cout) const { this->asMat().print(str, os); }
8771
8772 public: // original private
8778 T* const _data;
8779};
8780
8781template <typename T, size_t n_rows, size_t n_cols, MatType type, typename type_parent>
8783 public:
8789 MatRefRow(Mat<T, n_rows, n_cols, matType<type_parent>()>& m, size_t index)
8790 : _data(m.rawDataPtr() + index * n_cols) {
8791 static_assert(type == MatType::NORMAL, "We only support limited matType.");
8792 assert(index < n_rows && "Take the specific row by index requires 'The index should be smaller than the number "
8793 "of the matrix's rows.'");
8794 }
8795
8802 MatRefRow(const MatRefRow& m) : _data(m._data) {}
8803
8804 template <typename T_, size_t n_rows_, size_t n_cols_, MatType type_>
8806 for (size_t i = 0; i != size(); ++i) {
8808 _data[i] = m[i];
8809 }
8810 return *this;
8811 }
8812
8813 template <typename M>
8814 void assign(M m) {
8815 for (size_t i = 0; i != size(); ++i) {
8817 _data[i] = m[i];
8818 }
8819 }
8820
8826 inline static constexpr size_t size() noexcept { return n_cols; }
8827
8833 inline static constexpr MatType pType() noexcept { return matType<type_parent>(); }
8834
8842 T operator()(size_t r, size_t c) const {
8843 assert(r == 0 && "Row vector's row index should always be 0.");
8844 assert(c < n_cols && "Matrix column index should be within range");
8845 constexpr MatType p_type = pType();
8846 if (p_type == MatType::NORMAL) {
8847 return _data[c];
8848 } else {
8849 // Normally it is impossible to reach here.
8850 assert(!"Impossible! Unknown MatType!");
8851 }
8852 return _data[0];
8853 }
8854
8855 T& operator()(size_t r, size_t c) {
8856 assert(r == 0 && "Row vector's row index should always be 0.");
8857 assert(c < n_cols && "Matrix column index should be within range");
8858 constexpr MatType p_type = pType();
8859 if (p_type == MatType::NORMAL) {
8860 return _data[c];
8861 } else {
8862 // Normally it is impossible to reach here.
8863 assert(!"Impossible! Unknown MatType!");
8864 }
8865 return _data[0];
8866 }
8867
8874 T operator[](size_t index) const { return (*this)(0, index); }
8875
8876 T& operator[](size_t index) { return (*this)(0, index); }
8877
8882 operator RowVec<T, n_cols>() const {
8884 MAT_COPY_ROW:
8885 for (size_t i = 0; i != n_cols; ++i) {
8887 mat[i] = (*this)[i];
8888 }
8889 return mat;
8890 }
8891
8898 FLAMES_PRAGMA(INLINE);
8899 return static_cast<RowVec<T, n_cols>>(*this);
8900 }
8901
8908 FLAMES_PRAGMA(INLINE);
8909 return static_cast<RowVec<T, n_cols>>(*this);
8910 }
8911
8912 void print(const std::string& str = "", std::ostream& os = std::cout) const { this->asMat().print(str, os); }
8913
8914 public: // original private
8920 T* const _data;
8921};
8922
8923template <size_t first_col, size_t last_col, typename T, size_t n_rows, size_t n_cols, MatType type,
8924 typename type_parent>
8926 public:
8932 MatViewCols(const Mat<T, n_rows, n_cols, matType<type_parent>()>& m) : _data(m.rawDataPtr()) {
8933 static_assert(last_col < n_cols, "Take the successive cols by indexes requires 'The indexes should be smaller "
8934 "than the number of the matrix's cols.'");
8935 static_assert(first_col > 0, "Take the specific col by index requires 'The indexes can't be smaller than 0.'");
8936 static_assert(first_col <= last_col, "The first index should be smaller than the second one.");
8937 }
8938
8945
8951 inline static constexpr size_t size() noexcept {
8952 return type == MatType::NORMAL ? n_rows * n_cols
8953 : type == MatType::DIAGONAL ? n_rows
8954 : type == MatType::SCALAR ? 1
8955 : type == MatType::SUPPER ? (n_rows - 1) * n_rows / 2
8956 : type == MatType::SLOWER ? (n_rows - 1) * n_rows / 2
8957 : type == MatType::ASYM ? (n_rows - 1) * n_rows / 2
8958 : (1 + n_rows) * n_rows / 2;
8959 }
8960
8966 inline static constexpr MatType pType() noexcept { return matType<type_parent>(); }
8967
8975 T operator()(size_t r, size_t c) const {
8976 assert(c < (last_col - first_col + 1) &&
8977 "The col index must be small than the number of the successive columns .");
8978 assert(r > 0 && "The row index can't be smaller than 0.");
8979 constexpr MatType p_type = pType();
8980 if (p_type == MatType::NORMAL) {
8981 return _data[r * n_cols + c + first_col];
8982 } else if (p_type == MatType::DIAGONAL) {
8983 if (r == (c + first_col)) return _data[r];
8984 else return T(0);
8985 } else if (p_type == MatType::SCALAR) {
8986 if (r == (c + first_col)) return _data[0];
8987 else return T(0);
8988 } else if (p_type == MatType::UPPER) {
8989 if (r <= (c + first_col)) return _data[(2 * n_cols + 1 - r) * r / 2 + c + first_col - r];
8990 else return T(0);
8991 } else if (p_type == MatType::LOWER) {
8992 if (r >= (c + first_col)) return _data[(1 + r) * r / 2 + c + first_col - r];
8993 else return T(0);
8994 } else if (p_type == MatType::SUPPER) {
8995 if (r < (c + first_col)) return _data[(2 * n_cols + 1 - r) * r / 2 + c + first_col - 2 * r - 1];
8996 else return T(0);
8997 } else if (p_type == MatType::SLOWER) {
8998 if (r >= (c + first_col)) return _data[(1 + r) * r / 2 + c + first_col - r];
8999 else return T(0);
9000 } else if (p_type == MatType::SYM) {
9001 if (r <= (c + first_col)) return _data[(2 * n_cols + 1 - r) * r / 2 + c + first_col - r];
9002 else return _data[(2 * n_cols + 1 - (c + first_col)) * (c + first_col) / 2 + r - (c + first_col)];
9003 } else if (p_type == MatType::ASYM) {
9004 if (r < (c + first_col)) return -_data[(2 * n_cols + 1 - r) * r / 2 + (c + first_col) - r * 2 - 1];
9005 else if (r > (c + first_col))
9006 return _data[(2 * n_cols + 1 - (c + first_col)) * (c + first_col) / 2 + r - (c + first_col) * 2 - 1];
9007 else return T(0);
9008 } else {
9009 // Normally it is impossible to reach here.
9010 assert(!"Impossible! Unknown MatType!");
9011 }
9012 }
9013
9020 T operator[](size_t index) const {
9021 return (*this)(index / (last_col - first_col + 1), index % (last_col - first_col + 1));
9022 }
9023
9028 operator Mat<T, n_rows, last_col - first_col + 1, MatType::NORMAL>() const {
9029 Mat<T, n_rows, last_col - first_col + 1, MatType::NORMAL> mat;
9030 MAT_COPY_COLS:
9031 for (size_t i = 0; i != n_rows * (last_col - first_col + 1); ++i) {
9033 mat[i] = (*this)[i];
9034 }
9035 return mat;
9036 }
9037
9043 Mat<T, n_rows, last_col - first_col + 1, MatType::NORMAL> asMat() const {
9044 FLAMES_PRAGMA(INLINE);
9045 return static_cast<Mat<T, n_rows, last_col - first_col + 1, MatType::NORMAL>>(*this);
9046 }
9047
9048 public: // original private
9054 const T* _data;
9055};
9056
9057template <size_t first_row, size_t last_row, typename T, size_t n_rows, size_t n_cols, MatType type,
9058 typename type_parent>
9060 public:
9066 MatViewRows(const Mat<T, n_cols, n_rows, matType<type_parent>()>& m) : _data(m.rawDataPtr()) {
9067 static_assert(last_row < n_rows, "Take the successive rows by indexes requires 'The indexes should be smaller "
9068 "than the number of the matrix's rows.'");
9069 static_assert(first_row > 0, "Take the specific row by index requires 'The indexes can't be smaller than 0.'");
9070 static_assert(first_row <= last_row, "The first index should be smaller than the second one.");
9071 }
9072
9079
9085 inline static constexpr size_t size() noexcept {
9086 return type == MatType::NORMAL ? n_rows * n_cols
9087 : type == MatType::DIAGONAL ? n_rows
9088 : type == MatType::SCALAR ? 1
9089 : type == MatType::SUPPER ? (n_rows - 1) * n_rows / 2
9090 : type == MatType::SLOWER ? (n_rows - 1) * n_rows / 2
9091 : type == MatType::ASYM ? (n_rows - 1) * n_rows / 2
9092 : (1 + n_rows) * n_rows / 2;
9093 }
9094
9100 inline static constexpr MatType pType() noexcept { return matType<type_parent>(); }
9101
9109 T operator()(size_t r, size_t c) const {
9110 assert(r < last_row - first_row && "The row index must be small than the number of the successive rows .");
9111 assert(c > 0 && "The row index can't be smaller than 0.");
9112 constexpr MatType p_type = pType();
9113 if (p_type == MatType::NORMAL) {
9114 return _data[(r + first_row) * n_cols + c];
9115 } else if (p_type == MatType::DIAGONAL) {
9116 if ((r + first_row) == c) return _data[r];
9117 else return T(0);
9118 } else if (p_type == MatType::SCALAR) {
9119 if ((r + first_row) == c) return _data[0];
9120 else return T(0);
9121 } else if (p_type == MatType::UPPER) {
9122 if ((r + first_row) <= c)
9123 return _data[(2 * n_cols + 1 - (r + first_row)) * (r + first_row) / 2 + c - (r + first_row)];
9124 else return T(0);
9125 } else if (p_type == MatType::LOWER) {
9126 if ((r + first_row) >= c) return _data[(1 + (r + first_row)) * (r + first_row) / 2 + c];
9127 else return T(0);
9128 } else if (p_type == MatType::SUPPER) {
9129 if ((r + first_row) < c)
9130 return _data[(2 * n_cols + 1 - (r + first_row)) * (r + first_row) / 2 + c - 2 * (r + first_row) - 1];
9131 else return T(0);
9132 } else if (p_type == MatType::SLOWER) {
9133 if ((r + first_row) >= c) return _data[(1 + (r + first_row)) * (r + first_row) / 2 + c - (r + first_row)];
9134 else return T(0);
9135 } else if (p_type == MatType::SYM) {
9136 if ((r + first_row) <= c)
9137 return _data[(2 * n_cols + 1 - (r + first_row)) * (r + first_row) / 2 + c - (r + first_row)];
9138 else return _data[(2 * n_cols + 1 - c) * c / 2 + (r + first_row) - c];
9139 } else if (p_type == MatType::ASYM) {
9140 if ((r + first_row) < c)
9141 return -_data[(2 * n_cols + 1 - (r + first_row)) * (r + first_row) / 2 + c - (r + first_row) * 2 - 1];
9142 else if ((r + first_row) > c) return _data[(2 * n_cols + 1 - c) * c / 2 + r - c * 2 - 1];
9143 else return T(0);
9144 } else {
9145 // Normally it is impossible to reach here.
9146 assert(!"Impossible! Unknown MatType!");
9147 }
9148 }
9149
9156 T operator[](size_t index) const { return (*this)(index / n_cols, index % n_cols); }
9157
9162 operator Mat<T, last_row - first_row + 1, n_cols, MatType::NORMAL>() const {
9163 Mat<T, last_row - first_row + 1, n_cols, MatType::NORMAL> mat;
9164 MAT_COPY_ROWS:
9165 for (size_t i = 0; i != n_rows * (last_row - first_row + 1); ++i) {
9167 mat[i] = (*this)[i];
9168 }
9169 return mat;
9170 }
9171
9177 Mat<T, last_row - first_row + 1, n_cols, MatType::NORMAL> asMat() const {
9178 FLAMES_PRAGMA(INLINE);
9179 return static_cast<Mat<T, last_row - first_row + 1, n_cols, MatType::NORMAL>>(*this);
9180 }
9181
9187 Mat<T, last_row - first_row + 1, n_cols, MatType::NORMAL> asVec() const {
9188 FLAMES_PRAGMA(INLINE);
9189 return static_cast<Mat<T, last_row - first_row + 1, n_cols, MatType::NORMAL>>(*this);
9190 }
9191
9192 public: // original private
9198 const T* _data;
9199};
9200
9219template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
9220 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
9221 typename T2, size_t n_rows, size_t n_cols, MatType type1, MatType type2>
9222static inline Mat<T1, n_rows, n_cols, sumType(type1, type2)>
9223operator+(const M1<T1, n_rows, n_cols, type1, _unused1...>& mat_L,
9224 const M2<T2, n_rows, n_cols, type2, _unused2...>& mat_R) {
9225 FLAMES_PRAGMA(INLINE)
9227 return mat.add(mat_L, mat_R);
9228}
9229
9245template <template <class, size_t, size_t, MatType, class...> typename M, typename... _unused, typename T1, typename T2,
9246 size_t n_rows, size_t n_cols, MatType type1, MatType type2>
9249 FLAMES_PRAGMA(INLINE)
9250 return mat_L.add(mat_R);
9251}
9252
9271template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
9272 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
9273 typename T2, size_t n_rows, size_t n_cols, MatType type1, MatType type2>
9274static inline Mat<T1, n_rows, n_cols, sumType(type1, type2)>
9275operator-(const M1<T1, n_rows, n_cols, type1, _unused1...>& mat_L,
9276 const M2<T2, n_rows, n_cols, type2, _unused2...>& mat_R) {
9277 FLAMES_PRAGMA(INLINE)
9279 return mat.sub(mat_L, mat_R);
9280}
9281
9297template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
9298 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
9299 typename T2, size_t n_rows, size_t n_cols, MatType type1, MatType type2>
9300static inline M1<T1, n_rows, n_cols, type1>& operator-=(M1<T1, n_rows, n_cols, type1, _unused1...>& mat_L,
9301 const M2<T2, n_rows, n_cols, type2, _unused2...>& mat_R) {
9302 FLAMES_PRAGMA(INLINE)
9303 return mat_L.sub(mat_R);
9304}
9305
9324template <template <class, size_t, size_t, MatType, class...> typename M, typename... _unused, typename T1, typename T2,
9325 size_t n_rows, size_t n_cols, MatType type1, MatType type2,
9326 std::enable_if_t<(std::is_same<T1, bool>::value), bool> = true>
9327static inline Mat<T1, n_rows, n_cols, mulType(type1, type2, n_rows, n_cols, n_cols)>
9329 FLAMES_PRAGMA(INLINE)
9330 Mat<T2, n_rows, n_cols, mulType(type1, type2, n_rows, n_cols, n_cols)> tmp;
9331 tmp.mul(mat, mat_R);
9332 return mat = tmp;
9333}
9334
9350template <template <class, size_t, size_t, MatType, class...> typename M, typename... _unused, typename T1, typename T2,
9351 size_t n_rows, size_t n_cols, MatType type1, MatType type2,
9352 std::enable_if_t<!(std::is_same<T1, bool>::value), bool> = true>
9353static inline Mat<T1, n_rows, n_cols, mulType(type1, type2, n_rows, n_cols, n_cols)>
9354operator*=(Mat<T1, n_rows, n_cols, type1>& mat, const M<T2, n_cols, n_cols, type2, _unused...>& mat_R) {
9355 FLAMES_PRAGMA(INLINE)
9356 Mat<T1, n_rows, n_cols, mulType(type1, type2, n_rows, n_cols, n_cols)> tmp;
9357 tmp.mul(mat, mat_R);
9358 return mat = tmp;
9359}
9360
9376template <template <class, size_t, size_t, MatType, class...> typename M, typename... _unused, typename T,
9377 typename ScalarT, size_t n_rows, size_t n_cols, MatType type,
9378 std::enable_if_t<std::is_arithmetic<std::remove_reference_t<ScalarT>>::value, bool> = true>
9380 FLAMES_PRAGMA(INLINE)
9381 return mat.mul(s);
9382}
9383
9401template <template <class, size_t, size_t, MatType, class...> typename M, typename... _unused, typename T,
9402 typename ScalarT, size_t n_rows, size_t n_cols, MatType type,
9403 std::enable_if_t<std::is_arithmetic<std::remove_reference_t<ScalarT>>::value, bool> = true>
9405 FLAMES_PRAGMA(INLINE)
9407 return mat.mul(mat_L, s);
9408}
9409
9428template <template <class, size_t, size_t, MatType, class...> typename M, typename... _unused, typename T,
9429 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>
9431 ap_fixed<AP_W, AP_I, AP_Q, AP_O, AP_N> s) {
9432 FLAMES_PRAGMA(INLINE)
9434 return mat.mul(mat_L, s);
9435}
9436
9454template <template <class, size_t, size_t, MatType, class...> typename M, typename... _unused, typename T,
9455 typename ScalarT, size_t n_rows, size_t n_cols, MatType type,
9456 std::enable_if_t<std::is_arithmetic<std::remove_reference_t<ScalarT>>::value, bool> = true>
9458 FLAMES_PRAGMA(INLINE)
9460 return mat.mul(mat_R, s);
9461}
9462
9481template <template <class, size_t, size_t, MatType, class...> typename M, typename... _unused, typename T,
9482 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>
9483static inline Mat<T, n_rows, n_cols, type> operator*(ap_fixed<AP_W, AP_I, AP_Q, AP_O, AP_N> s,
9485 FLAMES_PRAGMA(INLINE)
9487 return mat.mul(mat_R, s);
9488}
9489
9513template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
9514 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
9515 typename T2, size_t n_rows, size_t comm, size_t n_cols, MatType type1, MatType type2,
9516 std::enable_if_t<(std::is_same<T1, bool>::value), bool> = true>
9517static inline Mat<T2, n_rows, n_cols, mulType(type1, type2, n_rows, comm, n_cols)>
9518operator*(const M1<T1, n_rows, comm, type1, _unused1...>& mat_L,
9519 const M2<T2, comm, n_cols, type2, _unused2...>& mat_R) {
9520 Mat<T2, n_rows, n_cols, mulType(type1, type2, n_rows, comm, n_cols)> mat;
9521 mat.mul(mat_L, mat_R);
9522 return mat;
9523 // if "return mat.mul(mat_L, mat_R);" , then there will be a error. But I don't know why.
9524}
9525
9526template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
9527 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
9528 typename T2, size_t n_rows, size_t comm, size_t n_cols, MatType type1, MatType type2,
9529 std::enable_if_t<!(std::is_same<T1, bool>::value), bool> = true>
9530static inline Mat<T1, n_rows, n_cols, mulType(type1, type2, n_rows, comm, n_cols)>
9531operator*(const M1<T1, n_rows, comm, type1, _unused1...>& mat_L,
9532 const M2<T2, comm, n_cols, type2, _unused2...>& mat_R) {
9533 Mat<T1, n_rows, n_cols, mulType(type1, type2, n_rows, comm, n_cols)> mat;
9534 mat.mul(mat_L, mat_R);
9535 return mat;
9536 // if "return mat.mul(mat_L, mat_R);" , then there will be a error. But I don't know why.
9537}
9538
9560template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
9561 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
9562 typename T2, size_t n_rows, size_t n_cols, MatType type>
9563Mat<T1, n_rows, n_cols, type> operator%(const M1<T1, n_rows, n_cols, type, _unused1...>& mat_L,
9564 const M2<T2, n_rows, n_cols, type, _unused2...>& mat_R) {
9566 return mat.emul(mat_L, mat_R);
9567}
9568
9587template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
9588 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
9589 typename T2, size_t n_rows, size_t n_cols, MatType type>
9590Mat<bool, n_rows, n_cols, type> operator==(const M1<T1, n_rows, n_cols, type, _unused1...>& mat_L,
9591 const M2<T2, n_rows, n_cols, type, _unused2...>& mat_R) {
9593OPERATOR_EQUAL:
9594 for (size_t i = 0; i != mat_L.size(); ++i) {
9596 mat[i] = mat_L[i] == mat_R[i];
9597 }
9598 return mat;
9599}
9600
9619template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
9620 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
9621 typename T2, size_t n_rows, size_t n_cols, MatType type>
9622Mat<bool, n_rows, n_cols, type> operator!=(const M1<T1, n_rows, n_cols, type, _unused1...>& mat_L,
9623 const M2<T2, n_rows, n_cols, type, _unused2...>& mat_R) {
9625OPERATOR_UNEQUAL:
9626 for (size_t i = 0; i != mat_L.size(); ++i) {
9628 mat[i] = mat_L[i] != mat_R[i];
9629 }
9630 return mat;
9631}
9632
9651template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
9652 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
9653 typename T2, size_t n_rows, size_t n_cols, MatType type>
9654Mat<bool, n_rows, n_cols, type> operator>(const M1<T1, n_rows, n_cols, type, _unused1...>& mat_L,
9655 const M2<T2, n_rows, n_cols, type, _unused2...>& mat_R) {
9657OPERATOR_GREATER:
9658 for (size_t i = 0; i != mat_L.size(); ++i) {
9660 mat[i] = mat_L[i] > mat_R[i];
9661 }
9662 return mat;
9663}
9664
9683template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
9684 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
9685 typename T2, size_t n_rows, size_t n_cols, MatType type>
9686Mat<bool, n_rows, n_cols, type> operator<(const M1<T1, n_rows, n_cols, type, _unused1...>& mat_L,
9687 const M2<T2, n_rows, n_cols, type, _unused2...>& mat_R) {
9688 Mat<bool, n_rows, n_cols, type> mat;
9689OPERATOR_LESS:
9690 for (size_t i = 0; i != mat_L.size(); ++i) {
9692 mat[i] = mat_L[i] < mat_R[i];
9693 }
9694 return mat;
9695}
9696
9715template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
9716 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
9717 typename T2, size_t n_rows, size_t n_cols, MatType type>
9718Mat<bool, n_rows, n_cols, type> operator>=(const M1<T1, n_rows, n_cols, type, _unused1...>& mat_L,
9719 const M2<T2, n_rows, n_cols, type, _unused2...>& mat_R) {
9721OPERATOR_GEQ:
9722 for (size_t i = 0; i != mat_L.size(); ++i) {
9724 mat[i] = mat_L[i] >= mat_R[i];
9725 }
9726 return mat;
9727}
9728
9747template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
9748 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
9749 typename T2, size_t n_rows, size_t n_cols, MatType type>
9750Mat<bool, n_rows, n_cols, type> operator<=(const M1<T1, n_rows, n_cols, type, _unused1...>& mat_L,
9751 const M2<T2, n_rows, n_cols, type, _unused2...>& mat_R) {
9752 Mat<bool, n_rows, n_cols, type> mat;
9753OPERATOR_LEQ:
9754 for (size_t i = 0; i != mat_L.size(); ++i) {
9756 mat[i] = mat_L[i] <= mat_R[i];
9757 }
9758 return mat;
9759}
9760
9779template <template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
9780 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
9781 typename T2, size_t n_rows, size_t n_cols, MatType type>
9782Mat<T1, n_rows, n_cols, type> mod(const M1<T1, n_rows, n_cols, type, _unused1...>& mat_L,
9783 const M2<T2, n_rows, n_cols, type, _unused2...>& mat_R) {
9785OPERATOR_LEQ:
9786 for (size_t i = 0; i != mat_L.size(); ++i) {
9788 mat[i] = mat_L[i] % mat_R[i]; // Operator % Should be defined, otherwise compilation error.
9789 }
9790 return mat;
9791}
9792
9793template <typename Tp = double, template <class, size_t, size_t, MatType, class...> typename M1, typename... _unused1,
9794 template <class, size_t, size_t, MatType, class...> typename M2, typename... _unused2, typename T1,
9795 typename T2, size_t L_rows, size_t L_cols, size_t R_rows, size_t R_cols, MatType type,
9796 std::enable_if_t<L_rows * L_cols == R_rows * R_cols, bool> = true>
9797Tp innerProd(const M1<T1, L_rows, L_cols, type, _unused1...>& mat_L,
9798 const M2<T2, R_rows, R_cols, type, _unused2...>& mat_R) {
9799 assert(mat_L.size() == mat_R.size() && "Dimension should meet for innerProd.");
9800 Tp result = 0;
9801INNER_PROD:
9802 for (size_t i = 0; i != mat_L.size(); ++i) {
9804 result += static_cast<Tp>(mat_L[i] * mat_R[i]);
9805 }
9806 return result;
9807}
9808
9821template <typename T, size_t n_rows, size_t n_cols, MatType type>
9822static inline std::ostream& operator<<(std::ostream& os, const Mat<T, n_rows, n_cols, type>& mat) {
9823 mat.print("", os);
9824 return os;
9825}
9826
9827} // namespace flames
9828
9829#ifndef FLAMES_PRESERVE_WARNING
9830# ifdef __SYNTHESIS__
9831# pragma GCC diagnostic pop
9832# endif
9833#endif
9834
9835#ifdef DEFINED_INLINE
9836# define INLINE inline
9837# undef DEFINED_INLINE
9838#endif
9839
9840#endif
Matrix.
Definition core.hpp:575
Mat & sub(const M< T2, n_rows, n_cols, type2, _unused... > &mat_R)
Matrix self minus a matrix.
Definition core.hpp:1749
MatViewOpp< T, n_rows, n_cols, type > opp_() const
Matrix opposite as a read only view.
Definition core.hpp:6300
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:5819
T operator[](size_t index) const
Get read only element by row major index from the data array.
Definition core.hpp:860
Mat & mul(ap_int< AP_W > s)
Matrix self multiply ap_int integer.
Definition core.hpp:1926
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:5691
Vec< T, n_rows > diagVec() const
Take the diagonal vector of a matrix and make a copy.
Definition core.hpp:6417
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:6876
T * rawDataPtr()
Get the raw data array pointer.
Definition core.hpp:6779
MatRefCol< T, n_rows, n_cols, MatType::NORMAL, MType< type > > col_(size_t index)
Definition core.hpp:5512
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:5891
T & operator()(size_t r, size_t c)
Get writeable data element by row index and column index.
Definition core.hpp:931
void _tryAssign(size_t r, size_t c, T value)
Try to assign a value to a specific position.
Definition core.hpp:6793
Mat & t(const M< T2, n_cols, n_rows, type2, _unused... > &mat)
Transpose.
Definition core.hpp:5937
Mat< T, n_rows, n_cols, MatType::NORMAL > offDiag() const
Take the off diagonal of a matrix and make a copy.
Definition core.hpp:6538
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:5559
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:6618
Mat & diagMat(const M< T2, n_rows, n_cols, type2, _unused... > &mat)
Take the diagonal of a matrix.
Definition core.hpp:6337
Mat & diagVec(const M< T2, n_rows, n_rows, type2, _unused... > &mat)
Take the diagonal vector of a matrix.
Definition core.hpp:6394
Mat(Init init)
Definition core.hpp:754
Mat & oppSelf()
In-place matrix opposite.
Definition core.hpp:6314
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:6903
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:6824
Mat & tSelf()
In-place transpose.
Definition core.hpp:6223
Mat(T *const ptr, InitAfterwards opt=InitAfterwards::NONE)
Definition core.hpp:792
Mat & diagRowVec(const M< T2, n_cols, n_cols, type2, _unused... > &mat)
Take the diagonal row vector of a matrix.
Definition core.hpp:6452
~Mat()
Destroy the Mat object.
Definition core.hpp:825
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:6675
Mat & invDiag(const M< T2, n_cols, n_rows, type2, _unused... > &mat)
Inverse the diagonal matrix.
Definition core.hpp:6581
Mat & rows(const M1< T1, rows_, cols_, type1, _unused1... > &mat, M2 vector)
Take discrete rows of a matrix by container.
Definition core.hpp:5783
T & operator[](size_t index)
Get writeable element by row major index from the data array.
Definition core.hpp:874
void setZero()
Set all elements of the matrix to zero.
Definition core.hpp:989
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:5728
Mat & opp(const M< T2, n_rows, n_cols, type, _unused... > &mat)
Calculate the opposite of a matrix.
Definition core.hpp:6262
Mat & mul(const M< T2, n_rows, n_cols, type, _unused... > &mat, ScalarT s)
Matrix times a scalar.
Definition core.hpp:1779
const T * rawDataPtr() const
Definition core.hpp:6781
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:6558
MatViewOpp< T, n_rows, n_cols, type > operator-() const
The unary minus operator.
Definition core.hpp:6765
MatViewT< T, n_cols, n_rows, tType(type)> t_()
Transpose as a read only view.
Definition core.hpp:6210
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:5754
Mat invNSA(size_t iter=4) const
Matrix inverse using Newton-Schulz iterative method (NSA) as a copy.
Definition core.hpp:6651
Mat & cols(const M1< T1, rows_, cols_, type1, _unused1... > &mat, M2 vector)
Take discrete cols of a matrix by container.
Definition core.hpp:5855
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:5506
Mat & mul(ScalarT s)
Matrix self multiply a scalar.
Definition core.hpp:1884
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:1086
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:5490
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:1832
Mat & mul(ap_fixed< AP_W, AP_I, AP_Q, AP_O, AP_N > s)
Matrix self multiply ap_fixed float.
Definition core.hpp:1950
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:5637
Mat & mul(std::complex< ScalarT > s)
Matrix self multiply a complex number.
Definition core.hpp:1906
void col(size_t c, const M< T2, rows_, cols_, type2, _unused... > &mat)
Definition core.hpp:5466
Mat()
Construct a new Mat object.
Definition core.hpp:614
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:6432
T & value()
Get the writeable value from 1x1 matrix.
Definition core.hpp:6723
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:6374
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:7053
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:6969
static constexpr size_t size() noexcept
Get the matrix size of storage.
Definition core.hpp:842
Mat & mul(const M< T2, n_rows, n_cols, type, _unused... > &mat, std::complex< ScalarT > s)
Matrix times a complex number.
Definition core.hpp:1807
Mat< T, n_rows, n_cols, MatType::SLOWER > t() const
Transpose SUPPER matrix as a copy.
Definition core.hpp:6130
Tp power() const
Definition core.hpp:6699
Mat & cols(const M< T2, rows_, cols_, type2, _unused... > &mat, size_t first_col)
Take a row of a matrix by index as a read only view.
Definition core.hpp:5601
Mat & row(const M< T2, rows_, cols_, type2, _unused... > &mat, size_t r)
Take a row of a matrix by index.
Definition core.hpp:5535
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:1444
Mat & abs_()
Apply 'abs' (absolute value) to itself.
Definition core.hpp:5913
Mat(const T *ptr, InitAfterwards opt=InitAfterwards::NONE)
Construct a new Mat object from raw data pointer.
Definition core.hpp:765
bool read(const std::string &file_name)
Definition core.hpp:991
Mat< T, n_rows, n_cols, MatType::UPPER > t() const
Transpose LOWER matrix as a copy.
Definition core.hpp:6099
Mat t() const
Transpose DIAGONAL/SCALAR/SYM matrix as a copy.
Definition core.hpp:6047
T element_type
Definition core.hpp:602
Mat< T, n_rows, n_cols, MatType::LOWER > t() const
Transpose UPPER matrix as a copy.
Definition core.hpp:6068
void _sa_multiply(const T1 &tmp_L, const T2 &tmp_R, const HLSVec &use_assign)
Systolic array multiplication.
Definition core.hpp:6927
Mat(T val)
Construct a new Mat object with initial value.
Definition core.hpp:633
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:5662
void setValue(T val)
Set all elements of the matrix to a value.
Definition core.hpp:978
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:6690
Mat< T, n_cols, n_rows, type > t() const
Transpose NORMAL matrix as a copy.
Definition core.hpp:6016
Mat & col(const M< T2, rows_, cols_, type2, _unused... > &mat, size_t c)
Take a column of a matrix by index.
Definition core.hpp:5452
Mat & offDiag(const M< T2, n_cols, n_rows, type2, _unused... > &mat)
Take the off diagonal of a matrix.
Definition core.hpp:6510
Mat invDiag() const
Inverse the diagonal matrix and makes a copy.
Definition core.hpp:6596
void print(const std::string &str="", std::ostream &os=std::cout) const
Print the matrix.
Definition core.hpp:6734
Mat opp() const
Calculate the opposite of a matrix and make a copy.
Definition core.hpp:6285
T value() const
Get the value from 1x1 matrix.
Definition core.hpp:6713
Mat(std::initializer_list< T2 > list)
Definition core.hpp:736
MatViewT< T, n_cols, n_rows, tType(type)> t_() const
Definition core.hpp:6212
RowVec< T, n_cols > diagRowVec() const
Take the diagonal row vector of a matrix and make a copy.
Definition core.hpp:6475
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:1861
Mat(const Mat &mat)
Copy constructor from a Mat object.
Definition core.hpp:654
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:1990
Mat & add(const M< T2, n_rows, n_cols, type2, _unused... > &mat_R)
Matrix self plus a matrix.
Definition core.hpp:1387
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:6490
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:5427
MatView< T, n_rows, n_cols, type > operator+() const
The unary plus operator.
Definition core.hpp:6754
T operator()(size_t r, size_t c) const
Get read only data element by row index and column index.
Definition core.hpp:887
Mat(const Mat< T2, _rows, _cols, _type > &mat)
Definition core.hpp:673
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:1053
Mat(const std::vector< T > &vec)
Construct a new Mat object from std::vector.
Definition core.hpp:718
Mat< T, n_rows, n_cols, MatType::DIAGONAL > diagMat() const
Take the diagonal of a matrix and make a copy.
Definition core.hpp:6360
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:1411
T value_type
Definition core.hpp:603
void _tryPlus(size_t r, size_t c, T value)
Try to plus a value to a specific position.
Definition core.hpp:6839
Definition core.hpp:8641
void assign(M m)
Definition core.hpp:8672
T operator[](size_t index) const
Get the read only element by array row major index.
Definition core.hpp:8732
T operator()(size_t r, size_t c) const
Get the read only data element from row and column index.
Definition core.hpp:8700
T & operator()(size_t r, size_t c)
Definition core.hpp:8713
Vec< T, n_rows > asMat() const
Explicitly make a Mat copy.
Definition core.hpp:8755
T *const _data
Raw data pointer.
Definition core.hpp:8778
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:8648
T & operator[](size_t index)
Definition core.hpp:8734
static constexpr size_t size() noexcept
The data element number.
Definition core.hpp:8684
MatRefCol(const MatRefCol &m)
Copy constructor.
Definition core.hpp:8660
Vec< T, n_rows > asVec() const
Explicitly make a Mat (Vec) copy.
Definition core.hpp:8765
void print(const std::string &str="", std::ostream &os=std::cout) const
Definition core.hpp:8770
MatRefCol & operator=(const Mat< T_, n_rows_, n_cols_, type_ > &m)
Definition core.hpp:8663
static constexpr MatType pType() noexcept
Parent matrix as MatType.
Definition core.hpp:8691
Definition core.hpp:7303
T operator[](size_t index) const
Get the read only element by array row major index.
Definition core.hpp:7452
T operator()(size_t r, size_t c) const
Get the read only data element from row and column index.
Definition core.hpp:7359
void col(size_t c, const M< T2, rows_, cols_, type2, _unused... > &mat)
Definition core.hpp:7517
T *const _data
Definition core.hpp:7623
MatRef & operator=(const Mat< T, n_rows, n_cols, type > &m)
Definition core.hpp:7336
Mat< T, n_rows, n_cols, type > asMat() const
Explicitly make a Mat copy.
Definition core.hpp:7614
T & operator[](size_t index)
Get the writeable element by array row major index.
Definition core.hpp:7464
static constexpr size_t size() noexcept
The data element number.
Definition core.hpp:7326
void assign(M m)
Definition core.hpp:7345
MatViewT< T, n_cols, n_rows, type > t_() const
Definition core.hpp:7576
void setValue(T val)
Set all elements of the matrix to a value.
Definition core.hpp:7475
MatRef & col(const M< T2, rows_, cols_, type2, _unused... > &mat, size_t c)
Take a column of a matrix by index.
Definition core.hpp:7504
void print(const std::string &str="", std::ostream &os=std::cout) const
Definition core.hpp:7619
MatRef & add(const M< T2, n_rows, n_cols, type2, _unused... > &mat_R)
Definition core.hpp:7554
MatRef & sub(const M< T2, n_rows, n_cols, type2, _unused... > &mat_R)
Definition core.hpp:7566
T & operator()(size_t r, size_t c)
Get writeable data element by row index and column index.
Definition core.hpp:7404
Tp abssum() const
Definition core.hpp:7589
MatRef(Mat< T, n_rows, n_cols, type > &m)
Construct a new MatView object from raw data pointer.
Definition core.hpp:7310
void setZero()
Set all elements of the matrix to zero.
Definition core.hpp:7486
MatRef(const T *const ptr)
Definition core.hpp:7312
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:7541
Tp power() const
Definition core.hpp:7579
MatRef(const MatRef &m)
Copy constructor.
Definition core.hpp:7319
Definition core.hpp:8782
T *const _data
Raw data pointer.
Definition core.hpp:8920
T operator()(size_t r, size_t c) const
Get the read only data element from row and column index.
Definition core.hpp:8842
void assign(M m)
Definition core.hpp:8814
static constexpr size_t size() noexcept
The data element number.
Definition core.hpp:8826
static constexpr MatType pType() noexcept
Parent matrix as MatType.
Definition core.hpp:8833
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:8789
T & operator[](size_t index)
Definition core.hpp:8876
RowVec< T, n_cols > asMat() const
Explicitly make a Mat copy.
Definition core.hpp:8897
void print(const std::string &str="", std::ostream &os=std::cout) const
Definition core.hpp:8912
T operator[](size_t index) const
Get the read only element by array row major index.
Definition core.hpp:8874
MatRefRow & operator=(const Mat< T_, n_rows_, n_cols_, type_ > &m)
Definition core.hpp:8805
MatRefRow(const MatRefRow &m)
Copy constructor.
Definition core.hpp:8802
T & operator()(size_t r, size_t c)
Definition core.hpp:8855
RowVec< T, n_cols > asVec() const
Explicitly make a Mat (RowVec) copy.
Definition core.hpp:8907
Read only view version of a certain column as colunm vector.
Definition core.hpp:8424
T operator[](size_t index) const
Get the read only element by array row major index.
Definition core.hpp:8484
MatViewCol(const MatViewCol &m)
Copy constructor.
Definition core.hpp:8442
Vec< T, n_rows > asMat() const
Explicitly make a Mat copy.
Definition core.hpp:8505
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:8431
Vec< T, n_rows > asVec() const
Explicitly make a Mat (Vec) copy.
Definition core.hpp:8515
void print(const std::string &str="", std::ostream &os=std::cout) const
Definition core.hpp:8520
static constexpr size_t size() noexcept
The data element number.
Definition core.hpp:8449
T operator()(size_t r, size_t c) const
Get the read only data element from row and column index.
Definition core.hpp:8465
static constexpr MatType pType() noexcept
Parent matrix as MatType.
Definition core.hpp:8456
const T *const _data
Raw data pointer.
Definition core.hpp:8528
Read only view version of successive columns.
Definition core.hpp:8925
static constexpr size_t size() noexcept
The data element number.
Definition core.hpp:8951
MatViewCols(const Mat< T, n_rows, n_cols, matType< type_parent >()> &m)
Construct a new MatViewCols object from raw data pointer.
Definition core.hpp:8932
MatViewCols(const MatViewCols &m)
Copy constructor.
Definition core.hpp:8944
const T * _data
Raw data pointer.
Definition core.hpp:9054
T operator()(size_t r, size_t c) const
Get the read only data element from row and column index.
Definition core.hpp:8975
T operator[](size_t index) const
Get the read only element by array row major index.
Definition core.hpp:9020
Mat< T, n_rows, last_col - first_col+1, MatType::NORMAL > asMat() const
Explicitly make a Mat copy.
Definition core.hpp:9043
static constexpr MatType pType() noexcept
Parent matrix as MatType.
Definition core.hpp:8966
Read only view version of a diagonal matrix.
Definition core.hpp:7888
MatViewDiagMat(const Mat< T, N, N, matType< type_parent >()> &m)
Construct a new MatViewDiagMat object from a raw data pointer.
Definition core.hpp:7895
T operator()(size_t r, size_t c) const
Get the read only data element from row and column index.
Definition core.hpp:7950
static constexpr size_t size() noexcept
The data element number.
Definition core.hpp:7926
Mat< T, N, N, MatType::DIAGONAL > inv() const
Return a inverse matrix.
Definition core.hpp:7911
static constexpr MatType pType() noexcept
Parent matrix as MatType.
Definition core.hpp:7941
T operator[](size_t index) const
Get the read only element by array row major index.
Definition core.hpp:7983
Mat< T, N, N, MatType::DIAGONAL > asMat() const
Explicitly make a Mat copy.
Definition core.hpp:8009
MatViewDiagMat(const MatViewDiagMat &m)
Copy constructor.
Definition core.hpp:7904
const T * _data
Raw data pointer.
Definition core.hpp:8020
Read only view version of a diagonal matrix as row vector.
Definition core.hpp:8166
MatViewDiagRowVec(const MatViewDiagRowVec &m)
Copy constructor.
Definition core.hpp:8182
static constexpr MatType pType() noexcept
Parent matrix as MatType.
Definition core.hpp:8204
T operator[](size_t index) const
Get the read only element by array row major index.
Definition core.hpp:8246
MatViewDiagRowVec(const Mat< T, N, N, matType< type_parent >()> &m)
Construct a new MatViewDiagRowVec object from raw data pointer.
Definition core.hpp:8173
RowVec< T, N > asRowVec() const
Explicitly make a Mat (RowVec) copy.
Definition core.hpp:8278
const T * _data
Raw data pointer.
Definition core.hpp:8289
RowVec< T, N > asMat() const
Explicitly make a Mat copy.
Definition core.hpp:8268
T operator()(size_t r, size_t c) const
Get the read only data element from row and column index.
Definition core.hpp:8213
static constexpr size_t size() noexcept
The data element number.
Definition core.hpp:8189
Read only view version of a diagonal matrix as vector.
Definition core.hpp:8024
Vec< T, N > inv() const
Return a inverse matrix.
Definition core.hpp:8062
T operator[](size_t index) const
Get the read only element by array row major index.
Definition core.hpp:8119
MatViewDiagVec(const Mat< T, N, N, matType< type_parent >()> &m)
Construct a new MatViewDiagVec object from raw data pointer.
Definition core.hpp:8031
Vec< T, N > asVec() const
Explicitly make a Mat (Vec) copy.
Definition core.hpp:8151
static constexpr size_t size() noexcept
The data element number.
Definition core.hpp:8047
static constexpr MatType pType() noexcept
Parent matrix as MatType.
Definition core.hpp:8077
const T * _data
Raw data pointer.
Definition core.hpp:8162
T operator()(size_t r, size_t c) const
Get the read only data element from row and column index.
Definition core.hpp:8086
MatViewDiagVec(const MatViewDiagVec &m)
Copy constructor.
Definition core.hpp:8040
Vec< T, N > asMat() const
Explicitly make a Mat copy.
Definition core.hpp:8141
Read only view version of a matrix.
Definition core.hpp:7057
static constexpr size_t size() noexcept
The data element number.
Definition core.hpp:7081
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:7217
void assign(M m)
Definition core.hpp:7100
MatView(const T *const ptr)
Definition core.hpp:7067
MatView(Mat< T, n_rows, n_cols, type > &m)
Definition core.hpp:7065
T operator()(size_t r, size_t c) const
Get the read only data element from row and column index.
Definition core.hpp:7114
MatView & operator=(const Mat< T, n_rows, n_cols, type > &m)
Definition core.hpp:7091
void print(const std::string &str="", std::ostream &os=std::cout) const
Definition core.hpp:7295
MatView & sub(const M< T2, n_rows, n_cols, type2, _unused... > &mat_R)
Definition core.hpp:7242
const T *const _data
Definition core.hpp:7299
MatViewT< T, n_cols, n_rows, type > t_() const
Definition core.hpp:7252
T operator[](size_t index) const
Get the read only element by array row major index.
Definition core.hpp:7158
MatView(const Mat< T, n_rows, n_cols, type > &m)
Construct a new MatView object from raw data pointer.
Definition core.hpp:7064
Tp abssum() const
Definition core.hpp:7265
Tp power() const
Definition core.hpp:7255
MatView & col(const M< T2, rows_, cols_, type2, _unused... > &mat, size_t c)
Take a column of a matrix by index.
Definition core.hpp:7180
MatView(const MatView &m)
Copy constructor.
Definition core.hpp:7074
void col(size_t c, const M< T2, rows_, cols_, type2, _unused... > &mat)
Definition core.hpp:7193
Mat< T, n_rows, n_cols, type > asMat() const
Explicitly make a Mat copy.
Definition core.hpp:7290
MatView & add(const M< T2, n_rows, n_cols, type2, _unused... > &mat_R)
Definition core.hpp:7230
Read only view version of a off diagonal.
Definition core.hpp:8293
T operator()(size_t r, size_t c) const
Get the read only data element from row and column index.
Definition core.hpp:8340
static constexpr size_t size() noexcept
The data element number.
Definition core.hpp:8316
MatViewOffDiag(const MatViewOffDiag &m)
Copy constructor.
Definition core.hpp:8309
const T * _data
Raw data pointer.
Definition core.hpp:8420
T operator[](size_t index) const
Get the read only element by array row major index.
Definition core.hpp:8383
Mat< T, N, N, MatType::NORMAL > asMat() const
Explicitly make a Mat copy.
Definition core.hpp:8409
static constexpr MatType pType() noexcept
Parent matrix as MatType.
Definition core.hpp:8331
MatViewOffDiag(const Mat< T, N, N, matType< type_parent >()> &m)
Construct a new MatViewOffDiag object from raw data pointer.
Definition core.hpp:8300
Read only view version of the opposite of a matrix.
Definition core.hpp:7627
MatViewOpp(const Mat< T, n_cols, n_rows, type > &m)
Construct a new MatViewOpp object from raw data pointer.
Definition core.hpp:7634
T operator()(size_t r, size_t c) const
Get the read only data element from row and column index.
Definition core.hpp:7665
const T * _data
Definition core.hpp:7735
MatViewOpp(const MatViewOpp &m)
Copy constructor.
Definition core.hpp:7641
static constexpr size_t size() noexcept
The data element number.
Definition core.hpp:7648
Mat< T, n_rows, n_cols, type > asMat() const
Explicitly make a Mat copy.
Definition core.hpp:7729
T operator[](size_t index) const
Get the read only element by array row major index.
Definition core.hpp:7708
Read only view version of a certain row as row vector.
Definition core.hpp:8532
Vec< T, n_rows > asRowVec() const
Explicitly make a Mat (RowVec) copy.
Definition core.hpp:8624
T operator()(size_t r, size_t c) const
Get the read only data element from row and column index.
Definition core.hpp:8574
T operator[](size_t index) const
Get the read only element by array row major index.
Definition core.hpp:8593
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:8539
static constexpr MatType pType() noexcept
Parent matrix as MatType.
Definition core.hpp:8565
RowVec< T, n_cols > asMat() const
Explicitly make a Mat copy.
Definition core.hpp:8614
const T *const _data
Raw data pointer.
Definition core.hpp:8637
static constexpr size_t size() noexcept
The data element number.
Definition core.hpp:8558
MatViewRow(const MatViewRow &m)
Copy constructor.
Definition core.hpp:8551
void print(const std::string &str="", std::ostream &os=std::cout) const
Definition core.hpp:8629
Read only view version of successive rows.
Definition core.hpp:9059
static constexpr size_t size() noexcept
The data element number.
Definition core.hpp:9085
Mat< T, last_row - first_row+1, n_cols, MatType::NORMAL > asMat() const
Explicitly make a Mat copy.
Definition core.hpp:9177
static constexpr MatType pType() noexcept
Parent matrix as MatType.last_col.
Definition core.hpp:9100
const T * _data
Raw data pointer.
Definition core.hpp:9198
T operator[](size_t index) const
Get the read only element by array row major index.
Definition core.hpp:9156
Mat< T, last_row - first_row+1, n_cols, MatType::NORMAL > asVec() const
Explicitly make a Mat (Vec) copy.
Definition core.hpp:9187
MatViewRows(const Mat< T, n_cols, n_rows, matType< type_parent >()> &m)
Construct a new MatViewRows object from raw data pointer.
Definition core.hpp:9066
T operator()(size_t r, size_t c) const
Get the read only data element from row and column index.
Definition core.hpp:9109
MatViewRows(const MatViewRows &m)
Copy constructor.
Definition core.hpp:9078
Read only view version of a transposed matrix.
Definition core.hpp:7739
MatViewT(const Mat< T, n_cols, n_rows, tType(type)> &m)
Construct a new MatViewT object from raw data pointer.
Definition core.hpp:7746
T operator()(size_t r, size_t c) const
Get the read only data element from row and column index.
Definition core.hpp:7782
static constexpr size_t size() noexcept
The data element number.
Definition core.hpp:7765
MatViewT(T *ptr)
Definition core.hpp:7758
T *const _data
Raw data pointer.
Definition core.hpp:7884
MatViewT(Mat< T, n_cols, n_rows, tType(type)> &m)
Definition core.hpp:7747
T operator[](size_t index) const
Get the read only element by array row major index.
Definition core.hpp:7825
Mat< T, n_rows, n_cols, type > asMat() const
Explicitly make a Mat copy.
Definition core.hpp:7872
MatViewT(const MatViewT &m)
Copy constructor.
Definition core.hpp:7754
Tensor.
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:566
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::DIAGONAL > MATTYPE_DIAGONAL
Diagonal matrix as a class type.
Definition core.hpp:187
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:9404
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:9247
constexpr MatType sumType(MatType type1, MatType type2) noexcept
Summation type of two matrices.
Definition core.hpp:229
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::SUPPER > MATTYPE_SUPPER
Strict upper triangular matrix as a class type.
Definition core.hpp:195
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:9750
constexpr size_t supperRow(size_t index, size_t N)
Calculate the row index of a strict upper triangular matrix.
Definition core.hpp:350
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 greater or equal comparison.
Definition core.hpp:9718
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:9782
std::integral_constant< int, MatType::NORMAL > MATTYPE_NORMAL
Normal matrix as a class type.
Definition core.hpp:185
Init
Definition core.hpp:572
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:9590
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:9275
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:9328
constexpr size_t slowerRow(size_t index, size_t N)
Calculate the row index of a strict lower triangular matrix.
Definition core.hpp:366
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
Mat< T, 1, N > RowVec
Row vector.
Definition core.hpp:422
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:9563
constexpr MatType tType(MatType type) noexcept
Transpose type of a matrix.
Definition core.hpp:303
std::integral_constant< int, MatType::UPPER > MATTYPE_UPPER
Upper triangular matrix as a class type.
Definition core.hpp:191
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:9654
Mat< T, N, 1 > Vec
Column vector.
Definition core.hpp:412
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:9822
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:9300
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:9622
std::integral_constant< int, MatType::SLOWER > MATTYPE_SLOWER
Strict lower triangular matrix as a class type.
Definition core.hpp:197
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:9686
std::integral_constant< int, type > MType
Get the class form of MatType.
Definition core.hpp:220
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:9797
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:9223
constexpr MatType matType()
Get the MatType value from the class form.
Definition core.hpp:210