XLPack API: C/C++ 使用例

Cプログラム例 (例題(1), Visual C)

Visual C (Visual Studio (Windows版)) を使用した例です. 行列を列優先(VBAやFortranと同じ, 通常のC/C++の格納順番とは行と列が反対)で格納していることに注意してください.
aとbに1次元配列を使います(リファレンスマニュアルは下のClangの例のように可変長2次元配列で表記していますがVisual Cの場合には読み替えてください).

#include <stdio.h>
#include "cnumlib.h"

int main(void)
{
    double a[3][3] = {
        { 0.2, -0.32, -0.8 },
        { -0.11, 0.81, -0.92 },
        { -0.93, 0.37, -0.29 } };
    double b[] = { -0.3727, 0.4319, -1.4247 };
    int n = 3, nrhs = 1, lda = 3, ldb = 3, ipiv[3], info;

    dgesv(n, nrhs, lda, (double *)a, ipiv, ldb, b, &info);
    printf("x = %f  %f  %f\n", b[0], b[1], b[2]);
    printf("info = %d\n", info);
    return 0;
}

実行結果

x = 0.860000  0.640000  0.510000
info = 0

Cプログラム例 (例題(1), Clang)

Clang ではC99の可変長配列が使えるのでaとbには2次元配列を使います.

#include <stdio.h>
#include "cnumlib.h"

int main(void)
{
    double a[3][3] = {
        { 0.2, -0.32, -0.8 },
        { -0.11, 0.81, -0.92 },
        { -0.93, 0.37, -0.29 } };
    double b[] = { -0.3727, 0.4319, -1.4247 };
    int n = 3, nrhs = 1, lda = 3, ldb = 3, ipiv[3], info;

    dgesv(n, nrhs, lda, a, ipiv, ldb, (double (*)[ldb])b, &info);
    printf("x = %f  %f  %f\n", b[0], b[1], b[2]);
    printf("info = %d\n", info);
    return 0;
}

Cプログラム例 (例題(1), LAPACKE 行優先)

LAPACKEでは第1パラメータで行優先の配列を使うことを指定できます. これにより行列の記述を数学表記と同じにすることができます. 内部処理としては, 計算開始前に配列の転置を行い, 計算終了後に再び転置をします. ldb = 1 となっていることに注意してください. これは, aだけでなくbも転置処理を行う仕様になっており, bとしては横ベクトルの入力を期待されているからです.

#include <stdio.h>
#include "lapacke.h"

int main(void)
{
    double a[3][3] = {
        { 0.2, -0.11, -0.93 },
        { -0.32, 0.81, 0.37 },
        { -0.8, -0.92, -0.29 } };
    double b[] = { -0.3727, 0.4319, -1.4247 };
    int n = 3, nrhs = 1, lda = 3, ldb = 1, ipiv[3], info;

    info = LAPACKE_dgesv(LAPACK_ROW_MAJOR, n, nrhs, (double *)a, lda, ipiv, b, ldb);
    printf("x = %f  %f  %f\n", b[0], b[1], b[2]);
    printf("info = %d\n", info);
    return 0;
}

C++プログラム例 (例題(1))

ヘッダーファイルは cnumlib (XLPack Liteでは cnumlib_lite) を使うことができます(info引数に注意). 行列はClangの場合でも一次元配列に入れます.

#include <iostream>
#include "cnumlib"
using namespace std;

int main(void)
{
    double a[3][3] = {
        { 0.2, -0.32, -0.8 },
        { -0.11, 0.81, -0.92 },
        { -0.93, 0.37, -0.29 } };
    double b[] = { -0.3727, 0.4319, -1.4247 };
    int n = 3, nrhs = 1, lda = 3, ldb = 3, ipiv[3], info;

    dgesv(n, nrhs, lda, (double *)a, ipiv, ldb, b, info);
    cout << "x = " << b[0] << ", " << b[1] << ", " << b[2] << endl;
    cout << "info = " << info << endl;
    return 0;
}

Cプログラム例 (例題(2))

例題(2)ではf(x)の積分をqk15を使って求めます. qk15はf(x)を定義する外部関数を必要とします. 外部関数はCで作成することができ, qk15は必要なときにそれを呼び出します.

#include <stdio.h>
#include "cnumlib.h"

double f(double x)
{
    return 1/(1 + x*x);
}

void test_qk15()
{
    double a, b, result, abserr, resabs, resasc;

    a = 0; b = 4;
    qk15(f, a, b, &result, &abserr, &resabs, &resasc);
    printf("result = %g, abserr = %g\n", result, abserr);
}

実行結果

result = 1.32582, abserr = 0.00148272