| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060 | // 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 eliminationtemplate<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 endtemplate<>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 zeroestemplate<>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 {    BOOST_STATIC_CONSTEXPR long size = sizeof(Set::lookup((wrap<T>*)0));    BOOST_STATIC_CONSTEXPR 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;    BOOST_STATIC_CONSTEXPR 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;        BOOST_STATIC_CONSTEXPR 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;    BOOST_STATIC_CONSTEXPR 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
 |