mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-04-01 12:43:47 +00:00
[libc] Add multithreading support for exhaustive testing and MPFRUtils.
Add threading support for exhaustive testing and MPFRUtils. Reviewed By: sivachandra Differential Revision: https://reviews.llvm.org/D117028
This commit is contained in:
parent
f7c589d3e7
commit
8cd81274ff
@ -63,6 +63,7 @@ endfunction(get_object_files_for_test)
|
||||
# HDRS <list of .h files for the test>
|
||||
# DEPENDS <list of dependencies>
|
||||
# COMPILE_OPTIONS <list of special compile options for this target>
|
||||
# LINK_OPTIONS <list of special linking options for this target>
|
||||
# )
|
||||
function(add_libc_unittest target_name)
|
||||
if(NOT LLVM_INCLUDE_TESTS)
|
||||
@ -71,9 +72,9 @@ function(add_libc_unittest target_name)
|
||||
|
||||
cmake_parse_arguments(
|
||||
"LIBC_UNITTEST"
|
||||
"" # No optional arguments
|
||||
"NO_RUN_POSTBUILD" # Optional arguments
|
||||
"SUITE" # Single value arguments
|
||||
"SRCS;HDRS;DEPENDS;COMPILE_OPTIONS" # Multi-value arguments
|
||||
"SRCS;HDRS;DEPENDS;COMPILE_OPTIONS;LINK_OPTIONS" # Multi-value arguments
|
||||
"NO_LIBC_UNITTEST_TEST_MAIN"
|
||||
${ARGN}
|
||||
)
|
||||
@ -140,6 +141,12 @@ function(add_libc_unittest target_name)
|
||||
endif()
|
||||
|
||||
target_link_libraries(${fq_target_name} PRIVATE ${link_object_files})
|
||||
if(LIBC_UNITTEST_LINK_OPTIONS)
|
||||
target_link_options(
|
||||
${fq_target_name}
|
||||
PRIVATE ${LIBC_UNITTEST_LINK_OPTIONS}
|
||||
)
|
||||
endif()
|
||||
|
||||
set_target_properties(${fq_target_name}
|
||||
PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
||||
@ -155,11 +162,14 @@ function(add_libc_unittest target_name)
|
||||
target_link_libraries(${fq_target_name} PRIVATE LibcUnitTest LibcUnitTestMain libc_test_utils)
|
||||
endif()
|
||||
|
||||
add_custom_command(
|
||||
TARGET ${fq_target_name}
|
||||
POST_BUILD
|
||||
COMMAND $<TARGET_FILE:${fq_target_name}>
|
||||
)
|
||||
if(NOT LIBC_UNITTEST_NO_RUN_POSTBUILD)
|
||||
add_custom_command(
|
||||
TARGET ${fq_target_name}
|
||||
POST_BUILD
|
||||
COMMAND $<TARGET_FILE:${fq_target_name}>
|
||||
)
|
||||
endif()
|
||||
|
||||
if(LIBC_UNITTEST_SUITE)
|
||||
add_dependencies(
|
||||
${LIBC_UNITTEST_SUITE}
|
||||
|
@ -1,5 +1,15 @@
|
||||
add_libc_exhaustive_testsuite(libc_math_exhaustive_tests)
|
||||
|
||||
add_object_library(
|
||||
exhaustive_test
|
||||
HDRS
|
||||
exhaustive_test.h
|
||||
SRCS
|
||||
exhaustive_test.cpp
|
||||
DEPENDS
|
||||
libc.src.__support.CPP.standalone_cpp
|
||||
)
|
||||
|
||||
add_fp_unittest(
|
||||
sqrtf_test
|
||||
NEED_MPFR
|
||||
@ -54,13 +64,17 @@ add_fp_unittest(
|
||||
|
||||
add_fp_unittest(
|
||||
logf_test
|
||||
NO_RUN_POSTBUILD
|
||||
NEED_MPFR
|
||||
SUITE
|
||||
libc_math_exhaustive_tests
|
||||
SRCS
|
||||
logf_test.cpp
|
||||
DEPENDS
|
||||
.exhaustive_test
|
||||
libc.include.math
|
||||
libc.src.math.logf
|
||||
libc.src.__support.FPUtil.fputil
|
||||
LINK_OPTIONS
|
||||
-lpthread
|
||||
)
|
||||
|
58
libc/test/src/math/exhaustive/exhaustive_test.cpp
Normal file
58
libc/test/src/math/exhaustive/exhaustive_test.cpp
Normal file
@ -0,0 +1,58 @@
|
||||
//===-- 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 <fenv.h>
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
#include "exhaustive_test.h"
|
||||
#include "utils/UnitTest/Test.h"
|
||||
|
||||
template <typename T>
|
||||
void LlvmLibcExhaustiveTest<T>::test_full_range(T start, T stop, int nthreads,
|
||||
mpfr::RoundingMode rounding) {
|
||||
std::vector<std::thread> thread_list(nthreads);
|
||||
T increment = (stop - start - 1) / nthreads + 1;
|
||||
T begin = start;
|
||||
T end = start + increment - 1;
|
||||
for (int i = 0; i < nthreads; ++i) {
|
||||
thread_list.emplace_back([this, begin, end, rounding]() {
|
||||
std::stringstream msg;
|
||||
msg << "-- Testing from " << begin << " to " << end << " [0x" << std::hex
|
||||
<< begin << ", 0x" << end << ") ..." << std::endl;
|
||||
std::cout << msg.str();
|
||||
msg.str("");
|
||||
|
||||
check(begin, end, rounding);
|
||||
|
||||
msg << "** Finished testing from " << std::dec << begin << " to " << end
|
||||
<< " [0x" << std::hex << begin << ", 0x" << end << ")" << std::endl;
|
||||
std::cout << msg.str();
|
||||
});
|
||||
begin += increment;
|
||||
end += increment;
|
||||
if (end > stop)
|
||||
end = stop;
|
||||
}
|
||||
for (auto &thread : thread_list) {
|
||||
if (thread.joinable()) {
|
||||
thread.join();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template void
|
||||
LlvmLibcExhaustiveTest<uint32_t>::test_full_range(uint32_t, uint32_t, int,
|
||||
mpfr::RoundingMode);
|
||||
template void
|
||||
LlvmLibcExhaustiveTest<uint64_t>::test_full_range(uint64_t, uint64_t, int,
|
||||
mpfr::RoundingMode);
|
26
libc/test/src/math/exhaustive/exhaustive_test.h
Normal file
26
libc/test/src/math/exhaustive/exhaustive_test.h
Normal file
@ -0,0 +1,26 @@
|
||||
//===-- 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 "utils/MPFRWrapper/MPFRUtils.h"
|
||||
#include "utils/UnitTest/Test.h"
|
||||
|
||||
// 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)
|
||||
namespace mpfr = __llvm_libc::testing::mpfr;
|
||||
|
||||
template <typename T>
|
||||
struct LlvmLibcExhaustiveTest : public __llvm_libc::testing::Test {
|
||||
// Break [start, stop) into `nthreads` subintervals and apply *check to each
|
||||
// subinterval in parallel.
|
||||
void test_full_range(T start, T stop, int nthreads,
|
||||
mpfr::RoundingMode rounding);
|
||||
|
||||
virtual void check(T start, T stop, mpfr::RoundingMode rounding);
|
||||
};
|
@ -6,21 +6,46 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "exhaustive_test.h"
|
||||
#include "src/__support/FPUtil/FPBits.h"
|
||||
#include "src/math/logf.h"
|
||||
#include "utils/MPFRWrapper/MPFRUtils.h"
|
||||
#include "utils/UnitTest/FPMatcher.h"
|
||||
#include "utils/UnitTest/Test.h"
|
||||
|
||||
using FPBits = __llvm_libc::fputil::FPBits<float>;
|
||||
|
||||
namespace mpfr = __llvm_libc::testing::mpfr;
|
||||
|
||||
TEST(LlvmLibcLogfExhaustiveTest, AllValues) {
|
||||
uint32_t bits = 0U;
|
||||
do {
|
||||
FPBits xbits(bits);
|
||||
float x = float(xbits);
|
||||
EXPECT_MPFR_MATCH(mpfr::Operation::Log, x, __llvm_libc::logf(x), 0.5);
|
||||
} while (bits++ < 0x7f7f'ffffU);
|
||||
struct LlvmLibcLogfExhaustiveTest : public LlvmLibcExhaustiveTest<uint32_t> {
|
||||
void check(uint32_t start, uint32_t stop,
|
||||
mpfr::RoundingMode rounding) override {
|
||||
mpfr::ForceRoundingMode r(rounding);
|
||||
uint32_t bits = start;
|
||||
do {
|
||||
FPBits xbits(bits);
|
||||
float x = float(xbits);
|
||||
EXPECT_MPFR_MATCH(mpfr::Operation::Log, x, __llvm_libc::logf(x), 0.5,
|
||||
rounding);
|
||||
} while (bits++ < stop);
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(LlvmLibcLogfExhaustiveTest, RoundNearestTieToEven) {
|
||||
test_full_range(/*start=*/0U, /*stop=*/0x7f80'0000U, /*nthreads=*/16,
|
||||
mpfr::RoundingMode::Nearest);
|
||||
}
|
||||
|
||||
TEST_F(LlvmLibcLogfExhaustiveTest, RoundUp) {
|
||||
test_full_range(/*start=*/0U, /*stop=*/0x7f80'0000U, /*nthreads=*/16,
|
||||
mpfr::RoundingMode::Upward);
|
||||
}
|
||||
|
||||
TEST_F(LlvmLibcLogfExhaustiveTest, RoundDown) {
|
||||
test_full_range(/*start=*/0U, /*stop=*/0x7f80'0000U, /*nthreads=*/16,
|
||||
mpfr::RoundingMode::Downward);
|
||||
}
|
||||
|
||||
TEST_F(LlvmLibcLogfExhaustiveTest, RoundTowardZero) {
|
||||
test_full_range(/*start=*/0U, /*stop=*/0x7f80'0000U, /*nthreads=*/16,
|
||||
mpfr::RoundingMode::TowardZero);
|
||||
}
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include <cmath>
|
||||
#include <fenv.h>
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
|
||||
@ -571,6 +572,10 @@ ternary_operation_one_output(Operation op, InputType x, InputType y,
|
||||
}
|
||||
}
|
||||
|
||||
// Remark: For all the explain_*_error functions, we will use std::stringstream
|
||||
// to build the complete error messages before sending it to the outstream `OS`
|
||||
// once at the end. This will stop the error messages from interleaving when
|
||||
// the tests are running concurrently.
|
||||
template <typename T>
|
||||
void explain_unary_operation_single_output_error(Operation op, T input,
|
||||
T matchValue,
|
||||
@ -582,18 +587,20 @@ void explain_unary_operation_single_output_error(Operation op, T input,
|
||||
MPFRNumber mpfr_result;
|
||||
mpfr_result = unary_operation(op, input, precision, rounding);
|
||||
MPFRNumber mpfrMatchValue(matchValue);
|
||||
OS << "Match value not within tolerance value of MPFR result:\n"
|
||||
std::stringstream ss;
|
||||
ss << "Match value not within tolerance value of MPFR result:\n"
|
||||
<< " Input decimal: " << mpfrInput.str() << '\n';
|
||||
__llvm_libc::fputil::testing::describeValue(" Input bits: ", input, OS);
|
||||
OS << '\n' << " Match decimal: " << mpfrMatchValue.str() << '\n';
|
||||
__llvm_libc::fputil::testing::describeValue(" Input bits: ", input, ss);
|
||||
ss << '\n' << " Match decimal: " << mpfrMatchValue.str() << '\n';
|
||||
__llvm_libc::fputil::testing::describeValue(" Match bits: ", matchValue,
|
||||
OS);
|
||||
OS << '\n' << " MPFR result: " << mpfr_result.str() << '\n';
|
||||
ss);
|
||||
ss << '\n' << " MPFR result: " << mpfr_result.str() << '\n';
|
||||
__llvm_libc::fputil::testing::describeValue(
|
||||
" MPFR rounded: ", mpfr_result.as<T>(), OS);
|
||||
OS << '\n';
|
||||
OS << " ULP error: " << std::to_string(mpfr_result.ulp(matchValue))
|
||||
" MPFR rounded: ", mpfr_result.as<T>(), ss);
|
||||
ss << '\n';
|
||||
ss << " ULP error: " << std::to_string(mpfr_result.ulp(matchValue))
|
||||
<< '\n';
|
||||
OS << ss.str();
|
||||
}
|
||||
|
||||
template void
|
||||
@ -616,31 +623,33 @@ void explain_unary_operation_two_outputs_error(
|
||||
int mpfrIntResult;
|
||||
MPFRNumber mpfr_result = unary_operation_two_outputs(op, input, mpfrIntResult,
|
||||
precision, rounding);
|
||||
std::stringstream ss;
|
||||
|
||||
if (mpfrIntResult != libc_result.i) {
|
||||
OS << "MPFR integral result: " << mpfrIntResult << '\n'
|
||||
ss << "MPFR integral result: " << mpfrIntResult << '\n'
|
||||
<< "Libc integral result: " << libc_result.i << '\n';
|
||||
} else {
|
||||
OS << "Integral result from libc matches integral result from MPFR.\n";
|
||||
ss << "Integral result from libc matches integral result from MPFR.\n";
|
||||
}
|
||||
|
||||
MPFRNumber mpfrMatchValue(libc_result.f);
|
||||
OS << "Libc floating point result is not within tolerance value of the MPFR "
|
||||
ss << "Libc floating point result is not within tolerance value of the MPFR "
|
||||
<< "result.\n\n";
|
||||
|
||||
OS << " Input decimal: " << mpfrInput.str() << "\n\n";
|
||||
ss << " Input decimal: " << mpfrInput.str() << "\n\n";
|
||||
|
||||
OS << "Libc floating point value: " << mpfrMatchValue.str() << '\n';
|
||||
ss << "Libc floating point value: " << mpfrMatchValue.str() << '\n';
|
||||
__llvm_libc::fputil::testing::describeValue(
|
||||
" Libc floating point bits: ", libc_result.f, OS);
|
||||
OS << "\n\n";
|
||||
" Libc floating point bits: ", libc_result.f, ss);
|
||||
ss << "\n\n";
|
||||
|
||||
OS << " MPFR result: " << mpfr_result.str() << '\n';
|
||||
ss << " MPFR result: " << mpfr_result.str() << '\n';
|
||||
__llvm_libc::fputil::testing::describeValue(
|
||||
" MPFR rounded: ", mpfr_result.as<T>(), OS);
|
||||
OS << '\n'
|
||||
" MPFR rounded: ", mpfr_result.as<T>(), ss);
|
||||
ss << '\n'
|
||||
<< " ULP error: "
|
||||
<< std::to_string(mpfr_result.ulp(libc_result.f)) << '\n';
|
||||
OS << ss.str();
|
||||
}
|
||||
|
||||
template void explain_unary_operation_two_outputs_error<float>(
|
||||
@ -665,17 +674,19 @@ void explain_binary_operation_two_outputs_error(
|
||||
MPFRNumber mpfr_result = binary_operation_two_outputs(
|
||||
op, input.x, input.y, mpfrIntResult, precision, rounding);
|
||||
MPFRNumber mpfrMatchValue(libc_result.f);
|
||||
std::stringstream ss;
|
||||
|
||||
OS << "Input decimal: x: " << mpfrX.str() << " y: " << mpfrY.str() << '\n'
|
||||
ss << "Input decimal: x: " << mpfrX.str() << " y: " << mpfrY.str() << '\n'
|
||||
<< "MPFR integral result: " << mpfrIntResult << '\n'
|
||||
<< "Libc integral result: " << libc_result.i << '\n'
|
||||
<< "Libc floating point result: " << mpfrMatchValue.str() << '\n'
|
||||
<< " MPFR result: " << mpfr_result.str() << '\n';
|
||||
__llvm_libc::fputil::testing::describeValue(
|
||||
"Libc floating point result bits: ", libc_result.f, OS);
|
||||
"Libc floating point result bits: ", libc_result.f, ss);
|
||||
__llvm_libc::fputil::testing::describeValue(
|
||||
" MPFR rounded bits: ", mpfr_result.as<T>(), OS);
|
||||
OS << "ULP error: " << std::to_string(mpfr_result.ulp(libc_result.f)) << '\n';
|
||||
" MPFR rounded bits: ", mpfr_result.as<T>(), ss);
|
||||
ss << "ULP error: " << std::to_string(mpfr_result.ulp(libc_result.f)) << '\n';
|
||||
OS << ss.str();
|
||||
}
|
||||
|
||||
template void explain_binary_operation_two_outputs_error<float>(
|
||||
@ -701,20 +712,22 @@ void explain_binary_operation_one_output_error(
|
||||
MPFRNumber mpfr_result =
|
||||
binary_operation_one_output(op, input.x, input.y, precision, rounding);
|
||||
MPFRNumber mpfrMatchValue(libc_result);
|
||||
std::stringstream ss;
|
||||
|
||||
OS << "Input decimal: x: " << mpfrX.str() << " y: " << mpfrY.str() << '\n';
|
||||
ss << "Input decimal: x: " << mpfrX.str() << " y: " << mpfrY.str() << '\n';
|
||||
__llvm_libc::fputil::testing::describeValue("First input bits: ", input.x,
|
||||
OS);
|
||||
ss);
|
||||
__llvm_libc::fputil::testing::describeValue("Second input bits: ", input.y,
|
||||
OS);
|
||||
ss);
|
||||
|
||||
OS << "Libc result: " << mpfrMatchValue.str() << '\n'
|
||||
ss << "Libc result: " << mpfrMatchValue.str() << '\n'
|
||||
<< "MPFR result: " << mpfr_result.str() << '\n';
|
||||
__llvm_libc::fputil::testing::describeValue(
|
||||
"Libc floating point result bits: ", libc_result, OS);
|
||||
"Libc floating point result bits: ", libc_result, ss);
|
||||
__llvm_libc::fputil::testing::describeValue(
|
||||
" MPFR rounded bits: ", mpfr_result.as<T>(), OS);
|
||||
OS << "ULP error: " << std::to_string(mpfr_result.ulp(libc_result)) << '\n';
|
||||
" MPFR rounded bits: ", mpfr_result.as<T>(), ss);
|
||||
ss << "ULP error: " << std::to_string(mpfr_result.ulp(libc_result)) << '\n';
|
||||
OS << ss.str();
|
||||
}
|
||||
|
||||
template void explain_binary_operation_one_output_error<float>(
|
||||
@ -741,23 +754,25 @@ void explain_ternary_operation_one_output_error(
|
||||
MPFRNumber mpfr_result = ternary_operation_one_output(
|
||||
op, input.x, input.y, input.z, precision, rounding);
|
||||
MPFRNumber mpfrMatchValue(libc_result);
|
||||
std::stringstream ss;
|
||||
|
||||
OS << "Input decimal: x: " << mpfrX.str() << " y: " << mpfrY.str()
|
||||
ss << "Input decimal: x: " << mpfrX.str() << " y: " << mpfrY.str()
|
||||
<< " z: " << mpfrZ.str() << '\n';
|
||||
__llvm_libc::fputil::testing::describeValue("First input bits: ", input.x,
|
||||
OS);
|
||||
ss);
|
||||
__llvm_libc::fputil::testing::describeValue("Second input bits: ", input.y,
|
||||
OS);
|
||||
ss);
|
||||
__llvm_libc::fputil::testing::describeValue("Third input bits: ", input.z,
|
||||
OS);
|
||||
ss);
|
||||
|
||||
OS << "Libc result: " << mpfrMatchValue.str() << '\n'
|
||||
ss << "Libc result: " << mpfrMatchValue.str() << '\n'
|
||||
<< "MPFR result: " << mpfr_result.str() << '\n';
|
||||
__llvm_libc::fputil::testing::describeValue(
|
||||
"Libc floating point result bits: ", libc_result, OS);
|
||||
"Libc floating point result bits: ", libc_result, ss);
|
||||
__llvm_libc::fputil::testing::describeValue(
|
||||
" MPFR rounded bits: ", mpfr_result.as<T>(), OS);
|
||||
OS << "ULP error: " << std::to_string(mpfr_result.ulp(libc_result)) << '\n';
|
||||
" MPFR rounded bits: ", mpfr_result.as<T>(), ss);
|
||||
ss << "ULP error: " << std::to_string(mpfr_result.ulp(libc_result)) << '\n';
|
||||
OS << ss.str();
|
||||
}
|
||||
|
||||
template void explain_ternary_operation_one_output_error<float>(
|
||||
|
@ -10,6 +10,7 @@
|
||||
|
||||
#include "src/__support/FPUtil/FPBits.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
namespace __llvm_libc {
|
||||
@ -30,10 +31,9 @@ uintToHex(T X, size_t Length = sizeof(T) * 2) {
|
||||
return s;
|
||||
}
|
||||
|
||||
template <typename ValType>
|
||||
template <typename ValType, typename StreamType>
|
||||
cpp::EnableIfType<cpp::IsFloatingPointType<ValType>::Value, void>
|
||||
describeValue(const char *label, ValType value,
|
||||
testutils::StreamWrapper &stream) {
|
||||
describeValue(const char *label, ValType value, StreamType &stream) {
|
||||
stream << label;
|
||||
|
||||
FPBits<ValType> bits(value);
|
||||
@ -49,15 +49,19 @@ describeValue(const char *label, ValType value,
|
||||
(fputil::ExponentWidth<ValType>::VALUE - 1) / 4 + 1;
|
||||
constexpr int mantissaWidthInHex =
|
||||
(fputil::MantissaWidth<ValType>::VALUE - 1) / 4 + 1;
|
||||
constexpr int bitsWidthInHex =
|
||||
sizeof(typename fputil::FPBits<ValType>::UIntType) * 2;
|
||||
|
||||
stream << "Sign: " << (bits.get_sign() ? '1' : '0') << ", "
|
||||
<< "Exponent: 0x"
|
||||
stream << "0x"
|
||||
<< uintToHex<typename fputil::FPBits<ValType>::UIntType>(
|
||||
bits.uintval(), bitsWidthInHex)
|
||||
<< ", (S | E | M) = (" << (bits.get_sign() ? '1' : '0') << " | 0x"
|
||||
<< uintToHex<uint16_t>(bits.get_unbiased_exponent(),
|
||||
exponentWidthInHex)
|
||||
<< ", "
|
||||
<< "Mantissa: 0x"
|
||||
<< " | 0x"
|
||||
<< uintToHex<typename fputil::FPBits<ValType>::UIntType>(
|
||||
bits.get_mantissa(), mantissaWidthInHex);
|
||||
bits.get_mantissa(), mantissaWidthInHex)
|
||||
<< ")";
|
||||
}
|
||||
|
||||
stream << '\n';
|
||||
@ -70,6 +74,11 @@ template void describeValue<double>(const char *, double,
|
||||
template void describeValue<long double>(const char *, long double,
|
||||
testutils::StreamWrapper &);
|
||||
|
||||
template void describeValue<float>(const char *, float, std::stringstream &);
|
||||
template void describeValue<double>(const char *, double, std::stringstream &);
|
||||
template void describeValue<long double>(const char *, long double,
|
||||
std::stringstream &);
|
||||
|
||||
} // namespace testing
|
||||
} // namespace fputil
|
||||
} // namespace __llvm_libc
|
||||
|
@ -17,10 +17,9 @@ namespace __llvm_libc {
|
||||
namespace fputil {
|
||||
namespace testing {
|
||||
|
||||
template <typename ValType>
|
||||
template <typename ValType, typename StreamType>
|
||||
cpp::EnableIfType<cpp::IsFloatingPointType<ValType>::Value, void>
|
||||
describeValue(const char *label, ValType value,
|
||||
testutils::StreamWrapper &stream);
|
||||
describeValue(const char *label, ValType value, StreamType &stream);
|
||||
|
||||
template <typename T, __llvm_libc::testing::TestCondition Condition>
|
||||
class FPMatcher : public __llvm_libc::testing::Matcher<T> {
|
||||
|
Loading…
x
Reference in New Issue
Block a user