From patchwork Fri Dec 2 22:51:57 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Joseph Myers X-Patchwork-Id: 702176 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3tVqD83QNkz9t1H for ; Sat, 3 Dec 2016 09:52:24 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; secure) header.d=sourceware.org header.i=@sourceware.org header.b="tqKZlqFF"; dkim-atps=neutral DomainKey-Signature: a=rsa-sha1; c=nofws; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:date:from:to:subject:message-id:mime-version :content-type; q=dns; s=default; b=JRgkxce6wHR7WrOpuUzSwfxh2/AhT 0TvrCP3X+uJqrq49dyM5W/wBwX2uF3vfHQ+wsoiadXJacNj0FfRzWAhVRDm4Unkw QYFJzNEX6YhJjnzFknd9s9DJO6t6wQaFdVJx39g9hWzMujQiOdWBDnP4Th8yf5lk gVTrn6tABtcOeQ= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:date:from:to:subject:message-id:mime-version :content-type; s=default; bh=ypJUsxSvoUZLqFmhmCczBq0GVXU=; b=tqK ZlqFFdy6XF/pqpuV4T3B1slTAu6TVi8doqgoKJvlKnK8JnvqBXzNWZ12s3Vg3Ik3 lz6ZFXp9GyKaReNt2tBIKu5VK1jEf4thQCbCrlC5uMOEd/0yQPGmhACyQqOgqW+t yUSCO8nWC33Pku53Jt9quW6MCCLJIlNuRJK5YxdA= Received: (qmail 71878 invoked by alias); 2 Dec 2016 22:52:17 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 71864 invoked by uid 89); 2 Dec 2016 22:52:17 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=0.5 required=5.0 tests=AWL, BAYES_50, RCVD_IN_DNSWL_NONE, SPF_PASS, URIBL_RED autolearn=ham version=3.3.2 spammy=accordance, ui, deliberate, becoming X-HELO: relay1.mentorg.com Date: Fri, 2 Dec 2016 22:51:57 +0000 From: Joseph Myers To: Subject: Fix pow (qNaN, 0) result with -lieee (bug 20919), remove dead parts of wrappers [committed] Message-ID: User-Agent: Alpine 2.20 (DEB 67 2015-01-07) MIME-Version: 1.0 X-ClientProxiedBy: svr-ies-mbx-01.mgc.mentorg.com (139.181.222.1) To svr-ies-mbx-01.mgc.mentorg.com (139.181.222.1) The dbl-64 implementation of __ieee754_pow returns a NaN for pow (qNaN, 0) when it should return 1. Normally this is covered up by the wrappers ending up calling __kernel_standard which fixes up the result for this case, but for -lieee the wrappers are bypassed and the bad result gets through as a return value. Now, the wrappers fixing this are dealing with variant error handling that wants a result of NaN for pow (qNaN, 0), and only ever call __kernel_standard for this case if NaN resulted from __ieee754_pow. This leads to a question of whether the dbl-64 code might be deliberately returning NaN in order to use those code paths. However, I can find no sign that this is deliberate. If it were deliberate one would expect other implementations to do the same, and would expect the return of NaN to be very old, but it appears it came in by accident when the present e_pow.c implementation replaced an fdlibm implementation in 2001. So it appears to be unintended that this path through the pow wrapper could be used at all. So this patch fixes the implementation to return 1 in this case as expected. This is consistent with all the other implementations. The relevant path through the wrappers is now unreachable, so is removed (which is the main motivation of this patch: to avoid that path becoming accidentally reachable when implementing TS 18661-1 semantics that pow (sNaN, 0) should return qNaN with "invalid" raised). Another path that would require __ieee754_pow (0, 0) to return 0 is also unreachable (as all implementations return 1, in accordance with C99 semantics), so is removed as well. Note: we don't have anything set up to test -lieee, which in any case is obsolescent (at some point we should remove the ability for new programs to access _LIB_VERSION or define matherr and have it called by glibc). So testing will be implicit through sNaN tests added when making sNaN inputs work correctly for pow functions. Tested for x86_64 and x86. Committed. 2016-12-02 Joseph Myers [BZ #20919] * sysdeps/ieee754/dbl-64/e_pow.c (__ieee754_pow): Do not return NaN first argument when raised to power 0. * math/w_pow.c (__pow): Do not check for NaN or zero results from raising to power zero. * math/w_powf.c (__powf): Likewise. * math/w_powl.c (__powl): Likewise. * sysdeps/ieee754/k_standard.c (__kernel_standard): Do not handle pow (0, 0) or pow (NaN, 0). diff --git a/math/w_pow.c b/math/w_pow.c index 12c0591..ed79dbd 100644 --- a/math/w_pow.c +++ b/math/w_pow.c @@ -29,13 +29,7 @@ __pow (double x, double y) { if (_LIB_VERSION != _IEEE_) { - if (isnan (x)) - { - if (y == 0.0) - /* pow(NaN,0.0) */ - return __kernel_standard (x, y, 42); - } - else if (isfinite (x) && isfinite (y)) + if (isfinite (x) && isfinite (y)) { if (isnan (z)) /* pow neg**non-int */ @@ -55,19 +49,11 @@ __pow (double x, double y) } } } - else if (__builtin_expect (z == 0.0, 0) && isfinite (x) && isfinite (y) + else if (__builtin_expect (z == 0.0, 0) + && isfinite (x) && x != 0 && isfinite (y) && _LIB_VERSION != _IEEE_) - { - if (x == 0.0) - { - if (y == 0.0) - /* pow(0.0,0.0) */ - return __kernel_standard (x, y, 20); - } - else - /* pow underflow */ - return __kernel_standard (x, y, 22); - } + /* pow underflow */ + return __kernel_standard (x, y, 22); return z; } diff --git a/math/w_powf.c b/math/w_powf.c index 2e786e2..ec157a3 100644 --- a/math/w_powf.c +++ b/math/w_powf.c @@ -29,13 +29,7 @@ __powf (float x, float y) { if (_LIB_VERSION != _IEEE_) { - if (isnan (x)) - { - if (y == 0.0f) - /* pow(NaN,0.0) */ - return __kernel_standard_f (x, y, 142); - } - else if (isfinite (x) && isfinite (y)) + if (isfinite (x) && isfinite (y)) { if (isnan (z)) /* pow neg**non-int */ @@ -55,19 +49,11 @@ __powf (float x, float y) } } } - else if (__builtin_expect (z == 0.0f, 0) && isfinite (x) && isfinite (y) + else if (__builtin_expect (z == 0.0f, 0) + && isfinite (x) && x != 0 && isfinite (y) && _LIB_VERSION != _IEEE_) - { - if (x == 0.0f) - { - if (y == 0.0f) - /* pow(0.0,0.0) */ - return __kernel_standard_f (x, y, 120); - } - else - /* pow underflow */ - return __kernel_standard_f (x, y, 122); - } + /* pow underflow */ + return __kernel_standard_f (x, y, 122); return z; } diff --git a/math/w_powl.c b/math/w_powl.c index be02e1e..9b86651 100644 --- a/math/w_powl.c +++ b/math/w_powl.c @@ -29,13 +29,7 @@ __powl (long double x, long double y) { if (_LIB_VERSION != _IEEE_) { - if (isnan (x)) - { - if (y == 0.0L) - /* pow(NaN,0.0) */ - return __kernel_standard_l (x, y, 242); - } - else if (isfinite (x) && isfinite (y)) + if (isfinite (x) && isfinite (y)) { if (isnan (z)) /* pow neg**non-int */ @@ -55,19 +49,11 @@ __powl (long double x, long double y) } } } - else if (__builtin_expect (z == 0.0L, 0) && isfinite (x) && isfinite (y) + else if (__builtin_expect (z == 0.0L, 0) + && isfinite (x) && x != 0 && isfinite (y) && _LIB_VERSION != _IEEE_) - { - if (x == 0.0L) - { - if (y == 0.0L) - /* pow(0.0,0.0) */ - return __kernel_standard_l (x, y, 220); - } - else - /* pow underflow */ - return __kernel_standard_l (x, y, 222); - } + /* pow underflow */ + return __kernel_standard_l (x, y, 222); return z; } diff --git a/sysdeps/ieee754/dbl-64/e_pow.c b/sysdeps/ieee754/dbl-64/e_pow.c index bd758b5..db6ecf7 100644 --- a/sysdeps/ieee754/dbl-64/e_pow.c +++ b/sysdeps/ieee754/dbl-64/e_pow.c @@ -73,7 +73,8 @@ __ieee754_pow (double x, double y) { /* of y */ qx = u.i[HIGH_HALF] & 0x7fffffff; /* Is x a NaN? */ - if (((qx == 0x7ff00000) && (u.i[LOW_HALF] != 0)) || (qx > 0x7ff00000)) + if ((((qx == 0x7ff00000) && (u.i[LOW_HALF] != 0)) || (qx > 0x7ff00000)) + && y != 0) return x; if (y == 1.0) return x; diff --git a/sysdeps/ieee754/k_standard.c b/sysdeps/ieee754/k_standard.c index c8aebbf..b100b3e 100644 --- a/sysdeps/ieee754/k_standard.c +++ b/sysdeps/ieee754/k_standard.c @@ -60,7 +60,6 @@ static double zero = 0.0; /* used as const */ * 17-- log(x<0) * 18-- log10(0) * 19-- log10(x<0) - * 20-- pow(0.0,0.0) * 21-- pow(x,y) overflow * 22-- pow(x,y) underflow * 23-- pow(0,negative) @@ -82,7 +81,6 @@ static double zero = 0.0; /* used as const */ * 39-- yn(x>X_TLOSS, n) * 40-- tgamma(finite) overflow * 41-- tgamma(-integer) - * 42-- pow(NaN,0.0) * 43-- +0**neg * 44-- exp2 overflow * 45-- exp2 underflow @@ -461,20 +459,6 @@ __kernel_standard(double x, double y, int type) __set_errno (EDOM); } break; - case 20: - case 120: - case 220: - /* pow(0.0,0.0) */ - /* error only if _LIB_VERSION == _SVID_ */ - exc.type = DOMAIN; - exc.name = CSTR ("pow"); - exc.retval = zero; - if (_LIB_VERSION != _SVID_) exc.retval = 1.0; - else if (!matherr(&exc)) { - (void) WRITE2("pow(0,0): DOMAIN error\n", 23); - __set_errno (EDOM); - } - break; case 21: case 121: case 221: @@ -845,20 +829,6 @@ __kernel_standard(double x, double y, int type) __set_errno (EDOM); } break; - case 42: - case 142: - case 242: - /* pow(NaN,0.0) */ - /* error only if _LIB_VERSION == _SVID_ & _XOPEN_ */ - exc.type = DOMAIN; - exc.name = CSTR ("pow"); - exc.retval = x; - if (_LIB_VERSION == _IEEE_ || - _LIB_VERSION == _POSIX_) exc.retval = 1.0; - else if (!matherr(&exc)) { - __set_errno (EDOM); - } - break; case 44: case 144: