[libc-commits] [libc] 9532074 - [libc][math] Clean up exhaustive tests implementations.

Tue Ly via libc-commits libc-commits at lists.llvm.org
Wed Jun 28 04:59:04 PDT 2023


Author: Tue Ly
Date: 2023-06-28T07:58:46-04:00
New Revision: 9532074a9d575d3b052121c24bf60bdd50bcf684

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

LOG: [libc][math] Clean up exhaustive tests implementations.

Clean up exhaustive tests.  Let check functions return number of failures instead of passed/failed.

Reviewed By: sivachandra

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

Added: 
    

Modified: 
    libc/src/math/docs/add_math_function.md
    libc/test/src/math/exhaustive/CMakeLists.txt
    libc/test/src/math/exhaustive/acosf_test.cpp
    libc/test/src/math/exhaustive/acoshf_test.cpp
    libc/test/src/math/exhaustive/asinf_test.cpp
    libc/test/src/math/exhaustive/asinhf_test.cpp
    libc/test/src/math/exhaustive/atanf_test.cpp
    libc/test/src/math/exhaustive/atanhf_test.cpp
    libc/test/src/math/exhaustive/cosf_test.cpp
    libc/test/src/math/exhaustive/coshf_test.cpp
    libc/test/src/math/exhaustive/exhaustive_test.h
    libc/test/src/math/exhaustive/exp10f_test.cpp
    libc/test/src/math/exhaustive/exp2f_test.cpp
    libc/test/src/math/exhaustive/expf_test.cpp
    libc/test/src/math/exhaustive/expm1f_test.cpp
    libc/test/src/math/exhaustive/hypotf_test.cpp
    libc/test/src/math/exhaustive/log10f_test.cpp
    libc/test/src/math/exhaustive/log1pf_test.cpp
    libc/test/src/math/exhaustive/log2f_test.cpp
    libc/test/src/math/exhaustive/logf_test.cpp
    libc/test/src/math/exhaustive/sincosf_test.cpp
    libc/test/src/math/exhaustive/sinf_test.cpp
    libc/test/src/math/exhaustive/sinhf_test.cpp
    libc/test/src/math/exhaustive/sqrtf_test.cpp
    libc/test/src/math/exhaustive/tanf_test.cpp
    libc/test/src/math/exhaustive/tanhf_test.cpp

Removed: 
    libc/test/src/math/exhaustive/exhaustive_test.cpp


################################################################################
diff  --git a/libc/src/math/docs/add_math_function.md b/libc/src/math/docs/add_math_function.md
index 09ac06e15103a..cf4d31661daf3 100644
--- a/libc/src/math/docs/add_math_function.md
+++ b/libc/src/math/docs/add_math_function.md
@@ -111,11 +111,11 @@ order to find exceptional cases for your function's implementation.
 ```
   libc/test/src/math/exhaustive/CMakeLists.txt
 ```
-- The template class `LlvmLibcExhaustiveTest` located at:
+- The template class `LlvmLibcExhaustiveMathTest` located at:
 ```
   libc/test/src/math/exhaustive/exhaustive_test.h
 ```
-can be inherited for conveniently parallelizing the exhaustive tests.
+can be used for conveniently parallelizing the exhaustive tests.
 
 ### Performance tests
 

diff  --git a/libc/test/src/math/exhaustive/CMakeLists.txt b/libc/test/src/math/exhaustive/CMakeLists.txt
index 4c3f524f0b904..f3f0c279795b1 100644
--- a/libc/test/src/math/exhaustive/CMakeLists.txt
+++ b/libc/test/src/math/exhaustive/CMakeLists.txt
@@ -1,11 +1,9 @@
 add_libc_exhaustive_testsuite(libc_math_exhaustive_tests)
 
-add_object_library(
+add_header_library(
   exhaustive_test
   HDRS
     exhaustive_test.h
-  SRCS
-    exhaustive_test.cpp
 )
 
 add_fp_unittest(

diff  --git a/libc/test/src/math/exhaustive/acosf_test.cpp b/libc/test/src/math/exhaustive/acosf_test.cpp
index 66970744b5daa..4cece0b76ecac 100644
--- a/libc/test/src/math/exhaustive/acosf_test.cpp
+++ b/libc/test/src/math/exhaustive/acosf_test.cpp
@@ -7,72 +7,27 @@
 //===----------------------------------------------------------------------===//
 
 #include "exhaustive_test.h"
-#include "src/__support/FPUtil/FPBits.h"
 #include "src/math/acosf.h"
 #include "utils/MPFRWrapper/MPFRUtils.h"
 
-#include <thread>
-
-using FPBits = __llvm_libc::fputil::FPBits<float>;
-
 namespace mpfr = __llvm_libc::testing::mpfr;
 
-struct LlvmLibcAcosfExhaustiveTest : public LlvmLibcExhaustiveTest<uint32_t> {
-  bool check(uint32_t start, uint32_t stop,
-             mpfr::RoundingMode rounding) override {
-    mpfr::ForceRoundingMode r(rounding);
-    if (!r.success)
-      return true;
-    uint32_t bits = start;
-    bool result = true;
-    do {
-      FPBits xbits(bits);
-      float x = float(xbits);
-      result &= TEST_MPFR_MATCH(mpfr::Operation::Acos, x, __llvm_libc::acosf(x),
-                                0.5, rounding);
-    } while (bits++ < stop);
-    return result;
-  }
-};
-
-static const int NUM_THREADS = std::thread::hardware_concurrency();
+using LlvmLibcAcosfExhaustiveTest =
+    LlvmLibcUnaryOpExhaustiveMathTest<float, mpfr::Operation::Acos,
+                                      __llvm_libc::acosf>;
 
 // Range: [0, Inf];
-static const uint32_t POS_START = 0x0000'0000U;
-static const uint32_t POS_STOP = 0x7f80'0000U;
-
-TEST_F(LlvmLibcAcosfExhaustiveTest, PostiveRangeRoundNearestTieToEven) {
-  test_full_range(POS_START, POS_STOP, mpfr::RoundingMode::Nearest);
-}
-
-TEST_F(LlvmLibcAcosfExhaustiveTest, PostiveRangeRoundUp) {
-  test_full_range(POS_START, POS_STOP, mpfr::RoundingMode::Upward);
-}
+static constexpr uint32_t POS_START = 0x0000'0000U;
+static constexpr uint32_t POS_STOP = 0x7f80'0000U;
 
-TEST_F(LlvmLibcAcosfExhaustiveTest, PostiveRangeRoundDown) {
-  test_full_range(POS_START, POS_STOP, mpfr::RoundingMode::Downward);
-}
-
-TEST_F(LlvmLibcAcosfExhaustiveTest, PostiveRangeRoundTowardZero) {
-  test_full_range(POS_START, POS_STOP, mpfr::RoundingMode::TowardZero);
+TEST_F(LlvmLibcAcosfExhaustiveTest, PostiveRange) {
+  test_full_range_all_roundings(POS_START, POS_STOP);
 }
 
 // Range: [-Inf, 0];
-static const uint32_t NEG_START = 0xb000'0000U;
-static const uint32_t NEG_STOP = 0xff80'0000U;
-
-TEST_F(LlvmLibcAcosfExhaustiveTest, NegativeRangeRoundNearestTieToEven) {
-  test_full_range(NEG_START, NEG_STOP, mpfr::RoundingMode::Nearest);
-}
-
-TEST_F(LlvmLibcAcosfExhaustiveTest, NegativeRangeRoundUp) {
-  test_full_range(NEG_START, NEG_STOP, mpfr::RoundingMode::Upward);
-}
-
-TEST_F(LlvmLibcAcosfExhaustiveTest, NegativeRangeRoundDown) {
-  test_full_range(NEG_START, NEG_STOP, mpfr::RoundingMode::Downward);
-}
+static constexpr uint32_t NEG_START = 0xb000'0000U;
+static constexpr uint32_t NEG_STOP = 0xff80'0000U;
 
-TEST_F(LlvmLibcAcosfExhaustiveTest, NegativeRangeRoundTowardZero) {
-  test_full_range(NEG_START, NEG_STOP, mpfr::RoundingMode::TowardZero);
+TEST_F(LlvmLibcAcosfExhaustiveTest, NegativeRange) {
+  test_full_range_all_roundings(NEG_START, NEG_STOP);
 }

diff  --git a/libc/test/src/math/exhaustive/acoshf_test.cpp b/libc/test/src/math/exhaustive/acoshf_test.cpp
index 6f1196292e278..1dd993c26b8ca 100644
--- a/libc/test/src/math/exhaustive/acoshf_test.cpp
+++ b/libc/test/src/math/exhaustive/acoshf_test.cpp
@@ -7,52 +7,19 @@
 //===----------------------------------------------------------------------===//
 
 #include "exhaustive_test.h"
-#include "src/__support/FPUtil/FPBits.h"
 #include "src/math/acoshf.h"
 #include "utils/MPFRWrapper/MPFRUtils.h"
 
-#include <thread>
-
-using FPBits = __llvm_libc::fputil::FPBits<float>;
-
 namespace mpfr = __llvm_libc::testing::mpfr;
 
-struct LlvmLibcAcoshfExhaustiveTest : public LlvmLibcExhaustiveTest<uint32_t> {
-  bool check(uint32_t start, uint32_t stop,
-             mpfr::RoundingMode rounding) override {
-    mpfr::ForceRoundingMode r(rounding);
-    if (!r.success)
-      return true;
-    uint32_t bits = start;
-    bool result = true;
-    do {
-      FPBits xbits(bits);
-      float x = float(xbits);
-      result &= TEST_MPFR_MATCH(mpfr::Operation::Acosh, x,
-                                __llvm_libc::acoshf(x), 0.5, rounding);
-    } while (bits++ < stop);
-    return result;
-  }
-};
-
-static const int NUM_THREADS = std::thread::hardware_concurrency();
+using LlvmLibcAcoshfExhaustiveTest =
+    LlvmLibcUnaryOpExhaustiveMathTest<float, mpfr::Operation::Acosh,
+                                      __llvm_libc::acoshf>;
 
 // Range: [1, Inf];
-static const uint32_t POS_START = 0x3f80'0000U;
-static const uint32_t POS_STOP = 0x7f80'0000U;
-
-TEST_F(LlvmLibcAcoshfExhaustiveTest, PostiveRangeRoundNearestTieToEven) {
-  test_full_range(POS_START, POS_STOP, mpfr::RoundingMode::Nearest);
-}
-
-TEST_F(LlvmLibcAcoshfExhaustiveTest, PostiveRangeRoundUp) {
-  test_full_range(POS_START, POS_STOP, mpfr::RoundingMode::Upward);
-}
-
-TEST_F(LlvmLibcAcoshfExhaustiveTest, PostiveRangeRoundDown) {
-  test_full_range(POS_START, POS_STOP, mpfr::RoundingMode::Downward);
-}
+static constexpr uint32_t POS_START = 0x3f80'0000U;
+static constexpr uint32_t POS_STOP = 0x7f80'0000U;
 
-TEST_F(LlvmLibcAcoshfExhaustiveTest, PostiveRangeRoundTowardZero) {
-  test_full_range(POS_START, POS_STOP, mpfr::RoundingMode::TowardZero);
+TEST_F(LlvmLibcAcoshfExhaustiveTest, PostiveRangeRound) {
+  test_full_range_all_roundings(POS_START, POS_STOP);
 }

diff  --git a/libc/test/src/math/exhaustive/asinf_test.cpp b/libc/test/src/math/exhaustive/asinf_test.cpp
index 4296259f08211..5dcb625304a1f 100644
--- a/libc/test/src/math/exhaustive/asinf_test.cpp
+++ b/libc/test/src/math/exhaustive/asinf_test.cpp
@@ -7,73 +7,27 @@
 //===----------------------------------------------------------------------===//
 
 #include "exhaustive_test.h"
-#include "src/__support/FPUtil/FPBits.h"
 #include "src/math/asinf.h"
 #include "utils/MPFRWrapper/MPFRUtils.h"
 
-#include <thread>
-
-using FPBits = __llvm_libc::fputil::FPBits<float>;
-
 namespace mpfr = __llvm_libc::testing::mpfr;
 
-struct LlvmLibcAsinfExhaustiveTest : public LlvmLibcExhaustiveTest<uint32_t> {
-  bool check(uint32_t start, uint32_t stop,
-             mpfr::RoundingMode rounding) override {
-    mpfr::ForceRoundingMode r(rounding);
-    if (!r.success)
-      return true;
-    uint32_t bits = start;
-    bool result = true;
-    do {
-      FPBits xbits(bits);
-      float x = float(xbits);
-      result &= TEST_MPFR_MATCH(mpfr::Operation::Asin, x, __llvm_libc::asinf(x),
-                                0.5, rounding);
-      // if (!result) break;
-    } while (bits++ < stop);
-    return result;
-  }
-};
-
-static const int NUM_THREADS = std::thread::hardware_concurrency();
+using LlvmLibcAsinfExhaustiveTest =
+    LlvmLibcUnaryOpExhaustiveMathTest<float, mpfr::Operation::Asin,
+                                      __llvm_libc::asinf>;
 
 // Range: [0, Inf];
-static const uint32_t POS_START = 0x0000'0000U;
-static const uint32_t POS_STOP = 0x7f80'0000U;
-
-TEST_F(LlvmLibcAsinfExhaustiveTest, PostiveRangeRoundNearestTieToEven) {
-  test_full_range(POS_START, POS_STOP, mpfr::RoundingMode::Nearest);
-}
-
-TEST_F(LlvmLibcAsinfExhaustiveTest, PostiveRangeRoundUp) {
-  test_full_range(POS_START, POS_STOP, mpfr::RoundingMode::Upward);
-}
+static constexpr uint32_t POS_START = 0x0000'0000U;
+static constexpr uint32_t POS_STOP = 0x7f80'0000U;
 
-TEST_F(LlvmLibcAsinfExhaustiveTest, PostiveRangeRoundDown) {
-  test_full_range(POS_START, POS_STOP, mpfr::RoundingMode::Downward);
-}
-
-TEST_F(LlvmLibcAsinfExhaustiveTest, PostiveRangeRoundTowardZero) {
-  test_full_range(POS_START, POS_STOP, mpfr::RoundingMode::TowardZero);
+TEST_F(LlvmLibcAsinfExhaustiveTest, PostiveRange) {
+  test_full_range_all_roundings(POS_START, POS_STOP);
 }
 
 // Range: [-Inf, 0];
-static const uint32_t NEG_START = 0x8000'0000U;
-static const uint32_t NEG_STOP = 0xff80'0000U;
-
-TEST_F(LlvmLibcAsinfExhaustiveTest, NegativeRangeRoundNearestTieToEven) {
-  test_full_range(NEG_START, NEG_STOP, mpfr::RoundingMode::Nearest);
-}
-
-TEST_F(LlvmLibcAsinfExhaustiveTest, NegativeRangeRoundUp) {
-  test_full_range(NEG_START, NEG_STOP, mpfr::RoundingMode::Upward);
-}
-
-TEST_F(LlvmLibcAsinfExhaustiveTest, NegativeRangeRoundDown) {
-  test_full_range(NEG_START, NEG_STOP, mpfr::RoundingMode::Downward);
-}
+static constexpr uint32_t NEG_START = 0xb000'0000U;
+static constexpr uint32_t NEG_STOP = 0xff80'0000U;
 
-TEST_F(LlvmLibcAsinfExhaustiveTest, NegativeRangeRoundTowardZero) {
-  test_full_range(NEG_START, NEG_STOP, mpfr::RoundingMode::TowardZero);
+TEST_F(LlvmLibcAsinfExhaustiveTest, NegativeRange) {
+  test_full_range_all_roundings(NEG_START, NEG_STOP);
 }

diff  --git a/libc/test/src/math/exhaustive/asinhf_test.cpp b/libc/test/src/math/exhaustive/asinhf_test.cpp
index 296e42c0d25d5..6af0ec0d6b03d 100644
--- a/libc/test/src/math/exhaustive/asinhf_test.cpp
+++ b/libc/test/src/math/exhaustive/asinhf_test.cpp
@@ -7,72 +7,27 @@
 //===----------------------------------------------------------------------===//
 
 #include "exhaustive_test.h"
-#include "src/__support/FPUtil/FPBits.h"
 #include "src/math/asinhf.h"
 #include "utils/MPFRWrapper/MPFRUtils.h"
 
-#include <thread>
-
-using FPBits = __llvm_libc::fputil::FPBits<float>;
-
 namespace mpfr = __llvm_libc::testing::mpfr;
 
-struct LlvmLibcAsinhfExhaustiveTest : public LlvmLibcExhaustiveTest<uint32_t> {
-  bool check(uint32_t start, uint32_t stop,
-             mpfr::RoundingMode rounding) override {
-    mpfr::ForceRoundingMode r(rounding);
-    if (!r.success)
-      return true;
-    uint32_t bits = start;
-    bool result = true;
-    do {
-      FPBits xbits(bits);
-      float x = float(xbits);
-      result &= TEST_MPFR_MATCH(mpfr::Operation::Asinh, x,
-                                __llvm_libc::asinhf(x), 0.5, rounding);
-    } while (bits++ < stop);
-    return result;
-  }
-};
-
-static const int NUM_THREADS = std::thread::hardware_concurrency();
+using LlvmLibcAsinhfExhaustiveTest =
+    LlvmLibcUnaryOpExhaustiveMathTest<float, mpfr::Operation::Asinh,
+                                      __llvm_libc::asinhf>;
 
 // Range: [0, Inf];
-static const uint32_t POS_START = 0x0000'0000U;
-static const uint32_t POS_STOP = 0x7f80'0000U;
-
-TEST_F(LlvmLibcAsinhfExhaustiveTest, PostiveRangeRoundNearestTieToEven) {
-  test_full_range(POS_START, POS_STOP, mpfr::RoundingMode::Nearest);
-}
-
-TEST_F(LlvmLibcAsinhfExhaustiveTest, PostiveRangeRoundUp) {
-  test_full_range(POS_START, POS_STOP, mpfr::RoundingMode::Upward);
-}
+static constexpr uint32_t POS_START = 0x0000'0000U;
+static constexpr uint32_t POS_STOP = 0x7f80'0000U;
 
-TEST_F(LlvmLibcAsinhfExhaustiveTest, PostiveRangeRoundDown) {
-  test_full_range(POS_START, POS_STOP, mpfr::RoundingMode::Downward);
+TEST_F(LlvmLibcAsinhfExhaustiveTest, PostiveRange) {
+  test_full_range_all_roundings(POS_START, POS_STOP);
 }
 
-TEST_F(LlvmLibcAsinhfExhaustiveTest, PostiveRangeRoundTowardZero) {
-  test_full_range(POS_START, POS_STOP, mpfr::RoundingMode::TowardZero);
-}
-
-// Range: [-1.0, 0];
-static const uint32_t NEG_START = 0x8000'0000U;
-static const uint32_t NEG_STOP = 0xff80'0000U;
-
-TEST_F(LlvmLibcAsinhfExhaustiveTest, NegativeRangeRoundNearestTieToEven) {
-  test_full_range(NEG_START, NEG_STOP, mpfr::RoundingMode::Nearest);
-}
-
-TEST_F(LlvmLibcAsinhfExhaustiveTest, NegativeRangeRoundUp) {
-  test_full_range(NEG_START, NEG_STOP, mpfr::RoundingMode::Upward);
-}
-
-TEST_F(LlvmLibcAsinhfExhaustiveTest, NegativeRangeRoundDown) {
-  test_full_range(NEG_START, NEG_STOP, mpfr::RoundingMode::Downward);
-}
+// Range: [-Inf, 0];
+static constexpr uint32_t NEG_START = 0xb000'0000U;
+static constexpr uint32_t NEG_STOP = 0xff80'0000U;
 
-TEST_F(LlvmLibcAsinhfExhaustiveTest, NegativeRangeRoundTowardZero) {
-  test_full_range(NEG_START, NEG_STOP, mpfr::RoundingMode::TowardZero);
+TEST_F(LlvmLibcAsinhfExhaustiveTest, NegativeRange) {
+  test_full_range_all_roundings(NEG_START, NEG_STOP);
 }

diff  --git a/libc/test/src/math/exhaustive/atanf_test.cpp b/libc/test/src/math/exhaustive/atanf_test.cpp
index c2a1055ac4edf..c7c891ecbbd1e 100644
--- a/libc/test/src/math/exhaustive/atanf_test.cpp
+++ b/libc/test/src/math/exhaustive/atanf_test.cpp
@@ -7,72 +7,27 @@
 //===----------------------------------------------------------------------===//
 
 #include "exhaustive_test.h"
-#include "src/__support/FPUtil/FPBits.h"
 #include "src/math/atanf.h"
 #include "utils/MPFRWrapper/MPFRUtils.h"
 
-#include <thread>
-
-using FPBits = __llvm_libc::fputil::FPBits<float>;
-
 namespace mpfr = __llvm_libc::testing::mpfr;
 
-struct LlvmLibcAtanfExhaustiveTest : public LlvmLibcExhaustiveTest<uint32_t> {
-  bool check(uint32_t start, uint32_t stop,
-             mpfr::RoundingMode rounding) override {
-    mpfr::ForceRoundingMode r(rounding);
-    if (!r.success)
-      return true;
-    uint32_t bits = start;
-    bool result = true;
-    do {
-      FPBits xbits(bits);
-      float x = float(xbits);
-      result &= TEST_MPFR_MATCH(mpfr::Operation::Atan, x, __llvm_libc::atanf(x),
-                                0.5, rounding);
-    } while (bits++ < stop);
-    return result;
-  }
-};
-
-static const int NUM_THREADS = std::thread::hardware_concurrency();
-
-// Range: [0, 1.0];
-static const uint32_t POS_START = 0x0000'0000U;
-static const uint32_t POS_STOP = FPBits::inf().uintval();
+using LlvmLibcAtanfExhaustiveTest =
+    LlvmLibcUnaryOpExhaustiveMathTest<float, mpfr::Operation::Atan,
+                                      __llvm_libc::atanf>;
 
-TEST_F(LlvmLibcAtanfExhaustiveTest, PostiveRangeRoundNearestTieToEven) {
-  test_full_range(POS_START, POS_STOP, mpfr::RoundingMode::Nearest);
-}
-
-TEST_F(LlvmLibcAtanfExhaustiveTest, PostiveRangeRoundUp) {
-  test_full_range(POS_START, POS_STOP, mpfr::RoundingMode::Upward);
-}
+// Range: [0, Inf];
+static constexpr uint32_t POS_START = 0x0000'0000U;
+static constexpr uint32_t POS_STOP = 0x7f80'0000U;
 
-TEST_F(LlvmLibcAtanfExhaustiveTest, PostiveRangeRoundDown) {
-  test_full_range(POS_START, POS_STOP, mpfr::RoundingMode::Downward);
+TEST_F(LlvmLibcAtanfExhaustiveTest, PostiveRange) {
+  test_full_range_all_roundings(POS_START, POS_STOP);
 }
 
-TEST_F(LlvmLibcAtanfExhaustiveTest, PostiveRangeRoundTowardZero) {
-  test_full_range(POS_START, POS_STOP, mpfr::RoundingMode::TowardZero);
-}
-
-// Range: [-1.0, 0];
-static const uint32_t NEG_START = 0x8000'0000U;
-static const uint32_t NEG_STOP = FPBits::neg_inf().uintval();
-
-TEST_F(LlvmLibcAtanfExhaustiveTest, NegativeRangeRoundNearestTieToEven) {
-  test_full_range(NEG_START, NEG_STOP, mpfr::RoundingMode::Nearest);
-}
-
-TEST_F(LlvmLibcAtanfExhaustiveTest, NegativeRangeRoundUp) {
-  test_full_range(NEG_START, NEG_STOP, mpfr::RoundingMode::Upward);
-}
-
-TEST_F(LlvmLibcAtanfExhaustiveTest, NegativeRangeRoundDown) {
-  test_full_range(NEG_START, NEG_STOP, mpfr::RoundingMode::Downward);
-}
+// Range: [-Inf, 0];
+static constexpr uint32_t NEG_START = 0xb000'0000U;
+static constexpr uint32_t NEG_STOP = 0xff80'0000U;
 
-TEST_F(LlvmLibcAtanfExhaustiveTest, NegativeRangeRoundTowardZero) {
-  test_full_range(NEG_START, NEG_STOP, mpfr::RoundingMode::TowardZero);
+TEST_F(LlvmLibcAtanfExhaustiveTest, NegativeRange) {
+  test_full_range_all_roundings(NEG_START, NEG_STOP);
 }

diff  --git a/libc/test/src/math/exhaustive/atanhf_test.cpp b/libc/test/src/math/exhaustive/atanhf_test.cpp
index b4746a8349c62..17bd6ec9dda04 100644
--- a/libc/test/src/math/exhaustive/atanhf_test.cpp
+++ b/libc/test/src/math/exhaustive/atanhf_test.cpp
@@ -11,68 +11,24 @@
 #include "src/math/atanhf.h"
 #include "utils/MPFRWrapper/MPFRUtils.h"
 
-#include <thread>
-
 using FPBits = __llvm_libc::fputil::FPBits<float>;
 
-namespace mpfr = __llvm_libc::testing::mpfr;
-
-struct LlvmLibcAtanhfExhaustiveTest : public LlvmLibcExhaustiveTest<uint32_t> {
-  bool check(uint32_t start, uint32_t stop,
-             mpfr::RoundingMode rounding) override {
-    mpfr::ForceRoundingMode r(rounding);
-    if (!r.success)
-      return true;
-    uint32_t bits = start;
-    bool result = true;
-    do {
-      FPBits xbits(bits);
-      float x = float(xbits);
-      result &= TEST_MPFR_MATCH(mpfr::Operation::Atanh, x,
-                                __llvm_libc::atanhf(x), 0.5, rounding);
-    } while (bits++ < stop);
-    return result;
-  }
-};
-
-static const int NUM_THREADS = std::thread::hardware_concurrency();
+using LlvmLibcAtanhfExhaustiveTest =
+    LlvmLibcUnaryOpExhaustiveMathTest<float, mpfr::Operation::Atanh,
+                                      __llvm_libc::atanhf>;
 
 // Range: [0, 1.0];
 static const uint32_t POS_START = 0x0000'0000U;
 static const uint32_t POS_STOP = FPBits(1.0f).uintval();
 
-TEST_F(LlvmLibcAtanhfExhaustiveTest, PostiveRangeRoundNearestTieToEven) {
-  test_full_range(POS_START, POS_STOP, mpfr::RoundingMode::Nearest);
-}
-
-TEST_F(LlvmLibcAtanhfExhaustiveTest, PostiveRangeRoundUp) {
-  test_full_range(POS_START, POS_STOP, mpfr::RoundingMode::Upward);
-}
-
-TEST_F(LlvmLibcAtanhfExhaustiveTest, PostiveRangeRoundDown) {
-  test_full_range(POS_START, POS_STOP, mpfr::RoundingMode::Downward);
-}
-
-TEST_F(LlvmLibcAtanhfExhaustiveTest, PostiveRangeRoundTowardZero) {
-  test_full_range(POS_START, POS_STOP, mpfr::RoundingMode::TowardZero);
+TEST_F(LlvmLibcAtanhfExhaustiveTest, PostiveRange) {
+  test_full_range_all_roundings(POS_START, POS_STOP);
 }
 
 // Range: [-1.0, 0];
 static const uint32_t NEG_START = 0x8000'0000U;
 static const uint32_t NEG_STOP = FPBits(-1.0f).uintval();
 
-TEST_F(LlvmLibcAtanhfExhaustiveTest, NegativeRangeRoundNearestTieToEven) {
-  test_full_range(NEG_START, NEG_STOP, mpfr::RoundingMode::Nearest);
-}
-
-TEST_F(LlvmLibcAtanhfExhaustiveTest, NegativeRangeRoundUp) {
-  test_full_range(NEG_START, NEG_STOP, mpfr::RoundingMode::Upward);
-}
-
-TEST_F(LlvmLibcAtanhfExhaustiveTest, NegativeRangeRoundDown) {
-  test_full_range(NEG_START, NEG_STOP, mpfr::RoundingMode::Downward);
-}
-
-TEST_F(LlvmLibcAtanhfExhaustiveTest, NegativeRangeRoundTowardZero) {
-  test_full_range(NEG_START, NEG_STOP, mpfr::RoundingMode::TowardZero);
+TEST_F(LlvmLibcAtanhfExhaustiveTest, NegativeRange) {
+  test_full_range_all_roundings(NEG_START, NEG_STOP);
 }

diff  --git a/libc/test/src/math/exhaustive/cosf_test.cpp b/libc/test/src/math/exhaustive/cosf_test.cpp
index 67bd0c5140843..465d8242bc854 100644
--- a/libc/test/src/math/exhaustive/cosf_test.cpp
+++ b/libc/test/src/math/exhaustive/cosf_test.cpp
@@ -7,72 +7,27 @@
 //===----------------------------------------------------------------------===//
 
 #include "exhaustive_test.h"
-#include "src/__support/FPUtil/FPBits.h"
 #include "src/math/cosf.h"
-#include "test/UnitTest/FPMatcher.h"
 #include "utils/MPFRWrapper/MPFRUtils.h"
 
-#include <thread>
-
-using FPBits = __llvm_libc::fputil::FPBits<float>;
-
 namespace mpfr = __llvm_libc::testing::mpfr;
 
-struct LlvmLibcCosfExhaustiveTest : public LlvmLibcExhaustiveTest<uint32_t> {
-  bool check(uint32_t start, uint32_t stop,
-             mpfr::RoundingMode rounding) override {
-    mpfr::ForceRoundingMode r(rounding);
-    if (!r.success)
-      return true;
-    uint32_t bits = start;
-    bool result = true;
-    do {
-      FPBits xbits(bits);
-      float x = float(xbits);
-      bool r = TEST_MPFR_MATCH(mpfr::Operation::Cos, x, __llvm_libc::cosf(x),
-                               0.5, rounding);
-      result &= r;
-    } while (++bits < stop);
-    return result;
-  }
-};
+using LlvmLibcCosfExhaustiveTest =
+    LlvmLibcUnaryOpExhaustiveMathTest<float, mpfr::Operation::Cos,
+                                      __llvm_libc::cosf>;
 
-// Range: [0, +Inf);
+// Range: [0, Inf];
 static constexpr uint32_t POS_START = 0x0000'0000U;
 static constexpr uint32_t POS_STOP = 0x7f80'0000U;
 
-TEST_F(LlvmLibcCosfExhaustiveTest, PostiveRangeRoundNearestTieToEven) {
-  test_full_range(POS_START, POS_STOP, mpfr::RoundingMode::Nearest);
-}
-
-TEST_F(LlvmLibcCosfExhaustiveTest, PostiveRangeRoundUp) {
-  test_full_range(POS_START, POS_STOP, mpfr::RoundingMode::Upward);
-}
-
-TEST_F(LlvmLibcCosfExhaustiveTest, PostiveRangeRoundDown) {
-  test_full_range(POS_START, POS_STOP, mpfr::RoundingMode::Downward);
-}
-
-TEST_F(LlvmLibcCosfExhaustiveTest, PostiveRangeRoundTowardZero) {
-  test_full_range(POS_START, POS_STOP, mpfr::RoundingMode::TowardZero);
+TEST_F(LlvmLibcCosfExhaustiveTest, PostiveRange) {
+  test_full_range_all_roundings(POS_START, POS_STOP);
 }
 
-// Range: (-Inf, 0];
-static constexpr uint32_t NEG_START = 0x8000'0000U;
+// Range: [-Inf, 0];
+static constexpr uint32_t NEG_START = 0xb000'0000U;
 static constexpr uint32_t NEG_STOP = 0xff80'0000U;
 
-TEST_F(LlvmLibcCosfExhaustiveTest, NegativeRangeRoundNearestTieToEven) {
-  test_full_range(NEG_START, NEG_STOP, mpfr::RoundingMode::Nearest);
-}
-
-TEST_F(LlvmLibcCosfExhaustiveTest, NegativeRangeRoundUp) {
-  test_full_range(NEG_START, NEG_STOP, mpfr::RoundingMode::Upward);
-}
-
-TEST_F(LlvmLibcCosfExhaustiveTest, NegativeRangeRoundDown) {
-  test_full_range(NEG_START, NEG_STOP, mpfr::RoundingMode::Downward);
-}
-
-TEST_F(LlvmLibcCosfExhaustiveTest, NegativeRangeRoundTowardZero) {
-  test_full_range(NEG_START, NEG_STOP, mpfr::RoundingMode::TowardZero);
+TEST_F(LlvmLibcCosfExhaustiveTest, NegativeRange) {
+  test_full_range_all_roundings(NEG_START, NEG_STOP);
 }

diff  --git a/libc/test/src/math/exhaustive/coshf_test.cpp b/libc/test/src/math/exhaustive/coshf_test.cpp
index ce7a000d98477..5fb4856b0cf79 100644
--- a/libc/test/src/math/exhaustive/coshf_test.cpp
+++ b/libc/test/src/math/exhaustive/coshf_test.cpp
@@ -7,51 +7,27 @@
 //===----------------------------------------------------------------------===//
 
 #include "exhaustive_test.h"
-#include "src/__support/FPUtil/FPBits.h"
 #include "src/math/coshf.h"
-#include "test/UnitTest/FPMatcher.h"
 #include "utils/MPFRWrapper/MPFRUtils.h"
 
-#include <thread>
-
-using FPBits = __llvm_libc::fputil::FPBits<float>;
-
 namespace mpfr = __llvm_libc::testing::mpfr;
 
-struct LlvmLibcCoshfExhaustiveTest : public LlvmLibcExhaustiveTest<uint32_t> {
-  bool check(uint32_t start, uint32_t stop,
-             mpfr::RoundingMode rounding) override {
-    mpfr::ForceRoundingMode r(rounding);
-    if (!r.success)
-      return true;
-    uint32_t bits = start;
-    bool result = true;
-    do {
-      FPBits xbits(bits);
-      float x = float(xbits);
-      result &= TEST_MPFR_MATCH(mpfr::Operation::Cosh, x, __llvm_libc::coshf(x),
-                                0.5, rounding);
-    } while (bits++ < stop);
-    return result;
-  }
-};
+using LlvmLibcCoshfExhaustiveTest =
+    LlvmLibcUnaryOpExhaustiveMathTest<float, mpfr::Operation::Cosh,
+                                      __llvm_libc::coshf>;
 
-// Range: [0, 90];
+// Range: [0, Inf];
 static constexpr uint32_t POS_START = 0x0000'0000U;
-static constexpr uint32_t POS_STOP = 0x42b4'0000U;
+static constexpr uint32_t POS_STOP = 0x7f80'0000U;
 
-TEST_F(LlvmLibcCoshfExhaustiveTest, PostiveRangeRoundNearestTieToEven) {
-  test_full_range(POS_START, POS_STOP, mpfr::RoundingMode::Nearest);
+TEST_F(LlvmLibcCoshfExhaustiveTest, PostiveRange) {
+  test_full_range_all_roundings(POS_START, POS_STOP);
 }
 
-TEST_F(LlvmLibcCoshfExhaustiveTest, PostiveRangeRoundUp) {
-  test_full_range(POS_START, POS_STOP, mpfr::RoundingMode::Upward);
-}
-
-TEST_F(LlvmLibcCoshfExhaustiveTest, PostiveRangeRoundDown) {
-  test_full_range(POS_START, POS_STOP, mpfr::RoundingMode::Downward);
-}
+// Range: [-Inf, 0];
+static constexpr uint32_t NEG_START = 0xb000'0000U;
+static constexpr uint32_t NEG_STOP = 0xff80'0000U;
 
-TEST_F(LlvmLibcCoshfExhaustiveTest, PostiveRangeRoundTowardZero) {
-  test_full_range(POS_START, POS_STOP, mpfr::RoundingMode::TowardZero);
+TEST_F(LlvmLibcCoshfExhaustiveTest, NegativeRange) {
+  test_full_range_all_roundings(NEG_START, NEG_STOP);
 }

diff  --git a/libc/test/src/math/exhaustive/exhaustive_test.cpp b/libc/test/src/math/exhaustive/exhaustive_test.cpp
deleted file mode 100644
index a6d8929560c9e..0000000000000
--- a/libc/test/src/math/exhaustive/exhaustive_test.cpp
+++ /dev/null
@@ -1,94 +0,0 @@
-//===-- Exhaustive test template for math functions -------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include <atomic>
-#include <fenv.h>
-#include <functional>
-#include <iostream>
-#include <mutex>
-#include <sstream>
-#include <thread>
-#include <vector>
-
-#include "src/__support/FPUtil/FPBits.h"
-
-#include "exhaustive_test.h"
-
-template <typename T, typename FloatType>
-void LlvmLibcExhaustiveTest<T, FloatType>::test_full_range(
-    T start, T stop, mpfr::RoundingMode rounding) {
-  int n_threads = std::thread::hardware_concurrency();
-  std::vector<std::thread> thread_list;
-  std::mutex mx_cur_val;
-  int current_percent = -1;
-  T current_value = start;
-  std::atomic<uint64_t> failed(0);
-  for (int i = 0; i < n_threads; ++i) {
-    thread_list.emplace_back([&, this]() {
-      while (true) {
-        T range_begin, range_end;
-        int new_percent = -1;
-        {
-          std::lock_guard<std::mutex> lock(mx_cur_val);
-          if (current_value == stop)
-            return;
-
-          range_begin = current_value;
-          if (stop >= increment && stop - increment >= current_value) {
-            range_end = current_value + increment;
-          } else {
-            range_end = stop;
-          }
-          current_value = range_end;
-          int pc = 100.0 * (range_end - start) / (stop - start);
-          if (current_percent != pc) {
-            new_percent = pc;
-            current_percent = pc;
-          }
-        }
-        if (new_percent >= 0) {
-          std::stringstream msg;
-          msg << new_percent << "% is in process     \r";
-          std::cout << msg.str() << std::flush;
-        }
-
-        bool check_passed = check(range_begin, range_end, rounding);
-        if (!check_passed) {
-          std::stringstream msg;
-          msg << "Test failed in range: " << std::dec << range_begin << " to "
-              << range_end << " [0x" << std::hex << range_begin << ", 0x"
-              << range_end << "), [" << std::hexfloat
-              << static_cast<FloatType>(__llvm_libc::fputil::FPBits<FloatType>(
-                     static_cast<T>(range_begin)))
-              << ", "
-              << static_cast<FloatType>(
-                     __llvm_libc::fputil::FPBits<FloatType>(range_end))
-              << ") " << std::endl;
-          std::cerr << msg.str() << std::flush;
-
-          failed.fetch_add(1);
-        }
-      }
-    });
-  }
-
-  for (auto &thread : thread_list) {
-    if (thread.joinable()) {
-      thread.join();
-    }
-  }
-  std::cout << std::endl;
-  std::cout << "Test " << ((failed > 0) ? "FAILED" : "PASSED") << std::endl;
-  ASSERT_EQ(failed.load(), uint64_t(0));
-}
-
-template void
-    LlvmLibcExhaustiveTest<uint32_t>::test_full_range(uint32_t, uint32_t,
-                                                      mpfr::RoundingMode);
-template void LlvmLibcExhaustiveTest<uint64_t, double>::test_full_range(
-    uint64_t, uint64_t, mpfr::RoundingMode);

diff  --git a/libc/test/src/math/exhaustive/exhaustive_test.h b/libc/test/src/math/exhaustive/exhaustive_test.h
index 9f9b6bfc1cf5c..00dad034dd6cc 100644
--- a/libc/test/src/math/exhaustive/exhaustive_test.h
+++ b/libc/test/src/math/exhaustive/exhaustive_test.h
@@ -8,25 +8,164 @@
 
 #include "src/__support/CPP/type_traits.h"
 #include "src/__support/FPUtil/FPBits.h"
+#include "test/UnitTest/FPMatcher.h"
 #include "test/UnitTest/Test.h"
 #include "utils/MPFRWrapper/MPFRUtils.h"
 
+#include <atomic>
+#include <functional>
+#include <iostream>
+#include <mutex>
+#include <sstream>
+#include <thread>
+#include <vector>
+
 // To test exhaustively for inputs in the range [start, stop) in parallel:
-// 1. Inherit from LlvmLibcExhaustiveTest class
-// 2. Overide the test method: void check(T, T, RoundingMode)
-// 4. Call: test_full_range(start, stop, nthreads, rounding)
+// 1. Define a Checker class with:
+//    - FloatType: define floating point type to be used.
+//    - FPBits: fputil::FPBits<FloatType>.
+//    - UIntType: define bit type for the corresponding floating point type.
+//    - uint64_t check(start, stop, rounding_mode): a method to test in given
+//          range for a given rounding mode, which returns the number of
+//          failures.
+// 2. Use LlvmLibcExhaustiveMathTest<Checker> class
+// 3. Call: test_full_range(start, stop, nthreads, rounding)
+//       or test_full_range_all_roundings(start, stop).
+// * For single input single output math function, use the convenient template:
+//   LlvmLibcUnaryOpExhaustiveMathTest<FloatType, Op, Func>.
 namespace mpfr = __llvm_libc::testing::mpfr;
 
-template <typename T, typename FloatType = float>
-struct LlvmLibcExhaustiveTest : public __llvm_libc::testing::Test {
-  static constexpr T increment = (1 << 20);
-  static_assert(
-      __llvm_libc::cpp::is_same_v<
-          T, typename __llvm_libc::fputil::FPBits<FloatType>::UIntType>,
-      "Types are not consistent");
+template <typename T> using UnaryOp = T(T);
+
+template <typename T, mpfr::Operation Op, UnaryOp<T> Func>
+struct UnaryOpChecker : public virtual __llvm_libc::testing::Test {
+  using FloatType = T;
+  using FPBits = __llvm_libc::fputil::FPBits<FloatType>;
+  using UIntType = typename FPBits::UIntType;
+
+  static constexpr UnaryOp<FloatType> *FUNC = Func;
+
+  // Check in a range, return the number of failures.
+  uint64_t check(UIntType start, UIntType stop, mpfr::RoundingMode rounding) {
+    mpfr::ForceRoundingMode r(rounding);
+    if (!r.success)
+      return (stop > start);
+    UIntType bits = start;
+    uint64_t failed = 0;
+    do {
+      FPBits xbits(bits);
+      FloatType x = FloatType(xbits);
+      bool correct =
+          TEST_MPFR_MATCH_ROUNDING_SILENTLY(Op, x, FUNC(x), 0.5, rounding);
+      failed += (!correct);
+      // Uncomment to print out failed values.
+      // if (!correct) {
+      //   TEST_MPFR_MATCH(Op::Operation, x, Op::func(x), 0.5, rounding);
+      // }
+    } while (bits++ < stop);
+    return failed;
+  }
+};
+
+// Checker class needs inherit from __llvm_libc::testing::Test and provide
+//   UIntType and check method.
+template <typename Checker>
+struct LlvmLibcExhaustiveMathTest : public virtual __llvm_libc::testing::Test,
+                                    public Checker {
+  using FloatType = typename Checker::FloatType;
+  using FPBits = typename Checker::FPBits;
+  using UIntType = typename Checker::UIntType;
+
+  static constexpr UIntType INCREMENT = (1 << 20);
+
   // Break [start, stop) into `nthreads` subintervals and apply *check to each
   // subinterval in parallel.
-  void test_full_range(T start, T stop, mpfr::RoundingMode rounding);
+  void test_full_range(UIntType start, UIntType stop,
+                       mpfr::RoundingMode rounding) {
+    int n_threads = std::thread::hardware_concurrency();
+    std::vector<std::thread> thread_list;
+    std::mutex mx_cur_val;
+    int current_percent = -1;
+    UIntType current_value = start;
+    std::atomic<uint64_t> failed(0);
+
+    for (int i = 0; i < n_threads; ++i) {
+      thread_list.emplace_back([&, this]() {
+        while (true) {
+          UIntType range_begin, range_end;
+          int new_percent = -1;
+          {
+            std::lock_guard<std::mutex> lock(mx_cur_val);
+            if (current_value == stop)
+              return;
 
-  virtual bool check(T start, T stop, mpfr::RoundingMode rounding) = 0;
+            range_begin = current_value;
+            if (stop >= INCREMENT && stop - INCREMENT >= current_value) {
+              range_end = current_value + INCREMENT;
+            } else {
+              range_end = stop;
+            }
+            current_value = range_end;
+            int pc = 100.0 * (range_end - start) / (stop - start);
+            if (current_percent != pc) {
+              new_percent = pc;
+              current_percent = pc;
+            }
+          }
+          if (new_percent >= 0) {
+            std::stringstream msg;
+            msg << new_percent << "% is in process     \r";
+            std::cout << msg.str() << std::flush;
+          }
+
+          uint64_t failed_in_range =
+              Checker::check(range_begin, range_end, rounding);
+          if (failed_in_range > 0) {
+            std::stringstream msg;
+            msg << "Test failed for " << std::dec << failed_in_range
+                << " inputs in range: " << range_begin << " to " << range_end
+                << " [0x" << std::hex << range_begin << ", 0x" << range_end
+                << "), [" << std::hexfloat
+                << static_cast<FloatType>(FPBits(range_begin)) << ", "
+                << static_cast<FloatType>(FPBits(range_end)) << ")\n";
+            std::cerr << msg.str() << std::flush;
+
+            failed.fetch_add(failed_in_range);
+          }
+        }
+      });
+    }
+
+    for (auto &thread : thread_list) {
+      if (thread.joinable()) {
+        thread.join();
+      }
+    }
+
+    std::cout << std::endl;
+    std::cout << "Test " << ((failed > 0) ? "FAILED" : "PASSED") << std::endl;
+    ASSERT_EQ(failed.load(), uint64_t(0));
+  }
+
+  void test_full_range_all_roundings(UIntType start, UIntType stop) {
+    std::cout << "-- Testing for FE_TONEAREST in range [0x" << std::hex << start
+              << ", 0x" << stop << ") --" << std::dec << std::endl;
+    test_full_range(start, stop, mpfr::RoundingMode::Nearest);
+
+    std::cout << "-- Testing for FE_UPWARD in range [0x" << std::hex << start
+              << ", 0x" << stop << ") --" << std::dec << std::endl;
+    test_full_range(start, stop, mpfr::RoundingMode::Upward);
+
+    std::cout << "-- Testing for FE_DOWNWARD in range [0x" << std::hex << start
+              << ", 0x" << stop << ") --" << std::dec << std::endl;
+    test_full_range(start, stop, mpfr::RoundingMode::Downward);
+
+    std::cout << "-- Testing for FE_TOWARDZERO in range [0x" << std::hex
+              << start << ", 0x" << stop << ") --" << std::dec << std::endl;
+    test_full_range(start, stop, mpfr::RoundingMode::TowardZero);
+  };
 };
+
+template <typename FloatType, mpfr::Operation Op, UnaryOp<FloatType> Func>
+using LlvmLibcUnaryOpExhaustiveMathTest =
+    LlvmLibcExhaustiveMathTest<UnaryOpChecker<FloatType, Op, Func>>;

diff  --git a/libc/test/src/math/exhaustive/exp10f_test.cpp b/libc/test/src/math/exhaustive/exp10f_test.cpp
index 67f9514b358a9..eba0f65de1a8f 100644
--- a/libc/test/src/math/exhaustive/exp10f_test.cpp
+++ b/libc/test/src/math/exhaustive/exp10f_test.cpp
@@ -7,71 +7,27 @@
 //===----------------------------------------------------------------------===//
 
 #include "exhaustive_test.h"
-#include "src/__support/FPUtil/FPBits.h"
 #include "src/math/exp10f.h"
-#include "test/UnitTest/FPMatcher.h"
 #include "utils/MPFRWrapper/MPFRUtils.h"
 
-#include <thread>
-
-using FPBits = __llvm_libc::fputil::FPBits<float>;
-
 namespace mpfr = __llvm_libc::testing::mpfr;
 
-struct LlvmLibcExp10fExhaustiveTest : public LlvmLibcExhaustiveTest<uint32_t> {
-  bool check(uint32_t start, uint32_t stop,
-             mpfr::RoundingMode rounding) override {
-    mpfr::ForceRoundingMode r(rounding);
-    if (!r.success)
-      return true;
-    uint32_t bits = start;
-    bool result = true;
-    do {
-      FPBits xbits(bits);
-      float x = float(xbits);
-      result &= TEST_MPFR_MATCH(mpfr::Operation::Exp10, x,
-                                __llvm_libc::exp10f(x), 0.5, rounding);
-    } while (bits++ < stop);
-    return result;
-  }
-};
+using LlvmLibcExp10fExhaustiveTest =
+    LlvmLibcUnaryOpExhaustiveMathTest<float, mpfr::Operation::Exp10,
+                                      __llvm_libc::exp10f>;
 
-// Range: [0, 89];
+// Range: [0, Inf];
 static constexpr uint32_t POS_START = 0x0000'0000U;
-static constexpr uint32_t POS_STOP = 0x42b2'0000U;
-
-TEST_F(LlvmLibcExp10fExhaustiveTest, PostiveRangeRoundNearestTieToEven) {
-  test_full_range(POS_START, POS_STOP, mpfr::RoundingMode::Nearest);
-}
-
-TEST_F(LlvmLibcExp10fExhaustiveTest, PostiveRangeRoundUp) {
-  test_full_range(POS_START, POS_STOP, mpfr::RoundingMode::Upward);
-}
-
-TEST_F(LlvmLibcExp10fExhaustiveTest, PostiveRangeRoundDown) {
-  test_full_range(POS_START, POS_STOP, mpfr::RoundingMode::Downward);
-}
-
-TEST_F(LlvmLibcExp10fExhaustiveTest, PostiveRangeRoundTowardZero) {
-  test_full_range(POS_START, POS_STOP, mpfr::RoundingMode::TowardZero);
-}
-
-// Range: [-104, 0];
-static constexpr uint32_t NEG_START = 0x8000'0000U;
-static constexpr uint32_t NEG_STOP = 0xc2d0'0000U;
+static constexpr uint32_t POS_STOP = 0x7f80'0000U;
 
-TEST_F(LlvmLibcExp10fExhaustiveTest, NegativeRangeRoundNearestTieToEven) {
-  test_full_range(NEG_START, NEG_STOP, mpfr::RoundingMode::Nearest);
+TEST_F(LlvmLibcExp10fExhaustiveTest, PostiveRange) {
+  test_full_range_all_roundings(POS_START, POS_STOP);
 }
 
-TEST_F(LlvmLibcExp10fExhaustiveTest, NegativeRangeRoundUp) {
-  test_full_range(NEG_START, NEG_STOP, mpfr::RoundingMode::Upward);
-}
-
-TEST_F(LlvmLibcExp10fExhaustiveTest, NegativeRangeRoundDown) {
-  test_full_range(NEG_START, NEG_STOP, mpfr::RoundingMode::Downward);
-}
+// Range: [-Inf, 0];
+static constexpr uint32_t NEG_START = 0xb000'0000U;
+static constexpr uint32_t NEG_STOP = 0xff80'0000U;
 
-TEST_F(LlvmLibcExp10fExhaustiveTest, NegativeRangeRoundTowardZero) {
-  test_full_range(NEG_START, NEG_STOP, mpfr::RoundingMode::TowardZero);
+TEST_F(LlvmLibcExp10fExhaustiveTest, NegativeRange) {
+  test_full_range_all_roundings(NEG_START, NEG_STOP);
 }

diff  --git a/libc/test/src/math/exhaustive/exp2f_test.cpp b/libc/test/src/math/exhaustive/exp2f_test.cpp
index de8b230e9f91b..8c9b88988ba68 100644
--- a/libc/test/src/math/exhaustive/exp2f_test.cpp
+++ b/libc/test/src/math/exhaustive/exp2f_test.cpp
@@ -7,69 +7,27 @@
 //===----------------------------------------------------------------------===//
 
 #include "exhaustive_test.h"
-#include "src/__support/FPUtil/FPBits.h"
 #include "src/math/exp2f.h"
-#include "test/UnitTest/FPMatcher.h"
 #include "utils/MPFRWrapper/MPFRUtils.h"
 
-using FPBits = __llvm_libc::fputil::FPBits<float>;
-
 namespace mpfr = __llvm_libc::testing::mpfr;
 
-struct LlvmLibcExp2fExhaustiveTest : public LlvmLibcExhaustiveTest<uint32_t> {
-  bool check(uint32_t start, uint32_t stop,
-             mpfr::RoundingMode rounding) override {
-    mpfr::ForceRoundingMode r(rounding);
-    if (!r.success)
-      return true;
-    uint32_t bits = start;
-    bool result = true;
-    do {
-      FPBits xbits(bits);
-      float x = float(xbits);
-      result &= TEST_MPFR_MATCH(mpfr::Operation::Exp2, x, __llvm_libc::exp2f(x),
-                                0.5, rounding);
-    } while (bits++ < stop);
-    return result;
-  }
-};
+using LlvmLibcExp2fExhaustiveTest =
+    LlvmLibcUnaryOpExhaustiveMathTest<float, mpfr::Operation::Exp2,
+                                      __llvm_libc::exp2f>;
 
-// Range: [0, +Inf];
+// Range: [0, Inf];
 static constexpr uint32_t POS_START = 0x0000'0000U;
 static constexpr uint32_t POS_STOP = 0x7f80'0000U;
 
-TEST_F(LlvmLibcExp2fExhaustiveTest, PostiveRangeRoundNearestTieToEven) {
-  test_full_range(POS_START, POS_STOP, mpfr::RoundingMode::Nearest);
-}
-
-TEST_F(LlvmLibcExp2fExhaustiveTest, PostiveRangeRoundUp) {
-  test_full_range(POS_START, POS_STOP, mpfr::RoundingMode::Upward);
-}
-
-TEST_F(LlvmLibcExp2fExhaustiveTest, PostiveRangeRoundDown) {
-  test_full_range(POS_START, POS_STOP, mpfr::RoundingMode::Downward);
-}
-
-TEST_F(LlvmLibcExp2fExhaustiveTest, PostiveRangeRoundTowardZero) {
-  test_full_range(POS_START, POS_STOP, mpfr::RoundingMode::TowardZero);
+TEST_F(LlvmLibcExp2fExhaustiveTest, PostiveRange) {
+  test_full_range_all_roundings(POS_START, POS_STOP);
 }
 
 // Range: [-Inf, 0];
-static constexpr uint32_t NEG_START = 0x8000'0000U;
+static constexpr uint32_t NEG_START = 0xb000'0000U;
 static constexpr uint32_t NEG_STOP = 0xff80'0000U;
 
-TEST_F(LlvmLibcExp2fExhaustiveTest, NegativeRangeRoundNearestTieToEven) {
-  test_full_range(NEG_START, NEG_STOP, mpfr::RoundingMode::Nearest);
-}
-
-TEST_F(LlvmLibcExp2fExhaustiveTest, NegativeRangeRoundUp) {
-  test_full_range(NEG_START, NEG_STOP, mpfr::RoundingMode::Upward);
-}
-
-TEST_F(LlvmLibcExp2fExhaustiveTest, NegativeRangeRoundDown) {
-  test_full_range(NEG_START, NEG_STOP, mpfr::RoundingMode::Downward);
-}
-
-TEST_F(LlvmLibcExp2fExhaustiveTest, NegativeRangeRoundTowardZero) {
-  test_full_range(NEG_START, NEG_STOP, mpfr::RoundingMode::TowardZero);
+TEST_F(LlvmLibcExp2fExhaustiveTest, NegativeRange) {
+  test_full_range_all_roundings(NEG_START, NEG_STOP);
 }

diff  --git a/libc/test/src/math/exhaustive/expf_test.cpp b/libc/test/src/math/exhaustive/expf_test.cpp
index 64bf814229b39..75002a2de9653 100644
--- a/libc/test/src/math/exhaustive/expf_test.cpp
+++ b/libc/test/src/math/exhaustive/expf_test.cpp
@@ -7,71 +7,27 @@
 //===----------------------------------------------------------------------===//
 
 #include "exhaustive_test.h"
-#include "src/__support/FPUtil/FPBits.h"
 #include "src/math/expf.h"
-#include "test/UnitTest/FPMatcher.h"
 #include "utils/MPFRWrapper/MPFRUtils.h"
 
-#include <thread>
-
-using FPBits = __llvm_libc::fputil::FPBits<float>;
-
 namespace mpfr = __llvm_libc::testing::mpfr;
 
-struct LlvmLibcExpfExhaustiveTest : public LlvmLibcExhaustiveTest<uint32_t> {
-  bool check(uint32_t start, uint32_t stop,
-             mpfr::RoundingMode rounding) override {
-    mpfr::ForceRoundingMode r(rounding);
-    if (!r.success)
-      return true;
-    uint32_t bits = start;
-    bool result = true;
-    do {
-      FPBits xbits(bits);
-      float x = float(xbits);
-      result &= TEST_MPFR_MATCH(mpfr::Operation::Exp, x, __llvm_libc::expf(x),
-                                0.5, rounding);
-    } while (bits++ < stop);
-    return result;
-  }
-};
+using LlvmLibcExpfExhaustiveTest =
+    LlvmLibcUnaryOpExhaustiveMathTest<float, mpfr::Operation::Exp,
+                                      __llvm_libc::expf>;
 
-// Range: [0, 89];
+// Range: [0, Inf];
 static constexpr uint32_t POS_START = 0x0000'0000U;
-static constexpr uint32_t POS_STOP = 0x42b2'0000U;
-
-TEST_F(LlvmLibcExpfExhaustiveTest, PostiveRangeRoundNearestTieToEven) {
-  test_full_range(POS_START, POS_STOP, mpfr::RoundingMode::Nearest);
-}
-
-TEST_F(LlvmLibcExpfExhaustiveTest, PostiveRangeRoundUp) {
-  test_full_range(POS_START, POS_STOP, mpfr::RoundingMode::Upward);
-}
-
-TEST_F(LlvmLibcExpfExhaustiveTest, PostiveRangeRoundDown) {
-  test_full_range(POS_START, POS_STOP, mpfr::RoundingMode::Downward);
-}
-
-TEST_F(LlvmLibcExpfExhaustiveTest, PostiveRangeRoundTowardZero) {
-  test_full_range(POS_START, POS_STOP, mpfr::RoundingMode::TowardZero);
-}
-
-// Range: [-104, 0];
-static constexpr uint32_t NEG_START = 0x8000'0000U;
-static constexpr uint32_t NEG_STOP = 0xc2d0'0000U;
+static constexpr uint32_t POS_STOP = 0x7f80'0000U;
 
-TEST_F(LlvmLibcExpfExhaustiveTest, NegativeRangeRoundNearestTieToEven) {
-  test_full_range(NEG_START, NEG_STOP, mpfr::RoundingMode::Nearest);
+TEST_F(LlvmLibcExpfExhaustiveTest, PostiveRange) {
+  test_full_range_all_roundings(POS_START, POS_STOP);
 }
 
-TEST_F(LlvmLibcExpfExhaustiveTest, NegativeRangeRoundUp) {
-  test_full_range(NEG_START, NEG_STOP, mpfr::RoundingMode::Upward);
-}
-
-TEST_F(LlvmLibcExpfExhaustiveTest, NegativeRangeRoundDown) {
-  test_full_range(NEG_START, NEG_STOP, mpfr::RoundingMode::Downward);
-}
+// Range: [-Inf, 0];
+static constexpr uint32_t NEG_START = 0xb000'0000U;
+static constexpr uint32_t NEG_STOP = 0xff80'0000U;
 
-TEST_F(LlvmLibcExpfExhaustiveTest, NegativeRangeRoundTowardZero) {
-  test_full_range(NEG_START, NEG_STOP, mpfr::RoundingMode::TowardZero);
+TEST_F(LlvmLibcExpfExhaustiveTest, NegativeRange) {
+  test_full_range_all_roundings(NEG_START, NEG_STOP);
 }

diff  --git a/libc/test/src/math/exhaustive/expm1f_test.cpp b/libc/test/src/math/exhaustive/expm1f_test.cpp
index 29543b5b7f9ba..2cd27f1e88f27 100644
--- a/libc/test/src/math/exhaustive/expm1f_test.cpp
+++ b/libc/test/src/math/exhaustive/expm1f_test.cpp
@@ -7,71 +7,27 @@
 //===----------------------------------------------------------------------===//
 
 #include "exhaustive_test.h"
-#include "src/__support/FPUtil/FPBits.h"
 #include "src/math/expm1f.h"
-#include "test/UnitTest/FPMatcher.h"
 #include "utils/MPFRWrapper/MPFRUtils.h"
 
-#include <thread>
-
-using FPBits = __llvm_libc::fputil::FPBits<float>;
-
 namespace mpfr = __llvm_libc::testing::mpfr;
 
-struct LlvmLibcExpm1fExhaustiveTest : public LlvmLibcExhaustiveTest<uint32_t> {
-  bool check(uint32_t start, uint32_t stop,
-             mpfr::RoundingMode rounding) override {
-    mpfr::ForceRoundingMode r(rounding);
-    if (!r.success)
-      return true;
-    uint32_t bits = stop;
-    bool result = true;
-    do {
-      FPBits xbits(bits);
-      float x = float(xbits);
-      result &= TEST_MPFR_MATCH(mpfr::Operation::Expm1, x,
-                                __llvm_libc::expm1f(x), 0.5, rounding);
-    } while (bits-- > start);
-    return result;
-  }
-};
+using LlvmLibcExpm1fExhaustiveTest =
+    LlvmLibcUnaryOpExhaustiveMathTest<float, mpfr::Operation::Expm1,
+                                      __llvm_libc::expm1f>;
 
-// Range: [0, 89];
+// Range: [0, Inf];
 static constexpr uint32_t POS_START = 0x0000'0000U;
-static constexpr uint32_t POS_STOP = 0x42b2'0000U;
-
-TEST_F(LlvmLibcExpm1fExhaustiveTest, PostiveRangeRoundNearestTieToEven) {
-  test_full_range(POS_START, POS_STOP, mpfr::RoundingMode::Nearest);
-}
-
-TEST_F(LlvmLibcExpm1fExhaustiveTest, PostiveRangeRoundUp) {
-  test_full_range(POS_START, POS_STOP, mpfr::RoundingMode::Upward);
-}
-
-TEST_F(LlvmLibcExpm1fExhaustiveTest, PostiveRangeRoundDown) {
-  test_full_range(POS_START, POS_STOP, mpfr::RoundingMode::Downward);
-}
-
-TEST_F(LlvmLibcExpm1fExhaustiveTest, PostiveRangeRoundTowardZero) {
-  test_full_range(POS_START, POS_STOP, mpfr::RoundingMode::TowardZero);
-}
-
-// Range: [-104, 0];
-static constexpr uint32_t NEG_START = 0x8000'0000U;
-static constexpr uint32_t NEG_STOP = 0xc2d0'0000U;
+static constexpr uint32_t POS_STOP = 0x7f80'0000U;
 
-TEST_F(LlvmLibcExpm1fExhaustiveTest, NegativeRangeRoundNearestTieToEven) {
-  test_full_range(NEG_START, NEG_STOP, mpfr::RoundingMode::Nearest);
+TEST_F(LlvmLibcExpm1fExhaustiveTest, PostiveRange) {
+  test_full_range_all_roundings(POS_START, POS_STOP);
 }
 
-TEST_F(LlvmLibcExpm1fExhaustiveTest, NegativeRangeRoundUp) {
-  test_full_range(NEG_START, NEG_STOP, mpfr::RoundingMode::Upward);
-}
-
-TEST_F(LlvmLibcExpm1fExhaustiveTest, NegativeRangeRoundDown) {
-  test_full_range(NEG_START, NEG_STOP, mpfr::RoundingMode::Downward);
-}
+// Range: [-Inf, 0];
+static constexpr uint32_t NEG_START = 0xb000'0000U;
+static constexpr uint32_t NEG_STOP = 0xff80'0000U;
 
-TEST_F(LlvmLibcExpm1fExhaustiveTest, NegativeRangeRoundTowardZero) {
-  test_full_range(NEG_START, NEG_STOP, mpfr::RoundingMode::TowardZero);
+TEST_F(LlvmLibcExpm1fExhaustiveTest, NegativeRange) {
+  test_full_range_all_roundings(NEG_START, NEG_STOP);
 }

diff  --git a/libc/test/src/math/exhaustive/hypotf_test.cpp b/libc/test/src/math/exhaustive/hypotf_test.cpp
index 8463f88c7f26c..c45e7412a7b12 100644
--- a/libc/test/src/math/exhaustive/hypotf_test.cpp
+++ b/libc/test/src/math/exhaustive/hypotf_test.cpp
@@ -13,13 +13,14 @@
 #include "test/UnitTest/FPMatcher.h"
 #include "utils/MPFRWrapper/MPFRUtils.h"
 
-using FPBits = __llvm_libc::fputil::FPBits<float>;
-
 namespace mpfr = __llvm_libc::testing::mpfr;
 
-struct LlvmLibcHypotfExhaustiveTest : public LlvmLibcExhaustiveTest<uint32_t> {
-  bool check(uint32_t start, uint32_t stop,
-             mpfr::RoundingMode rounding) override {
+struct HypotfChecker : public virtual __llvm_libc::testing::Test {
+  using FloatType = float;
+  using FPBits = __llvm_libc::fputil::FPBits<float>;
+  using UIntType = typename FPBits::UIntType;
+
+  uint64_t check(uint32_t start, uint32_t stop, mpfr::RoundingMode rounding) {
     // Range of the second input: [2^37, 2^48).
     constexpr uint32_t Y_START = (37U + 127U) << 23;
     constexpr uint32_t Y_STOP = (48U + 127U) << 23;
@@ -28,41 +29,32 @@ struct LlvmLibcHypotfExhaustiveTest : public LlvmLibcExhaustiveTest<uint32_t> {
     if (!r.success)
       return true;
     uint32_t xbits = start;
-    bool result = true;
+    uint64_t failed = 0;
     do {
       float x = float(FPBits(xbits));
       uint32_t ybits = Y_START;
       do {
         float y = float(FPBits(ybits));
-        result &= TEST_FP_EQ(__llvm_libc::fputil::hypot(x, y),
-                             __llvm_libc::hypotf(x, y));
+        bool correct = TEST_FP_EQ(__llvm_libc::fputil::hypot(x, y),
+                                  __llvm_libc::hypotf(x, y));
         // Using MPFR will be much slower.
         // mpfr::BinaryInput<float> input{x, y};
-        // EXPECT_MPFR_MATCH(mpfr::Operation::Hypot, input,
-        // __llvm_libc::hypotf(x, y), 0.5,
-        //                   rounding);
+        // bool correct = TEST_MPFR_MATCH_ROUNDING_SILENTLY(
+        //     mpfr::Operation::Hypot, input, __llvm_libc::hypotf(x, y), 0.5,
+        //     rounding);
+        failed += (!correct);
       } while (ybits++ < Y_STOP);
     } while (xbits++ < stop);
-    return result;
+    return failed;
   }
 };
 
+using LlvmLibcHypotfExhaustiveTest = LlvmLibcExhaustiveMathTest<HypotfChecker>;
+
 // Range of the first input: [2^23, 2^24);
 static constexpr uint32_t START = (23U + 127U) << 23;
 static constexpr uint32_t STOP = ((23U + 127U) << 23) + 1;
 
-TEST_F(LlvmLibcHypotfExhaustiveTest, RoundNearestTieToEven) {
-  test_full_range(START, STOP, mpfr::RoundingMode::Nearest);
-}
-
-TEST_F(LlvmLibcHypotfExhaustiveTest, RoundUp) {
-  test_full_range(START, STOP, mpfr::RoundingMode::Upward);
-}
-
-TEST_F(LlvmLibcHypotfExhaustiveTest, RoundDown) {
-  test_full_range(START, STOP, mpfr::RoundingMode::Downward);
-}
-
-TEST_F(LlvmLibcHypotfExhaustiveTest, RoundTowardZero) {
-  test_full_range(START, STOP, mpfr::RoundingMode::TowardZero);
+TEST_F(LlvmLibcHypotfExhaustiveTest, PositiveRange) {
+  test_full_range_all_roundings(START, STOP);
 }

diff  --git a/libc/test/src/math/exhaustive/log10f_test.cpp b/libc/test/src/math/exhaustive/log10f_test.cpp
index 58f6ecb513a0f..912fda144be67 100644
--- a/libc/test/src/math/exhaustive/log10f_test.cpp
+++ b/libc/test/src/math/exhaustive/log10f_test.cpp
@@ -7,51 +7,19 @@
 //===----------------------------------------------------------------------===//
 
 #include "exhaustive_test.h"
-#include "src/__support/FPUtil/FPBits.h"
 #include "src/math/log10f.h"
-#include "test/UnitTest/FPMatcher.h"
 #include "utils/MPFRWrapper/MPFRUtils.h"
 
-using FPBits = __llvm_libc::fputil::FPBits<float>;
-
 namespace mpfr = __llvm_libc::testing::mpfr;
 
-struct LlvmLibcLog10fExhaustiveTest : public LlvmLibcExhaustiveTest<uint32_t> {
-  bool check(uint32_t start, uint32_t stop,
-             mpfr::RoundingMode rounding) override {
-    mpfr::ForceRoundingMode r(rounding);
-    if (!r.success)
-      return true;
-    uint32_t bits = start;
-    bool result = true;
-    do {
-      FPBits xbits(bits);
-      float x = float(xbits);
-      result &= TEST_MPFR_MATCH(mpfr::Operation::Log10, x,
-                                __llvm_libc::log10f(x), 0.5, rounding);
-    } while (bits++ < stop);
-    return result;
-  }
-};
-
-// Range: All non-negative;
-static constexpr uint32_t START = 0x0000'0000U;
-static constexpr uint32_t STOP = 0x7f80'0000U;
-// Range: [1, 10];
-// static constexpr uint32_t START = 0x3f80'0000U;
-// static constexpr uint32_t STOP  = 0x41c0'0000U;
-TEST_F(LlvmLibcLog10fExhaustiveTest, RoundNearestTieToEven) {
-  test_full_range(START, STOP, mpfr::RoundingMode::Nearest);
-}
-
-TEST_F(LlvmLibcLog10fExhaustiveTest, RoundUp) {
-  test_full_range(START, STOP, mpfr::RoundingMode::Upward);
-}
+using LlvmLibcLog10fExhaustiveTest =
+    LlvmLibcUnaryOpExhaustiveMathTest<float, mpfr::Operation::Log10,
+                                      __llvm_libc::log10f>;
 
-TEST_F(LlvmLibcLog10fExhaustiveTest, RoundDown) {
-  test_full_range(START, STOP, mpfr::RoundingMode::Downward);
-}
+// Range: [0, Inf];
+static constexpr uint32_t POS_START = 0x0000'0000U;
+static constexpr uint32_t POS_STOP = 0x7f80'0000U;
 
-TEST_F(LlvmLibcLog10fExhaustiveTest, RoundTowardZero) {
-  test_full_range(START, STOP, mpfr::RoundingMode::TowardZero);
+TEST_F(LlvmLibcLog10fExhaustiveTest, PostiveRange) {
+  test_full_range_all_roundings(POS_START, POS_STOP);
 }

diff  --git a/libc/test/src/math/exhaustive/log1pf_test.cpp b/libc/test/src/math/exhaustive/log1pf_test.cpp
index 88944d5c7f499..992781571f035 100644
--- a/libc/test/src/math/exhaustive/log1pf_test.cpp
+++ b/libc/test/src/math/exhaustive/log1pf_test.cpp
@@ -7,69 +7,27 @@
 //===----------------------------------------------------------------------===//
 
 #include "exhaustive_test.h"
-#include "src/__support/FPUtil/FPBits.h"
 #include "src/math/log1pf.h"
-#include "test/UnitTest/FPMatcher.h"
 #include "utils/MPFRWrapper/MPFRUtils.h"
 
-using FPBits = __llvm_libc::fputil::FPBits<float>;
-
 namespace mpfr = __llvm_libc::testing::mpfr;
 
-struct LlvmLibcLog1pfExhaustiveTest : public LlvmLibcExhaustiveTest<uint32_t> {
-  bool check(uint32_t start, uint32_t stop,
-             mpfr::RoundingMode rounding) override {
-    mpfr::ForceRoundingMode r(rounding);
-    if (!r.success)
-      return true;
-    uint32_t bits = start;
-    bool result = true;
-    do {
-      FPBits xbits(bits);
-      float x = float(xbits);
-      result &= TEST_MPFR_MATCH(mpfr::Operation::Log1p, x,
-                                __llvm_libc::log1pf(x), 0.5, rounding);
-    } while (bits++ < stop);
-    return result;
-  }
-};
-
-// Range: All non-negative;
-static constexpr uint32_t START = 0x0000'0000U;
-static constexpr uint32_t STOP = 0x7f80'0000U;
-
-TEST_F(LlvmLibcLog1pfExhaustiveTest, RoundNearestTieToEven) {
-  test_full_range(START, STOP, mpfr::RoundingMode::Nearest);
-}
+using LlvmLibcLog1pfExhaustiveTest =
+    LlvmLibcUnaryOpExhaustiveMathTest<float, mpfr::Operation::Log1p,
+                                      __llvm_libc::log1pf>;
 
-TEST_F(LlvmLibcLog1pfExhaustiveTest, RoundUp) {
-  test_full_range(START, STOP, mpfr::RoundingMode::Upward);
-}
-
-TEST_F(LlvmLibcLog1pfExhaustiveTest, RoundDown) {
-  test_full_range(START, STOP, mpfr::RoundingMode::Downward);
-}
+// Range: [0, Inf];
+static constexpr uint32_t POS_START = 0x0000'0000U;
+static constexpr uint32_t POS_STOP = 0x7f80'0000U;
 
-TEST_F(LlvmLibcLog1pfExhaustiveTest, RoundTowardZero) {
-  test_full_range(START, STOP, mpfr::RoundingMode::TowardZero);
+TEST_F(LlvmLibcLog1pfExhaustiveTest, PostiveRange) {
+  test_full_range_all_roundings(POS_START, POS_STOP);
 }
 
 // Range: [-1, 0];
-static constexpr uint32_t NEG_START = 0x8000'0000U;
+static constexpr uint32_t NEG_START = 0xb000'0000U;
 static constexpr uint32_t NEG_STOP = 0xbf7f'ffffU;
 
-TEST_F(LlvmLibcLog1pfExhaustiveTest, NegativeRoundNearestTieToEven) {
-  test_full_range(NEG_START, NEG_STOP, mpfr::RoundingMode::Nearest);
-}
-
-TEST_F(LlvmLibcLog1pfExhaustiveTest, NegativeRoundUp) {
-  test_full_range(NEG_START, NEG_STOP, mpfr::RoundingMode::Upward);
-}
-
-TEST_F(LlvmLibcLog1pfExhaustiveTest, NegativeRoundDown) {
-  test_full_range(NEG_START, NEG_STOP, mpfr::RoundingMode::Downward);
-}
-
-TEST_F(LlvmLibcLog1pfExhaustiveTest, NegativeRoundTowardZero) {
-  test_full_range(NEG_START, NEG_STOP, mpfr::RoundingMode::TowardZero);
+TEST_F(LlvmLibcLog1pfExhaustiveTest, NegativeRange) {
+  test_full_range_all_roundings(NEG_START, NEG_STOP);
 }

diff  --git a/libc/test/src/math/exhaustive/log2f_test.cpp b/libc/test/src/math/exhaustive/log2f_test.cpp
index fb674ffa7cb07..249ea2e1dfaa1 100644
--- a/libc/test/src/math/exhaustive/log2f_test.cpp
+++ b/libc/test/src/math/exhaustive/log2f_test.cpp
@@ -7,49 +7,19 @@
 //===----------------------------------------------------------------------===//
 
 #include "exhaustive_test.h"
-#include "src/__support/FPUtil/FPBits.h"
 #include "src/math/log2f.h"
-#include "test/UnitTest/FPMatcher.h"
 #include "utils/MPFRWrapper/MPFRUtils.h"
 
-using FPBits = __llvm_libc::fputil::FPBits<float>;
-
 namespace mpfr = __llvm_libc::testing::mpfr;
 
-struct LlvmLibcLog2fExhaustiveTest : public LlvmLibcExhaustiveTest<uint32_t> {
-  bool check(uint32_t start, uint32_t stop,
-             mpfr::RoundingMode rounding) override {
-    mpfr::ForceRoundingMode r(rounding);
-    if (!r.success)
-      return true;
-    uint32_t bits = start;
-    bool result = true;
-    do {
-      FPBits xbits(bits);
-      float x = float(xbits);
-      result &= TEST_MPFR_MATCH(mpfr::Operation::Log2, x, __llvm_libc::log2f(x),
-                                0.5, rounding);
-    } while (bits++ < stop);
-    return result;
-  }
-};
-
-TEST_F(LlvmLibcLog2fExhaustiveTest, RoundNearestTieToEven) {
-  test_full_range(/*start=*/0U, /*stop=*/0x7f80'0000U,
-                  mpfr::RoundingMode::Nearest);
-}
-
-TEST_F(LlvmLibcLog2fExhaustiveTest, RoundUp) {
-  test_full_range(/*start=*/0U, /*stop=*/0x7f80'0000U,
-                  mpfr::RoundingMode::Upward);
-}
+using LlvmLibcLog2fExhaustiveTest =
+    LlvmLibcUnaryOpExhaustiveMathTest<float, mpfr::Operation::Log2,
+                                      __llvm_libc::log2f>;
 
-TEST_F(LlvmLibcLog2fExhaustiveTest, RoundDown) {
-  test_full_range(/*start=*/0U, /*stop=*/0x7f80'0000U,
-                  mpfr::RoundingMode::Downward);
-}
+// Range: [0, Inf];
+static constexpr uint32_t POS_START = 0x0000'0000U;
+static constexpr uint32_t POS_STOP = 0x7f80'0000U;
 
-TEST_F(LlvmLibcLog2fExhaustiveTest, RoundTowardZero) {
-  test_full_range(/*start=*/0U, /*stop=*/0x7f80'0000U,
-                  mpfr::RoundingMode::TowardZero);
+TEST_F(LlvmLibcLog2fExhaustiveTest, PostiveRange) {
+  test_full_range_all_roundings(POS_START, POS_STOP);
 }

diff  --git a/libc/test/src/math/exhaustive/logf_test.cpp b/libc/test/src/math/exhaustive/logf_test.cpp
index e67d6ce74ed6f..cf54ba5e78c23 100644
--- a/libc/test/src/math/exhaustive/logf_test.cpp
+++ b/libc/test/src/math/exhaustive/logf_test.cpp
@@ -7,49 +7,19 @@
 //===----------------------------------------------------------------------===//
 
 #include "exhaustive_test.h"
-#include "src/__support/FPUtil/FPBits.h"
 #include "src/math/logf.h"
-#include "test/UnitTest/FPMatcher.h"
 #include "utils/MPFRWrapper/MPFRUtils.h"
 
-using FPBits = __llvm_libc::fputil::FPBits<float>;
-
 namespace mpfr = __llvm_libc::testing::mpfr;
 
-struct LlvmLibcLogfExhaustiveTest : public LlvmLibcExhaustiveTest<uint32_t> {
-  bool check(uint32_t start, uint32_t stop,
-             mpfr::RoundingMode rounding) override {
-    mpfr::ForceRoundingMode r(rounding);
-    if (!r.success)
-      return true;
-    uint32_t bits = start;
-    bool result = true;
-    do {
-      FPBits xbits(bits);
-      float x = float(xbits);
-      result &= TEST_MPFR_MATCH(mpfr::Operation::Log, x, __llvm_libc::logf(x),
-                                0.5, rounding);
-    } while (bits++ < stop);
-    return result;
-  }
-};
-
-TEST_F(LlvmLibcLogfExhaustiveTest, RoundNearestTieToEven) {
-  test_full_range(/*start=*/0U, /*stop=*/0x7f80'0000U,
-                  mpfr::RoundingMode::Nearest);
-}
-
-TEST_F(LlvmLibcLogfExhaustiveTest, RoundUp) {
-  test_full_range(/*start=*/0U, /*stop=*/0x7f80'0000U,
-                  mpfr::RoundingMode::Upward);
-}
+using LlvmLibcLogfExhaustiveTest =
+    LlvmLibcUnaryOpExhaustiveMathTest<float, mpfr::Operation::Log,
+                                      __llvm_libc::logf>;
 
-TEST_F(LlvmLibcLogfExhaustiveTest, RoundDown) {
-  test_full_range(/*start=*/0U, /*stop=*/0x7f80'0000U,
-                  mpfr::RoundingMode::Downward);
-}
+// Range: [0, Inf];
+static constexpr uint32_t POS_START = 0x0000'0000U;
+static constexpr uint32_t POS_STOP = 0x7f80'0000U;
 
-TEST_F(LlvmLibcLogfExhaustiveTest, RoundTowardZero) {
-  test_full_range(/*start=*/0U, /*stop=*/0x7f80'0000U,
-                  mpfr::RoundingMode::TowardZero);
+TEST_F(LlvmLibcLogfExhaustiveTest, PostiveRange) {
+  test_full_range_all_roundings(POS_START, POS_STOP);
 }

diff  --git a/libc/test/src/math/exhaustive/sincosf_test.cpp b/libc/test/src/math/exhaustive/sincosf_test.cpp
index ecda2cbbf57f8..dfc222821ecb1 100644
--- a/libc/test/src/math/exhaustive/sincosf_test.cpp
+++ b/libc/test/src/math/exhaustive/sincosf_test.cpp
@@ -7,73 +7,55 @@
 //===----------------------------------------------------------------------===//
 
 #include "exhaustive_test.h"
-#include "src/__support/FPUtil/FPBits.h"
 #include "src/math/sincosf.h"
-#include "test/UnitTest/FPMatcher.h"
 #include "utils/MPFRWrapper/MPFRUtils.h"
 
-#include <thread>
-
-using FPBits = __llvm_libc::fputil::FPBits<float>;
-
 namespace mpfr = __llvm_libc::testing::mpfr;
 
-struct LlvmLibcSinCosfExhaustiveTest : public LlvmLibcExhaustiveTest<uint32_t> {
-  bool check(uint32_t start, uint32_t stop,
-             mpfr::RoundingMode rounding) override {
-    mpfr::ForceRoundingMode r(rounding);
-    if (!r.success)
-      return true;
-    uint32_t bits = start;
-    bool result = true;
+struct SincosfChecker : public virtual __llvm_libc::testing::Test {
+  using FloatType = float;
+  using FPBits = __llvm_libc::fputil::FPBits<float>;
+  using UIntType = uint32_t;
+
+  uint64_t check(UIntType start, UIntType stop, mpfr::RoundingMode rounding) {
+    UIntType bits = start;
+    uint64_t failed = 0;
     do {
       FPBits xbits(bits);
-      float x = float(xbits);
-      float sinx, cosx;
+      FloatType x = FloatType(xbits);
+      FloatType sinx, cosx;
       __llvm_libc::sincosf(x, &sinx, &cosx);
-      result &= TEST_MPFR_MATCH(mpfr::Operation::Sin, x, sinx, 0.5, rounding);
-      result &= TEST_MPFR_MATCH(mpfr::Operation::Cos, x, cosx, 0.5, rounding);
-    } while (++bits < stop);
-    return result;
+
+      bool correct = TEST_MPFR_MATCH_ROUNDING_SILENTLY(mpfr::Operation::Sin, x,
+                                                       sinx, 0.5, rounding);
+      correct = correct && TEST_MPFR_MATCH_ROUNDING_SILENTLY(
+                               mpfr::Operation::Cos, x, cosx, 0.5, rounding);
+      failed += (!correct);
+      // Uncomment to print out failed values.
+      // if (!correct) {
+      //   TEST_MPFR_MATCH(mpfr::Operation::Sin, x, sinx, 0.5, rounding);
+      //   TEST_MPFR_MATCH(mpfr::Operation::Cos, x, cosx, 0.5, rounding);
+      // }
+    } while (bits++ < stop);
+    return failed;
   }
 };
 
-// Range: [0, +Inf);
+using LlvmLibcSincosfExhaustiveTest =
+    LlvmLibcExhaustiveMathTest<SincosfChecker>;
+
+// Range: [0, Inf];
 static constexpr uint32_t POS_START = 0x0000'0000U;
 static constexpr uint32_t POS_STOP = 0x7f80'0000U;
 
-TEST_F(LlvmLibcSinCosfExhaustiveTest, PostiveRangeRoundNearestTieToEven) {
-  test_full_range(POS_START, POS_STOP, mpfr::RoundingMode::Nearest);
-}
-
-TEST_F(LlvmLibcSinCosfExhaustiveTest, PostiveRangeRoundUp) {
-  test_full_range(POS_START, POS_STOP, mpfr::RoundingMode::Upward);
-}
-
-TEST_F(LlvmLibcSinCosfExhaustiveTest, PostiveRangeRoundDown) {
-  test_full_range(POS_START, POS_STOP, mpfr::RoundingMode::Downward);
+TEST_F(LlvmLibcSincosfExhaustiveTest, PostiveRange) {
+  test_full_range_all_roundings(POS_START, POS_STOP);
 }
 
-TEST_F(LlvmLibcSinCosfExhaustiveTest, PostiveRangeRoundTowardZero) {
-  test_full_range(POS_START, POS_STOP, mpfr::RoundingMode::TowardZero);
-}
-
-// Range: (-Inf, 0];
-static constexpr uint32_t NEG_START = 0x8000'0000U;
-static constexpr uint32_t NEG_STOP = 0xff80'0000U;
-
-TEST_F(LlvmLibcSinCosfExhaustiveTest, NegativeRangeRoundNearestTieToEven) {
-  test_full_range(NEG_START, NEG_STOP, mpfr::RoundingMode::Nearest);
-}
-
-TEST_F(LlvmLibcSinCosfExhaustiveTest, NegativeRangeRoundUp) {
-  test_full_range(NEG_START, NEG_STOP, mpfr::RoundingMode::Upward);
-}
-
-TEST_F(LlvmLibcSinCosfExhaustiveTest, NegativeRangeRoundDown) {
-  test_full_range(NEG_START, NEG_STOP, mpfr::RoundingMode::Downward);
-}
+// Range: [-1, 0];
+static constexpr uint32_t NEG_START = 0xb000'0000U;
+static constexpr uint32_t NEG_STOP = 0xbf7f'ffffU;
 
-TEST_F(LlvmLibcSinCosfExhaustiveTest, NegativeRangeRoundTowardZero) {
-  test_full_range(NEG_START, NEG_STOP, mpfr::RoundingMode::TowardZero);
+TEST_F(LlvmLibcSincosfExhaustiveTest, NegativeRange) {
+  test_full_range_all_roundings(NEG_START, NEG_STOP);
 }

diff  --git a/libc/test/src/math/exhaustive/sinf_test.cpp b/libc/test/src/math/exhaustive/sinf_test.cpp
index 4749ef68636b8..1c0ce568eadf7 100644
--- a/libc/test/src/math/exhaustive/sinf_test.cpp
+++ b/libc/test/src/math/exhaustive/sinf_test.cpp
@@ -7,72 +7,27 @@
 //===----------------------------------------------------------------------===//
 
 #include "exhaustive_test.h"
-#include "src/__support/FPUtil/FPBits.h"
 #include "src/math/sinf.h"
-#include "test/UnitTest/FPMatcher.h"
 #include "utils/MPFRWrapper/MPFRUtils.h"
 
-#include <thread>
-
-using FPBits = __llvm_libc::fputil::FPBits<float>;
-
 namespace mpfr = __llvm_libc::testing::mpfr;
 
-struct LlvmLibcSinfExhaustiveTest : public LlvmLibcExhaustiveTest<uint32_t> {
-  bool check(uint32_t start, uint32_t stop,
-             mpfr::RoundingMode rounding) override {
-    mpfr::ForceRoundingMode r(rounding);
-    if (!r.success)
-      return true;
-    uint32_t bits = start;
-    bool result = true;
-    do {
-      FPBits xbits(bits);
-      float x = float(xbits);
-      bool r = TEST_MPFR_MATCH(mpfr::Operation::Sin, x, __llvm_libc::sinf(x),
-                               0.5, rounding);
-      result &= r;
-    } while (++bits < stop);
-    return result;
-  }
-};
+using LlvmLibcSinfExhaustiveTest =
+    LlvmLibcUnaryOpExhaustiveMathTest<float, mpfr::Operation::Sin,
+                                      __llvm_libc::sinf>;
 
-// Range: [0, +Inf);
+// Range: [0, Inf];
 static constexpr uint32_t POS_START = 0x0000'0000U;
 static constexpr uint32_t POS_STOP = 0x7f80'0000U;
 
-TEST_F(LlvmLibcSinfExhaustiveTest, PostiveRangeRoundNearestTieToEven) {
-  test_full_range(POS_START, POS_STOP, mpfr::RoundingMode::Nearest);
-}
-
-TEST_F(LlvmLibcSinfExhaustiveTest, PostiveRangeRoundUp) {
-  test_full_range(POS_START, POS_STOP, mpfr::RoundingMode::Upward);
-}
-
-TEST_F(LlvmLibcSinfExhaustiveTest, PostiveRangeRoundDown) {
-  test_full_range(POS_START, POS_STOP, mpfr::RoundingMode::Downward);
-}
-
-TEST_F(LlvmLibcSinfExhaustiveTest, PostiveRangeRoundTowardZero) {
-  test_full_range(POS_START, POS_STOP, mpfr::RoundingMode::TowardZero);
+TEST_F(LlvmLibcSinfExhaustiveTest, PostiveRange) {
+  test_full_range_all_roundings(POS_START, POS_STOP);
 }
 
-// Range: (-Inf, 0];
-static constexpr uint32_t NEG_START = 0x8000'0000U;
+// Range: [-Inf, 0];
+static constexpr uint32_t NEG_START = 0xb000'0000U;
 static constexpr uint32_t NEG_STOP = 0xff80'0000U;
 
-TEST_F(LlvmLibcSinfExhaustiveTest, NegativeRangeRoundNearestTieToEven) {
-  test_full_range(NEG_START, NEG_STOP, mpfr::RoundingMode::Nearest);
-}
-
-TEST_F(LlvmLibcSinfExhaustiveTest, NegativeRangeRoundUp) {
-  test_full_range(NEG_START, NEG_STOP, mpfr::RoundingMode::Upward);
-}
-
-TEST_F(LlvmLibcSinfExhaustiveTest, NegativeRangeRoundDown) {
-  test_full_range(NEG_START, NEG_STOP, mpfr::RoundingMode::Downward);
-}
-
-TEST_F(LlvmLibcSinfExhaustiveTest, NegativeRangeRoundTowardZero) {
-  test_full_range(NEG_START, NEG_STOP, mpfr::RoundingMode::TowardZero);
+TEST_F(LlvmLibcSinfExhaustiveTest, NegativeRange) {
+  test_full_range_all_roundings(NEG_START, NEG_STOP);
 }

diff  --git a/libc/test/src/math/exhaustive/sinhf_test.cpp b/libc/test/src/math/exhaustive/sinhf_test.cpp
index a2fa540a98907..50f1094abf14f 100644
--- a/libc/test/src/math/exhaustive/sinhf_test.cpp
+++ b/libc/test/src/math/exhaustive/sinhf_test.cpp
@@ -7,71 +7,27 @@
 //===----------------------------------------------------------------------===//
 
 #include "exhaustive_test.h"
-#include "src/__support/FPUtil/FPBits.h"
 #include "src/math/sinhf.h"
-#include "test/UnitTest/FPMatcher.h"
 #include "utils/MPFRWrapper/MPFRUtils.h"
 
-#include <thread>
-
-using FPBits = __llvm_libc::fputil::FPBits<float>;
-
 namespace mpfr = __llvm_libc::testing::mpfr;
 
-struct LlvmLibcSinhfExhaustiveTest : public LlvmLibcExhaustiveTest<uint32_t> {
-  bool check(uint32_t start, uint32_t stop,
-             mpfr::RoundingMode rounding) override {
-    mpfr::ForceRoundingMode r(rounding);
-    if (!r.success)
-      return true;
-    uint32_t bits = start;
-    bool result = true;
-    do {
-      FPBits xbits(bits);
-      float x = float(xbits);
-      result &= TEST_MPFR_MATCH(mpfr::Operation::Sinh, x, __llvm_libc::sinhf(x),
-                                0.5, rounding);
-    } while (bits++ < stop);
-    return result;
-  }
-};
+using LlvmLibcSinhfExhaustiveTest =
+    LlvmLibcUnaryOpExhaustiveMathTest<float, mpfr::Operation::Sinh,
+                                      __llvm_libc::sinhf>;
 
-// Range: [0, 90];
+// Range: [0, Inf];
 static constexpr uint32_t POS_START = 0x0000'0000U;
-static constexpr uint32_t POS_STOP = 0x42b4'0000U;
-
-TEST_F(LlvmLibcSinhfExhaustiveTest, PostiveRangeRoundNearestTieToEven) {
-  test_full_range(POS_START, POS_STOP, mpfr::RoundingMode::Nearest);
-}
-
-TEST_F(LlvmLibcSinhfExhaustiveTest, PostiveRangeRoundUp) {
-  test_full_range(POS_START, POS_STOP, mpfr::RoundingMode::Upward);
-}
-
-TEST_F(LlvmLibcSinhfExhaustiveTest, PostiveRangeRoundDown) {
-  test_full_range(POS_START, POS_STOP, mpfr::RoundingMode::Downward);
-}
-
-TEST_F(LlvmLibcSinhfExhaustiveTest, PostiveRangeRoundTowardZero) {
-  test_full_range(POS_START, POS_STOP, mpfr::RoundingMode::TowardZero);
-}
-
-// Range: [-90, 0];
-static constexpr uint32_t NEG_START = 0x8000'0000U;
-static constexpr uint32_t NEG_STOP = 0xc2b4'0000U;
+static constexpr uint32_t POS_STOP = 0x7f80'0000U;
 
-TEST_F(LlvmLibcSinhfExhaustiveTest, NegativeRangeRoundNearestTieToEven) {
-  test_full_range(NEG_START, NEG_STOP, mpfr::RoundingMode::Nearest);
+TEST_F(LlvmLibcSinhfExhaustiveTest, PostiveRange) {
+  test_full_range_all_roundings(POS_START, POS_STOP);
 }
 
-TEST_F(LlvmLibcSinhfExhaustiveTest, NegativeRangeRoundUp) {
-  test_full_range(NEG_START, NEG_STOP, mpfr::RoundingMode::Upward);
-}
-
-TEST_F(LlvmLibcSinhfExhaustiveTest, NegativeRangeRoundDown) {
-  test_full_range(NEG_START, NEG_STOP, mpfr::RoundingMode::Downward);
-}
+// Range: [-Inf, 0];
+static constexpr uint32_t NEG_START = 0xb000'0000U;
+static constexpr uint32_t NEG_STOP = 0xff80'0000U;
 
-TEST_F(LlvmLibcSinhfExhaustiveTest, NegativeRangeRoundTowardZero) {
-  test_full_range(NEG_START, NEG_STOP, mpfr::RoundingMode::TowardZero);
+TEST_F(LlvmLibcSinhfExhaustiveTest, NegativeRange) {
+  test_full_range_all_roundings(NEG_START, NEG_STOP);
 }

diff  --git a/libc/test/src/math/exhaustive/sqrtf_test.cpp b/libc/test/src/math/exhaustive/sqrtf_test.cpp
index 28f7e43f6050c..e475182a9359a 100644
--- a/libc/test/src/math/exhaustive/sqrtf_test.cpp
+++ b/libc/test/src/math/exhaustive/sqrtf_test.cpp
@@ -6,20 +6,20 @@
 //
 //===---------------------------------------------------------------------===//
 
-#include "src/__support/FPUtil/FPBits.h"
+#include "exhaustive_test.h"
 #include "src/math/sqrtf.h"
 #include "utils/MPFRWrapper/MPFRUtils.h"
-#include <math.h>
-
-using FPBits = __llvm_libc::fputil::FPBits<float>;
 
 namespace mpfr = __llvm_libc::testing::mpfr;
 
-TEST(LlvmLibcSqrtfExhaustiveTest, AllValues) {
-  uint32_t bits = 0;
-  do {
-    FPBits xbits(bits);
-    float x = float(xbits);
-    ASSERT_MPFR_MATCH(mpfr::Operation::Sqrt, x, __llvm_libc::sqrtf(x), 0.5);
-  } while (bits++ < 0xffff'ffffU);
+using LlvmLibcSqrtfExhaustiveTest =
+    LlvmLibcUnaryOpExhaustiveMathTest<float, mpfr::Operation::Sqrt,
+                                      __llvm_libc::sqrtf>;
+
+// Range: [0, Inf];
+static constexpr uint32_t POS_START = 0x0000'0000U;
+static constexpr uint32_t POS_STOP = 0x7f80'0000U;
+
+TEST_F(LlvmLibcSqrtfExhaustiveTest, PostiveRange) {
+  test_full_range_all_roundings(POS_START, POS_STOP);
 }

diff  --git a/libc/test/src/math/exhaustive/tanf_test.cpp b/libc/test/src/math/exhaustive/tanf_test.cpp
index 3597517de3d9b..9e1278b4c3ea5 100644
--- a/libc/test/src/math/exhaustive/tanf_test.cpp
+++ b/libc/test/src/math/exhaustive/tanf_test.cpp
@@ -8,79 +8,27 @@
 //===----------------------------------------------------------------------===//
 
 #include "exhaustive_test.h"
-#include "src/__support/FPUtil/FPBits.h"
 #include "src/math/tanf.h"
-#include "test/UnitTest/FPMatcher.h"
 #include "utils/MPFRWrapper/MPFRUtils.h"
 
-#include <thread>
-
-using FPBits = __llvm_libc::fputil::FPBits<float>;
-
 namespace mpfr = __llvm_libc::testing::mpfr;
 
-static constexpr int TOLERANCE = 3;
+using LlvmLibcTanfExhaustiveTest =
+    LlvmLibcUnaryOpExhaustiveMathTest<float, mpfr::Operation::Tan,
+                                      __llvm_libc::tanf>;
 
-struct LlvmLibcTanfExhaustiveTest : public LlvmLibcExhaustiveTest<uint32_t> {
-  bool check(uint32_t start, uint32_t stop,
-             mpfr::RoundingMode rounding) override {
-    mpfr::ForceRoundingMode r(rounding);
-    if (!r.success)
-      return true;
-    uint32_t bits = start;
-    bool result = true;
-    int tol = TOLERANCE;
-    do {
-      FPBits xbits(bits);
-      float x = float(xbits);
-      bool r = TEST_MPFR_MATCH(mpfr::Operation::Tan, x, __llvm_libc::tanf(x),
-                               0.5, rounding);
-      result &= r;
-      if (!r)
-        --tol;
-      if (!tol)
-        break;
-    } while (++bits < stop);
-    return result;
-  }
-};
-
-// Range: [0, +Inf);
+// Range: [0, Inf];
 static constexpr uint32_t POS_START = 0x0000'0000U;
 static constexpr uint32_t POS_STOP = 0x7f80'0000U;
 
-TEST_F(LlvmLibcTanfExhaustiveTest, PostiveRangeRoundNearestTieToEven) {
-  test_full_range(POS_START, POS_STOP, mpfr::RoundingMode::Nearest);
-}
-
-TEST_F(LlvmLibcTanfExhaustiveTest, PostiveRangeRoundUp) {
-  test_full_range(POS_START, POS_STOP, mpfr::RoundingMode::Upward);
-}
-
-TEST_F(LlvmLibcTanfExhaustiveTest, PostiveRangeRoundDown) {
-  test_full_range(POS_START, POS_STOP, mpfr::RoundingMode::Downward);
+TEST_F(LlvmLibcTanfExhaustiveTest, PostiveRange) {
+  test_full_range_all_roundings(POS_START, POS_STOP);
 }
 
-TEST_F(LlvmLibcTanfExhaustiveTest, PostiveRangeRoundTowardZero) {
-  test_full_range(POS_START, POS_STOP, mpfr::RoundingMode::TowardZero);
-}
-
-// Range: (-Inf, 0];
-static constexpr uint32_t NEG_START = 0x8000'0000U;
+// Range: [-Inf, 0];
+static constexpr uint32_t NEG_START = 0xb000'0000U;
 static constexpr uint32_t NEG_STOP = 0xff80'0000U;
 
-TEST_F(LlvmLibcTanfExhaustiveTest, NegativeRangeRoundNearestTieToEven) {
-  test_full_range(NEG_START, NEG_STOP, mpfr::RoundingMode::Nearest);
-}
-
-TEST_F(LlvmLibcTanfExhaustiveTest, NegativeRangeRoundUp) {
-  test_full_range(NEG_START, NEG_STOP, mpfr::RoundingMode::Upward);
-}
-
-TEST_F(LlvmLibcTanfExhaustiveTest, NegativeRangeRoundDown) {
-  test_full_range(NEG_START, NEG_STOP, mpfr::RoundingMode::Downward);
-}
-
-TEST_F(LlvmLibcTanfExhaustiveTest, NegativeRangeRoundTowardZero) {
-  test_full_range(NEG_START, NEG_STOP, mpfr::RoundingMode::TowardZero);
+TEST_F(LlvmLibcTanfExhaustiveTest, NegativeRange) {
+  test_full_range_all_roundings(NEG_START, NEG_STOP);
 }

diff  --git a/libc/test/src/math/exhaustive/tanhf_test.cpp b/libc/test/src/math/exhaustive/tanhf_test.cpp
index c7bb4e8e112e3..3c3951c14ffdc 100644
--- a/libc/test/src/math/exhaustive/tanhf_test.cpp
+++ b/libc/test/src/math/exhaustive/tanhf_test.cpp
@@ -7,72 +7,27 @@
 //===----------------------------------------------------------------------===//
 
 #include "exhaustive_test.h"
-#include "src/__support/FPUtil/FPBits.h"
 #include "src/math/tanhf.h"
 #include "utils/MPFRWrapper/MPFRUtils.h"
 
-#include <thread>
-
-using FPBits = __llvm_libc::fputil::FPBits<float>;
-
 namespace mpfr = __llvm_libc::testing::mpfr;
 
-struct LlvmLibcTanhfExhaustiveTest : public LlvmLibcExhaustiveTest<uint32_t> {
-  bool check(uint32_t start, uint32_t stop,
-             mpfr::RoundingMode rounding) override {
-    mpfr::ForceRoundingMode r(rounding);
-    if (!r.success)
-      return true;
-    uint32_t bits = start;
-    bool result = true;
-    do {
-      FPBits xbits(bits);
-      float x = float(xbits);
-      result &= TEST_MPFR_MATCH(mpfr::Operation::Tanh, x, __llvm_libc::tanhf(x),
-                                0.5, rounding);
-    } while (bits++ < stop);
-    return result;
-  }
-};
-
-static const int NUM_THREADS = std::thread::hardware_concurrency();
-
-// Range: [0, INF];
-static const uint32_t POS_START = 0x0000'0000U;
-static const uint32_t POS_STOP = FPBits::inf(false).uintval();
+using LlvmLibcTanhfExhaustiveTest =
+    LlvmLibcUnaryOpExhaustiveMathTest<float, mpfr::Operation::Tanh,
+                                      __llvm_libc::tanhf>;
 
-TEST_F(LlvmLibcTanhfExhaustiveTest, PostiveRangeRoundNearestTieToEven) {
-  test_full_range(POS_START, POS_STOP, mpfr::RoundingMode::Nearest);
-}
-
-TEST_F(LlvmLibcTanhfExhaustiveTest, PostiveRangeRoundUp) {
-  test_full_range(POS_START, POS_STOP, mpfr::RoundingMode::Upward);
-}
+// Range: [0, Inf];
+static constexpr uint32_t POS_START = 0x0000'0000U;
+static constexpr uint32_t POS_STOP = 0x7f80'0000U;
 
-TEST_F(LlvmLibcTanhfExhaustiveTest, PostiveRangeRoundDown) {
-  test_full_range(POS_START, POS_STOP, mpfr::RoundingMode::Downward);
+TEST_F(LlvmLibcTanhfExhaustiveTest, PostiveRange) {
+  test_full_range_all_roundings(POS_START, POS_STOP);
 }
 
-TEST_F(LlvmLibcTanhfExhaustiveTest, PostiveRangeRoundTowardZero) {
-  test_full_range(POS_START, POS_STOP, mpfr::RoundingMode::TowardZero);
-}
-
-// Range: [-INF, 0];
-static const uint32_t NEG_START = 0x8000'0000U;
-static const uint32_t NEG_STOP = FPBits::inf(true).uintval();
-
-TEST_F(LlvmLibcTanhfExhaustiveTest, NegativeRangeRoundNearestTieToEven) {
-  test_full_range(NEG_START, NEG_STOP, mpfr::RoundingMode::Nearest);
-}
-
-TEST_F(LlvmLibcTanhfExhaustiveTest, NegativeRangeRoundUp) {
-  test_full_range(NEG_START, NEG_STOP, mpfr::RoundingMode::Upward);
-}
-
-TEST_F(LlvmLibcTanhfExhaustiveTest, NegativeRangeRoundDown) {
-  test_full_range(NEG_START, NEG_STOP, mpfr::RoundingMode::Downward);
-}
+// Range: [-Inf, 0];
+static constexpr uint32_t NEG_START = 0xb000'0000U;
+static constexpr uint32_t NEG_STOP = 0xff80'0000U;
 
-TEST_F(LlvmLibcTanhfExhaustiveTest, NegativeRangeRoundTowardZero) {
-  test_full_range(NEG_START, NEG_STOP, mpfr::RoundingMode::TowardZero);
+TEST_F(LlvmLibcTanhfExhaustiveTest, NegativeRange) {
+  test_full_range_all_roundings(NEG_START, NEG_STOP);
 }


        


More information about the libc-commits mailing list