たまたま面白いサイトに出くわしました。本来再帰が許されていない FORTRAN77 で、シンタックスエラーを出さず、違法と合法のスレスレで再帰を実現する方法を発見した方がおられました。
http://www.esm.psu.edu/~ajm138/fortranexamples.html
自分自身を関数引数としてとるという、今まで聞いたことも見たこともない*1非常に興味深い方法で再帰を実現していて大変関心させられました。FORTRAN77 は規格の上では、副プログラムの変数は AUTOMATIC になっているので、引数の類をスタックに積むような事は自動でやってくれています。したがって、プログラムに何ら無理で不自然なところはありません。
ただ処理系によっては FORTRAN66 との互換性を保つために、デフォルトで副プログラムの変数を SAVE 扱いにしている場合もままあり、その場合はコンパイラオプションで本来の規格に忠実に AUTOMATIC 変数扱いにする必要があります。
非常に面白いアイデアで、私的には近年まれにみるヒット作で、FORTRAN77 もまだまだ奥深いなと思いました。
ついでなので、このアイデアに基づいて QuickSort を書いてみました。
ソース・プログラム
RANDOM_NUMBER() は Fortran90 のサブルーチンですが、面倒なので利用しました。それ以外はFORTRAN77 の範囲で記述したつもりです。(print *, x も 90 かw)
PROGRAM MAIN PARAMETER(NMAX = 10**7) REAL X(NMAX), WK(NMAX) EXTERNAL QSORT C Fortran90 : random_number call random_number(X) N = NMAX CALL QSORT(N, X, WK, QSORT) print *, any(x(1:n - 1) > x(2:)) ! print *, x STOP END C FORTRAN77 RECURSIVE SUBROUTINE C based on the idea by Andrew J. Miller http://www.esm.psu.edu/~ajm138/fortranexamples.html SUBROUTINE QSORT(N, X, WK, DUMSUB) REAL X(N), WK(N) EXTERNAL DUMSUB IF (N .LE. 1) RETURN K = 1 J = N PIVOT = X(1) DO 10 I = 2, N IF (X(I) .LT. PIVOT) THEN WK(K) = X(I) K = K + 1 ELSE WK(J) = X(I) J = J - 1 END IF 10 CONTINUE DO 20 I = 1, K - 1 X(I) = WK(I) 20 CONTINUE X(K) = PIVOT DO 30 I = K + 1, N X(I) = WK(I) 30 CONTINUE CALL DUMSUB(K - 1, X, WK, DUMSUB) CALL DUMSUB(N - K, X(K + 1), WK(K + 1), DUMSUB) RETURN END