pow.hpp 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. // Boost pow.hpp header file
  2. // Computes a power with exponent known at compile-time
  3. // (C) Copyright Bruno Lalande 2008.
  4. // (C) Copyright Matt Borland 2024.
  5. // Distributed under the Boost Software License, Version 1.0.
  6. // (See accompanying file LICENSE_1_0.txt or copy at
  7. // http://www.boost.org/LICENSE_1_0.txt)
  8. // See http://www.boost.org for updates, documentation, and revision history.
  9. #ifndef BOOST_MATH_POW_HPP
  10. #define BOOST_MATH_POW_HPP
  11. #include <boost/math/tools/config.hpp>
  12. #include <boost/math/policies/policy.hpp>
  13. #include <boost/math/policies/error_handling.hpp>
  14. #include <boost/math/tools/promotion.hpp>
  15. #ifndef BOOST_MATH_HAS_NVRTC
  16. #include <boost/math/special_functions/math_fwd.hpp>
  17. #endif
  18. namespace boost {
  19. namespace math {
  20. #ifdef _MSC_VER
  21. #pragma warning(push)
  22. #pragma warning(disable:4702) // Unreachable code, only triggered in release mode and /W4
  23. #endif
  24. namespace detail {
  25. template <int N, int M = N%2>
  26. struct positive_power
  27. {
  28. template <typename T>
  29. BOOST_MATH_GPU_ENABLED static constexpr T result(T base)
  30. {
  31. T power = positive_power<N/2>::result(base);
  32. return power * power;
  33. }
  34. };
  35. template <int N>
  36. struct positive_power<N, 1>
  37. {
  38. template <typename T>
  39. BOOST_MATH_GPU_ENABLED static constexpr T result(T base)
  40. {
  41. T power = positive_power<N/2>::result(base);
  42. return base * power * power;
  43. }
  44. };
  45. template <>
  46. struct positive_power<1, 1>
  47. {
  48. template <typename T>
  49. BOOST_MATH_GPU_ENABLED static constexpr T result(T base){ return base; }
  50. };
  51. template <int N, bool>
  52. struct power_if_positive
  53. {
  54. template <typename T, class Policy>
  55. BOOST_MATH_GPU_ENABLED static constexpr T result(T base, const Policy&)
  56. { return positive_power<N>::result(base); }
  57. };
  58. template <int N>
  59. struct power_if_positive<N, false>
  60. {
  61. template <typename T, class Policy>
  62. BOOST_MATH_GPU_ENABLED static constexpr T result(T base, const Policy& policy)
  63. {
  64. if (base == 0)
  65. {
  66. return policies::raise_overflow_error<T>(
  67. "boost::math::pow(%1%)",
  68. "Attempted to compute a negative power of 0",
  69. policy
  70. );
  71. }
  72. return T(1) / positive_power<-N>::result(base);
  73. }
  74. };
  75. template <>
  76. struct power_if_positive<0, true>
  77. {
  78. template <typename T, class Policy>
  79. BOOST_MATH_GPU_ENABLED static constexpr T result(T base, const Policy& policy)
  80. {
  81. if (base == 0)
  82. {
  83. return policies::raise_indeterminate_result_error<T>(
  84. "boost::math::pow(%1%)",
  85. "The result of pow<0>(%1%) is undetermined",
  86. base,
  87. T(1),
  88. policy
  89. );
  90. }
  91. return T(1);
  92. }
  93. };
  94. template <int N>
  95. struct select_power_if_positive
  96. {
  97. using type = power_if_positive<N, (N >= 0)>;
  98. };
  99. } // namespace detail
  100. template <int N, typename T, class Policy>
  101. BOOST_MATH_GPU_ENABLED constexpr inline typename tools::promote_args<T>::type pow(T base, const Policy& policy)
  102. {
  103. using result_type = typename tools::promote_args<T>::type;
  104. return detail::select_power_if_positive<N>::type::result(static_cast<result_type>(base), policy);
  105. }
  106. template <int N, typename T>
  107. BOOST_MATH_GPU_ENABLED constexpr inline typename tools::promote_args<T>::type pow(T base)
  108. { return pow<N>(base, policies::policy<>()); }
  109. #ifdef _MSC_VER
  110. #pragma warning(pop)
  111. #endif
  112. } // namespace math
  113. } // namespace boost
  114. #endif