From 8917bd3eb331c54477da8a59fc8a009f47477237 Mon Sep 17 00:00:00 2001 From: Wilco Dijkstra Date: Fri, 24 Oct 2025 14:26:50 +0000 Subject: [PATCH] math: Fix powf special case [BZ #33563] Fix powf (0x1.fffffep+127, 1.0f) to return 0x1.fffffep+127 when rouding upwards. Cleanup the special case code - performance improves by ~1.2%. This fixes BZ #33563. Reviewed-by: Adhemerval Zanella --- sysdeps/ieee754/flt-32/e_powf.c | 46 ++++++++++++++++++++------------- 1 file changed, 28 insertions(+), 18 deletions(-) diff --git a/sysdeps/ieee754/flt-32/e_powf.c b/sysdeps/ieee754/flt-32/e_powf.c index 06587140fb..07b68c2bac 100644 --- a/sysdeps/ieee754/flt-32/e_powf.c +++ b/sysdeps/ieee754/flt-32/e_powf.c @@ -202,30 +202,40 @@ __powf (float x, float y) ix -= 23 << 23; } } - double_t logx = log2_inline (ix); - double_t ylogx = (double) y * logx; /* Note: cannot overflow, y is single prec. */ + /* y * log2(x) cannot overflow since y is single precision. */ + double_t ylogx = (double) y * log2_inline (ix); + + /* Check whether |y*log(x)| >= 126. */ if (__glibc_unlikely ((asuint64 (ylogx) >> 47 & 0xffff) >= asuint64 (126.0 * POWF_SCALE) >> 47)) { - /* |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 - && math_narrow_eval (1.0f + math_opt_barrier (0x1p-25f)) != 1.0f) - || (sign_bias - && math_narrow_eval (-1.0f - math_opt_barrier (0x1p-25f)) - != -1.0f)) - return __math_oflowf (sign_bias); + if (ylogx <= -150.0 * POWF_SCALE) return __math_uflowf (sign_bias); -#if WANT_ERRNO_UFLOW - if (ylogx < -149.0 * POWF_SCALE) + + if (WANT_ERRNO_UFLOW && ylogx < -149.0 * POWF_SCALE) return __math_may_uflowf (sign_bias); -#endif + + /* |x^y| > 0x1.ffffffp127. */ + if (!WANT_ROUNDING && ylogx > 0x1.fffffffd1d571p+6 * POWF_SCALE) + return __math_oflowf (sign_bias); + + if (WANT_ROUNDING && ylogx > 0x1.fffffffa3aae2p+6 * POWF_SCALE) + { + if (ylogx > 0x1.fffffffd1d571p+6 * POWF_SCALE) + return __math_oflowf (sign_bias); + + /* |x^y| > 0x1.fffffep127, check if we round away from 0. */ + if (ylogx != 0x1.fffffffa3aae3p+6 * POWF_SCALE) + { + float x = math_opt_barrier (0x1p-25f); + if ((!sign_bias && math_narrow_eval (1.0f + x) != 1.0f) + || (sign_bias && math_narrow_eval (-1.0f - x) != -1.0f)) + return __math_oflowf (sign_bias); + } + + return sign_bias ? -0x1.fffffep127 : 0x1.fffffep127; + } } return (float) exp2_inline (ylogx, sign_bias); } -- 2.47.3