SWIGによる行列/複素数 C++ライブラリのRubyへの移植

プログラミングの練習がて作成しているC++の行列ライブラリ(matrix.h)、並びに複素数ライブラリ(complex.h)があります。このような標準的なライブラリはどの言語においても先達が素晴らしいプログラムを用意してくれているので、それを新たに作ることは"車輪の再発明"、すなわち時間の浪費という非常に疎まれる行為であることには違いないのですが、今まで自身で育ててきたものは出来が悪くてもかわいいものです。そこで自作の行列、複素数C++ライブラリをRubyに移植してみることにしました。

Rubyへの移植ということですが、RubyはC/C++との親和性を非常に意識しているので、C/C++でプログラムを書くことによって新たな拡張ライブラリを追加できます。このプログラムを書くにあたっては、既に用意されたRubyの言語としての機能と、新たに付け加えたい機能のインターフェイスを取るために、Ruby側で既に用意した関数を使いつつ、型の変換やクラスの階層構造の指示等を行うことになります。すなわち、付け加えたい機能の部分のプログラムが既にある場合には、このインターフェイスの部分の記述だけをすればよく、そのようなプログラムをラッパーと呼んでいます。今回はこのラッパーを作成することによって、C++で書かれた行列、複素数をRubyから使えるようにしました。

このラッパー、実はほぼ全自動で生成することが可能です。表題にあるSWIGがその役割を果たしてくれます。SWIGは、C/C++言語で書かれたプログラムの構造を解析し、対象となるスクリプト言語にあわせたラッパーを生成してくれます。特殊な指示、例えば、あの関数はスクリプト言語から呼び出して欲しくない、あるいは、あの関数に別名をつけたい、といった事情は手動で記述する必要がありますが、それ以外の部分についてはSWIGが全て解決してくれるのです。またSWIGは対象言語としてRuby以外にも、PerlやJavaは勿論のこと、様々な言語に対応しています。

SWIGはどのようなプログラムを解析してラッパーを生成するのか、また全自動で対応できない場合にはどうすればよいのか、といった内容を記述したインターフェイスファイルを入力とし、出力がラッパーとなります。今回の場合はFenrirMath.iというファイルがそのファイルにあたり、行列/複素数の解析を行うことや、関数に別名をつける指示などを盛り込んでみました。ラッパーが生成されたら、あとは対象とする言語にあわせて拡張ライブラリをビルドする作業(Rubyならextconf.rbによるmakefile生成後make)にうつるわけですが、その作業はmakefileで自動化してみました。もしビルドを試されるようでしたら、足りないファイルはcommonディレクトリ等で探してみてください。

以上をもって無事移植が完了しました。Rubyに元々用意されている複素数/行列ライブラリとの比較のためにFenrirMathTest.rbというテストユニットを書いてみましたが、自作ライブラリと元々あるライブラリとで動作結果が一致しました。これで、これからは元のC++ライブラリも含めて安心して使えます。目下の課題としては、cygwin+gcc 3.4.4による行列式の計算がえらく遅いことで、VC2008を利用したビルドにもチャレンジしてみようと思います。

※その後、FFTも統合しました。上記リンクは常に最新のファイルに飛んでいますので、更新は反映されています。
ところでテストプログラムを書いている際に気になったのですが、行列でLU分解をした際、Uの対角成分を1とするのは珍しいことなのでしょうか? GNU::GSLではLの対角成分が1となっているようです。

※※その後、sqrt(平方根)の計算ができるようになっています。

March 21, 2008 00:23 fenrir が投稿 : 固定リンク | | このエントリーを含むはてなブックマーク

コメント

コメントする