【发布时间】:2014-06-29 00:36:05
【问题描述】:
令 A 为 DIMENSION(m,n,p) 的多维数组。 Fortran 中是否允许对 A 进行线性索引(使用单个索引)?如果是这样,线性索引和多维索引之间的对应关系是什么?
也就是说A(i)是否允许,A(i)对应的是哪个元素(遍历的维度是什么顺序)?
【问题讨论】:
令 A 为 DIMENSION(m,n,p) 的多维数组。 Fortran 中是否允许对 A 进行线性索引(使用单个索引)?如果是这样,线性索引和多维索引之间的对应关系是什么?
也就是说A(i)是否允许,A(i)对应的是哪个元素(遍历的维度是什么顺序)?
【问题讨论】:
http://www.obliquity.com/computer/fortran/array.html 解释说数组是以“列为主”的形式存储的,所以最左边的索引变化最快,其次是最左边的第二个,依此类推(我相信这与 C 正好相反) .尝试像一维一样索引多维数组似乎很不明智,但正如上面链接的页面所解释的那样,您的编译器将生成执行此操作的代码(因此非常快)您以正确的顺序嵌套循环。
【讨论】:
您可以将 3D 数组传递给函数或子例程,就好像它是 1D 数组一样,如下面的代码所示。我不推荐使用此功能,但您会在 Fortran 90 之前的代码中看到它。
program xarray
implicit none
! demonstrate storage association
integer, parameter :: n1 = 2, n2 = 4, n3 = 3
integer :: i1,i2,i3,arr(n1,n2,n3)
forall (i1=1:n1,i2=1:n2,i3=1:n3) arr(i1,i2,i3) = i1 + 10*i2 + 100*i3
print*,"arr =",arr
! output: arr = 111 112 121 122 131 132 141 142 211 212 221 222 231 232 241 242 311 312 321 322 331 332 341 342
call print_array(arr,n1*n2*n3)
end program xarray
subroutine print_array(arr,n)
implicit none
integer, intent(in) :: arr(n)
integer, intent(in) :: n
print*,"arr(1), arr(n) =",arr(1),arr(n)
! output: arr(1), arr(n) = 111 342
end subroutine print_array
【讨论】:
对于声明为dimension A(m,n,p) 的数组,它不允许像A(i) 那样引用。但是,线性索引,即所谓的数组元素顺序是一个重要的概念。正如another answer 中所述,最左边的索引是变化最快的。 A(1,1,1) 紧接在 A(2,1,1)、...、A(1,2,1) 等之前。
数组元素顺序由于各种关联等而变得有用。例如 - 除非有真正需要,否则我不会推荐它们 - equivalence 和与假定大小数组的参数关联允许很多相同的事情。
作为一项更现代的功能,可以使用pointer bounds remapping。当然,还有一个副本,reshape 内在函数。
【讨论】:
我会添加以下可能性,即使我从未使用过它,因为我觉得它令人困惑。有人(Nek5000,见第 22 页)声称它更快。
do i=1,nx1*ny1*nz1*nelv u(i,1,1,1) = vx(i,1,1,1) enddo这等同于但优于(为什么?):
do e=1,nelv do k=1,nz1 do j=1,ny1 do i=1,nx1 u(i,j,k,e) = vx(i,j,k,e) enddo enddo enddo enddo这等同于但大大优于(为什么?):
do i=1,nx1 do j=1,ny1 do k=1,nz1 do e=1,nelv u(i,j,k,e) = vx(i,j,k,e) enddo enddo enddo enddo
【讨论】: