annotate DEPENDENCIES/generic/include/boost/units/detail/conversion_impl.hpp @ 125:34e428693f5d vext

Vext -> Repoint
author Chris Cannam
date Thu, 14 Jun 2018 11:15:39 +0100
parents 2665513ce2d3
children
rev   line source
Chris@16 1 // Boost.Units - A C++ library for zero-overhead dimensional analysis and
Chris@16 2 // unit/quantity manipulation and conversion
Chris@16 3 //
Chris@16 4 // Copyright (C) 2003-2008 Matthias Christian Schabel
Chris@16 5 // Copyright (C) 2007-2008 Steven Watanabe
Chris@16 6 //
Chris@16 7 // Distributed under the Boost Software License, Version 1.0. (See
Chris@16 8 // accompanying file LICENSE_1_0.txt or copy at
Chris@16 9 // http://www.boost.org/LICENSE_1_0.txt)
Chris@16 10
Chris@16 11 #ifndef BOOST_UNITS_DETAIL_CONVERSION_IMPL_HPP
Chris@16 12 #define BOOST_UNITS_DETAIL_CONVERSION_IMPL_HPP
Chris@16 13
Chris@16 14 #include <boost/mpl/bool.hpp>
Chris@16 15 #include <boost/mpl/and.hpp>
Chris@16 16 #include <boost/mpl/divides.hpp>
Chris@16 17 #include <boost/preprocessor/seq/enum.hpp>
Chris@16 18 #include <boost/type_traits/is_same.hpp>
Chris@16 19
Chris@16 20 #include <boost/units/heterogeneous_system.hpp>
Chris@16 21 #include <boost/units/homogeneous_system.hpp>
Chris@16 22 #include <boost/units/reduce_unit.hpp>
Chris@16 23 #include <boost/units/static_rational.hpp>
Chris@16 24 #include <boost/units/units_fwd.hpp>
Chris@16 25 #include <boost/units/detail/dimension_list.hpp>
Chris@16 26 #include <boost/units/detail/heterogeneous_conversion.hpp>
Chris@16 27 #include <boost/units/detail/one.hpp>
Chris@16 28 #include <boost/units/detail/static_rational_power.hpp>
Chris@16 29 #include <boost/units/detail/unscale.hpp>
Chris@16 30
Chris@16 31 #include <boost/units/units_fwd.hpp>
Chris@16 32
Chris@16 33 namespace boost {
Chris@16 34
Chris@16 35 namespace units {
Chris@16 36
Chris@16 37 namespace detail {
Chris@16 38
Chris@16 39 template<class Source, class Dest>
Chris@16 40 struct conversion_factor_helper;
Chris@16 41
Chris@16 42 template<class Source, class Dest>
Chris@16 43 struct call_base_unit_converter;
Chris@16 44
Chris@16 45 }
Chris@16 46
Chris@16 47 /// INTERNAL ONLY
Chris@16 48 struct undefined_base_unit_converter_base {
Chris@16 49 static const bool is_defined = false;
Chris@16 50 };
Chris@16 51
Chris@16 52 /// INTERNAL ONLY
Chris@16 53 struct no_default_conversion {
Chris@16 54 static const bool is_defined = false;
Chris@16 55 };
Chris@16 56
Chris@16 57 /// INTERNAL ONLY
Chris@16 58 template<class BaseUnit>
Chris@16 59 struct unscaled_get_default_conversion : no_default_conversion { };
Chris@16 60
Chris@16 61 /// INTERNAL ONLY
Chris@16 62 template<bool is_defined>
Chris@16 63 struct unscaled_get_default_conversion_impl;
Chris@16 64
Chris@16 65 /// INTERNAL ONLY
Chris@16 66 template<>
Chris@16 67 struct unscaled_get_default_conversion_impl<true>
Chris@16 68 {
Chris@16 69 template<class T>
Chris@16 70 struct apply
Chris@16 71 {
Chris@16 72 typedef typename unscaled_get_default_conversion<typename unscale<T>::type>::type type;
Chris@16 73 };
Chris@16 74 };
Chris@16 75
Chris@16 76 /// INTERNAL ONLY
Chris@16 77 template<>
Chris@16 78 struct unscaled_get_default_conversion_impl<false>
Chris@16 79 {
Chris@16 80 template<class T>
Chris@16 81 struct apply
Chris@16 82 {
Chris@16 83 typedef typename T::unit_type type;
Chris@16 84 };
Chris@16 85 };
Chris@16 86
Chris@16 87 /// INTERNAL ONLY
Chris@16 88 template<class BaseUnit>
Chris@16 89 struct get_default_conversion
Chris@16 90 {
Chris@16 91 typedef typename unscaled_get_default_conversion_impl<
Chris@16 92 unscaled_get_default_conversion<typename unscale<BaseUnit>::type>::is_defined
Chris@16 93 >::template apply<BaseUnit>::type type;
Chris@16 94 };
Chris@16 95
Chris@16 96 /// INTERNAL ONLY
Chris@16 97 template<class Source, class Destination>
Chris@16 98 struct select_base_unit_converter
Chris@16 99 {
Chris@16 100 typedef Source source_type;
Chris@16 101 typedef Destination destination_type;
Chris@16 102 };
Chris@16 103
Chris@16 104 /// INTERNAL ONLY
Chris@16 105 template<class Source, class Dest>
Chris@16 106 struct base_unit_converter_base : undefined_base_unit_converter_base {
Chris@16 107 };
Chris@16 108
Chris@16 109 /// INTERNAL ONLY
Chris@16 110 template<class Source>
Chris@16 111 struct base_unit_converter_base<Source, BOOST_UNITS_MAKE_HETEROGENEOUS_UNIT(Source, typename Source::dimension_type)>
Chris@16 112 {
Chris@16 113 static const bool is_defined = true;
Chris@16 114 typedef one type;
Chris@16 115 static type value() {
Chris@16 116 one result;
Chris@16 117 return(result);
Chris@16 118 }
Chris@16 119 };
Chris@16 120
Chris@16 121 /// INTERNAL ONLY
Chris@16 122 template<class Source, class Dest>
Chris@16 123 struct base_unit_converter : base_unit_converter_base<Source, Dest> { };
Chris@16 124
Chris@16 125 namespace detail {
Chris@16 126
Chris@16 127 template<class Source, class Dest>
Chris@16 128 struct do_call_base_unit_converter {
Chris@16 129 typedef select_base_unit_converter<typename unscale<Source>::type, typename unscale<Dest>::type> selector;
Chris@16 130 typedef typename selector::source_type source_type;
Chris@16 131 typedef typename selector::destination_type destination_type;
Chris@16 132 typedef base_unit_converter<source_type, destination_type> converter;
Chris@16 133 typedef typename mpl::divides<typename get_scale_list<Source>::type, typename get_scale_list<source_type>::type>::type source_factor;
Chris@16 134 typedef typename mpl::divides<typename get_scale_list<Dest>::type, typename get_scale_list<destination_type>::type>::type destination_factor;
Chris@16 135 typedef typename mpl::divides<source_factor, destination_factor>::type factor;
Chris@16 136 typedef eval_scale_list<factor> eval_factor;
Chris@16 137 typedef typename multiply_typeof_helper<typename converter::type, typename eval_factor::type>::type type;
Chris@16 138 static type value()
Chris@16 139 {
Chris@16 140 return(converter::value() * eval_factor::value());
Chris@16 141 }
Chris@16 142 };
Chris@16 143
Chris@16 144 template<bool forward_is_defined, bool reverse_is_defined>
Chris@16 145 struct call_base_unit_converter_base_unit_impl;
Chris@16 146
Chris@16 147 template<>
Chris@16 148 struct call_base_unit_converter_base_unit_impl<true, true>
Chris@16 149 {
Chris@16 150 template<class Source, class Dest>
Chris@16 151 struct apply
Chris@16 152 : do_call_base_unit_converter<Source, typename Dest::unit_type>
Chris@16 153 {
Chris@16 154 };
Chris@16 155 };
Chris@16 156
Chris@16 157 template<>
Chris@16 158 struct call_base_unit_converter_base_unit_impl<true, false>
Chris@16 159 {
Chris@16 160 template<class Source, class Dest>
Chris@16 161 struct apply
Chris@16 162 : do_call_base_unit_converter<Source, typename Dest::unit_type>
Chris@16 163 {
Chris@16 164 };
Chris@16 165 };
Chris@16 166
Chris@16 167 template<>
Chris@16 168 struct call_base_unit_converter_base_unit_impl<false, true>
Chris@16 169 {
Chris@16 170 template<class Source, class Dest>
Chris@16 171 struct apply
Chris@16 172 {
Chris@16 173 typedef do_call_base_unit_converter<Dest, typename Source::unit_type> converter;
Chris@16 174 typedef typename divide_typeof_helper<one, typename converter::type>::type type;
Chris@16 175 static type value() {
Chris@16 176 one numerator;
Chris@16 177 return(numerator / converter::value());
Chris@16 178 }
Chris@16 179 };
Chris@16 180 };
Chris@16 181
Chris@16 182 template<>
Chris@16 183 struct call_base_unit_converter_base_unit_impl<false, false>
Chris@16 184 {
Chris@16 185 template<class Source, class Dest>
Chris@16 186 struct apply
Chris@16 187 {
Chris@16 188 typedef typename reduce_unit<typename get_default_conversion<Source>::type>::type new_source;
Chris@16 189 typedef typename reduce_unit<typename get_default_conversion<Dest>::type>::type new_dest;
Chris@16 190 typedef call_base_unit_converter<Source, new_source> start;
Chris@16 191 typedef detail::conversion_factor_helper<
Chris@16 192 new_source,
Chris@16 193 new_dest
Chris@16 194 > conversion;
Chris@16 195 typedef call_base_unit_converter<Dest, new_dest> end;
Chris@16 196 typedef typename divide_typeof_helper<
Chris@16 197 typename multiply_typeof_helper<
Chris@16 198 typename start::type,
Chris@16 199 typename conversion::type
Chris@16 200 >::type,
Chris@16 201 typename end::type
Chris@16 202 >::type type;
Chris@16 203 static type value() {
Chris@16 204 return(start::value() * conversion::value() / end::value());
Chris@16 205 }
Chris@16 206 };
Chris@16 207 };
Chris@16 208
Chris@16 209 template<int N>
Chris@16 210 struct get_default_conversion_impl
Chris@16 211 {
Chris@16 212 template<class Begin>
Chris@16 213 struct apply
Chris@16 214 {
Chris@16 215 typedef typename Begin::item source_pair;
Chris@16 216 typedef typename source_pair::value_type exponent;
Chris@16 217 typedef typename source_pair::tag_type source;
Chris@16 218 typedef typename reduce_unit<typename get_default_conversion<source>::type>::type new_source;
Chris@16 219 typedef typename get_default_conversion_impl<N-1>::template apply<typename Begin::next> next_iteration;
Chris@16 220 typedef typename multiply_typeof_helper<typename power_typeof_helper<new_source, exponent>::type, typename next_iteration::unit_type>::type unit_type;
Chris@16 221 typedef call_base_unit_converter<source, new_source> conversion;
Chris@16 222 typedef typename multiply_typeof_helper<typename conversion::type, typename next_iteration::type>::type type;
Chris@16 223 static type value() {
Chris@16 224 return(static_rational_power<exponent>(conversion::value()) * next_iteration::value());
Chris@16 225 }
Chris@16 226 };
Chris@16 227 };
Chris@16 228
Chris@16 229 template<>
Chris@16 230 struct get_default_conversion_impl<0>
Chris@16 231 {
Chris@16 232 template<class Begin>
Chris@16 233 struct apply
Chris@16 234 {
Chris@16 235 typedef unit<dimensionless_type, heterogeneous_system<heterogeneous_system_impl<dimensionless_type, dimensionless_type, no_scale> > > unit_type;
Chris@16 236 typedef one type;
Chris@16 237 static one value() {
Chris@16 238 one result;
Chris@16 239 return(result);
Chris@16 240 }
Chris@16 241 };
Chris@16 242 };
Chris@16 243
Chris@16 244 template<bool is_defined>
Chris@16 245 struct call_base_unit_converter_impl;
Chris@16 246
Chris@16 247 template<>
Chris@16 248 struct call_base_unit_converter_impl<true>
Chris@16 249 {
Chris@16 250 template<class Source, class Dest>
Chris@16 251 struct apply
Chris@16 252 : do_call_base_unit_converter<Source, Dest>
Chris@16 253 {
Chris@16 254 };
Chris@16 255 };
Chris@16 256
Chris@16 257 template<>
Chris@16 258 struct call_base_unit_converter_impl<false>
Chris@16 259 {
Chris@16 260 template<class Source, class Dest>
Chris@16 261 struct apply {
Chris@16 262 typedef typename reduce_unit<typename get_default_conversion<Source>::type>::type new_source;
Chris@16 263 typedef typename Dest::system_type::type system_list;
Chris@16 264 typedef typename get_default_conversion_impl<system_list::size::value>::template apply<system_list> impl;
Chris@16 265 typedef typename impl::unit_type new_dest;
Chris@16 266 typedef call_base_unit_converter<Source, new_source> start;
Chris@16 267 typedef conversion_factor_helper<new_source, new_dest> conversion;
Chris@16 268 typedef typename divide_typeof_helper<
Chris@16 269 typename multiply_typeof_helper<
Chris@16 270 typename start::type,
Chris@16 271 typename conversion::type
Chris@16 272 >::type,
Chris@16 273 typename impl::type
Chris@16 274 >::type type;
Chris@16 275 static type value() {
Chris@16 276 return(start::value() * conversion::value() / impl::value());
Chris@16 277 }
Chris@16 278 };
Chris@16 279 };
Chris@16 280
Chris@16 281 #define BOOST_UNITS_DETAIL_BASE_UNIT_CONVERTER_IS_DEFINED(Source, Dest)\
Chris@16 282 base_unit_converter<\
Chris@16 283 typename select_base_unit_converter<typename unscale<Source>::type, typename unscale<Dest>::type>::source_type,\
Chris@16 284 typename select_base_unit_converter<typename unscale<Source>::type, typename unscale<Dest>::type>::destination_type\
Chris@16 285 >::is_defined
Chris@16 286
Chris@16 287 template<class Source, class Dest>
Chris@16 288 struct call_base_unit_converter : call_base_unit_converter_impl<BOOST_UNITS_DETAIL_BASE_UNIT_CONVERTER_IS_DEFINED(Source, Dest)>::template apply<Source, Dest>
Chris@16 289 {
Chris@16 290 };
Chris@16 291
Chris@16 292 template<class Source, class Dest>
Chris@16 293 struct call_base_unit_converter<Source, BOOST_UNITS_MAKE_HETEROGENEOUS_UNIT(Dest, typename Source::dimension_type)> :
Chris@16 294 call_base_unit_converter_base_unit_impl<
Chris@16 295 BOOST_UNITS_DETAIL_BASE_UNIT_CONVERTER_IS_DEFINED(Source, typename Dest::unit_type),
Chris@16 296 BOOST_UNITS_DETAIL_BASE_UNIT_CONVERTER_IS_DEFINED(Dest, typename Source::unit_type)
Chris@16 297 >::template apply<Source, Dest>
Chris@16 298 {
Chris@16 299 };
Chris@16 300
Chris@16 301 template<int N>
Chris@16 302 struct conversion_impl
Chris@16 303 {
Chris@16 304 template<class Begin, class DestinationSystem>
Chris@16 305 struct apply
Chris@16 306 {
Chris@16 307 typedef typename conversion_impl<N-1>::template apply<
Chris@16 308 typename Begin::next,
Chris@16 309 DestinationSystem
Chris@16 310 > next_iteration;
Chris@16 311 typedef typename Begin::item unit_pair;
Chris@16 312 typedef typename unit_pair::tag_type unit;
Chris@16 313 typedef typename unit::dimension_type dimensions;
Chris@16 314 typedef typename reduce_unit<units::unit<dimensions, DestinationSystem> >::type reduced_unit;
Chris@16 315 typedef detail::call_base_unit_converter<unit, reduced_unit> converter;
Chris@16 316 typedef typename multiply_typeof_helper<typename converter::type, typename next_iteration::type>::type type;
Chris@16 317 static type value() { return(static_rational_power<typename unit_pair::value_type>(converter::value()) * next_iteration::value()); }
Chris@16 318 };
Chris@16 319 };
Chris@16 320
Chris@16 321 template<>
Chris@16 322 struct conversion_impl<0>
Chris@16 323 {
Chris@16 324 template<class Begin, class DestinationSystem>
Chris@16 325 struct apply
Chris@16 326 {
Chris@16 327 typedef one type;
Chris@16 328 static type value() { one result; return(result); }
Chris@16 329 };
Chris@16 330 };
Chris@16 331
Chris@16 332 } // namespace detail
Chris@16 333
Chris@16 334 /// forward to conversion_factor (intentionally allowing ADL)
Chris@16 335 /// INTERNAL ONLY
Chris@16 336 template<class Unit1, class T1, class Unit2, class T2>
Chris@16 337 struct conversion_helper<quantity<Unit1, T1>, quantity<Unit2, T2> >
Chris@16 338 {
Chris@16 339 /// INTERNAL ONLY
Chris@16 340 typedef quantity<Unit2, T2> destination_type;
Chris@16 341 static destination_type convert(const quantity<Unit1, T1>& source)
Chris@16 342 {
Chris@16 343 Unit1 u1;
Chris@16 344 Unit2 u2;
Chris@16 345 return(destination_type::from_value(static_cast<T2>(source.value() * conversion_factor(u1, u2))));
Chris@16 346 }
Chris@16 347 };
Chris@16 348
Chris@16 349 namespace detail {
Chris@16 350
Chris@16 351 template<class Source, class Dest>
Chris@16 352 struct conversion_factor_helper;
Chris@16 353
Chris@16 354 template<class D, class L1, class L2>
Chris@16 355 struct conversion_factor_helper<unit<D, homogeneous_system<L1> >, unit<D, homogeneous_system<L2> > >
Chris@16 356 : conversion_factor_helper<
Chris@16 357 typename reduce_unit<unit<D, homogeneous_system<L1> > >::type,
Chris@16 358 typename reduce_unit<unit<D, homogeneous_system<L2> > >::type
Chris@16 359 >
Chris@16 360 {
Chris@16 361 //typedef typename reduce_unit<unit<D, homogeneous_system<L1> > >::type source_unit;
Chris@16 362 //typedef typename source_unit::system_type::type unit_list;
Chris@16 363 //typedef typename detail::conversion_impl<unit_list::size::value>::template apply<
Chris@16 364 // unit_list,
Chris@16 365 // homogeneous_system<L2>
Chris@16 366 //> impl;
Chris@16 367 //typedef typename impl::type type;
Chris@16 368 //static type value()
Chris@16 369 //{
Chris@16 370 // return(impl::value());
Chris@16 371 //}
Chris@16 372 };
Chris@16 373
Chris@16 374 template<class D, class L1, class L2>
Chris@16 375 struct conversion_factor_helper<unit<D, heterogeneous_system<L1> >, unit<D, homogeneous_system<L2> > >
Chris@16 376 : conversion_factor_helper<
Chris@16 377 typename reduce_unit<unit<D, heterogeneous_system<L1> > >::type,
Chris@16 378 typename reduce_unit<unit<D, homogeneous_system<L2> > >::type
Chris@16 379 >
Chris@16 380 {
Chris@16 381 //typedef typename detail::conversion_impl<L1::type::size::value>::template apply<
Chris@16 382 // typename L1::type,
Chris@16 383 // homogeneous_system<L2>
Chris@16 384 //> impl;
Chris@16 385 //typedef eval_scale_list<typename L1::scale> scale;
Chris@16 386 //typedef typename multiply_typeof_helper<typename impl::type, typename scale::type>::type type;
Chris@16 387 //static type value()
Chris@16 388 //{
Chris@16 389 // return(impl::value() * scale::value());
Chris@16 390 //}
Chris@16 391 };
Chris@16 392
Chris@16 393 // There is no simple algorithm for doing this conversion
Chris@16 394 // other than just defining it as the reverse of the
Chris@16 395 // heterogeneous->homogeneous case
Chris@16 396 template<class D, class L1, class L2>
Chris@16 397 struct conversion_factor_helper<unit<D, homogeneous_system<L1> >, unit<D, heterogeneous_system<L2> > >
Chris@16 398 : conversion_factor_helper<
Chris@16 399 typename reduce_unit<unit<D, homogeneous_system<L1> > >::type,
Chris@16 400 typename reduce_unit<unit<D, heterogeneous_system<L2> > >::type
Chris@16 401 >
Chris@16 402 {
Chris@16 403 //typedef typename detail::conversion_impl<L2::type::size::value>::template apply<
Chris@16 404 // typename L2::type,
Chris@16 405 // homogeneous_system<L1>
Chris@16 406 //> impl;
Chris@16 407 //typedef eval_scale_list<typename L2::scale> scale;
Chris@16 408 //typedef typename multiply_typeof_helper<typename impl::type, typename scale::type>::type type;
Chris@16 409 //static type value()
Chris@16 410 //{
Chris@16 411 // one numerator;
Chris@16 412 // return(numerator / (impl::value() * scale::value()));
Chris@16 413 //}
Chris@16 414 };
Chris@16 415
Chris@16 416 /// Requires that all possible conversions
Chris@16 417 /// between base units are defined.
Chris@16 418 template<class D, class S1, class S2>
Chris@16 419 struct conversion_factor_helper<unit<D, heterogeneous_system<S1> >, unit<D, heterogeneous_system<S2> > >
Chris@16 420 {
Chris@16 421 /// INTERNAL ONLY
Chris@16 422 typedef typename detail::extract_base_units<S1::type::size::value>::template apply<
Chris@16 423 typename S1::type,
Chris@16 424 dimensionless_type
Chris@16 425 >::type from_base_units;
Chris@16 426 /// INTERNAL ONLY
Chris@16 427 typedef typename detail::extract_base_units<S2::type::size::value>::template apply<
Chris@16 428 typename S2::type,
Chris@16 429 from_base_units
Chris@16 430 >::type all_base_units;
Chris@16 431 /// INTERNAL ONLY
Chris@16 432 typedef typename detail::make_homogeneous_system<all_base_units>::type system;
Chris@16 433 typedef typename detail::conversion_impl<S1::type::size::value>::template apply<
Chris@16 434 typename S1::type,
Chris@16 435 system
Chris@16 436 > conversion1;
Chris@16 437 typedef typename detail::conversion_impl<S2::type::size::value>::template apply<
Chris@16 438 typename S2::type,
Chris@16 439 system
Chris@16 440 > conversion2;
Chris@16 441 typedef eval_scale_list<typename mpl::divides<typename S1::scale, typename S2::scale>::type> scale;
Chris@16 442 typedef typename multiply_typeof_helper<
Chris@16 443 typename conversion1::type,
Chris@16 444 typename divide_typeof_helper<typename scale::type, typename conversion2::type>::type
Chris@16 445 >::type type;
Chris@16 446 static type value()
Chris@16 447 {
Chris@16 448 return(conversion1::value() * (scale::value() / conversion2::value()));
Chris@16 449 }
Chris@16 450 };
Chris@16 451
Chris@16 452 } // namespace detail
Chris@16 453
Chris@16 454 } // namespace units
Chris@16 455
Chris@16 456 } // namespace boost
Chris@16 457
Chris@16 458 #endif // BOOST_UNITS_CONVERSION_IMPL_HPP