配列の位置の移動したい、つまり、ある行列があった場合、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)