Mercurial > hg > vamp-build-and-test
comparison DEPENDENCIES/generic/include/boost/units/detail/conversion_impl.hpp @ 16:2665513ce2d3
Add boost headers
author | Chris Cannam |
---|---|
date | Tue, 05 Aug 2014 11:11:38 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
15:663ca0da4350 | 16:2665513ce2d3 |
---|---|
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_CONVERSION_IMPL_HPP | |
12 #define BOOST_UNITS_DETAIL_CONVERSION_IMPL_HPP | |
13 | |
14 #include <boost/mpl/bool.hpp> | |
15 #include <boost/mpl/and.hpp> | |
16 #include <boost/mpl/divides.hpp> | |
17 #include <boost/preprocessor/seq/enum.hpp> | |
18 #include <boost/type_traits/is_same.hpp> | |
19 | |
20 #include <boost/units/heterogeneous_system.hpp> | |
21 #include <boost/units/homogeneous_system.hpp> | |
22 #include <boost/units/reduce_unit.hpp> | |
23 #include <boost/units/static_rational.hpp> | |
24 #include <boost/units/units_fwd.hpp> | |
25 #include <boost/units/detail/dimension_list.hpp> | |
26 #include <boost/units/detail/heterogeneous_conversion.hpp> | |
27 #include <boost/units/detail/one.hpp> | |
28 #include <boost/units/detail/static_rational_power.hpp> | |
29 #include <boost/units/detail/unscale.hpp> | |
30 | |
31 #include <boost/units/units_fwd.hpp> | |
32 | |
33 namespace boost { | |
34 | |
35 namespace units { | |
36 | |
37 namespace detail { | |
38 | |
39 template<class Source, class Dest> | |
40 struct conversion_factor_helper; | |
41 | |
42 template<class Source, class Dest> | |
43 struct call_base_unit_converter; | |
44 | |
45 } | |
46 | |
47 /// INTERNAL ONLY | |
48 struct undefined_base_unit_converter_base { | |
49 static const bool is_defined = false; | |
50 }; | |
51 | |
52 /// INTERNAL ONLY | |
53 struct no_default_conversion { | |
54 static const bool is_defined = false; | |
55 }; | |
56 | |
57 /// INTERNAL ONLY | |
58 template<class BaseUnit> | |
59 struct unscaled_get_default_conversion : no_default_conversion { }; | |
60 | |
61 /// INTERNAL ONLY | |
62 template<bool is_defined> | |
63 struct unscaled_get_default_conversion_impl; | |
64 | |
65 /// INTERNAL ONLY | |
66 template<> | |
67 struct unscaled_get_default_conversion_impl<true> | |
68 { | |
69 template<class T> | |
70 struct apply | |
71 { | |
72 typedef typename unscaled_get_default_conversion<typename unscale<T>::type>::type type; | |
73 }; | |
74 }; | |
75 | |
76 /// INTERNAL ONLY | |
77 template<> | |
78 struct unscaled_get_default_conversion_impl<false> | |
79 { | |
80 template<class T> | |
81 struct apply | |
82 { | |
83 typedef typename T::unit_type type; | |
84 }; | |
85 }; | |
86 | |
87 /// INTERNAL ONLY | |
88 template<class BaseUnit> | |
89 struct get_default_conversion | |
90 { | |
91 typedef typename unscaled_get_default_conversion_impl< | |
92 unscaled_get_default_conversion<typename unscale<BaseUnit>::type>::is_defined | |
93 >::template apply<BaseUnit>::type type; | |
94 }; | |
95 | |
96 /// INTERNAL ONLY | |
97 template<class Source, class Destination> | |
98 struct select_base_unit_converter | |
99 { | |
100 typedef Source source_type; | |
101 typedef Destination destination_type; | |
102 }; | |
103 | |
104 /// INTERNAL ONLY | |
105 template<class Source, class Dest> | |
106 struct base_unit_converter_base : undefined_base_unit_converter_base { | |
107 }; | |
108 | |
109 /// INTERNAL ONLY | |
110 template<class Source> | |
111 struct base_unit_converter_base<Source, BOOST_UNITS_MAKE_HETEROGENEOUS_UNIT(Source, typename Source::dimension_type)> | |
112 { | |
113 static const bool is_defined = true; | |
114 typedef one type; | |
115 static type value() { | |
116 one result; | |
117 return(result); | |
118 } | |
119 }; | |
120 | |
121 /// INTERNAL ONLY | |
122 template<class Source, class Dest> | |
123 struct base_unit_converter : base_unit_converter_base<Source, Dest> { }; | |
124 | |
125 namespace detail { | |
126 | |
127 template<class Source, class Dest> | |
128 struct do_call_base_unit_converter { | |
129 typedef select_base_unit_converter<typename unscale<Source>::type, typename unscale<Dest>::type> selector; | |
130 typedef typename selector::source_type source_type; | |
131 typedef typename selector::destination_type destination_type; | |
132 typedef base_unit_converter<source_type, destination_type> converter; | |
133 typedef typename mpl::divides<typename get_scale_list<Source>::type, typename get_scale_list<source_type>::type>::type source_factor; | |
134 typedef typename mpl::divides<typename get_scale_list<Dest>::type, typename get_scale_list<destination_type>::type>::type destination_factor; | |
135 typedef typename mpl::divides<source_factor, destination_factor>::type factor; | |
136 typedef eval_scale_list<factor> eval_factor; | |
137 typedef typename multiply_typeof_helper<typename converter::type, typename eval_factor::type>::type type; | |
138 static type value() | |
139 { | |
140 return(converter::value() * eval_factor::value()); | |
141 } | |
142 }; | |
143 | |
144 template<bool forward_is_defined, bool reverse_is_defined> | |
145 struct call_base_unit_converter_base_unit_impl; | |
146 | |
147 template<> | |
148 struct call_base_unit_converter_base_unit_impl<true, true> | |
149 { | |
150 template<class Source, class Dest> | |
151 struct apply | |
152 : do_call_base_unit_converter<Source, typename Dest::unit_type> | |
153 { | |
154 }; | |
155 }; | |
156 | |
157 template<> | |
158 struct call_base_unit_converter_base_unit_impl<true, false> | |
159 { | |
160 template<class Source, class Dest> | |
161 struct apply | |
162 : do_call_base_unit_converter<Source, typename Dest::unit_type> | |
163 { | |
164 }; | |
165 }; | |
166 | |
167 template<> | |
168 struct call_base_unit_converter_base_unit_impl<false, true> | |
169 { | |
170 template<class Source, class Dest> | |
171 struct apply | |
172 { | |
173 typedef do_call_base_unit_converter<Dest, typename Source::unit_type> converter; | |
174 typedef typename divide_typeof_helper<one, typename converter::type>::type type; | |
175 static type value() { | |
176 one numerator; | |
177 return(numerator / converter::value()); | |
178 } | |
179 }; | |
180 }; | |
181 | |
182 template<> | |
183 struct call_base_unit_converter_base_unit_impl<false, false> | |
184 { | |
185 template<class Source, class Dest> | |
186 struct apply | |
187 { | |
188 typedef typename reduce_unit<typename get_default_conversion<Source>::type>::type new_source; | |
189 typedef typename reduce_unit<typename get_default_conversion<Dest>::type>::type new_dest; | |
190 typedef call_base_unit_converter<Source, new_source> start; | |
191 typedef detail::conversion_factor_helper< | |
192 new_source, | |
193 new_dest | |
194 > conversion; | |
195 typedef call_base_unit_converter<Dest, new_dest> end; | |
196 typedef typename divide_typeof_helper< | |
197 typename multiply_typeof_helper< | |
198 typename start::type, | |
199 typename conversion::type | |
200 >::type, | |
201 typename end::type | |
202 >::type type; | |
203 static type value() { | |
204 return(start::value() * conversion::value() / end::value()); | |
205 } | |
206 }; | |
207 }; | |
208 | |
209 template<int N> | |
210 struct get_default_conversion_impl | |
211 { | |
212 template<class Begin> | |
213 struct apply | |
214 { | |
215 typedef typename Begin::item source_pair; | |
216 typedef typename source_pair::value_type exponent; | |
217 typedef typename source_pair::tag_type source; | |
218 typedef typename reduce_unit<typename get_default_conversion<source>::type>::type new_source; | |
219 typedef typename get_default_conversion_impl<N-1>::template apply<typename Begin::next> next_iteration; | |
220 typedef typename multiply_typeof_helper<typename power_typeof_helper<new_source, exponent>::type, typename next_iteration::unit_type>::type unit_type; | |
221 typedef call_base_unit_converter<source, new_source> conversion; | |
222 typedef typename multiply_typeof_helper<typename conversion::type, typename next_iteration::type>::type type; | |
223 static type value() { | |
224 return(static_rational_power<exponent>(conversion::value()) * next_iteration::value()); | |
225 } | |
226 }; | |
227 }; | |
228 | |
229 template<> | |
230 struct get_default_conversion_impl<0> | |
231 { | |
232 template<class Begin> | |
233 struct apply | |
234 { | |
235 typedef unit<dimensionless_type, heterogeneous_system<heterogeneous_system_impl<dimensionless_type, dimensionless_type, no_scale> > > unit_type; | |
236 typedef one type; | |
237 static one value() { | |
238 one result; | |
239 return(result); | |
240 } | |
241 }; | |
242 }; | |
243 | |
244 template<bool is_defined> | |
245 struct call_base_unit_converter_impl; | |
246 | |
247 template<> | |
248 struct call_base_unit_converter_impl<true> | |
249 { | |
250 template<class Source, class Dest> | |
251 struct apply | |
252 : do_call_base_unit_converter<Source, Dest> | |
253 { | |
254 }; | |
255 }; | |
256 | |
257 template<> | |
258 struct call_base_unit_converter_impl<false> | |
259 { | |
260 template<class Source, class Dest> | |
261 struct apply { | |
262 typedef typename reduce_unit<typename get_default_conversion<Source>::type>::type new_source; | |
263 typedef typename Dest::system_type::type system_list; | |
264 typedef typename get_default_conversion_impl<system_list::size::value>::template apply<system_list> impl; | |
265 typedef typename impl::unit_type new_dest; | |
266 typedef call_base_unit_converter<Source, new_source> start; | |
267 typedef conversion_factor_helper<new_source, new_dest> conversion; | |
268 typedef typename divide_typeof_helper< | |
269 typename multiply_typeof_helper< | |
270 typename start::type, | |
271 typename conversion::type | |
272 >::type, | |
273 typename impl::type | |
274 >::type type; | |
275 static type value() { | |
276 return(start::value() * conversion::value() / impl::value()); | |
277 } | |
278 }; | |
279 }; | |
280 | |
281 #define BOOST_UNITS_DETAIL_BASE_UNIT_CONVERTER_IS_DEFINED(Source, Dest)\ | |
282 base_unit_converter<\ | |
283 typename select_base_unit_converter<typename unscale<Source>::type, typename unscale<Dest>::type>::source_type,\ | |
284 typename select_base_unit_converter<typename unscale<Source>::type, typename unscale<Dest>::type>::destination_type\ | |
285 >::is_defined | |
286 | |
287 template<class Source, class Dest> | |
288 struct call_base_unit_converter : call_base_unit_converter_impl<BOOST_UNITS_DETAIL_BASE_UNIT_CONVERTER_IS_DEFINED(Source, Dest)>::template apply<Source, Dest> | |
289 { | |
290 }; | |
291 | |
292 template<class Source, class Dest> | |
293 struct call_base_unit_converter<Source, BOOST_UNITS_MAKE_HETEROGENEOUS_UNIT(Dest, typename Source::dimension_type)> : | |
294 call_base_unit_converter_base_unit_impl< | |
295 BOOST_UNITS_DETAIL_BASE_UNIT_CONVERTER_IS_DEFINED(Source, typename Dest::unit_type), | |
296 BOOST_UNITS_DETAIL_BASE_UNIT_CONVERTER_IS_DEFINED(Dest, typename Source::unit_type) | |
297 >::template apply<Source, Dest> | |
298 { | |
299 }; | |
300 | |
301 template<int N> | |
302 struct conversion_impl | |
303 { | |
304 template<class Begin, class DestinationSystem> | |
305 struct apply | |
306 { | |
307 typedef typename conversion_impl<N-1>::template apply< | |
308 typename Begin::next, | |
309 DestinationSystem | |
310 > next_iteration; | |
311 typedef typename Begin::item unit_pair; | |
312 typedef typename unit_pair::tag_type unit; | |
313 typedef typename unit::dimension_type dimensions; | |
314 typedef typename reduce_unit<units::unit<dimensions, DestinationSystem> >::type reduced_unit; | |
315 typedef detail::call_base_unit_converter<unit, reduced_unit> converter; | |
316 typedef typename multiply_typeof_helper<typename converter::type, typename next_iteration::type>::type type; | |
317 static type value() { return(static_rational_power<typename unit_pair::value_type>(converter::value()) * next_iteration::value()); } | |
318 }; | |
319 }; | |
320 | |
321 template<> | |
322 struct conversion_impl<0> | |
323 { | |
324 template<class Begin, class DestinationSystem> | |
325 struct apply | |
326 { | |
327 typedef one type; | |
328 static type value() { one result; return(result); } | |
329 }; | |
330 }; | |
331 | |
332 } // namespace detail | |
333 | |
334 /// forward to conversion_factor (intentionally allowing ADL) | |
335 /// INTERNAL ONLY | |
336 template<class Unit1, class T1, class Unit2, class T2> | |
337 struct conversion_helper<quantity<Unit1, T1>, quantity<Unit2, T2> > | |
338 { | |
339 /// INTERNAL ONLY | |
340 typedef quantity<Unit2, T2> destination_type; | |
341 static destination_type convert(const quantity<Unit1, T1>& source) | |
342 { | |
343 Unit1 u1; | |
344 Unit2 u2; | |
345 return(destination_type::from_value(static_cast<T2>(source.value() * conversion_factor(u1, u2)))); | |
346 } | |
347 }; | |
348 | |
349 namespace detail { | |
350 | |
351 template<class Source, class Dest> | |
352 struct conversion_factor_helper; | |
353 | |
354 template<class D, class L1, class L2> | |
355 struct conversion_factor_helper<unit<D, homogeneous_system<L1> >, unit<D, homogeneous_system<L2> > > | |
356 : conversion_factor_helper< | |
357 typename reduce_unit<unit<D, homogeneous_system<L1> > >::type, | |
358 typename reduce_unit<unit<D, homogeneous_system<L2> > >::type | |
359 > | |
360 { | |
361 //typedef typename reduce_unit<unit<D, homogeneous_system<L1> > >::type source_unit; | |
362 //typedef typename source_unit::system_type::type unit_list; | |
363 //typedef typename detail::conversion_impl<unit_list::size::value>::template apply< | |
364 // unit_list, | |
365 // homogeneous_system<L2> | |
366 //> impl; | |
367 //typedef typename impl::type type; | |
368 //static type value() | |
369 //{ | |
370 // return(impl::value()); | |
371 //} | |
372 }; | |
373 | |
374 template<class D, class L1, class L2> | |
375 struct conversion_factor_helper<unit<D, heterogeneous_system<L1> >, unit<D, homogeneous_system<L2> > > | |
376 : conversion_factor_helper< | |
377 typename reduce_unit<unit<D, heterogeneous_system<L1> > >::type, | |
378 typename reduce_unit<unit<D, homogeneous_system<L2> > >::type | |
379 > | |
380 { | |
381 //typedef typename detail::conversion_impl<L1::type::size::value>::template apply< | |
382 // typename L1::type, | |
383 // homogeneous_system<L2> | |
384 //> impl; | |
385 //typedef eval_scale_list<typename L1::scale> scale; | |
386 //typedef typename multiply_typeof_helper<typename impl::type, typename scale::type>::type type; | |
387 //static type value() | |
388 //{ | |
389 // return(impl::value() * scale::value()); | |
390 //} | |
391 }; | |
392 | |
393 // There is no simple algorithm for doing this conversion | |
394 // other than just defining it as the reverse of the | |
395 // heterogeneous->homogeneous case | |
396 template<class D, class L1, class L2> | |
397 struct conversion_factor_helper<unit<D, homogeneous_system<L1> >, unit<D, heterogeneous_system<L2> > > | |
398 : conversion_factor_helper< | |
399 typename reduce_unit<unit<D, homogeneous_system<L1> > >::type, | |
400 typename reduce_unit<unit<D, heterogeneous_system<L2> > >::type | |
401 > | |
402 { | |
403 //typedef typename detail::conversion_impl<L2::type::size::value>::template apply< | |
404 // typename L2::type, | |
405 // homogeneous_system<L1> | |
406 //> impl; | |
407 //typedef eval_scale_list<typename L2::scale> scale; | |
408 //typedef typename multiply_typeof_helper<typename impl::type, typename scale::type>::type type; | |
409 //static type value() | |
410 //{ | |
411 // one numerator; | |
412 // return(numerator / (impl::value() * scale::value())); | |
413 //} | |
414 }; | |
415 | |
416 /// Requires that all possible conversions | |
417 /// between base units are defined. | |
418 template<class D, class S1, class S2> | |
419 struct conversion_factor_helper<unit<D, heterogeneous_system<S1> >, unit<D, heterogeneous_system<S2> > > | |
420 { | |
421 /// INTERNAL ONLY | |
422 typedef typename detail::extract_base_units<S1::type::size::value>::template apply< | |
423 typename S1::type, | |
424 dimensionless_type | |
425 >::type from_base_units; | |
426 /// INTERNAL ONLY | |
427 typedef typename detail::extract_base_units<S2::type::size::value>::template apply< | |
428 typename S2::type, | |
429 from_base_units | |
430 >::type all_base_units; | |
431 /// INTERNAL ONLY | |
432 typedef typename detail::make_homogeneous_system<all_base_units>::type system; | |
433 typedef typename detail::conversion_impl<S1::type::size::value>::template apply< | |
434 typename S1::type, | |
435 system | |
436 > conversion1; | |
437 typedef typename detail::conversion_impl<S2::type::size::value>::template apply< | |
438 typename S2::type, | |
439 system | |
440 > conversion2; | |
441 typedef eval_scale_list<typename mpl::divides<typename S1::scale, typename S2::scale>::type> scale; | |
442 typedef typename multiply_typeof_helper< | |
443 typename conversion1::type, | |
444 typename divide_typeof_helper<typename scale::type, typename conversion2::type>::type | |
445 >::type type; | |
446 static type value() | |
447 { | |
448 return(conversion1::value() * (scale::value() / conversion2::value())); | |
449 } | |
450 }; | |
451 | |
452 } // namespace detail | |
453 | |
454 } // namespace units | |
455 | |
456 } // namespace boost | |
457 | |
458 #endif // BOOST_UNITS_CONVERSION_IMPL_HPP |