Re: exp2(3) bug?

2014-06-02 Thread Benjamin Baier
You might want to read up on floating point arithmetic. (rounding and 
representation)


On 06/02/14 05:13, Daniel Dickman wrote:

I hit this problem while working with the numpy 1.8.1 regress suite
which has some tests that are currently failing.

Here is a reduced test case of the logaddexp2 python function which
ends up calling exp2. Is this a bug in the openbsd exp2
implementation?

---8---
#include stdio.h
#include stdlib.h
#include math.h

int main(void) {
 double x;
 double y;

 // x = log2(5)
 x = 2.32192809489;
 // y = 2**(log2(5))
 y = exp2(x);

 printf(expected: 5.0\n);
 printf(actual:   %f\n, y);

---8---

on a linux/x86_64 machine:

# gcc -lm test.c  ./a.out
expected: 5.0
actual:   5.00

on an openbsd/i386 machine:

# gcc -lm test.c  ./a.out
expected: 5.0
actual:   4.994404





Re: exp2(3) bug?

2014-06-02 Thread Mark Kettenis
 Date: Mon, 02 Jun 2014 09:34:20 +0200
 From: Benjamin Baier program...@netzbasis.de
 
 You might want to read up on floating point arithmetic. (rounding and 
 representation)

Well, the difference between 4.994404 and 5.0 is a bit large to blame
rounding and binary representation.  And other OpenBSD platforms
(amd64, sparc64, powerpc) return the expected result.  So I'd say that
there is a bug in the i386-specific implementation of exp2(3).

 On 06/02/14 05:13, Daniel Dickman wrote:
  I hit this problem while working with the numpy 1.8.1 regress suite
  which has some tests that are currently failing.
 
  Here is a reduced test case of the logaddexp2 python function which
  ends up calling exp2. Is this a bug in the openbsd exp2
  implementation?
 
  ---8---
  #include stdio.h
  #include stdlib.h
  #include math.h
 
  int main(void) {
   double x;
   double y;
 
   // x = log2(5)
   x = 2.32192809489;
   // y = 2**(log2(5))
   y = exp2(x);
 
   printf(expected: 5.0\n);
   printf(actual:   %f\n, y);
 
  ---8---
 
  on a linux/x86_64 machine:
 
  # gcc -lm test.c  ./a.out
  expected: 5.0
  actual:   5.00
 
  on an openbsd/i386 machine:
 
  # gcc -lm test.c  ./a.out
  expected: 5.0
  actual:   4.994404
 
 
 



Re: exp2(3) bug?

2014-06-02 Thread Benjamin Baier
Ok i might have been quick to judge, because i don't really trust 
floating point arithmetic.


btw. exp2f works correct on i386.

On 06/02/14 10:17, Mark Kettenis wrote:

Date: Mon, 02 Jun 2014 09:34:20 +0200
From: Benjamin Baier program...@netzbasis.de

You might want to read up on floating point arithmetic. (rounding and
representation)


Well, the difference between 4.994404 and 5.0 is a bit large to blame
rounding and binary representation.  And other OpenBSD platforms
(amd64, sparc64, powerpc) return the expected result.  So I'd say that
there is a bug in the i386-specific implementation of exp2(3).


On 06/02/14 05:13, Daniel Dickman wrote:

I hit this problem while working with the numpy 1.8.1 regress suite
which has some tests that are currently failing.

Here is a reduced test case of the logaddexp2 python function which
ends up calling exp2. Is this a bug in the openbsd exp2
implementation?

---8---
#include stdio.h
#include stdlib.h
#include math.h

int main(void) {
  double x;
  double y;

  // x = log2(5)
  x = 2.32192809489;
  // y = 2**(log2(5))
  y = exp2(x);

  printf(expected: 5.0\n);
  printf(actual:   %f\n, y);

---8---

on a linux/x86_64 machine:

# gcc -lm test.c  ./a.out
expected: 5.0
actual:   5.00

on an openbsd/i386 machine:

# gcc -lm test.c  ./a.out
expected: 5.0
actual:   4.994404








Re: exp2(3) bug?

2014-06-02 Thread Mark Kettenis
 Date: Mon, 2 Jun 2014 10:17:53 +0200 (CEST)
 From: Mark Kettenis mark.kette...@xs4all.nl
 
  Date: Mon, 02 Jun 2014 09:34:20 +0200
  From: Benjamin Baier program...@netzbasis.de
  
  You might want to read up on floating point arithmetic. (rounding and 
  representation)
 
 Well, the difference between 4.994404 and 5.0 is a bit large to blame
 rounding and binary representation.  And other OpenBSD platforms
 (amd64, sparc64, powerpc) return the expected result.  So I'd say that
 there is a bug in the i386-specific implementation of exp2(3).

And here is a fix.  There actually isn't any i386-specific code, but
i386 is special and needs STRICT_ALIGN() to work properly for double
as well as float.  FreeBSD made the same change a while ago:

http://svnweb.FreeBSD.org/base/head/lib/msun/src/math_private.h?revision=240827view=markup

Haven't run the regression tests yet with this change.


Index: src/math_private.h
===
RCS file: /cvs/src/lib/libm/src/math_private.h,v
retrieving revision 1.16
diff -u -p -r1.16 math_private.h
--- src/math_private.h  12 Nov 2013 20:35:09 -  1.16
+++ src/math_private.h  2 Jun 2014 09:30:13 -
@@ -349,7 +349,7 @@ do {
\
 #defineSTRICT_ASSIGN(type, lval, rval) do {\
volatile type __lval;   \
\
-   if (sizeof(type) = sizeof(double)) \
+   if (sizeof(type) = sizeof(long double))\
(lval) = (rval);\
else {  \
__lval = (rval);\



Re: exp2(3) bug?

2014-06-02 Thread Daniel Dickman
Hi Benjamin,

On Mon, Jun 2, 2014 at 3:34 AM, Benjamin Baier program...@netzbasis.de wrote:
 You might want to read up on floating point arithmetic. (rounding and
 representation)


The error in floating point calculations is typically measured in
ulps. The error shown in this example is far too big for the
existing calculation to be correct. I'm linking to the wikipedia
article for some background reading for you but there's a lot more
info on the web on this topic:
http://en.wikipedia.org/wiki/Unit_in_the_last_place



 On 06/02/14 05:13, Daniel Dickman wrote:

 I hit this problem while working with the numpy 1.8.1 regress suite
 which has some tests that are currently failing.

 Here is a reduced test case of the logaddexp2 python function which
 ends up calling exp2. Is this a bug in the openbsd exp2
 implementation?

 ---8---
 #include stdio.h
 #include stdlib.h
 #include math.h

 int main(void) {
  double x;
  double y;

  // x = log2(5)
  x = 2.32192809489;
  // y = 2**(log2(5))
  y = exp2(x);

  printf(expected: 5.0\n);
  printf(actual:   %f\n, y);

 ---8---

 on a linux/x86_64 machine:

 # gcc -lm test.c  ./a.out
 expected: 5.0
 actual:   5.00

 on an openbsd/i386 machine:

 # gcc -lm test.c  ./a.out
 expected: 5.0
 actual:   4.994404





Re: exp2(3) bug?

2014-06-02 Thread Daniel Dickman
On Mon, Jun 2, 2014 at 5:33 AM, Mark Kettenis mark.kette...@xs4all.nl wrote:
 Date: Mon, 2 Jun 2014 10:17:53 +0200 (CEST)
 From: Mark Kettenis mark.kette...@xs4all.nl

  Date: Mon, 02 Jun 2014 09:34:20 +0200
  From: Benjamin Baier program...@netzbasis.de
 
  You might want to read up on floating point arithmetic. (rounding and
  representation)

 Well, the difference between 4.994404 and 5.0 is a bit large to blame
 rounding and binary representation.  And other OpenBSD platforms
 (amd64, sparc64, powerpc) return the expected result.  So I'd say that
 there is a bug in the i386-specific implementation of exp2(3).

 And here is a fix.  There actually isn't any i386-specific code, but
 i386 is special and needs STRICT_ALIGN() to work properly for double
 as well as float.  FreeBSD made the same change a while ago:


Fixes my test case and the numpy test. So ok daniel@ for what it's worth...


 http://svnweb.FreeBSD.org/base/head/lib/msun/src/math_private.h?revision=240827view=markup

 Haven't run the regression tests yet with this change.


 Index: src/math_private.h
 ===
 RCS file: /cvs/src/lib/libm/src/math_private.h,v
 retrieving revision 1.16
 diff -u -p -r1.16 math_private.h
 --- src/math_private.h  12 Nov 2013 20:35:09 -  1.16
 +++ src/math_private.h  2 Jun 2014 09:30:13 -
 @@ -349,7 +349,7 @@ do {  
   \
  #defineSTRICT_ASSIGN(type, lval, rval) do {\
 volatile type __lval;   \
 \
 -   if (sizeof(type) = sizeof(double)) \
 +   if (sizeof(type) = sizeof(long double))\
 (lval) = (rval);\
 else {  \
 __lval = (rval);\



Re: exp2(3) bug?

2014-06-02 Thread Martynas Venckus
On 6/2/14, Mark Kettenis mark.kette...@xs4all.nl wrote:
 Date: Mon, 2 Jun 2014 10:17:53 +0200 (CEST)
 From: Mark Kettenis mark.kette...@xs4all.nl

  Date: Mon, 02 Jun 2014 09:34:20 +0200
  From: Benjamin Baier program...@netzbasis.de
 
  You might want to read up on floating point arithmetic. (rounding and
  representation)

 Well, the difference between 4.994404 and 5.0 is a bit large to blame
 rounding and binary representation.  And other OpenBSD platforms
 (amd64, sparc64, powerpc) return the expected result.  So I'd say that
 there is a bug in the i386-specific implementation of exp2(3).

 And here is a fix.  There actually isn't any i386-specific code, but
 i386 is special and needs STRICT_ALIGN() to work properly for double
 as well as float.  FreeBSD made the same change a while ago:

 http://svnweb.FreeBSD.org/base/head/lib/msun/src/math_private.h?revision=240827view=markup

You are quick.  Thanks for figuring this out.

Ugh ... it was intentionally left broken as an optimization.  That's crazy.

OK martynas@.

 Haven't run the regression tests yet with this change.


 Index: src/math_private.h
 ===
 RCS file: /cvs/src/lib/libm/src/math_private.h,v
 retrieving revision 1.16
 diff -u -p -r1.16 math_private.h
 --- src/math_private.h12 Nov 2013 20:35:09 -  1.16
 +++ src/math_private.h2 Jun 2014 09:30:13 -
 @@ -349,7 +349,7 @@ do {  
 \
  #define  STRICT_ASSIGN(type, lval, rval) do {\
   volatile type __lval;   \
   \
 - if (sizeof(type) = sizeof(double)) \
 + if (sizeof(type) = sizeof(long double))\
   (lval) = (rval);\
   else {  \
   __lval = (rval);\