[libc-commits] [libc] [libc][math] Integer-only, statically rounded implementation of expf (PR #209406)
via libc-commits
libc-commits at lists.llvm.org
Mon Aug 17 21:01:04 PDT 2026
=?utf-8?q?Hoàng_Minh_Thiên?=,=?utf-8?q?Hoàng_Minh_Thiên?=,
=?utf-8?q?Hoàng_Minh_Thiên?=,=?utf-8?q?Hoàng_Minh_Thiên?=,
=?utf-8?q?Hoàng_Minh_Thiên?=,=?utf-8?q?Hoàng_Minh_Thiên?=,
=?utf-8?q?Hoàng_Minh_Thiên?=,=?utf-8?q?Hoàng_Minh_Thiên?=,
=?utf-8?q?Hoàng_Minh_Thiên?=,=?utf-8?q?Hoàng_Minh_Thiên?=,
=?utf-8?q?Hoàng_Minh_Thiên?=,=?utf-8?q?Hoàng_Minh_Thiên?=,
=?utf-8?q?Hoàng_Minh_Thiên?=,=?utf-8?q?Hoàng_Minh_Thiên?=,
=?utf-8?q?Hoàng_Minh_Thiên?=,=?utf-8?q?Hoàng_Minh_Thiên?=,
=?utf-8?q?Hoàng_Minh_Thiên?=,=?utf-8?q?Hoàng_Minh_Thiên?=,
=?utf-8?q?Hoàng_Minh_Thiên?=,=?utf-8?q?Hoàng_Minh_Thiên?=,
=?utf-8?q?Hoàng_Minh_Thiên?Message-ID:
In-Reply-To: <llvm.org/llvm/llvm-project/pull/209406 at github.com>
================
@@ -170,43 +193,52 @@ LIBC_INLINE float expf(float x, int rounding) {
EXPF_COEFFS[5], EXPF_COEFFS[6], EXPF_COEFFS[7],
EXPF_COEFFS[8], EXPF_COEFFS[9], EXPF_COEFFS[10]);
- // Dropping some last bits (won't need them as we're casting into 32-bit float
- // anyway)
- constexpr uint32_t DROP_BITS = 2;
- if (LIBC_UNLIKELY(is_neg && d >= 0)) { // subnormal
- // 1 + p
- uint64_t full_val =
- (uint64_t(1) << (64 - DROP_BITS)) | (p.val[0] >> DROP_BITS);
-
-// add rounding bit
-// skip for R0, RD
-#ifdef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
- if (LIBC_UNLIKELY(rounding != FE_TONEAREST))
-#endif
- full_val += (uint64_t(1) << ((41 - DROP_BITS) + d));
-
- // RU
-#ifndef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
- if (LIBC_UNLIKELY(rounding == FE_UPWARD)) {
- constexpr uint64_t ROUND_UP_MASK = (uint64_t(1) << DROP_BITS) - 1;
- full_val += ROUND_UP_MASK;
- }
-#endif
+ uint32_t shift_length = 40;
+ uint32_t leading_one = 0;
- // shift back to align to 32-bit float representation
- uint32_t result = static_cast<uint32_t>(full_val >> ((42 - DROP_BITS) + d));
+ if (is_neg && d >= 0) { // subnormal
+ e_y_unbiased = 0;
+ leading_one = 1 << (24 - d);
+ shift_length += d;
+ }
+
+#ifndef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
+ if (rounding == FE_TONEAREST) {
+ uint32_t result =
+ (static_cast<uint32_t>(p.val[0] >> shift_length) + 1 + leading_one);
+ result >>= 1;
+ result += e_y_unbiased;
+
+ std::cout << e_y_unbiased << ' ' << shift_length << ' ' << result
+ << std::endl;
+ std::cout << p.val[0] << std::endl;
+ std::cout << l2y_r_frac.val[0] << std::endl;
+ std::cout << leading_one << std::endl;
return cpp::bit_cast<float>(result);
}
+#else
+ uint32_t result = (static_cast<uint32_t>(p.val[0] >> shift_length) + 1);
+ result >>= 1;
+ result += e_y_unbiased;
+
+ return cpp::bit_cast<float>(result);
+#endif // !LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
----------------
lntue wrote:
also put other rounding modes below inside `#else`
https://github.com/llvm/llvm-project/pull/209406
More information about the libc-commits
mailing list