使用矢量的N-D数组的访问元素。

时间:2022-08-06 21:32:52

Is there a way I can access the nth element of an array a, where n is a 1D array and size(n) is the rank of a.

是否有一种方法可以访问数组a的第n个元素,其中n是1D数组,size(n)是a的秩。

Edit 2015-08-22 15:21

编辑2015-08-22 15:21

I am thinking of something similar to

我在想类似的事情

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

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

    write(*,*) a(b)

end program Example1D

So I can call like this

我可以这样叫。

program Want2D
    integer :: a(6,5), b(2)

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

    write(*,*) a(b)

end program Want2D

1 个解决方案

#1


0  

You are attempting to use a vector-subscript (e.g. Fortran 2008, cl. 6.5.3.3.2). This allows you to use a vector (1D array) to select random elements from an array dimension. This, however, cannot be used exactly as you intend it to select an element from multiple dimensions.

您正在尝试使用向量-下标(例如Fortran 2008, cl)。6.5.3.3.2)。这允许您使用向量(1D数组)从数组维度中选择随机元素。但是,不能按照您希望的那样从多个维度中选择元素。

From 6.5.3.3 (emphasis mine):

我从6.5.3.3(重点):

In an array-section having a section-subscript-list, each subscript-triplet and vector-subscript in the section sub- script list indicates a sequence of subscripts, which may be empty. Each subscript in such a sequence shall be within the bounds for its dimension unless the sequence is empty. The array section is the set of elements from the array determined by all possible subscript lists obtainable from the single subscripts or sequences of subscripts specified by each section subscript.

在具有分段订阅列表的array-section中,分段订阅列表中的每个subscript-triplet和vector-subscript列表指示了一个下标序列,该序列可能是空的。这样一个序列中的每个下标都应该在其维度的范围内,除非序列是空的。数组部分是数组中的一组元素,这些元素由所有可能的下标列表决定,这些列表可以从单个下标中获取,也可以从每个分段下标指定的下标序列中获取。

If you goal in your example code is to select the element a(5,3) with your vector b = [5, 3], then you could change your write from

如果您的示例代码的目标是选择向量b =[5,3]的元素a(5,3),那么您可以更改您的写入

write (*,*) a(b)           ! doesn't work

to:

:

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

You can do more complicated array-sections with b of higher ranks as long as you use a 1D section for each dimension of a. For example if a is a 5x5 array, you could get the corners with of a as a 2x2 array with:

只要在a的每个维度上都使用一个1D的分段,就可以用更高级别的b来做更复杂的arraysections。

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)

In the comments below you requested that this be abstracted to an n-dimensional array a. Below is a function I consider ugly due to its need to use c interop in a way I consider a hack. You'll also need a newer compiler to even use the code, as it depends on assumed-rank arrays. Here is a module containing a subroutine that takes a 2-dimensional b containing array indices to print and an n-dimensional a to get the values from.

在下面的评论中,您要求将它抽象为一个n维数组a。您还需要一个更新的编译器来使用这些代码,因为它依赖于假定秩数组。这是一个包含子程序的模块,该子程序使用一个包含数组索引的二维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

This takes in assumed-rank a, which is not directly usable in Fortran except to pass as an actual argument to a C interface. However, we can use other parts of c-interop to get the C pointer to a, then turn it into a Fortran pointer of the appropriate shape. Now we have a in a usable form, but we have to do this within if/else blocks properly reference the different cases. I've only implemented up to 3-dimensional a, the rest is left as an exercise to the reader.

这采用了假定-秩a,它在Fortran中不能直接使用,除非作为一个实际的参数传递给C接口。但是,我们可以使用C -interop的其他部分来获得C指针到a,然后将它转换成适当形状的Fortran指针。现在我们有了可用的a,但是我们必须在if/else块中正确引用不同的情况。我只实现了3维a,其余的留给读者作为练习。

To use this function, here is an example:

要使用这个函数,这里有一个例子:

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

This constructs a 3-dim a, a 2-dim a, and a 1-dim a, and a few 2-dim b's with the locations of the corners of the arrays and then we call the function to print the locations of the vector from the array.

它构造了一个3-dim a、2-dim a和1-dim a,以及一些2-dim b和数组角的位置,然后我们调用函数从数组中打印矢量的位置。

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

I compiled and tested this with gfortran 5.2 and I have no idea the current state of support for assumed-rank arrays in other version of gfortran or in other Fortran compilers.

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

#1


0  

You are attempting to use a vector-subscript (e.g. Fortran 2008, cl. 6.5.3.3.2). This allows you to use a vector (1D array) to select random elements from an array dimension. This, however, cannot be used exactly as you intend it to select an element from multiple dimensions.

您正在尝试使用向量-下标(例如Fortran 2008, cl)。6.5.3.3.2)。这允许您使用向量(1D数组)从数组维度中选择随机元素。但是,不能按照您希望的那样从多个维度中选择元素。

From 6.5.3.3 (emphasis mine):

我从6.5.3.3(重点):

In an array-section having a section-subscript-list, each subscript-triplet and vector-subscript in the section sub- script list indicates a sequence of subscripts, which may be empty. Each subscript in such a sequence shall be within the bounds for its dimension unless the sequence is empty. The array section is the set of elements from the array determined by all possible subscript lists obtainable from the single subscripts or sequences of subscripts specified by each section subscript.

在具有分段订阅列表的array-section中,分段订阅列表中的每个subscript-triplet和vector-subscript列表指示了一个下标序列,该序列可能是空的。这样一个序列中的每个下标都应该在其维度的范围内,除非序列是空的。数组部分是数组中的一组元素,这些元素由所有可能的下标列表决定,这些列表可以从单个下标中获取,也可以从每个分段下标指定的下标序列中获取。

If you goal in your example code is to select the element a(5,3) with your vector b = [5, 3], then you could change your write from

如果您的示例代码的目标是选择向量b =[5,3]的元素a(5,3),那么您可以更改您的写入

write (*,*) a(b)           ! doesn't work

to:

:

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

You can do more complicated array-sections with b of higher ranks as long as you use a 1D section for each dimension of a. For example if a is a 5x5 array, you could get the corners with of a as a 2x2 array with:

只要在a的每个维度上都使用一个1D的分段,就可以用更高级别的b来做更复杂的arraysections。

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)

In the comments below you requested that this be abstracted to an n-dimensional array a. Below is a function I consider ugly due to its need to use c interop in a way I consider a hack. You'll also need a newer compiler to even use the code, as it depends on assumed-rank arrays. Here is a module containing a subroutine that takes a 2-dimensional b containing array indices to print and an n-dimensional a to get the values from.

在下面的评论中,您要求将它抽象为一个n维数组a。您还需要一个更新的编译器来使用这些代码,因为它依赖于假定秩数组。这是一个包含子程序的模块,该子程序使用一个包含数组索引的二维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

This takes in assumed-rank a, which is not directly usable in Fortran except to pass as an actual argument to a C interface. However, we can use other parts of c-interop to get the C pointer to a, then turn it into a Fortran pointer of the appropriate shape. Now we have a in a usable form, but we have to do this within if/else blocks properly reference the different cases. I've only implemented up to 3-dimensional a, the rest is left as an exercise to the reader.

这采用了假定-秩a,它在Fortran中不能直接使用,除非作为一个实际的参数传递给C接口。但是,我们可以使用C -interop的其他部分来获得C指针到a,然后将它转换成适当形状的Fortran指针。现在我们有了可用的a,但是我们必须在if/else块中正确引用不同的情况。我只实现了3维a,其余的留给读者作为练习。

To use this function, here is an example:

要使用这个函数,这里有一个例子:

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

This constructs a 3-dim a, a 2-dim a, and a 1-dim a, and a few 2-dim b's with the locations of the corners of the arrays and then we call the function to print the locations of the vector from the array.

它构造了一个3-dim a、2-dim a和1-dim a,以及一些2-dim b和数组角的位置,然后我们调用函数从数组中打印矢量的位置。

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

I compiled and tested this with gfortran 5.2 and I have no idea the current state of support for assumed-rank arrays in other version of gfortran or in other Fortran compilers.

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