C言語の関数を取り込む(import)その3

gnuplot 5.0以降では、C言語で書かれた関数をgnuplotで取り込んで使うための非常に強力なコマンド「import」が使えるようになりました。ここでは、そのimportコマンドの使い方について詳細に解説します。

gslのインストール(MinGW-W64/MSYS2の場合)

これまでの例は、あまりimportコマンドのご利益が感じられなかったかもしれません。しかし、C言語には強力なライブラリが配布されていますので、それらをうまく取り込むことで、これまでのgnuplotではできなかったことも可能になります。

ここでは、GNU Scientific Library (GSL)をインストールするやり方を紹介します。GSLは特殊関数、積分や微分、方程式の解など様々な数値計算の機能を提供するC言語・C++のパッケージです。GSLをgnuplot上で使うやり方はこちら(計算機は楽し・gnuplot Tips集)でも解説されています。

まず、GSLを、その1.5で紹介したMinGW-W64/MSYS2にインストールする方法を解説します。

  1. MSYS2をスタートメニューから起動します。コンソールから、
    pacman -S --needed mingw-w64-x86_64-gsl
    と入力します。32bitの場合は
    pacman -S --needed mingw-w64-i686-gsl
    とします。
  2. インストールするか聞かれるので、Yを入力して「Enter」すると、インストールが始まります。
  3. インストールに成功したら、exitを入力してコンソールを閉じます。

GSLを使うプログラムの例

以下の例では、GSLの中の特殊関数のパッケージを用いて、任意の次数のベッセル関数を呼び出せるJn(n,x)をgnuplot上で使えるようにすることを目指します。

GSLでは、gsl_sf_bessel_Jnという関数が定義されていて、任意の整数次数nのベッセル関数を計算できます。以下に、それをgnuplotにimportするためのcプログラムを示します。

#include "gnuplot_plugin.h"
#include <math.h>
#include <gsl/gsl_sf_bessel.h>

DLLEXPORT struct value Jn(int nargs, struct value *arg, void *p){

  struct value r;
  double x;
  int n;
  
  RETURN_ERROR_IF_WRONG_NARGS(r, nargs, 2);
  RETURN_ERROR_IF_NONNUMERIC(r, arg[0]);
  RETURN_ERROR_IF_NONNUMERIC(r, arg[1]);
  
  r.type = CMPLX;
  n = IVAL(arg[0]);
  x = RVAL(arg[1]);
  
  r.v.cmplx_val.real = gsl_sf_bessel_Jn(n, x);
  r.v.cmplx_val.imag = 0.0;
  
  return r;
}

GSLのベッセル関数群はgsl/gsl_sf_bessel.hというヘッダファイルに含まれているので、それを#includeする必要があります。それさえすれば、後はほとんどその2の例と同じようにプログラムできます。

これのファイルをgsl_bessel_Jn.cという名前で、gnuplot_plugin.hなどを用意したフォルダ(その1その1.5参照)に保存します。スタートメニューから、「MinGW-w64 Win64 Shell」を起動します。(32bitの場合は「MinGW-w64 Win32 Shell」。いずれの場合も、「MSYS2 Shell」ではないことに注意。)そして、ファイルを保存したフォルダにどうした後、以下のコマンドでコンパイルします。

gcc -static -shared -o gsl_bessel_Jn.dll gsl_bessel_Jn.c -lgsl -DHAVE_CONFIG_H -I.

GSLのライブラリファイルを静的に使うために、-lgslというオプションと-staticオプションを用いています。末尾のピリオドに注意してください。コンパイルに成功すると、gsl_bessel_Jn.dllというファイルが生成されます。

これを、以下のようなgnuplotスクリプトで呼び出します。

import Jn(n,x) from "gsl_bessel_Jn"
plot Jn(0,x), Jn(1,x), Jn(2,x), Jn(3,x), Jn(4,x), Jn(5,x)

これを実行すると、以下のようなグラフが得られます。通常のgnuplotでは不可能だった、2次以上のベッセル関数も計算できています。

その4へ続きます。