FORTRAN77入門
目次
- はじめに
- 動作環境
- 対象者
- FORTRANとは?
- g77とは?
- 最終目的
- コメント
- コーディング規約
- 基本構造
- ハローワールド
- ルール
- データ形式
- 演算子
- 配列(DIMENSIONAL)
- I/O
- 制御構造
- 関数
- フォーマット
- API(Intrinsic Functions)
- その他
- デバック
- 最後に
- 参考資料
はじめに
FORTRANとは?
g77とは?
GNU ProjectのFortranコンパイラ。 ANSI FORTRAN 77を基にGNU機能拡張をしています。 Fortran 95のためにはg95があります。
最終目的
FORTRAN77を学習することで、現代言語との差異を理解します。またこの学習成果として2cバイナリクロックのFORTRAN77版を 作成します。
コメント
* lower-case letters ok.C FORTRAN66 comments can also be denoted by the letter C
コメントは*からはじまる。カラムが72を超えないようにする。アスキー文字'C'でもコメントが可能であるが、 FORTRAN66の時の下位互換である。
コーディング規約
なし。
基本構造
c
c hello.f
c
c
INTEGER i
write(*,*)'hello world'
goto 1
1 write(*,*)'1 is label'
end
大文字小文字は、評価しません。コメントを4行書き、INTEGER型の変数iを指定、writeで標準出力goto 1でラベル1へ移動、 writeで'1 is label'を標準出力に表示します。最後にendでプログラムを終了します。注意すべきは、ステートメントのはじめ6文字分は空白にしなければならない事です。Fortranが作られた時代のプログラミングは、ディスプレイではなく紙での入出力が行われていたからです。
このようにレイアウトが決まっていることを固定形式という。JavaやCなどの現代高水準言語は自由形式という。以下のようにラベル・ContinuationMaker・文・カードナンバー用領域となるため、実際にソースコードが記述できる部分はStatement fieldの部分だけになる。
| 12345 | 6 | 7-72 | 73-80 |
| Label field | Continuation Maker field | Statement field | hold card sequence number |
ハローワールド
c
c hello.f
c
write(*,*)'hello world'
end
ルール
大文字のA-Z(the 26 upper-case letters)と0-9(the 10 digits)と特殊文字13個(+-*/ =().,':$)のみ利用可能 ブランクと空白は全てプログラムとして無視される。 カラム1-5はラベルフィールド カラム6はcontinuation makerフィールド カラム7-72はステートメントフィールド
$ cat rule.fcc
crule.f
c
c234567
PROGRAM rule
WRITE(UNIT=*, FMT=*)'aaaaaassssssddddddddddddddddddddddddffffffffffffffff'
STOP
END
$ g77 rule.f
rule.f: In program `rule':rule.f:6: WRITE(UNIT=*, FMT=*)'aaaaaassssssddddddddddddddddddddddddfffffffff
1
2Character constant at (1) has no closing apostrophe at (2)
カラム6にcontinuation makerのダラーマークを設定している。 JavaやBourneシェルの\マークと同様である。
c
c rule.f
c
c234567
PROGRAM rule
WRITE(UNIT=*, FMT=*)'aaaaaassssssddddddddddddddddddddddddfffffffff
$fffffff'
STOP
END
データ形式
- INTEGER
- REAL (floating-point representation)
- DOUBLE PRECISION
- COMPLEX
- LOGICAL
- CHARACTER サンプル
c
c hello.f
c
INTEGER i
INTEGER j
REAL price
REAL tax
tax = 0.05
write(*,*)'input i'
read(*,*) i
write(*,*)'input j'
read(*,*) j
price = (i + j) * (1 + tax)
write(*,*)'price=',price,'\n'
end
サンプル
PROGRAM lazy
INTEGER Ival=100.11
REAL Rval=100.01
WRITE(UNIT=*, FMT=*)Ival
WRITE(UNIT=*, FMT=*)Rval
stop
end
PROGRAM lazy
Ival=100.11
Rval=100.01
WRITE(UNIT=*, FMT=*)Ival
WRITE(UNIT=*, FMT=*)Rval
stop
end
変数名の始めにIをつける(Ival)とInteger型になるので、シンボルネームが必要なくなる。 実際はI-Nの一文字。Real型の場合は、A-HまたはO-Zを最初の一文字にするとREAL型になる。
CHARACTERのサンプル
PROGRAM FLEX
CHARACTER CODE*8
CHARACTER CLASS*6
CHARACTER TITLE*16
*
CLASS = CODE('SECRET')
TITLE = CODE('ORDER OF BATTLE')
WRITE(UNIT=*, FMT=*) CLASS
WRITE(UNIT=*, FMT=*) TITLE
END
*
CHARACTER*(*) FUNCTION CODE(WORD)
CHARACTER WORD*(*)
CHARACTER BUFFER*80
DO 15, I=1, LEN(WORD)
BUFFER(I:I) = CHAR(ICHAR(WORD(I:I)) + 1)
15 CONTINUE
CODE = BUFFER
END
演算子
Authmetic Excpressions
**でExponentiationが可能だが剰余は無い。c
c cal.f
c
program cal
implicit none
c
integer a;
a = (100 + 1 - 1) * 2 / 200
a = (a + 9) ** 2
write(*,*) 'answer=',a,'\n'
stop
end
Relational Excpressions
.LT. Less Than .LE. Less than or Equal to .EQ. EQual to .NE. Not Equal to .GT. Grater Than .GE. Grater Than or Equal to
PROGRAM EXIF1
IF ('a' .EQ. 'b') THEN
WRITE(UNIT=*, FMT=*) 'EQUAL'
ELSE IF ('c' .NE. 'D') THEN
WRITE(UNIT=*, FMT=*) 'NOT EQUAL'
ELSE
WRITE(UNIT=*, FMT=*) 'OTHER'
END IF
END
Logical Expressions
.NOT. .AND. .OR. .EQV. .NEQV.
IF (LGE(CDATA, '4') .AND. LLE(CDATA, '7')) THEN
CARY(2,J)='*'
WRITE(UNIT=*,FMT=*) '*'
ELSE
CARY(2,J)=' '
WRITE(UNIT=*,FMT=*) ' '
END IF
配列(DIMENSIONAL)
*
* dimension.f
*
PROGRAM DMSN
* ONE-DIMENSIONAL ARRAYS
* Fortran arrays are indexed from 1 and up.
REAL ARY(10)
* arbitrary index range following syntax
* like Language C that is indexed indexed from 0 through 19.
REAL CARY(0:10)
* TWO-DIMENSIONAL ARRAYS
REAL TARY(4,6)
* SET INITIAL DATA
DO 20 J=1,3
DO 10 I=1,6
TARY(J,I)=I*J
10 CONTINUE
20 CONTINUE
END
I/O
サンプル
c
c hello.f
c
INTEGER i
write(*,*)'input:'
read(*,*) i
write(*,*)'output=',i,'\n'
c
c print instruction same write.
print *,'output=',i,'\n'
end
c
c print.f
c
c
INTEGER i
read(*,*) i
print *, 'output=',i
end
c hello.f
c
open(unit=10,file='output')
write(10,*)'aaaa'
write(10,*)'bbbb'
write(10,*)'cccc'
close(10)
end
制御構造
分岐
IF ( condition ) THEN ELSE IF ( condition) THEN ELSE END IF
PROGRAM EXIF1
IF ('a' .EQ. 'b') THEN
WRITE(UNIT=*, FMT=*) 'EQUAL'
ELSE IF ('c' .NE. 'D') THEN
WRITE(UNIT=*, FMT=*) 'NOT EQUAL'
ELSE
WRITE(UNIT=*, FMT=*) 'OTHER'
END IF
END
*
* if.f
*
PROGRAM IF
INTEGER IN1, IN2
WRITE(UNIT=*,FMT=*)'Enter 2 number'
READ(UNIT=*, FMT=*) IN1, IN2
WRITE(UNIT=*,FMT=*)'ans=', AD(IN1,IN2)
END
REAL FUNCTION AD(A1,A2)
IF (A1 .NE. 1) THEN
WRITE(UNIT=*,FMT=*)'hoge'
ELSE
AD = A1 + A2
END IF
END
* TRIANG
*
PROGRAM TRIANG
WRITE(UNIT=*,FMT=*)'Enter lengths of three sides:'
READ(UNIT=*,FMT=*) SIDEA, SIDEB, SIDEC
WRITE(UNIT=*,FMT=*)'Area is ' ,AREA3(SIDEA,SIDEB,SIDEC)
END
FUNCTION AREA3(A, B, C)
* Computes the area of a triangle from lengths of sides
* If arguments are invalid issues error message and returns zero.
REAL A, B, C
S = (A + B + C)/2.0
FACTOR = S * (S-A) * (S-B) * (S-C)
IF(FACTOR .LE. 0.0) THEN
STOP 'Impossible triangle'
ELSE
AREA3 = SQRT(FACTOR)
END IF
END
反復
DO Loop
DO ラベル 変数=値,ループ回数 処理 ラベル CONTINUE
DOの後がラベル名になる。
*
* doloop.f
*
PROGRAM DOLOOP
* REAL AMOUNT
* REAL PCRATE
* INTEGER NYEARS
* REAL RATE
WRITE(UNIT=*, FMT=*)'Enter amount, % rate, years'
READ(UNIT=*, FMT=*) AMOUNT, PCRATE, NYEARS
RATE = PCRATE / 100.0
REPAY = RATE * AMOUNT / (1.0 - (1.0 + RATE)**(-NYEARS))
WRITE(UNIT=*, FMT=*)'Annual repayments are ', REPAY
WRITE(UNIT=*, FMT=*)'End of Year Balance'
* like 'for (int iyear = 1; iyear NYSERS; IYEAR++)
DO 15, IYEAR = 1,NYEARS
AMOUNT = AMOUNT + (AMOUNT * RATE) - REPAY
WRITE(UNIT=*, FMT=*) IYEAR, AMOUNT
15 CONTINUE
END
関数
FUNCTION 関数名(引数...) 処理 関数名を戻り値にする事 END
*
* TRIANG
*
PROGRAM TRIANG
WRITE(UNIT=*,FMT=*)'Enter lengths of three sides:'
READ(UNIT=*,FMT=*) SIDEA, SIDEB, SIDEC
WRITE(UNIT=*,FMT=*)'Area is ' ,AREA3(SIDEA,SIDEB,SIDEC)
END
FUNCTION AREA3(A, B, C)
* Computes the area of a triangle from lengths of sides
S = (A + B + C)/2.0
AREA3= SQRT(S * (S-A) * (S-B) * (S-C))
END
SUBROUTINE 関数名 処理 END
*
* return.f
*
PROGRAM hoge
CALL SUBT(A)
WRITE(UNIT=*, FMT=*)'a=',A
A=100
WRITE(UNIT=*, FMT=*)'a=',A
RCODE = FUNCB(ARG1)
WRITE(UNIT=*, FMT=*)'ARG1=',ARG1
WRITE(UNIT=*, FMT=*)'RCODE=',RCODE
END
SUBROUTINE SUBT(A)
A = 10
WRITE(UNIT=*, FMT=*)'a=',A
END
FUNCTION FUNCB(B)
B = 20
FUNCB = 50
END
フォーマット
API(Intrinsic Functions)
言語標準のライブラリは30個と非常に少ない。関数名だけ列挙する。
ABS ACOS AIMAG ANINT ATAN2 CHAR CMPLX CONJG COS DBLE DIM DPROD EXP ICHAR INDEX INT LEN LGE LGT LLE LLT LOG LOG10 MAX MIN MOD REAL SIGN SQRT TAN
その他
外部プログラムの呼び出し アセンブラを変更していますので、必要な方のみリンクを進んでください。
デバック
g77はコンパイル時に当然だがエラーを標準出力に吐き出すので問題なくデバックできるだろう。
最後に
FORTRANは世界初の高水準言語であるため非常にアセンブラに近いことが理解できた。高水準であるという上でアセンブラでのPUSH,POP,JUMPなどより、人間が思考しやすいように、IF,DO,GOTO,ROUTINEなどの自然言語が使われている事が改めて実感できた。また2004年6月現在の言語はライブラリを使う事でさらに上位の志向(デザインパターンなど)を考慮して実装できるが、C言語に比べてもさらに自分でライブラリを作成しなければならないことが理解できた。またg77コンパイラから実行ファイルを生成しているので、きわめて速度が早いことが確認できた。そして標準ライブラリ(Intrinstic Functions)の個数やコンパイラ言語としては、容易な文法習得からも、なぜ今日までこの言語が科学技術計算で利用されているかも理解できた。科学技術計算においては、FORTRAN言語はあくまでも目的解決のツールであり、言語の複雑さや問題を解決する方法の多様性は時として必要のないのだろう。FORTRANが作られた歴史的背景もあるが、C/C++などに対して極めてシンプルであり、量子コンピュータなどの新たなパラダイムシフトが生まれても生き残る言語のような気がする。
参考資料
Professional Programmer's Guide to Fortran77
http://www.uopmu.ees.osakafu-u.ac.jp/~yabu/soft/

