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