RE: Floating point exception in strtod()

2018-04-09 Thread Soegtrop, Michael
Dear Corinna,

> ...which is what I described in the rest of my mail :)

ah, yes, sorry. I stumbled on the "0x96c75d80 which appears to be perfectly 
valid for a 32 bit int", fell on my nose and looks like I forgot to walk on 
then.

Best regards,

Michael
Intel Deutschland GmbH
Registered Address: Am Campeon 10-12, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de
Managing Directors: Christin Eisenschmid, Christian Lamprechter
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928


Re: Floating point exception in strtod()

2018-04-09 Thread Corinna Vinschen
On Apr  9 14:45, Soegtrop, Michael wrote:
> Dear Corinna,
> 
> > L is of type Long == int32_t, aadj is of type double.  The value of
> > aadj at this time is 2529648000.0 == 0x96c75d80 which appears to be
> > perfectly valid for a 32 bit int.
> 
> 2529648000 is a valid unsigned long, but not a valid signed long. The
> largest 32 bit long is 2^31-1 = 2147483647. 0x96c75d80 interpreted as
> a signed long is a negative number.
> 
> I would say if floating point instructions are used to convert
> 2529648000 to a signed 32 bit integer, they should produce an
> FE_INVALID exception.

...which is what I described in the rest of my mail :)


Corinna

-- 
Corinna Vinschen  Please, send mails regarding Cygwin to
Cygwin Maintainer cygwin AT cygwin DOT com
Red Hat


signature.asc
Description: PGP signature


RE: Floating point exception in strtod()

2018-04-09 Thread Soegtrop, Michael
Dear Corinna,

> L is of type Long == int32_t, aadj is of type double.  The value of aadj at 
> this time is 2529648000.0 == 0x96c75d80 which appears to be perfectly valid 
> for a 32 bit int.

2529648000 is a valid unsigned long, but not a valid signed long. The largest 
32 bit long is 2^31-1 = 2147483647. 0x96c75d80 interpreted as a signed long is 
a negative number.

I would say if floating point instructions are used to convert 2529648000 to a 
signed 32 bit integer, they should produce an FE_INVALID exception.
 
Best regards,

Michael
Intel Deutschland GmbH
Registered Address: Am Campeon 10-12, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de
Managing Directors: Christin Eisenschmid, Christian Lamprechter
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928


Re: Floating point exception in strtod()

2018-04-09 Thread Corinna Vinschen
On Apr  9 08:09, Ken Brown wrote:
> On 4/9/2018 5:47 AM, Corinna Vinschen wrote:
> > On Apr  7 13:40, Ken Brown wrote:
> > > $ cat strtod_test.c
> > > #include 
> > > #include 
> > > #include 
> > > 
> > > int
> > > main ()
> > > {
> > >/* The following number comes from /usr/share/asymptote/ode.asy.  */
> > >const char *str = "121645100408832000.0";
> > >char *ptr;
> > > 
> > >feenableexcept (FE_INVALID);
> > >strtod (str, );
> > > 
> > >/* If there was an exception, the following will not get executed.  */
> > >printf ("No exception.\n");
> > > }
> > > 
> > > $ gcc strtod_test.c
> > > 
> > > $ ./a
> > > Floating point exception (core dumped)
> > > 
> > > [The above was on x86.  On x86_64 there's simply no output.]
> > > 
> > > I have no idea what's special about the number 121645100408832000.0, but 
> > > the
> > > problem goes away if, for example, I replace the leading 1 by 2.
> > 
> > GDB shows that the exception occurs in newlib/libc/stdlib/strtod.c
> > line 1189, in this statment, which looks rather inconspicious at
> > first glance:
> > 
> > L = (Long)aadj;
> > 
> > L is of type Long == int32_t, aadj is of type double.  The
> > value of aadj at this time is 2529648000.0 == 0x96c75d80 which
> > appears to be perfectly valid for a 32 bit int.
> > 
> > However, on 64 bit for example the assembler statement generating the FP
> > exception is
> > 
> >cvttsd2si %xmm0,%eax
> > 
> > It is documented that this statemnt may raise FE_INVALID or FE_INEXACT
> > exceptions.  The problem is that the generated 32 bit value is a
> > negative signed int value, while the source operand is positive.  So the
> > conversion is, in fact, invalid.
> > 
> > I applied a fix to newlib's strtod, to always use 64 bit ints in this
> > place.  This fixes the problem and no exception is raised.
> 
> Thanks for the explanation and the quick fix.  I'm sorry for causing
> confusion by also sending this to the newlib list.

No, that's fine.  Actually it belonged to the newlib ML in the first
place, so it's good it's in the archives there.


Thanks,
Corinna

-- 
Corinna Vinschen  Please, send mails regarding Cygwin to
Cygwin Maintainer cygwin AT cygwin DOT com
Red Hat


signature.asc
Description: PGP signature


Re: Floating point exception in strtod()

2018-04-09 Thread Ken Brown

On 4/9/2018 5:47 AM, Corinna Vinschen wrote:

On Apr  7 13:40, Ken Brown wrote:

$ cat strtod_test.c
#include 
#include 
#include 

int
main ()
{
   /* The following number comes from /usr/share/asymptote/ode.asy.  */
   const char *str = "121645100408832000.0";
   char *ptr;

   feenableexcept (FE_INVALID);
   strtod (str, );

   /* If there was an exception, the following will not get executed.  */
   printf ("No exception.\n");
}

$ gcc strtod_test.c

$ ./a
Floating point exception (core dumped)

[The above was on x86.  On x86_64 there's simply no output.]

I have no idea what's special about the number 121645100408832000.0, but the
problem goes away if, for example, I replace the leading 1 by 2.


GDB shows that the exception occurs in newlib/libc/stdlib/strtod.c
line 1189, in this statment, which looks rather inconspicious at
first glance:

L = (Long)aadj;

L is of type Long == int32_t, aadj is of type double.  The
value of aadj at this time is 2529648000.0 == 0x96c75d80 which
appears to be perfectly valid for a 32 bit int.

However, on 64 bit for example the assembler statement generating the FP
exception is

   cvttsd2si %xmm0,%eax

It is documented that this statemnt may raise FE_INVALID or FE_INEXACT
exceptions.  The problem is that the generated 32 bit value is a
negative signed int value, while the source operand is positive.  So the
conversion is, in fact, invalid.

I applied a fix to newlib's strtod, to always use 64 bit ints in this
place.  This fixes the problem and no exception is raised.


Thanks for the explanation and the quick fix.  I'm sorry for causing 
confusion by also sending this to the newlib list.


Ken


--
Problem reports:   http://cygwin.com/problems.html
FAQ:   http://cygwin.com/faq/
Documentation: http://cygwin.com/docs.html
Unsubscribe info:  http://cygwin.com/ml/#unsubscribe-simple



Re: Floating point exception in strtod()

2018-04-09 Thread Corinna Vinschen
On Apr  7 13:40, Ken Brown wrote:
> $ cat strtod_test.c
> #include 
> #include 
> #include 
> 
> int
> main ()
> {
>   /* The following number comes from /usr/share/asymptote/ode.asy.  */
>   const char *str = "121645100408832000.0";
>   char *ptr;
> 
>   feenableexcept (FE_INVALID);
>   strtod (str, );
> 
>   /* If there was an exception, the following will not get executed.  */
>   printf ("No exception.\n");
> }
> 
> $ gcc strtod_test.c
> 
> $ ./a
> Floating point exception (core dumped)
> 
> [The above was on x86.  On x86_64 there's simply no output.]
> 
> I have no idea what's special about the number 121645100408832000.0, but the
> problem goes away if, for example, I replace the leading 1 by 2.

GDB shows that the exception occurs in newlib/libc/stdlib/strtod.c
line 1189, in this statment, which looks rather inconspicious at
first glance:

   L = (Long)aadj;

L is of type Long == int32_t, aadj is of type double.  The
value of aadj at this time is 2529648000.0 == 0x96c75d80 which
appears to be perfectly valid for a 32 bit int.

However, on 64 bit for example the assembler statement generating the FP
exception is

  cvttsd2si %xmm0,%eax

It is documented that this statemnt may raise FE_INVALID or FE_INEXACT
exceptions.  The problem is that the generated 32 bit value is a
negative signed int value, while the source operand is positive.  So the
conversion is, in fact, invalid.

I applied a fix to newlib's strtod, to always use 64 bit ints in this
place.  This fixes the problem and no exception is raised.

I'm just generating new developer snapshots.  They should be available
in half an hour or so on https://cygwin.com/snapshots/

FTR, the somewhat more complex strtold implementation is not affected.


Corinna

-- 
Corinna Vinschen  Please, send mails regarding Cygwin to
Cygwin Maintainer cygwin AT cygwin DOT com
Red Hat


signature.asc
Description: PGP signature


RE: Floating point exception in strtod()

2018-04-08 Thread Soegtrop, Michael
> Probably doesn't fit precisely into a double.  Does strtold behave
> better?

actually both numbers can be represented exactly as IEEE double. In Maxima:

(%i1)   factor(121645100408832000);
(%o1)   2^16*3^8*5^3*7^2*11*13*17*19
(%i2)   float(log(3^8*5^3*7^2*11*13*17*19)/log(2));
(%o2)   40.75545582601886

(%i3)   factor(221645100408832000);
(%o3)   2^16*5^3*31*41*1361*15641
(%i4)   float(log(5^3*31*41*1361*15641)/log(2));
(%o4)   41.62102908434535

So the first number has 41 bits and the second 42 after removing powers of 2. 
The significand size of a double is 53 bits (including the implicit 1).

Best regards,

Michael
Intel Deutschland GmbH
Registered Address: Am Campeon 10-12, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de
Managing Directors: Christin Eisenschmid, Christian Lamprechter
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928


Re: Floating point exception in strtod()

2018-04-08 Thread Hans-Bernhard Bröker

Am 08.04.2018 um 05:11 schrieb Duncan Roe:


I tried in 64-bit with the same result as Eliot: works fine w/out
feenableexcept, no o/p with feenableexcept.


Just in case this may have been overlooked: please note that "no output" 
actually means the program crashed because of an uncaught SIGFPE, just 
like the 32-bit version does.


The only difference between 32-bit and 64-bit versions of the program is 
that the 32-bit one outputs the "core dumped" message and writes a 
stackdump, whereas the 64-bit one just dies without _any_ detectable 
symptoms: no message, no stackdump file, nothing.


--
Problem reports:   http://cygwin.com/problems.html
FAQ:   http://cygwin.com/faq/
Documentation: http://cygwin.com/docs.html
Unsubscribe info:  http://cygwin.com/ml/#unsubscribe-simple



Re: Floating point exception in strtod()

2018-04-07 Thread Duncan Roe
On Sat, Apr 07, 2018 at 04:56:13PM -0400, Eliot Moss wrote:
> On 4/7/2018 1:40 PM, Ken Brown wrote:
> > $ cat strtod_test.c
> > #include 
> > #include 
> > #include 
> >
> > int
> > main ()
> > {
> >    /* The following number comes from /usr/share/asymptote/ode.asy.  */
> >    const char *str = "121645100408832000.0";
> >    char *ptr;
> >
> >    feenableexcept (FE_INVALID);
> >    strtod (str, );
> >
> >    /* If there was an exception, the following will not get executed.  */
> >    printf ("No exception.\n");
> > }
>
> If I do the same thing WITHOUT the feenableexcept, it works fine.
> Perhaps strtod catches an exception and then applies a different
> method in some cases, or perhaps it wants exceptions off and
> deals with things its own way.
>
> If I include the feenableexcept, I get the same behavior you
> reported (in 32-bit; I did not test 64-bit).
>
> Regards - Eliot Moss
>
I tried in 64-bit with the same result as Eliot: works fine w/out
feenableexcept, no o/p with feenableexcept.

Cheers ... Duncan.

--
Problem reports:   http://cygwin.com/problems.html
FAQ:   http://cygwin.com/faq/
Documentation: http://cygwin.com/docs.html
Unsubscribe info:  http://cygwin.com/ml/#unsubscribe-simple



Re: Floating point exception in strtod()

2018-04-07 Thread Eliot Moss

On 4/7/2018 1:40 PM, Ken Brown wrote:

$ cat strtod_test.c
#include 
#include 
#include 

int
main ()
{
   /* The following number comes from /usr/share/asymptote/ode.asy.  */
   const char *str = "121645100408832000.0";
   char *ptr;

   feenableexcept (FE_INVALID);
   strtod (str, );

   /* If there was an exception, the following will not get executed.  */
   printf ("No exception.\n");
}


If I do the same thing WITHOUT the feenableexcept, it works fine.
Perhaps strtod catches an exception and then applies a different
method in some cases, or perhaps it wants exceptions off and
deals with things its own way.

If I include the feenableexcept, I get the same behavior you
reported (in 32-bit; I did not test 64-bit).

Regards - Eliot Moss

--
Problem reports:   http://cygwin.com/problems.html
FAQ:   http://cygwin.com/faq/
Documentation: http://cygwin.com/docs.html
Unsubscribe info:  http://cygwin.com/ml/#unsubscribe-simple



Re: Floating point exception in strtod()

2018-04-07 Thread Dan Kegel
Is that 19! ?  Probably doesn't fit precisely into a double.  Does strtold
behave better?

Some implementations throw on unrepresentable numbers, e.g.
https://docs.oracle.com/cd/E19253-01/816-5168/6mbb3hrte/index.html

Ken Brown  schrieb am Sa., 7. Apr. 2018, 10:40:

> $ cat strtod_test.c
> #include 
> #include 
> #include 
>
> int
> main ()
> {
>/* The following number comes from /usr/share/asymptote/ode.asy.  */
>const char *str = "121645100408832000.0";
>char *ptr;
>
>feenableexcept (FE_INVALID);
>strtod (str, );
>
>/* If there was an exception, the following will not get executed.  */
>printf ("No exception.\n");
> }
>
> $ gcc strtod_test.c
>
> $ ./a
> Floating point exception (core dumped)
>
> [The above was on x86.  On x86_64 there's simply no output.]
>
> I have no idea what's special about the number 121645100408832000.0, but
> the problem goes away if, for example, I replace the leading 1 by 2.
>
> Ken
>
> --
> Problem reports:   http://cygwin.com/problems.html
> FAQ:   http://cygwin.com/faq/
> Documentation: http://cygwin.com/docs.html
> Unsubscribe info:  http://cygwin.com/ml/#unsubscribe-simple
>
>
>

--
Problem reports:   http://cygwin.com/problems.html
FAQ:   http://cygwin.com/faq/
Documentation: http://cygwin.com/docs.html
Unsubscribe info:  http://cygwin.com/ml/#unsubscribe-simple