ARCS6 AR6-REV.24062600
読み取り中…
検索中…
一致する文字列を見つけられません
Matrix.hh
[詳解]
1
5//
6// Copyright (C) 2011-2022 Yokokura, Yuki
7// This program is free software;
8// you can redistribute it and/or modify it under the terms of the BSD License.
9// For details, see the License.txt file.
10//
11// 以下,コメント。
12// ・各々の関数における計算結果はMATLAB/Maximaと比較して合っていることを確認している。
13// ・ただし,LU分解やコレスキー分解などの一見した表現が定まらない関数では,当然,MATLABとは異なる結果を出力するように見える。
14// ・動的メモリ版に比べてかなり高速の行列演算が可能。
15
16#ifndef MATRIX
17#define MATRIX
18
19#include <string>
20#include <cmath>
21#include <cassert>
22#include <array>
23#include <complex>
24
25// ARCS組込み用マクロ
26#ifdef ARCS_IN
27 // ARCSに組み込まれる場合
28 #include "ARCSassert.hh"
29#else
30 // ARCSに組み込まれない場合
31 #define arcs_assert(a) (assert(a))
32#endif
33
34#define PrintMatSize(a) (PrintMatSize_Macro((a),#a))
35#define PrintMatrix(a,b) (PrintMatrix_Macro((a),b,#a))
36#define PrintMat(a) (PrintMat_Macro((a),#a))
37
38namespace ARCS { // ARCS名前空間
43template <size_t NN, size_t MM, typename TT = double>
44class Matrix {
45 public:
47 enum LUperm {
49 EVEN
50 };
51
53 constexpr Matrix()
54 : Nindex(0), Mindex(0), Data({0})
55 {
56 static_assert(NN != 0); // サイズゼロの行列は禁止
57 static_assert(MM != 0); // サイズゼロの行列は禁止
58 FillAll(0); // すべての要素を零で初期化
59 }
60
63 constexpr explicit Matrix(const TT InitValue)
64 : Nindex(0), Mindex(0), Data({0})
65 {
66 static_assert(NN != 0); // サイズゼロの行列は禁止
67 static_assert(MM != 0); // サイズゼロの行列は禁止
68 FillAll(InitValue); // すべての要素を指定した値で初期化
69 }
70
73 constexpr Matrix(std::initializer_list<TT> InitList)
74 : Nindex(0), Mindex(0), Data({0})
75 {
76 static_assert(NN != 0); // サイズゼロの行列は禁止
77 static_assert(MM != 0); // サイズゼロの行列は禁止
78 const TT* ListVal = InitList.begin(); // 初期化リストの最初のポインタ位置
79 size_t Ni = 0; // 行カウンタ
80 size_t Mi = 0; // 列カウンタ
81 for(size_t i = 0; i < InitList.size(); ++i){
82 // 初期化リストを順番に読み込んでいく
83 assert(Ni < N); // 行カウンタが行の長さ以内かチェック
84 assert(Mi < M); // 列カウンタが列の長さ以内かチェック
85 Data[Ni][Mi] = (TT)ListVal[i]; // 行列の要素を埋める
86 Ni++; // 行カウンタをインクリメント
87 if(Ni == N){ // 行カウンタが最後まで行き着いたら,
88 Ni = 0; // 行カウンタを零に戻して,
89 Mi++; // その代わりに,列カウンタをインクリメント
90 }
91 }
92 }
93
94 /*
96 Matrix(Matrix&& r)
97 : Nindex(0), Mindex(0), Data(std::move(r.Data))
98 {
99
100 }
101 */
102
104 constexpr Matrix(const Matrix& right)
105 : Nindex(0), Mindex(0), Data(right.Data)
106 {
107
108 }
109
110 /* constexprコンストラクタのための「trivial destructor」
112 ~Matrix(){
113
114 }
115 */
116
120 constexpr auto& operator=(const Matrix& right){
121 static_assert(this->N == right.N, "Matrix Size Error"); // 行列のサイズチェック
122 static_assert(this->M == right.M, "Matrix Size Error"); // 行列のサイズチェック
123 for(size_t i = 0; i < N; ++i){
124 for(size_t j = 0; j < M; ++j) this->Data[i][j] = right.Data[i][j];
125 }
126 return (*this);
127 }
128
131 constexpr auto operator+(void) const{
132 Matrix ret;
133 for(size_t i = 0; i < N; ++i){
134 for(size_t j = 0; j < M; ++j) ret.Data[i][j] = Data[i][j];
135 }
136 return ret;
137 }
138
141 constexpr auto operator-(void) const{
142 Matrix ret;
143 for(size_t i = 0; i < N; ++i){
144 for(size_t j = 0; j < M; ++j) ret.Data[i][j] = -Data[i][j];
145 }
146 return ret;
147 }
148
152 constexpr auto operator+(const Matrix& right) const{
153 static_assert(N == right.N, "Matrix Size Error"); // 行列のサイズチェック
154 static_assert(M == right.M, "Matrix Size Error"); // 行列のサイズチェック
155 Matrix ret;
156 for(size_t i = 0; i < N; ++i){
157 for(size_t j = 0; j < M; ++j) ret.Data[i][j] = Data[i][j] + right.Data[i][j];
158 }
159 return ret;
160 }
161
165 constexpr auto operator+(const TT& right) const{
166 Matrix ret;
167 for(size_t i = 0; i < N; ++i){
168 for(size_t j = 0; j < M; ++j) ret.Data[i][j] = Data[i][j] + right;
169 }
170 return ret;
171 }
172
176 constexpr auto operator-(const Matrix& right) const{
177 static_assert(N == right.N, "Matrix Size Error"); // 行列のサイズチェック
178 static_assert(M == right.M, "Matrix Size Error"); // 行列のサイズチェック
179 Matrix ret;
180 for(size_t i = 0; i < N; ++i){
181 for(size_t j = 0; j < M; ++j) ret.Data[i][j] = Data[i][j] - right.Data[i][j];
182 }
183 return ret;
184 }
185
189 constexpr auto operator-(const TT& right) const{
190 Matrix ret;
191 for(size_t i = 0; i < N; ++i){
192 for(size_t j = 0; j < M; ++j) ret.Data[i][j] = Data[i][j] - right;
193 }
194 return ret;
195 }
196
200 template <size_t Nright, size_t Mright, typename Tright>
201 constexpr auto operator*(const Matrix<Nright,Mright,Tright>& right) const{
202 static_assert(N == right.M, "Matrix Size Error"); // 行列のサイズチェック
203 Matrix<right.N,M,TT> ret;
204 for(size_t k = 0; k < right.N; ++k){
205 for(size_t i = 0; i < N; ++i){
206 for(size_t j = 0; j < M; ++j) ret.Data[k][j] += Data[i][j]*right.Data[k][i];
207 }
208 }
209 return ret;
210 }
211
215 constexpr auto operator*(const TT& right) const{
216 Matrix ret;
217 for(size_t i = 0; i < N; ++i){
218 for(size_t j = 0; j < M; ++j) ret.Data[i][j] = Data[i][j]*right;
219 }
220 return ret;
221 }
222
226 constexpr auto operator/(const TT& right) const{
227 Matrix ret;
228 for(size_t i = 0; i < N; ++i){
229 for(size_t j = 0; j < M; ++j) ret.Data[i][j] = Data[i][j]/right;
230 }
231 return ret;
232 }
233
237 constexpr auto& operator+=(const Matrix& right){
238 static_assert(this->N == right.N, "Matrix Size Error"); // 行列のサイズチェック
239 static_assert(this->M == right.M, "Matrix Size Error"); // 行列のサイズチェック
240 for(size_t i = 0; i < N; ++i){
241 for(size_t j = 0; j < M; ++j) this->Data[i][j] = this->Data[i][j] + right.Data[i][j];
242 }
243 return (*this);
244 }
245
249 constexpr auto& operator+=(const TT& right){
250 for(size_t i = 0; i < N; ++i){
251 for(size_t j = 0; j < M; ++j) this->Data[i][j] = this->Data[i][j] + right;
252 }
253 return (*this);
254 }
255
259 constexpr auto& operator-=(const Matrix& right){
260 static_assert(this->N == right.N, "Matrix Size Error"); // 行列のサイズチェック
261 static_assert(this->M == right.M, "Matrix Size Error"); // 行列のサイズチェック
262 for(size_t j = 0; j < M; ++j){
263 for(size_t i = 0; i < N; ++i) this->Data[i][j] = this->Data[i][j] - right.Data[i][j];
264 }
265 return (*this);
266 }
267
271 constexpr auto& operator-=(const TT& right){
272 for(size_t i = 0; i < N; ++i){
273 for(size_t j = 0; j < M; ++j) this->Data[i][j] = this->Data[i][j] - right;
274 }
275 return (*this);
276 }
277
281 constexpr auto operator^(const size_t& right) const{
282 Matrix A;
283 for(size_t i = 0; i < N; ++i){
284 for(size_t j = 0; j < M; ++j) A.Data[i][j] = Data[i][j];
285 }
286 Matrix ret = A;
287 for(size_t k = 1; k < right; ++k) ret = ret*A;
288 return ret;
289 }
290
294 constexpr auto operator&(const Matrix& right) const{
295 static_assert(N == right.N, "Matrix Size Error"); // 行列のサイズチェック
296 static_assert(M == right.M, "Matrix Size Error"); // 行列のサイズチェック
297 Matrix ret;
298 for(size_t i = 0; i < N; ++i){
299 for(size_t j = 0; j < M; ++j) ret.Data[i][j] = Data[i][j]*right.Data[i][j];
300 }
301 return ret;
302 }
303
307 constexpr auto operator%(const Matrix& right) const{
308 static_assert(N == right.N, "Matrix Size Error"); // 行列のサイズチェック
309 static_assert(M == right.M, "Matrix Size Error"); // 行列のサイズチェック
310 Matrix ret;
311 for(size_t i = 0; i < N; ++i){
312 for(size_t j = 0; j < M; ++j) ret.Data[i][j] = Data[i][j]/right.Data[i][j];
313 }
314 return ret;
315 }
316
320 constexpr TT operator[](size_t m) const{
321 arcs_assert(m != 0); // 「0」始まり防止チェック
322 return Data[0][m-1];
323 }
324
328 constexpr TT& operator[](size_t m){
329 arcs_assert(m != 0); // 「0」始まり防止チェック
330 return Data[0][m-1];
331 }
332
337 constexpr TT operator()(size_t m, size_t n) const{
338 return Data[n-1][m-1];
339 }
340
345 constexpr TT& operator()(size_t m, size_t n){
346 return Data[n-1][m-1];
347 }
348
352 constexpr friend Matrix operator+(const TT& left, const Matrix& right){
353 Matrix ret;
354 for(size_t i = 0; i < right.N; ++i){
355 for(size_t j = 0; j < right.M; ++j) ret.Data[i][j] = left + right.Data[i][j];
356 }
357 return ret;
358 }
359
363 constexpr friend Matrix operator-(const TT& left, const Matrix& right){
365 for(size_t i = 0; i < right.N; ++i){
366 for(size_t j = 0; j < right.M; ++j) ret.Data[i][j] = left - right.Data[i][j];
367 }
368 return ret;
369 }
370
374 constexpr friend Matrix operator*(const TT& left, const Matrix& right){
376 for(size_t i = 0; i < right.N; ++i){
377 for(size_t j = 0; j < right.M; ++j) ret.Data[i][j] = right.Data[i][j]*left;
378 }
379 return ret;
380 }
381
384 template<typename T1, typename... T2> // 可変長引数テンプレート
385 constexpr void Set(const T1& u1, const T2&... u2){ // 再帰で順番に可変長引数を読み込んでいく
386 arcs_assert(Nindex < N); // 行カウンタが行の長さ以内かチェック
387 arcs_assert(Mindex < M); // 列カウンタが列の長さ以内かチェック
388 Data[Nindex][Mindex] = (TT)u1; // 行列の要素を埋める
389 Nindex++; // 行カウンタをインクリメント
390 if(Nindex == N){ // 行カウンタが最後まで行き着いたら,
391 Nindex = 0; // 行カウンタを零に戻して,
392 Mindex++; // その代わりに,列カウンタをインクリメント
393 }
394 Set(u2...); // 自分自身を呼び出す(再帰)
395 }
396 constexpr void Set(){
397 // 再帰の最後に呼ばれる関数
398 Nindex = 0; // すべての作業が終わったので,
399 Mindex = 0; // 行,列カウンタを零に戻しておく
400 }
401
404 template<typename T1, typename... T2> // 可変長引数テンプレート
405 constexpr void Get(T1& u1, T2&... u2){ // 再帰で順番に可変長引数を読み込んでいく
406 arcs_assert(Nindex < N); // 行カウンタが行の長さ以内かチェック
407 arcs_assert(Mindex < M); // 列カウンタが列の長さ以内かチェック
408 u1 = Data[Nindex][Mindex]; // 行列の要素から読み込み
409 Nindex++; // 行カウンタをインクリメント
410 if(Nindex == N){ // 行カウンタが最後まで行き着いたら,
411 Nindex = 0; // 行カウンタを零に戻して,
412 Mindex++; // その代わりに,列カウンタをインクリメント
413 }
414 Get(u2...); // 自分自身を呼び出す(再帰)
415 }
416 constexpr void Get(){
417 // 再帰の最後に呼ばれる関数
418 Nindex = 0; // すべての作業が終わったので,
419 Mindex = 0; // 行,列カウンタを零に戻しておく
420 }
421
424 constexpr void LoadArray(const std::array<TT, MM>& Array){
425 arcs_assert(N == 1);
426 arcs_assert(M == MM);
427 for(size_t j = 0; j < M; ++j) Data[0][j] = Array[j];
428 }
429
432 constexpr void StoreArray(std::array<TT, MM>& Array) const{
433 arcs_assert(N == 1);
434 arcs_assert(M == MM);
435 for(size_t j = 0; j < M; ++j) Array[j] = Data[0][j];
436 }
437
440 constexpr void LoadArray(const std::array<std::array<TT, NN>, MM>& Array){
441 arcs_assert(N == NN);
442 arcs_assert(M == MM);
443 for(size_t i = 0; i < N; ++i){
444 for(size_t j = 0; j < M; ++j) Data[i][j] = Array[j][i];
445 }
446 }
447
450 template<size_t VM>
451 constexpr void LoadShortVector(const Matrix<1,VM,TT>& v){
452 static_assert(VM < MM); // 読み込む縦ベクトルの方が短いかチェック
453 for(size_t i = 0; i < VM; ++i){
454 Data[0][i] = v.Data[0][i];
455 }
456 }
457
462 constexpr void SetElem(size_t m, size_t n, TT val){
463 arcs_assert(1<=n && n<=N && 1<=m && m<=M); // サイズチェック
464 Data[n-1][m-1] = val;
465 }
466
471 constexpr TT GetElem(size_t m, size_t n) const {
472 arcs_assert(1<=n && n<=N && 1<=m && m<=M); // サイズチェック
473 return Data[n-1][m-1];
474 }
475
480 constexpr void SetElement(size_t n, size_t m, TT val){
481 arcs_assert(1<=n && n<=N && 1<=m && m<=M); // サイズチェック
482 Data[n-1][m-1] = val;
483 }
484
489 constexpr TT GetElement(size_t n, size_t m) const {
490 arcs_assert(1<=n && n<=N && 1<=m && m<=M); // サイズチェック
491 return Data[n-1][m-1];
492 }
493
498 template<size_t VM>
499 constexpr Matrix<1,VM,TT> GetVerticalVec(size_t n, size_t m){
500 arcs_assert(1<=n && n<=N && 1<=m && m<=M); // サイズチェック
502 for(size_t i = 0; i < VM; ++i){
503 r.Data[0][i] = Data[n-1][m-1+i];
504 }
505 return r;
506 }
507
512 template<size_t HN>
513 constexpr Matrix<HN,1,TT> GetHorizontalVec(size_t n, size_t m){
514 arcs_assert(1<=n && n<=N && 1<=m && m<=M); // サイズチェック
516 for(size_t i = 0; i < HN; ++i){
517 r.Data[i][0] = Data[n-1+i][m-1];
518 }
519 return r;
520 }
521
526 template<size_t VM>
527 constexpr void SetVerticalVec(Matrix<1,VM,TT> v, size_t n, size_t m){
528 arcs_assert(1<=n && n<=N && 1<=m && m<=M); // サイズチェック
529 for(size_t i = 0; i < VM; ++i){
530 Data[n-1][m-1+i] = v.Data[0][i];
531 }
532 }
533
538 template<size_t HN>
539 constexpr void SetHorizontalVec(Matrix<HN,1,TT> h, size_t n, size_t m){
540 arcs_assert(1<=n && n<=N && 1<=m && m<=M); // サイズチェック
541 for(size_t i = 0; i < HN; ++i){
542 Data[n-1+i][m-1] = h.Data[i][0];
543 }
544 }
545
548 constexpr void FillAll(TT u){
549 for(size_t i = 0; i < N; ++i){
550 for(size_t j = 0; j < M; ++j) Data[i][j] = u;
551 }
552 }
553
555 constexpr void FillAllZero(void){
556 FillAll(0);
557 }
558
561 constexpr size_t GetWidthLength(void) const {
562 return N;
563 }
564
567 constexpr size_t GetHeightLength(void) const {
568 return M;
569 }
570
573 constexpr bool isEnabledSIMD(void){
574 return false;
575 }
576
580 friend void PrintMatSize_Macro(const Matrix& u, const std::string& varname){
581 printf("%s = [ %zu x %zu ]\n", varname.c_str(), u.N, u.M);
582 }
583
588 friend void PrintMatrix_Macro(const Matrix& u, const std::string& format, const std::string& varname){
589 printf("%s = \n", varname.c_str());
590 for(size_t j = 0; j < u.M; ++j){
591 printf("[ ");
592 for(size_t i = 0; i < u.N; ++i){
593 // データ型によって表示方法を変える
594 if constexpr(std::is_same_v<TT, std::complex<double>> || std::is_same_v<TT, std::complex<float>>){
595 // 複素数型の場合
596 // 実数部の表示
597 printf(format.c_str(), u.Data[i][j].real());
598 // 虚数部の表示
599 if(0.0 <= u.Data[i][j].imag()){
600 printf(" + j");
601 }else{
602 printf(" - j");
603 }
604 printf( format.c_str(), std::abs(u.Data[i][j].imag()) );
605 }else{
606 // それ以外の場合
607 printf(format.c_str(), u.Data[i][j]);
608 }
609 printf(" ");
610 }
611 printf("]\n");
612 }
613 printf("\n");
614 }
615
619 friend void PrintMat_Macro(const Matrix& u, const std::string& varname){
620 // データ型によって書式指定子を変える
621 // double型かfloat型の場合
622 if constexpr(std::is_same_v<TT, double> || std::is_same_v<TT, float>){
623 PrintMatrix_Macro(u, "% g", varname);
624 return;
625 }
626
627 // int型の場合
628 if constexpr(std::is_same_v<TT, int>){
629 PrintMatrix_Macro(u, "% d", varname);
630 return;
631 }
632
633 // long型の場合
634 if constexpr(std::is_same_v<TT, long>){
635 PrintMatrix_Macro(u, "% ld", varname);
636 return;
637 }
638
639 // 複素数型の場合
640 if constexpr(std::is_same_v<TT, std::complex<double>> || std::is_same_v<TT, std::complex<float>>){
641 PrintMatrix_Macro(u, "% g", varname);
642 return;
643 }
644 }
645
648 static constexpr Matrix zeros(void){
649 Matrix ret;
650 return ret;
651 }
652
655 static constexpr Matrix ones(void){
656 Matrix ret;
657 ret.FillAll(1);
658 return ret;
659 }
660
663 static constexpr Matrix<NN,NN,TT> ident(void){
664 static_assert(NN == MM, "Matrix Size Error"); // 行列のサイズチェック
665 Matrix ret;
666 if constexpr(std::is_same_v<TT, std::complex<double>> || std::is_same_v<TT, std::complex<float>>){
667 // 複素数型の場合
668 for(size_t i = 0; i < N; ++i) ret.SetElem(i+1,i+1, std::complex(1.0,0.0)); // 対角成分を 1 + j0 で埋める
669 }else{
670 // それ以外の場合
671 for(size_t i = 0; i < N; ++i) ret.SetElem(i+1,i+1, 1); // 対角成分を 1 で埋める
672 }
673 return ret;
674 }
675
678 static constexpr Matrix<NN,NN,TT> eye(void){
680 }
681
684 static constexpr Matrix ramp(void){
685 static_assert(NN == 1, "Matrix Size Error"); // 行列のサイズチェック
686 Matrix ret;
687 for(size_t j = 1; j <= M; ++j) ret[j] = j; // 単調増加を書き込む
688 return ret;
689 }
690
694 constexpr friend Matrix<MM,NN,TT> tp(const Matrix<NN,MM,TT>& U){
695 Matrix<U.M,U.N,TT> y;
696 for(size_t j = 0; j < U.M; ++j){
697 for(size_t i = 0; i < U.N; ++i) y.Data[j][i] = U.Data[i][j];
698 }
699 return y;
700 }
701
705 constexpr friend TT tr(const Matrix& U){
706 static_assert(U.N == U.M, "Matrix Size Error"); // 正方行列であることのチェック
707 TT y = 0;
708 for(size_t i = 0; i < U.N; ++i) y += (TT)U.Data[i][i];
709 return y;
710 }
711
715 constexpr friend TT prod(const Matrix& U){
716 static_assert(U.N == U.M, "Matrix Size Error"); // 正方行列であることのチェック
717 TT y = 1;
718 for(size_t i = 0; i < U.N; ++i) y *= U.Data[i][i];
719 return y;
720 }
721
725 constexpr friend Matrix<1,std::min(NN,MM),TT> diag(const Matrix& U){
726 constexpr size_t K = std::min(NN,MM);
728 for(size_t i = 0; i < K; ++i) y.Data[0][i] = U.Data[i][i];
729 return y;
730 }
731
735 constexpr friend Matrix<1,MM,TT> sumrow(const Matrix& U){
736 Matrix<1,U.M,TT> y;
737 for(size_t i = 0; i < U.N; ++i){
738 for(size_t j = 0; j < U.M; ++j) y.Data[0][j] += U.Data[i][j];
739 }
740 return y;
741 }
742
746 constexpr friend Matrix<NN,1,TT> sumcolumn(const Matrix& U){
747 Matrix<U.N,1,TT> y;
748 for(size_t i = 0; i < U.N; ++i){
749 for(size_t j = 0; j < U.M; ++j) y.Data[i][0] += U.Data[i][j];
750 }
751 return y;
752 }
753
757 constexpr friend double sumall(const Matrix& U){
758 const Matrix<1,1> y = sumrow(sumcolumn(U));
759 return y[1];
760 }
761
765 constexpr friend TT max(const Matrix& u){
766 static_assert( (u.N == 1)||(u.M == 1), "Input is NOT vector." ); // ベクトルかチェック
767 size_t k = 0;
768 TT y = 0;
769 if(u.M == 1){
770 // 行ベクトルの場合
771 for(size_t i = 1; i < u.N; ++i)if(u.Data[k][0] < u.Data[i][0]) k = i;
772 y = u.Data[k][0];
773 }
774 if(u.N == 1){
775 // 列ベクトルの場合
776 for(size_t i = 1; i < u.M; ++i)if(u.Data[0][k] < u.Data[0][i]) k = i;
777 y = u.Data[0][k];
778 }
779 return y;
780 }
781
785 constexpr friend TT absmax(const Matrix& u){
786 static_assert( (u.N == 1)||(u.M == 1), "Input is NOT vector." ); // ベクトルかチェック
787 size_t k = 0;
788 TT y = 0;
789 if(u.M == 1){
790 // 行ベクトルの場合
791 for(size_t i = 1; i < u.N; ++i)if(fabs(u.Data[k][0]) < fabs(u.Data[i][0])) k = i;
792 y = u.Data[k][0];
793 }
794 if(u.N == 1){
795 // 列ベクトルの場合
796 for(size_t i = 1; i < u.M; ++i)if(fabs(u.Data[0][k]) < fabs(u.Data[0][i])) k = i;
797 y = u.Data[0][k];
798 }
799 return y;
800 }
801
805 constexpr friend size_t maxidx(const Matrix& u){
806 static_assert( (u.N == 1)||(u.M == 1), "Input is NOT vector." ); // ベクトルかチェック
807 size_t k = 0;
808 if(u.M == 1){
809 // 行ベクトルの場合
810 for(size_t i = 1; i < u.N; ++i)if(u.Data[k][0] < u.Data[i][0]) k = i;
811 }
812 if(u.N == 1){
813 // 列ベクトルの場合
814 for(size_t i = 1; i < u.M; ++i)if(u.Data[0][k] < u.Data[0][i]) k = i;
815 }
816 return k + 1;
817 }
818
822 constexpr friend size_t absmaxidx(const Matrix& u){
823 static_assert( (u.N == 1)||(u.M == 1), "Input is NOT vector." ); // ベクトルかチェック
824 size_t k = 0;
825 if(u.M == 1){
826 // 行ベクトルの場合
827 for(size_t i = 1; i < u.N; ++i)if(fabs(u.Data[k][0]) < fabs(u.Data[i][0])) k = i;
828 }
829 if(u.N == 1){
830 // 列ベクトルの場合
831 for(size_t i = 1; i < u.M; ++i)if(fabs(u.Data[0][k]) < fabs(u.Data[0][i])) k = i;
832 }
833 return k + 1;
834 }
835
839 constexpr friend size_t nonzeroele(const Matrix& U){
840 size_t ret = 0;
841 for(size_t i = 0; i < U.N; ++i){
842 for(size_t j = 0; j < U.M; ++j){
843 if(epsilon < std::abs(U.Data[i][j])) ++ret;
844 }
845 }
846 return ret;
847 }
848
852 constexpr friend size_t rank(const Matrix& A){
853 static_assert(NN == MM, "Matrix Size Error"); // 正方行列のみ対応
854 Matrix<NN,NN,TT> U, S, V;
855 SVD(A, U, S, V); // まず特異値分解して,
856 return nonzeroele(diag(S)); // S行列の対角要素の非ゼロをカウントするとそれがランク
857 }
858
863 constexpr friend Matrix<NN,1,TT> getrow(const Matrix& U, size_t m){
864 arcs_assert(0 < m && m <= U.M); // 指定した行が行列の高さ以内かチェック
865 Matrix<U.N,1,TT> y;
866 for(size_t i=0;i<U.N;i++) y.Data[i][0] = U.Data[i][m-1];
867 return y;
868 }
869
874 constexpr friend void setrow(Matrix& U, const Matrix<NN,1,TT>& v, size_t m){
875 static_assert(U.N == v.N, "Matrix Size Error"); // 行列の幅と横ベクトルの長さが等しいかチェック
876 static_assert(v.M == 1, "Input is NOT vector.");// 行ベクトルかチェック
877 arcs_assert(0 < m && m <= U.M); // 指定した行が行列の高さ以内かチェック
878 for(size_t i=0;i<U.N;i++) U.Data[i][m-1] = v.Data[i][0];
879 }
880
885 constexpr friend void setrow(Matrix& U, const std::array<TT, NN>& v, size_t m){
886 static_assert(U.N == NN, "Matrix Size Error"); // 行列の幅と横ベクトルの長さが等しいかチェック
887 arcs_assert(0 < m && m <= U.M); // 指定した行が行列の高さ以内かチェック
888 for(size_t i=0;i<U.N;i++) U.Data[i][m-1] = v.at(i);
889 }
890
895 constexpr friend void swaprow(Matrix& U, size_t m1, size_t m2){
896 arcs_assert(m1 <= U.M); // 行が高さ以内かチェック
897 arcs_assert(m2 <= U.M); // 行が高さ以内かチェック
898 Matrix<U.N,1,TT> p, q; // バッファ用ベクトル
899 p = getrow(U,m1); // m1行目を抽出
900 q = getrow(U,m2); // m2行目を抽出
901 setrow(U, p, m2); // m2行目に書き込み
902 setrow(U, q, m1); // m1行目に書き込み
903 }
904
911 constexpr friend void fillrow(Matrix& U, TT a, size_t m, size_t n1, size_t n2){
912 arcs_assert(0 < m && m <= U.M); // 列が幅以内かチェック
913 arcs_assert(0 < n1 && n1 <= U.N); // 列が高さ以内かチェック
914 arcs_assert(0 < n2 && n2 <= U.N); // 列が高さ以内かチェック
915 arcs_assert(n1 <= n2); // 開始列と終了列が入れ替わらないかチェック
916 for(size_t i=n1;i<=n2;i++) U.Data[i-1][m-1] = a;
917 }
918
923 constexpr friend Matrix<1,MM,TT> getcolumn(const Matrix& U, size_t n){
924 arcs_assert(n <= U.N); // 指定した列が行列の幅以内かチェック
925 Matrix<1,U.M,TT> y;
926 for(size_t i=0;i<U.M;i++) y.Data[0][i] = U.Data[n-1][i];
927 return y;
928 }
929
934 constexpr friend void setcolumn(Matrix& U, const Matrix<1,MM,TT>& v, size_t n){
935 static_assert(U.M == v.M, "Matrix Size Error"); // 行列の高さ列ベクトルの長さが等しいかチェック
936 static_assert(v.N == 1, "Input is NOT vector."); // 列ベクトルかチェック
937 arcs_assert(0 < n && n <= U.N); // 指定した列が行列の幅以内かチェック
938 for(size_t i=0;i<U.M;i++) U.Data[n-1][i] = v.Data[0][i];
939 }
940
945 constexpr friend void setcolumn(Matrix& U, const std::array<TT,MM>& v, size_t n){
946 static_assert(U.M == MM, "Matrix Size Error"); // 行列の高さ列ベクトルの長さが等しいかチェック
947 arcs_assert(0 < n && n <= U.N); // 指定した列が行列の幅以内かチェック
948 for(size_t i=0;i<U.M;i++) U.Data[n-1][i] = v.at(i);
949 }
950
955 constexpr friend void swapcolumn(Matrix& U, size_t n1, size_t n2){
956 arcs_assert(n1 <= U.N); // 列が幅以内かチェック
957 arcs_assert(n2 <= U.N); // 列が幅以内かチェック
958 Matrix<1,U.M,TT> p, q; // バッファ用ベクトル
959 p = getcolumn(U,n1); // n1列目を抽出
960 q = getcolumn(U,n2); // n2列目を抽出
961 setcolumn(U,p,n2); // n2列目に書き込み
962 setcolumn(U,q,n1); // n1列目に書き込み
963 }
964
971 constexpr friend void fillcolumn(Matrix& U, TT a, size_t n, size_t m1, size_t m2){
972 arcs_assert(n <= U.N); // 列が幅以内かチェック
973 arcs_assert(m1 <= U.M); // 行が高さ以内かチェック
974 arcs_assert(m2 <= U.M); // 行が高さ以内かチェック
975 arcs_assert(m1 <= m2); // 開始行と終了行が入れ替わらないかチェック
976 for(size_t i=m1;i<=m2;i++) U.Data[n-1][i-1] = a;
977 }
978
985 template <size_t VM>
986 constexpr friend void setvvector(Matrix<NN,MM,TT>& U, const Matrix<1,VM,TT>& v, size_t n, size_t m){
987 arcs_assert(0 < n && n <= NN); // 指定した列が行列の幅以内かチェック
988 arcs_assert(VM + m - 1 <= MM); // 縦ベクトルの下がハミ出ないかチェック
989 for(size_t i = 0; i < VM; ++i) U.Data[n-1][m-1+i] = v.Data[0][i];
990 }
991
998 template <size_t VM>
999 constexpr friend void getvvector(const Matrix<NN,MM,TT>& U, size_t n, size_t m, Matrix<1,VM,TT>& v){
1000 arcs_assert(0 < n && n <= NN); // 指定した列が行列の幅以内かチェック
1001 arcs_assert(VM + m - 1 <= MM); // 縦ベクトルの下がハミ出ないかチェック
1002 for(size_t i = 0; i < VM; ++i) v.Data[0][i] = U.Data[n-1][m-1+i];
1003 }
1004
1011 template <size_t VN>
1012 constexpr friend void gethvector(const Matrix<NN,MM,TT>& U, size_t m, size_t n, Matrix<VN,1,TT>& h){
1013 arcs_assert(0 < m && m <= MM); // 指定した行が行列の高さ以内かチェック
1014 arcs_assert(VN + n - 1 <= NN); // 横ベクトルの右がハミ出ないかチェック
1015 for(size_t i = 0; i < VN; ++i) h.Data[0][i] = U.Data[n-1+i][m-1];
1016 }
1017
1025 template <size_t SN, size_t SM>
1026 constexpr friend void getsubmatrix(const Matrix<NN,MM,TT>& U, size_t n, size_t m, Matrix<SN,SM,TT>& Y){
1027 static_assert(SN <= NN); // 小行列の方が幅が小さいかチェック
1028 static_assert(SM <= MM); // 小行列の方が高さが小さいかチェック
1029 arcs_assert(SN + n - 1 <= NN); // 右側がハミ出ないかチェック
1030 arcs_assert(SM + m - 1 <= MM); // 下側がハミ出ないかチェック
1032 for(size_t i = 1; i <= SN; ++i){
1033 getvvector(U, i + n - 1, m, v);
1034 setcolumn(Y, v, i);
1035 }
1036 }
1037
1045 template <size_t SN, size_t SM>
1046 constexpr friend void setsubmatrix(Matrix<NN,MM,TT>& U, size_t n, size_t m, const Matrix<SN,SM,TT>& A){
1047 static_assert(SN <= NN); // 小行列の方が幅が小さいかチェック
1048 static_assert(SM <= MM); // 小行列の方が高さが小さいかチェック
1049 arcs_assert(SN + n - 1 <= NN); // 右側がハミ出ないかチェック
1050 arcs_assert(SM + m - 1 <= MM); // 下側がハミ出ないかチェック
1052 for(size_t i = 1; i <= SN; ++i){
1053 v = getcolumn(A, i);
1054 setvvector(U, v, i + n - 1, m);
1055 }
1056 }
1057
1062 constexpr friend Matrix orderrow(const Matrix& U, const Matrix<1,MM,int>& v){
1063 static_assert(U.M == v.M, "Matrix and Vector Size Error"); // 行列の高さと列ベクトルの長さが同じかチェック
1064 Matrix Y;
1065 for(size_t i=0;i<U.M;i++){
1066 setrow(Y, getrow(U, (size_t)v.Data[0][i]), i+1);
1067 }
1068 return Y;
1069 }
1070
1075 constexpr friend Matrix reorderrow(const Matrix& U, const Matrix<1,MM,int>& v){
1076 static_assert(U.M == v.M, "Matrix and Vector Size Error"); // 行列の高さと列ベクトルの長さが同じかチェック
1077 Matrix Y = U;
1078 Matrix<1,MM,int> p = v;
1079 for(size_t i=1;i<=U.M;i++){
1080 swaprow(Y,i,p.Data[0][i-1]);
1081 swaprow(p,i,p.Data[0][i-1]);
1082 }
1083 return Y;
1084 }
1085
1089 constexpr friend Matrix shiftup(const Matrix& U){
1090 Matrix Y;
1091 for(size_t i = 2; i <= U.M; ++i){
1092 setrow(Y, getrow(U, i), i - 1); // 横ベクトルを抽出して1つ上の行に書き込み
1093 }
1094 return Y;
1095 }
1096
1101 constexpr friend Matrix shiftup(const Matrix& U, const size_t a){
1102 Matrix Y = U;
1103 for(size_t i = 0; i < a; ++i){
1104 Y = shiftup(Y);
1105 }
1106 return Y;
1107 }
1108
1112 constexpr friend Matrix shiftdown(const Matrix& U){
1113 Matrix Y;
1114 for(size_t i = 2; i <= U.M; ++i){
1115 setrow(Y, getrow(U, i - 1), i); // 横ベクトルを抽出して1つ下の行に書き込み
1116 }
1117 return Y;
1118 }
1119
1124 constexpr friend Matrix shiftdown(const Matrix& U, const size_t a){
1125 Matrix Y = U;
1126 for(size_t i = 0; i < a; ++i){
1127 Y = shiftdown(Y);
1128 }
1129 return Y;
1130 }
1131
1135 constexpr friend Matrix shiftright(const Matrix& U){
1136 Matrix Y;
1137 for(size_t i = 2; i <= U.M; ++i){
1138 setcolumn(Y, getcolumn(U, i - 1), i); // 縦ベクトルを抽出して1つ右の行に書き込み
1139 }
1140 return Y;
1141 }
1142
1147 constexpr friend Matrix shiftright(const Matrix& U, const size_t a){
1148 Matrix Y = U;
1149 for(size_t i = 0; i < a; ++i){
1150 Y = shiftright(Y);
1151 }
1152 return Y;
1153 }
1154
1158 constexpr friend Matrix shiftleft(const Matrix& U){
1159 Matrix Y;
1160 for(size_t i = 2; i <= U.M; ++i){
1161 setcolumn(Y, getcolumn(U, i), i - 1); // 縦ベクトルを抽出して1つ左の行に書き込み
1162 }
1163 return Y;
1164 }
1165
1170 constexpr friend Matrix shiftleft(const Matrix& U, const size_t a){
1171 Matrix Y = U;
1172 for(size_t i = 0; i < a; ++i){
1173 Y = shiftleft(Y);
1174 }
1175 return Y;
1176 }
1177
1182 constexpr friend Matrix gettriup(const Matrix& U, const size_t k){
1183 Matrix Y;
1184 for(size_t i = 0; i < MM; ++i){
1185 for(size_t j = i + k; j < NN; ++j){
1186 Y.Data[j][i] = U.Data[j][i];
1187 }
1188 }
1189 return Y;
1190 }
1191
1195 constexpr friend Matrix gettriup(const Matrix& U){
1196 return gettriup(U, 0);
1197 }
1198
1202 constexpr friend TT infnorm(const Matrix& U){
1203 return max(sumcolumn(abse(tp(U))));
1204 }
1205
1209 constexpr friend TT euclidnorm(const Matrix<NN,MM,TT>& v){
1210 Matrix<1,1,TT> ret;
1211 if constexpr(std::is_same_v<TT,std::complex<double>>){
1212 // 複素数型の場合
1213 if constexpr(NN == 1){
1214 // 縦ベクトルの場合
1215 ret = Htp(v)*v;
1216 }else if constexpr(MM == 1){
1217 // 横ベクトルの場合
1218 ret = v*Htp(v);
1219 }
1220 }else{
1221 // 実数型の場合
1222 if constexpr(NN == 1){
1223 // 縦ベクトルの場合
1224 ret = tp(v)*v;
1225 }else if constexpr(MM == 1){
1226 // 横ベクトルの場合
1227 ret = v*tp(v);
1228 }else{
1229 // 行列の場合
1230 ret = sumcolumn(sumrow(v & v));
1231 }
1232 }
1233 return std::sqrt(ret[1]);
1234 }
1235
1242 constexpr friend enum LUperm LU(const Matrix& A, Matrix& L, Matrix& U, Matrix<1,MM,int>& v){
1243 static_assert(A.N == A.M, "Matrix Size Error"); // 正方行列かチェック
1244 Matrix X = A;
1245 size_t perm_count = 0;
1246 double max_buff = 0;
1248
1249 // 並べ替え記憶列ベクトルの準備
1250 for(size_t i = 0; i < X.N; ++i) v.Data[0][i] = i + 1; // 並べ替え記憶列ベクトルに1から昇順の番号を書き込む
1251
1252 size_t k = 0;
1253 for(size_t j = 0; j < X.N-1; ++j){
1254 // j列目の中での行要素の最大値を探す
1255 k = j; // 対角要素番号で初期化
1256 max_buff = std::abs(X.Data[j][j]); // 対角要素で初期化
1257 for(size_t i = j + 1; i < X.M; ++i){
1258 if(max_buff < std::abs(X.Data[j][i])){
1259 k = i;
1260 max_buff = std::abs(X.Data[j][i]);
1261 }
1262 }
1263 // 行入れ替えが必要なときは,
1264 if(k != j){
1265 swaprow(v,j+1,k+1); // 並べ替え記憶列ベクトルのj行目とk行目を並べ替え
1266 swaprow(X,j+1,k+1); // j行目とk行目を並べ替え
1267 perm_count++;
1268 }
1269 if( fabs(X.Data[j][j]) < X.epsilon )continue;
1270 {
1271 // 対角要素が零なら,j列目においてはLU分解が終わっているので,以下の処理はスキップ
1272 // ここからLU分解
1273 for(size_t i = j + 1; i < X.M; ++i){
1274 X.Data[j][i] /= X.Data[j][j]; // 対角要素で除算
1275 for(size_t l = j + 1; l < X.N; ++l){
1276 X.Data[l][i] -= X.Data[j][i]*X.Data[l][j];
1277 }
1278 }
1279 }
1280 }
1281 // 下三角行列と上三角行列に分離する
1282 for(size_t j = 0; j < X.N; ++j){
1283 for(size_t i = j; i < X.M; ++i){
1284 if(i == j){
1285 L.Data[j][i] = 1; // 下三角行列の対角要素はすべて1
1286 }else{
1287 L.Data[j][i] = X.Data[j][i]; // 下三角のみコピー
1288 }
1289 }
1290 for(size_t i = 0; i <= j; ++i) U.Data[j][i] = X.Data[j][i]; // 上三角のみコピー
1291 }
1292 // 並べ替え回数の判定
1293 if(perm_count % 2 == 0){
1294 ret = Matrix::EVEN; // 奇数のとき
1295 }else{
1296 ret = Matrix::ODD; // 偶数のとき
1297 }
1298 return ret;
1299 }
1300
1305 constexpr friend void Cholesky(const Matrix& A, Matrix& L, Matrix& D){
1306 static_assert(A.N == A.M, "Matrix Size Error"); // Aが正方行列かチェック
1307 L.Data[0][0] = A.Data[0][0];
1308 D.Data[0][0] = 1.0/L.Data[0][0];
1309
1310 for(size_t i = 1; i < A.N; ++i){
1311 for(size_t j = 0; j <= i; ++j){
1312 TT lld = A.Data[j][i];
1313 for(size_t k = 0; k < j; ++k){
1314 lld -= L.Data[k][i]*L.Data[k][j]*D.Data[k][k];
1315 }
1316 L.Data[j][i] = lld;
1317 }
1318 D.Data[i][i] = 1.0/L.Data[i][i];
1319 }
1320 }
1321
1325 constexpr friend void Cholesky(const Matrix& A, Matrix& L){
1326 Matrix Lp, Dp;
1327 Cholesky(A, Lp, Dp);// まずコレスキー分解してから,
1328 L = Lp*sqrte(Dp); // 対角行列の平方根を取って,下三角行列に掛けたものを出力
1329 }
1330
1337 constexpr friend void QR(const Matrix<NN,MM,TT>& A, Matrix<MM,MM,TT>& Q, Matrix<NN,MM,TT>& R){
1338 constexpr size_t K = std::min(NN,MM);
1345 HA = A;
1346 Q = I;
1347
1348 if constexpr(std::is_same_v<TT, std::complex<double>>){
1349 // Householder Reflections を使ったQR分解アルゴリズム(複素数版)
1350 Matrix<1,1,TT> vHv;
1351 e[1] = std::complex(1.0, 0.0);
1352 for(size_t k = 1; k <= K; ++k){
1353 a = getcolumn(HA, k);
1354 a = shiftup(a, k - 1);
1355 v = a + sgn(a[1])*euclidnorm(a)*e;
1356 vHv = Htp(v)*v;
1357 if(k != 1) I.SetElement(MM - (k - 2), MM - (k - 2), 0);
1358 if(std::abs(vHv[1]) < epsilon) vHv[1] = epscomp;
1359 H = I - 2.0*v*Htp(v)/vHv[1];
1360 H = shiftdown(H, k - 1);
1361 H = shiftright(H, k - 1);
1362 for(size_t i = 1; i < k; ++i) H.SetElement(i,i, 1);
1363 HA = H*HA;
1364 Q = Q*H;
1365 }
1366 R = HA;
1367 }else{
1368 // Householder Reflections を使ったQR分解アルゴリズム(実数版)
1369 Matrix<1,1,TT> vTv;
1370 e[1] = 1;
1371 for(size_t k = 1; k <= K; ++k){
1372 a = getcolumn(HA, k);
1373 a = shiftup(a, k - 1);
1374 v = a + sgn(a[1])*euclidnorm(a)*e;
1375 vTv = tp(v)*v;
1376 if(k != 1) I.SetElement(MM - (k - 2), MM - (k - 2), 0);
1377 if( 0 <= vTv[1] && vTv[1] < epsilon) vTv[1] = epsilon;
1378 if(-epsilon <= vTv[1] && vTv[1] < 0 ) vTv[1] = -epsilon;
1379 H = I - 2.0*v*tp(v)/vTv[1];
1380 H = shiftdown(H, k - 1);
1381 H = shiftright(H, k - 1);
1382 for(size_t i = 1; i < k; ++i) H.SetElement(i,i, 1);
1383 HA = H*HA;
1384 Q = Q*H;
1385 }
1386 R = HA;
1387 }
1388 }
1389
1396 constexpr friend void SVD(const Matrix<NN,MM,TT>& A, Matrix<MM,MM,TT>& U, Matrix<NN,MM,TT>& S, Matrix<NN,NN,TT>& V){
1397 constexpr size_t LoopMax = 100*std::max(NN,MM); // ループ打ち切り最大回数
1398 Matrix<NN,MM,TT> Snm;
1399 Matrix<MM,NN,TT> Smn;
1403 double E = 0, F = 0;
1404
1405 // 初期化
1407 Snm = A;
1409 TT Error = 1;
1410
1411 // ループ打ち切り最大回数に達するまでループ
1412 for(size_t l = 0; l < LoopMax; ++l){
1413 if(Error < epsilon) break; // 誤差がイプシロンを下回ったらループ打ち切り
1414 QR(Snm, Qm, Snm);
1415 U = U*Qm;
1416 QR(tp(Snm), Qn, Smn);
1417 V = V*Qn;
1418 e = gettriup(Smn, 1);
1419 E = euclidnorm(e);
1420 F = euclidnorm(diag(Smn));
1421 if(-epsilon < F && F < epsilon) F = 1;
1422 Error = E/F;
1423 Snm = tp(Smn);
1424 }
1425
1426 // 符号修正
1427 Matrix<1,std::min(NN,MM),TT> Sd = diag(Smn);
1429 for(size_t k = 1; k <= std::min(NN,MM); ++k){
1430 TT Sdn = Sd[k];
1431 S.SetElement(k,k, std::abs(Sdn));
1432 if(Sdn < 0){
1433 setcolumn(U, -getcolumn(U, k), k);
1434 }
1435 }
1436 }
1437
1442 constexpr friend std::tuple<Matrix<MM,MM,TT>, Matrix<NN,MM,TT>, Matrix<NN,NN,TT>> SVD(const Matrix<NN,MM,TT>& A){
1446 SVD(A, U, S, V); // SVD特異値分解
1447 return {U, S, V}; // タプルで返す
1448 }
1449
1454 constexpr friend void Schur(const Matrix<NN,MM,TT>& A, Matrix<NN,MM,TT>& Q, Matrix<NN,MM,TT>& U){
1455 static_assert(A.N == A.M, "Matrix Size Error"); // Aが正方行列かチェック
1456
1457 // QR法によるシュール分解
1458 Matrix<NN,MM,TT> Tk = A, Qk, Rk, Qa;
1459 Qa = Matrix<NN,MM,TT>::eye();
1460 for(size_t k = 0; k < ITERATION_MAX; ++k){
1461 QR(Tk, Qk, Rk);
1462 Tk = Rk*Qk;
1463 Qa = Qa*Qk;
1464 if(std::abs(Tk.GetElement(1,A.M)) < A.epsilon) break;
1465 }
1466 Q = Qa;
1467 U = Tk;
1468 }
1469
1474 constexpr friend void solve(const Matrix& A, const Matrix<1,MM,TT>& b, Matrix<1,NN,TT>& x){
1475 static_assert(A.N == A.M, "Matrix Size Error"); // Aが正方行列かチェック
1476 static_assert(b.M == A.M, "Matrix and Vector Size Error"); // Aの高さとbの高さが同じかチェック
1477 static_assert(b.N == 1, "Input is NOT vector."); // bは縦ベクトルかチェック
1478
1479 if constexpr(MM == 1){
1480 // スカラーの場合
1481 x[1] = b[1]/A.GetElement(1,1); // スカラーのときはそのまま単純に除算
1482 }else{
1483 // 行列の場合
1484 // Ax = b において A をLU分解すると,(LU)x = b になって L(Ux) = b と表現できることを利用する。
1485 Matrix<A.N,A.N,TT> L, U;
1486 Matrix<1,A.N,TT> d, bb;
1487 Matrix<1,A.N,int> v;
1488 TT buff = 0;
1489 LU(A, L, U, v); // まず,LU分解(並べ替え有り)してから,Ux = d と勝手に置き換えて考える。
1490 bb = orderrow(b, v);// bベクトルも並べ替える
1491 // その次に Ld = b の方を d について解いて,
1492 // (下記では,Lの対角要素が1となるLU分解がなされているものとして計算する)
1493 d.Data[0][0] = bb.Data[0][0];
1494 for(size_t i = 1; i < A.N; ++i){
1495 for(size_t j = 0; j <= i - 1; ++j) buff += L.Data[j][i]*d.Data[0][j];
1496 d.Data[0][i] = (bb.Data[0][i] - buff);
1497 buff = 0;
1498 }
1499 // さらに Ux = d を x について解く。
1500 x.Data[0][A.N-1] = d.Data[0][A.N-1]/U.Data[A.N-1][A.N-1];
1501 for(int k = A.N - 2; 0 <= k; --k){
1502 for(size_t j = (size_t)k + 1; j < A.N; ++j){
1503 buff += U.Data[j][k]*x.Data[0][j];
1504 }
1505 x.Data[0][k] = (d.Data[0][k] - buff)/U.Data[k][k];
1506 buff = 0;
1507 }
1508 }
1509 }
1510
1515 constexpr friend Matrix<1,MM,TT> solve(const Matrix& A, const Matrix<1,MM,TT>& b){
1516 Matrix<1,A.N,TT> x;
1517 solve(A, b, x);
1518 return x; // 最終的な答えのxベクトルを返す
1519 }
1520
1525 constexpr friend void solve_upper_tri(const Matrix& U, const Matrix<1,MM,TT>& b, Matrix<1,NN,TT>& x){
1526 static_assert(U.N == U.M, "Matrix Size Error"); // Uが正方行列かチェック
1527 static_assert(b.M == U.M, "Matrix and Vector Size Error"); // Uの高さとbの高さが同じかチェック
1528 static_assert(b.N == 1, "Input is NOT vector."); // bは縦ベクトルかチェック
1529
1530 if constexpr(MM == 1){
1531 // スカラーの場合
1532 x[1] = b[1]/U.GetElement(1,1); // スカラーのときはそのまま単純に除算
1533 }else{
1534 // 行列の場合
1535 Matrix<1,U.N,int> v;
1536 TT buff = 0;
1537 // 既にUは上三角行列なのでLU分解は不要
1538 // Ux = b を x について解く。
1539 x.Data[0][U.N-1] = b.Data[0][U.N-1]/U.Data[U.N-1][U.N-1];
1540 for(int k = U.N - 2; 0 <= k; --k){
1541 for(size_t j = (size_t)k + 1; j < U.N; ++j){
1542 buff += U.Data[j][k]*x.Data[0][j];
1543 }
1544 x.Data[0][k] = (b.Data[0][k] - buff)/U.Data[k][k];
1545 buff = 0;
1546 }
1547 }
1548 }
1549
1553 constexpr friend TT det(const Matrix& A){
1554 static_assert(A.N == A.M, "Matrix Size Error"); // Aが正方行列かチェック
1555 Matrix<A.N,A.N,TT> L, U;
1556 Matrix<1,A.N,int> v;
1557 int sign; // 符号
1558 if(LU(A, L, U, v) == Matrix::ODD){ // LU分解と符号判定
1559 sign = -1; // 奇数のとき
1560 }else{
1561 sign = 1; // 偶数のとき
1562 }
1563 // |A| = |L||U| でしかも |L|と|U|は対角要素の総積に等しく,さらにLの対角要素は1なので|L|は省略可。
1564 // 最後にLU分解のときの並べ替え回数によって符号反転をする。
1565 return (TT)sign*prod(U);
1566 }
1567
1571 constexpr friend Matrix inv(const Matrix& A){
1572 static_assert(A.N == A.M, "Matrix Size Error"); // Aが正方行列かチェック
1573 Matrix I = Matrix<A.N,A.N,TT>::ident(); // 単位行列の生成
1574 Matrix<1,A.N,TT> x, b;
1575 Matrix<A.N,A.N,TT> Ainv;
1576 for(size_t n = 1; n <= A.N; ++n){
1577 b = getcolumn(I, n); // 単位行列のn列目を切り出してbベクトルとする
1578 solve(A, b, x); // Ax = b の連立1次方程式をxについて解く
1579 setcolumn(Ainv, x, n); // xはAの逆行列のn列目となるので、Ainvのn列目にxを書き込む
1580 }
1581 return Ainv; // 最終的に得られる逆行列を返す
1582 }
1583
1588 constexpr friend Matrix inv(const Matrix& A, size_t k){
1589 arcs_assert(k <= A.N); // kが範囲内かチェック
1590 Matrix I = Matrix<A.N,A.N,TT>::ident(); // 単位行列の生成
1591
1592 // 正則にするためにk列より右下の対角成分を「1」にする
1593 Matrix<A.N,A.N,TT> A2 = A;
1594 for(size_t j = k + 1; j <= A.N; ++j){
1595 A2.SetElement(j, j, 1);
1596 }
1597
1598 // k列までの逆行列を計算
1599 Matrix<1,A.N,TT> x, b;
1600 Matrix<A.N,A.N,TT> Ainv;
1601 for(size_t n = 1; n <= k; ++n){
1602 b = getcolumn(I, n); // 単位行列のn列目を切り出してbベクトルとする
1603 solve(A2, b, x); // Ax = b の連立1次方程式をxについて解く
1604 setcolumn(Ainv, x, n); // xはAの逆行列のn列目となるので、Ainvのn列目にxを書き込む
1605 }
1606 return Ainv; // 最終的に得られる逆行列を返す
1607 }
1608
1612 constexpr friend Matrix inv_with_check(const Matrix& A){
1613 static_assert(A.N == A.M, "Matrix Size Error"); // Aが正方行列かチェック
1614 arcs_assert(A.epsilon < std::abs(det(A))); // 正則かチェック
1615 return inv(A); // 最終的に得られる逆行列を返す
1616 }
1617
1621 constexpr friend void inv_upper_tri(const Matrix& U, Matrix& Uinv){
1622 static_assert(U.N == U.M, "Matrix Size Error"); // Uが正方行列かチェック
1623 static_assert(Uinv.N == Uinv.M, "Matrix Size Error"); // Uinvが正方行列かチェック
1624 static_assert(U.N == Uinv.N, "Matrix Size Error"); // UとUinvが同じサイズかチェック
1625 Matrix I = Matrix<U.N,U.N,TT>::ident(); // 単位行列の生成
1626 Matrix<1,U.N,TT> x, b;
1627 for(size_t n = 1; n <= U.N; ++n){
1628 b = getcolumn(I, n); // 単位行列のn列目を切り出してbベクトルとする
1629 solve_upper_tri(U, b, x); // Ux = b の連立1次方程式をxについて解く
1630 setcolumn(Uinv, x, n); // xはUの逆行列のn列目となるので、Uinvのn列目にxを書き込む
1631 }
1632 // Uinvが最終的に得られる逆行列
1633 }
1634
1639 constexpr friend void inv_upper_tri(const Matrix& U, size_t k, Matrix& Uinv){
1640 static_assert(U.N == U.M, "Matrix Size Error"); // Uが正方行列かチェック
1641 static_assert(Uinv.N == Uinv.M, "Matrix Size Error"); // Uinvが正方行列かチェック
1642 static_assert(U.N == Uinv.N, "Matrix Size Error"); // UとUinvが同じサイズかチェック
1643 Matrix I = Matrix<U.N,U.N,TT>::ident(); // 単位行列の生成
1644
1645 // 正則にするためにk列より右下の対角成分を「1」にする
1646 Matrix<U.N,U.N,TT> U2 = U;
1647 for(size_t j = k + 1; j <= U.N; ++j){
1648 U2.SetElement(j, j, 1);
1649 }
1650
1651 // k列までの逆行列を計算
1652 Matrix<1,U.N,TT> x, b;
1653 for(size_t n = 1; n <= k; ++n){
1654 b = getcolumn(I, n); // 単位行列のn列目を切り出してbベクトルとする
1655 solve_upper_tri(U2, b, x); // Ux = b の連立1次方程式をxについて解く
1656 setcolumn(Uinv, x, n); // xはUの逆行列のn列目となるので、Uinvのn列目にxを書き込む
1657 }
1658 // Uinvが最終的に得られる逆行列
1659 }
1660
1664 constexpr friend Matrix<MM,NN,TT> lpinv(const Matrix& A){
1665 static_assert(A.N < A.M, "Matrix Size Error"); // 縦長行列かチェック
1666 return inv(tp(A)*A)*tp(A);
1667 }
1668
1673 constexpr friend Matrix<MM,NN,TT> lpinv(const Matrix& A, size_t k){
1674 Matrix<MM,NN> At = tp(A);
1675 Matrix<NN,NN> A2 = At*A;
1676 return inv(A2, k)*At;
1677 }
1678
1682 constexpr friend Matrix<MM,NN,TT> rpinv(const Matrix& A){
1683 static_assert(A.M < A.N, "Matrix Size Error"); // 横長行列かチェック
1684 return tp(A)*inv(A*tp(A));
1685 }
1686
1691 constexpr friend Matrix<MM,NN,TT> rpinv(const Matrix& A, size_t k){
1692 Matrix<MM,NN> At = tp(A);
1693 Matrix<MM,MM> A2 = A*At;
1694 return At*inv(A2, k);
1695 }
1696
1701 constexpr friend Matrix expm(const Matrix& U, size_t Order){
1702 static_assert(U.N == U.M, "Matrix Size Error"); // 正方行列かチェック
1703 int e = 0;
1704 TT c = 1;
1705 bool flag = false;
1706 // ノルムでスケーリング
1707 frexp(infnorm(U),&e);
1708 Matrix<U.N,U.M,TT> A;
1709 if(0 < e){
1710 A = pow(0.5,e+1)*U;
1711 }else{
1712 e = 0;
1713 A = 0.5*U;
1714 }
1715 // 行列のパデ近似の計算
1716 Matrix<A.N,A.N,TT> I = ident();// 単位行列の生成
1717 Matrix<A.N,A.N,TT> L = I, R = I, X = I, cX;
1718 for(size_t i = 1; i <= Order; ++i){
1719 c = c*(TT)(Order - i + 1)/(TT)(i*(2*Order - i + 1)); // パデ近似係数の計算
1720 X = A*X; // A^Mの計算
1721 cX = c*X; // cM*A^Mの計算
1722 R += cX; // R = I + c1*A + c2*A*A + c3*A*A*A + ... + cM*A^M
1723 if(flag == true){
1724 L += cX; // L = I + c1*A + c2*A*A + c3*A*A*A + ... + cM*A^M の正の係数の場合
1725 }else{
1726 L -= cX; // L = I + c1*A + c2*A*A + c3*A*A*A + ... + cM*A^M の負の係数の場合
1727 }
1728 flag = !flag; // 正負係数の場合分け用フラグ
1729 }
1730 // スケールを元に戻す
1731 Matrix Y = inv(L)*R;
1732 for(size_t i = 0; i < (size_t)e + 1; ++i){
1733 Y = Y*Y;
1734 }
1735 return Y; // 最終的に得られる行列指数を返す
1736 }
1737
1744 constexpr friend Matrix integral_expm(const Matrix& U, const TT T, const size_t DIV, const size_t P){
1745 static_assert(U.N == U.M, "Matrix Size Error"); // 正方行列かチェック
1746 const TT h = T/((TT)(2*DIV)); // 時間ステップ
1747 TT t = 0; // 時刻
1748 // シンプソン法による定積分の実行
1749 Matrix<U.N,U.M,TT> S1, S2;
1750 for(size_t i = 1; i <= DIV; ++i){
1751 t = h*(TT)(2*i - 1);
1752 S1 += expm(U*t, P);
1753 }
1754 for(size_t i = 1; i <= DIV - 1; ++i){
1755 t = h*(TT)(2*i);
1756 S2 += expm(U*t, P);
1757 }
1758 return h/3.0*( Matrix<U.N,U.N,TT>::eye() + 4.0*S1 + 2.0*S2 + expm(U*T,P) ); // 最終的な定積分結果を返す
1759 }
1760
1764 constexpr friend Matrix expe(const Matrix& U){
1765 Matrix Y;
1766 for(size_t i = 0; i < U.N; ++i){
1767 for(size_t j = 0; j < U.M; ++j) Y.Data[i][j] = std::exp(U.Data[i][j]);
1768 }
1769 return Y;
1770 }
1771
1775 constexpr friend Matrix loge(const Matrix& U){
1776 Matrix Y;
1777 for(size_t i = 0; i < U.N; ++i){
1778 for(size_t j = 0; j < U.M; ++j) Y.Data[i][j] = std::log(U.Data[i][j]);
1779 }
1780 return Y;
1781 }
1782
1786 constexpr friend Matrix abse(const Matrix& U){
1787 Matrix Y;
1788 for(size_t i = 0; i < U.N; ++i){
1789 for(size_t j = 0; j < U.M; ++j) Y.Data[i][j] = std::abs(U.Data[i][j]);
1790 }
1791 return Y;
1792 }
1793
1797 constexpr friend Matrix sqrte(const Matrix& U){
1798 Matrix Y;
1799 for(size_t i = 0; i < U.N; ++i){
1800 for(size_t j = 0; j < U.M; ++j) Y.Data[i][j] = std::sqrt(U.Data[i][j]);
1801 }
1802 return Y;
1803 }
1804
1808 constexpr friend void sqrte(const Matrix& U, Matrix& Y){
1809 for(size_t i = 0; i < U.N; ++i){
1810 for(size_t j = 0; j < U.M; ++j) Y.Data[i][j] = std::sqrt(U.Data[i][j]);
1811 }
1812 }
1813
1817 constexpr friend Matrix tanhe(const Matrix& U){
1818 Matrix Y;
1819 for(size_t i = 0; i < U.N; ++i){
1820 for(size_t j = 0; j < U.M; ++j) Y.Data[i][j] = std::tanh(U.Data[i][j]);
1821 }
1822 return Y;
1823 }
1824
1828 constexpr friend Matrix<NN,MM,double> reale(const Matrix& U){
1829 static_assert(std::is_same_v<TT, std::complex<double>>, "Matrix Type Error"); // 複素数型のみ対応
1831 for(size_t i = 0; i < U.N; ++i){
1832 for(size_t j = 0; j < U.M; ++j) Y.Data[i][j] = U.Data[i][j].real();
1833 }
1834 return Y;
1835 }
1836
1840 constexpr void real(const Matrix<NN,MM,double>& U){
1841 static_assert(N == NN, "Matrix Size Error");
1842 static_assert(M == MM, "Matrix Size Error");
1843 for(size_t i = 0; i < N; ++i){
1844 for(size_t j = 0; j < M; ++j) Data[i][j] = std::complex(U.Data[i][j], 0.0);
1845 }
1846 }
1847
1851 constexpr friend Matrix<NN,MM,double> image(const Matrix& U){
1852 static_assert(std::is_same_v<TT, std::complex<double>>, "Matrix Type Error"); // 複素数型のみ対応
1854 for(size_t i = 0; i < U.N; ++i){
1855 for(size_t j = 0; j < U.M; ++j) Y.Data[i][j] = U.Data[i][j].imag();
1856 }
1857 return Y;
1858 }
1859
1863 constexpr friend Matrix<NN,MM,double> mage(const Matrix& U){
1864 static_assert(std::is_same_v<TT, std::complex<double>>, "Matrix Type Error"); // 複素数型のみ対応
1866 for(size_t i = 0; i < U.N; ++i){
1867 for(size_t j = 0; j < U.M; ++j) Y.Data[i][j] = std::abs(U.Data[i][j]);
1868 }
1869 return Y;
1870 }
1871
1875 constexpr friend Matrix<NN,MM,double> arge(const Matrix& U){
1876 static_assert(std::is_same_v<TT, std::complex<double>>, "Matrix Type Error"); // 複素数型のみ対応
1878 for(size_t i = 0; i < U.N; ++i){
1879 for(size_t j = 0; j < U.M; ++j) Y.Data[i][j] = std::arg(U.Data[i][j]);
1880 }
1881 return Y;
1882 }
1883
1888 static_assert(std::is_same_v<TT, std::complex<double>>, "Matrix Type Error"); // 複素数型のみ対応
1890 for(size_t i = 0; i < U.N; ++i){
1891 for(size_t j = 0; j < U.M; ++j) Y.Data[i][j] = std::conj(U.Data[i][j]);
1892 }
1893 return Y;
1894 }
1895
1900 static_assert(std::is_same_v<TT, std::complex<double>>, "Matrix Type Error"); // 複素数型のみ対応
1901 return conje(tp(U)); // 転置して複素共役
1902 }
1903
1908 static_assert(NN == MM, "Matrix Size Error"); // 正方行列のみ対応
1909 constexpr size_t LoopMax = 100*NN; // ループ打ち切り最大回数
1910 auto I = Matrix<NN,NN,std::complex<double>>::eye(); // 単位行列
1912 std::complex<double> a, b, c, d, mu;
1913
1914 if constexpr(std::is_same_v<TT, std::complex<double>>){
1915 // 入力が複素数型の場合
1916 A = U;
1917 }else{
1918 // 入力が実数型の場合
1919 A.real(U);
1920 }
1921
1922 // 複素数QR法による固有値計算
1923 for(size_t k = 1; k < LoopMax; ++k){
1924 // Aの最右下2×2小行列の固有値を求める
1925 a = A.GetElement(NN - 1, NN - 1);
1926 b = A.GetElement(NN , NN - 1);
1927 c = A.GetElement(NN - 1, NN );
1928 d = A.GetElement(NN , NN );
1929 mu = ( (a + d) + std::sqrt((a + d)*(a + d) - 4.0*(a*d - b*c)) )/2.0;
1930
1931 // QR分解と収束計算
1932 QR(A - mu*I, Q, R);
1933 A = R*Q + mu*I;
1934
1935 if(std::abs(std::abs(tr(Q)) - (double)NN) < epsilon) break; // 単位行列に漸近したらループ打ち切り
1936 }
1937
1938 return diag(A); // Aの対角要素が固有値
1939 }
1940
1945 static_assert(NN == MM, "Matrix Size Error"); // 正方行列のみ対応
1946 constexpr size_t LoopMax = 100*std::max(NN,MM); // ループ打ち切り最大回数
1948
1949 if constexpr(std::is_same_v<TT, std::complex<double>>){
1950 // 入力が複素数型の場合
1951 A = U;
1952 }else{
1953 // 入力が実数型の場合
1954 A.real(U);
1955 }
1956
1957 // べき乗法による固有ベクトル計算
1960 for(size_t k = 1; k < LoopMax; ++k){
1961 y = A*x;
1962 x = y/euclidnorm(y);
1963 }
1964
1965 return x;
1966 }
1967
1974 template<size_t PP, size_t QQ>
1978
1979 // 縦方向に小行列で埋めていく
1980 for(size_t j = 1; j <= MM; ++j){
1981 // 横方向に小行列で埋めていく
1982 for(size_t i = 1; i <= NN; ++i){
1983 A = Ul(j,i)*Ur;
1984 setsubmatrix(Y, (i - 1)*PP + 1, (j - 1)*QQ + 1, A);
1985 }
1986 }
1987
1988 return Y;
1989 }
1990
1994 constexpr friend Matrix<1,NN*MM,TT> vec(const Matrix<NN,MM,TT>& U){
1996
1997 // 横方向に走査
1998 size_t k = 0;
1999 for(size_t i = 1; i <= NN; ++i){
2000 // 縦方向に走査
2001 for(size_t j = 1; j <= MM; ++j){
2002 k++;
2003 Y(k,1) = U(j,i);
2004 }
2005 }
2006
2007 return Y;
2008 }
2009
2015 template<size_t PP, size_t QQ>
2016 constexpr static void vecinv(const Matrix<NN,MM,TT>& v, Matrix<PP,QQ,TT>& Y){
2017 static_assert(NN == 1); // 入力は縦ベクトルかチェック
2018 static_assert(PP*QQ == MM); // 要素数が同じかチェック
2019
2020 // 横方向に走査
2021 size_t k = 0;
2022 for(size_t i = 1; i <= PP; ++i){
2023 // 縦方向に走査
2024 for(size_t j = 1; j <= QQ; ++j){
2025 k++;
2026 Y(j,i) = v(k,1);
2027 }
2028 }
2029 }
2030
2036 template<size_t PP, size_t QQ>
2037 constexpr static Matrix<PP,QQ,TT> vecinv(const Matrix<NN,MM,TT>& v){
2039 vecinv(v, Y);
2040 return Y;
2041 }
2042
2043 private:
2044 static constexpr double epsilon = 1e-12;
2045 static constexpr std::complex<double> epscomp = std::complex(1e-12, 1e-12);
2046 static constexpr size_t ITERATION_MAX = 10000;
2047 size_t Nindex;
2048 size_t Mindex;
2049
2053 static constexpr TT sgn(TT u){
2054 TT ret = 0;
2055 if constexpr(std::is_same_v<TT, std::complex<double>>){
2056 // 複素数型の場合
2057 if(u == std::complex(0.0, 0.0)){
2058 ret = std::complex(0.0, 0.0);
2059 }else{
2060 ret = u/std::abs(u);
2061 }
2062 }else{
2063 // 実数型の場合
2064 if((TT)0 <= u){
2065 ret = (TT)1;
2066 }else{
2067 ret = (TT)(-1);
2068 }
2069 }
2070 return ret;
2071 }
2072
2073 public:
2074 static constexpr size_t N = NN;
2075 static constexpr size_t M = MM;
2076 std::array<std::array<TT, M>, N> Data;
2077};
2078}
2079
2080#endif
2081
ARCS用ASSERTクラス
#define arcs_assert(a)
ARCS用assertマクロ a : assert条件
Definition ARCSassert.hh:17
行列/ベクトル計算クラス(テンプレート版)
Definition Matrix.hh:44
constexpr friend void Cholesky(const Matrix &A, Matrix &L, Matrix &D)
修正コレスキー分解(LDL^T版)
Definition Matrix.hh:1305
constexpr friend Matrix< 1, NN, std::complex< double > > eigen(const Matrix< NN, MM, TT > &U)
固有値を返す関数
Definition Matrix.hh:1907
constexpr auto operator+(const Matrix &right) const
行列加算演算子 (行列同士の加算の場合)
Definition Matrix.hh:152
constexpr friend void setrow(Matrix &U, const Matrix< NN, 1, TT > &v, size_t m)
指定した行を横ベクトルで上書きする関数
Definition Matrix.hh:874
constexpr friend void sqrte(const Matrix &U, Matrix &Y)
行列要素の平方根を参照で返す関数
Definition Matrix.hh:1808
constexpr void SetElem(size_t m, size_t n, TT val)
指定した要素番号に値を設定する関数 (並び順逆版)
Definition Matrix.hh:462
constexpr friend Matrix shiftright(const Matrix &U)
行列の各要素を右に1列分シフトする関数(最左段の列はゼロになる)
Definition Matrix.hh:1135
constexpr auto operator*(const TT &right) const
行列乗算演算子 (行列*スカラーの場合)
Definition Matrix.hh:215
constexpr friend Matrix< MM, NN, std::complex< double > > Htp(const Matrix< NN, MM, TT > &U)
エルミート転置行列を返す関数
Definition Matrix.hh:1899
constexpr friend void setrow(Matrix &U, const std::array< TT, NN > &v, size_t m)
指定した行を横ベクトル(std::array)で上書きする関数
Definition Matrix.hh:885
constexpr TT GetElement(size_t n, size_t m) const
指定した要素番号の値を返す関数
Definition Matrix.hh:489
constexpr friend std::tuple< Matrix< MM, MM, TT >, Matrix< NN, MM, TT >, Matrix< NN, NN, TT > > SVD(const Matrix< NN, MM, TT > &A)
SVD特異値分解(タプルで返す版) 補足:MATLABとはU,S,Vの符号関係が入れ替わっている場合があるが正常なSVDであることは確認済み
Definition Matrix.hh:1442
constexpr friend void setcolumn(Matrix &U, const Matrix< 1, MM, TT > &v, size_t n)
指定した列を縦ベクトルで上書きする関数
Definition Matrix.hh:934
constexpr friend void swaprow(Matrix &U, size_t m1, size_t m2)
指定した行と行を入れ替える関数
Definition Matrix.hh:895
constexpr friend Matrix< MM, NN, TT > lpinv(const Matrix &A)
左擬似逆行列を返す関数 (Aが縦長行列の場合)
Definition Matrix.hh:1664
constexpr friend Matrix< NN, MM, std::complex< double > > conje(const Matrix &U)
複素数行列要素の共役を返す関数
Definition Matrix.hh:1887
constexpr friend Matrix< 1, std::min(NN, MM), TT > diag(const Matrix &U)
行列の対角要素を縦ベクトルで返す関数
Definition Matrix.hh:725
constexpr friend void inv_upper_tri(const Matrix &U, size_t k, Matrix &Uinv)
上三角行列の逆行列を返す関数(左上小行列のサイズ指定版)
Definition Matrix.hh:1639
friend void PrintMatSize_Macro(const Matrix &u, const std::string &varname)
行列のサイズの表示 (この関数はマクロを介して呼ばれることを想定している)
Definition Matrix.hh:580
constexpr friend enum LUperm LU(const Matrix &A, Matrix &L, Matrix &U, Matrix< 1, MM, int > &v)
LU分解
Definition Matrix.hh:1242
constexpr friend Matrix integral_expm(const Matrix &U, const TT T, const size_t DIV, const size_t P)
指数行列の数値定積分[0,T]をする関数
Definition Matrix.hh:1744
constexpr Matrix< HN, 1, TT > GetHorizontalVec(size_t n, size_t m)
指定した先頭位置から横ベクトルを抜き出して返す関数
Definition Matrix.hh:513
static constexpr size_t N
行列の幅(列の数, 横)
Definition Matrix.hh:2074
constexpr friend double sumall(const Matrix &U)
行列の全要素を加算して出力する関数
Definition Matrix.hh:757
constexpr auto & operator+=(const Matrix &right)
行列加算代入演算子 (行列=行列+行列の場合)
Definition Matrix.hh:237
constexpr friend Matrix< 1, NN *MM, TT > vec(const Matrix< NN, MM, TT > &U)
vec作用素(行列→縦ベクトル)
Definition Matrix.hh:1994
constexpr TT operator()(size_t m, size_t n) const
行列括弧演算子(行列の(m,n)要素の値を返す。GetElem(m,n)と同じ意味。ただしサイズチェックは行わない。)
Definition Matrix.hh:337
constexpr friend Matrix operator-(const TT &left, const Matrix &right)
行列減算演算子 (スカラー-行列の場合)
Definition Matrix.hh:363
constexpr auto operator-(const Matrix &right) const
行列減算演算子 (行列同士の減算の場合)
Definition Matrix.hh:176
friend void PrintMat_Macro(const Matrix &u, const std::string &varname)
行列の要素を表示 (書式指定なし版,この関数はマクロを介して呼ばれることを想定している)
Definition Matrix.hh:619
constexpr auto operator*(const Matrix< Nright, Mright, Tright > &right) const
行列乗算演算子 (行列同士の乗算の場合)
Definition Matrix.hh:201
constexpr auto operator%(const Matrix &right) const
行列アダマール除算演算子 (行列の要素ごとの除算)
Definition Matrix.hh:307
constexpr Matrix< 1, VM, TT > GetVerticalVec(size_t n, size_t m)
指定した先頭位置から縦ベクトルを抜き出して返す関数
Definition Matrix.hh:499
constexpr friend size_t maxidx(const Matrix &u)
ベクトル要素の最大値の要素番号を返す関数
Definition Matrix.hh:805
constexpr friend void setcolumn(Matrix &U, const std::array< TT, MM > &v, size_t n)
指定した列を縦ベクトル(std::array)で上書きする関数
Definition Matrix.hh:945
constexpr friend void fillrow(Matrix &U, TT a, size_t m, size_t n1, size_t n2)
m行目のn1列目からm2列目を数値aで埋める関数 (n1 <= n2 であること)
Definition Matrix.hh:911
constexpr Matrix(const TT InitValue)
コンストラクタ(任意初期値版)
Definition Matrix.hh:63
constexpr friend Matrix shiftdown(const Matrix &U, const size_t a)
行列の各要素を下にa行分シフトする関数(最上段の行はゼロになる)
Definition Matrix.hh:1124
constexpr TT & operator()(size_t m, size_t n)
行列括弧演算子(行列の(m,n)要素に値を設定する。SetElem(m,n,val)と同じ意味。ただしサイズチェックは行わない。)
Definition Matrix.hh:345
constexpr Matrix(const Matrix &right)
コピーコンストラクタ
Definition Matrix.hh:104
constexpr void Set(const T1 &u1, const T2 &... u2)
行列要素に値を設定する関数
Definition Matrix.hh:385
constexpr friend Matrix shiftleft(const Matrix &U)
行列の各要素を左に1列分シフトする関数(最右段の列はゼロになる)
Definition Matrix.hh:1158
constexpr friend void swapcolumn(Matrix &U, size_t n1, size_t n2)
指定した列と列を入れ替える関数
Definition Matrix.hh:955
constexpr friend Matrix sqrte(const Matrix &U)
行列要素の平方根を返す関数
Definition Matrix.hh:1797
constexpr friend Matrix expm(const Matrix &U, size_t Order)
行列指数関数 e^(U)
Definition Matrix.hh:1701
constexpr void LoadArray(const std::array< std::array< TT, NN >, MM > &Array)
2次元std::array配列を読み込む関数
Definition Matrix.hh:440
constexpr friend Matrix loge(const Matrix &U)
行列要素の自然対数を返す関数
Definition Matrix.hh:1775
constexpr friend void setsubmatrix(Matrix< NN, MM, TT > &U, size_t n, size_t m, const Matrix< SN, SM, TT > &A)
小行列を行列の指定位置に上書きする関数
Definition Matrix.hh:1046
constexpr friend Matrix< MM, NN, TT > rpinv(const Matrix &A, size_t k)
右擬似逆行列を返す関数 (Aが横長行列の場合, 左上小行列のサイズ指定版)
Definition Matrix.hh:1691
constexpr TT GetElem(size_t m, size_t n) const
指定した要素番号の値を返す関数 (並び順逆版)
Definition Matrix.hh:471
constexpr auto operator-(const TT &right) const
行列減算演算子 (行列-スカラーの場合)
Definition Matrix.hh:189
constexpr friend Matrix< MM, NN, TT > tp(const Matrix< NN, MM, TT > &U)
転置行列を返す関数
Definition Matrix.hh:694
constexpr friend void setvvector(Matrix< NN, MM, TT > &U, const Matrix< 1, VM, TT > &v, size_t n, size_t m)
指定した列を縦ベクトルで指定位置に上書きする関数
Definition Matrix.hh:986
constexpr auto operator+(void) const
単項プラス演算子
Definition Matrix.hh:131
constexpr auto operator^(const size_t &right) const
行列べき乗演算子
Definition Matrix.hh:281
constexpr void LoadShortVector(const Matrix< 1, VM, TT > &v)
短い縦ベクトルを読み込み,且つ残りはゼロで埋める関数
Definition Matrix.hh:451
constexpr friend Matrix< 1, NN, std::complex< double > > eigenvec(const Matrix< NN, MM, TT > &U)
最大固有値の固有ベクトルを返す関数
Definition Matrix.hh:1944
constexpr friend Matrix< NN, MM, double > reale(const Matrix &U)
複素数行列要素の実数部を返す関数
Definition Matrix.hh:1828
constexpr friend TT prod(const Matrix &U)
行列の対角要素の総積を返す関数
Definition Matrix.hh:715
static constexpr Matrix ones(void)
m行n列の要素がすべて1の行列を返す関数
Definition Matrix.hh:655
constexpr friend Matrix shiftup(const Matrix &U)
行列の各要素を上に1行分シフトする関数(最下段の行はゼロになる)
Definition Matrix.hh:1089
constexpr auto & operator-=(const TT &right)
行列減算代入演算子 (行列=行列-スカラーの場合)
Definition Matrix.hh:271
static constexpr Matrix< PP, QQ, TT > vecinv(const Matrix< NN, MM, TT > &v)
vec作用素の逆(縦ベクトル→行列)
Definition Matrix.hh:2037
constexpr friend Matrix shiftright(const Matrix &U, const size_t a)
行列の各要素を右にa列分シフトする関数(最左段の列はゼロになる)
Definition Matrix.hh:1147
constexpr friend void SVD(const Matrix< NN, MM, TT > &A, Matrix< MM, MM, TT > &U, Matrix< NN, MM, TT > &S, Matrix< NN, NN, TT > &V)
SVD特異値分解(引数で返す版) 補足:MATLABとはU,S,Vの符号関係が入れ替わっている場合があるが正常なSVDであることは確認済み
Definition Matrix.hh:1396
constexpr friend Matrix tanhe(const Matrix &U)
行列要素のtanhを返す関数
Definition Matrix.hh:1817
constexpr friend Matrix shiftup(const Matrix &U, const size_t a)
行列の各要素を上にa行分シフトする関数(最下段の行はゼロになる)
Definition Matrix.hh:1101
constexpr auto operator&(const Matrix &right) const
行列アダマール積演算子 (行列の要素ごとの乗算)
Definition Matrix.hh:294
constexpr friend TT euclidnorm(const Matrix< NN, MM, TT > &v)
ベクトルのユークリッドノルムを返す関数
Definition Matrix.hh:1209
constexpr friend void inv_upper_tri(const Matrix &U, Matrix &Uinv)
上三角行列の逆行列を返す関数
Definition Matrix.hh:1621
constexpr friend size_t rank(const Matrix &A)
行列のランクを返す関数
Definition Matrix.hh:852
constexpr friend Matrix inv(const Matrix &A, size_t k)
逆行列を返す関数 (正則チェック無し, 左上小行列のサイズ指定版)
Definition Matrix.hh:1588
constexpr friend Matrix orderrow(const Matrix &U, const Matrix< 1, MM, int > &v)
並び替え記憶列ベクトルvの行番号に従って,入力行列Uの行を並び替える関数
Definition Matrix.hh:1062
constexpr TT operator[](size_t m) const
縦ベクトル添字演算子(縦ベクトルのm番目の要素の値を返す。GetElement(1,m)と同じ意味。ただしサイズチェックは行わない。)
Definition Matrix.hh:320
constexpr friend TT det(const Matrix &A)
行列式の値を返す関数
Definition Matrix.hh:1553
constexpr friend Matrix< MM, NN, TT > rpinv(const Matrix &A)
右擬似逆行列を返す関数 (Aが横長行列の場合)
Definition Matrix.hh:1682
constexpr friend Matrix< NN, 1, TT > sumcolumn(const Matrix &U)
列方向(縦方向)へ加算して横ベクトルを出力する関数
Definition Matrix.hh:746
constexpr void FillAll(TT u)
すべての要素を指定した値で埋める関数
Definition Matrix.hh:548
constexpr friend void getvvector(const Matrix< NN, MM, TT > &U, size_t n, size_t m, Matrix< 1, VM, TT > &v)
指定した列から縦ベクトルを指定位置から抽出する関数
Definition Matrix.hh:999
constexpr friend void fillcolumn(Matrix &U, TT a, size_t n, size_t m1, size_t m2)
n列目のm1行目からm2行目を数値aで埋める関数 (m1 <= m2 であること)
Definition Matrix.hh:971
constexpr TT & operator[](size_t m)
縦ベクトル添字演算子(縦ベクトルのm番目の要素に値を設定する。SetElement(1,n,val)と同じ意味。ただしサイズチェックは行わない。)
Definition Matrix.hh:328
constexpr friend TT tr(const Matrix &U)
行列のトレースを返す関数
Definition Matrix.hh:705
constexpr Matrix(std::initializer_list< TT > InitList)
コンストラクタ(初期化リスト版)
Definition Matrix.hh:73
constexpr friend TT absmax(const Matrix &u)
ベクトル要素の絶対値の最大値を返す関数
Definition Matrix.hh:785
constexpr friend Matrix operator*(const TT &left, const Matrix &right)
行列乗算演算子 (スカラー*行列の場合)
Definition Matrix.hh:374
constexpr auto operator+(const TT &right) const
行列加算演算子 (行列+スカラーの場合)
Definition Matrix.hh:165
constexpr void LoadArray(const std::array< TT, MM > &Array)
1次元std::array配列を縦ベクトルとして読み込む関数
Definition Matrix.hh:424
constexpr friend Matrix shiftdown(const Matrix &U)
行列の各要素を下に1行分シフトする関数(最上段の行はゼロになる)
Definition Matrix.hh:1112
LUperm
LU分解の際の並べ替えが偶数回/奇数回発生したことを返すための定義
Definition Matrix.hh:47
@ ODD
奇数
Definition Matrix.hh:48
@ EVEN
偶数
Definition Matrix.hh:49
constexpr friend Matrix< NN, MM, double > image(const Matrix &U)
複素数行列要素の虚数部を返す関数
Definition Matrix.hh:1851
constexpr friend Matrix operator+(const TT &left, const Matrix &right)
行列加算演算子 (スカラー+行列の場合)
Definition Matrix.hh:352
constexpr friend Matrix inv_with_check(const Matrix &A)
逆行列を返す関数 (正則チェック有り)
Definition Matrix.hh:1612
constexpr friend void QR(const Matrix< NN, MM, TT > &A, Matrix< MM, MM, TT > &Q, Matrix< NN, MM, TT > &R)
QR分解 補足:実数型のときMATLABとはQとRの符号関係が逆の場合があるが正常なQR分解であることは確認済み 補足:複素数型のときMATLABとは全く違う値が得られるが,正常なQR分解であることは確...
Definition Matrix.hh:1337
constexpr friend Matrix shiftleft(const Matrix &U, const size_t a)
行列の各要素を左にa列分シフトする関数(最右段の列はゼロになる)
Definition Matrix.hh:1170
constexpr friend Matrix< 1, MM, TT > sumrow(const Matrix &U)
行方向(横方向)へ加算して縦ベクトルを出力する関数
Definition Matrix.hh:735
constexpr void StoreArray(std::array< TT, MM > &Array) const
縦ベクトルを1次元std::array配列に書き込む関数
Definition Matrix.hh:432
constexpr friend Matrix gettriup(const Matrix &U, const size_t k)
行列のk番目より上の上三角部分を返す関数(下三角はゼロになる)
Definition Matrix.hh:1182
constexpr friend TT max(const Matrix &u)
ベクトル要素の最大値を返す関数
Definition Matrix.hh:765
constexpr friend Matrix< 1, MM, TT > solve(const Matrix &A, const Matrix< 1, MM, TT > &b)
Ax = bの形の線形連立1次方程式をxについて解く関数(戻り値として返す版)
Definition Matrix.hh:1515
constexpr friend void Schur(const Matrix< NN, MM, TT > &A, Matrix< NN, MM, TT > &Q, Matrix< NN, MM, TT > &U)
Schur分解
Definition Matrix.hh:1454
constexpr friend Matrix expe(const Matrix &U)
行列要素の指数関数を返す関数
Definition Matrix.hh:1764
static constexpr Matrix< NN, NN, TT > ident(void)
n行n列の単位行列を返す関数
Definition Matrix.hh:663
constexpr auto & operator+=(const TT &right)
行列加算代入演算子 (行列=行列+スカラーの場合)
Definition Matrix.hh:249
constexpr friend Matrix< MM, NN, TT > lpinv(const Matrix &A, size_t k)
左擬似逆行列を返す関数 (Aが縦長行列の場合, 左上小行列のサイズ指定版)
Definition Matrix.hh:1673
constexpr friend void Cholesky(const Matrix &A, Matrix &L)
修正コレスキー分解(LL^T版)
Definition Matrix.hh:1325
constexpr auto operator-(void) const
単項マイナス演算子
Definition Matrix.hh:141
static constexpr Matrix< NN, NN, TT > eye(void)
n行n列の単位行列を返す関数 (identのエイリアス)
Definition Matrix.hh:678
constexpr bool isEnabledSIMD(void)
MatrixクラスがSIMD命令が有効に設定されているかを返す関数
Definition Matrix.hh:573
constexpr auto & operator=(const Matrix &right)
行列代入演算子
Definition Matrix.hh:120
constexpr void SetHorizontalVec(Matrix< HN, 1, TT > h, size_t n, size_t m)
指定した先頭位置に横ベクトルを埋め込む関数
Definition Matrix.hh:539
constexpr friend TT infnorm(const Matrix &U)
行列の無限大ノルムを返す関数
Definition Matrix.hh:1202
static constexpr void vecinv(const Matrix< NN, MM, TT > &v, Matrix< PP, QQ, TT > &Y)
vec作用素の逆(縦ベクトル→行列)
Definition Matrix.hh:2016
constexpr void SetVerticalVec(Matrix< 1, VM, TT > v, size_t n, size_t m)
指定した先頭位置に縦ベクトルを埋め込む関数
Definition Matrix.hh:527
constexpr void real(const Matrix< NN, MM, double > &U)
複素数行列要素の実数部に値をセットする関数
Definition Matrix.hh:1840
constexpr friend Matrix< 1, MM, TT > getcolumn(const Matrix &U, size_t n)
指定した列から縦ベクトルとして抽出する関数
Definition Matrix.hh:923
static constexpr Matrix ramp(void)
単調増加の縦ベクトルを返す関数
Definition Matrix.hh:684
friend void PrintMatrix_Macro(const Matrix &u, const std::string &format, const std::string &varname)
行列の要素を表示 (書式指定あり版,この関数はマクロを介して呼ばれることを想定している)
Definition Matrix.hh:588
constexpr void SetElement(size_t n, size_t m, TT val)
指定した要素番号に値を設定する関数
Definition Matrix.hh:480
constexpr friend Matrix< NN *PP, MM *QQ, TT > Kronecker(const Matrix< NN, MM, TT > &Ul, const Matrix< PP, QQ, TT > &Ur)
クロネッカー積
Definition Matrix.hh:1975
constexpr friend Matrix< NN, 1, TT > getrow(const Matrix &U, size_t m)
指定した行から横ベクトルとして抽出する関数
Definition Matrix.hh:863
constexpr friend size_t nonzeroele(const Matrix &U)
行列の非ゼロ要素数を返す関数
Definition Matrix.hh:839
constexpr friend void gethvector(const Matrix< NN, MM, TT > &U, size_t m, size_t n, Matrix< VN, 1, TT > &h)
指定した行から横ベクトルを指定位置から抽出する関数
Definition Matrix.hh:1012
constexpr friend void getsubmatrix(const Matrix< NN, MM, TT > &U, size_t n, size_t m, Matrix< SN, SM, TT > &Y)
行列から指定位置の小行列を抽出する関数
Definition Matrix.hh:1026
constexpr auto operator/(const TT &right) const
行列スカラー除算演算子 (行列/スカラーの場合)
Definition Matrix.hh:226
constexpr void Get(T1 &u1, T2 &... u2)
行列要素から値を読み込む関数
Definition Matrix.hh:405
constexpr friend void solve_upper_tri(const Matrix &U, const Matrix< 1, MM, TT > &b, Matrix< 1, NN, TT > &x)
Uは上三角行列で,Ux = bの形の線形連立1次方程式をxについて解く関数(引数で返す版)
Definition Matrix.hh:1525
constexpr friend Matrix reorderrow(const Matrix &U, const Matrix< 1, MM, int > &v)
並び替え記憶列ベクトルvが昇順になるように,入力行列Uの行を並び替えて元に戻す関数
Definition Matrix.hh:1075
constexpr friend Matrix inv(const Matrix &A)
逆行列を返す関数 (正則チェック無し)
Definition Matrix.hh:1571
constexpr friend void solve(const Matrix &A, const Matrix< 1, MM, TT > &b, Matrix< 1, NN, TT > &x)
Ax = bの形の線形連立1次方程式をxについて解く関数(引数で返す版)
Definition Matrix.hh:1474
constexpr size_t GetHeightLength(void) const
行列の高さ(行数)を返す関数
Definition Matrix.hh:567
static constexpr Matrix zeros(void)
m行n列の零行列を返す関数
Definition Matrix.hh:648
constexpr auto & operator-=(const Matrix &right)
行列減算代入演算子 (行列=行列-行列の場合)
Definition Matrix.hh:259
std::array< std::array< TT, M >, N > Data
データ格納用変数 配列要素の順番は Data[N列(横)][M行(縦)] なので注意
Definition Matrix.hh:2076
constexpr friend Matrix gettriup(const Matrix &U)
行列の上三角部分を返す関数(下三角はゼロになる)
Definition Matrix.hh:1195
constexpr Matrix()
コンストラクタ
Definition Matrix.hh:53
constexpr friend size_t absmaxidx(const Matrix &u)
ベクトル要素の絶対値の最大値の要素番号を返す関数
Definition Matrix.hh:822
constexpr friend Matrix< NN, MM, double > mage(const Matrix &U)
複素数行列要素の大きさを返す関数
Definition Matrix.hh:1863
constexpr friend Matrix abse(const Matrix &U)
行列要素の絶対値を返す関数
Definition Matrix.hh:1786
constexpr size_t GetWidthLength(void) const
行列の幅(列数)を返す関数
Definition Matrix.hh:561
constexpr void FillAllZero(void)
すべての要素を指定したゼロで埋める関数
Definition Matrix.hh:555
constexpr friend Matrix< NN, MM, double > arge(const Matrix &U)
複素数行列要素の偏角を返す関数
Definition Matrix.hh:1875
static constexpr size_t M
行列の高さ(行の数, 縦)
Definition Matrix.hh:2075