Select 在Fortran中从p*p*n数组中选择k*k子数组
我在Fortran中有一个ppn数组,我想从那个更大的数组中提取k*k子数组。我试过这样做,但不确定是否有效:Select 在Fortran中从p*p*n数组中选择k*k子数组,select,multidimensional-array,fortran,extract,Select,Multidimensional Array,Fortran,Extract,我在Fortran中有一个ppn数组,我想从那个更大的数组中提取k*k子数组。我试过这样做,但不确定是否有效: do i=1,p vp(i)=i end do help=y(1:p,t)*vp do t = 1, n A(1:k,1:k,t) = B(pack(help,help>0), pack(help,help>0), t) end do 其中y包含值0和1,1表示希望将行/列作为子阵列。这行得通吗?如果不行,那同一件事怎么办?谢谢。如果我了解您想要做什么,下面
do i=1,p
vp(i)=i
end do
help=y(1:p,t)*vp
do t = 1, n
A(1:k,1:k,t) = B(pack(help,help>0), pack(help,help>0), t)
end do
其中y包含值0和1,1表示希望将行/列作为子阵列。这行得通吗?如果不行,那同一件事怎么办?谢谢。如果我了解您想要做什么,下面是一个示例程序,它提取选定的列和行,但不使用太多的数组表示法
program test
integer, parameter :: Adim = 2
integer, parameter :: Bdim = 3
integer, dimension (Adim,Adim) :: A
integer, dimension (Bdim,Bdim) :: B
logical, dimension (Bdim) :: good_row = [.true., .false., .true.]
logical, dimension (Bdim) :: good_col = [.false., .true., .true.]
integer :: i, j, ia, ja, ib, jb
if (count (good_row) /= Adim .or. count (good_col) /= Adim) then
write (*, *) 'selection arrays not setup correctly.'
stop
end if
do i=1, Bdim
do j=1, Bdim
B (i,j) = i + i*j**2 ! test values
end do
end do
do i=1, Bdim
write (*, *) (B (i, j), j=1, Bdim)
end do
ia = 0
do ib=1, Bdim
if (good_row (ib)) then
ia = ia + 1
ja = 0
do jb=1, Bdim
if (good_col (jb)) then
ja = ja + 1
!write (*, *) ia, ja, ib, jb
A(ia,ja) = B(ib,jb)
end if
end do
end if
end do
write (*, *)
do i=1, Adim
write (*, *) (A (i, j), j=1, Adim)
end do
stop
end program test
如果我了解您想要做什么,下面是一个示例程序,它提取选定的列和行,但不使用太多的数组表示法
program test
integer, parameter :: Adim = 2
integer, parameter :: Bdim = 3
integer, dimension (Adim,Adim) :: A
integer, dimension (Bdim,Bdim) :: B
logical, dimension (Bdim) :: good_row = [.true., .false., .true.]
logical, dimension (Bdim) :: good_col = [.false., .true., .true.]
integer :: i, j, ia, ja, ib, jb
if (count (good_row) /= Adim .or. count (good_col) /= Adim) then
write (*, *) 'selection arrays not setup correctly.'
stop
end if
do i=1, Bdim
do j=1, Bdim
B (i,j) = i + i*j**2 ! test values
end do
end do
do i=1, Bdim
write (*, *) (B (i, j), j=1, Bdim)
end do
ia = 0
do ib=1, Bdim
if (good_row (ib)) then
ia = ia + 1
ja = 0
do jb=1, Bdim
if (good_col (jb)) then
ja = ja + 1
!write (*, *) ia, ja, ib, jb
A(ia,ja) = B(ib,jb)
end if
end do
end if
end do
write (*, *)
do i=1, Adim
write (*, *) (A (i, j), j=1, Adim)
end do
stop
end program test
解决方案二,在矢量1D阵列级别使用阵列操作-将主回路替换为:
ia = 0
do ib=1, Bdim
if (good_row (ib)) then
ia = ia + 1
A (ia,:) = pack (B(ib,:), good_col)
end if
end do
解决方案三,完全使用阵列操作:
program test
integer, parameter :: Adim = 2
integer, parameter :: Bdim = 3
integer, dimension (Adim,Adim) :: A
integer, dimension (Bdim,Bdim) :: B
logical, dimension (Bdim,Bdim) :: mask
integer :: i, j
mask (1,:) = [.false., .true., .true.]
mask (2,:) = .false.
mask (3,:) = [.false., .true., .true.]
do i=1, Bdim
do j=1, Bdim
B (i,j) = i + i*j**2 ! test values
end do
end do
do i=1, Bdim
write (*, *) (B (i, j), j=1, Bdim)
end do
A = reshape ( pack (B, mask), [Adim, Adim] )
write (*, *)
do i=1, Adim
write (*, *) (A (i, j), j=1, Adim)
end do
stop
end program test
解决方案二,在矢量1D阵列级别使用阵列操作-将主回路替换为:
ia = 0
do ib=1, Bdim
if (good_row (ib)) then
ia = ia + 1
A (ia,:) = pack (B(ib,:), good_col)
end if
end do
解决方案三,完全使用阵列操作:
program test
integer, parameter :: Adim = 2
integer, parameter :: Bdim = 3
integer, dimension (Adim,Adim) :: A
integer, dimension (Bdim,Bdim) :: B
logical, dimension (Bdim,Bdim) :: mask
integer :: i, j
mask (1,:) = [.false., .true., .true.]
mask (2,:) = .false.
mask (3,:) = [.false., .true., .true.]
do i=1, Bdim
do j=1, Bdim
B (i,j) = i + i*j**2 ! test values
end do
end do
do i=1, Bdim
write (*, *) (B (i, j), j=1, Bdim)
end do
A = reshape ( pack (B, mask), [Adim, Adim] )
write (*, *)
do i=1, Adim
write (*, *) (A (i, j), j=1, Adim)
end do
stop
end program test
不确定这些非代码片段是否对您有用,但是 不要忘记Fortran的数组分段功能。 不要忘记,您可以使用向量下标来获取数组部分,例如,您可以选择向量v的元素,如下所示: v/1、3、6、5、10/
向量下标可以应用于秩大于1的数组。用这种方式了解您的订阅需求会伤到我的头,但您可能想试试。不确定这些非代码片段是否对您有用,但是 不要忘记Fortran的数组分段功能。 不要忘记,您可以使用向量下标来获取数组部分,例如,您可以选择向量v的元素,如下所示: v/1、3、6、5、10/
向量下标可以应用于秩大于1的数组。这样弄清楚你的订阅要求会伤到我的头,但你可能想试试。是的,它应该会起作用,你甚至不需要dot=。。。环路 使用gfortran 4.2.3正确编译后
b=
111 112 113 114
121 122 123 124
131 132 133 134
141 142 143 144
211 212 213 214
221 222 223 224
231 232 233 234
241 242 243 244
a=
111 113 114
131 133 134
141 143 144
211 213 214
231 233 234
241 243 244
你也可以使用
k = count( y> 0)
a(1:k,1:k,:) = b( pack(idx,y>0) , pack(idx,y>0) , :)
或者用逻辑思维。对。还有,错。而不是1和0
program main
integer,dimension(3,3,2):: a
integer,dimension(4,4,2):: b
logical,dimension(4):: y
integer,dimension(4):: idx
integer:: i,j,k
idx = (/ (i,i=1,4) /)
y = idx /= 2
b(:,:,:)=reshape((/((((i+10*j+100*k),i=1,4),j=1,4),k=1,2)/),(/4,4,2/))
k = count( y )
a(1:k,1:k,:) = b( pack(idx,y) , pack(idx,y) , :)
print '(A2/,(4I4))','b=',b
print '(A2/,(3I4))','a=',a
end
是的,它应该工作,你甚至不需要做t=。。。环路 使用gfortran 4.2.3正确编译后
b=
111 112 113 114
121 122 123 124
131 132 133 134
141 142 143 144
211 212 213 214
221 222 223 224
231 232 233 234
241 242 243 244
a=
111 113 114
131 133 134
141 143 144
211 213 214
231 233 234
241 243 244
你也可以使用
k = count( y> 0)
a(1:k,1:k,:) = b( pack(idx,y>0) , pack(idx,y>0) , :)
或者用逻辑思维。对。还有,错。而不是1和0
program main
integer,dimension(3,3,2):: a
integer,dimension(4,4,2):: b
logical,dimension(4):: y
integer,dimension(4):: idx
integer:: i,j,k
idx = (/ (i,i=1,4) /)
y = idx /= 2
b(:,:,:)=reshape((/((((i+10*j+100*k),i=1,4),j=1,4),k=1,2)/),(/4,4,2/))
k = count( y )
a(1:k,1:k,:) = b( pack(idx,y) , pack(idx,y) , :)
print '(A2/,(4I4))','b=',b
print '(A2/,(3I4))','a=',a
end