将 1D 数组传递给 3D 数组
Pass 1D array to 3D array
我在 Fortran 中使用 API,它提供了写入数据的例程。假设它的名字是 api_write_data
。这个例程需要一个数组作为参数,它可以是 1、2 或 3 维。
我想编写一个子例程作为此 API 例程的包装器。但是因此我有必要编写一个可以处理 1D、2D 或 3D 数组并将它们正确传递给 API 例程的例程。我怎样才能做到这一点?我可以这样做吗?
我的方法是这样的,但它不起作用:
subroutine write_data(array)
implicit none
integer, dimension(:,:,:), intent(in):: array
call api_write_data(array)
end subroutine write_data
但是,当我使用一维数组调用此例程时,出现已知错误:
Error: Rank mismatch in argument 'array' at (1) (rank-3 and rank-1)
在 Fortran 中有什么方法可以做那种事情吗?对我来说,有必要将数组作为 1D、2D 或 3D 数组传递给 write_data
例程。但是,我可以将数组作为一维数组传递给 api_write_data
.
你知道我该怎么做吗?
您可以使用 Fortran 接口定义多个版本的例程:
interface write_data
module procedure write_data_1d
module procedure write_data_2d
module procedure write_data_3d
end interface write_data
然后这些程序可以处理不同类型的输入。然后在这些过程中,您可以使用 RESHAPE 函数将输入转换为方便的形状,以便所有三个都可以调用一个公共子例程来实现您所做的任何逻辑。
reshape
函数的替代方法可能是使用指向多维数组的一维指针:
p(1:size(c)) => c(:,:,:)
您可以将指针作为一维数组传递,而无需进行复制。事实上,它应该和传递数组本身一样快。
当然,您需要一些方法来告诉子例程数组的形状:
module test_mod
contains
subroutine print_arr( arr, dimX, dimY, dimZ )
integer,intent(in) :: arr(:)
integer,intent(in) :: dimX, dimY, dimZ
if ( dimZ == 0 ) then
if ( dimY == 0 ) then
! 1D
print *, "1D array provided"
print *, "a(4) =", arr(4)
else
! 2D
print *, "2D array provided"
print *, "a(1,2) =", arr((2-1)*dimX+1)
endif
else
! 3D
print *, "3D array provided"
print *, "a(1,2,1) =", arr( ((1-1)*dimY + (2-1))*dimX+1)
endif
end subroutine
end module
program test
use test_mod
integer :: i
integer, target :: a(8)
integer, target :: b(4,2)
integer, target :: c(2,2,2)
integer, pointer :: p(:)
a = [ (i,i=1,8) ]
b = reshape( a, [4,2] )
c = reshape( a, [2,2,2] )
p(1:size(a)) => a(:)
call print_arr( p, 8, 0, 0 )
p(1:size(b)) => b(:,:)
call print_arr( p, 4, 2, 0 )
p(1:size(c)) => c(:,:,:)
call print_arr( p, 2, 2, 2 )
end program
反之亦然...您可以将 1D 数组映射到 3D 指针:
integer, pointer :: p2(:,:,:)
!...
p2(1:4,1:2,1:1) => a
我在 Fortran 中使用 API,它提供了写入数据的例程。假设它的名字是 api_write_data
。这个例程需要一个数组作为参数,它可以是 1、2 或 3 维。
我想编写一个子例程作为此 API 例程的包装器。但是因此我有必要编写一个可以处理 1D、2D 或 3D 数组并将它们正确传递给 API 例程的例程。我怎样才能做到这一点?我可以这样做吗?
我的方法是这样的,但它不起作用:
subroutine write_data(array)
implicit none
integer, dimension(:,:,:), intent(in):: array
call api_write_data(array)
end subroutine write_data
但是,当我使用一维数组调用此例程时,出现已知错误:
Error: Rank mismatch in argument 'array' at (1) (rank-3 and rank-1)
在 Fortran 中有什么方法可以做那种事情吗?对我来说,有必要将数组作为 1D、2D 或 3D 数组传递给 write_data
例程。但是,我可以将数组作为一维数组传递给 api_write_data
.
你知道我该怎么做吗?
您可以使用 Fortran 接口定义多个版本的例程:
interface write_data
module procedure write_data_1d
module procedure write_data_2d
module procedure write_data_3d
end interface write_data
然后这些程序可以处理不同类型的输入。然后在这些过程中,您可以使用 RESHAPE 函数将输入转换为方便的形状,以便所有三个都可以调用一个公共子例程来实现您所做的任何逻辑。
reshape
函数的替代方法可能是使用指向多维数组的一维指针:
p(1:size(c)) => c(:,:,:)
您可以将指针作为一维数组传递,而无需进行复制。事实上,它应该和传递数组本身一样快。 当然,您需要一些方法来告诉子例程数组的形状:
module test_mod
contains
subroutine print_arr( arr, dimX, dimY, dimZ )
integer,intent(in) :: arr(:)
integer,intent(in) :: dimX, dimY, dimZ
if ( dimZ == 0 ) then
if ( dimY == 0 ) then
! 1D
print *, "1D array provided"
print *, "a(4) =", arr(4)
else
! 2D
print *, "2D array provided"
print *, "a(1,2) =", arr((2-1)*dimX+1)
endif
else
! 3D
print *, "3D array provided"
print *, "a(1,2,1) =", arr( ((1-1)*dimY + (2-1))*dimX+1)
endif
end subroutine
end module
program test
use test_mod
integer :: i
integer, target :: a(8)
integer, target :: b(4,2)
integer, target :: c(2,2,2)
integer, pointer :: p(:)
a = [ (i,i=1,8) ]
b = reshape( a, [4,2] )
c = reshape( a, [2,2,2] )
p(1:size(a)) => a(:)
call print_arr( p, 8, 0, 0 )
p(1:size(b)) => b(:,:)
call print_arr( p, 4, 2, 0 )
p(1:size(c)) => c(:,:,:)
call print_arr( p, 2, 2, 2 )
end program
反之亦然...您可以将 1D 数组映射到 3D 指针:
integer, pointer :: p2(:,:,:)
!...
p2(1:4,1:2,1:1) => a