[Numpy-discussion] isnan and co: cleaning up

David Cournapeau david@ar.media.kyoto-u.ac...
Fri Sep 5 00:06:07 CDT 2008


    While working on my branch to clean the math configuration, I
noticed that the code for isnan and co became quite convoluted. autoconf
info file has a mention of it, and suggests the following for
portability (section 5.5.1 of autoconf):

     The C99 standard says that `isinf' and `isnan' are macros.  On
     some systems just macros are available (e.g., HP-UX and Solaris
     10), on some systems both macros and functions (e.g., glibc
     2.3.2), and on some systems only functions (e.g., IRIX 6 and
     Solaris 9).  In some cases these functions are declared in
     nonstandard headers like `<sunmath.h>' and defined in non-default
     libraries like `-lm' or `-lsunmath'.

     The C99 `isinf' and `isnan' macros work correctly with `long
     double' arguments, but pre-C99 systems that use functions
     typically assume `double' arguments.  On such a system, `isinf'
     incorrectly returns true for a finite `long double' argument that
     is outside the range of `double'.

     To work around this porting mess, you can use code like the

     #include <math.h>

          #ifndef isnan
          # define isnan(x) \
              (sizeof (x) == sizeof (long double) ? isnan_ld (x) \
               : sizeof (x) == sizeof (double) ? isnan_d (x) \
               : isnan_f (x))
          static inline int isnan_f  (float       x) { return x != x; }
          static inline int isnan_d  (double      x) { return x != x; }
          static inline int isnan_ld (long double x) { return x != x; }

          #ifndef isinf
          # define isinf(x) \
              (sizeof (x) == sizeof (long double) ? isinf_ld (x) \
               : sizeof (x) == sizeof (double) ? isinf_d (x) \
               : isinf_f (x))
          static inline int isinf_f  (float       x) { return isnan (x -
x); }
          static inline int isinf_d  (double      x) { return isnan (x -
x); }
          static inline int isinf_ld (long double x) { return isnan (x -
x); }

     Use `AC_C_INLINE' (*note C Compiler::) so that this code works on
     compilers that lack the `inline' keyword.  Some optimizing
     compilers mishandle these definitions, but systems with that bug
     typically have missing or broken `isnan' functions anyway, so it's
     probably not worth worrying about.

This is simpler than the current code (I actually understand what the
above case does; the current code in numpy has many cases which I do not
understand), does not need any C code (_isnan and co), and probably more
portable since autoconf has a lot of experience there. Is the code in
_isnan really better than just relying on the nan property x != x ? (Do
we support platforms without a IEE754 FPU ?)

Does anyone has any thought on replacing the current code by the above
(modulo the inline part, which we can drop for now) ?



More information about the Numpy-discussion mailing list