1 //   Boost pow.hpp header file
2 //   Computes a power with exponent known at compile-time
3 
4 //  (C) Copyright Bruno Lalande 2008.
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 
9 //  See http://www.boost.org for updates, documentation, and revision history.
10 
11 
12 #ifndef BOOST_MATH_POW_HPP
13 #define BOOST_MATH_POW_HPP
14 
15 
16 #include <boost/math/special_functions/math_fwd.hpp>
17 #include <boost/math/policies/policy.hpp>
18 #include <boost/math/policies/error_handling.hpp>
19 #include <boost/math/tools/promotion.hpp>
20 #include <boost/mpl/greater_equal.hpp>
21 
22 
23 namespace boost {
24 namespace math {
25 
26 #ifdef BOOST_MSVC
27 #pragma warning(push)
28 #pragma warning(disable:4702) // Unreachable code, only triggered in release mode and /W4
29 #endif
30 
31 namespace detail {
32 
33 
34 template <int N, int M = N%2>
35 struct positive_power
36 {
37     template <typename T>
resultboost::math::detail::positive_power38     static BOOST_CXX14_CONSTEXPR T result(T base)
39     {
40         T power = positive_power<N/2>::result(base);
41         return power * power;
42     }
43 };
44 
45 template <int N>
46 struct positive_power<N, 1>
47 {
48     template <typename T>
resultboost::math::detail::positive_power49     static BOOST_CXX14_CONSTEXPR T result(T base)
50     {
51         T power = positive_power<N/2>::result(base);
52         return base * power * power;
53     }
54 };
55 
56 template <>
57 struct positive_power<1, 1>
58 {
59     template <typename T>
resultboost::math::detail::positive_power60     static BOOST_CXX14_CONSTEXPR T result(T base){ return base; }
61 };
62 
63 
64 template <int N, bool>
65 struct power_if_positive
66 {
67     template <typename T, class Policy>
resultboost::math::detail::power_if_positive68     static BOOST_CXX14_CONSTEXPR T result(T base, const Policy&)
69     { return positive_power<N>::result(base); }
70 };
71 
72 template <int N>
73 struct power_if_positive<N, false>
74 {
75     template <typename T, class Policy>
resultboost::math::detail::power_if_positive76     static BOOST_CXX14_CONSTEXPR T result(T base, const Policy& policy)
77     {
78         if (base == 0)
79         {
80             return policies::raise_overflow_error<T>(
81                        "boost::math::pow(%1%)",
82                        "Attempted to compute a negative power of 0",
83                        policy
84                    );
85         }
86 
87         return T(1) / positive_power<-N>::result(base);
88     }
89 };
90 
91 template <>
92 struct power_if_positive<0, true>
93 {
94     template <typename T, class Policy>
resultboost::math::detail::power_if_positive95     static BOOST_CXX14_CONSTEXPR T result(T base, const Policy& policy)
96     {
97         if (base == 0)
98         {
99             return policies::raise_indeterminate_result_error<T>(
100                        "boost::math::pow(%1%)",
101                        "The result of pow<0>(%1%) is undetermined",
102                        base,
103                        T(1),
104                        policy
105                    );
106         }
107 
108         return T(1);
109     }
110 };
111 
112 
113 template <int N>
114 struct select_power_if_positive
115 {
116     typedef typename mpl::greater_equal<
117                          boost::integral_constant<int, N>,
118                          boost::integral_constant<int, 0>
119                      >::type is_positive;
120 
121     typedef power_if_positive<N, is_positive::value> type;
122 };
123 
124 
125 }  // namespace detail
126 
127 
128 template <int N, typename T, class Policy>
pow(T base,const Policy & policy)129 BOOST_CXX14_CONSTEXPR inline typename tools::promote_args<T>::type pow(T base, const Policy& policy)
130 {
131    typedef typename tools::promote_args<T>::type result_type;
132    return detail::select_power_if_positive<N>::type::result(static_cast<result_type>(base), policy);
133 }
134 
135 template <int N, typename T>
pow(T base)136 BOOST_CXX14_CONSTEXPR inline typename tools::promote_args<T>::type pow(T base)
137 { return pow<N>(base, policies::policy<>()); }
138 
139 #ifdef BOOST_MSVC
140 #pragma warning(pop)
141 #endif
142 
143 }  // namespace math
144 }  // namespace boost
145 
146 
147 #endif
148