Cannot use usual self-equivalency to identify nan in nvfortran

Viewed 103

In most fortran compilers, like gfortran, in order to identify little old nans, you would check by doing some sort of equivalency test, utilising the fact that nan is not self-equivalent. For example, if nanny=nan, then (nanny/=nanny) should output T. So, for the following code:

program test_nan
implicit none

real :: nanny,zero=0.0


nanny=zero/zero
print*,nanny

if (nanny/=nanny) then
    print*,"found by self-equivalency"
else
    print*,"not found by self-equivalency"
end if

if (nanny-1==nanny) then
    print*,"found by perpetual transigence"
else
    print*,"not found by perpetual transigence"
end if
    
if (nanny>1000000000000.0) then
    print*,"found by big number"
else
    print*,"not found by big number"
end if

end program

If I compile this in gfortran and run, I get:

              NaN
 found by self-equivalency
 not found by perpetual transigence
 not found by big number

But, doing the same with nvfortran gives:

             NaN
 not found by self-equivalency
 not found by perpetual transigence
 not found by big number

Is there a way in nvfortran that I can check for nans?

1 Answers

Since Fortran 2003 the standard way to test for NaNs is via the IEEE 754-1985 support provided by the language. An example is below. Note testing a variable for equality with itself is not a good idea as optimisers will often remove it - which may be what you are seeing above. Also dividing by zero produces implementation defined behaviour, so after that point anything can happens - the code below shows the standard way to produce a NaN.

ijb@ijb-Latitude-5410:~/work/stack$ cat nan.f90
program test_nan

  Use, Intrinsic :: ieee_arithmetic, Only : ieee_signaling_nan, &
       ieee_support_nan, ieee_value, ieee_is_nan

  implicit none

  real :: nanny

  If( .Not. ieee_support_nan( nanny ) ) Then
     Write( *, * ) 'Processor does not support NaNs'
     Stop
  End If

  nanny = ieee_value( nanny, ieee_signaling_nan )
  If( ieee_is_nan( nanny ) ) Then
     Write( *, * ) 'Nanny is a Nan'
  Else
     Write( *, * ) 'Nanny is NOT a Nan, she is ', nanny
  End If

  nanny = 3.0
  If( ieee_is_nan( nanny ) ) Then
     Write( *, * ) 'Nanny is a Nan'
  Else
     Write( *, * ) 'Nanny is NOT a Nan, she is ', nanny
  End If

end program test_nan
ijb@ijb-Latitude-5410:~/work/stack$ gfortran --version
GNU Fortran (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0
Copyright (C) 2019 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

ijb@ijb-Latitude-5410:~/work/stack$ gfortran -std=f2018 -Wall -Wextra -fcheck=all -O -Wuse-without-only nan.f90 -o nan
ijb@ijb-Latitude-5410:~/work/stack$ ./nan
 Nanny is a Nan
 Nanny is NOT a Nan, she is    3.00000000    
ijb@ijb-Latitude-5410:~/work/stack$ 
Related