In case someone is still looking for an answer, I find that the following works with gfortran -O3 -Ofast -ffast-math
(gfortran version 9.3.0):
is_nan = (.not. (x <= huge(x) .and. x >= -huge(x))) .and. (.not. abs(x) > huge(x))
Indeed, I have posted on GitHub some functions for checking Inf/NaN, which aim to work even when compilers are invoked with aggressive optimization flags, such as gfortran -Ofast
. Some simple tests are also included in the GitHub repository.
The ieee_is_nan
included in ieee_arithmetic
of gfortran 9.3.0 does not work with aggressive optimization flags like -Ofast
(although it is not surprising). In addition, some compilers (gfortran 9.3.0, ifort 21.0, and nagfor 7.0) are buggy concerning the return type of ieee_is_nan
when some special compilation options are imposed, as has been discussed here on Fortran Discourse.
For your convenience, I copy-paste the main code below. More details can be found on GitHub.
! consts.f90
module consts_mod
implicit none
private
public :: SP, DP
integer, parameter :: SP = kind(0.0)
integer, parameter :: DP = kind(0.0D0)
end module consts_mod
! infnan.f90
module infnan_mod
use consts_mod, only : SP, DP
implicit none
private
public :: is_nan, is_finite, is_inf, is_posinf, is_neginf
interface is_nan
module procedure is_nan_sp, is_nan_dp
end interface is_nan
interface is_finite
module procedure is_finite_sp, is_finite_dp
end interface is_finite
interface is_posinf
module procedure is_posinf_sp, is_posinf_dp
end interface is_posinf
interface is_neginf
module procedure is_neginf_sp, is_neginf_dp
end interface is_neginf
interface is_inf
module procedure is_inf_sp, is_inf_dp
end interface is_inf
contains
elemental pure function is_nan_sp(x) result(y)
implicit none
real(SP), intent(in) :: x
logical :: y
y = (.not. (x <= huge(x) .and. x >= -huge(x))) .and. (.not. abs(x) > huge(x))
end function is_nan_sp
elemental pure function is_nan_dp(x) result(y)
implicit none
real(DP), intent(in) :: x
logical :: y
y = (.not. (x <= huge(x) .and. x >= -huge(x))) .and. (.not. abs(x) > huge(x))
end function is_nan_dp
elemental pure function is_finite_sp(x) result(y)
implicit none
real(SP), intent(in) :: x
logical :: y
y = (x <= huge(x) .and. x >= -huge(x))
end function is_finite_sp
elemental pure function is_finite_dp(x) result(y)
implicit none
real(DP), intent(in) :: x
logical :: y
y = (x <= huge(x) .and. x >= -huge(x))
end function is_finite_dp
elemental pure function is_inf_sp(x) result(y)
implicit none
real(SP), intent(in) :: x
logical :: y
y = (abs(x) > huge(x))
end function is_inf_sp
elemental pure function is_inf_dp(x) result(y)
implicit none
real(DP), intent(in) :: x
logical :: y
y = (abs(x) > huge(x))
end function is_inf_dp
elemental pure function is_posinf_sp(x) result(y)
implicit none
real(SP), intent(in) :: x
logical :: y
y = (abs(x) > huge(x)) .and. (x > 0)
end function is_posinf_sp
elemental pure function is_posinf_dp(x) result(y)
implicit none
real(DP), intent(in) :: x
logical :: y
y = (abs(x) > huge(x)) .and. (x > 0)
end function is_posinf_dp
elemental pure function is_neginf_sp(x) result(y)
implicit none
real(SP), intent(in) :: x
logical :: y
y = (abs(x) > huge(x)) .and. (x < 0)
end function is_neginf_sp
elemental pure function is_neginf_dp(x) result(y)
implicit none
real(DP), intent(in) :: x
logical :: y
y = (abs(x) > huge(x)) .and. (x < 0)
end function is_neginf_dp
end module infnan_mod
fast-math
, you are promising the compiler that it can freely pretend that NaNs do not exist. This means that computations that would ordinarily produce NaN may not, and that the compiler can optimize away any code that checks for NaNs (since you promised that they don’t exist!), which makesisnan
essentially useless. Your question is the equivalent of speeding on a curvy mountain road at night wearing a blindfold, and worrying about your busted tail light. – Bree