]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // Boost.Units - A C++ library for zero-overhead dimensional analysis and |
2 | // unit/quantity manipulation and conversion | |
3 | // | |
4 | // Copyright (C) 2003-2008 Matthias Christian Schabel | |
5 | // Copyright (C) 2007-2008 Steven Watanabe | |
6 | // | |
7 | // Distributed under the Boost Software License, Version 1.0. (See | |
8 | // accompanying file LICENSE_1_0.txt or copy at | |
9 | // http://www.boost.org/LICENSE_1_0.txt) | |
10 | ||
11 | #ifndef BOOST_UNITS_DETAIL_STATIC_RATIONAL_POWER_HPP | |
12 | #define BOOST_UNITS_DETAIL_STATIC_RATIONAL_POWER_HPP | |
13 | ||
14 | #include <boost/config/no_tr1/cmath.hpp> | |
15 | ||
16 | #include <boost/units/detail/one.hpp> | |
17 | #include <boost/units/operators.hpp> | |
18 | ||
19 | namespace boost { | |
20 | ||
21 | namespace units { | |
22 | ||
23 | template<long N,long D> | |
24 | class static_rational; | |
25 | ||
26 | namespace detail { | |
27 | ||
28 | namespace typeof_pow_adl_barrier { | |
29 | ||
30 | using std::pow; | |
31 | ||
32 | template<class Y> | |
33 | struct typeof_pow | |
34 | { | |
35 | #if defined(BOOST_UNITS_HAS_BOOST_TYPEOF) | |
36 | BOOST_TYPEOF_NESTED_TYPEDEF_TPL(nested, pow(typeof_::make<Y>(), 0.0)) | |
37 | typedef typename nested::type type; | |
38 | #elif defined(BOOST_UNITS_HAS_MWERKS_TYPEOF) | |
39 | typedef __typeof__(pow(typeof_::make<Y>(), 0.0)) type; | |
40 | #elif defined(BOOST_UNITS_HAS_GNU_TYPEOF) | |
41 | typedef typeof(pow(typeof_::make<Y>(), 0.0)) type; | |
42 | #else | |
43 | typedef Y type; | |
44 | #endif | |
45 | }; | |
46 | ||
47 | } | |
48 | ||
49 | template<class R, class Y> | |
50 | struct static_rational_power_impl | |
51 | { | |
52 | typedef typename typeof_pow_adl_barrier::typeof_pow<Y>::type type; | |
53 | static type call(const Y& y) | |
54 | { | |
55 | using std::pow; | |
56 | return(pow(y, static_cast<double>(R::Numerator) / static_cast<double>(R::Denominator))); | |
57 | } | |
58 | }; | |
59 | ||
60 | template<class R> | |
61 | struct static_rational_power_impl<R, one> | |
62 | { | |
63 | typedef one type; | |
64 | static one call(const one&) | |
65 | { | |
66 | one result; | |
67 | return(result); | |
68 | } | |
69 | }; | |
70 | ||
71 | template<long N> | |
72 | struct static_rational_power_impl<static_rational<N, 1>, one> | |
73 | { | |
74 | typedef one type; | |
75 | static one call(const one&) | |
76 | { | |
77 | one result; | |
78 | return(result); | |
79 | } | |
80 | }; | |
81 | ||
82 | template<long N, bool = (N % 2 == 0)> | |
83 | struct static_int_power_impl; | |
84 | ||
85 | template<long N> | |
86 | struct static_int_power_impl<N, true> | |
87 | { | |
88 | template<class Y, class R> | |
89 | struct apply | |
90 | { | |
91 | typedef typename multiply_typeof_helper<Y, Y>::type square_type; | |
92 | typedef typename static_int_power_impl<(N >> 1)>::template apply<square_type, R> next; | |
93 | typedef typename next::type type; | |
94 | static type call(const Y& y, const R& r) | |
95 | { | |
96 | const square_type square = y * y; | |
97 | return(next::call(square, r)); | |
98 | } | |
99 | }; | |
100 | }; | |
101 | ||
102 | template<long N> | |
103 | struct static_int_power_impl<N, false> | |
104 | { | |
105 | template<class Y, class R> | |
106 | struct apply | |
107 | { | |
108 | typedef typename multiply_typeof_helper<Y, Y>::type square_type; | |
109 | typedef typename multiply_typeof_helper<Y, R>::type new_r; | |
110 | typedef typename static_int_power_impl<(N >> 1)>::template apply<square_type, new_r> next; | |
111 | typedef typename next::type type; | |
112 | static type call(const Y& y, const R& r) | |
113 | { | |
114 | const Y square = y * y; | |
115 | return(next::call(square, y * r)); | |
116 | } | |
117 | }; | |
118 | }; | |
119 | ||
120 | template<> | |
121 | struct static_int_power_impl<1, false> | |
122 | { | |
123 | template<class Y, class R> | |
124 | struct apply | |
125 | { | |
126 | typedef typename multiply_typeof_helper<Y, R>::type type; | |
127 | static type call(const Y& y, const R& r) | |
128 | { | |
129 | return(y * r); | |
130 | } | |
131 | }; | |
132 | }; | |
133 | ||
134 | template<> | |
135 | struct static_int_power_impl<0, true> | |
136 | { | |
137 | template<class Y, class R> | |
138 | struct apply | |
139 | { | |
140 | typedef R type; | |
141 | static R call(const Y&, const R& r) | |
142 | { | |
143 | return(r); | |
144 | } | |
145 | }; | |
146 | }; | |
147 | ||
148 | template<int N, bool = (N < 0)> | |
149 | struct static_int_power_sign_impl; | |
150 | ||
151 | template<int N> | |
152 | struct static_int_power_sign_impl<N, false> | |
153 | { | |
154 | template<class Y> | |
155 | struct apply | |
156 | { | |
157 | typedef typename static_int_power_impl<N>::template apply<Y, one> impl; | |
158 | typedef typename impl::type type; | |
159 | static type call(const Y& y) | |
160 | { | |
161 | one result; | |
162 | return(impl::call(y, result)); | |
163 | } | |
164 | }; | |
165 | }; | |
166 | ||
167 | template<int N> | |
168 | struct static_int_power_sign_impl<N, true> | |
169 | { | |
170 | template<class Y> | |
171 | struct apply | |
172 | { | |
173 | typedef typename static_int_power_impl<-N>::template apply<Y, one> impl; | |
174 | typedef typename divide_typeof_helper<one, typename impl::type>::type type; | |
175 | static type call(const Y& y) | |
176 | { | |
177 | one result; | |
178 | return(result/impl::call(y, result)); | |
179 | } | |
180 | }; | |
181 | }; | |
182 | ||
183 | template<long N, class Y> | |
184 | struct static_rational_power_impl<static_rational<N, 1>, Y> | |
185 | { | |
186 | typedef typename static_int_power_sign_impl<N>::template apply<Y> impl; | |
187 | typedef typename impl::type type; | |
188 | static type call(const Y& y) | |
189 | { | |
190 | return(impl::call(y)); | |
191 | } | |
192 | }; | |
193 | ||
194 | template<class R, class Y> | |
195 | typename detail::static_rational_power_impl<R, Y>::type static_rational_power(const Y& y) | |
196 | { | |
197 | return(detail::static_rational_power_impl<R, Y>::call(y)); | |
198 | } | |
199 | ||
200 | } // namespace detail | |
201 | ||
202 | } // namespace units | |
203 | ||
204 | } // namespace boost | |
205 | ||
206 | #endif |