【问题标题】:Determining variable type in Fortran在 Fortran 中确定变量类型
【发布时间】:2010-04-01 12:13:13
【问题描述】:

在 Fortran 中,有没有办法确定变量的类型?

需要变量类型的可能用例如下。我们将变量的类型作为参数传递给函数,以便能够使用该函数调用特定于类型的代码,从而无需为每种数据类型使用单独的类似函数。

【问题讨论】:

  • 什么年份的 fortran? 77? 9倍? 200 倍?

标签: variables types fortran


【解决方案1】:

如果你弄乱了 KIND 内在函数和指针,你也许可以做你想做的事,但如果你只关心函数和子例程的签名,那就把它留给 Fortran。如果你定义

function calc8(arg1)
    real(8), intent(in) :: arg1
    ...

function calc4(arg1)
    real(4), intent(in) :: arg1
    ...

在一个模块中,并声明一个这样的接口

interface calc
    module procedure calc8
    module procedure calc4
end interface

(警告,我没有仔细检查语法,这是你的责任。)

然后 Fortran 会将调用匹配到正确版本的函数。当然,您必须编写函数的两个版本,但这确实是 Fortran 95 的做法。这可能很乏味,我倾向于编写一个通用版本并运行一个 sed 脚本来专门化它。这有点杂乱无章,但确实有效。

如果函数的代码除了参数的种类之外是相同的,我有时会为 real(8)(或其他)编写函数并为 real(4) 编写一个版本,它调用 real(8) 版本的包装在类型转换中。

在 Fortran 2003 中,改进了定义多态和泛型函数的方法,但我还没有真正了解它们。

【讨论】:

  • 那太复杂了。原始问题不需要继承或附加功能。
【解决方案2】:

是的,有两种方法。

第一种方法确实需要您为每种变量类型编写单独的函数或子例程,但您不必调用不同的函数。这可能与您想要的足够接近,也可能不够接近。您编写单独的例程,然后编写一个接口来创建一个通用函数或包装这些特定子例程的子例程。您不必传递变量类型,或者在调用中做任何特殊的事情——这一切都是通过声明完成的,并且由编译器自动从变量本身完成,只要变量足够不同,编译器可以区分他们(有关于需要什么的规则)。这类似于内部函数的工作方式——您可以使用实参数、双精度实参数或复数参数调用 sin,编译器会调用正确的实际函数并返回匹配的结果。 High Performance Mark 沿着这些思路提出了一个解决方案。对于另一个问题,我发布了一个工作示例,其中变量的显着特征是数组等级:how to write wrapper for 'allocate'。这种方法的一个优点是它得到了 Fortran 编译器的广泛支持。

在 Fortran 2003/2008 中,有很多面向对象的特性。引用 Metcalf、Reid 和 Cohen 的“Fortran 95/2003 解释”,“要根据多态实体的动态类型执行替代代码并访问动态部分,select type 构造是假如。” select type 语句有点类似于 select case 语句。这是由更少的编译器支持的。同样,您不必传递类型,因为编译器可以根据变量本身来计算它。但它必须是多态类型......英特尔 ifort 和 gfortran 都列出了支持的类型和多态数据类型——后者在 gfortran 中具有一些实验性方面 (http://gcc.gnu.org/wiki/Fortran2003)。这些是这些编译器的最新添加。

【讨论】:

【解决方案3】:

这是一段代码,它决定了事物的类型。该操作很简单,但您应该能够将其扩展到您的用例。

module element_to_datatype
    use iso_fortran_env
    use mpi_f08
    implicit none

    contains

        function get_element_datatype(element) result(datatype)
            class(*), intent(in) :: element
            type(MPI_Datatype) :: datatype
            select type(element)
                ! REAL types
                type is ( real(kind=REAL32) )
                    datatype = MPI_REAL4
                type is ( real(kind=REAL64) )
                    datatype = MPI_REAL8
                ! COMPLEX types
                type is ( complex(kind=REAL32) )
                    datatype = MPI_COMPLEX8
                type is ( complex(kind=REAL64) )
                    datatype = MPI_COMPLEX16
                ! INTEGER types
                type is ( integer(kind=INT8) )
                    datatype = MPI_INTEGER1
                type is ( integer(kind=INT16) )
                    datatype = MPI_INTEGER2
                type is ( integer(kind=INT32) )
                    datatype = MPI_INTEGER4
                type is ( integer(kind=INT64) )
                    datatype = MPI_INTEGER8
                ! OTHER types
                type is ( logical )
                    datatype = MPI_LOGICAL
            end select
        end function

end module element_to_datatype

之前的答案显示了如何使用接口执行此操作,因此我不会重复。

【讨论】:

  • 请注意,之前在其他答案中已经提到过。但没有代码示例。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-02-29
  • 2011-02-08
  • 2021-03-04
  • 2012-08-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多