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
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