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) 2007-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_HETEROGENEOUS_SYSTEM_HPP
|
Chris@16
|
12 #define BOOST_UNITS_HETEROGENEOUS_SYSTEM_HPP
|
Chris@16
|
13
|
Chris@16
|
14 /// \file
|
Chris@16
|
15 /// \brief A heterogeneous system is a sorted list of base unit/exponent pairs.
|
Chris@16
|
16
|
Chris@16
|
17 #include <boost/mpl/bool.hpp>
|
Chris@16
|
18 #include <boost/mpl/plus.hpp>
|
Chris@16
|
19 #include <boost/mpl/times.hpp>
|
Chris@16
|
20 #include <boost/mpl/divides.hpp>
|
Chris@16
|
21 #include <boost/mpl/negate.hpp>
|
Chris@16
|
22 #include <boost/mpl/less.hpp>
|
Chris@16
|
23 #include <boost/mpl/size.hpp>
|
Chris@16
|
24 #include <boost/mpl/begin.hpp>
|
Chris@16
|
25 #include <boost/mpl/next.hpp>
|
Chris@16
|
26 #include <boost/mpl/deref.hpp>
|
Chris@16
|
27 #include <boost/mpl/front.hpp>
|
Chris@16
|
28 #include <boost/mpl/push_front.hpp>
|
Chris@16
|
29 #include <boost/mpl/pop_front.hpp>
|
Chris@16
|
30 #include <boost/mpl/assert.hpp>
|
Chris@16
|
31 #include <boost/type_traits/is_same.hpp>
|
Chris@16
|
32
|
Chris@16
|
33 #include <boost/units/config.hpp>
|
Chris@16
|
34 #include <boost/units/static_rational.hpp>
|
Chris@16
|
35 #include <boost/units/dimension.hpp>
|
Chris@16
|
36 #include <boost/units/units_fwd.hpp>
|
Chris@16
|
37 #include <boost/units/detail/push_front_if.hpp>
|
Chris@16
|
38 #include <boost/units/detail/push_front_or_add.hpp>
|
Chris@16
|
39 #include <boost/units/detail/linear_algebra.hpp>
|
Chris@16
|
40 #include <boost/units/detail/unscale.hpp>
|
Chris@16
|
41
|
Chris@16
|
42 namespace boost {
|
Chris@16
|
43
|
Chris@16
|
44 namespace units {
|
Chris@16
|
45
|
Chris@16
|
46 namespace detail {
|
Chris@16
|
47
|
Chris@16
|
48 // A normal system is a sorted list of base units.
|
Chris@16
|
49 // A heterogeneous system is a sorted list of base unit/exponent pairs.
|
Chris@16
|
50 // As long as we don't need to convert heterogeneous systems
|
Chris@16
|
51 // directly everything is cool.
|
Chris@16
|
52
|
Chris@16
|
53 template<class T>
|
Chris@16
|
54 struct is_zero : mpl::false_ {};
|
Chris@16
|
55
|
Chris@16
|
56 template<>
|
Chris@16
|
57 struct is_zero<static_rational<0> > : mpl::true_ {};
|
Chris@16
|
58
|
Chris@16
|
59 } // namespace detail
|
Chris@16
|
60
|
Chris@16
|
61 /// INTERNAL ONLY
|
Chris@16
|
62 template<class L, class Dimensions, class Scale>
|
Chris@16
|
63 struct heterogeneous_system_impl
|
Chris@16
|
64 {
|
Chris@16
|
65 typedef L type;
|
Chris@16
|
66 typedef Dimensions dimensions;
|
Chris@16
|
67 typedef Scale scale;
|
Chris@16
|
68 };
|
Chris@16
|
69
|
Chris@16
|
70 /// INTERNAL ONLY
|
Chris@16
|
71 typedef dimensionless_type no_scale;
|
Chris@16
|
72
|
Chris@16
|
73 /// A system that can represent any possible combination
|
Chris@16
|
74 /// of units at the expense of not preserving information
|
Chris@16
|
75 /// about how it was created. Do not create specializations
|
Chris@16
|
76 /// of this template directly. Instead use @c reduce_unit and
|
Chris@16
|
77 /// @c base_unit<...>::unit_type.
|
Chris@16
|
78 template<class T>
|
Chris@16
|
79 struct heterogeneous_system : T {};
|
Chris@16
|
80
|
Chris@16
|
81 /// INTERNAL ONLY
|
Chris@16
|
82 struct heterogeneous_system_dim_tag {};
|
Chris@16
|
83
|
Chris@16
|
84 /// INTERNAL ONLY
|
Chris@16
|
85 template<class Unit, class Exponent>
|
Chris@16
|
86 struct heterogeneous_system_dim
|
Chris@16
|
87 {
|
Chris@16
|
88 typedef heterogeneous_system_dim_tag tag;
|
Chris@16
|
89 typedef heterogeneous_system_dim type;
|
Chris@16
|
90 typedef Unit tag_type;
|
Chris@16
|
91 typedef Exponent value_type;
|
Chris@16
|
92 };
|
Chris@16
|
93
|
Chris@16
|
94 /// INTERNAL ONLY
|
Chris@16
|
95 #define BOOST_UNITS_MAKE_HETEROGENEOUS_UNIT(BaseUnit, Dimensions) \
|
Chris@16
|
96 boost::units::unit< \
|
Chris@16
|
97 Dimensions, \
|
Chris@16
|
98 boost::units::heterogeneous_system< \
|
Chris@16
|
99 boost::units::heterogeneous_system_impl< \
|
Chris@16
|
100 boost::units::list< \
|
Chris@16
|
101 boost::units::heterogeneous_system_dim< \
|
Chris@16
|
102 BaseUnit, \
|
Chris@16
|
103 boost::units::static_rational<1> \
|
Chris@16
|
104 >, \
|
Chris@16
|
105 boost::units::dimensionless_type \
|
Chris@16
|
106 >, \
|
Chris@16
|
107 Dimensions, \
|
Chris@16
|
108 boost::units::no_scale \
|
Chris@16
|
109 > \
|
Chris@16
|
110 > \
|
Chris@16
|
111 >
|
Chris@16
|
112
|
Chris@16
|
113 } // namespace units
|
Chris@16
|
114
|
Chris@16
|
115 } // namespace boost
|
Chris@16
|
116
|
Chris@16
|
117
|
Chris@16
|
118 #if BOOST_UNITS_HAS_BOOST_TYPEOF
|
Chris@16
|
119
|
Chris@16
|
120 #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()
|
Chris@16
|
121
|
Chris@16
|
122 BOOST_TYPEOF_REGISTER_TEMPLATE(boost::units::heterogeneous_system_impl, (class)(class)(class))
|
Chris@16
|
123 BOOST_TYPEOF_REGISTER_TEMPLATE(boost::units::heterogeneous_system, (class))
|
Chris@16
|
124 BOOST_TYPEOF_REGISTER_TEMPLATE(boost::units::heterogeneous_system_dim, (class)(class))
|
Chris@16
|
125
|
Chris@16
|
126 #endif
|
Chris@16
|
127
|
Chris@16
|
128 namespace boost {
|
Chris@16
|
129
|
Chris@16
|
130 namespace mpl {
|
Chris@16
|
131
|
Chris@16
|
132 /// INTERNAL ONLY
|
Chris@16
|
133 template<>
|
Chris@16
|
134 struct less_impl<boost::units::heterogeneous_system_dim_tag, boost::units::heterogeneous_system_dim_tag>
|
Chris@16
|
135 {
|
Chris@16
|
136 template<class T0, class T1>
|
Chris@16
|
137 struct apply : mpl::less<typename T0::tag_type, typename T1::tag_type> {};
|
Chris@16
|
138 };
|
Chris@16
|
139
|
Chris@16
|
140 }
|
Chris@16
|
141
|
Chris@16
|
142 namespace units {
|
Chris@16
|
143
|
Chris@16
|
144 namespace detail {
|
Chris@16
|
145
|
Chris@16
|
146 template<class Unit1, class Exponent1>
|
Chris@16
|
147 struct is_empty_dim<heterogeneous_system_dim<Unit1,Exponent1> > : detail::is_zero<Exponent1> {};
|
Chris@16
|
148
|
Chris@16
|
149 } // namespace detail
|
Chris@16
|
150
|
Chris@16
|
151 } // namespace units
|
Chris@16
|
152
|
Chris@16
|
153 namespace mpl {
|
Chris@16
|
154
|
Chris@16
|
155 /// INTERNAL ONLY
|
Chris@16
|
156 template<>
|
Chris@16
|
157 struct plus_impl<boost::units::heterogeneous_system_dim_tag, boost::units::heterogeneous_system_dim_tag>
|
Chris@16
|
158 {
|
Chris@16
|
159 template<class T0, class T1>
|
Chris@16
|
160 struct apply
|
Chris@16
|
161 {
|
Chris@16
|
162 typedef boost::units::heterogeneous_system_dim<
|
Chris@16
|
163 typename T0::tag_type,
|
Chris@16
|
164 typename mpl::plus<typename T0::value_type,typename T1::value_type>::type
|
Chris@16
|
165 > type;
|
Chris@16
|
166 };
|
Chris@16
|
167 };
|
Chris@16
|
168
|
Chris@16
|
169 /// INTERNAL ONLY
|
Chris@16
|
170 template<>
|
Chris@16
|
171 struct times_impl<boost::units::heterogeneous_system_dim_tag, boost::units::detail::static_rational_tag>
|
Chris@16
|
172 {
|
Chris@16
|
173 template<class T0, class T1>
|
Chris@16
|
174 struct apply
|
Chris@16
|
175 {
|
Chris@16
|
176 typedef boost::units::heterogeneous_system_dim<
|
Chris@16
|
177 typename T0::tag_type,
|
Chris@16
|
178 typename mpl::times<typename T0::value_type,T1>::type
|
Chris@16
|
179 > type;
|
Chris@16
|
180 };
|
Chris@16
|
181 };
|
Chris@16
|
182
|
Chris@16
|
183 /// INTERNAL ONLY
|
Chris@16
|
184 template<>
|
Chris@16
|
185 struct divides_impl<boost::units::heterogeneous_system_dim_tag, boost::units::detail::static_rational_tag>
|
Chris@16
|
186 {
|
Chris@16
|
187 template<class T0, class T1>
|
Chris@16
|
188 struct apply
|
Chris@16
|
189 {
|
Chris@16
|
190 typedef boost::units::heterogeneous_system_dim<
|
Chris@16
|
191 typename T0::tag_type,
|
Chris@16
|
192 typename mpl::divides<typename T0::value_type,T1>::type
|
Chris@16
|
193 > type;
|
Chris@16
|
194 };
|
Chris@16
|
195 };
|
Chris@16
|
196
|
Chris@16
|
197 /// INTERNAL ONLY
|
Chris@16
|
198 template<>
|
Chris@16
|
199 struct negate_impl<boost::units::heterogeneous_system_dim_tag>
|
Chris@16
|
200 {
|
Chris@16
|
201 template<class T>
|
Chris@16
|
202 struct apply
|
Chris@16
|
203 {
|
Chris@16
|
204 typedef boost::units::heterogeneous_system_dim<typename T::tag_type, typename mpl::negate<typename T::value_type>::type> type;
|
Chris@16
|
205 };
|
Chris@16
|
206 };
|
Chris@16
|
207
|
Chris@16
|
208 } // namespace mpl
|
Chris@16
|
209
|
Chris@16
|
210 namespace units {
|
Chris@16
|
211
|
Chris@16
|
212 namespace detail {
|
Chris@16
|
213
|
Chris@16
|
214 template<int N>
|
Chris@16
|
215 struct make_heterogeneous_system_impl
|
Chris@16
|
216 {
|
Chris@16
|
217 template<class UnitsBegin, class ExponentsBegin>
|
Chris@16
|
218 struct apply
|
Chris@16
|
219 {
|
Chris@16
|
220 typedef typename push_front_if<!(is_zero<typename ExponentsBegin::item>::value)>::template apply<
|
Chris@16
|
221 typename make_heterogeneous_system_impl<N-1>::template apply<
|
Chris@16
|
222 typename UnitsBegin::next,
|
Chris@16
|
223 typename ExponentsBegin::next
|
Chris@16
|
224 >::type,
|
Chris@16
|
225 heterogeneous_system_dim<typename UnitsBegin::item, typename ExponentsBegin::item>
|
Chris@16
|
226 >::type type;
|
Chris@16
|
227 };
|
Chris@16
|
228 };
|
Chris@16
|
229
|
Chris@16
|
230 template<>
|
Chris@16
|
231 struct make_heterogeneous_system_impl<0>
|
Chris@16
|
232 {
|
Chris@16
|
233 template<class UnitsBegin, class ExponentsBegin>
|
Chris@16
|
234 struct apply
|
Chris@16
|
235 {
|
Chris@16
|
236 typedef dimensionless_type type;
|
Chris@16
|
237 };
|
Chris@16
|
238 };
|
Chris@16
|
239
|
Chris@16
|
240 template<class Dimensions, class System>
|
Chris@16
|
241 struct make_heterogeneous_system
|
Chris@16
|
242 {
|
Chris@16
|
243 typedef typename calculate_base_unit_exponents<typename System::type, Dimensions>::type exponents;
|
Chris@16
|
244 BOOST_MPL_ASSERT_MSG((!boost::is_same<exponents, inconsistent>::value), the_specified_dimension_is_not_representible_in_the_given_system, (types<Dimensions, System>));
|
Chris@16
|
245 typedef typename make_heterogeneous_system_impl<System::type::size::value>::template apply<
|
Chris@16
|
246 typename System::type,
|
Chris@16
|
247 exponents
|
Chris@16
|
248 >::type unit_list;
|
Chris@16
|
249 typedef heterogeneous_system<heterogeneous_system_impl<unit_list, Dimensions, no_scale> > type;
|
Chris@16
|
250 };
|
Chris@16
|
251
|
Chris@16
|
252 template<class Dimensions, class T>
|
Chris@16
|
253 struct make_heterogeneous_system<Dimensions, heterogeneous_system<T> >
|
Chris@16
|
254 {
|
Chris@16
|
255 typedef heterogeneous_system<T> type;
|
Chris@16
|
256 };
|
Chris@16
|
257
|
Chris@16
|
258 template<class T0, class T1>
|
Chris@16
|
259 struct multiply_systems
|
Chris@16
|
260 {
|
Chris@16
|
261 typedef heterogeneous_system<
|
Chris@16
|
262 heterogeneous_system_impl<
|
Chris@16
|
263 typename mpl::times<typename T0::type, typename T1::type>::type,
|
Chris@16
|
264 typename mpl::times<typename T0::dimensions, typename T1::dimensions>::type,
|
Chris@16
|
265 typename mpl::times<typename T0::scale, typename T1::scale>::type
|
Chris@16
|
266 >
|
Chris@16
|
267 > type;
|
Chris@16
|
268 };
|
Chris@16
|
269
|
Chris@16
|
270 template<class T0, class T1>
|
Chris@16
|
271 struct divide_systems
|
Chris@16
|
272 {
|
Chris@16
|
273 typedef heterogeneous_system<
|
Chris@16
|
274 heterogeneous_system_impl<
|
Chris@16
|
275 typename mpl::divides<typename T0::type, typename T1::type>::type,
|
Chris@16
|
276 typename mpl::divides<typename T0::dimensions, typename T1::dimensions>::type,
|
Chris@16
|
277 typename mpl::divides<typename T0::scale, typename T1::scale>::type
|
Chris@16
|
278 >
|
Chris@16
|
279 > type;
|
Chris@16
|
280 };
|
Chris@16
|
281
|
Chris@16
|
282 } // namespace detail
|
Chris@16
|
283
|
Chris@16
|
284 /// INTERNAL ONLY
|
Chris@16
|
285 template<class S, long N, long D>
|
Chris@16
|
286 struct static_power<heterogeneous_system<S>, static_rational<N,D> >
|
Chris@16
|
287 {
|
Chris@16
|
288 typedef heterogeneous_system<
|
Chris@16
|
289 heterogeneous_system_impl<
|
Chris@16
|
290 typename static_power<typename S::type, static_rational<N,D> >::type,
|
Chris@16
|
291 typename static_power<typename S::dimensions, static_rational<N,D> >::type,
|
Chris@16
|
292 typename static_power<typename S::scale, static_rational<N,D> >::type
|
Chris@16
|
293 >
|
Chris@16
|
294 > type;
|
Chris@16
|
295 };
|
Chris@16
|
296
|
Chris@16
|
297 /// INTERNAL ONLY
|
Chris@16
|
298 template<class S, long N, long D>
|
Chris@16
|
299 struct static_root<heterogeneous_system<S>, static_rational<N,D> >
|
Chris@16
|
300 {
|
Chris@16
|
301 typedef heterogeneous_system<
|
Chris@16
|
302 heterogeneous_system_impl<
|
Chris@16
|
303 typename static_root<typename S::type, static_rational<N,D> >::type,
|
Chris@16
|
304 typename static_root<typename S::dimensions, static_rational<N,D> >::type,
|
Chris@16
|
305 typename static_root<typename S::scale, static_rational<N,D> >::type
|
Chris@16
|
306 >
|
Chris@16
|
307 > type;
|
Chris@16
|
308 };
|
Chris@16
|
309
|
Chris@16
|
310 namespace detail {
|
Chris@16
|
311
|
Chris@16
|
312 template<int N>
|
Chris@16
|
313 struct unscale_heterogeneous_system_impl
|
Chris@16
|
314 {
|
Chris@16
|
315 template<class Begin>
|
Chris@16
|
316 struct apply
|
Chris@16
|
317 {
|
Chris@16
|
318 typedef typename push_front_or_add<
|
Chris@16
|
319 typename unscale_heterogeneous_system_impl<N-1>::template apply<
|
Chris@16
|
320 typename Begin::next
|
Chris@16
|
321 >::type,
|
Chris@16
|
322 typename unscale<typename Begin::item>::type
|
Chris@16
|
323 >::type type;
|
Chris@16
|
324 };
|
Chris@16
|
325 };
|
Chris@16
|
326
|
Chris@16
|
327 template<>
|
Chris@16
|
328 struct unscale_heterogeneous_system_impl<0>
|
Chris@16
|
329 {
|
Chris@16
|
330 template<class Begin>
|
Chris@16
|
331 struct apply
|
Chris@16
|
332 {
|
Chris@16
|
333 typedef dimensionless_type type;
|
Chris@16
|
334 };
|
Chris@16
|
335 };
|
Chris@16
|
336
|
Chris@16
|
337 } // namespace detail
|
Chris@16
|
338
|
Chris@16
|
339 /// Unscale all the base units. e.g
|
Chris@16
|
340 /// km s -> m s
|
Chris@16
|
341 /// cm km -> m^2
|
Chris@16
|
342 /// INTERNAL ONLY
|
Chris@16
|
343 template<class T>
|
Chris@16
|
344 struct unscale<heterogeneous_system<T> >
|
Chris@16
|
345 {
|
Chris@16
|
346 typedef heterogeneous_system<
|
Chris@16
|
347 heterogeneous_system_impl<
|
Chris@16
|
348 typename detail::unscale_heterogeneous_system_impl<
|
Chris@16
|
349 T::type::size::value
|
Chris@16
|
350 >::template apply<
|
Chris@16
|
351 typename T::type
|
Chris@16
|
352 >::type,
|
Chris@16
|
353 typename T::dimensions,
|
Chris@16
|
354 no_scale
|
Chris@16
|
355 >
|
Chris@16
|
356 > type;
|
Chris@16
|
357 };
|
Chris@16
|
358
|
Chris@16
|
359 /// INTERNAL ONLY
|
Chris@16
|
360 template<class Unit, class Exponent>
|
Chris@16
|
361 struct unscale<heterogeneous_system_dim<Unit, Exponent> >
|
Chris@16
|
362 {
|
Chris@16
|
363 typedef heterogeneous_system_dim<typename unscale<Unit>::type, Exponent> type;
|
Chris@16
|
364 };
|
Chris@16
|
365
|
Chris@16
|
366 namespace detail {
|
Chris@16
|
367
|
Chris@16
|
368 template<int N>
|
Chris@16
|
369 struct get_scale_list_of_heterogeneous_system_impl
|
Chris@16
|
370 {
|
Chris@16
|
371 template<class Begin>
|
Chris@16
|
372 struct apply
|
Chris@16
|
373 {
|
Chris@16
|
374 typedef typename mpl::times<
|
Chris@16
|
375 typename get_scale_list_of_heterogeneous_system_impl<N-1>::template apply<
|
Chris@16
|
376 typename Begin::next
|
Chris@16
|
377 >::type,
|
Chris@16
|
378 typename get_scale_list<typename Begin::item>::type
|
Chris@16
|
379 >::type type;
|
Chris@16
|
380 };
|
Chris@16
|
381 };
|
Chris@16
|
382
|
Chris@16
|
383 template<>
|
Chris@16
|
384 struct get_scale_list_of_heterogeneous_system_impl<0>
|
Chris@16
|
385 {
|
Chris@16
|
386 template<class Begin>
|
Chris@16
|
387 struct apply
|
Chris@16
|
388 {
|
Chris@16
|
389 typedef dimensionless_type type;
|
Chris@16
|
390 };
|
Chris@16
|
391 };
|
Chris@16
|
392
|
Chris@16
|
393 } // namespace detail
|
Chris@16
|
394
|
Chris@16
|
395 /// INTERNAL ONLY
|
Chris@16
|
396 template<class T>
|
Chris@16
|
397 struct get_scale_list<heterogeneous_system<T> >
|
Chris@16
|
398 {
|
Chris@16
|
399 typedef typename mpl::times<
|
Chris@16
|
400 typename detail::get_scale_list_of_heterogeneous_system_impl<
|
Chris@16
|
401 T::type::size::value
|
Chris@16
|
402 >::template apply<typename T::type>::type,
|
Chris@16
|
403 typename T::scale
|
Chris@16
|
404 >::type type;
|
Chris@16
|
405 };
|
Chris@16
|
406
|
Chris@16
|
407 /// INTERNAL ONLY
|
Chris@16
|
408 template<class Unit, class Exponent>
|
Chris@16
|
409 struct get_scale_list<heterogeneous_system_dim<Unit, Exponent> >
|
Chris@16
|
410 {
|
Chris@16
|
411 typedef typename static_power<typename get_scale_list<Unit>::type, Exponent>::type type;
|
Chris@16
|
412 };
|
Chris@16
|
413
|
Chris@16
|
414 namespace detail {
|
Chris@16
|
415
|
Chris@16
|
416 template<class System, class Dimension>
|
Chris@16
|
417 struct check_system : mpl::false_ {};
|
Chris@16
|
418
|
Chris@16
|
419 template<class System, class Dimension, class Scale>
|
Chris@16
|
420 struct check_system<heterogeneous_system<heterogeneous_system_impl<System, Dimension, Scale> >, Dimension> : mpl::true_ {};
|
Chris@16
|
421
|
Chris@16
|
422 } // namespace detail
|
Chris@16
|
423
|
Chris@16
|
424 } // namespace units
|
Chris@16
|
425
|
Chris@16
|
426 } // namespace boost
|
Chris@16
|
427
|
Chris@16
|
428 #endif
|