dimension_impl.hpp 8.5 KB

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