std::vector間の演算を定義したら快適になった
C++で行列やベクトルを扱いたいときは, Eigenを使うことが多い.
しかし, 非常に簡単なプログラムの場合, Eigenを使うまでも無いような場合も多々ある.
そこで, #include<vector>
のstd::vector
間の演算を定義することで, シンプルでカスタマイズ性の高い機能を提供する.
コメントをいただきました: std::valarrayという数値演算に特化した一次元配列クラスがあるようです
vec_op
githubにvec_opを公開した.
vec_op.hppを#include "vec_op.hpp"
するだけで使用可能.
使用例は, sample.cppを参照.
その実行結果は, こちらを参照.
これらのリンク先のみで理解できるが, 一部抜粋して説明する.
vec_op.hpp
例えば, std::vector
間の+
は, 以下のように実装されている.
template <class T>
std::vector<T> operator+(const std::vector<T> &v1, const std::vector<T> &v2) {
std::vector<T> ans = v1;
for (size_t i = 0, size = ans.size(); i < size; ++i)
ans[i] += v2[i];
return ans;
}
演算子の他に, よく使いそうな機能として名前空間vec_op
に関数を定義した.
例えば, 内積dot
は以下の通り.
namespace vec_op {
// (...略...)
template <class T>
T dot(const std::vector<T> &v1, const std::vector<T> &v2) {
T ans(0);
for (size_t i = 0, size = v1.size(); i < size; ++i)
ans += v1[i] * v2[i];
return ans;
}
// (...略...)
}
sample.cpp
四則演算+
, -
, *
, /
や, べき乗^
の使用例.
matlabの+
, -
, .*
, ./
, .^
に対応している.
cout << "v1 + v2 = " << v1 + v2 << endl;
cout << "v1 - v2 = " << v1 - v2 << endl;
cout << "v1 * v2 = " << v1 * v2 << endl;
cout << "v1 / v2 = " << v1 / v2 << endl;
cout << "v1 ^ v2 = " << (v1 ^ v2) << endl;
ベクトルとスカラーの演算にも対応.
cout << "v1 + c = " << v1 + c << endl;
cout << "v1 - c = " << v1 - c << endl;
cout << "v1 * c = " << v1 * c << endl;
cout << "v1 / c = " << v1 / c << endl;
cout << "v1 ^ c = " << (v1 ^ c) << endl;
cout << "c ^ v1 = " << (c ^ v1) << endl;
その他機能の利用例.
cout << "dot(v1, v2) = " << vec_op::dot(v1, v2) << endl;
cout << "sum(v1) = " << vec_op::sum(v1) << endl;
cout << "prod(v1) = " << vec_op::prod(v1) << endl;
cout << "cast<double, int>(v1) = " << vec_op::cast<double, int>(v1) << endl;
cout << "concat(v1, v2) = " << vec_op::concat(v1, v2) << endl;
cout << "sort(v1) = " << vec_op::sort(v1) << endl;
cout << "argsort(v1) = " << vec_op::argsort(v1) << endl;
cout << "randomIndex(10) = " << vec_op::randomIndex(10) << endl;
cout << "range(10) = " << vec_op::range(10) << endl;
cout << "range(2,10,2) = " << vec_op::range(2, 10, 2) << endl;
メリット
- Includeするだけで関数/演算が使えるようになる
- カスタマイズ性が高い
- 並列化したければ自分でoperator定義のforループにopenmpをつければよい
- 気軽に関数/演算子を追加していける