Edited at

std::vector間の演算を定義したら快適になった


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をつければよい

    • 気軽に関数/演算子を追加していける