gpt4 book ai didi

fortran - 如何为 'allocate' 编写包装器

转载 作者:行者123 更新时间:2023-12-04 06:28:48 25 4
gpt4 key购买 nike

我正在尝试为“分配”函数编写一个包装器,即接收数组和维度、分配内存并返回分配的数组的函数。最重要的是该函数必须与不同等级的数组一起使用。但是我必须在函数接口(interface)中明确声明数组的等级,在这种情况下,只有当我将特定等级的数组作为参数传递时,代码才会编译。例如,此代码无法编译:

module memory_allocator
contains

subroutine memory(array, length)
implicit none

real(8), allocatable, intent(out), dimension(:) :: array
integer, intent(in) :: length

integer :: ierr

print *, "memory: before: ", allocated(array)

allocate(array(length), stat=ierr)
if (ierr /= 0) then
print *, "error allocating memory: ierr=", ierr
end if

print *, "memory: after: ", allocated(array)

end subroutine memory

subroutine freem(array)
implicit none

real(8), allocatable, dimension(:) :: array

print *, "freem: before: ", allocated(array)
deallocate(array)
print *, "freem: after: ", allocated(array)

end subroutine freem

end module memory_allocator

program alloc
use memory_allocator
implicit none

integer, parameter :: n = 3
real(8), allocatable, dimension(:,:,:) :: foo
integer :: i, j, k

print *, "main: before memory: ", allocated(foo)
call memory(foo, n*n*n)
print *, "main: after memory: ", allocated(foo)

do i = 1,n
do j = 1,n
do k = 1, n
foo(i, j, k) = real(i*j*k)
end do
end do
end do

print *, foo

print *, "main: before freem: ", allocated(foo)
call freem(foo)
print *, "main: after freem: ", allocated(foo)

end program alloc

编译错误:
gfortran -o alloc alloc.f90 -std=f2003
alloc.f90:46.14:

call memory(foo, n*n*n)
1
Error: Rank mismatch in argument 'array' at (1) (1 and 3)
alloc.f90:60.13:

call freem(foo)
1
Error: Rank mismatch in argument 'array' at (1) (1 and 3)

有没有办法实现这样的包装?

谢谢!

最佳答案

这可以通过通用接口(interface) block 来完成。您必须为要处理的每个等级创建过程,例如 memory_1d、memory_2d、... memory_4d。 (显然很多剪切和粘贴。)然后您编写一个通用接口(interface) block ,为所有这些过程提供替代名称内存作为通用过程名称。当您调用内存时,编译器会根据参数的排名来区分应该调用哪个 memory_Xd。您的 freem 功能也是如此。

这就是 sin 等内部函数长期以来的工作方式——您可以使用各种预置的真实参数或复杂参数调用 sin,编译器会使用实际的 sin 函数来调用。在真正古老的 FORTRAN 中,您必须为不同的 sin 函数使用不同的名称。现在现代 Fortran,您可以使用自己的例程设置相同的东西。

编辑:添加一个演示方法和语法的代码示例:

module double_array_mod

implicit none

interface double_array
module procedure double_vector
module procedure double_array_2D
end interface double_array

private ! hides items not listed on public statement
public :: double_array

contains

subroutine double_vector (vector)
integer, dimension (:), intent (inout) :: vector
vector = 2 * vector
end subroutine double_vector

subroutine double_array_2D (array)
integer, dimension (:,:), intent (inout) :: array
array = 2 * array
end subroutine double_array_2D

end module double_array_mod


program demo_user_generic

use double_array_mod

implicit none

integer, dimension (2) :: A = [1, 2]
integer, dimension (2,2) :: B = reshape ( [11, 12, 13, 14], [2,2] )
integer :: i

write (*, '( / "vector before:", / 2(2X, I3) )' ) A
call double_array (A)
write (*, '( / "vector after:", / 2(2X, I3) )' ) A

write (*, '( / "2D array before:" )' )
do i=1, 2
write (*, '( 2(2X, I3) )' ) B (i, :)
end do
call double_array (B)
write (*, '( / "2D array after:" )' )
do i=1, 2
write (*, '( 2(2X, I3) )' ) B (i, :)
end do

stop
end program demo_user_generic

关于fortran - 如何为 'allocate' 编写包装器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2257248/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com