【Fortran学習|初心者向け】Fortranの次世代機能「想定ランク配列」で、次元を気にしない汎用関数を作ろう

導入:なぜ「想定ランク配列」が必要なのか

数値計算の現場では、同じような処理(例えば配列の全要素の合計を出す、特定の値を代入するなど)を、次元数が異なる配列に対して何度も書かなければならないことがあります。従来の方法では、1次元用、2次元用…と個別にサブルーチンを用意する必要があり、非常に手間がかかっていました。「想定ランク配列(Assumed-rank Array)」を使うと、次元数がいくつであっても同じコードで処理できるようになり、コードの重複を防ぎ、メンテナンス性を大幅に向上させることができます。

基礎知識:想定ランク配列とは?

通常、Fortranで配列を引数に取る際は「real :: a(10, 10)」のように次元を指定する必要があります。しかし、Fortran 2018で導入された「想定ランク配列」は、引数の宣言に「(..)」という特殊な記法を用いることで、その配列が何次元であるかを実行時まで決定しないようにする仕組みです。これにより、ライブラリの汎用性が飛躍的に高まります。

実装:次元を意識しない処理の書き方

想定ランク配列を使う場合、配列のランク(次元数)を確認するために「rank()」という組み込み関数を併用するのが一般的です。また、配列の形状(各次元の大きさ)を取得するには「size()」や「lbound()」「ubound()」などの関数を使用します。これにより、配列の構造を動的に解析しながら、効率的な計算を行うことが可能です。

サンプルプログラム

以下は、どのような次元の配列が渡されても、その全要素の合計値を出力する汎用的なサブルーチンの例です。

module math_utils
  implicit none
contains

  subroutine print_total_sum(a)
    ! (..) とすることで任意の次元数を受け取れるようにする
    real, intent(in) :: a(..)
    integer :: r, i
    
    ! 現在の配列のランク(次元数)を取得
    r = rank(a)
    
    ! 合計値を計算(全要素をフラットに扱う)
    ! 内部的にはランクに関わらずメモリ上の連続領域として処理される
    print , "渡された配列の次元数: ", r
    print , "配列の全要素数: ", size(a)
    print , "全要素の合計値: ", sum(a)
  end subroutine print_total_sum
end module math_utils

program test
  use math_utils
  real :: vec(3) = [1.0, 2.0, 3.0]
  real :: mat(2, 2) = reshape([1.0, 2.0, 3.0, 4.0], [2, 2])

  ! 1次元配列を渡す
  call print_total_sum(vec)
  ! 2次元配列を渡す(同じサブルーチンでOK!)
  call print_total_sum(mat)
end program test

応用・注意点:現場での活用と陥りやすい罠

1. 内部での形状操作に注意
想定ランク配列は、次元数が不定なため、特定の次元(例えば「2次元目の要素」など)を直接指定してアクセスすることはできません。特定の次元を操作したい場合は、必ず `rank()` 関数で次元数を判定し、条件分岐(if文やselect rank構文)を用いて処理を分ける必要があります。

2. コンパイラの対応状況
この機能は比較的新しい規格(Fortran 2018)であるため、使用するコンパイラが最新のバージョンであることを確認してください。古い環境ではコンパイルエラーになる可能性があります。

3. 性能への意識
非常に便利な機能ですが、実行時に次元を判定するコストがわずかに発生します。超大規模な計算で、かつサブルーチン呼び出しがループの内側にあるような極限の最適化が求められる場所では、必要に応じて静的な次元指定と使い分けるのがプロの数値計算エンジニアの流儀です。

コメント

タイトルとURLをコピーしました