sqrt.hpp 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  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. // Constexpr implementation of sqrt function
  7. #ifndef BOOST_MATH_CCMATH_SQRT
  8. #define BOOST_MATH_CCMATH_SQRT
  9. #include <cmath>
  10. #include <limits>
  11. #include <type_traits>
  12. #include <boost/math/ccmath/abs.hpp>
  13. #include <boost/math/ccmath/isnan.hpp>
  14. #include <boost/math/ccmath/isinf.hpp>
  15. #include <boost/math/tools/is_constant_evaluated.hpp>
  16. namespace boost::math::ccmath {
  17. namespace detail {
  18. template <typename Real>
  19. constexpr Real sqrt_impl_2(Real x, Real s, Real s2)
  20. {
  21. return !(s < s2) ? s2 : sqrt_impl_2(x, (x / s + s) / 2, s);
  22. }
  23. template <typename Real>
  24. constexpr Real sqrt_impl_1(Real x, Real s)
  25. {
  26. return sqrt_impl_2(x, (x / s + s) / 2, s);
  27. }
  28. template <typename Real>
  29. constexpr Real sqrt_impl(Real x)
  30. {
  31. return sqrt_impl_1(x, x > 1 ? x : Real(1));
  32. }
  33. } // namespace detail
  34. template <typename Real, std::enable_if_t<!std::is_integral_v<Real>, bool> = true>
  35. constexpr Real sqrt(Real x)
  36. {
  37. if(BOOST_MATH_IS_CONSTANT_EVALUATED(x))
  38. {
  39. if (boost::math::ccmath::isnan(x) ||
  40. (boost::math::ccmath::isinf(x) && x > 0) ||
  41. boost::math::ccmath::abs(x) == Real(0))
  42. {
  43. return x;
  44. }
  45. // Domain error is implementation defined so return NAN
  46. else if (boost::math::ccmath::isinf(x) && x < 0)
  47. {
  48. return std::numeric_limits<Real>::quiet_NaN();
  49. }
  50. return detail::sqrt_impl<Real>(x);
  51. }
  52. else
  53. {
  54. using std::sqrt;
  55. return sqrt(x);
  56. }
  57. }
  58. template <typename Z, std::enable_if_t<std::is_integral_v<Z>, bool> = true>
  59. constexpr double sqrt(Z x)
  60. {
  61. return detail::sqrt_impl<double>(static_cast<double>(x));
  62. }
  63. } // Namespaces
  64. #endif // BOOST_MATH_CCMATH_SQRT