[PATCH] math: Fix powf special case [BZ #33563]

Adhemerval Zanella Netto adhemerval.zanella@linaro.org
Tue Oct 28 12:08:49 GMT 2025



On 27/10/25 12:31, Wilco Dijkstra wrote:
> 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.
> 
> Passes regress, OK for commit?

LGTM, thanks.

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>

> 
> ---
> 
> diff --git a/sysdeps/ieee754/flt-32/e_powf.c b/sysdeps/ieee754/flt-32/e_powf.c
> index 06587140fbbf47291fae86566efc7946f49ad466..07b68c2bac3f0da025de8eae658f8bf6176dba15 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);
>  }
> 
> 
> 
> 



More information about the Libc-alpha mailing list