linear_algebra.hpp

来自「Boost provides free peer-reviewed portab」· HPP 代码 · 共 1,075 行 · 第 1/3 页

HPP
1,075
字号
// 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::item current_row;        typedef typename determine_extra_equations_skip_zeros_impl<            current_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 MatrixWithFirstColumnStripped, class Result>    struct apply {        typedef list<typename RowsBegin::item::next, dimensionless_type> next_equations;        typedef list<typename create_row_of_identity<CurrentColumn, TotalColumns>::type, Result> type;    };};template<int RemainingRows>struct determine_extra_equations_impl {    template<class RowsBegin, class EliminateAgainst>    struct apply {        typedef list<            typename eliminate_from_pair_of_equations<typename RowsBegin::item, EliminateAgainst>::type,            typename determine_extra_equations_impl<RemainingRows-1>::template apply<typename RowsBegin::next, EliminateAgainst>::type        > type;    };};template<>struct determine_extra_equations_impl<0> {    template<class RowsBegin, class EliminateAgainst>    struct apply {        typedef dimensionless_type type;    };};template<int RemainingColumns, bool is_done>struct determine_extra_equations {    template<class RowsBegin, int TotalColumns, class Result>    struct apply {        typedef typename RowsBegin::item top_row;        typedef typename determine_extra_equations_skip_zeros_impl<            top_row::item::Numerator == 0,            RowsBegin::item::size::value == 1        >::template apply<            RowsBegin,            RowsBegin::size::value,            TotalColumns - RemainingColumns,            TotalColumns,            Result        > column_info;        typedef typename determine_extra_equations<            RemainingColumns - 1,            column_info::next_equations::size::value == 0        >::template apply<            typename column_info::next_equations,            TotalColumns,            typename column_info::type        >::type type;    };};template<int RemainingColumns>struct determine_extra_equations<RemainingColumns, true> {    template<class RowsBegin, int TotalColumns, class Result>    struct apply {        typedef typename determine_extra_equations<RemainingColumns - 1, true>::template apply<            RowsBegin,            TotalColumns,            list<typename create_row_of_identity<TotalColumns - RemainingColumns, TotalColumns>::type, Result>        >::type type;    };};template<>struct determine_extra_equations<0, true> {    template<class RowsBegin, int TotalColumns, class Result>    struct apply {        typedef Result type;    };};// Stage 2// invert the matrix using Gauss-Jordan 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>

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?