David,
On Thu, 11 Mar 2004, David Berry wrote:
> I've just been poked by Bill Joye about the isnan problem in AST.
> Now that I look into this a bit more, it starts to dawn on me that the
> basic cause of the problem is that isnan is not part of the ansi
> standard.
Ooooh yes it is:
7.12.3.4 The isnan macro
Synopsis
1 #include <math.h>
int isnan(real-floating x);
Description
2 The isnan macro determines whether its argument value is a NaN. First,
an argument represented in a format wider than its semantic type is
converted to its semantic type. Then determination is based on the type
of the argument.197)
Returns
3 The isnan macro returns a nonzero value if and only if its
argument has a NaN value.
This is from ISO/IEC 9899:1999 (E) -- are you looking at the C89 standard?
K&R's math.h doesn't mention isnan at all, but that's because their
Appendices A and B refer to the 1988 draft ANSI standard X3.159-1989.
That's the one that became C89, I think, and which was therefore
superceded by C99.
> AST is compiled with "gcc -ansi" on linux which results in
> neither the isnan macro nor the isnan function being declared in math.h.
Because they're specified as macros in ISO-9899, there's no
requirement that a isnan function be defined, but the isnan macro
should be.
> One of the things that AST brags about is that it is pure "ansi C".
> So really the best solution would probably be for me to do away altogether
> with the isnan calls, by doing more checks before performing the
> calculations that potentially produce the nans which are being checked
> for.
The right thing to do in this case is, I think, what specmap.c and
mapping.c do:
#if !HAVE_DECL_ISNAN
# if HAVE_ISNAN
/* Seems that math.h does not include a prototype for isnan */
int isnan( double );
# else
# define isnan(x) ((x) != (x))
# endif
#endif
(they should also have configure.ac check whether math.h and friends
exists before trying to include it, but it doesn't do that at present
-- since it's standard, that's verging on the paranoid).
This is perfectly legitimate -- if you don't have a isnan macro
defined by the compiler, then you can define one yourself. In more
involved cases than this, the usual thing is to test whether a
function exists, and distribute your own basic implementation for use
if it doesn't. And in fact there's an autoconf macro which supports
just that: AC_REPLACE_FUNCS(ping) tests whether function `ping'
exists, and if it doesn't, adds ping.c to the list of files to be
built, and in any case adds ping.c to the list of files to distribute:
ping.c has your backup implementation of the function. I've only once
had to resort to this in fact.
See you,
Norman
--
---------------------------------------------------------------------------
Norman Gray http://www.astro.gla.ac.uk/users/norman/
Physics and Astronomy, University of Glasgow, UK [log in to unmask]
|