[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