NetBSD Problem Report #45391
From njoly@lanfeust.sis.pasteur.fr Thu Sep 22 13:51:37 2011
Return-Path: <njoly@lanfeust.sis.pasteur.fr>
Received: from mail.netbsd.org (mail.netbsd.org [204.152.190.11])
by www.NetBSD.org (Postfix) with ESMTP id 6D5A063C411
for <gnats-bugs@gnats.NetBSD.org>; Thu, 22 Sep 2011 13:51:37 +0000 (UTC)
Message-Id: <20110922123447.2A781DC9BD@lanfeust.sis.pasteur.fr>
Date: Thu, 22 Sep 2011 14:34:47 +0200 (CEST)
From: njoly@pasteur.fr
Reply-To: njoly@pasteur.fr
To: gnats-bugs@gnats.NetBSD.org
Subject: pow(3) wrong result for x = 0.0 and y < 0
X-Send-Pr-Version: 3.95
>Number: 45391
>Category: port-amd64
>Synopsis: pow(3) wrong result for x = 0.0 and y < 0
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: port-amd64-maintainer
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Thu Sep 22 13:55:00 +0000 2011
>Last-Modified: Wed Sep 09 04:45:00 +0000 2015
>Originator: Nicolas Joly
>Release: NetBSD 5.99.55
>Organization:
Institut Pasteur
>Environment:
System: NetBSD lanfeust.sis.pasteur.fr 5.99.55 NetBSD 5.99.55 (LANFEUST) #0: Wed Sep 21 22:29:04 CEST 2011 njoly@lanfeust.sis.pasteur.fr:/local/src/NetBSD/obj.amd64/sys/arch/amd64/compile/LANFEUST amd64
Architecture: x86_64
Machine: amd64
>Description:
According to the OpenGroup online document for pow(3)[1]; for x = 0.0 and
y < 0 the result should be HUGE_VAL, but its sign depends on both sign of
x and odd/even property of y. Currently, at least on amd64, the result
is always -HUGE_VAL.
The following sample code do succeed on NetBSD/alpha, FreeBSD/amd64,
Linux/x86_64 (native and compat32) but fail on NetBSD/amd64 (native
and compat32).
njoly@lanfeust [netbsd/math]> cat pow.c
#include <assert.h>
#include <math.h>
int main() {
double d;
d = pow(+0.0, -4.0);
assert(d == HUGE_VAL);
d = pow(-0.0, -4.0);
assert(d == HUGE_VAL);
d = pow(+0.0, -5.0);
assert(d == +HUGE_VAL);
d = pow(-0.0, -5.0);
assert(d == -HUGE_VAL);
return 0; }
njoly@lanfeust [netbsd/math]> cc -g -lm -o pow pow.c
njoly@lanfeust [netbsd/math]> ./pow
assertion "d == HUGE_VAL" failed: file "pow.c", line 9, function "main"
zsh: abort (core dumped) ./pow
njoly@lanfeust [netbsd/math]> cc -m32 -g -lm -o pow pow.c
njoly@lanfeust [netbsd/math]> ./pow
assertion "d == HUGE_VAL" failed: file "pow.c", line 9, function "main"
zsh: abort (core dumped) ./pow
[1] http://pubs.opengroup.org/onlinepubs/009604599/functions/pow.html
>How-To-Repeat:
Check the above code on amd64 and possibly other arches.
>Fix:
please.
>Audit-Trail:
From: "Jukka Ruohonen" <jruoho@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc:
Subject: PR/45391 CVS commit: src/tests/lib/libm
Date: Fri, 23 Sep 2011 13:48:29 +0000
Module Name: src
Committed By: jruoho
Date: Fri Sep 23 13:48:28 UTC 2011
Modified Files:
src/tests/lib/libm: t_pow.c
Log Message:
More bugs in pow(3); cases for PR port-amd64/45391.
To generate a diff of this commit:
cvs rdiff -u -r1.1 -r1.2 src/tests/lib/libm/t_pow.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
From: David Holland <dholland-bugs@netbsd.org>
To: gnats-bugs@netbsd.org
Cc:
Subject: Re: port-amd64/45391: pow(3) wrong result for x = 0.0 and y < 0
Date: Sun, 22 Apr 2012 18:46:51 +0000
There is a candidate patch in PR 45755, which I'm closing as a
duplicate.
This problem doesn't appear to be amd64-specific. Is there any reason
it shouldn't be switched to category 'lib'?
(and is there any reason not to commit the patch in PR 45755?)
--
David A. Holland
dholland@netbsd.org
From: "NARUSE, Yui" <naruse@airemix.jp>
To: gnats-bugs@netbsd.org
Cc:
Subject: Re: port-amd64/45391: pow(3) wrong result for x = 0.0 and y < 0
Date: Tue, 15 May 2012 09:25:38 +0900
Hi,
I reported a duplicated pr, lib/45755, and attached a patch.
But I noticed it is wrong.
I show a correct patch as below.
It makes related tests pass.
Thanks,
Index: lib/libm/src/k_standard.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvsroot/src/lib/libm/src/k_standard.c,v
retrieving revision 1.17
diff -u -r1.17 k_standard.c
--- lib/libm/src/k_standard.c 11 Apr 2011 15:17:33 -0000 1.17
+++ lib/libm/src/k_standard.c 15 May 2012 00:24:07 -0000
@@ -469,7 +469,7 @@
if (_LIB_VERSION =3D=3D _SVID_)
exc.retval =3D zero;
else
- exc.retval =3D -HUGE_VAL;
+ exc.retval =3D HUGE_VAL;
if (_LIB_VERSION =3D=3D _POSIX_)
errno =3D EDOM;
else if (!matherr(&exc)) {
--=20
NARUSE, Yui =A0<naruse@airemix.jp>
From: David Holland <dholland-bugs@netbsd.org>
To: gnats-bugs@NetBSD.org
Cc:
Subject: Re: port-amd64/45391: pow(3) wrong result for x = 0.0 and y < 0
Date: Mon, 7 Oct 2013 05:29:02 +0000
On Tue, May 15, 2012 at 12:30:05AM +0000, NARUSE, Yui wrote:
> Hi,
>
> I reported a duplicated pr, lib/45755, and attached a patch.
> But I noticed it is wrong.
>
> I show a correct patch as below.
> It makes related tests pass.
This has still not been committed; is there any reason I shouldn't
go ahead and commit?
--
David A. Holland
dholland@netbsd.org
From: "David A. Holland" <dholland@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc:
Subject: PR/45391 CVS commit: src/lib/libm/src
Date: Tue, 8 Sep 2015 05:23:31 +0000
Module Name: src
Committed By: dholland
Date: Tue Sep 8 05:23:31 UTC 2015
Modified Files:
src/lib/libm/src: k_standard.c
Log Message:
Apply patch in PR 45391 from Yui NARUSE: generate HUGE_VAL rather than
-HUGE_VAL for 0^negative. No objection after asking nearly two years
ago if I shouldn't just commit it.
To generate a diff of this commit:
cvs rdiff -u -r1.19 -r1.20 src/lib/libm/src/k_standard.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
From: "David A. Holland" <dholland@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc:
Subject: PR/45391 CVS commit: src/tests/lib/libm
Date: Tue, 8 Sep 2015 05:24:28 +0000
Module Name: src
Committed By: dholland
Date: Tue Sep 8 05:24:27 UTC 2015
Modified Files:
src/tests/lib/libm: t_pow.c
Log Message:
Clear the XFAIL from PR 45391.
To generate a diff of this commit:
cvs rdiff -u -r1.3 -r1.4 src/tests/lib/libm/t_pow.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
From: David Holland <dholland-bugs@netbsd.org>
To: gnats-bugs@netbsd.org, tech-userlevel@netbsd.org
Cc:
Subject: Re: port-amd64/45391: pow(3) wrong result for x = 0.0 and y < 0
Date: Tue, 8 Sep 2015 08:29:14 +0000
On Mon, Oct 07, 2013 at 05:30:00AM +0000, David Holland wrote:
> On Tue, May 15, 2012 at 12:30:05AM +0000, NARUSE, Yui wrote:
> > Hi,
> >
> > I reported a duplicated pr, lib/45755, and attached a patch.
> > But I noticed it is wrong.
> >
> > I show a correct patch as below.
> > It makes related tests pass.
>
> This has still not been committed; is there any reason I shouldn't
> go ahead and commit?
So, it turns out to cause other cases to fail. The following
additional (gross) change is needed to get all the right answers out.
Should I commit this, or revert?
Index: src/w_pow.c
===================================================================
RCS file: /cvsroot/src/lib/libm/src/w_pow.c,v
retrieving revision 1.7
diff -u -p -r1.7 w_pow.c
--- src/w_pow.c 26 May 2002 22:02:02 -0000 1.7
+++ src/w_pow.c 8 Sep 2015 08:25:42 -0000
@@ -43,8 +43,26 @@ pow(double x, double y) /* wrapper pow *
if(x==0.0){
if(y==0.0)
return __kernel_standard(x,y,20); /* pow(0.0,0.0) */
- if(finite(y)&&y<0.0)
- return __kernel_standard(x,y,23); /* pow(0.0,negative) */
+ if(finite(y)&&y<0.0) {
+ double z2;
+
+ /*
+ * -0^even is supposed to generate +HUGE_VAL;
+ * -0^odd is supposed to generate -HUGE_VAL.
+ *
+ * __kernel_standard doesn't know this and yields
+ * positive HUGE_VAL by default in both cases.
+ *
+ * However, __ieee754_pow produces what we want, and
+ * contains the not-entirely-trivial logic to check if
+ * y is odd, so if __kernel_standard yields HUGE_VAL
+ * return the original result instead; that will be
+ * -HUGE_VAL in the right cases.
+ */
+ z2 = __kernel_standard(x,y,23); /* pow(0.0,negative) */
+ if (z2 != HUGE_VAL)
+ return z2;
+ }
return z;
}
if(!finite(z)) {
Index: src/w_powf.c
===================================================================
RCS file: /cvsroot/src/lib/libm/src/w_powf.c,v
retrieving revision 1.6
diff -u -p -r1.6 w_powf.c
--- src/w_powf.c 26 May 2002 22:02:02 -0000 1.6
+++ src/w_powf.c 8 Sep 2015 08:25:42 -0000
@@ -46,9 +46,15 @@ powf(float x, float y) /* wrapper powf *
if(y==(float)0.0)
/* powf(0.0,0.0) */
return (float)__kernel_standard((double)x,(double)y,120);
- if(finitef(y)&&y<(float)0.0)
+ if(finitef(y)&&y<(float)0.0) {
/* powf(0.0,negative) */
- return (float)__kernel_standard((double)x,(double)y,123);
+ double z2;
+
+ /* see analogous case in w_pow.c */
+ z2 = __kernel_standard((double)x,(double)y,123);
+ if (z2 != HUGE_VAL)
+ return (float)z2;
+ }
return z;
}
if(!finitef(z)) {
--
David A. Holland
dholland@netbsd.org
From: David Holland <dholland-tech@netbsd.org>
To: gnats-bugs@netbsd.org, tech-userlevel@netbsd.org
Cc:
Subject: Re: port-amd64/45391: pow(3) wrong result for x = 0.0 and y < 0
Date: Tue, 8 Sep 2015 08:41:55 +0000
On Tue, Sep 08, 2015 at 08:29:14AM +0000, David Holland wrote:
> On Mon, Oct 07, 2013 at 05:30:00AM +0000, David Holland wrote:
> > On Tue, May 15, 2012 at 12:30:05AM +0000, NARUSE, Yui wrote:
> > > Hi,
> > >
> > > I reported a duplicated pr, lib/45755, and attached a patch.
> > > But I noticed it is wrong.
> > >
> > > I show a correct patch as below.
> > > It makes related tests pass.
> >
> > This has still not been committed; is there any reason I shouldn't
> > go ahead and commit?
>
> So, it turns out to cause other cases to fail. The following
> additional (gross) change is needed to get all the right answers out.
>
> Should I commit this, or revert?
Also, what's pow(+/-0, non-integer) supposed to produce?
--
David A. Holland
dholland@netbsd.org
From: David Holland <dholland-tech@netbsd.org>
To: gnats-bugs@netbsd.org, tech-userlevel@netbsd.org
Cc:
Subject: Re: port-amd64/45391: pow(3) wrong result for x = 0.0 and y < 0
Date: Tue, 8 Sep 2015 16:03:54 +0000
On Tue, Sep 08, 2015 at 08:41:55AM +0000, David Holland wrote:
> Also, what's pow(+/-0, non-integer) supposed to produce?
Erm, that was supposed to be "negative non-integer"...
--
David A. Holland
dholland@netbsd.org
From: Taylor R Campbell <campbell+netbsd-tech-userlevel@mumble.net>
To: David Holland <dholland-tech@netbsd.org>
Cc: gnats-bugs@netbsd.org, tech-userlevel@netbsd.org
Subject: Re: port-amd64/45391: pow(3) wrong result for x = 0.0 and y < 0
Date: Tue, 8 Sep 2015 16:13:33 +0000
Date: Tue, 8 Sep 2015 16:03:54 +0000
From: David Holland <dholland-tech@netbsd.org>
On Tue, Sep 08, 2015 at 08:41:55AM +0000, David Holland wrote:
> Also, what's pow(+/-0, non-integer) supposed to produce?
Erm, that was supposed to be "negative non-integer"...
IEEE 754-2008, Sec. 9.2.1 `Special values', p. 45:
> For the pow function (integral exponents get special treatment):
> ...
> pow(+/-0, y) is +infinity and signals the divideByZero exception for =
finite y<0 and not an odd integer
From: David Holland <dholland-tech@netbsd.org>
To: Taylor R Campbell <campbell+netbsd-tech-userlevel@mumble.net>
Cc: David Holland <dholland-tech@netbsd.org>, gnats-bugs@netbsd.org,
tech-userlevel@netbsd.org
Subject: Re: port-amd64/45391: pow(3) wrong result for x = 0.0 and y < 0
Date: Wed, 9 Sep 2015 04:41:53 +0000
On Tue, Sep 08, 2015 at 04:13:33PM +0000, Taylor R Campbell wrote:
> Date: Tue, 8 Sep 2015 16:03:54 +0000
> From: David Holland <dholland-tech@netbsd.org>
>
> On Tue, Sep 08, 2015 at 08:41:55AM +0000, David Holland wrote:
> > Also, what's pow(+/-0, non-integer) supposed to produce?
>
> Erm, that was supposed to be "negative non-integer"...
>
> IEEE 754-2008, Sec. 9.2.1 `Special values', p. 45:
>
> > For the pow function (integral exponents get special treatment):
> > ...
> > pow(+/-0, y) is +infinity and signals the divideByZero exception for finite y<0 and not an odd integer
What our existing tests want is:
pow(+0.0, -4.0) == +HUGE_VAL
pow(-0.0, -4.0) == +HUGE_VAL
pow(+0.0, -5.0) == +HUGE_VAL
pow(-0.0, -5.0) == -HUGE_VAL
pow(+0.0, -4.5) == (not checked)
pow(-0.0, -4.5) == (not checked)
Before the commit I made last night, these all yield -HUGE_VAL. With
the commit, they all yield +HUGE_VAL. With the additional change I
proposed but didn't commit, the first four are as requested by the
existing tests, and the last two yield +HUGE_VAL.
I guess other than not signaling that's ok... maybe I should commit
that additional change after all. Although it's pretty gross. Or I
could revert the lot until someone has time to look at it more
carefully.
--
David A. Holland
dholland@netbsd.org
(Contact us)
$NetBSD: query-full-pr,v 1.39 2013/11/01 18:47:49 spz Exp $
$NetBSD: gnats_config.sh,v 1.8 2006/05/07 09:23:38 tsutsui Exp $
Copyright © 1994-2014
The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.