約 5,158,708 件
https://w.atwiki.jp/c-phys/pages/12.html
☆フリーのFortran環境をパソコンへ導入する方法☆ Windows7にて、下記の方法でやってもうまく動作しないことを確認しています。(2013/09/23) 下記の記事を全面的に書き直しますので、現状の記事は参考程度に留めておいて下さい。 現在のところ、MinGWはインストールせず、g95のみインストールして使用する方法が最も簡単と思われます。 他にもフリーのFortranはいっぱい有りますので、自分に有ったコンパイラーを探してインストールいただければ幸いです。 1、「MinGW」をインストールする。 以下の説明ではインストール場所はCドライブ直下(C \MinGW)であるとします。 (それ以外の場所にインストールする場合は以下の文章でC \MinGWの部分をC \***\---\MinGWに読みかえて下さい。 C \***\---\とは、あなたがインストールした場所のことです。) 注意点:インストール先のパスに空白が含まれていると、後でトラブルの原因になるため、「Program Files」へのインストールは避けてください。 まずはこちらのリンクから下記の画面に飛んで、MinGWのインストーラをダウンロードして下さい。 (2011年2月1日の時点ではmingw-get-inst-20101030.exeが配布されています。) 保存した「mingw-get-inst-20101030.exe」をダブルクリックするとこちらのサイトのような画面が現れるので、指示に従い「Next 」を選択していきましょう。 途中、下記の画面のように「c++ compiler」、「fortran compiler」、「ObjC compiler」の3つのみ選択することをお勧めします。 MSYS関連、MinGW Developer Toolkitは必ずしも選択しなくてOKです。 (fortran compilerはfortranのコンパイラですので必ず選択して下さい。c++も選択しておけば、C++で書かれたソースファイルもコンパイル可能になります。) 2、MinGWにパスを通す。 まず、パスを通す「バッチファイル」を作ります。テキストエディタを開き次のように一行書きます。 PATH=C \MinGW\bin;%PATH% または、 PATH %PATH%;C \MinGW\bin 上の二つのどちらでも結構です。次にこのファイルを「mingw.bat」という名前で「C \MinGW」フォルダの中に保存します。 (つける名前は半角英数なら何でも良いですが、拡張子は.batにします。) これでパスが通ります。 3、コマンドプロンプトのショートカットを作ります。 「スタート」→「すべてのプログラム」→「アクセサリ」→「コマンドプロンプト」 のところを右クリックし(注 コマンドプロンプトは立ち上げません)、「コピー」で、デスクトップなど自分が良く使う場所に貼り付けます。 そして、以下のように設定します。 Windows 7/Vista/XP/2000の場合 コマンドプロンプトを右クリック→「プロパティ」→「ショートカット」と追い、 「リンク先」の所を %SystemRoot%\system32\cmd.exe /k "C \MinGW\mingw" と変更する。(上記1行をコピー ペーストしていただいて構いません。) Windows Me/9x系の場合 MS-DOSプロンプト上で「右クリック」→「プロパティ」→「プログラム」を追い 「バッチファイル」の所を C \MinGW\mingw.bat と変更する。 これは、ドライブCの下にMinGWがあり、その中にmingw.batがある場合ですが、 今までの手順通りに行なっていれば、このまま、気にせずコピー ペーストして下さい。 4、コマンドプロンプト上で「右クリック」→「プロパティ」→「ショートカット」と追い、「作業フォルダ」の所を.fファイルを保存するフォルダに設定する。 例えばデスクトップの「FORTRAN」という名前のフォルダで作業するなら、 "C \Documents and Settings\(USER_NAME)\デスクトップ\FORTRAN" と入力する。((USER_NAME)の部分は人によって変わります。) 5、g95(Fortran95)を追加インストール 手順1~4まで行えばFortran77の文法は使えますが、Fortran90の文法は使えません。 そこでFortran90の文法も使えるようにg95(Fortran95)を追加でインストールしましょう。 ただしコマンドプロンプト上でのコンパイルの呪文が、g77→g95と変更されますので注意が必要です。 なぜなら、Fortran90の文法で書かれたプログラムをg77の命令でコンパイルできないからです。 インストールは簡単で、The G95 ProjectからStable versionのSelf-extracting Windows x86(g95-MinGW.exe)をダウンロードして、 C \MinGW\ に上書きインストールするだけでOKです。(2011年2月1日の時点ではStable version 0.91, March 2008が最新版です。) 6、以上で完了です。 では作ったコマンドプロンプトのショートカットを開いてプログラムを実行できるか確認してみましょう。 コンパイルコマンドは、 g95 ファイル名.f90 ←g95とfilename.f90の間は半角一文字空けます。 で、コンパイルできたら、(作業フォルダにa.exeができるので) a (Enter key) ←a と入力して(Enter key)を押します。 という風にして、プログラムを実行します。 ☆FORTRANリンク集☆ Fortran ResQ - 初心者のためのFortran入門 やさしいフォートラン講座 FORTRANプログラミング初級編 FORTRAN入門(pdf) cpadでg77を使う裏技 フォートランリンク集 ☆練習問題☆ 1、4次のルンゲ-クッタ法を用いて適当な常微分方程式を解いてみよう。 2、ガウスの消去法を用いて連立一次方程式を解いてみよう。
https://w.atwiki.jp/c-phys/pages/13.html
☆フリーのFortran環境をパソコンへ導入する方法(Windows XPの場合)☆ 1、まずコンパイラー(Silverfrost FTN77)をインストールする。 こちらからftn77pe.exeをダウンロードした後、ダブルクリックしてインストールして下さい。 2、CPad(エディタ)をインストールする。 こちらからfcpad231.lzhをダウンロードし、適当な場所に解凍しましょう。 fcpad.exeを起動して1でインストールしたftn77.exeの場所とプログラムファイルを保存する場所を指定して下さい。 後はCPadでプログラムファイルを開いて、青い三角ボタン(コンパイル&実行)を押せば、勝手にコマンドプロンプトを起動してプログラムが実行できます。非常に簡単です。この素晴らしいソフト(CPad)を作製された方のHPはこちらです。感謝。 なお、上記の方法だと、Fortran77の文法しか使えません。例えば、プログラムは6カラム空けてから書き始めなければなりません。 Fortran90以降の文法(配列など)を使いたい場合は、g95やgfortranをインストールしましょう。
https://w.atwiki.jp/kisohige/pages/31.html
Fortranに関するひげさんの備忘録的なもの。勉強したことをかくこともあるかもしれませんが大抵ぐぐればわかります。 一応公開しておきます。 注.基本Fortran90の話です。 Fortran77以前のことは触れてないですし、77以前の環境でここに書かれていることをするとはエラーが出るかもしれません。 まぁこんなページを参考にする人なんていないと思いますが、一応。 Fortranとは 環境 コンパイラ エディタ 使ってる本 Fortran使った関数、コマンドまとめ 変数型 なんかその他の便利な情報 数学系ライブラリ集 京都大学数理研究所 大浦拓也氏作。本人曰く実用に耐えるらしい。 Fortranとは ひげさんが現状勉強を進めている、プログラム高級言語のひとつ。高級言語としては世界最古らしいです。また蓮舫氏に2位でいいと言われたスパコンなんかはこの言語でプログラムをしているらしいです。 ▲ページ先頭へ 環境 参考になるかわかりませんが、自分の環境を晒しておきます。 メイン機(芙蓉) OS Ubuntu10.10/Windows XP Home Edition SP3 CPU Intel(R)Pentium(R) 1.73GHz RAM 1.49GB サブ機(陽炎) OS Ubuntu10.10 CPU Core 2 Duo RAM 2.0GB 最初はWindowsで運用していましたが、Linuxのほうが圧倒的に環境が整えやすいです。つかUnix環境ならいいのか? その辺はよくわかりませんが、2010年11月くらいから、開発環境のOSはUbuntu10.10を使用しています。 ▲ページ先頭へ コンパイラ ひげさんはgfortranというコンパイラを使用しています。コンパイラってなんぞ?という人はとりあえずググるなり、プログラムの入門書を買うなりしてください。親切に解説してくれているサイトはたくさんあります。 Windowsに導入 下のリンクはgfortranがおいてあるところです。英語なんで頑張って読んで自分の環境にあったものをインストールしてください。英語読むのダルいよ!って方はもっと親切に解説しているページがるので、gfortranでググってください。 ↓ gfortran 以下にひげさんがgfortranを使ってて起こったことをまとめてみます。 普通にwindows用のインストール用バイナリファイル(?)をダウンロード。起動してクリックしていけばOK。ただし途中でどのコンパイラをインストールするかきかれるので、ちゃんとFortranにチェックを入れてやりましょう。 XPでしか動かない模様。(2010年春時点)windows7ではどうもパスが通りませんでした。パスの設定の方法はちょっと難しかったので理解することを断念しました。 パスは自動でついかされません。(微妙に不親切。)手動で追加すれば大丈夫。gfortran.exeのあるディレクトリまで通してやりましょう。 Vistaで使おうとしたらNortonにトロイの木馬として退治されました。 とりあえず7以降は手軽にやるならXPモードを使いましょう。XPモードが使えるのは7Pro以上なので要注意。おそらく一般家庭で使っているであろうHomeEditionではXPモードは使えません。 ただし、XPモードはびっくりするほど重いので、正直おすすめしません。Linuxとデュアルブートが楽かも。 ちなみに上のwebサイトには、XP、Vista、7どれでも使える、と書いてあった気がします。 Ubuntuの場合Synapaticマネージャから一発でインストールできます。Windowsより手軽です。 ほかにもg95とかフリーのコンパイラはたくさん転がっています。詳細、使い方はググってくださいな。 正直なところ、g95の方が入門書で勧められてたりして、評判がよさそうです。 Ubuntuに導入 Synapaticマネージャで検索してボタン一発です。ラクチン。 ▲ページ先頭へ エディタ WindowsはSAKURA、Ubuntuはデフォルトのgeditを使用しています。強調設定をいじって見やすくしましょう。でもぶっちゃけた話、メモ帳でも編集はできます。 サクラエディタの強調設定について サクラエディタの強調用キーワードファイルにFortranはないので、適当にダウンロードしてきて設定してやりましょう。 ▲ページ先頭へ 使ってる本 この本使って勉強してます。 ザ・Fortran90/95 戸川隼人著 サイエンス社 入門FORTRAN90 ラリー・ニーホ+サンフォード・リストマー著 ピアソンエデュケーション ▲ページ先頭へ
https://w.atwiki.jp/fmemo/pages/16.html
ifortのコンパイルオプション g95のコンパイルオプション エンディアンを指定したいときifort g95 Fortranデバッグ用オプション 実行時に引き数を渡したいとき 整数のサイズ doループの仕様 内部入出力文 参考になるサイト ifortのコンパイルオプション 倍精度オプション $ ifort -r8 test.f90 デバッグオプション。これをつけないと配列の領域外参照をしていてもエラーにならないことがある。最適化オプションと併用するとエラーが起きるかもしれない? $ ifort -CB -traceback -g -check test.f90 書式無しファイル入出力でreclの単位を1byteにするとき。 $ ifort -assume byterecl test.f90 g95のコンパイルオプション デバッグしたいとき。 $ g95 -g -Wall -fbounds-check -ftrace=full test.f90 エンディアンを指定したいとき ifort 環境変数FORT_CONVERTn(nは数字)をBIG_ENDIANまたはLITTLE_ENDIANにすると、その装置番号で開いているファイルのエンディアンの扱いを変更できる。 $ FORT_CONVERT10=BIG_ENDIAN # 装置番号10番をBIG_ENDIANにしたいとき $ FORT_CONVERT15=LITTLE_ENDIAN # 装置番号15番をLITTLE_ENDAINにしたいとき すべてのエンディアンを一括して指定したいときは以下のオプションをつける -convert big_endian -convert little_endian g95 環境変数G95_ENDIAN=BIG, G95_ENDIAN=LITTLEを使う。 Fortranデバッグ用オプション 実行時に引き数を渡したいとき iargc, getargを使えばよい。これは非標準だが多くのコンパイラで使える。 program main implicit none integer i integer iargc, num character(128) var ! iargcは引数の数を返す関数 num = iargc() write(*,*) num ! getargは引数を返すサブルーチン do i=1,num call getarg(i,var) write(*,*) trim(var) enddo stop end program $ ./iargc_getarg.exe Anne Beth Chris 3 Anne Beth Chris ちなみに、0番目には"./iargc_getarg.exe"が入る。 参考サイトfortran備忘録 整数のサイズ integer(1)=1バイト整数 -128〜127 doループの仕様 do i=1,10 .... enddo のdoループが終わった直後のiの値は11 内部入出力文 character(64) char char= 100 200 read(char,*) num1, num2 write(*,*) "num1= ", num1 program main implicit none integer i,num character(100) fmt,cnum real(8) var i=4 num = 4 var = 1.23456 write(cnum, (i2) ) num write(*,*) trim(cnum) fmt = ( //trim(cnum)// f10.4) write(*,*) trim(fmt) write(*,fmt) var,var,var,var stop end program main 参考になるサイト Fortran縦々横々 Fortranの玉手箱
https://w.atwiki.jp/miura_takashi/pages/26.html
gfortran gfortran をとりあえずhpc.sourceforge.net から入れていたが、最近MacOSX用にパッケージ化してくれたヒトがいるらしい。しかしいれてみると gfortran -O2 -fno-range-check -c fftsg.f dyld Library not loaded /usr/lib/libiconv.2.dylib Referenced from /usr/local/bin/gfortran Reason Incompatible library version gfortran requires version 7.0.0 or later, but libiconv.2.dylib provides version 5.0.0 というエラーが出て止まるようになった。これはいかん。とりあえずlibiconv.2.dylib で検索をかけてみると、 http //homepage.mac.com/matsuan_tamachan/software/LibIconv.html - というページが出てきた。これを見て最新版をインストールする。ついでに $ export DYLD_LIBRARY_PATH="/usr/local/lib" を入れて新しい版を認識するようにしてみたが、今度は gfortran -O2 -fno-range-check -c fftsg.f make[1] *** [fftsg.o] Bus error make *** [double] Error 2 が出て止まる。元に戻す。 ifort install intelでもfortranを出している。 http //www.intel.com/cd/software/products/asmo-na/eng/282048.htm これが Intel Mac だと最適化して非常に早くなるという噂を聞いたので、評価版をダウンロードして入れてみる。これはインストーラが付属していて特に問題なし。とりあえずMakefile でコンパイラをifortに変えると fortcom Error fortmain.f, line 32 Syntax error, found END-OF-STATEMENT when expecting one of = .EQV. .NEQV. .XOR. .OR. .AND. .LT. .LE. = .EQ. == .NE. /= .GT. ... dimension u(imax,jmax), v(imax,jmax), eig_u(imax,jmax), eig_v(imax,jmax) --------------------------------------------------------------------------------^ compilation aborted for fortmain.f (code 1) make *** [fortmain.o] Error 1 というエラーが出て止まる。 ためしに、 gfortran fortmain.f をかけてみると、 fortmain.f 32.72 dimension u(imax,jmax), v(imax,jmax), eig_u(imax,jmax), eig_v(ima 1 Error Expected another dimension in array declaration at (1) が出て止まる。ほぼ同じ場所で止まっているようだ。ということは、Makefile に入っている-ffixed-line-length-noneが効いているようだ。Fortran の文法の問題か?代わりに-extend-source を入れると通った。しかしこんどは Linking Type1.out ... ld multiple definitions of symbol _main /opt/intel/fc/10.0.016/lib/for_main.o definition of _main in section (__TEXT,__text) fname.o definition of _main in section (__TEXT,__text) make *** [Type1.out] Error 1 というのが出る。検索をかけてみたら lists.apple.com—msg00012.html http //lists.apple.com/archives/fortran-dev/2007/Jul/msg00012.html というのがあったので、-nofor-main というオプションをLDFLAGSにつけてやったら通った。完了。
https://w.atwiki.jp/usapfrog/pages/37.html
Matlabが遅いよってことで一から勉強するよ Hello Worldまで コンパイラだけなら、linuxは常備(なかったらyumなどで)。 [Windows] OctaveかMingGW環境で手に入る。 Windowsならインストール後"C \Octave\Octave3.6.4_gcc4.6.2\mingw\bin"と"C \Octave\Octave3.6.4_gcc4.6.2\mingw\msys\1.0\bin" または、"C \MinGW\bin"と"C \MinGW\msys\1.0\bin"にパスを通しとくのを忘れないこと。 (LAPACKを使う予定があるならOctaveをいれておくこと) [Mac] macportsやhomebrewなどで、gfortranをインストールする。 $ vi test.f90 program main write(*,*) Hello World end $ gfortran test.f90 $ a.exe 開発環境/IDE まあでも、やっぱIDE欲しいよ。 (WindowsならMinGW導入後) EclipseのPhotranを導入する。 導入法に従って、インストール。 (今までのeclipseに後付しないんなら Eclipse for Parallel Application Developersを落としてきて解凍すればよし) ついでに日本語化をしておく。 http //mergedoc.sourceforge.jp/の真ん中下くらいのPleiades プラグインをダウンロード・解凍 中身をeclipseのフォルダにコピペ・統合する。 eclipse.iniの最終行に以下を追加 -javaagent plugins/jp.sourceforge.mergedoc.pleiades/pleiades.jar 初回のみ同梱のeclipse.exe -clean.cmdから起動する 64bit windowsで起動時にJavaがエラーがないとエラーが出るときは、64bit javaを手動でインストールして、http //www.java.com/ja/download/manual.jsp、C \Program Files\Java\jre7\binにパスを通すこと 新規→プロジェクトでFortranぽいのを選ぶ 新規→ソースでFortranソースを選ぶ 上のプログラム書く ビルド・実行 (合間にでるオプションは Local Fortran Application, MinGW gdb) 参考 (pdf)eclipseでFortranプログラムの作り方 コード規約 流儀が本やらサイトによってそれぞれみたいだけど大体以下をベースに。 気象研究所 北海道大学 Fortran90 Tips NAG Fortran入門 FortranTips 変数宣言 変数同士の計算式は大体C同様で計算できる。 複素数標準実装、倍精度のdの使い方が特徴的。 というよか、Fortranでは少し神経質に倍精度指定しなきゃならないらしい。 うっかり1.0とか使うと、単精度になり桁に余計なゴミが入る。 program sampleinteger alogical preal(8) yreal(8), parameter pi = 3.14159 !定数など。(=Cのconst)complex(8) scharacter(len=4) w a = 3p = .true.y = 42.0d0 !dは 3e-3のeみたいに使うs = (6.0d0, 3.0d0) !これで s = 6 + 3iw = "abcd" print *, a, z, u, wend program sample 追記 characterはcharcter w*4でなく上記フォーマットのほうが了解性の点で良いらしい。 掛け算と混同してもいかんしね。 配列 足し算・内積。行数がずいぶん削れるのがありがたい。 printの書式はCとちょっと違う感じ。 program sample implicit none integer, parameter D = 3 real(8) x(D) = (/1d0, 2d0, 3d0/) real(8) y(D) = (/2d0, 1d0, -1d0/) real(8) z(D), v(D) real(8) w real(8) A(D,D) A(1,1 3) = (/ 8.0d0, 1.0d0, 6.0d0 /) A(2,1 3) = (/ 3.0d0, 5.0d0, 7.0d0 /) A(3,1 3) = (/ 4.0d0, 9.0d0, 2.0d0 /) z( ) = x( ) + y( ) v = matmul(A, x) w = dot_product(x, y) print "(a, f8.3, f8.3, f8.3)", "z=", z print "(a, f8.3, f8.3, f8.3)", "v=", v print "(a, f8.3)", "w=", wend program sample 結果 z= 3.000 3.000 2.000 v= 28.000 34.000 28.000 w= 1.000 ループ・分岐 do i=初期,限界,増分 else if (condition) then program sampleinteger i, j, kj=0; k=0do i=1,20 print *, "loop i=", i k= k + 3 if ( k 15) then print *, "exiting loop..." exit ! = break in C end if if ( k 6) cycle ! = continue in C j= j + 2enddoprint *, j, kend program sample 結果 loop i= 1 loop i= 2 loop i= 3 loop i= 4 loop i= 5 loop i= 6 exiting loop... 4 18 関数・モジュール 追記 引数には入出力指定を示すintent(in/out/inout)を付記すること。 sampmodule.f90 module sampmodule implicit none real(8),parameter c = 340d0 real(8),parameter rho = 1.3d0containsinteger function smd_test(a, b, x) integer, intent(in) a, b, x smd_test = a + b * xend function smd_testreal(8) function smd_pres(u) real(8), intent(in) u smd_pres = rho * c * uend function smd_presend module sampmodule sample.f90 program sample use sampmodule implicit none integer d real(8) p print *,c d = smd_test(1, 3, 5) print *,d p = smd_pres(2.0d0) print *,pend program sample ベクトルを返すとき 戻り値がベクトルの時は、resultを指定する。例は外積関数。 function cross(a,b) result(axb) implicit none real(8),dimension(3) axb real(8),dimension(3),intent(in) a real(8),dimension(3),intent(in) b axb(1) = a(2)*b(3) - a(3)*b(2) axb(2) = a(3)*b(1) - a(1)*b(3) axb(3) = a(1)*b(2) - a(2)*b(1)end function cross テキストIO statusのオプションが "r/w"に対応して、"old / (new, replace)" 追記をしたいときはopen文にposition= append オプションを付ける。 エラー処理をしたければiostat=status(整数変数)をつければ、 open時読み込みエラーをstatusに格納してくれて、open時のエラーをスルーできる。 program sample implicit none integer i, j, status integer,parameter fout = 11 integer,parameter fin = 12 real(8) x(20,20) do i=1,20 do j=1,20 x(i, j) = i * 100d0 + j; enddo enddo open(fout, file= mydata.dat , status= replace ) write(fout, *) x close(fout) open(fin, file= mydata.dat , status= old , iostat=status) if ( status .ne. 0 ) stop read(fin, *) x close(fin)end program sample バイナリIO サイズを指定して、オプションが長くなるだけ。 access, form, recl, rec program sample integer siz = 20*20*8 open(fin, file= mydata.bin , access= direct , form= unformatted , status= old , recl=siz) read(fin, rec=1) x close(fin) open(fout, file= mydata.bin , access= direct , form= unformatted , status= replace , recl=siz) write(fout,rec=1) x close(fout)end program sample 共有メモリメモリ並列(SMP) gfortranの共有メモリ並列(-fopenmp)はコンパイラオプションの最適化(-O3)とどこか相性悪いらしく、 扱う配列サイズがやや大きい場合、segmentaion faultを吐くことがあるらしい。 この場合、最適化は(-O1)を指定するとうまくいくことがある。 program sample implicit none integer, parameter n=36 integer i, ene(n), res ene( ) = 0 res = 3 !$omp parallel do private(i) do i=1,n ene(i) = 2*i + res end do !$omp end parallel do print *, ene( )end program sample バグった時はprivate指定をもう一度見なおしておくと良い。 3次逆行列/3次方程式 N 4のときは、素直にLapackとか然るべき数値計算ルーチンを使うべきだけど、 多用する3x3くらいは、(必要なライブラリかき集めるのめんどいし、四角い車輪の再生産にあるけど) 自分で書いていい気がする。 function inv3(A) result(Y) implicit none real(8), intent(in) A(3,3) real(8) Y(3,3) real(8) det integer i,j det = 0 do i=1,3 det = det + A(i,1)*cofact3(A,i,1) end do do i=1,3 do j=1,3 Y(i,j) = cofact3(A,j,i) / det end do end doend function inv3real(8) function cofact3(A,i,j) implicit none real(8), intent(in) A(3,3) integer, intent(in) i, j integer i2, i3, j2, j3 i2 = mod(i, 3)+1; i3 = mod(i+1, 3)+1; j2 = mod(j, 3)+1; j3 = mod(j+1, 3)+1; cofact3 = A(i2,j2)*A(i3,j3)-A(i2,j3)*A(i3,j2)end function cofact3 !wikipediaの三次方程式の解の公式・実部しか取ってこないので注意subroutine solve3(x, a) implicit none real(8), intent(out) x(NDIM) real(8), intent(in) a(NDIM) integer k complex(8) j, w, y(NDIM), p, q, R, S j = (0, 1) w = 0.5d0*(-1d0+j*sqrt(3d0)) p = a(2)-a(1)**2/3d0 q = a(3)-a(2)*a(1)/3d0+2d0/27d0*a(1)**3 R=(-q/2d0 + sqrt((q/2d0)**2 + (p/3d0)**3))**(1d0/3d0) S=(-q/2d0 - sqrt((q/2d0)**2 + (p/3d0)**3))**(1d0/3d0) do k=1,3 y(k) = w**(k-1) * R + w**(4-k) * S x(k) = real(y(k),8) - a(3)/3d0 end doend subroutine solve3
https://w.atwiki.jp/imops-forth/pages/13.html
Forth言語特性 Forth言語では、古典的には"間接スレッディング方式"という特殊な実行形式が採用され、"コンパイル"というときにも特殊な意味で用いられていた。 しかし、ここでの話はマシン語を生成するネイティブコード・コンパイラを対象とするため、その解説は省く。参照 Forth系の言語ではコンパイラの作成が非常に容易ともいわれる。その第一の理由は構文解析や意味解析のためのコードを書く必要がないからだ。 Forth言語には特殊記号のようなものは、ほとんど — 全くというわけでもないが — ない。記号のように見えるものも、一つ一つが実行上の意味を持っている。その各々はワード(word)と呼ばれる。そのワードが書かれてある順番に実行されていくだけ、というのが原則となる(当然、例外も多くある)。ワードの特定には、まず区切り文字で区切られた文字列が取られる。続いて、その文字列を名前とするワードが既に辞書(dictionary)に登録されているかどうかが確認される。区切り文字としては、原則として、空白、タブ、改行のみが用いられる(コードファイルの初めと終わりも、文字ではないが、ワードの区切りとなる)。そのため、forthでは空白文字に挟まれた文字列を取り出す、ということだけで何を実行・コンパイルすべきかがわかってしまうのである。 他方、通常のプログラミング言語では、"+"のような明確に加法演算としての意味を持つ記号さえ、それ単独では実行あるいはコンパイル上の意味には何ら結びつけられていない、ただの文字記号である。構文解析を経て文(statement)の意味を判定した上で初めてそこで何を行うべきかがわかるのである。 上のようなforthの特性は、手練のプログラマには好都合だ。しかし、自分のような素人にはかえって困った事態であるともいえる。 というのも、世にあるコンパイラ作成のための標準的テキストブックでは、その分量の半分くらいは字句解析・構文解析・意味解析に割かれているのである。初級的になればなるほどその割合は増える。逆に言えば、forthコンパイラを構築するとき正に知りたいような事柄には、ごく僅かのページ数しか割かれていない。そのため、記述が簡潔に過ぎ、少し考えれば容易にわかるような大雑把なことしか書かれていない事も多い。しかし、これは仕方のない事でもある。まず、通常の数式のような外観を持つ表記を実際の計算手順に落とすには、必ず先読みと構文解析が必要になる。そして、さらにいえば、コンパイラ設計の教科書の目的は、コンパイラ設計が自分でできるようになるための方法を(その一冊で)教えることでは必ずしもないのである。そこでの目的はむしろ、様々なコンピュータ・アルゴリズム(定型的な処理手順)の応用を教えることなのだ。コードテキスト解析の領域は、いかにもコンピュータらしい考え方やアルゴリズムの応用が豊富に見いだせるようだ。教科書がこの領域の解説を無しで済ませるわけにはいかないのだ。 結局、教科書や体系書のようなものも入門書のようなものも、一冊も読まなかった。既存のコードとネットで拾った英語の論文の類だけが参考書だった。 マシンコード生成 重点はコード生成だった。しかし、直ちにマシン語を吐くものを初めから考えた。中間コードや仮想マシンは考えなかった。 Forthは実は古典的には仮想マシン方式といえる。仮想スタックマシンである。中間コード方式ではないが、上に述べた字句解析・構文解析・意味解析の部分が軽いため、インタープリタでも高速だった。コンパイルされた後はもちろんさらに速くなる。マシン語を直接生成するコンパイラに匹敵するものさえあった。しかし、コンパイラの最適化技術は進み、マシンも変化した。 最新のネイティブコード方式、つまり、最適化されたマシン語を生成・実行するタイプのforthでも、forth特有のデータスタックは維持されている。スタックマシンは仮想といってもコンピュータの実際の動作に極めて近い。そしてforthコードはその仮想スタックマシンのマシン語の様な基本ワード群から成るのである。スタックマシンという仮想マシンをつくってしまえば、その上でforthコードは、マシン語のように — つまりワードに動作を一対一に対応させるように — 実行・コンパイルできるわけだ。 けれども、パラメターをすべていちいちスタックに押し込んだりスタック操作ワードに合わせてアイテムを入れ替えたりするのでは、今ひとつ速度がでない。それでも32bitモードのx86ならある程度仕方がないが、64bitモードでは、32bitでは8本しかない汎用レジスタが16本に増えているのである。スタックメモリにはキャッシュは効くだろうが、レジスタを使う方が数倍速い。ど素人の初心者ではあるが、あまりに遅いコードを吐くコンパイラはつくりたくなかったのである。また、模範となった環境であるPowerMopsは、PowerPCが持つ多数のレジスタを用いて大規模に最適化されたものであったため、あまりに実行速度に落差のあるものではマズいとも思ったからである。 結果として、そこそこレジスタを多用するコード生成はできたと思う。したがって(素人作のオープンソースフリーウェアの)iMopsでさえ、その中身まではforthのようには実行されてはいない。データスタックはむしろ臨時のデータ避難場所として使われている。しかし、もちろん全体としてはスタックフレームではなく1セル1アイテムのスタックとして動作する。多くのネイティブforthコンパイラでもそうだろうと思う。Forthのスタックは実装そのものだと考えている人は今も多いが、forthのスタックとはむしろ抽象データ型である。 とはいえ、iMopsではその“避難”の頻度は割に高い。本当にきちんとやるには、ワード定義の終わりまで先読みして、全体として最適化するか、後になって判明した情報を使って既にコンパイルした部分を再コンパイルするかしないといけない。X86は単位マシンインストラクションのバイト長が区々なため、再コンパイルはかなりキツい。完全に最適化しようとすれば、コンパイル速度はかなり落ちるだろう。しかし、そういった大域的最適化で実際に書いたコードと全然違う処理に変換してしまうのは、あまりforth的ではない。forthでは、プログラマが自分で最適なコードを書く、というのが原則である。それができるし、またプログラマも普通にそうするというのが、forth言語環境の良さであり面白さでもある。iMopsの場合、データスタックに4つ以上のデータを積まないことと、条件分岐のところでは特にスタックを浅く保てるようにすることが、速いコードを生成する基本になっている。 雑論 知識量ではなく、目的の明確さが重要 「コンパイラやインタープリタをつくりたい」と考えると、定評のある教科書、よくあるのがドラゴンの本とか、そういう分厚くて重厚な本の内容を全部勉強しようとする人がいる。勉強するのはよいことではあろうし、学校のペーパーテストとかならそれでバッチリなのだろうが、実際に何かモノをつくるという目的のためには、迂遠な方法であると思う。多分、大抵はあまりの分量に挫折し、それどころか、最後まで勉強し切っても、まだ、どうやってつくるのか分からないという結果に終わるかも知れない。コンパイラやインタープリタの制作が高度な技だと思われている主要な理由は、そんなところにあるのではないかとさえ思われる。「あんなに高度な本を習得しても、まだできない」とかナントカ。 確かに、コンパイラをつくるとなれば、コンピュータという機械がどんな風に動いているか、とか、標準的にはどういう処理手順で回すことになっているのか、とか、そもそもコンパイラというプログラムは何ができないといけないのか、とか、そういう知識は必要である。そして、最近の便利な開発環境で普通にプログラムを書いているだけでは、そういうことは知らないかも知れない。けれども、実際は、そんなに詳しく知る必要はない。だいたい分かっていればいいのである。一番必要なのは、たくさんの知識と学識を身につけることではなくて、今まさにやろうとしていることを明確にすることである。作ろうとしている言語の基本文法と、インタープリタ方式にするかコンパイラにするかみたいなことは、初めに決めないといけない。基本構文を解析する部分は、フロントエンド問題、出力をどうするかはバックエンド問題などといわれるらしい。 インタープリタ方式かコンパイラ方式か 自分の場合、Mac OS Xで動くx86上でネイティブなコンパイラ方式のMops開発環境、ということで初めから絞られていたので、選択の余地はなかった。それをつくる上で解決しなければならない問題、を考えればよいだけだった。Mac OS X上で、Mac OS X用のソフトウェアを開発するとなれば、Xcodeで、言語はObjective-Cとか、ともかくC言語系、というのが普通だが、それだとあまりに当たり前であるし、forth系の異常なほど単純な機構を実現するのに、相当複雑な技を駆使しないといけないように思われた。そこで、forthの伝統的方法、つまり、自己生成という経路で構築することにした。最近のforth系は核部分はC言語で書かれることが多く、それにはいくつかもっともな理由があるのだが、Mopsに関しては、Mopsを構築するのに、Mops以外、他のコンパイラもリンカも要らない。 コンパイラ方式は、原則全て機械語に変換してから実行するので一般に実行速度は速く、インタープリタ方式では、機械の動作に変換しながら実行するので実行速度は遅めになる。ただ、最近は、計算速度が速い機械が多く、よほど濃い処理をしない限り、インタープリタでも、体感で差は感じられないことが多い。一般には、コンパイラ方式の方が難しく、初心者はインタープリタがよい、みたいな空気があるように思われる。けれども、本当はそうでもないような気がする。 とはいえ、まあ、確かにコンパイラ方式だと乗り越えなければならない、結構高いハードルがある。けれども、それは「ターゲット機械のマシン語を知る」というところではなくて、実行可能ファイルをつくるというところにある。厳密に言うと、多くの場合、実行可能ファイルを生成するのは、コンパイラの仕事ではなくて、(静的)リンカという別ソフトウェアの担当である。そういうのも全部まとめてコンパイラセットなどといったりするわけである。「コンパイラの設計」みたいなタイトルの本は、狭い意味でのコンパイラ、つまり、マシン語に変換するという部分のソフトウェアの解説であることが多い。しかも、その"マシン語"は架空のRISCマシンのアセンブリ言語だったりする。実用ではなくて原理を説明する、といわれれば、まあ、確かにそれでいいのだという気もするが、タイトルには「実用」とか書いてあったりする。一番高いハードルまでは、全然到達する気もないのである。そういう意味でも、書籍というのは割とあてにならない。とはいえ、この辺は同じ機械でもOSが違えば違う、みたいなところなので、教科書に書くというわけにもいかないのも確かであるのだが。 インタープリタ方式だと、インタープリタ自体がソフトウェアとして常駐している状態なので、独立に起動できるような実行可能ファイルをつくる必要はない。だから、今の環境で動くアプリケーションを書き出せる開発環境があれば、後はコンパイラ本に書かれてあるようなことだけで済む。そういう、いわば資料的な意味で、インタープリタをつくる方が易しいのである。というか、アプリケーション開発環境とコンパイラ本の世界で限定してみれば、インタープリタしかつくれないのである。だからといって、インタープリタをつくる方が、コンパイラ作成よりも、技術的に易しいとか初歩的だとはいえないように思う。プリミティブ(単位になる動作)を、どんな風に腑分けするかとかは、実行速度にも関連してくるので、結構、面倒な判断である。逆に、コンパイラだと、そういうプリミティブは機械の規格でばっちり決められているので、迷う必要がない。 インタープリタ方式は、今日ではプログラミングの主流となっている。ウェブ経由のプログラムは、コマンド処理のスクリプトというレベルのものであっても、詰まる所はインタープリタによる動作である。連動して動く一組のアプリケーションを、柔軟性や可変性を保ったまま連結する方法として、内部インタープリタ(スクリプト)の機構を持たせる場合も多い。インタープリタはテキストファイルであるソースコードの書き換えで動作を任意に変更することができるが、機械命令にコンパイルしてしまった場合には、コンパイラを用いて再構築し直さないことには、動作を変更できない、というのが一般的だからである。このような意味では、コンパイラをつくるよりも、インタープリタをつくる方が実践的意味があるようにも思える。 とはいえ、例えば、コンパイラ系のforthやMopsでは、ソフトウェア内部にコンパイラを組み込んで、内部スクリプトに利用することもできる。この場合、コンパイラ方式であるため処理は高速でありながら、内容は可変的である。同じことは、「オレ言語」でもできるはずであるから、そこでインタープリタにこだわる理由は、実はないのである。 要は工夫次第で何とかなる場合が多いのであって、どっちでもつくる側としては大差ないよ、という感じだろうか。 【補】用語の問題 何いってんのか、単語の意味が分からん、という人のために、説明。といっても、教科書にあるような正確な定義ではなくて、ここだけの語用の話。背景も説明するので、教科書とかの定義が、一体何がいいたくてそういう風になっているのかも分かるようになる。かも。 ネイティブコード:そのコンピュータの機械語のこと。OSとかには依存せず、機械(ハードウェア)にのみ依存する。 ソースコード:ブログラミング言語で書かれたプログラム。普通はテキストファイルとして保存される。インタープリタもコンパイラも、これをファイルから読み込んで機械の動作に変換する。コーディングをするというのは、これを書くこと。プログラミングをするといっても同義のこともあるが、それにはもっと抽象的な設計や仕様書を書く(その用語もプログラミング言語と呼ばれる)場合も含まれる。コーディングしないプログラマーもいる。テキストファイルといっても文字自体は1バイト(8ビット ビットは1または0の一桁分)単位の数値で符号化(1文字1バイトとは限らない)されているので、コンパイラやインタープリタは、その符号を解析し、何を命令しているのかをプログラミング言語の文法にしたがって判別し、それと同等の処理動作を表す機械語に変換(そして実行)するのである。 インタープリタ:ソースコードを読み込んで、そのプログラムを実行するアプリケーションソフトウェア。最近は仮想機械(バーチャルマシン)ということが多いようだ。呼称の違いは考え方の問題で、コンピュータやOSとインタープリタを込みで考え、ソースコードを機械命令のように実行できる機械と見なすという発想で、仮想機械というようだが、ちょっと商売くさい意図が感じられる気がする。動作は、原始的というか原子的な部分は、もうアプリケーションで組んでしまって、ソースコードの内容を解析して、その原始的動作の系列に分解して実行するわけである。 コンパイラ:ソースコードを読み込んで、その内容を"機械が"実行できる命令の系列に変換して保存するアプリケーションソフトウェア。意図的にかなりぼかした説明。"機械が"に引用符を付けたのは、Javaとかのコンパイラは、本当の機械命令に変換するのではないのに、やはりコンパイラだからである。同じJavaでも機械命令に変換するのもあったりするのでややこしい。また、「保存する」先もファイルとは限らない。メモリーでもよい。ファイルに保存したとしても、それがそのまま実行可能なファイルとは限らない点は先述。「コンパイル」というと機械命令に変換することと短絡してしまう傾向はあるが、もともとはそういう意味ではないらしい。コンパイルは普通の英語なのであって、製本するという意味がある。それがコンピュータに適用された際には、多分、プログラムの内容を、機械で実行される命令の系列として一本に束ねる、というような意味合いであったのではないかと思われる。だから、forthはインタープリタ環境であったけれども、定義は「コンパイル」されるのである。コンパイラの出力が機械命令を含んだファイルとして保存されるとき、生成されるファイルは、オブジェクトファイルとかアーカイブファイルとかいわれたりする。この種のファイルはそのまま実行はできないことが多い。後でリンカが処理する。だから利用されるリンカアプリケーションに依存して形式は決まる。オブジェクトファイルにはリンク用に関数のリンク表も組み込まれる。関数(サブルーチン)の名前と対応する機械命令系列の位置(同じファイル内にある場合)などを、符号や文字列や数値を用いた既定の形式で書き込む。この表(テーブル)も必要ならコンパイラが生成すべきデータである。 実行可能ファイル:アプリケーションを起動する過程は、実はそれほど単純ではない。OSがその過程をサポートするわけだが、OSが理解できるようなファイル形式(内容のことではない)でないと何をどうサポートしていいかわからない。つまり、OSが「あ、これはアプリケーションで、起動するにはコレコレが必要だな」と理解できるような形式というのが、実行可能ファイル形式である。だから、それはOSと一緒に規格として決まっている。Mac OS XだとMach-Oフォーマットという名前で呼ばれている。Windowsは、良く知らないが、.exeの形式で、形式名はPE。確かおおもとはCOFF(UNIXのだったと思う)というのだったとどっかで見た気がする。略号のoは「オブジェクトファイル」のオである、確か。以前のPowerPC MacではPEFという名前で、Windowsのものと名前が似ているが、WindowsのPEのPはポータブルで、PPC Mac のPEFのPはPreferredなので別物である。ただ、基本は古いUNIXでの規格を元にしているようなので、大まかな形式は似ている。だいたい、ヘッダデータというのが冒頭に付いていて、実行ファイルであることとか、実質部分の大きさや配置構造、エントリーポイント(コードの最初の位置)、起動に必要な情報や命令とかが、既定の符号とか数値、文字列などで記録されている。そしてその後に、まさに機械命令の系列とかグローバル変数のための領域(実質部分)とかが続いているわけである。実行可能ファイルにも動的に関数にリンクするためのテーブル(表)が、普通ついている。ちなみに、LinuxではELFという名前だったと思う。 リンカ:最後の「カー」は伸ばした方がいい(linker つなげるもの)と思うが、ここでは略す。リンカには二種類ある。静的リンカと動的リンカである。コンパイラの後に作動して実行可能ファイルをつくるのは静的リンカである。リンケージエディターとかリンクエディターとかいったりもする。動作としては、生成されたオブジェクトファイルから必要な部分をコピーして1つのファイルにまとめ、オブジェクトファイルのリンク表を使って呼び出しとかをうまく整合させて動作可能な状態にし、ヘッダをつくって実行可能ファイルフォーマットにするのである。また、実行ファイル用の関数リンク表もつくる。外部から関数にリンクしたり、逆に、外部の関数にリンクしたりするのに利用するのである。この「外部とのリンク」を実現するのが動的リンカである。動的リンカはOSサービスとして常駐しているソフトウェアで、アプリケーションが動作中に外部の関数を利用したいとき、この動的リンカの助けを借りてリンクするのである。動的リンクは、関数名文字列を渡して関数ポインタをもらい、そこにジャンプする、という感じになっている。 コンパイラ方式のハードル 実行可能ファイルを出力するコンパイラ方式の開発環境をつくろうとすると、ちょっと前にも書いたように、ターゲット環境の実行可能ファイルフォーマットの仕様を調べないといけない。これは英語であれば大抵資料はある。Macの場合、Appleの開発資料サイトにある。けれども、実は、ファイルフォーマットだけ分かっても、不十分である。というのは、外部関数を呼び出さないことには、アプリケーションは大したことができないからである。OSサービスとか標準Cライブラリの関数とか、外部関数の呼び出しは、ヒープメモリーを確保するという低レベルなことにさえも必要である。関数呼び出し一般には、そのための関数があるので、それを使えば良い。ところが、その関数も外部関数なのである。つまり、問題は、最初のOS関数呼び出しはどうするのか?である。 Mac OS Xで使われるMach-Oフォーマットに関しては、関連部分がオープンソースプロジェクトになっていたりして、自分の場合はナントカ動作方法は分かった。要するに、関数ポインタ専用フレームをデータ域内に準備して、その位置をヘッダで明示しておけば、アプリケーションを起動する際、OS側(ローダーと呼ばれるアプリケーション)が、外部への動的リンク用関数など、必要な関数のポインタをその場所に書き込んでくれるのである。Mach-Oの場合、そのポインタ格納用フィールドは、dyldセクションと呼ばれる。フルでいえば、ダイナミックリンクエディターセクションであるらしい(なぜか後半はleではなくldである。)。その枠の冒頭にはジェネリックな関数呼び出し用関数のポインタが格納される。Mopsでは、起動時のセットアップのために呼び出される外部関数が数個あるが、これらは、このジェネリック呼び出し関数を使って関数ポインタを取り、そこに分岐する。一旦取った関数ポインタは普通、終了まで変更されることはないので、保存しておいて、二回目以降は、そのポインタで直接リンクする。この数個の関数の中には、関数名から外部関数ポインタを取るための標準関数(dlopen()とdlsym())も含まれている。これらの関数は、いってみれば、動的リンカのサービス関数なわけである。本当はこの二つだけ取っておけば後は全部リンクできるのだが、他にも数個、初期の外部呼出関数として同じ方法で呼び出している。それら以外は、全部、標準の動的リンク関数を用いている。オブジェクティブCのメソッドとかにもリンク可能になる。オブジェクティブCの、Cocoaなど、ハイレベルな外見のオブジェクト指向部分といえども、中身はC言語型の補助関数の組み合わせだからである。 Mac OS以外の環境での実行可能ファイルの規格や起動の手順も似たようなもののようではあるが、細かいところはどうなっているのかよくわからない。これは調べるしかない。普及した環境なら、多分結構資料は充実しているし、ネット経由でタダで手に入ると思う。ただし、英語だと思うけれども。コンピュータ関係なら、英語にひるまなければ、大抵のことは調べがつく。 とはいえ、どうしても分からないというときには、インタープリタ方式にして、実行可能ファイル形式の部分は、既に手元にある開発環境にまかせてしまうという手もある。それにもかかわらず、やっぱりコンパイラ方式にしたい、というのであれば、いくつか可能性はある。 このページは、もう長くなってしまったので、ベージを替えて続きを書いてみることにする。(そのうち)
https://w.atwiki.jp/nino-add-up/pages/22.html
インストール CD-ROMを入れて指示に従うだけ Compaq Visual Fortran 使い方 Develper Studioを起動 [file]- [New]- FilesタブのFortran Free Format Source Fileを選択 同時にFilenameを入力してLocationの設定をちゃんとしておく Programを書いてCompile- Build- Execute Programで計算開始 結果はwrite文を用いて表示またはファイルに出力させる VineLinuxの場合 f77 filename でコンパイル a.out が作成される ./a.out で実行 ./a.out result.txt でファイルに書き出しができる f77 filename -o name で name という実行ファイルが作られる ./name で実行 Programのきまり 最初にプログラムの開始を宣言 ex. Program programname 最後にプログラムの終わりを宣言 ex. end program programname(開始を宣言したときのprogramnameと一致していないとエラー) 「!」以降はコメント文 整数、単精度、倍精度の区別を意識する必要あり(参考:型宣言文,誤差) 型宣言文 if文 データの入力(read文+format)? データの出力(write文+format)? その他 Fortranの組み込み関数 エラー番号は参考になる(ソフト内は英語表記だがXLsoftのHPでは日本語のオンラインドキュメントがある.) Fortran90の小技 参考 Compaq Visual Fortran Fortran ResQ Wikipedia(Fortran90) [PR] メールフォーム
https://w.atwiki.jp/ciez/pages/36.html
Using C/C++ and Fortran together Using C/C++ and Fortran together http //www.yolinux.com/TUTORIALS/LinuxTutorialMixingFortranAndC.html http //arnholm.org/software/cppf77/cppf77.htm
https://w.atwiki.jp/maseken/pages/23.html
Fortranについて. 注意点,過去に困ったことやその解決法などをメモ せっかくためた経験値をムダにしないために. Fortran Fortranとは, 間瀬研では,「Developer Studio」というソフトを使う. 使い方に関しては,マニュアル参照 適宜マニュアルで関数の使い方を調べながら使うといいと思う 基本的な関数 fopen ファイルを開く fid = fopen(...) fscanf データを読む A = fscanf(fid,....) surf plot 詳しい使い方はマニュアル参照