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> |
38 | static 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> |
49 | static 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> |
60 | static 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> |
68 | static 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> |
76 | static 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> |
95 | static 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> |
129 | 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 | |
136 | template <int N, typename T> |
137 | inline typename tools::promote_args<T>::type pow(T base) |
138 | { return pow<N>(base, policies::policy<>()); } |
139 | |
140 | #ifdef BOOST_MSVC |
141 | #pragma warning(pop) |
142 | #endif |
143 | |
144 | } // namespace math |
145 | } // namespace boost |
146 | |
147 | |
148 | #endif |
149 | |