[libc-commits] [libc] [libc][stdfix] Implement fxdivi functions (rdivi) (PR #154914)

Shreeyash Pandey via libc-commits libc-commits at lists.llvm.org
Fri Sep 5 12:23:35 PDT 2025


https://github.com/bojle updated https://github.com/llvm/llvm-project/pull/154914

>From f54208ee781fde878a42dcb573afa92293ffabe3 Mon Sep 17 00:00:00 2001
From: Shreeyash Pandey <shreeyash335 at gmail.com>
Date: Fri, 22 Aug 2025 14:16:57 +0530
Subject: [PATCH 1/4] [libc][stdfix] Implement fxdivi functions

Signed-off-by: Shreeyash Pandey <shreeyash335 at gmail.com>
---
 libc/config/linux/riscv/entrypoints.txt  |  1 +
 libc/config/linux/x86_64/entrypoints.txt |  1 +
 libc/include/stdfix.yaml                 |  8 ++++
 libc/src/__support/fixed_point/fx_bits.h | 53 ++++++++++++++++++++
 libc/src/stdfix/CMakeLists.txt           | 14 ++++++
 libc/src/stdfix/rdivi.cpp                | 21 ++++++++
 libc/src/stdfix/rdivi.h                  | 21 ++++++++
 libc/test/src/stdfix/CMakeLists.txt      | 16 +++++++
 libc/test/src/stdfix/DivITest.h          | 61 ++++++++++++++++++++++++
 libc/test/src/stdfix/rdivi_test.cpp      | 14 ++++++
 10 files changed, 210 insertions(+)
 create mode 100644 libc/src/stdfix/rdivi.cpp
 create mode 100644 libc/src/stdfix/rdivi.h
 create mode 100644 libc/test/src/stdfix/DivITest.h
 create mode 100644 libc/test/src/stdfix/rdivi_test.cpp

diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt
index 1a03683d72e61..b783dd4b04c74 100644
--- a/libc/config/linux/riscv/entrypoints.txt
+++ b/libc/config/linux/riscv/entrypoints.txt
@@ -986,6 +986,7 @@ if(LIBC_COMPILER_HAS_FIXED_POINT)
     libc.src.stdfix.idivulr
     libc.src.stdfix.idivuk
     libc.src.stdfix.idivulk
+    libc.src.stdfix.rdivi
   )
 endif()
 
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 5590f1a15ac57..f6beccc7229dd 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -1019,6 +1019,7 @@ if(LIBC_COMPILER_HAS_FIXED_POINT)
     libc.src.stdfix.idivulr
     libc.src.stdfix.idivuk
     libc.src.stdfix.idivulk
+    libc.src.stdfix.rdivi
   )
 endif()
 
diff --git a/libc/include/stdfix.yaml b/libc/include/stdfix.yaml
index 5b385124eb63d..451330c3478d2 100644
--- a/libc/include/stdfix.yaml
+++ b/libc/include/stdfix.yaml
@@ -544,3 +544,11 @@ functions:
     arguments:
       - type: unsigned long accum
     guard: LIBC_COMPILER_HAS_FIXED_POINT
+  - name: rdivi
+    standards:
+      - stdc_ext
+    return_type: fract
+    arguments:
+      - type: int
+      - type: int
+    guard: LIBC_COMPILER_HAS_FIXED_POINT
diff --git a/libc/src/__support/fixed_point/fx_bits.h b/libc/src/__support/fixed_point/fx_bits.h
index 00c6119b4f353..9069031786b0a 100644
--- a/libc/src/__support/fixed_point/fx_bits.h
+++ b/libc/src/__support/fixed_point/fx_bits.h
@@ -224,6 +224,59 @@ idiv(T x, T y) {
   return static_cast<XType>(result);
 }
 
+LIBC_INLINE long accum nrstep(long accum d, long accum x0) {
+  auto v = x0 * (2.lk - (d * x0));
+  return v;
+}
+
+/* Divide the two integers and return a fixed_point value
+ *
+ * For reference, see:
+ * https://en.wikipedia.org/wiki/Division_algorithm#Newton%E2%80%93Raphson_division
+ * https://stackoverflow.com/a/9231996
+ */
+template <typename XType> LIBC_INLINE constexpr XType divi(int n, int d) {
+  // If the value of the second operand of the / operator is zero, the
+  // behavior is undefined. Ref: ISO/IEC TR 18037:2008(E) p.g. 16
+  LIBC_CRASH_ON_VALUE(d, 0);
+
+  if (LIBC_UNLIKELY(n == 0)) {
+    return FXRep<XType>::ZERO();
+  }
+  bool d_is_signed = false;
+  if (d < 0) {
+    d = (d * -1);
+    d_is_signed = true;
+  }
+
+  unsigned int nv = static_cast<unsigned int>(n);
+  unsigned int dv = static_cast<unsigned int>(d);
+  unsigned int clz = cpp::countl_zero<unsigned int>(dv) - 1;
+  unsigned long int scaled_val = dv << clz;
+  /* Scale denominator to be in the range of [0.5,1] */
+  FXBits<long accum> d_scaled{scaled_val};
+  unsigned long int scaled_val_n = nv << clz;
+  /* Scale the numerator as much as the denominator to maintain correctness of
+   * the original equation
+   */
+  FXBits<long accum> n_scaled{scaled_val_n};
+  long accum n_scaled_val = n_scaled.get_val();
+  long accum d_scaled_val = d_scaled.get_val();
+  /* x0 = (48/17) - (32/17) * d_n */
+  long accum a = 2.8235lk; /* 48/17 */
+  long accum b = 1.8823lk; /* 32/17 */
+  long accum initial_approx = a - (b * d_scaled_val);
+  long accum val = nrstep(d_scaled_val, initial_approx);
+  val = nrstep(d_scaled_val, val);
+  val = nrstep(d_scaled_val, val);
+  val = nrstep(d_scaled_val, val);
+  long accum res = n_scaled_val * val;
+  if (d_is_signed) {
+    res *= static_cast<XType>(-1);
+  }
+  return static_cast<XType>(res);
+}
+
 } // namespace fixed_point
 } // namespace LIBC_NAMESPACE_DECL
 
diff --git a/libc/src/stdfix/CMakeLists.txt b/libc/src/stdfix/CMakeLists.txt
index 843111e3f80b1..3cbabd17ad34c 100644
--- a/libc/src/stdfix/CMakeLists.txt
+++ b/libc/src/stdfix/CMakeLists.txt
@@ -89,6 +89,20 @@ foreach(suffix IN ITEMS r lr k lk ur ulr uk ulk)
   )
 endforeach()
 
+foreach(suffix IN ITEMS r)
+  add_entrypoint_object(
+    ${suffix}divi
+    HDRS
+      ${suffix}divi.h
+    SRCS
+      ${suffix}divi.cpp
+    COMPILE_OPTIONS
+      ${libc_opt_high_flag}
+    DEPENDS
+      libc.src.__support.fixed_point.fx_bits
+  )
+endforeach()
+
 add_entrypoint_object(
   uhksqrtus
   HDRS
diff --git a/libc/src/stdfix/rdivi.cpp b/libc/src/stdfix/rdivi.cpp
new file mode 100644
index 0000000000000..227b412879a38
--- /dev/null
+++ b/libc/src/stdfix/rdivi.cpp
@@ -0,0 +1,21 @@
+//===-- Implementation of rdivi function ---------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "rdivi.h"
+#include "include/llvm-libc-macros/stdfix-macros.h" // fract
+#include "src/__support/common.h"                   // LLVM_LIBC_FUNCTION
+#include "src/__support/fixed_point/fx_bits.h"      // fixed_point
+#include "src/__support/macros/config.h"            // LIBC_NAMESPACE_DECL
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(fract, rdivi, (int a, int b)) {
+  return fixed_point::divi<fract>(a,b);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/stdfix/rdivi.h b/libc/src/stdfix/rdivi.h
new file mode 100644
index 0000000000000..aeda1ee9d40f0
--- /dev/null
+++ b/libc/src/stdfix/rdivi.h
@@ -0,0 +1,21 @@
+//===-- Implementation header for rdivi ------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_STDFIX_RDIVI_H
+#define LLVM_LIBC_SRC_STDFIX_RDIVI_H
+
+#include "include/llvm-libc-macros/stdfix-macros.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+fract rdivi(int a, int b);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_STDFIX_RDIVI_H
diff --git a/libc/test/src/stdfix/CMakeLists.txt b/libc/test/src/stdfix/CMakeLists.txt
index e2b4bc1805f7c..741522276feaa 100644
--- a/libc/test/src/stdfix/CMakeLists.txt
+++ b/libc/test/src/stdfix/CMakeLists.txt
@@ -120,6 +120,22 @@ foreach(suffix IN ITEMS r lr k lk ur ulr uk ulk)
   )
 endforeach()
 
+foreach(suffix IN ITEMS r)
+  add_libc_test(
+    ${suffix}divi_test
+    SUITE
+      libc-stdfix-tests
+    HDRS
+      DivITest.h
+    SRCS
+      ${suffix}divi_test.cpp
+    DEPENDS
+      libc.src.stdfix.${suffix}divi
+      libc.src.__support.fixed_point.fx_bits
+      libc.hdr.signal_macros
+  )
+endforeach()
+
 add_libc_test(
   uhksqrtus_test
   SUITE
diff --git a/libc/test/src/stdfix/DivITest.h b/libc/test/src/stdfix/DivITest.h
new file mode 100644
index 0000000000000..6642a5a4c93ab
--- /dev/null
+++ b/libc/test/src/stdfix/DivITest.h
@@ -0,0 +1,61 @@
+//===-- Utility class to test fxdivi functions ------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/__support/CPP/type_traits.h"
+#include "src/__support/fixed_point/fx_bits.h"
+#include "src/__support/fixed_point/fx_rep.h"
+#include "test/UnitTest/Test.h"
+
+template <typename XType> XType get_epsilon() {
+  // TODO: raise error
+  return 0;
+}
+template <> fract get_epsilon() { return FRACT_EPSILON; }
+template <> unsigned fract get_epsilon() { return UFRACT_EPSILON; }
+template <> long fract get_epsilon() { return LFRACT_EPSILON; }
+
+template <typename XType>
+class DivITest : public LIBC_NAMESPACE::testing::Test {
+  using FXRep = LIBC_NAMESPACE::fixed_point::FXRep<XType>;
+  using FXBits = LIBC_NAMESPACE::fixed_point::FXBits<XType>;
+
+public:
+  typedef XType (*DivIFunc)(int, int);
+
+  void testBasic(DivIFunc func) {
+    XType epsilon = get_epsilon<XType>();
+    EXPECT_LT((func(2, 3) - 0.666666r), epsilon);
+    EXPECT_LT((func(3, 4) - 0.75r), epsilon);
+    EXPECT_LT((func(1043, 2764) - 0.37735r), epsilon);
+    EXPECT_LT((func(60000, 720293) - 0.083299r), epsilon);
+
+    EXPECT_EQ(func(128, 256), 0.5r);
+    EXPECT_EQ(func(1, 2), 0.5r);
+    EXPECT_EQ(func(1, 4), 0.25r);
+    EXPECT_EQ(func(1, 8), 0.125r);
+    EXPECT_EQ(func(1, 16), 0.0625r);
+
+    EXPECT_EQ(func(-1, 2), -0.5r);
+    EXPECT_EQ(func(1, -4), -0.25r);
+    EXPECT_EQ(func(-1, 8), -0.125r);
+    EXPECT_EQ(func(1, -16), -0.0625r);
+  }
+
+  void testSpecial(DivIFunc func) {
+    EXPECT_EQ(func(0,10), 0.r);
+    EXPECT_DEATH([func] { func(10, 0); }, WITH_SIGNAL(-1));
+    EXPECT_EQ(func(-32768,32768), FRACT_MIN);
+    EXPECT_EQ(func(32767,32768), FRACT_MAX);  
+  }
+};
+
+#define LIST_DIVI_TESTS(Name, XType, func)                                     \
+  using LlvmLibc##Name##diviTest = DivITest<XType>;                            \
+  TEST_F(LlvmLibc##Name##diviTest, Basic) { testBasic(&func); }                \
+  TEST_F(LlvmLibc##Name##diviTest, Special) { testSpecial(&func); }                \
+  static_assert(true, "Require semicolon.")
diff --git a/libc/test/src/stdfix/rdivi_test.cpp b/libc/test/src/stdfix/rdivi_test.cpp
new file mode 100644
index 0000000000000..10ab366679a36
--- /dev/null
+++ b/libc/test/src/stdfix/rdivi_test.cpp
@@ -0,0 +1,14 @@
+//===-- Unittests for rdivi -----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "DivITest.h"
+
+#include "llvm-libc-macros/stdfix-macros.h" // fract
+#include "src/stdfix/rdivi.h"
+
+LIST_DIVI_TESTS(r, fract, LIBC_NAMESPACE::rdivi);

>From 040e83342ab4bd051b584e7cdbad91158ce06426 Mon Sep 17 00:00:00 2001
From: Shreeyash Pandey <shreeyash335 at gmail.com>
Date: Sun, 31 Aug 2025 01:01:23 +0530
Subject: [PATCH 2/4] [libc][stdfix] add a couple more tests and error info for
 divi

Signed-off-by: Shreeyash Pandey <shreeyash335 at gmail.com>
---
 libc/src/__support/fixed_point/fx_bits.h | 11 +++++++++++
 libc/test/src/stdfix/DivITest.h          | 20 ++++++++++++--------
 2 files changed, 23 insertions(+), 8 deletions(-)

diff --git a/libc/src/__support/fixed_point/fx_bits.h b/libc/src/__support/fixed_point/fx_bits.h
index 9069031786b0a..b6c88998d2bd4 100644
--- a/libc/src/__support/fixed_point/fx_bits.h
+++ b/libc/src/__support/fixed_point/fx_bits.h
@@ -265,10 +265,21 @@ template <typename XType> LIBC_INLINE constexpr XType divi(int n, int d) {
   /* x0 = (48/17) - (32/17) * d_n */
   long accum a = 2.8235lk; /* 48/17 */
   long accum b = 1.8823lk; /* 32/17 */
+  /* Error of the initial approximation, as derived
+   * from the wikipedia article is
+   *  E0 = 1/17 = 0.059 (5.9%)
+   */
   long accum initial_approx = a - (b * d_scaled_val);
+  /* Each newton-raphson iteration will square the error, due
+   * to quadratic convergence. So,
+   *  E1 = (0.059)^2 = 0.0034
+   */
   long accum val = nrstep(d_scaled_val, initial_approx);
+  /* E2 = 0.0000121 */
   val = nrstep(d_scaled_val, val);
+  /* E3 = 1.468e−10 */
   val = nrstep(d_scaled_val, val);
+  /* E4 = 2.155e−20 */
   val = nrstep(d_scaled_val, val);
   long accum res = n_scaled_val * val;
   if (d_is_signed) {
diff --git a/libc/test/src/stdfix/DivITest.h b/libc/test/src/stdfix/DivITest.h
index 6642a5a4c93ab..f3ac145ad0af8 100644
--- a/libc/test/src/stdfix/DivITest.h
+++ b/libc/test/src/stdfix/DivITest.h
@@ -11,10 +11,7 @@
 #include "src/__support/fixed_point/fx_rep.h"
 #include "test/UnitTest/Test.h"
 
-template <typename XType> XType get_epsilon() {
-  // TODO: raise error
-  return 0;
-}
+template <typename XType> XType get_epsilon() = delete;
 template <> fract get_epsilon() { return FRACT_EPSILON; }
 template <> unsigned fract get_epsilon() { return UFRACT_EPSILON; }
 template <> long fract get_epsilon() { return LFRACT_EPSILON; }
@@ -29,10 +26,10 @@ class DivITest : public LIBC_NAMESPACE::testing::Test {
 
   void testBasic(DivIFunc func) {
     XType epsilon = get_epsilon<XType>();
-    EXPECT_LT((func(2, 3) - 0.666666r), epsilon);
+    EXPECT_LT((func(2, 3) - 0.666656494140625r), epsilon);
     EXPECT_LT((func(3, 4) - 0.75r), epsilon);
-    EXPECT_LT((func(1043, 2764) - 0.37735r), epsilon);
-    EXPECT_LT((func(60000, 720293) - 0.083299r), epsilon);
+    EXPECT_LT((func(1043, 2764) - 0.3773516643r), epsilon);
+    EXPECT_LT((func(60000, 720293) - 0.08329943509r), epsilon);
 
     EXPECT_EQ(func(128, 256), 0.5r);
     EXPECT_EQ(func(1, 2), 0.5r);
@@ -48,9 +45,16 @@ class DivITest : public LIBC_NAMESPACE::testing::Test {
 
   void testSpecial(DivIFunc func) {
     EXPECT_EQ(func(0,10), 0.r);
-    EXPECT_DEATH([func] { func(10, 0); }, WITH_SIGNAL(-1));
+    EXPECT_EQ(func(0,-10), 0.r);
     EXPECT_EQ(func(-32768,32768), FRACT_MIN);
     EXPECT_EQ(func(32767,32768), FRACT_MAX);  
+    EXPECT_EQ(func(INT_MAX,INT_MAX), 1.0r);
+    EXPECT_EQ(func(INT_MAX-1,INT_MAX), 0.99999999r);
+    EXPECT_EQ(func(INT_MIN,INT_MAX), FRACT_MIN);
+    /* Expecting 0 here as fract is not precise enough to 
+     * handle 1/INT_MAX
+     */
+    EXPECT_EQ(func(1, INT_MAX), 0.r);
   }
 };
 

>From 71d283b5b0c64f65c21d23d83f5bf7ea7f58f355 Mon Sep 17 00:00:00 2001
From: Shreeyash Pandey <shreeyash335 at gmail.com>
Date: Sat, 6 Sep 2025 00:45:14 +0530
Subject: [PATCH 3/4] [libc] add a few tests to handles edge cases with
 FRACT_{MIN/MAX}

Signed-off-by: Shreeyash Pandey <shreeyash335 at gmail.com>
---
 libc/src/__support/fixed_point/fx_bits.h | 30 ++++++++++++++++--------
 libc/test/src/stdfix/DivITest.h          | 27 +++++++++++++--------
 2 files changed, 37 insertions(+), 20 deletions(-)

diff --git a/libc/src/__support/fixed_point/fx_bits.h b/libc/src/__support/fixed_point/fx_bits.h
index b6c88998d2bd4..cae79c449eb2e 100644
--- a/libc/src/__support/fixed_point/fx_bits.h
+++ b/libc/src/__support/fixed_point/fx_bits.h
@@ -243,14 +243,10 @@ template <typename XType> LIBC_INLINE constexpr XType divi(int n, int d) {
   if (LIBC_UNLIKELY(n == 0)) {
     return FXRep<XType>::ZERO();
   }
-  bool d_is_signed = false;
-  if (d < 0) {
-    d = (d * -1);
-    d_is_signed = true;
-  }
+  bool result_is_negative = (n < 0) ^ (d < 0);
 
-  unsigned int nv = static_cast<unsigned int>(n);
-  unsigned int dv = static_cast<unsigned int>(d);
+  unsigned int nv = static_cast<unsigned int>(n < 0 ? -n : n);
+  unsigned int dv = static_cast<unsigned int>(d < 0 ? -d : d);
   unsigned int clz = cpp::countl_zero<unsigned int>(dv) - 1;
   unsigned long int scaled_val = dv << clz;
   /* Scale denominator to be in the range of [0.5,1] */
@@ -281,11 +277,25 @@ template <typename XType> LIBC_INLINE constexpr XType divi(int n, int d) {
   val = nrstep(d_scaled_val, val);
   /* E4 = 2.155e−20 */
   val = nrstep(d_scaled_val, val);
+
   long accum res = n_scaled_val * val;
-  if (d_is_signed) {
-    res *= static_cast<XType>(-1);
+
+  if (result_is_negative) {
+    res *= static_cast<long accum>(-1);
+  }
+
+  // Check for overflow before returning
+  long accum max_val = static_cast<long accum>(FXRep<XType>::MAX());
+  long accum min_val = static_cast<long accum>(FXRep<XType>::MIN());
+
+  /* Per clause 7.18a.6.1, saturate values on overflow */
+  if (res > max_val) {
+    return FXRep<XType>::MAX();
+  } else if (res < min_val) {
+    return FXRep<XType>::MIN();
+  } else {
+    return static_cast<XType>(res);
   }
-  return static_cast<XType>(res);
 }
 
 } // namespace fixed_point
diff --git a/libc/test/src/stdfix/DivITest.h b/libc/test/src/stdfix/DivITest.h
index f3ac145ad0af8..fbb8ad684dca7 100644
--- a/libc/test/src/stdfix/DivITest.h
+++ b/libc/test/src/stdfix/DivITest.h
@@ -11,6 +11,8 @@
 #include "src/__support/fixed_point/fx_rep.h"
 #include "test/UnitTest/Test.h"
 
+#include <stdio.h>
+
 template <typename XType> XType get_epsilon() = delete;
 template <> fract get_epsilon() { return FRACT_EPSILON; }
 template <> unsigned fract get_epsilon() { return UFRACT_EPSILON; }
@@ -44,22 +46,27 @@ class DivITest : public LIBC_NAMESPACE::testing::Test {
   }
 
   void testSpecial(DivIFunc func) {
-    EXPECT_EQ(func(0,10), 0.r);
-    EXPECT_EQ(func(0,-10), 0.r);
-    EXPECT_EQ(func(-32768,32768), FRACT_MIN);
-    EXPECT_EQ(func(32767,32768), FRACT_MAX);  
-    EXPECT_EQ(func(INT_MAX,INT_MAX), 1.0r);
-    EXPECT_EQ(func(INT_MAX-1,INT_MAX), 0.99999999r);
-    EXPECT_EQ(func(INT_MIN,INT_MAX), FRACT_MIN);
-    /* Expecting 0 here as fract is not precise enough to 
+    XType epsilon = get_epsilon<XType>();
+    EXPECT_EQ(func(0, 10), 0.r);
+    EXPECT_EQ(func(0, -10), 0.r);
+    EXPECT_EQ(func(-(1 << FRACT_FBIT), 1 << FRACT_FBIT), FRACT_MIN);
+    EXPECT_EQ(func((1 << FRACT_FBIT) - 1, 1 << FRACT_FBIT), FRACT_MAX);
+    /* From Section 7.18a.6.1, functions returning a fixed-point value, the
+     * return value is saturated on overflow. */
+    EXPECT_EQ(func(INT_MAX, INT_MAX), FRACT_MAX);
+    EXPECT_LT(func(INT_MAX - 1, INT_MAX) - 0.99999999r, epsilon);
+    EXPECT_EQ(func(INT_MIN, INT_MAX), FRACT_MIN);
+    /* Expecting 0 here as fract is not precise enough to
      * handle 1/INT_MAX
      */
-    EXPECT_EQ(func(1, INT_MAX), 0.r);
+    EXPECT_LT(func(1, INT_MAX) - 0.r, epsilon);
+    /* This results in 1.1739, which should be saturated to FRACT_MAX */
+    EXPECT_EQ(func(27, 23), FRACT_MAX);
   }
 };
 
 #define LIST_DIVI_TESTS(Name, XType, func)                                     \
   using LlvmLibc##Name##diviTest = DivITest<XType>;                            \
   TEST_F(LlvmLibc##Name##diviTest, Basic) { testBasic(&func); }                \
-  TEST_F(LlvmLibc##Name##diviTest, Special) { testSpecial(&func); }                \
+  TEST_F(LlvmLibc##Name##diviTest, Special) { testSpecial(&func); }            \
   static_assert(true, "Require semicolon.")

>From cfe512246bbfe782f82ae964c7a6648fa7a79957 Mon Sep 17 00:00:00 2001
From: Shreeyash Pandey <shreeyash335 at gmail.com>
Date: Sat, 6 Sep 2025 00:53:08 +0530
Subject: [PATCH 4/4] [libc] fix formatting for rdivi.cpp

Signed-off-by: Shreeyash Pandey <shreeyash335 at gmail.com>
---
 libc/src/stdfix/rdivi.cpp | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/libc/src/stdfix/rdivi.cpp b/libc/src/stdfix/rdivi.cpp
index 227b412879a38..56de3eb3a5ed4 100644
--- a/libc/src/stdfix/rdivi.cpp
+++ b/libc/src/stdfix/rdivi.cpp
@@ -6,16 +6,16 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "rdivi.h"
 #include "include/llvm-libc-macros/stdfix-macros.h" // fract
-#include "src/__support/common.h"                   // LLVM_LIBC_FUNCTION
-#include "src/__support/fixed_point/fx_bits.h"      // fixed_point
-#include "src/__support/macros/config.h"            // LIBC_NAMESPACE_DECL
+#include "rdivi.h"
+#include "src/__support/common.h"              // LLVM_LIBC_FUNCTION
+#include "src/__support/fixed_point/fx_bits.h" // fixed_point
+#include "src/__support/macros/config.h"       // LIBC_NAMESPACE_DECL
 
 namespace LIBC_NAMESPACE_DECL {
 
 LLVM_LIBC_FUNCTION(fract, rdivi, (int a, int b)) {
-  return fixed_point::divi<fract>(a,b);
+  return fixed_point::divi<fract>(a, b);
 }
 
 } // namespace LIBC_NAMESPACE_DECL



More information about the libc-commits mailing list