diff options
author | OverMighty <its.overmighty@gmail.com> | 2024-06-25 22:44:47 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-06-25 16:44:47 -0400 |
commit | ef05b0322307318eb806c0bd4cdcdae9e31d477b (patch) | |
tree | 747dd5a2ef2e469493db60090fdd0c91fff16674 /libc/test | |
parent | 3c24eb39fb7e9c8b61992c86cb44d8cacc5853d2 (diff) | |
download | llvm-ef05b0322307318eb806c0bd4cdcdae9e31d477b.zip llvm-ef05b0322307318eb806c0bd4cdcdae9e31d477b.tar.gz llvm-ef05b0322307318eb806c0bd4cdcdae9e31d477b.tar.bz2 |
[libc][math][c23] Add MPFR exhaustive test for fmodf16 (#94656)
Diffstat (limited to 'libc/test')
-rw-r--r-- | libc/test/src/math/exhaustive/CMakeLists.txt | 19 | ||||
-rw-r--r-- | libc/test/src/math/exhaustive/exhaustive_test.h | 124 | ||||
-rw-r--r-- | libc/test/src/math/exhaustive/fmodf16_test.cpp | 41 |
3 files changed, 168 insertions, 16 deletions
diff --git a/libc/test/src/math/exhaustive/CMakeLists.txt b/libc/test/src/math/exhaustive/CMakeLists.txt index 34df872..fb3596c 100644 --- a/libc/test/src/math/exhaustive/CMakeLists.txt +++ b/libc/test/src/math/exhaustive/CMakeLists.txt @@ -4,6 +4,10 @@ add_header_library( exhaustive_test HDRS exhaustive_test.h + DEPENDS + libc.src.__support.CPP.type_traits + libc.src.__support.FPUtil.fp_bits + libc.src.__support.macros.properties.types ) add_fp_unittest( @@ -278,6 +282,21 @@ add_fp_unittest( ) add_fp_unittest( + fmodf16_test + NO_RUN_POSTBUILD + NEED_MPFR + SUITE + libc_math_exhaustive_tests + SRCS + fmodf16_test.cpp + DEPENDS + .exhaustive_test + libc.src.math.fmodf16 + LINK_LIBRARIES + -lpthread +) + +add_fp_unittest( coshf_test NO_RUN_POSTBUILD NEED_MPFR diff --git a/libc/test/src/math/exhaustive/exhaustive_test.h b/libc/test/src/math/exhaustive/exhaustive_test.h index 13e2727..6f0c78eb 100644 --- a/libc/test/src/math/exhaustive/exhaustive_test.h +++ b/libc/test/src/math/exhaustive/exhaustive_test.h @@ -8,6 +8,7 @@ #include "src/__support/CPP/type_traits.h" #include "src/__support/FPUtil/FPBits.h" +#include "src/__support/macros/properties/types.h" #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" #include "utils/MPFRWrapper/MPFRUtils.h" @@ -68,9 +69,46 @@ struct UnaryOpChecker : public virtual LIBC_NAMESPACE::testing::Test { } }; +template <typename OutType, typename InType = OutType> +using BinaryOp = OutType(InType, InType); + +template <typename OutType, typename InType, mpfr::Operation Op, + BinaryOp<OutType, InType> Func> +struct BinaryOpChecker : public virtual LIBC_NAMESPACE::testing::Test { + using FloatType = InType; + using FPBits = LIBC_NAMESPACE::fputil::FPBits<FloatType>; + using StorageType = typename FPBits::StorageType; + + // Check in a range, return the number of failures. + uint64_t check(StorageType x_start, StorageType x_stop, StorageType y_start, + StorageType y_stop, mpfr::RoundingMode rounding) { + mpfr::ForceRoundingMode r(rounding); + if (!r.success) + return x_stop > x_start || y_stop > y_start; + StorageType xbits = x_start; + uint64_t failed = 0; + do { + FloatType x = FPBits(xbits).get_val(); + StorageType ybits = y_start; + do { + FloatType y = FPBits(ybits).get_val(); + mpfr::BinaryInput<FloatType> input{x, y}; + bool correct = TEST_MPFR_MATCH_ROUNDING_SILENTLY(Op, input, Func(x, y), + 0.5, rounding); + failed += (!correct); + // Uncomment to print out failed values. + // if (!correct) { + // EXPECT_MPFR_MATCH_ROUNDING(Op, input, Func(x, y), 0.5, rounding); + // } + } while (ybits++ < y_stop); + } while (xbits++ < x_stop); + return failed; + } +}; + // Checker class needs inherit from LIBC_NAMESPACE::testing::Test and provide // StorageType and check method. -template <typename Checker> +template <typename Checker, size_t Increment = 1 << 20> struct LlvmLibcExhaustiveMathTest : public virtual LIBC_NAMESPACE::testing::Test, public Checker { @@ -78,12 +116,35 @@ struct LlvmLibcExhaustiveMathTest using FPBits = typename Checker::FPBits; using StorageType = typename Checker::StorageType; - static constexpr StorageType INCREMENT = (1 << 20); + void explain_failed_range(std::stringstream &msg, StorageType x_begin, + StorageType x_end) { +#ifdef LIBC_TYPES_HAS_FLOAT16 + using T = LIBC_NAMESPACE::cpp::conditional_t< + LIBC_NAMESPACE::cpp::is_same_v<FloatType, float16>, float, FloatType>; +#else + using T = FloatType; +#endif + + msg << x_begin << " to " << x_end << " [0x" << std::hex << x_begin << ", 0x" + << x_end << "), [" << std::hexfloat + << static_cast<T>(FPBits(x_begin).get_val()) << ", " + << static_cast<T>(FPBits(x_end).get_val()) << ")"; + } + + void explain_failed_range(std::stringstream &msg, StorageType x_begin, + StorageType x_end, StorageType y_begin, + StorageType y_end) { + msg << "x "; + explain_failed_range(msg, x_begin, x_end); + msg << ", y "; + explain_failed_range(msg, y_begin, y_end); + } // Break [start, stop) into `nthreads` subintervals and apply *check to each // subinterval in parallel. - void test_full_range(StorageType start, StorageType stop, - mpfr::RoundingMode rounding) { + template <typename... T> + void test_full_range(mpfr::RoundingMode rounding, StorageType start, + StorageType stop, T... extra_range_bounds) { int n_threads = std::thread::hardware_concurrency(); std::vector<std::thread> thread_list; std::mutex mx_cur_val; @@ -102,8 +163,8 @@ struct LlvmLibcExhaustiveMathTest return; range_begin = current_value; - if (stop >= INCREMENT && stop - INCREMENT >= current_value) { - range_end = current_value + INCREMENT; + if (stop >= Increment && stop - Increment >= current_value) { + range_end = current_value + Increment; } else { range_end = stop; } @@ -120,15 +181,14 @@ struct LlvmLibcExhaustiveMathTest std::cout << msg.str() << std::flush; } - uint64_t failed_in_range = - Checker::check(range_begin, range_end, rounding); + uint64_t failed_in_range = Checker::check( + range_begin, range_end, extra_range_bounds..., 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 << FPBits(range_begin).get_val() - << ", " << FPBits(range_end).get_val() << ")\n"; + << " inputs in range: "; + explain_failed_range(msg, start, stop, extra_range_bounds...); + msg << "\n"; std::cerr << msg.str() << std::flush; failed.fetch_add(failed_in_range); @@ -151,19 +211,46 @@ struct LlvmLibcExhaustiveMathTest void test_full_range_all_roundings(StorageType start, StorageType 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); + test_full_range(mpfr::RoundingMode::Nearest, start, stop); 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); + test_full_range(mpfr::RoundingMode::Upward, start, stop); 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); + test_full_range(mpfr::RoundingMode::Downward, start, stop); 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); + test_full_range(mpfr::RoundingMode::TowardZero, start, stop); + }; + + void test_full_range_all_roundings(StorageType x_start, StorageType x_stop, + StorageType y_start, StorageType y_stop) { + std::cout << "-- Testing for FE_TONEAREST in x range [0x" << std::hex + << x_start << ", 0x" << x_stop << "), y range [0x" << y_start + << ", 0x" << y_stop << ") --" << std::dec << std::endl; + test_full_range(mpfr::RoundingMode::Nearest, x_start, x_stop, y_start, + y_stop); + + std::cout << "-- Testing for FE_UPWARD in x range [0x" << std::hex + << x_start << ", 0x" << x_stop << "), y range [0x" << y_start + << ", 0x" << y_stop << ") --" << std::dec << std::endl; + test_full_range(mpfr::RoundingMode::Upward, x_start, x_stop, y_start, + y_stop); + + std::cout << "-- Testing for FE_DOWNWARD in x range [0x" << std::hex + << x_start << ", 0x" << x_stop << "), y range [0x" << y_start + << ", 0x" << y_stop << ") --" << std::dec << std::endl; + test_full_range(mpfr::RoundingMode::Downward, x_start, x_stop, y_start, + y_stop); + + std::cout << "-- Testing for FE_TOWARDZERO in x range [0x" << std::hex + << x_start << ", 0x" << x_stop << "), y range [0x" << y_start + << ", 0x" << y_stop << ") --" << std::dec << std::endl; + test_full_range(mpfr::RoundingMode::TowardZero, x_start, x_stop, y_start, + y_stop); }; }; @@ -175,3 +262,8 @@ template <typename OutType, typename InType, mpfr::Operation Op, UnaryOp<OutType, InType> Func> using LlvmLibcUnaryNarrowingOpExhaustiveMathTest = LlvmLibcExhaustiveMathTest<UnaryOpChecker<OutType, InType, Op, Func>>; + +template <typename FloatType, mpfr::Operation Op, BinaryOp<FloatType> Func> +using LlvmLibcBinaryOpExhaustiveMathTest = + LlvmLibcExhaustiveMathTest<BinaryOpChecker<FloatType, FloatType, Op, Func>, + 1 << 2>; diff --git a/libc/test/src/math/exhaustive/fmodf16_test.cpp b/libc/test/src/math/exhaustive/fmodf16_test.cpp new file mode 100644 index 0000000..067cec9 --- /dev/null +++ b/libc/test/src/math/exhaustive/fmodf16_test.cpp @@ -0,0 +1,41 @@ +//===-- Exhaustive test for fmodf16 ---------------------------------------===// +// +// 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 "exhaustive_test.h" +#include "src/math/fmodf16.h" +#include "utils/MPFRWrapper/MPFRUtils.h" + +namespace mpfr = LIBC_NAMESPACE::testing::mpfr; + +using LlvmLibcFmodf16ExhaustiveTest = + LlvmLibcBinaryOpExhaustiveMathTest<float16, mpfr::Operation::Fmod, + LIBC_NAMESPACE::fmodf16>; + +// Range: [0, Inf]; +static constexpr uint16_t POS_START = 0x0000U; +static constexpr uint16_t POS_STOP = 0x7c00U; + +// Range: [-Inf, 0]; +static constexpr uint16_t NEG_START = 0x8000U; +static constexpr uint16_t NEG_STOP = 0xfc00U; + +TEST_F(LlvmLibcFmodf16ExhaustiveTest, PostivePositiveRange) { + test_full_range_all_roundings(POS_START, POS_STOP, POS_START, POS_STOP); +} + +TEST_F(LlvmLibcFmodf16ExhaustiveTest, PostiveNegativeRange) { + test_full_range_all_roundings(POS_START, POS_STOP, NEG_START, NEG_STOP); +} + +TEST_F(LlvmLibcFmodf16ExhaustiveTest, NegativePositiveRange) { + test_full_range_all_roundings(NEG_START, NEG_STOP, POS_START, POS_STOP); +} + +TEST_F(LlvmLibcFmodf16ExhaustiveTest, NegativeNegativeRange) { + test_full_range_all_roundings(NEG_START, NEG_STOP, POS_START, POS_STOP); +} |