Невозможно использовать обычную самоэквивалентность для идентификации nan в nvfortran

#fortran #nan #nvidia

Вопрос:

В большинстве компиляторов fortran, таких как gfortran, чтобы идентифицировать маленькие старые nan, вы бы проверили, выполнив какой-то тест на эквивалентность, используя тот факт, что nan не является самоэквивалентным. Например, если nanny=nan , то (nanny/=nanny) следует выводить T . Итак, для следующего кода:

 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
 

Если я скомпилирую это в gfortran и запущу, я получу:

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

Но, делая то же самое с nvfortran, вы получаете:

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

Есть ли в nvfortran способ, которым я могу проверить наличие nans?

Ответ №1:

Начиная с Fortran 2003 стандартным способом тестирования NaNs является поддержка IEEE 754-1985, предоставляемая языком. Пример приведен ниже. Примечание.Тестирование переменной на равенство с самой собой не является хорошей идеей, так как оптимизаторы часто удаляют ее, что может быть тем, что вы видите выше. Также деление на ноль приводит к определенному поведению реализации, поэтому после этого момента может произойти все, что угодно — приведенный ниже код показывает стандартный способ получения NaN.

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

  Use, Intrinsic :: ieee_arithmetic, Only : ieee_signaling_nan, amp;
       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$ 
 

Комментарии:

1. Просто отмечу, что это работает с:GNU Fortran (GCC) 10.2.0 и с:nvfortran 21.1-0 64-разрядный LLVM. Спасибо, Йен.