]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/units/include/boost/units/detail/conversion_impl.hpp
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / units / include / boost / units / detail / conversion_impl.hpp
CommitLineData
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_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
33namespace boost {
34
35namespace units {
36
37namespace detail {
38
39template<class Source, class Dest>
40struct conversion_factor_helper;
41
42template<class Source, class Dest>
43struct call_base_unit_converter;
44
45}
46
47/// INTERNAL ONLY
48struct undefined_base_unit_converter_base {
49 static const bool is_defined = false;
50};
51
52/// INTERNAL ONLY
53struct no_default_conversion {
54 static const bool is_defined = false;
55};
56
57/// INTERNAL ONLY
58template<class BaseUnit>
59struct unscaled_get_default_conversion : no_default_conversion { };
60
61/// INTERNAL ONLY
62template<bool is_defined>
63struct unscaled_get_default_conversion_impl;
64
65/// INTERNAL ONLY
66template<>
67struct 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
77template<>
78struct 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
88template<class BaseUnit>
89struct 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
97template<class Source, class Destination>
98struct select_base_unit_converter
99{
100 typedef Source source_type;
101 typedef Destination destination_type;
102};
103
104/// INTERNAL ONLY
105template<class Source, class Dest>
106struct base_unit_converter_base : undefined_base_unit_converter_base {
107};
108
109/// INTERNAL ONLY
110template<class Source>
111struct 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
122template<class Source, class Dest>
123struct base_unit_converter : base_unit_converter_base<Source, Dest> { };
124
125namespace detail {
126
127template<class Source, class Dest>
128struct 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
144template<bool forward_is_defined, bool reverse_is_defined>
145struct call_base_unit_converter_base_unit_impl;
146
147template<>
148struct 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
157template<>
158struct 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
167template<>
168struct 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
182template<>
183struct 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
209template<int N>
210struct 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
229template<>
230struct 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
244template<bool is_defined>
245struct call_base_unit_converter_impl;
246
247template<>
248struct 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
257template<>
258struct 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
287template<class Source, class Dest>
288struct 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
292template<class Source, class Dest>
293struct 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
301template<int N>
302struct 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
321template<>
322struct 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
336template<class Unit1, class T1, class Unit2, class T2>
337struct 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
349namespace detail {
350
351template<class Source, class Dest>
352struct conversion_factor_helper;
353
354template<class D, class L1, class L2>
355struct 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
374template<class D, class L1, class L2>
375struct 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
396template<class D, class L1, class L2>
397struct 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.
418template<class D, class S1, class S2>
419struct 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