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