#zip
二つの数列 (a1,a2,...), (b1,b2,...) があって、これを (a1, b1), (a2, b2),... の形にまとめ直す処理を、近年 zip 関数と名づけることが多いようです。
Fortran には、そのような関数などはありませんが、たまに使いたくなる時があります。時々組み込み関数だけで出来ないかと考えていましたが、ふと、その昔 APL では行列の転置で同じ事をやっていたのを思い出しました。
ここでは、アイデア丸パクリで transpose & reshape 関数で試してみることにします。(一つの配列にまとめるので、型が一緒じゃないとできませんが。)
##実行結果
ある整数 N に対して、N 以下で N と互いに疎な正整数の数を数える Euler のファイ関数を計算します。素数 p に対しては p-1 となります。ここでは定義に従って、互いに疎な数を力づくで求めています。
1 1
2 1
3 2
4 2
5 4
6 2
7 6
8 4
9 6
10 4
11 10
12 4
13 12
14 6
15 8
16 8
17 16
18 6
19 18
20 8
##ソースプログラム
ここで [1:20] というのは Intel Fortran の独自拡張で [1,2,...,20] という配列を構成します。[(i, i = 1, 20)] と同じ意味です。
インデックスと配列の値を、並べて縦書きにするときに、DO..LOOP が必要なく、DO 変数も要らなくなってます。(ただし非標準な Intel 拡張使ってますがw)
module m_mod
implicit none
contains
pure elemental integer function igcd(ia, ib)
integer, value :: ia, ib
igcd = ia
do
if (ib == 0) exit
ia = ib
ib = mod(igcd, ib)
igcd = ia
end do
end function igcd
impure elemental integer function ieuler_phi(n) ! F2008 impure
integer, intent(in) :: n
integer :: i, m(n) ! F2008?
m = [(i, i = 1, n)]
ieuler_phi = count(igcd(n, m) == 1)
end function ieuler_phi
end module m_mod
program zip
use m_mod
implicit none
print '((2i5))', transpose(reshape([[1:20], ieuler_phi([1:20])], [20, 2])) ! [1:20] non-standard ! [(i,i=1,20)]
end program zip