[libc-commits] [libc] [libc][stdfix] Implement divifx functions in LLVM libc (PR #206115)
via libc-commits
libc-commits at lists.llvm.org
Wed Jul 15 21:46:40 PDT 2026
================
@@ -0,0 +1,176 @@
+//===-- Utility class to test divifx 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 "test/UnitTest/Test.h"
+
+#include "hdr/signal_macros.h"
+#include "llvm-libc-macros/stdfix-macros.h"
+#include "src/__support/CPP/limits.h"
+#include "src/__support/fixed_point/fx_bits.h"
+#include "src/__support/fixed_point/fx_rep.h"
+
+namespace cpp = LIBC_NAMESPACE::cpp;
+
+template <typename IntType, typename FXType>
+class DiviFxTest : public LIBC_NAMESPACE::testing::Test {
+
+ using FXRep = LIBC_NAMESPACE::fixed_point::FXRep<FXType>;
+
+ static constexpr FXType max = FXRep::MAX();
+ static constexpr FXType min = FXRep::MIN();
+ static constexpr FXType zero = FXRep::ZERO();
+ static constexpr FXType epsilon = FXRep::EPS();
+ static constexpr FXType one_half = FXRep::ONE_HALF();
+ static constexpr FXType one_fourth = FXRep::ONE_FOURTH();
+ static constexpr FXType one_eighth = FXRep::ONE_EIGHTH();
+
+ static constexpr bool is_signed = (FXRep::SIGN_LEN > 0);
+ static constexpr bool has_integral = (FXRep::INTEGRAL_LEN > 0);
+
+public:
+ typedef IntType (*DiviFxFunc)(IntType, FXType);
+
+ void testBasicNumbers(DiviFxFunc func) {
+
+ EXPECT_EQ(func(0, one_eighth), static_cast<IntType>(0));
+ EXPECT_EQ(func(0, one_fourth), static_cast<IntType>(0));
+ EXPECT_EQ(func(0, one_half), static_cast<IntType>(0));
+ EXPECT_EQ(func(1, one_eighth), static_cast<IntType>(8));
+ EXPECT_EQ(func(1, one_fourth), static_cast<IntType>(4));
+ EXPECT_EQ(func(1, one_half), static_cast<IntType>(2));
+ EXPECT_EQ(func(2, one_eighth), static_cast<IntType>(16));
+ EXPECT_EQ(func(2, one_fourth), static_cast<IntType>(8));
+ EXPECT_EQ(func(2, one_half), static_cast<IntType>(4));
+
+ // Verify rounding towards 0.
+ EXPECT_EQ(func(1, 3 * one_fourth), static_cast<IntType>(1));
+ EXPECT_EQ(func(2, 3 * one_fourth), static_cast<IntType>(2));
+
+ if constexpr (is_signed) {
+ EXPECT_EQ(func(-1, one_half), static_cast<IntType>(-2));
+ EXPECT_EQ(func(1, -one_half), static_cast<IntType>(-2));
+ EXPECT_EQ(func(-1, -one_half), static_cast<IntType>(2));
+ EXPECT_EQ(func(-2, one_fourth), static_cast<IntType>(-8));
+ EXPECT_EQ(func(2, -one_fourth), static_cast<IntType>(-8));
+
+ // Verify rounding towards 0.
+ EXPECT_EQ(func(-1, 3 * one_fourth), static_cast<IntType>(-1));
+ EXPECT_EQ(func(1, -3 * one_fourth), static_cast<IntType>(-1));
+ EXPECT_EQ(func(-2, 3 * one_fourth), static_cast<IntType>(-2));
+ EXPECT_EQ(func(2, -3 * one_fourth), static_cast<IntType>(-2));
+
+ EXPECT_EQ(func(1, static_cast<FXType>(-1)), static_cast<IntType>(-1));
+ EXPECT_EQ(func(-1, static_cast<FXType>(-1)), static_cast<IntType>(1));
+ }
+
+ if constexpr (has_integral) {
+ EXPECT_EQ(func(1, static_cast<FXType>(1)), static_cast<IntType>(1));
+
+ if constexpr (is_signed) {
+ EXPECT_EQ(func(-1, static_cast<FXType>(1)), static_cast<IntType>(-1));
+ }
+
+ // Only run these tests for accum types that can represent these operands.
+ constexpr FXType max_test_operand = static_cast<FXType>(4);
+
+ if constexpr (max >= max_test_operand) {
+ EXPECT_EQ(func(3, 2.5), static_cast<IntType>(1));
+ EXPECT_EQ(func(2, 3.5), static_cast<IntType>(0));
+ EXPECT_EQ(func(3, 1.5), static_cast<IntType>(2));
+ EXPECT_EQ(func(4, 2.0), static_cast<IntType>(2));
+
+ if constexpr (is_signed) {
+ EXPECT_EQ(func(2, -3.5), static_cast<IntType>(0));
+ EXPECT_EQ(func(-3, 2.5), static_cast<IntType>(-1));
+ EXPECT_EQ(func(-3, 1.5), static_cast<IntType>(-2));
+ EXPECT_EQ(func(-3, -2.5), static_cast<IntType>(1));
+ }
+ }
+ }
+ }
+
+ void testEdgeCases(DiviFxFunc func) {
+
+ constexpr IntType int_max = cpp::numeric_limits<IntType>::max();
+
+ if constexpr (has_integral) {
+ EXPECT_EQ(func(int_max, static_cast<FXType>(1)), int_max);
+ }
+
+ if constexpr (is_signed) {
+ EXPECT_EQ(func(int_max, static_cast<FXType>(-1)), -int_max);
+ }
+
+ // Only valid when integral bits (excluding sign) exceed fraction bits.
+ // Otherwise 1<<FRACTION_LEN may not fit in IntType.
+ if constexpr ((FXRep::INTEGRAL_LEN) > FXRep::FRACTION_LEN) {
+ constexpr IntType epsilon_result = static_cast<IntType>(1)
+ << FXRep::FRACTION_LEN;
+ EXPECT_EQ(func(1, epsilon), epsilon_result);
+ if constexpr (is_signed) {
+ EXPECT_EQ(func(1, -epsilon), -epsilon_result);
+ EXPECT_EQ(func(-1, epsilon), -epsilon_result);
+ EXPECT_EQ(func(-1, -epsilon), epsilon_result);
+ }
+ }
+
+ if constexpr (has_integral) {
+ constexpr IntType largest_positive =
----------------
Sukumarsawant wrote:
You can try doing the intermediate calculation in unsigned to avoid the failure
https://github.com/llvm/llvm-project/pull/206115
More information about the libc-commits
mailing list