行列計算ライブラリのBlitzのコードがカッコいい件

iOSで行列計算したいなーという事で、ちょろちょろ調べているとBlitzっていうC++のライブラリが見つかったんですけど、すごくカッコよくてビックリしました。

このライブラリ使うと以下のようなノリで行列計算が出来ます。AとBを初期化してる部分がエレガント過ぎますね。

#include <iostream>
#include <blitz/array.h>

using namespace std;
using namespace blitz;

int main(int argc, char** argv) {

    Array<float, 2> A(3,3), B(3,3), C(3,3), D(3, 3);

    A = 1, 0, 0,
        2, 2, 2,
        1, 0, 0;
    
    B = 0, 0, 7,
        0, 8, 0,
        9, 9, 9;

    C = A + B;
    D = A * B;

    cout << "A = " << A << endl
         << "B = " << B << endl
         << "C = " << C << endl
         << "D = " << D << endl;

    return 0;
}

C++でこんなんどうやって実現すんの?と思ってコードを読んでみると、operator=とoperator,を上手く組み合わせて実装されていました。C++にoperator,なんてあったんですね。知りませんでした。下記が該当部分を抜粋したものになります。

class Array : public MemoryBlockReference<P_numtype> 
{
    ...
	
    ListInitializationSwitch<T_array> operator=(T_numtype x)
    {
      return ListInitializationSwitch<T_array>(*this, x);
    }

	...
}

class ListInitializationSwitch
{
    ....
	
    ListInitializer<T_numtype, T_iterator> operator,(T_numtype x)
    {
        wipeOnDestruct_ = false;
        T_iterator iter = array_.getInitializationIterator();
        *iter = value_;
	    ++iter;
        *iter = x;
	    ++iter;
        return ListInitializer<T_numtype, T_iterator>(iter);
    }
	
	...
}

class ListInitializer
{
    ...
	
    ListInitializer<T_numtype, T_iterator> operator,(T_numtype x)
    {
        *iter_ = x;
	    ++iter_;
        return ListInitializer<T_numtype, T_iterator>(iter_);
    }

	...
	
}

Arrayのoperator=でListInitializationSwitchを、そのoperator,で今度はListInitializerを返しています。後はListInitializerのoperator,で順々に行列を初期化する流れになっています。一旦Switchクラスを噛ませている理由がパッと分からないのですが、さっきの行列代入処理をエレガントに書く為の執念を感じて感動しました。

久々に美しいC++を見て、あぁこういうプログラミングもあったぁと思い出しまして、ここ数年PythonとかCocoaとかお膳立てされた環境で、API組み合わせるばっかりだったなぁと妙に反省させられた今日この頃です。

Leave a Reply

Your email address will not be published. Required fields are marked *