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

こ雲淡風輕ζ 提交于 2019-12-01 11:35:16

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.

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