我有一个子程序,填充任意长度的1级数组。
subroutine populate_array_1D(array)
implicit none
integer, dimension(:), intent(out) :: array
array(:) = 1
end subroutine populate_array_1D
我现在想要使用重载修改此例程以接受更高维度的数组。
interface populate_array
module procedure populate_array_1D, populate_array_2D, populate_array_3D
end interface populate_array
我想要做的是将更高维度的子程序引回到1D子程序。
到目前为止我的想法:
切割数组,然后逐个传递切片:
subroutine populate_array_2D(array)
implicit none
integer, dimension(:,:), intent(out) :: array
integer :: i
do i = lbound(array, 2), ubound(array, 2)
call populate_array_1D(array(:, i))
end do
end subroutine populate_array_2D
创建一个新的自动1D数组,然后使用reshape
:
subroutine populate_array_3D(array)
implicit none
integer, dimension(:,:,:), intent(out) :: array
integer :: tmp_array(size(array))
call populate_array_1D(tmp_array)
array = reshape(tmp_array, shape(array))
end subroutine populate_array_3D
假设,就像在这个例子中,任何一个版本的结果都没问题,我只担心性能。 (我应该补充一点,我不能只制作一个elemental
子程序,因为它不能pure
。)
或者是否有一个更好的版本,我可以将多维数组传递到一个假装它是一维数组的子程序中?
(最终我想用不同编译器和/或机器上尽可能确定的PRNG替换对RANDOM_NUMBER
的调用,假设它们使用相同的种子。)
答案 0 :(得分:0)
正如francescalus所指出的那样,基本过程可能是不纯正的(从Fortran 2008开始)。
或者,您可以使用Fortran的固有C互操作性 获得对2D阵列的内存位置的低级访问。下面的子例程构建一个指向2D数组的1D指针:
subroutine populate_array_2D(array)
use iso_c_binding, only: C_F_POINTER, C_LOC
integer, dimension(:,:), target, contiguous, intent(out) :: array
integer, dimension(:), pointer :: ptr_1d
call C_F_POINTER (C_LOC(array), ptr_1d, [size(array)])
call populate_array_1D(ptr_1d)
end subroutine populate_array_2D
对c_f_pointer
的呼叫可以替换为
指针中的等效绑定重映射列表:
ptr_1d(1:size(array)) => array
(尽管使用ifort18进行编译会错误地显示warning message,这对于Fortran 2008无效)。