From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 59329 invoked by alias); 25 Mar 2016 09:00:18 -0000 Mailing-List: contact cygwin-apps-help@cygwin.com; run by ezmlm Precedence: bulk Sender: cygwin-apps-owner@cygwin.com List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Mail-Followup-To: cygwin-apps@cygwin.com Received: (qmail 59296 invoked by uid 89); 25 Mar 2016 09:00:17 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.0 required=5.0 tests=AWL,BAYES_00,RCVD_IN_DNSWL_LOW,SPF_PASS autolearn=ham version=3.3.2 spammy=targeted, innocent, lied, 0x1p X-HELO: mail-in-08.arcor-online.net Received: from mail-in-08.arcor-online.net (HELO mail-in-08.arcor-online.net) (151.189.21.48) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (CAMELLIA256-SHA encrypted) ESMTPS; Fri, 25 Mar 2016 09:00:06 +0000 Received: from mail-in-11-z2.arcor-online.net (mail-in-11-z2.arcor-online.net [151.189.8.28]) by mx.arcor.de (Postfix) with ESMTP id 3qWch269jSzGXG8 for ; Fri, 25 Mar 2016 10:00:02 +0100 (CET) Received: from mail-in-14.arcor-online.net (mail-in-14.arcor-online.net [151.189.21.54]) by mail-in-11-z2.arcor-online.net (Postfix) with ESMTP id CFF9131E909 for ; Fri, 25 Mar 2016 10:00:02 +0100 (CET) X-DKIM: Sendmail DKIM Filter v2.8.2 mail-in-14.arcor-online.net 3qWch153xNz6WBf Received: from Gertrud (p54B46F42.dip0.t-ipconnect.de [84.180.111.66]) (Authenticated sender: stromeko@arcor.de) by mail-in-14.arcor-online.net (Postfix) with ESMTPSA id 3qWch153xNz6WBf for ; Fri, 25 Mar 2016 10:00:00 +0100 (CET) From: Achim Gratz To: cygwin-apps@cygwin.com Subject: Re: Dodgy functions (finitel, strold) References: <56EC6BDA.7050505@cornell.edu> <20160318214509.GD11113@calimero.vinschen.de> <8760whmn3a.fsf@Rainer.invalid> <20160320152540.GG11113@calimero.vinschen.de> <87wpoxkm28.fsf@Rainer.invalid> <56EF0583.5030302@cygwin.com> <87lh58xav0.fsf_-_@Rainer.invalid> <87h9fvygky.fsf@Rainer.invalid> Date: Sat, 26 Mar 2016 19:41:00 -0000 In-Reply-To: <87h9fvygky.fsf@Rainer.invalid> (Achim Gratz's message of "Thu, 24 Mar 2016 17:40:45 +0100") Message-ID: <87r3ezrkz9.fsf_-_@Rainer.invalid> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/25.0.91 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain X-SW-Source: 2016-03/txt/msg00154.txt.bz2 Achim Gratz writes: > Achim Gratz writes: >> Long story short, they seem to report a finite value on at least some >> NaN constructs and then the %a format for the Perl sprintf outputs those >> bits as a hex FP number rather than just printing "NaN". On 64bit the >> culprit is actually finitel, of course, since Perl gets compiled with >> long doubles. > > And looking into newlib this seems to be a compile bug, because the > function just uses an intrinsic. But the compiler is innocent, because newlib uses the wrong intrinsic or an incomplete implementation. If it must be using that intrinsic for compatibility reasons, it would need to implement --8<---------------cut here---------------start------------->8--- return (x == x) ? (__builtin_isinf_sign (x) == 0) : 0; --8<---------------cut here---------------end--------------->8--- so it doesn't report NaN as finite. NaN compares unequal even with itself, so the first part implements !isnan(x). But it should really just use --8<---------------cut here---------------start------------->8--- return __builtin_isfinite; --8<---------------cut here---------------end--------------->8--- provided that is available from all targeted compilers. So it's a newlib bug. But for whatever reason I couldn't make it appear in a simple test case, most likely because gcc somehow recognized something about it and replaced it with the correct version when compiling with the standard options, so it never links in the wrong newlib implementation. However, compiling with -std=c89 (like Perl) finally teases it out. I've extended the test program from Corinna so it compiles with both options and doesn't crash with no input. This also uncovered a separate bug with strtold (which is only available in C99 mode). --8<---------------cut here---------------start------------->8--- #include #include #include int test_infsgn (double x) { return __builtin_isinf_sign (x) == 0; } int test_infsgnl (long double x) { return __builtin_isinf_sign (x) == 0; } int test_finite (double x) { return __builtin_isfinite (x); } int test_finitel (long double x) { return __builtin_isfinite (x); } int main (int argc, char **argv) { printf ("===== got %d argument(s)\n", argc); int i=0; while (++i < argc) { double a = strtod (argv[i], NULL); #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) long double b = strtold (argv[i], NULL); #endif long double c = a; #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) printf ("===== arg[%d] = (double) %a = (long double) %La = (long double)(double) %La\n", i, a, b, c); #else printf ("===== arg[%d] = (double) %a = (long double)(double) %La\n", i, a, c); #endif printf ("infsgn: (double) %d\n", test_infsgn (a)); #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) printf ("infsgn: (long double) %d\n", test_infsgnl (b)); #endif printf ("infsgn: (long double)(double) %d\n", test_infsgnl (c)); printf ("finite: (double) %d\n", test_finite (a)); #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) printf ("finite: (long double) %d\n", test_finitel (b)); #endif printf ("finite: (long double)(double) %d\n", test_finitel (c)); printf ("newlib: (double) %d\n", finite (a)); #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) printf ("newlib: (long double) %d\n", finitel (b)); #endif printf ("newlib: (long double)(double) %d\n", finitel (c)); } printf ("===== ran out of args\n"); return 0; } --8<---------------cut here---------------end--------------->8--- Compilation with C89 showing the newlib bug: --8<---------------cut here---------------start------------->8--- $ gcc -std=c89 infnan.c -o infnan && ./infnan 1 nan -inf +inf ===== got 5 argument(s) ===== arg[1] = (double) 0x1p+0 = (long double)(double) 0x1p+0 infsgn: (double) 1 infsgn: (long double)(double) 1 finite: (double) 1 finite: (long double)(double) 1 newlib: (double) 1 newlib: (long double)(double) 1 ===== arg[2] = (double) nan = (long double)(double) nan infsgn: (double) 1 infsgn: (long double)(double) 1 finite: (double) 0 finite: (long double)(double) 0 newlib: (double) 0 newlib: (long double)(double) 1 ===== arg[3] = (double) -inf = (long double)(double) -inf infsgn: (double) 0 infsgn: (long double)(double) 0 finite: (double) 0 finite: (long double)(double) 0 newlib: (double) 0 newlib: (long double)(double) 0 ===== arg[4] = (double) inf = (long double)(double) inf infsgn: (double) 0 infsgn: (long double)(double) 0 finite: (double) 0 finite: (long double)(double) 0 newlib: (double) 0 newlib: (long double)(double) 0 ===== ran out of args --8<---------------cut here---------------end--------------->8--- Compilation with C99 showing that strtold still doesn't work correctly (it folds Inf->NaN): --8<---------------cut here---------------start------------->8--- gcc -std=c99 infnan.c -o infnan && ./infnan 1 nan -inf +inf ===== got 5 argument(s) ===== arg[1] = (double) 0x1p+0 = (long double) 0x1p+0 = (long double)(double) 0x1p+0 infsgn: (double) 1 infsgn: (long double) 1 infsgn: (long double)(double) 1 finite: (double) 1 finite: (long double) 1 finite: (long double)(double) 1 newlib: (double) 1 newlib: (long double) 1 newlib: (long double)(double) 1 ===== arg[2] = (double) nan = (long double) nan = (long double)(double) nan infsgn: (double) 1 infsgn: (long double) 1 infsgn: (long double)(double) 1 finite: (double) 0 finite: (long double) 0 finite: (long double)(double) 0 newlib: (double) 0 newlib: (long double) 1 newlib: (long double)(double) 1 ===== arg[3] = (double) -inf = (long double) nan = (long double)(double) -inf infsgn: (double) 0 infsgn: (long double) 1 infsgn: (long double)(double) 0 finite: (double) 0 finite: (long double) 0 finite: (long double)(double) 0 newlib: (double) 0 newlib: (long double) 1 newlib: (long double)(double) 0 ===== arg[4] = (double) inf = (long double) nan = (long double)(double) inf infsgn: (double) 0 infsgn: (long double) 1 infsgn: (long double)(double) 0 finite: (double) 0 finite: (long double) 0 finite: (long double)(double) 0 newlib: (double) 0 newlib: (long double) 1 newlib: (long double)(double) 0 ===== ran out of args --8<---------------cut here---------------end--------------->8--- Finally, here's gcc making a run-around the bug in newlib (it was no fun finding _that_, since it cost me two days of sleuthing to recognize that I'd been lied to by the test program): --8<---------------cut here---------------start------------->8--- $ gcc infnan.c -o infnan && ./infnan 1 nan -inf +inf ===== got 5 argument(s) ===== arg[1] = (double) 0x1p+0 = (long double) 0x1p+0 = (long double)(double) 0x1p+0 infsgn: (double) 1 infsgn: (long double) 1 infsgn: (long double)(double) 1 finite: (double) 1 finite: (long double) 1 finite: (long double)(double) 1 newlib: (double) 1 newlib: (long double) 1 newlib: (long double)(double) 1 ===== arg[2] = (double) nan = (long double) nan = (long double)(double) nan infsgn: (double) 1 infsgn: (long double) 1 infsgn: (long double)(double) 1 finite: (double) 0 finite: (long double) 0 finite: (long double)(double) 0 newlib: (double) 0 newlib: (long double) 0 newlib: (long double)(double) 0 ===== arg[3] = (double) -inf = (long double) nan = (long double)(double) -inf infsgn: (double) 0 infsgn: (long double) 1 infsgn: (long double)(double) 0 finite: (double) 0 finite: (long double) 0 finite: (long double)(double) 0 newlib: (double) 0 newlib: (long double) 0 newlib: (long double)(double) 0 ===== arg[4] = (double) inf = (long double) nan = (long double)(double) inf infsgn: (double) 0 infsgn: (long double) 1 infsgn: (long double)(double) 0 finite: (double) 0 finite: (long double) 0 finite: (long double)(double) 0 newlib: (double) 0 newlib: (long double) 0 newlib: (long double)(double) 0 ===== ran out of args --8<---------------cut here---------------end--------------->8--- Regards, Achim. -- +<[Q+ Matrix-12 WAVE#46+305 Neuron microQkb Andromeda XTk Blofeld]>+ Factory and User Sound Singles for Waldorf Blofeld: http://Synth.Stromeko.net/Downloads.html#WaldorfSounds