[libc-commits] [libc] [libc][math] Add bit-rounding roundf implementation (PR #221648)

via libc-commits libc-commits at lists.llvm.org
Sun Sep 6 23:17:07 PDT 2026


https://github.com/sriramshastry created https://github.com/llvm/llvm-project/pull/221648

Add a float-specific fputil::round overload for roundf. It uses FPBits<float> and the biased exponent to handle sub-unit values, already-integral inputs, and finite values with fractional bits.

For finite fractional values, add the rounding bit and clear the lower mask. This implements round-to-nearest with halfway cases away from zero using integer operations on the float encoding.

Tests: libc.test.src.math.smoke.roundf_test
Tests: libc.test.src.math.smoke.roundf_test.__NO_ROUND_OPT

>From 3e971a2659eb5ce656f35620b9b7fbd360b8c918 Mon Sep 17 00:00:00 2001
From: Sriram Shastry <sriramshastry at gmail.com>
Date: Fri, 4 Sep 2026 12:41:21 +0530
Subject: [PATCH] [libc][math] Add bit-rounding roundf implementation

Add a float-specific fputil::round overload for roundf. It uses
FPBits<float> and the biased exponent to handle sub-unit values,
already-integral inputs, and finite values with fractional bits.

For finite fractional values, add the rounding bit and clear the
lower mask. This implements round-to-nearest with halfway cases away
from zero using integer operations on the float encoding.

Tests: libc.test.src.math.smoke.roundf_test
Tests: libc.test.src.math.smoke.roundf_test.__NO_ROUND_OPT
---
 .../FPUtil/NearestIntegerOperations.h         | 25 +++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/libc/src/__support/FPUtil/NearestIntegerOperations.h b/libc/src/__support/FPUtil/NearestIntegerOperations.h
index 203e3c43ae9c9..7e52e8cfb18d6 100644
--- a/libc/src/__support/FPUtil/NearestIntegerOperations.h
+++ b/libc/src/__support/FPUtil/NearestIntegerOperations.h
@@ -104,6 +104,31 @@ LIBC_INLINE constexpr T floor(T x) {
   }
 }
 
+LIBC_INLINE constexpr float round(float x) {
+  using FloatBits = FPBits<float>;
+  using StorageType = typename FloatBits::StorageType;
+
+  FloatBits bits(x);
+  StorageType x_u = bits.uintval();
+  StorageType biased_exponent = bits.get_biased_exponent();
+
+  if (biased_exponent <= FloatBits::EXP_BIAS - 1) {
+    if (biased_exponent == FloatBits::EXP_BIAS - 1)
+      return FloatBits::one(bits.sign()).get_val();
+    return FloatBits::zero(bits.sign()).get_val();
+  }
+
+  if (biased_exponent >= FloatBits::EXP_BIAS + FloatBits::FRACTION_LEN)
+    return x;
+
+  StorageType exponent = biased_exponent - FloatBits::EXP_BIAS;
+  StorageType round_bit = StorageType(1)
+                          << (FloatBits::FRACTION_LEN - exponent - 1);
+  StorageType mask = static_cast<StorageType>((round_bit << 1) - 1);
+  return FloatBits(static_cast<StorageType>((x_u + round_bit) & ~mask))
+      .get_val();
+}
+
 template <typename T, cpp::enable_if_t<cpp::is_floating_point_v<T>, int> = 0>
 LIBC_INLINE constexpr T round(T x) {
   using StorageType = typename FPBits<T>::StorageType;



More information about the libc-commits mailing list