1.5.8 メソッド(元サブルーチン)へのデータ引渡

引数によるデータの引渡では, 前述の配列の記憶順序を意識したテクニックがよく使われる. MATH1のIFALIB, RFALIB, VRALIBなどでは, 1次元配列の要素を飛び飛びに使うための引数(jxなど)が必ずある. これは, 多次元配列を同じメソッド(元サブルーチン)またはメソッド(元関数)で処理するためのものである. これらのルーチンの動作を理解するために, 以下のプログラムを見て欲しい.

 

      REAL X(100)
      ......
      CALL SUM(X, 100, 1, XSUM)
      ......
      END

      SUBROUTINE SUM(X, N, JX, XSUM)
      REAL X(*)

      XSUM = 0.
      DO 100 I=1, JX*(N-1)+1, JX
        XSUM = XSUM + X(I)
  100 CONTINUE
      END
 

このメソッド(元サブルーチン)は1次元配列xの和を求めて, xsumとして返すものである. この同じメソッド(元サブルーチン)を2次元配列y に対して

      REAL Y(10,10) 
      ........
      CALL SUM(Y(2,1), 10, 10, YSUM)
      ......
      END

という様に使うと メソッド(元サブルーチン)sumは, 以下のように2次元配列要素Y(2,1)を 先頭とする記憶領域を1次元配列xに割り当てる.



Y(2,1) Y(3,1) $ \cdots $ Y(10,1) Y(1,2) Y(2,2) $ \cdots $ Y(10,2) Y(1,3) Y(2,3) $ \cdots $
X(1) X(2) $ \cdots $ X(9) X(10) X(11) $ \cdots $ X(19) X(20) X(21) $ \cdots $


その1次元配列xの要素を10 (JX) 個おきに10個の和をとると, Y(2,1), Y(2,2), ..., Y(2,10) という具合に, 二次元配列 yの第2添字についての和をとることになる.

ここで, メソッド(元サブルーチン)の中では配列xの長さはわからず, 単に, X(1)を先頭とする1つながりのデータとして扱われていることに 注意して欲しい. 配列がメソッド(元サブルーチン)に渡されるとき, メインプログラムの配列の中身がメソッド(元サブルーチン)の 配列の中身にコピーされるのではなく, メインプログラムの中の配列の番地だけが渡され, メソッド(元サブルーチン)の方はその番地を基準に処理を行うのである. このようなことを意識してプログラムを書くと, 少ない引数で柔軟な処理が可能になる.

もう一つの応用例を紹介しよう.


      SUBROUTINE SUM2(X, imax, IX, JX, XSUM)
      REAL X(imax,JX)

      XSUM = 0. 
      DO 100 I=1,IX 
      DO 100 J=1,JY 
        XSUM = XSUM + X(I,J) 
  100 CONTINUE 
      END 

これは2次元配列X(I,J)の一部の和をとるものであるが, これを

 

      REAL X(102,102)
      ........
      CALL SUM2(X(2,2), 102, 100, 100, XSUM)
      ........

という具合に使うと, 102×102の2次元配列のデータのうち, 周辺を残して真中の 100×100の部分, すなわち, (2,2)-(101,101)を対角線とする部分の和をとることができる. MATH1のルーチンで, このような使い方を想定しているものはないが, GRPH2のコンターを描くルーチンなどで応用すると便利である.

なお, メソッド(元サブルーチン)に渡すことのできる引数のなかに, 「手続き名」がある. これは, 他の引数と異なり「変数」ではないので, 動的な変更はできないが, これが指定できるおかげで, MATH1のvrfna/vifnaの様に, メソッド(元サブルーチン)を呼ぶ際に使うべきメソッド(元関数)を指定することが可能になる. この場合, 実引数に指定する手続き名は, メソッド(元サブルーチン)を呼ぶ プログラムの中で EXTERNAL文またはINTRINSIC文により 手続き名であることを宣言しておかなければならない.