81 lines · plain
1// (C) Copyright Matt Borland 2021.2// Use, modification and distribution are subject to the3// Boost Software License, Version 1.0. (See accompanying file4// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)5//6// Constexpr implementation of sqrt function7 8#ifndef BOOST_MATH_CCMATH_SQRT9#define BOOST_MATH_CCMATH_SQRT10 11#include <boost/math/ccmath/detail/config.hpp>12 13#ifdef BOOST_MATH_NO_CCMATH14#error "The header <boost/math/sqrt.hpp> can only be used in C++17 and later."15#endif16 17#include <boost/math/ccmath/abs.hpp>18#include <boost/math/ccmath/isnan.hpp>19#include <boost/math/ccmath/isinf.hpp>20#include <boost/math/tools/is_constant_evaluated.hpp>21 22namespace boost::math::ccmath { 23 24namespace detail {25 26template <typename Real>27constexpr Real sqrt_impl_2(Real x, Real s, Real s2)28{29 return !(s < s2) ? s2 : sqrt_impl_2(x, (x / s + s) / 2, s);30}31 32template <typename Real>33constexpr Real sqrt_impl_1(Real x, Real s)34{35 return sqrt_impl_2(x, (x / s + s) / 2, s);36}37 38template <typename Real>39constexpr Real sqrt_impl(Real x)40{41 return sqrt_impl_1(x, x > 1 ? x : Real(1));42}43 44} // namespace detail45 46template <typename Real, std::enable_if_t<!std::is_integral_v<Real>, bool> = true>47constexpr Real sqrt(Real x)48{49 if(BOOST_MATH_IS_CONSTANT_EVALUATED(x))50 {51 if (boost::math::ccmath::isnan(x) || 52 (boost::math::ccmath::isinf(x) && x > 0) ||53 boost::math::ccmath::abs(x) == Real(0))54 {55 return x;56 }57 // Domain error is implementation defined so return NAN58 else if (boost::math::ccmath::isinf(x) && x < 0)59 {60 return std::numeric_limits<Real>::quiet_NaN();61 }62 63 return detail::sqrt_impl<Real>(x);64 }65 else66 {67 using std::sqrt;68 return sqrt(x);69 }70}71 72template <typename Z, std::enable_if_t<std::is_integral_v<Z>, bool> = true>73constexpr double sqrt(Z x)74{75 return detail::sqrt_impl<double>(static_cast<double>(x));76}77 78} // Namespaces79 80#endif // BOOST_MATH_CCMATH_SQRT81