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) 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_IMPL_HPP 12 #define BOOST_UNITS_DIMENSION_IMPL_HPP 13 14 #include <boost/mpl/begin_end.hpp> 15 #include <boost/mpl/deref.hpp> 16 #include <boost/mpl/if.hpp> 17 #include <boost/mpl/list.hpp> 18 #include <boost/mpl/next.hpp> 19 #include <boost/mpl/size.hpp> 20 #include <boost/mpl/less.hpp> 21 22 #include <boost/units/config.hpp> 23 #include <boost/units/dimensionless_type.hpp> 24 #include <boost/units/static_rational.hpp> 25 #include <boost/units/units_fwd.hpp> 26 #include <boost/units/detail/dimension_list.hpp> 27 #include <boost/units/detail/push_front_if.hpp> 28 #include <boost/units/detail/push_front_or_add.hpp> 29 30 /// \file 31 /// \brief Core class and metaprogramming utilities for compile-time dimensional analysis. 32 33 namespace boost { 34 35 namespace units { 36 37 namespace detail { 38 39 template<int N> 40 struct insertion_sort_dims_insert; 41 42 template<bool is_greater> 43 struct insertion_sort_dims_comparison_impl; 44 45 // have to recursively add the element to the next sequence. 46 template<> 47 struct insertion_sort_dims_comparison_impl<true> { 48 template<class Begin, int N, class T> 49 struct apply { 50 typedef list< 51 typename Begin::item, 52 typename insertion_sort_dims_insert<N - 1>::template apply< 53 typename Begin::next, 54 T 55 >::type 56 > type; 57 }; 58 }; 59 60 // either prepend the current element or join it to 61 // the first remaining element of the sequence. 62 template<> 63 struct insertion_sort_dims_comparison_impl<false> { 64 template<class Begin, int N, class T> 65 struct apply { 66 typedef typename push_front_or_add<Begin, T>::type type; 67 }; 68 }; 69 70 template<int N> 71 struct insertion_sort_dims_insert { 72 template<class Begin, class T> 73 struct apply { 74 typedef typename insertion_sort_dims_comparison_impl<mpl::less<typename Begin::item, T>::value>::template apply< 75 Begin, 76 N, 77 T 78 >::type type; 79 }; 80 }; 81 82 template<> 83 struct insertion_sort_dims_insert<0> { 84 template<class Begin, class T> 85 struct apply { 86 typedef list<T, dimensionless_type> type; 87 }; 88 }; 89 90 template<int N> 91 struct insertion_sort_dims_mpl_sequence { 92 template<class Begin> 93 struct apply { 94 typedef typename insertion_sort_dims_mpl_sequence<N - 1>::template apply<typename mpl::next<Begin>::type>::type next; 95 typedef typename insertion_sort_dims_insert<(next::size::value)>::template apply<next, typename mpl::deref<Begin>::type>::type type; 96 }; 97 }; 98 99 template<> 100 struct insertion_sort_dims_mpl_sequence<0> { 101 template<class Begin> 102 struct apply { 103 typedef dimensionless_type type; 104 }; 105 }; 106 107 template<int N> 108 struct insertion_sort_dims_impl { 109 template<class Begin> 110 struct apply { 111 typedef typename insertion_sort_dims_impl<N - 1>::template apply<typename Begin::next>::type next; 112 typedef typename insertion_sort_dims_insert<(next::size::value)>::template apply<next, typename Begin::item>::type type; 113 }; 114 }; 115 116 template<> 117 struct insertion_sort_dims_impl<0> { 118 template<class Begin> 119 struct apply { 120 typedef dimensionless_type type; 121 }; 122 }; 123 124 template<class T> 125 struct sort_dims 126 { 127 typedef typename insertion_sort_dims_mpl_sequence<mpl::size<T>::value>::template apply<typename mpl::begin<T>::type>::type type; 128 }; 129 130 131 template<class T, class Next> 132 struct sort_dims<list<T, Next> > 133 { 134 typedef typename insertion_sort_dims_impl<list<T, Next>::size::value>::template apply<list<T, Next> >::type type; 135 }; 136 137 /// sorted sequences can be merged in linear time 138 template<bool less, bool greater> 139 struct merge_dimensions_func; 140 141 template<int N1, int N2> 142 struct merge_dimensions_impl; 143 144 template<> 145 struct merge_dimensions_func<true, false> 146 { 147 template<typename Begin1, typename Begin2, int N1, int N2> 148 struct apply 149 { 150 typedef list< 151 typename Begin1::item, 152 typename merge_dimensions_impl<N1 - 1, N2>::template apply< 153 typename Begin1::next, 154 Begin2 155 >::type 156 > type; 157 }; 158 }; 159 160 template<> 161 struct merge_dimensions_func<false, true> { 162 template<typename Begin1, typename Begin2, int N1, int N2> 163 struct apply 164 { 165 typedef list< 166 typename Begin2::item, 167 typename merge_dimensions_impl<N2 - 1, N1>::template apply< 168 typename Begin2::next, 169 Begin1 170 >::type 171 > type; 172 }; 173 }; 174 175 template<> 176 struct merge_dimensions_func<false, false> { 177 template<typename Begin1, typename Begin2, int N1, int N2> 178 struct apply 179 { 180 typedef typename mpl::plus<typename Begin1::item, typename Begin2::item>::type combined; 181 typedef typename push_front_if<!is_empty_dim<combined>::value>::template apply< 182 typename merge_dimensions_impl<N1 - 1, N2 - 1>::template apply< 183 typename Begin1::next, 184 typename Begin2::next 185 >::type, 186 combined 187 >::type type; 188 }; 189 }; 190 191 template<int N1, int N2> 192 struct merge_dimensions_impl { 193 template<typename Begin1, typename Begin2> 194 struct apply 195 { 196 typedef typename Begin1::item dim1; 197 typedef typename Begin2::item dim2; 198 199 typedef typename merge_dimensions_func<(mpl::less<dim1,dim2>::value == true), 200 (mpl::less<dim2,dim1>::value == true)>::template apply< 201 Begin1, 202 Begin2, 203 N1, 204 N2 205 >::type type; 206 }; 207 }; 208 209 template<typename Sequence1, typename Sequence2> 210 struct merge_dimensions 211 { 212 typedef typename detail::merge_dimensions_impl<Sequence1::size::value, 213 Sequence2::size::value>::template 214 apply< 215 Sequence1, 216 Sequence2 217 >::type type; 218 }; 219 220 template<int N> 221 struct iterator_to_list 222 { 223 template<typename Begin> 224 struct apply 225 { 226 typedef list< 227 typename Begin::item, 228 typename iterator_to_list<N - 1>::template apply< 229 typename Begin::next 230 >::type 231 > type; 232 }; 233 }; 234 235 template<> 236 struct iterator_to_list<0> 237 { 238 template<typename Begin> 239 struct apply { 240 typedef dimensionless_type type; 241 }; 242 }; 243 244 template<int N> 245 struct merge_dimensions_impl<N, 0> 246 { 247 template<typename Begin1, typename Begin2> 248 struct apply 249 { 250 typedef typename iterator_to_list<N>::template apply<Begin1>::type type; 251 }; 252 }; 253 254 template<int N> 255 struct merge_dimensions_impl<0, N> 256 { 257 template<typename Begin1, typename Begin2> 258 struct apply 259 { 260 typedef typename iterator_to_list<N>::template apply<Begin2>::type type; 261 }; 262 }; 263 264 template<> 265 struct merge_dimensions_impl<0, 0> 266 { 267 template<typename Begin1, typename Begin2> 268 struct apply 269 { 270 typedef dimensionless_type type; 271 }; 272 }; 273 274 template<int N> 275 struct static_inverse_impl 276 { 277 template<typename Begin> 278 struct apply { 279 typedef list< 280 typename mpl::negate<typename Begin::item>::type, 281 typename static_inverse_impl<N - 1>::template apply< 282 typename Begin::next 283 >::type 284 > type; 285 }; 286 }; 287 288 template<> 289 struct static_inverse_impl<0> 290 { 291 template<typename Begin> 292 struct apply 293 { 294 typedef dimensionless_type type; 295 }; 296 }; 297 298 template<int N> 299 struct static_power_impl 300 { 301 template<typename Begin, typename Ex> 302 struct apply 303 { 304 typedef list< 305 typename mpl::times<typename Begin::item, Ex>::type, 306 typename detail::static_power_impl<N - 1>::template apply<typename Begin::next, Ex>::type 307 > type; 308 }; 309 }; 310 311 template<> 312 struct static_power_impl<0> 313 { 314 template<typename Begin, typename Ex> 315 struct apply 316 { 317 typedef dimensionless_type type; 318 }; 319 }; 320 321 template<int N> 322 struct static_root_impl { 323 template<class Begin, class Ex> 324 struct apply { 325 typedef list< 326 typename mpl::divides<typename Begin::item, Ex>::type, 327 typename detail::static_root_impl<N - 1>::template apply<typename Begin::next, Ex>::type 328 > type; 329 }; 330 }; 331 332 template<> 333 struct static_root_impl<0> { 334 template<class Begin, class Ex> 335 struct apply 336 { 337 typedef dimensionless_type type; 338 }; 339 }; 340 341 } // namespace detail 342 343 } // namespace units 344 345 } // namespace boost 346 347 #endif // BOOST_UNITS_DIMENSION_IMPL_HPP 348