tech-userlevel 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
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