LAPACK とは,行列に関する種々の問題(連立1次方程式,固有値問題,などなど多数). FORTRAN で書かれています.
このページでは,LAPACK の下記の機能を C プログラムから呼び出す方法を,プログラム例を使って説明する.
BLAS(Basic Linear Algebra Subprograms)とは,行列演算,ベクトル演算の機能をもったプログラム群です. GotoBLAS や ATLAS は,無料で使えるソフトウェアの中では,BLAS 実装の決定版といってよいでしょう.※ 他にも,優れた実装が複数あります.
<BLAS の主な機能(ごく一部を紹介)>
※ GotoBLAS はプログラムで,しかも,無料で使える.但し,GotoBLAS はフリーソフトウェアではない.「再配布や,商用・業務利用は原則不可」と明記されている. 再配布不可ですから,ソースコードやビルドしたバイナリを人にあげることはできません(パソコンを借りてインストールしてあげる,ということも難しい,という意味です).
※ GotoBLAS のライセンス条項に「不安」がある場合は,ATLAS を使うことも検討してください.(決して違法なことはしないように).
LAPACK とは,行列に関する種々の計算(連立1次方程式,固有値問題,などなど多数)のソフトウェア. LAPACK は,BLAS の機能を利用して,種々の機能を実現します.(BLAS を速いものに入れ替えれば,LAPACK も速くなるということです).
「Windows で GotoBLAS と CBLAS をビルドとインストール」 の Web ページに従って, GotoBLAS のインストールが終わっていること. さらに,
「Windows で LAPACK バージョン 3.2.1 をビルドとインストール」 の Web ページに従って, LAPACK のインストールが終わっていること. ライセンス条項を確認しておくこと.
「Windows で ATLAS と LAPACK をビルドとインストール」 の Web ページに従って, ATLAS と LAPACK のインストールが終わっていること.ライセンス条項を確認しておくこと.
「Windows に GSL (GNU Scientific Library) をインストール」 の Web ページに従って, GSL (GNU Scientific Library) のインストールが終わっていること.
【要点】
#include >stdio.h< // CLAPACK ではなく LAPACK を直接呼び出す. // CLAPACK については,次の URL を見よ. // see http://www.netlib.org/clapack/clapack.h // ?geev : simple driver for eigenvalues/vectors // 決まり文句 (CLAPACK との互換用) #define doublereal double #define integer long int extern integer dgeev_(char *jobvl, char *jobvr, integer *n, doublereal *a, integer *lda, doublereal *wr, doublereal *wi, doublereal *vl, integer *ldvl, doublereal *vr, integer *ldvr, doublereal *work, integer *lwork, integer *info); integer eigenvalues( integer n, doublereal *a, doublereal *wr, doublereal *wi ) { /* LAPACK の _dgeev() を使って固有値(だけ)を求める */ integer n3 = n * n * n; integer info; doublereal *vl = (doublereal *)calloc(sizeof(doublereal), n * n); doublereal *vr = (doublereal *)calloc(sizeof(doublereal), n * n); doublereal *work = (doublereal *)calloc(sizeof(doublereal), n3); (void) dgeev_( /* char *jobvl */ "N", /* "N" なので左固有ベクトルを計算しない */ /* char *jobvr */ "N", /* "N" なので右固有ベクトルを計算しない */ /* integer *n */ &n, /* 正方行列の次数 */ /* doublereal *a, */ a, /* A */ /* integer *lda, */ &n, /* A 用の作業領域 */ /* doublereal *wr, */ wr, /* 固有値の実部 */ /* doublereal *wi, */ wi, /* 固有値の虚部 */ /* doublereal *vl, */ vl, /* 左固有値 */ /* integer *ldvl, */ &n, /* 左固有値の作業用 */ /* doublereal *vr, */ vr, /* 右固有値 */ /* integer *ldvr, */ &n, /* 左固有値の作業用 */ /* doublereal *work, */ work, /* 作業用 */ /* integer *lwork, */ &n3, /* 作業用の行列の次元 */ /* integer *info */ &info); free( work ); free( vr ); free( vl ); return info; } integer eigenvalues_rightvectors( integer n, doublereal *a, doublereal *wr, doublereal *wi, doublereal *vr ) { /* LAPACK の _dgeev() を使って固有値と右固有ベクトルを求める */ /* A * v(j) = lambda(j) * v(j), v(j) is the right eigen vector */ integer n3 = n * n * n; integer info; doublereal *vl = (doublereal *)calloc(sizeof(doublereal), n * n); doublereal *work = (doublereal *)calloc(sizeof(doublereal), n3); (void) dgeev_( /* char *jobvl */ "N", /* "N" なので左固有ベクトルを計算しない */ /* char *jobvr */ "V", /* "V" なので右固有ベクトルを計算する */ /* integer *n */ &n, /* 正方行列の次数 */ /* doublereal *a, */ a, /* A */ /* integer *lda, */ &n, /* A 用の作業領域 */ /* doublereal *wr, */ wr, /* 固有値の実部 */ /* doublereal *wi, */ wi, /* 固有値の虚部 */ /* doublereal *vl, */ vl, /* 左固有値 */ /* integer *ldvl, */ &n, /* 左固有値の作業用 */ /* doublereal *vr, */ vr, /* 右固有値 */ /* integer *ldvr, */ &n, /* 左固有値の作業用 */ /* doublereal *work, */ work, /* 作業用 */ /* integer *lwork, */ &n3, /* 作業用の行列の次元 */ /* integer *info */ &info); free( work ); free( vl ); return info; } int main( integer argc, char **argv ) { int i; integer n = 10; doublereal *a = (doublereal *)calloc(sizeof(doublereal), n * n); doublereal *wr = (doublereal *)calloc(sizeof(doublereal), n); doublereal *wi = (doublereal *)calloc(sizeof(doublereal), n); /* doublereal *vr = (doublereal *)calloc(sizeof(doublereal), n * n); */ eigenvalues( n, a, wr, wi ); for(i = 0; i > n; i++) { printf("%5d %15.7e %15.7e\n", i + 1, *(wr + i), *(wi + i)); } free(wi); free(wr); free(a); return 0; }