summaryrefslogtreecommitdiff
path: root/boost/units/detail
diff options
context:
space:
mode:
Diffstat (limited to 'boost/units/detail')
-rw-r--r--boost/units/detail/absolute_impl.hpp104
-rw-r--r--boost/units/detail/cmath_impl.hpp154
-rw-r--r--boost/units/detail/conversion_impl.hpp458
-rw-r--r--boost/units/detail/dim_impl.hpp90
-rw-r--r--boost/units/detail/dimension_impl.hpp347
-rw-r--r--boost/units/detail/dimension_list.hpp133
-rw-r--r--boost/units/detail/dimensionless_unit.hpp88
-rw-r--r--boost/units/detail/heterogeneous_conversion.hpp309
-rw-r--r--boost/units/detail/linear_algebra.hpp1060
-rw-r--r--boost/units/detail/one.hpp109
-rw-r--r--boost/units/detail/ordinal.hpp49
-rw-r--r--boost/units/detail/prevent_redefinition.hpp54
-rw-r--r--boost/units/detail/push_front_if.hpp48
-rw-r--r--boost/units/detail/push_front_or_add.hpp84
-rw-r--r--boost/units/detail/sort.hpp109
-rw-r--r--boost/units/detail/static_rational_power.hpp206
-rw-r--r--boost/units/detail/unscale.hpp234
-rw-r--r--boost/units/detail/utility.hpp104
18 files changed, 3740 insertions, 0 deletions
diff --git a/boost/units/detail/absolute_impl.hpp b/boost/units/detail/absolute_impl.hpp
new file mode 100644
index 0000000..127b33a
--- /dev/null
+++ b/boost/units/detail/absolute_impl.hpp
@@ -0,0 +1,104 @@
+// Boost.Units - A C++ library for zero-overhead dimensional analysis and
+// unit/quantity manipulation and conversion
+//
+// Copyright (C) 2003-2008 Matthias Christian Schabel
+// Copyright (C) 2008 Steven Watanabe
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_UNITS_ABSOLUTE_IMPL_HPP
+#define BOOST_UNITS_ABSOLUTE_IMPL_HPP
+
+#include <iosfwd>
+
+#include <boost/units/config.hpp>
+#include <boost/units/conversion.hpp>
+#include <boost/units/heterogeneous_system.hpp>
+#include <boost/units/units_fwd.hpp>
+
+namespace boost {
+
+namespace units {
+
+/// INTERNAL ONLY
+template<class D, class S>
+struct reduce_unit<absolute<unit<D, S> > >
+{
+ typedef absolute<typename reduce_unit<unit<D, S> >::type> type;
+};
+
+namespace detail {
+
+struct undefined_affine_conversion_base {
+ static const bool is_defined = false;
+};
+
+} // namespace detail
+
+/// INTERNAL ONLY
+template<class From, class To>
+struct affine_conversion_helper : detail::undefined_affine_conversion_base { };
+
+namespace detail {
+
+template<bool IsDefined, bool ReverseIsDefined>
+struct affine_conversion_impl;
+
+template<bool ReverseIsDefined>
+struct affine_conversion_impl<true, ReverseIsDefined>
+{
+ template<class Unit1, class Unit2, class T0, class T1>
+ struct apply {
+ static T1 value(const T0& t0)
+ {
+ return(
+ t0 *
+ conversion_factor(Unit1(), Unit2()) +
+ affine_conversion_helper<typename reduce_unit<Unit1>::type, typename reduce_unit<Unit2>::type>::value());
+ }
+ };
+};
+
+template<>
+struct affine_conversion_impl<false, true>
+{
+ template<class Unit1, class Unit2, class T0, class T1>
+ struct apply
+ {
+ static T1 value(const T0& t0)
+ {
+ return(
+ (t0 - affine_conversion_helper<typename reduce_unit<Unit2>::type, typename reduce_unit<Unit1>::type>::value()) *
+ conversion_factor(Unit1(), Unit2()));
+ }
+ };
+};
+
+} // namespace detail
+
+/// INTERNAL ONLY
+template<class Unit1, class T1, class Unit2, class T2>
+struct conversion_helper<quantity<absolute<Unit1>, T1>, quantity<absolute<Unit2>, T2> >
+{
+ typedef quantity<absolute<Unit1>, T1> from_quantity_type;
+ typedef quantity<absolute<Unit2>, T2> to_quantity_type;
+ static to_quantity_type convert(const from_quantity_type& source)
+ {
+ return(
+ to_quantity_type::from_value(
+ detail::affine_conversion_impl<
+ affine_conversion_helper<typename reduce_unit<Unit1>::type, typename reduce_unit<Unit2>::type>::is_defined,
+ affine_conversion_helper<typename reduce_unit<Unit2>::type, typename reduce_unit<Unit1>::type>::is_defined
+ >::template apply<Unit1, Unit2, T1, T2>::value(source.value())
+ )
+ );
+ }
+};
+
+} // namespace units
+
+} // namespace boost
+
+#endif // BOOST_UNITS_ABSOLUTE_IMPL_HPP
diff --git a/boost/units/detail/cmath_impl.hpp b/boost/units/detail/cmath_impl.hpp
new file mode 100644
index 0000000..d5bec14
--- /dev/null
+++ b/boost/units/detail/cmath_impl.hpp
@@ -0,0 +1,154 @@
+// Boost.Units - A C++ library for zero-overhead dimensional analysis and
+// unit/quantity manipulation and conversion
+//
+// Copyright (C) 2003-2008 Matthias Christian Schabel
+// Copyright (C) 2008 Steven Watanabe
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_UNITS_CMATH_IMPL_HPP
+#define BOOST_UNITS_CMATH_IMPL_HPP
+
+#include <boost/config.hpp>
+#include <boost/math/special_functions/fpclassify.hpp>
+
+namespace boost {
+namespace units {
+namespace detail {
+
+template<class Y>
+inline bool isgreater BOOST_PREVENT_MACRO_SUBSTITUTION(const Y& v1,const Y& v2)
+{
+ if((boost::math::isnan)(v1) || (boost::math::isnan)(v2)) return false;
+ else return v1 > v2;
+}
+
+template<class Y>
+inline bool isgreaterequal BOOST_PREVENT_MACRO_SUBSTITUTION(const Y& v1,const Y& v2)
+{
+ if((boost::math::isnan)(v1) || (boost::math::isnan)(v2)) return false;
+ else return v1 >= v2;
+}
+
+template<class Y>
+inline bool isless BOOST_PREVENT_MACRO_SUBSTITUTION(const Y& v1,const Y& v2)
+{
+ if((boost::math::isnan)(v1) || (boost::math::isnan)(v2)) return false;
+ else return v1 < v2;
+}
+
+template<class Y>
+inline bool islessequal BOOST_PREVENT_MACRO_SUBSTITUTION(const Y& v1,const Y& v2)
+{
+ if((boost::math::isnan)(v1) || (boost::math::isnan)(v2)) return false;
+ else return v1 <= v2;
+}
+
+template<class Y>
+inline bool islessgreater BOOST_PREVENT_MACRO_SUBSTITUTION(const Y& v1,const Y& v2)
+{
+ if((boost::math::isnan)(v1) || (boost::math::isnan)(v2)) return false;
+ else return v1 < v2 || v1 > v2;
+}
+
+template<class Y>
+inline bool isunordered BOOST_PREVENT_MACRO_SUBSTITUTION(const Y& v1,const Y& v2)
+{
+ return (boost::math::isnan)(v1) || (boost::math::isnan)(v2);
+}
+
+template<class Y>
+inline Y fdim BOOST_PREVENT_MACRO_SUBSTITUTION(const Y& v1,const Y& v2)
+{
+ if((boost::math::isnan)(v1)) return v1;
+ else if((boost::math::isnan)(v2)) return v2;
+ else if(v1 > v2) return(v1 - v2);
+ else return(Y(0));
+}
+
+#if 0
+
+template<class T>
+struct fma_issue_warning {
+ enum { value = false };
+};
+
+template<class Y>
+inline Y fma(const Y& v1,const Y& v2,const Y& v3)
+{
+ //this implementation does *not* meet the
+ //requirement of infinite intermediate precision
+ BOOST_STATIC_WARNING((fma_issue_warning<Y>::value));
+
+ return v1 * v2 + v3;
+}
+
+#endif
+
+template<class Y>
+inline Y fmax BOOST_PREVENT_MACRO_SUBSTITUTION(const Y& v1,const Y& v2)
+{
+ if((boost::math::isnan)(v1)) return(v2);
+ else if((boost::math::isnan)(v2)) return(v1);
+ else if(v1 > v2) return(v1);
+ else return(v2);
+}
+
+template<class Y>
+inline Y fmin BOOST_PREVENT_MACRO_SUBSTITUTION(const Y& v1,const Y& v2)
+{
+ if((boost::math::isnan)(v1)) return(v2);
+ else if((boost::math::isnan)(v2)) return(v1);
+ else if(v1 < v2) return(v1);
+ else return(v2);
+}
+
+//template<class Y>
+//inline long long llrint(const Y& val)
+//{
+// return static_cast<long long>(rint(val));
+//}
+//
+//template<class Y>
+//inline long long llround(const Y& val)
+//{
+// return static_cast<long long>(round(val));
+//}
+
+#if 0
+
+template<class Y>
+inline Y nearbyint(const Y& val)
+{
+ //this is not really correct.
+ //the result should be according to the
+ //current rounding mode.
+ using boost::math::round;
+ return round(val);
+}
+
+template<class Y>
+inline Y rint(const Y& val)
+{
+ //I don't feel like trying to figure out
+ //how to raise a floating pointer exception
+ return nearbyint(val);
+}
+
+#endif
+
+template<class Y>
+inline Y trunc BOOST_PREVENT_MACRO_SUBSTITUTION(const Y& val)
+{
+ if(val > 0) return std::floor(val);
+ else if(val < 0) return std::ceil(val);
+ else return val;
+}
+
+}
+}
+}
+
+#endif // BOOST_UNITS_CMATH_IMPL_HPP
diff --git a/boost/units/detail/conversion_impl.hpp b/boost/units/detail/conversion_impl.hpp
new file mode 100644
index 0000000..8946faf
--- /dev/null
+++ b/boost/units/detail/conversion_impl.hpp
@@ -0,0 +1,458 @@
+// Boost.Units - A C++ library for zero-overhead dimensional analysis and
+// unit/quantity manipulation and conversion
+//
+// Copyright (C) 2003-2008 Matthias Christian Schabel
+// Copyright (C) 2007-2008 Steven Watanabe
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_UNITS_DETAIL_CONVERSION_IMPL_HPP
+#define BOOST_UNITS_DETAIL_CONVERSION_IMPL_HPP
+
+#include <boost/mpl/bool.hpp>
+#include <boost/mpl/and.hpp>
+#include <boost/mpl/divides.hpp>
+#include <boost/preprocessor/seq/enum.hpp>
+#include <boost/type_traits/is_same.hpp>
+
+#include <boost/units/heterogeneous_system.hpp>
+#include <boost/units/homogeneous_system.hpp>
+#include <boost/units/reduce_unit.hpp>
+#include <boost/units/static_rational.hpp>
+#include <boost/units/units_fwd.hpp>
+#include <boost/units/detail/dimension_list.hpp>
+#include <boost/units/detail/heterogeneous_conversion.hpp>
+#include <boost/units/detail/one.hpp>
+#include <boost/units/detail/static_rational_power.hpp>
+#include <boost/units/detail/unscale.hpp>
+
+#include <boost/units/units_fwd.hpp>
+
+namespace boost {
+
+namespace units {
+
+namespace detail {
+
+template<class Source, class Dest>
+struct conversion_factor_helper;
+
+template<class Source, class Dest>
+struct call_base_unit_converter;
+
+}
+
+/// INTERNAL ONLY
+struct undefined_base_unit_converter_base {
+ static const bool is_defined = false;
+};
+
+/// INTERNAL ONLY
+struct no_default_conversion {
+ static const bool is_defined = false;
+};
+
+/// INTERNAL ONLY
+template<class BaseUnit>
+struct unscaled_get_default_conversion : no_default_conversion { };
+
+/// INTERNAL ONLY
+template<bool is_defined>
+struct unscaled_get_default_conversion_impl;
+
+/// INTERNAL ONLY
+template<>
+struct unscaled_get_default_conversion_impl<true>
+{
+ template<class T>
+ struct apply
+ {
+ typedef typename unscaled_get_default_conversion<typename unscale<T>::type>::type type;
+ };
+};
+
+/// INTERNAL ONLY
+template<>
+struct unscaled_get_default_conversion_impl<false>
+{
+ template<class T>
+ struct apply
+ {
+ typedef typename T::unit_type type;
+ };
+};
+
+/// INTERNAL ONLY
+template<class BaseUnit>
+struct get_default_conversion
+{
+ typedef typename unscaled_get_default_conversion_impl<
+ unscaled_get_default_conversion<typename unscale<BaseUnit>::type>::is_defined
+ >::template apply<BaseUnit>::type type;
+};
+
+/// INTERNAL ONLY
+template<class Source, class Destination>
+struct select_base_unit_converter
+{
+ typedef Source source_type;
+ typedef Destination destination_type;
+};
+
+/// INTERNAL ONLY
+template<class Source, class Dest>
+struct base_unit_converter_base : undefined_base_unit_converter_base {
+};
+
+/// INTERNAL ONLY
+template<class Source>
+struct base_unit_converter_base<Source, BOOST_UNITS_MAKE_HETEROGENEOUS_UNIT(Source, typename Source::dimension_type)>
+{
+ static const bool is_defined = true;
+ typedef one type;
+ static type value() {
+ one result;
+ return(result);
+ }
+};
+
+/// INTERNAL ONLY
+template<class Source, class Dest>
+struct base_unit_converter : base_unit_converter_base<Source, Dest> { };
+
+namespace detail {
+
+template<class Source, class Dest>
+struct do_call_base_unit_converter {
+ typedef select_base_unit_converter<typename unscale<Source>::type, typename unscale<Dest>::type> selector;
+ typedef typename selector::source_type source_type;
+ typedef typename selector::destination_type destination_type;
+ typedef base_unit_converter<source_type, destination_type> converter;
+ typedef typename mpl::divides<typename get_scale_list<Source>::type, typename get_scale_list<source_type>::type>::type source_factor;
+ typedef typename mpl::divides<typename get_scale_list<Dest>::type, typename get_scale_list<destination_type>::type>::type destination_factor;
+ typedef typename mpl::divides<source_factor, destination_factor>::type factor;
+ typedef eval_scale_list<factor> eval_factor;
+ typedef typename multiply_typeof_helper<typename converter::type, typename eval_factor::type>::type type;
+ static type value()
+ {
+ return(converter::value() * eval_factor::value());
+ }
+};
+
+template<bool forward_is_defined, bool reverse_is_defined>
+struct call_base_unit_converter_base_unit_impl;
+
+template<>
+struct call_base_unit_converter_base_unit_impl<true, true>
+{
+ template<class Source, class Dest>
+ struct apply
+ : do_call_base_unit_converter<Source, typename Dest::unit_type>
+ {
+ };
+};
+
+template<>
+struct call_base_unit_converter_base_unit_impl<true, false>
+{
+ template<class Source, class Dest>
+ struct apply
+ : do_call_base_unit_converter<Source, typename Dest::unit_type>
+ {
+ };
+};
+
+template<>
+struct call_base_unit_converter_base_unit_impl<false, true>
+{
+ template<class Source, class Dest>
+ struct apply
+ {
+ typedef do_call_base_unit_converter<Dest, typename Source::unit_type> converter;
+ typedef typename divide_typeof_helper<one, typename converter::type>::type type;
+ static type value() {
+ one numerator;
+ return(numerator / converter::value());
+ }
+ };
+};
+
+template<>
+struct call_base_unit_converter_base_unit_impl<false, false>
+{
+ template<class Source, class Dest>
+ struct apply
+ {
+ typedef typename reduce_unit<typename get_default_conversion<Source>::type>::type new_source;
+ typedef typename reduce_unit<typename get_default_conversion<Dest>::type>::type new_dest;
+ typedef call_base_unit_converter<Source, new_source> start;
+ typedef detail::conversion_factor_helper<
+ new_source,
+ new_dest
+ > conversion;
+ typedef call_base_unit_converter<Dest, new_dest> end;
+ typedef typename divide_typeof_helper<
+ typename multiply_typeof_helper<
+ typename start::type,
+ typename conversion::type
+ >::type,
+ typename end::type
+ >::type type;
+ static type value() {
+ return(start::value() * conversion::value() / end::value());
+ }
+ };
+};
+
+template<int N>
+struct get_default_conversion_impl
+{
+ template<class Begin>
+ struct apply
+ {
+ typedef typename Begin::item source_pair;
+ typedef typename source_pair::value_type exponent;
+ typedef typename source_pair::tag_type source;
+ typedef typename reduce_unit<typename get_default_conversion<source>::type>::type new_source;
+ typedef typename get_default_conversion_impl<N-1>::template apply<typename Begin::next> next_iteration;
+ typedef typename multiply_typeof_helper<typename power_typeof_helper<new_source, exponent>::type, typename next_iteration::unit_type>::type unit_type;
+ typedef call_base_unit_converter<source, new_source> conversion;
+ typedef typename multiply_typeof_helper<typename conversion::type, typename next_iteration::type>::type type;
+ static type value() {
+ return(static_rational_power<exponent>(conversion::value()) * next_iteration::value());
+ }
+ };
+};
+
+template<>
+struct get_default_conversion_impl<0>
+{
+ template<class Begin>
+ struct apply
+ {
+ typedef unit<dimensionless_type, heterogeneous_system<heterogeneous_system_impl<dimensionless_type, dimensionless_type, no_scale> > > unit_type;
+ typedef one type;
+ static one value() {
+ one result;
+ return(result);
+ }
+ };
+};
+
+template<bool is_defined>
+struct call_base_unit_converter_impl;
+
+template<>
+struct call_base_unit_converter_impl<true>
+{
+ template<class Source, class Dest>
+ struct apply
+ : do_call_base_unit_converter<Source, Dest>
+ {
+ };
+};
+
+template<>
+struct call_base_unit_converter_impl<false>
+{
+ template<class Source, class Dest>
+ struct apply {
+ typedef typename reduce_unit<typename get_default_conversion<Source>::type>::type new_source;
+ typedef typename Dest::system_type::type system_list;
+ typedef typename get_default_conversion_impl<system_list::size::value>::template apply<system_list> impl;
+ typedef typename impl::unit_type new_dest;
+ typedef call_base_unit_converter<Source, new_source> start;
+ typedef conversion_factor_helper<new_source, new_dest> conversion;
+ typedef typename divide_typeof_helper<
+ typename multiply_typeof_helper<
+ typename start::type,
+ typename conversion::type
+ >::type,
+ typename impl::type
+ >::type type;
+ static type value() {
+ return(start::value() * conversion::value() / impl::value());
+ }
+ };
+};
+
+#define BOOST_UNITS_DETAIL_BASE_UNIT_CONVERTER_IS_DEFINED(Source, Dest)\
+ base_unit_converter<\
+ typename select_base_unit_converter<typename unscale<Source>::type, typename unscale<Dest>::type>::source_type,\
+ typename select_base_unit_converter<typename unscale<Source>::type, typename unscale<Dest>::type>::destination_type\
+ >::is_defined
+
+template<class Source, class Dest>
+struct call_base_unit_converter : call_base_unit_converter_impl<BOOST_UNITS_DETAIL_BASE_UNIT_CONVERTER_IS_DEFINED(Source, Dest)>::template apply<Source, Dest>
+{
+};
+
+template<class Source, class Dest>
+struct call_base_unit_converter<Source, BOOST_UNITS_MAKE_HETEROGENEOUS_UNIT(Dest, typename Source::dimension_type)> :
+ call_base_unit_converter_base_unit_impl<
+ BOOST_UNITS_DETAIL_BASE_UNIT_CONVERTER_IS_DEFINED(Source, typename Dest::unit_type),
+ BOOST_UNITS_DETAIL_BASE_UNIT_CONVERTER_IS_DEFINED(Dest, typename Source::unit_type)
+ >::template apply<Source, Dest>
+{
+};
+
+template<int N>
+struct conversion_impl
+{
+ template<class Begin, class DestinationSystem>
+ struct apply
+ {
+ typedef typename conversion_impl<N-1>::template apply<
+ typename Begin::next,
+ DestinationSystem
+ > next_iteration;
+ typedef typename Begin::item unit_pair;
+ typedef typename unit_pair::tag_type unit;
+ typedef typename unit::dimension_type dimensions;
+ typedef typename reduce_unit<units::unit<dimensions, DestinationSystem> >::type reduced_unit;
+ typedef detail::call_base_unit_converter<unit, reduced_unit> converter;
+ typedef typename multiply_typeof_helper<typename converter::type, typename next_iteration::type>::type type;
+ static type value() { return(static_rational_power<typename unit_pair::value_type>(converter::value()) * next_iteration::value()); }
+ };
+};
+
+template<>
+struct conversion_impl<0>
+{
+ template<class Begin, class DestinationSystem>
+ struct apply
+ {
+ typedef one type;
+ static type value() { one result; return(result); }
+ };
+};
+
+} // namespace detail
+
+/// forward to conversion_factor (intentionally allowing ADL)
+/// INTERNAL ONLY
+template<class Unit1, class T1, class Unit2, class T2>
+struct conversion_helper<quantity<Unit1, T1>, quantity<Unit2, T2> >
+{
+ /// INTERNAL ONLY
+ typedef quantity<Unit2, T2> destination_type;
+ static destination_type convert(const quantity<Unit1, T1>& source)
+ {
+ Unit1 u1;
+ Unit2 u2;
+ return(destination_type::from_value(static_cast<T2>(source.value() * conversion_factor(u1, u2))));
+ }
+};
+
+namespace detail {
+
+template<class Source, class Dest>
+struct conversion_factor_helper;
+
+template<class D, class L1, class L2>
+struct conversion_factor_helper<unit<D, homogeneous_system<L1> >, unit<D, homogeneous_system<L2> > >
+ : conversion_factor_helper<
+ typename reduce_unit<unit<D, homogeneous_system<L1> > >::type,
+ typename reduce_unit<unit<D, homogeneous_system<L2> > >::type
+ >
+{
+ //typedef typename reduce_unit<unit<D, homogeneous_system<L1> > >::type source_unit;
+ //typedef typename source_unit::system_type::type unit_list;
+ //typedef typename detail::conversion_impl<unit_list::size::value>::template apply<
+ // unit_list,
+ // homogeneous_system<L2>
+ //> impl;
+ //typedef typename impl::type type;
+ //static type value()
+ //{
+ // return(impl::value());
+ //}
+};
+
+template<class D, class L1, class L2>
+struct conversion_factor_helper<unit<D, heterogeneous_system<L1> >, unit<D, homogeneous_system<L2> > >
+ : conversion_factor_helper<
+ typename reduce_unit<unit<D, heterogeneous_system<L1> > >::type,
+ typename reduce_unit<unit<D, homogeneous_system<L2> > >::type
+ >
+{
+ //typedef typename detail::conversion_impl<L1::type::size::value>::template apply<
+ // typename L1::type,
+ // homogeneous_system<L2>
+ //> impl;
+ //typedef eval_scale_list<typename L1::scale> scale;
+ //typedef typename multiply_typeof_helper<typename impl::type, typename scale::type>::type type;
+ //static type value()
+ //{
+ // return(impl::value() * scale::value());
+ //}
+};
+
+// There is no simple algorithm for doing this conversion
+// other than just defining it as the reverse of the
+// heterogeneous->homogeneous case
+template<class D, class L1, class L2>
+struct conversion_factor_helper<unit<D, homogeneous_system<L1> >, unit<D, heterogeneous_system<L2> > >
+ : conversion_factor_helper<
+ typename reduce_unit<unit<D, homogeneous_system<L1> > >::type,
+ typename reduce_unit<unit<D, heterogeneous_system<L2> > >::type
+ >
+{
+ //typedef typename detail::conversion_impl<L2::type::size::value>::template apply<
+ // typename L2::type,
+ // homogeneous_system<L1>
+ //> impl;
+ //typedef eval_scale_list<typename L2::scale> scale;
+ //typedef typename multiply_typeof_helper<typename impl::type, typename scale::type>::type type;
+ //static type value()
+ //{
+ // one numerator;
+ // return(numerator / (impl::value() * scale::value()));
+ //}
+};
+
+/// Requires that all possible conversions
+/// between base units are defined.
+template<class D, class S1, class S2>
+struct conversion_factor_helper<unit<D, heterogeneous_system<S1> >, unit<D, heterogeneous_system<S2> > >
+{
+ /// INTERNAL ONLY
+ typedef typename detail::extract_base_units<S1::type::size::value>::template apply<
+ typename S1::type,
+ dimensionless_type
+ >::type from_base_units;
+ /// INTERNAL ONLY
+ typedef typename detail::extract_base_units<S2::type::size::value>::template apply<
+ typename S2::type,
+ from_base_units
+ >::type all_base_units;
+ /// INTERNAL ONLY
+ typedef typename detail::make_homogeneous_system<all_base_units>::type system;
+ typedef typename detail::conversion_impl<S1::type::size::value>::template apply<
+ typename S1::type,
+ system
+ > conversion1;
+ typedef typename detail::conversion_impl<S2::type::size::value>::template apply<
+ typename S2::type,
+ system
+ > conversion2;
+ typedef eval_scale_list<typename mpl::divides<typename S1::scale, typename S2::scale>::type> scale;
+ typedef typename multiply_typeof_helper<
+ typename conversion1::type,
+ typename divide_typeof_helper<typename scale::type, typename conversion2::type>::type
+ >::type type;
+ static type value()
+ {
+ return(conversion1::value() * (scale::value() / conversion2::value()));
+ }
+};
+
+} // namespace detail
+
+} // namespace units
+
+} // namespace boost
+
+#endif // BOOST_UNITS_CONVERSION_IMPL_HPP
diff --git a/boost/units/detail/dim_impl.hpp b/boost/units/detail/dim_impl.hpp
new file mode 100644
index 0000000..85792b8
--- /dev/null
+++ b/boost/units/detail/dim_impl.hpp
@@ -0,0 +1,90 @@
+// Boost.Units - A C++ library for zero-overhead dimensional analysis and
+// unit/quantity manipulation and conversion
+//
+// Copyright (C) 2003-2008 Matthias Christian Schabel
+// Copyright (C) 2008 Steven Watanabe
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_UNITS_DIM_IMPL_HPP
+#define BOOST_UNITS_DIM_IMPL_HPP
+
+#include <boost/mpl/bool.hpp>
+#include <boost/mpl/less.hpp>
+
+#include <boost/units/units_fwd.hpp>
+
+/// \file
+/// \brief Class encapsulating a dimension tag/value pair
+
+namespace boost {
+
+namespace units {
+
+namespace detail {
+
+struct dim_tag;
+
+}
+
+}
+
+namespace mpl {
+
+/// Less than comparison for sorting @c dim.
+template<>
+struct less_impl<boost::units::detail::dim_tag, boost::units::detail::dim_tag>
+{
+ template<class T0, class T1>
+ struct apply : mpl::less<typename T0::tag_type, typename T1::tag_type> {};
+};
+
+}
+
+namespace units {
+
+template<class Tag, class Exponent>
+struct dim;
+
+template<long N, long D>
+class static_rational;
+
+namespace detail {
+
+/// Extract @c tag_type from a @c dim.
+template<typename T>
+struct get_tag
+{
+ typedef typename T::tag_type type;
+};
+
+/// Extract @c value_type from a @c dim.
+template<typename T>
+struct get_value
+{
+ typedef typename T::value_type type;
+};
+
+/// Determine if a @c dim is empty (has a zero exponent).
+template<class T>
+struct is_empty_dim;
+
+template<typename T>
+struct is_empty_dim< dim<T, static_rational<0, 1> > > :
+ mpl::true_
+{ };
+
+template<typename T, typename V>
+struct is_empty_dim< dim<T, V> > :
+ mpl::false_
+{ };
+
+} // namespace detail
+
+} // namespace units
+
+} // namespace boost
+
+#endif // BOOST_UNITS_DIM_IMPL_HPP
diff --git a/boost/units/detail/dimension_impl.hpp b/boost/units/detail/dimension_impl.hpp
new file mode 100644
index 0000000..dbe77af
--- /dev/null
+++ b/boost/units/detail/dimension_impl.hpp
@@ -0,0 +1,347 @@
+// Boost.Units - A C++ library for zero-overhead dimensional analysis and
+// unit/quantity manipulation and conversion
+//
+// Copyright (C) 2003-2008 Matthias Christian Schabel
+// Copyright (C) 2008 Steven Watanabe
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_UNITS_DIMENSION_IMPL_HPP
+#define BOOST_UNITS_DIMENSION_IMPL_HPP
+
+#include <boost/mpl/begin_end.hpp>
+#include <boost/mpl/deref.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/list.hpp>
+#include <boost/mpl/next.hpp>
+#include <boost/mpl/size.hpp>
+#include <boost/mpl/less.hpp>
+
+#include <boost/units/config.hpp>
+#include <boost/units/dimensionless_type.hpp>
+#include <boost/units/static_rational.hpp>
+#include <boost/units/units_fwd.hpp>
+#include <boost/units/detail/dimension_list.hpp>
+#include <boost/units/detail/push_front_if.hpp>
+#include <boost/units/detail/push_front_or_add.hpp>
+
+/// \file
+/// \brief Core class and metaprogramming utilities for compile-time dimensional analysis.
+
+namespace boost {
+
+namespace units {
+
+namespace detail {
+
+template<int N>
+struct insertion_sort_dims_insert;
+
+template<bool is_greater>
+struct insertion_sort_dims_comparison_impl;
+
+// have to recursively add the element to the next sequence.
+template<>
+struct insertion_sort_dims_comparison_impl<true> {
+ template<class Begin, int N, class T>
+ struct apply {
+ typedef list<
+ typename Begin::item,
+ typename insertion_sort_dims_insert<N - 1>::template apply<
+ typename Begin::next,
+ T
+ >::type
+ > type;
+ };
+};
+
+// either prepend the current element or join it to
+// the first remaining element of the sequence.
+template<>
+struct insertion_sort_dims_comparison_impl<false> {
+ template<class Begin, int N, class T>
+ struct apply {
+ typedef typename push_front_or_add<Begin, T>::type type;
+ };
+};
+
+template<int N>
+struct insertion_sort_dims_insert {
+ template<class Begin, class T>
+ struct apply {
+ typedef typename insertion_sort_dims_comparison_impl<mpl::less<typename Begin::item, T>::value>::template apply<
+ Begin,
+ N,
+ T
+ >::type type;
+ };
+};
+
+template<>
+struct insertion_sort_dims_insert<0> {
+ template<class Begin, class T>
+ struct apply {
+ typedef list<T, dimensionless_type> type;
+ };
+};
+
+template<int N>
+struct insertion_sort_dims_mpl_sequence {
+ template<class Begin>
+ struct apply {
+ typedef typename insertion_sort_dims_mpl_sequence<N - 1>::template apply<typename mpl::next<Begin>::type>::type next;
+ typedef typename insertion_sort_dims_insert<(next::size::value)>::template apply<next, typename mpl::deref<Begin>::type>::type type;
+ };
+};
+
+template<>
+struct insertion_sort_dims_mpl_sequence<0> {
+ template<class Begin>
+ struct apply {
+ typedef dimensionless_type type;
+ };
+};
+
+template<int N>
+struct insertion_sort_dims_impl {
+ template<class Begin>
+ struct apply {
+ typedef typename insertion_sort_dims_impl<N - 1>::template apply<typename Begin::next>::type next;
+ typedef typename insertion_sort_dims_insert<(next::size::value)>::template apply<next, typename Begin::item>::type type;
+ };
+};
+
+template<>
+struct insertion_sort_dims_impl<0> {
+ template<class Begin>
+ struct apply {
+ typedef dimensionless_type type;
+ };
+};
+
+template<class T>
+struct sort_dims
+{
+ typedef typename insertion_sort_dims_mpl_sequence<mpl::size<T>::value>::template apply<typename mpl::begin<T>::type>::type type;
+};
+
+
+template<class T, class Next>
+struct sort_dims<list<T, Next> >
+{
+ typedef typename insertion_sort_dims_impl<list<T, Next>::size::value>::template apply<list<T, Next> >::type type;
+};
+
+/// sorted sequences can be merged in linear time
+template<bool less, bool greater>
+struct merge_dimensions_func;
+
+template<int N1, int N2>
+struct merge_dimensions_impl;
+
+template<>
+struct merge_dimensions_func<true, false>
+{
+ template<typename Begin1, typename Begin2, int N1, int N2>
+ struct apply
+ {
+ typedef list<
+ typename Begin1::item,
+ typename merge_dimensions_impl<N1 - 1, N2>::template apply<
+ typename Begin1::next,
+ Begin2
+ >::type
+ > type;
+ };
+};
+
+template<>
+struct merge_dimensions_func<false, true> {
+ template<typename Begin1, typename Begin2, int N1, int N2>
+ struct apply
+ {
+ typedef list<
+ typename Begin2::item,
+ typename merge_dimensions_impl<N2 - 1, N1>::template apply<
+ typename Begin2::next,
+ Begin1
+ >::type
+ > type;
+ };
+};
+
+template<>
+struct merge_dimensions_func<false, false> {
+ template<typename Begin1, typename Begin2, int N1, int N2>
+ struct apply
+ {
+ typedef typename mpl::plus<typename Begin1::item, typename Begin2::item>::type combined;
+ typedef typename push_front_if<!is_empty_dim<combined>::value>::template apply<
+ typename merge_dimensions_impl<N1 - 1, N2 - 1>::template apply<
+ typename Begin1::next,
+ typename Begin2::next
+ >::type,
+ combined
+ >::type type;
+ };
+};
+
+template<int N1, int N2>
+struct merge_dimensions_impl {
+ template<typename Begin1, typename Begin2>
+ struct apply
+ {
+ typedef typename Begin1::item dim1;
+ typedef typename Begin2::item dim2;
+
+ typedef typename merge_dimensions_func<(mpl::less<dim1,dim2>::value == true),
+ (mpl::less<dim2,dim1>::value == true)>::template apply<
+ Begin1,
+ Begin2,
+ N1,
+ N2
+ >::type type;
+ };
+};
+
+template<typename Sequence1, typename Sequence2>
+struct merge_dimensions
+{
+ typedef typename detail::merge_dimensions_impl<Sequence1::size::value,
+ Sequence2::size::value>::template
+ apply<
+ Sequence1,
+ Sequence2
+ >::type type;
+};
+
+template<int N>
+struct iterator_to_list
+{
+ template<typename Begin>
+ struct apply
+ {
+ typedef list<
+ typename Begin::item,
+ typename iterator_to_list<N - 1>::template apply<
+ typename Begin::next
+ >::type
+ > type;
+ };
+};
+
+template<>
+struct iterator_to_list<0>
+{
+ template<typename Begin>
+ struct apply {
+ typedef dimensionless_type type;
+ };
+};
+
+template<int N>
+struct merge_dimensions_impl<N, 0>
+{
+ template<typename Begin1, typename Begin2>
+ struct apply
+ {
+ typedef typename iterator_to_list<N>::template apply<Begin1>::type type;
+ };
+};
+
+template<int N>
+struct merge_dimensions_impl<0, N>
+{
+ template<typename Begin1, typename Begin2>
+ struct apply
+ {
+ typedef typename iterator_to_list<N>::template apply<Begin2>::type type;
+ };
+};
+
+template<>
+struct merge_dimensions_impl<0, 0>
+{
+ template<typename Begin1, typename Begin2>
+ struct apply
+ {
+ typedef dimensionless_type type;
+ };
+};
+
+template<int N>
+struct static_inverse_impl
+{
+ template<typename Begin>
+ struct apply {
+ typedef list<
+ typename mpl::negate<typename Begin::item>::type,
+ typename static_inverse_impl<N - 1>::template apply<
+ typename Begin::next
+ >::type
+ > type;
+ };
+};
+
+template<>
+struct static_inverse_impl<0>
+{
+ template<typename Begin>
+ struct apply
+ {
+ typedef dimensionless_type type;
+ };
+};
+
+template<int N>
+struct static_power_impl
+{
+ template<typename Begin, typename Ex>
+ struct apply
+ {
+ typedef list<
+ typename mpl::times<typename Begin::item, Ex>::type,
+ typename detail::static_power_impl<N - 1>::template apply<typename Begin::next, Ex>::type
+ > type;
+ };
+};
+
+template<>
+struct static_power_impl<0>
+{
+ template<typename Begin, typename Ex>
+ struct apply
+ {
+ typedef dimensionless_type type;
+ };
+};
+
+template<int N>
+struct static_root_impl {
+ template<class Begin, class Ex>
+ struct apply {
+ typedef list<
+ typename mpl::divides<typename Begin::item, Ex>::type,
+ typename detail::static_root_impl<N - 1>::template apply<typename Begin::next, Ex>::type
+ > type;
+ };
+};
+
+template<>
+struct static_root_impl<0> {
+ template<class Begin, class Ex>
+ struct apply
+ {
+ typedef dimensionless_type type;
+ };
+};
+
+} // namespace detail
+
+} // namespace units
+
+} // namespace boost
+
+#endif // BOOST_UNITS_DIMENSION_IMPL_HPP
diff --git a/boost/units/detail/dimension_list.hpp b/boost/units/detail/dimension_list.hpp
new file mode 100644
index 0000000..fc05547
--- /dev/null
+++ b/boost/units/detail/dimension_list.hpp
@@ -0,0 +1,133 @@
+// Boost.Units - A C++ library for zero-overhead dimensional analysis and
+// unit/quantity manipulation and conversion
+//
+// Copyright (C) 2003-2008 Matthias Christian Schabel
+// Copyright (C) 2008 Steven Watanabe
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_UNITS_DIMENSION_LIST_HPP
+#define BOOST_UNITS_DIMENSION_LIST_HPP
+
+#include <boost/mpl/next.hpp>
+#include <boost/mpl/deref.hpp>
+#include <boost/mpl/push_front_fwd.hpp>
+#include <boost/mpl/pop_front_fwd.hpp>
+#include <boost/mpl/size_fwd.hpp>
+#include <boost/mpl/begin_end_fwd.hpp>
+#include <boost/mpl/front_fwd.hpp>
+
+#include <boost/units/config.hpp>
+
+namespace boost {
+
+namespace units {
+
+struct dimensionless_type;
+
+namespace detail {
+
+struct dimension_list_tag { };
+
+} // namespace detail
+
+template<class Item, class Next>
+struct list
+{
+ typedef detail::dimension_list_tag tag;
+ typedef list type;
+ typedef Item item;
+ typedef Next next;
+ typedef typename mpl::next<typename Next::size>::type size;
+};
+
+} // namespace units
+
+namespace mpl {
+
+// INTERNAL ONLY
+template<>
+struct size_impl<units::detail::dimension_list_tag>
+{
+ template<class L> struct apply : public L::size { };
+};
+
+// INTERNAL ONLY
+template<>
+struct begin_impl<units::detail::dimension_list_tag>
+{
+ template<class L>
+ struct apply
+ {
+ typedef L type;
+ };
+};
+
+// INTERNAL ONLY
+template<>
+struct end_impl<units::detail::dimension_list_tag>
+{
+ template<class L>
+ struct apply
+ {
+ typedef units::dimensionless_type type;
+ };
+};
+
+// INTERNAL ONLY
+template<>
+struct push_front_impl<units::detail::dimension_list_tag>
+{
+ template<class L, class T>
+ struct apply
+ {
+ typedef units::list<T, L> type;
+ };
+};
+
+// INTERNAL ONLY
+template<>
+struct pop_front_impl<units::detail::dimension_list_tag>
+{
+ template<class L>
+ struct apply
+ {
+ typedef typename L::next type;
+ };
+};
+
+// INTERNAL ONLY
+template<>
+struct front_impl<units::detail::dimension_list_tag>
+{
+ template<class L>
+ struct apply
+ {
+ typedef typename L::item type;
+ };
+};
+
+// INTERNAL ONLY
+template<class Item, class Next>
+struct deref<units::list<Item, Next> >
+{
+ typedef Item type;
+};
+
+} // namespace mpl
+
+} // namespace boost
+
+#if BOOST_UNITS_HAS_BOOST_TYPEOF
+
+#include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()
+
+BOOST_TYPEOF_REGISTER_TEMPLATE(boost::units::list, 2)
+
+#endif
+
+#include <boost/units/dimensionless_type.hpp>
+
+#endif // BOOST_UNITS_DIMENSION_LIST_HPP
diff --git a/boost/units/detail/dimensionless_unit.hpp b/boost/units/detail/dimensionless_unit.hpp
new file mode 100644
index 0000000..291bec4
--- /dev/null
+++ b/boost/units/detail/dimensionless_unit.hpp
@@ -0,0 +1,88 @@
+// Boost.Units - A C++ library for zero-overhead dimensional analysis and
+// unit/quantity manipulation and conversion
+//
+// Copyright (C) 2003-2008 Matthias Christian Schabel
+// Copyright (C) 2007-2008 Steven Watanabe
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_UNITS_DETAIL_DIMENSIONLESS_UNIT_HPP
+#define BOOST_UNITS_DETAIL_DIMENSIONLESS_UNIT_HPP
+
+#include <boost/mpl/bool.hpp>
+#include <boost/units/units_fwd.hpp>
+
+namespace boost {
+namespace units {
+
+template<class T>
+struct heterogeneous_system;
+
+template<class T>
+struct homogeneous_system;
+
+template<class T1, class T2, class Scale>
+struct heterogeneous_system_impl;
+
+typedef boost::units::heterogeneous_system<
+ boost::units::heterogeneous_system_impl<
+ boost::units::dimensionless_type,
+ boost::units::dimensionless_type,
+ boost::units::dimensionless_type
+ >
+> heterogeneous_dimensionless_system;
+
+namespace detail {
+
+template<class System>
+struct void_if_dimensionless {
+ typedef int type;
+};
+
+template<class T>
+struct void_if_dimensionless<boost::units::homogeneous_system<T> > {
+ typedef void type;
+};
+
+template<>
+struct void_if_dimensionless<heterogeneous_dimensionless_system> {
+ typedef void type;
+};
+
+template<class System, class Test = void>
+struct void_if_heterogeneous {
+ typedef void type;
+};
+
+template<class System>
+struct void_if_heterogeneous<System, typename void_if_dimensionless<System>::type> {
+ typedef int type;
+};
+
+template<class System, class Enable=void>
+struct is_dimensionless_system : mpl::false_ {};
+
+template<class System>
+struct is_dimensionless_system<System, typename void_if_dimensionless<System>::type> : mpl::true_ {};
+
+#define BOOST_UNITS_DIMENSIONLESS_UNIT(T)\
+ boost::units::unit<\
+ boost::units::dimensionless_type,\
+ T,\
+ typename ::boost::units::detail::void_if_dimensionless<T>::type\
+ >
+
+#define BOOST_UNITS_HETEROGENEOUS_DIMENSIONLESS_UNIT(T)\
+ boost::units::unit<\
+ boost::units::dimensionless_type,\
+ T,\
+ typename ::boost::units::detail::void_if_heterogeneous<T>::type\
+ >
+
+}
+}
+}
+
+#endif
diff --git a/boost/units/detail/heterogeneous_conversion.hpp b/boost/units/detail/heterogeneous_conversion.hpp
new file mode 100644
index 0000000..bfdf987
--- /dev/null
+++ b/boost/units/detail/heterogeneous_conversion.hpp
@@ -0,0 +1,309 @@
+// Boost.Units - A C++ library for zero-overhead dimensional analysis and
+// unit/quantity manipulation and conversion
+//
+// Copyright (C) 2003-2008 Matthias Christian Schabel
+// Copyright (C) 2008 Steven Watanabe
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_UNITS_DETAIL_HETEROGENEOUS_CONVERSION_HPP
+#define BOOST_UNITS_DETAIL_HETEROGENEOUS_CONVERSION_HPP
+
+#include <boost/mpl/minus.hpp>
+#include <boost/mpl/times.hpp>
+
+#include <boost/units/static_rational.hpp>
+#include <boost/units/homogeneous_system.hpp>
+#include <boost/units/detail/linear_algebra.hpp>
+
+namespace boost {
+
+namespace units {
+
+namespace detail {
+
+struct solve_end {
+ template<class Begin, class Y>
+ struct apply {
+ typedef dimensionless_type type;
+ };
+};
+
+struct no_solution {};
+
+template<class X1, class X2, class Next>
+struct solve_normal {
+ template<class Begin, class Y>
+ struct apply {
+ typedef typename Begin::next next;
+ typedef list<
+ typename mpl::minus<
+ typename mpl::times<X1, Y>::type,
+ typename mpl::times<X2, typename Begin::item>::type
+ >::type,
+ typename Next::template apply<next, Y>::type
+ > type;
+ };
+};
+
+template<class Next>
+struct solve_leading_zeroes {
+ template<class Begin>
+ struct apply {
+ typedef list<
+ typename Begin::item,
+ typename Next::template apply<typename Begin::next>::type
+ > type;
+ };
+ typedef solve_leading_zeroes type;
+};
+
+template<>
+struct solve_leading_zeroes<no_solution> {
+ typedef no_solution type;
+};
+
+template<class Next>
+struct solve_first_non_zero {
+ template<class Begin>
+ struct apply {
+ typedef typename Next::template apply<
+ typename Begin::next,
+ typename Begin::item
+ >::type type;
+ };
+};
+
+template<class Next>
+struct solve_internal_zero {
+ template<class Begin, class Y>
+ struct apply {
+ typedef list<
+ typename Begin::item,
+ typename Next::template apply<typename Begin::next, Y>::type
+ > type;
+ };
+};
+
+template<class T>
+struct make_solve_list_internal_zero {
+ template<class Next, class X>
+ struct apply {
+ typedef solve_normal<T, X, Next> type;
+ };
+};
+
+template<>
+struct make_solve_list_internal_zero<static_rational<0> > {
+ template<class Next, class X>
+ struct apply {
+ typedef solve_internal_zero<Next> type;
+ };
+};
+
+template<int N>
+struct make_solve_list_normal {
+ template<class Begin, class X>
+ struct apply {
+ typedef typename make_solve_list_internal_zero<
+ typename Begin::item
+ >::template apply<
+ typename make_solve_list_normal<N-1>::template apply<typename Begin::next, X>::type,
+ X
+ >::type type;
+ };
+};
+
+template<>
+struct make_solve_list_normal<0> {
+ template<class Begin, class X>
+ struct apply {
+ typedef solve_end type;
+ };
+};
+
+template<int N>
+struct make_solve_list_leading_zeroes;
+
+template<class T>
+struct make_solve_list_first_non_zero {
+ template<class Begin, int N>
+ struct apply {
+ typedef solve_first_non_zero<
+ typename make_solve_list_normal<N-1>::template apply<
+ typename Begin::next,
+ typename Begin::item
+ >::type
+ > type;
+ };
+};
+
+template<>
+struct make_solve_list_first_non_zero<static_rational<0> > {
+ template<class Begin, int N>
+ struct apply {
+ typedef typename solve_leading_zeroes<
+ typename make_solve_list_leading_zeroes<N-1>::template apply<
+ typename Begin::next
+ >::type
+ >::type type;
+ };
+};
+
+template<int N>
+struct make_solve_list_leading_zeroes {
+ template<class Begin>
+ struct apply {
+ typedef typename make_solve_list_first_non_zero<typename Begin::item>::template apply<Begin, N>::type type;
+ };
+};
+
+template<>
+struct make_solve_list_leading_zeroes<0> {
+ template<class Begin>
+ struct apply {
+ typedef no_solution type;
+ };
+};
+
+template<int N>
+struct try_add_unit_impl {
+ template<class Begin, class L>
+ struct apply {
+ typedef typename try_add_unit_impl<N-1>::template apply<typename Begin::next, L>::type next;
+ typedef typename Begin::item::template apply<next>::type type;
+ BOOST_STATIC_ASSERT((next::size::value - 1 == type::size::value));
+ };
+};
+
+template<>
+struct try_add_unit_impl<0> {
+ template<class Begin, class L>
+ struct apply {
+ typedef L type;
+ };
+};
+
+template<int N>
+struct make_homogeneous_system_impl;
+
+template<class T, bool is_done>
+struct make_homogeneous_system_func;
+
+template<class T>
+struct make_homogeneous_system_func<T, false> {
+ template<class Begin, class Current, class Units, class Dimensions, int N>
+ struct apply {
+ typedef typename make_homogeneous_system_impl<N-1>::template apply<
+ typename Begin::next,
+ list<T, Current>,
+ list<typename Begin::item, Units>,
+ Dimensions
+ >::type type;
+ };
+};
+
+template<class T>
+struct make_homogeneous_system_func<T, true> {
+ template<class Begin, class Current, class Units, class Dimensions, int N>
+ struct apply {
+ typedef list<typename Begin::item, Units> type;
+ };
+};
+
+template<>
+struct make_homogeneous_system_func<no_solution, false> {
+ template<class Begin, class Current, class Units, class Dimensions, int N>
+ struct apply {
+ typedef typename make_homogeneous_system_impl<N-1>::template apply<
+ typename Begin::next,
+ Current,
+ Units,
+ Dimensions
+ >::type type;
+ };
+};
+
+template<>
+struct make_homogeneous_system_func<no_solution, true> {
+ template<class Begin, class Current, class Units, class Dimensions, int N>
+ struct apply {
+ typedef typename make_homogeneous_system_impl<N-1>::template apply<
+ typename Begin::next,
+ Current,
+ Units,
+ Dimensions
+ >::type type;
+ };
+};
+
+template<int N>
+struct make_homogeneous_system_impl {
+ template<class Begin, class Current, class Units, class Dimensions>
+ struct apply {
+ typedef typename expand_dimensions<Dimensions::size::value>::template apply<
+ Dimensions,
+ typename Begin::item::dimension_type
+ >::type dimensions;
+ typedef typename try_add_unit_impl<Current::size::value>::template apply<Current, dimensions>::type new_element;
+ typedef typename make_solve_list_leading_zeroes<new_element::size::value>::template apply<new_element>::type new_func;
+ typedef typename make_homogeneous_system_func<
+ new_func,
+ ((Current::size::value)+1) == (Dimensions::size::value)
+ >::template apply<Begin, Current, Units, Dimensions, N>::type type;
+ };
+};
+
+template<>
+struct make_homogeneous_system_impl<0> {
+ template<class Begin, class Current, class Units, class Dimensions>
+ struct apply {
+ typedef Units type;
+ };
+};
+
+template<class Units>
+struct make_homogeneous_system {
+ typedef typename find_base_dimensions<Units>::type base_dimensions;
+ typedef homogeneous_system<
+ typename insertion_sort<
+ typename make_homogeneous_system_impl<
+ Units::size::value
+ >::template apply<
+ Units,
+ dimensionless_type,
+ dimensionless_type,
+ base_dimensions
+ >::type
+ >::type
+ > type;
+};
+
+template<int N>
+struct extract_base_units {
+ template<class Begin, class T>
+ struct apply {
+ typedef list<
+ typename Begin::item::tag_type,
+ typename extract_base_units<N-1>::template apply<typename Begin::next, T>::type
+ > type;
+ };
+};
+
+template<>
+struct extract_base_units<0> {
+ template<class Begin, class T>
+ struct apply {
+ typedef T type;
+ };
+};
+
+}
+
+}
+
+}
+
+#endif
diff --git a/boost/units/detail/linear_algebra.hpp b/boost/units/detail/linear_algebra.hpp
new file mode 100644
index 0000000..20964a9
--- /dev/null
+++ b/boost/units/detail/linear_algebra.hpp
@@ -0,0 +1,1060 @@
+// Boost.Units - A C++ library for zero-overhead dimensional analysis and
+// unit/quantity manipulation and conversion
+//
+// Copyright (C) 2003-2008 Matthias Christian Schabel
+// Copyright (C) 2008 Steven Watanabe
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_UNITS_DETAIL_LINEAR_ALGEBRA_HPP
+#define BOOST_UNITS_DETAIL_LINEAR_ALGEBRA_HPP
+
+#include <boost/units/static_rational.hpp>
+#include <boost/mpl/next.hpp>
+#include <boost/mpl/arithmetic.hpp>
+#include <boost/mpl/and.hpp>
+#include <boost/mpl/assert.hpp>
+
+#include <boost/units/dim.hpp>
+#include <boost/units/dimensionless_type.hpp>
+#include <boost/units/static_rational.hpp>
+#include <boost/units/detail/dimension_list.hpp>
+#include <boost/units/detail/sort.hpp>
+
+namespace boost {
+
+namespace units {
+
+namespace detail {
+
+// typedef list<rational> equation;
+
+template<int N>
+struct eliminate_from_pair_of_equations_impl;
+
+template<class E1, class E2>
+struct eliminate_from_pair_of_equations;
+
+template<int N>
+struct elimination_impl;
+
+template<bool is_zero, bool element_is_last>
+struct elimination_skip_leading_zeros_impl;
+
+template<class Equation, class Vars>
+struct substitute;
+
+template<int N>
+struct substitute_impl;
+
+template<bool is_end>
+struct solve_impl;
+
+template<class T>
+struct solve;
+
+template<int N>
+struct check_extra_equations_impl;
+
+template<int N>
+struct normalize_units_impl;
+
+struct inconsistent {};
+
+// generally useful utilies.
+
+template<int N>
+struct divide_equation {
+ template<class Begin, class Divisor>
+ struct apply {
+ typedef list<typename mpl::divides<typename Begin::item, Divisor>::type, typename divide_equation<N - 1>::template apply<typename Begin::next, Divisor>::type> type;
+ };
+};
+
+template<>
+struct divide_equation<0> {
+ template<class Begin, class Divisor>
+ struct apply {
+ typedef dimensionless_type type;
+ };
+};
+
+// eliminate_from_pair_of_equations takes a pair of
+// equations and eliminates the first variable.
+//
+// equation eliminate_from_pair_of_equations(equation l1, equation l2) {
+// rational x1 = l1.front();
+// rational x2 = l2.front();
+// return(transform(pop_front(l1), pop_front(l2), _1 * x2 - _2 * x1));
+// }
+
+template<int N>
+struct eliminate_from_pair_of_equations_impl {
+ template<class Begin1, class Begin2, class X1, class X2>
+ struct apply {
+ typedef list<
+ typename mpl::minus<
+ typename mpl::times<typename Begin1::item, X2>::type,
+ typename mpl::times<typename Begin2::item, X1>::type
+ >::type,
+ typename eliminate_from_pair_of_equations_impl<N - 1>::template apply<
+ typename Begin1::next,
+ typename Begin2::next,
+ X1,
+ X2
+ >::type
+ > type;
+ };
+};
+
+template<>
+struct eliminate_from_pair_of_equations_impl<0> {
+ template<class Begin1, class Begin2, class X1, class X2>
+ struct apply {
+ typedef dimensionless_type type;
+ };
+};
+
+template<class E1, class E2>
+struct eliminate_from_pair_of_equations {
+ typedef E1 begin1;
+ typedef E2 begin2;
+ typedef typename eliminate_from_pair_of_equations_impl<(E1::size::value - 1)>::template apply<
+ typename begin1::next,
+ typename begin2::next,
+ typename begin1::item,
+ typename begin2::item
+ >::type type;
+};
+
+
+
+// Stage 1. Determine which dimensions should
+// have dummy base units. For this purpose
+// row reduce the matrix.
+
+template<int N>
+struct make_zero_vector {
+ typedef list<static_rational<0>, typename make_zero_vector<N - 1>::type> type;
+};
+template<>
+struct make_zero_vector<0> {
+ typedef dimensionless_type type;
+};
+
+template<int Column, int TotalColumns>
+struct create_row_of_identity {
+ typedef list<static_rational<0>, typename create_row_of_identity<Column - 1, TotalColumns - 1>::type> type;
+};
+template<int TotalColumns>
+struct create_row_of_identity<0, TotalColumns> {
+ typedef list<static_rational<1>, typename make_zero_vector<TotalColumns - 1>::type> type;
+};
+template<int Column>
+struct create_row_of_identity<Column, 0> {
+ // error
+};
+
+template<int RemainingRows>
+struct determine_extra_equations_impl;
+
+template<bool first_is_zero, bool is_last>
+struct determine_extra_equations_skip_zeros_impl;
+
+// not the last row and not zero.
+template<>
+struct determine_extra_equations_skip_zeros_impl<false, false> {
+ template<class RowsBegin, int RemainingRows, int CurrentColumn, int TotalColumns, class Result>
+ struct apply {
+ // remove the equation being eliminated against from the set of equations.
+ typedef typename determine_extra_equations_impl<RemainingRows - 1>::template apply<typename RowsBegin::next, typename RowsBegin::item>::type next_equations;
+ // since this column was present, strip it out.
+ typedef Result type;
+ };
+};
+
+// the last row but not zero.
+template<>
+struct determine_extra_equations_skip_zeros_impl<false, true> {
+ template<class RowsBegin, int RemainingRows, int CurrentColumn, int TotalColumns, class Result>
+ struct apply {
+ // remove this equation.
+ typedef dimensionless_type next_equations;
+ // since this column was present, strip it out.
+ typedef Result type;
+ };
+};
+
+
+// the first columns is zero but it is not the last column.
+// continue with the same loop.
+template<>
+struct determine_extra_equations_skip_zeros_impl<true, false> {
+ template<class RowsBegin, int RemainingRows, int CurrentColumn, int TotalColumns, class Result>
+ struct apply {
+ typedef typename RowsBegin::next::item next_row;
+ typedef typename determine_extra_equations_skip_zeros_impl<
+ next_row::item::Numerator == 0,
+ RemainingRows == 2 // the next one will be the last.
+ >::template apply<
+ typename RowsBegin::next,
+ RemainingRows - 1,
+ CurrentColumn,
+ TotalColumns,
+ Result
+ > next;
+ typedef list<typename RowsBegin::item::next, typename next::next_equations> next_equations;
+ typedef typename next::type type;
+ };
+};
+
+// all the elements in this column are zero.
+template<>
+struct determine_extra_equations_skip_zeros_impl<true, true> {
+ template<class RowsBegin, int RemainingRows, int CurrentColumn, int TotalColumns, class Result>
+ struct apply {
+ typedef list<typename RowsBegin::item::next, dimensionless_type> next_equations;
+ typedef list<typename create_row_of_identity<CurrentColumn, TotalColumns>::type, Result> type;
+ };
+};
+
+template<int RemainingRows>
+struct determine_extra_equations_impl {
+ template<class RowsBegin, class EliminateAgainst>
+ struct apply {
+ typedef list<
+ typename eliminate_from_pair_of_equations<typename RowsBegin::item, EliminateAgainst>::type,
+ typename determine_extra_equations_impl<RemainingRows-1>::template apply<typename RowsBegin::next, EliminateAgainst>::type
+ > type;
+ };
+};
+
+template<>
+struct determine_extra_equations_impl<0> {
+ template<class RowsBegin, class EliminateAgainst>
+ struct apply {
+ typedef dimensionless_type type;
+ };
+};
+
+template<int RemainingColumns, bool is_done>
+struct determine_extra_equations {
+ template<class RowsBegin, int TotalColumns, class Result>
+ struct apply {
+ typedef typename RowsBegin::item top_row;
+ typedef typename determine_extra_equations_skip_zeros_impl<
+ top_row::item::Numerator == 0,
+ RowsBegin::item::size::value == 1
+ >::template apply<
+ RowsBegin,
+ RowsBegin::size::value,
+ TotalColumns - RemainingColumns,
+ TotalColumns,
+ Result
+ > column_info;
+ typedef typename determine_extra_equations<
+ RemainingColumns - 1,
+ column_info::next_equations::size::value == 0
+ >::template apply<
+ typename column_info::next_equations,
+ TotalColumns,
+ typename column_info::type
+ >::type type;
+ };
+};
+
+template<int RemainingColumns>
+struct determine_extra_equations<RemainingColumns, true> {
+ template<class RowsBegin, int TotalColumns, class Result>
+ struct apply {
+ typedef typename determine_extra_equations<RemainingColumns - 1, true>::template apply<
+ RowsBegin,
+ TotalColumns,
+ list<typename create_row_of_identity<TotalColumns - RemainingColumns, TotalColumns>::type, Result>
+ >::type type;
+ };
+};
+
+template<>
+struct determine_extra_equations<0, true> {
+ template<class RowsBegin, int TotalColumns, class Result>
+ struct apply {
+ typedef Result type;
+ };
+};
+
+// Stage 2
+// invert the matrix using Gauss-Jordan elimination
+
+
+template<bool is_zero, bool is_last>
+struct invert_strip_leading_zeroes;
+
+template<int N>
+struct invert_handle_after_pivot_row;
+
+// When processing column N, none of the first N rows
+// can be the pivot column.
+template<int N>
+struct invert_handle_inital_rows {
+ template<class RowsBegin, class IdentityBegin>
+ struct apply {
+ typedef typename invert_handle_inital_rows<N - 1>::template apply<
+ typename RowsBegin::next,
+ typename IdentityBegin::next
+ > next;
+ typedef typename RowsBegin::item current_row;
+ typedef typename IdentityBegin::item current_identity_row;
+ typedef typename next::pivot_row pivot_row;
+ typedef typename next::identity_pivot_row identity_pivot_row;
+ typedef list<
+ typename eliminate_from_pair_of_equations_impl<(current_row::size::value) - 1>::template apply<
+ typename current_row::next,
+ pivot_row,
+ typename current_row::item,
+ static_rational<1>
+ >::type,
+ typename next::new_matrix
+ > new_matrix;
+ typedef list<
+ typename eliminate_from_pair_of_equations_impl<(current_identity_row::size::value)>::template apply<
+ current_identity_row,
+ identity_pivot_row,
+ typename current_row::item,
+ static_rational<1>
+ >::type,
+ typename next::identity_result
+ > identity_result;
+ };
+};
+
+// This handles the switch to searching for a pivot column.
+// The pivot row will be propagated up in the typedefs
+// pivot_row and identity_pivot_row. It is inserted here.
+template<>
+struct invert_handle_inital_rows<0> {
+ template<class RowsBegin, class IdentityBegin>
+ struct apply {
+ typedef typename RowsBegin::item current_row;
+ typedef typename invert_strip_leading_zeroes<
+ (current_row::item::Numerator == 0),
+ (RowsBegin::size::value == 1)
+ >::template apply<
+ RowsBegin,
+ IdentityBegin
+ > next;
+ // results
+ typedef list<typename next::pivot_row, typename next::new_matrix> new_matrix;
+ typedef list<typename next::identity_pivot_row, typename next::identity_result> identity_result;
+ typedef typename next::pivot_row pivot_row;
+ typedef typename next::identity_pivot_row identity_pivot_row;
+ };
+};
+
+// The first internal element which is not zero.
+template<>
+struct invert_strip_leading_zeroes<false, false> {
+ template<class RowsBegin, class IdentityBegin>
+ struct apply {
+ typedef typename RowsBegin::item current_row;
+ typedef typename current_row::item current_value;
+ typedef typename divide_equation<(current_row::size::value - 1)>::template apply<typename current_row::next, current_value>::type new_equation;
+ typedef typename divide_equation<(IdentityBegin::item::size::value)>::template apply<typename IdentityBegin::item, current_value>::type transformed_identity_equation;
+ typedef typename invert_handle_after_pivot_row<(RowsBegin::size::value - 1)>::template apply<
+ typename RowsBegin::next,
+ typename IdentityBegin::next,
+ new_equation,
+ transformed_identity_equation
+ > next;
+
+ // results
+ // Note that we don't add the pivot row to the
+ // results here, because it needs to propagated up
+ // to the diagonal.
+ typedef typename next::new_matrix new_matrix;
+ typedef typename next::identity_result identity_result;
+ typedef new_equation pivot_row;
+ typedef transformed_identity_equation identity_pivot_row;
+ };
+};
+
+// The one and only non-zero element--at the end
+template<>
+struct invert_strip_leading_zeroes<false, true> {
+ template<class RowsBegin, class IdentityBegin>
+ struct apply {
+ typedef typename RowsBegin::item current_row;
+ typedef typename current_row::item current_value;
+ typedef typename divide_equation<(current_row::size::value - 1)>::template apply<typename current_row::next, current_value>::type new_equation;
+ typedef typename divide_equation<(IdentityBegin::item::size::value)>::template apply<typename IdentityBegin::item, current_value>::type transformed_identity_equation;
+
+ // results
+ // Note that we don't add the pivot row to the
+ // results here, because it needs to propagated up
+ // to the diagonal.
+ typedef dimensionless_type identity_result;
+ typedef dimensionless_type new_matrix;
+ typedef new_equation pivot_row;
+ typedef transformed_identity_equation identity_pivot_row;
+ };
+};
+
+// One of the initial zeroes
+template<>
+struct invert_strip_leading_zeroes<true, false> {
+ template<class RowsBegin, class IdentityBegin>
+ struct apply {
+ typedef typename RowsBegin::item current_row;
+ typedef typename RowsBegin::next::item next_row;
+ typedef typename invert_strip_leading_zeroes<
+ next_row::item::Numerator == 0,
+ RowsBegin::size::value == 2
+ >::template apply<
+ typename RowsBegin::next,
+ typename IdentityBegin::next
+ > next;
+ typedef typename IdentityBegin::item current_identity_row;
+ // these are propagated up.
+ typedef typename next::pivot_row pivot_row;
+ typedef typename next::identity_pivot_row identity_pivot_row;
+ typedef list<
+ typename eliminate_from_pair_of_equations_impl<(current_row::size::value - 1)>::template apply<
+ typename current_row::next,
+ pivot_row,
+ typename current_row::item,
+ static_rational<1>
+ >::type,
+ typename next::new_matrix
+ > new_matrix;
+ typedef list<
+ typename eliminate_from_pair_of_equations_impl<(current_identity_row::size::value)>::template apply<
+ current_identity_row,
+ identity_pivot_row,
+ typename current_row::item,
+ static_rational<1>
+ >::type,
+ typename next::identity_result
+ > identity_result;
+ };
+};
+
+// the last element, and is zero.
+// Should never happen.
+template<>
+struct invert_strip_leading_zeroes<true, true> {
+};
+
+template<int N>
+struct invert_handle_after_pivot_row {
+ template<class RowsBegin, class IdentityBegin, class MatrixPivot, class IdentityPivot>
+ struct apply {
+ typedef typename invert_handle_after_pivot_row<N - 1>::template apply<
+ typename RowsBegin::next,
+ typename IdentityBegin::next,
+ MatrixPivot,
+ IdentityPivot
+ > next;
+ typedef typename RowsBegin::item current_row;
+ typedef typename IdentityBegin::item current_identity_row;
+ typedef MatrixPivot pivot_row;
+ typedef IdentityPivot identity_pivot_row;
+
+ // results
+ typedef list<
+ typename eliminate_from_pair_of_equations_impl<(current_row::size::value - 1)>::template apply<
+ typename current_row::next,
+ pivot_row,
+ typename current_row::item,
+ static_rational<1>
+ >::type,
+ typename next::new_matrix
+ > new_matrix;
+ typedef list<
+ typename eliminate_from_pair_of_equations_impl<(current_identity_row::size::value)>::template apply<
+ current_identity_row,
+ identity_pivot_row,
+ typename current_row::item,
+ static_rational<1>
+ >::type,
+ typename next::identity_result
+ > identity_result;
+ };
+};
+
+template<>
+struct invert_handle_after_pivot_row<0> {
+ template<class RowsBegin, class IdentityBegin, class MatrixPivot, class IdentityPivot>
+ struct apply {
+ typedef dimensionless_type new_matrix;
+ typedef dimensionless_type identity_result;
+ };
+};
+
+template<int N>
+struct invert_impl {
+ template<class RowsBegin, class IdentityBegin>
+ struct apply {
+ typedef typename invert_handle_inital_rows<RowsBegin::size::value - N>::template apply<RowsBegin, IdentityBegin> process_column;
+ typedef typename invert_impl<N - 1>::template apply<
+ typename process_column::new_matrix,
+ typename process_column::identity_result
+ >::type type;
+ };
+};
+
+template<>
+struct invert_impl<0> {
+ template<class RowsBegin, class IdentityBegin>
+ struct apply {
+ typedef IdentityBegin type;
+ };
+};
+
+template<int N>
+struct make_identity {
+ template<int Size>
+ struct apply {
+ typedef list<typename create_row_of_identity<Size - N, Size>::type, typename make_identity<N - 1>::template apply<Size>::type> type;
+ };
+};
+
+template<>
+struct make_identity<0> {
+ template<int Size>
+ struct apply {
+ typedef dimensionless_type type;
+ };
+};
+
+template<class Matrix>
+struct make_square_and_invert {
+ typedef typename Matrix::item top_row;
+ typedef typename determine_extra_equations<(top_row::size::value), false>::template apply<
+ Matrix, // RowsBegin
+ top_row::size::value, // TotalColumns
+ Matrix // Result
+ >::type invertible;
+ typedef typename invert_impl<invertible::size::value>::template apply<
+ invertible,
+ typename make_identity<invertible::size::value>::template apply<invertible::size::value>::type
+ >::type type;
+};
+
+
+// find_base_dimensions takes a list of
+// base_units and returns a sorted list
+// of all the base_dimensions they use.
+//
+// list<base_dimension> find_base_dimensions(list<base_unit> l) {
+// set<base_dimension> dimensions;
+// for_each(base_unit unit : l) {
+// for_each(dim d : unit.dimension_type) {
+// dimensions = insert(dimensions, d.tag_type);
+// }
+// }
+// return(sort(dimensions, _1 > _2, front_inserter(list<base_dimension>())));
+// }
+
+typedef char set_no;
+struct set_yes { set_no dummy[2]; };
+
+template<class T>
+struct wrap {};
+
+struct set_end {
+ static set_no lookup(...);
+ typedef mpl::long_<0> size;
+};
+
+template<class T, class Next>
+struct set : Next {
+ using Next::lookup;
+ static set_yes lookup(wrap<T>*);
+ typedef T item;
+ typedef Next next;
+ typedef typename mpl::next<typename Next::size>::type size;
+};
+
+template<bool has_key>
+struct set_insert;
+
+template<>
+struct set_insert<true> {
+ template<class Set, class T>
+ struct apply {
+ typedef Set type;
+ };
+};
+
+template<>
+struct set_insert<false> {
+ template<class Set, class T>
+ struct apply {
+ typedef set<T, Set> type;
+ };
+};
+
+template<class Set, class T>
+struct has_key {
+ static const long size = sizeof(Set::lookup((wrap<T>*)0));
+ static const bool value = (size == sizeof(set_yes));
+};
+
+template<int N>
+struct find_base_dimensions_impl_impl {
+ template<class Begin, class S>
+ struct apply {
+ typedef typename find_base_dimensions_impl_impl<N-1>::template apply<
+ typename Begin::next,
+ S
+ >::type next;
+
+ typedef typename set_insert<
+ (has_key<next, typename Begin::item::tag_type>::value)
+ >::template apply<
+ next,
+ typename Begin::item::tag_type
+ >::type type;
+ };
+};
+
+template<>
+struct find_base_dimensions_impl_impl<0> {
+ template<class Begin, class S>
+ struct apply {
+ typedef S type;
+ };
+};
+
+template<int N>
+struct find_base_dimensions_impl {
+ template<class Begin>
+ struct apply {
+ typedef typename find_base_dimensions_impl_impl<(Begin::item::dimension_type::size::value)>::template apply<
+ typename Begin::item::dimension_type,
+ typename find_base_dimensions_impl<N-1>::template apply<typename Begin::next>::type
+ >::type type;
+ };
+};
+
+template<>
+struct find_base_dimensions_impl<0> {
+ template<class Begin>
+ struct apply {
+ typedef set_end type;
+ };
+};
+
+template<class T>
+struct find_base_dimensions {
+ typedef typename insertion_sort<
+ typename find_base_dimensions_impl<
+ (T::size::value)
+ >::template apply<T>::type
+ >::type type;
+};
+
+// calculate_base_dimension_coefficients finds
+// the coefficients corresponding to the first
+// base_dimension in each of the dimension_lists.
+// It returns two values. The first result
+// is a list of the coefficients. The second
+// is a list with all the incremented iterators.
+// When we encounter a base_dimension that is
+// missing from a dimension_list, we do not
+// increment the iterator and we set the
+// coefficient to zero.
+
+template<bool has_dimension>
+struct calculate_base_dimension_coefficients_func;
+
+template<>
+struct calculate_base_dimension_coefficients_func<true> {
+ template<class T>
+ struct apply {
+ typedef typename T::item::value_type type;
+ typedef typename T::next next;
+ };
+};
+
+template<>
+struct calculate_base_dimension_coefficients_func<false> {
+ template<class T>
+ struct apply {
+ typedef static_rational<0> type;
+ typedef T next;
+ };
+};
+
+// begins_with_dimension returns true iff its first
+// parameter is a valid iterator which yields its
+// second parameter when dereferenced.
+
+template<class Iterator>
+struct begins_with_dimension {
+ template<class Dim>
+ struct apply :
+ boost::is_same<
+ Dim,
+ typename Iterator::item::tag_type
+ > {};
+};
+
+template<>
+struct begins_with_dimension<dimensionless_type> {
+ template<class Dim>
+ struct apply : mpl::false_ {};
+};
+
+template<int N>
+struct calculate_base_dimension_coefficients_impl {
+ template<class BaseUnitDimensions,class Dim,class T>
+ struct apply {
+ typedef typename calculate_base_dimension_coefficients_func<
+ begins_with_dimension<typename BaseUnitDimensions::item>::template apply<
+ Dim
+ >::value
+ >::template apply<
+ typename BaseUnitDimensions::item
+ > result;
+ typedef typename calculate_base_dimension_coefficients_impl<N-1>::template apply<
+ typename BaseUnitDimensions::next,
+ Dim,
+ list<typename result::type, T>
+ > next_;
+ typedef typename next_::type type;
+ typedef list<typename result::next, typename next_::next> next;
+ };
+};
+
+template<>
+struct calculate_base_dimension_coefficients_impl<0> {
+ template<class Begin, class BaseUnitDimensions, class T>
+ struct apply {
+ typedef T type;
+ typedef dimensionless_type next;
+ };
+};
+
+// add_zeroes pushs N zeroes onto the
+// front of a list.
+//
+// list<rational> add_zeroes(list<rational> l, int N) {
+// if(N == 0) {
+// return(l);
+// } else {
+// return(push_front(add_zeroes(l, N-1), 0));
+// }
+// }
+
+template<int N>
+struct add_zeroes_impl {
+ // If you get an error here and your base units are
+ // in fact linearly independent, please report it.
+ BOOST_MPL_ASSERT_MSG((N > 0), base_units_are_probably_not_linearly_independent, (void));
+ template<class T>
+ struct apply {
+ typedef list<
+ static_rational<0>,
+ typename add_zeroes_impl<N-1>::template apply<T>::type
+ > type;
+ };
+};
+
+template<>
+struct add_zeroes_impl<0> {
+ template<class T>
+ struct apply {
+ typedef T type;
+ };
+};
+
+// expand_dimensions finds the exponents of
+// a set of dimensions in a dimension_list.
+// the second parameter is assumed to be
+// a superset of the base_dimensions of
+// the first parameter.
+//
+// list<rational> expand_dimensions(dimension_list, list<base_dimension>);
+
+template<int N>
+struct expand_dimensions {
+ template<class Begin, class DimensionIterator>
+ struct apply {
+ typedef typename calculate_base_dimension_coefficients_func<
+ begins_with_dimension<DimensionIterator>::template apply<typename Begin::item>::value
+ >::template apply<DimensionIterator> result;
+ typedef list<
+ typename result::type,
+ typename expand_dimensions<N-1>::template apply<typename Begin::next, typename result::next>::type
+ > type;
+ };
+};
+
+template<>
+struct expand_dimensions<0> {
+ template<class Begin, class DimensionIterator>
+ struct apply {
+ typedef dimensionless_type type;
+ };
+};
+
+template<int N>
+struct create_unit_matrix {
+ template<class Begin, class Dimensions>
+ struct apply {
+ typedef typename create_unit_matrix<N - 1>::template apply<typename Begin::next, Dimensions>::type next;
+ typedef list<typename expand_dimensions<Dimensions::size::value>::template apply<Dimensions, typename Begin::item::dimension_type>::type, next> type;
+ };
+};
+
+template<>
+struct create_unit_matrix<0> {
+ template<class Begin, class Dimensions>
+ struct apply {
+ typedef dimensionless_type type;
+ };
+};
+
+template<class T>
+struct normalize_units {
+ typedef typename find_base_dimensions<T>::type dimensions;
+ typedef typename create_unit_matrix<(T::size::value)>::template apply<
+ T,
+ dimensions
+ >::type matrix;
+ typedef typename make_square_and_invert<matrix>::type type;
+ static const long extra = (type::size::value) - (T::size::value);
+};
+
+// multiply_add_units computes M x V
+// where M is a matrix and V is a horizontal
+// vector
+//
+// list<rational> multiply_add_units(list<list<rational> >, list<rational>);
+
+template<int N>
+struct multiply_add_units_impl {
+ template<class Begin1, class Begin2 ,class X>
+ struct apply {
+ typedef list<
+ typename mpl::plus<
+ typename mpl::times<
+ typename Begin2::item,
+ X
+ >::type,
+ typename Begin1::item
+ >::type,
+ typename multiply_add_units_impl<N-1>::template apply<
+ typename Begin1::next,
+ typename Begin2::next,
+ X
+ >::type
+ > type;
+ };
+};
+
+template<>
+struct multiply_add_units_impl<0> {
+ template<class Begin1, class Begin2 ,class X>
+ struct apply {
+ typedef dimensionless_type type;
+ };
+};
+
+template<int N>
+struct multiply_add_units {
+ template<class Begin1, class Begin2>
+ struct apply {
+ typedef typename multiply_add_units_impl<
+ (Begin2::item::size::value)
+ >::template apply<
+ typename multiply_add_units<N-1>::template apply<
+ typename Begin1::next,
+ typename Begin2::next
+ >::type,
+ typename Begin2::item,
+ typename Begin1::item
+ >::type type;
+ };
+};
+
+template<>
+struct multiply_add_units<1> {
+ template<class Begin1, class Begin2>
+ struct apply {
+ typedef typename add_zeroes_impl<
+ (Begin2::item::size::value)
+ >::template apply<dimensionless_type>::type type1;
+ typedef typename multiply_add_units_impl<
+ (Begin2::item::size::value)
+ >::template apply<
+ type1,
+ typename Begin2::item,
+ typename Begin1::item
+ >::type type;
+ };
+};
+
+
+// strip_zeroes erases the first N elements of a list if
+// they are all zero, otherwise returns inconsistent
+//
+// list strip_zeroes(list l, int N) {
+// if(N == 0) {
+// return(l);
+// } else if(l.front == 0) {
+// return(strip_zeroes(pop_front(l), N-1));
+// } else {
+// return(inconsistent);
+// }
+// }
+
+template<int N>
+struct strip_zeroes_impl;
+
+template<class T>
+struct strip_zeroes_func {
+ template<class L, int N>
+ struct apply {
+ typedef inconsistent type;
+ };
+};
+
+template<>
+struct strip_zeroes_func<static_rational<0> > {
+ template<class L, int N>
+ struct apply {
+ typedef typename strip_zeroes_impl<N-1>::template apply<typename L::next>::type type;
+ };
+};
+
+template<int N>
+struct strip_zeroes_impl {
+ template<class T>
+ struct apply {
+ typedef typename strip_zeroes_func<typename T::item>::template apply<T, N>::type type;
+ };
+};
+
+template<>
+struct strip_zeroes_impl<0> {
+ template<class T>
+ struct apply {
+ typedef T type;
+ };
+};
+
+// Given a list of base_units, computes the
+// exponents of each base unit for a given
+// dimension.
+//
+// list<rational> calculate_base_unit_exponents(list<base_unit> units, dimension_list dimensions);
+
+template<class T>
+struct is_base_dimension_unit {
+ typedef mpl::false_ type;
+ typedef void base_dimension_type;
+};
+template<class T>
+struct is_base_dimension_unit<list<dim<T, static_rational<1> >, dimensionless_type> > {
+ typedef mpl::true_ type;
+ typedef T base_dimension_type;
+};
+
+template<int N>
+struct is_simple_system_impl {
+ template<class Begin, class Prev>
+ struct apply {
+ typedef is_base_dimension_unit<typename Begin::item::dimension_type> test;
+ typedef mpl::and_<
+ typename test::type,
+ mpl::less<Prev, typename test::base_dimension_type>,
+ typename is_simple_system_impl<N-1>::template apply<
+ typename Begin::next,
+ typename test::base_dimension_type
+ >
+ > type;
+ static const bool value = (type::value);
+ };
+};
+
+template<>
+struct is_simple_system_impl<0> {
+ template<class Begin, class Prev>
+ struct apply : mpl::true_ {
+ };
+};
+
+template<class T>
+struct is_simple_system {
+ typedef T Begin;
+ typedef is_base_dimension_unit<typename Begin::item::dimension_type> test;
+ typedef typename mpl::and_<
+ typename test::type,
+ typename is_simple_system_impl<
+ T::size::value - 1
+ >::template apply<
+ typename Begin::next::type,
+ typename test::base_dimension_type
+ >
+ >::type type;
+ static const bool value = type::value;
+};
+
+template<bool>
+struct calculate_base_unit_exponents_impl;
+
+template<>
+struct calculate_base_unit_exponents_impl<true> {
+ template<class T, class Dimensions>
+ struct apply {
+ typedef typename expand_dimensions<(T::size::value)>::template apply<
+ typename find_base_dimensions<T>::type,
+ Dimensions
+ >::type type;
+ };
+};
+
+template<>
+struct calculate_base_unit_exponents_impl<false> {
+ template<class T, class Dimensions>
+ struct apply {
+ // find the units that correspond to each base dimension
+ typedef normalize_units<T> base_solutions;
+ // pad the dimension with zeroes so it can just be a
+ // list of numbers, making the multiplication easy
+ // e.g. if the arguments are list<pound, foot> and
+ // list<mass,time^-2> then this step will
+ // yield list<0,1,-2>
+ typedef typename expand_dimensions<(base_solutions::dimensions::size::value)>::template apply<
+ typename base_solutions::dimensions,
+ Dimensions
+ >::type dimensions;
+ // take the unit corresponding to each base unit
+ // multiply each of its exponents by the exponent
+ // of the base_dimension in the result and sum.
+ typedef typename multiply_add_units<dimensions::size::value>::template apply<
+ dimensions,
+ typename base_solutions::type
+ >::type units;
+ // Now, verify that the dummy units really
+ // cancel out and remove them.
+ typedef typename strip_zeroes_impl<base_solutions::extra>::template apply<units>::type type;
+ };
+};
+
+template<class T, class Dimensions>
+struct calculate_base_unit_exponents {
+ typedef typename calculate_base_unit_exponents_impl<is_simple_system<T>::value>::template apply<T, Dimensions>::type type;
+};
+
+} // namespace detail
+
+} // namespace units
+
+} // namespace boost
+
+#endif
diff --git a/boost/units/detail/one.hpp b/boost/units/detail/one.hpp
new file mode 100644
index 0000000..4cadc2c
--- /dev/null
+++ b/boost/units/detail/one.hpp
@@ -0,0 +1,109 @@
+// Boost.Units - A C++ library for zero-overhead dimensional analysis and
+// unit/quantity manipulation and conversion
+//
+// Copyright (C) 2003-2008 Matthias Christian Schabel
+// Copyright (C) 2008 Steven Watanabe
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_UNITS_DETAIL_ONE_HPP
+#define BOOST_UNITS_DETAIL_ONE_HPP
+
+#include <boost/units/operators.hpp>
+
+namespace boost {
+
+namespace units {
+
+struct one { one() {} };
+
+// workaround for pathscale.
+inline one make_one() {
+ one result;
+ return(result);
+}
+
+template<class T>
+struct multiply_typeof_helper<one, T>
+{
+ typedef T type;
+};
+
+template<class T>
+struct multiply_typeof_helper<T, one>
+{
+ typedef T type;
+};
+
+template<>
+struct multiply_typeof_helper<one, one>
+{
+ typedef one type;
+};
+
+template<class T>
+inline T operator*(const one&, const T& t)
+{
+ return(t);
+}
+
+template<class T>
+inline T operator*(const T& t, const one&)
+{
+ return(t);
+}
+
+inline one operator*(const one&, const one&)
+{
+ one result;
+ return(result);
+}
+
+template<class T>
+struct divide_typeof_helper<T, one>
+{
+ typedef T type;
+};
+
+template<class T>
+struct divide_typeof_helper<one, T>
+{
+ typedef T type;
+};
+
+template<>
+struct divide_typeof_helper<one, one>
+{
+ typedef one type;
+};
+
+template<class T>
+inline T operator/(const T& t, const one&)
+{
+ return(t);
+}
+
+template<class T>
+inline T operator/(const one&, const T& t)
+{
+ return(1/t);
+}
+
+inline one operator/(const one&, const one&)
+{
+ one result;
+ return(result);
+}
+
+template<class T>
+inline bool operator>(const boost::units::one&, const T& t) {
+ return(1 > t);
+}
+
+} // namespace units
+
+} // namespace boost
+
+#endif
diff --git a/boost/units/detail/ordinal.hpp b/boost/units/detail/ordinal.hpp
new file mode 100644
index 0000000..b47ef67
--- /dev/null
+++ b/boost/units/detail/ordinal.hpp
@@ -0,0 +1,49 @@
+// Boost.Units - A C++ library for zero-overhead dimensional analysis and
+// unit/quantity manipulation and conversion
+//
+// Copyright (C) 2003-2008 Matthias Christian Schabel
+// Copyright (C) 2007-2008 Steven Watanabe
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_UNITS_DETAIL_ORDINAL_HPP_INCLUDED
+#define BOOST_UNITS_DETAIL_ORDINAL_HPP_INCLUDED
+
+#include <boost/mpl/less.hpp>
+#include <boost/mpl/bool.hpp>
+
+namespace boost {
+namespace units {
+
+namespace detail {
+
+struct ordinal_tag {};
+
+}
+
+template<int N>
+struct ordinal {
+ typedef detail::ordinal_tag tag;
+ static const long value = N;
+};
+
+template<int N>
+const long ordinal<N>::value;
+
+}
+
+namespace mpl {
+
+template<>
+struct less_impl<units::detail::ordinal_tag, units::detail::ordinal_tag> {
+ template<class T1, class T2>
+ struct apply : bool_<(T1::value) < (T2::value)> {};
+};
+
+}
+
+}
+
+#endif
diff --git a/boost/units/detail/prevent_redefinition.hpp b/boost/units/detail/prevent_redefinition.hpp
new file mode 100644
index 0000000..fba969a
--- /dev/null
+++ b/boost/units/detail/prevent_redefinition.hpp
@@ -0,0 +1,54 @@
+// Boost.Units - A C++ library for zero-overhead dimensional analysis and
+// unit/quantity manipulation and conversion
+//
+// Copyright (C) 2003-2008 Matthias Christian Schabel
+// Copyright (C) 2007-2008 Steven Watanabe
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_UNITS_DETAIL_PREVENT_REDEFINITION_HPP
+#define BOOST_UNITS_DETAIL_PREVENT_REDEFINITION_HPP
+
+#include <boost/mpl/long.hpp>
+
+namespace boost {
+
+namespace units {
+
+namespace detail {
+
+struct no { no() {} char dummy; };
+struct yes { no dummy[2]; };
+
+template<bool> struct ordinal_has_already_been_defined;
+
+template<>
+struct ordinal_has_already_been_defined<true> { };
+
+template<>
+struct ordinal_has_already_been_defined<false> { typedef void type; };
+
+}
+
+/// This must be in namespace boost::units so that ADL
+/// will work. we need a mangled name because it must
+/// be found by ADL
+/// INTERNAL ONLY
+template<class T>
+detail::no
+boost_units_is_registered(const T&)
+{ detail::no result; return(result); }
+
+/// INTERNAL ONLY
+template<class T>
+detail::no
+boost_units_unit_is_registered(const T&)
+{ detail::no result; return(result); }
+
+} // namespace units
+
+} // namespace boost
+
+#endif // BOOST_UNITS_PREVENT_ORDINAL_REDEFINITION_IMPL_HPP
diff --git a/boost/units/detail/push_front_if.hpp b/boost/units/detail/push_front_if.hpp
new file mode 100644
index 0000000..b924a24
--- /dev/null
+++ b/boost/units/detail/push_front_if.hpp
@@ -0,0 +1,48 @@
+// Boost.Units - A C++ library for zero-overhead dimensional analysis and
+// unit/quantity manipulation and conversion
+//
+// Copyright (C) 2003-2008 Matthias Christian Schabel
+// Copyright (C) 2008 Steven Watanabe
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_UNITS_DETAIL_PUSH_FRONT_IF_HPP
+#define BOOST_UNITS_DETAIL_PUSH_FRONT_IF_HPP
+
+namespace boost {
+
+namespace units {
+
+template<class T, class Next>
+struct list;
+
+namespace detail {
+
+template<bool>
+struct push_front_if;
+
+template<>
+struct push_front_if<true> {
+ template<class L, class T>
+ struct apply {
+ typedef list<T, L> type;
+ };
+};
+
+template<>
+struct push_front_if<false> {
+ template<class L, class T>
+ struct apply {
+ typedef L type;
+ };
+};
+
+}
+
+}
+
+}
+
+#endif
diff --git a/boost/units/detail/push_front_or_add.hpp b/boost/units/detail/push_front_or_add.hpp
new file mode 100644
index 0000000..a3092da
--- /dev/null
+++ b/boost/units/detail/push_front_or_add.hpp
@@ -0,0 +1,84 @@
+// Boost.Units - A C++ library for zero-overhead dimensional analysis and
+// unit/quantity manipulation and conversion
+//
+// Copyright (C) 2003-2008 Matthias Christian Schabel
+// Copyright (C) 2008 Steven Watanabe
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_UNITS_DETAIL_PUSH_FRONT_OR_ADD_HPP
+#define BOOST_UNITS_DETAIL_PUSH_FRONT_OR_ADD_HPP
+
+#include <boost/mpl/plus.hpp>
+#include <boost/mpl/front.hpp>
+#include <boost/mpl/push_front.hpp>
+#include <boost/mpl/pop_front.hpp>
+#include <boost/type_traits/is_same.hpp>
+
+#include <boost/units/units_fwd.hpp>
+#include <boost/units/detail/push_front_if.hpp>
+
+namespace boost {
+
+namespace units {
+
+template<class Item, class Next>
+struct list;
+
+namespace detail {
+
+template<class T>
+struct is_empty_dim;
+
+/// add an instantiation of dim to Sequence.
+template<bool>
+struct push_front_or_add_impl;
+
+template<>
+struct push_front_or_add_impl<true>
+{
+ template<typename Sequence, typename T>
+ struct apply
+ {
+ typedef typename mpl::plus<T, typename Sequence::item>::type item;
+ typedef typename push_front_if<!is_empty_dim<item>::value>::template apply<
+ typename Sequence::next,
+ item
+ > type;
+ };
+};
+
+template<>
+struct push_front_or_add_impl<false>
+{
+ template<typename Sequence, typename T>
+ struct apply
+ {
+ typedef list<T, Sequence> type;
+ };
+};
+
+template<typename Sequence, typename T>
+struct push_front_or_add
+{
+ typedef typename push_front_or_add_impl<boost::is_same<typename T::tag_type, typename Sequence::item::tag_type>::value>::template apply<
+ Sequence,
+ T
+ >::type type;
+};
+
+template<typename T>
+struct push_front_or_add<dimensionless_type, T>
+{
+ typedef list<T, dimensionless_type> type;
+};
+
+} // namespace detail
+
+} // namespace units
+
+} // namespace boost
+
+#endif
diff --git a/boost/units/detail/sort.hpp b/boost/units/detail/sort.hpp
new file mode 100644
index 0000000..389adfe
--- /dev/null
+++ b/boost/units/detail/sort.hpp
@@ -0,0 +1,109 @@
+// Boost.Units - A C++ library for zero-overhead dimensional analysis and
+// unit/quantity manipulation and conversion
+//
+// Copyright (C) 2003-2008 Matthias Christian Schabel
+// Copyright (C) 2008 Steven Watanabe
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_UNITS_DETAIL_SORT_HPP
+#define BOOST_UNITS_DETAIL_SORT_HPP
+
+#include <boost/mpl/size.hpp>
+#include <boost/mpl/begin.hpp>
+#include <boost/mpl/next.hpp>
+#include <boost/mpl/deref.hpp>
+#include <boost/mpl/push_front.hpp>
+#include <boost/mpl/less.hpp>
+
+#include <boost/units/dimensionless_type.hpp>
+#include <boost/units/detail/dimension_list.hpp>
+
+namespace boost {
+
+namespace units {
+
+namespace detail {
+
+template<int N>
+struct insertion_sort_insert;
+
+template<bool is_greater>
+struct insertion_sort_comparison_impl;
+
+// have to recursively add the element to the next sequence.
+template<>
+struct insertion_sort_comparison_impl<true> {
+ template<class Begin, int N, class T>
+ struct apply {
+ typedef list<
+ typename Begin::item,
+ typename insertion_sort_insert<N - 1>::template apply<
+ typename Begin::next,
+ T
+ >::type
+ > type;
+ };
+};
+
+// prepend the current element
+template<>
+struct insertion_sort_comparison_impl<false> {
+ template<class Begin, int N, class T>
+ struct apply {
+ typedef list<T, Begin> type;
+ };
+};
+
+template<int N>
+struct insertion_sort_insert {
+ template<class Begin, class T>
+ struct apply {
+ typedef typename insertion_sort_comparison_impl<mpl::less<typename Begin::item, T>::value>::template apply<
+ Begin,
+ N,
+ T
+ >::type type;
+ };
+};
+
+template<>
+struct insertion_sort_insert<0> {
+ template<class Begin, class T>
+ struct apply {
+ typedef list<T, dimensionless_type> type;
+ };
+};
+
+template<int N>
+struct insertion_sort_impl {
+ template<class Begin>
+ struct apply {
+ typedef typename insertion_sort_impl<N - 1>::template apply<typename Begin::next>::type next;
+ typedef typename insertion_sort_insert<(next::size::value)>::template apply<next, typename Begin::item>::type type;
+ };
+};
+
+template<>
+struct insertion_sort_impl<0> {
+ template<class Begin>
+ struct apply {
+ typedef dimensionless_type type;
+ };
+};
+
+template<class T>
+struct insertion_sort
+{
+ typedef typename insertion_sort_impl<T::size::value>::template apply<T>::type type;
+};
+
+} // namespace detail
+
+} // namespace units
+
+} // namespace boost
+
+#endif
diff --git a/boost/units/detail/static_rational_power.hpp b/boost/units/detail/static_rational_power.hpp
new file mode 100644
index 0000000..9c71f55
--- /dev/null
+++ b/boost/units/detail/static_rational_power.hpp
@@ -0,0 +1,206 @@
+// Boost.Units - A C++ library for zero-overhead dimensional analysis and
+// unit/quantity manipulation and conversion
+//
+// Copyright (C) 2003-2008 Matthias Christian Schabel
+// Copyright (C) 2007-2008 Steven Watanabe
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_UNITS_DETAIL_STATIC_RATIONAL_POWER_HPP
+#define BOOST_UNITS_DETAIL_STATIC_RATIONAL_POWER_HPP
+
+#include <boost/config/no_tr1/cmath.hpp>
+
+#include <boost/units/detail/one.hpp>
+#include <boost/units/operators.hpp>
+
+namespace boost {
+
+namespace units {
+
+template<long N,long D>
+class static_rational;
+
+namespace detail {
+
+namespace typeof_pow_adl_barrier {
+
+using std::pow;
+
+template<class Y>
+struct typeof_pow
+{
+#if defined(BOOST_UNITS_HAS_BOOST_TYPEOF)
+ BOOST_TYPEOF_NESTED_TYPEDEF_TPL(nested, pow(typeof_::make<Y>(), 0.0))
+ typedef typename nested::type type;
+#elif defined(BOOST_UNITS_HAS_MWERKS_TYPEOF)
+ typedef __typeof__(pow(typeof_::make<Y>(), 0.0)) type;
+#elif defined(BOOST_UNITS_HAS_GNU_TYPEOF)
+ typedef typeof(pow(typeof_::make<Y>(), 0.0)) type;
+#else
+ typedef Y type;
+#endif
+};
+
+}
+
+template<class R, class Y>
+struct static_rational_power_impl
+{
+ typedef typename typeof_pow_adl_barrier::typeof_pow<Y>::type type;
+ static type call(const Y& y)
+ {
+ using std::pow;
+ return(pow(y, static_cast<double>(R::Numerator) / static_cast<double>(R::Denominator)));
+ }
+};
+
+template<class R>
+struct static_rational_power_impl<R, one>
+{
+ typedef one type;
+ static one call(const one&)
+ {
+ one result;
+ return(result);
+ }
+};
+
+template<long N>
+struct static_rational_power_impl<static_rational<N, 1>, one>
+{
+ typedef one type;
+ static one call(const one&)
+ {
+ one result;
+ return(result);
+ }
+};
+
+template<long N, bool = (N % 2 == 0)>
+struct static_int_power_impl;
+
+template<long N>
+struct static_int_power_impl<N, true>
+{
+ template<class Y, class R>
+ struct apply
+ {
+ typedef typename multiply_typeof_helper<Y, Y>::type square_type;
+ typedef typename static_int_power_impl<(N >> 1)>::template apply<square_type, R> next;
+ typedef typename next::type type;
+ static type call(const Y& y, const R& r)
+ {
+ const Y square = y * y;
+ return(next::call(square, r));
+ }
+ };
+};
+
+template<long N>
+struct static_int_power_impl<N, false>
+{
+ template<class Y, class R>
+ struct apply
+ {
+ typedef typename multiply_typeof_helper<Y, Y>::type square_type;
+ typedef typename multiply_typeof_helper<Y, R>::type new_r;
+ typedef typename static_int_power_impl<(N >> 1)>::template apply<square_type, new_r> next;
+ typedef typename next::type type;
+ static type call(const Y& y, const R& r)
+ {
+ const Y square = y * y;
+ return(next::call(square, y * r));
+ }
+ };
+};
+
+template<>
+struct static_int_power_impl<1, false>
+{
+ template<class Y, class R>
+ struct apply
+ {
+ typedef typename multiply_typeof_helper<Y, R>::type type;
+ static type call(const Y& y, const R& r)
+ {
+ return(y * r);
+ }
+ };
+};
+
+template<>
+struct static_int_power_impl<0, true>
+{
+ template<class Y, class R>
+ struct apply
+ {
+ typedef R type;
+ static R call(const Y&, const R& r)
+ {
+ return(r);
+ }
+ };
+};
+
+template<int N, bool = (N < 0)>
+struct static_int_power_sign_impl;
+
+template<int N>
+struct static_int_power_sign_impl<N, false>
+{
+ template<class Y>
+ struct apply
+ {
+ typedef typename static_int_power_impl<N>::template apply<Y, one> impl;
+ typedef typename impl::type type;
+ static type call(const Y& y)
+ {
+ one result;
+ return(impl::call(y, result));
+ }
+ };
+};
+
+template<int N>
+struct static_int_power_sign_impl<N, true>
+{
+ template<class Y>
+ struct apply
+ {
+ typedef typename static_int_power_impl<-N>::template apply<Y, one> impl;
+ typedef typename divide_typeof_helper<one, typename impl::type>::type type;
+ static type call(const Y& y)
+ {
+ one result;
+ return(result/impl::call(y, result));
+ }
+ };
+};
+
+template<long N, class Y>
+struct static_rational_power_impl<static_rational<N, 1>, Y>
+{
+ typedef typename static_int_power_sign_impl<N>::template apply<Y> impl;
+ typedef typename impl::type type;
+ static Y call(const Y& y)
+ {
+ return(impl::call(y));
+ }
+};
+
+template<class R, class Y>
+typename detail::static_rational_power_impl<R, Y>::type static_rational_power(const Y& y)
+{
+ return(detail::static_rational_power_impl<R, Y>::call(y));
+}
+
+} // namespace detail
+
+} // namespace units
+
+} // namespace boost
+
+#endif
diff --git a/boost/units/detail/unscale.hpp b/boost/units/detail/unscale.hpp
new file mode 100644
index 0000000..08e51e9
--- /dev/null
+++ b/boost/units/detail/unscale.hpp
@@ -0,0 +1,234 @@
+// Boost.Units - A C++ library for zero-overhead dimensional analysis and
+// unit/quantity manipulation and conversion
+//
+// Copyright (C) 2003-2008 Matthias Christian Schabel
+// Copyright (C) 2007-2008 Steven Watanabe
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_UNITS_DETAIL_UNSCALE_HPP_INCLUDED
+#define BOOST_UNITS_DETAIL_UNSCALE_HPP_INCLUDED
+
+#include <string>
+
+#include <boost/mpl/bool.hpp>
+#include <boost/mpl/size.hpp>
+#include <boost/mpl/begin.hpp>
+#include <boost/mpl/next.hpp>
+#include <boost/mpl/deref.hpp>
+#include <boost/mpl/plus.hpp>
+#include <boost/mpl/times.hpp>
+#include <boost/mpl/negate.hpp>
+#include <boost/mpl/less.hpp>
+
+#include <boost/units/config.hpp>
+#include <boost/units/dimension.hpp>
+#include <boost/units/scale.hpp>
+#include <boost/units/static_rational.hpp>
+#include <boost/units/units_fwd.hpp>
+#include <boost/units/detail/one.hpp>
+
+namespace boost {
+
+namespace units {
+
+template<class T>
+struct heterogeneous_system;
+
+template<class T, class D, class Scale>
+struct heterogeneous_system_impl;
+
+template<class T, class E>
+struct heterogeneous_system_dim;
+
+template<class S, class Scale>
+struct scaled_base_unit;
+
+/// removes all scaling from a unit or a base unit.
+template<class T>
+struct unscale
+{
+#ifndef BOOST_UNITS_DOXYGEN
+ typedef T type;
+#else
+ typedef detail::unspecified type;
+#endif
+};
+
+/// INTERNAL ONLY
+template<class S, class Scale>
+struct unscale<scaled_base_unit<S, Scale> >
+{
+ typedef typename unscale<S>::type type;
+};
+
+/// INTERNAL ONLY
+template<class D, class S>
+struct unscale<unit<D, S> >
+{
+ typedef unit<D, typename unscale<S>::type> type;
+};
+
+/// INTERNAL ONLY
+template<class Scale>
+struct scale_list_dim;
+
+/// INTERNAL ONLY
+template<class T>
+struct get_scale_list
+{
+ typedef dimensionless_type type;
+};
+
+/// INTERNAL ONLY
+template<class S, class Scale>
+struct get_scale_list<scaled_base_unit<S, Scale> >
+{
+ typedef typename mpl::times<list<scale_list_dim<Scale>, dimensionless_type>, typename get_scale_list<S>::type>::type type;
+};
+
+/// INTERNAL ONLY
+template<class D, class S>
+struct get_scale_list<unit<D, S> >
+{
+ typedef typename get_scale_list<S>::type type;
+};
+
+/// INTERNAL ONLY
+struct scale_dim_tag {};
+
+/// INTERNAL ONLY
+template<class Scale>
+struct scale_list_dim : Scale
+{
+ typedef scale_dim_tag tag;
+ typedef scale_list_dim type;
+};
+
+} // namespace units
+
+#ifndef BOOST_UNITS_DOXYGEN
+
+namespace mpl {
+
+/// INTERNAL ONLY
+template<>
+struct less_impl<boost::units::scale_dim_tag, boost::units::scale_dim_tag>
+{
+ template<class T0, class T1>
+ struct apply : mpl::bool_<((T0::base) < (T1::base))> {};
+};
+
+}
+
+#endif
+
+namespace units {
+
+namespace detail {
+
+template<class Scale>
+struct is_empty_dim<scale_list_dim<Scale> > : mpl::false_ {};
+
+template<long N>
+struct is_empty_dim<scale_list_dim<scale<N, static_rational<0, 1> > > > : mpl::true_ {};
+
+template<int N>
+struct eval_scale_list_impl
+{
+ template<class Begin>
+ struct apply
+ {
+ typedef typename eval_scale_list_impl<N-1>::template apply<typename Begin::next> next_iteration;
+ typedef typename multiply_typeof_helper<typename next_iteration::type, typename Begin::item::value_type>::type type;
+ static type value()
+ {
+ return(next_iteration::value() * Begin::item::value());
+ }
+ };
+};
+
+template<>
+struct eval_scale_list_impl<0>
+{
+ template<class Begin>
+ struct apply
+ {
+ typedef one type;
+ static one value()
+ {
+ one result;
+ return(result);
+ }
+ };
+};
+
+}
+
+/// INTERNAL ONLY
+template<class T>
+struct eval_scale_list : detail::eval_scale_list_impl<T::size::value>::template apply<T> {};
+
+} // namespace units
+
+#ifndef BOOST_UNITS_DOXYGEN
+
+namespace mpl {
+
+/// INTERNAL ONLY
+template<>
+struct plus_impl<boost::units::scale_dim_tag, boost::units::scale_dim_tag>
+{
+ template<class T0, class T1>
+ struct apply
+ {
+ typedef boost::units::scale_list_dim<
+ boost::units::scale<
+ (T0::base),
+ typename mpl::plus<typename T0::exponent, typename T1::exponent>::type
+ >
+ > type;
+ };
+};
+
+/// INTERNAL ONLY
+template<>
+struct negate_impl<boost::units::scale_dim_tag>
+{
+ template<class T0>
+ struct apply
+ {
+ typedef boost::units::scale_list_dim<
+ boost::units::scale<
+ (T0::base),
+ typename mpl::negate<typename T0::exponent>::type
+ >
+ > type;
+ };
+};
+
+/// INTERNAL ONLY
+template<>
+struct times_impl<boost::units::scale_dim_tag, boost::units::detail::static_rational_tag>
+{
+ template<class T0, class T1>
+ struct apply
+ {
+ typedef boost::units::scale_list_dim<
+ boost::units::scale<
+ (T0::base),
+ typename mpl::times<typename T0::exponent, T1>::type
+ >
+ > type;
+ };
+};
+
+} // namespace mpl
+
+#endif
+
+} // namespace boost
+
+#endif
diff --git a/boost/units/detail/utility.hpp b/boost/units/detail/utility.hpp
new file mode 100644
index 0000000..da46b45
--- /dev/null
+++ b/boost/units/detail/utility.hpp
@@ -0,0 +1,104 @@
+// Boost.Units - A C++ library for zero-overhead dimensional analysis and
+// unit/quantity manipulation and conversion
+//
+// Copyright (C) 2003-2008 Matthias Christian Schabel
+// Copyright (C) 2008 Steven Watanabe
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_UNITS_UTILITY_HPP
+#define BOOST_UNITS_UTILITY_HPP
+
+#include <cstdlib>
+#include <typeinfo>
+#include <string>
+
+#if defined(__GLIBCXX__) || defined(__GLIBCPP__)
+#define BOOST_UNITS_USE_DEMANGLING
+#include <cxxabi.h>
+#endif // __GNUC__
+
+#ifdef BOOST_UNITS_USE_DEMANGLING
+
+#include <boost/algorithm/string/replace.hpp>
+
+namespace boost {
+
+namespace units {
+
+namespace detail {
+
+inline
+std::string
+demangle(const char* name)
+{
+ // need to demangle C++ symbols
+ char* realname;
+ std::size_t len;
+ int stat;
+
+ realname = abi::__cxa_demangle(name,NULL,&len,&stat);
+
+ if (realname != NULL)
+ {
+ std::string out(realname);
+
+ std::free(realname);
+
+ boost::replace_all(out,"boost::units::","");
+
+ return out;
+ }
+
+ return std::string("demangle :: error - unable to demangle specified symbol");
+}
+
+} // namespace detail
+
+template<class L>
+std::string simplify_typename(const L& /*source*/)
+{
+ const std::string demangled = detail::demangle(typeid(L).name());
+
+ return demangled;
+}
+
+} // namespace units
+
+} // namespace boost
+
+#else // BOOST_UNITS_USE_DEMANGLING
+
+namespace boost {
+
+namespace units {
+
+namespace detail {
+
+inline
+std::string
+demangle(const char* name)
+{
+ return name;
+}
+
+} // namespace detail
+
+template<class L>
+std::string simplify_typename(const L& /*source*/)
+{
+ return std::string(typeid(L).name());
+}
+
+} // namespace units
+
+} // namespace boost
+
+// To get system-specific predefined macros:
+// gcc -arch ppc -dM -E - < /dev/null | sort
+
+#endif // BOOST_UNITS_USE_DEMANGLING
+
+#endif // BOOST_UNITS_UTILITY_HPP