Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

FINDLOC equivalent for NAN

ereisch
New Contributor II
4,062 Views

Is there a FINDLOC() equivalent that can be used for IEEE NAN values?  It is my understanding I cannot use FINDLOC with IEEE_VALUE( 1,0, IEEE_QUIET_NAN ), because the IEEE NAN values (signaling or quiet) don't equal anything, "including itself".

I can obviously just put in a DO loop across the array and check for IEEE_IS_NAN, but I'm assuming (possibly erroneously?) that FINDLOC() has a more efficient implementation under the hood.

0 Kudos
32 Replies
Arjen_Markus
Honored Contributor I
1,167 Views

I do not think there is a standard feature for achieving an initialisation to NaN within the source code. Instead you will have to rely on the compiler offering options for this. Both gfortran and Intel Fortran have such options, as I am sure, have others.

I experimented with the IEEE function ieee_value, but you cannot use that in initialisation expressions. Oddly enough, the program I used for this experimentation causes an ICE in Intel Fortran 2018 and in oneAPI Intel Fortran:

program init_nan
    use, intrinsic :: ieee_arithmetic

    real, parameter :: qnan = ieee_value(x,ieee_quiet_nan) !<== Here the ICE happens

    type mytype
        real :: x = qnan !ieee_value(x,ieee_quiet_nan)
    end type

    type(mytype) :: y

    !y%x = ieee_value(x,ieee_quiet_nan)
    write(*,*) y
end program init_nan

 

0 Kudos
JohnNichols
Valued Contributor III
1,153 Views

In @Arjen_Markus did you need to declare the X for creating the IEEE number

This works 

 program Console11
    use Base
    use, intrinsic :: ieee_arithmetic

    

    implicit none
    
    real X1
    logical yes
    real(kind=dp) qnan 
    real(kind=dp) T
    TYPE, BIND(C) :: FOO_PACKET
      REAL(KIND=dp) :: X 
      REAL(KIND=dp) :: Y 
      real(KIND=dp) :: Z  
      END TYPE
    integer i
    
    Type(FOO_PACKET) :: P1
    
     DATA i/Z'FFFFFFFF'/ 
    
    qnan = IEEE_VALUE(T,ieee_quiet_nan) !<== Here the ICE happens
    P1%Z = qnan
    yes = .false.
    X1 = 1.0
    ! Variables
    ! Body of Console11
    print *, 'Hello World'
    yes = ISNAN(X1)
    print *,yes
    yes = ISNAN(P1%X)
    print *,yes
    yes = ISNAN(P1%Z)
    print *,yes
    end program Console11

 

But in the end you could do the same thing with a Logical variable in the type and set it equal to false on creation and positive once valued.  its just a semaphore flag.  

0 Kudos
Arjen_Markus
Honored Contributor I
1,146 Views

Oh, dear, I forgot the "x" argument indeed. But apparently, you cannot use the standard function ieee_value in initialisation expressions (this is a complicated area :)). And the function isnan is not part of the standard.

0 Kudos
JohnNichols
Valued Contributor III
1,135 Views

Observation:

You would not be a regular writer on this board if you did not push the Fortran boundaries.

We are the Federales, do we care about stinking standards

 

0 Kudos
JohnNichols
Valued Contributor III
1,132 Views

initialize with ieee -- I tried a lot of combinations IFORT does not allow it that I could find. 

 

0 Kudos
Steve_Lionel
Honored Contributor III
1,118 Views

I too had thought that one could use IEEE_VALUE in a constant expression, but no - only "Transformational" intrinsics from IEEE_ARITHMETIC and IEEE_EXCEPTIONS can be used, and that limits you to IEEE_SELECTED_REAL_KIND. (I don't pretend to be an expert on the IEEE modules.)

0 Kudos
Arjen_Markus
Honored Contributor I
1,106 Views

Indeed, gfortran complains about this as well.

By the way, Intel Fortran 2018 and oneAPI give a strange message about a variant of the program I posted before:

init_nan.f90(14): error #6959: The array constructor must be a constant.   [IEEE_VALUE]
        real :: x = ieee_value(x,ieee_quiet_nan)
--------------------^
compilation aborted for init_nan.f90 (code 1)

 

The program in question:

program init_nan
    use, intrinsic :: ieee_arithmetic
    type mytype
        real :: x = ieee_value(x,ieee_quiet_nan)
    end type

    type(mytype) :: y

    write(*,*) y
end program init_nan
0 Kudos
jimdempseyatthecove
Honored Contributor III
1,084 Views

A work around:

    
subroutine init_nan
!>> use, intrinsic :: ieee_arithmetic
    real, parameter :: IEEE754_SP_QNAN = Z'7FFFFFFF'
    real(8), parameter :: IEEE754_DP_QNAN = Z'7FFFFFFFFFFFFFFF'

!>> real, parameter :: qnan = ieee_value(x,ieee_quiet_nan) !<== Here the ICE happens
    real, parameter :: qnan = IEEE754_SP_QNAN

    type mytype
        real :: x = qnan !ieee_value(x,ieee_quiet_nan)
    end type

    type(mytype) :: y

    !y%x = ieee_value(x,ieee_quiet_nan)
    write(*,*) y
end subroutine init_nan    

Jim Dempsey

0 Kudos
JohnNichols
Valued Contributor III
1,073 Views

 

!  Console11.f90 
!
!  FUNCTIONS:
!  Console11 - Entry point of console application.
!

!****************************************************************************
!
!  PROGRAM: Console11
!
!  PURPOSE:  Entry point for the console application.
!
!****************************************************************************

    program Console11
    use Base
    use, intrinsic :: ieee_arithmetic

    

    implicit none
    
    real X1
    logical yes
    real(kind=dp) qnan 
    real(kind=dp) T
    TYPE, BIND(C) :: FOO_PACKET
      REAL(KIND=dp) :: X 
      REAL(KIND=dp) :: Y 
      real(KIND=dp) :: Z  
      END TYPE
    integer i
    
    Type(FOO_PACKET) :: P1
    
     DATA i/Z'FFFFFFFF'/ 
    
    qnan = IEEE_VALUE(T,ieee_quiet_nan) !<== Here the ICE happens
    P1%Z = qnan
    yes = .false.
    X1 = 1.0
    ! Variables
    ! Body of Console11
    print *, 'Hello World'
    yes = ISNAN(X1)
    print *,yes
    yes = ISNAN(P1%X)
    print *,yes
    yes = ISNAN(P1%Z)
    print *,yes
    call init_nan()
    
    end program Console11

subroutine init_nan
!>> use, intrinsic :: ieee_arithmetic
    real, parameter :: IEEE754_SP_QNAN = Z'7FFFFFFF'
    real(8), parameter :: IEEE754_DP_QNAN = Z'7FFFFFFFFFFFFFFF'

!>> real, parameter :: qnan = ieee_value(x,ieee_quiet_nan) !<== Here the ICE happens
    real, parameter :: qnan = IEEE754_SP_QNAN

    
    type mytype
        real :: x = qnan !ieee_value(x,ieee_quiet_nan)
    end type
    
    type(mytype) :: y
    write(*,*)qnan
    print *, 'Hello World'

    !y%x = ieee_value(x,ieee_quiet_nan)
    write(*,*) y
end subroutine init_nan    

 

 

In Visual Studio on the autos and locals one cannot see a value for qnan -- I had never noticed that parameters do not show up - interesting, 

Observation:

Opera does not color code the Fortran on these posts, whereas IE makes it look like Visual Studio 

IE -- the program that has a few features that make it worth keeping around - often like an oft loved board.

0 Kudos
andrew_4619
Honored Contributor II
1,052 Views

John there  is an compiler option you need to set to show debug parameters

0 Kudos
JohnNichols
Valued Contributor III
1,032 Views

Philosophically,  and irrespective of the language after all this is just an intermediate translation into Machine Language and Backus was really with Fortran taking the first steps to what ultimately must be the universal compiler, BNF style. 

The use of a NAN is just a logical flag in this context for this problem and a defined types with a logical flag recording set of the variables would be cleaner and simpler to understand for future readers of the program.  

@jimdempseyatthecove  solution requires that the nan is dependent on the architecture whether 32 or 64 bits, what happens at 128 bits.  If we can think about it humans will invent it. 

The recent code that some one wanted to get working on this site, had program defining dependencies scattered all over the program.  This is ok for a single developer with a good memory, but it is poor real practice. 

that is what I like about this site.  Great people, interesting conversation and high controversy over simple topics.  

Although whoever invented counting arrays from 0 has a special place in the seventh level of Dante's world.  

0 Kudos
jimdempseyatthecove
Honored Contributor III
1,027 Views

>>...solution requires that the nan is dependent on the architecture whether 32 or 64 bits, what happens at 128 bits.  

The IEEE 754 standard specifies a binary128 as having:

The IEEE 754 standard specifies a binary16 as having the following format:

ergo

real(16), parameter :: IEEE754_QP_QNAN = Z'7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF'
! and if and when half precision supported...
real(2), parameter :: IEEE754_HP_QNAN = Z'7FFF'

Jim Dempsey

0 Kudos
Reply