[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
Fri Jul 11 19:08:47 PDT 2025


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

>From b78aaa33c054ddb52de45541c1b72088144b4209 Mon Sep 17 00:00:00 2001
From: krishna2803 <kpandey81930 at gmail.com>
Date: Fri, 20 Jun 2025 06:57:34 +0530
Subject: [PATCH 01/30] 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 cc941f23135a6..cf1984294b667 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 f4dc9ce6b1217953f66b1fadf1019fae511d7341 Mon Sep 17 00:00:00 2001
From: krishna2803 <kpandey81930 at gmail.com>
Date: Fri, 20 Jun 2025 06:58:00 +0530
Subject: [PATCH 02/30] 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 d4aaa8f9a018910ceee8f43817e07ea82d5a1285 Mon Sep 17 00:00:00 2001
From: krishna2803 <kpandey81930 at gmail.com>
Date: Fri, 20 Jun 2025 10:07:07 +0530
Subject: [PATCH 03/30] 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 cf1984294b667..4b09be3884a0b 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 a4d49467ad46b5d25652ee216e4ed649973dacca Mon Sep 17 00:00:00 2001
From: krishna2803 <kpandey81930 at gmail.com>
Date: Fri, 20 Jun 2025 10:07:34 +0530
Subject: [PATCH 04/30] 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 dfd90057b6ebf..ec1126a134bc0 100644
--- a/libc/test/src/__support/FPUtil/CMakeLists.txt
+++ b/libc/test/src/__support/FPUtil/CMakeLists.txt
@@ -49,3 +49,15 @@ add_fp_unittest(
   DEPENDS
     libc.src.__support.FPUtil.bfloat16
 )
+
+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 18c9503c3aa74b53666a0159372d5722f0c3ab55 Mon Sep 17 00:00:00 2001
From: krishna2803 <kpandey81930 at gmail.com>
Date: Fri, 20 Jun 2025 10:17:19 +0530
Subject: [PATCH 05/30] fix: spelling

Signed-off-by: krishna2803 <kpandey81930 at gmail.com>
---
 libc/src/__support/FPUtil/CMakeLists.txt      |  4 ++--
 ...ionOperations.h => ComparisonOperations.h} | 20 +++++++++----------
 ...est.cpp => comparison_operations_test.cpp} |  4 ++--
 3 files changed, 14 insertions(+), 14 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 4b09be3884a0b..b696c40d513f4 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/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 88585ca30b7c9e1af2ff1c499b9597a41c933bf0 Mon Sep 17 00:00:00 2001
From: krishna2803 <kpandey81930 at gmail.com>
Date: Fri, 20 Jun 2025 10:23:07 +0530
Subject: [PATCH 06/30] 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;                                                 \

>From b6c3150d51c67bc0730583b91fa52e894c8b8d36 Mon Sep 17 00:00:00 2001
From: krishna2803 <kpandey81930 at gmail.com>
Date: Fri, 20 Jun 2025 10:25:24 +0530
Subject: [PATCH 07/30] style: clang-format

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 94c234446ad8e..47494ecf70fe4 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(LlvmLibc##Name##ComparisionOperationsTest, 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(LlvmLibc##Name##ComparisionOperationsTest, 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(LlvmLibc##Name##ComparisionOperationsTest, 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(LlvmLibc##Name##ComparisionOperationsTest, 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(LlvmLibc##Name##ComparisionOperationsTest, 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(LlvmLibc##Name##ComparisionOperationsTest, 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;                                                 \

>From 0995bbcdd13223c10280cafe0b742918cc449b3a Mon Sep 17 00:00:00 2001
From: Krishna Pandey <kpandey81930 at gmail.com>
Date: Tue, 1 Jul 2025 02:04:09 +0530
Subject: [PATCH 08/30] style: nits

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

diff --git a/libc/src/__support/FPUtil/CMakeLists.txt b/libc/src/__support/FPUtil/CMakeLists.txt
index b696c40d513f4..dcba4546963ed 100644
--- a/libc/src/__support/FPUtil/CMakeLists.txt
+++ b/libc/src/__support/FPUtil/CMakeLists.txt
@@ -214,10 +214,10 @@ add_header_library(
   HDRS
     ComparisonOperations.h
   DEPENDS
-    .fp_bits
     .fenv_impl
-    libc.src.__support.CPP.type_traits
+    .fp_bits
     libc.src.__support.config
+    libc.src.__support.CPP.type_traits
 )
 
 add_header_library(

>From ed237f19c33cb4f5b4df20e35dd7b1a8cfcf256c Mon Sep 17 00:00:00 2001
From: Krishna Pandey <kpandey81930 at gmail.com>
Date: Wed, 2 Jul 2025 20:54:56 +0530
Subject: [PATCH 09/30] fix: typo in CMakeLists.txt

Signed-off-by: Krishna Pandey <kpandey81930 at gmail.com>
---
 libc/src/__support/FPUtil/CMakeLists.txt      | 2 +-
 libc/test/src/__support/FPUtil/CMakeLists.txt | 5 +++--
 2 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/libc/src/__support/FPUtil/CMakeLists.txt b/libc/src/__support/FPUtil/CMakeLists.txt
index dcba4546963ed..fc6e95de74122 100644
--- a/libc/src/__support/FPUtil/CMakeLists.txt
+++ b/libc/src/__support/FPUtil/CMakeLists.txt
@@ -216,7 +216,7 @@ add_header_library(
   DEPENDS
     .fenv_impl
     .fp_bits
-    libc.src.__support.config
+  libc.src.__support.macros.config
     libc.src.__support.CPP.type_traits
 )
 
diff --git a/libc/test/src/__support/FPUtil/CMakeLists.txt b/libc/test/src/__support/FPUtil/CMakeLists.txt
index ec1126a134bc0..c1e84f1bf20ee 100644
--- a/libc/test/src/__support/FPUtil/CMakeLists.txt
+++ b/libc/test/src/__support/FPUtil/CMakeLists.txt
@@ -57,7 +57,8 @@ add_fp_unittest(
   SRCS
     comparision_operations_test.cpp
   DEPENDS
+    libc.src.__support.FPUtil.comparison_operations
     libc.src.__support.FPUtil.fp_bits
-    # libc.src.__support.FPUtil.comparision_operations
+    libc.src.__support.macros.properties.types
+    libc.src.__support.sign
 )
-

>From 4e14d3666a5fb3bb3f2ae269421cd87a578c2748 Mon Sep 17 00:00:00 2001
From: Krishna Pandey <kpandey81930 at gmail.com>
Date: Wed, 2 Jul 2025 20:55:28 +0530
Subject: [PATCH 10/30] chore: remove fputil::not_equals

Signed-off-by: Krishna Pandey <kpandey81930 at gmail.com>
---
 .../__support/FPUtil/ComparisonOperations.h   |  5 +--
 .../FPUtil/comparison_operations_test.cpp     | 34 -------------------
 2 files changed, 3 insertions(+), 36 deletions(-)

diff --git a/libc/src/__support/FPUtil/ComparisonOperations.h b/libc/src/__support/FPUtil/ComparisonOperations.h
index cf71a14df0465..ad8514fd02d40 100644
--- a/libc/src/__support/FPUtil/ComparisonOperations.h
+++ b/libc/src/__support/FPUtil/ComparisonOperations.h
@@ -1,4 +1,4 @@
-//===-- Comparison 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.
@@ -64,7 +64,8 @@ LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<T>, bool> less_than(T x,
   FPBits x_bits(x);
   FPBits y_bits(y);
 
-  if (x_bits.is_signaling_nan() || y_bits.is_signaling_nan())
+  if (x_bits.is_signaling_nan() || y_bits.is_signaling_nan() ||
+      x_bits.is_quiet_nan() || y_bits.is_quiet_nan())
     fputil::raise_except_if_required(FE_INVALID);
 
   // Any comparison with NaN returns false
diff --git a/libc/test/src/__support/FPUtil/comparison_operations_test.cpp b/libc/test/src/__support/FPUtil/comparison_operations_test.cpp
index 47494ecf70fe4..e55a9194d956b 100644
--- a/libc/test/src/__support/FPUtil/comparison_operations_test.cpp
+++ b/libc/test/src/__support/FPUtil/comparison_operations_test.cpp
@@ -12,7 +12,6 @@
 #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;
@@ -62,38 +61,6 @@ using LIBC_NAMESPACE::fputil::not_equals;
     EXPECT_FALSE(equals(pos_normal, nan));                                     \
   }
 
-#define TEST_NOT_EQUALS(Name, Type)                                            \
-  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();                           \
-    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(LlvmLibc##Name##ComparisionOperationsTest, LessThan) {                  \
     using Bits = LIBC_NAMESPACE::fputil::FPBits<Type>;                         \
@@ -237,7 +204,6 @@ using LIBC_NAMESPACE::fputil::not_equals;
 
 #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)                                         \

>From 1265ac6222d52b506af568dba405b416fa0ee8a7 Mon Sep 17 00:00:00 2001
From: Krishna Pandey <kpandey81930 at gmail.com>
Date: Fri, 4 Jul 2025 18:15:26 +0530
Subject: [PATCH 11/30] chore: remove fputil::not_equals function and TODOs

Signed-off-by: Krishna Pandey <kpandey81930 at gmail.com>
---
 libc/src/__support/FPUtil/ComparisonOperations.h | 10 ----------
 1 file changed, 10 deletions(-)

diff --git a/libc/src/__support/FPUtil/ComparisonOperations.h b/libc/src/__support/FPUtil/ComparisonOperations.h
index ad8514fd02d40..28e46630c737c 100644
--- a/libc/src/__support/FPUtil/ComparisonOperations.h
+++ b/libc/src/__support/FPUtil/ComparisonOperations.h
@@ -46,13 +46,6 @@ LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<T>, bool> equals(T x,
   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)
@@ -84,9 +77,6 @@ LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<T>, bool> less_than(T x,
   // since we store the float in the format: s | e | m
   // 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
-
   // both negative
   if (x_bits.is_neg())
     return x_bits.uintval() > y_bits.uintval();

>From f36925ef2cf1b63e46ebc08b20167e6b6dcc42ef Mon Sep 17 00:00:00 2001
From: Krishna Pandey <kpandey81930 at gmail.com>
Date: Fri, 4 Jul 2025 19:47:55 +0530
Subject: [PATCH 12/30] chore: add tests for quiet and signaling nans.

Signed-off-by: Krishna Pandey <kpandey81930 at gmail.com>
---
 .../FPUtil/comparison_operations_test.cpp     | 173 ++++++++++++++----
 1 file changed, 142 insertions(+), 31 deletions(-)

diff --git a/libc/test/src/__support/FPUtil/comparison_operations_test.cpp b/libc/test/src/__support/FPUtil/comparison_operations_test.cpp
index e55a9194d956b..388d8b7a18e04 100644
--- a/libc/test/src/__support/FPUtil/comparison_operations_test.cpp
+++ b/libc/test/src/__support/FPUtil/comparison_operations_test.cpp
@@ -18,11 +18,6 @@ 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(LlvmLibc##Name##ComparisionOperationsTest, Equals) {                    \
@@ -31,7 +26,8 @@ using LIBC_NAMESPACE::fputil::not_equals;
     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 qnan = Bits::quiet_nan().get_val();                                   \
+    Type snan = Bits::signaling_nan().get_val();                               \
     Type pos_normal = Type(3.14);                                              \
     Type neg_normal = Type(-2.71);                                             \
     Type pos_large = Type(1000000.0);                                          \
@@ -54,11 +50,39 @@ using LIBC_NAMESPACE::fputil::not_equals;
     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));                                     \
+    EXPECT_FALSE(equals(qnan, qnan));                                          \
+    EXPECT_FALSE(equals(qnan, pos_normal));                                    \
+    EXPECT_FALSE(equals(qnan, pos_zero));                                      \
+    EXPECT_FALSE(equals(qnan, pos_inf));                                       \
+    EXPECT_FALSE(equals(pos_normal, qnan));                                    \
+                                                                               \
+    LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);                       \
+    EXPECT_FALSE(equals(snan, snan));                                          \
+    EXPECT_FP_EXCEPTION(FE_INVALID);                                           \
+                                                                               \
+    LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);                       \
+    EXPECT_FALSE(equals(snan, qnan));                                          \
+    EXPECT_FP_EXCEPTION(FE_INVALID);                                           \
+                                                                               \
+    LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);                       \
+    EXPECT_FALSE(equals(qnan, snan));                                          \
+    EXPECT_FP_EXCEPTION(FE_INVALID);                                           \
+                                                                               \
+    LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);                       \
+    EXPECT_FALSE(equals(snan, pos_normal));                                    \
+    EXPECT_FP_EXCEPTION(FE_INVALID);                                           \
+                                                                               \
+    LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);                       \
+    EXPECT_FALSE(equals(pos_normal, snan));                                    \
+    EXPECT_FP_EXCEPTION(FE_INVALID);                                           \
+                                                                               \
+    LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);                       \
+    EXPECT_FALSE(equals(snan, pos_inf));                                       \
+    EXPECT_FP_EXCEPTION(FE_INVALID);                                           \
+                                                                               \
+    LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);                       \
+    EXPECT_FALSE(equals(snan, pos_zero));                                      \
+    EXPECT_FP_EXCEPTION(FE_INVALID);                                           \
   }
 
 #define TEST_LESS_THAN(Name, Type)                                             \
@@ -68,7 +92,8 @@ using LIBC_NAMESPACE::fputil::not_equals;
     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 qnan = Bits::quiet_nan().get_val();                                   \
+    Type snan = Bits::signaling_nan().get_val();                               \
     Type pos_small = Type(0.1);                                                \
     Type neg_small = Type(-0.1);                                               \
     Type pos_large = Type(1000000.0);                                          \
@@ -96,9 +121,29 @@ using LIBC_NAMESPACE::fputil::not_equals;
     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));                                         \
+    LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);                       \
+    EXPECT_FALSE(less_than(qnan, pos_small));                                  \
+    EXPECT_FP_EXCEPTION(FE_INVALID);                                           \
+                                                                               \
+    LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);                       \
+    EXPECT_FALSE(less_than(pos_small, qnan));                                  \
+    EXPECT_FP_EXCEPTION(FE_INVALID);                                           \
+                                                                               \
+    LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);                       \
+    EXPECT_FALSE(less_than(qnan, qnan));                                       \
+    EXPECT_FP_EXCEPTION(FE_INVALID);                                           \
+                                                                               \
+    LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);                       \
+    EXPECT_FALSE(less_than(snan, pos_small));                                  \
+    EXPECT_FP_EXCEPTION(FE_INVALID);                                           \
+                                                                               \
+    LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);                       \
+    EXPECT_FALSE(less_than(pos_small, snan));                                  \
+    EXPECT_FP_EXCEPTION(FE_INVALID);                                           \
+                                                                               \
+    LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);                       \
+    EXPECT_FALSE(less_than(snan, snan));                                       \
+    EXPECT_FP_EXCEPTION(FE_INVALID);                                           \
   }
 
 #define TEST_GREATER_THAN(Name, Type)                                          \
@@ -108,7 +153,8 @@ using LIBC_NAMESPACE::fputil::not_equals;
     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 qnan = Bits::quiet_nan().get_val();                                   \
+    Type snan = Bits::signaling_nan().get_val();                               \
     Type pos_small = Type(0.1);                                                \
     Type neg_small = Type(-0.1);                                               \
     Type pos_large = Type(1000000.0);                                          \
@@ -131,9 +177,29 @@ using LIBC_NAMESPACE::fputil::not_equals;
     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));                                      \
+    LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);                       \
+    EXPECT_FALSE(greater_than(qnan, pos_small));                               \
+    EXPECT_FP_EXCEPTION(FE_INVALID);                                           \
+                                                                               \
+    LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);                       \
+    EXPECT_FALSE(greater_than(pos_small, qnan));                               \
+    EXPECT_FP_EXCEPTION(FE_INVALID);                                           \
+                                                                               \
+    LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);                       \
+    EXPECT_FALSE(greater_than(qnan, qnan));                                    \
+    EXPECT_FP_EXCEPTION(FE_INVALID);                                           \
+                                                                               \
+    LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);                       \
+    EXPECT_FALSE(greater_than(snan, pos_small));                               \
+    EXPECT_FP_EXCEPTION(FE_INVALID);                                           \
+                                                                               \
+    LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);                       \
+    EXPECT_FALSE(greater_than(pos_small, snan));                               \
+    EXPECT_FP_EXCEPTION(FE_INVALID);                                           \
+                                                                               \
+    LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);                       \
+    EXPECT_FALSE(greater_than(snan, snan));                                    \
+    EXPECT_FP_EXCEPTION(FE_INVALID);                                           \
   }
 
 #define TEST_LESS_THAN_OR_EQUALS(Name, Type)                                   \
@@ -143,7 +209,8 @@ using LIBC_NAMESPACE::fputil::not_equals;
     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 qnan = Bits::quiet_nan().get_val();                                   \
+    Type snan = Bits::signaling_nan().get_val();                               \
     Type pos_small = Type(0.1);                                                \
     Type neg_small = Type(-0.1);                                               \
     Type pos_large = Type(1000000.0);                                          \
@@ -164,9 +231,29 @@ using LIBC_NAMESPACE::fputil::not_equals;
     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));                               \
+    LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);                       \
+    EXPECT_FALSE(less_than_or_equals(qnan, pos_small));                        \
+    EXPECT_FP_EXCEPTION(FE_INVALID);                                           \
+                                                                               \
+    LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);                       \
+    EXPECT_FALSE(less_than_or_equals(pos_small, qnan));                        \
+    EXPECT_FP_EXCEPTION(FE_INVALID);                                           \
+                                                                               \
+    LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);                       \
+    EXPECT_FALSE(less_than_or_equals(qnan, qnan));                             \
+    EXPECT_FP_EXCEPTION(FE_INVALID);                                           \
+                                                                               \
+    LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);                       \
+    EXPECT_FALSE(less_than_or_equals(snan, pos_small));                        \
+    EXPECT_FP_EXCEPTION(FE_INVALID);                                           \
+                                                                               \
+    LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);                       \
+    EXPECT_FALSE(less_than_or_equals(pos_small, snan));                        \
+    EXPECT_FP_EXCEPTION(FE_INVALID);                                           \
+                                                                               \
+    LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);                       \
+    EXPECT_FALSE(less_than_or_equals(snan, snan));                             \
+    EXPECT_FP_EXCEPTION(FE_INVALID);                                           \
   }
 
 #define TEST_GREATER_THAN_OR_EQUALS(Name, Type)                                \
@@ -176,7 +263,8 @@ using LIBC_NAMESPACE::fputil::not_equals;
     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 qnan = Bits::quiet_nan().get_val();                                   \
+    Type snan = Bits::signaling_nan().get_val();                               \
     Type pos_small = Type(0.1);                                                \
     Type neg_small = Type(-0.1);                                               \
     Type pos_large = Type(1000000.0);                                          \
@@ -197,9 +285,29 @@ using LIBC_NAMESPACE::fputil::not_equals;
     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));                            \
+    LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);                       \
+    EXPECT_FALSE(greater_than_or_equals(qnan, pos_small));                     \
+    EXPECT_FP_EXCEPTION(FE_INVALID);                                           \
+                                                                               \
+    LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);                       \
+    EXPECT_FALSE(greater_than_or_equals(pos_small, qnan));                     \
+    EXPECT_FP_EXCEPTION(FE_INVALID);                                           \
+                                                                               \
+    LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);                       \
+    EXPECT_FALSE(greater_than_or_equals(qnan, qnan));                          \
+    EXPECT_FP_EXCEPTION(FE_INVALID);                                           \
+                                                                               \
+    LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);                       \
+    EXPECT_FALSE(greater_than_or_equals(snan, pos_small));                     \
+    EXPECT_FP_EXCEPTION(FE_INVALID);                                           \
+                                                                               \
+    LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);                       \
+    EXPECT_FALSE(greater_than_or_equals(pos_small, snan));                     \
+    EXPECT_FP_EXCEPTION(FE_INVALID);                                           \
+                                                                               \
+    LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);                       \
+    EXPECT_FALSE(greater_than_or_equals(snan, snan));                          \
+    EXPECT_FP_EXCEPTION(FE_INVALID);                                           \
   }
 
 #define TEST_COMPARISON_OPS(Name, Type)                                        \
@@ -211,10 +319,13 @@ using LIBC_NAMESPACE::fputil::not_equals;
 
 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))
+
+// We have to use type alias here, since FPBits<(long double)> is not allowed
+// if we do TEST_COMPARISON_OPS(LongDouble, (long double));
+// and Type(x) for Type = long double evaulates to long double(x)which  is not
+// allowed if we do TEST_COMPARISON_OPS(LongDouble, long double);
+using long_double = long double;
+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 cd5d38b31789009ff7da8fd06a59b06927b636f3 Mon Sep 17 00:00:00 2001
From: Krishna Pandey <kpandey81930 at gmail.com>
Date: Fri, 4 Jul 2025 23:16:19 +0530
Subject: [PATCH 13/30] chore: address nits

Signed-off-by: Krishna Pandey <kpandey81930 at gmail.com>
---
 libc/src/__support/FPUtil/CMakeLists.txt         | 2 +-
 libc/src/__support/FPUtil/ComparisonOperations.h | 8 ++++----
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/libc/src/__support/FPUtil/CMakeLists.txt b/libc/src/__support/FPUtil/CMakeLists.txt
index fc6e95de74122..9d6692e7efdd9 100644
--- a/libc/src/__support/FPUtil/CMakeLists.txt
+++ b/libc/src/__support/FPUtil/CMakeLists.txt
@@ -216,8 +216,8 @@ add_header_library(
   DEPENDS
     .fenv_impl
     .fp_bits
-  libc.src.__support.macros.config
     libc.src.__support.CPP.type_traits
+  libc.src.__support.macros.config
 )
 
 add_header_library(
diff --git a/libc/src/__support/FPUtil/ComparisonOperations.h b/libc/src/__support/FPUtil/ComparisonOperations.h
index 28e46630c737c..216673bbb6be0 100644
--- a/libc/src/__support/FPUtil/ComparisonOperations.h
+++ b/libc/src/__support/FPUtil/ComparisonOperations.h
@@ -9,10 +9,10 @@
 #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>
-#include "src/__support/CPP/type_traits.h" // enable_if, is_floating_point
-#include "src/__support/macros/config.h"   // LIBC_NAMESPACE_DECL
+#include "FEnvImpl.h"
+#include "FPBits.h"
+#include "src/__support/CPP/type_traits.h"
+#include "src/__support/macros/config.h"
 
 namespace LIBC_NAMESPACE_DECL {
 namespace fputil {

>From 692a15e3ffaf47fd83361007245e934972613534 Mon Sep 17 00:00:00 2001
From: Krishna Pandey <kpandey81930 at gmail.com>
Date: Fri, 4 Jul 2025 23:17:02 +0530
Subject: [PATCH 14/30] refactor: move tests inside FEnvSafeTest class

Signed-off-by: Krishna Pandey <kpandey81930 at gmail.com>
---
 .../FPUtil/comparison_operations_test.cpp     | 591 +++++++++---------
 1 file changed, 301 insertions(+), 290 deletions(-)

diff --git a/libc/test/src/__support/FPUtil/comparison_operations_test.cpp b/libc/test/src/__support/FPUtil/comparison_operations_test.cpp
index 388d8b7a18e04..e14c5e2bfcea4 100644
--- a/libc/test/src/__support/FPUtil/comparison_operations_test.cpp
+++ b/libc/test/src/__support/FPUtil/comparison_operations_test.cpp
@@ -1,4 +1,4 @@
-//===-- Unittests for Comparison 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.
@@ -10,6 +10,7 @@
 #include "src/__support/FPUtil/FPBits.h"
 #include "src/__support/macros/properties/types.h"
 #include "src/__support/sign.h"
+#include "test/UnitTest/FEnvSafeTest.h"
 #include "test/UnitTest/FPMatcher.h"
 #include "test/UnitTest/Test.h"
 
@@ -19,313 +20,323 @@ using LIBC_NAMESPACE::fputil::greater_than_or_equals;
 using LIBC_NAMESPACE::fputil::less_than;
 using LIBC_NAMESPACE::fputil::less_than_or_equals;
 
-#define TEST_EQUALS(Name, Type)                                                \
-  TEST(LlvmLibc##Name##ComparisionOperationsTest, 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 qnan = Bits::quiet_nan().get_val();                                   \
-    Type snan = Bits::signaling_nan().get_val();                               \
-    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(qnan, qnan));                                          \
-    EXPECT_FALSE(equals(qnan, pos_normal));                                    \
-    EXPECT_FALSE(equals(qnan, pos_zero));                                      \
-    EXPECT_FALSE(equals(qnan, pos_inf));                                       \
-    EXPECT_FALSE(equals(pos_normal, qnan));                                    \
-                                                                               \
-    LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);                       \
-    EXPECT_FALSE(equals(snan, snan));                                          \
-    EXPECT_FP_EXCEPTION(FE_INVALID);                                           \
-                                                                               \
-    LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);                       \
-    EXPECT_FALSE(equals(snan, qnan));                                          \
-    EXPECT_FP_EXCEPTION(FE_INVALID);                                           \
-                                                                               \
-    LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);                       \
-    EXPECT_FALSE(equals(qnan, snan));                                          \
-    EXPECT_FP_EXCEPTION(FE_INVALID);                                           \
-                                                                               \
-    LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);                       \
-    EXPECT_FALSE(equals(snan, pos_normal));                                    \
-    EXPECT_FP_EXCEPTION(FE_INVALID);                                           \
-                                                                               \
-    LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);                       \
-    EXPECT_FALSE(equals(pos_normal, snan));                                    \
-    EXPECT_FP_EXCEPTION(FE_INVALID);                                           \
-                                                                               \
-    LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);                       \
-    EXPECT_FALSE(equals(snan, pos_inf));                                       \
-    EXPECT_FP_EXCEPTION(FE_INVALID);                                           \
-                                                                               \
-    LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);                       \
-    EXPECT_FALSE(equals(snan, pos_zero));                                      \
-    EXPECT_FP_EXCEPTION(FE_INVALID);                                           \
+template <typename T>
+class ComparisonOperationsTest : public LIBC_NAMESPACE::testing::FEnvSafeTest {
+  DECLARE_SPECIAL_CONSTANTS(T)
+
+  static constexpr T normal1 = T(3.14);
+  static constexpr T normal2 = T(2.71);
+  static constexpr T small = T(0.1);
+  static constexpr T neg_small = T(-0.1);
+  static constexpr T large = T(10000.0);
+  static constexpr T neg_large = T(-10000.0);
+
+public:
+  void test_equals() {
+    EXPECT_TRUE(equals(neg_zero, neg_zero));
+    EXPECT_TRUE(equals(zero, neg_zero));
+    EXPECT_TRUE(equals(neg_zero, zero));
+
+    EXPECT_TRUE(equals(inf, inf));
+    EXPECT_TRUE(equals(neg_inf, neg_inf));
+    EXPECT_FALSE(equals(inf, neg_inf));
+    EXPECT_FALSE(equals(neg_inf, inf));
+
+    EXPECT_TRUE(equals(normal1, normal1));
+    EXPECT_TRUE(equals(normal2, normal2));
+    EXPECT_FALSE(equals(normal1, normal2));
+    EXPECT_FALSE(equals(normal1, -normal1));
+
+    LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);
+    auto test_qnan = [&](T x, T y) {
+      EXPECT_FALSE(equals(x, y));
+      // NOTE: equals and not equals operations should raise FE_INVALID for
+      // quiet NaN operands
+      EXPECT_FP_EXCEPTION(0);
+    };
+
+    test_qnan(aNaN, aNaN);
+    test_qnan(aNaN, neg_aNaN);
+    test_qnan(aNaN, zero);
+    test_qnan(aNaN, inf);
+    test_qnan(aNaN, normal1);
+
+    test_qnan(neg_aNaN, neg_aNaN);
+    test_qnan(neg_aNaN, aNaN);
+    test_qnan(neg_aNaN, zero);
+    test_qnan(neg_aNaN, inf);
+    test_qnan(neg_aNaN, normal1);
+
+    auto test_snan = [&](T x, T y) {
+      LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);
+      EXPECT_FALSE(equals(x, y));
+      EXPECT_FP_EXCEPTION(FE_INVALID);
+    };
+
+    test_snan(sNaN, sNaN);
+    test_snan(sNaN, neg_sNaN);
+    test_snan(sNaN, aNaN);
+    test_snan(sNaN, neg_aNaN);
+    test_snan(sNaN, zero);
+    test_snan(sNaN, neg_zero);
+    test_snan(sNaN, inf);
+    test_snan(sNaN, neg_inf);
+    test_snan(sNaN, normal1);
+
+    test_snan(neg_sNaN, neg_sNaN);
+    test_snan(neg_sNaN, sNaN);
+    test_snan(neg_sNaN, aNaN);
+    test_snan(neg_sNaN, neg_aNaN);
+    test_snan(neg_sNaN, zero);
+    test_snan(neg_sNaN, neg_zero);
+    test_snan(neg_sNaN, inf);
+    test_snan(neg_sNaN, neg_inf);
+    test_snan(neg_sNaN, normal1);
   }
 
-#define TEST_LESS_THAN(Name, Type)                                             \
-  TEST(LlvmLibc##Name##ComparisionOperationsTest, 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 qnan = Bits::quiet_nan().get_val();                                   \
-    Type snan = Bits::signaling_nan().get_val();                               \
-    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));                                 \
-                                                                               \
-    LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);                       \
-    EXPECT_FALSE(less_than(qnan, pos_small));                                  \
-    EXPECT_FP_EXCEPTION(FE_INVALID);                                           \
-                                                                               \
-    LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);                       \
-    EXPECT_FALSE(less_than(pos_small, qnan));                                  \
-    EXPECT_FP_EXCEPTION(FE_INVALID);                                           \
-                                                                               \
-    LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);                       \
-    EXPECT_FALSE(less_than(qnan, qnan));                                       \
-    EXPECT_FP_EXCEPTION(FE_INVALID);                                           \
-                                                                               \
-    LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);                       \
-    EXPECT_FALSE(less_than(snan, pos_small));                                  \
-    EXPECT_FP_EXCEPTION(FE_INVALID);                                           \
-                                                                               \
-    LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);                       \
-    EXPECT_FALSE(less_than(pos_small, snan));                                  \
-    EXPECT_FP_EXCEPTION(FE_INVALID);                                           \
-                                                                               \
-    LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);                       \
-    EXPECT_FALSE(less_than(snan, snan));                                       \
-    EXPECT_FP_EXCEPTION(FE_INVALID);                                           \
+  void test_less_than() {
+    EXPECT_TRUE(less_than(neg_small, small));
+    EXPECT_TRUE(less_than(small, large));
+
+    EXPECT_TRUE(less_than(neg_large, neg_small));
+    EXPECT_FALSE(less_than(large, small));
+    EXPECT_FALSE(less_than(small, neg_small));
+
+    EXPECT_FALSE(less_than(zero, neg_zero));
+    EXPECT_FALSE(less_than(neg_zero, zero));
+    EXPECT_FALSE(less_than(zero, zero));
+
+    EXPECT_TRUE(less_than(neg_small, zero));
+    EXPECT_TRUE(less_than(neg_zero, small));
+    EXPECT_FALSE(less_than(small, zero));
+
+    EXPECT_TRUE(less_than(neg_inf, inf));
+    EXPECT_TRUE(less_than(neg_inf, neg_small));
+    EXPECT_TRUE(less_than(small, inf));
+    EXPECT_FALSE(less_than(inf, small));
+
+    EXPECT_FALSE(less_than(small, small));
+    EXPECT_FALSE(less_than(neg_inf, neg_inf));
+
+    auto test_qnan = [&](T x, T y) {
+      LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);
+      EXPECT_FALSE(less_than(x, y));
+      // NOTE: All signaling comparison operations other than equals and not
+      // equals should raise FE_INVALID when comparing with NaN
+      // see Note after table 5.1 in IEEE Std 754-2019
+      //    [...] The Signaling predicates in Table 5.1 signal the invalid
+      //    operation exception on quiet NaN operands to warn of potential
+      //    incorrect behavior of programs written assuming trichotomy.
+      EXPECT_FP_EXCEPTION(FE_INVALID);
+    };
+
+    test_qnan(aNaN, small);
+    test_qnan(small, aNaN);
+    test_qnan(aNaN, aNaN);
+    test_qnan(neg_aNaN, neg_small);
+    test_qnan(neg_small, neg_aNaN);
+    test_qnan(neg_aNaN, neg_aNaN);
+
+    auto test_snan = [&](T x, T y) {
+      LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);
+      EXPECT_FALSE(less_than(x, y));
+      EXPECT_FP_EXCEPTION(FE_INVALID);
+    };
+
+    test_snan(sNaN, small);
+    test_snan(sNaN, neg_small);
+    test_snan(sNaN, zero);
+    test_snan(sNaN, inf);
+    test_snan(sNaN, aNaN);
+    test_snan(sNaN, sNaN);
+
+    test_snan(neg_sNaN, small);
+    test_snan(neg_sNaN, neg_small);
+    test_snan(neg_sNaN, zero);
+    test_snan(neg_sNaN, inf);
+    test_snan(neg_sNaN, aNaN);
+    test_snan(neg_sNaN, neg_sNaN);
   }
+  void test_greater_than() {
+    EXPECT_TRUE(greater_than(large, neg_small));
+    EXPECT_TRUE(greater_than(neg_small, neg_large));
+
+    EXPECT_FALSE(greater_than(large, large));
+    EXPECT_FALSE(greater_than(neg_small, large));
+
+    EXPECT_FALSE(greater_than(zero, neg_zero));
+    EXPECT_FALSE(greater_than(neg_zero, zero));
+
+    EXPECT_TRUE(greater_than(inf, neg_inf));
+    EXPECT_TRUE(greater_than(inf, large));
+    EXPECT_TRUE(greater_than(large, neg_inf));
+    EXPECT_FALSE(greater_than(neg_inf, inf));
 
-#define TEST_GREATER_THAN(Name, Type)                                          \
-  TEST(LlvmLibc##Name##ComparisionOperationsTest, 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 qnan = Bits::quiet_nan().get_val();                                   \
-    Type snan = Bits::signaling_nan().get_val();                               \
-    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));                              \
-                                                                               \
-    LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);                       \
-    EXPECT_FALSE(greater_than(qnan, pos_small));                               \
-    EXPECT_FP_EXCEPTION(FE_INVALID);                                           \
-                                                                               \
-    LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);                       \
-    EXPECT_FALSE(greater_than(pos_small, qnan));                               \
-    EXPECT_FP_EXCEPTION(FE_INVALID);                                           \
-                                                                               \
-    LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);                       \
-    EXPECT_FALSE(greater_than(qnan, qnan));                                    \
-    EXPECT_FP_EXCEPTION(FE_INVALID);                                           \
-                                                                               \
-    LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);                       \
-    EXPECT_FALSE(greater_than(snan, pos_small));                               \
-    EXPECT_FP_EXCEPTION(FE_INVALID);                                           \
-                                                                               \
-    LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);                       \
-    EXPECT_FALSE(greater_than(pos_small, snan));                               \
-    EXPECT_FP_EXCEPTION(FE_INVALID);                                           \
-                                                                               \
-    LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);                       \
-    EXPECT_FALSE(greater_than(snan, snan));                                    \
-    EXPECT_FP_EXCEPTION(FE_INVALID);                                           \
+    EXPECT_FALSE(greater_than(large, large));
+    EXPECT_FALSE(greater_than(inf, inf));
+
+    auto test_qnan = [&](T x, T y) {
+      LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);
+      EXPECT_FALSE(greater_than(x, y));
+      EXPECT_FP_EXCEPTION(FE_INVALID);
+    };
+
+    test_qnan(aNaN, large);
+    test_qnan(large, aNaN);
+    test_qnan(aNaN, aNaN);
+    test_qnan(neg_aNaN, neg_small);
+    test_qnan(neg_small, neg_aNaN);
+    test_qnan(neg_aNaN, neg_aNaN);
+
+    auto test_snan = [&](T x, T y) {
+      LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);
+      EXPECT_FALSE(greater_than(x, y));
+      EXPECT_FP_EXCEPTION(FE_INVALID);
+    };
+
+    test_snan(sNaN, large);
+    test_snan(sNaN, neg_small);
+    test_snan(sNaN, zero);
+    test_snan(sNaN, inf);
+    test_snan(sNaN, aNaN);
+    test_snan(sNaN, sNaN);
+
+    test_snan(neg_sNaN, large);
+    test_snan(neg_sNaN, neg_small);
+    test_snan(neg_sNaN, zero);
+    test_snan(neg_sNaN, inf);
+    test_snan(neg_sNaN, aNaN);
+    test_snan(neg_sNaN, neg_sNaN);
   }
 
-#define TEST_LESS_THAN_OR_EQUALS(Name, Type)                                   \
-  TEST(LlvmLibc##Name##ComparisionOperationsTest, 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 qnan = Bits::quiet_nan().get_val();                                   \
-    Type snan = Bits::signaling_nan().get_val();                               \
-    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));                   \
-                                                                               \
-    LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);                       \
-    EXPECT_FALSE(less_than_or_equals(qnan, pos_small));                        \
-    EXPECT_FP_EXCEPTION(FE_INVALID);                                           \
-                                                                               \
-    LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);                       \
-    EXPECT_FALSE(less_than_or_equals(pos_small, qnan));                        \
-    EXPECT_FP_EXCEPTION(FE_INVALID);                                           \
-                                                                               \
-    LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);                       \
-    EXPECT_FALSE(less_than_or_equals(qnan, qnan));                             \
-    EXPECT_FP_EXCEPTION(FE_INVALID);                                           \
-                                                                               \
-    LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);                       \
-    EXPECT_FALSE(less_than_or_equals(snan, pos_small));                        \
-    EXPECT_FP_EXCEPTION(FE_INVALID);                                           \
-                                                                               \
-    LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);                       \
-    EXPECT_FALSE(less_than_or_equals(pos_small, snan));                        \
-    EXPECT_FP_EXCEPTION(FE_INVALID);                                           \
-                                                                               \
-    LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);                       \
-    EXPECT_FALSE(less_than_or_equals(snan, snan));                             \
-    EXPECT_FP_EXCEPTION(FE_INVALID);                                           \
+  void test_less_than_or_equals() {
+    EXPECT_TRUE(less_than_or_equals(neg_small, small));
+    EXPECT_TRUE(less_than_or_equals(small, large));
+    EXPECT_TRUE(less_than_or_equals(neg_inf, small));
+
+    EXPECT_TRUE(less_than_or_equals(small, small));
+    EXPECT_TRUE(less_than_or_equals(zero, neg_zero));
+    EXPECT_TRUE(less_than_or_equals(inf, inf));
+
+    EXPECT_FALSE(less_than_or_equals(small, neg_small));
+    EXPECT_FALSE(less_than_or_equals(large, small));
+    EXPECT_FALSE(less_than_or_equals(inf, small));
+
+    EXPECT_TRUE(less_than_or_equals(neg_large, small));
+    EXPECT_FALSE(less_than_or_equals(large, neg_small));
+
+    auto test_qnan = [&](T x, T y) {
+      LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);
+      EXPECT_FALSE(less_than_or_equals(x, y));
+      EXPECT_FP_EXCEPTION(FE_INVALID);
+    };
+
+    test_qnan(aNaN, small);
+    test_qnan(small, aNaN);
+    test_qnan(aNaN, aNaN);
+    test_qnan(neg_aNaN, neg_small);
+    test_qnan(neg_small, neg_aNaN);
+    test_qnan(neg_aNaN, neg_aNaN);
+
+    auto test_snan = [&](T x, T y) {
+      LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);
+      EXPECT_FALSE(less_than_or_equals(x, y));
+      EXPECT_FP_EXCEPTION(FE_INVALID);
+    };
+
+    test_snan(sNaN, small);
+    test_snan(sNaN, neg_small);
+    test_snan(sNaN, zero);
+    test_snan(sNaN, inf);
+    test_snan(sNaN, aNaN);
+    test_snan(sNaN, sNaN);
+
+    test_snan(neg_sNaN, small);
+    test_snan(neg_sNaN, neg_small);
+    test_snan(neg_sNaN, zero);
+    test_snan(neg_sNaN, inf);
+    test_snan(neg_sNaN, aNaN);
+    test_snan(neg_sNaN, neg_sNaN);
   }
 
-#define TEST_GREATER_THAN_OR_EQUALS(Name, Type)                                \
-  TEST(LlvmLibc##Name##ComparisionOperationsTest, 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 qnan = Bits::quiet_nan().get_val();                                   \
-    Type snan = Bits::signaling_nan().get_val();                               \
-    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));                \
-                                                                               \
-    LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);                       \
-    EXPECT_FALSE(greater_than_or_equals(qnan, pos_small));                     \
-    EXPECT_FP_EXCEPTION(FE_INVALID);                                           \
-                                                                               \
-    LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);                       \
-    EXPECT_FALSE(greater_than_or_equals(pos_small, qnan));                     \
-    EXPECT_FP_EXCEPTION(FE_INVALID);                                           \
-                                                                               \
-    LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);                       \
-    EXPECT_FALSE(greater_than_or_equals(qnan, qnan));                          \
-    EXPECT_FP_EXCEPTION(FE_INVALID);                                           \
-                                                                               \
-    LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);                       \
-    EXPECT_FALSE(greater_than_or_equals(snan, pos_small));                     \
-    EXPECT_FP_EXCEPTION(FE_INVALID);                                           \
-                                                                               \
-    LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);                       \
-    EXPECT_FALSE(greater_than_or_equals(pos_small, snan));                     \
-    EXPECT_FP_EXCEPTION(FE_INVALID);                                           \
-                                                                               \
-    LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);                       \
-    EXPECT_FALSE(greater_than_or_equals(snan, snan));                          \
-    EXPECT_FP_EXCEPTION(FE_INVALID);                                           \
+  void test_greater_than_or_equals() {
+    EXPECT_TRUE(greater_than_or_equals(small, neg_small));
+    EXPECT_TRUE(greater_than_or_equals(large, small));
+    EXPECT_TRUE(greater_than_or_equals(inf, small));
+
+    EXPECT_TRUE(greater_than_or_equals(small, small));
+    EXPECT_TRUE(greater_than_or_equals(zero, neg_zero));
+    EXPECT_TRUE(greater_than_or_equals(neg_inf, neg_inf));
+
+    EXPECT_FALSE(greater_than_or_equals(neg_small, small));
+    EXPECT_FALSE(greater_than_or_equals(small, large));
+    EXPECT_FALSE(greater_than_or_equals(neg_inf, small));
+
+    EXPECT_TRUE(greater_than_or_equals(large, neg_small));
+    EXPECT_FALSE(greater_than_or_equals(neg_large, small));
+
+    auto test_qnan = [&](T x, T y) {
+      LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);
+      EXPECT_FALSE(greater_than_or_equals(x, y));
+      EXPECT_FP_EXCEPTION(FE_INVALID);
+    };
+
+    test_qnan(aNaN, small);
+    test_qnan(small, aNaN);
+    test_qnan(aNaN, aNaN);
+    test_qnan(neg_aNaN, neg_small);
+    test_qnan(neg_small, neg_aNaN);
+    test_qnan(neg_aNaN, neg_aNaN);
+
+    auto test_snan = [&](T x, T y) {
+      LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);
+      EXPECT_FALSE(greater_than_or_equals(x, y));
+      EXPECT_FP_EXCEPTION(FE_INVALID);
+    };
+
+    test_snan(sNaN, small);
+    test_snan(sNaN, neg_small);
+    test_snan(sNaN, zero);
+    test_snan(sNaN, inf);
+    test_snan(sNaN, aNaN);
+    test_snan(sNaN, sNaN);
+
+    test_snan(neg_sNaN, small);
+    test_snan(neg_sNaN, neg_small);
+    test_snan(neg_sNaN, zero);
+    test_snan(neg_sNaN, inf);
+    test_snan(neg_sNaN, aNaN);
+    test_snan(neg_sNaN, neg_sNaN);
   }
+};
 
 #define TEST_COMPARISON_OPS(Name, Type)                                        \
-  TEST_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)
+  using LlvmLibc##Name##ComparisonOperationsTest =                             \
+      ComparisonOperationsTest<Type>;                                          \
+  TEST_F(LlvmLibc##Name##ComparisonOperationsTest, Equals) { test_equals(); }  \
+  TEST_F(LlvmLibc##Name##ComparisonOperationsTest, LessThan) {                 \
+    test_less_than();                                                          \
+  }                                                                            \
+  TEST_F(LlvmLibc##Name##ComparisonOperationsTest, GreaterThan) {              \
+    test_greater_than();                                                       \
+  }                                                                            \
+  TEST_F(LlvmLibc##Name##ComparisonOperationsTest, LessThanOrEquals) {         \
+    test_less_than_or_equals();                                                \
+  }                                                                            \
+  TEST_F(LlvmLibc##Name##ComparisonOperationsTest, GreaterThanOrEquals) {      \
+    test_greater_than_or_equals();                                             \
+  }
 
 TEST_COMPARISON_OPS(Float, float)
 TEST_COMPARISON_OPS(Double, double)
 
-// We have to use type alias here, since FPBits<(long double)> is not allowed
-// if we do TEST_COMPARISON_OPS(LongDouble, (long double));
-// and Type(x) for Type = long double evaulates to long double(x)which  is not
+// We have to use type alias here, since FPBits<(long double)> is not
+// allowed if we do TEST_COMPARISON_OPS(LongDouble, (long double)); and
+// Type(x) for Type = long double evaluates to long double(x)which  is not
 // allowed if we do TEST_COMPARISON_OPS(LongDouble, long double);
 using long_double = long double;
 TEST_COMPARISON_OPS(LongDouble, long_double)
+
 #ifdef LIBC_TYPES_HAS_FLOAT16
 TEST_COMPARISON_OPS(Float16, float16)
 #endif // LIBC_TYPES_HAS_FLOAT16

>From 71869fdea0807bad9097f76ab28a37cb763d419a Mon Sep 17 00:00:00 2001
From: Krishna Pandey <kpandey81930 at gmail.com>
Date: Sat, 5 Jul 2025 00:28:19 +0530
Subject: [PATCH 15/30] chore: further nits

Signed-off-by: Krishna Pandey <kpandey81930 at gmail.com>
---
 .../src/__support/FPUtil/ComparisonOperations.h | 13 ++++++++++---
 .../FPUtil/comparison_operations_test.cpp       | 17 +++--------------
 2 files changed, 13 insertions(+), 17 deletions(-)

diff --git a/libc/src/__support/FPUtil/ComparisonOperations.h b/libc/src/__support/FPUtil/ComparisonOperations.h
index 216673bbb6be0..05c9a056ecf09 100644
--- a/libc/src/__support/FPUtil/ComparisonOperations.h
+++ b/libc/src/__support/FPUtil/ComparisonOperations.h
@@ -17,7 +17,8 @@
 namespace LIBC_NAMESPACE_DECL {
 namespace fputil {
 
-// IEEE Standard 754-2019. Section 5.11
+// All predicates are hereby implemented as per IEEE Std 754-2019
+// Implements compareQuietEqual predicate
 // Rules for comparison within the same floating point type
 // 1. +0 = −0
 // 2. (i)   +inf  = +inf
@@ -46,7 +47,8 @@ LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<T>, bool> equals(T x,
   return x_bits.uintval() == y_bits.uintval();
 }
 
-// Rules:
+// Implements compareSignalingLess predicate
+// Section 5.11 Rules:
 // 1. -inf < x (x != -inf)
 // 2. x < +inf (x != +inf)
 // 3. Any comparison with NaN return false
@@ -62,8 +64,10 @@ LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<T>, bool> less_than(T x,
     fputil::raise_except_if_required(FE_INVALID);
 
   // Any comparison with NaN returns false
-  if (x_bits.is_nan() || y_bits.is_nan())
+  if (x_bits.is_nan() || y_bits.is_nan()) {
+    fputil::raise_except_if_required(FE_INVALID);
     return false;
+  }
 
   if (x_bits.is_zero() && y_bits.is_zero())
     return false;
@@ -85,6 +89,7 @@ LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<T>, bool> less_than(T x,
   return x_bits.uintval() < y_bits.uintval();
 }
 
+// Implements compareSignalingGreater predicate
 // x < y => y > x
 template <typename T>
 LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<T>, bool>
@@ -92,6 +97,7 @@ greater_than(T x, T y) {
   return less_than(y, x);
 }
 
+// Implements compareSignalingLessEqual predicate
 // following is expression is correct, accounting for NaN case(s) as well
 // x <= y => (x < y) || (x == y)
 template <typename T>
@@ -100,6 +106,7 @@ less_than_or_equals(T x, T y) {
   return less_than(x, y) || equals(x, y);
 }
 
+// Implements compareSignalingGreaterEqual predicate
 // 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>
diff --git a/libc/test/src/__support/FPUtil/comparison_operations_test.cpp b/libc/test/src/__support/FPUtil/comparison_operations_test.cpp
index e14c5e2bfcea4..91835de7be536 100644
--- a/libc/test/src/__support/FPUtil/comparison_operations_test.cpp
+++ b/libc/test/src/__support/FPUtil/comparison_operations_test.cpp
@@ -47,8 +47,8 @@ class ComparisonOperationsTest : public LIBC_NAMESPACE::testing::FEnvSafeTest {
     EXPECT_FALSE(equals(normal1, normal2));
     EXPECT_FALSE(equals(normal1, -normal1));
 
-    LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);
     auto test_qnan = [&](T x, T y) {
+      LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);
       EXPECT_FALSE(equals(x, y));
       // NOTE: equals and not equals operations should raise FE_INVALID for
       // quiet NaN operands
@@ -121,12 +121,6 @@ class ComparisonOperationsTest : public LIBC_NAMESPACE::testing::FEnvSafeTest {
     auto test_qnan = [&](T x, T y) {
       LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);
       EXPECT_FALSE(less_than(x, y));
-      // NOTE: All signaling comparison operations other than equals and not
-      // equals should raise FE_INVALID when comparing with NaN
-      // see Note after table 5.1 in IEEE Std 754-2019
-      //    [...] The Signaling predicates in Table 5.1 signal the invalid
-      //    operation exception on quiet NaN operands to warn of potential
-      //    incorrect behavior of programs written assuming trichotomy.
       EXPECT_FP_EXCEPTION(FE_INVALID);
     };
 
@@ -157,6 +151,7 @@ class ComparisonOperationsTest : public LIBC_NAMESPACE::testing::FEnvSafeTest {
     test_snan(neg_sNaN, aNaN);
     test_snan(neg_sNaN, neg_sNaN);
   }
+
   void test_greater_than() {
     EXPECT_TRUE(greater_than(large, neg_small));
     EXPECT_TRUE(greater_than(neg_small, neg_large));
@@ -329,13 +324,7 @@ class ComparisonOperationsTest : public LIBC_NAMESPACE::testing::FEnvSafeTest {
 
 TEST_COMPARISON_OPS(Float, float)
 TEST_COMPARISON_OPS(Double, double)
-
-// We have to use type alias here, since FPBits<(long double)> is not
-// allowed if we do TEST_COMPARISON_OPS(LongDouble, (long double)); and
-// Type(x) for Type = long double evaluates to long double(x)which  is not
-// allowed if we do TEST_COMPARISON_OPS(LongDouble, long double);
-using long_double = long double;
-TEST_COMPARISON_OPS(LongDouble, long_double)
+TEST_COMPARISON_OPS(LongDouble, long double)
 
 #ifdef LIBC_TYPES_HAS_FLOAT16
 TEST_COMPARISON_OPS(Float16, float16)

>From 634355f89270a7c9754cd9d8f2cd0c8ebe1ca397 Mon Sep 17 00:00:00 2001
From: Krishna Pandey <kpandey81930 at gmail.com>
Date: Sat, 5 Jul 2025 00:34:16 +0530
Subject: [PATCH 16/30] chore: remove NOTE

Signed-off-by: Krishna Pandey <kpandey81930 at gmail.com>
---
 libc/test/src/__support/FPUtil/comparison_operations_test.cpp | 2 --
 1 file changed, 2 deletions(-)

diff --git a/libc/test/src/__support/FPUtil/comparison_operations_test.cpp b/libc/test/src/__support/FPUtil/comparison_operations_test.cpp
index 91835de7be536..4b3ddd2b0e9b4 100644
--- a/libc/test/src/__support/FPUtil/comparison_operations_test.cpp
+++ b/libc/test/src/__support/FPUtil/comparison_operations_test.cpp
@@ -50,8 +50,6 @@ class ComparisonOperationsTest : public LIBC_NAMESPACE::testing::FEnvSafeTest {
     auto test_qnan = [&](T x, T y) {
       LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);
       EXPECT_FALSE(equals(x, y));
-      // NOTE: equals and not equals operations should raise FE_INVALID for
-      // quiet NaN operands
       EXPECT_FP_EXCEPTION(0);
     };
 

>From 8ef1629bb55cc9f08d7080031015653a403a1ef8 Mon Sep 17 00:00:00 2001
From: Krishna Pandey <kpandey81930 at gmail.com>
Date: Wed, 9 Jul 2025 21:04:18 +0530
Subject: [PATCH 17/30] nit: indentation

Signed-off-by: Krishna Pandey <kpandey81930 at gmail.com>
---
 libc/src/__support/FPUtil/CMakeLists.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libc/src/__support/FPUtil/CMakeLists.txt b/libc/src/__support/FPUtil/CMakeLists.txt
index 9d6692e7efdd9..b14bf3c6d4ecd 100644
--- a/libc/src/__support/FPUtil/CMakeLists.txt
+++ b/libc/src/__support/FPUtil/CMakeLists.txt
@@ -260,7 +260,7 @@ add_header_library(
   HDRS
     cast.h
   DEPENDS
-    .dyadic_float
+  .dyadic_flfoat
     .fp_bits
     libc.hdr.fenv_macros
     libc.src.__support.CPP.algorithm

>From a084f4bde6e9e99f75e33111a489627ce884c901 Mon Sep 17 00:00:00 2001
From: Krishna Pandey <kpandey81930 at gmail.com>
Date: Thu, 10 Jul 2025 23:10:42 +0530
Subject: [PATCH 18/30] fix: CMakeLists.txt

Signed-off-by: Krishna Pandey <kpandey81930 at gmail.com>
---
 libc/src/__support/FPUtil/CMakeLists.txt      | 4 ++--
 libc/test/src/__support/FPUtil/CMakeLists.txt | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/libc/src/__support/FPUtil/CMakeLists.txt b/libc/src/__support/FPUtil/CMakeLists.txt
index b14bf3c6d4ecd..a5771c4d270be 100644
--- a/libc/src/__support/FPUtil/CMakeLists.txt
+++ b/libc/src/__support/FPUtil/CMakeLists.txt
@@ -217,7 +217,7 @@ add_header_library(
     .fenv_impl
     .fp_bits
     libc.src.__support.CPP.type_traits
-  libc.src.__support.macros.config
+    libc.src.__support.macros.config
 )
 
 add_header_library(
@@ -260,7 +260,7 @@ add_header_library(
   HDRS
     cast.h
   DEPENDS
-  .dyadic_flfoat
+    .dyadic_float
     .fp_bits
     libc.hdr.fenv_macros
     libc.src.__support.CPP.algorithm
diff --git a/libc/test/src/__support/FPUtil/CMakeLists.txt b/libc/test/src/__support/FPUtil/CMakeLists.txt
index c1e84f1bf20ee..3c6a392b87daf 100644
--- a/libc/test/src/__support/FPUtil/CMakeLists.txt
+++ b/libc/test/src/__support/FPUtil/CMakeLists.txt
@@ -51,11 +51,11 @@ 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.comparison_operations
     libc.src.__support.FPUtil.fp_bits

>From 5fb4864fca6295b6b4709d67cdaa60e51d72beba Mon Sep 17 00:00:00 2001
From: Krishna Pandey <kpandey81930 at gmail.com>
Date: Thu, 10 Jul 2025 23:59:30 +0530
Subject: [PATCH 19/30] nit: commit suggestions

Co-authored-by: OverMighty <its.overmighty at gmail.com>
---
 libc/src/__support/FPUtil/ComparisonOperations.h          | 8 +++-----
 .../src/__support/FPUtil/comparison_operations_test.cpp   | 4 +---
 2 files changed, 4 insertions(+), 8 deletions(-)

diff --git a/libc/src/__support/FPUtil/ComparisonOperations.h b/libc/src/__support/FPUtil/ComparisonOperations.h
index 05c9a056ecf09..411c06f0e1728 100644
--- a/libc/src/__support/FPUtil/ComparisonOperations.h
+++ b/libc/src/__support/FPUtil/ComparisonOperations.h
@@ -24,7 +24,7 @@ namespace fputil {
 // 2. (i)   +inf  = +inf
 //    (ii)  -inf  = -inf
 //    (iii) -inf != +inf
-// 3. Any comparison with NaN return false except (NaN != NaN => true)
+// 3. Any comparison with NaN returns false
 template <typename T>
 LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<T>, bool> equals(T x,
                                                                        T y) {
@@ -43,7 +43,6 @@ 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 comparisons of different signs
   return x_bits.uintval() == y_bits.uintval();
 }
 
@@ -78,8 +77,8 @@ LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<T>, bool> less_than(T x,
   if (x_bits.is_pos() && y_bits.is_neg())
     return false;
 
-  // since we store the float in the format: s | e | m
-  // the comparisons should work if we directly compare the uintval's
+  // since floating-point numbers are stored in the format: s | e | m
+  // we can directly compare the uintval's
 
   // both negative
   if (x_bits.is_neg())
@@ -98,7 +97,6 @@ greater_than(T x, T y) {
 }
 
 // Implements compareSignalingLessEqual predicate
-// 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>
diff --git a/libc/test/src/__support/FPUtil/comparison_operations_test.cpp b/libc/test/src/__support/FPUtil/comparison_operations_test.cpp
index 4b3ddd2b0e9b4..94a8a93e50c69 100644
--- a/libc/test/src/__support/FPUtil/comparison_operations_test.cpp
+++ b/libc/test/src/__support/FPUtil/comparison_operations_test.cpp
@@ -1,4 +1,4 @@
-//===-- Unittests for Comparison Operations for FPBits class --------------===//
+//===-- Unittests for comparison operations on floating-point numbers -----===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -7,9 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "src/__support/FPUtil/ComparisonOperations.h"
-#include "src/__support/FPUtil/FPBits.h"
 #include "src/__support/macros/properties/types.h"
-#include "src/__support/sign.h"
 #include "test/UnitTest/FEnvSafeTest.h"
 #include "test/UnitTest/FPMatcher.h"
 #include "test/UnitTest/Test.h"

>From 2e671ac2dddafb225f66a5b886d742ab7ac5ff62 Mon Sep 17 00:00:00 2001
From: Krishna Pandey <kpandey81930 at gmail.com>
Date: Fri, 11 Jul 2025 00:09:07 +0530
Subject: [PATCH 20/30] chore: remove redundant if

Signed-off-by: Krishna Pandey <kpandey81930 at gmail.com>
---
 libc/src/__support/FPUtil/ComparisonOperations.h | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/libc/src/__support/FPUtil/ComparisonOperations.h b/libc/src/__support/FPUtil/ComparisonOperations.h
index 05c9a056ecf09..d85464fdcbba3 100644
--- a/libc/src/__support/FPUtil/ComparisonOperations.h
+++ b/libc/src/__support/FPUtil/ComparisonOperations.h
@@ -59,10 +59,6 @@ LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<T>, bool> less_than(T x,
   FPBits x_bits(x);
   FPBits y_bits(y);
 
-  if (x_bits.is_signaling_nan() || y_bits.is_signaling_nan() ||
-      x_bits.is_quiet_nan() || y_bits.is_quiet_nan())
-    fputil::raise_except_if_required(FE_INVALID);
-
   // Any comparison with NaN returns false
   if (x_bits.is_nan() || y_bits.is_nan()) {
     fputil::raise_except_if_required(FE_INVALID);

>From 54d857032622bf74fb8b0b63418ef9137bcd50b8 Mon Sep 17 00:00:00 2001
From: Krishna Pandey <kpandey81930 at gmail.com>
Date: Fri, 11 Jul 2025 00:17:43 +0530
Subject: [PATCH 21/30] add: comparison operation tests for Float128

Signed-off-by: Krishna Pandey <kpandey81930 at gmail.com>
---
 .../test/src/__support/FPUtil/comparison_operations_test.cpp | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/libc/test/src/__support/FPUtil/comparison_operations_test.cpp b/libc/test/src/__support/FPUtil/comparison_operations_test.cpp
index 4b3ddd2b0e9b4..f34d4955a771b 100644
--- a/libc/test/src/__support/FPUtil/comparison_operations_test.cpp
+++ b/libc/test/src/__support/FPUtil/comparison_operations_test.cpp
@@ -8,6 +8,7 @@
 
 #include "src/__support/FPUtil/ComparisonOperations.h"
 #include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/FPUtil/bfloat16.h"
 #include "src/__support/macros/properties/types.h"
 #include "src/__support/sign.h"
 #include "test/UnitTest/FEnvSafeTest.h"
@@ -327,3 +328,7 @@ TEST_COMPARISON_OPS(LongDouble, long double)
 #ifdef LIBC_TYPES_HAS_FLOAT16
 TEST_COMPARISON_OPS(Float16, float16)
 #endif // LIBC_TYPES_HAS_FLOAT16
+
+#ifdef LIBC_TYPES_HAS_FLOAT128
+TEST_COMPARISON_OPS(Float128, float128)
+#endif // LIBC_TYPES_HAS_FLOAT128

>From 893711c0d9630e095fd4c6c5a628406181cffa98 Mon Sep 17 00:00:00 2001
From: Krishna Pandey <kpandey81930 at gmail.com>
Date: Fri, 11 Jul 2025 12:32:50 +0530
Subject: [PATCH 22/30] add[WIP]: comparison operator tests for bfloat16

Signed-off-by: Krishna Pandey <kpandey81930 at gmail.com>
---
 .../FPUtil/comparison_operations_test.cpp     | 20 ++++++++++++-------
 1 file changed, 13 insertions(+), 7 deletions(-)

diff --git a/libc/test/src/__support/FPUtil/comparison_operations_test.cpp b/libc/test/src/__support/FPUtil/comparison_operations_test.cpp
index 6027ecd5b4711..5f278fe15adde 100644
--- a/libc/test/src/__support/FPUtil/comparison_operations_test.cpp
+++ b/libc/test/src/__support/FPUtil/comparison_operations_test.cpp
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "src/__support/FPUtil/ComparisonOperations.h"
+#include "src/__support/FPUtil/bfloat16.h"
 #include "src/__support/macros/properties/types.h"
 #include "test/UnitTest/FEnvSafeTest.h"
 #include "test/UnitTest/FPMatcher.h"
@@ -18,16 +19,19 @@ using LIBC_NAMESPACE::fputil::greater_than_or_equals;
 using LIBC_NAMESPACE::fputil::less_than;
 using LIBC_NAMESPACE::fputil::less_than_or_equals;
 
+using BFloat16 = LIBC_NAMESPACE::fputil::BFloat16;
+
 template <typename T>
 class ComparisonOperationsTest : public LIBC_NAMESPACE::testing::FEnvSafeTest {
   DECLARE_SPECIAL_CONSTANTS(T)
 
-  static constexpr T normal1 = T(3.14);
-  static constexpr T normal2 = T(2.71);
-  static constexpr T small = T(0.1);
-  static constexpr T neg_small = T(-0.1);
-  static constexpr T large = T(10000.0);
-  static constexpr T neg_large = T(-10000.0);
+  const T normal1 = T(3.14);
+  const T neg_normal1 = T(-3.14);
+  const T normal2 = T(2.71);
+  const T small = T(0.1);
+  const T neg_small = T(-0.1);
+  const T large = T(10000.0);
+  const T neg_large = T(-10000.0);
 
 public:
   void test_equals() {
@@ -43,7 +47,7 @@ class ComparisonOperationsTest : public LIBC_NAMESPACE::testing::FEnvSafeTest {
     EXPECT_TRUE(equals(normal1, normal1));
     EXPECT_TRUE(equals(normal2, normal2));
     EXPECT_FALSE(equals(normal1, normal2));
-    EXPECT_FALSE(equals(normal1, -normal1));
+    EXPECT_FALSE(equals(normal1, neg_normal1));
 
     auto test_qnan = [&](T x, T y) {
       LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);
@@ -329,3 +333,5 @@ TEST_COMPARISON_OPS(Float16, float16)
 #ifdef LIBC_TYPES_HAS_FLOAT128
 TEST_COMPARISON_OPS(Float128, float128)
 #endif // LIBC_TYPES_HAS_FLOAT128
+
+TEST_COMPARISON_OPS(BFloat16, BFloat16)

>From 06685584ae69897278fc6bb4b0b9152ef284e083 Mon Sep 17 00:00:00 2001
From: Krishna Pandey <kpandey81930 at gmail.com>
Date: Fri, 11 Jul 2025 20:02:54 +0530
Subject: [PATCH 23/30] fix: comparison tests for bfloat16

Signed-off-by: Krishna Pandey <kpandey81930 at gmail.com>
---
 .../FPUtil/comparison_operations_test.cpp     | 27 ++++++++++++++-----
 1 file changed, 20 insertions(+), 7 deletions(-)

diff --git a/libc/test/src/__support/FPUtil/comparison_operations_test.cpp b/libc/test/src/__support/FPUtil/comparison_operations_test.cpp
index 5f278fe15adde..5196cd969829d 100644
--- a/libc/test/src/__support/FPUtil/comparison_operations_test.cpp
+++ b/libc/test/src/__support/FPUtil/comparison_operations_test.cpp
@@ -25,15 +25,27 @@ template <typename T>
 class ComparisonOperationsTest : public LIBC_NAMESPACE::testing::FEnvSafeTest {
   DECLARE_SPECIAL_CONSTANTS(T)
 
-  const T normal1 = T(3.14);
-  const T neg_normal1 = T(-3.14);
-  const T normal2 = T(2.71);
-  const T small = T(0.1);
-  const T neg_small = T(-0.1);
-  const T large = T(10000.0);
-  const T neg_large = T(-10000.0);
+  T normal1;
+  T neg_normal1;
+  T normal2;
+  T small;
+  T neg_small;
+  T large;
+  T neg_large;
 
 public:
+  void SetUp() override {
+    with_fenv_preserved([this]() {
+      normal1 = T(3.14);
+      neg_normal1 = T(-3.14);
+      normal2 = T(2.71);
+      small = T(0.1);
+      neg_small = T(-0.1);
+      large = T(10000.0);
+      neg_large = T(-10000.0);
+    });
+  }
+
   void test_equals() {
     EXPECT_TRUE(equals(neg_zero, neg_zero));
     EXPECT_TRUE(equals(zero, neg_zero));
@@ -71,6 +83,7 @@ class ComparisonOperationsTest : public LIBC_NAMESPACE::testing::FEnvSafeTest {
       LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);
       EXPECT_FALSE(equals(x, y));
       EXPECT_FP_EXCEPTION(FE_INVALID);
+      LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);
     };
 
     test_snan(sNaN, sNaN);

>From 386da5682f018c5fc0a0e29c6f7a4a94509e4391 Mon Sep 17 00:00:00 2001
From: Krishna Pandey <kpandey81930 at gmail.com>
Date: Fri, 11 Jul 2025 21:08:58 +0530
Subject: [PATCH 24/30] fix: make bfloat16 compatible constexpr compatible

Signed-off-by: Krishna Pandey <kpandey81930 at gmail.com>
---
 libc/src/__support/FPUtil/bfloat16.h          |  5 +++-
 libc/src/__support/FPUtil/cast.h              |  3 ++-
 libc/src/__support/FPUtil/rounding_mode.h     |  6 ++++-
 .../FPUtil/comparison_operations_test.cpp     | 25 ++++++-------------
 4 files changed, 18 insertions(+), 21 deletions(-)

diff --git a/libc/src/__support/FPUtil/bfloat16.h b/libc/src/__support/FPUtil/bfloat16.h
index bc0b8b23896fc..5cf7b51e8ad21 100644
--- a/libc/src/__support/FPUtil/bfloat16.h
+++ b/libc/src/__support/FPUtil/bfloat16.h
@@ -43,7 +43,10 @@ struct BFloat16 {
 
       fputil::DyadicFloat<cpp::numeric_limits<cpp::make_unsigned_t<T>>::digits>
           xd(sign, 0, value);
-      bits = xd.template as<bfloat16, /*ShouldSignalExceptions=*/true>().bits;
+      bits = xd.template as<
+                   bfloat16,
+                   /*ShouldSignalExceptions=*/!cpp::is_constant_evaluated()>()
+                 .bits;
 
     } else {
       bits = fputil::cast<bfloat16>(static_cast<float>(value)).bits;
diff --git a/libc/src/__support/FPUtil/cast.h b/libc/src/__support/FPUtil/cast.h
index e6fad1be7d053..595a0ecb53d29 100644
--- a/libc/src/__support/FPUtil/cast.h
+++ b/libc/src/__support/FPUtil/cast.h
@@ -65,7 +65,8 @@ cast(InType x) {
     constexpr size_t MAX_FRACTION_LEN =
         cpp::max(OutFPBits::FRACTION_LEN, InFPBits::FRACTION_LEN);
     DyadicFloat<cpp::bit_ceil(MAX_FRACTION_LEN)> xd(x);
-    return xd.template as<OutType, /*ShouldSignalExceptions=*/true>();
+    return xd.template as<
+        OutType, /*ShouldSignalExceptions=*/!cpp::is_constant_evaluated()>();
   }
 
   return static_cast<OutType>(x);
diff --git a/libc/src/__support/FPUtil/rounding_mode.h b/libc/src/__support/FPUtil/rounding_mode.h
index bc66d09b94160..12ccf33ea146f 100644
--- a/libc/src/__support/FPUtil/rounding_mode.h
+++ b/libc/src/__support/FPUtil/rounding_mode.h
@@ -10,6 +10,7 @@
 #define LLVM_LIBC_SRC___SUPPORT_FPUTIL_ROUNDING_MODE_H
 
 #include "hdr/fenv_macros.h"
+#include "src/__support/CPP/type_traits.h"
 #include "src/__support/macros/attributes.h" // LIBC_INLINE
 #include "src/__support/macros/config.h"
 
@@ -63,7 +64,10 @@ LIBC_INLINE bool fenv_is_round_to_zero() {
 }
 
 // Quick free standing get rounding mode based on the above observations.
-LIBC_INLINE int quick_get_round() {
+LIBC_INLINE constexpr int quick_get_round() {
+  if constexpr (cpp::is_constant_evaluated())
+    return FE_TONEAREST;
+
   static volatile float x = 0x1.0p-24f;
   float y = x;
   float z = (0x1.000002p0f + y) + (-1.0f - y);
diff --git a/libc/test/src/__support/FPUtil/comparison_operations_test.cpp b/libc/test/src/__support/FPUtil/comparison_operations_test.cpp
index 5196cd969829d..5580dd95f2656 100644
--- a/libc/test/src/__support/FPUtil/comparison_operations_test.cpp
+++ b/libc/test/src/__support/FPUtil/comparison_operations_test.cpp
@@ -25,26 +25,15 @@ template <typename T>
 class ComparisonOperationsTest : public LIBC_NAMESPACE::testing::FEnvSafeTest {
   DECLARE_SPECIAL_CONSTANTS(T)
 
-  T normal1;
-  T neg_normal1;
-  T normal2;
-  T small;
-  T neg_small;
-  T large;
-  T neg_large;
+  static constexpr T normal1 = T(3.14);
+  static constexpr T neg_normal1 = T(-3.14);
+  static constexpr T normal2 = T(2.71);
+  static constexpr T small = T(0.1);
+  static constexpr T neg_small = T(-0.1);
+  static constexpr T large = T(10000.0);
+  static constexpr T neg_large = T(-10000.0);
 
 public:
-  void SetUp() override {
-    with_fenv_preserved([this]() {
-      normal1 = T(3.14);
-      neg_normal1 = T(-3.14);
-      normal2 = T(2.71);
-      small = T(0.1);
-      neg_small = T(-0.1);
-      large = T(10000.0);
-      neg_large = T(-10000.0);
-    });
-  }
 
   void test_equals() {
     EXPECT_TRUE(equals(neg_zero, neg_zero));

>From 831c609d7199f0a4065aa7b492ceb72d1f13a4ec Mon Sep 17 00:00:00 2001
From: Krishna Pandey <kpandey81930 at gmail.com>
Date: Fri, 11 Jul 2025 21:47:16 +0530
Subject: [PATCH 25/30] chore: clang-format

Signed-off-by: Krishna Pandey <kpandey81930 at gmail.com>
---
 libc/test/src/__support/FPUtil/comparison_operations_test.cpp | 1 -
 1 file changed, 1 deletion(-)

diff --git a/libc/test/src/__support/FPUtil/comparison_operations_test.cpp b/libc/test/src/__support/FPUtil/comparison_operations_test.cpp
index 5580dd95f2656..9c5b5ac4cacd1 100644
--- a/libc/test/src/__support/FPUtil/comparison_operations_test.cpp
+++ b/libc/test/src/__support/FPUtil/comparison_operations_test.cpp
@@ -34,7 +34,6 @@ class ComparisonOperationsTest : public LIBC_NAMESPACE::testing::FEnvSafeTest {
   static constexpr T neg_large = T(-10000.0);
 
 public:
-
   void test_equals() {
     EXPECT_TRUE(equals(neg_zero, neg_zero));
     EXPECT_TRUE(equals(zero, neg_zero));

>From 02098dfd5090ab00c6065a4ade440b5ad136ac01 Mon Sep 17 00:00:00 2001
From: Krishna Pandey <kpandey81930 at gmail.com>
Date: Fri, 11 Jul 2025 21:48:00 +0530
Subject: [PATCH 26/30] chore: add missing CMake dependency

Co-authored-by: OverMighty <its.overmighty at gmail.com>
---
 libc/test/src/__support/FPUtil/CMakeLists.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/libc/test/src/__support/FPUtil/CMakeLists.txt b/libc/test/src/__support/FPUtil/CMakeLists.txt
index 3c6a392b87daf..9ac0882fe45f6 100644
--- a/libc/test/src/__support/FPUtil/CMakeLists.txt
+++ b/libc/test/src/__support/FPUtil/CMakeLists.txt
@@ -57,6 +57,7 @@ add_fp_unittest(
   SRCS
     comparison_operations_test.cpp
   DEPENDS
+    libc.src.__support.FPUtil.bfloat16
     libc.src.__support.FPUtil.comparison_operations
     libc.src.__support.FPUtil.fp_bits
     libc.src.__support.macros.properties.types

>From c89020ae79c6531194c4d8415d8949d983264989 Mon Sep 17 00:00:00 2001
From: Krishna Pandey <kpandey81930 at gmail.com>
Date: Fri, 11 Jul 2025 21:52:16 +0530
Subject: [PATCH 27/30] fix: add pragma to suppress C++23 warnings

Signed-off-by: Krishna Pandey <kpandey81930 at gmail.com>
---
 libc/src/__support/FPUtil/rounding_mode.h | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/libc/src/__support/FPUtil/rounding_mode.h b/libc/src/__support/FPUtil/rounding_mode.h
index 12ccf33ea146f..b867b0a70fbb3 100644
--- a/libc/src/__support/FPUtil/rounding_mode.h
+++ b/libc/src/__support/FPUtil/rounding_mode.h
@@ -63,6 +63,14 @@ LIBC_INLINE bool fenv_is_round_to_zero() {
   return ((0x1.000002p0f + y) + (-1.0f - y) == 0x1.0p-23f);
 }
 
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wc++23-extensions"
+#elif defined(__GNUC__)
+#pragma gcc diagnostic push
+#pragma gcc diagnostic ignored "-Wc++23-extensions"
+#endif
+
 // Quick free standing get rounding mode based on the above observations.
 LIBC_INLINE constexpr int quick_get_round() {
   if constexpr (cpp::is_constant_evaluated())
@@ -79,6 +87,12 @@ LIBC_INLINE constexpr int quick_get_round() {
   return (2.0f + y == 2.0f) ? FE_TONEAREST : FE_UPWARD;
 }
 
+#ifdef __clang__
+#pragma clang diagnostic pop
+#elif defined(__GNUC__)
+#pragma gcc diagnostic pop
+#endif
+
 } // namespace fputil
 } // namespace LIBC_NAMESPACE_DECL
 

>From 904bde69e1e7bd0b0ca2216d9dfd1aa6d5827bc0 Mon Sep 17 00:00:00 2001
From: Krishna Pandey <kpandey81930 at gmail.com>
Date: Fri, 11 Jul 2025 22:40:09 +0530
Subject: [PATCH 28/30] fix: revert quick_get_round() changes

Signed-off-by: Krishna Pandey <kpandey81930 at gmail.com>
---
 libc/src/__support/FPUtil/rounding_mode.h | 19 +------------------
 1 file changed, 1 insertion(+), 18 deletions(-)

diff --git a/libc/src/__support/FPUtil/rounding_mode.h b/libc/src/__support/FPUtil/rounding_mode.h
index b867b0a70fbb3..5be9190b808f1 100644
--- a/libc/src/__support/FPUtil/rounding_mode.h
+++ b/libc/src/__support/FPUtil/rounding_mode.h
@@ -63,19 +63,8 @@ LIBC_INLINE bool fenv_is_round_to_zero() {
   return ((0x1.000002p0f + y) + (-1.0f - y) == 0x1.0p-23f);
 }
 
-#ifdef __clang__
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wc++23-extensions"
-#elif defined(__GNUC__)
-#pragma gcc diagnostic push
-#pragma gcc diagnostic ignored "-Wc++23-extensions"
-#endif
-
 // Quick free standing get rounding mode based on the above observations.
-LIBC_INLINE constexpr int quick_get_round() {
-  if constexpr (cpp::is_constant_evaluated())
-    return FE_TONEAREST;
-
+LIBC_INLINE int quick_get_round() {
   static volatile float x = 0x1.0p-24f;
   float y = x;
   float z = (0x1.000002p0f + y) + (-1.0f - y);
@@ -87,12 +76,6 @@ LIBC_INLINE constexpr int quick_get_round() {
   return (2.0f + y == 2.0f) ? FE_TONEAREST : FE_UPWARD;
 }
 
-#ifdef __clang__
-#pragma clang diagnostic pop
-#elif defined(__GNUC__)
-#pragma gcc diagnostic pop
-#endif
-
 } // namespace fputil
 } // namespace LIBC_NAMESPACE_DECL
 

>From 6140e0d1f5154c57e1b11ee822b5f59dfefe53ea Mon Sep 17 00:00:00 2001
From: Krishna Pandey <kpandey81930 at gmail.com>
Date: Fri, 11 Jul 2025 22:48:24 +0530
Subject: [PATCH 29/30] chore: add guards against quick_get_round in constant
 evaluation mode

Signed-off-by: Krishna Pandey <kpandey81930 at gmail.com>
---
 libc/src/__support/FPUtil/dyadic_float.h | 76 ++++++++++++------------
 1 file changed, 39 insertions(+), 37 deletions(-)

diff --git a/libc/src/__support/FPUtil/dyadic_float.h b/libc/src/__support/FPUtil/dyadic_float.h
index 3464e4aa9423f..56ffa04286a1d 100644
--- a/libc/src/__support/FPUtil/dyadic_float.h
+++ b/libc/src/__support/FPUtil/dyadic_float.h
@@ -184,29 +184,30 @@ template <size_t Bits> struct DyadicFloat {
 
     int unbiased_exp = get_unbiased_exponent();
 
-    if (unbiased_exp + FPBits::EXP_BIAS >= FPBits::MAX_BIASED_EXPONENT) {
-      if constexpr (ShouldSignalExceptions) {
-        set_errno_if_required(ERANGE);
-        raise_except_if_required(FE_OVERFLOW | FE_INEXACT);
-      }
+    if constexpr (!cpp::is_constant_evaluated())
+      if (unbiased_exp + FPBits::EXP_BIAS >= FPBits::MAX_BIASED_EXPONENT) {
+        if constexpr (ShouldSignalExceptions) {
+          set_errno_if_required(ERANGE);
+          raise_except_if_required(FE_OVERFLOW | FE_INEXACT);
+        }
 
-      switch (quick_get_round()) {
-      case FE_TONEAREST:
-        return FPBits::inf(sign).get_val();
-      case FE_TOWARDZERO:
-        return FPBits::max_normal(sign).get_val();
-      case FE_DOWNWARD:
-        if (sign.is_pos())
-          return FPBits::max_normal(Sign::POS).get_val();
-        return FPBits::inf(Sign::NEG).get_val();
-      case FE_UPWARD:
-        if (sign.is_neg())
-          return FPBits::max_normal(Sign::NEG).get_val();
-        return FPBits::inf(Sign::POS).get_val();
-      default:
-        __builtin_unreachable();
+        switch (quick_get_round()) {
+        case FE_TONEAREST:
+          return FPBits::inf(sign).get_val();
+        case FE_TOWARDZERO:
+          return FPBits::max_normal(sign).get_val();
+        case FE_DOWNWARD:
+          if (sign.is_pos())
+            return FPBits::max_normal(Sign::POS).get_val();
+          return FPBits::inf(Sign::NEG).get_val();
+        case FE_UPWARD:
+          if (sign.is_neg())
+            return FPBits::max_normal(Sign::NEG).get_val();
+          return FPBits::inf(Sign::POS).get_val();
+        default:
+          __builtin_unreachable();
+        }
       }
-    }
 
     StorageType out_biased_exp = 0;
     StorageType out_mantissa = 0;
@@ -245,22 +246,23 @@ template <size_t Bits> struct DyadicFloat {
     StorageType result =
         FPBits::create_value(sign, out_biased_exp, out_mantissa).uintval();
 
-    switch (quick_get_round()) {
-    case FE_TONEAREST:
-      if (round && (lsb || sticky))
-        ++result;
-      break;
-    case FE_DOWNWARD:
-      if (sign.is_neg() && (round || sticky))
-        ++result;
-      break;
-    case FE_UPWARD:
-      if (sign.is_pos() && (round || sticky))
-        ++result;
-      break;
-    default:
-      break;
-    }
+    if constexpr (!cpp::is_constant_evaluated())
+      switch (quick_get_round()) {
+      case FE_TONEAREST:
+        if (round && (lsb || sticky))
+          ++result;
+        break;
+      case FE_DOWNWARD:
+        if (sign.is_neg() && (round || sticky))
+          ++result;
+        break;
+      case FE_UPWARD:
+        if (sign.is_pos() && (round || sticky))
+          ++result;
+        break;
+      default:
+        break;
+      }
 
     if (ShouldSignalExceptions && (round || sticky)) {
       int excepts = FE_INEXACT;

>From 98808e7b6f22711ddced9dbb4a73eccbbc2e8680 Mon Sep 17 00:00:00 2001
From: Krishna Pandey <kpandey81930 at gmail.com>
Date: Sat, 12 Jul 2025 07:38:22 +0530
Subject: [PATCH 30/30] chore: few changes

Co-authored-by: OverMighty <its.overmighty at gmail.com>
---
 libc/src/__support/FPUtil/dyadic_float.h      | 12 +++++++++---
 libc/test/src/__support/FPUtil/CMakeLists.txt |  2 --
 2 files changed, 9 insertions(+), 5 deletions(-)

diff --git a/libc/src/__support/FPUtil/dyadic_float.h b/libc/src/__support/FPUtil/dyadic_float.h
index 56ffa04286a1d..aa9691935ed53 100644
--- a/libc/src/__support/FPUtil/dyadic_float.h
+++ b/libc/src/__support/FPUtil/dyadic_float.h
@@ -184,14 +184,17 @@ template <size_t Bits> struct DyadicFloat {
 
     int unbiased_exp = get_unbiased_exponent();
 
-    if constexpr (!cpp::is_constant_evaluated())
       if (unbiased_exp + FPBits::EXP_BIAS >= FPBits::MAX_BIASED_EXPONENT) {
         if constexpr (ShouldSignalExceptions) {
           set_errno_if_required(ERANGE);
           raise_except_if_required(FE_OVERFLOW | FE_INEXACT);
         }
 
-        switch (quick_get_round()) {
+      int rounding_mode = FE_TONEAREST;
+      if constexpr (!cpp::is_constant_evaluated())
+        rounding_mode = quick_get_round();
+
+      switch (rounding_mode) {
         case FE_TONEAREST:
           return FPBits::inf(sign).get_val();
         case FE_TOWARDZERO:
@@ -246,8 +249,11 @@ template <size_t Bits> struct DyadicFloat {
     StorageType result =
         FPBits::create_value(sign, out_biased_exp, out_mantissa).uintval();
 
+    int rounding_mode = FE_TONEAREST;
     if constexpr (!cpp::is_constant_evaluated())
-      switch (quick_get_round()) {
+      rounding_mode = quick_get_round();
+
+    switch (rounding_mode) {
       case FE_TONEAREST:
         if (round && (lsb || sticky))
           ++result;
diff --git a/libc/test/src/__support/FPUtil/CMakeLists.txt b/libc/test/src/__support/FPUtil/CMakeLists.txt
index 9ac0882fe45f6..d2a6dfdfac580 100644
--- a/libc/test/src/__support/FPUtil/CMakeLists.txt
+++ b/libc/test/src/__support/FPUtil/CMakeLists.txt
@@ -59,7 +59,5 @@ add_fp_unittest(
   DEPENDS
     libc.src.__support.FPUtil.bfloat16
     libc.src.__support.FPUtil.comparison_operations
-    libc.src.__support.FPUtil.fp_bits
     libc.src.__support.macros.properties.types
-    libc.src.__support.sign
 )



More information about the libc-commits mailing list