]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/boost/units/detail/conversion_impl.hpp
update sources to ceph Nautilus 14.2.1
[ceph.git] / ceph / src / boost / 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 {
11fdf7f2 49 BOOST_STATIC_CONSTEXPR bool is_defined = false;
7c673cae
FG
50};
51
52/// INTERNAL ONLY
53struct no_default_conversion {
11fdf7f2 54 BOOST_STATIC_CONSTEXPR bool is_defined = false;
7c673cae
FG
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{
11fdf7f2 113 BOOST_STATIC_CONSTEXPR bool is_defined = true;
7c673cae 114 typedef one type;
11fdf7f2
TL
115 static BOOST_CONSTEXPR type value() {
116 return(one());
7c673cae
FG
117 }
118};
119
120/// INTERNAL ONLY
121template<class Source, class Dest>
122struct base_unit_converter : base_unit_converter_base<Source, Dest> { };
123
124namespace detail {
125
126template<class Source, class Dest>
127struct do_call_base_unit_converter {
128 typedef select_base_unit_converter<typename unscale<Source>::type, typename unscale<Dest>::type> selector;
129 typedef typename selector::source_type source_type;
130 typedef typename selector::destination_type destination_type;
131 typedef base_unit_converter<source_type, destination_type> converter;
132 typedef typename mpl::divides<typename get_scale_list<Source>::type, typename get_scale_list<source_type>::type>::type source_factor;
133 typedef typename mpl::divides<typename get_scale_list<Dest>::type, typename get_scale_list<destination_type>::type>::type destination_factor;
134 typedef typename mpl::divides<source_factor, destination_factor>::type factor;
135 typedef eval_scale_list<factor> eval_factor;
136 typedef typename multiply_typeof_helper<typename converter::type, typename eval_factor::type>::type type;
11fdf7f2 137 static BOOST_CONSTEXPR type value()
7c673cae
FG
138 {
139 return(converter::value() * eval_factor::value());
140 }
141};
142
143template<bool forward_is_defined, bool reverse_is_defined>
144struct call_base_unit_converter_base_unit_impl;
145
146template<>
147struct call_base_unit_converter_base_unit_impl<true, true>
148{
149 template<class Source, class Dest>
150 struct apply
151 : do_call_base_unit_converter<Source, typename Dest::unit_type>
152 {
153 };
154};
155
156template<>
157struct call_base_unit_converter_base_unit_impl<true, false>
158{
159 template<class Source, class Dest>
160 struct apply
161 : do_call_base_unit_converter<Source, typename Dest::unit_type>
162 {
163 };
164};
165
166template<>
167struct call_base_unit_converter_base_unit_impl<false, true>
168{
169 template<class Source, class Dest>
170 struct apply
171 {
172 typedef do_call_base_unit_converter<Dest, typename Source::unit_type> converter;
173 typedef typename divide_typeof_helper<one, typename converter::type>::type type;
11fdf7f2
TL
174 static BOOST_CONSTEXPR type value() {
175 return(one() / converter::value());
7c673cae
FG
176 }
177 };
178};
179
180template<>
181struct call_base_unit_converter_base_unit_impl<false, false>
182{
183 template<class Source, class Dest>
184 struct apply
185 {
186 typedef typename reduce_unit<typename get_default_conversion<Source>::type>::type new_source;
187 typedef typename reduce_unit<typename get_default_conversion<Dest>::type>::type new_dest;
188 typedef call_base_unit_converter<Source, new_source> start;
189 typedef detail::conversion_factor_helper<
190 new_source,
191 new_dest
192 > conversion;
193 typedef call_base_unit_converter<Dest, new_dest> end;
194 typedef typename divide_typeof_helper<
195 typename multiply_typeof_helper<
196 typename start::type,
197 typename conversion::type
198 >::type,
199 typename end::type
200 >::type type;
11fdf7f2 201 static BOOST_CONSTEXPR type value() {
7c673cae
FG
202 return(start::value() * conversion::value() / end::value());
203 }
204 };
205};
206
207template<int N>
208struct get_default_conversion_impl
209{
210 template<class Begin>
211 struct apply
212 {
213 typedef typename Begin::item source_pair;
214 typedef typename source_pair::value_type exponent;
215 typedef typename source_pair::tag_type source;
216 typedef typename reduce_unit<typename get_default_conversion<source>::type>::type new_source;
217 typedef typename get_default_conversion_impl<N-1>::template apply<typename Begin::next> next_iteration;
218 typedef typename multiply_typeof_helper<typename power_typeof_helper<new_source, exponent>::type, typename next_iteration::unit_type>::type unit_type;
219 typedef call_base_unit_converter<source, new_source> conversion;
220 typedef typename multiply_typeof_helper<typename conversion::type, typename next_iteration::type>::type type;
11fdf7f2 221 static BOOST_CONSTEXPR type value() {
7c673cae
FG
222 return(static_rational_power<exponent>(conversion::value()) * next_iteration::value());
223 }
224 };
225};
226
227template<>
228struct get_default_conversion_impl<0>
229{
230 template<class Begin>
231 struct apply
232 {
233 typedef unit<dimensionless_type, heterogeneous_system<heterogeneous_system_impl<dimensionless_type, dimensionless_type, no_scale> > > unit_type;
234 typedef one type;
11fdf7f2
TL
235 static BOOST_CONSTEXPR one value() {
236 return(one());
7c673cae
FG
237 }
238 };
239};
240
241template<bool is_defined>
242struct call_base_unit_converter_impl;
243
244template<>
245struct call_base_unit_converter_impl<true>
246{
247 template<class Source, class Dest>
248 struct apply
249 : do_call_base_unit_converter<Source, Dest>
250 {
251 };
252};
253
254template<>
255struct call_base_unit_converter_impl<false>
256{
257 template<class Source, class Dest>
258 struct apply {
259 typedef typename reduce_unit<typename get_default_conversion<Source>::type>::type new_source;
260 typedef typename Dest::system_type::type system_list;
261 typedef typename get_default_conversion_impl<system_list::size::value>::template apply<system_list> impl;
262 typedef typename impl::unit_type new_dest;
263 typedef call_base_unit_converter<Source, new_source> start;
264 typedef conversion_factor_helper<new_source, new_dest> conversion;
265 typedef typename divide_typeof_helper<
266 typename multiply_typeof_helper<
267 typename start::type,
268 typename conversion::type
269 >::type,
270 typename impl::type
271 >::type type;
11fdf7f2 272 static BOOST_CONSTEXPR type value() {
7c673cae
FG
273 return(start::value() * conversion::value() / impl::value());
274 }
275 };
276};
277
278#define BOOST_UNITS_DETAIL_BASE_UNIT_CONVERTER_IS_DEFINED(Source, Dest)\
279 base_unit_converter<\
280 typename select_base_unit_converter<typename unscale<Source>::type, typename unscale<Dest>::type>::source_type,\
281 typename select_base_unit_converter<typename unscale<Source>::type, typename unscale<Dest>::type>::destination_type\
282 >::is_defined
283
284template<class Source, class Dest>
285struct call_base_unit_converter : call_base_unit_converter_impl<BOOST_UNITS_DETAIL_BASE_UNIT_CONVERTER_IS_DEFINED(Source, Dest)>::template apply<Source, Dest>
286{
287};
288
289template<class Source, class Dest>
290struct call_base_unit_converter<Source, BOOST_UNITS_MAKE_HETEROGENEOUS_UNIT(Dest, typename Source::dimension_type)> :
291 call_base_unit_converter_base_unit_impl<
292 BOOST_UNITS_DETAIL_BASE_UNIT_CONVERTER_IS_DEFINED(Source, typename Dest::unit_type),
293 BOOST_UNITS_DETAIL_BASE_UNIT_CONVERTER_IS_DEFINED(Dest, typename Source::unit_type)
294 >::template apply<Source, Dest>
295{
296};
297
298template<int N>
299struct conversion_impl
300{
301 template<class Begin, class DestinationSystem>
302 struct apply
303 {
304 typedef typename conversion_impl<N-1>::template apply<
305 typename Begin::next,
306 DestinationSystem
307 > next_iteration;
308 typedef typename Begin::item unit_pair;
309 typedef typename unit_pair::tag_type unit;
310 typedef typename unit::dimension_type dimensions;
311 typedef typename reduce_unit<units::unit<dimensions, DestinationSystem> >::type reduced_unit;
312 typedef detail::call_base_unit_converter<unit, reduced_unit> converter;
313 typedef typename multiply_typeof_helper<typename converter::type, typename next_iteration::type>::type type;
11fdf7f2 314 static BOOST_CONSTEXPR type value() { return(static_rational_power<typename unit_pair::value_type>(converter::value()) * next_iteration::value()); }
7c673cae
FG
315 };
316};
317
318template<>
319struct conversion_impl<0>
320{
321 template<class Begin, class DestinationSystem>
322 struct apply
323 {
324 typedef one type;
11fdf7f2 325 static BOOST_CONSTEXPR type value() { return(one()); }
7c673cae
FG
326 };
327};
328
329} // namespace detail
330
331/// forward to conversion_factor (intentionally allowing ADL)
332/// INTERNAL ONLY
333template<class Unit1, class T1, class Unit2, class T2>
334struct conversion_helper<quantity<Unit1, T1>, quantity<Unit2, T2> >
335{
336 /// INTERNAL ONLY
337 typedef quantity<Unit2, T2> destination_type;
11fdf7f2 338 static BOOST_CONSTEXPR destination_type convert(const quantity<Unit1, T1>& source)
7c673cae 339 {
11fdf7f2 340 return(destination_type::from_value(static_cast<T2>(source.value() * conversion_factor(Unit1(), Unit2()))));
7c673cae
FG
341 }
342};
343
344namespace detail {
345
346template<class Source, class Dest>
347struct conversion_factor_helper;
348
349template<class D, class L1, class L2>
350struct conversion_factor_helper<unit<D, homogeneous_system<L1> >, unit<D, homogeneous_system<L2> > >
351 : conversion_factor_helper<
352 typename reduce_unit<unit<D, homogeneous_system<L1> > >::type,
353 typename reduce_unit<unit<D, homogeneous_system<L2> > >::type
354 >
355{
356 //typedef typename reduce_unit<unit<D, homogeneous_system<L1> > >::type source_unit;
357 //typedef typename source_unit::system_type::type unit_list;
358 //typedef typename detail::conversion_impl<unit_list::size::value>::template apply<
359 // unit_list,
360 // homogeneous_system<L2>
361 //> impl;
362 //typedef typename impl::type type;
11fdf7f2 363 //static BOOST_CONSTEXPR type value()
7c673cae
FG
364 //{
365 // return(impl::value());
366 //}
367};
368
369template<class D, class L1, class L2>
370struct conversion_factor_helper<unit<D, heterogeneous_system<L1> >, unit<D, homogeneous_system<L2> > >
371 : conversion_factor_helper<
372 typename reduce_unit<unit<D, heterogeneous_system<L1> > >::type,
373 typename reduce_unit<unit<D, homogeneous_system<L2> > >::type
374 >
375{
376 //typedef typename detail::conversion_impl<L1::type::size::value>::template apply<
377 // typename L1::type,
378 // homogeneous_system<L2>
379 //> impl;
380 //typedef eval_scale_list<typename L1::scale> scale;
381 //typedef typename multiply_typeof_helper<typename impl::type, typename scale::type>::type type;
11fdf7f2 382 //static BOOST_CONSTEXPR type value()
7c673cae
FG
383 //{
384 // return(impl::value() * scale::value());
385 //}
386};
387
388// There is no simple algorithm for doing this conversion
389// other than just defining it as the reverse of the
390// heterogeneous->homogeneous case
391template<class D, class L1, class L2>
392struct conversion_factor_helper<unit<D, homogeneous_system<L1> >, unit<D, heterogeneous_system<L2> > >
393 : conversion_factor_helper<
394 typename reduce_unit<unit<D, homogeneous_system<L1> > >::type,
395 typename reduce_unit<unit<D, heterogeneous_system<L2> > >::type
396 >
397{
398 //typedef typename detail::conversion_impl<L2::type::size::value>::template apply<
399 // typename L2::type,
400 // homogeneous_system<L1>
401 //> impl;
402 //typedef eval_scale_list<typename L2::scale> scale;
403 //typedef typename multiply_typeof_helper<typename impl::type, typename scale::type>::type type;
11fdf7f2 404 //static BOOST_CONSTEXPR type value()
7c673cae 405 //{
11fdf7f2 406 // return(one() / (impl::value() * scale::value()));
7c673cae
FG
407 //}
408};
409
410/// Requires that all possible conversions
411/// between base units are defined.
412template<class D, class S1, class S2>
413struct conversion_factor_helper<unit<D, heterogeneous_system<S1> >, unit<D, heterogeneous_system<S2> > >
414{
415 /// INTERNAL ONLY
416 typedef typename detail::extract_base_units<S1::type::size::value>::template apply<
417 typename S1::type,
418 dimensionless_type
419 >::type from_base_units;
420 /// INTERNAL ONLY
421 typedef typename detail::extract_base_units<S2::type::size::value>::template apply<
422 typename S2::type,
423 from_base_units
424 >::type all_base_units;
425 /// INTERNAL ONLY
426 typedef typename detail::make_homogeneous_system<all_base_units>::type system;
427 typedef typename detail::conversion_impl<S1::type::size::value>::template apply<
428 typename S1::type,
429 system
430 > conversion1;
431 typedef typename detail::conversion_impl<S2::type::size::value>::template apply<
432 typename S2::type,
433 system
434 > conversion2;
435 typedef eval_scale_list<typename mpl::divides<typename S1::scale, typename S2::scale>::type> scale;
436 typedef typename multiply_typeof_helper<
437 typename conversion1::type,
438 typename divide_typeof_helper<typename scale::type, typename conversion2::type>::type
439 >::type type;
11fdf7f2 440 static BOOST_CONSTEXPR type value()
7c673cae
FG
441 {
442 return(conversion1::value() * (scale::value() / conversion2::value()));
443 }
444};
445
446} // namespace detail
447
448} // namespace units
449
450} // namespace boost
451
452#endif // BOOST_UNITS_CONVERSION_IMPL_HPP