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 11 #ifndef BOOST_UNITS_DIMENSION_HPP 12 #define BOOST_UNITS_DIMENSION_HPP 13 14 #include <boost/static_assert.hpp> 15 16 #include <boost/type_traits/is_same.hpp> 17 18 #include <boost/mpl/arithmetic.hpp> 19 20 #include <boost/units/static_rational.hpp> 21 #include <boost/units/detail/dimension_list.hpp> 22 #include <boost/units/detail/dimension_impl.hpp> 23 24 /// \file 25 /// \brief Core metaprogramming utilities for compile-time dimensional analysis. 26 27 namespace boost { 28 29 namespace units { 30 31 /// Reduce dimension list to cardinal form. This algorithm collapses duplicate 32 /// base dimension tags and sorts the resulting list by the tag ordinal value. 33 /// Dimension lists that resolve to the same dimension are guaranteed to be 34 /// represented by an identical type. 35 /// 36 /// The argument should be an MPL forward sequence containing instances 37 /// of the @c dim template. 38 /// 39 /// The result is also an MPL forward sequence. It also supports the 40 /// following metafunctions to allow use as a dimension. 41 /// 42 /// - @c mpl::plus is defined only on two equal dimensions and returns the argument unchanged. 43 /// - @c mpl::minus is defined only for two equal dimensions and returns the argument unchanged. 44 /// - @c mpl::negate will return its argument unchanged. 45 /// - @c mpl::times is defined for any dimensions and adds corresponding exponents. 46 /// - @c mpl::divides is defined for any dimensions and subtracts the exponents of the 47 /// right had argument from the corresponding exponents of the left had argument. 48 /// Missing base dimension tags are assumed to have an exponent of zero. 49 /// - @c static_power takes a dimension and a static_rational and multiplies all 50 /// the exponents of the dimension by the static_rational. 51 /// - @c static_root takes a dimension and a static_rational and divides all 52 /// the exponents of the dimension by the static_rational. 53 template<typename Seq> 54 struct make_dimension_list 55 { 56 typedef typename detail::sort_dims<Seq>::type type; 57 }; 58 59 /// Raise a dimension list to a scalar power. 60 template<typename DL,typename Ex> 61 struct static_power 62 { 63 typedef typename detail::static_power_impl<DL::size::value>::template apply< 64 DL, 65 Ex 66 >::type type; 67 }; 68 69 /// Take a scalar root of a dimension list. 70 template<typename DL,typename Rt> 71 struct static_root 72 { 73 typedef typename detail::static_root_impl<DL::size::value>::template apply< 74 DL, 75 Rt 76 >::type type; 77 }; 78 79 } // namespace units 80 81 #ifndef BOOST_UNITS_DOXYGEN 82 83 namespace mpl { 84 85 template<> 86 struct plus_impl<boost::units::detail::dimension_list_tag,boost::units::detail::dimension_list_tag> 87 { 88 template<class T0, class T1> 89 struct apply 90 { 91 BOOST_STATIC_ASSERT((boost::is_same<T0,T1>::value == true)); 92 typedef T0 type; 93 }; 94 }; 95 96 template<> 97 struct minus_impl<boost::units::detail::dimension_list_tag,boost::units::detail::dimension_list_tag> 98 { 99 template<class T0, class T1> 100 struct apply 101 { 102 BOOST_STATIC_ASSERT((boost::is_same<T0,T1>::value == true)); 103 typedef T0 type; 104 }; 105 }; 106 107 template<> 108 struct times_impl<boost::units::detail::dimension_list_tag,boost::units::detail::dimension_list_tag> 109 { 110 template<class T0, class T1> 111 struct apply 112 { 113 typedef typename boost::units::detail::merge_dimensions<T0,T1>::type type; 114 }; 115 }; 116 117 template<> 118 struct divides_impl<boost::units::detail::dimension_list_tag,boost::units::detail::dimension_list_tag> 119 { 120 template<class T0, class T1> 121 struct apply 122 { 123 typedef typename boost::units::detail::merge_dimensions< 124 T0, 125 typename boost::units::detail::static_inverse_impl< 126 T1::size::value 127 >::template apply< 128 T1 129 >::type 130 >::type type; 131 }; 132 }; 133 134 template<> 135 struct negate_impl<boost::units::detail::dimension_list_tag> 136 { 137 template<class T0> 138 struct apply 139 { 140 typedef T0 type; 141 }; 142 }; 143 144 } // namespace mpl 145 146 #endif 147 148 } // namespace boost 149 150 #endif // BOOST_UNITS_DIMENSION_HPP 151