From patchwork Tue Mar 25 02:26:18 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alan Modra X-Patchwork-Id: 259 X-Patchwork-Delegate: azanella@linux.vnet.ibm.com Return-Path: X-Original-To: siddhesh@wilcox.dreamhost.com Delivered-To: siddhesh@wilcox.dreamhost.com Received: from homiemail-mx22.g.dreamhost.com (caibbdcaabij.dreamhost.com [208.113.200.189]) by wilcox.dreamhost.com (Postfix) with ESMTP id D8B5C360172 for ; Mon, 24 Mar 2014 19:26:48 -0700 (PDT) Received: by homiemail-mx22.g.dreamhost.com (Postfix, from userid 14307373) id 89FF04FE76B7; Mon, 24 Mar 2014 19:26:48 -0700 (PDT) X-Original-To: glibc@patchwork.siddhesh.in Delivered-To: x14307373@homiemail-mx22.g.dreamhost.com 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 homiemail-mx22.g.dreamhost.com (Postfix) with ESMTPS id 66D9650D2D1C for ; Mon, 24 Mar 2014 19:26:48 -0700 (PDT) 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=g9J+rsDYtN4I/Zb+m0AOcQGYHRcSK PugPpcDwQdXlPHzsU8OnxqDHvMwT6Vt8vlaX6tPQQ9E6vZmdZJLZseFvwcb7cjCg ubkpsf6ytgPWnjEh4rJGp1BbijDW4VFQ8/gYMY43qnbZG26SXSil78RFBPEGptfV EaI15zN/lpueZM= 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=BVVg1o16gF6/VVOu4LfKfW2Mqhg=; b=iXq VphspJt896FRePlaHhS90IDImV6jVb+c+qcDDnp82ueOf74fiIuec1pHYI/Gt+do rIF1mSy5F5hsJzSb19Clxf2fwbAKE95yytFvo1QwEmhzkmzLVAo6e7qTilYSYMfV C23zA9MP6WWxB/ZtWmmdzCWWl5CKgclGif2E6O/4= Received: (qmail 7106 invoked by alias); 25 Mar 2014 02:26:45 -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 7093 invoked by uid 89); 25 Mar 2014 02:26:42 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.9 required=5.0 tests=AWL, BAYES_00, FREEMAIL_FROM, RCVD_IN_DNSWL_NONE, SPF_PASS autolearn=ham version=3.3.2 X-HELO: mail-pd0-f177.google.com X-Received: by 10.68.197.99 with SMTP id it3mr75635579pbc.37.1395714383748; Mon, 24 Mar 2014 19:26:23 -0700 (PDT) Date: Tue, 25 Mar 2014 12:56:18 +1030 From: Alan Modra To: libc-alpha@sourceware.org Subject: [PowerPC64] Correct IBM long double nextafterl Message-ID: <20140325022618.GF18201@bubble.grove.modra.org> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.21 (2010-09-15) X-DH-Original-To: glibc@patchwork.siddhesh.in Fix for values near a power of two, and some tidies. The added tests do cause some new fails, because IBM long double isn't supposed to support rounding modes other than round-to-nearest. I believe powerpc should have a math-tests.h like arm and mips that limits the tested rounding modes. [BZ #16739] * sysdeps/ieee754/ldbl-128ibm/s_nextafterl.c (__nextafterl): Correct output when value is near a power of two. Use int64_t for lx and remove casts. Use decimal rather than hex exponent constants. Don't use long double multiplication when double will suffice. * math/libm-test.inc (nextafter_test_data): Add tests. diff --git a/math/libm-test.inc b/math/libm-test.inc index 5e50f0e..e97b18a 100644 --- a/math/libm-test.inc +++ b/math/libm-test.inc @@ -8312,6 +8312,14 @@ static const struct test_ff_f_data nextafter_test_data[] = // XXX Enable once gcc is fixed. //TEST_ff_f (nextafter, 0x0.00000040000000000000p-16385L, -0.1L, 0x0.0000003ffffffff00000p-16385L), #endif +#if defined TEST_LDOUBLE && LDBL_MANT_DIG == 106 + TEST_ff_f (nextafter, 1.0L, -10.0L, 1.0L-0x1p-106L, NO_EXCEPTION), + TEST_ff_f (nextafter, 1.0L, 10.0L, 1.0L+0x1p-105L, NO_EXCEPTION), + TEST_ff_f (nextafter, 1.0L-0x1p-106L, 10.0L, 1.0L, NO_EXCEPTION), + TEST_ff_f (nextafter, -1.0L, -10.0L, -1.0L-0x1p-105L, NO_EXCEPTION), + TEST_ff_f (nextafter, -1.0L, 10.0L, -1.0L+0x1p-106L, NO_EXCEPTION), + TEST_ff_f (nextafter, -1.0L+0x1p-106L, -10.0L, -1.0L, NO_EXCEPTION), +#endif /* XXX We need the hexadecimal FP number representation here for further tests. */ diff --git a/sysdeps/ieee754/ldbl-128ibm/s_nextafterl.c b/sysdeps/ieee754/ldbl-128ibm/s_nextafterl.c index 30b1540..bf57cb8 100644 --- a/sysdeps/ieee754/ldbl-128ibm/s_nextafterl.c +++ b/sysdeps/ieee754/ldbl-128ibm/s_nextafterl.c @@ -30,8 +30,7 @@ static char rcsid[] = "$NetBSD: $"; long double __nextafterl(long double x, long double y) { - int64_t hx,hy,ihx,ihy; - uint64_t lx; + int64_t hx, hy, ihx, ihy, lx; double xhi, xlo, yhi; ldbl_unpack (x, &xhi, &xlo); @@ -79,19 +78,28 @@ long double __nextafterl(long double x, long double y) u = math_opt_barrier (x); x -= __LDBL_DENORM_MIN__; if (ihx < 0x0360000000000000LL - || (hx > 0 && (int64_t) lx <= 0) - || (hx < 0 && (int64_t) lx > 1)) { + || (hx > 0 && lx <= 0) + || (hx < 0 && lx > 1)) { u = u * u; math_force_eval (u); /* raise underflow flag */ } return x; } - if (ihx < 0x06a0000000000000LL) { /* ulp will denormal */ - INSERT_WORDS64 (yhi, hx & (0x7ffLL<<52)); - u = yhi; - u *= 0x1.0000000000000p-105L; + /* If the high double is an exact power of two and the low + double is the opposite sign, then 1ulp is one less than + what we might determine from the high double. Similarly + if X is an exact power of two, and positive, because + making it a little smaller will result in the exponent + decreasing by one and normalisation of the mantissa. */ + if ((hx & 0x000fffffffffffffLL) == 0 + && ((lx != 0 && (hx ^ lx) < 0) + || (lx == 0 && hx >= 0))) + ihx -= 1LL << 52; + if (ihx < (106LL << 52)) { /* ulp will denormal */ + INSERT_WORDS64 (yhi, ihx & (0x7ffLL<<52)); + u = yhi * 0x1p-105; } else { - INSERT_WORDS64 (yhi, (hx & (0x7ffLL<<52))-(0x069LL<<52)); + INSERT_WORDS64 (yhi, (ihx & (0x7ffLL<<52))-(105LL<<52)); u = yhi; } return x - u; @@ -109,8 +117,8 @@ long double __nextafterl(long double x, long double y) u = math_opt_barrier (x); x += __LDBL_DENORM_MIN__; if (ihx < 0x0360000000000000LL - || (hx > 0 && (int64_t) lx < 0 && lx != 0x8000000000000001LL) - || (hx < 0 && (int64_t) lx >= 0)) { + || (hx > 0 && lx < 0 && lx != 0x8000000000000001LL) + || (hx < 0 && lx >= 0)) { u = u * u; math_force_eval (u); /* raise underflow flag */ } @@ -118,12 +126,21 @@ long double __nextafterl(long double x, long double y) x = -0.0L; return x; } - if (ihx < 0x06a0000000000000LL) { /* ulp will denormal */ - INSERT_WORDS64 (yhi, hx & (0x7ffLL<<52)); - u = yhi; - u *= 0x1.0000000000000p-105L; + /* If the high double is an exact power of two and the low + double is the opposite sign, then 1ulp is one less than + what we might determine from the high double. Similarly + if X is an exact power of two, and negative, because + making it a little larger will result in the exponent + decreasing by one and normalisation of the mantissa. */ + if ((hx & 0x000fffffffffffffLL) == 0 + && ((lx != 0 && (hx ^ lx) < 0) + || (lx == 0 && hx < 0))) + ihx -= 1LL << 52; + if (ihx < (106LL << 52)) { /* ulp will denormal */ + INSERT_WORDS64 (yhi, ihx & (0x7ffLL<<52)); + u = yhi * 0x1p-105; } else { - INSERT_WORDS64 (yhi, (hx & (0x7ffLL<<52))-(0x069LL<<52)); + INSERT_WORDS64 (yhi, (ihx & (0x7ffLL<<52))-(105LL<<52)); u = yhi; } return x + u;