NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: port-amd64/45391: pow(3) wrong result for x = 0.0 and y < 0



The following reply was made to PR port-amd64/45391; it has been noted by GNATS.

From: David Holland <dholland-bugs%netbsd.org@localhost>
To: gnats-bugs%netbsd.org@localhost, tech-userlevel%netbsd.org@localhost
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@localhost
 


Home | Main Index | Thread Index | Old Index