119 lines · c
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-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef LLVM_LIBC_TEST_SRC_MATH_NEARBYINTTEST_H10#define LLVM_LIBC_TEST_SRC_MATH_NEARBYINTTEST_H11 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 19using namespace LIBC_NAMESPACE::fputil::testing;20 21namespace mpfr = LIBC_NAMESPACE::testing::mpfr;22 23template <typename T>24class 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 43public:44 using NearbyIntFunc = T (*)(T);45 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 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 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 be96 // 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_H119