Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:53:13

0001 // Boost.Units - A C++ library for zero-overhead dimensional analysis and 
0002 // unit/quantity manipulation and conversion
0003 //
0004 // Copyright (C) 2003-2008 Matthias Christian Schabel
0005 // Copyright (C) 2007-2008 Steven Watanabe
0006 //
0007 // Distributed under the Boost Software License, Version 1.0. (See
0008 // accompanying file LICENSE_1_0.txt or copy at
0009 // http://www.boost.org/LICENSE_1_0.txt)
0010 
0011 #ifndef BOOST_UNITS_DETAIL_CONVERSION_IMPL_HPP
0012 #define BOOST_UNITS_DETAIL_CONVERSION_IMPL_HPP
0013 
0014 #include <boost/mpl/bool.hpp>
0015 #include <boost/mpl/and.hpp>
0016 #include <boost/mpl/divides.hpp>
0017 #include <boost/preprocessor/seq/enum.hpp>
0018 #include <boost/type_traits/is_same.hpp>
0019 
0020 #include <boost/units/heterogeneous_system.hpp>
0021 #include <boost/units/homogeneous_system.hpp>
0022 #include <boost/units/reduce_unit.hpp>
0023 #include <boost/units/static_rational.hpp>
0024 #include <boost/units/units_fwd.hpp>
0025 #include <boost/units/detail/dimension_list.hpp>
0026 #include <boost/units/detail/heterogeneous_conversion.hpp>
0027 #include <boost/units/detail/one.hpp>
0028 #include <boost/units/detail/static_rational_power.hpp>
0029 #include <boost/units/detail/unscale.hpp>
0030 
0031 #include <boost/units/units_fwd.hpp>
0032 
0033 namespace boost {
0034 
0035 namespace units {
0036 
0037 namespace detail {
0038 
0039 template<class Source, class Dest>
0040 struct conversion_factor_helper;
0041 
0042 template<class Source, class Dest>
0043 struct call_base_unit_converter;
0044 
0045 }
0046 
0047 /// INTERNAL ONLY
0048 struct undefined_base_unit_converter_base {
0049     BOOST_STATIC_CONSTEXPR bool is_defined = false;
0050 };
0051 
0052 /// INTERNAL ONLY
0053 struct no_default_conversion {
0054     BOOST_STATIC_CONSTEXPR bool is_defined = false;
0055 };
0056 
0057 /// INTERNAL ONLY
0058 template<class BaseUnit>
0059 struct unscaled_get_default_conversion : no_default_conversion { };
0060 
0061 /// INTERNAL ONLY
0062 template<bool is_defined>
0063 struct unscaled_get_default_conversion_impl;
0064 
0065 /// INTERNAL ONLY
0066 template<>
0067 struct unscaled_get_default_conversion_impl<true>
0068 {
0069     template<class T>
0070     struct apply
0071     {
0072         typedef typename unscaled_get_default_conversion<typename unscale<T>::type>::type type;
0073     };
0074 };
0075 
0076 /// INTERNAL ONLY
0077 template<>
0078 struct unscaled_get_default_conversion_impl<false>
0079 {
0080     template<class T>
0081     struct apply
0082     {
0083         typedef typename T::unit_type type;
0084     };
0085 };
0086 
0087 /// INTERNAL ONLY
0088 template<class BaseUnit>
0089 struct get_default_conversion
0090 {
0091     typedef typename unscaled_get_default_conversion_impl<
0092         unscaled_get_default_conversion<typename unscale<BaseUnit>::type>::is_defined
0093     >::template apply<BaseUnit>::type type;
0094 };
0095 
0096 /// INTERNAL ONLY
0097 template<class Source, class Destination>
0098 struct select_base_unit_converter
0099 {
0100     typedef Source source_type;
0101     typedef Destination destination_type;
0102 };
0103 
0104 /// INTERNAL ONLY
0105 template<class Source, class Dest>
0106 struct base_unit_converter_base : undefined_base_unit_converter_base {
0107 };
0108 
0109 /// INTERNAL ONLY
0110 template<class Source>
0111 struct base_unit_converter_base<Source, BOOST_UNITS_MAKE_HETEROGENEOUS_UNIT(Source, typename Source::dimension_type)>
0112 {
0113     BOOST_STATIC_CONSTEXPR bool is_defined = true;
0114     typedef one type;
0115     static BOOST_CONSTEXPR type value() {
0116         return(one());
0117     }
0118 };
0119 
0120 /// INTERNAL ONLY
0121 template<class Source, class Dest>
0122 struct base_unit_converter : base_unit_converter_base<Source, Dest> { };
0123 
0124 namespace detail {
0125 
0126 template<class Source, class Dest>
0127 struct do_call_base_unit_converter {
0128     typedef select_base_unit_converter<typename unscale<Source>::type, typename unscale<Dest>::type> selector;
0129     typedef typename selector::source_type source_type;
0130     typedef typename selector::destination_type destination_type;
0131     typedef base_unit_converter<source_type, destination_type> converter;
0132     typedef typename mpl::divides<typename get_scale_list<Source>::type, typename get_scale_list<source_type>::type>::type source_factor;
0133     typedef typename mpl::divides<typename get_scale_list<Dest>::type, typename get_scale_list<destination_type>::type>::type destination_factor;
0134     typedef typename mpl::divides<source_factor, destination_factor>::type factor;
0135     typedef eval_scale_list<factor> eval_factor;
0136     typedef typename multiply_typeof_helper<typename converter::type, typename eval_factor::type>::type type;
0137     static BOOST_CONSTEXPR type value()
0138     {
0139         return(converter::value() * eval_factor::value());
0140     }
0141 };
0142 
0143 template<bool forward_is_defined, bool reverse_is_defined>
0144 struct call_base_unit_converter_base_unit_impl;
0145 
0146 template<>
0147 struct call_base_unit_converter_base_unit_impl<true, true>
0148 {
0149     template<class Source, class Dest>
0150     struct apply
0151         : do_call_base_unit_converter<Source, typename Dest::unit_type> 
0152     {
0153     };
0154 };
0155 
0156 template<>
0157 struct call_base_unit_converter_base_unit_impl<true, false>
0158 {
0159     template<class Source, class Dest>
0160     struct apply
0161         : do_call_base_unit_converter<Source, typename Dest::unit_type> 
0162     {
0163     };
0164 };
0165 
0166 template<>
0167 struct call_base_unit_converter_base_unit_impl<false, true>
0168 {
0169     template<class Source, class Dest>
0170     struct apply
0171     {
0172         typedef do_call_base_unit_converter<Dest, typename Source::unit_type> converter;
0173         typedef typename divide_typeof_helper<one, typename converter::type>::type type;
0174         static BOOST_CONSTEXPR type value() {
0175             return(one() / converter::value());
0176         }
0177     };
0178 };
0179 
0180 template<>
0181 struct call_base_unit_converter_base_unit_impl<false, false>
0182 {
0183     template<class Source, class Dest>
0184     struct apply
0185     {
0186         typedef typename reduce_unit<typename get_default_conversion<Source>::type>::type new_source;
0187         typedef typename reduce_unit<typename get_default_conversion<Dest>::type>::type new_dest;
0188         typedef call_base_unit_converter<Source, new_source> start;
0189         typedef detail::conversion_factor_helper<
0190             new_source,
0191             new_dest
0192         > conversion;
0193         typedef call_base_unit_converter<Dest, new_dest> end;
0194         typedef typename divide_typeof_helper<
0195             typename multiply_typeof_helper<
0196                 typename start::type,
0197                 typename conversion::type
0198             >::type,
0199             typename end::type
0200         >::type type;
0201         static BOOST_CONSTEXPR type value() {
0202             return(start::value() * conversion::value() / end::value());
0203         }
0204     };
0205 };
0206 
0207 template<int N>
0208 struct get_default_conversion_impl
0209 {
0210     template<class Begin>
0211     struct apply
0212     {
0213         typedef typename Begin::item source_pair;
0214         typedef typename source_pair::value_type exponent;
0215         typedef typename source_pair::tag_type source;
0216         typedef typename reduce_unit<typename get_default_conversion<source>::type>::type new_source;
0217         typedef typename get_default_conversion_impl<N-1>::template apply<typename Begin::next> next_iteration;
0218         typedef typename multiply_typeof_helper<typename power_typeof_helper<new_source, exponent>::type, typename next_iteration::unit_type>::type unit_type;
0219         typedef call_base_unit_converter<source, new_source> conversion;
0220         typedef typename multiply_typeof_helper<typename conversion::type, typename next_iteration::type>::type type;
0221         static BOOST_CONSTEXPR type value() {
0222             return(static_rational_power<exponent>(conversion::value()) * next_iteration::value());
0223         }
0224     };
0225 };
0226 
0227 template<>
0228 struct get_default_conversion_impl<0>
0229 {
0230     template<class Begin>
0231     struct apply
0232     {
0233         typedef unit<dimensionless_type, heterogeneous_system<heterogeneous_system_impl<dimensionless_type, dimensionless_type, no_scale> > > unit_type;
0234         typedef one type;
0235         static BOOST_CONSTEXPR one value() {
0236             return(one());
0237         }
0238     };
0239 };
0240 
0241 template<bool is_defined>
0242 struct call_base_unit_converter_impl;
0243 
0244 template<>
0245 struct call_base_unit_converter_impl<true>
0246 {
0247     template<class Source, class Dest>
0248     struct apply
0249         : do_call_base_unit_converter<Source, Dest> 
0250     {
0251     };
0252 };
0253 
0254 template<>
0255 struct call_base_unit_converter_impl<false>
0256 {
0257     template<class Source, class Dest>
0258     struct apply {
0259         typedef typename reduce_unit<typename get_default_conversion<Source>::type>::type new_source;
0260         typedef typename Dest::system_type::type system_list;
0261         typedef typename get_default_conversion_impl<system_list::size::value>::template apply<system_list> impl;
0262         typedef typename impl::unit_type new_dest;
0263         typedef call_base_unit_converter<Source, new_source> start;
0264         typedef conversion_factor_helper<new_source, new_dest> conversion;
0265         typedef typename divide_typeof_helper<
0266             typename multiply_typeof_helper<
0267                 typename start::type,
0268                 typename conversion::type
0269             >::type,
0270             typename impl::type
0271         >::type type;
0272         static BOOST_CONSTEXPR type value() {
0273             return(start::value() * conversion::value() / impl::value());
0274         }
0275     };
0276 };
0277 
0278 #define BOOST_UNITS_DETAIL_BASE_UNIT_CONVERTER_IS_DEFINED(Source, Dest)\
0279     base_unit_converter<\
0280         typename select_base_unit_converter<typename unscale<Source>::type, typename unscale<Dest>::type>::source_type,\
0281         typename select_base_unit_converter<typename unscale<Source>::type, typename unscale<Dest>::type>::destination_type\
0282     >::is_defined
0283 
0284 template<class Source, class Dest>
0285 struct call_base_unit_converter : call_base_unit_converter_impl<BOOST_UNITS_DETAIL_BASE_UNIT_CONVERTER_IS_DEFINED(Source, Dest)>::template apply<Source, Dest>
0286 {
0287 };
0288 
0289 template<class Source, class Dest>
0290 struct call_base_unit_converter<Source, BOOST_UNITS_MAKE_HETEROGENEOUS_UNIT(Dest, typename Source::dimension_type)> :
0291     call_base_unit_converter_base_unit_impl<
0292         BOOST_UNITS_DETAIL_BASE_UNIT_CONVERTER_IS_DEFINED(Source, typename Dest::unit_type),
0293         BOOST_UNITS_DETAIL_BASE_UNIT_CONVERTER_IS_DEFINED(Dest, typename Source::unit_type)
0294     >::template apply<Source, Dest>
0295 {
0296 };
0297 
0298 template<int N>
0299 struct conversion_impl
0300 {
0301     template<class Begin, class DestinationSystem>
0302     struct apply
0303     {
0304         typedef typename conversion_impl<N-1>::template apply<
0305             typename Begin::next,
0306             DestinationSystem
0307         > next_iteration;
0308         typedef typename Begin::item unit_pair;
0309         typedef typename unit_pair::tag_type unit;
0310         typedef typename unit::dimension_type dimensions;
0311         typedef typename reduce_unit<units::unit<dimensions, DestinationSystem> >::type reduced_unit;
0312         typedef detail::call_base_unit_converter<unit, reduced_unit> converter;
0313         typedef typename multiply_typeof_helper<typename converter::type, typename next_iteration::type>::type type;
0314         static BOOST_CONSTEXPR type value() { return(static_rational_power<typename unit_pair::value_type>(converter::value()) * next_iteration::value()); }
0315     };
0316 };
0317 
0318 template<>
0319 struct conversion_impl<0>
0320 {
0321     template<class Begin, class DestinationSystem>
0322     struct apply
0323     {
0324         typedef one type;
0325         static BOOST_CONSTEXPR type value() { return(one()); }
0326     };
0327 };
0328 
0329 } // namespace detail
0330 
0331 /// forward to conversion_factor (intentionally allowing ADL)
0332 /// INTERNAL ONLY
0333 template<class Unit1, class T1, class Unit2, class T2>
0334 struct conversion_helper<quantity<Unit1, T1>, quantity<Unit2, T2> >
0335 {
0336     /// INTERNAL ONLY
0337     typedef quantity<Unit2, T2> destination_type;
0338     static BOOST_CONSTEXPR destination_type convert(const quantity<Unit1, T1>& source)
0339     {
0340         return(destination_type::from_value(static_cast<T2>(source.value() * conversion_factor(Unit1(), Unit2()))));
0341     }
0342 };
0343 
0344 namespace detail {
0345 
0346 template<class Source, class Dest>
0347 struct conversion_factor_helper;
0348 
0349 template<class D, class L1, class L2>
0350 struct conversion_factor_helper<unit<D, homogeneous_system<L1> >, unit<D, homogeneous_system<L2> > >
0351   : conversion_factor_helper<
0352         typename reduce_unit<unit<D, homogeneous_system<L1> > >::type,
0353         typename reduce_unit<unit<D, homogeneous_system<L2> > >::type
0354     >
0355 {
0356     //typedef typename reduce_unit<unit<D, homogeneous_system<L1> > >::type source_unit;
0357     //typedef typename source_unit::system_type::type unit_list;
0358     //typedef typename detail::conversion_impl<unit_list::size::value>::template apply<
0359     //    unit_list,
0360     //    homogeneous_system<L2>
0361     //> impl;
0362     //typedef typename impl::type type;
0363     //static BOOST_CONSTEXPR type value()
0364     //{
0365     //    return(impl::value());
0366     //}
0367 };
0368 
0369 template<class D, class L1, class L2>
0370 struct conversion_factor_helper<unit<D, heterogeneous_system<L1> >, unit<D, homogeneous_system<L2> > >
0371   : conversion_factor_helper<
0372         typename reduce_unit<unit<D, heterogeneous_system<L1> > >::type,
0373         typename reduce_unit<unit<D, homogeneous_system<L2> > >::type
0374     >
0375 {
0376     //typedef typename detail::conversion_impl<L1::type::size::value>::template apply<
0377     //    typename L1::type,
0378     //    homogeneous_system<L2>
0379     //> impl;
0380     //typedef eval_scale_list<typename L1::scale> scale;
0381     //typedef typename multiply_typeof_helper<typename impl::type, typename scale::type>::type type;
0382     //static BOOST_CONSTEXPR type value()
0383     //{
0384     //    return(impl::value() * scale::value());
0385     //}
0386 };
0387 
0388 // There is no simple algorithm for doing this conversion
0389 // other than just defining it as the reverse of the
0390 // heterogeneous->homogeneous case
0391 template<class D, class L1, class L2>
0392 struct conversion_factor_helper<unit<D, homogeneous_system<L1> >, unit<D, heterogeneous_system<L2> > >
0393   : conversion_factor_helper<
0394         typename reduce_unit<unit<D, homogeneous_system<L1> > >::type,
0395         typename reduce_unit<unit<D, heterogeneous_system<L2> > >::type
0396     >
0397 {
0398     //typedef typename detail::conversion_impl<L2::type::size::value>::template apply<
0399     //    typename L2::type,
0400     //    homogeneous_system<L1>
0401     //> impl;
0402     //typedef eval_scale_list<typename L2::scale> scale;
0403     //typedef typename multiply_typeof_helper<typename impl::type, typename scale::type>::type type;
0404     //static BOOST_CONSTEXPR type value()
0405     //{
0406     //    return(one() / (impl::value() * scale::value()));
0407     //}
0408 };
0409 
0410 /// Requires that all possible conversions
0411 /// between base units are defined.
0412 template<class D, class S1, class S2>
0413 struct conversion_factor_helper<unit<D, heterogeneous_system<S1> >, unit<D, heterogeneous_system<S2> > >
0414 {
0415     /// INTERNAL ONLY
0416     typedef typename detail::extract_base_units<S1::type::size::value>::template apply<
0417         typename S1::type,
0418         dimensionless_type
0419     >::type from_base_units;
0420     /// INTERNAL ONLY
0421     typedef typename detail::extract_base_units<S2::type::size::value>::template apply<
0422         typename S2::type,
0423         from_base_units
0424     >::type all_base_units;
0425     /// INTERNAL ONLY
0426     typedef typename detail::make_homogeneous_system<all_base_units>::type system;
0427     typedef typename detail::conversion_impl<S1::type::size::value>::template apply<
0428         typename S1::type,
0429         system
0430     > conversion1;
0431     typedef typename detail::conversion_impl<S2::type::size::value>::template apply<
0432         typename S2::type,
0433         system
0434     > conversion2;
0435     typedef eval_scale_list<typename mpl::divides<typename S1::scale, typename S2::scale>::type> scale;
0436     typedef typename multiply_typeof_helper<
0437         typename conversion1::type,
0438         typename divide_typeof_helper<typename scale::type, typename conversion2::type>::type
0439     >::type type;
0440     static BOOST_CONSTEXPR type value()
0441     {
0442         return(conversion1::value() * (scale::value() / conversion2::value()));
0443     }
0444 };
0445 
0446 } // namespace detail
0447 
0448 } // namespace units
0449 
0450 } // namespace boost
0451 
0452 #endif // BOOST_UNITS_CONVERSION_IMPL_HPP