fortran66のブログ

fortran について書きます。

Fortran で、複数個の整数変数の AND や OR を取りたいことがあるのですが、Fortran90 以降で用意された IAND や IOR 関数は引数を二つしか取れず、IAND や IOR を入れ子式に用いなければなりません。

m = IOR(I, IOR(J, K))

これを

m = IOR(I, J, K)

の様な形で、かつ任意個の引数を取れるようにするのは Fortran の規格内では出来ません。
しかしながら、Array Constructor を使うと、それに近い形を実現することが出来ます。

考え方は、一次元配列を引数としてその全要素にわたる IAND, IOR をとる関数を用意して、呼び出し側では Array Constructor に、変数を並べることで、配列として関数に引き渡すというものです。つまり

m = IOR( [I, J, K] )

このような形式での呼び出しでよければ、文法の範囲内で目的が実現できます。


ここで、Array Constructor とは Fortran90 で導入されたもので、(/ i, j, k /) が i,j,k を要素に持つ配列とみなされる仕組みです。Fortran2003 で (/..../) の代わりに、[....] と大括弧が使えるようになりました。

下の例では、IAND,IOR 関数にオーバーロードして定義しています。

MODULE m_test
IMPLICIT NONE
!------------------------
INTERFACE ior
 MODULE PROCEDURE mor
END INTERFACE
INTERFACE iand
 MODULE PROCEDURE mand
END INTERFACE
!------------------------
CONTAINS
!-------------------------------------------------------------
INTEGER FUNCTION mand(iarray)
INTEGER, INTENT(IN) :: iarray(:)
INTEGER :: i
mand = -1 ! all bits 1 
DO i = 1, SIZE(iarray)
 mand = IAND(mand, iarray(i))
END DO
RETURN
END FUNCTION mand
!-------------------------------------------------------------
INTEGER FUNCTION mor(iarray)
INTEGER, INTENT(IN) :: iarray(:)
INTEGER :: i
mor = 0 ! all bits 0 
DO i = 1, SIZE(iarray)
 mor = IOR(mor, iarray(i))
END DO
RETURN
END FUNCTION mor
!-------------------------------------------------------------
END MODULE m_test
!==================================================================
PROGRAM test
USE m_test
IMPLICIT NONE
INTEGER :: i, j, k, m
i = 1
j = 2**2 + 1
k = 2**4 + 1
m = IAND(IAND(i, j), k)
PRINT '(B32.32, 1x, B32.32)', m, IAND([i, j, k])
m = IOR(IOR(i, j), k)
PRINT '(B32.32, 1x, B32.32)', m, IOR([i, j, k])
STOP
END PROGRAM test