一度関数ブロックを定義すると、それを通常の関数を呼び出すのと同じように どこでもその名前で呼び出すことができます。返り値が適切でない場合、関数 ブロックを、数式の一部としてでなく、コマンド "evaluate" で呼び出すこと ができます。
例:
function $sinc(arg) << EOF if (arg == 0) { return 1.0 } return sin(arg) / arg EOF
gnuplot> plot $sinc(x) with lines title "sinc(x) as a function block"
名前付き引数の一覧は、関数ブロックの宣言時に指定する必要はありません。 コマンドラインで指定した関数の引数の個数とその値は、関数ブロックの内部 から、整数変数 ARGC とそれに対応する配列 ARGV[ARGC] でアクセスできます。 以下参照: ARGV (83.1)。これにより、可変な個数の引数を操作できる関数ブロック を定義することができます。call 文によるファイルの読み込みとは違い、 引数は文字列変数化 (例えば ARG1) はされません。
例:
function $max << EOF local max = real("-Inf") if (ARGC == 0) { return NaN } do for [i=1:ARGC] { if (max < ARGV[i]) { max = ARGV[i] } } return max EOF gnuplot> foo = $max( f(A), 2.0, C, Array[3] ) gnuplot> baz = $max( foo, 100. )
関数ブロックをサポートする一番の目的は、複雑な関数を gnuplot 内部で直 接定義できるようにすることです。もちろん、同じ関数を C や Fortran でコ ードした場合よりも実行速度は遅くなりますが、これは色々な目的に答えるこ とを可能にします。実行速度が重要な場合は、代わりにその関数を別にプラグ インとして実装すればいいでしょう (以下参照: plugins (26))。
関数ブロックを使う 2 つ目の目的は、gnuplot コマンドが、これを使う以外 には存在できないような状況でその実行を可能にすることです。例えばあなた が 2 つの CSV ファイルからのデータを描画したいが、一つのファイルはフィ ールドがカンマ区切りで、もう一方はセミコロン区切りであるとします。通常 この属性に対しては、事前にコマンド set datafile をセットしますが、そ れは plot コマンドが使用するすべてのファイルに適用されてしまいます。し かし我々は、各ファイルが plot コマンドで参照される直前にそれを設定する ように呼びだすような関数ブロックを定義できます。
function $set_csv(char) << EOF set datafile separator char EOF plot tmp=$set_csv(",") FILE1, tmp=$set_csv(";") FILE2
制限:
関数ブロックを使う自明でない例として、複素対数ガンマ関数 lngamma に対 する 15 項 Lanczos 近似の実装とグラフがデモコレクション内にあります。 function_block.dem
この関数ブロックによる実装は、同じアルゴリズムで C で直接コードされて
いる組み込み関数の lnGamma と比べて、だいたい 25 倍位遅いですが、それ
でも対話型での 3 次元グラフの回転には十分な位の速さです。
デモにある関数定義は以下の通り。
15 項 Lanczos 近似を用いた
log(z) の関数ブロックによる実装
array coef[15] = [ ... ] function $Lanczos(z) << EOD local Sum = coef[1] + sum [k=2:15] coef[k] / (z + k - 1) local temp = z + 671./128. temp = (z + 0.5) * log(temp) - temp temp = temp + log( sqrt(2*pi) * Sum/z ) return temp EOD function $Reflect(z) << EOD local w = $Lanczos(1.0 - z) local temp = log( sin(pi * z) ) return log(pi) - (w + temp) EOD my_lngamma(z) = (z == 0) ? NaN : (real(z) < 0.5) ? $Reflect(z) : $Lanczos(z) |
関数ブロックの使用は試験段階です。 詳細は、リリース版に含まれる前に変更される可能性があります。
竹野茂治@新潟工科大学