NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
lib/41931: log(-INFINITY) or log(-1.0) gives uexpected results
>Number: 41931
>Category: lib
>Synopsis: log(-INFINITY) or log(-1.0) gives uexpected results
>Confidential: no
>Severity: non-critical
>Priority: medium
>Responsible: lib-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Mon Aug 24 13:40:00 +0000 2009
>Originator: Havard Eidnes
>Release: NetBSD 5.0_RC3
>Organization:
I Try...
>Environment:
System: NetBSD smistad.uninett.no 5.0_RC3 NetBSD 5.0_RC3 (MAANEN) #4: Mon Mar
30 02:52:40 CEST 2009
he%maanen.uninett.no@localhost:/usr/obj/sys/arch/i386/compile/MAANEN i386
Architecture: i386
Machine: i386
>Description:
It appears that ANSI C specifies that log(-INFINITY) or
log(negative value) is supposed to return a NaN.
Instead, -INFINITY is returned.
>How-To-Repeat:
------------------------------
#include <math.h>
#include <stdio.h>
#include <errno.h>
/* Ref. a.o. http://www.ansic.net/showlog.php?id=31&res=log%20function */
int
main(int argc, char **argv)
{
double a, b;
a = INFINITY;
b = log(a);
printf("log(Inf) = %5f errno=%2d (expected: inf / %d)\n",
b, errno, 0);
a = -INFINITY;
b = log(a);
printf("log(-Inf) = %5f errno=%2d (expected: NaN / %d)\n",
b, errno, EDOM);
a = -1;
b = log(a);
printf("log(-1) = %5f errno=%2d (expected: NaN / %d)\n",
b, errno, EDOM);
return 0;
}
------------------------------
When run on my host, this program produces:
log(Inf) = inf errno= 0 (expected: inf / 0)
log(-Inf) = -inf errno=33 (expected: NaN / 33)
log(-1) = -inf errno=33 (expected: NaN / 33)
The same is the result when run on a sparc64/5.0 host.
I've looked at lib/libm/src/w_log.c, I think the __ieee754_log()
function is chosen, and I've looked at
lib/libm/src/e_log.c which implements that function, and
replicated the "hx/lx" extraction in my own code, and hx
definitely ends up as negative when -INFINITY is passed,
and a NaN results from the division by zero.
The comments in e_log.c even say:
* Special cases:
* log(x) is NaN with signal if x < 0 (including -INF) ;
* log(+INF) is +INF; log(0) is -INF with signal;
* log(NaN) is that NaN with no signal.
which conforms with the expected behaviour and with
section F.9.3.7 in ISO/IEC 9899 committee draft at
http://www.open-std.org/Jtc1/sc22/wg14/www/docs/n1124.pdf
My small test program:
------------------------------
#include <sys/types.h>
#include <math.h>
#include <stdio.h>
#if (BYTE_ORDER == BIG_ENDIAN) || (defined(__arm__) && !defined(__VFP_FP__))
typedef union
{
double value;
struct
{
u_int32_t msw;
u_int32_t lsw;
} parts;
} ieee_double_shape_type;
#endif
#if (BYTE_ORDER == LITTLE_ENDIAN) && \
!(defined(__arm__) && !defined(__VFP_FP__))
typedef union
{
double value;
struct
{
u_int32_t lsw;
u_int32_t msw;
} parts;
} ieee_double_shape_type;
#endif
/* Get two 32 bit ints from a double. */
#define EXTRACT_WORDS(ix0,ix1,d) \
do { \
ieee_double_shape_type ew_u; \
ew_u.value = (d); \
(ix0) = ew_u.parts.msw; \
(ix1) = ew_u.parts.lsw; \
} while (/*CONSTCOND*/0)
static const double zero = 0.0;
int
main(int argc, char **argv)
{
double a, b;
int32_t hx;
uint32_t lx;
a = -INFINITY;
printf("Decode of -INFINITY:\n");
EXTRACT_WORDS(hx, lx, a);
if (hx < 0) {
printf("hx < 0 (as expected)\n");
} else {
printf("hx >= 0 (NOT expected)\n");
}
a = -INFINITY;
b = (a-a)/zero;
printf("(-Inf - -Inf)/0.0 = %f (expected NaN)\n", b);
return 0;
}
------------------------------
which when run on my host produces
Decode of -INFINITY:
hx < 0 (as expected)
(-Inf - -Inf)/0.0 = nan (expected NaN)
(The root trigger of this problem was an attempted upgrade
of pkgsrc/lang/parrot to version 1.5.0, and a self-test tripped
over this unexpected result.)
>Fix:
Sorry, I don't know.
Home |
Main Index |
Thread Index |
Old Index