Mailing-List: contact cygwin-help AT cygwin DOT com; run by ezmlm List-Subscribe: List-Archive: List-Post: List-Help: , 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" 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 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit 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 #include 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/