NetBSD Problem Report #46388
From sjamaan@frohike.homeunix.org Sun Apr 29 14:53:05 2012
Return-Path: <sjamaan@frohike.homeunix.org>
Received: from mail.netbsd.org (mail.netbsd.org [149.20.53.66])
by www.NetBSD.org (Postfix) with ESMTP id 5C36563B86B
for <gnats-bugs@gnats.NetBSD.org>; Sun, 29 Apr 2012 14:53:05 +0000 (UTC)
Message-Id: <20120429145147.342ECF7E02D@frohike.homeunix.org>
Date: Sun, 29 Apr 2012 16:51:47 +0200 (CEST)
From: Peter.Bex@xs4all.nl
Reply-To: Peter.Bex@xs4all.nl
To: gnats-bugs@gnats.NetBSD.org
Subject: pow() behaves inconsistently and not POSIXly correct
X-Send-Pr-Version: 3.95
>Number: 46388
>Category: standards
>Synopsis: pow(1, inf) results in NaN or 1.0 in different situations
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: standards-manager
>State: closed
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Sun Apr 29 14:55:00 +0000 2012
>Closed-Date: Tue May 01 06:08:11 +0000 2012
>Last-Modified: Tue May 01 06:08:11 +0000 2012
>Originator: Peter Bex
>Release: NetBSD 5.0.1_PATCH
>Organization:
N/A
>Environment:
System: NetBSD frohike.homeunix.org 5.0.1_PATCH NetBSD 5.0.1_PATCH (FROHIKE) #0: Tue Aug 11 22:31:56 CEST 2009 sjamaan@frohike.homeunix.org:/usr/obj/sys/arch/amd64/compile/FROHIKE amd64
Architecture: x86_64
Machine: amd64
>Description:
The pow() function does not behave like the specification at
http://pubs.opengroup.org/onlinepubs/9699919799/functions/pow.html
says it should for infinity (and NaN?) values.
Worse, gcc seems to optimize calls to pow with constant values away
and replace it with POSIXly correct values, which means the result
may differ depending on how the code is structured and possibly also
on which optimization level is chosen.
See below for the offending code.
>How-To-Repeat:
$ cat test.c
#include <stdio.h>
#include <math.h>
int main(void) {
double m1 = 1.0, m2 = -1.0/0.0;
printf("directly: pow(%f, %f) = %lf\n", (double)1.0, (double)-1.0/0.0, pow(1.0, -1.0/0.0));
printf("indirectly: pow(%f, %f) = %lf\n", m1, m2, pow(m1, m2));
return 0;
}
$ gcc -lm test.c
$ ./a.out
directly: pow(1.000000, -inf) = 1.000000
indirectly: pow(1.000000, -inf) = nan
This is obviously inconsistent, and SuS says the second line is
wrong:
"For any value of y (including NaN), if x is +1, 1.0 shall be returned."
Looking at the generated assembly, there's only one call to
the pow function (and when commenting out the "indirect" line and
compiling/linking without libm I get no error), so it looks like
GCC decides to optimize away this call, even though I specified
no optimization level.
By the way, the spec also says:
"If x is -1, and y is ±Inf, 1.0 shall be returned."
This goes wrong as well:
directly: pow(-1.000000, -inf) = nan
indirectly: pow(-1.000000, -inf) = nan
Looking at the generated assembly, this contains two calls
to pow(). I don't know why GCC decides not to optimize away
pow(-1.0, -1.0/0.0) but it does for pow(1.0, -1.0/0.0)....
>Fix:
No patch since this code is a little above my head, but
it looks like the problem occurs in src/lib/libm/src/e_pow.c:145
That line reads
return y - y; /* inf**+-1 is NaN */
but just above, it says
if (iy==0x7ff00000) { /* y is +-inf */
this means that the comment on line 145 is wrong, and I think the
returned value is wrong as well because this seems to be the
branch that's taken for pow(1, -inf).
>Release-Note:
>Audit-Trail:
State-Changed-From-To: open->closed
State-Changed-By: jruoho@NetBSD.org
State-Changed-When: Tue, 01 May 2012 06:08:11 +0000
State-Changed-Why:
I will close this as duplicate of PR lib/45372 (but see also port-amd64/45391).
There is also a test case (with expected failure) for this particular bug
(tests/lib/libm/t_pow, 'pow_one_neg_x').
But feel free to append any notes to the above PRs. As you noted, NetBSD's
libm implementation and modern gcc do not play well together.
>Unformatted:
(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.