[PATCH 4/5] math: Optimize frexpl (intel96) with fast path for normal numbers
Osama Abdelkader
osama.abdelkader@gmail.com
Tue Oct 21 22:05:21 GMT 2025
Add fast path optimization for frexpl using
a single unsigned comparison to identify normal floating-point numbers and
return immediately via exponent manipulation.
The implementation uses symbolic constants (FREXPL_EXP, EXPONENT_BIAS,
SIGN_MASK) for better readability and maintainability.
For normal numbers (exponent 1 to 32766), the function extracts the unbiased
exponent and sets the result exponent to -1 + bias (0x3ffe) to place the
value in [0.5, 1.0), avoiding branches and extra operations.
Benchmark results on Intel Core i9-13900H (13th Gen):
Baseline: 25.543 ns/op
Optimized: 24.402 ns/op (average of 3 runs)
Speedup: 1.05x (4.5% faster)
Signed-off-by: Osama Abdelkader <osama.abdelkader@gmail.com>
---
sysdeps/ieee754/ldbl-96/s_frexpl.c | 35 ++++++++++++++++++++----------
1 file changed, 24 insertions(+), 11 deletions(-)
diff --git a/sysdeps/ieee754/ldbl-96/s_frexpl.c b/sysdeps/ieee754/ldbl-96/s_frexpl.c
index c610704cca..2ce3d7d9e4 100644
--- a/sysdeps/ieee754/ldbl-96/s_frexpl.c
+++ b/sysdeps/ieee754/ldbl-96/s_frexpl.c
@@ -38,22 +38,35 @@ two65 = 3.68934881474191032320e+19L; /* 0x4040, 0x80000000, 0x00000000 */
# error "Cannot handle this MANT_DIG"
#endif
+/* Biased exponent for result in [0.5, 1.0): 0x3ffe = -1 + 16383. */
+#define FREXPL_EXP 0x3ffe
+#define EXPONENT_BIAS 16383
+#define SIGN_MASK 0x8000
long double __frexpl(long double x, int *eptr)
{
- uint32_t se, hx, ix, lx;
+ uint32_t se, hx, lx;
GET_LDOUBLE_WORDS(se,hx,lx,x);
- ix = 0x7fff&se;
+ uint32_t ex = 0x7fff & se;
+
+ /* Fast path for normal numbers. */
+ if (__glibc_likely ((ex - 1U) < 0x7ffe))
+ {
+ *eptr = ex - EXPONENT_BIAS + 1;
+ se = (se & SIGN_MASK) | FREXPL_EXP;
+ SET_LDOUBLE_EXP(x,se);
+ return x;
+ }
+
+ /* Handle special cases: zero, subnormal, infinity, NaN. */
*eptr = 0;
- if(ix==0x7fff||((ix|hx|lx)==0)) return x + x; /* 0,inf,nan */
- if (ix==0x0000) { /* subnormal */
- x *= two65;
- GET_LDOUBLE_EXP(se,x);
- ix = se&0x7fff;
- *eptr = -65;
- }
- *eptr += ix-16382;
- se = (se & 0x8000) | 0x3ffe;
+ if (ex == 0x7fff || ((ex | hx | lx) == 0)) return x + x; /* 0,inf,nan */
+ /* Subnormal */
+ x *= two65;
+ GET_LDOUBLE_EXP(se,x);
+ ex = se & 0x7fff;
+ *eptr = ex - EXPONENT_BIAS - 65 + 1;
+ se = (se & SIGN_MASK) | FREXPL_EXP;
SET_LDOUBLE_EXP(x,se);
return x;
}
--
2.43.0
More information about the Libc-alpha
mailing list