从Fortran中的p * p * n数组中选择k * k子阵列

时间:2010-01-27 13:20:15

标签: select multidimensional-array fortran extract

我在Fortran中有一个p p n数组,我想从那个更大的数组中提取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意味着行/列想要子数组。这是否有效,如果没有,那么同样的事情是如何实现的?感谢。

4 个答案:

答案 0 :(得分:0)

如果我理解你想要做什么,这里有一个示例程序,它提取选定的列和行,但不使用多数数组表示法。

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

答案 1 :(得分:0)

解决方案二,使用向量(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

答案 2 :(得分:0)

不确定这些非代码片段是否对您有用;但

  • 不要忘记Fortran的数组切片功能。
  • 不要忘记您可以使用向量下标来获取数组部分,例如,您可以选择向量v的元素,如下所示:

    v((/ 1,3,6,5,10 /))

矢量下标可以应用于排名大于1的数组。以这种方式弄清楚你的下标需求会让我头痛,但你可能想尝试一下。

答案 3 :(得分:0)

是的,它应该有效,你甚至不需要do t = ...循环

  program main
  integer,dimension(3,3,2):: a
  integer,dimension(4,4,2):: b
  integer,dimension(4):: y
  integer,dimension(4):: idx
  integer:: i,j,k

  y = (/ 1 , 0 , 1 , 1 /)
  idx = (/ (i,i=1,4) /)
  b(:,:,:)=reshape((/((((i+10*j+100*k),i=1,4),j=1,4),k=1,2)/),(/4,4,2/))
  a(:,:,:) = b( pack(idx,y>0) , pack(idx,y>0) , :)

  print '(A2/,(4I4))','b=',b
  print '(A2/,(3I4))','a=',a

  end

使用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) , :)

或者想想使用LOGICAL .true。和.false。而不是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