fkittred@bbn.com (Fletcher Kittredge) (09/21/90)
I need to determine whether a double precision floating point number is a IEEE NaN or INF (+ or -) value on Sun, HP and DEC RISC systems. Sun and HP supply the isnan() and isinf() functions. I can't find these functions on the DEC systems. There is a include file called /usr/include/nan.h which seems to have macros for determining these values, but the macros seem to be for a high-endian MIPS system, not DEC's low-endian version. Can anyone help me with this? thanks! fletcher Fletcher E. Kittredge fkittred@bbn.com Platforms and Tools Group BBN Software Products Company 10 Fawcett St. Cambridge, MA. 02138
mark@mips.COM (Mark G. Johnson) (09/22/90)
In article <59582@bbn.BBN.COM> fkittred@spca.bbn.com (Fletcher Kittredge) writes: > >I need to determine whether a double precision floating point number is >a IEEE NaN or INF (+ or -) value on Sun, HP and DEC RISC systems. Sun You could resort to coding your own routines. Just as an simple-simon demonstration of this possibility, the following hack was thrown together in 3 minutes. It was tested on the DECstation 3100 and works under compiler optimization levels 0, 1, 2, and 3. These codes are far from optimum, but they give a flavor of how you might proceed. Flame if you must, keeping in mind that the goal below is getting an answer, not efficiency. The basic ideas are (1) if you compare IEEE NaN with anything, the comparison fails. Even a==a fails if a is NaN. (2) Infinity is what you get when you overflow a computation. ----------------------------------------------------------------------------- #include <stdio.h> #include <math.h> /* test if argument is IEEE double precision NaN */ int inn(a) double a; { if(a==a) return(0) ; else return(1); } /* test if argument is IEEE double precision Infinity (+ or -) */ int iff(b) double b; { double c, d; /* laboriously create +Infinity and -Infinity */ c = 1e10; c = (c*c); c = (c*c); c = (c*c); c = (c*c); c = (c*c); c = (c*c); d = -1.0 *c; if((b==c) || (b==d)) return(1); else return(0); } main() { double x, y, z, q, v ; /* set z equal to +Infinity */ z = 1e10 ; z = z*z ; z = z*z ; z = z*z ; z = z*z ; z = z*z ; z = z*z ; z = z*z ; z = z*z ; /* set y equal to NaN */ y = z/z ; /* set x equal to 1.0 */ x = 1.0 ; printf(" Is %le a NAN? answer: %d \n", x, inn(x)); printf(" Is %le a NAN? answer: %d \n", y, inn(y)); printf(" Is %le a NAN? answer: %d \n", z, inn(z)); printf(" Is %le an infinity? answer: %d \n", x, iff(x)); printf(" Is %le an infinity? answer: %d \n", y, iff(y)); printf(" Is %le an infinity? answer: %d \n", z, iff(z)); } -- -- Mark Johnson MIPS Computer Systems, 930 E. Arques M/S 2-02, Sunnyvale, CA 94086 (408) 524-8308 mark@mips.com {or ...!decwrl!mips!mark}
frank@croton.enet.dec.com (Frank Wortner) (09/24/90)
The ULTRIX 4.0 distribution includes a fixed /usr/include/nan.h file. If you can't upgrade, your could try just reversing the bit fields in the nan.h file. For example, in the inf_parts structure, the fraction_low bit field is the first instead of the last. Regards, Frank
lindahl@violet.berkeley.edu (Ken Lindahl 642-0866) (09/25/90)
In article <59582@bbn.BBN.COM> fkittred@spca.bbn.com (Fletcher Kittredge) writes: > >I need to determine whether a double precision floating point number is >a IEEE NaN or INF (+ or -) value on Sun, HP and DEC RISC systems. Sun >and HP supply the isnan() and isinf() functions. I can't find these >functions on the DEC systems. There is a include file called >/usr/include/nan.h which seems to have macros for determining these >values, but the macros seem to be for a high-endian MIPS system, not >DEC's low-endian version. > >Can anyone help me with this? > >thanks! >fletcher > Under Ultrix V3.1, an alternative is to use either fp_class_f() or fp_classd(), which are in libc.a (not libm.a!). The man page for fp_class_[fd]() is missing from my system (there is a reference to it at the bottom of the ieee(3m) page), but by trying the obvious, I've concluded that the syntax is int fp_class_f(x) float x; int fp_class_d(x) double x; The integer values returned are defined in <fp_class.h>. In another reply, frank@croton.enet.dec.com (Frank Wortner) writes: >The ULTRIX 4.0 distribution includes a fixed /usr/include/nan.h file. >If you can't upgrade, >your could try just reversing the bit fields in the nan.h file. For >example, in the inf_parts >structure, the fraction_low bit field is the first instead of the last. I tried this and it works nicely. Thanks, Frank, for the suggestion; I know it's obvious, but I must confess that I hadn't thought of it. The IsINF(), IsPosNAN(), and IsNegNAN() macros should only be used after IsNANorINF() has already tested TRUE -- otherwise, these three macros could return TRUE for some non-exceptional values. Finally, here's an observation and a possible bug: the log() function in libm.a handles exceptions differently than the log() function in libm43.a. Specifically, libm.a libm43.a -------------- --------- log(0) = NaN (negative) = -Infinity log(Infinity) = NaN (negative) = Infinity I don't know which of these behaviors is consistent with IEEE 754 (I haven't actually read it), but the libm43.a version seems more useful to me. Beyond that, the math(3m) man page seems to imply that libm.a and libm43.a should be comparable except perhaps for speed and very small differences in returned values. This is not true for the the two versions of log(). Comments, anyone? By the way, I have not performed any kind of exhaustive search for discrencies between libm.a and libm43.a; I just stumbled across this one. Ken Lindahl lindahl@violet.berkeley.edu Advanced Technology Planning, Information Systems and Technology University of California at Berkeley