[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