FortranにC言語から固定配列を渡す

科学計算の場合、行列式や1次元配列、2次元配列が頻繁に出てくる…と思われる。
Fortran の場合、あまり可変配列を使わずに、あらかじめメモリ領域を確保する固定配列を使う…ってそうしていたのだが、最近はどうなのだろう。可変にするとメモリの確保に時間がかかってスピードに問題がでるので、固定長さの配列のほうが有利。

module structmodule
    implicit none
    ! struct define
    type F3D
        double precision :: x,y,z
    end type F3D
contains
    ! one array 
    integer function sum1( v, count )
        integer :: v(10)
        integer :: i, total
        integer :: count
        
        total = 0
        do i=1,count
            print *, 'in sum1: ', i, v(i) 
            total = total + v(i)
        end do
        sum1 = total
    end function sum1
    ! 二次元配列を渡す
    integer function sum2( v, cnti, cntj )
        integer :: v(3,4)
        integer :: cnti, cntj
        integer :: i,j
        integer :: total
        
        total = 0
        do i=1,cnti
            do j=1,cntj
                print *,i,j,v(i,j)
                total = total + v(i,j)
            end do
        end do
        sum2 = total
    end function sum2
end module structmodule

引き数で配列の数を渡しているが、内部で固定にしかならないので、この場合はあまり意味がない。
最大長をチェックしてオーバーフローにならないように気を付けるとか。

extern "C" {
	// 1次元配列
	int STRUCTMODULE_mp_SUM1( int ary[], int *count );
	// 2次元配列
	int STRUCTMODULE_mp_SUM2( int ary[][3], int *cnti, int *cntj );
}
	int v1[] = {1,2,3,4,5,6,7,8,9,10};
	int count = 10;
	int sum1 = STRUCTMODULE_mp_SUM1( v1, &count );
	cout << "ans:" << sum1 << endl;

	int v2[4][3] = {
		{1,2,3},
		{2,3,4},
		{3,4,5},
		{4,5,6},
	};
	int cnti = 3, cntj = 4;
	int sum2 = STRUCTMODULE_mp_SUM2( v2, &cnti, &cntj );
	cout << "ans:" << sum2 << endl;

注意しないといけないのは、Fortranは「1」始まりで、C++は「0」始まりということ。なので、Fortranで「3」番目にアクセスをすると、C++では添え字の「2」にアクセスする(0始まりなので、3番目の要素になる)。配列そのものを扱う場合には気にならないが、index を渡す場合には注意が必要。
Fortranのほうを0始まりにできるオプションもあるらしいのだが、元のソースに合わせるとすると標準的な1始まりの配列を扱うほうがよかろう。

あと、2次元配列の場合は、次元が逆のように見える。これは、Fortranのほうにあわせて作る。

カテゴリー: 開発, Fortran パーマリンク