heterogeneous_conversion.hpp 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  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_DETAIL_HETEROGENEOUS_CONVERSION_HPP
  11. #define BOOST_UNITS_DETAIL_HETEROGENEOUS_CONVERSION_HPP
  12. #include <boost/mpl/minus.hpp>
  13. #include <boost/mpl/times.hpp>
  14. #include <boost/units/static_rational.hpp>
  15. #include <boost/units/homogeneous_system.hpp>
  16. #include <boost/units/detail/linear_algebra.hpp>
  17. namespace boost {
  18. namespace units {
  19. namespace detail {
  20. struct solve_end {
  21. template<class Begin, class Y>
  22. struct apply {
  23. typedef dimensionless_type type;
  24. };
  25. };
  26. struct no_solution {};
  27. template<class X1, class X2, class Next>
  28. struct solve_normal {
  29. template<class Begin, class Y>
  30. struct apply {
  31. typedef typename Begin::next next;
  32. typedef list<
  33. typename mpl::minus<
  34. typename mpl::times<X1, Y>::type,
  35. typename mpl::times<X2, typename Begin::item>::type
  36. >::type,
  37. typename Next::template apply<next, Y>::type
  38. > type;
  39. };
  40. };
  41. template<class Next>
  42. struct solve_leading_zeroes {
  43. template<class Begin>
  44. struct apply {
  45. typedef list<
  46. typename Begin::item,
  47. typename Next::template apply<typename Begin::next>::type
  48. > type;
  49. };
  50. typedef solve_leading_zeroes type;
  51. };
  52. template<>
  53. struct solve_leading_zeroes<no_solution> {
  54. typedef no_solution type;
  55. };
  56. template<class Next>
  57. struct solve_first_non_zero {
  58. template<class Begin>
  59. struct apply {
  60. typedef typename Next::template apply<
  61. typename Begin::next,
  62. typename Begin::item
  63. >::type type;
  64. };
  65. };
  66. template<class Next>
  67. struct solve_internal_zero {
  68. template<class Begin, class Y>
  69. struct apply {
  70. typedef list<
  71. typename Begin::item,
  72. typename Next::template apply<typename Begin::next, Y>::type
  73. > type;
  74. };
  75. };
  76. template<class T>
  77. struct make_solve_list_internal_zero {
  78. template<class Next, class X>
  79. struct apply {
  80. typedef solve_normal<T, X, Next> type;
  81. };
  82. };
  83. template<>
  84. struct make_solve_list_internal_zero<static_rational<0> > {
  85. template<class Next, class X>
  86. struct apply {
  87. typedef solve_internal_zero<Next> type;
  88. };
  89. };
  90. template<int N>
  91. struct make_solve_list_normal {
  92. template<class Begin, class X>
  93. struct apply {
  94. typedef typename make_solve_list_internal_zero<
  95. typename Begin::item
  96. >::template apply<
  97. typename make_solve_list_normal<N-1>::template apply<typename Begin::next, X>::type,
  98. X
  99. >::type type;
  100. };
  101. };
  102. template<>
  103. struct make_solve_list_normal<0> {
  104. template<class Begin, class X>
  105. struct apply {
  106. typedef solve_end type;
  107. };
  108. };
  109. template<int N>
  110. struct make_solve_list_leading_zeroes;
  111. template<class T>
  112. struct make_solve_list_first_non_zero {
  113. template<class Begin, int N>
  114. struct apply {
  115. typedef solve_first_non_zero<
  116. typename make_solve_list_normal<N-1>::template apply<
  117. typename Begin::next,
  118. typename Begin::item
  119. >::type
  120. > type;
  121. };
  122. };
  123. template<>
  124. struct make_solve_list_first_non_zero<static_rational<0> > {
  125. template<class Begin, int N>
  126. struct apply {
  127. typedef typename solve_leading_zeroes<
  128. typename make_solve_list_leading_zeroes<N-1>::template apply<
  129. typename Begin::next
  130. >::type
  131. >::type type;
  132. };
  133. };
  134. template<int N>
  135. struct make_solve_list_leading_zeroes {
  136. template<class Begin>
  137. struct apply {
  138. typedef typename make_solve_list_first_non_zero<typename Begin::item>::template apply<Begin, N>::type type;
  139. };
  140. };
  141. template<>
  142. struct make_solve_list_leading_zeroes<0> {
  143. template<class Begin>
  144. struct apply {
  145. typedef no_solution type;
  146. };
  147. };
  148. template<int N>
  149. struct try_add_unit_impl {
  150. template<class Begin, class L>
  151. struct apply {
  152. typedef typename try_add_unit_impl<N-1>::template apply<typename Begin::next, L>::type next;
  153. typedef typename Begin::item::template apply<next>::type type;
  154. BOOST_STATIC_ASSERT((next::size::value - 1 == type::size::value));
  155. };
  156. };
  157. template<>
  158. struct try_add_unit_impl<0> {
  159. template<class Begin, class L>
  160. struct apply {
  161. typedef L type;
  162. };
  163. };
  164. template<int N>
  165. struct make_homogeneous_system_impl;
  166. template<class T, bool is_done>
  167. struct make_homogeneous_system_func;
  168. template<class T>
  169. struct make_homogeneous_system_func<T, false> {
  170. template<class Begin, class Current, class Units, class Dimensions, int N>
  171. struct apply {
  172. typedef typename make_homogeneous_system_impl<N-1>::template apply<
  173. typename Begin::next,
  174. list<T, Current>,
  175. list<typename Begin::item, Units>,
  176. Dimensions
  177. >::type type;
  178. };
  179. };
  180. template<class T>
  181. struct make_homogeneous_system_func<T, true> {
  182. template<class Begin, class Current, class Units, class Dimensions, int N>
  183. struct apply {
  184. typedef list<typename Begin::item, Units> type;
  185. };
  186. };
  187. template<>
  188. struct make_homogeneous_system_func<no_solution, false> {
  189. template<class Begin, class Current, class Units, class Dimensions, int N>
  190. struct apply {
  191. typedef typename make_homogeneous_system_impl<N-1>::template apply<
  192. typename Begin::next,
  193. Current,
  194. Units,
  195. Dimensions
  196. >::type type;
  197. };
  198. };
  199. template<>
  200. struct make_homogeneous_system_func<no_solution, true> {
  201. template<class Begin, class Current, class Units, class Dimensions, int N>
  202. struct apply {
  203. typedef typename make_homogeneous_system_impl<N-1>::template apply<
  204. typename Begin::next,
  205. Current,
  206. Units,
  207. Dimensions
  208. >::type type;
  209. };
  210. };
  211. template<int N>
  212. struct make_homogeneous_system_impl {
  213. template<class Begin, class Current, class Units, class Dimensions>
  214. struct apply {
  215. typedef typename expand_dimensions<Dimensions::size::value>::template apply<
  216. Dimensions,
  217. typename Begin::item::dimension_type
  218. >::type dimensions;
  219. typedef typename try_add_unit_impl<Current::size::value>::template apply<Current, dimensions>::type new_element;
  220. typedef typename make_solve_list_leading_zeroes<new_element::size::value>::template apply<new_element>::type new_func;
  221. typedef typename make_homogeneous_system_func<
  222. new_func,
  223. ((Current::size::value)+1) == (Dimensions::size::value)
  224. >::template apply<Begin, Current, Units, Dimensions, N>::type type;
  225. };
  226. };
  227. template<>
  228. struct make_homogeneous_system_impl<0> {
  229. template<class Begin, class Current, class Units, class Dimensions>
  230. struct apply {
  231. typedef Units type;
  232. };
  233. };
  234. template<class Units>
  235. struct make_homogeneous_system {
  236. typedef typename find_base_dimensions<Units>::type base_dimensions;
  237. typedef homogeneous_system<
  238. typename insertion_sort<
  239. typename make_homogeneous_system_impl<
  240. Units::size::value
  241. >::template apply<
  242. Units,
  243. dimensionless_type,
  244. dimensionless_type,
  245. base_dimensions
  246. >::type
  247. >::type
  248. > type;
  249. };
  250. template<int N>
  251. struct extract_base_units {
  252. template<class Begin, class T>
  253. struct apply {
  254. typedef list<
  255. typename Begin::item::tag_type,
  256. typename extract_base_units<N-1>::template apply<typename Begin::next, T>::type
  257. > type;
  258. };
  259. };
  260. template<>
  261. struct extract_base_units<0> {
  262. template<class Begin, class T>
  263. struct apply {
  264. typedef T type;
  265. };
  266. };
  267. }
  268. }
  269. }
  270. #endif