[comp.lang.fortran] detecting Nan's

JBS@IBM.COM (01/11/91)

>      if(dnum*0d0 .ne. 0d0) write(*,1)
>1     format(' The variable dnum is equal to NAN!')

       Is this correct?  Suppose dnum is Inf.
                          James B. Shearer

khb@chiba.Eng.Sun.COM (Keith Bierman fpgroup) (01/11/91)

In article <9101110259.AA28451@ucbvax.Berkeley.EDU> JBS@IBM.COM writes:

   Newsgroups: comp.lang.fortran
   Date: 11 Jan 91 02:56:52 GMT
   Sender: daemon@ucbvax.BERKELEY.EDU
   Lines: 5

   >      if(dnum*0d0 .ne. 0d0) write(*,1)
   >1     format(' The variable dnum is equal to NAN!')

	  Is this correct?  Suppose dnum is Inf.

No, it isn't. Aside from reading the standard, let's try code!

      real dnum/1.0/,x/0.0/
      dnum=dnum/x
      print*,dnum
      if(dnum*0d0 .ne. 0d0) print*," is nan?",dnum
      end
      
f77 bork.f && a.out
bork.f:
 MAIN:
 Inf           
 is nan? Inf           

On some systems, vendors will have been kind and provided library
functions. For example, on a Sun one might code something like

      real dnum/1.0/,x/0.0/
      integer ir_isnan,ir_isinf  ! libm function
      dnum=dnum/x
      print*,dnum
      
      if (ir_isnan(dnum)) print*,"dnum IS NaN"
      if (ir_isinf(dnum)) print*,"dnum IS Inf"

      end
      
f77 bork.f && a.out
bork.f:
 MAIN:
 Inf           
dnum IS Inf

It would be more in keeping with the notion of standard compliance, to
not treat ir_* as both a logical and an integer, so one might quite
reasonably prefer to either declare ir* as logicals (despite the libm
definition) or to test the value

	if (ir() .eq. 1)

On systems which are ieee hw compliant, but have not provided the sw
hooks, one can easily code these functions in whatever language seems
most appropriate. To test for NaN it is probably best to use the
result of the appropriate mask ANDed with the value under test.

note that on a Sun, unless user overridden there will also be a
message from ieee_retrospective, ala

 Warning: the following IEEE floating-point arithmetic exceptions 
 occurred in this program and were never cleared: 
 Division by Zero; 

Final note, if memory serves, the right mask is 0x7ff00000

cheers

--
----------------------------------------------------------------
Keith H. Bierman    kbierman@Eng.Sun.COM | khb@chiba.Eng.Sun.COM
SMI 2550 Garcia 12-33			 | (415 336 2648)   
    Mountain View, CA 94043

mcqueen@acf4.NYU.EDU (David M. McQueen) (01/12/91)

Recently, Frank Elliott, one of the mathematicians here at the Courant
Institute, found himself in the position of trying to detect NaN in his
C code on a Stellar GS2000. Although the man pages suggested that there were
library functions for NaN-detection (e.g., "isnand") , in fact the installed
library did not have these functions. Frank came up with a clever kludge
which I have translated to (and used in) Fortran. We have taken to calling
this "Elliott's Device". The Fortran translation below is not guaranteed to
be portable, but I think it could be made portable with relatively little
work. I would not recommend this for numerically intensive applications :-).
 
      character*80 test
      x = 0.0
      y = 0.0
      z = x/y
      write(6,*) z
      write(test,*) z
c     Elliott's Device
      write(6,'(a)') test
      if (test(1:4) .eq. ' NaN') write(6,*) 'z is NaN'
      end
 
-------------------------------------------------------------------------------
PS:
 
I tried to post this earlier and it may or may not have actually gotten out. I
have received email (from Peter Shenkin; thank you, Peter) that the line:
 
      write(test,*) z
 
is an illegal unformatted internal write. I have done this successfully on
a Sun 3/50 running f77 under SunOS 4.1. No guarantees can be made about
other systems.

mcqueen@acf4.NYU.EDU (David M. McQueen) (01/12/91)

From mcqueen@acf4.NYU.EDU  Fri Jan 11 14:00:26 1991
Received: from ACF4.NYU.EDU by cmcl2.NYU.EDU (5.61/1.34)
	id AA22195; Fri, 11 Jan 91 14:00:26 -0500
Received: by acf4.NYU.EDU (5.61/1.34)
	id AA27169; Fri, 11 Jan 91 13:59:59 -0500
Date: Fri, 11 Jan 91 13:59:59 -0500
From: mcqueen@acf4.NYU.EDU (David M. McQueen)
Message-Id: <9101111859.AA27169@acf4.NYU.EDU>
To: rnews@cmcl2.NYU.EDU

Relay-Version: version nyu B notes v1.6.1 1/11/90; site acf4.NYU.EDU
From: mcqueen@acf4.NYU.EDU (David M. McQueen)
Date: 11 Jan 91 13:59 EST
Date-Received: 11 Jan 91 13:59 EST
Subject: Re: detecting Nan's
Message-ID: <13160008@acf4.NYU.EDU>
Path: acf4!mcqueen
Newsgroups: comp.lang.fortran
Posting-Version: version nyu B notes v1.6.1 1/11/90; site acf4.NYU.EDU
Organization: New York University
References: <9101110259.AA28451@ucbvax.Berkeley.EDU>

Recently, Frank Elliott, one of the mathematicians here at the Courant
Institute, found himself in the position of trying to detect NaN in his
C code on a Stellar GS2000. Although the man pages suggested that there were
library functions for NaN-detection (e.g., "isnand") , in fact the installed
library did not have these functions. Frank came up with a clever kludge
which I have translated to (and used in) Fortran. We have taken to calling
this "Elliott's Device". The Fortran translation below is not guaranteed to
be portable, but I think it could be made portable with relatively little
work. I would not recommend this for numerically intensive applications :-).

      character*80 test
      x = 0.0
      y = 0.0
      z = x/y
      write(6,*) z
      write(test,*) z
c     Elliott's Device
      write(6,'(a)') test
      if (test(1:4) .eq. ' NaN') write(6,*) 'z is NaN'
      end

-------------------------------------------------------------------------------
PS:

I tried to post this earlier and it may or may not have actually gotten out. I
have received email (from Peter Shenkin; thank you, Peter) that the line:

      write(test,*) z

is an illegal unformatted internal write. I have done this successfully on
a Sun 3/50 running f77 under SunOS 4.1. No guarantees can be made about
other systems.