我想编译一个启用了gfortran和-O3 -ffast-math
的程序,因为它可以大大提高性能。我很困惑,gfortran的isnan()
捕获了一些NaN,但不是全部。看完之后
Checking if a double (or float) is NaN in C++
how do I make a portable isnan/isinf function
Negative NaN is not a NaN?
我给人的印象是,即使启用了快速数学功能,人们也可以通过位错检查C中的NaN。但是,这让我感到迷惑
可能会导致依赖于的确切实现的程序的输出不正确
数学函数的IEEE或ISO规则/规范。
根据gcc 4.7.2的手册页。那么,如果没有按照IEEE标准表示数字,您怎么知道要检查哪一位呢?如果知道的话,您将如何在Fortran 95/03/08中实现它?
不要费心发布(x \= x)
或类似的解决方案,这些解决方案取决于IEEE规则。它们给出与isnan()
相同的结果。我也知道-ffpe-trap=invalid,zero,overflow
,但是不想停止该程序。如果有帮助,我的操作系统是64位LinuxMint14。如果在Fortran中无法实现,那么防水C解决方案也不错。
最佳答案
首先,我要指出的是,gfortran 4.9支持IEEE_arithmetic模块。但是,我不能依靠gfortran 4.9,它太新了。
我实际上在实践中使用的是将检查x/=x
移至没有-ffast-math
并且没有链接时间优化的情况下编译的过程:
module ieee_arithmetic
!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
use iso_fortran_env
!common extension isnan may actually fail with optimizations above
! intrinsic isnan
interface ieee_is_nan
module procedure ieee_is_nan_real32
module procedure ieee_is_nan_real64
end interface
contains
logical function ieee_is_nan_real32(x) result(res)
real(real32), intent(in) :: x
res = x /= x
end function
logical elemental function ieee_is_nan_real64(x) result(res)
real(real64), intent(in) :: x
res = x /= x
end function
end module
它在单独的文件中,然后在不使用
-Ofast
,--ffast-math
和-flto
的情况下进行编译。当心缺少内联会严重降低性能。关于optimization - 是否可以在gfortran -O3 -ffast-math中使isnan()工作?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/15944614/