NetBSD-Bugs archive

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

lib/45755: pow(0.0, negative) returns wrong value



>Number:         45755
>Category:       lib
>Synopsis:       pow(0.0, negative) returns wrong value
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    lib-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Thu Dec 29 06:55:00 +0000 2011
>Originator:     Yui NARUSE
>Release:        NetBSD 5.99.56 i386
>Organization:
>Environment:
NetBSD nbsd.rubyci.org 5.99.56 NetBSD 5.99.56 (GENERIC) #0: Sat Nov 19 01:13:35 
JST 2011  root%nbsd.rubyci.org@localhost:/usr/obj/sys/arch/i386/compile/GENERIC 
i386
>Description:
POSIX says "For y < 0, if x is zero, a [CX]   pole  error may occur and pow(), 
powf(), and powl() shall return ±HUGE_VAL, ±HUGE_VALF, and ±HUGE_VALL, 
respectively. [MX]   On systems that support the IEC 60559 Floating-Point 
option, a pole error shall occur and pow(), powf(), and powl() shall return 
±HUGE_VAL, ±HUGE_VALF, and ±HUGE_VALL, respectively if y is an odd integer, or 
HUGE_VAL, HUGE_VALF, and HUGE_VALL, respectively if y is not an odd integer."
http://pubs.opengroup.org/onlinepubs/9699919799/functions/pow.html

So pow(0.0, negative) should return positive infinity other than pow(-0.0, 
negatieve odd) as following like IEEE754:
__ieee754_pow(0.0, -1): inf
__ieee754_pow(0.0, -2): inf
__ieee754_pow(-0.0, -1): -inf
__ieee754_pow(-0.0, -2): inf
But current implementation returns negative infinity other than pow(+0.0, 
positive odd):
pow(0.0, -1): inf
pow(0.0, -2): -inf
pow(-0.0, -1): -inf
pow(-0.0, -2): -inf
>How-To-Repeat:
% cat pow.c
#include <math.h>
#include <stdio.h>
double __ieee754_pow(double x, double y);
int main(void)
{
    fprintf(stderr,"LIB_VERSION: %d (POSIX: 2)\n",_LIB_VERSION);
    fprintf(stderr,"pow(0.0, -1): %f\n",pow(0.0, -1));
    fprintf(stderr,"pow(0.0, -2): %f\n",pow(0.0, -2));
    fprintf(stderr,"pow(-0.0, -1): %f\n",pow(-0.0, -1));
    fprintf(stderr,"pow(-0.0, -2): %f\n",pow(-0.0, -2));
    fprintf(stderr,"__ieee754_pow(0.0, -1): %f\n",__ieee754_pow(0.0, -1));
    fprintf(stderr,"__ieee754_pow(0.0, -2): %f\n",__ieee754_pow(0.0, -2));
    fprintf(stderr,"__ieee754_pow(-0.0, -1): %f\n",__ieee754_pow(-0.0, -1));
    fprintf(stderr,"__ieee754_pow(-0.0, -2): %f\n",__ieee754_pow(-0.0, -2));
    return 0;
}
% cc -lm pow.c&&./a.out
LIB_VERSION: 2 (POSIX: 2)
pow(0.0, -1): inf
pow(0.0, -2): -inf
pow(-0.0, -1): -inf
pow(-0.0, -2): -inf
__ieee754_pow(0.0, -1): inf
__ieee754_pow(0.0, -2): inf
__ieee754_pow(-0.0, -1): -inf
__ieee754_pow(-0.0, -2): inf
>Fix:
--- lib/libm/src/k_standard.c.orig        2011-12-29 15:02:55.000000000 +0900
+++ lib/libm/src/k_standard.c   2011-12-29 15:23:45.000000000 +0900
@@ -468,8 +468,6 @@ __kernel_standard(double x, double y, in
                exc.name = type < 100 ? "pow" : "powf";
                if (_LIB_VERSION == _SVID_)
                  exc.retval = zero;
-               else
-                 exc.retval = -HUGE_VAL;
                if (_LIB_VERSION == _POSIX_)
                  errno = EDOM;
                else if (!matherr(&exc)) {



Home | Main Index | Thread Index | Old Index