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_HETEROGENEOUS_SYSTEM_HPP Chris@16: #define BOOST_UNITS_HETEROGENEOUS_SYSTEM_HPP Chris@16: Chris@16: /// \file Chris@16: /// \brief A heterogeneous system is a sorted list of base unit/exponent pairs. 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: #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: Chris@16: namespace boost { Chris@16: Chris@16: namespace units { Chris@16: Chris@16: namespace detail { Chris@16: Chris@16: // A normal system is a sorted list of base units. Chris@16: // A heterogeneous system is a sorted list of base unit/exponent pairs. Chris@16: // As long as we don't need to convert heterogeneous systems Chris@16: // directly everything is cool. Chris@16: Chris@16: template Chris@16: struct is_zero : mpl::false_ {}; Chris@16: Chris@16: template<> Chris@16: struct is_zero > : mpl::true_ {}; Chris@16: Chris@16: } // namespace detail Chris@16: Chris@16: /// INTERNAL ONLY Chris@16: template Chris@16: struct heterogeneous_system_impl Chris@16: { Chris@16: typedef L type; Chris@16: typedef Dimensions dimensions; Chris@16: typedef Scale scale; Chris@16: }; Chris@16: Chris@16: /// INTERNAL ONLY Chris@16: typedef dimensionless_type no_scale; Chris@16: Chris@16: /// A system that can represent any possible combination Chris@16: /// of units at the expense of not preserving information Chris@16: /// about how it was created. Do not create specializations Chris@16: /// of this template directly. Instead use @c reduce_unit and Chris@16: /// @c base_unit<...>::unit_type. Chris@16: template Chris@16: struct heterogeneous_system : T {}; Chris@16: Chris@16: /// INTERNAL ONLY Chris@16: struct heterogeneous_system_dim_tag {}; Chris@16: Chris@16: /// INTERNAL ONLY Chris@16: template Chris@16: struct heterogeneous_system_dim Chris@16: { Chris@16: typedef heterogeneous_system_dim_tag tag; Chris@16: typedef heterogeneous_system_dim type; Chris@16: typedef Unit tag_type; Chris@16: typedef Exponent value_type; Chris@16: }; Chris@16: Chris@16: /// INTERNAL ONLY Chris@16: #define BOOST_UNITS_MAKE_HETEROGENEOUS_UNIT(BaseUnit, Dimensions) \ Chris@16: boost::units::unit< \ Chris@16: Dimensions, \ Chris@16: boost::units::heterogeneous_system< \ Chris@16: boost::units::heterogeneous_system_impl< \ Chris@16: boost::units::list< \ Chris@16: boost::units::heterogeneous_system_dim< \ Chris@16: BaseUnit, \ Chris@16: boost::units::static_rational<1> \ Chris@16: >, \ Chris@16: boost::units::dimensionless_type \ Chris@16: >, \ Chris@16: Dimensions, \ Chris@16: boost::units::no_scale \ Chris@16: > \ Chris@16: > \ Chris@16: > Chris@16: Chris@16: } // namespace units Chris@16: Chris@16: } // namespace boost Chris@16: Chris@16: Chris@16: #if BOOST_UNITS_HAS_BOOST_TYPEOF Chris@16: Chris@16: #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP() Chris@16: Chris@16: BOOST_TYPEOF_REGISTER_TEMPLATE(boost::units::heterogeneous_system_impl, (class)(class)(class)) Chris@16: BOOST_TYPEOF_REGISTER_TEMPLATE(boost::units::heterogeneous_system, (class)) Chris@16: BOOST_TYPEOF_REGISTER_TEMPLATE(boost::units::heterogeneous_system_dim, (class)(class)) Chris@16: Chris@16: #endif Chris@16: Chris@16: namespace boost { Chris@16: Chris@16: namespace mpl { Chris@16: Chris@16: /// INTERNAL ONLY Chris@16: template<> Chris@16: struct less_impl Chris@16: { Chris@16: template Chris@16: struct apply : mpl::less {}; Chris@16: }; Chris@16: Chris@16: } Chris@16: Chris@16: namespace units { Chris@16: Chris@16: namespace detail { Chris@16: Chris@16: template Chris@16: struct is_empty_dim > : detail::is_zero {}; Chris@16: Chris@16: } // namespace detail Chris@16: Chris@16: } // namespace units Chris@16: Chris@16: namespace mpl { Chris@16: Chris@16: /// INTERNAL ONLY Chris@16: template<> Chris@16: struct plus_impl Chris@16: { Chris@16: template Chris@16: struct apply Chris@16: { Chris@16: typedef boost::units::heterogeneous_system_dim< Chris@16: typename T0::tag_type, Chris@16: typename mpl::plus::type Chris@16: > type; Chris@16: }; Chris@16: }; Chris@16: Chris@16: /// INTERNAL ONLY Chris@16: template<> Chris@16: struct times_impl Chris@16: { Chris@16: template Chris@16: struct apply Chris@16: { Chris@16: typedef boost::units::heterogeneous_system_dim< Chris@16: typename T0::tag_type, Chris@16: typename mpl::times::type Chris@16: > type; Chris@16: }; Chris@16: }; Chris@16: Chris@16: /// INTERNAL ONLY Chris@16: template<> Chris@16: struct divides_impl Chris@16: { Chris@16: template Chris@16: struct apply Chris@16: { Chris@16: typedef boost::units::heterogeneous_system_dim< Chris@16: typename T0::tag_type, Chris@16: typename mpl::divides::type Chris@16: > type; Chris@16: }; Chris@16: }; Chris@16: Chris@16: /// INTERNAL ONLY Chris@16: template<> Chris@16: struct negate_impl Chris@16: { Chris@16: template Chris@16: struct apply Chris@16: { Chris@16: typedef boost::units::heterogeneous_system_dim::type> type; Chris@16: }; Chris@16: }; Chris@16: Chris@16: } // namespace mpl Chris@16: Chris@16: namespace units { Chris@16: Chris@16: namespace detail { Chris@16: Chris@16: template Chris@16: struct make_heterogeneous_system_impl Chris@16: { Chris@16: template Chris@16: struct apply Chris@16: { Chris@16: typedef typename push_front_if::value)>::template apply< Chris@16: typename make_heterogeneous_system_impl::template apply< Chris@16: typename UnitsBegin::next, Chris@16: typename ExponentsBegin::next Chris@16: >::type, Chris@16: heterogeneous_system_dim Chris@16: >::type type; Chris@16: }; Chris@16: }; Chris@16: Chris@16: template<> Chris@16: struct make_heterogeneous_system_impl<0> Chris@16: { Chris@16: template Chris@16: struct apply Chris@16: { Chris@16: typedef dimensionless_type type; Chris@16: }; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct make_heterogeneous_system Chris@16: { Chris@16: typedef typename calculate_base_unit_exponents::type exponents; Chris@16: BOOST_MPL_ASSERT_MSG((!boost::is_same::value), the_specified_dimension_is_not_representible_in_the_given_system, (types)); Chris@16: typedef typename make_heterogeneous_system_impl::template apply< Chris@16: typename System::type, Chris@16: exponents Chris@16: >::type unit_list; Chris@16: typedef heterogeneous_system > type; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct make_heterogeneous_system > Chris@16: { Chris@16: typedef heterogeneous_system type; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct multiply_systems Chris@16: { Chris@16: typedef heterogeneous_system< Chris@16: heterogeneous_system_impl< Chris@16: typename mpl::times::type, Chris@16: typename mpl::times::type, Chris@16: typename mpl::times::type Chris@16: > Chris@16: > type; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct divide_systems Chris@16: { Chris@16: typedef heterogeneous_system< Chris@16: heterogeneous_system_impl< Chris@16: typename mpl::divides::type, Chris@16: typename mpl::divides::type, Chris@16: typename mpl::divides::type Chris@16: > Chris@16: > type; Chris@16: }; Chris@16: Chris@16: } // namespace detail Chris@16: Chris@16: /// INTERNAL ONLY Chris@16: template Chris@16: struct static_power, static_rational > Chris@16: { Chris@16: typedef heterogeneous_system< Chris@16: heterogeneous_system_impl< Chris@16: typename static_power >::type, Chris@16: typename static_power >::type, Chris@16: typename static_power >::type Chris@16: > Chris@16: > type; Chris@16: }; Chris@16: Chris@16: /// INTERNAL ONLY Chris@16: template Chris@16: struct static_root, static_rational > Chris@16: { Chris@16: typedef heterogeneous_system< Chris@16: heterogeneous_system_impl< Chris@16: typename static_root >::type, Chris@16: typename static_root >::type, Chris@16: typename static_root >::type Chris@16: > Chris@16: > type; Chris@16: }; Chris@16: Chris@16: namespace detail { Chris@16: Chris@16: template Chris@16: struct unscale_heterogeneous_system_impl Chris@16: { Chris@16: template Chris@16: struct apply Chris@16: { Chris@16: typedef typename push_front_or_add< Chris@16: typename unscale_heterogeneous_system_impl::template apply< Chris@16: typename Begin::next Chris@16: >::type, Chris@16: typename unscale::type Chris@16: >::type type; Chris@16: }; Chris@16: }; Chris@16: Chris@16: template<> Chris@16: struct unscale_heterogeneous_system_impl<0> Chris@16: { Chris@16: template Chris@16: struct apply Chris@16: { Chris@16: typedef dimensionless_type type; Chris@16: }; Chris@16: }; Chris@16: Chris@16: } // namespace detail Chris@16: Chris@16: /// Unscale all the base units. e.g Chris@16: /// km s -> m s Chris@16: /// cm km -> m^2 Chris@16: /// INTERNAL ONLY Chris@16: template Chris@16: struct unscale > Chris@16: { Chris@16: typedef heterogeneous_system< Chris@16: heterogeneous_system_impl< Chris@16: typename detail::unscale_heterogeneous_system_impl< Chris@16: T::type::size::value Chris@16: >::template apply< Chris@16: typename T::type Chris@16: >::type, Chris@16: typename T::dimensions, Chris@16: no_scale Chris@16: > Chris@16: > type; Chris@16: }; Chris@16: Chris@16: /// INTERNAL ONLY Chris@16: template Chris@16: struct unscale > Chris@16: { Chris@16: typedef heterogeneous_system_dim::type, Exponent> type; Chris@16: }; Chris@16: Chris@16: namespace detail { Chris@16: Chris@16: template Chris@16: struct get_scale_list_of_heterogeneous_system_impl Chris@16: { Chris@16: template Chris@16: struct apply Chris@16: { Chris@16: typedef typename mpl::times< Chris@16: typename get_scale_list_of_heterogeneous_system_impl::template apply< Chris@16: typename Begin::next Chris@16: >::type, Chris@16: typename get_scale_list::type Chris@16: >::type type; Chris@16: }; Chris@16: }; Chris@16: Chris@16: template<> Chris@16: struct get_scale_list_of_heterogeneous_system_impl<0> Chris@16: { Chris@16: template Chris@16: struct apply Chris@16: { Chris@16: typedef dimensionless_type type; Chris@16: }; Chris@16: }; Chris@16: Chris@16: } // namespace detail Chris@16: Chris@16: /// INTERNAL ONLY Chris@16: template Chris@16: struct get_scale_list > Chris@16: { Chris@16: typedef typename mpl::times< Chris@16: typename detail::get_scale_list_of_heterogeneous_system_impl< Chris@16: T::type::size::value Chris@16: >::template apply::type, Chris@16: typename T::scale Chris@16: >::type type; Chris@16: }; Chris@16: Chris@16: /// INTERNAL ONLY Chris@16: template Chris@16: struct get_scale_list > Chris@16: { Chris@16: typedef typename static_power::type, Exponent>::type type; Chris@16: }; Chris@16: Chris@16: namespace detail { Chris@16: Chris@16: template Chris@16: struct check_system : mpl::false_ {}; Chris@16: Chris@16: template Chris@16: struct check_system >, Dimension> : mpl::true_ {}; Chris@16: Chris@16: } // namespace detail Chris@16: Chris@16: } // namespace units Chris@16: Chris@16: } // namespace boost Chris@16: Chris@16: #endif