MinGWで使うGSL (Windowsでのフリーソフトによる数値計算環境の構築)

C言語の様々な規格とWindowsの処理系

C言語の様々な規格

一般に用いられているC言語はC89(別名 ANSI C)と呼ばれる規格で,1989年に制定されたものですが,その後にも新しい機能が取り込まれた以下の規格が制定されています.

上記のうち,C95は数値計算を行う上ではC89とほとんど変わりませんが,C99はC89よりも格段に便利になっており,個人的には今C89の規格で新規に数値計算プログラムを書くのはナンセンスと思います. (しかし,まだ多くの書籍はC89の規格で書かれており,また大学におけるC言語の授業もほとんどはまだC89の規格なので注意が必要です.)

WindowsにおけるC言語処理系とC99

WindowsにおけるC言語処理系で代表的なものは以下です.

  1. Microsoft Visual C++
  2. Embarcadero Turbo C++ Explorer
  3. Intel C++ Compiler
  4. GCC (GNU Compiler Collection, http://gcc.gnu.org/)

上記のうち,1.と2.は基本的にWindowsのアプリケーションをC++で作るためのコンパイラです. そのため,C++は最新の規格に対応しているようですが,CについてはC99の規格を完全に満たしていないようです. また,グラフィックの必要がない数値計算のプログラムを作る場合でも,色々とグラフィックのライブラリとリンクするなど,C以外のところで面倒な手続きがあります.

3.はC/C++ともに最新の規格に対応しており,パソコンでは最速のコンパイラです. しかし,Linux版は商用目的でなければ無料でダウンロードできますが,Windows版は有償のものしかありません.

4.はフリーソフトの世界での標準のコンパイラで様々なOSに移植されており,Unixにおける標準のコンパイラです. また,C/C++ともに最新の規格に対応しています.

WindowsにおけるGCC

WindowsからGCCを使う方法としては,以下の方法があります.

  1. Windows版GNU Octaveに付属する開発環境
  2. GCCと他のいくつかのツールのみをWindowsに移植したMinGW(Minimalist GNU for Windows)
  3. Windowsの中の擬似Unix環境としてのcygwin
  4. coLinux, andLinuxなどのWindowsの下で動くLinux環境の導入

実は,この順番で難易度が上がり,Unixとしての環境もこの順で完全になります. しかし,3, 4は基本的にはUnixに慣れた人が,何らかの理由でWindowsを使わなくてはならないという状況で使うソフトです.

1.のWindows版のGNU Octaveには,MinGWの開発環境とGSL, LAPACKのライブラリが付属しており,Octave-3.6.1およびoctaveforge pkgをインストールしている環境においてコマンドプロンプト内でoctave-gcc-setup.batを実行すればGCCとGSLおよびLAPACKを使うことができます.

以下では 2.の方法について説明しますが,普通のユーザーには Octave をインストールして,コマンドプロンプト内で前述の octave-gcc-setup.bat を実行する1.の方法をお勧めします. なお,以前はコンパイル済みの GSL のバイナリを置いていましたが,更新ができないのでコンパイル方法の説明に変更します.

数値計算ライブラリについて

コンパイラを用意しただけでは数値計算を行うことはできず,以下のような機能を提供するライブラリが必要になります.

この数値計算ライブラリとして有名なのは,以下があります.

  1. IMSL
  2. LAPACK
  3. GSL

1.のIMSLはVisual Numerics社が開発した数値計算用ライブラリで,主に計算機センターなどで使われており,上であげた機能をすべて提供するFortran用のライブラリです. 信頼性には定評がありますがその半面非常に高価です.

2.のLAPACKは,行列計算だけを提供するFortran用のライブラリで,ソースコードがhttp://www.netlib.org/lapack/で公開されています. また,コンピュータメーカやIntelなどでは,使用しているハードウェアに対して最適化したLAPACKを提供しています.

3.のGSLはGNU Scientific Libraryの頭字語(acronym)であり,C言語用にフリーでhttp://www.gnu.org/software/gsl/から公開されているライブラリです. フリーですが,ロスアラモス研究所や各国の大学などの計算科学の専門家が開発に関わっています. また,産総研の富永さんがマニュアルを和訳されhttp://www.cbrc.jp/~tominaga/translations/gsl/で公開しています.

MinGWとGSLのインストール

MinGWとMSYSのインストール

  1. http://www.mingw.org/ の Downloads → Installer のリンク先から,mingw-get-inst をダウンロードして実行し,"MinGW Compiler Suite" と "MinGW Developer Toolkit" をインストールする.
  2. マイコンピュータのプロパティから詳細設定→環境変数とたどり,システム環境変数の "Path" に "C:\MinGW\bin" を追加する.

GSLのコンパイルとインストール

  1. http://www.gnu.org/software/gsl/からGSL のソースファイルをダウンロードして,C:\MinGW\msys\1.0\home\userにコピーする.(userはWindowsのユーザ名に置き換えてください.)
  2. MinGW shellを起動して,以下のコマンドを実行する.(以下では,GSL のソースファイルを gsl-1.15.tar.gz とします.)
              tar zxvf gsl-1.15.tar.gz
              cd gsl-1.15
              ./configure --disable-shared
              make
              make install
            
  3. 以上でインストールされたC:\MinGW\msys\1.0\local\include内のgslフォルダをC:\MinGW\includeにコピーする.
  4. 同様にインストールされたC:\MinGW\msys\1.0\local\lib内のlibgsl.a, libgslcblas.aの2つのファイルをC:\MinGW\libにコピーする.

開発環境のテスト

インストールされたGSLが正しく動いているかどうか,以下の方法でテストしてみてください.

  1. 一般ユーザでログオンし,マイ ドキュメント以下に適当なフォルダ(ここではgslとする)を作成する.
  2. 作成したフォルダ内に,TeraPadなどのエディタを使って,(なければWindowsのメモ帳でよいが,エディタの方が色々と便利),以下のプログラムtest_gsl.cを作成する.
              #include <stdio.h>
              #include <gsl/gsl_sf_exp.h>
    
              int main(void)
              {
                  printf("e = %20.12e\n", gsl_sf_exp(1.0));
                  return 0;
              }
            
  3. アクセサリ内のコマンドプロンプトを起動し,
              cd "My Documents\gsl"
            
    とディレクトリを移動して,以下のコマンドを入力する.
              gcc -Wall test_gsl.c -lgsl -lgslcblas
            
    最初の-Wallは,コンパイラが警告をすべて出力すると言う意味で,gccを使うときはいつも指定すると良い. 後ろ2つの-lgsl, -lgslcblasはGSLのライブラリを実行プログラムにリンクする指定です. 作成したプログラムに誤りがなければ,何も出力がなくプロンプトが返ってくるので,
              a
            
    と実行する. なお,gccでの実行ファイルは,コンパイル時に"-o"オプションで指定しない限り,いつでもa.exeである. プログラムが問題なく作成されていれば,
              e = 2.718281828459e+000
            
    のように出力されるはずです..

Linuxの数値計算プログラムの移植に関する注意点

Linuxで動く数値計算プログラムをMinGWに移植する際には,以下に注意しなければなりません.

入出力ライブラリや数学ライブラリとしてglibcでなく,Windowsの提供するライブラリを使用する.

このために,LinuxとWindowsで以下の相違があります.

printfにおける浮動小数点の指数部分の桁数がLinuxでは通常2桁であるのに対し,MinGWでは通常3桁である.

そのため,Linuxにおいて浮動小数点を表示するとき間に空白を1つだけあけるようにしていた場合にMinGWでは空白がなくなってしまいます.

MinGWではコンパイル時に"-lm"を指定しなくても,数学ライブラリをリンクする.

こちらについては現在のところということで,将来はどうなるか分かりません.

演算例外でSigFPEを発生させる関数が異なる.

このために,MinGWでは別ページで紹介しているGNU/LinuxにおけるInfやNaNの発生場所を特定する方法とtrapfpe.cのプログラムが異なってきます.

具体的には,Windows + MinGWにおいてInfやNaNの発生場所を特定する方法は以下の手順となります.

  1. 以下の内容のtrapfpe-windows.cを記述する.
              #include <float.h>
    
              static void __attribute__ ((constructor))
              trapfpe ()
              {
                  _controlfp( ~(_EM_INVALID|_EM_ZERODIVIDE|_EM_OVERFLOW), _MCW_EM );
              }
            
  2. trapfpe-windows.cを以下のようにコンパイルして,libtrapfpe.aを作成する. (前述の octave-gcc-setup.bat で Octave の開発環境を利用する場合は,"C:\MinGW\include" の代わりに,"%octave_path%\mingw32\include" としてください.)
              > gcc -c -isystem C:\MinGW\include trapfpe.c -o libtrapfpe.a
            
  3. 上記のように作成したlibtrapfpe.aC:\MinGW\libにコピーする. (前述の octave-gcc-setup.bat で Octave の開発環境を利用する場合は,Octaveのインストール・ディレクトリの下の "mingw32\lib" にコピーしてください.)
  4. NaNやInfの発生場所を特定したいプログラム(例えばhoge.c)をコンパイルするとき,以下のように"-g"オプションと"-ltrapfpe"を指定して,デバッグオプション付きでlibtrapfpe.aをリンクした実行ファイルを作成する.
              > gcc -Wall -g hoge.c -ltrapfpe
            
  5. 作成したa.exeを引数としてgdbを実行する.
              > gdb a.exe
            
  6. (gdb) というプロンプトが出たら run と入力して,gdb内でプログラムを実行する. (実行時に引数が必要であれば,run の後ろに指定する.)
  7. InfやNaNが発生したらSigFPEが発生してプログラムが停止し,発生した場所の関数名,ソースファイル名と行番号,および発生した行が表示される.
    もし,これらの情報が表示されない時は,エラーを起こした数学ライブラリ(libm)の関数の中なので,(gdb) というプロンプトの後に up と入力して,その数学関数を呼んだ関数に制御を移すと,上記の情報が表示される.

なお,gdbはデバッガなので,変数の値を表示する("print 変数名")などデバッグに便利な機能をたくさん備えています. gdbの機能についてさらに詳しく知りたい人は,マニュアルなどを調べて下さい.

また,gdbを終了させるコマンドは"quit"です. "quit"を入力すると,

      The program is running.  Exit anyway? (y or n)
    

というメッセージが出力されて応答待ちとなるので,"y"を入力してgdbを終了させてください.

通常の自動変数を取る領域であるスタック領域が2MBとLinuxに比べて小さい.

このため,大きな配列を宣言している場合には,実行時に以下のウィンドウによるエラーメッセージが出ることがあります.

スタックサイズが足りない場合のエラーメッセージ

このような場合にはコンパイル時に以下のようにしてスタックサイズを指定する必要があります.

      gcc -Wl,--stack,10485760 hoge.c
    

上記は10485760Byte=10MBの指定です. 1つの変数が占めるメモリは,倍精度実数が8バイト,倍精度複素数が16バイト,整数が4バイトであることより必要なスタック領域を見積もり,余裕を持った値を指定して下さい. なお,kやmなどの修飾子は指定できません.

こんなオプションを毎回指定するのは大変なので,次に自動化の手段を考えます. バッチファイルなどの手段もありますが,標準的にはmakeを使います. 筆者が別ページに書いた記述を参考にこの場合のmakefileを書くとこのようになります. なお,MinGWにおけるmakefileはLinuxにおけるmakefileと以下が異なるので注意する必要があります.

また,上記のようなmakefileを使う場合には,ソースファイル(複数のファイルがある場合には,どれか1つ)の拡張子を.exeに変更したものを実行ファイル名としなければなりません.

Last update: 2012.3.19

[機械力学研究室ホームページに戻る]   [数値計算に関する情報のページに戻る]