pow.hpp 3.3 KB

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