hypot.hpp 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. // (C) Copyright John Maddock 2005-2021.
  2. // (C) Copyright Matt Borland 2021.
  3. // Use, modification and distribution are subject to the
  4. // Boost Software License, Version 1.0. (See accompanying file
  5. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. #ifndef BOOST_MATH_CCMATH_HYPOT_HPP
  7. #define BOOST_MATH_CCMATH_HYPOT_HPP
  8. #include <boost/math/ccmath/detail/config.hpp>
  9. #ifdef BOOST_MATH_NO_CCMATH
  10. #error "The header <boost/math/hypot.hpp> can only be used in C++17 and later."
  11. #endif
  12. #include <array>
  13. #include <boost/math/tools/config.hpp>
  14. #include <boost/math/tools/promotion.hpp>
  15. #include <boost/math/ccmath/sqrt.hpp>
  16. #include <boost/math/ccmath/abs.hpp>
  17. #include <boost/math/ccmath/isinf.hpp>
  18. #include <boost/math/ccmath/isnan.hpp>
  19. #include <boost/math/ccmath/detail/swap.hpp>
  20. namespace boost::math::ccmath {
  21. namespace detail {
  22. template <typename T>
  23. constexpr T hypot_impl(T x, T y) noexcept
  24. {
  25. x = boost::math::ccmath::abs(x);
  26. y = boost::math::ccmath::abs(y);
  27. if (y > x)
  28. {
  29. boost::math::ccmath::detail::swap(x, y);
  30. }
  31. if(x * std::numeric_limits<T>::epsilon() >= y)
  32. {
  33. return x;
  34. }
  35. T rat = y / x;
  36. return x * boost::math::ccmath::sqrt(1 + rat * rat);
  37. }
  38. } // Namespace detail
  39. template <typename Real, std::enable_if_t<!std::is_integral_v<Real>, bool> = true>
  40. constexpr Real hypot(Real x, Real y) noexcept
  41. {
  42. if(BOOST_MATH_IS_CONSTANT_EVALUATED(x))
  43. {
  44. if (boost::math::ccmath::abs(x) == static_cast<Real>(0))
  45. {
  46. return boost::math::ccmath::abs(y);
  47. }
  48. else if (boost::math::ccmath::abs(y) == static_cast<Real>(0))
  49. {
  50. return boost::math::ccmath::abs(x);
  51. }
  52. // Return +inf even if the other argument is NaN
  53. else if (boost::math::ccmath::isinf(x) || boost::math::ccmath::isinf(y))
  54. {
  55. return std::numeric_limits<Real>::infinity();
  56. }
  57. else if (boost::math::ccmath::isnan(x))
  58. {
  59. return x;
  60. }
  61. else if (boost::math::ccmath::isnan(y))
  62. {
  63. return y;
  64. }
  65. return boost::math::ccmath::detail::hypot_impl(x, y);
  66. }
  67. else
  68. {
  69. using std::hypot;
  70. return hypot(x, y);
  71. }
  72. }
  73. template <typename T1, typename T2>
  74. constexpr auto hypot(T1 x, T2 y) noexcept
  75. {
  76. if(BOOST_MATH_IS_CONSTANT_EVALUATED(x))
  77. {
  78. using promoted_type = boost::math::tools::promote_args_2_t<T1, T2>;
  79. return boost::math::ccmath::hypot(static_cast<promoted_type>(x), static_cast<promoted_type>(y));
  80. }
  81. else
  82. {
  83. using std::hypot;
  84. return hypot(x, y);
  85. }
  86. }
  87. constexpr float hypotf(float x, float y) noexcept
  88. {
  89. return boost::math::ccmath::hypot(x, y);
  90. }
  91. #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
  92. constexpr long double hypotl(long double x, long double y) noexcept
  93. {
  94. return boost::math::ccmath::hypot(x, y);
  95. }
  96. #endif
  97. } // Namespaces
  98. #endif // BOOST_MATH_CCMATH_HYPOT_HPP