pow.hpp 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  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. #include <boost/mpl/greater_equal.hpp>
  15. namespace boost {
  16. namespace math {
  17. #ifdef BOOST_MSVC
  18. #pragma warning(push)
  19. #pragma warning(disable:4702) // Unreachable code, only triggered in release mode and /W4
  20. #endif
  21. namespace detail {
  22. template <int N, int M = N%2>
  23. struct positive_power
  24. {
  25. template <typename T>
  26. static T result(T base)
  27. {
  28. T power = positive_power<N/2>::result(base);
  29. return power * power;
  30. }
  31. };
  32. template <int N>
  33. struct positive_power<N, 1>
  34. {
  35. template <typename T>
  36. static T result(T base)
  37. {
  38. T power = positive_power<N/2>::result(base);
  39. return base * power * power;
  40. }
  41. };
  42. template <>
  43. struct positive_power<1, 1>
  44. {
  45. template <typename T>
  46. static T result(T base){ return base; }
  47. };
  48. template <int N, bool>
  49. struct power_if_positive
  50. {
  51. template <typename T, class Policy>
  52. static T result(T base, const Policy&)
  53. { return positive_power<N>::result(base); }
  54. };
  55. template <int N>
  56. struct power_if_positive<N, false>
  57. {
  58. template <typename T, class Policy>
  59. static T result(T base, const Policy& policy)
  60. {
  61. if (base == 0)
  62. {
  63. return policies::raise_overflow_error<T>(
  64. "boost::math::pow(%1%)",
  65. "Attempted to compute a negative power of 0",
  66. policy
  67. );
  68. }
  69. return T(1) / positive_power<-N>::result(base);
  70. }
  71. };
  72. template <>
  73. struct power_if_positive<0, true>
  74. {
  75. template <typename T, class Policy>
  76. static T result(T base, const Policy& policy)
  77. {
  78. if (base == 0)
  79. {
  80. return policies::raise_indeterminate_result_error<T>(
  81. "boost::math::pow(%1%)",
  82. "The result of pow<0>(%1%) is undetermined",
  83. base,
  84. T(1),
  85. policy
  86. );
  87. }
  88. return T(1);
  89. }
  90. };
  91. template <int N>
  92. struct select_power_if_positive
  93. {
  94. typedef typename mpl::greater_equal<
  95. mpl::int_<N>,
  96. mpl::int_<0>
  97. >::type is_positive;
  98. typedef power_if_positive<N, is_positive::value> type;
  99. };
  100. } // namespace detail
  101. template <int N, typename T, class Policy>
  102. inline typename tools::promote_args<T>::type pow(T base, const Policy& policy)
  103. {
  104. typedef typename tools::promote_args<T>::type result_type;
  105. return detail::select_power_if_positive<N>::type::result(static_cast<result_type>(base), policy);
  106. }
  107. template <int N, typename T>
  108. inline typename tools::promote_args<T>::type pow(T base)
  109. { return pow<N>(base, policies::policy<>()); }
  110. #ifdef BOOST_MSVC
  111. #pragma warning(pop)
  112. #endif
  113. } // namespace math
  114. } // namespace boost
  115. #endif