Mail Archives: cygwin/2005/02/02/15:57:39
There was a thread about this problem a few months ago
(http://sources.redhat.com/ml/cygwin/2004-08/msg00128.html). The
OP at that time was referred to the newlib mailing list, but I
can't find anything on the topic there.
I've recently run into this problem as well, and may have some
new information on it. First, here's an example that shows the
problem:
#include <stdio.h>
#include <math.h>
int main() {
float f = 12.34;
double d = 12.34;
long double ld = 12.34;
printf("f = %d\nd = %d\nld = %d\n",
isfinite(f), isfinite(d), isfinite(ld));
}
This prints
f = 1
d = 0
ld = 0
instead of all values being "1" as expected. The value of
isfinite() appears to be consistent across runs with the same
executable, but it varies with usage. For example, executing all
three isfinite() invocations first, saving the results, and
printing the saved values gives different output. For another
example, the application where I encountered this problem can be
built with different feature sets by build options; specifying
different build options (none directly affecting the code where
isfinite() is used) causes isfinite() to return different results
for the same input, presumably just based on the differing memory
images of the executables or differing stack garbage.
The definitions of isfinite() (and fpclassify(), on which
isfinite() depends) from math.h are as follows:
> #define fpclassify(x) \
> (__extension__ ({__typeof__(x) __x = (x); \
> (sizeof (__x) == sizeof (float)) ? __fpclassifyf(__x) : __fpclassifyd(__x);}))
>
> #define isfinite(x) \
> (__extension__ ({__typeof__(x) __x = (x); \
> fpclassify(__x) != FP_INFINITE && fpclassify(__x) != FP_NAN;}))
In the test cases I ran, fpclassify(), used directly rather than
as part of isfinite(), always returns the correct result for the
given value. As an experiment, I tried redefining isfinite() to
incorporate the features of fpclassify() directly rather than
invoking it:
> #undef isfinite
>
> #define isfinite(x) \
> (__extension__ ({__typeof__(x) __x = (x); \
> int __y=(sizeof(__x)==sizeof(float)?__fpclassifyf(__x):__fpclassifyd(__x)); \
> __y != FP_INFINITE && __y != FP_NAN;}))
In all the cases I tried, this version of isfinite() gave correct
results. Given the instability of the behavior with the math.h
definition of isfinite(), I'm not sure whether this can be
attributed to some problem with the nested macro calls or whether
it's just harder to create a failing scenario with this
definition. However, I thought I'd pass the experience along in
case it triggered some association among the cognoscenti.
As someone who is not too knowledgeable about Cygwin, I do have
some questions about the definition of isfinite() in math.h.
Where did this math.h header come from? It doesn't look like the
math.h on my Linux system (but that's gcc 3.3.3 rather than
3.4.1, so I probably shouldn't expect it to be the same, I
guess). In addition to triggering this bug, there's another
problem with this definition: it doesn't handle long double. The
math.h on my Linux system uses three functions -- __finitef(),
__finite(), and __finitel() -- for implementing isfinite(), while
the Cygwin math.h only uses __fpclassifyf() and __fpclassifyd(),
omitting a version for long double. This could give false
positives for infinities if the long double value overflows when
converted to a double in the call to __fpclassifyd().
--
William M. (Mike) Miller | Edison Design Group, Inc.
wmm AT world DOT std DOT com
--
Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple
Problem reports: http://cygwin.com/problems.html
Documentation: http://cygwin.com/docs.html
FAQ: http://cygwin.com/faq/
- Raw text -