NAG関数を使用するNAG関数を使用するNAG Functions
ヘッダファイルNAG header Files
NAG関数を呼ぶには、ヘッダーファイルまたはNAG関数が宣言されているファイルをインクルードする必要があります。
すべてのNAGヘッダファイルを共通で使用する1つのヘッダファイルを下記に示します。通常、このヘッダファイルだけをコードにインクルードします。
#include <OC_nag.h> // 全てに共通のNAGヘッダファイル
1つまたは数個のみのNAG関数が使われている場合、それぞれ個々のNAGヘッダファイルをインクルードすることもできます。例えば、NAG関数 f02abcがコード内で使われている場合、2つの関連ヘッダファイルをインクルードする必要があります。
#include <NAG\nag.h> // NAG 構造体と型の定義
#include <NAG\nagf02.h> // f02 関数の宣言も含む
エラー構造体NAG Error Structure
すべてのNAG関数は、NagError構造体へのポインタの1つの引数を取ります。この構造体は、NAG関数の実行が成功したかどうかをテストするために使われます。
下記のサンプルは、NAG関数f02abc がうまく動作するかどうかを示します。
NagError err; // エラー構造体を宣言
f02abc(n, mx, n, r, v, n, &err); // NAG f02abc 関数の呼び出し
if( err.code != NE_NOERROR ) // エラーが発生したら
printf(err.message); // エラーメッセージを出力
呼び出しが成功したかどうかを知る必要が無ければ、エラー構造体の宣言は必要ありません。そしてNAGERR_DEFAULT マクロが代わりに渡されます。このマクロはNULLポインタです。NAG関数の将来のバージョンとの互換性を確実にするため、エラー構造体無しで操作できるなら、このマクロを使用した方がよいでしょう。
f02abc(n, mx, n, r, v, n, NAGERR_DEFAULT);
コールバック関数NAG Callback Functions
NAGライブラリで、ほとんどのルーチンはコールバック関数を含みます。コールバック関数を定義する前に、関数が呼ばれるときにNAGが期待している戻り型と引数の型を知る必要があります。
例えば、NAG関数 d01ajc は次のようになります。ヘッダファイルnagd01.h で、最初の引数が NAG_D01AJC_FUN f であることが分かります。この引数はコールバック関数です。そして、nag_types.h で、NAG_D01AJC_FUN がNAG_D01_FUN の型であることがわかり、以下のように定義されます。
typedef double (NAG_CALL * NAG_D01_FUN)(double);
そして、次のようにコールバック関数を定義します。
double NAG_CALL myFunc(double x)
{
double result;
// 'x'で処理
return result;
}
NAG 関数d01ajc を呼び出すと、上述で定義した myFunc は、最初の引く数として渡されます。
c05adcを呼び出すサンプル
このサンプルは、NAG関数c05adc を呼び出す方法を示し、この4番目の引数がコールバック関数の引数です。NAG_C05ADC_FUN 型のこのコールバック関数は、nag_types.h で定義されます。
typedef double (NAG_CALL * NAG_C05ADC_FUN)(double);
定義から、戻り型と引数の型がdoubleであることが分かります。そして、次のようにコールバック関数を定義できます。
double NAG_CALL myC05ADCfunc(double x)
{
return exp(-x)-x;
}
以下のコードは、コールバック関数myC05ADCfunc を渡して、関数 c05adc を呼び出す方法を示しています。
double a = 0.0, b = 1.0, x, ftol = 0.0, xtol = 1e-05;
NagError err;
c05adc(a, b, &x, myC05ADCfunc, xtol, ftol, &err);
NAGがOriginからデータを取得
多くのNAG関数は、数値データの配列へのポインタを取ります。Originのワークシートおよび行列シートは、そのデータのポインタを取得できます。このポインタはNAG関数に渡すことができます。Origin Cで、データはDataset または DataRange オブジェクトを使って渡されます。 以下のセクションでは、DatasetおよびDataRangeを使ってワークシートからデータを渡す方法を示しています。DataRangeを使う方法がお勧めです。
Dataset
DatasetがNAG関数で期待されているデータ型であれば、DatasetオブジェクトをNAG関数に渡すことができます。Originワークシート列のデータ型は、デフォルトで文字と数値です。すべてではありませんが、ほとんどのNAG関数に対しては、NAG関数が浮動小数点または整数型のポインタを期待しているので、このデータ型を渡すことができません。
DatasetがNAG関数で期待されているデータ型であることが確実な場合、次のコードはDatasetオブジェクトをNAG関数に渡すのに使うことができます。
// アクティブワークシートへのアクセス
Worksheet wks = Project.ActiveLayer();
// データセットを構築し、wksデータにアクセス
Dataset dsX, dsY;
dsX.Attach(wks, 0);
dsY.Attach(wks, 1);
// NAGの nag_1d_spline_interpolant(e01bac)関数を呼び出し
NagError err;
Nag_Spline spline;
e01bac(m, dsX, dsY, &spline, &err);
DataRange
DataRangeクラスは、仮にワークシート列が文字と数値データ型であったとしても、ワークシートからのデータをvectorに取得するGetDataメソッドを提供します。GetDataメソッドは、欠損値を持つ行を簡単に無視でき、これはNAG関数にデータを渡すときに大変重要です。
DataRangeを使って、OriginからNAG関数にデータを渡すのはより安全で、お勧めです。以下のサンプルで、実際の方法を示しています。
void call_NAG_example()
{
int i, numPoints = 5;
// 新しいワークシートページを作成.
WorksheetPage pg;
pg.Create("origin");
// アクティブワークシートにアクセスして2列追加
Worksheet wks = Project.ActiveLayer();
// X2列追加
i = wks.AddCol();
Column col(wks, i);
col.SetType(OKDATAOBJ_DESIGNATION_X);
// Y2列追加
wks.AddCol();
// 最初の2列でいくつかの開始XY値を作成
Dataset dsX, dsY;
dsX.Attach(wks, 0);
dsY.Attach(wks, 1);
for (i = 0; i < numPoints; i++)
{
int r = rnd(0) * 10;
if (r < 1)
r = 1;
if (i > 0)
r += dsX[i - 1];
dsX.Add(r);
dsY.Add(rnd(0));
}
// データ範囲オブジェクトを作成
DataRange dr;
dr.Add(wks, 0, "X");
dr.Add(wks, 1, "Y");
// データ範囲を使用してwks からデータをvedtorにコピー
// このコピーは、欠損値を持つ行を無視
vector vX1, vY1;
dr.GetData(DRR_GET_DEPENDENT, 0, NULL, NULL, &vY1, &vX1);
// NAGを呼び出して係数を計算
NagError err;
Nag_Spline spline;
e01bac(vX1.GetSize(), vX1, vY1, &spline, &err);
// スプラインの XY 値を取得
vector vX2, vY2;
double fit, xarg;
for (i = 0; i < vX1.GetSize(); i++)
{
vX2.Add(vX1[i]);
vY2.Add(vY1[i]);
if (i < vX1.GetSize() - 1)
{
xarg = (vX1[i] + vX1[i + 1]) * 0.5;
e02bbc(xarg, &fit, &spline, &err);
vX2.Add(xarg);
vY2.Add(fit);
}
}
//NAGで割り当てられたメモリを解放
NAG_FREE(spline.lamda);
NAG_FREE(spline.c);
// ワークシートにスプライン値をコピー
dsX.Attach(wks, 2);
dsX = vX2;
dsY.Attach(wks, 3);
dsY = vY2;
}
NAG e04関数の呼び出し方法
次のサンプルは、NAG関数nag_opt_simplex_easyを安全に呼び出す方法を示します。結果はファイルに出力します。
#include <OC_nag.h>
#define NULLFN NULL
void text_e04cbc()
{
double objf;
double x[2];
Integer maxcal, n;
NagError fail;
printf("\ne04cbc example: \n");
maxcal = 100;
n = 2;
x[0] = 0.4;
x[1] = -0.8;
tolf = sqrt(nag_machine_precision);
tolx = sqrt(tolf);
try
{
// NAG関数 e04cbc = nag_opt_simplex_easy 呼び出し
nag_opt_simplex_easy(n, x, &objf, tolf, tolx, funct, NULLFN, maxcal, NAGCOMM_NULL, &fail);
}
catch(int err)
{
printf("\nerror = %d\n", err); // 例外がある場合
}
printf("fail->code = %d\n", fail.code); // エラーコード
printf("fail->message = %s\n", fail.message); // エラーメッセージ
printf("The final function value is %12.4f\n", objf);
printf("at the point");
for (int ii = 1; ii <= n; ++ii)
{
printf(" %12.4f", x[ii-1]);
}
printf("\n");
}
// nag_opt_simplex_easy のコールバック関数
void NAG_CALL funct(Integer n, double* xc, double* objf, Nag_Comm* comm)
{
*objf = exp(xc[0])*(xc[0]*4.0*(xc[0]+xc[1])+xc[1]*2.0*(xc[1]+1.0)+1.0);
}
|