[PATCH] math: Optimize frexp with fast path for normal numbers

Wilco Dijkstra Wilco.Dijkstra@arm.com
Tue Oct 21 22:30:53 GMT 2025


Hi,

> +  uint32_t ex = 0x7ff & (ix >> 52);

> It can be either:
>
>  uint32_t ex = get_exponent (ix) + EXPONENT_BIAS;
>
> Or maybe add a new function get_exponent_unbiased.
 
For this case we need the raw exponent, so eg.

uint32_t ex = (ix >> MANTISSA_MASK) & 0x7ff;

will work (and please avoid writing x = 2 + x rather than x = x + 2!).

> -  if (__glibc_likely (ex != 0x7ff && x != 0.0))
> +  /* Fast path for normal numbers.  */
> +  if (__glibc_likely ((ex - 1) < 0x7fe))
>      {
> -      /* Not zero and finite.  */
> -      e = ex - 1022;
> -      if (__glibc_unlikely (ex == 0))
> -     {
> -       /* Subnormal.  */
> -       x *= 0x1p54;
> -       EXTRACT_WORDS64 (ix, x);
> -       ex = 0x7ff & (ix >> 52);
> -       e = ex - 1022 - 54;
> -     }
> +      *eptr = ex - 1022;
> +      return asdouble ((ix & INT64_C (0x800fffffffffffff)) | INT64_C (0x3fe0000000000000));

> I think this like is too long, maybe:
>
>  return asdouble ((ix & (MANTISSA_MASK | SIGN_MASK)
>                   | INT64_C (0x3fe0000000000000));
>
> And maybe add INT64_C (0x3fe0000000000000) as a macro.

Also the question is whether this expression results in good code on
most targets - 64-bit immediates are best avoided in general.

> +    }
> 
> +  /* Handle special cases: zero, subnormal, infinity, NaN.  */
> +  int e = 0;
> +  if (__glibc_likely (ex != 0x7ff && x != 0.0))
> +    {
> +      /* Subnormal.  */
> +      x *= 0x1p54;
> +      EXTRACT_WORDS64 (ix, x);

  ix = asuint64 (x);

> +      ex = 0x7ff & (ix >> 52);
> +      e = ex - 1022 - 54;
>        ix = (ix & INT64_C (0x800fffffffffffff)) | INT64_C (0x3fe0000000000000);
>        INSERT_WORDS64 (x, ix);
>      }

Denormals are best handled by using clz I think.

Cheers,
Wilco


More information about the Libc-alpha mailing list