[Numpy-discussion] isnan and co: cleaning up
David Cournapeau
david at ar.media.kyoto-u.ac.jp
Fri Sep 5 01:06:07 EDT 2008
Hi,
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
following.
#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; }
#endif
#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); }
#endif
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) ?
cheers,
David
More information about the NumPy-Discussion
mailing list