]>
Commit | Line | Data |
---|---|---|
1e59de90 TL |
1 | // (C) Copyright Matt Borland 2021. |
2 | // Use, modification and distribution are subject to the | |
3 | // Boost Software License, Version 1.0. (See accompanying file | |
4 | // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
5 | ||
6 | #include <cmath> | |
7 | #include <limits> | |
8 | #include <type_traits> | |
9 | #include <boost/math/ccmath/sqrt.hpp> | |
10 | #include <boost/core/lightweight_test.hpp> | |
11 | ||
12 | #ifdef BOOST_HAS_FLOAT128 | |
13 | #include <boost/multiprecision/float128.hpp> | |
14 | ||
15 | template <typename Real> | |
16 | void test_mp_sqrt() | |
17 | { | |
18 | constexpr Real tol = 2*std::numeric_limits<Real>::epsilon(); | |
19 | ||
20 | // Sqrt(2) | |
21 | constexpr Real test_val = boost::math::ccmath::sqrt(Real(2)); | |
22 | constexpr Real sqrt2 = Real(1.4142135623730950488016887242096980785696718753769480731766797379Q); | |
23 | constexpr Real abs_test_error = (test_val - sqrt2) > 0 ? (test_val - sqrt2) : (sqrt2 - test_val); | |
24 | static_assert(abs_test_error < tol, "Out of tolerance"); | |
25 | ||
26 | // inf | |
27 | constexpr Real test_inf = boost::math::ccmath::sqrt(std::numeric_limits<Real>::infinity()); | |
28 | static_assert(test_inf == std::numeric_limits<Real>::infinity(), "Not infinity"); | |
29 | ||
30 | // NAN | |
31 | constexpr Real test_nan = boost::math::ccmath::sqrt(std::numeric_limits<Real>::quiet_NaN()); | |
32 | static_assert(test_nan, "Not a NAN"); | |
33 | ||
34 | // 100'000'000 | |
35 | constexpr Real test_100m = boost::math::ccmath::sqrt(100000000); | |
36 | static_assert(test_100m == 10000, "Incorrect"); | |
37 | } | |
38 | ||
39 | #endif | |
40 | ||
41 | template <typename Real> | |
42 | void test_float_sqrt() | |
43 | { | |
44 | using std::abs; | |
45 | ||
46 | constexpr Real tol = 2*std::numeric_limits<Real>::epsilon(); | |
47 | ||
48 | constexpr Real test_val = boost::math::ccmath::sqrt(Real(2)); | |
49 | constexpr Real sqrt2 = Real(1.4142135623730950488016887l); | |
50 | constexpr Real abs_test_error = (test_val - sqrt2) > 0 ? (test_val - sqrt2) : (sqrt2 - test_val); | |
51 | static_assert(abs_test_error < tol, "Out of tolerance"); | |
52 | ||
53 | Real known_val = std::sqrt(Real(2)); | |
54 | BOOST_TEST(abs(test_val - known_val) < tol); | |
55 | ||
56 | // 1000 eps | |
57 | constexpr Real test_1000 = boost::math::ccmath::sqrt(1000*std::numeric_limits<Real>::epsilon()); | |
58 | Real known_1000 = std::sqrt(1000*std::numeric_limits<Real>::epsilon()); | |
59 | BOOST_TEST(abs(test_1000 - known_1000) < tol); | |
60 | ||
61 | // inf | |
62 | constexpr Real test_inf = boost::math::ccmath::sqrt(std::numeric_limits<Real>::infinity()); | |
63 | static_assert(test_inf == std::numeric_limits<Real>::infinity(), "Not infinity"); | |
64 | ||
65 | // NAN | |
66 | constexpr Real test_nan = boost::math::ccmath::sqrt(std::numeric_limits<Real>::quiet_NaN()); | |
67 | static_assert(test_nan, "Not a NAN"); | |
68 | ||
69 | // 100'000'000 | |
70 | constexpr Real test_100m = boost::math::ccmath::sqrt(100000000); | |
71 | static_assert(test_100m == 10000, "Incorrect"); | |
72 | ||
73 | // MAX / 2 | |
74 | // Only tests float since double and long double will exceed maximum template depth | |
75 | if constexpr (std::is_same_v<float, Real>) | |
76 | { | |
77 | constexpr Real test_max = boost::math::ccmath::sqrt((std::numeric_limits<Real>::max)() / 2); | |
78 | Real known_max = std::sqrt((std::numeric_limits<Real>::max)() / 2); | |
79 | BOOST_TEST(abs(test_max - known_max) < tol); | |
80 | } | |
81 | } | |
82 | ||
83 | template <typename Z> | |
84 | void test_int_sqrt() | |
85 | { | |
86 | using std::abs; | |
87 | ||
88 | constexpr double tol = 2*std::numeric_limits<double>::epsilon(); | |
89 | ||
90 | constexpr double test_val = boost::math::ccmath::sqrt(Z(2)); | |
91 | constexpr double dummy = 1; | |
92 | static_assert(test_val > dummy, "Not constexpr"); | |
93 | ||
94 | double known_val = std::sqrt(2.0); | |
95 | ||
96 | BOOST_TEST(abs(test_val - known_val) < tol); | |
97 | } | |
98 | ||
99 | // Only test on platforms that provide BOOST_MATH_IS_CONSTANT_EVALUATED | |
100 | #ifndef BOOST_MATH_NO_CONSTEXPR_DETECTION | |
101 | int main() | |
102 | { | |
103 | test_float_sqrt<float>(); | |
104 | test_float_sqrt<double>(); | |
105 | ||
106 | #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS | |
107 | test_float_sqrt<long double>(); | |
108 | #endif | |
109 | ||
110 | #if defined(BOOST_HAS_FLOAT128) && !defined(BOOST_MATH_USING_BUILTIN_CONSTANT_P) | |
111 | test_mp_sqrt<boost::multiprecision::float128>(); | |
112 | #endif | |
113 | ||
114 | test_int_sqrt<int>(); | |
115 | test_int_sqrt<unsigned>(); | |
116 | test_int_sqrt<long>(); | |
117 | test_int_sqrt<std::int32_t>(); | |
118 | test_int_sqrt<std::int64_t>(); | |
119 | test_int_sqrt<std::uint32_t>(); | |
120 | ||
121 | return boost::report_errors(); | |
122 | } | |
123 | #else | |
124 | int main() | |
125 | { | |
126 | return 0; | |
127 | } | |
128 | #endif |