1 //===-- Utility class to test different flavors of nearbyint ----*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef LLVM_LIBC_TEST_SRC_MATH_NEARBYINTTEST_H 10 #define LLVM_LIBC_TEST_SRC_MATH_NEARBYINTTEST_H 11 12 #include "src/__support/CPP/algorithm.h" 13 #include "src/__support/CPP/array.h" 14 #include "test/UnitTest/FEnvSafeTest.h" 15 #include "test/UnitTest/FPMatcher.h" 16 #include "test/UnitTest/Test.h" 17 #include "utils/MPFRWrapper/MPFRUtils.h" 18 19 using namespace LIBC_NAMESPACE::fputil::testing; 20 21 namespace mpfr = LIBC_NAMESPACE::testing::mpfr; 22 23 template <typename T> 24 class NearbyIntTestTemplate : public LIBC_NAMESPACE::testing::FEnvSafeTest { 25 26 DECLARE_SPECIAL_CONSTANTS(T) 27 28 static constexpr LIBC_NAMESPACE::cpp::array<RoundingMode, 4> ROUNDING_MODES = 29 { 30 RoundingMode::Upward, 31 RoundingMode::Downward, 32 RoundingMode::TowardZero, 33 RoundingMode::Nearest, 34 }; 35 36 static constexpr StorageType MIN_SUBNORMAL = 37 FPBits::min_subnormal().uintval(); 38 static constexpr StorageType MAX_SUBNORMAL = 39 FPBits::max_subnormal().uintval(); 40 static constexpr StorageType MIN_NORMAL = FPBits::min_normal().uintval(); 41 static constexpr StorageType MAX_NORMAL = FPBits::max_normal().uintval(); 42 43 public: 44 using NearbyIntFunc = T (*)(T); 45 test_round_numbers(NearbyIntFunc func)46 void test_round_numbers(NearbyIntFunc func) { 47 for (RoundingMode mode : ROUNDING_MODES) { 48 if (ForceRoundingMode r(mode); r.success) { 49 EXPECT_FP_EQ(func(T(1.0)), mpfr::round(T(1.0), mode)); 50 EXPECT_FP_EQ(func(T(-1.0)), mpfr::round(T(-1.0), mode)); 51 EXPECT_FP_EQ(func(T(10.0)), mpfr::round(T(10.0), mode)); 52 EXPECT_FP_EQ(func(T(-10.0)), mpfr::round(T(-10.0), mode)); 53 EXPECT_FP_EQ(func(T(1234.0)), mpfr::round(T(1234.0), mode)); 54 EXPECT_FP_EQ(func(T(-1234.0)), mpfr::round(T(-1234.0), mode)); 55 } 56 } 57 } 58 test_fractions(NearbyIntFunc func)59 void test_fractions(NearbyIntFunc func) { 60 for (RoundingMode mode : ROUNDING_MODES) { 61 if (ForceRoundingMode r(mode); r.success) { 62 EXPECT_FP_EQ(func(T(0.5)), mpfr::round(T(0.5), mode)); 63 EXPECT_FP_EQ(func(T(-0.5)), mpfr::round(T(-0.5), mode)); 64 EXPECT_FP_EQ(func(T(0.115)), mpfr::round(T(0.115), mode)); 65 EXPECT_FP_EQ(func(T(-0.115)), mpfr::round(T(-0.115), mode)); 66 EXPECT_FP_EQ(func(T(0.715)), mpfr::round(T(0.715), mode)); 67 EXPECT_FP_EQ(func(T(-0.715)), mpfr::round(T(-0.715), mode)); 68 } 69 } 70 } 71 test_subnormal_range(NearbyIntFunc func)72 void test_subnormal_range(NearbyIntFunc func) { 73 constexpr int COUNT = 100'001; 74 const StorageType STEP = LIBC_NAMESPACE::cpp::max( 75 static_cast<StorageType>((MAX_SUBNORMAL - MIN_SUBNORMAL) / COUNT), 76 StorageType(1)); 77 for (StorageType i = MIN_SUBNORMAL; i <= MAX_SUBNORMAL; i += STEP) { 78 T x = FPBits(i).get_val(); 79 for (RoundingMode mode : ROUNDING_MODES) { 80 if (ForceRoundingMode r(mode); r.success) { 81 EXPECT_FP_EQ(func(x), mpfr::round(x, mode)); 82 } 83 } 84 } 85 } 86 87 void test_normal_range(NearbyIntFunc func) { 88 constexpr int COUNT = 100'001; 89 const StorageType STEP = LIBC_NAMESPACE::cpp::max( 90 static_cast<StorageType>((MAX_NORMAL - MIN_NORMAL) / COUNT), 91 StorageType(1)); 92 for (StorageType i = MIN_NORMAL; i <= MAX_NORMAL; i += STEP) { 93 FPBits xbits(i); 94 T x = xbits.get_val(); 95 // In normal range on x86 platforms, the long double implicit 1 bit can be 96 // zero making the numbers NaN. We will skip them. 97 if (xbits.is_nan()) 98 continue; 99 100 for (RoundingMode mode : ROUNDING_MODES) { 101 if (ForceRoundingMode r(mode); r.success) { 102 EXPECT_FP_EQ(func(x), mpfr::round(x, mode)); 103 } 104 } 105 } 106 } 107 }; 108 109 #define LIST_NEARBYINT_TESTS(F, func) \ 110 using LlvmLibcNearbyIntTest = NearbyIntTestTemplate<F>; \ 111 TEST_F(LlvmLibcNearbyIntTest, RoundNumbers) { test_round_numbers(&func); } \ 112 TEST_F(LlvmLibcNearbyIntTest, Fractions) { test_fractions(&func); } \ 113 TEST_F(LlvmLibcNearbyIntTest, SubnormalRange) { \ 114 test_subnormal_range(&func); \ 115 } \ 116 TEST_F(LlvmLibcNearbyIntTest, NormalRange) { test_normal_range(&func); } 117 118 #endif // LLVM_LIBC_TEST_SRC_MATH_NEARBYINTTEST_H 119