Boost.uBLAS の補完ライブラリの使い方 - その2

今回も前回紹介したuBLASの補完ライブラリの一部の機能について説明します.
今回説明するのは次の機能です.

  • norm_2_sq
  • norm_frobenius_sq

これらはそれぞれ ublas.norm_2, ublas.norm_frobenius の自乗を返します.
しかし,皆さんはこれらの機能を冗長だと思われるかもしれません.
実際,norm_2_sq はユークリッドノルムの自乗を返しますが,これは

vector v;
inner_prod(v, v);

のように内積として計算できるからです.しかし,次の例を考えてみてください.

vector v;
matrix m;
inner_prod(prod(m, v), prod(m, v));

このように,m x v のノルムの自乗を計算したい場合,prod(m, v) を 2 回行わなければなりません.もちろん,

vector v;
matrix m;
vector u(prod(m, v));
inner_prod(u, u);

のように,一旦 u に代入するようにすれば,prod は 1 回ですみます.しかし,私はこのような些細な問題の為に新しい変数を導入するという複雑さの増加は馬鹿げていると感じます.また,

vector v;
matrix m;
double norm = norm_2(prod(m, v));
double norm_sq = norm * norm;

のような方法も同様の理由により受け入れ難く感じます.さらにこのコードの場合,norm_2 が sqrt して返した結果に対して square するという屈辱的な無駄も生じます.私はこの種の無駄が大嫌いなのです.例えそれが大したコストでなくてもです.


つまり,norm_2_sq と norm_frobenius_sq を実装した理由は個人的な意見によるところが大きいですが,それでもこれらの機能を必要としている人は少なからずいるはずです.


さて,動機はさておき,以下のテストコードでこれらの機能の動作を確認できます.

test.cpp

#include "numeric.hpp"
#include <boost/numeric/ublas/io.hpp>


int main()
{
    boost::numeric::ublas::vector<double> v(3);
    boost::numeric::ublas::matrix<double> m(3, 3);

    v(0) = 1; v(1) = 2; v(2) = 3;

    m(0, 0) = 1; m(0, 1) = 2; m(0, 2) = 3;
    m(1, 0) = 4; m(1, 1) = 5; m(1, 2) = 6;
    m(2, 0) = 7; m(2, 1) = 8; m(2, 2) = 9;

    std::cout << v << std::endl;
    std::cout << m << std::endl;

    std::cout << numeric::ublas::norm_2_sq(v) << std::endl;         // ユークリッドノルムの自乗
    std::cout << numeric::ublas::norm_frobenius_sq(m) << std::endl; // フロベニウスノルムの自乗

    return 0;
}
  • VC9
  • g++ (GCC) 3.4.4 (cygming special)

でのコンパイルを確認しています.

実行してみると,正しく計算できていることが分かります.


次回は sum, trace, diag_prod について説明する予定です.
それでは.