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

How to get around a NaN?

ferrad
New User
2,733 Views
I have successfully found where our code is trying to access a NaN, using full checking. However, now I know it is there I will fix it later, so what I want to do is move around it to find the next error. So I put in the following code:
if(isnan(tables_pl(i))) then
tables_mlf(i,nzone,temp_loc) = 0.0
else
tables_mlf(i,nzone,temp_loc) = tables_pl(i)
endif
However, I still get a floating point exception trying to access the NaN, but now on the if statement. Why can't the isnan test just return a .true., execute the next line and carry on to the next problem?
Adrian
0 Kudos
25 Replies
ferrad
New User
422 Views

Jim,

That works, thanks. From what I interpret of the fixNaN function, itwill catchall real numbers where the 1st (or is it last?) byte is FF. While that will catch all NaN's as per your previous definition, will it not catch other non-NaN's as well - ie. can a regular number not have an FF in this position?

Adrian

0 Kudos
ferrad
New User
422 Views

Jim,

Here's another NaNbut it failsyour fixNaN check (2141473776 - right most byte is 7F)

Adrian

0 Kudos
ferrad
New User
422 Views

Jim,

Well I guess I'm confused now: I found good reals (notNaN's) with both FF and 7F as the most significant byte. These are FF000000 (-1.7014118E+38) and 7F000000 (+1.7014118E+38).

The former would fail your fixNaN test, and the latter gives an example where you can't rely on 7F to give always a NaN either.

Adrian

0 Kudos
ferrad
New User
422 Views

Jim,

I got the answer through comp.lang.fortran. This works:

function fixNaN(i)
logical :: fixNaN
integer :: i
if((i .ge. Z'FF800001' .and. i .le. Z'FFFFFFFF') .or.
& (i .ge. Z'7F800001' .and. i .le. Z'7FFFFFFF')) then
fixNaN = .true.
else
fixNaN = .false.
endif
end function fixNaN

FYI, the standard is IEE 754, and the url is http://babbage.cs.qc.edu/courses/cs341/IEEE-754references.html

Adrian

0 Kudos
jim_dempsey
Beginner
422 Views

Here is a more complete function (not debugged)

Code:

! test for NaN on REAL*4 (referenced as INTEGER*4
function fixNaN(i)
    logical :: fixNaN
    integer(4) :: i
    integer :: SignBit, ExponentBits, FractionBits, MSBFractionBit
    logical :: isNegative
    logical :: isSNaN   ! Signaling NaN
    logical :: isQNan   ! Quite (non) Signaling NaN
    logical :: isPlusZero
    logical :: isPositiveDenormalizedeReal
    logical :: isPositiveNormalizedeReal
    logical :: isPlusInfinity
    logical :: isPositiveSNaN   ! Signaling NaN
    logical :: isPositiveQNan   ! Quite (non) Signaling NaN
    logical :: isNegativeZero
    logical :: isNegativeDenormalizedeReal
    logical :: isNegativeNormalizedeReal
    logical :: isNegativeInfinity
    logical :: isNegativeSNaN   ! Signaling NaN
    logical :: isNegativeQNan   ! Quite (non) Signaling NaN

    fixNaN = .false.    ! defaults are false
    isNegative = .false.
    isSNaN = .false.
    isQNaN = .false.
    isPlusZero = .false.
    isPositiveDenormalizedeReal = .false.
    isPositiveNormalizedeReal = .false.
    isPlusInfinity = .false.
    isPositiveSNaN = .false.
    isPositiveQNaV = .false.
    isNegativeZero = .false.
    isNegativeDenormalizedeReal = .false.
    isNegativeNormalizedeReal = .false.
    isNegativeInfinity = .false.
    isNegativeSNaN = .false.
    isNegativeQNaN = .false.
    ! Bitfields in i
    ! Z'80000000' - Sign bit
    ! Z'7F800000' - Exponent
    ! Z'007FFFFF' - Fraction
    ! Z'00400000' - MSB of Fraction
    SignBit = IAND(i,Z'80000000')
    ExponentBits = IAND(i,Z'7F800000')
    FractionBits = IAND(i,Z'007FFFFF')
    MSBFractionBit = IAND(i,Z'00400000')
    if(SignBit .eq. 0) then
        if(ExponentBits .eq. 0) then
            if(FractionBits .eq. 0) then
                isPlusZero = .true.
                return
            endif
            isPositiveDenormalizedeReal = .true.
            return
        endif
        ! ExponentBits .ne. 0
        if(ExponentBits .eq. Z'7F800000') then
            if(FractionBits .eq. 0) then
                isPlusInfinity = .true.
                return
            endif
            if(MSBFractionBit .eq. 0) then
                isPositiveSNaN = .true.
                isSNaN = .true.
                fixNaN = .true.
                return
            endif
            isPositiveQNaN = .true.
            isQNaN = .true.
            fixNaN = .true.
            return
        endif
        isPositiveNormalizedeReal =  = .true.
        return
    endif
    ! SignBit .ne. 0
    if(ExponentBits .eq. 0) then
        if(FractionBits .eq. 0) then
            isNegativeZero = .true.
            return
        endif
        isNegativeDenormalizedeReal = .true.
        return
    endif
    ! ExponentBits .ne. 0
    if(ExponentBits .eq. Z'7F800000') then
        if(FractionBits .eq. 0) then
            isNegativeInfinity = .true.
            return
        endif
        if(MSBFractionBit .eq. 0) then
            isNegativeSNaN = .true.
            isSNaN = .true.
            fixNaN = .true.
            return
        endif
        isNegativeQNaN = .true.
        isQNaN = .true.
        fixNaN = .true.
        return
    endif
    isNegativeNormalizedeReal =  = .true.
    return
end function fixNaN



0 Kudos
Reply