From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 95798 invoked by alias); 11 Dec 2018 11:55:51 -0000 Mailing-List: contact newlib-cvs-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: newlib-cvs-owner@sourceware.org Received: (qmail 95418 invoked by uid 9078); 11 Dec 2018 11:55:51 -0000 Date: Tue, 11 Dec 2018 11:55:00 -0000 Message-ID: <20181211115551.95415.qmail@sourceware.org> Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: Corinna Vinschen To: newlib-cvs@sourceware.org Subject: [newlib-cygwin] Fix powf overflow handling in non-nearest rounding mode X-Act-Checkin: newlib-cygwin X-Git-Author: Szabolcs Nagy X-Git-Refname: refs/heads/master X-Git-Oldrev: 55db4a8e3ae0aef3a3530a82515d8ba5d2ea121c X-Git-Newrev: df6915f029ac9acd2b479ea898388cbd7dda4974 X-SW-Source: 2018-q4/txt/msg00040.txt.bz2 https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=df6915f029ac9acd2b479ea898388cbd7dda4974 commit df6915f029ac9acd2b479ea898388cbd7dda4974 Author: Szabolcs Nagy Date: Mon Dec 10 14:40:01 2018 +0000 Fix powf overflow handling in non-nearest rounding mode The threshold value at which powf overflows depends on the rounding mode and the current check did not take this into account. So when the result was rounded away from zero it could become infinity without setting errno to ERANGE. Example: pow(0x1.7ac7cp+5, 23) is 0x1.fffffep+127 + 0.1633ulp If the result goes above 0x1.fffffep+127 + 0.5ulp then errno is set, which is fine in nearest rounding mode, but powf(0x1.7ac7cp+5, 23) is inf in upward rounding mode powf(-0x1.7ac7cp+5, 23) is -inf in downward rounding mode and the previous implementation did not set errno in these cases. The fix tries to avoid affecting the common code path or calling a function that may introduce a stack frame, so float arithmetics is used to check the rounding mode and the threshold is selected accordingly. Diff: --- newlib/libm/common/sf_pow.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/newlib/libm/common/sf_pow.c b/newlib/libm/common/sf_pow.c index f7b22b6..2946c61 100644 --- a/newlib/libm/common/sf_pow.c +++ b/newlib/libm/common/sf_pow.c @@ -220,7 +220,17 @@ powf (float x, float y) { /* |y*log(x)| >= 126. */ if (ylogx > 0x1.fffffffd1d571p+6 * POWF_SCALE) + /* |x^y| > 0x1.ffffffp127. */ return __math_oflowf (sign_bias); + if (WANT_ROUNDING && WANT_ERRNO + && ylogx > 0x1.fffffffa3aae2p+6 * POWF_SCALE) + /* |x^y| > 0x1.fffffep127, check if we round away from 0. */ + if ((!sign_bias + && eval_as_float (1.0f + opt_barrier_float (0x1p-25f)) != 1.0f) + || (sign_bias + && eval_as_float (-1.0f - opt_barrier_float (0x1p-25f)) + != -1.0f)) + return __math_oflowf (sign_bias); if (ylogx <= -150.0 * POWF_SCALE) return __math_uflowf (sign_bias); #if WANT_ERRNO_UFLOW