1 //===-- Utility class to test different flavors of hypot ------------------===//
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_HYPOTTEST_H
10 #define LLVM_LIBC_TEST_SRC_MATH_HYPOTTEST_H
11 
12 #include "src/__support/FPUtil/FPBits.h"
13 #include "utils/MPFRWrapper/MPFRUtils.h"
14 #include "utils/UnitTest/FPMatcher.h"
15 #include "utils/UnitTest/Test.h"
16 
17 #include <math.h>
18 
19 namespace mpfr = __llvm_libc::testing::mpfr;
20 
21 template <typename T>
22 class HypotTestTemplate : public __llvm_libc::testing::Test {
23 private:
24   using Func = T (*)(T, T);
25   using FPBits = __llvm_libc::fputil::FPBits<T>;
26   using UIntType = typename FPBits::UIntType;
27   const T nan = T(__llvm_libc::fputil::FPBits<T>::build_nan(1));
28   const T inf = T(__llvm_libc::fputil::FPBits<T>::inf());
29   const T neg_inf = T(__llvm_libc::fputil::FPBits<T>::neg_inf());
30   const T zero = T(__llvm_libc::fputil::FPBits<T>::zero());
31   const T neg_zero = T(__llvm_libc::fputil::FPBits<T>::neg_zero());
32 
33 public:
test_special_numbers(Func func)34   void test_special_numbers(Func func) {
35     EXPECT_FP_EQ(func(inf, nan), inf);
36     EXPECT_FP_EQ(func(nan, neg_inf), inf);
37     EXPECT_FP_EQ(func(zero, inf), inf);
38     EXPECT_FP_EQ(func(neg_inf, neg_zero), inf);
39 
40     EXPECT_FP_EQ(func(nan, nan), nan);
41     EXPECT_FP_EQ(func(nan, zero), nan);
42     EXPECT_FP_EQ(func(neg_zero, nan), nan);
43 
44     EXPECT_FP_EQ(func(neg_zero, zero), zero);
45   }
46 
test_subnormal_range(Func func)47   void test_subnormal_range(Func func) {
48     constexpr UIntType COUNT = 1000001;
49     for (unsigned scale = 0; scale < 4; ++scale) {
50       UIntType max_value = FPBits::MAX_SUBNORMAL << scale;
51       UIntType step = (max_value - FPBits::MIN_SUBNORMAL) / COUNT;
52       for (int signs = 0; signs < 4; ++signs) {
53         for (UIntType v = FPBits::MIN_SUBNORMAL, w = max_value;
54              v <= max_value && w >= FPBits::MIN_SUBNORMAL;
55              v += step, w -= step) {
56           T x = T(FPBits(v)), y = T(FPBits(w));
57           if (signs % 2 == 1) {
58             x = -x;
59           }
60           if (signs >= 2) {
61             y = -y;
62           }
63 
64           mpfr::BinaryInput<T> input{x, y};
65           ASSERT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Hypot, input,
66                                          func(x, y), 0.5);
67         }
68       }
69     }
70   }
71 
test_normal_range(Func func)72   void test_normal_range(Func func) {
73     constexpr UIntType COUNT = 1000001;
74     constexpr UIntType STEP = (FPBits::MAX_NORMAL - FPBits::MIN_NORMAL) / COUNT;
75     for (int signs = 0; signs < 4; ++signs) {
76       for (UIntType v = FPBits::MIN_NORMAL, w = FPBits::MAX_NORMAL;
77            v <= FPBits::MAX_NORMAL && w >= FPBits::MIN_NORMAL;
78            v += STEP, w -= STEP) {
79         T x = T(FPBits(v)), y = T(FPBits(w));
80         if (signs % 2 == 1) {
81           x = -x;
82         }
83         if (signs >= 2) {
84           y = -y;
85         }
86 
87         mpfr::BinaryInput<T> input{x, y};
88         ASSERT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Hypot, input,
89                                        func(x, y), 0.5);
90       }
91     }
92   }
93 
test_input_list(Func func,int n,const mpfr::BinaryInput<T> * inputs)94   void test_input_list(Func func, int n, const mpfr::BinaryInput<T> *inputs) {
95     for (int i = 0; i < n; ++i) {
96       ASSERT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Hypot, inputs[i],
97                                      func(inputs[i].x, inputs[i].y), 0.5);
98     }
99   }
100 };
101 
102 #endif // LLVM_LIBC_TEST_SRC_MATH_HYPOTTEST_H
103