1 | //===-- Utility class to test fixed-point sqrt ------------------*- 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 | #include "test/UnitTest/Test.h" |
10 | |
11 | #include "src/__support/CPP/bit.h" |
12 | #include "src/__support/FPUtil/BasicOperations.h" |
13 | #include "src/__support/FPUtil/sqrt.h" |
14 | #include "src/__support/fixed_point/fx_rep.h" |
15 | #include "src/__support/fixed_point/sqrt.h" |
16 | |
17 | template <typename T> class SqrtTest : public LIBC_NAMESPACE::testing::Test { |
18 | |
19 | using FXRep = LIBC_NAMESPACE::fixed_point::FXRep<T>; |
20 | static constexpr T zero = FXRep::ZERO(); |
21 | static constexpr T min = FXRep::MIN(); |
22 | static constexpr T max = FXRep::MAX(); |
23 | static constexpr T half = static_cast<T>(0.5); |
24 | static constexpr T quarter = static_cast<T>(0.25); |
25 | static constexpr T one = |
26 | (FXRep::INTEGRAL_LEN > 0) ? static_cast<T>(1) : FXRep::MAX(); |
27 | static constexpr T eps = FXRep::EPS(); |
28 | |
29 | public: |
30 | typedef T (*SqrtFunc)(T); |
31 | |
32 | void testSpecialNumbers(SqrtFunc func) { |
33 | EXPECT_EQ(zero, func(zero)); |
34 | EXPECT_EQ(half, func(quarter)); |
35 | |
36 | if constexpr (FXRep::INTEGRAL_LEN) { |
37 | EXPECT_EQ(one, func(one)); |
38 | EXPECT_EQ(static_cast<T>(2.0), func(static_cast<T>(4.0))); |
39 | } |
40 | |
41 | using StorageType = typename FXRep::StorageType; |
42 | |
43 | constexpr size_t COUNT = 255; |
44 | constexpr StorageType STEP = |
45 | ~StorageType(0) / static_cast<StorageType>(COUNT); |
46 | constexpr double ERR = 3.0 * static_cast<double>(eps); |
47 | StorageType x = 0; |
48 | for (size_t i = 0; i < COUNT; ++i, x += STEP) { |
49 | T v = LIBC_NAMESPACE::cpp::bit_cast<T>(x); |
50 | double v_d = static_cast<double>(v); |
51 | double errors = LIBC_NAMESPACE::fputil::abs( |
52 | x: static_cast<double>(func(v)) - LIBC_NAMESPACE::fputil::sqrt(x: v_d)); |
53 | if (errors > ERR) { |
54 | // Print out the failure input and output. |
55 | EXPECT_EQ(v, zero); |
56 | EXPECT_EQ(func(v), zero); |
57 | } |
58 | ASSERT_TRUE(errors <= ERR); |
59 | } |
60 | } |
61 | }; |
62 | |
63 | #define LIST_SQRT_TESTS(T, func) \ |
64 | using LlvmLibcSqrtTest = SqrtTest<T>; \ |
65 | TEST_F(LlvmLibcSqrtTest, SpecialNumbers) { testSpecialNumbers(&func); } \ |
66 | static_assert(true, "Require semicolon.") |
67 | |