octave は Matlab には劣るかもしれないが,かなり多くのことができる.それらのうち, liboctave で実装されているものはもちろん C++ から利用できるのだが,そうでないもの,例えばスクリプトやDLDなどによって提供されているものについても, C++ から利用できる場合がある.そのための力技テクニックを紹介する.
liboctave に関するドキュメントはとても少ない.よって liboctave で可能なことを増やすためには,どうしてもコードを読み,場合によっては改変する必要がある.
情報源 †
- octaveマニュアル(PDF)
- liboctaveマニュアル(HTML) : ほとんど説明がない.
- octaveのソースのdoxygen(HTML) : とりあえず Class List (Classes), File List (Files) あたりを眺めてみることをおすすめする.
- Octave-Forge - Extra packages for GNU Octave -- Function Reference
octaveマニュアルを C++ のために読む †
octaveは liboctave+C++ で書かれているから,octaveマニュアルに書かれていることは,すべて C++ 上で実現できる. octave で利用できる関数が, C++ ではどのように実装されているかを探す方法を述べておこう.
octaveがデフォルトで使える関数は次の4つのうちいずれかの形式で提供されており,関数の説明箇所でどの形式かが明記されている.
- Function File
- The function described is defned using Octave commands stored in a text file. See Section 11.7 [Function Files], page 113.
- Built-in Function
- The function described is written in a language like C++, C, or Fortran, and is part of the compiled Octave binary.
- Loadable Function
- The function described is written in a language like C++, C, or Fortran. On systems that support dynamic linking of user-supplied functions, it may be automatically linked while Octave is running, but only if it is needed. See Appendix A [Dynami-cally Linked Functions], page 441.
- Mapping Function
- The function described works element-by-element for matrix and vector arguments.
[octaveマニュアル p.21 から抜粋]
この情報をもとにしてC++で使いたい関数を調べ,利用する. octave のソースコードを調べるので, octave のソースをどこかに展開しておく必要がある.以下では octave-src-dir は, octave のソースディレクトリを指すものとする.
[Function File] の利用 †
基本的に, octave-src-dir/scripts に"関数名.m"というファイル名で置かれている.このスクリプトを liboctave+C++ に翻訳する という力技で,C++から利用できるようになる.ちなみに octave のスクリプトを C++ のソースに自動翻訳するプログラムも存在するようだが,信頼性は低いようだ.
[Built-in Function] の利用 †
基本的に octave-src-dir/src/data.cc で定義されている.例えば columns というビルトイン関数は, data.cc で
01302 DEFUN (columns, args, ,
01303 "-*- texinfo -*-\n\
01304 @deftypefn {Built-in Function} {} columns (@var{a})\n\
01305 Return the number of columns of @var{a}.\n\
01306 @seealso{size, numel, rows, length, isscalar, isvector, and ismatrix}\n\
01307 @end deftypefn")
01308 {
01309 octave_value retval;
01310
01311 if (args.length () == 1)
01312 retval = args(0).columns ();
01313 else
01314 print_usage ();
01315
01316 return retval;
01317 }
のように定義されている.前半6行は octave に関数を提供するためのマクロ,残りが関数の中身である. octave_value retval は関数の戻り値で, args(0) は関数の最初の引数(行列)である. retval = args(0).columns (); で,行列の列数を retval に代入していることがわかる.
このように, data.cc からビルトイン関数の定義場所を探して,それを C++ 向けに少し書き直せば,比較的容易に C++ からビルトイン関数が利用できるようになる.
[Loadable Function] の利用 †
これは「C++ で記述した関数を octave から利用する」方法によって提供されている関数である.この提供方法はビルトイン関数とほとんど同じで,既に C++ で実装されているため,容易に書き直せるだろう.これらの関数は octave-src-dir/src/DLD-FUNCTIONS に置かれていて,多くの関数が 関数名.cc で定義されている.
[Mapping Function] の利用 †
多くの関数が octave-src-dir/src/mappers.cc で定義されているようだ.例えば octave の isspace は mappers.cc で
00103 static int
00104 xisspace (int c)
00105 {
00106 return isspace (c);
00107 }
00511 DEFUN_MAPPER (isspace, xisspace, 0, 0, 0, 0, 0, 0.0, 0.0, 0, 0,
00512 "-*- texinfo -*-\n\
00513 @deftypefn {Mapping Function} {} isspace (@var{s})\n\
00514 Return 1 for whitespace characters (space, formfeed, newline,\n\
00515 carriage return, tab, and vertical tab).\n\
00516 @end deftypefn");
のように定義されている.前半は xisspace というC++の関数を定義しており,後半は octave の isspace を C++ の xisspace にマップしていると考えられる.
見つからない場合 †
ほとんどの関数のC++による実装が上記の探し方で見つかるはずだが,それでも見つからない場合は,利用したい関数名を octave のソースディレクトリで grep コマンドなどによって調べよう.