File indexing completed on 2025-01-18 09:53:13
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #ifndef BOOST_UNITS_DETAIL_HETEROGENEOUS_CONVERSION_HPP
0012 #define BOOST_UNITS_DETAIL_HETEROGENEOUS_CONVERSION_HPP
0013
0014 #include <boost/mpl/minus.hpp>
0015 #include <boost/mpl/times.hpp>
0016
0017 #include <boost/units/static_rational.hpp>
0018 #include <boost/units/homogeneous_system.hpp>
0019 #include <boost/units/detail/linear_algebra.hpp>
0020
0021 namespace boost {
0022
0023 namespace units {
0024
0025 namespace detail {
0026
0027 struct solve_end {
0028 template<class Begin, class Y>
0029 struct apply {
0030 typedef dimensionless_type type;
0031 };
0032 };
0033
0034 struct no_solution {};
0035
0036 template<class X1, class X2, class Next>
0037 struct solve_normal {
0038 template<class Begin, class Y>
0039 struct apply {
0040 typedef typename Begin::next next;
0041 typedef list<
0042 typename mpl::minus<
0043 typename mpl::times<X1, Y>::type,
0044 typename mpl::times<X2, typename Begin::item>::type
0045 >::type,
0046 typename Next::template apply<next, Y>::type
0047 > type;
0048 };
0049 };
0050
0051 template<class Next>
0052 struct solve_leading_zeroes {
0053 template<class Begin>
0054 struct apply {
0055 typedef list<
0056 typename Begin::item,
0057 typename Next::template apply<typename Begin::next>::type
0058 > type;
0059 };
0060 typedef solve_leading_zeroes type;
0061 };
0062
0063 template<>
0064 struct solve_leading_zeroes<no_solution> {
0065 typedef no_solution type;
0066 };
0067
0068 template<class Next>
0069 struct solve_first_non_zero {
0070 template<class Begin>
0071 struct apply {
0072 typedef typename Next::template apply<
0073 typename Begin::next,
0074 typename Begin::item
0075 >::type type;
0076 };
0077 };
0078
0079 template<class Next>
0080 struct solve_internal_zero {
0081 template<class Begin, class Y>
0082 struct apply {
0083 typedef list<
0084 typename Begin::item,
0085 typename Next::template apply<typename Begin::next, Y>::type
0086 > type;
0087 };
0088 };
0089
0090 template<class T>
0091 struct make_solve_list_internal_zero {
0092 template<class Next, class X>
0093 struct apply {
0094 typedef solve_normal<T, X, Next> type;
0095 };
0096 };
0097
0098 template<>
0099 struct make_solve_list_internal_zero<static_rational<0> > {
0100 template<class Next, class X>
0101 struct apply {
0102 typedef solve_internal_zero<Next> type;
0103 };
0104 };
0105
0106 template<int N>
0107 struct make_solve_list_normal {
0108 template<class Begin, class X>
0109 struct apply {
0110 typedef typename make_solve_list_internal_zero<
0111 typename Begin::item
0112 >::template apply<
0113 typename make_solve_list_normal<N-1>::template apply<typename Begin::next, X>::type,
0114 X
0115 >::type type;
0116 };
0117 };
0118
0119 template<>
0120 struct make_solve_list_normal<0> {
0121 template<class Begin, class X>
0122 struct apply {
0123 typedef solve_end type;
0124 };
0125 };
0126
0127 template<int N>
0128 struct make_solve_list_leading_zeroes;
0129
0130 template<class T>
0131 struct make_solve_list_first_non_zero {
0132 template<class Begin, int N>
0133 struct apply {
0134 typedef solve_first_non_zero<
0135 typename make_solve_list_normal<N-1>::template apply<
0136 typename Begin::next,
0137 typename Begin::item
0138 >::type
0139 > type;
0140 };
0141 };
0142
0143 template<>
0144 struct make_solve_list_first_non_zero<static_rational<0> > {
0145 template<class Begin, int N>
0146 struct apply {
0147 typedef typename solve_leading_zeroes<
0148 typename make_solve_list_leading_zeroes<N-1>::template apply<
0149 typename Begin::next
0150 >::type
0151 >::type type;
0152 };
0153 };
0154
0155 template<int N>
0156 struct make_solve_list_leading_zeroes {
0157 template<class Begin>
0158 struct apply {
0159 typedef typename make_solve_list_first_non_zero<typename Begin::item>::template apply<Begin, N>::type type;
0160 };
0161 };
0162
0163 template<>
0164 struct make_solve_list_leading_zeroes<0> {
0165 template<class Begin>
0166 struct apply {
0167 typedef no_solution type;
0168 };
0169 };
0170
0171 template<int N>
0172 struct try_add_unit_impl {
0173 template<class Begin, class L>
0174 struct apply {
0175 typedef typename try_add_unit_impl<N-1>::template apply<typename Begin::next, L>::type next;
0176 typedef typename Begin::item::template apply<next>::type type;
0177 BOOST_STATIC_ASSERT((next::size::value - 1 == type::size::value));
0178 };
0179 };
0180
0181 template<>
0182 struct try_add_unit_impl<0> {
0183 template<class Begin, class L>
0184 struct apply {
0185 typedef L type;
0186 };
0187 };
0188
0189 template<int N>
0190 struct make_homogeneous_system_impl;
0191
0192 template<class T, bool is_done>
0193 struct make_homogeneous_system_func;
0194
0195 template<class T>
0196 struct make_homogeneous_system_func<T, false> {
0197 template<class Begin, class Current, class Units, class Dimensions, int N>
0198 struct apply {
0199 typedef typename make_homogeneous_system_impl<N-1>::template apply<
0200 typename Begin::next,
0201 list<T, Current>,
0202 list<typename Begin::item, Units>,
0203 Dimensions
0204 >::type type;
0205 };
0206 };
0207
0208 template<class T>
0209 struct make_homogeneous_system_func<T, true> {
0210 template<class Begin, class Current, class Units, class Dimensions, int N>
0211 struct apply {
0212 typedef list<typename Begin::item, Units> type;
0213 };
0214 };
0215
0216 template<>
0217 struct make_homogeneous_system_func<no_solution, false> {
0218 template<class Begin, class Current, class Units, class Dimensions, int N>
0219 struct apply {
0220 typedef typename make_homogeneous_system_impl<N-1>::template apply<
0221 typename Begin::next,
0222 Current,
0223 Units,
0224 Dimensions
0225 >::type type;
0226 };
0227 };
0228
0229 template<>
0230 struct make_homogeneous_system_func<no_solution, true> {
0231 template<class Begin, class Current, class Units, class Dimensions, int N>
0232 struct apply {
0233 typedef typename make_homogeneous_system_impl<N-1>::template apply<
0234 typename Begin::next,
0235 Current,
0236 Units,
0237 Dimensions
0238 >::type type;
0239 };
0240 };
0241
0242 template<int N>
0243 struct make_homogeneous_system_impl {
0244 template<class Begin, class Current, class Units, class Dimensions>
0245 struct apply {
0246 typedef typename expand_dimensions<Dimensions::size::value>::template apply<
0247 Dimensions,
0248 typename Begin::item::dimension_type
0249 >::type dimensions;
0250 typedef typename try_add_unit_impl<Current::size::value>::template apply<Current, dimensions>::type new_element;
0251 typedef typename make_solve_list_leading_zeroes<new_element::size::value>::template apply<new_element>::type new_func;
0252 typedef typename make_homogeneous_system_func<
0253 new_func,
0254 ((Current::size::value)+1) == (Dimensions::size::value)
0255 >::template apply<Begin, Current, Units, Dimensions, N>::type type;
0256 };
0257 };
0258
0259 template<>
0260 struct make_homogeneous_system_impl<0> {
0261 template<class Begin, class Current, class Units, class Dimensions>
0262 struct apply {
0263 typedef Units type;
0264 };
0265 };
0266
0267 template<class Units>
0268 struct make_homogeneous_system {
0269 typedef typename find_base_dimensions<Units>::type base_dimensions;
0270 typedef homogeneous_system<
0271 typename insertion_sort<
0272 typename make_homogeneous_system_impl<
0273 Units::size::value
0274 >::template apply<
0275 Units,
0276 dimensionless_type,
0277 dimensionless_type,
0278 base_dimensions
0279 >::type
0280 >::type
0281 > type;
0282 };
0283
0284 template<int N>
0285 struct extract_base_units {
0286 template<class Begin, class T>
0287 struct apply {
0288 typedef list<
0289 typename Begin::item::tag_type,
0290 typename extract_base_units<N-1>::template apply<typename Begin::next, T>::type
0291 > type;
0292 };
0293 };
0294
0295 template<>
0296 struct extract_base_units<0> {
0297 template<class Begin, class T>
0298 struct apply {
0299 typedef T type;
0300 };
0301 };
0302
0303 }
0304
0305 }
0306
0307 }
0308
0309 #endif