home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / C and C++ / Science⁄Math / VideoToolbox / VideoToolboxSources / IsNan.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-09-14  |  4.4 KB  |  101 lines  |  [TEXT/KAHL]

  1. /* IsNan.c
  2. Fast, portable routines to check for IEEE transfinite numbers: INF and NAN. You
  3. should also look at the macro IsFinite() in VideoToolbox.h.
  4.  
  5. IsNan and IsInf assume that every NAN's most significant mantissa bit is set,
  6. which is apparently an informal convention supported by the Intel and Motorola
  7. math chips. The definition of a NAN in the Apple Numerics book only says that a
  8. NAN is distinguished from an INF by having a nonzero mantissa. Unfortunately, a
  9. strict test of this would require testing all 8 bytes, and in fact the routines
  10. in Plaugher's The Standard C Library do exactly this. However, this seems
  11. wasteful since the 255 different NANs that can be specified by the one byte NAN
  12. type are obviously more than enough for most programs. Indeed, since the
  13. Motorola chip doesn't preserve NAN type, the number of NAN types is rather
  14. academic; a single NAN type seems to be plenty for most applications. While it
  15. is possible to assemble a NAN with zero type, which is preserved through 8881
  16. operations, and which printf("%f") prints as NAN00, the SANE routines all seem
  17. to immediately convert the zero type NAN to type 4, so IsNan() does too.
  18.  
  19. The assert() tests referring to sizeof(double) are evaluated by the compiler,
  20. with no runtime penalty.
  21.  
  22. The Numerical Extensions to C group has proposed in their draft standard that
  23. routines very similar to these become a part of Standard C. Anyone interested in
  24. writing such routines should read: Plauger, P. J. (1992) The Standard C Library.
  25. Englewood Cliffs, NJ: Prentice Hall.
  26.  
  27. PORTABILITY: Standard C. Should work on Motorola and Intel processors, but has
  28. only been tested on 680x0 processors in Macintosh computers.
  29.  
  30. HISTORY:
  31. 8/24/91 dgp    made compatible with THINK C 5.0.
  32. 12/23/91 dgp I replaced the #if statements by ordinary if statements, which are 
  33.     more readable and are allowed to use the sizeof() operator.
  34.     Note that most of the if statements will be evaluated and removed by the
  35.     compiler, with no runtime penalty.
  36. 12/23/91 dgp Wrote my own code to replace the SANE code since it's too slow.
  37.     This makes IsNan() about 5 times faster.
  38.     My code is based on the Apple Numerics Manual, 2nd edition. It says that
  39.     a number is a NAN iff the exponent is all ones and the fraction is nonzero.
  40.     I make a slight shortcut in checking only the top 15 bits of the fraction,
  41.     since that includes the byte that specifies the NAN type, on the premise
  42.     that all NANs that I will actually see in practice will have nonzero type.
  43.     My code handles the ordinary cases of 10 or 12 byte doubles. The weird
  44.     case of shorter doubles (which are unlikely since they run very slowly)
  45.     are detected by the assert() test at the beginning.
  46. 12/23/91 dgp Asked the THINK C compiler not to time this routine.
  47. 12/29/91 dgp Eliminated the need for Sane.h and Types.h. The sane stuff
  48.     now appears in its own file: Sane.c. 
  49.     Wrote IsInf().
  50.     Wrote a new macro definition, in VideoToolbox.h, for IsFinite(), 
  51.     that allows fast inline testing for whether a number is ok, i.e. neither 
  52.     NAN nor INF. 
  53. 1/14/92    dgp    Changed IsNan() to now return the type (1..255) of the NAN, or zero
  54.     if not a NAN. This will break programs that assume the true value is always 1,
  55.     e.g. nans+=IsNan(a);
  56.     Fixed IsInf() to correctly return sign of ±INF.
  57. 1/18/92    dgp    Rewrote routines, making them simpler, and always checking the most 
  58.     significant bit of the mantissa in testing for NAN.
  59. 6/5/93    dgp    Updated documentation.
  60. */
  61.  
  62. /* #include "VideoToolbox.h" */
  63. #include <assert.h>
  64. #pragma options(!profile)    /* THINK C: attribute to the caller the time spent here. */
  65. #define EXPONENT 0
  66. #define MANTISSA (1+(sizeof(double)-10)/sizeof(short))
  67. int IsNan(double x);
  68. int IsInf(double x);
  69.  
  70. int IsNan(double x)
  71. /* Returns x's NAN type (1...255) or zero if x is not a NAN. */
  72. /* If NaN type is zero, return 4, as do the Apple routines. */
  73. {
  74.     register short i;
  75.  
  76.     assert(sizeof(double)==10 || sizeof(double)==12);
  77.     if((((short *)&x)[EXPONENT] & 0x7FFF)==0x7FFF){        /* either NAN or INF */
  78.         i=((short *)&x)[MANTISSA] & 0x7FFF;
  79.         if(i==0)return 0;
  80.         i&=0xFF;
  81.         if(i!=0)return i;
  82.         else return 4;
  83.     } else return 0;
  84. }
  85.  
  86. int IsInf(double x)
  87. /* Returns -1 for -INF, 0 for not INF, and +1 for +INF. */
  88. {
  89.     register short i;
  90.  
  91.     assert(sizeof(double)==10 || sizeof(double)==12);
  92.     i=((short *)&x)[EXPONENT];
  93.     if((i & 0x7FFF)==0x7FFF){                            /*  either NAN or INF */
  94.         if((((short *)&x)[MANTISSA] & 0x7FFF)==0){
  95.             if(i<0)return -1;                            /*  -INF */
  96.             else return 1;                                /*  +INF */
  97.         }
  98.     }
  99.     return 0;
  100. }
  101.