如果有人仍在寻找答案,我发现以下适用于gfortran -O3 -Ofast -ffast-math
(gfortran 版本 9.3.0):
is_nan = (.not. (x <= huge(x) .and. x >= -huge(x))) .and. (.not. abs(x) > huge(x))
事实上,我在GitHub 上发布了一些检查 Inf/NaN 的函数,这些函数旨在即使在使用激进的优化标志调用编译器时也能正常工作,例如gfortran -Ofast
. GitHub 存储库中还包含一些简单的测试。
gfortran 9.3.0中ieee_is_nan
包含ieee_arithmetic
的内容不适用于激进的优化标志-Ofast
(尽管这并不奇怪)。此外,一些编译器(gfortran 9.3.0、ifort 21.0 和 nagfor 7.0)在强制执行某些特殊编译选项时的返回类型存在错误,正如Fortran Discourseieee_is_nan
上所讨论的。
为了您的方便,我复制粘贴下面的主要代码。更多细节可以在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