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関数は、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ライブラリで、ほとんどのルーチンはコールバック関数を含みます。コールバック関数を定義する前に、関数が呼ばれるときに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 は、最初の引く数として渡されます。
このサンプルは、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 Cで、データはDataset または DataRange オブジェクトを使って渡されます。 以下のセクションでは、DatasetおよびDataRangeを使ってワークシートからデータを渡す方法を示しています。DataRangeを使う方法がお勧めです。
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クラスは、仮にワークシート列が文字と数値データ型であったとしても、ワークシートからのデータを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関数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); }