delorie.com/archives/browse.cgi   search  
Mail Archives: cygwin/2005/02/02/15:57:39

Mailing-List: contact cygwin-help AT cygwin DOT com; run by ezmlm
List-Subscribe: <mailto:cygwin-subscribe AT cygwin DOT com>
List-Archive: <http://sourceware.org/ml/cygwin/>
List-Post: <mailto:cygwin AT cygwin DOT com>
List-Help: <mailto:cygwin-help AT cygwin DOT com>, <http://sourceware.org/ml/#faqs>
Sender: cygwin-owner AT cygwin DOT com
Mail-Followup-To: cygwin AT cygwin DOT com
Delivered-To: mailing list cygwin AT cygwin DOT com
Message-ID: <42013E8B.7050509@world.std.com>
Date: Wed, 02 Feb 2005 15:56:43 -0500
From: "William M. (Mike) Miller" <wmm AT world DOT std DOT com>
User-Agent: Mozilla Thunderbird 0.8 (Windows/20040913)
MIME-Version: 1.0
To: cygwin AT cygwin DOT com
Subject: Wrong results from isfinite with gcc 3.4.1

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 -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019