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 | |