[libc-commits] [libc] db936e0 - [libc][NFC] Add library of floating point test matchers.

Siva Chandra Reddy via libc-commits libc-commits at lists.llvm.org
Fri Aug 7 23:34:30 PDT 2020


Author: Siva Chandra Reddy
Date: 2020-08-07T23:34:15-07:00
New Revision: db936e0e915377a58032dccc13bedbfccf0a1ca8

URL: https://github.com/llvm/llvm-project/commit/db936e0e915377a58032dccc13bedbfccf0a1ca8
DIFF: https://github.com/llvm/llvm-project/commit/db936e0e915377a58032dccc13bedbfccf0a1ca8.diff

LOG: [libc][NFC] Add library of floating point test matchers.

This eliminates UnitTest's dependency on FPUtil and hence prevents
non-math tests from depending indirectly on FPUtil. The patch
essentially moves some of the existing pieces into a library of its own.

Along the way, renamed add_math_unittest to add_fp_unittest.

Reviewed By: lntue

Differential Revision: https://reviews.llvm.org/D85486

Added: 
    libc/utils/FPUtil/TestHelpers.cpp
    libc/utils/FPUtil/TestHelpers.h

Modified: 
    libc/test/src/math/CMakeLists.txt
    libc/test/src/math/fmax_test.cpp
    libc/test/src/math/fmaxf_test.cpp
    libc/test/src/math/fmaxl_test.cpp
    libc/test/src/math/fmin_test.cpp
    libc/test/src/math/fminf_test.cpp
    libc/test/src/math/fminl_test.cpp
    libc/utils/FPUtil/CMakeLists.txt
    libc/utils/UnitTest/Test.cpp
    libc/utils/UnitTest/Test.h

Removed: 
    


################################################################################
diff  --git a/libc/test/src/math/CMakeLists.txt b/libc/test/src/math/CMakeLists.txt
index 3bd40f6b32f1..f5a1e0e51a71 100644
--- a/libc/test/src/math/CMakeLists.txt
+++ b/libc/test/src/math/CMakeLists.txt
@@ -1,6 +1,6 @@
 add_libc_testsuite(libc_math_unittests)
 
-function(add_math_unittest name)
+function(add_fp_unittest name)
   cmake_parse_arguments(
     "MATH_UNITTEST"
     "NEED_MPFR" # No optional arguments
@@ -17,13 +17,14 @@ function(add_math_unittest name)
   endif()
 
   add_libc_unittest(${name} ${MATH_UNITTEST_UNPARSED_ARGUMENTS})
+  get_fq_target_name(${name} fq_target_name)
+  target_link_libraries(${fq_target_name} PRIVATE LibcFPTestHelpers)
   if(MATH_UNITTEST_NEED_MPFR)
-    get_fq_target_name(${name} fq_target_name)
     target_link_libraries(${fq_target_name} PRIVATE libcMPFRWrapper -lmpfr -lgmp)
   endif()
-endfunction(add_math_unittest)
+endfunction(add_fp_unittest)
 
-add_math_unittest(
+add_fp_unittest(
   cosf_test
   NEED_MPFR
   SUITE
@@ -39,7 +40,7 @@ add_math_unittest(
     libc.utils.FPUtil.fputil
 )
 
-add_math_unittest(
+add_fp_unittest(
   sinf_test
   NEED_MPFR
   SUITE
@@ -55,7 +56,7 @@ add_math_unittest(
     libc.utils.FPUtil.fputil
 )
 
-add_math_unittest(
+add_fp_unittest(
   sincosf_test
   NEED_MPFR
   SUITE
@@ -71,7 +72,7 @@ add_math_unittest(
     libc.utils.FPUtil.fputil
 )
 
-add_math_unittest(
+add_fp_unittest(
   fabs_test
   NEED_MPFR
   SUITE
@@ -84,7 +85,7 @@ add_math_unittest(
     libc.utils.FPUtil.fputil
 )
 
-add_math_unittest(
+add_fp_unittest(
   fabsf_test
   NEED_MPFR
   SUITE
@@ -97,7 +98,7 @@ add_math_unittest(
     libc.utils.FPUtil.fputil
 )
 
-add_math_unittest(
+add_fp_unittest(
   fabsl_test
   NEED_MPFR
   SUITE
@@ -110,7 +111,7 @@ add_math_unittest(
     libc.utils.FPUtil.fputil
 )
 
-add_math_unittest(
+add_fp_unittest(
   trunc_test
   NEED_MPFR
   SUITE
@@ -123,7 +124,7 @@ add_math_unittest(
     libc.utils.FPUtil.fputil
 )
 
-add_math_unittest(
+add_fp_unittest(
   truncf_test
   NEED_MPFR
   SUITE
@@ -136,7 +137,7 @@ add_math_unittest(
     libc.utils.FPUtil.fputil
 )
 
-add_math_unittest(
+add_fp_unittest(
   truncl_test
   NEED_MPFR
   SUITE
@@ -149,7 +150,7 @@ add_math_unittest(
     libc.utils.FPUtil.fputil
 )
 
-add_math_unittest(
+add_fp_unittest(
   ceil_test
   NEED_MPFR
   SUITE
@@ -162,7 +163,7 @@ add_math_unittest(
     libc.utils.FPUtil.fputil
 )
 
-add_math_unittest(
+add_fp_unittest(
   ceilf_test
   NEED_MPFR
   SUITE
@@ -175,7 +176,7 @@ add_math_unittest(
     libc.utils.FPUtil.fputil
 )
 
-add_math_unittest(
+add_fp_unittest(
   ceill_test
   NEED_MPFR
   SUITE
@@ -188,7 +189,7 @@ add_math_unittest(
     libc.utils.FPUtil.fputil
 )
 
-add_math_unittest(
+add_fp_unittest(
   floor_test
   NEED_MPFR
   SUITE
@@ -201,7 +202,7 @@ add_math_unittest(
     libc.utils.FPUtil.fputil
 )
 
-add_math_unittest(
+add_fp_unittest(
   floorf_test
   NEED_MPFR
   SUITE
@@ -214,7 +215,7 @@ add_math_unittest(
     libc.utils.FPUtil.fputil
 )
 
-add_math_unittest(
+add_fp_unittest(
   floorl_test
   NEED_MPFR
   SUITE
@@ -227,7 +228,7 @@ add_math_unittest(
     libc.utils.FPUtil.fputil
 )
 
-add_math_unittest(
+add_fp_unittest(
   round_test
   NEED_MPFR
   SUITE
@@ -240,7 +241,7 @@ add_math_unittest(
     libc.utils.FPUtil.fputil
 )
 
-add_math_unittest(
+add_fp_unittest(
   roundf_test
   NEED_MPFR
   SUITE
@@ -253,7 +254,7 @@ add_math_unittest(
     libc.utils.FPUtil.fputil
 )
 
-add_math_unittest(
+add_fp_unittest(
   roundl_test
   NEED_MPFR
   SUITE
@@ -266,7 +267,7 @@ add_math_unittest(
     libc.utils.FPUtil.fputil
 )
 
-add_math_unittest(
+add_fp_unittest(
   expf_test
   NEED_MPFR
   SUITE
@@ -280,7 +281,7 @@ add_math_unittest(
     libc.utils.FPUtil.fputil
 )
 
-add_math_unittest(
+add_fp_unittest(
   exp2f_test
   NEED_MPFR
   SUITE
@@ -294,7 +295,7 @@ add_math_unittest(
     libc.utils.FPUtil.fputil
 )
 
-add_math_unittest(
+add_fp_unittest(
   copysign_test
   SUITE
     libc_math_unittests
@@ -306,7 +307,7 @@ add_math_unittest(
     libc.utils.FPUtil.fputil
 )
 
-add_math_unittest(
+add_fp_unittest(
   copysignf_test
   SUITE
     libc_math_unittests
@@ -318,7 +319,7 @@ add_math_unittest(
     libc.utils.FPUtil.fputil
 )
 
-add_math_unittest(
+add_fp_unittest(
   copysignl_test
   SUITE
     libc_math_unittests
@@ -330,7 +331,7 @@ add_math_unittest(
     libc.utils.FPUtil.fputil
 )
 
-add_math_unittest(
+add_fp_unittest(
   frexp_test
   SUITE
     libc_math_unittests
@@ -342,7 +343,7 @@ add_math_unittest(
     libc.utils.FPUtil.fputil
 )
 
-add_math_unittest(
+add_fp_unittest(
   frexpf_test
   SUITE
     libc_math_unittests
@@ -354,7 +355,7 @@ add_math_unittest(
     libc.utils.FPUtil.fputil
 )
 
-add_math_unittest(
+add_fp_unittest(
   frexpl_test
   SUITE
     libc_math_unittests
@@ -366,7 +367,7 @@ add_math_unittest(
     libc.utils.FPUtil.fputil
 )
 
-add_math_unittest(
+add_fp_unittest(
   logb_test
   SUITE
     libc_math_unittests
@@ -378,7 +379,7 @@ add_math_unittest(
     libc.utils.FPUtil.fputil
 )
 
-add_math_unittest(
+add_fp_unittest(
   logbf_test
   SUITE
     libc_math_unittests
@@ -390,7 +391,7 @@ add_math_unittest(
     libc.utils.FPUtil.fputil
 )
 
-add_math_unittest(
+add_fp_unittest(
   logbl_test
   SUITE
     libc_math_unittests
@@ -402,7 +403,7 @@ add_math_unittest(
     libc.utils.FPUtil.fputil
 )
 
-add_math_unittest(
+add_fp_unittest(
   modf_test
   SUITE
     libc_math_unittests
@@ -414,7 +415,7 @@ add_math_unittest(
     libc.utils.FPUtil.fputil
 )
 
-add_math_unittest(
+add_fp_unittest(
   modff_test
   SUITE
     libc_math_unittests
@@ -426,7 +427,7 @@ add_math_unittest(
     libc.utils.FPUtil.fputil
 )
 
-add_math_unittest(
+add_fp_unittest(
   modfl_test
   SUITE
     libc_math_unittests
@@ -438,7 +439,7 @@ add_math_unittest(
     libc.utils.FPUtil.fputil
 )
 
-add_math_unittest(
+add_fp_unittest(
   fminf_test
   SUITE
     libc_math_unittests
@@ -450,7 +451,7 @@ add_math_unittest(
     libc.utils.FPUtil.fputil
 )
 
-add_math_unittest(
+add_fp_unittest(
   fmin_test
   SUITE
     libc_math_unittests
@@ -462,7 +463,7 @@ add_math_unittest(
     libc.utils.FPUtil.fputil
 )
 
-add_math_unittest(
+add_fp_unittest(
   fminl_test
   SUITE
     libc_math_unittests
@@ -474,7 +475,7 @@ add_math_unittest(
     libc.utils.FPUtil.fputil
 )
 
-add_math_unittest(
+add_fp_unittest(
   fmaxf_test
   SUITE
     libc_math_unittests
@@ -486,7 +487,7 @@ add_math_unittest(
     libc.utils.FPUtil.fputil
 )
 
-add_math_unittest(
+add_fp_unittest(
   fmax_test
   SUITE
     libc_math_unittests
@@ -498,7 +499,7 @@ add_math_unittest(
     libc.utils.FPUtil.fputil
 )
 
-add_math_unittest(
+add_fp_unittest(
   fmaxl_test
   SUITE
     libc_math_unittests

diff  --git a/libc/test/src/math/fmax_test.cpp b/libc/test/src/math/fmax_test.cpp
index 8d1c6c276382..0dc57e4290fc 100644
--- a/libc/test/src/math/fmax_test.cpp
+++ b/libc/test/src/math/fmax_test.cpp
@@ -9,6 +9,7 @@
 #include "include/math.h"
 #include "src/math/fmax.h"
 #include "utils/FPUtil/FPBits.h"
+#include "utils/FPUtil/TestHelpers.h"
 #include "utils/UnitTest/Test.h"
 
 using FPBits = __llvm_libc::fputil::FPBits<double>;
@@ -18,36 +19,36 @@ double inf = FPBits::inf();
 double negInf = FPBits::negInf();
 
 TEST(FmaxTest, NaNArg) {
-  EXPECT_EQ(inf, __llvm_libc::fmax(nan, inf));
-  EXPECT_EQ(negInf, __llvm_libc::fmax(negInf, nan));
-  EXPECT_EQ(0.0, __llvm_libc::fmax(nan, 0.0));
-  EXPECT_EQ(-0.0, __llvm_libc::fmax(-0.0, nan));
-  EXPECT_EQ(-1.2345, __llvm_libc::fmax(nan, -1.2345));
-  EXPECT_EQ(1.2345, __llvm_libc::fmax(1.2345, nan));
+  EXPECT_FP_EQ(inf, __llvm_libc::fmax(nan, inf));
+  EXPECT_FP_EQ(negInf, __llvm_libc::fmax(negInf, nan));
+  EXPECT_FP_EQ(0.0, __llvm_libc::fmax(nan, 0.0));
+  EXPECT_FP_EQ(-0.0, __llvm_libc::fmax(-0.0, nan));
+  EXPECT_FP_EQ(-1.2345, __llvm_libc::fmax(nan, -1.2345));
+  EXPECT_FP_EQ(1.2345, __llvm_libc::fmax(1.2345, nan));
   EXPECT_NE(isnan(__llvm_libc::fmax(nan, nan)), 0);
 }
 
 TEST(FmaxTest, InfArg) {
-  EXPECT_EQ(inf, __llvm_libc::fmax(negInf, inf));
-  EXPECT_EQ(inf, __llvm_libc::fmax(inf, 0.0));
-  EXPECT_EQ(inf, __llvm_libc::fmax(-0.0, inf));
-  EXPECT_EQ(inf, __llvm_libc::fmax(inf, 1.2345));
-  EXPECT_EQ(inf, __llvm_libc::fmax(-1.2345, inf));
+  EXPECT_FP_EQ(inf, __llvm_libc::fmax(negInf, inf));
+  EXPECT_FP_EQ(inf, __llvm_libc::fmax(inf, 0.0));
+  EXPECT_FP_EQ(inf, __llvm_libc::fmax(-0.0, inf));
+  EXPECT_FP_EQ(inf, __llvm_libc::fmax(inf, 1.2345));
+  EXPECT_FP_EQ(inf, __llvm_libc::fmax(-1.2345, inf));
 }
 
 TEST(FmaxTest, NegInfArg) {
-  EXPECT_EQ(inf, __llvm_libc::fmax(inf, negInf));
-  EXPECT_EQ(0.0, __llvm_libc::fmax(negInf, 0.0));
-  EXPECT_EQ(-0.0, __llvm_libc::fmax(-0.0, negInf));
-  EXPECT_EQ(-1.2345, __llvm_libc::fmax(negInf, -1.2345));
-  EXPECT_EQ(1.2345, __llvm_libc::fmax(1.2345, negInf));
+  EXPECT_FP_EQ(inf, __llvm_libc::fmax(inf, negInf));
+  EXPECT_FP_EQ(0.0, __llvm_libc::fmax(negInf, 0.0));
+  EXPECT_FP_EQ(-0.0, __llvm_libc::fmax(-0.0, negInf));
+  EXPECT_FP_EQ(-1.2345, __llvm_libc::fmax(negInf, -1.2345));
+  EXPECT_FP_EQ(1.2345, __llvm_libc::fmax(1.2345, negInf));
 }
 
 TEST(FmaxTest, BothZero) {
-  EXPECT_EQ(0.0, __llvm_libc::fmax(0.0, 0.0));
-  EXPECT_EQ(0.0, __llvm_libc::fmax(-0.0, 0.0));
-  EXPECT_EQ(0.0, __llvm_libc::fmax(0.0, -0.0));
-  EXPECT_EQ(-0.0, __llvm_libc::fmax(-0.0, -0.0));
+  EXPECT_FP_EQ(0.0, __llvm_libc::fmax(0.0, 0.0));
+  EXPECT_FP_EQ(0.0, __llvm_libc::fmax(-0.0, 0.0));
+  EXPECT_FP_EQ(0.0, __llvm_libc::fmax(0.0, -0.0));
+  EXPECT_FP_EQ(-0.0, __llvm_libc::fmax(-0.0, -0.0));
 }
 
 TEST(FmaxTest, InDoubleRange) {
@@ -65,9 +66,9 @@ TEST(FmaxTest, InDoubleRange) {
       continue;
 
     if (x > y) {
-      ASSERT_EQ(x, __llvm_libc::fmax(x, y));
+      EXPECT_FP_EQ(x, __llvm_libc::fmax(x, y));
     } else {
-      ASSERT_EQ(y, __llvm_libc::fmax(x, y));
+      EXPECT_FP_EQ(y, __llvm_libc::fmax(x, y));
     }
   }
 }

diff  --git a/libc/test/src/math/fmaxf_test.cpp b/libc/test/src/math/fmaxf_test.cpp
index fe9eaad171bd..fc8f1cc2512c 100644
--- a/libc/test/src/math/fmaxf_test.cpp
+++ b/libc/test/src/math/fmaxf_test.cpp
@@ -9,6 +9,7 @@
 #include "include/math.h"
 #include "src/math/fmaxf.h"
 #include "utils/FPUtil/FPBits.h"
+#include "utils/FPUtil/TestHelpers.h"
 #include "utils/UnitTest/Test.h"
 
 using FPBits = __llvm_libc::fputil::FPBits<float>;
@@ -18,36 +19,36 @@ float inf = FPBits::inf();
 float negInf = FPBits::negInf();
 
 TEST(FmaxfTest, NaNArg) {
-  EXPECT_EQ(inf, __llvm_libc::fmaxf(nan, inf));
-  EXPECT_EQ(negInf, __llvm_libc::fmaxf(negInf, nan));
-  EXPECT_EQ(0.0f, __llvm_libc::fmaxf(nan, 0.0f));
-  EXPECT_EQ(-0.0f, __llvm_libc::fmaxf(-0.0f, nan));
-  EXPECT_EQ(-1.2345f, __llvm_libc::fmaxf(nan, -1.2345f));
-  EXPECT_EQ(1.2345f, __llvm_libc::fmaxf(1.2345f, nan));
+  EXPECT_FP_EQ(inf, __llvm_libc::fmaxf(nan, inf));
+  EXPECT_FP_EQ(negInf, __llvm_libc::fmaxf(negInf, nan));
+  EXPECT_FP_EQ(0.0f, __llvm_libc::fmaxf(nan, 0.0f));
+  EXPECT_FP_EQ(-0.0f, __llvm_libc::fmaxf(-0.0f, nan));
+  EXPECT_FP_EQ(-1.2345f, __llvm_libc::fmaxf(nan, -1.2345f));
+  EXPECT_FP_EQ(1.2345f, __llvm_libc::fmaxf(1.2345f, nan));
   EXPECT_NE(isnan(__llvm_libc::fmaxf(nan, nan)), 0);
 }
 
 TEST(FmaxfTest, InfArg) {
-  EXPECT_EQ(inf, __llvm_libc::fmaxf(negInf, inf));
-  EXPECT_EQ(inf, __llvm_libc::fmaxf(inf, 0.0f));
-  EXPECT_EQ(inf, __llvm_libc::fmaxf(-0.0f, inf));
-  EXPECT_EQ(inf, __llvm_libc::fmaxf(inf, 1.2345f));
-  EXPECT_EQ(inf, __llvm_libc::fmaxf(-1.2345f, inf));
+  EXPECT_FP_EQ(inf, __llvm_libc::fmaxf(negInf, inf));
+  EXPECT_FP_EQ(inf, __llvm_libc::fmaxf(inf, 0.0f));
+  EXPECT_FP_EQ(inf, __llvm_libc::fmaxf(-0.0f, inf));
+  EXPECT_FP_EQ(inf, __llvm_libc::fmaxf(inf, 1.2345f));
+  EXPECT_FP_EQ(inf, __llvm_libc::fmaxf(-1.2345f, inf));
 }
 
 TEST(FmaxfTest, NegInfArg) {
-  EXPECT_EQ(inf, __llvm_libc::fmaxf(inf, negInf));
-  EXPECT_EQ(0.0f, __llvm_libc::fmaxf(negInf, 0.0f));
-  EXPECT_EQ(-0.0f, __llvm_libc::fmaxf(-0.0f, negInf));
-  EXPECT_EQ(-1.2345f, __llvm_libc::fmaxf(negInf, -1.2345f));
-  EXPECT_EQ(1.2345f, __llvm_libc::fmaxf(1.2345f, negInf));
+  EXPECT_FP_EQ(inf, __llvm_libc::fmaxf(inf, negInf));
+  EXPECT_FP_EQ(0.0f, __llvm_libc::fmaxf(negInf, 0.0f));
+  EXPECT_FP_EQ(-0.0f, __llvm_libc::fmaxf(-0.0f, negInf));
+  EXPECT_FP_EQ(-1.2345f, __llvm_libc::fmaxf(negInf, -1.2345f));
+  EXPECT_FP_EQ(1.2345f, __llvm_libc::fmaxf(1.2345f, negInf));
 }
 
 TEST(FmaxfTest, BothZero) {
-  EXPECT_EQ(0.0f, __llvm_libc::fmaxf(0.0f, 0.0f));
-  EXPECT_EQ(0.0f, __llvm_libc::fmaxf(-0.0f, 0.0f));
-  EXPECT_EQ(0.0f, __llvm_libc::fmaxf(0.0f, -0.0f));
-  EXPECT_EQ(-0.0f, __llvm_libc::fmaxf(-0.0f, -0.0f));
+  EXPECT_FP_EQ(0.0f, __llvm_libc::fmaxf(0.0f, 0.0f));
+  EXPECT_FP_EQ(0.0f, __llvm_libc::fmaxf(-0.0f, 0.0f));
+  EXPECT_FP_EQ(0.0f, __llvm_libc::fmaxf(0.0f, -0.0f));
+  EXPECT_FP_EQ(-0.0f, __llvm_libc::fmaxf(-0.0f, -0.0f));
 }
 
 TEST(FmaxfTest, InFloatRange) {
@@ -65,9 +66,9 @@ TEST(FmaxfTest, InFloatRange) {
       continue;
 
     if (x > y) {
-      ASSERT_EQ(x, __llvm_libc::fmaxf(x, y));
+      ASSERT_FP_EQ(x, __llvm_libc::fmaxf(x, y));
     } else {
-      ASSERT_EQ(y, __llvm_libc::fmaxf(x, y));
+      ASSERT_FP_EQ(y, __llvm_libc::fmaxf(x, y));
     }
   }
 }

diff  --git a/libc/test/src/math/fmaxl_test.cpp b/libc/test/src/math/fmaxl_test.cpp
index 9c7aa21582eb..ac62899d1a96 100644
--- a/libc/test/src/math/fmaxl_test.cpp
+++ b/libc/test/src/math/fmaxl_test.cpp
@@ -9,6 +9,7 @@
 #include "include/math.h"
 #include "src/math/fmaxl.h"
 #include "utils/FPUtil/FPBits.h"
+#include "utils/FPUtil/TestHelpers.h"
 #include "utils/UnitTest/Test.h"
 
 using FPBits = __llvm_libc::fputil::FPBits<long double>;
@@ -18,36 +19,36 @@ long double inf = FPBits::inf();
 long double negInf = FPBits::negInf();
 
 TEST(FmaxlTest, NaNArg) {
-  EXPECT_EQ(inf, __llvm_libc::fmaxl(nan, inf));
-  EXPECT_EQ(negInf, __llvm_libc::fmaxl(negInf, nan));
-  EXPECT_EQ(0.0L, __llvm_libc::fmaxl(nan, 0.0L));
-  EXPECT_EQ(-0.0L, __llvm_libc::fmaxl(-0.0L, nan));
-  EXPECT_EQ(-1.2345L, __llvm_libc::fmaxl(nan, -1.2345L));
-  EXPECT_EQ(1.2345L, __llvm_libc::fmaxl(1.2345L, nan));
+  EXPECT_FP_EQ(inf, __llvm_libc::fmaxl(nan, inf));
+  EXPECT_FP_EQ(negInf, __llvm_libc::fmaxl(negInf, nan));
+  EXPECT_FP_EQ(0.0L, __llvm_libc::fmaxl(nan, 0.0L));
+  EXPECT_FP_EQ(-0.0L, __llvm_libc::fmaxl(-0.0L, nan));
+  EXPECT_FP_EQ(-1.2345L, __llvm_libc::fmaxl(nan, -1.2345L));
+  EXPECT_FP_EQ(1.2345L, __llvm_libc::fmaxl(1.2345L, nan));
   EXPECT_NE(isnan(__llvm_libc::fmaxl(nan, nan)), 0);
 }
 
 TEST(FmaxlTest, InfArg) {
-  EXPECT_EQ(inf, __llvm_libc::fmaxl(negInf, inf));
-  EXPECT_EQ(inf, __llvm_libc::fmaxl(inf, 0.0L));
-  EXPECT_EQ(inf, __llvm_libc::fmaxl(-0.0L, inf));
-  EXPECT_EQ(inf, __llvm_libc::fmaxl(inf, 1.2345L));
-  EXPECT_EQ(inf, __llvm_libc::fmaxl(-1.2345L, inf));
+  EXPECT_FP_EQ(inf, __llvm_libc::fmaxl(negInf, inf));
+  EXPECT_FP_EQ(inf, __llvm_libc::fmaxl(inf, 0.0L));
+  EXPECT_FP_EQ(inf, __llvm_libc::fmaxl(-0.0L, inf));
+  EXPECT_FP_EQ(inf, __llvm_libc::fmaxl(inf, 1.2345L));
+  EXPECT_FP_EQ(inf, __llvm_libc::fmaxl(-1.2345L, inf));
 }
 
 TEST(FmaxlTest, NegInfArg) {
-  EXPECT_EQ(inf, __llvm_libc::fmaxl(inf, negInf));
-  EXPECT_EQ(0.0L, __llvm_libc::fmaxl(negInf, 0.0L));
-  EXPECT_EQ(-0.0L, __llvm_libc::fmaxl(-0.0L, negInf));
-  EXPECT_EQ(-1.2345L, __llvm_libc::fmaxl(negInf, -1.2345L));
-  EXPECT_EQ(1.2345L, __llvm_libc::fmaxl(1.2345L, negInf));
+  EXPECT_FP_EQ(inf, __llvm_libc::fmaxl(inf, negInf));
+  EXPECT_FP_EQ(0.0L, __llvm_libc::fmaxl(negInf, 0.0L));
+  EXPECT_FP_EQ(-0.0L, __llvm_libc::fmaxl(-0.0L, negInf));
+  EXPECT_FP_EQ(-1.2345L, __llvm_libc::fmaxl(negInf, -1.2345L));
+  EXPECT_FP_EQ(1.2345L, __llvm_libc::fmaxl(1.2345L, negInf));
 }
 
 TEST(FmaxlTest, BothZero) {
-  EXPECT_EQ(0.0L, __llvm_libc::fmaxl(0.0L, 0.0L));
-  EXPECT_EQ(0.0L, __llvm_libc::fmaxl(-0.0L, 0.0L));
-  EXPECT_EQ(0.0L, __llvm_libc::fmaxl(0.0L, -0.0L));
-  EXPECT_EQ(-0.0L, __llvm_libc::fmaxl(-0.0L, -0.0L));
+  EXPECT_FP_EQ(0.0L, __llvm_libc::fmaxl(0.0L, 0.0L));
+  EXPECT_FP_EQ(0.0L, __llvm_libc::fmaxl(-0.0L, 0.0L));
+  EXPECT_FP_EQ(0.0L, __llvm_libc::fmaxl(0.0L, -0.0L));
+  EXPECT_FP_EQ(-0.0L, __llvm_libc::fmaxl(-0.0L, -0.0L));
 }
 
 TEST(FmaxlTest, InLongDoubleRange) {
@@ -65,9 +66,9 @@ TEST(FmaxlTest, InLongDoubleRange) {
       continue;
 
     if (x > y) {
-      ASSERT_EQ(x, __llvm_libc::fmaxl(x, y));
+      ASSERT_FP_EQ(x, __llvm_libc::fmaxl(x, y));
     } else {
-      ASSERT_EQ(y, __llvm_libc::fmaxl(x, y));
+      ASSERT_FP_EQ(y, __llvm_libc::fmaxl(x, y));
     }
   }
 }

diff  --git a/libc/test/src/math/fmin_test.cpp b/libc/test/src/math/fmin_test.cpp
index 7fd1e8af1e51..47a4433f0c95 100644
--- a/libc/test/src/math/fmin_test.cpp
+++ b/libc/test/src/math/fmin_test.cpp
@@ -9,6 +9,7 @@
 #include "include/math.h"
 #include "src/math/fmin.h"
 #include "utils/FPUtil/FPBits.h"
+#include "utils/FPUtil/TestHelpers.h"
 #include "utils/UnitTest/Test.h"
 
 using FPBits = __llvm_libc::fputil::FPBits<double>;
@@ -18,36 +19,36 @@ double inf = static_cast<double>(FPBits::inf());
 double negInf = static_cast<double>(FPBits::negInf());
 
 TEST(FminTest, NaNArg) {
-  EXPECT_EQ(inf, __llvm_libc::fmin(nan, inf));
-  EXPECT_EQ(negInf, __llvm_libc::fmin(negInf, nan));
-  EXPECT_EQ(0.0, __llvm_libc::fmin(nan, 0.0));
-  EXPECT_EQ(-0.0, __llvm_libc::fmin(-0.0, nan));
-  EXPECT_EQ(-1.2345, __llvm_libc::fmin(nan, -1.2345));
-  EXPECT_EQ(1.2345, __llvm_libc::fmin(1.2345, nan));
+  EXPECT_FP_EQ(inf, __llvm_libc::fmin(nan, inf));
+  EXPECT_FP_EQ(negInf, __llvm_libc::fmin(negInf, nan));
+  EXPECT_FP_EQ(0.0, __llvm_libc::fmin(nan, 0.0));
+  EXPECT_FP_EQ(-0.0, __llvm_libc::fmin(-0.0, nan));
+  EXPECT_FP_EQ(-1.2345, __llvm_libc::fmin(nan, -1.2345));
+  EXPECT_FP_EQ(1.2345, __llvm_libc::fmin(1.2345, nan));
   EXPECT_NE(isnan(__llvm_libc::fmin(nan, nan)), 0);
 }
 
 TEST(FminTest, InfArg) {
-  EXPECT_EQ(negInf, __llvm_libc::fmin(negInf, inf));
-  EXPECT_EQ(0.0, __llvm_libc::fmin(inf, 0.0));
-  EXPECT_EQ(-0.0, __llvm_libc::fmin(-0.0, inf));
-  EXPECT_EQ(1.2345, __llvm_libc::fmin(inf, 1.2345));
-  EXPECT_EQ(-1.2345, __llvm_libc::fmin(-1.2345, inf));
+  EXPECT_FP_EQ(negInf, __llvm_libc::fmin(negInf, inf));
+  EXPECT_FP_EQ(0.0, __llvm_libc::fmin(inf, 0.0));
+  EXPECT_FP_EQ(-0.0, __llvm_libc::fmin(-0.0, inf));
+  EXPECT_FP_EQ(1.2345, __llvm_libc::fmin(inf, 1.2345));
+  EXPECT_FP_EQ(-1.2345, __llvm_libc::fmin(-1.2345, inf));
 }
 
 TEST(FminTest, NegInfArg) {
-  EXPECT_EQ(negInf, __llvm_libc::fmin(inf, negInf));
-  EXPECT_EQ(negInf, __llvm_libc::fmin(negInf, 0.0));
-  EXPECT_EQ(negInf, __llvm_libc::fmin(-0.0, negInf));
-  EXPECT_EQ(negInf, __llvm_libc::fmin(negInf, -1.2345));
-  EXPECT_EQ(negInf, __llvm_libc::fmin(1.2345, negInf));
+  EXPECT_FP_EQ(negInf, __llvm_libc::fmin(inf, negInf));
+  EXPECT_FP_EQ(negInf, __llvm_libc::fmin(negInf, 0.0));
+  EXPECT_FP_EQ(negInf, __llvm_libc::fmin(-0.0, negInf));
+  EXPECT_FP_EQ(negInf, __llvm_libc::fmin(negInf, -1.2345));
+  EXPECT_FP_EQ(negInf, __llvm_libc::fmin(1.2345, negInf));
 }
 
 TEST(FminTest, BothZero) {
-  EXPECT_EQ(0.0, __llvm_libc::fmin(0.0, 0.0));
-  EXPECT_EQ(-0.0, __llvm_libc::fmin(-0.0, 0.0));
-  EXPECT_EQ(-0.0, __llvm_libc::fmin(0.0, -0.0));
-  EXPECT_EQ(-0.0, __llvm_libc::fmin(-0.0, -0.0));
+  EXPECT_FP_EQ(0.0, __llvm_libc::fmin(0.0, 0.0));
+  EXPECT_FP_EQ(-0.0, __llvm_libc::fmin(-0.0, 0.0));
+  EXPECT_FP_EQ(-0.0, __llvm_libc::fmin(0.0, -0.0));
+  EXPECT_FP_EQ(-0.0, __llvm_libc::fmin(-0.0, -0.0));
 }
 
 TEST(FminTest, InFloatRange) {
@@ -65,9 +66,9 @@ TEST(FminTest, InFloatRange) {
       continue;
 
     if (x < y) {
-      ASSERT_EQ(x, __llvm_libc::fmin(x, y));
+      ASSERT_FP_EQ(x, __llvm_libc::fmin(x, y));
     } else {
-      ASSERT_EQ(y, __llvm_libc::fmin(x, y));
+      ASSERT_FP_EQ(y, __llvm_libc::fmin(x, y));
     }
   }
 }

diff  --git a/libc/test/src/math/fminf_test.cpp b/libc/test/src/math/fminf_test.cpp
index dea4e7ccf524..20bcdb950291 100644
--- a/libc/test/src/math/fminf_test.cpp
+++ b/libc/test/src/math/fminf_test.cpp
@@ -9,6 +9,7 @@
 #include "include/math.h"
 #include "src/math/fminf.h"
 #include "utils/FPUtil/FPBits.h"
+#include "utils/FPUtil/TestHelpers.h"
 #include "utils/UnitTest/Test.h"
 
 using FPBits = __llvm_libc::fputil::FPBits<float>;
@@ -18,36 +19,36 @@ float inf = static_cast<float>(FPBits::inf());
 float negInf = static_cast<float>(FPBits::negInf());
 
 TEST(FminfTest, NaNArg) {
-  EXPECT_EQ(inf, __llvm_libc::fminf(nan, inf));
-  EXPECT_EQ(negInf, __llvm_libc::fminf(negInf, nan));
-  EXPECT_EQ(0.0f, __llvm_libc::fminf(nan, 0.0f));
-  EXPECT_EQ(-0.0f, __llvm_libc::fminf(-0.0f, nan));
-  EXPECT_EQ(-1.2345f, __llvm_libc::fminf(nan, -1.2345f));
-  EXPECT_EQ(1.2345f, __llvm_libc::fminf(1.2345f, nan));
+  EXPECT_FP_EQ(inf, __llvm_libc::fminf(nan, inf));
+  EXPECT_FP_EQ(negInf, __llvm_libc::fminf(negInf, nan));
+  EXPECT_FP_EQ(0.0f, __llvm_libc::fminf(nan, 0.0f));
+  EXPECT_FP_EQ(-0.0f, __llvm_libc::fminf(-0.0f, nan));
+  EXPECT_FP_EQ(-1.2345f, __llvm_libc::fminf(nan, -1.2345f));
+  EXPECT_FP_EQ(1.2345f, __llvm_libc::fminf(1.2345f, nan));
   EXPECT_NE(isnan(__llvm_libc::fminf(nan, nan)), 0);
 }
 
 TEST(FminfTest, InfArg) {
-  EXPECT_EQ(negInf, __llvm_libc::fminf(negInf, inf));
-  EXPECT_EQ(0.0f, __llvm_libc::fminf(inf, 0.0f));
-  EXPECT_EQ(-0.0f, __llvm_libc::fminf(-0.0f, inf));
-  EXPECT_EQ(1.2345f, __llvm_libc::fminf(inf, 1.2345f));
-  EXPECT_EQ(-1.2345f, __llvm_libc::fminf(-1.2345f, inf));
+  EXPECT_FP_EQ(negInf, __llvm_libc::fminf(negInf, inf));
+  EXPECT_FP_EQ(0.0f, __llvm_libc::fminf(inf, 0.0f));
+  EXPECT_FP_EQ(-0.0f, __llvm_libc::fminf(-0.0f, inf));
+  EXPECT_FP_EQ(1.2345f, __llvm_libc::fminf(inf, 1.2345f));
+  EXPECT_FP_EQ(-1.2345f, __llvm_libc::fminf(-1.2345f, inf));
 }
 
 TEST(FminfTest, NegInfArg) {
-  EXPECT_EQ(negInf, __llvm_libc::fminf(inf, negInf));
-  EXPECT_EQ(negInf, __llvm_libc::fminf(negInf, 0.0f));
-  EXPECT_EQ(negInf, __llvm_libc::fminf(-0.0f, negInf));
-  EXPECT_EQ(negInf, __llvm_libc::fminf(negInf, -1.2345f));
-  EXPECT_EQ(negInf, __llvm_libc::fminf(1.2345f, negInf));
+  EXPECT_FP_EQ(negInf, __llvm_libc::fminf(inf, negInf));
+  EXPECT_FP_EQ(negInf, __llvm_libc::fminf(negInf, 0.0f));
+  EXPECT_FP_EQ(negInf, __llvm_libc::fminf(-0.0f, negInf));
+  EXPECT_FP_EQ(negInf, __llvm_libc::fminf(negInf, -1.2345f));
+  EXPECT_FP_EQ(negInf, __llvm_libc::fminf(1.2345f, negInf));
 }
 
 TEST(FminfTest, BothZero) {
-  EXPECT_EQ(0.0f, __llvm_libc::fminf(0.0f, 0.0f));
-  EXPECT_EQ(-0.0f, __llvm_libc::fminf(-0.0f, 0.0f));
-  EXPECT_EQ(-0.0f, __llvm_libc::fminf(0.0f, -0.0f));
-  EXPECT_EQ(-0.0f, __llvm_libc::fminf(-0.0f, -0.0f));
+  EXPECT_FP_EQ(0.0f, __llvm_libc::fminf(0.0f, 0.0f));
+  EXPECT_FP_EQ(-0.0f, __llvm_libc::fminf(-0.0f, 0.0f));
+  EXPECT_FP_EQ(-0.0f, __llvm_libc::fminf(0.0f, -0.0f));
+  EXPECT_FP_EQ(-0.0f, __llvm_libc::fminf(-0.0f, -0.0f));
 }
 
 TEST(FminfTest, InFloatRange) {
@@ -65,9 +66,9 @@ TEST(FminfTest, InFloatRange) {
       continue;
 
     if (x < y) {
-      ASSERT_EQ(x, __llvm_libc::fminf(x, y));
+      ASSERT_FP_EQ(x, __llvm_libc::fminf(x, y));
     } else {
-      ASSERT_EQ(y, __llvm_libc::fminf(x, y));
+      ASSERT_FP_EQ(y, __llvm_libc::fminf(x, y));
     }
   }
 }

diff  --git a/libc/test/src/math/fminl_test.cpp b/libc/test/src/math/fminl_test.cpp
index 3eabb55b0cab..ea770bc07e4f 100644
--- a/libc/test/src/math/fminl_test.cpp
+++ b/libc/test/src/math/fminl_test.cpp
@@ -9,6 +9,7 @@
 #include "include/math.h"
 #include "src/math/fminl.h"
 #include "utils/FPUtil/FPBits.h"
+#include "utils/FPUtil/TestHelpers.h"
 #include "utils/UnitTest/Test.h"
 
 using FPBits = __llvm_libc::fputil::FPBits<long double>;
@@ -18,36 +19,36 @@ long double inf = static_cast<long double>(FPBits::inf());
 long double negInf = static_cast<long double>(FPBits::negInf());
 
 TEST(FminlTest, NaNArg) {
-  EXPECT_EQ(inf, __llvm_libc::fminl(nan, inf));
-  EXPECT_EQ(negInf, __llvm_libc::fminl(negInf, nan));
-  EXPECT_EQ(0.0L, __llvm_libc::fminl(nan, 0.0L));
-  EXPECT_EQ(-0.0L, __llvm_libc::fminl(-0.0L, nan));
-  EXPECT_EQ(-1.2345L, __llvm_libc::fminl(nan, -1.2345L));
-  EXPECT_EQ(1.2345L, __llvm_libc::fminl(1.2345L, nan));
+  EXPECT_FP_EQ(inf, __llvm_libc::fminl(nan, inf));
+  EXPECT_FP_EQ(negInf, __llvm_libc::fminl(negInf, nan));
+  EXPECT_FP_EQ(0.0L, __llvm_libc::fminl(nan, 0.0L));
+  EXPECT_FP_EQ(-0.0L, __llvm_libc::fminl(-0.0L, nan));
+  EXPECT_FP_EQ(-1.2345L, __llvm_libc::fminl(nan, -1.2345L));
+  EXPECT_FP_EQ(1.2345L, __llvm_libc::fminl(1.2345L, nan));
   EXPECT_NE(isnan(__llvm_libc::fminl(nan, nan)), 0);
 }
 
 TEST(FminlTest, InfArg) {
-  EXPECT_EQ(negInf, __llvm_libc::fminl(negInf, inf));
-  EXPECT_EQ(0.0L, __llvm_libc::fminl(inf, 0.0L));
-  EXPECT_EQ(-0.0L, __llvm_libc::fminl(-0.0L, inf));
-  EXPECT_EQ(1.2345L, __llvm_libc::fminl(inf, 1.2345L));
-  EXPECT_EQ(-1.2345L, __llvm_libc::fminl(-1.2345L, inf));
+  EXPECT_FP_EQ(negInf, __llvm_libc::fminl(negInf, inf));
+  EXPECT_FP_EQ(0.0L, __llvm_libc::fminl(inf, 0.0L));
+  EXPECT_FP_EQ(-0.0L, __llvm_libc::fminl(-0.0L, inf));
+  EXPECT_FP_EQ(1.2345L, __llvm_libc::fminl(inf, 1.2345L));
+  EXPECT_FP_EQ(-1.2345L, __llvm_libc::fminl(-1.2345L, inf));
 }
 
 TEST(FminlTest, NegInfArg) {
-  EXPECT_EQ(negInf, __llvm_libc::fminl(inf, negInf));
-  EXPECT_EQ(negInf, __llvm_libc::fminl(negInf, 0.0L));
-  EXPECT_EQ(negInf, __llvm_libc::fminl(-0.0L, negInf));
-  EXPECT_EQ(negInf, __llvm_libc::fminl(negInf, -1.2345L));
-  EXPECT_EQ(negInf, __llvm_libc::fminl(1.2345L, negInf));
+  EXPECT_FP_EQ(negInf, __llvm_libc::fminl(inf, negInf));
+  EXPECT_FP_EQ(negInf, __llvm_libc::fminl(negInf, 0.0L));
+  EXPECT_FP_EQ(negInf, __llvm_libc::fminl(-0.0L, negInf));
+  EXPECT_FP_EQ(negInf, __llvm_libc::fminl(negInf, -1.2345L));
+  EXPECT_FP_EQ(negInf, __llvm_libc::fminl(1.2345L, negInf));
 }
 
 TEST(FminlTest, BothZero) {
-  EXPECT_EQ(0.0L, __llvm_libc::fminl(0.0L, 0.0L));
-  EXPECT_EQ(-0.0L, __llvm_libc::fminl(-0.0L, 0.0L));
-  EXPECT_EQ(-0.0L, __llvm_libc::fminl(0.0L, -0.0L));
-  EXPECT_EQ(-0.0L, __llvm_libc::fminl(-0.0L, -0.0L));
+  EXPECT_FP_EQ(0.0L, __llvm_libc::fminl(0.0L, 0.0L));
+  EXPECT_FP_EQ(-0.0L, __llvm_libc::fminl(-0.0L, 0.0L));
+  EXPECT_FP_EQ(-0.0L, __llvm_libc::fminl(0.0L, -0.0L));
+  EXPECT_FP_EQ(-0.0L, __llvm_libc::fminl(-0.0L, -0.0L));
 }
 
 TEST(FminlTest, InLongDoubleRange) {
@@ -65,9 +66,9 @@ TEST(FminlTest, InLongDoubleRange) {
       continue;
 
     if (x < y) {
-      ASSERT_EQ(x, __llvm_libc::fminl(x, y));
+      ASSERT_FP_EQ(x, __llvm_libc::fminl(x, y));
     } else {
-      ASSERT_EQ(y, __llvm_libc::fminl(x, y));
+      ASSERT_FP_EQ(y, __llvm_libc::fminl(x, y));
     }
   }
 }

diff  --git a/libc/utils/FPUtil/CMakeLists.txt b/libc/utils/FPUtil/CMakeLists.txt
index e6113723592d..ea9112005751 100644
--- a/libc/utils/FPUtil/CMakeLists.txt
+++ b/libc/utils/FPUtil/CMakeLists.txt
@@ -20,3 +20,17 @@ add_header_library(
   DEPENDS
     libc.utils.CPP.standalone_cpp
 )
+
+add_llvm_library(
+  LibcFPTestHelpers
+    TestHelpers.cpp
+    TestHelpers.h
+)
+target_include_directories(LibcFPTestHelpers PUBLIC ${LIBC_SOURCE_DIR})
+target_link_libraries(LibcFPTestHelpers LibcUnitTest LLVMSupport)
+add_dependencies(
+  LibcFPTestHelpers
+  LibcUnitTest
+  libc.utils.CPP.standalone_cpp
+  libc.utils.FPUtil.fputil
+)

diff  --git a/libc/utils/FPUtil/TestHelpers.cpp b/libc/utils/FPUtil/TestHelpers.cpp
new file mode 100644
index 000000000000..189efe6a0bd1
--- /dev/null
+++ b/libc/utils/FPUtil/TestHelpers.cpp
@@ -0,0 +1,75 @@
+//===-- TestMatchers.cpp ----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "TestHelpers.h"
+
+#include "FPBits.h"
+
+#include "llvm/ADT/StringExtras.h"
+
+#include <string>
+
+namespace __llvm_libc {
+namespace fputil {
+namespace testing {
+
+// Return the first N hex digits of an integer as a string in upper case.
+template <typename T>
+cpp::EnableIfType<cpp::IsIntegral<T>::Value, std::string>
+uintToHex(T X, size_t Length = sizeof(T) * 2) {
+  std::string s(Length, '0');
+
+  for (auto it = s.rbegin(), end = s.rend(); it != end; ++it, X >>= 4) {
+    unsigned char Mod = static_cast<unsigned char>(X) & 15;
+    *it = llvm::hexdigit(Mod, true);
+  }
+
+  return s;
+}
+
+template <typename ValType>
+cpp::EnableIfType<cpp::IsFloatingPointType<ValType>::Value, void>
+describeValue(const char *label, ValType value,
+              testutils::StreamWrapper &stream) {
+  stream << label;
+
+  FPBits<ValType> bits(value);
+  if (bits.isNaN()) {
+    stream << "(NaN)";
+  } else if (bits.isInf()) {
+    if (bits.sign)
+      stream << "(-Infinity)";
+    else
+      stream << "(+Infinity)";
+  } else {
+    constexpr int exponentWidthInHex =
+        (fputil::ExponentWidth<ValType>::value - 1) / 4 + 1;
+    constexpr int mantissaWidthInHex =
+        (fputil::MantissaWidth<ValType>::value - 1) / 4 + 1;
+
+    stream << "Sign: " << (bits.sign ? '1' : '0') << ", "
+           << "Exponent: 0x"
+           << uintToHex<uint16_t>(bits.exponent, exponentWidthInHex) << ", "
+           << "Mantissa: 0x"
+           << uintToHex<typename fputil::FPBits<ValType>::UIntType>(
+                  bits.mantissa, mantissaWidthInHex);
+  }
+
+  stream << '\n';
+}
+
+template void describeValue<float>(const char *, float,
+                                   testutils::StreamWrapper &);
+template void describeValue<double>(const char *, double,
+                                    testutils::StreamWrapper &);
+template void describeValue<long double>(const char *, long double,
+                                         testutils::StreamWrapper &);
+
+} // namespace testing
+} // namespace fputil
+} // namespace __llvm_libc

diff  --git a/libc/utils/FPUtil/TestHelpers.h b/libc/utils/FPUtil/TestHelpers.h
new file mode 100644
index 000000000000..941c4d64622b
--- /dev/null
+++ b/libc/utils/FPUtil/TestHelpers.h
@@ -0,0 +1,92 @@
+//===-- TestMatchers.h ------------------------------------------*- 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_UTILS_FPUTIL_TEST_HELPERS_H
+#define LLVM_LIBC_UTILS_FPUTIL_TEST_HELPERS_H
+
+#include "FPBits.h"
+
+#include "utils/UnitTest/Test.h"
+
+namespace __llvm_libc {
+namespace fputil {
+namespace testing {
+
+template <typename ValType>
+cpp::EnableIfType<cpp::IsFloatingPointType<ValType>::Value, void>
+describeValue(const char *label, ValType value,
+              testutils::StreamWrapper &stream);
+
+template <typename T, __llvm_libc::testing::TestCondition Condition>
+class FPMatcher : public __llvm_libc::testing::Matcher<T> {
+  static_assert(__llvm_libc::cpp::IsFloatingPointType<T>::Value,
+                "FPMatcher can only be used with floating point values.");
+  static_assert(Condition == __llvm_libc::testing::Cond_EQ ||
+                    Condition == __llvm_libc::testing::Cond_NE,
+                "Unsupported FPMathcer test condition.");
+
+  T expected;
+  T actual;
+
+public:
+  FPMatcher(T expectedValue) : expected(expectedValue) {}
+
+  bool match(T actualValue) {
+    actual = actualValue;
+    fputil::FPBits<T> actualBits(actual), expectedBits(expected);
+    if (Condition == __llvm_libc::testing::Cond_EQ)
+      return (actualBits.isNaN() && expectedBits.isNaN()) ||
+             (actualBits.bitsAsUInt() == expectedBits.bitsAsUInt());
+
+    // If condition == Cond_NE.
+    if (actualBits.isNaN())
+      return !expectedBits.isNaN();
+    return expectedBits.isNaN() ||
+           (actualBits.bitsAsUInt() != expectedBits.bitsAsUInt());
+  }
+
+  void explainError(testutils::StreamWrapper &stream) override {
+    describeValue("Expected floating point value: ", expected, stream);
+    describeValue("  Actual floating point value: ", actual, stream);
+  }
+};
+
+template <__llvm_libc::testing::TestCondition C, typename T>
+FPMatcher<T, C> getMatcher(T expectedValue) {
+  return FPMatcher<T, C>(expectedValue);
+}
+
+} // namespace testing
+} // namespace fputil
+} // namespace __llvm_libc
+
+#define EXPECT_FP_EQ(expected, actual)                                         \
+  EXPECT_THAT(                                                                 \
+      actual,                                                                  \
+      __llvm_libc::fputil::testing::getMatcher<__llvm_libc::testing::Cond_EQ>( \
+          expected))
+
+#define ASSERT_FP_EQ(expected, actual)                                         \
+  ASSERT_THAT(                                                                 \
+      actual,                                                                  \
+      __llvm_libc::fputil::testing::getMatcher<__llvm_libc::testing::Cond_EQ>( \
+          expected))
+
+#define EXPECT_FP_NE(expected, actual)                                         \
+  EXPECT_THAT(                                                                 \
+      actual,                                                                  \
+      __llvm_libc::fputil::testing::getMatcher<__llvm_libc::testing::Cond_NE>( \
+          expected))
+
+#define ASSERT_FP_NE(expected, actual)                                         \
+  ASSERT_THAT(                                                                 \
+      actual,                                                                  \
+      __llvm_libc::fputil::testing::getMatcher<__llvm_libc::testing::Cond_NE>( \
+          expected))
+
+#endif // LLVM_LIBC_UTILS_FPUTIL_TEST_HELPERS_H

diff  --git a/libc/utils/UnitTest/Test.cpp b/libc/utils/UnitTest/Test.cpp
index 84730ad31cca..67c81e8c00ef 100644
--- a/libc/utils/UnitTest/Test.cpp
+++ b/libc/utils/UnitTest/Test.cpp
@@ -8,7 +8,6 @@
 
 #include "Test.h"
 
-#include "utils/FPUtil/FPBits.h"
 #include "utils/testutils/ExecuteFunction.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/StringRef.h"
@@ -34,60 +33,26 @@ class RunContext {
 
 namespace internal {
 
-// Display the first N hexadecimal digits of an integer in upper case.
-template <typename T>
-cpp::EnableIfType<cpp::IsIntegral<T>::Value, std::string>
-uintToHex(T X, size_t Length = sizeof(T) * 2) {
-  std::string s(Length, '0');
-
-  for (auto it = s.rbegin(), end = s.rend(); it != end; ++it, X >>= 4) {
-    unsigned char Mod = static_cast<unsigned char>(X) & 15;
-    *it = llvm::hexdigit(Mod, true);
-  }
-
-  return s;
-}
-
-// When the value is not floating-point type, just display it as normal.
+// When the value is of integral type, just display it as normal.
 template <typename ValType>
-cpp::EnableIfType<!cpp::IsFloatingPointType<ValType>::Value, std::string>
+cpp::EnableIfType<cpp::IsIntegral<ValType>::Value, std::string>
 describeValue(ValType Value) {
   return std::to_string(Value);
 }
 
-template <> std::string describeValue<llvm::StringRef>(llvm::StringRef Value) {
-  return std::string(Value);
-}
+std::string describeValue(llvm::StringRef Value) { return std::string(Value); }
 
 // When the value is __uint128_t, also show its hexadecimal digits.
 // Using template to force exact match, prevent ambiguous promotion.
 template <> std::string describeValue<__uint128_t>(__uint128_t Value) {
-  return "0x" + uintToHex(Value);
-}
+  std::string S(sizeof(__uint128_t) * 2, '0');
 
-// When the value is a floating point type, also show its sign | exponent |
-// mantissa.
-template <typename ValType>
-cpp::EnableIfType<cpp::IsFloatingPointType<ValType>::Value, std::string>
-describeValue(ValType Value) {
-  fputil::FPBits<ValType> Bits(Value);
-
-  if (Bits.isNaN()) {
-    return "(NaN)";
-  } else if (Bits.isInf()) {
-    return Bits.sign ? "(-Infinity)" : "(+Infinity)";
-  } else {
-    constexpr int ExponentWidthInHex =
-        (fputil::ExponentWidth<ValType>::value - 1) / 4 + 1;
-    constexpr int MantissaWidthInHex =
-        (fputil::MantissaWidth<ValType>::value - 1) / 4 + 1;
-
-    return std::string("Sign: ") + (Bits.sign ? '1' : '0') + ", Exponent: 0x" +
-           uintToHex<uint16_t>(Bits.exponent, ExponentWidthInHex) +
-           ", Mantissa: 0x" +
-           uintToHex<typename fputil::FPBits<ValType>::UIntType>(
-               Bits.mantissa, MantissaWidthInHex);
+  for (auto I = S.rbegin(), End = S.rend(); I != End; ++I, Value >>= 4) {
+    unsigned char Mod = static_cast<unsigned char>(Value) & 15;
+    *I = llvm::hexdigit(Mod, true);
   }
+
+  return "0x" + S;
 }
 
 template <typename ValType>
@@ -104,23 +69,6 @@ void explainDifference(ValType LHS, ValType RHS, const char *LHSStr,
                << Offset << "Which is: " << describeValue(RHS) << '\n';
 }
 
-template <typename ValType>
-cpp::EnableIfType<!cpp::IsFloatingPointType<ValType>::Value, bool>
-testEQ(ValType LHS, ValType RHS) {
-  return LHS == RHS;
-}
-
-// For floating points, we consider all NaNs are equal, and +0.0 is not equal to
-// -0.0.
-template <typename ValType>
-cpp::EnableIfType<cpp::IsFloatingPointType<ValType>::Value, bool>
-testEQ(ValType LHS, ValType RHS) {
-  fputil::FPBits<ValType> LHSBits(LHS), RHSBits(RHS);
-
-  return (LHSBits.isNaN() && RHSBits.isNaN()) ||
-         (LHSBits.bitsAsUInt() == RHSBits.bitsAsUInt());
-}
-
 template <typename ValType>
 bool test(RunContext &Ctx, TestCondition Cond, ValType LHS, ValType RHS,
           const char *LHSStr, const char *RHSStr, const char *File,
@@ -131,14 +79,14 @@ bool test(RunContext &Ctx, TestCondition Cond, ValType LHS, ValType RHS,
 
   switch (Cond) {
   case Cond_EQ:
-    if (testEQ(LHS, RHS))
+    if (LHS == RHS)
       return true;
 
     Ctx.markFail();
     ExplainDifference("equal to");
     return false;
   case Cond_NE:
-    if (!testEQ(LHS, RHS))
+    if (LHS != RHS)
       return true;
 
     Ctx.markFail();
@@ -290,7 +238,7 @@ template bool Test::test<__uint128_t, 0>(RunContext &Ctx, TestCondition Cond,
                                          __uint128_t LHS, __uint128_t RHS,
                                          const char *LHSStr, const char *RHSStr,
                                          const char *File, unsigned long Line);
-
+/*
 template bool Test::test<float, 0>(RunContext &Ctx, TestCondition Cond,
                                    float LHS, float RHS, const char *LHSStr,
                                    const char *RHSStr, const char *File,
@@ -305,7 +253,7 @@ template bool Test::test<long double, 0>(RunContext &Ctx, TestCondition Cond,
                                          long double LHS, long double RHS,
                                          const char *LHSStr, const char *RHSStr,
                                          const char *File, unsigned long Line);
-
+*/
 bool Test::testStrEq(RunContext &Ctx, const char *LHS, const char *RHS,
                      const char *LHSStr, const char *RHSStr, const char *File,
                      unsigned long Line) {

diff  --git a/libc/utils/UnitTest/Test.h b/libc/utils/UnitTest/Test.h
index ec92bd218752..71b5a01b88cb 100644
--- a/libc/utils/UnitTest/Test.h
+++ b/libc/utils/UnitTest/Test.h
@@ -78,7 +78,7 @@ class Test {
   // |Cond| on mismatched |LHS| and |RHS| types can potentially succeed because
   // of type promotion.
   template <typename ValType,
-            cpp::EnableIfType<cpp::IsArithmetic<ValType>::Value, int> = 0>
+            cpp::EnableIfType<cpp::IsIntegral<ValType>::Value, int> = 0>
   static bool test(RunContext &Ctx, TestCondition Cond, ValType LHS,
                    ValType RHS, const char *LHSStr, const char *RHSStr,
                    const char *File, unsigned long Line) {


        


More information about the libc-commits mailing list