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_DETAIL_UNSCALE_HPP_INCLUDED 12 #define BOOST_UNITS_DETAIL_UNSCALE_HPP_INCLUDED 13 14 #include <string> 15 16 #include <boost/mpl/bool.hpp> 17 #include <boost/mpl/size.hpp> 18 #include <boost/mpl/begin.hpp> 19 #include <boost/mpl/next.hpp> 20 #include <boost/mpl/deref.hpp> 21 #include <boost/mpl/plus.hpp> 22 #include <boost/mpl/times.hpp> 23 #include <boost/mpl/negate.hpp> 24 #include <boost/mpl/less.hpp> 25 26 #include <boost/units/config.hpp> 27 #include <boost/units/dimension.hpp> 28 #include <boost/units/scale.hpp> 29 #include <boost/units/static_rational.hpp> 30 #include <boost/units/units_fwd.hpp> 31 #include <boost/units/detail/one.hpp> 32 33 namespace boost { 34 35 namespace units { 36 37 template<class T> 38 struct heterogeneous_system; 39 40 template<class T, class D, class Scale> 41 struct heterogeneous_system_impl; 42 43 template<class T, class E> 44 struct heterogeneous_system_dim; 45 46 template<class S, class Scale> 47 struct scaled_base_unit; 48 49 /// removes all scaling from a unit or a base unit. 50 template<class T> 51 struct unscale 52 { 53 #ifndef BOOST_UNITS_DOXYGEN 54 typedef T type; 55 #else 56 typedef detail::unspecified type; 57 #endif 58 }; 59 60 /// INTERNAL ONLY 61 template<class S, class Scale> 62 struct unscale<scaled_base_unit<S, Scale> > 63 { 64 typedef typename unscale<S>::type type; 65 }; 66 67 /// INTERNAL ONLY 68 template<class D, class S> 69 struct unscale<unit<D, S> > 70 { 71 typedef unit<D, typename unscale<S>::type> type; 72 }; 73 74 /// INTERNAL ONLY 75 template<class Scale> 76 struct scale_list_dim; 77 78 /// INTERNAL ONLY 79 template<class T> 80 struct get_scale_list 81 { 82 typedef dimensionless_type type; 83 }; 84 85 /// INTERNAL ONLY 86 template<class S, class Scale> 87 struct get_scale_list<scaled_base_unit<S, Scale> > 88 { 89 typedef typename mpl::times<list<scale_list_dim<Scale>, dimensionless_type>, typename get_scale_list<S>::type>::type type; 90 }; 91 92 /// INTERNAL ONLY 93 template<class D, class S> 94 struct get_scale_list<unit<D, S> > 95 { 96 typedef typename get_scale_list<S>::type type; 97 }; 98 99 /// INTERNAL ONLY 100 struct scale_dim_tag {}; 101 102 /// INTERNAL ONLY 103 template<class Scale> 104 struct scale_list_dim : Scale 105 { 106 typedef scale_dim_tag tag; 107 typedef scale_list_dim type; 108 }; 109 110 } // namespace units 111 112 #ifndef BOOST_UNITS_DOXYGEN 113 114 namespace mpl { 115 116 /// INTERNAL ONLY 117 template<> 118 struct less_impl<boost::units::scale_dim_tag, boost::units::scale_dim_tag> 119 { 120 template<class T0, class T1> 121 struct apply : mpl::bool_<((T0::base) < (T1::base))> {}; 122 }; 123 124 } 125 126 #endif 127 128 namespace units { 129 130 namespace detail { 131 132 template<class Scale> 133 struct is_empty_dim<scale_list_dim<Scale> > : mpl::false_ {}; 134 135 template<long N> 136 struct is_empty_dim<scale_list_dim<scale<N, static_rational<0, 1> > > > : mpl::true_ {}; 137 138 template<int N> 139 struct eval_scale_list_impl 140 { 141 template<class Begin> 142 struct apply 143 { 144 typedef typename eval_scale_list_impl<N-1>::template apply<typename Begin::next> next_iteration; 145 typedef typename multiply_typeof_helper<typename next_iteration::type, typename Begin::item::value_type>::type type; valueboost::units::detail::eval_scale_list_impl::apply146 static BOOST_CONSTEXPR type value() 147 { 148 return(next_iteration::value() * Begin::item::value()); 149 } 150 }; 151 }; 152 153 template<> 154 struct eval_scale_list_impl<0> 155 { 156 template<class Begin> 157 struct apply 158 { 159 typedef one type; valueboost::units::detail::eval_scale_list_impl::apply160 static BOOST_CONSTEXPR one value() 161 { 162 return(one()); 163 } 164 }; 165 }; 166 167 } 168 169 /// INTERNAL ONLY 170 template<class T> 171 struct eval_scale_list : detail::eval_scale_list_impl<T::size::value>::template apply<T> {}; 172 173 } // namespace units 174 175 #ifndef BOOST_UNITS_DOXYGEN 176 177 namespace mpl { 178 179 /// INTERNAL ONLY 180 template<> 181 struct plus_impl<boost::units::scale_dim_tag, boost::units::scale_dim_tag> 182 { 183 template<class T0, class T1> 184 struct apply 185 { 186 typedef boost::units::scale_list_dim< 187 boost::units::scale< 188 (T0::base), 189 typename mpl::plus<typename T0::exponent, typename T1::exponent>::type 190 > 191 > type; 192 }; 193 }; 194 195 /// INTERNAL ONLY 196 template<> 197 struct negate_impl<boost::units::scale_dim_tag> 198 { 199 template<class T0> 200 struct apply 201 { 202 typedef boost::units::scale_list_dim< 203 boost::units::scale< 204 (T0::base), 205 typename mpl::negate<typename T0::exponent>::type 206 > 207 > type; 208 }; 209 }; 210 211 /// INTERNAL ONLY 212 template<> 213 struct times_impl<boost::units::scale_dim_tag, boost::units::detail::static_rational_tag> 214 { 215 template<class T0, class T1> 216 struct apply 217 { 218 typedef boost::units::scale_list_dim< 219 boost::units::scale< 220 (T0::base), 221 typename mpl::times<typename T0::exponent, T1>::type 222 > 223 > type; 224 }; 225 }; 226 227 /// INTERNAL ONLY 228 template<> 229 struct divides_impl<boost::units::scale_dim_tag, boost::units::detail::static_rational_tag> 230 { 231 template<class T0, class T1> 232 struct apply 233 { 234 typedef boost::units::scale_list_dim< 235 boost::units::scale< 236 (T0::base), 237 typename mpl::divides<typename T0::exponent, T1>::type 238 > 239 > type; 240 }; 241 }; 242 243 } // namespace mpl 244 245 #endif 246 247 } // namespace boost 248 249 #endif 250