• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===-- Utility class to test different flavors of float sub ----*- 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_SUBTEST_H
10 #define LLVM_LIBC_TEST_SRC_MATH_SUBTEST_H
11 
12 #include "src/__support/CPP/algorithm.h"
13 #include "test/UnitTest/FEnvSafeTest.h"
14 #include "test/UnitTest/FPMatcher.h"
15 #include "test/UnitTest/Test.h"
16 #include "utils/MPFRWrapper/MPFRUtils.h"
17 
18 namespace mpfr = LIBC_NAMESPACE::testing::mpfr;
19 
20 template <typename OutType, typename InType>
21 class SubTest : public LIBC_NAMESPACE::testing::FEnvSafeTest {
22 
23   struct InConstants {
24     DECLARE_SPECIAL_CONSTANTS(InType)
25   };
26 
27   using InFPBits = typename InConstants::FPBits;
28   using InStorageType = typename InConstants::StorageType;
29 
30   static constexpr InStorageType IN_MAX_NORMAL_U =
31       InFPBits::max_normal().uintval();
32   static constexpr InStorageType IN_MIN_NORMAL_U =
33       InFPBits::min_normal().uintval();
34   static constexpr InStorageType IN_MAX_SUBNORMAL_U =
35       InFPBits::max_subnormal().uintval();
36   static constexpr InStorageType IN_MIN_SUBNORMAL_U =
37       InFPBits::min_subnormal().uintval();
38 
39 public:
40   using SubFunc = OutType (*)(InType, InType);
41 
test_subnormal_range(SubFunc func)42   void test_subnormal_range(SubFunc func) {
43     constexpr int COUNT = 100'001;
44     constexpr InStorageType STEP = LIBC_NAMESPACE::cpp::max(
45         static_cast<InStorageType>((IN_MAX_SUBNORMAL_U - IN_MIN_SUBNORMAL_U) /
46                                    COUNT),
47         InStorageType(1));
48     for (InStorageType i = IN_MIN_SUBNORMAL_U; i <= IN_MAX_SUBNORMAL_U;
49          i += STEP) {
50       InType x = InFPBits(i).get_val();
51       InType y = InFPBits(static_cast<InStorageType>(IN_MAX_SUBNORMAL_U - i))
52                      .get_val();
53       mpfr::BinaryInput<InType> input{x, y};
54       EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Sub, input, func(x, y),
55                                      0.5);
56     }
57   }
58 
59   void test_normal_range(SubFunc func) {
60     constexpr int COUNT = 100'001;
61     constexpr InStorageType STEP = LIBC_NAMESPACE::cpp::max(
62         static_cast<InStorageType>((IN_MAX_NORMAL_U - IN_MIN_NORMAL_U) / COUNT),
63         InStorageType(1));
64     for (InStorageType i = IN_MIN_NORMAL_U; i <= IN_MAX_NORMAL_U; i += STEP) {
65       InType x = InFPBits(i).get_val();
66       InType y =
67           InFPBits(static_cast<InStorageType>(IN_MAX_NORMAL_U - i)).get_val();
68       mpfr::BinaryInput<InType> input{x, y};
69       EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Sub, input, func(x, y),
70                                      0.5);
71     }
72   }
73 };
74 
75 #define LIST_SUB_TESTS(OutType, InType, func)                                  \
76   using LlvmLibcSubTest = SubTest<OutType, InType>;                            \
77   TEST_F(LlvmLibcSubTest, SubnormalRange) { test_subnormal_range(&func); }     \
78   TEST_F(LlvmLibcSubTest, NormalRange) { test_normal_range(&func); }
79 
80 #define LIST_SUB_SAME_TYPE_TESTS(suffix, OutType, InType, func)                \
81   using LlvmLibcSubTest##suffix = SubTest<OutType, InType>;                    \
82   TEST_F(LlvmLibcSubTest##suffix, SubnormalRange) {                            \
83     test_subnormal_range(&func);                                               \
84   }                                                                            \
85   TEST_F(LlvmLibcSubTest##suffix, NormalRange) { test_normal_range(&func); }
86 
87 #endif // LLVM_LIBC_TEST_SRC_MATH_SUBTEST_H
88