【发布时间】:2020-01-07 14:50:16
【问题描述】:
我有一个接受两个数字的函数,我不在乎它们是整数、实数还是 32 位或 64 位。对于下面的例子,我只是把它写成一个简单的乘法。在 Fortran 90 中,您可以使用接口块来执行此操作,但如果您想涵盖将两个数字相乘的所有可能交互,则必须编写 16 个(!)函数,每个数字可以是 int32、int64、real32 或真正的64。
在 Fortran 2003 中,您还有一些其他选项,例如用于多态性的 class(*),我找到了一种方法,只需在相乘之前将所有输入转换为实数:
! compiled on linux with gfortran 4.8.5
program main
integer, target :: i = 2
real(4), target :: x = 2.0
real(8), target :: y = 2.0
character, target :: c = 'a'
print *, multiply(i,x)
print *, multiply(x,i)
print *, multiply(i,i)
print *, multiply(y,y)
print *, multiply(c,c)
contains
function multiply(p,q)
real :: multiply
class(*) :: p, q
real :: r, s
r = 0.0 ; s = 0.0
select type(p)
type is (integer(4)) ; r = p
type is (integer(8)) ; r = p
type is (real(4)) ; r = p
type is (real(8)) ; r = p
class default ; print *, "p is not a real or int"
end select
select type(q)
type is (integer(4)) ; s = q
type is (integer(8)) ; s = q
type is (real(4)) ; s = q
type is (real(8)) ; s = q
class default ; print *, "q is not a real or int"
end select
multiply = r * s
end function multiply
end program main
这似乎是一种改进。至少这里的代码量在类型数量上是线性的而不是二次的,但我想知道是否还有更好的方法来做到这一点?如您所见,我仍然需要编写两次select type 代码,将“r”更改为“s”,将“p”更改为“q”。
我尝试将选择类型块转换为函数,但无法使其工作。但我对任何可以进一步改进的替代方案感兴趣。看起来这将是一个常见问题,但到目前为止我还没有找到任何比这更好的通用方法。
编辑添加:显然有计划改进 Fortran w.r.t.正如@SteveLionel 的评论中所指出的那样,将来会出现这个问题。 @roygvib 进一步提供了一个特定提案的链接,该提案也很好地解释了这个问题:https://j3-fortran.org/doc/year/13/13-236.txt
【问题讨论】:
-
如果您使用
use iso_fortran_env,您可以使用type is (real(4))和type is (real(8))或real32和real64而不是4和8。 -
@AboAmmar 谢谢!我已更新问题以反映此建议。
-
这是一种可以通过泛型编程解决的问题。 Fortran 标准没有很好的特性,但是委员会已经开始开发这样的工作,以便将来对该标准进行修订。
-
@SteveLionel 谢谢,我很期待!
标签: fortran fortran2003