Message ID | 20240913123858.2294-1-fabian.schriever@gtd-gmbh.de |
---|---|
State | New |
Headers |
Return-Path: <newlib-bounces~patchwork=sourceware.org@sourceware.org> X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id EDF123858C35 for <patchwork@sourceware.org>; Fri, 13 Sep 2024 12:42:55 +0000 (GMT) X-Original-To: newlib@sourceware.org Delivered-To: newlib@sourceware.org Received: from gtd-gmbh.de (mail.gtd.eu [46.24.46.35]) by sourceware.org (Postfix) with ESMTPS id 8CE883858D28 for <newlib@sourceware.org>; Fri, 13 Sep 2024 12:42:39 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 8CE883858D28 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=gtd-gmbh.de Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=gtd-gmbh.de ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 8CE883858D28 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=46.24.46.35 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1726231362; cv=none; b=Bwqm71bnMNIINnK1o6Jnk9e8ZWgk8q3sk7dRAQVsfV8kIsGHAw1rBO+DRU9YBu3W6NVqBEclIpQ2XRSmapuIWV+ci4CEgrn5oMFiQrS5E9lo8LXfpWNRjrjJkxHA4hhiRv8fuIYShQhJ3lN8EGWyy+R5lXu454MbYjQMWGHyZgI= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1726231362; c=relaxed/simple; bh=R5OYv8kEu6cglZ/2BdqGcQV5HjJ8BJlJ/kVwvLoVNaY=; h=DKIM-Signature:From:To:Subject:Date:Message-Id:MIME-Version; b=AmesnMUrfmJcjC1AjkmQ7Vdb+K6R0Rmu3Z08NkcR5YXQLjtdaB/0GxHExcPLf1twsYHquhPCrJzupuv8saIZ8xEON01LqPY2EveWMPQZvFq0S6IEiV6g1GUL3oK7T81pUdmK1RcbfvPkSi2Cgwa5lKYVXSX1ACRF+lbr5UQSSa4= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=simple; d=gtd-gmbh.de; s=nk2048220908; t=1726231161; x=1726835961; i=fabian.schriever@gtd-gmbh.de; q=dns/txt; h=From:To:Cc:Subject: Date:Message-Id:MIME-Version:Content-Transfer-Encoding; bh=R5OYv 8kEu6cglZ/2BdqGcQV5HjJ8BJlJ/kVwvLoVNaY=; b=DcJiKetp1UbN3RxlPBucO RKavtA3bC33leSkQGXsqOl3nVcouKbTCrWQTDDgm+qUpqt/X4IMenqBp3k4Gc/zW fXUbzFp092YDzIUi715V/3qZ/dGLsf4i3bk7fQDOWS0g2D7z4E+xVHEVVeHiX3dD DT8WalqiaZA3Dj0aq9XAmr1JxNtKIMYT7qA/31oi+3yzQgowO/8ALVvZMgldVrit ExqoeH2PQOWDWoidHtFdyIXI5IyitSisz58riICeiqOr6JDkTcbgMbA3f0JmYi0S +HEcUOVvA6mUWY8PB9iMExiB9QyLafV3RlPJpwxDef6pvudrChAV4636i+h3BFnw A== X-MDAV-Result: clean X-MDAV-Processed: gtd-gmbh.de, Fri, 13 Sep 2024 14:39:21 +0200 Received: from localhost.localdomain [(95.223.184.231)] by gtd-gmbh.de (MDaemon PRO v24.0.1) with ESMTPSA id md5001020720652.msg; Fri, 13 Sep 2024 14:39:20 +0200 X-Spam-Processed: gtd-gmbh.de, Fri, 13 Sep 2024 14:39:20 +0200 (not processed: message from trusted or authenticated source) X-MDRemoteIP: 95.223.184.231 X-MDHelo: localhost.localdomain X-MDArrival-Date: Fri, 13 Sep 2024 14:39:20 +0200 X-Authenticated-Sender: fabian.schriever@gtd-gmbh.de X-Return-Path: prvs=198623b2e7=fabian.schriever@gtd-gmbh.de X-Envelope-From: fabian.schriever@gtd-gmbh.de X-MDaemon-Deliver-To: newlib@sourceware.org From: Fabian Schriever <fabian.schriever@gtd-gmbh.de> To: newlib@sourceware.org Cc: Fabian Schriever <fabian.schriever@gtd-gmbh.de> Subject: [PATCH 2/3 v2] powf: Fixed 2 bugs in the computation /* t_h=ax+bp[k] High */. (FreeBSD) Date: Fri, 13 Sep 2024 14:38:58 +0200 Message-Id: <20240913123858.2294-1-fabian.schriever@gtd-gmbh.de> X-Mailer: git-send-email 2.33.0.windows.1 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-MDCFSigsAdded: gtd-gmbh.de X-Spam-Status: No, score=-10.6 required=5.0 tests=BAYES_00, DKIM_INVALID, DKIM_SIGNED, GIT_PATCH_0, KAM_DMARC_STATUS, RCVD_IN_MSPIKE_H2, SPF_HELO_PASS, SPF_PASS, TXREP, UNPARSEABLE_RELAY autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: newlib@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Newlib mailing list <newlib.sourceware.org> List-Unsubscribe: <https://sourceware.org/mailman/options/newlib>, <mailto:newlib-request@sourceware.org?subject=unsubscribe> List-Archive: <https://sourceware.org/pipermail/newlib/> List-Post: <mailto:newlib@sourceware.org> List-Help: <mailto:newlib-request@sourceware.org?subject=help> List-Subscribe: <https://sourceware.org/mailman/listinfo/newlib>, <mailto:newlib-request@sourceware.org?subject=subscribe> Errors-To: newlib-bounces~patchwork=sourceware.org@sourceware.org |
Series |
None
|
|
Commit Message
Fabian Schriever
Sept. 13, 2024, 12:38 p.m. UTC
(1) The bit for the 1.0 part of bp[k] was right shifted by 4. This seems to have been caused by a typo in converting e_pow.c to e_powf.c. (2) The lower 12 bits of ax+bp[k] were not discarded, so t_h was actually plain ax+bp[k]. This seems to have been caused by a logic error in the conversion. These bugs gave wrong results like: powf(-1.1, 101.0) = -15158.703 (should be -15158.707) hex values: BF8CCCCD 42CA0000 C66CDAD0 C66CDAD4 Fixing (1) gives a result wrong in the opposite direction (hex C66CDAD8), and fixing (2) gives the correct result. ucbtest has been reporting this particular wrong result on i386 systems with unpatched libraries for 9 years. I finally figured out the extent of the bugs. On i386's they are normally hidden by extra precision. We use the trick of representing floats as a sum of 2 floats (one much smaller) to get extra precision in intermediate calculations without explicitly using more than float precision. This trick is just a pessimization when extra precision is available naturally (as it always is when dealing with IEEE single precision, so the float precision part of the library is mostly misimplemented). (1) and (2) break the trick in different ways, except on i386's it turns out that the intermediate calculations are done in enough precision to mask both the bugs and the limited precision of the float variables (as far as ucbtest can check). ucbtest detects the bugs because it forces float precision, but this is not a normal mode of operation so the bug normally has little effect on i386's. On systems that do float arithmetic in float precision, e.g., amd64's, there is no accidental extra precision and the bugs just give wrong results. Reference: https://github.com/freebsd/freebsd-src/commit/12be4e0d5a54a6750913aee2564d164baa71f0dc Original Author: Bruce Evans --- newlib/libm/math/ef_pow.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
Comments
(Sorry for the previous accidental message) I was running the glibc test cases and found this one: powf(0x1.059c76p+0, 0x1.ff80bep+11) The desired result is 0x1.fffcaap+127, but newlib yields 0x1.fffbf8p+127. I tracked this down to an imprecise constant 'cp' for 2/(3*ln(2)) used in the computation. From 3dd0fce84efd8a45e3501175c05086f8a1cbd832 Mon Sep 17 00:00:00 2001 From: Keith Packard <keithp@keithp.com> Date: Wed, 25 Sep 2024 18:34:28 -0700 Subject: [PATCH] libm: Improve powf accuracy One of the constants, 'cp', was not correctly converted to extended precision (using two floats) leading to reduced precision in the computation of log2(x). The new values use a larger value for cp_h which is closer to the actual value. That leaves a smaller magnitude for cp_l resulting in increased precision for the result. These values were computed according to the Veltkamp/Dekker method. 2/(3*ln2): 0x1.ec709dc3a03fd748p-1 Old cp_h: 0x1.ec7p-1 New cp_h: 0x1.ec8p-1 The desired value is much closer to the higher value than the lower. Signed-off-by: Keith Packard <keithp@keithp.com> --- newlib/libm/math/ef_pow.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/newlib/libm/math/ef_pow.c b/newlib/libm/math/ef_pow.c index a2aba1054..d69f1ae48 100644 --- a/newlib/libm/math/ef_pow.c +++ b/newlib/libm/math/ef_pow.c @@ -47,8 +47,8 @@ lg2_h = 6.93145752e-01, /* 0x3f317200 */ lg2_l = 1.42860654e-06, /* 0x35bfbe8c */ ovt = 4.2995665694e-08, /* -(128-log2(ovfl+.5ulp)) */ cp = 9.6179670095e-01, /* 0x3f76384f =2/(3ln2) */ -cp_h = 9.6179199219e-01, /* 0x3f763800 =head of cp */ -cp_l = 4.7017383622e-06, /* 0x369dc3a0 =tail of cp_h */ +cp_h = 9.61914062e-01, /* 0x3f764000 =head of cp */ +cp_l = -1.17368574e-04, /* 0xb8f623c6 =tail of cp */ ivln2 = 1.4426950216e+00, /* 0x3fb8aa3b =1/ln2 */ ivln2_h = 1.4426879883e+00, /* 0x3fb8aa00 =16b 1/ln2*/ ivln2_l = 7.0526075433e-06; /* 0x36eca570 =1/ln2 tail*/
On 26.09.24 04:11, Keith Packard wrote: > From 3dd0fce84efd8a45e3501175c05086f8a1cbd832 Mon Sep 17 00:00:00 2001 > From: Keith Packard <keithp@keithp.com> > Date: Wed, 25 Sep 2024 18:34:28 -0700 > Subject: [PATCH] libm: Improve powf accuracy > > One of the constants, 'cp', was not correctly converted to extended > precision (using two floats) leading to reduced precision in the > computation of log2(x). > > The new values use a larger value for cp_h which is closer to the > actual value. That leaves a smaller magnitude for cp_l resulting in > increased precision for the result. These values were computed > according to the Veltkamp/Dekker method. > > 2/(3*ln2): 0x1.ec709dc3a03fd748p-1 > Old cp_h: 0x1.ec7p-1 > New cp_h: 0x1.ec8p-1 > > The desired value is much closer to the higher value than the lower. > > Signed-off-by: Keith Packard <keithp@keithp.com> > --- > newlib/libm/math/ef_pow.c | 4 ++-- > 1 file changed, 2 insertions(+), 2 deletions(-) > > diff --git a/newlib/libm/math/ef_pow.c b/newlib/libm/math/ef_pow.c > index a2aba1054..d69f1ae48 100644 > --- a/newlib/libm/math/ef_pow.c > +++ b/newlib/libm/math/ef_pow.c > @@ -47,8 +47,8 @@ lg2_h = 6.93145752e-01, /* 0x3f317200 */ > lg2_l = 1.42860654e-06, /* 0x35bfbe8c */ > ovt = 4.2995665694e-08, /* -(128-log2(ovfl+.5ulp)) */ > cp = 9.6179670095e-01, /* 0x3f76384f =2/(3ln2) */ > -cp_h = 9.6179199219e-01, /* 0x3f763800 =head of cp */ > -cp_l = 4.7017383622e-06, /* 0x369dc3a0 =tail of cp_h */ > +cp_h = 9.61914062e-01, /* 0x3f764000 =head of cp */ > +cp_l = -1.17368574e-04, /* 0xb8f623c6 =tail of cp */ > ivln2 = 1.4426950216e+00, /* 0x3fb8aa3b =1/ln2 */ > ivln2_h = 1.4426879883e+00, /* 0x3fb8aa00 =16b 1/ln2*/ > ivln2_l = 7.0526075433e-06; /* 0x36eca570 =1/ln2 tail*/ This looks correct, thanks Keith! A very similar change has also been done in FreeBSD: https://github.com/freebsd/freebsd-src/commit/b4437c3d322a0f6d23d12b6f76d2fc72d2ff0ec2
diff --git a/newlib/libm/math/ef_pow.c b/newlib/libm/math/ef_pow.c index 4ceba3d24..8687f5071 100644 --- a/newlib/libm/math/ef_pow.c +++ b/newlib/libm/math/ef_pow.c @@ -173,7 +173,8 @@ ivln2_l = 7.0526075433e-06; /* 0x36eca570 =1/ln2 tail*/ GET_FLOAT_WORD(is,s_h); SET_FLOAT_WORD(s_h,is&0xfffff000); /* t_h=ax+bp[k] High */ - SET_FLOAT_WORD(t_h,((ix>>1)|0x20000000)+0x0040000+(k<<21)); + is = ((ix >> 1) & 0xfffff000U) | 0x20000000; + SET_FLOAT_WORD(t_h, is + 0x00400000 + (k << 21)); t_l = ax - (t_h-bp[k]); s_l = v*((u-s_h*t_h)-s_h*t_l); /* compute log(ax) */