TMatrixで要素を文字解釈し、行列に値を詰める
解析で使おうかなぁと思ってCode snippetを書いたのですが、結局使わないことになったので、供養します。
はじめに
ある行列
$$
A =
\begin{pmatrix}
a_{00} & a_{01} & a_{02} \\
a_{10} & a_{11} & a_{12} \\
a_{20} & a_{21} & a_{22}
\end{pmatrix}
$$
があったときに、ある行列要素(例として$a_{11}$)にString型の変数"a_11"
でアクセスできるようにするコードを書きます。
これを実装するには、C++の連想配列であるstd::map
を使用します。ここではC++98を想定していますので、C++11以降で使えるauto
を使わないでやっております。
方針
まず、行列要素のindexと文字列を紐付ける連想配列を作ります。そのあとに、入力させる文字列と値を連想配列で作り、コード内で文字解釈をして行列にFillする感じにします。行列は2つのindexを持つので、二重配列でも良いのですが、ここではstd::pair
を使おうと思います。
また、indexの連想配列でLoopを回し、入力された要素と同じ文字列があると対応する値を行列に詰めるようにします。それにはiteratorを返すfind
を使います。
実装
早速、実装です。
#include <map> // std::mapに必要
#include <utility> // std::pairに必要
#include <iostream>
#include "TString.h"
#include "TMatrixD.h"
void map_test()
{
const UInt_t size = 3;
std::map<TString, std::pair<UInt_t, UInt_t> > idx; // "文字列 -> index pairの連想配列
for (UInt_t i = 0; i != size; ++i) {
for (UInt_t j = 0; j != size; ++j) {
idx[TString::Format("a_%d%d",i,j)] = std::make_pair(i,j); // "a_ij"の文字列と行列要素を紐付ける
}
}
std::map<TString, Double_t> mp; // 文字列 -> 行列要素 (ここは本来外部入力させる予定)
mp["a_01"] = 0.1;
mp["a_02"] = 0.2;
mp["a_10"] = 1.0;
mp["a_11"] = 1.1;
mp["a_20"] = 2.0;
mp["a_22"] = 2.2;
TMatrixD A(size, size);
for(std::map<TString, std::pair<UInt_t, UInt_t> >::iterator itr_idx = idx.begin(); itr_idx != idx.end(); ++itr_idx) {
std::map<TString, Double_t>::iterator itr_mp = mp.find(itr_idx->first);
if (itr_mp != mp.end()) {
A[itr_idx->second.first][itr_idx->second.second] = itr_mp->second;
} else {
A[itr_idx->second.first][itr_idx->second.second] = 0.;
}
}
A.Print();
}
これの実行結果は
3x3 matrix is as follows
| 0 | 1 | 2 |
--------------------------------------------
0 | 0 0.1 0.2
1 | 1 1.1 0
2 | 2 0 2.2
となります。値を指定していない行列要素には0を詰めるようにしてあります。