[libc-commits] [libc] abf1c82 - [libc] Extend MPFRMatcher to handle 2-input-1-output and support hypot function.

Tue Ly via libc-commits libc-commits at lists.llvm.org
Mon Sep 14 11:56:47 PDT 2020


Author: Tue Ly
Date: 2020-09-14T14:53:46-04:00
New Revision: abf1c82dcc5c54f2bbd65eb7b30cc40de2bd7147

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

LOG: [libc] Extend MPFRMatcher to handle 2-input-1-output and support hypot function.

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

Added: 
    

Modified: 
    libc/utils/MPFRWrapper/MPFRUtils.cpp
    libc/utils/MPFRWrapper/MPFRUtils.h

Removed: 
    


################################################################################
diff  --git a/libc/utils/MPFRWrapper/MPFRUtils.cpp b/libc/utils/MPFRWrapper/MPFRUtils.cpp
index 0520d8ae3ed9..56764e9740b0 100644
--- a/libc/utils/MPFRWrapper/MPFRUtils.cpp
+++ b/libc/utils/MPFRWrapper/MPFRUtils.cpp
@@ -133,6 +133,12 @@ class MPFRNumber {
     return result;
   }
 
+  MPFRNumber hypot(const MPFRNumber &b) {
+    MPFRNumber result;
+    mpfr_hypot(result.value, value, b.value, MPFR_RNDN);
+    return result;
+  }
+
   MPFRNumber remquo(const MPFRNumber &divisor, int &quotient) {
     MPFRNumber remainder;
     long q;
@@ -276,6 +282,18 @@ unaryOperationTwoOutputs(Operation op, InputType input, int &output) {
   }
 }
 
+template <typename InputType>
+cpp::EnableIfType<cpp::IsFloatingPointType<InputType>::Value, MPFRNumber>
+binaryOperationOneOutput(Operation op, InputType x, InputType y) {
+  MPFRNumber inputX(x), inputY(y);
+  switch (op) {
+  case Operation::Hypot:
+    return inputX.hypot(inputY);
+  default:
+    __builtin_unreachable();
+  }
+}
+
 template <typename InputType>
 cpp::EnableIfType<cpp::IsFloatingPointType<InputType>::Value, MPFRNumber>
 binaryOperationTwoOutputs(Operation op, InputType x, InputType y, int &output) {
@@ -401,6 +419,41 @@ template void explainBinaryOperationTwoOutputsError<long double>(
     Operation, const BinaryInput<long double> &,
     const BinaryOutput<long double> &, testutils::StreamWrapper &);
 
+template <typename T>
+void explainBinaryOperationOneOutputError(Operation op,
+                                          const BinaryInput<T> &input,
+                                          T libcResult,
+                                          testutils::StreamWrapper &OS) {
+  MPFRNumber mpfrX(input.x);
+  MPFRNumber mpfrY(input.y);
+  FPBits<T> xbits(input.x);
+  FPBits<T> ybits(input.y);
+  MPFRNumber mpfrResult = binaryOperationOneOutput(op, input.x, input.y);
+  MPFRNumber mpfrMatchValue(libcResult);
+
+  OS << "Input decimal: x: " << mpfrX.str() << " y: " << mpfrY.str() << '\n';
+  __llvm_libc::fputil::testing::describeValue("First input bits: ", input.x,
+                                              OS);
+  __llvm_libc::fputil::testing::describeValue("Second input bits: ", input.y,
+                                              OS);
+
+  OS << "Libc result: " << mpfrMatchValue.str() << '\n'
+     << "MPFR result: " << mpfrResult.str() << '\n';
+  __llvm_libc::fputil::testing::describeValue(
+      "Libc floating point result bits: ", libcResult, OS);
+  __llvm_libc::fputil::testing::describeValue(
+      "              MPFR rounded bits: ", mpfrResult.as<T>(), OS);
+  OS << "ULP error: " << std::to_string(mpfrResult.ulp(libcResult)) << '\n';
+}
+
+template void explainBinaryOperationOneOutputError<float>(
+    Operation, const BinaryInput<float> &, float, testutils::StreamWrapper &);
+template void explainBinaryOperationOneOutputError<double>(
+    Operation, const BinaryInput<double> &, double, testutils::StreamWrapper &);
+template void explainBinaryOperationOneOutputError<long double>(
+    Operation, const BinaryInput<long double> &, long double,
+    testutils::StreamWrapper &);
+
 template <typename T>
 bool compareUnaryOperationSingleOutput(Operation op, T input, T libcResult,
                                        double ulpError) {
@@ -480,6 +533,26 @@ template bool compareBinaryOperationTwoOutputs<long double>(
     Operation, const BinaryInput<long double> &,
     const BinaryOutput<long double> &, double);
 
+template <typename T>
+bool compareBinaryOperationOneOutput(Operation op, const BinaryInput<T> &input,
+                                     T libcResult, double ulpError) {
+  MPFRNumber mpfrResult = binaryOperationOneOutput(op, input.x, input.y);
+  double ulp = mpfrResult.ulp(libcResult);
+
+  bool bitsAreEven = ((FPBits<T>(libcResult).bitsAsUInt() & 1) == 0);
+  return (ulp < ulpError) ||
+         ((ulp == ulpError) && ((ulp != 0.5) || bitsAreEven));
+}
+
+template bool compareBinaryOperationOneOutput<float>(Operation,
+                                                     const BinaryInput<float> &,
+                                                     float, double);
+template bool
+compareBinaryOperationOneOutput<double>(Operation, const BinaryInput<double> &,
+                                        double, double);
+template bool compareBinaryOperationOneOutput<long double>(
+    Operation, const BinaryInput<long double> &, long double, double);
+
 } // namespace internal
 
 } // namespace mpfr

diff  --git a/libc/utils/MPFRWrapper/MPFRUtils.h b/libc/utils/MPFRWrapper/MPFRUtils.h
index b46f09dd5e55..6fb9fe5c47b6 100644
--- a/libc/utils/MPFRWrapper/MPFRUtils.h
+++ b/libc/utils/MPFRWrapper/MPFRUtils.h
@@ -47,7 +47,7 @@ enum class Operation : int {
   // input and produce a single floating point number of the same type as
   // output.
   BeginBinaryOperationsSingleOutput,
-  // TODO: Add operations like hypot.
+  Hypot,
   EndBinaryOperationsSingleOutput,
 
   // Operations which take two floating point numbers of the same type as
@@ -109,6 +109,10 @@ bool compareBinaryOperationTwoOutputs(Operation op, const BinaryInput<T> &input,
                                       const BinaryOutput<T> &libcOutput,
                                       double t);
 
+template <typename T>
+bool compareBinaryOperationOneOutput(Operation op, const BinaryInput<T> &input,
+                                     T libcOutput, double t);
+
 template <typename T>
 void explainUnaryOperationSingleOutputError(Operation op, T input, T matchValue,
                                             testutils::StreamWrapper &OS);
@@ -122,6 +126,12 @@ void explainBinaryOperationTwoOutputsError(Operation op,
                                            const BinaryOutput<T> &matchValue,
                                            testutils::StreamWrapper &OS);
 
+template <typename T>
+void explainBinaryOperationOneOutputError(Operation op,
+                                          const BinaryInput<T> &input,
+                                          T matchValue,
+                                          testutils::StreamWrapper &OS);
+
 template <Operation op, typename InputType, typename OutputType>
 class MPFRMatcher : public testing::Matcher<OutputType> {
   InputType input;
@@ -153,7 +163,7 @@ class MPFRMatcher : public testing::Matcher<OutputType> {
 
   template <typename T>
   static bool match(const BinaryInput<T> &in, T out, double tolerance) {
-    // TODO: Implement the comparision function and error reporter.
+    return compareBinaryOperationOneOutput(op, in, out, tolerance);
   }
 
   template <typename T>
@@ -183,6 +193,12 @@ class MPFRMatcher : public testing::Matcher<OutputType> {
                            testutils::StreamWrapper &OS) {
     explainBinaryOperationTwoOutputsError(op, in, out, OS);
   }
+
+  template <typename T>
+  static void explainError(const BinaryInput<T> &in, T out,
+                           testutils::StreamWrapper &OS) {
+    explainBinaryOperationOneOutputError(op, in, out, OS);
+  }
 };
 
 } // namespace internal


        


More information about the libc-commits mailing list