1061 lines
		
	
	
		
			33 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
		
		
			
		
	
	
			1061 lines
		
	
	
		
			33 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| 
								 | 
							
								// 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::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
							 |