[PATCH 2/5] math: Optimize frexpf (binary32) with fast path for normal numbers
Osama Abdelkader
osama.abdelkader@gmail.com
Tue Oct 21 22:05:19 GMT 2025
Add fast path optimization for frexpf using a single unsigned comparison
to identify normal floating-point numbers and return immediately via bit
manipulation.
The implementation uses asuint()/asfloat() from math_config.h and symbolic
constants (MANTISSA_MASK, SIGN_MASK, EXPONENT_BIAS, MANTISSA_WIDTH) for
better readability and maintainability.
For normal numbers (exponent 1 to 254), the function extracts the unbiased
exponent and constructs the result in [0.5, 1.0) using direct bit operations,
avoiding branches and floating-point operations.
Benchmark results on Intel Core i9-13900H (13th Gen):
Baseline: 5.858 ns/op
Optimized: 5.878 ns/op (average of 3 runs)
Speedup: Neutral (within measurement noise)
Signed-off-by: Osama Abdelkader <osama.abdelkader@gmail.com>
---
sysdeps/ieee754/flt-32/s_frexpf.c | 37 +++++++++++++++++++------------
1 file changed, 23 insertions(+), 14 deletions(-)
diff --git a/sysdeps/ieee754/flt-32/s_frexpf.c b/sysdeps/ieee754/flt-32/s_frexpf.c
index 59fef66a6b..da08c9367c 100644
--- a/sysdeps/ieee754/flt-32/s_frexpf.c
+++ b/sysdeps/ieee754/flt-32/s_frexpf.c
@@ -18,27 +18,36 @@ static char rcsid[] = "$NetBSD: s_frexpf.c,v 1.5 1995/05/10 20:47:26 jtc Exp $";
#include <math.h>
#include <math_private.h>
+#include "math_config.h"
#include <libm-alias-float.h>
static const float
two25 = 3.3554432000e+07; /* 0x4c000000 */
+/* Exponent bits for result in [0.5, 1.0): 0x7e = -1 + EXPONENT_BIAS. */
+#define FREXPF_EXP \
+ (((uint32_t) (EXPONENT_BIAS - 1)) << MANTISSA_WIDTH)
+
float __frexpf(float x, int *eptr)
{
- int32_t hx,ix;
- GET_FLOAT_WORD(hx,x);
- ix = 0x7fffffff&hx;
+ uint32_t hx = asuint (x);
+ uint32_t ex = (hx >> MANTISSA_WIDTH) & 0xff;
+
+ /* Fast path for normal numbers. */
+ if (__glibc_likely ((ex - 1) < 0xfe))
+ {
+ *eptr = ex - EXPONENT_BIAS + 1;
+ return asfloat ((hx & (MANTISSA_MASK | SIGN_MASK)) | FREXPF_EXP);
+ }
+
+ /* Handle special cases: zero, subnormal, infinity, NaN. */
+ uint32_t ix = hx & 0x7fffffff;
*eptr = 0;
- if(ix>=0x7f800000||(ix==0)) return x + x; /* 0,inf,nan */
- if (ix<0x00800000) { /* subnormal */
- x *= two25;
- GET_FLOAT_WORD(hx,x);
- ix = hx&0x7fffffff;
- *eptr = -25;
- }
- *eptr += (ix>>23)-126;
- hx = (hx&0x807fffff)|0x3f000000;
- SET_FLOAT_WORD(x,hx);
- return x;
+ if (ix >= 0x7f800000 || (ix == 0)) return x + x; /* 0,inf,nan */
+ /* Subnormal */
+ x *= two25;
+ hx = asuint (x);
+ *eptr = ((hx & 0x7fffffff) >> MANTISSA_WIDTH) - EXPONENT_BIAS - 25 + 1;
+ return asfloat ((hx & (MANTISSA_MASK | SIGN_MASK)) | FREXPF_EXP);
}
libm_alias_float (__frexp, frexp)
--
2.43.0
More information about the Libc-alpha
mailing list