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

NetBSD Home
NetBSD PR Database Search

(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.