xref: /aosp_15_r20/external/llvm-libc/test/src/math/HypotTest.h (revision 71db0c75aadcf003ffe3238005f61d7618a3fead)
1*71db0c75SAndroid Build Coastguard Worker //===-- Utility class to test different flavors of hypot ------------------===//
2*71db0c75SAndroid Build Coastguard Worker //
3*71db0c75SAndroid Build Coastguard Worker // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*71db0c75SAndroid Build Coastguard Worker // See https://llvm.org/LICENSE.txt for license information.
5*71db0c75SAndroid Build Coastguard Worker // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*71db0c75SAndroid Build Coastguard Worker //
7*71db0c75SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
8*71db0c75SAndroid Build Coastguard Worker 
9*71db0c75SAndroid Build Coastguard Worker #ifndef LLVM_LIBC_TEST_SRC_MATH_HYPOTTEST_H
10*71db0c75SAndroid Build Coastguard Worker #define LLVM_LIBC_TEST_SRC_MATH_HYPOTTEST_H
11*71db0c75SAndroid Build Coastguard Worker 
12*71db0c75SAndroid Build Coastguard Worker #include "src/__support/FPUtil/FPBits.h"
13*71db0c75SAndroid Build Coastguard Worker #include "test/UnitTest/FEnvSafeTest.h"
14*71db0c75SAndroid Build Coastguard Worker #include "test/UnitTest/FPMatcher.h"
15*71db0c75SAndroid Build Coastguard Worker #include "test/UnitTest/Test.h"
16*71db0c75SAndroid Build Coastguard Worker #include "utils/MPFRWrapper/MPFRUtils.h"
17*71db0c75SAndroid Build Coastguard Worker 
18*71db0c75SAndroid Build Coastguard Worker #include "hdr/math_macros.h"
19*71db0c75SAndroid Build Coastguard Worker 
20*71db0c75SAndroid Build Coastguard Worker using LIBC_NAMESPACE::Sign;
21*71db0c75SAndroid Build Coastguard Worker 
22*71db0c75SAndroid Build Coastguard Worker namespace mpfr = LIBC_NAMESPACE::testing::mpfr;
23*71db0c75SAndroid Build Coastguard Worker 
24*71db0c75SAndroid Build Coastguard Worker template <typename T>
25*71db0c75SAndroid Build Coastguard Worker class HypotTestTemplate : public LIBC_NAMESPACE::testing::FEnvSafeTest {
26*71db0c75SAndroid Build Coastguard Worker private:
27*71db0c75SAndroid Build Coastguard Worker   using Func = T (*)(T, T);
28*71db0c75SAndroid Build Coastguard Worker   using FPBits = LIBC_NAMESPACE::fputil::FPBits<T>;
29*71db0c75SAndroid Build Coastguard Worker 
30*71db0c75SAndroid Build Coastguard Worker   using StorageType = typename FPBits::StorageType;
31*71db0c75SAndroid Build Coastguard Worker   const T nan = FPBits::quiet_nan().get_val();
32*71db0c75SAndroid Build Coastguard Worker   const T inf = FPBits::inf().get_val();
33*71db0c75SAndroid Build Coastguard Worker   const T neg_inf = FPBits::inf(Sign::NEG).get_val();
34*71db0c75SAndroid Build Coastguard Worker   const T zero = FPBits::zero().get_val();
35*71db0c75SAndroid Build Coastguard Worker   const T neg_zero = FPBits::zero(Sign::NEG).get_val();
36*71db0c75SAndroid Build Coastguard Worker   const T max_normal = FPBits::max_normal().get_val();
37*71db0c75SAndroid Build Coastguard Worker   const T min_normal = FPBits::min_normal().get_val();
38*71db0c75SAndroid Build Coastguard Worker   const T max_subnormal = FPBits::max_subnormal().get_val();
39*71db0c75SAndroid Build Coastguard Worker   const T min_subnormal = FPBits::min_subnormal().get_val();
40*71db0c75SAndroid Build Coastguard Worker 
41*71db0c75SAndroid Build Coastguard Worker   static constexpr StorageType MAX_NORMAL = FPBits::max_normal().uintval();
42*71db0c75SAndroid Build Coastguard Worker   static constexpr StorageType MIN_NORMAL = FPBits::min_normal().uintval();
43*71db0c75SAndroid Build Coastguard Worker   static constexpr StorageType MAX_SUBNORMAL =
44*71db0c75SAndroid Build Coastguard Worker       FPBits::max_subnormal().uintval();
45*71db0c75SAndroid Build Coastguard Worker   static constexpr StorageType MIN_SUBNORMAL =
46*71db0c75SAndroid Build Coastguard Worker       FPBits::min_subnormal().uintval();
47*71db0c75SAndroid Build Coastguard Worker 
48*71db0c75SAndroid Build Coastguard Worker public:
test_special_numbers(Func func)49*71db0c75SAndroid Build Coastguard Worker   void test_special_numbers(Func func) {
50*71db0c75SAndroid Build Coastguard Worker     constexpr int N = 13;
51*71db0c75SAndroid Build Coastguard Worker     const T SpecialInputs[N] = {inf,           neg_inf,        zero,
52*71db0c75SAndroid Build Coastguard Worker                                 neg_zero,      max_normal,     min_normal,
53*71db0c75SAndroid Build Coastguard Worker                                 max_subnormal, min_subnormal,  -max_normal,
54*71db0c75SAndroid Build Coastguard Worker                                 -min_normal,   -max_subnormal, -min_subnormal};
55*71db0c75SAndroid Build Coastguard Worker 
56*71db0c75SAndroid Build Coastguard Worker     EXPECT_FP_EQ(func(inf, nan), inf);
57*71db0c75SAndroid Build Coastguard Worker     EXPECT_FP_EQ(func(nan, neg_inf), inf);
58*71db0c75SAndroid Build Coastguard Worker     EXPECT_FP_EQ(func(nan, nan), nan);
59*71db0c75SAndroid Build Coastguard Worker     EXPECT_FP_EQ(func(nan, zero), nan);
60*71db0c75SAndroid Build Coastguard Worker     EXPECT_FP_EQ(func(neg_zero, nan), nan);
61*71db0c75SAndroid Build Coastguard Worker 
62*71db0c75SAndroid Build Coastguard Worker     for (int i = 0; i < N; ++i) {
63*71db0c75SAndroid Build Coastguard Worker       for (int j = 0; j < N; ++j) {
64*71db0c75SAndroid Build Coastguard Worker         mpfr::BinaryInput<T> input{SpecialInputs[i], SpecialInputs[j]};
65*71db0c75SAndroid Build Coastguard Worker         EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Hypot, input,
66*71db0c75SAndroid Build Coastguard Worker                                        func(SpecialInputs[i], SpecialInputs[j]),
67*71db0c75SAndroid Build Coastguard Worker                                        0.5);
68*71db0c75SAndroid Build Coastguard Worker       }
69*71db0c75SAndroid Build Coastguard Worker     }
70*71db0c75SAndroid Build Coastguard Worker   }
71*71db0c75SAndroid Build Coastguard Worker 
test_subnormal_range(Func func)72*71db0c75SAndroid Build Coastguard Worker   void test_subnormal_range(Func func) {
73*71db0c75SAndroid Build Coastguard Worker     constexpr StorageType COUNT = 10'001;
74*71db0c75SAndroid Build Coastguard Worker     for (unsigned scale = 0; scale < 4; ++scale) {
75*71db0c75SAndroid Build Coastguard Worker       StorageType max_value = MAX_SUBNORMAL << scale;
76*71db0c75SAndroid Build Coastguard Worker       StorageType step = (max_value - MIN_SUBNORMAL) / COUNT;
77*71db0c75SAndroid Build Coastguard Worker       for (int signs = 0; signs < 4; ++signs) {
78*71db0c75SAndroid Build Coastguard Worker         for (StorageType v = MIN_SUBNORMAL, w = max_value;
79*71db0c75SAndroid Build Coastguard Worker              v <= max_value && w >= MIN_SUBNORMAL; v += step, w -= step) {
80*71db0c75SAndroid Build Coastguard Worker           T x = FPBits(v).get_val(), y = FPBits(w).get_val();
81*71db0c75SAndroid Build Coastguard Worker           if (signs % 2 == 1) {
82*71db0c75SAndroid Build Coastguard Worker             x = -x;
83*71db0c75SAndroid Build Coastguard Worker           }
84*71db0c75SAndroid Build Coastguard Worker           if (signs >= 2) {
85*71db0c75SAndroid Build Coastguard Worker             y = -y;
86*71db0c75SAndroid Build Coastguard Worker           }
87*71db0c75SAndroid Build Coastguard Worker 
88*71db0c75SAndroid Build Coastguard Worker           mpfr::BinaryInput<T> input{x, y};
89*71db0c75SAndroid Build Coastguard Worker           ASSERT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Hypot, input,
90*71db0c75SAndroid Build Coastguard Worker                                          func(x, y), 0.5);
91*71db0c75SAndroid Build Coastguard Worker         }
92*71db0c75SAndroid Build Coastguard Worker       }
93*71db0c75SAndroid Build Coastguard Worker     }
94*71db0c75SAndroid Build Coastguard Worker   }
95*71db0c75SAndroid Build Coastguard Worker 
96*71db0c75SAndroid Build Coastguard Worker   void test_normal_range(Func func) {
97*71db0c75SAndroid Build Coastguard Worker     constexpr StorageType COUNT = 10'001;
98*71db0c75SAndroid Build Coastguard Worker     constexpr StorageType STEP = (MAX_NORMAL - MIN_NORMAL) / COUNT;
99*71db0c75SAndroid Build Coastguard Worker     for (int signs = 0; signs < 4; ++signs) {
100*71db0c75SAndroid Build Coastguard Worker       for (StorageType v = MIN_NORMAL, w = MAX_NORMAL;
101*71db0c75SAndroid Build Coastguard Worker            v <= MAX_NORMAL && w >= MIN_NORMAL; v += STEP, w -= STEP) {
102*71db0c75SAndroid Build Coastguard Worker         T x = FPBits(v).get_val(), y = FPBits(w).get_val();
103*71db0c75SAndroid Build Coastguard Worker         if (signs % 2 == 1) {
104*71db0c75SAndroid Build Coastguard Worker           x = -x;
105*71db0c75SAndroid Build Coastguard Worker         }
106*71db0c75SAndroid Build Coastguard Worker         if (signs >= 2) {
107*71db0c75SAndroid Build Coastguard Worker           y = -y;
108*71db0c75SAndroid Build Coastguard Worker         }
109*71db0c75SAndroid Build Coastguard Worker 
110*71db0c75SAndroid Build Coastguard Worker         mpfr::BinaryInput<T> input{x, y};
111*71db0c75SAndroid Build Coastguard Worker         ASSERT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Hypot, input,
112*71db0c75SAndroid Build Coastguard Worker                                        func(x, y), 0.5);
113*71db0c75SAndroid Build Coastguard Worker       }
114*71db0c75SAndroid Build Coastguard Worker     }
115*71db0c75SAndroid Build Coastguard Worker   }
116*71db0c75SAndroid Build Coastguard Worker 
test_input_list(Func func,int n,const mpfr::BinaryInput<T> * inputs)117*71db0c75SAndroid Build Coastguard Worker   void test_input_list(Func func, int n, const mpfr::BinaryInput<T> *inputs) {
118*71db0c75SAndroid Build Coastguard Worker     for (int i = 0; i < n; ++i) {
119*71db0c75SAndroid Build Coastguard Worker       ASSERT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Hypot, inputs[i],
120*71db0c75SAndroid Build Coastguard Worker                                      func(inputs[i].x, inputs[i].y), 0.5);
121*71db0c75SAndroid Build Coastguard Worker     }
122*71db0c75SAndroid Build Coastguard Worker   }
123*71db0c75SAndroid Build Coastguard Worker };
124*71db0c75SAndroid Build Coastguard Worker 
125*71db0c75SAndroid Build Coastguard Worker #endif // LLVM_LIBC_TEST_SRC_MATH_HYPOTTEST_H
126