fortran66のブログ

fortran について書きます。

Fortranに於けるfilterとmap

Fortranは配列がいわゆる first class object になっており、配列の扱いに長けています。Fortran90 以降、ほとんどの組み込み関数は elemental 属性を持っており、定義上スカラーを引数として取る関数に配列を渡すと、結果を配列として返します。これは、LISP などの MAP 演算子に相当する作用をします。

MAP f(x) [a_i] = [f(a_i)]

の如く、

f([a_i]) = [f(a_i)]

のように働きます。これは関数と配列生成子の交換関係とも見ることができます。さらに Fortran95 から、ユーザー定義関数やサブルーチンにも、このような elemental な属性を持たせることが可能になりました。これにより、スカラーに対する定義を書けば配列の rank を問題にする必要がなくなりました。
これはループ変数を省略できるうえ、コンパイラによる自動並列化を助ける非常に便利な機能です。

同様に、Fortran90 では、配列に対する filter 作用を持つ組み込み関数も用意されています。それは pack 関数で、その有用性は最近になって Fortran コミュニティーに共有される常識となってきました。
haskell などで

filter (cond) [list]

と書かれるものが、pack 関数を用いると、

pack([array], mask)

という形で表されます。
これも非常に便利な機能で、quick sort などもきわめて簡潔に表せます。

PURE RECURSIVE FUNCTION qsort(x) RESULT(res) ! Quick Sort
REAL, INTENT(IN) :: x(:)
REAL :: res( SIZE(x) )
IF ( SIZE(x) > 1 ) THEN
 res = [ qsort(PACK( x(2:), x(2:) > x(1) )), x(1), qsort(PACK( x(2:), x(2:) <= x(1) )) ] 
ELSE
 res = x
END IF
RETURN
END FUNCTION qsort