[libc-commits] [libc] [libc][math] Add Generic Comparison Operations for floating point types (PR #144983)

Krishna Pandey via libc-commits libc-commits at lists.llvm.org
Thu Jun 19 21:54:16 PDT 2025


https://github.com/krishna2803 created https://github.com/llvm/llvm-project/pull/144983

The PR implements the following generic comparison operation functions for floating point types along with unittests:
- `fputil::equals`
- `fputil::not_equals`
- `fputil::less_than`
- `fputil::less_than_or_equals`
- `fputil::greater_than`
- `fputil::greater_than_or_equals`

cc @lntue @overmighty 

>From 8b4ef346e4386cad6d4a0a295ddfb4e8dd3c9c2c Mon Sep 17 00:00:00 2001
From: krishna2803 <kpandey81930 at gmail.com>
Date: Fri, 20 Jun 2025 06:57:34 +0530
Subject: [PATCH 1/6] feat: add ComparisionOperations for FPBits

Signed-off-by: krishna2803 <kpandey81930 at gmail.com>
---
 libc/src/__support/FPUtil/CMakeLists.txt      |  10 ++
 .../__support/FPUtil/ComparisionOperations.h  | 121 ++++++++++++++++++
 2 files changed, 131 insertions(+)
 create mode 100644 libc/src/__support/FPUtil/ComparisionOperations.h

diff --git a/libc/src/__support/FPUtil/CMakeLists.txt b/libc/src/__support/FPUtil/CMakeLists.txt
index bfe0170f09fd9..16989cdecf6fb 100644
--- a/libc/src/__support/FPUtil/CMakeLists.txt
+++ b/libc/src/__support/FPUtil/CMakeLists.txt
@@ -209,6 +209,16 @@ add_header_library(
     libc.src.__support.macros.properties.types
 )
 
+add_header_library(
+  comparision_operations
+  HDRS
+    ComparisionOperations.h
+  DEPENDS
+    .fp_bits
+    .fenv_impl
+    libc.src.__support.config
+)
+
 add_header_library(
   hypot
   HDRS
diff --git a/libc/src/__support/FPUtil/ComparisionOperations.h b/libc/src/__support/FPUtil/ComparisionOperations.h
new file mode 100644
index 0000000000000..fed3927eeecff
--- /dev/null
+++ b/libc/src/__support/FPUtil/ComparisionOperations.h
@@ -0,0 +1,121 @@
+//===-- Comparision operations on floating point numbers --------*- 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___SUPPORT_FPUTIL_COMPARISIONOPERATIONS_H
+#define LLVM_LIBC_SRC___SUPPORT_FPUTIL_COMPARISIONOPERATIONS_H
+
+#include "FEnvImpl.h" // raise_except_if_required
+#include "FPBits.h" // FPBits<T>
+#include "src/__support/macros/config.h" // LIBC_NAMESPACE_DECL
+
+namespace LIBC_NAMESPACE_DECL {
+namespace fputil {
+
+// IEEE Standard 754-2019. Section 5.11
+// Rules for comparision within the same floating point type
+// 1. +0 = −0
+// 2. (i)   +inf  = +inf
+//    (ii)  -inf  = -inf
+//    (iii) -inf != +inf
+// 3. Any comparision with NaN return false except (NaN != NaN => true)
+template <typename T>
+LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<T>, bool> equals(T x,
+                                                                       T y) {
+  using FPBits = FPBits<T>;
+  FPBits x_bits(x);
+  FPBits y_bits(y);
+
+  if (x_bits.is_signaling_nan() || y_bits.is_signaling_nan())
+    fputil::raise_except_if_required(FE_INVALID);
+
+  // NaN == x returns false for every x
+  if (x_bits.is_nan() || y_bits.is_nan())
+    return false;
+
+  // +/- 0 == +/- 0
+  if (x_bits.is_zero() && y_bits.is_zero())
+    return true;
+
+  // should also work for comparisions of different signs
+  return x_bits.uintval() == y_bits.uintval();
+}
+
+// !(x == y) => x != y
+template <typename T>
+LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<T>, bool>
+not_equals(T x, T y) {
+  return !equals(x, y);
+}
+
+// Rules:
+// 1. -inf < x (x != -inf)
+// 2. x < +inf (x != +inf)
+// 3. Any comparision with NaN return false
+template <typename T>
+LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<T>, bool> less_than(T x,
+                                                                          T y) {
+  using FPBits = FPBits<T>;
+  FPBits x_bits(x);
+  FPBits y_bits(y);
+
+  if (x_bits.is_signaling_nan() || y_bits.is_signaling_nan())
+    fputil::raise_except_if_required(FE_INVALID);
+
+  // Any comparision with NaN returns false
+  if (x_bits.is_nan() || y_bits.is_nan())
+    return false;
+
+  if (x_bits.is_zero() && y_bits.is_zero())
+    return false;
+
+  if (x_bits.is_neg() && y_bits.is_pos())
+    return true;
+
+  if (x_bits.is_pos() && y_bits.is_neg())
+    return false;
+
+  // since we store the float in the format: s | e | m
+  // the comparisions should work if we directly compare the uintval's
+
+  // TODO: verify if we should use FPBits.get_exponent and FPBits.get_mantissa
+  // instead of directly comparing uintval's
+
+  // both negative
+  if (x_bits.is_neg())
+    return x_bits.uintval() > y_bits.uintval();
+
+  // both positive
+  return x_bits.uintval() < y_bits.uintval();
+}
+
+// x < y => y > x
+template <typename T>
+LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<T>, bool>
+greater_than(T x, T y) {
+  return less_than(y, x);
+}
+
+// following is expression is correct, accounting for NaN case(s) as well
+// x <= y => (x < y) || (x == y)
+template <typename T>
+LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<T>, bool>
+less_than_or_equals(T x, T y) {
+  return less_than(x, y) || equals(x, y);
+}
+
+// x >= y => (x > y) || (x == y) => (y < x) || (x == y)
+template <typename T>
+LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<T>, bool>
+greater_than_or_equals(T x, T y) {
+  return less_than(y, x) || equals(x, y);
+}
+
+} // namespace fputil
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_FPUTIL_COMPARISIONOPERATIONS_H

>From f0997ab545a6845b9bf38e03e3bde4aac9612c7e Mon Sep 17 00:00:00 2001
From: krishna2803 <kpandey81930 at gmail.com>
Date: Fri, 20 Jun 2025 06:58:00 +0530
Subject: [PATCH 2/6] style: clang-format

Signed-off-by: krishna2803 <kpandey81930 at gmail.com>
---
 libc/src/__support/FPUtil/ComparisionOperations.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/libc/src/__support/FPUtil/ComparisionOperations.h b/libc/src/__support/FPUtil/ComparisionOperations.h
index fed3927eeecff..b8551998ba2be 100644
--- a/libc/src/__support/FPUtil/ComparisionOperations.h
+++ b/libc/src/__support/FPUtil/ComparisionOperations.h
@@ -9,8 +9,8 @@
 #ifndef LLVM_LIBC_SRC___SUPPORT_FPUTIL_COMPARISIONOPERATIONS_H
 #define LLVM_LIBC_SRC___SUPPORT_FPUTIL_COMPARISIONOPERATIONS_H
 
-#include "FEnvImpl.h" // raise_except_if_required
-#include "FPBits.h" // FPBits<T>
+#include "FEnvImpl.h"                    // raise_except_if_required
+#include "FPBits.h"                      // FPBits<T>
 #include "src/__support/macros/config.h" // LIBC_NAMESPACE_DECL
 
 namespace LIBC_NAMESPACE_DECL {

>From 2a4dc5fc98c0e56c3e888bf2e216ee1fec1fb5d9 Mon Sep 17 00:00:00 2001
From: krishna2803 <kpandey81930 at gmail.com>
Date: Fri, 20 Jun 2025 10:07:07 +0530
Subject: [PATCH 3/6] chore: reorganize includes

Signed-off-by: krishna2803 <kpandey81930 at gmail.com>
---
 libc/src/__support/FPUtil/CMakeLists.txt          | 1 +
 libc/src/__support/FPUtil/ComparisionOperations.h | 7 ++++---
 2 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/libc/src/__support/FPUtil/CMakeLists.txt b/libc/src/__support/FPUtil/CMakeLists.txt
index 16989cdecf6fb..6b2ca3bb77fd9 100644
--- a/libc/src/__support/FPUtil/CMakeLists.txt
+++ b/libc/src/__support/FPUtil/CMakeLists.txt
@@ -216,6 +216,7 @@ add_header_library(
   DEPENDS
     .fp_bits
     .fenv_impl
+    libc.src.__support.CPP.type_traits
     libc.src.__support.config
 )
 
diff --git a/libc/src/__support/FPUtil/ComparisionOperations.h b/libc/src/__support/FPUtil/ComparisionOperations.h
index b8551998ba2be..a4cdd4214b4db 100644
--- a/libc/src/__support/FPUtil/ComparisionOperations.h
+++ b/libc/src/__support/FPUtil/ComparisionOperations.h
@@ -9,9 +9,10 @@
 #ifndef LLVM_LIBC_SRC___SUPPORT_FPUTIL_COMPARISIONOPERATIONS_H
 #define LLVM_LIBC_SRC___SUPPORT_FPUTIL_COMPARISIONOPERATIONS_H
 
-#include "FEnvImpl.h"                    // raise_except_if_required
-#include "FPBits.h"                      // FPBits<T>
-#include "src/__support/macros/config.h" // LIBC_NAMESPACE_DECL
+#include "FEnvImpl.h"                      // raise_except_if_required
+#include "FPBits.h"                        // FPBits<T>
+#include "src/__support/CPP/type_traits.h" // enable_if, is_floating_point
+#include "src/__support/macros/config.h"   // LIBC_NAMESPACE_DECL
 
 namespace LIBC_NAMESPACE_DECL {
 namespace fputil {

>From e44e43e11f1fc754f43bb0cad5c8f33585be41e2 Mon Sep 17 00:00:00 2001
From: krishna2803 <kpandey81930 at gmail.com>
Date: Fri, 20 Jun 2025 10:07:34 +0530
Subject: [PATCH 4/6] feat: add basic unittests for Comparision Operations

Signed-off-by: krishna2803 <kpandey81930 at gmail.com>
---
 libc/test/src/__support/FPUtil/CMakeLists.txt |  12 +
 .../FPUtil/comparision_operations_test.cpp    | 254 ++++++++++++++++++
 2 files changed, 266 insertions(+)
 create mode 100644 libc/test/src/__support/FPUtil/comparision_operations_test.cpp

diff --git a/libc/test/src/__support/FPUtil/CMakeLists.txt b/libc/test/src/__support/FPUtil/CMakeLists.txt
index 1e64e9ba425a5..851506ccec6e2 100644
--- a/libc/test/src/__support/FPUtil/CMakeLists.txt
+++ b/libc/test/src/__support/FPUtil/CMakeLists.txt
@@ -38,3 +38,15 @@ add_fp_unittest(
   DEPENDS
     libc.src.__support.FPUtil.rounding_mode
 )
+
+add_fp_unittest(
+  comparision_operations_test
+  SUITE
+    libc-fputil-tests
+  SRCS
+    comparision_operations_test.cpp
+  DEPENDS
+    libc.src.__support.FPUtil.fp_bits
+    # libc.src.__support.FPUtil.comparision_operations
+)
+
diff --git a/libc/test/src/__support/FPUtil/comparision_operations_test.cpp b/libc/test/src/__support/FPUtil/comparision_operations_test.cpp
new file mode 100644
index 0000000000000..a2ac13723bae5
--- /dev/null
+++ b/libc/test/src/__support/FPUtil/comparision_operations_test.cpp
@@ -0,0 +1,254 @@
+//===-- Unittests for Comparision Operations for FPBits class -------------===//
+//
+// 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/FPUtil/ComparisionOperations.h"
+#include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/macros/properties/types.h"
+#include "src/__support/sign.h"
+#include "test/UnitTest/FPMatcher.h"
+#include "test/UnitTest/Test.h"
+#include "utils/MPFRWrapper/MPFRUtils.h"
+
+using LIBC_NAMESPACE::fputil::equals;
+using LIBC_NAMESPACE::fputil::greater_than;
+using LIBC_NAMESPACE::fputil::greater_than_or_equals;
+using LIBC_NAMESPACE::fputil::less_than;
+using LIBC_NAMESPACE::fputil::less_than_or_equals;
+using LIBC_NAMESPACE::fputil::not_equals;
+
+// FIXME: currently i have used NAN here
+// need to find a better way to get a NAN floating point type
+// - need to see if FPRep could be used?
+
+#define TEST_EQUALS(Name, Type)                                                \
+  TEST(LlvmLibcDyadic##Name##Test, Equals) {                                   \
+    using Bits = LIBC_NAMESPACE::fputil::FPBits<Type>;                         \
+    Type pos_zero = Bits::zero().get_val();                                    \
+    Type neg_zero = -pos_zero;                                                 \
+    Type pos_inf = Bits::inf().get_val();                                      \
+    Type neg_inf = Bits::inf(Sign::NEG).get_val();                             \
+    Type nan = NAN;                                                            \
+    Type pos_normal = Type(3.14);                                              \
+    Type neg_normal = Type(-2.71);                                             \
+    Type pos_large = Type(1000000.0);                                          \
+    Type neg_large = Type(-1000000.0);                                         \
+                                                                               \
+    EXPECT_TRUE(equals(pos_zero, pos_zero));                                   \
+    EXPECT_TRUE(equals(neg_zero, neg_zero));                                   \
+    EXPECT_TRUE(equals(pos_inf, pos_inf));                                     \
+    EXPECT_TRUE(equals(neg_inf, neg_inf));                                     \
+    EXPECT_TRUE(equals(pos_normal, pos_normal));                               \
+    EXPECT_TRUE(equals(neg_normal, neg_normal));                               \
+                                                                               \
+    EXPECT_TRUE(equals(pos_zero, neg_zero));                                   \
+    EXPECT_TRUE(equals(neg_zero, pos_zero));                                   \
+                                                                               \
+    EXPECT_FALSE(equals(pos_normal, neg_normal));                              \
+    EXPECT_FALSE(equals(pos_normal, pos_large));                               \
+    EXPECT_FALSE(equals(pos_inf, neg_inf));                                    \
+    EXPECT_FALSE(equals(pos_inf, pos_normal));                                 \
+    EXPECT_FALSE(equals(neg_inf, neg_normal));                                 \
+    EXPECT_FALSE(equals(pos_large, neg_large));                                \
+                                                                               \
+    EXPECT_FALSE(equals(nan, nan));                                            \
+    EXPECT_FALSE(equals(nan, pos_normal));                                     \
+    EXPECT_FALSE(equals(nan, pos_zero));                                       \
+    EXPECT_FALSE(equals(nan, pos_inf));                                        \
+    EXPECT_FALSE(equals(pos_normal, nan));                                     \
+  }
+
+#define TEST_NOT_EQUALS(Name, Type)                                            \
+  TEST(LlvmLibcDyadic##Name##Test, NotEquals) {                                \
+    using Bits = LIBC_NAMESPACE::fputil::FPBits<Type>;                         \
+    Type pos_zero = Bits::zero().get_val();                                    \
+    Type neg_zero = Bits::zero(Sign::NEG).get_val();                           \
+    Type pos_inf = Bits::inf().get_val();                                      \
+    Type neg_inf = Bits::inf(Sign::NEG).get_val();                             \
+    Type nan = NAN;                                                            \
+    Type pos_normal = Type(3.14);                                              \
+    Type neg_normal = Type(-2.71);                                             \
+    Type pos_large = Type(1000000.0);                                          \
+    Type neg_large = Type(-1000000.0);                                         \
+                                                                               \
+    EXPECT_FALSE(not_equals(pos_zero, pos_zero));                              \
+    EXPECT_FALSE(not_equals(pos_zero, neg_zero));                              \
+    EXPECT_FALSE(not_equals(pos_inf, pos_inf));                                \
+    EXPECT_FALSE(not_equals(neg_inf, neg_inf));                                \
+    EXPECT_FALSE(not_equals(pos_normal, pos_normal));                          \
+                                                                               \
+    EXPECT_TRUE(not_equals(pos_normal, neg_normal));                           \
+    EXPECT_TRUE(not_equals(pos_inf, neg_inf));                                 \
+    EXPECT_TRUE(not_equals(pos_normal, pos_zero));                             \
+    EXPECT_TRUE(not_equals(pos_large, neg_large));                             \
+    EXPECT_TRUE(not_equals(pos_inf, pos_normal));                              \
+                                                                               \
+    EXPECT_TRUE(not_equals(nan, nan));                                         \
+    EXPECT_TRUE(not_equals(nan, pos_normal));                                  \
+    EXPECT_TRUE(not_equals(nan, pos_zero));                                    \
+    EXPECT_TRUE(not_equals(nan, pos_inf));                                     \
+    EXPECT_TRUE(not_equals(pos_normal, nan));                                  \
+  }
+
+#define TEST_LESS_THAN(Name, Type)                                             \
+  TEST(LlvmLibcDyadic##Name##Test, LessThan) {                                 \
+    using Bits = LIBC_NAMESPACE::fputil::FPBits<Type>;                         \
+    Type pos_zero = Bits::zero().get_val();                                    \
+    Type neg_zero = -pos_zero;                                                 \
+    Type pos_inf = Bits::inf().get_val();                                      \
+    Type neg_inf = Bits::inf(Sign::NEG).get_val();                             \
+    Type nan = NAN;                                                            \
+    Type pos_small = Type(0.1);                                                \
+    Type neg_small = Type(-0.1);                                               \
+    Type pos_large = Type(1000000.0);                                          \
+    Type neg_large = Type(-1000000.0);                                         \
+                                                                               \
+    EXPECT_TRUE(less_than(neg_small, pos_small));                              \
+    EXPECT_TRUE(less_than(pos_small, pos_large));                              \
+    EXPECT_TRUE(less_than(neg_large, neg_small));                              \
+    EXPECT_FALSE(less_than(pos_large, pos_small));                             \
+    EXPECT_FALSE(less_than(pos_small, neg_small));                             \
+                                                                               \
+    EXPECT_FALSE(less_than(pos_zero, neg_zero));                               \
+    EXPECT_FALSE(less_than(neg_zero, pos_zero));                               \
+    EXPECT_FALSE(less_than(pos_zero, pos_zero));                               \
+                                                                               \
+    EXPECT_TRUE(less_than(neg_small, pos_zero));                               \
+    EXPECT_TRUE(less_than(neg_zero, pos_small));                               \
+    EXPECT_FALSE(less_than(pos_small, pos_zero));                              \
+                                                                               \
+    EXPECT_TRUE(less_than(neg_inf, pos_inf));                                  \
+    EXPECT_TRUE(less_than(neg_inf, neg_small));                                \
+    EXPECT_TRUE(less_than(pos_small, pos_inf));                                \
+    EXPECT_FALSE(less_than(pos_inf, pos_small));                               \
+                                                                               \
+    EXPECT_FALSE(less_than(pos_small, pos_small));                             \
+    EXPECT_FALSE(less_than(neg_inf, neg_inf));                                 \
+                                                                               \
+    EXPECT_FALSE(less_than(nan, pos_small));                                   \
+    EXPECT_FALSE(less_than(pos_small, nan));                                   \
+    EXPECT_FALSE(less_than(nan, nan));                                         \
+  }
+
+#define TEST_GREATER_THAN(Name, Type)                                          \
+  TEST(LlvmLibcDyadic##Name##Test, GreaterThan) {                              \
+    using Bits = LIBC_NAMESPACE::fputil::FPBits<Type>;                         \
+    Type pos_zero = Bits::zero().get_val();                                    \
+    Type neg_zero = -pos_zero;                                                 \
+    Type pos_inf = Bits::inf().get_val();                                      \
+    Type neg_inf = Bits::inf(Sign::NEG).get_val();                             \
+    Type nan = NAN;                                                            \
+    Type pos_small = Type(0.1);                                                \
+    Type neg_small = Type(-0.1);                                               \
+    Type pos_large = Type(1000000.0);                                          \
+    Type neg_large = Type(-1000000.0);                                         \
+                                                                               \
+    EXPECT_TRUE(greater_than(pos_small, neg_small));                           \
+    EXPECT_TRUE(greater_than(pos_large, pos_small));                           \
+    EXPECT_TRUE(greater_than(neg_small, neg_large));                           \
+    EXPECT_FALSE(greater_than(pos_small, pos_large));                          \
+    EXPECT_FALSE(greater_than(neg_small, pos_small));                          \
+                                                                               \
+    EXPECT_FALSE(greater_than(pos_zero, neg_zero));                            \
+    EXPECT_FALSE(greater_than(neg_zero, pos_zero));                            \
+                                                                               \
+    EXPECT_TRUE(greater_than(pos_inf, neg_inf));                               \
+    EXPECT_TRUE(greater_than(pos_inf, pos_small));                             \
+    EXPECT_TRUE(greater_than(pos_small, neg_inf));                             \
+    EXPECT_FALSE(greater_than(neg_inf, pos_inf));                              \
+                                                                               \
+    EXPECT_FALSE(greater_than(pos_small, pos_small));                          \
+    EXPECT_FALSE(greater_than(pos_inf, pos_inf));                              \
+                                                                               \
+    EXPECT_FALSE(greater_than(nan, pos_small));                                \
+    EXPECT_FALSE(greater_than(pos_small, nan));                                \
+    EXPECT_FALSE(greater_than(nan, nan));                                      \
+  }
+
+#define TEST_LESS_THAN_OR_EQUALS(Name, Type)                                   \
+  TEST(LlvmLibcDyadic##Name##Test, LessThanOrEquals) {                         \
+    using Bits = LIBC_NAMESPACE::fputil::FPBits<Type>;                         \
+    Type pos_zero = Bits::zero().get_val();                                    \
+    Type neg_zero = -pos_zero;                                                 \
+    Type pos_inf = Bits::inf().get_val();                                      \
+    Type neg_inf = Bits::inf(Sign::NEG).get_val();                             \
+    Type nan = NAN;                                                            \
+    Type pos_small = Type(0.1);                                                \
+    Type neg_small = Type(-0.1);                                               \
+    Type pos_large = Type(1000000.0);                                          \
+    Type neg_large = Type(-1000000.0);                                         \
+                                                                               \
+    EXPECT_TRUE(less_than_or_equals(neg_small, pos_small));                    \
+    EXPECT_TRUE(less_than_or_equals(pos_small, pos_large));                    \
+    EXPECT_TRUE(less_than_or_equals(neg_inf, pos_small));                      \
+                                                                               \
+    EXPECT_TRUE(less_than_or_equals(pos_small, pos_small));                    \
+    EXPECT_TRUE(less_than_or_equals(pos_zero, neg_zero));                      \
+    EXPECT_TRUE(less_than_or_equals(pos_inf, pos_inf));                        \
+                                                                               \
+    EXPECT_FALSE(less_than_or_equals(pos_small, neg_small));                   \
+    EXPECT_FALSE(less_than_or_equals(pos_large, pos_small));                   \
+    EXPECT_FALSE(less_than_or_equals(pos_inf, pos_small));                     \
+                                                                               \
+    EXPECT_TRUE(less_than_or_equals(neg_large, pos_small));                    \
+    EXPECT_FALSE(less_than_or_equals(pos_large, neg_small));                   \
+                                                                               \
+    EXPECT_FALSE(less_than_or_equals(nan, pos_small));                         \
+    EXPECT_FALSE(less_than_or_equals(pos_small, nan));                         \
+    EXPECT_FALSE(less_than_or_equals(nan, nan));                               \
+  }
+
+#define TEST_GREATER_THAN_OR_EQUALS(Name, Type)                                \
+  TEST(LlvmLibcDyadic##Name##Test, GreaterThanOrEquals) {                      \
+    using Bits = LIBC_NAMESPACE::fputil::FPBits<Type>;                         \
+    Type pos_zero = Bits::zero().get_val();                                    \
+    Type neg_zero = -pos_zero;                                                 \
+    Type pos_inf = Bits::inf().get_val();                                      \
+    Type neg_inf = Bits::inf(Sign::NEG).get_val();                             \
+    Type nan = NAN;                                                            \
+    Type pos_small = Type(0.1);                                                \
+    Type neg_small = Type(-0.1);                                               \
+    Type pos_large = Type(1000000.0);                                          \
+    Type neg_large = Type(-1000000.0);                                         \
+                                                                               \
+    EXPECT_TRUE(greater_than_or_equals(pos_small, neg_small));                 \
+    EXPECT_TRUE(greater_than_or_equals(pos_large, pos_small));                 \
+    EXPECT_TRUE(greater_than_or_equals(pos_inf, pos_small));                   \
+                                                                               \
+    EXPECT_TRUE(greater_than_or_equals(pos_small, pos_small));                 \
+    EXPECT_TRUE(greater_than_or_equals(pos_zero, neg_zero));                   \
+    EXPECT_TRUE(greater_than_or_equals(neg_inf, neg_inf));                     \
+                                                                               \
+    EXPECT_FALSE(greater_than_or_equals(neg_small, pos_small));                \
+    EXPECT_FALSE(greater_than_or_equals(pos_small, pos_large));                \
+    EXPECT_FALSE(greater_than_or_equals(neg_inf, pos_small));                  \
+                                                                               \
+    EXPECT_TRUE(greater_than_or_equals(pos_large, neg_small));                 \
+    EXPECT_FALSE(greater_than_or_equals(neg_large, pos_small));                \
+                                                                               \
+    EXPECT_FALSE(greater_than_or_equals(nan, pos_small));                      \
+    EXPECT_FALSE(greater_than_or_equals(pos_small, nan));                      \
+    EXPECT_FALSE(greater_than_or_equals(nan, nan));                            \
+  }
+
+#define TEST_COMPARISON_OPS(Name, Type)                                        \
+  TEST_EQUALS(Name, Type)                                                      \
+  TEST_NOT_EQUALS(Name, Type)                                                  \
+  TEST_LESS_THAN(Name, Type)                                                   \
+  TEST_GREATER_THAN(Name, Type)                                                \
+  TEST_LESS_THAN_OR_EQUALS(Name, Type)                                         \
+  TEST_GREATER_THAN_OR_EQUALS(Name, Type)
+
+TEST_COMPARISON_OPS(Float, float)
+TEST_COMPARISON_OPS(Double, double)
+// FIXME:  error: expected '(' for function-style cast or type construction
+// TEST_COMPARISON_OPS(LongDouble, (long double))
+#ifdef LIBC_TYPES_HAS_FLOAT16
+TEST_COMPARISON_OPS(Float16, float16)
+#endif // LIBC_TYPES_HAS_FLOAT16
+
+// TODO: add other types if this is correct?

>From 8c30aa2672a9f897f701611ef134e5f2b581f774 Mon Sep 17 00:00:00 2001
From: krishna2803 <kpandey81930 at gmail.com>
Date: Fri, 20 Jun 2025 10:17:19 +0530
Subject: [PATCH 5/6] fix: spelling

Signed-off-by: krishna2803 <kpandey81930 at gmail.com>
---
 libc/src/__support/FPUtil/CMakeLists.txt      |  4 ++--
 ...ionOperations.h => ComparisonOperations.h} | 20 +++++++++----------
 libc/test/src/__support/FPUtil/CMakeLists.txt |  6 +++---
 ...est.cpp => comparison_operations_test.cpp} |  4 ++--
 4 files changed, 17 insertions(+), 17 deletions(-)
 rename libc/src/__support/FPUtil/{ComparisionOperations.h => ComparisonOperations.h} (83%)
 rename libc/test/src/__support/FPUtil/{comparision_operations_test.cpp => comparison_operations_test.cpp} (99%)

diff --git a/libc/src/__support/FPUtil/CMakeLists.txt b/libc/src/__support/FPUtil/CMakeLists.txt
index 6b2ca3bb77fd9..ce068df8d4c03 100644
--- a/libc/src/__support/FPUtil/CMakeLists.txt
+++ b/libc/src/__support/FPUtil/CMakeLists.txt
@@ -210,9 +210,9 @@ add_header_library(
 )
 
 add_header_library(
-  comparision_operations
+  comparison_operations
   HDRS
-    ComparisionOperations.h
+    ComparisonOperations.h
   DEPENDS
     .fp_bits
     .fenv_impl
diff --git a/libc/src/__support/FPUtil/ComparisionOperations.h b/libc/src/__support/FPUtil/ComparisonOperations.h
similarity index 83%
rename from libc/src/__support/FPUtil/ComparisionOperations.h
rename to libc/src/__support/FPUtil/ComparisonOperations.h
index a4cdd4214b4db..cf71a14df0465 100644
--- a/libc/src/__support/FPUtil/ComparisionOperations.h
+++ b/libc/src/__support/FPUtil/ComparisonOperations.h
@@ -1,4 +1,4 @@
-//===-- Comparision operations on floating point numbers --------*- C++ -*-===//
+//===-- Comparison operations on floating point numbers --------*- C++ -*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -6,8 +6,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_LIBC_SRC___SUPPORT_FPUTIL_COMPARISIONOPERATIONS_H
-#define LLVM_LIBC_SRC___SUPPORT_FPUTIL_COMPARISIONOPERATIONS_H
+#ifndef LLVM_LIBC_SRC___SUPPORT_FPUTIL_COMPARISONOPERATIONS_H
+#define LLVM_LIBC_SRC___SUPPORT_FPUTIL_COMPARISONOPERATIONS_H
 
 #include "FEnvImpl.h"                      // raise_except_if_required
 #include "FPBits.h"                        // FPBits<T>
@@ -18,12 +18,12 @@ namespace LIBC_NAMESPACE_DECL {
 namespace fputil {
 
 // IEEE Standard 754-2019. Section 5.11
-// Rules for comparision within the same floating point type
+// Rules for comparison within the same floating point type
 // 1. +0 = −0
 // 2. (i)   +inf  = +inf
 //    (ii)  -inf  = -inf
 //    (iii) -inf != +inf
-// 3. Any comparision with NaN return false except (NaN != NaN => true)
+// 3. Any comparison with NaN return false except (NaN != NaN => true)
 template <typename T>
 LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<T>, bool> equals(T x,
                                                                        T y) {
@@ -42,7 +42,7 @@ LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<T>, bool> equals(T x,
   if (x_bits.is_zero() && y_bits.is_zero())
     return true;
 
-  // should also work for comparisions of different signs
+  // should also work for comparisons of different signs
   return x_bits.uintval() == y_bits.uintval();
 }
 
@@ -56,7 +56,7 @@ not_equals(T x, T y) {
 // Rules:
 // 1. -inf < x (x != -inf)
 // 2. x < +inf (x != +inf)
-// 3. Any comparision with NaN return false
+// 3. Any comparison with NaN return false
 template <typename T>
 LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<T>, bool> less_than(T x,
                                                                           T y) {
@@ -67,7 +67,7 @@ LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<T>, bool> less_than(T x,
   if (x_bits.is_signaling_nan() || y_bits.is_signaling_nan())
     fputil::raise_except_if_required(FE_INVALID);
 
-  // Any comparision with NaN returns false
+  // Any comparison with NaN returns false
   if (x_bits.is_nan() || y_bits.is_nan())
     return false;
 
@@ -81,7 +81,7 @@ LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<T>, bool> less_than(T x,
     return false;
 
   // since we store the float in the format: s | e | m
-  // the comparisions should work if we directly compare the uintval's
+  // the comparisons should work if we directly compare the uintval's
 
   // TODO: verify if we should use FPBits.get_exponent and FPBits.get_mantissa
   // instead of directly comparing uintval's
@@ -119,4 +119,4 @@ greater_than_or_equals(T x, T y) {
 } // namespace fputil
 } // namespace LIBC_NAMESPACE_DECL
 
-#endif // LLVM_LIBC_SRC___SUPPORT_FPUTIL_COMPARISIONOPERATIONS_H
+#endif // LLVM_LIBC_SRC___SUPPORT_FPUTIL_COMPARISONOPERATIONS_H
diff --git a/libc/test/src/__support/FPUtil/CMakeLists.txt b/libc/test/src/__support/FPUtil/CMakeLists.txt
index 851506ccec6e2..1dcd666ec3d25 100644
--- a/libc/test/src/__support/FPUtil/CMakeLists.txt
+++ b/libc/test/src/__support/FPUtil/CMakeLists.txt
@@ -40,13 +40,13 @@ add_fp_unittest(
 )
 
 add_fp_unittest(
-  comparision_operations_test
+  comparison_operations_test
   SUITE
     libc-fputil-tests
   SRCS
-    comparision_operations_test.cpp
+    comparison_operations_test.cpp
   DEPENDS
     libc.src.__support.FPUtil.fp_bits
-    # libc.src.__support.FPUtil.comparision_operations
+    # libc.src.__support.FPUtil.comparison_operations
 )
 
diff --git a/libc/test/src/__support/FPUtil/comparision_operations_test.cpp b/libc/test/src/__support/FPUtil/comparison_operations_test.cpp
similarity index 99%
rename from libc/test/src/__support/FPUtil/comparision_operations_test.cpp
rename to libc/test/src/__support/FPUtil/comparison_operations_test.cpp
index a2ac13723bae5..10ea0a8004dcc 100644
--- a/libc/test/src/__support/FPUtil/comparision_operations_test.cpp
+++ b/libc/test/src/__support/FPUtil/comparison_operations_test.cpp
@@ -1,4 +1,4 @@
-//===-- Unittests for Comparision Operations for FPBits class -------------===//
+//===-- Unittests for Comparison Operations for FPBits class -------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -6,7 +6,7 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "src/__support/FPUtil/ComparisionOperations.h"
+#include "src/__support/FPUtil/ComparisonOperations.h"
 #include "src/__support/FPUtil/FPBits.h"
 #include "src/__support/macros/properties/types.h"
 #include "src/__support/sign.h"

>From d1e54eddd86f9fe39873e5711026475453eb5150 Mon Sep 17 00:00:00 2001
From: krishna2803 <kpandey81930 at gmail.com>
Date: Fri, 20 Jun 2025 10:23:07 +0530
Subject: [PATCH 6/6] chore: change `Dyadic` -> `ComparisonOperations` under
 tests

Signed-off-by: krishna2803 <kpandey81930 at gmail.com>
---
 .../__support/FPUtil/comparison_operations_test.cpp  | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/libc/test/src/__support/FPUtil/comparison_operations_test.cpp b/libc/test/src/__support/FPUtil/comparison_operations_test.cpp
index 10ea0a8004dcc..94c234446ad8e 100644
--- a/libc/test/src/__support/FPUtil/comparison_operations_test.cpp
+++ b/libc/test/src/__support/FPUtil/comparison_operations_test.cpp
@@ -26,7 +26,7 @@ using LIBC_NAMESPACE::fputil::not_equals;
 // - need to see if FPRep could be used?
 
 #define TEST_EQUALS(Name, Type)                                                \
-  TEST(LlvmLibcDyadic##Name##Test, Equals) {                                   \
+  TEST(LlvmLibc##Name##ComparisionOperationsTest, Equals) {                                   \
     using Bits = LIBC_NAMESPACE::fputil::FPBits<Type>;                         \
     Type pos_zero = Bits::zero().get_val();                                    \
     Type neg_zero = -pos_zero;                                                 \
@@ -63,7 +63,7 @@ using LIBC_NAMESPACE::fputil::not_equals;
   }
 
 #define TEST_NOT_EQUALS(Name, Type)                                            \
-  TEST(LlvmLibcDyadic##Name##Test, NotEquals) {                                \
+  TEST(LlvmLibc##Name##ComparisionOperationsTest, NotEquals) {                                \
     using Bits = LIBC_NAMESPACE::fputil::FPBits<Type>;                         \
     Type pos_zero = Bits::zero().get_val();                                    \
     Type neg_zero = Bits::zero(Sign::NEG).get_val();                           \
@@ -95,7 +95,7 @@ using LIBC_NAMESPACE::fputil::not_equals;
   }
 
 #define TEST_LESS_THAN(Name, Type)                                             \
-  TEST(LlvmLibcDyadic##Name##Test, LessThan) {                                 \
+  TEST(LlvmLibc##Name##ComparisionOperationsTest, LessThan) {                                 \
     using Bits = LIBC_NAMESPACE::fputil::FPBits<Type>;                         \
     Type pos_zero = Bits::zero().get_val();                                    \
     Type neg_zero = -pos_zero;                                                 \
@@ -135,7 +135,7 @@ using LIBC_NAMESPACE::fputil::not_equals;
   }
 
 #define TEST_GREATER_THAN(Name, Type)                                          \
-  TEST(LlvmLibcDyadic##Name##Test, GreaterThan) {                              \
+  TEST(LlvmLibc##Name##ComparisionOperationsTest, GreaterThan) {                              \
     using Bits = LIBC_NAMESPACE::fputil::FPBits<Type>;                         \
     Type pos_zero = Bits::zero().get_val();                                    \
     Type neg_zero = -pos_zero;                                                 \
@@ -170,7 +170,7 @@ using LIBC_NAMESPACE::fputil::not_equals;
   }
 
 #define TEST_LESS_THAN_OR_EQUALS(Name, Type)                                   \
-  TEST(LlvmLibcDyadic##Name##Test, LessThanOrEquals) {                         \
+  TEST(LlvmLibc##Name##ComparisionOperationsTest, LessThanOrEquals) {                         \
     using Bits = LIBC_NAMESPACE::fputil::FPBits<Type>;                         \
     Type pos_zero = Bits::zero().get_val();                                    \
     Type neg_zero = -pos_zero;                                                 \
@@ -203,7 +203,7 @@ using LIBC_NAMESPACE::fputil::not_equals;
   }
 
 #define TEST_GREATER_THAN_OR_EQUALS(Name, Type)                                \
-  TEST(LlvmLibcDyadic##Name##Test, GreaterThanOrEquals) {                      \
+  TEST(LlvmLibc##Name##ComparisionOperationsTest, GreaterThanOrEquals) {                      \
     using Bits = LIBC_NAMESPACE::fputil::FPBits<Type>;                         \
     Type pos_zero = Bits::zero().get_val();                                    \
     Type neg_zero = -pos_zero;                                                 \



More information about the libc-commits mailing list