How to detect a NaN in list directed input in fortran

Viewed 473

I read real valued data from an input file with list directed input. What is the best way to detect a NaN via iostat=iostatus?

As an example for the input for a large program I need to read a file like:

1   NaN    1.0
2   nan    2.0

where there are occasionally "NaN"s instead of real valued numbers. with READ(ird, *, iostat=iostatus) nr, r1, r2 no iostatus is flagged for gfortran 7.4.0 on UBUNTU!

Apparently the input error is treated as a quiet NaN instead of a signalling NaN. The gfortran compiler options do not seem to provide an option to turn this into a signalling NaN. The fortran standard at https://j3-fortran.org/doc/year/18/18-007r1.pdf does not specify treatment of a Nan in list directed input.

In section 13.7.2.3.2 there is info for formatted input, and it specifically states that the Nan on input is treated as a quiet NaN.

I found a documentation on the NAG compiler and it states explicitely that a NaN on input is never flagged as a signalling NaN.

The philosophy behind these decisions in the standard beats me. I would have expected that this shoud be an error.

If the line is changed to:

read(ird, *, err=10, iostat=iostatus) nr, r1, r2
10 continue

the iostatus changes to +5001 ! But I do not really want to resort back to the ancient err= clause.

I am aware that I could read the line into a character string, analyze the string for the presence of any "NaN" and proceed. I could as in the example analyse ieee_is_nan(). That seems however unnecessarily tedious given the iostat= clause.

So is there a compiler option that I missed ?

PROGRAM main
USE ieee_arithmetic
IMPLICIT NONE
INTEGER, PARAMETER :: IRD = 12
INTEGER :: iostatus
REAL    :: r1 = -1.0, r2 = -1.0
INTEGER :: nr = 0
CHARACTER(LEN=1024) :: line = ' '

OPEN(UNIT=IRD,FILE='data.data', STATUS='old')

READ(IRD, *, IOSTAT=iostatus, IOMSG=line) nr, r1, r2
WRITE(*,*) iostatus, nr, r1, r2, ieee_is_nan(r1), line(1:LEN_TRIM(line))

r1 = -1.0
r2 = -1.0

READ(IRD, ERR=10, IOSTAT=iostatus, IOMSG=line) nr, r1, r2
10 CONTINUE
WRITE(*,*) iostatus, nr, r1, r2, ieee_is_nan(r1), line(1:LEN_TRIM(line))

CLOSE(UNIT=IRD)
END PROGRAM main

The output of my program is: (Shortened insignificant digits and blanks)

0  1              NaN   1.00 T 
5001  1  -1.00      -1.00 F
Missing format for FORMATTED data transfer

At the first read iostatus is set to 0, while on the second read its set to 5001!

0 Answers
Related