Is it possible to make isnan() work in gfortran -O3 -ffast-math?

柔情痞子 提交于 2019-12-01 08:04:49

问题


I would like to compile a program with gfortran and -O3 -ffast-math enabled, since it gives a nice performance boost. I was rather confused, that gfortran's isnan() catched some NaN's but not all of them. After reading

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?

I am under the impression that people are able to check for NaN's in C via bit-fiddling even with fast-math enabled. However, this puzzles me since fast-math

can result in incorrect output for programs that depend on an exact implementation of IEEE or ISO rules/specifications for math functions.

According to the man page of gcc 4.7.2. So how do you know which bit to check, if the numbers are not represented according to IEEE standard? And if you know it, how would you implement it in Fortran 95/03/08?

Don't bother to post (x \= x) or simlar solutions which depend on IEEE rules. They give the same result as isnan(). I am also aware of -ffpe-trap=invalid,zero,overflow, but don't want to stop the program. If it helps, my OS is 64-bit LinuxMint 14. If it is not possible in Fortran, a waterproof C solution would also be nice.


回答1:


First I would point out that gfortran 4.9 supports the IEEE_arithmetic module. However, I cannot depend on gfortran 4.9, it is too fresh.

What I actually use in practice is to move the check x/=x to a procedure which is compiled without -ffast-math and without link time optimizations:

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

It is in a separate file, which is then compiled without -Ofast, --ffast-math and without -flto. Beware the lack of inlining can case serious performance decrease.




回答2:


I was facing the same problem in gfortran-4.7 and started to experiment with some expressions. For my Test Cases this one returned true if x is a NaN:

check = ((x*2d0==x).AND.(
         (x<-epsilon(1.d0)).OR.
         (x>+epsilon(1.d0))))

I've checked only double precision values and -O2 -ffast-math, -O3 -ffast-math options. Note that this returns .false. if using no optimization flags, thus you would have to combine it with

isnan(x) .OR. check


来源:https://stackoverflow.com/questions/15944614/is-it-possible-to-make-isnan-work-in-gfortran-o3-ffast-math

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!