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