我想用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中实现它?
不要费心发布依赖于IEEE规则的(x \= x)
或类似解决方案。它们给出与isnan()
相同的结果。我也知道-ffpe-trap=invalid,zero,overflow
,但不想停止该计划。如果它有帮助,我的操作系统是64位LinuxMint 14.如果在Fortran中不可能,防水C解决方案也会很好。
答案 0 :(得分:3)
首先我要指出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
的情况下进行编译。当心缺乏内联可能导致严重的性能下降。
答案 1 :(得分:1)
我在gfortran-4.7中遇到了同样的问题,并开始尝试一些表达式。对于我的测试用例,如果x是NaN,则返回true:
check = ((x*2d0==x).AND.(
(x<-epsilon(1.d0)).OR.
(x>+epsilon(1.d0))))
我只检查了双精度值和-O2 -ffast-math,-O3 -ffast-math选项。请注意,这会返回.false。如果不使用优化标志,则必须将其与
组合isnan(x) .OR. check