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
1,246 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
jim_dempsey
Beginner
1,094 Views

I use the following code. Please adapt to your requirements

JFP_CLASS = FP_CLASS(FPLEN(JTETH1))
SELECT CASE (JFP_CLASS)
CASE (0)
call DOSTOP('TOSSF21 FOR_K_FP_SNAN')
CASE(1)
call DOSTOP('TOSSF21 FOR_K_FP_QNAN')
CASE(2)
call DOSTOP('TOSSF21 FOR_K_FP_POS_INF')
CASE(3)
call DOSTOP('TOSSF21 FOR_K_FP_NEG_INF')
CASE(4)
! OK - FOR_K_FP_POS_NORM
CASE(5)
! OK - FOR_K_FP_NEG_NORM
CASE(6)
call DOSTOP('TOSSF21 FOR_K_FP_POS_DENORM')
CASE(7)
call DOSTOP('TOSSF21 FOR_K_FP_NEG_DENORM')
CASE(8)
! OK - FOR_K_FP_POS_ZERO
CASE(9)
! OK - FOR_K_FP_NEG_ZERO ? Saw this with 0. * 9.900990099009901E-003
! ? could have been -0. * 9.900990099009901E-003
CASE DEFAULT
call DOSTOP('TOSSF21 FOR_K_FP_unknown')
END SELECT

The subroutine DOSTOP is a routine I call in lieu of performing a STOP (which is too hard to perform tracebacks). When debugging I keep a breakpoint in the suvroutine DOSTOP and it makes for an easy bug detection.

! common routine to perform CALL DOSTOP()
SUBROUTINE DOSTOP(CVAR)

CHARACTER*(*) CVAR

! place break point here
WRITE(IOUERR,*) CVAR
STOP 'DOSTOP'
! If you wish to continue use debugger to...
! Set Next Statement here
RETURN
END SUBROUTINE DOSTOP

Jim Dempsey

0 Kudos
ferrad
New User
1,094 Views

Not sure when I would call this stuff. If I call it before my isnan test, I have no exception. If I call it after, the exception has already occurred.

What I really need is for the code to go on past this NaN exception. I thought that's what isnan() would do - Steve am I right?

Adrian

0 Kudos
Intel_C_Intel
Employee
1,094 Views

Hello

You couldtake out this code (with NaN) and compile it in a separate file without any runtime checking, that is, typically full optimization and the /nocheck option. The rest of you files are with full error checking /check:all and all the other useful traps that have been added recently (read documentation).

Lars Petter

0 Kudos
ferrad
New User
1,094 Views
Yes, I can do that, but it would be better if isnan() worked.
Adrian
0 Kudos
jim_dempsey
Beginner
1,094 Views

>>

Not sure when I would call this stuff. If I call it before my isnan test, I have no exception. If I call it after, the exception has already occurred.

<<

You call this in place of isnan(YourVariableHere) with breakpoints inserted accordingly.

This can be used to catch both types of NaN as well as other odd values.

It is up to you to determine the appropriate action to take. You can make a function call out of this if you have many such places to test.

Cleaned up code follows

JFP_CLASS = FP_CLASS(YourVariableHere)
SELECT CASE (JFP_CLASS)
CASE(0) ! FOR_K_FP_SNAN
YourVariableHere = 0
CASE(1) ! FOR_K_FP_QNAN
YourVariableHere = 0
CASE(2) ! FOR_K_FP_POS_INF
! do nothing
CASE(3) ! FOR_K_FP_NEG_INF
! do nothing
CASE(4) ! FOR_K_FP_POS_NORM
! do nothing
CASE(5) ! FOR_K_FP_NEG_NORM
! do nothing
CASE(6) ! FOR_K_FP_POS_DENORM
YourVariableHere = YourVariableHere ! try to normalize
CASE(7) ! FOR_K_FP_NEG_DENORM
YourVariableHere = YourVariableHere ! try to normalize
CASE(8) ! FOR_K_FP_POS_ZERO
! do nothing
CASE(9) ! FOR_K_FP_NEG_ZERO
YourVariableHere = 0
CASE DEFAULT
call DOSTOP('FOR_K_FP_unknown')
END SELECT


Jim Dempsey

0 Kudos
ferrad
New User
1,094 Views

I just tried that, but it still stops in the external routine with an exception on the line:

if(isnan(tables_pl(i))) then

The external routine is compiled with:

ifort /nologo /c /iface:cvf /Zi /nocheck /dbglibs /Tfmlf_restart_dynamic1.for /define:INTEL9 /Qsave /Fomlf_restart_dynamic1.obj /fpconstant /real_size:64 /Zi /4R8 /nocheck /extend-source:132 /debug-parameters:all

Adrian

0 Kudos
ferrad
New User
1,094 Views

Nope that still fails on the line:

JFP_CLASS =

FP_CLASS(tables_pl(i))

when tables_pl(i) is a NaN
Same external routine is above, same compiler switches.
0 Kudos
ferrad
New User
1,094 Views

Jim,

Interesting observation: I have breakpoints set for cases 1 and 2 above. It stops for some NaN's in the correct place (case 1) and sets the value to zero, but for others it stops with the exception on the JFP_CLASS = FPCLASS(... line.

All NaN's have different bit patterns.

Adrian

0 Kudos
Steven_L_Intel1
Employee
1,094 Views
Neither ISNAN nor FP_CLASS should trigger an error when a NaN is accessed. If you have an example where it does, please submit a test case to Intel Premier Support.
0 Kudos
jim_dempsey
Beginner
1,094 Views

It may be that you have an invalid address (as opposed to the contents at the address is NaN).

Your test was for an element of an array.

Check:

1) see that the array was allocated (or pointer valid)

2) if the array name is passed into a subroutine (which is where the failure is) make sure the dummy argument is indeed the address of thearray you assume it is.

3) verify the index is valid.

4) verify the array type is indeed what you expect it to be (e.g. the subroutine where the failure is encountered expects REAL(8) but the caller is passing in REAL(4), or INTEGER(4), ...)

5) check the other unusual JFP_CLASS case statements

Jim

0 Kudos
ferrad
New User
1,094 Views

> 1) see that the array was allocated (or pointer valid)

It is an array in a common block, and I can see its contents without any problemin the watch window.

> 2) if the array name is passed into a subroutine (which is where the failure is) make sure the dummy argument is indeed the address of thearray you assume it is.

n/a (common block var)

> 3) verify the index is valid.

index is 69019 (array is sized larger than that).

> 4) verify the array type is indeed what you expect it to be (e.g. the subroutine where the failure is encountered expects REAL(8) but the caller is passing in REAL(4), or INTEGER(4), ...)

It's a real*4 array.

> 5) check the other unusual JFP_CLASS case statements

The code works fine for the previous 69018 values of i.

See attached screen capture,

Adrian

0 Kudos
ferrad
New User
1,094 Views

Steve, I'm trying to reproduce this in a standalone program. I need to write out the bit patterns for these reals into some file, then read them in again into my standalone program. What format do I use write and read these bit patterns?

Adrian

0 Kudos
ferrad
New User
1,094 Views

Steve,

Never mind, I've reproduced it. I'll submit to Premier Support now.

Adrian

0 Kudos
jim_dempsey
Beginner
1,094 Views
Is this a multi-threaded program?
Also, when you get the NaN set the display to Hex. This will help to determine if there is a bug in FP_CLASS. IEEE definition of NaN
Not A Number

The value NaN (Not a Number) is used to represent a value that does not represent a real number. NaN's are represented by a bit pattern with an exponent of all 1s and a non-zero fraction. There are two categories of NaN: QNaN (Quiet NaN) and SNaN (Signalling NaN).

A QNaN is a NaN with the most significant fraction bit set. QNaN's propagate freely through most arithmetic operations. These values pop out of an operation when the result is not mathematically defined.

An SNaN is a NaN with the most significant fraction bit clear. It is used to signal an exception when used in operations. SNaN's can be handy to assign to uninitialized variables to trap premature usage.

Semantically, QNaN's denote indeterminate operations, while SNaN's denote invalid operations.

Jim Dempsey

0 Kudos
ferrad
New User
1,094 Views

No, just a regular single threaded app. I have reproduced it on a small program and submitted it to premier support.

Adrian

FYI, the NaN causing this type of problem is:

data i1 /4287075194/
real*4 r1
equivalence (r1,i1)

if you're interested, I can send you the example.

0 Kudos
jim_dempsey
Beginner
1,094 Views

Thanks for the statements. On my system the isnan test works as it should. See .JPG

Jim Dempsey

0 Kudos
ferrad
New User
1,094 Views

You have to compile the file with /Od /fpe:0 to see the problem - Premier support have reproduced it and are fixing it.

Adrian

0 Kudos
jim_dempsey
Beginner
1,094 Views

First example (prior .JPG) had Floating-Point Exception Handling set to:

Produce NaN, signed infinities, and denormal results

This .JPG has Floating-Point Exception Handling set to:

Underflow gives 0.0; Abort on other IEE exceptions

Jim Dempsey

0 Kudos
ferrad
New User
1,094 Views
If you change the first access of the NaN to an FP_CLASS statement and compile with /Od /fpe:0, you will get the error I mention. Here is my code:
program nantest
implicit none
integer*4 i1
integer JFP_CLASS
data i1 /4287075194/
real*4 r1
equivalence (r1,i1)
JFP_CLASS = FP_CLASS(r1)
end

Adrian
0 Kudos
jim_dempsey
Beginner
977 Views

Adrian,

Here is a work around. Note the isnan works when exceptions enabled.

Jim Dempsey
0 Kudos
Reply