dimension.hpp 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. // Boost.Units - A C++ library for zero-overhead dimensional analysis and
  2. // unit/quantity manipulation and conversion
  3. //
  4. // Copyright (C) 2003-2008 Matthias Christian Schabel
  5. // Copyright (C) 2007-2008 Steven Watanabe
  6. //
  7. // Distributed under the Boost Software License, Version 1.0. (See
  8. // accompanying file LICENSE_1_0.txt or copy at
  9. // http://www.boost.org/LICENSE_1_0.txt)
  10. #ifndef BOOST_UNITS_DIMENSION_HPP
  11. #define BOOST_UNITS_DIMENSION_HPP
  12. #include <boost/static_assert.hpp>
  13. #include <boost/type_traits/is_same.hpp>
  14. #include <boost/mpl/arithmetic.hpp>
  15. #include <boost/units/static_rational.hpp>
  16. #include <boost/units/detail/dimension_list.hpp>
  17. #include <boost/units/detail/dimension_impl.hpp>
  18. /// \file
  19. /// \brief Core metaprogramming utilities for compile-time dimensional analysis.
  20. namespace boost {
  21. namespace units {
  22. /// Reduce dimension list to cardinal form. This algorithm collapses duplicate
  23. /// base dimension tags and sorts the resulting list by the tag ordinal value.
  24. /// Dimension lists that resolve to the same dimension are guaranteed to be
  25. /// represented by an identical type.
  26. ///
  27. /// The argument should be an MPL forward sequence containing instances
  28. /// of the @c dim template.
  29. ///
  30. /// The result is also an MPL forward sequence. It also supports the
  31. /// following metafunctions to allow use as a dimension.
  32. ///
  33. /// - @c mpl::plus is defined only on two equal dimensions and returns the argument unchanged.
  34. /// - @c mpl::minus is defined only for two equal dimensions and returns the argument unchanged.
  35. /// - @c mpl::negate will return its argument unchanged.
  36. /// - @c mpl::times is defined for any dimensions and adds corresponding exponents.
  37. /// - @c mpl::divides is defined for any dimensions and subtracts the exponents of the
  38. /// right had argument from the corresponding exponents of the left had argument.
  39. /// Missing base dimension tags are assumed to have an exponent of zero.
  40. /// - @c static_power takes a dimension and a static_rational and multiplies all
  41. /// the exponents of the dimension by the static_rational.
  42. /// - @c static_root takes a dimension and a static_rational and divides all
  43. /// the exponents of the dimension by the static_rational.
  44. template<typename Seq>
  45. struct make_dimension_list
  46. {
  47. typedef typename detail::sort_dims<Seq>::type type;
  48. };
  49. /// Raise a dimension list to a scalar power.
  50. template<typename DL,typename Ex>
  51. struct static_power
  52. {
  53. typedef typename detail::static_power_impl<DL::size::value>::template apply<
  54. DL,
  55. Ex
  56. >::type type;
  57. };
  58. /// Take a scalar root of a dimension list.
  59. template<typename DL,typename Rt>
  60. struct static_root
  61. {
  62. typedef typename detail::static_root_impl<DL::size::value>::template apply<
  63. DL,
  64. Rt
  65. >::type type;
  66. };
  67. } // namespace units
  68. #ifndef BOOST_UNITS_DOXYGEN
  69. namespace mpl {
  70. template<>
  71. struct plus_impl<boost::units::detail::dimension_list_tag,boost::units::detail::dimension_list_tag>
  72. {
  73. template<class T0, class T1>
  74. struct apply
  75. {
  76. BOOST_STATIC_ASSERT((boost::is_same<T0,T1>::value == true));
  77. typedef T0 type;
  78. };
  79. };
  80. template<>
  81. struct minus_impl<boost::units::detail::dimension_list_tag,boost::units::detail::dimension_list_tag>
  82. {
  83. template<class T0, class T1>
  84. struct apply
  85. {
  86. BOOST_STATIC_ASSERT((boost::is_same<T0,T1>::value == true));
  87. typedef T0 type;
  88. };
  89. };
  90. template<>
  91. struct times_impl<boost::units::detail::dimension_list_tag,boost::units::detail::dimension_list_tag>
  92. {
  93. template<class T0, class T1>
  94. struct apply
  95. {
  96. typedef typename boost::units::detail::merge_dimensions<T0,T1>::type type;
  97. };
  98. };
  99. template<>
  100. struct divides_impl<boost::units::detail::dimension_list_tag,boost::units::detail::dimension_list_tag>
  101. {
  102. template<class T0, class T1>
  103. struct apply
  104. {
  105. typedef typename boost::units::detail::merge_dimensions<
  106. T0,
  107. typename boost::units::detail::static_inverse_impl<
  108. T1::size::value
  109. >::template apply<
  110. T1
  111. >::type
  112. >::type type;
  113. };
  114. };
  115. template<>
  116. struct negate_impl<boost::units::detail::dimension_list_tag>
  117. {
  118. template<class T0>
  119. struct apply
  120. {
  121. typedef T0 type;
  122. };
  123. };
  124. } // namespace mpl
  125. #endif
  126. } // namespace boost
  127. #endif // BOOST_UNITS_DIMENSION_HPP