如何检查 Fortran real 是否与 C float 兼容?

How to check that fortran real is compatible with C float?

我正在使用 iso-c 绑定和 modules/interfaces 等桥接 Fortran 和 C 之间的一些遗留代码。

通常,当将一个 fortran 数组传递给 C 时,我只是将它复制到另一个正确的 iso-c 绑定类型的数组中。然而,一些代码要求我传递一个大的(多 GB)数组。在这种情况下复制它是不明智的。此外,由于它来自第 3 方代码,因此也不可能更改 fortran 数组的类型 real(c_float)

不过,如果底层的 Fortran 数组与基于 C 浮点数的 API 不兼容,我很乐意抛出异常或编译失败。

有没有办法在编译时(或运行时)检查默认 real 是否与 C floatdouble 兼容?

如果需要的话,我正在使用 intel fortran 和 C 编译器。

默认 REAL 的种类和与 C 中的 float 互操作的 REAL 的种类之间的比较只是一个简单的整数比较。

您可以使此比较触发编译错误或运行时错误。

USE, INTRINSIC :: ISO_C_BINDING, ONLY: C_FLOAT    

! -99 is never a valid kind - so this will fail at compile time 
! if the test condition is false.
REAL(MERGE(KIND(1.0), -99, C_FLOAT == KIND(1.0)) :: dummy

IF (C_FLOAT /= KIND(1.0))  &
    ERROR STOP 'Default REAL isn''t interoperable with FLOAT!!'

C_FLOAT 如果 Fortran 处理器没有与之互操作的 REAL 类型,则其本身可能具有负值。

(对于某些 15.0.x 版本的 ifort,以下可用于编译时检查变体:

USE, INTRINSIC :: ISO_C_BINDING, ONLY: C_FLOAT
INTEGER, PARAMETER :: dummy_rk = MERGE(C_FLOAT, -99, KIND(1.0) == C_FLOAT)
! -99 is never a valid kind - so this will fail at compile time 
! if the test condition is false.
REAL(dummy_rk) :: dummy

有几个问题。

  • C 的 float 作为 C 函数参数和表达式求值的 double 传递。这很容易通过将指针传递给包含定义为 float(实际上使用 32 位浮点数)的结构或数组来克服。

  • Intel 的 Fortran 有几种真正的风格:real*4real*8real*16。默认情况下(编译器设置可能会更改这些),real 是真实的*4,double precisionreal*8。参见 documentation.

  • C 的 long double 类型在 Intel Fortran 中没有对应的类型,如果它被实现,将是 real*10 - 它 用于 x86 上表达式的中间值。

  • 当然还有 C 与 Fortran 的主要列与次要列数组布局问题(对于多维数组)。

如果是我,我会通过创建一个测试将已知数据(1.0、2.0、3.0、4.0,...)从 C 传递到 Fortran,反之亦然,然后打印值,从而为开发开辟道路或者将它们与它们应该是的进行比较。如果使用非整数,请务必使用适当的 epsilon 比较:

           if (abs (c_val - fortran_val) > 0.00001)  error();