diff --git a/libc/test/src/math/cosf_test.cpp b/libc/test/src/math/cosf_test.cpp
--- a/libc/test/src/math/cosf_test.cpp
+++ b/libc/test/src/math/cosf_test.cpp
@@ -69,35 +69,35 @@
   EXPECT_EQ(llvmlibc_errno, EDOM);
 }
 
-TEST(CosfTest, InFloatRange) {
+MPFR_TEST(CosfTest, InFloatRange) {
   constexpr uint32_t count = 1000000;
   constexpr uint32_t step = UINT32_MAX / count;
   for (uint32_t i = 0, v = 0; i <= count; ++i, v += step) {
     float x = as_float(v);
     if (isnan(x) || isinf(x))
       continue;
-    EXPECT_TRUE(mpfr::equalsCos(x, __llvm_libc::cosf(x), tolerance));
+    ASSERT_MPFR_EQ(mpfr::OP_Cos, x, __llvm_libc::cosf(x), tolerance);
   }
 }
 
 // For small values, cos(x) is 1.
-TEST(CosfTest, SmallValues) {
+MPFR_TEST(CosfTest, SmallValues) {
   float x = as_float(0x17800000);
   float result = __llvm_libc::cosf(x);
-  EXPECT_TRUE(mpfr::equalsCos(x, result, tolerance));
+  EXPECT_MPFR_EQ(mpfr::OP_Cos, x, result, tolerance);
   EXPECT_EQ(FloatBits::One, as_uint32_bits(result));
 
-  x = as_float(0x00400000);
+  x = as_float(0x0040000);
   result = __llvm_libc::cosf(x);
-  EXPECT_TRUE(mpfr::equalsCos(x, result, tolerance));
+  EXPECT_MPFR_EQ(mpfr::OP_Cos, x, result, tolerance);
   EXPECT_EQ(FloatBits::One, as_uint32_bits(result));
 }
 
 // SDCOMP-26094: check cosf in the cases for which the range reducer
 // returns values furthest beyond its nominal upper bound of pi/4.
-TEST(CosfTest, SDCOMP_26094) {
+MPFR_TEST(CosfTest, SDCOMP_26094) {
   for (uint32_t v : sdcomp26094Values) {
     float x = as_float(v);
-    EXPECT_TRUE(mpfr::equalsCos(x, __llvm_libc::cosf(x), tolerance));
+    ASSERT_MPFR_EQ(mpfr::OP_Cos, x, __llvm_libc::cosf(x), tolerance);
   }
 }
diff --git a/libc/test/src/math/sincosf_test.cpp b/libc/test/src/math/sincosf_test.cpp
--- a/libc/test/src/math/sincosf_test.cpp
+++ b/libc/test/src/math/sincosf_test.cpp
@@ -77,7 +77,7 @@
   EXPECT_EQ(llvmlibc_errno, EDOM);
 }
 
-TEST(SinCosfTest, InFloatRange) {
+MPFR_TEST(SinCosfTest, InFloatRange) {
   constexpr uint32_t count = 1000000;
   constexpr uint32_t step = UINT32_MAX / count;
   for (uint32_t i = 0, v = 0; i <= count; ++i, v += step) {
@@ -87,39 +87,39 @@
 
     float sin, cos;
     __llvm_libc::sincosf(x, &sin, &cos);
-    EXPECT_TRUE(mpfr::equalsCos(x, cos, tolerance));
-    EXPECT_TRUE(mpfr::equalsSin(x, sin, tolerance));
+    ASSERT_MPFR_EQ(mpfr::OP_Cos, x, cos, tolerance);
+    ASSERT_MPFR_EQ(mpfr::OP_Sin, x, sin, tolerance);
   }
 }
 
 // For small values, cos(x) is 1 and sin(x) is x.
-TEST(SinCosfTest, SmallValues) {
+MPFR_TEST(SinCosfTest, SmallValues) {
   uint32_t bits = 0x17800000;
   float x = as_float(bits);
   float result_cos, result_sin;
   __llvm_libc::sincosf(x, &result_sin, &result_cos);
-  EXPECT_TRUE(mpfr::equalsCos(x, result_cos, tolerance));
-  EXPECT_TRUE(mpfr::equalsSin(x, result_sin, tolerance));
+  EXPECT_MPFR_EQ(mpfr::OP_Cos, x, result_cos, tolerance);
+  EXPECT_MPFR_EQ(mpfr::OP_Sin, x, result_sin, tolerance);
   EXPECT_EQ(FloatBits::One, as_uint32_bits(result_cos));
   EXPECT_EQ(bits, as_uint32_bits(result_sin));
 
   bits = 0x00400000;
   x = as_float(bits);
   __llvm_libc::sincosf(x, &result_sin, &result_cos);
-  EXPECT_TRUE(mpfr::equalsCos(x, result_cos, tolerance));
-  EXPECT_TRUE(mpfr::equalsSin(x, result_sin, tolerance));
+  EXPECT_MPFR_EQ(mpfr::OP_Cos, x, result_cos, tolerance);
+  EXPECT_MPFR_EQ(mpfr::OP_Sin, x, result_sin, tolerance);
   EXPECT_EQ(FloatBits::One, as_uint32_bits(result_cos));
   EXPECT_EQ(bits, as_uint32_bits(result_sin));
 }
 
 // SDCOMP-26094: check sinf in the cases for which the range reducer
 // returns values furthest beyond its nominal upper bound of pi/4.
-TEST(SinCosfTest, SDCOMP_26094) {
+MPFR_TEST(SinCosfTest, SDCOMP_26094) {
   for (uint32_t v : sdcomp26094Values) {
     float x = as_float(v);
     float sin, cos;
     __llvm_libc::sincosf(x, &sin, &cos);
-    EXPECT_TRUE(mpfr::equalsCos(x, cos, tolerance));
-    EXPECT_TRUE(mpfr::equalsSin(x, sin, tolerance));
+    EXPECT_MPFR_EQ(mpfr::OP_Cos, x, cos, tolerance);
+    EXPECT_MPFR_EQ(mpfr::OP_Sin, x, sin, tolerance);
   }
 }
diff --git a/libc/test/src/math/sinf_test.cpp b/libc/test/src/math/sinf_test.cpp
--- a/libc/test/src/math/sinf_test.cpp
+++ b/libc/test/src/math/sinf_test.cpp
@@ -69,42 +69,42 @@
   EXPECT_EQ(llvmlibc_errno, EDOM);
 }
 
-TEST(SinfTest, InFloatRange) {
+MPFR_TEST(SinfTest, InFloatRange) {
   constexpr uint32_t count = 1000000;
   constexpr uint32_t step = UINT32_MAX / count;
   for (uint32_t i = 0, v = 0; i <= count; ++i, v += step) {
     float x = as_float(v);
     if (isnan(x) || isinf(x))
       continue;
-    EXPECT_TRUE(mpfr::equalsSin(x, __llvm_libc::sinf(x), tolerance));
+    ASSERT_MPFR_EQ(mpfr::OP_Sin, x, __llvm_libc::sinf(x), tolerance);
   }
 }
 
-TEST(SinfTest, SpecificBitPatterns) {
+MPFR_TEST(SinfTest, SpecificBitPatterns) {
   float x = as_float(0xc70d39a1);
-  EXPECT_TRUE(mpfr::equalsSin(x, __llvm_libc::sinf(x), tolerance));
+  EXPECT_MPFR_EQ(mpfr::OP_Sin, x, __llvm_libc::sinf(x), tolerance);
 }
 
 // For small values, sin(x) is x.
-TEST(SinfTest, SmallValues) {
+MPFR_TEST(SinfTest, SmallValues) {
   uint32_t bits = 0x17800000;
   float x = as_float(bits);
   float result = __llvm_libc::sinf(x);
-  EXPECT_TRUE(mpfr::equalsSin(x, result, tolerance));
+  EXPECT_MPFR_EQ(mpfr::OP_Sin, x, result, tolerance);
   EXPECT_EQ(bits, as_uint32_bits(result));
 
   bits = 0x00400000;
   x = as_float(bits);
   result = __llvm_libc::sinf(x);
-  EXPECT_TRUE(mpfr::equalsSin(x, result, tolerance));
+  EXPECT_MPFR_EQ(mpfr::OP_Sin, x, result, tolerance);
   EXPECT_EQ(bits, as_uint32_bits(result));
 }
 
 // SDCOMP-26094: check sinf in the cases for which the range reducer
 // returns values furthest beyond its nominal upper bound of pi/4.
-TEST(SinfTest, SDCOMP_26094) {
+MPFR_TEST(SinfTest, SDCOMP_26094) {
   for (uint32_t v : sdcomp26094Values) {
     float x = as_float(v);
-    EXPECT_TRUE(mpfr::equalsSin(x, __llvm_libc::sinf(x), tolerance));
+    EXPECT_MPFR_EQ(mpfr::OP_Sin, x, __llvm_libc::sinf(x), tolerance);
   }
 }
diff --git a/libc/utils/CPP/TypeTraits.h b/libc/utils/CPP/TypeTraits.h
--- a/libc/utils/CPP/TypeTraits.h
+++ b/libc/utils/CPP/TypeTraits.h
@@ -46,6 +46,19 @@
 template <typename T1, typename T2> struct IsSame : public FalseValue {};
 template <typename T> struct IsSame<T, T> : public TrueValue {};
 
+template <typename T> struct RemoveCV { typedef T Type; };
+template <typename T> struct RemoveCV<const T> { typedef T type; };
+template <typename T> struct RemoveCV<volatile T> { typedef T type; };
+template <typename T> struct RemoveCV<const volatile T> { typedef T type; };
+
+template <typename T> using RemoveCVType = typename RemoveCV<T>::Type;
+
+template <typename Type> struct IsFloatingPointType {
+  static constexpr bool Value = IsSame<float, RemoveCVType<Type>>::Value ||
+                                IsSame<double, RemoveCVType<Type>>::Value ||
+                                IsSame<long double, RemoveCVType<Type>>::Value;
+};
+
 } // namespace cpp
 } // namespace __llvm_libc
 
diff --git a/libc/utils/MPFRWrapper/CMakeLists.txt b/libc/utils/MPFRWrapper/CMakeLists.txt
--- a/libc/utils/MPFRWrapper/CMakeLists.txt
+++ b/libc/utils/MPFRWrapper/CMakeLists.txt
@@ -12,7 +12,8 @@
     MPFRUtils.cpp
     MPFRUtils.h
   )
-  target_link_libraries(libcMPFRWrapper -lmpfr -lgmp)
+  add_dependencies(libcMPFRWrapper libc.utils.CPP.standalone_cpp LibcUnitTest LLVMSupport)
+  target_link_libraries(libcMPFRWrapper -lmpfr -lgmp LibcUnitTest LLVMSupport)
 else()
   message(WARNING "Math tests using MPFR will be skipped.")
 endif()
diff --git a/libc/utils/MPFRWrapper/MPFRUtils.h b/libc/utils/MPFRWrapper/MPFRUtils.h
--- a/libc/utils/MPFRWrapper/MPFRUtils.h
+++ b/libc/utils/MPFRWrapper/MPFRUtils.h
@@ -9,6 +9,9 @@
 #ifndef LLVM_LIBC_UTILS_TESTUTILS_MPFRUTILS_H
 #define LLVM_LIBC_UTILS_TESTUTILS_MPFRUTILS_H
 
+#include "utils/CPP/TypeTraits.h"
+#include "utils/UnitTest/Test.h"
+
 #include <stdint.h>
 
 namespace __llvm_libc {
@@ -36,16 +39,44 @@
   uint32_t bits;
 };
 
-// Return true if |libcOutput| is within the tolerance |t| of the cos(x)
-// value as evaluated by MPFR.
-bool equalsCos(float x, float libcOutput, const Tolerance &t);
+enum Operation {
+  OP_Cos,
+  OP_Sin,
+};
+
+namespace internal {
 
-// Return true if |libcOutput| is within the tolerance |t| of the sin(x)
-// value as evaluated by MPFR.
-bool equalsSin(float x, float libcOutput, const Tolerance &t);
+template <typename T>
+bool compare(Operation op, T input, T libcOutput, const Tolerance &t);
+
+} // namespace internal
+
+class Test : public __llvm_libc::testing::Test {
+protected:
+  template <typename T,
+            __llvm_libc::cpp::EnableIfType<
+                __llvm_libc::cpp::IsFloatingPointType<T>::Value, int> = 0>
+  static bool compare(__llvm_libc::testing::mpfr::Operation op, T input,
+                      T libcOutput,
+                      const __llvm_libc::testing::mpfr::Tolerance &t) {
+    return internal::compare(op, input, libcOutput, t);
+  }
+};
 
 } // namespace mpfr
 } // namespace testing
 } // namespace __llvm_libc
 
+#define MPFR_TEST(SuiteName, TestName)                                         \
+  TEST_WITH_BASE_CLASS(SuiteName, TestName, __llvm_libc::testing::mpfr::Test)
+
+#define EXPECT_MPFR_EQ(op, input, libcOutput, tolerance)                       \
+  TEST_EXTENSION(__llvm_libc::testing::mpfr::Test::compare(                    \
+                     op, input, libcOutput, tolerance),                        \
+                 true)
+
+#define ASSERT_MPFR_EQ(op, input, libcOutput, tolerance)                       \
+  if (!EXPECT_MPFR_EQ(op, input, libcOutput, tolerance))                       \
+  return
+
 #endif // LLVM_LIBC_UTILS_TESTUTILS_MPFRUTILS_H
diff --git a/libc/utils/MPFRWrapper/MPFRUtils.cpp b/libc/utils/MPFRWrapper/MPFRUtils.cpp
--- a/libc/utils/MPFRWrapper/MPFRUtils.cpp
+++ b/libc/utils/MPFRWrapper/MPFRUtils.cpp
@@ -8,7 +8,8 @@
 
 #include "MPFRUtils.h"
 
-#include <iostream>
+#include "llvm/Support/raw_ostream.h"
+
 #include <mpfr.h>
 
 namespace __llvm_libc {
@@ -22,6 +23,9 @@
 
   mpfr_t value;
 
+  template <typename T>
+  friend bool internal::compare(Operation, T, T, const Tolerance &);
+
 public:
   MPFRNumber() { mpfr_init2(value, mpfrPrecision); }
 
@@ -30,6 +34,16 @@
     mpfr_set_flt(value, x, MPFR_RNDN);
   }
 
+  explicit MPFRNumber(double x) {
+    mpfr_init2(value, mpfrPrecision);
+    mpfr_set_d(value, x, MPFR_RNDN);
+  }
+
+  explicit MPFRNumber(long double x) {
+    mpfr_init2(value, mpfrPrecision);
+    mpfr_set_ld(value, x, MPFR_RNDN);
+  }
+
   MPFRNumber(const MPFRNumber &other) {
     mpfr_set(value, other.value, MPFR_RNDN);
   }
@@ -59,38 +73,60 @@
     return mpfr_lessequal_p(difference.value, tolerance.value);
   }
 
+  std::string str() const {
+    // 200 bytes should be more than sufficient to hold a 100-digit number
+    // plus additional bytes for the decimal point, '-' sign etc.
+    char buffer[200];
+    mpfr_sprintf(buffer, "%100.50Rf", value);
+    llvm::StringRef ref(buffer);
+    ref = ref.trim();
+    return ref.str();
+  }
+
   // These functions are useful for debugging.
   float asFloat() const { return mpfr_get_flt(value, MPFR_RNDN); }
   double asDouble() const { return mpfr_get_d(value, MPFR_RNDN); }
   void dump(const char *msg) const { mpfr_printf("%s%.128Rf\n", msg, value); }
+};
 
-public:
-  static MPFRNumber cos(float x) {
-    MPFRNumber result;
-    MPFRNumber mpfrX(x);
-    mpfr_cos(result.value, mpfrX.value, MPFR_RNDN);
-    return result;
+namespace internal {
+
+template <typename T>
+bool compare(Operation op, T input, T libcResult, const Tolerance &t) {
+  MPFRNumber mpfrResult;
+  MPFRNumber mpfrInput(input);
+  MPFRNumber mpfrLibcResult(libcResult);
+
+  switch (op) {
+  case OP_Cos:
+    mpfr_cos(mpfrResult.value, mpfrInput.value, MPFR_RNDN);
+    break;
+  case OP_Sin:
+    mpfr_sin(mpfrResult.value, mpfrInput.value, MPFR_RNDN);
+    break;
   }
 
-  static MPFRNumber sin(float x) {
-    MPFRNumber result;
-    MPFRNumber mpfrX(x);
-    mpfr_sin(result.value, mpfrX.value, MPFR_RNDN);
-    return result;
+  if (!mpfrResult.isEqual(mpfrLibcResult, t)) {
+    llvm::outs() << llvm::raw_ostream::RED
+                 << "Libc result is not within tolerance value of the MPFR "
+                 << "result:\n"
+                 << llvm::raw_ostream::RESET;
+    llvm::outs() << "      Input: " << mpfrInput.str() << '\n';
+    llvm::outs() << "Libc result: " << mpfrLibcResult.str() << '\n';
+    llvm::outs() << "MPFR result: " << mpfrResult.str() << '\n';
+
+    return false;
   }
-};
 
-bool equalsCos(float input, float libcOutput, const Tolerance &t) {
-  MPFRNumber mpfrResult = MPFRNumber::cos(input);
-  MPFRNumber libcResult(libcOutput);
-  return mpfrResult.isEqual(libcResult, t);
+  return true;
 }
 
-bool equalsSin(float input, float libcOutput, const Tolerance &t) {
-  MPFRNumber mpfrResult = MPFRNumber::sin(input);
-  MPFRNumber libcResult(libcOutput);
-  return mpfrResult.isEqual(libcResult, t);
-}
+template bool compare<float>(Operation, float, float, const Tolerance &);
+template bool compare<double>(Operation, double, double, const Tolerance &);
+template bool compare<long double>(Operation, long double, long double,
+                                   const Tolerance &);
+
+} // namespace internal
 
 } // namespace mpfr
 } // namespace testing
diff --git a/libc/utils/UnitTest/Test.h b/libc/utils/UnitTest/Test.h
--- a/libc/utils/UnitTest/Test.h
+++ b/libc/utils/UnitTest/Test.h
@@ -34,6 +34,7 @@
   Cond_LE,
   Cond_GT,
   Cond_GE,
+  Cond_Extension
 };
 
 namespace internal {
@@ -138,8 +139,8 @@
 } // namespace testing
 } // namespace __llvm_libc
 
-#define TEST(SuiteName, TestName)                                              \
-  class SuiteName##_##TestName : public __llvm_libc::testing::Test {           \
+#define TEST_WITH_BASE_CLASS(SuiteName, TestName, BaseClass)                   \
+  class SuiteName##_##TestName : public BaseClass {                            \
   public:                                                                      \
     SuiteName##_##TestName() { addTest(this); }                                \
     void Run(__llvm_libc::testing::RunContext &) override;                     \
@@ -148,15 +149,10 @@
   SuiteName##_##TestName SuiteName##_##TestName##_Instance;                    \
   void SuiteName##_##TestName::Run(__llvm_libc::testing::RunContext &Ctx)
 
+#define TEST(SuiteName, TestName)                                              \
+  TEST_WITH_BASE_CLASS(SuiteName, TestName, __llvm_libc::testing::Test)
 #define TEST_F(SuiteClass, TestName)                                           \
-  class SuiteClass##_##TestName : public SuiteClass {                          \
-  public:                                                                      \
-    SuiteClass##_##TestName() { addTest(this); }                               \
-    void Run(__llvm_libc::testing::RunContext &) override;                     \
-    const char *getName() const override { return #SuiteClass "." #TestName; } \
-  };                                                                           \
-  SuiteClass##_##TestName SuiteClass##_##TestName##_Instance;                  \
-  void SuiteClass##_##TestName::Run(__llvm_libc::testing::RunContext &Ctx)
+  TEST_WITH_BASE_CLASS(SuiteClass, TestName, SuiteClass)
 
 #define EXPECT_EQ(LHS, RHS)                                                    \
   __llvm_libc::testing::Test::test(Ctx, __llvm_libc::testing::Cond_EQ, (LHS),  \
@@ -226,6 +222,11 @@
   if (!EXPECT_FALSE(VAL))                                                      \
   return
 
+#define TEST_EXTENSION(LHS, RHS)                                               \
+  __llvm_libc::testing::Test::test(Ctx, __llvm_libc::testing::Cond_Extension,  \
+                                   (LHS), (RHS), #LHS, #RHS, __FILE__,         \
+                                   __LINE__)
+
 #define EXPECT_EXITS(FUNC, EXIT)                                               \
   __llvm_libc::testing::Test::testProcessExits(                                \
       Ctx, __llvm_libc::testing::Test::createCallable(FUNC), EXIT, #FUNC,      \
diff --git a/libc/utils/UnitTest/Test.cpp b/libc/utils/UnitTest/Test.cpp
--- a/libc/utils/UnitTest/Test.cpp
+++ b/libc/utils/UnitTest/Test.cpp
@@ -104,6 +104,14 @@
                  << "To be greater than or equal to: " << RHSStr << '\n'
                  << "                      Which is: " << RHS << '\n';
     return false;
+  case Cond_Extension:
+    if (LHS == RHS)
+      return true;
+    // Silently mark the check as a failure. The extension system is expected to
+    // report appropriate information.
+    Ctx.markFail();
+    llvm::outs() << File << ":" << Line << ": FAILURE\n";
+    return false;
   default:
     Ctx.markFail();
     llvm::outs() << "Unexpected test condition.\n";