LoginSignup
1
0

More than 5 years have passed since last update.

Fortran で zip 的連結

Last updated at Posted at 2017-11-11

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
1
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0