[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 "ient) {
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