123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452 |
- // Boost.Units - A C++ library for zero-overhead dimensional analysis and
- // unit/quantity manipulation and conversion
- //
- // Copyright (C) 2003-2008 Matthias Christian Schabel
- // Copyright (C) 2007-2008 Steven Watanabe
- //
- // Distributed under the Boost Software License, Version 1.0. (See
- // accompanying file LICENSE_1_0.txt or copy at
- // http://www.boost.org/LICENSE_1_0.txt)
- #ifndef BOOST_UNITS_DETAIL_CONVERSION_IMPL_HPP
- #define BOOST_UNITS_DETAIL_CONVERSION_IMPL_HPP
- #include <boost/mpl/bool.hpp>
- #include <boost/mpl/and.hpp>
- #include <boost/mpl/divides.hpp>
- #include <boost/preprocessor/seq/enum.hpp>
- #include <boost/type_traits/is_same.hpp>
- #include <boost/units/heterogeneous_system.hpp>
- #include <boost/units/homogeneous_system.hpp>
- #include <boost/units/reduce_unit.hpp>
- #include <boost/units/static_rational.hpp>
- #include <boost/units/units_fwd.hpp>
- #include <boost/units/detail/dimension_list.hpp>
- #include <boost/units/detail/heterogeneous_conversion.hpp>
- #include <boost/units/detail/one.hpp>
- #include <boost/units/detail/static_rational_power.hpp>
- #include <boost/units/detail/unscale.hpp>
- #include <boost/units/units_fwd.hpp>
- namespace boost {
- namespace units {
- namespace detail {
- template<class Source, class Dest>
- struct conversion_factor_helper;
- template<class Source, class Dest>
- struct call_base_unit_converter;
- }
- /// INTERNAL ONLY
- struct undefined_base_unit_converter_base {
- BOOST_STATIC_CONSTEXPR bool is_defined = false;
- };
- /// INTERNAL ONLY
- struct no_default_conversion {
- BOOST_STATIC_CONSTEXPR bool is_defined = false;
- };
- /// INTERNAL ONLY
- template<class BaseUnit>
- struct unscaled_get_default_conversion : no_default_conversion { };
- /// INTERNAL ONLY
- template<bool is_defined>
- struct unscaled_get_default_conversion_impl;
- /// INTERNAL ONLY
- template<>
- struct unscaled_get_default_conversion_impl<true>
- {
- template<class T>
- struct apply
- {
- typedef typename unscaled_get_default_conversion<typename unscale<T>::type>::type type;
- };
- };
- /// INTERNAL ONLY
- template<>
- struct unscaled_get_default_conversion_impl<false>
- {
- template<class T>
- struct apply
- {
- typedef typename T::unit_type type;
- };
- };
- /// INTERNAL ONLY
- template<class BaseUnit>
- struct get_default_conversion
- {
- typedef typename unscaled_get_default_conversion_impl<
- unscaled_get_default_conversion<typename unscale<BaseUnit>::type>::is_defined
- >::template apply<BaseUnit>::type type;
- };
- /// INTERNAL ONLY
- template<class Source, class Destination>
- struct select_base_unit_converter
- {
- typedef Source source_type;
- typedef Destination destination_type;
- };
- /// INTERNAL ONLY
- template<class Source, class Dest>
- struct base_unit_converter_base : undefined_base_unit_converter_base {
- };
- /// INTERNAL ONLY
- template<class Source>
- struct base_unit_converter_base<Source, BOOST_UNITS_MAKE_HETEROGENEOUS_UNIT(Source, typename Source::dimension_type)>
- {
- BOOST_STATIC_CONSTEXPR bool is_defined = true;
- typedef one type;
- static BOOST_CONSTEXPR type value() {
- return(one());
- }
- };
- /// INTERNAL ONLY
- template<class Source, class Dest>
- struct base_unit_converter : base_unit_converter_base<Source, Dest> { };
- namespace detail {
- template<class Source, class Dest>
- struct do_call_base_unit_converter {
- typedef select_base_unit_converter<typename unscale<Source>::type, typename unscale<Dest>::type> selector;
- typedef typename selector::source_type source_type;
- typedef typename selector::destination_type destination_type;
- typedef base_unit_converter<source_type, destination_type> converter;
- typedef typename mpl::divides<typename get_scale_list<Source>::type, typename get_scale_list<source_type>::type>::type source_factor;
- typedef typename mpl::divides<typename get_scale_list<Dest>::type, typename get_scale_list<destination_type>::type>::type destination_factor;
- typedef typename mpl::divides<source_factor, destination_factor>::type factor;
- typedef eval_scale_list<factor> eval_factor;
- typedef typename multiply_typeof_helper<typename converter::type, typename eval_factor::type>::type type;
- static BOOST_CONSTEXPR type value()
- {
- return(converter::value() * eval_factor::value());
- }
- };
- template<bool forward_is_defined, bool reverse_is_defined>
- struct call_base_unit_converter_base_unit_impl;
- template<>
- struct call_base_unit_converter_base_unit_impl<true, true>
- {
- template<class Source, class Dest>
- struct apply
- : do_call_base_unit_converter<Source, typename Dest::unit_type>
- {
- };
- };
- template<>
- struct call_base_unit_converter_base_unit_impl<true, false>
- {
- template<class Source, class Dest>
- struct apply
- : do_call_base_unit_converter<Source, typename Dest::unit_type>
- {
- };
- };
- template<>
- struct call_base_unit_converter_base_unit_impl<false, true>
- {
- template<class Source, class Dest>
- struct apply
- {
- typedef do_call_base_unit_converter<Dest, typename Source::unit_type> converter;
- typedef typename divide_typeof_helper<one, typename converter::type>::type type;
- static BOOST_CONSTEXPR type value() {
- return(one() / converter::value());
- }
- };
- };
- template<>
- struct call_base_unit_converter_base_unit_impl<false, false>
- {
- template<class Source, class Dest>
- struct apply
- {
- typedef typename reduce_unit<typename get_default_conversion<Source>::type>::type new_source;
- typedef typename reduce_unit<typename get_default_conversion<Dest>::type>::type new_dest;
- typedef call_base_unit_converter<Source, new_source> start;
- typedef detail::conversion_factor_helper<
- new_source,
- new_dest
- > conversion;
- typedef call_base_unit_converter<Dest, new_dest> end;
- typedef typename divide_typeof_helper<
- typename multiply_typeof_helper<
- typename start::type,
- typename conversion::type
- >::type,
- typename end::type
- >::type type;
- static BOOST_CONSTEXPR type value() {
- return(start::value() * conversion::value() / end::value());
- }
- };
- };
- template<int N>
- struct get_default_conversion_impl
- {
- template<class Begin>
- struct apply
- {
- typedef typename Begin::item source_pair;
- typedef typename source_pair::value_type exponent;
- typedef typename source_pair::tag_type source;
- typedef typename reduce_unit<typename get_default_conversion<source>::type>::type new_source;
- typedef typename get_default_conversion_impl<N-1>::template apply<typename Begin::next> next_iteration;
- typedef typename multiply_typeof_helper<typename power_typeof_helper<new_source, exponent>::type, typename next_iteration::unit_type>::type unit_type;
- typedef call_base_unit_converter<source, new_source> conversion;
- typedef typename multiply_typeof_helper<typename conversion::type, typename next_iteration::type>::type type;
- static BOOST_CONSTEXPR type value() {
- return(static_rational_power<exponent>(conversion::value()) * next_iteration::value());
- }
- };
- };
- template<>
- struct get_default_conversion_impl<0>
- {
- template<class Begin>
- struct apply
- {
- typedef unit<dimensionless_type, heterogeneous_system<heterogeneous_system_impl<dimensionless_type, dimensionless_type, no_scale> > > unit_type;
- typedef one type;
- static BOOST_CONSTEXPR one value() {
- return(one());
- }
- };
- };
- template<bool is_defined>
- struct call_base_unit_converter_impl;
- template<>
- struct call_base_unit_converter_impl<true>
- {
- template<class Source, class Dest>
- struct apply
- : do_call_base_unit_converter<Source, Dest>
- {
- };
- };
- template<>
- struct call_base_unit_converter_impl<false>
- {
- template<class Source, class Dest>
- struct apply {
- typedef typename reduce_unit<typename get_default_conversion<Source>::type>::type new_source;
- typedef typename Dest::system_type::type system_list;
- typedef typename get_default_conversion_impl<system_list::size::value>::template apply<system_list> impl;
- typedef typename impl::unit_type new_dest;
- typedef call_base_unit_converter<Source, new_source> start;
- typedef conversion_factor_helper<new_source, new_dest> conversion;
- typedef typename divide_typeof_helper<
- typename multiply_typeof_helper<
- typename start::type,
- typename conversion::type
- >::type,
- typename impl::type
- >::type type;
- static BOOST_CONSTEXPR type value() {
- return(start::value() * conversion::value() / impl::value());
- }
- };
- };
- #define BOOST_UNITS_DETAIL_BASE_UNIT_CONVERTER_IS_DEFINED(Source, Dest)\
- base_unit_converter<\
- typename select_base_unit_converter<typename unscale<Source>::type, typename unscale<Dest>::type>::source_type,\
- typename select_base_unit_converter<typename unscale<Source>::type, typename unscale<Dest>::type>::destination_type\
- >::is_defined
- template<class Source, class Dest>
- struct call_base_unit_converter : call_base_unit_converter_impl<BOOST_UNITS_DETAIL_BASE_UNIT_CONVERTER_IS_DEFINED(Source, Dest)>::template apply<Source, Dest>
- {
- };
- template<class Source, class Dest>
- struct call_base_unit_converter<Source, BOOST_UNITS_MAKE_HETEROGENEOUS_UNIT(Dest, typename Source::dimension_type)> :
- call_base_unit_converter_base_unit_impl<
- BOOST_UNITS_DETAIL_BASE_UNIT_CONVERTER_IS_DEFINED(Source, typename Dest::unit_type),
- BOOST_UNITS_DETAIL_BASE_UNIT_CONVERTER_IS_DEFINED(Dest, typename Source::unit_type)
- >::template apply<Source, Dest>
- {
- };
- template<int N>
- struct conversion_impl
- {
- template<class Begin, class DestinationSystem>
- struct apply
- {
- typedef typename conversion_impl<N-1>::template apply<
- typename Begin::next,
- DestinationSystem
- > next_iteration;
- typedef typename Begin::item unit_pair;
- typedef typename unit_pair::tag_type unit;
- typedef typename unit::dimension_type dimensions;
- typedef typename reduce_unit<units::unit<dimensions, DestinationSystem> >::type reduced_unit;
- typedef detail::call_base_unit_converter<unit, reduced_unit> converter;
- typedef typename multiply_typeof_helper<typename converter::type, typename next_iteration::type>::type type;
- static BOOST_CONSTEXPR type value() { return(static_rational_power<typename unit_pair::value_type>(converter::value()) * next_iteration::value()); }
- };
- };
- template<>
- struct conversion_impl<0>
- {
- template<class Begin, class DestinationSystem>
- struct apply
- {
- typedef one type;
- static BOOST_CONSTEXPR type value() { return(one()); }
- };
- };
- } // namespace detail
- /// forward to conversion_factor (intentionally allowing ADL)
- /// INTERNAL ONLY
- template<class Unit1, class T1, class Unit2, class T2>
- struct conversion_helper<quantity<Unit1, T1>, quantity<Unit2, T2> >
- {
- /// INTERNAL ONLY
- typedef quantity<Unit2, T2> destination_type;
- static BOOST_CONSTEXPR destination_type convert(const quantity<Unit1, T1>& source)
- {
- return(destination_type::from_value(static_cast<T2>(source.value() * conversion_factor(Unit1(), Unit2()))));
- }
- };
- namespace detail {
- template<class Source, class Dest>
- struct conversion_factor_helper;
- template<class D, class L1, class L2>
- struct conversion_factor_helper<unit<D, homogeneous_system<L1> >, unit<D, homogeneous_system<L2> > >
- : conversion_factor_helper<
- typename reduce_unit<unit<D, homogeneous_system<L1> > >::type,
- typename reduce_unit<unit<D, homogeneous_system<L2> > >::type
- >
- {
- //typedef typename reduce_unit<unit<D, homogeneous_system<L1> > >::type source_unit;
- //typedef typename source_unit::system_type::type unit_list;
- //typedef typename detail::conversion_impl<unit_list::size::value>::template apply<
- // unit_list,
- // homogeneous_system<L2>
- //> impl;
- //typedef typename impl::type type;
- //static BOOST_CONSTEXPR type value()
- //{
- // return(impl::value());
- //}
- };
- template<class D, class L1, class L2>
- struct conversion_factor_helper<unit<D, heterogeneous_system<L1> >, unit<D, homogeneous_system<L2> > >
- : conversion_factor_helper<
- typename reduce_unit<unit<D, heterogeneous_system<L1> > >::type,
- typename reduce_unit<unit<D, homogeneous_system<L2> > >::type
- >
- {
- //typedef typename detail::conversion_impl<L1::type::size::value>::template apply<
- // typename L1::type,
- // homogeneous_system<L2>
- //> impl;
- //typedef eval_scale_list<typename L1::scale> scale;
- //typedef typename multiply_typeof_helper<typename impl::type, typename scale::type>::type type;
- //static BOOST_CONSTEXPR type value()
- //{
- // return(impl::value() * scale::value());
- //}
- };
- // There is no simple algorithm for doing this conversion
- // other than just defining it as the reverse of the
- // heterogeneous->homogeneous case
- template<class D, class L1, class L2>
- struct conversion_factor_helper<unit<D, homogeneous_system<L1> >, unit<D, heterogeneous_system<L2> > >
- : conversion_factor_helper<
- typename reduce_unit<unit<D, homogeneous_system<L1> > >::type,
- typename reduce_unit<unit<D, heterogeneous_system<L2> > >::type
- >
- {
- //typedef typename detail::conversion_impl<L2::type::size::value>::template apply<
- // typename L2::type,
- // homogeneous_system<L1>
- //> impl;
- //typedef eval_scale_list<typename L2::scale> scale;
- //typedef typename multiply_typeof_helper<typename impl::type, typename scale::type>::type type;
- //static BOOST_CONSTEXPR type value()
- //{
- // return(one() / (impl::value() * scale::value()));
- //}
- };
- /// Requires that all possible conversions
- /// between base units are defined.
- template<class D, class S1, class S2>
- struct conversion_factor_helper<unit<D, heterogeneous_system<S1> >, unit<D, heterogeneous_system<S2> > >
- {
- /// INTERNAL ONLY
- typedef typename detail::extract_base_units<S1::type::size::value>::template apply<
- typename S1::type,
- dimensionless_type
- >::type from_base_units;
- /// INTERNAL ONLY
- typedef typename detail::extract_base_units<S2::type::size::value>::template apply<
- typename S2::type,
- from_base_units
- >::type all_base_units;
- /// INTERNAL ONLY
- typedef typename detail::make_homogeneous_system<all_base_units>::type system;
- typedef typename detail::conversion_impl<S1::type::size::value>::template apply<
- typename S1::type,
- system
- > conversion1;
- typedef typename detail::conversion_impl<S2::type::size::value>::template apply<
- typename S2::type,
- system
- > conversion2;
- typedef eval_scale_list<typename mpl::divides<typename S1::scale, typename S2::scale>::type> scale;
- typedef typename multiply_typeof_helper<
- typename conversion1::type,
- typename divide_typeof_helper<typename scale::type, typename conversion2::type>::type
- >::type type;
- static BOOST_CONSTEXPR type value()
- {
- return(conversion1::value() * (scale::value() / conversion2::value()));
- }
- };
- } // namespace detail
- } // namespace units
- } // namespace boost
- #endif // BOOST_UNITS_CONVERSION_IMPL_HPP
|