pow.hpp 3.1 KB

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