是否可以使 isnan() 在 gfortran -O3 -ffast-math 中工作?

bij*_*ncn 5 optimization fortran nan gfortran ieee-754

我想用 gfortran 编译一个程序并-O3 -ffast-math启用它,因为它可以提供很好的性能提升。我很困惑,gfortranisnan()捕获了一些 NaN,但不是全部。看完之后

检查 C++ 中的 double(或 float)是否为 NaN
如何制作可移植的 isnan/isinf 函数
负 NaN 不是 NaN?

我的印象是,即使启用了快速数学,人们也可以通过位调整来检查 C 中的 NaN。然而,这让我感到困惑,因为快速数学

可能会导致依赖于数学函数的 IEEE 或 ISO 规则/规范的精确实现的程序输出不正确。

根据 gcc 4.7.2 的手册页。那么,如果数字没有按照 IEEE 标准表示,您如何知道要检查哪一位呢?如果您知道它,您将如何在 Fortran 95/03/08 中实现它?

不要费心发布(x \= x)依赖于 IEEE 规则的类似解决方案。他们给出的结果与 相同isnan()。我也知道-ffpe-trap=invalid,zero,overflow,但不想停止该程序。如果有帮助的话,我的操作系统是 64 位 LinuxMint 14。如果 Fortran 中不可能,防水的 C 解决方案也很好。

Vla*_*r F 3

首先我要指出的是,gfortran 4.9 支持 IEEE_arithmetic 模块。然而,该模块中的过程中的检查可以被优化掉并且应用相同的逻辑。

然而,我不能依赖2014年的GCC 4.9,它太新鲜了。我使用了以下内容。

当我不得不使用时,x/=x我将检查x/=x移至一个在没有链接时间优化的情况下编译的过程-ffast-math

module my_is_nan_mod
  !poor man's replacement for the intrinsic module
  !do not use if the compiler supports the F2003 version
  !make sure not to use fast math optimizations when compiling
  use iso_fortran_env
  
  !the common extension isnan() may actually fail with fast math optimizations

  
  interface my_is_nan
    module procedure my_is_nan_real32
    module procedure my_is_nan_real64
  end interface

contains
  logical function my_is_nan_real32(x) result(res)
    real(real32), intent(in) :: x

    res = x /= x
  end function

  logical elemental function my_is_nan_real64(x) result(res)
    real(real64), intent(in) :: x

    res = x /= x
  end function

end module
Run Code Online (Sandbox Code Playgroud)

它位于一个单独的文件中,然后在不带-Ofast--ffast-math不带-flto. 请注意,缺少内联可能会导致性能严重下降。

-ffast-math编译器看到后x/=x,决定它不可能为真,并将表达式优化为.false.