Re: exp() / expl() on Linux and OpenBSD (expl() bug?)

2014-02-22 Thread Miod Vallat
  A fix has been committed, but there's still a problem on loongson with
  libm updated:

[...]

 This is definitely a problem in gdtoa. The values are always computed
 the same, but do not get printed correctly, as shown by this modified
 test program. Both lines should print 0.606531 for the long doubles, but
 don't always; this smells like an uninitialized value somewhere.

Well, it turned out this was caused by the program stack being aligned
to an 8 byte boundary, instead of a 16 byte boundary, causing long
double variables on the stack to be misaligned 50% of the time.

This has been fixed now.

Miod



Re: exp() / expl() on Linux and OpenBSD (expl() bug?)

2014-02-13 Thread Miod Vallat
 A fix has been committed, but there's still a problem on loongson with
 libm updated:
 
 $ ls -l /usr/lib/libm.so.*
 -r--r--r--  1 root  bin  926033 Feb 12 12:17 /usr/lib/libm.so.9.0
 $ cc -o expl expl.c -O2 -pipe -lm
 $ for in in 1 2 3 4 5 6 ; do ./expl ; done
 theta == 1, pr == -9.15569e-2474, pr2 == 6.10667e-4944
 theta == 1, pr == 0.606531, pr2 == 0.606531
 theta == 1, pr == 0.606531, pr2 == 0.606531
 theta == 1, pr == 0.606531, pr2 == 0.606531
 theta == 1, pr == -9.15569e-2474, pr2 == 6.10667e-4944
 theta == 1, pr == 0.606531, pr2 == 0.606531
 

This is definitely a problem in gdtoa. The values are always computed
the same, but do not get printed correctly, as shown by this modified
test program. Both lines should print 0.606531 for the long doubles, but
don't always; this smells like an uninitialized value somewhere.

#include stdio.h
#include stdlib.h
#include math.h

int
main(void)
{
double theta = 1;
long double lambda, pr, pr2;
static const uint64_t zpr[2] = {
#ifdef __MIPSEL__
0xa000ULL, 0x3ffe368b2fc6f960ULL
#else
0x3ffe368b2fc6f960ULL, 0xa000ULL
#endif
}, zpr2[2] = {
#ifdef __MIPSEL__
0x9fe7aceb46aa619cULL, 0x3ffe368b2fc6f960ULL
#else
0x3ffe368b2fc6f960ULL, 0x9fe7aceb46aa619cULL
#endif
};

lambda = (0.5*theta);
pr = exp(-lambda);
pr2 = expl(-lambda);

printf(theta == %g, pr == %Lg, pr2 == %Lg\n, theta, pr, pr2);
printf(theta == %g, pr == %Lg, pr2 == %Lg\n, theta, zpr[0], zpr[1],
zpr2[0], zpr2[1]);
exit(0);
}



Re: exp() / expl() on Linux and OpenBSD (expl() bug?)

2014-02-12 Thread Donovan Watteau
On Thu, 6 Feb 2014, Donovan Watteau wrote:
 David Coppa wrote:
  Take the following reduced test-case, adapted from what R's code
  does:
  
  ---8---
  
  #include stdio.h
  #include stdlib.h
  #include math.h
  
  int main(void) {
  double theta = 1;
  long double lambda, pr, pr2;
  
  lambda = (0.5*theta);
  pr = exp(-lambda);
  pr2 = expl(-lambda);
  
  printf(theta == %g, pr == %Lg, pr2 == %Lg\n, theta, pr, pr2);
  exit(0);
  }
  
  ---8---
  
  This produces the following output on Linux (x86_64):
  
  theta == 1, pr == 0.606531, pr2 == 0.606531
  
  While on OpenBSD -current amd64:
  
  theta == 1, pr == 0.606531, pr2 == nan
 
 FWIW, it looks even stranger on loongson:
 
 $ cc -o expl expl.c -O2 -pipe -lm
 $ ./expl
 theta == 1, pr == -9.15569e-2474, pr2 == 6.10667e-4944
 $ ./expl
 theta == 1, pr == 0.606531, pr2 == 0.606531
 $ ./expl
 theta == 1, pr == -9.15569e-2474, pr2 == 6.10667e-4944
 
 $ sysctl kern.version
 kern.version=OpenBSD 5.5-beta (GENERIC) #106: Mon Feb  3 01:47:15 MST 2014
 t...@loongson.openbsd.org:/usr/src/sys/arch/loongson/compile/GENERIC

A fix has been committed, but there's still a problem on loongson with
libm updated:

$ ls -l /usr/lib/libm.so.*
-r--r--r--  1 root  bin  926033 Feb 12 12:17 /usr/lib/libm.so.9.0
$ cc -o expl expl.c -O2 -pipe -lm
$ for in in 1 2 3 4 5 6 ; do ./expl ; done
theta == 1, pr == -9.15569e-2474, pr2 == 6.10667e-4944
theta == 1, pr == 0.606531, pr2 == 0.606531
theta == 1, pr == 0.606531, pr2 == 0.606531
theta == 1, pr == 0.606531, pr2 == 0.606531
theta == 1, pr == -9.15569e-2474, pr2 == 6.10667e-4944
theta == 1, pr == 0.606531, pr2 == 0.606531



Re: exp() / expl() on Linux and OpenBSD (expl() bug?)

2014-02-12 Thread Martynas Venckus
On 2/12/14, Donovan Watteau tso...@gmail.com wrote:
 On Thu, 6 Feb 2014, Donovan Watteau wrote:
 David Coppa wrote:
  Take the following reduced test-case, adapted from what R's code
  does:
 
  ---8---
 
  #include stdio.h
  #include stdlib.h
  #include math.h
 
  int main(void) {
 double theta = 1;
 long double lambda, pr, pr2;
 
 lambda = (0.5*theta);
 pr = exp(-lambda);
 pr2 = expl(-lambda);
 
 printf(theta == %g, pr == %Lg, pr2 == %Lg\n, theta, pr, pr2);
 exit(0);
  }
 
  ---8---
 
  This produces the following output on Linux (x86_64):
 
  theta == 1, pr == 0.606531, pr2 == 0.606531
 
  While on OpenBSD -current amd64:
 
  theta == 1, pr == 0.606531, pr2 == nan

 FWIW, it looks even stranger on loongson:

 $ cc -o expl expl.c -O2 -pipe -lm
 $ ./expl
 theta == 1, pr == -9.15569e-2474, pr2 == 6.10667e-4944
 $ ./expl
 theta == 1, pr == 0.606531, pr2 == 0.606531
 $ ./expl
 theta == 1, pr == -9.15569e-2474, pr2 == 6.10667e-4944

 $ sysctl kern.version
 kern.version=OpenBSD 5.5-beta (GENERIC) #106: Mon Feb  3 01:47:15 MST
 2014
 t...@loongson.openbsd.org:/usr/src/sys/arch/loongson/compile/GENERIC

 A fix has been committed, but there's still a problem on loongson with
 libm updated:

 $ ls -l /usr/lib/libm.so.*
 -r--r--r--  1 root  bin  926033 Feb 12 12:17 /usr/lib/libm.so.9.0
 $ cc -o expl expl.c -O2 -pipe -lm
 $ for in in 1 2 3 4 5 6 ; do ./expl ; done
 theta == 1, pr == -9.15569e-2474, pr2 == 6.10667e-4944
 theta == 1, pr == 0.606531, pr2 == 0.606531
 theta == 1, pr == 0.606531, pr2 == 0.606531
 theta == 1, pr == 0.606531, pr2 == 0.606531
 theta == 1, pr == -9.15569e-2474, pr2 == 6.10667e-4944
 theta == 1, pr == 0.606531, pr2 == 0.606531

This isn't related to exp/expl.  Looks like a bug in either compiler
or libc/printf/gdtoa.  I don't have the hardware so I couldn't tell
much more.

As usual, there are a few ways to fix it:
1. Debug it and provide a diff,
2. Donate hardware.  Oh, BTW I have a request for loongson in
http://www.openbsd.org/want.html sitting for over a year...



Re: exp() / expl() on Linux and OpenBSD (expl() bug?)

2014-02-11 Thread Mark Kettenis
 Date: Mon, 10 Feb 2014 22:35:02 -0700 (MST)
 From: Martynas Venckus marty...@cvs.openbsd.org
 
  Here's a diff that sticks a bit closer to the original code.  It's
  equivalent to your diff, and admittedly purely a matter of taste which
  version to prefer.
 
 I prefer my version better.  It's not '93 anymore and compilers are
 able to convert 0.0L and -1.0L precisely, otherwise we have a huge
 problem.  There's no need to obfuscate here by manually converting
 to floating point representation.
 
 Here's a diff which also includes same fix for ld128.  OK?

Fair enough.  Please commit.

 Index: ld128/s_floorl.c
 ===
 RCS file: /cvs/src/lib/libm/src/ld128/s_floorl.c,v
 retrieving revision 1.1
 diff -u -r1.1 s_floorl.c
 --- ld128/s_floorl.c  6 Jul 2011 00:02:42 -   1.1
 +++ ld128/s_floorl.c  11 Feb 2014 05:24:15 -
 @@ -34,10 +34,11 @@
   jj0 = ((i048)0x7fff)-0x3fff;
   if(jj048) {
   if(jj00) { /* raise inexact if x != 0 */
 - if(huge+x0.0) {/* return 0*sign(x) if |x|1 */
 - if(i0=0) {i0=i1=0;}
 + if(huge+x0.0) {
 + if(i0=0)
 + return 0.0L;
   else if(((i00x7fffLL)|i1)!=0)
 - { i0=0xbfffULL;i1=0;}
 + return -1.0L;
   }
   } else {
   i = (0xULL)jj0;
 Index: ld80/s_floorl.c
 ===
 RCS file: /cvs/src/lib/libm/src/ld80/s_floorl.c,v
 retrieving revision 1.2
 diff -u -r1.2 s_floorl.c
 --- ld80/s_floorl.c   25 Jul 2011 16:20:09 -  1.2
 +++ ld80/s_floorl.c   11 Feb 2014 05:24:01 -
 @@ -35,10 +35,11 @@
   jj0 = (se0x7fff)-0x3fff;
   if(jj031) {
   if(jj00) { /* raise inexact if x != 0 */
 - if(huge+x0.0) {/* return 0*sign(x) if |x|1 */
 - if(sx==0) {se=0;i0=i1=0;}
 + if(huge+x0.0) {
 + if(sx==0)
 + return 0.0L;
   else if(((se0x7fff)|i0|i1)!=0)
 - { se=0xbfff;i0=i1=0;}
 + return -1.0L;
   }
   } else {
   i = (0x7fff)jj0;
 
 



Re: exp() / expl() on Linux and OpenBSD (expl() bug?)

2014-02-10 Thread David Coppa
On Fri, Feb 7, 2014 at 4:03 PM, David Coppa dco...@gmail.com wrote:
 On Fri, Feb 7, 2014 at 3:49 PM, Mark Kettenis mark.kette...@xs4all.nl wrote:
 Date: Thu, 6 Feb 2014 23:07:58 -0800
 From: Martynas Venckus marty...@venck.us

 Yup.Does this diff fix it for you?

 Here's a diff that sticks a bit closer to the original code.  It's
 equivalent to your diff, and admittedly purely a matter of taste which
 version to prefer.

 Index: s_floorl.c
 ===
 RCS file: /home/cvs/src/lib/libm/src/ld80/s_floorl.c,v
 retrieving revision 1.2
 diff -u -p -r1.2 s_floorl.c
 --- s_floorl.c  25 Jul 2011 16:20:09 -  1.2
 +++ s_floorl.c  7 Feb 2014 14:43:19 -
 @@ -38,7 +38,7 @@ floorl(long double x)
 if(huge+x0.0) {/* return 0*sign(x) if |x|1 */
 if(sx==0) {se=0;i0=i1=0;}
 else if(((se0x7fff)|i0|i1)!=0)
 -   { se=0xbfff;i0=i1=0;}
 +   { se=0xbfff;i0=0x8000;i1=0;}
 }
 } else {
 i = (0x7fff)jj0;


 Just tested, and this one works too, of course...

 I'd be happy if this or the other one could be committed.

Ping



Re: exp() / expl() on Linux and OpenBSD (expl() bug?)

2014-02-10 Thread Martynas Venckus
 Here's a diff that sticks a bit closer to the original code.  It's
 equivalent to your diff, and admittedly purely a matter of taste which
 version to prefer.

I prefer my version better.  It's not '93 anymore and compilers are
able to convert 0.0L and -1.0L precisely, otherwise we have a huge
problem.  There's no need to obfuscate here by manually converting
to floating point representation.

Here's a diff which also includes same fix for ld128.  OK?

Index: ld128/s_floorl.c
===
RCS file: /cvs/src/lib/libm/src/ld128/s_floorl.c,v
retrieving revision 1.1
diff -u -r1.1 s_floorl.c
--- ld128/s_floorl.c6 Jul 2011 00:02:42 -   1.1
+++ ld128/s_floorl.c11 Feb 2014 05:24:15 -
@@ -34,10 +34,11 @@
jj0 = ((i048)0x7fff)-0x3fff;
if(jj048) {
if(jj00) { /* raise inexact if x != 0 */
-   if(huge+x0.0) {/* return 0*sign(x) if |x|1 */
-   if(i0=0) {i0=i1=0;}
+   if(huge+x0.0) {
+   if(i0=0)
+   return 0.0L;
else if(((i00x7fffLL)|i1)!=0)
-   { i0=0xbfffULL;i1=0;}
+   return -1.0L;
}
} else {
i = (0xULL)jj0;
Index: ld80/s_floorl.c
===
RCS file: /cvs/src/lib/libm/src/ld80/s_floorl.c,v
retrieving revision 1.2
diff -u -r1.2 s_floorl.c
--- ld80/s_floorl.c 25 Jul 2011 16:20:09 -  1.2
+++ ld80/s_floorl.c 11 Feb 2014 05:24:01 -
@@ -35,10 +35,11 @@
jj0 = (se0x7fff)-0x3fff;
if(jj031) {
if(jj00) { /* raise inexact if x != 0 */
-   if(huge+x0.0) {/* return 0*sign(x) if |x|1 */
-   if(sx==0) {se=0;i0=i1=0;}
+   if(huge+x0.0) {
+   if(sx==0)
+   return 0.0L;
else if(((se0x7fff)|i0|i1)!=0)
-   { se=0xbfff;i0=i1=0;}
+   return -1.0L;
}
} else {
i = (0x7fff)jj0;



Re: exp() / expl() on Linux and OpenBSD (expl() bug?)

2014-02-10 Thread David Coppa
On Tue, Feb 11, 2014 at 6:35 AM, Martynas Venckus
marty...@cvs.openbsd.org wrote:
 Here's a diff that sticks a bit closer to the original code.  It's
 equivalent to your diff, and admittedly purely a matter of taste which
 version to prefer.

 I prefer my version better.  It's not '93 anymore and compilers are
 able to convert 0.0L and -1.0L precisely, otherwise we have a huge
 problem.  There's no need to obfuscate here by manually converting
 to floating point representation.

 Here's a diff which also includes same fix for ld128.  OK?

OK with me.

Ciao,
David


 Index: ld128/s_floorl.c
 ===
 RCS file: /cvs/src/lib/libm/src/ld128/s_floorl.c,v
 retrieving revision 1.1
 diff -u -r1.1 s_floorl.c
 --- ld128/s_floorl.c6 Jul 2011 00:02:42 -   1.1
 +++ ld128/s_floorl.c11 Feb 2014 05:24:15 -
 @@ -34,10 +34,11 @@
 jj0 = ((i048)0x7fff)-0x3fff;
 if(jj048) {
 if(jj00) { /* raise inexact if x != 0 */
 -   if(huge+x0.0) {/* return 0*sign(x) if |x|1 */
 -   if(i0=0) {i0=i1=0;}
 +   if(huge+x0.0) {
 +   if(i0=0)
 +   return 0.0L;
 else if(((i00x7fffLL)|i1)!=0)
 -   { i0=0xbfffULL;i1=0;}
 +   return -1.0L;
 }
 } else {
 i = (0xULL)jj0;
 Index: ld80/s_floorl.c
 ===
 RCS file: /cvs/src/lib/libm/src/ld80/s_floorl.c,v
 retrieving revision 1.2
 diff -u -r1.2 s_floorl.c
 --- ld80/s_floorl.c 25 Jul 2011 16:20:09 -  1.2
 +++ ld80/s_floorl.c 11 Feb 2014 05:24:01 -
 @@ -35,10 +35,11 @@
 jj0 = (se0x7fff)-0x3fff;
 if(jj031) {
 if(jj00) { /* raise inexact if x != 0 */
 -   if(huge+x0.0) {/* return 0*sign(x) if |x|1 */
 -   if(sx==0) {se=0;i0=i1=0;}
 +   if(huge+x0.0) {
 +   if(sx==0)
 +   return 0.0L;
 else if(((se0x7fff)|i0|i1)!=0)
 -   { se=0xbfff;i0=i1=0;}
 +   return -1.0L;
 }
 } else {
 i = (0x7fff)jj0;




Re: exp() / expl() on Linux and OpenBSD (expl() bug?)

2014-02-07 Thread David Coppa
On Fri, Feb 7, 2014 at 8:07 AM, Martynas Venckus marty...@venck.us wrote:
 Yup.Does this diff fix it for you?

Yeah! It works.

And R-3's testsuite is also happy now.

Thanks a lot! And thanks to Daniel too...

ok dcoppa@ to commit it, obviously

Ciao,
David


 On 2/6/14, Daniel Dickman didick...@gmail.com wrote:
 I think I recently ran into a similar issue but I suspect the root cause
 might be the same. I think the floorl function is wrong for numbers slightly
 larger than -1 to numbers slightly below 0. In this range floorl returns -0
 instead of -1.

 On Feb 5, 2014, at 3:57 AM, David Coppa dco...@openbsd.org wrote:


 Hi!

 I hit this problem while working on updating math/R from version
 2.15.3 to the latest version (3.0.2).

 It started happening since upstream switched from double functions
 to C99 long double functions (expl, fabsl, ...), during the R-3
 development cycle.

 Take the following reduced test-case, adapted from what R's code
 does:

 ---8---

 #include stdio.h
 #include stdlib.h
 #include math.h

 int main(void) {
double theta = 1;
long double lambda, pr, pr2;

lambda = (0.5*theta);
pr = exp(-lambda);
pr2 = expl(-lambda);

printf(theta == %g, pr == %Lg, pr2 == %Lg\n, theta, pr, pr2);
exit(0);
 }

 ---8---

 This produces the following output on Linux (x86_64):

 theta == 1, pr == 0.606531, pr2 == 0.606531

 While on OpenBSD -current amd64:

 theta == 1, pr == 0.606531, pr2 == nan

 And indeed R-3's testsuite fails with the error message
 NaNs produced:

 Warning in pchisq(1e-300, df = 0, ncp = lam) : NaNs produced
 stopifnot(all.equal(p00, exp(-lam/2)),
 +   all.equal(p.0, exp(-lam/2)))
 Error: all.equal(p.0, exp(-lam/2)) is not TRUE
 Execution halted

 Is this a bug in our expl() ?

 Ciao,
 David





Re: exp() / expl() on Linux and OpenBSD (expl() bug?)

2014-02-07 Thread Mark Kettenis
 Date: Thu, 6 Feb 2014 23:07:58 -0800
 From: Martynas Venckus marty...@venck.us
 
 Yup.Does this diff fix it for you?

Here's a diff that sticks a bit closer to the original code.  It's
equivalent to your diff, and admittedly purely a matter of taste which
version to prefer.

Index: s_floorl.c
===
RCS file: /home/cvs/src/lib/libm/src/ld80/s_floorl.c,v
retrieving revision 1.2
diff -u -p -r1.2 s_floorl.c
--- s_floorl.c  25 Jul 2011 16:20:09 -  1.2
+++ s_floorl.c  7 Feb 2014 14:43:19 -
@@ -38,7 +38,7 @@ floorl(long double x)
if(huge+x0.0) {/* return 0*sign(x) if |x|1 */
if(sx==0) {se=0;i0=i1=0;}
else if(((se0x7fff)|i0|i1)!=0)
-   { se=0xbfff;i0=i1=0;}
+   { se=0xbfff;i0=0x8000;i1=0;}
}
} else {
i = (0x7fff)jj0;



Re: exp() / expl() on Linux and OpenBSD (expl() bug?)

2014-02-07 Thread David Coppa
On Fri, Feb 7, 2014 at 3:49 PM, Mark Kettenis mark.kette...@xs4all.nl wrote:
 Date: Thu, 6 Feb 2014 23:07:58 -0800
 From: Martynas Venckus marty...@venck.us

 Yup.Does this diff fix it for you?

 Here's a diff that sticks a bit closer to the original code.  It's
 equivalent to your diff, and admittedly purely a matter of taste which
 version to prefer.

 Index: s_floorl.c
 ===
 RCS file: /home/cvs/src/lib/libm/src/ld80/s_floorl.c,v
 retrieving revision 1.2
 diff -u -p -r1.2 s_floorl.c
 --- s_floorl.c  25 Jul 2011 16:20:09 -  1.2
 +++ s_floorl.c  7 Feb 2014 14:43:19 -
 @@ -38,7 +38,7 @@ floorl(long double x)
 if(huge+x0.0) {/* return 0*sign(x) if |x|1 */
 if(sx==0) {se=0;i0=i1=0;}
 else if(((se0x7fff)|i0|i1)!=0)
 -   { se=0xbfff;i0=i1=0;}
 +   { se=0xbfff;i0=0x8000;i1=0;}
 }
 } else {
 i = (0x7fff)jj0;


Just tested, and this one works too, of course...

I'd be happy if this or the other one could be committed.

ciao,
David



Re: exp() / expl() on Linux and OpenBSD (expl() bug?)

2014-02-06 Thread Donovan Watteau
David Coppa wrote:
 Take the following reduced test-case, adapted from what R's code
 does:
 
 ---8---
 
 #include stdio.h
 #include stdlib.h
 #include math.h
 
 int main(void) {
   double theta = 1;
   long double lambda, pr, pr2;
 
   lambda = (0.5*theta);
   pr = exp(-lambda);
   pr2 = expl(-lambda);
 
   printf(theta == %g, pr == %Lg, pr2 == %Lg\n, theta, pr, pr2);
   exit(0);
 }
 
 ---8---
 
 This produces the following output on Linux (x86_64):
 
 theta == 1, pr == 0.606531, pr2 == 0.606531
 
 While on OpenBSD -current amd64:
 
 theta == 1, pr == 0.606531, pr2 == nan

FWIW, it looks even stranger on loongson:

$ cc -o expl expl.c -O2 -pipe -lm
$ ./expl
theta == 1, pr == -9.15569e-2474, pr2 == 6.10667e-4944
$ ./expl
theta == 1, pr == 0.606531, pr2 == 0.606531
$ ./expl
theta == 1, pr == -9.15569e-2474, pr2 == 6.10667e-4944

$ sysctl kern.version
kern.version=OpenBSD 5.5-beta (GENERIC) #106: Mon Feb  3 01:47:15 MST 2014
t...@loongson.openbsd.org:/usr/src/sys/arch/loongson/compile/GENERIC



Re: exp() / expl() on Linux and OpenBSD (expl() bug?)

2014-02-06 Thread Daniel Dickman
I think I recently ran into a similar issue but I suspect the root cause might 
be the same. I think the floorl function is wrong for numbers slightly larger 
than -1 to numbers slightly below 0. In this range floorl returns -0 instead of 
-1.

 On Feb 5, 2014, at 3:57 AM, David Coppa dco...@openbsd.org wrote:
 
 
 Hi!
 
 I hit this problem while working on updating math/R from version
 2.15.3 to the latest version (3.0.2).
 
 It started happening since upstream switched from double functions
 to C99 long double functions (expl, fabsl, ...), during the R-3
 development cycle.
 
 Take the following reduced test-case, adapted from what R's code
 does:
 
 ---8---
 
 #include stdio.h
 #include stdlib.h
 #include math.h
 
 int main(void) {
double theta = 1;
long double lambda, pr, pr2;
 
lambda = (0.5*theta);
pr = exp(-lambda);
pr2 = expl(-lambda);
 
printf(theta == %g, pr == %Lg, pr2 == %Lg\n, theta, pr, pr2);
exit(0);
 }
 
 ---8---
 
 This produces the following output on Linux (x86_64):
 
 theta == 1, pr == 0.606531, pr2 == 0.606531
 
 While on OpenBSD -current amd64:
 
 theta == 1, pr == 0.606531, pr2 == nan
 
 And indeed R-3's testsuite fails with the error message
 NaNs produced:
 
 Warning in pchisq(1e-300, df = 0, ncp = lam) : NaNs produced
 stopifnot(all.equal(p00, exp(-lam/2)),
 +   all.equal(p.0, exp(-lam/2)))
 Error: all.equal(p.0, exp(-lam/2)) is not TRUE
 Execution halted
 
 Is this a bug in our expl() ?
 
 Ciao,
 David
 



Re: exp() / expl() on Linux and OpenBSD (expl() bug?)

2014-02-06 Thread Martynas Venckus
Yup.Does this diff fix it for you?

On 2/6/14, Daniel Dickman didick...@gmail.com wrote:
 I think I recently ran into a similar issue but I suspect the root cause
 might be the same. I think the floorl function is wrong for numbers slightly
 larger than -1 to numbers slightly below 0. In this range floorl returns -0
 instead of -1.

 On Feb 5, 2014, at 3:57 AM, David Coppa dco...@openbsd.org wrote:


 Hi!

 I hit this problem while working on updating math/R from version
 2.15.3 to the latest version (3.0.2).

 It started happening since upstream switched from double functions
 to C99 long double functions (expl, fabsl, ...), during the R-3
 development cycle.

 Take the following reduced test-case, adapted from what R's code
 does:

 ---8---

 #include stdio.h
 #include stdlib.h
 #include math.h

 int main(void) {
double theta = 1;
long double lambda, pr, pr2;

lambda = (0.5*theta);
pr = exp(-lambda);
pr2 = expl(-lambda);

printf(theta == %g, pr == %Lg, pr2 == %Lg\n, theta, pr, pr2);
exit(0);
 }

 ---8---

 This produces the following output on Linux (x86_64):

 theta == 1, pr == 0.606531, pr2 == 0.606531

 While on OpenBSD -current amd64:

 theta == 1, pr == 0.606531, pr2 == nan

 And indeed R-3's testsuite fails with the error message
 NaNs produced:

 Warning in pchisq(1e-300, df = 0, ncp = lam) : NaNs produced
 stopifnot(all.equal(p00, exp(-lam/2)),
 +   all.equal(p.0, exp(-lam/2)))
 Error: all.equal(p.0, exp(-lam/2)) is not TRUE
 Execution halted

 Is this a bug in our expl() ?

 Ciao,
 David


Index: s_floorl.c
===
RCS file: /cvs/src/lib/libm/src/ld80/s_floorl.c,v
retrieving revision 1.2
diff -u -r1.2 s_floorl.c
--- s_floorl.c  25 Jul 2011 16:20:09 -  1.2
+++ s_floorl.c  7 Feb 2014 07:01:59 -
@@ -35,10 +35,12 @@
jj0 = (se0x7fff)-0x3fff;
if(jj031) {
if(jj00) { /* raise inexact if x != 0 */
-   if(huge+x0.0) {/* return 0*sign(x) if |x|1 */
-   if(sx==0) {se=0;i0=i1=0;}
-   else if(((se0x7fff)|i0|i1)!=0)
-   { se=0xbfff;i0=i1=0;}
+   if(huge+x0.0) {
+   if(sx==0) {
+return 0.0L;
+} else if(((se0x7fff)|i0|i1)!=0) {
+   return -1.0L;
+}
}
} else {
i = (0x7fff)jj0;


exp() / expl() on Linux and OpenBSD (expl() bug?)

2014-02-05 Thread David Coppa

Hi!

I hit this problem while working on updating math/R from version
2.15.3 to the latest version (3.0.2).

It started happening since upstream switched from double functions
to C99 long double functions (expl, fabsl, ...), during the R-3
development cycle.

Take the following reduced test-case, adapted from what R's code
does:

---8---

#include stdio.h
#include stdlib.h
#include math.h

int main(void) {
double theta = 1;
long double lambda, pr, pr2;

lambda = (0.5*theta);
pr = exp(-lambda);
pr2 = expl(-lambda);

printf(theta == %g, pr == %Lg, pr2 == %Lg\n, theta, pr, pr2);
exit(0);
}

---8---

This produces the following output on Linux (x86_64):

theta == 1, pr == 0.606531, pr2 == 0.606531

While on OpenBSD -current amd64:

theta == 1, pr == 0.606531, pr2 == nan

And indeed R-3's testsuite fails with the error message
NaNs produced:

Warning in pchisq(1e-300, df = 0, ncp = lam) : NaNs produced
 stopifnot(all.equal(p00, exp(-lam/2)),
+   all.equal(p.0, exp(-lam/2)))
Error: all.equal(p.0, exp(-lam/2)) is not TRUE
Execution halted

Is this a bug in our expl() ?

Ciao,
David



Re: exp() / expl() on Linux and OpenBSD (expl() bug?)

2014-02-05 Thread Mark Kettenis
 Date: Wed, 5 Feb 2014 01:57:33 -0700
 From: David Coppa dco...@openbsd.org
 
 Hi!
 
 I hit this problem while working on updating math/R from version
 2.15.3 to the latest version (3.0.2).
 
 It started happening since upstream switched from double functions
 to C99 long double functions (expl, fabsl, ...), during the R-3
 development cycle.
 
 Take the following reduced test-case, adapted from what R's code
 does:
 
 ---8---
 
 #include stdio.h
 #include stdlib.h
 #include math.h
 
 int main(void) {
   double theta = 1;
   long double lambda, pr, pr2;
 
   lambda = (0.5*theta);
   pr = exp(-lambda);
   pr2 = expl(-lambda);
 
   printf(theta == %g, pr == %Lg, pr2 == %Lg\n, theta, pr, pr2);
   exit(0);
 }
 
 ---8---
 
 This produces the following output on Linux (x86_64):
 
 theta == 1, pr == 0.606531, pr2 == 0.606531
 
 While on OpenBSD -current amd64:
 
 theta == 1, pr == 0.606531, pr2 == nan
 
 And indeed R-3's testsuite fails with the error message
 NaNs produced:
 
 Warning in pchisq(1e-300, df = 0, ncp = lam) : NaNs produced
  stopifnot(all.equal(p00, exp(-lam/2)),
 +   all.equal(p.0, exp(-lam/2)))
 Error: all.equal(p.0, exp(-lam/2)) is not TRUE
 Execution halted
 
 Is this a bug in our expl() ?

Yes.



Re: exp() / expl() on Linux and OpenBSD (expl() bug?)

2014-02-05 Thread Mark Kettenis
 Date: Wed, 5 Feb 2014 01:57:33 -0700
 From: David Coppa dco...@openbsd.org
 
 
 Hi!
 
 I hit this problem while working on updating math/R from version
 2.15.3 to the latest version (3.0.2).
 
 It started happening since upstream switched from double functions
 to C99 long double functions (expl, fabsl, ...), during the R-3
 development cycle.
 
 Take the following reduced test-case, adapted from what R's code
 does:
 
 ---8---
 
 #include stdio.h
 #include stdlib.h
 #include math.h
 
 int main(void) {
   double theta = 1;
   long double lambda, pr, pr2;
 
   lambda = (0.5*theta);
   pr = exp(-lambda);
   pr2 = expl(-lambda);
 
   printf(theta == %g, pr == %Lg, pr2 == %Lg\n, theta, pr, pr2);
   exit(0);
 }
 
 ---8---
 
 This produces the following output on Linux (x86_64):
 
 theta == 1, pr == 0.606531, pr2 == 0.606531
 
 While on OpenBSD -current amd64:
 
 theta == 1, pr == 0.606531, pr2 == nan
 
 And indeed R-3's testsuite fails with the error message
 NaNs produced:
 
 Warning in pchisq(1e-300, df = 0, ncp = lam) : NaNs produced
  stopifnot(all.equal(p00, exp(-lam/2)),
 +   all.equal(p.0, exp(-lam/2)))
 Error: all.equal(p.0, exp(-lam/2)) is not TRUE
 Execution halted
 
 Is this a bug in our expl() ?

Oh, btw, the quad-precision code used on sparc64 gets this right.  So
the bug is probably somewhere in src/lib/limb/src/ld80.