Fortran cshift まとめ

配列の位置の移動したい、つまり、ある行列があった場合、n列目やm行目をx列目やy行目にずらしたいということはあるでしょうか。=>配列のシフトです。

Fortranで、そうした配列の移動をしたいときに活躍するcshiftについて紹介します。

Pythonを触ったことのある人は、Pythonのnp.roll()をFortranでやると思ってください。

1次元配列

1次元配列をずらす場合、以下のように記述します。

integer::array(5)=(/1,2,3,4,5/)
write(*,*)array
write(*,*)cshift(array, 1)
1 2 3 4 5
2 3 4 5 1

1個、左(負)方向にずれている様子が分かるかと思います。

n個、ずらしたい場合は、2つ目の引数をnにすればよいです。

反対に右(正)方向にずらしたい場合は、2つ目の引数をマイナスにすれば解決します。

integer::array(5)=(/1,2,3,4,5/)
write(*,*)array
write(*,*)cshift(array, -1)
1 2 3 4 5
5 1 2 3 4

2次元配列

2次元配列の場合、行方向、列方向の情報が必要になります。

例では、1から9までの3×3の行列で解説します。

上にシフト

integer, dimension(3,3) :: array,dim_1

array = reshape( (/ 1, 2, 3, 4, 5, 6, 7, 8, 9 /), (/ 3, 3 /))
write(*,*)"----array----"
write(*,*)array(:,1)
write(*,*)array(:,2)
write(*,*)array(:,3)
dim_1=cshift(abc, 1, DIM=2)
write(*,*)"----dim_1----"
write(*,*)dim_1(:,1)
write(*,*)dim_2(:,2)
write(*,*)dim_3(:,3)
----array----
1 2 3
4 5 6
7 8 9
----dim_1----
4 5 6 
7 8 9
1 2 3

わかりやすくするため、出力を工夫しています。

反対に、行列を下方向にずらす場合、1次元配列の時と同じで、2つ目の引数をマイナスにすれば解決します。

下にシフト

integer, dimension(3,3) :: array,dim_1

array = reshape( (/ 1, 2, 3, 4, 5, 6, 7, 8, 9 /), (/ 3, 3 /))
write(*,*)"----array----"
write(*,*)array(:,1)
write(*,*)array(:,2)
write(*,*)array(:,3)
dim_1=cshift(abc, -1, DIM=2)
write(*,*)"----dim_1----"
write(*,*)dim_1(:,1)
write(*,*)dim_2(:,2)
write(*,*)dim_3(:,3)
----array----
1 2 3
4 5 6
7 8 9
----dim_1----
7 8 9
1 2 3
4 5 6

左にシフト

integer, dimension(3,3) :: array,dim_2

array = reshape( (/ 1, 2, 3, 4, 5, 6, 7, 8, 9 /), (/ 3, 3 /))
write(*,*)"----array----"
write(*,*)array(1,:)
write(*,*)array(2,:)
write(*,*)array(3,:)
dim_2=cshift(abc, 1, DIM=1)
write(*,*)"----dim_2----"
write(*,*)dim_1(1,:)
write(*,*)dim_2(2,:)
write(*,*)dim_3(3,:)
----array----
1 2 3
4 5 6
7 8 9
----dim_2----
2 3 1
5 6 4
8 9 7

反対に、行列を右方向にずらす場合、1次元配列の時と同じで、2つ目の引数をマイナスにすれば解決します。

右にシフト

integer, dimension(3,3) :: array,dim_2

array = reshape( (/ 1, 2, 3, 4, 5, 6, 7, 8, 9 /), (/ 3, 3 /))
write(*,*)"----array----"
write(*,*)array(1,:)
write(*,*)array(2,:)
write(*,*)array(3,:)
dim_2=cshift(abc, -1, DIM=2)
write(*,*)"----dim_2----"
write(*,*)dim_1(1,:)
write(*,*)dim_2(2,:)
write(*,*)dim_3(3,:)
----array----
1 2 3
4 5 6
7 8 9
----dim_2----
3 1 2
6 4 5
9 7 8

個別にずらしたい

また、行方向、列方向で一定にずらすのではなく、バラバラにずらしたい場合はどうすればよいでしょうか。

こちらもcshifで出来ます。

行方向

3つ目の引数で、dim=1で指定してあげましょう。

2つ目の引数でそれぞれの行でずらす値を配列で指定します。

integer, dimension(3,3) :: abc,dim2
dim_2 = reshape( (/ 1, 2, 3, 4, 5, 6, 7, 8, 9 /), (/ 3, 3 /))
write(*,*)"----array----"
write(*,*)abc(:,1)
write(*,*)abc(:,2)
write(*,*)abc(:,3)
dim2=cshift(array, (/1,-1,1/), DIM=1)
write(*,*)"----dim_2-----"
write(*,*)dim_2(:,1)
write(*,*)dim_2(:,2)
write(*,*)dim_2(:,3)
----array----
1 2 3
4 5 6 
7 8 9
----dim_2----
2 3 1
6 4 5
8 9 7

列方向

3つ目の引数で、dim=2で指定してあげましょう。

2つ目の引数でそれぞれの列でずらす値を配列で指定します。

integer, dimension(3,3) :: abc,dim_1
array = reshape( (/ 1, 2, 3, 4, 5, 6, 7, 8, 9 /), (/ 3, 3 /))
write(*,*)"----array----"
write(*,*)array(:,1)
write(*,*)array(:,2)
write(*,*)array(:,3)
dim_1=cshift(array, (/1,-1,1/), DIM=2)
write(*,*)"----dim_1-----"
write(*,*)dim_1(:,1)
write(*,*)dim_1(:,2)
write(*,*)dim_1(:,3)
----array----
1 2 3
4 5 6
7 8 9
----dim_1----
4 8 6
7 2 9
1 5 3

まとめ

Fortranで配列をずらす場合、cshiftを用います。

!1次元
cshift(配列,ずらす数)

!2次元 
cshift(配列,ずらす数,dim=y)
ずらす数=正&&y=1:左
ずらす数=負&&y=1:右
ずらす数=正&&y=2:上
ずらす数=負&&y=2:下

!ずらす数を別々に設定
cshift(配列,(ずらす数),dim=num)