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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
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

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

1
2
3
4
5
6
extern "C" {
    // 1次元配列
    int STRUCTMODULE_mp_SUM1( int ary[], int *count );
    // 2次元配列
    int STRUCTMODULE_mp_SUM2( int ary[][3], int *cnti, int *cntj );
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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 パーマリンク