FORTRANコードを動かしてみる on Cygwin

計算科学系の文献ではFortranソースを見ることが時々あリます。

自分も時々見かけるのでそんな時のためにメモを残しておこうかと。

環境: Cygwin, Vim, Fortran90

Let’s FORTRAN!

「!」以外で始まる各行は先頭に6文字以上スペースを入れてください。

!?

「!」以外で始まる各行は先頭に6文字以上スペースを入れてください。

!!??

autocmd FileType fortran setl textwidth=6

どこかにあったFortranソース。

      W = (/ 1, 2, 3, 4, 5 /)
      SIG=2
      DO 30 J=1,5
      IF(SIG.GT.W(J)) GOTO 30
      PRINT * , J
      SIG=W(J)
30    CONTINUE

Error: Unexpected end of file in ‘/path/to/sample.f90’

なんかだめ。

さらっとGoogle先生で調べたけどわからなかったが、FortranソースにはPROGRAMとかいう記述が必要だったような。。。

      PROGRAM SAMPLE
      INTEGER W(5)
      W = (/ 1, 2, 3, 4, 5 /)
      SIG=2
      DO 30 J=1,5
      IF(SIG.GT.W(J)) GOTO 30
      PRINT * , J
      SIG=W(J)
30    CONTINUE
      END PROGRAM SAMPLE

2,3,4,5と表示されたということで実行できた。PROGRAMが必要なのね。

quickrun.vimを使って実行しています。quickrun便利(使いこなせてないけど)

Type Description
INTEGER 整数型
REAL 実数型
DOUBLE PRECISION 倍精度浮動小数点型
COMPLEX 複素数型
LOGICAL 論理型
CHARACTER 文字型

倍精度実数の使用

REAL(8) :: x, y, z

implicitであらかじめa-h, o-zで始まる変数名は倍精度実数とする指定をすることが多い。

IMPLICIT REAL*8 (A-H, O-Z)

implicitはプログラムの先頭で行う。

0.0の扱い

! 単精度0.0で初期化(小数点7桁以下の精度は保証されない)
REAL SUM = 0.0
! 精度が重要である場合には倍精度で初期化する
SUM = 0.0D0

暗黙の約束

i, j, k, l, m, nで始まる変数は整数型でそれ以外は実数型と扱われる。

この約束を取り消すには

IMPLICIT NONE

とする。

演算子

Operator Description
+ +
- -
* *
/ /
x**n x n
sin(x) sin(x)
cos(x) con(x)
tan(x) tan(x)
atan(x) atan(x)
exp(x) e x
log(x) log(x)
sqrt(x) sqrt(x)
abs(x) abs(x)
sign(x) x / |x|

入出力

PRINT * , A

*はフォーマット指定。*を指定すると適当な書式が選択される。(コンパイラ依存)

WRITEで同じ事ができますが、冗長になってしまうのでPRINTを使う。

READ * , A, B, C

PRINTと同様に*を指定すると、適切な書式が自動で指定されます。

  • ENTERが入力されるまで読み込みます
  • 複数並べると、スペース区切りで読み込みを行います

配列

  • インデックスはデフォルトでは1から
  • メモリ上にはColumn Majorの順で配置される
REAL, DIMENSION(5) :: A
REAL B(5), C(5)
INTEGER, DIMENSION(3, 3) :: D

インデックスを0から指定したい場合は以下のように宣言する。

REAL A(0:5)

配列の初期化

! 全て0に初期化
REAL :: a(10) = 0
! 多次元配列も同様
INTEGER, DIMENSION(10, 10) :: b = 1

配列構成子

/(ここに配列の構成を記述)/

INTEGER A(5)
A = (/ 1, 2, 3, 4, 5 /)
INTEGER :: B(5) = (/ 1, 2, 3, 4, 5 /)
REAL :: C(6) = (/2., 4., 6., 8., 10., 12. /)
! 1,2,3,4,5 : DO型反復
INTEGER :: D(5) = (/ (i,i=1,5) /)
! 5,10,15,20,25,30
REAL :: E(6) = (/ (i*5,i=1,6) /)

reshape関数を使うことによって更に柔軟な指定が可能になります

! 1,3,5
! 2,4,6
REAL :: A(2,3) = RESHAPE( (/1., 2., 3., 4., 5., 6./), (/2,3/) )
REAL :: B(2,3) = RESHAPE( (/1., 2., 3., 4., 5., 6./), SHAPE(a) )
! DO型反復も使用可能
! 1,5,9
! 2,6,10
! 3,7,11
! 4,8,12
INTEGER :: C(4,3) = RESHAPE( (/ (i,i=1,12) /), SHAPE(b) )

一括代入

INTEGER A(3)
! 10,10,10
A = 10
! 11,11,11
A = A + 1
INTEGER B(3), C(3)
B = 10
C = 10
! 20,20,20
A = B + C

ループ

     DO 20 I=1, M
       DO 10 J=2, N
         a(I,J) = I*M
10     CONTINUE
20   CONTINUE

GOTO文

    GOTO 10
    GO TO 10
10  IF A.LT.B PRINT * , A

if文

IF(A.LT.B) PRINT * , A

IF(A.GT.B) THEN
  PRINT * , B
ELSE
  PRINT * , A

IF(A.EQ.B) THEN
  PRINT * , A
ELSE IF(A.LT.B) THEN
  PRINT * , A
ELSE
  PRINT * , B

比較演算子

Operator or Description
A.LT.B A < B Less Than
A.LE.B A <= B Less than over Eaual to
A.EQ.B A == B EQual to
A.NE.B A /= B Not Equal to
A.GT.B A > B Greater Than
A.GE.B A >= B Greater than over Equal to

論理演算子

Operator Description Usage
.NOT. not .NOT. A.EQ.B
.AND. and A.EQ.B .AND. A.EQ.C
.OR. or A.LT.B .OR. A.LT.C
.EQV. logical eq A<0 .EQV. B<0
.NEQV. logical not eq A<0 .NEQV. B<0

関数

PROGRAMではなくSUBROUTINEで宣言する

SUBROUTINE HOGE(A, B, C)
  INTEGER A
  REAL B
  CHARACTER C
END SUBROUTINE