public inbox for cygwin-apps@cygwin.com
 help / color / mirror / Atom feed
From: Achim Gratz <Stromeko@nexgo.de>
To: cygwin-apps@cygwin.com
Subject: Re: Dodgy functions (finitel, strold)
Date: Sat, 26 Mar 2016 19:41:00 -0000	[thread overview]
Message-ID: <87r3ezrkz9.fsf_-_@Rainer.invalid> (raw)
In-Reply-To: <87h9fvygky.fsf@Rainer.invalid> (Achim Gratz's message of "Thu,	24 Mar 2016 17:40:45 +0100")

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 <stdio.h>
#include <stdlib.h>
#include <math.h>
 
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

  reply	other threads:[~2016-03-25  9:00 UTC|newest]

Thread overview: 40+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <announce.20160318203409.GA11113@calimero.vinschen.de>
     [not found] ` <56EC6BDA.7050505@cornell.edu>
2016-03-18 21:45   ` [ANNOUNCEMENT] TEST RELEASE: Cygwin 2.5.0-0.8 Corinna Vinschen
2016-03-18 22:25     ` Ken Brown
2016-03-18 22:40       ` Ken Brown
2016-03-18 23:05       ` Yaakov Selkowitz
2016-03-18 23:29         ` Yaakov Selkowitz
2016-03-19  2:24           ` Ken Brown
2016-03-19 10:32             ` Corinna Vinschen
2016-03-19 12:34               ` Ken Brown
2016-03-19 18:03                 ` Ken Brown
2016-03-20 15:26                   ` Corinna Vinschen
2016-03-20 19:27                     ` Ken Brown
2016-03-20 19:40                       ` Ken Brown
2016-03-20 20:18                       ` Ken Brown
2016-03-20 20:47                       ` Yaakov Selkowitz
2016-03-21 14:13                         ` Ken Brown
2016-03-21 16:30                           ` Corinna Vinschen
2016-03-21 17:59                             ` Ken Brown
2016-03-22 11:15                               ` Corinna Vinschen
2016-03-22 14:59                                 ` Ken Brown
2016-03-30 21:17                                   ` Corinna Vinschen
2016-03-31 11:55                                     ` Ken Brown
2016-03-20  4:50               ` Yaakov Selkowitz
2016-03-20 15:18                 ` Corinna Vinschen
2016-03-20 10:59     ` Achim Gratz
2016-03-20 11:14       ` Marco Atzeri
2016-03-20 15:25       ` Corinna Vinschen
2016-03-20 19:27         ` Achim Gratz
2016-03-20 20:53           ` Corinna Vinschen
2016-03-20 21:30             ` Corinna Vinschen
2016-03-20 20:24         ` Achim Gratz
2016-03-20 20:45           ` Yaakov Selkowitz
2016-03-22  9:31             ` Achim Gratz
2016-03-25  9:00             ` Dodgy functions (was: [ANNOUNCEMENT] TEST RELEASE: Cygwin 2.5.0-0.8) Achim Gratz
2016-03-26  0:16               ` Dodgy functions Achim Gratz
2016-03-26 19:41                 ` Achim Gratz [this message]
2016-03-29 16:09                   ` Dodgy functions (finitel, strold) Doug Henderson
2016-03-29 16:09                     ` Corinna Vinschen
2016-04-01 19:04                     ` Achim Gratz
2016-03-22 17:43     ` [ANNOUNCEMENT] TEST RELEASE: Cygwin 2.5.0-0.8 Chris Sutcliffe
2016-03-22 18:02       ` Corinna Vinschen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87r3ezrkz9.fsf_-_@Rainer.invalid \
    --to=stromeko@nexgo.de \
    --cc=cygwin-apps@cygwin.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).