如何编写zcopy?Fortran假定类型/假定秩哑元实用操作探讨
Fortran 假定类型与秩相关问题解答
1. 应当如何编写zcopy?
要实现通用的zcopy(将实数数组元素对转为复数数组),需利用Fortran的**假定类型(type(*))和假定秩((..))**特性,配合类型选择分支处理具体类型的操作。示例实现如下:
subroutine zcopy(n, x, incx, y, incy) implicit none integer, intent(in) :: n, incx, incy type(*), intent(in) :: x(..) ! 假定类型、假定秩的输入实数数组 type(*), intent(out) :: y(..) ! 假定类型、假定秩的输出复数数组 ! 校验输入输出类型是否符合预期 select type(x) type is (real(kind(1.d0))) select type(y) type is (complex(kind(1.d0))) ! 校验数组元素数量匹配(考虑步长) if (size(x, kind=8) * incy /= size(y, kind=8) * incx * 2) then error stop "zcopy: 输入输出数组元素数不匹配" end if ! 执行拷贝:将输入的连续实数对赋值给复数的实部、虚部 y%re = x(1::2*incx) y%im = x(2::2*incx) class default error stop "zcopy: 输出数组必须是双精度复数类型" end select class default error stop "zcopy: 输入数组必须是双精度实数类型" end select end subroutine zcopy
这个实现会先检查输入输出的类型合法性,再根据步长完成实数到复数的映射拷贝,完全符合Fortran标准。
2. 若除rank操作外,其他操作均需知晓类型,Fortran能否对假定类型、假定秩哑元执行实用操作?
可以,但必须通过**select type类型选择分支**明确哑元的具体类型后,才能执行类型相关的实用操作。
假定类型(type(*))本身是“类型未知”的,编译器无法直接对其进行类型依赖的操作(比如赋值给特定类型变量、算术运算等)。但通过select type分支到具体类型后,在分支内部就可以像普通类型变量/数组一样操作:比如数组切片、元素赋值、调用类型特定的函数等。
如果不做类型选择,仅能执行少数不依赖类型的操作:比如用size()获取数组大小、rank()获取秩、transfer()进行二进制内存拷贝(需注意内存布局兼容性)。
3. 能否不调用C函数实现copy_something_to_complex?
完全可以,不需要依赖C函数,有两种简洁的Fortran实现方式:
方式一:直接在子例程内处理
跳过单独的zcopy,直接在copy_something_to_complex内部通过类型选择完成逻辑:
subroutine copy_something_to_complex(dim, wd, wz) implicit none integer, parameter :: dp = kind(1.d0) integer, intent(in) :: dim type(*), intent(in) :: wd(..) complex(dp), intent(out):: wz(..) ! 校验数组秩是否为一维 if (rank(wd)/=1 .or. rank(wz)/=1) then error stop "copy_something_to_complex: 仅支持一维数组" end if ! 校验数组长度匹配 if (size(wd) /= 2*dim .or. size(wz)/=dim) then error stop "copy_something_to_complex: 数组维度不匹配" end if select type(wd) type is (real(dp)) ! 直接将实数对转为复数 wz = cmplx(wd(1::2), wd(2::2), kind=dp) class default error stop "copy_something_to_complex: 输入数组必须是双精度实数类型" end select end subroutine copy_something_to_complex
方式二:调用自制的Fortran版zcopy
直接调用第一个问题中实现的zcopy子例程即可:
subroutine copy_something_to_complex(dim, wd, wz) implicit none integer, parameter :: dp = kind(1.d0) integer, intent(in) :: dim type(*), intent(in) :: wd(..) complex(dp), intent(out):: wz(..) call zcopy(dim, wd, 1, wz, 1) end subroutine copy_something_to_complex
内容的提问来源于stack exchange,提问作者yarchik
相关产品推荐
相关产品推荐

