fortran66のブログ

fortran について書きます。

【メモ帳】単位行列を一行で生成 その2

単位行列一行生成

干支が回るくらい前に、単位行列を一行で生成してみましたが、Fortran 文法もこちらの理解も進んだので新たな生成を試みます。

fortran66.hatenablog.com

プログラム

前回の reshape によるものより、二次元の構造を素直に反映して分かりやすいと思います。merge 関数はスカラー値にも使え、三項演算子の代用になります。

fortran 2008 では、forall 構文内で局所変数を宣言できるようになりました。これは一般に fortran の整数の default 長が 4 byte 符号付整数であることが多くて 2 G で overflow するのに対して、昨今のメモリ増強によって配列サイズが 2G を超えることがままあるので、integer(int64) などで局所変数を宣言して乗り切りなさいという親心から出たもののようです。(ただしここでは default の int32 で宣言しています。また普通に i, j を宣言すれば Fortran 95 の範囲に収まります。)

    program unitmat
        implicit none
        integer :: m(8, 8)
        forall(integer::i = 1:8, j = 1:8) m(i, j) = merge(1, 0, i == j)
        print '(8i2)', transpose(m)
    end program unitmat
 1 0 0 0 0 0 0 0
 0 1 0 0 0 0 0 0
 0 0 1 0 0 0 0 0
 0 0 0 1 0 0 0 0
 0 0 0 0 1 0 0 0
 0 0 0 0 0 1 0 0
 0 0 0 0 0 0 1 0
 0 0 0 0 0 0 0 1

配列構成子による方法

昔の記事では配列構成子をテストしていたので、その方法でもやってみます。この場合ループ変数の i, j をあらかじめ宣言しておかねばなりませんが、allocatable 配列の自動 allocation が可能になります。

    program unitmat
        implicit none
        integer, allocatable :: m(:, :)
        integer :: i, j
        
        m = reshape([((merge(1, 0, i == j), j = 1, 8), i = 1, 8)], [8, 8])
        print '(8i2)', transpose(m)
    end program unitmat

学士会報 第958号

皇侃の論語義疏に、孔子の娘婿の公冶長が鳥語を解するゆえに鳥情報から死体のありかを当てて殺人犯扱いされ牢屋に入れられる話が出てきますが、学士会報の付録にシジュウカラの言葉を解して単語と文法を研究している人が出て来て面白かったです。公冶長はスズメの乞食速報「米俵を積んだ牛車がひっくり返って米食い放題の件」を聞いて笑ったことから無実が証明されて許されますが、今の支那人も事故でひっくり返った車から村人総出で積荷を盗んだりするので、進歩の無さにこっちも笑いがこぼれます。