使用向量

时间:2015-08-20 15:13:45

标签: arrays multidimensional-array fortran

有没有办法可以访问数组n的{​​{1}}元素,其中n是1D数组,asize(n)的等级。< / p>

编辑2015-08-22 15:21

我在考虑与

类似的东西
a

所以我可以像这样打电话

program Example1D
    integer :: a(6), b(1)

    a = reshape( (/ (i , i = 1, size(a) ) /) , shape(a) )
    b = (/ 5 /)

    write(*,*) a(b)

end program Example1D

1 个答案:

答案 0 :(得分:0)

您正在尝试使用 vector-subscript (例如Fortran 2008,cl.6.5.3.3.2)。这允许您使用向量(1D数组)从数组维​​度中选择随机元素。但是,这并不能完全用于从多个维度中选择元素。

从6.5.3.3(强调我的):

  

在具有 section-subscript-list array-section 中,每个 subscript-triplet vector-subscript 在子节中   脚本列表表示一系列下标,可能为空。 这样的序列中的每个下标应为   除非序列为空,否则在其维度的范围内。数组部分是来自的元素集   由所有可能的下标列表确定的数组,可从单个下标或下标序列获得   由每个部分下标指定。

如果您的示例代码中的目标是使用向量a(5,3)选择元素b = [5, 3],那么您可以从

更改您的写入
write (*,*) a(b)           ! doesn't work

为:

write (*,*) a(b(1),b(2))   ! does work

只要为b的每个维使用1D部分,就可以执行更高级别a更复杂的数组部分。例如,如果a是一个5x5数组,则可以使用a作为2x2数组的角点:

integer :: b(2,2)   ! 2 dimensional
b(1,:) = [1,5]
b(2,:) = [1,5]
write (*,*) a(b(1,:),b(2,:))   ! prints a(1,1), a(5,1), a(1,5), a(5,5)

在下面的评论中,您要求将其抽象为n维数组a。下面是一个我认为丑陋的函数,因为它需要以我认为是hack的方式使用c interop。您还需要一个更新的编译器来使用代码,因为它依赖于假定等级数组。这是一个包含子程序的模块,该子程序采用包含要打印的二维b数组索引,并使用n维a来获取值。

module future
  implicit none
contains
  subroutine print_array_vector(a, b)
    use, intrinsic :: iso_c_binding, only: c_loc, c_f_pointer
    implicit none
    integer, dimension(..), target :: a
    integer, dimension(:,:) :: b
    integer :: a_rank, b_len1
    integer, dimension(:,:,:), pointer :: a3 
    integer, dimension(:,:), pointer :: a2
    integer, dimension(:), pointer :: a1

    a_rank = rank(a)

    if (a_rank /= size(b,1)) then
       print *, "Rank mismatch between array and vector"
       return
    end if

    if (a_rank == 3) then
       call c_f_pointer(c_loc(a), a3, shape=[size(a,1), size(a,2), size(a,3)])
       print *, a3(b(1,:),b(2,:),b(3,:))
    else if (a_rank == 2) then
       call c_f_pointer(c_loc(a), a2, shape=[size(a,1), size(a,2)])
       print *, a2(b(1,:),b(2,:))
    else if (a_rank == 1) then
       call c_f_pointer(c_loc(a), a1, shape=[size(a,1)])
       print *, a1(b(1,:))
    else
       print *, "Unsupported rank"
       return
    end if
  end subroutine print_array_vector
end module future

这接受假定等级 a,除了作为实际参数传递给C接口之外,它不能直接在Fortran中使用。但是,我们可以使用c-interop的其他部分来获取a的C指针,然后将其转换为适当形状的Fortran指针。现在我们以可用的形式a,但我们必须在if / else块内正确引用不同的情况。我只实现了最多3维a,其余部分留给了读者。

要使用此功能,以下是一个示例:

program test
  use future
  implicit none
  integer :: a3(5,5,5), a2(5,5), a1(5)
  integer :: b3(3,2), b2(2,2), b1(1,2)
  integer :: i

  a3 = reshape([(i,i=1,125)],shape(a3))
  a2 = reshape([(i,i=1,25)],shape(a2))
  a1 = [(i,i=1,5)]

  b3 = reshape([1,1,1,5,5,5],shape(b3))
  b2 = reshape([1,1,5,5],shape(b2))
  b1 = reshape([1,5],shape(b1))

  call print_array_vector(a1,b1)
  call print_array_vector(a2,b2)
  call print_array_vector(a3,b3)
end program test

这构造了一个3-dim a,一个2-dim a和一个1-dim a,以及一些2-dim b&#39 ; s带有数组角点的位置,然后我们调用函数从数组中打印向量的位置。

% ./arraysection                           
           1           5
           1           5          21          25
           1           5          21          25         101         105         121         125

我用gfortran 5.2编译并测试了这个,我不知道在其他版本的gfortran或其他Fortran编译器中支持假定等级数组的当前状态。