NetBSD Problem Report #41931

From he@smistad.uninett.no  Mon Aug 24 13:37:41 2009
Return-Path: <he@smistad.uninett.no>
Received: from mail.netbsd.org (mail.netbsd.org [204.152.190.11])
	by www.NetBSD.org (Postfix) with ESMTP id 23E7A63BDF9
	for <gnats-bugs@gnats.NetBSD.org>; Mon, 24 Aug 2009 13:37:41 +0000 (UTC)
Message-Id: <20090824133737.BB7A73D0A4@smistad.uninett.no>
Date: Mon, 24 Aug 2009 15:37:37 +0200 (CEST)
From: he@NetBSD.org
Reply-To: he@NetBSD.org
To: gnats-bugs@gnats.NetBSD.org
Subject: log(-INFINITY) or log(-1.0) gives uexpected results
X-Send-Pr-Version: 3.95

>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:          closed
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Mon Aug 24 13:40:00 +0000 2009
>Closed-Date:    Mon Apr 30 22:33:45 +0000 2012
>Last-Modified:  Mon Apr 30 22:33:45 +0000 2012
>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:/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.

>Release-Note:

>Audit-Trail:
From: Havard Eidnes <he@NetBSD.org>
To: lib-bug-people@netbsd.org
Cc: gnats-bugs@netbsd.org, netbsd-bugs@netbsd.org
Subject: Re: lib/41931: log(-INFINITY) or log(-1.0) gives uexpected results
Date: Tue, 25 Aug 2009 00:39:21 +0200 (CEST)

 SGksDQoNCm1vcmUgaW5mbyBvbiB0aGlzLiAgSSB0aGluayBJJ3ZlIGNvbWUgYSBiaXQgY2xvc2Vy
 IHRvIHVuZGVyc3RhbmRpbmcNCndoYXQncyBoYXBwZW5pbmcuDQoNCkFjY29yZGluZyB0byBsaWIv
 bGlibS9NYWtlZmlsZSwgZm9yIG5vbi12YXggaG9zdHMsIGEgX01VTFRJX0xJQk0NCmlzIGJ1aWx0
 LCBhbmQgaXQncyBvZiB0aGUgX1BPU0lYX01PREUgdmFyaWV0eS4NCg0KVGhpcyBtZWFucyB0aGF0
 IGxpYi9saWJtL3NyYy93X2xvZy5jIGJ1aWxkcyB0aGUgImxvbmdlciIgdmVyc2lvbiwNCndoaWNo
 IGxvb2tzIGxpa2UgdGhpczoNCg0KICAgICAgICBkb3VibGUgejsNCiAgICAgICAgeiA9IF9faWVl
 ZTc1NF9sb2coeCk7DQogICAgICAgIGlmKF9MSUJfVkVSU0lPTiA9PSBfSUVFRV8gfHwgaXNuYW4o
 eCkgfHwgeCA+IDAuMCkgcmV0dXJuIHo7DQogICAgICAgIGlmKHg9PTAuMCkNCiAgICAgICAgICAg
 IHJldHVybiBfX2tlcm5lbF9zdGFuZGFyZCh4LHgsMTYpOyAvKiBsb2coMCkgKi8NCiAgICAgICAg
 ZWxzZQ0KICAgICAgICAgICAgcmV0dXJuIF9fa2VybmVsX3N0YW5kYXJkKHgseCwxNyk7IC8qIGxv
 Zyh4PDApICovDQoNCi4uLmFhbmQuLi4gX19rZXJuZWxfc3RhbmRhcmQoeCx4LDE3KSBicmluZ3Mg
 dXMgdG86DQoNCiAgICAgICAgICAgIGNhc2UgMTc6DQogICAgICAgICAgICBjYXNlIDExNzoNCiAg
 ICAgICAgICAgICAgICAvKiBsb2coeDwwKSAqLw0KICAgICAgICAgICAgICAgIGV4Yy50eXBlID0g
 RE9NQUlOOw0KICAgICAgICAgICAgICAgIGV4Yy5uYW1lID0gdHlwZSA8IDEwMCA/ICJsb2ciIDog
 ImxvZ2YiOw0KICAgICAgICAgICAgICAgIGlmIChfTElCX1ZFUlNJT04gPT0gX1NWSURfKQ0KICAg
 ICAgICAgICAgICAgICAgZXhjLnJldHZhbCA9IC1IVUdFOw0KICAgICAgICAgICAgICAgIGVsc2UN
 CiAgICAgICAgICAgICAgICAgIGV4Yy5yZXR2YWwgPSAtSFVHRV9WQUw7DQogICAgICAgICAgICAg
 ICAgaWYgKF9MSUJfVkVSU0lPTiA9PSBfUE9TSVhfKQ0KICAgICAgICAgICAgICAgICAgZXJybm8g
 PSBFRE9NOw0KICAgICAgICAgICAgICAgIGVsc2UgaWYgKCFtYXRoZXJyKCZleGMpKSB7DQogICAg
 ICAgICAgICAgICAgICBpZiAoX0xJQl9WRVJTSU9OID09IF9TVklEXykgew0KICAgICAgICAgICAg
 ICAgICAgICAgICAgKHZvaWQpIFdSSVRFMigibG9nOiBET01BSU4gZXJyb3JcbiIsIDE4KTsNCiAg
 ICAgICAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgICAgICBlcnJubyA9IEVET007DQog
 ICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgIGJyZWFrOw0KDQphbmQgc2luY2Ugd2Un
 cmUgbm90IHVzaW5nIHRoZSBfU1ZJRF8gdmFyaWFudCwgLUhVR0VfVkFMLA0KYWthLiAtSU5GSU5J
 VFkgaXMgcmV0dXJuZWQuDQoNCk5vdywgSSBob25lc3RseSBkb24ndCBxdWl0ZSBrbm93IHdoaWNo
 IHZhcmlhbnQgb2YgdGhlIFBPU0lYIHN0YW5kYXJkDQp0aGlzIGxpYnJhcnkgaXMgc3VwcG9zZWQg
 dG8gY29uZm9ybSB0bywgYnV0Li4uDQoNCiAgaHR0cDovL3d3dy5vcGVuZ3JvdXAub3JnL29ubGlu
 ZXB1YnMvOTY5OTkxOTc5OS9mdW5jdGlvbnMvbG9nLmh0bWwNCg0Kd2hpY2ggaXMgdGhlIElFRUUg
 U3RkIDEwMDMuMS0yMDA4IHNwZWMgZm9yIGxvZygpLCB3aGljaCBzYXlzIHRoYXQNCnRoZSBpbnRl
 bnRpb24gaXMgdG8gYmUgaWRlbnRpY2FsIHRvIElTTyBDLiAgQW55d2F5LCB0aGUgYWJvdmUNCnBh
 Z2Ugc2F5czoNCg0KICAgRm9yIGZpbml0ZSB2YWx1ZXMgb2YgeCB0aGF0IGFyZSBsZXNzIHRoYW4g
 MCwgW01YXSBbT3B0aW9uIFN0YXJ0XSBvcg0KICAgaWYgeCBpcyAtSW5mLCBbT3B0aW9uIEVuZF0g
 YSBkb21haW4gZXJyb3Igc2hhbGwgb2NjdXIsIGFuZCBbTVhdDQogICBbT3B0aW9uIFN0YXJ0XSBl
 aXRoZXIgYSBOYU4gKGlmIHN1cHBvcnRlZCksIG9yIFtPcHRpb24gRW5kXSBhbg0KICAgaW1wbGVt
 ZW50YXRpb24tZGVmaW5lZCB2YWx1ZSBzaGFsbCBiZSByZXR1cm5lZC4NCg0KTm93LCBjbGVhcmx5
 IHdlIGRvIHN1cHBvcnQgTmFOLg0KDQpBbmQgSVNPIEM5OSBhdA0KDQogICBodHRwOi8vd3d3Lm9w
 ZW4tc3RkLm9yZy9KVEMxL1NDMjIvV0cxNC93d3cvZG9jcy9uMTI1Ni5wZGYNCg0Kc2VjdGlvbiBG
 LjkuMy43IHNheXM6DQoNCiAgIGxvZyh4KSByZXR1cm5zIGEgTmFOIGFuZCByYWlzZXMgdGhlIOKA
 mOKAmGludmFsaWTigJnigJkgZmxvYXRpbmctcG9pbnQNCiAgIGV4Y2VwdGlvbiBmb3IgeCA8IDAu
 DQoNCmRvZXMgbm90IG9mZmVyIHRoZSBvcHRpb24gb2YgcmV0dXJuaW5nIGFuIGltcGxlbWVudGF0
 aW9uLWRlZmluZWQNCnZhbHVlLg0KDQpTbyB3aHkgZG9lcyB0aGUgYWJvdmUgY29kZSByZXR1cm4g
 LUlORklOSVRZIGluc3RlYWQgb2YgTmFOPw0KDQpPZiBjb3Vyc2UsIGludHJvZHVjaW5nIHRoZSBm
 b2xsb3dpbmcgYml0IG9mIGNvZGUgYXQgdGhlIHN0YXJ0IG9mIHRoZQ0KcHJvZ3JhbSBmaXhlcyB0
 aGUgcHJvYmxlbToNCg0KICAgICAgICBfTElCX1ZFUlNJT04gPSBfSUVFRV87DQoNCldpdGggdGhh
 dCwgdGhlIHRlc3QgcHJvZ3JhbSBwcmludHMgd2hhdCdzIGV4cGVjdGVkLg0KDQpSZWdhcmRzLA0K
 DQotIEhhdmFyZA0K

From: Havard Eidnes <he@NetBSD.org>
To: lib-bug-people@netbsd.org
Cc: gnats-bugs@netbsd.org, netbsd-bugs@netbsd.org
Subject: Re: lib/41931: log(-INFINITY) or log(-1.0) gives uexpected results
Date: Tue, 25 Aug 2009 00:54:56 +0200 (CEST)

 [[ re-send with the utf-8 replaced by ascii, so perhaps we avoid
    base64-encoding the message... ]]

 Hi,

 more info on this.  I think I've come a bit closer to understanding
 what's happening.

 According to lib/libm/Makefile, for non-vax hosts, a _MULTI_LIBM
 is built, and it's of the _POSIX_MODE variety.

 This means that lib/libm/src/w_log.c builds the "longer" version,
 which looks like this:

         double z;
         z = __ieee754_log(x);
         if(_LIB_VERSION == _IEEE_ || isnan(x) || x > 0.0) return z;
         if(x==0.0)
             return __kernel_standard(x,x,16); /* log(0) */
         else
             return __kernel_standard(x,x,17); /* log(x<0) */

 ...aand... __kernel_standard(x,x,17) brings us to:

             case 17:
             case 117:
                 /* log(x<0) */
                 exc.type = DOMAIN;
                 exc.name = type < 100 ? "log" : "logf";
                 if (_LIB_VERSION == _SVID_)
                   exc.retval = -HUGE;
                 else
                   exc.retval = -HUGE_VAL;
                 if (_LIB_VERSION == _POSIX_)
                   errno = EDOM;
                 else if (!matherr(&exc)) {
                   if (_LIB_VERSION == _SVID_) {
                         (void) WRITE2("log: DOMAIN error\n", 18);
                       }
                   errno = EDOM;
                 }
                 break;

 and since we're not using the _SVID_ variant, -HUGE_VAL,
 aka. -INFINITY is returned.

 Now, I honestly don't quite know which variant of the POSIX standard
 this library is supposed to conform to, but...

   http://www.opengroup.org/onlinepubs/9699919799/functions/log.html

 which is the IEEE Std 1003.1-2008 spec for log(), which says that
 the intention is to be identical to ISO C.  Anyway, the above
 page says:

    For finite values of x that are less than 0, [MX] [Option Start] or
    if x is -Inf, [Option End] a domain error shall occur, and [MX]
    [Option Start] either a NaN (if supported), or [Option End] an
    implementation-defined value shall be returned.

 Now, clearly we do support NaN.

 And ISO C99 at

    http://www.open-std.org/JTC1/SC22/WG14/www/docs/n1256.pdf

 section F.9.3.7 says:

    log(x) returns a NaN and raises the "invalid" floating-point
    exception for x < 0.

 does not offer the option of returning an implementation-defined
 value.

 So why does the above code return -INFINITY instead of NaN?

 Of course, introducing the following bit of code at the start of the
 program fixes the problem:

         _LIB_VERSION = _IEEE_;

 With that, the test program prints what's expected.

 Regards,

 - Havard

From: "Jukka Ruohonen" <jruoho@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc: 
Subject: PR/41931 CVS commit: src
Date: Sun, 10 Apr 2011 06:11:47 +0000

 Module Name:	src
 Committed By:	jruoho
 Date:		Sun Apr 10 06:11:47 UTC 2011

 Modified Files:
 	src/distrib/sets/lists/tests: mi
 	src/tests/lib/libm: Makefile
 Added Files:
 	src/tests/lib/libm: t_log.c

 Log Message:
 Add a test case for PR lib/41931 reported by he@. It was verified that these
 fail on NetBSD 5.99.48 amd64 but pass on amd64 Linux (glibc 2.7).


 To generate a diff of this commit:
 cvs rdiff -u -r1.301 -r1.302 src/distrib/sets/lists/tests/mi
 cvs rdiff -u -r1.4 -r1.5 src/tests/lib/libm/Makefile
 cvs rdiff -u -r0 -r1.1 src/tests/lib/libm/t_log.c

 Please note that diffs are not public domain; they are subject to the
 copyright notices on the relevant files.

State-Changed-From-To: open->feedback
State-Changed-By: drochner@NetBSD.org
State-Changed-When: Mon, 11 Apr 2011 15:19:20 +0000
State-Changed-Why:
should be fixed in k_standard.c rev.1.17


From: "Matthias Drochner" <drochner@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc: 
Subject: PR/41931 CVS commit: src/lib/libm/src
Date: Mon, 11 Apr 2011 15:17:34 +0000

 Module Name:	src
 Committed By:	drochner
 Date:		Mon Apr 11 15:17:34 UTC 2011

 Modified Files:
 	src/lib/libm/src: k_standard.c

 Log Message:
 let log(<0) return NaN rather than -inf in POSIX/XOPEN modes, as
 requested in PR lib/41931 by Havard Eidnes (the PR refers to POSIX,
 the OSF/1 manpage suggests that XOPEN should behave that way too)
 being here, do the same to log10 and log2


 To generate a diff of this commit:
 cvs rdiff -u -r1.16 -r1.17 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: Jukka Ruohonen <jruohonen@iki.fi>
To: gnats-bugs@NetBSD.org
Cc: 
Subject: Re: PR/41931 CVS commit: src/lib/libm/src
Date: Tue, 12 Apr 2011 06:00:42 +0300

 On Mon, Apr 11, 2011 at 03:20:04PM +0000, Matthias Drochner wrote:
 >  let log(<0) return NaN rather than -inf in POSIX/XOPEN modes, as
 >  requested in PR lib/41931 by Havard Eidnes (the PR refers to POSIX,
 >  the OSF/1 manpage suggests that XOPEN should behave that way too)
 >  being here, do the same to log10 and log2

 Thanks for fixing this. I think we should probably audit all applicable
 math(3) functions for this and other comparable issues.

From: "Jukka Ruohonen" <jruoho@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc: 
Subject: PR/41931 CVS commit: src/tests/lib/libm
Date: Tue, 12 Apr 2011 03:06:21 +0000

 Module Name:	src
 Committed By:	jruoho
 Date:		Tue Apr 12 03:06:21 UTC 2011

 Modified Files:
 	src/tests/lib/libm: t_log.c

 Log Message:
 PR lib/41931 should be fixed; remove expected failure.


 To generate a diff of this commit:
 cvs rdiff -u -r1.1 -r1.2 src/tests/lib/libm/t_log.c

 Please note that diffs are not public domain; they are subject to the
 copyright notices on the relevant files.

State-Changed-From-To: feedback->closed
State-Changed-By: dholland@NetBSD.org
State-Changed-When: Mon, 30 Apr 2012 22:33:45 +0000
State-Changed-Why:
Fixed a year ago.


>Unformatted:

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-2007 The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.