]>
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) 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_DIMENSION_IMPL_HPP | |
12 | #define BOOST_UNITS_DIMENSION_IMPL_HPP | |
13 | ||
14 | #include <boost/mpl/begin_end.hpp> | |
15 | #include <boost/mpl/deref.hpp> | |
16 | #include <boost/mpl/if.hpp> | |
17 | #include <boost/mpl/list.hpp> | |
18 | #include <boost/mpl/next.hpp> | |
19 | #include <boost/mpl/size.hpp> | |
20 | #include <boost/mpl/less.hpp> | |
21 | ||
22 | #include <boost/units/config.hpp> | |
23 | #include <boost/units/dimensionless_type.hpp> | |
24 | #include <boost/units/static_rational.hpp> | |
25 | #include <boost/units/units_fwd.hpp> | |
26 | #include <boost/units/detail/dimension_list.hpp> | |
27 | #include <boost/units/detail/push_front_if.hpp> | |
28 | #include <boost/units/detail/push_front_or_add.hpp> | |
29 | ||
30 | /// \file | |
31 | /// \brief Core class and metaprogramming utilities for compile-time dimensional analysis. | |
32 | ||
33 | namespace boost { | |
34 | ||
35 | namespace units { | |
36 | ||
37 | namespace detail { | |
38 | ||
39 | template<int N> | |
40 | struct insertion_sort_dims_insert; | |
41 | ||
42 | template<bool is_greater> | |
43 | struct insertion_sort_dims_comparison_impl; | |
44 | ||
45 | // have to recursively add the element to the next sequence. | |
46 | template<> | |
47 | struct insertion_sort_dims_comparison_impl<true> { | |
48 | template<class Begin, int N, class T> | |
49 | struct apply { | |
50 | typedef list< | |
51 | typename Begin::item, | |
52 | typename insertion_sort_dims_insert<N - 1>::template apply< | |
53 | typename Begin::next, | |
54 | T | |
55 | >::type | |
56 | > type; | |
57 | }; | |
58 | }; | |
59 | ||
60 | // either prepend the current element or join it to | |
61 | // the first remaining element of the sequence. | |
62 | template<> | |
63 | struct insertion_sort_dims_comparison_impl<false> { | |
64 | template<class Begin, int N, class T> | |
65 | struct apply { | |
66 | typedef typename push_front_or_add<Begin, T>::type type; | |
67 | }; | |
68 | }; | |
69 | ||
70 | template<int N> | |
71 | struct insertion_sort_dims_insert { | |
72 | template<class Begin, class T> | |
73 | struct apply { | |
74 | typedef typename insertion_sort_dims_comparison_impl<mpl::less<typename Begin::item, T>::value>::template apply< | |
75 | Begin, | |
76 | N, | |
77 | T | |
78 | >::type type; | |
79 | }; | |
80 | }; | |
81 | ||
82 | template<> | |
83 | struct insertion_sort_dims_insert<0> { | |
84 | template<class Begin, class T> | |
85 | struct apply { | |
86 | typedef list<T, dimensionless_type> type; | |
87 | }; | |
88 | }; | |
89 | ||
90 | template<int N> | |
91 | struct insertion_sort_dims_mpl_sequence { | |
92 | template<class Begin> | |
93 | struct apply { | |
94 | typedef typename insertion_sort_dims_mpl_sequence<N - 1>::template apply<typename mpl::next<Begin>::type>::type next; | |
95 | typedef typename insertion_sort_dims_insert<(next::size::value)>::template apply<next, typename mpl::deref<Begin>::type>::type type; | |
96 | }; | |
97 | }; | |
98 | ||
99 | template<> | |
100 | struct insertion_sort_dims_mpl_sequence<0> { | |
101 | template<class Begin> | |
102 | struct apply { | |
103 | typedef dimensionless_type type; | |
104 | }; | |
105 | }; | |
106 | ||
107 | template<int N> | |
108 | struct insertion_sort_dims_impl { | |
109 | template<class Begin> | |
110 | struct apply { | |
111 | typedef typename insertion_sort_dims_impl<N - 1>::template apply<typename Begin::next>::type next; | |
112 | typedef typename insertion_sort_dims_insert<(next::size::value)>::template apply<next, typename Begin::item>::type type; | |
113 | }; | |
114 | }; | |
115 | ||
116 | template<> | |
117 | struct insertion_sort_dims_impl<0> { | |
118 | template<class Begin> | |
119 | struct apply { | |
120 | typedef dimensionless_type type; | |
121 | }; | |
122 | }; | |
123 | ||
124 | template<class T> | |
125 | struct sort_dims | |
126 | { | |
127 | typedef typename insertion_sort_dims_mpl_sequence<mpl::size<T>::value>::template apply<typename mpl::begin<T>::type>::type type; | |
128 | }; | |
129 | ||
130 | ||
131 | template<class T, class Next> | |
132 | struct sort_dims<list<T, Next> > | |
133 | { | |
134 | typedef typename insertion_sort_dims_impl<list<T, Next>::size::value>::template apply<list<T, Next> >::type type; | |
135 | }; | |
136 | ||
137 | /// sorted sequences can be merged in linear time | |
138 | template<bool less, bool greater> | |
139 | struct merge_dimensions_func; | |
140 | ||
141 | template<int N1, int N2> | |
142 | struct merge_dimensions_impl; | |
143 | ||
144 | template<> | |
145 | struct merge_dimensions_func<true, false> | |
146 | { | |
147 | template<typename Begin1, typename Begin2, int N1, int N2> | |
148 | struct apply | |
149 | { | |
150 | typedef list< | |
151 | typename Begin1::item, | |
152 | typename merge_dimensions_impl<N1 - 1, N2>::template apply< | |
153 | typename Begin1::next, | |
154 | Begin2 | |
155 | >::type | |
156 | > type; | |
157 | }; | |
158 | }; | |
159 | ||
160 | template<> | |
161 | struct merge_dimensions_func<false, true> { | |
162 | template<typename Begin1, typename Begin2, int N1, int N2> | |
163 | struct apply | |
164 | { | |
165 | typedef list< | |
166 | typename Begin2::item, | |
167 | typename merge_dimensions_impl<N2 - 1, N1>::template apply< | |
168 | typename Begin2::next, | |
169 | Begin1 | |
170 | >::type | |
171 | > type; | |
172 | }; | |
173 | }; | |
174 | ||
175 | template<> | |
176 | struct merge_dimensions_func<false, false> { | |
177 | template<typename Begin1, typename Begin2, int N1, int N2> | |
178 | struct apply | |
179 | { | |
180 | typedef typename mpl::plus<typename Begin1::item, typename Begin2::item>::type combined; | |
181 | typedef typename push_front_if<!is_empty_dim<combined>::value>::template apply< | |
182 | typename merge_dimensions_impl<N1 - 1, N2 - 1>::template apply< | |
183 | typename Begin1::next, | |
184 | typename Begin2::next | |
185 | >::type, | |
186 | combined | |
187 | >::type type; | |
188 | }; | |
189 | }; | |
190 | ||
191 | template<int N1, int N2> | |
192 | struct merge_dimensions_impl { | |
193 | template<typename Begin1, typename Begin2> | |
194 | struct apply | |
195 | { | |
196 | typedef typename Begin1::item dim1; | |
197 | typedef typename Begin2::item dim2; | |
198 | ||
199 | typedef typename merge_dimensions_func<(mpl::less<dim1,dim2>::value == true), | |
200 | (mpl::less<dim2,dim1>::value == true)>::template apply< | |
201 | Begin1, | |
202 | Begin2, | |
203 | N1, | |
204 | N2 | |
205 | >::type type; | |
206 | }; | |
207 | }; | |
208 | ||
209 | template<typename Sequence1, typename Sequence2> | |
210 | struct merge_dimensions | |
211 | { | |
212 | typedef typename detail::merge_dimensions_impl<Sequence1::size::value, | |
213 | Sequence2::size::value>::template | |
214 | apply< | |
215 | Sequence1, | |
216 | Sequence2 | |
217 | >::type type; | |
218 | }; | |
219 | ||
220 | template<int N> | |
221 | struct iterator_to_list | |
222 | { | |
223 | template<typename Begin> | |
224 | struct apply | |
225 | { | |
226 | typedef list< | |
227 | typename Begin::item, | |
228 | typename iterator_to_list<N - 1>::template apply< | |
229 | typename Begin::next | |
230 | >::type | |
231 | > type; | |
232 | }; | |
233 | }; | |
234 | ||
235 | template<> | |
236 | struct iterator_to_list<0> | |
237 | { | |
238 | template<typename Begin> | |
239 | struct apply { | |
240 | typedef dimensionless_type type; | |
241 | }; | |
242 | }; | |
243 | ||
244 | template<int N> | |
245 | struct merge_dimensions_impl<N, 0> | |
246 | { | |
247 | template<typename Begin1, typename Begin2> | |
248 | struct apply | |
249 | { | |
250 | typedef typename iterator_to_list<N>::template apply<Begin1>::type type; | |
251 | }; | |
252 | }; | |
253 | ||
254 | template<int N> | |
255 | struct merge_dimensions_impl<0, N> | |
256 | { | |
257 | template<typename Begin1, typename Begin2> | |
258 | struct apply | |
259 | { | |
260 | typedef typename iterator_to_list<N>::template apply<Begin2>::type type; | |
261 | }; | |
262 | }; | |
263 | ||
264 | template<> | |
265 | struct merge_dimensions_impl<0, 0> | |
266 | { | |
267 | template<typename Begin1, typename Begin2> | |
268 | struct apply | |
269 | { | |
270 | typedef dimensionless_type type; | |
271 | }; | |
272 | }; | |
273 | ||
274 | template<int N> | |
275 | struct static_inverse_impl | |
276 | { | |
277 | template<typename Begin> | |
278 | struct apply { | |
279 | typedef list< | |
280 | typename mpl::negate<typename Begin::item>::type, | |
281 | typename static_inverse_impl<N - 1>::template apply< | |
282 | typename Begin::next | |
283 | >::type | |
284 | > type; | |
285 | }; | |
286 | }; | |
287 | ||
288 | template<> | |
289 | struct static_inverse_impl<0> | |
290 | { | |
291 | template<typename Begin> | |
292 | struct apply | |
293 | { | |
294 | typedef dimensionless_type type; | |
295 | }; | |
296 | }; | |
297 | ||
298 | template<int N> | |
299 | struct static_power_impl | |
300 | { | |
301 | template<typename Begin, typename Ex> | |
302 | struct apply | |
303 | { | |
304 | typedef list< | |
305 | typename mpl::times<typename Begin::item, Ex>::type, | |
306 | typename detail::static_power_impl<N - 1>::template apply<typename Begin::next, Ex>::type | |
307 | > type; | |
308 | }; | |
309 | }; | |
310 | ||
311 | template<> | |
312 | struct static_power_impl<0> | |
313 | { | |
314 | template<typename Begin, typename Ex> | |
315 | struct apply | |
316 | { | |
317 | typedef dimensionless_type type; | |
318 | }; | |
319 | }; | |
320 | ||
321 | template<int N> | |
322 | struct static_root_impl { | |
323 | template<class Begin, class Ex> | |
324 | struct apply { | |
325 | typedef list< | |
326 | typename mpl::divides<typename Begin::item, Ex>::type, | |
327 | typename detail::static_root_impl<N - 1>::template apply<typename Begin::next, Ex>::type | |
328 | > type; | |
329 | }; | |
330 | }; | |
331 | ||
332 | template<> | |
333 | struct static_root_impl<0> { | |
334 | template<class Begin, class Ex> | |
335 | struct apply | |
336 | { | |
337 | typedef dimensionless_type type; | |
338 | }; | |
339 | }; | |
340 | ||
341 | } // namespace detail | |
342 | ||
343 | } // namespace units | |
344 | ||
345 | } // namespace boost | |
346 | ||
347 | #endif // BOOST_UNITS_DIMENSION_IMPL_HPP |