fortran66のブログ

fortran について書きます。

【メモ帳】二次元配列を一次元化 その他

二次元配列を一次元ポインタ配列に結び付ける

FORTRAN77 時代は、副プログラムに配列を渡すとき、先頭番地しか渡されず、次元のチェックがなされなかったので、自由に形状を変えて使えたのですが、Fortran90 以降うるさくなってできなくなったうえに非連続な番地を指した pointer 配列が来る可能性もあるので最適化も効きにくくなるなど弊害も生じました。

ソフトウェアが書きやすく堅牢になっても、その支払う代償に見合うものが得られるのか吟味が必要ですが、ソフトウェアの人達はソースレベルの見栄えにこだわりすぎるのでバランスに欠ける嫌いがあります。ソフトウェアは計算機という道具を使役するための手段にすぎないので、それ自体に独立の価値を求めすぎるのもおかしな話だと思います。そのうち計算機を動かす機能を持たない、再帰的にポエムを記述する妙なイラスト付きの言語が出てくるのではなかろうかと思います。

ここでは、Fortran2008 で導入された次元を変えたポインタ割り付けと contiguous 属性の二つをつかって、二次元配列をサブルーチンに渡して一次元のポインタに結び付けます。contiguous 属性を持たせることで配列の番地の連続性を保障して最適化を妨げないようにします。

また Fortran2008 で導入された forall 文内で局所的にループ変数を宣言する機能を用いて楽をします。

ソース・プログラム

module m_sub
  implicit none
contains
  subroutine test(x)
    integer, target, contiguous, intent(out):: x(:, :)
    integer, pointer :: ap(:)
    ap(1:size(x)) => x
    forall (integer::i = 1:size(ap)) ap(i) = i
  end subroutine test    
end module m_sub

program hello
  use m_sub
  implicit none
  integer :: a(10,10)
  call test(a)
  print '(10(i3, 1x))', a
end program hello

実行結果

intel fortan v.18

  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  38  39  40
 41  42  43  44  45  46  47  48  49  50
 51  52  53  54  55  56  57  58  59  60
 61  62  63  64  65  66  67  68  69  70
 71  72  73  74  75  76  77  78  79  80
 81  82  83  84  85  86  87  88  89  90
 91  92  93  94  95  96  97  98  99 100
続行するには何かキーを押してください . . .

intel fortran associate のバグ?

派生型の中の変数を associate 文で別名付け(ポインタ)た後に、これを符号なし 8bit 整数に変換する目的で組み込み関数 achar に入力させた場合、結果が NULL というか 00h になるようです。associate を使わずに成分を直接入力したときや、int( i, int8) で符号付 8bit 変数に変換した時は期待通りの動作をします。

実行結果

achar(k)    = :
int(k)      =65:
int(k, int8)=65:
achar(t%i)  =A:
続行するには何かキーを押してください . . .

ソース・プログラム

    program Console5
      use, intrinsic :: iso_fortran_env
      implicit none
      integer :: i 
      type :: t_test
        integer :: i 
      end type t_test
      type(t_test) :: t
      t%i = int(Z'41')
      
      associate(k => t%i)
         print '(3g0)', 'achar(k)    =', achar(k), ':'
         print '(3g0)', 'int(k)      =', int(k), ':'
         print '(3g0)', 'int(k, int8)=', int(k, 8), ':'
         print '(3g0)', 'achar(t%i)  =', achar(t%i), ':'
      end associate
    end program Console5

Fortran ハンドブック

Fortran ハンドブック

Modern Fortran Explained (Numerical Mathematics and Scientific Computation)

Modern Fortran Explained (Numerical Mathematics and Scientific Computation)

  • 作者: Michael Metcalf,John Reid,Malcolm Cohen
  • 出版社/メーカー: Oxford University Press, U.S.A.
  • 発売日: 2011/05/08
  • メディア: ペーパーバック
  • この商品を含むブログを見る