diff -r 000000000000 -r bde4ae8d615e os/ossrv/ossrv_pub/boost_apis/boost/numeric/ublas/lu.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/os/ossrv/ossrv_pub/boost_apis/boost/numeric/ublas/lu.hpp Fri Jun 15 03:10:57 2012 +0200 @@ -0,0 +1,342 @@ +// +// Copyright (c) 2000-2002 +// Joerg Walter, Mathias Koch +// +// Permission to use, copy, modify, distribute and sell this software +// and its documentation for any purpose is hereby granted without fee, +// provided that the above copyright notice appear in all copies and +// that both that copyright notice and this permission notice appear +// in supporting documentation. The authors make no representations +// about the suitability of this software for any purpose. +// It is provided "as is" without express or implied warranty. +// +// The authors gratefully acknowledge the support of +// GeNeSys mbH & Co. KG in producing this work. +// + +#ifndef _BOOST_UBLAS_LU_ +#define _BOOST_UBLAS_LU_ + +#include +#include +#include +#include +#include + +// LU factorizations in the spirit of LAPACK and Golub & van Loan + +namespace boost { namespace numeric { namespace ublas { + + template > + class permutation_matrix: + public vector { + public: + typedef vector vector_type; + typedef typename vector_type::size_type size_type; + + // Construction and destruction + BOOST_UBLAS_INLINE + permutation_matrix (size_type size): + vector (size) { + for (size_type i = 0; i < size; ++ i) + (*this) (i) = i; + } + BOOST_UBLAS_INLINE + ~permutation_matrix () {} + + // Assignment + BOOST_UBLAS_INLINE + permutation_matrix &operator = (const permutation_matrix &m) { + vector_type::operator = (m); + return *this; + } + }; + + template + BOOST_UBLAS_INLINE + void swap_rows (const PM &pm, MV &mv, vector_tag) { + typedef typename PM::size_type size_type; + typedef typename MV::value_type value_type; + + size_type size = pm.size (); + for (size_type i = 0; i < size; ++ i) { + if (i != pm (i)) + std::swap (mv (i), mv (pm (i))); + } + } + template + BOOST_UBLAS_INLINE + void swap_rows (const PM &pm, MV &mv, matrix_tag) { + typedef typename PM::size_type size_type; + typedef typename MV::value_type value_type; + + size_type size = pm.size (); + for (size_type i = 0; i < size; ++ i) { + if (i != pm (i)) + row (mv, i).swap (row (mv, pm (i))); + } + } + // Dispatcher + template + BOOST_UBLAS_INLINE + void swap_rows (const PM &pm, MV &mv) { + swap_rows (pm, mv, typename MV::type_category ()); + } + + // LU factorization without pivoting + template + typename M::size_type lu_factorize (M &m) { + typedef M matrix_type; + typedef typename M::size_type size_type; + typedef typename M::value_type value_type; + +#if BOOST_UBLAS_TYPE_CHECK + matrix_type cm (m); +#endif + int singular = 0; + size_type size1 = m.size1 (); + size_type size2 = m.size2 (); + size_type size = (std::min) (size1, size2); + for (size_type i = 0; i < size; ++ i) { + matrix_column mci (column (m, i)); + matrix_row mri (row (m, i)); + if (m (i, i) != value_type/*zero*/()) { + project (mci, range (i + 1, size1)) *= value_type (1) / m (i, i); + } else if (singular == 0) { + singular = i + 1; + } + project (m, range (i + 1, size1), range (i + 1, size2)).minus_assign ( + outer_prod (project (mci, range (i + 1, size1)), + project (mri, range (i + 1, size2)))); + } +#if BOOST_UBLAS_TYPE_CHECK + BOOST_UBLAS_CHECK (singular != 0 || + detail::expression_type_check (prod (triangular_adaptor (m), + triangular_adaptor (m)), + cm), internal_logic ()); +#endif + return singular; + } + + // LU factorization with partial pivoting + template + typename M::size_type lu_factorize (M &m, PM &pm) { + typedef M matrix_type; + typedef typename M::size_type size_type; + typedef typename M::value_type value_type; + +#if BOOST_UBLAS_TYPE_CHECK + matrix_type cm (m); +#endif + int singular = 0; + size_type size1 = m.size1 (); + size_type size2 = m.size2 (); + size_type size = (std::min) (size1, size2); + for (size_type i = 0; i < size; ++ i) { + matrix_column mci (column (m, i)); + matrix_row mri (row (m, i)); + size_type i_norm_inf = i + index_norm_inf (project (mci, range (i, size1))); + BOOST_UBLAS_CHECK (i_norm_inf < size1, external_logic ()); + if (m (i_norm_inf, i) != value_type/*zero*/()) { + if (i_norm_inf != i) { + pm (i) = i_norm_inf; + row (m, i_norm_inf).swap (mri); + } else { + BOOST_UBLAS_CHECK (pm (i) == i_norm_inf, external_logic ()); + } + project (mci, range (i + 1, size1)) *= value_type (1) / m (i, i); + } else if (singular == 0) { + singular = i + 1; + } + project (m, range (i + 1, size1), range (i + 1, size2)).minus_assign ( + outer_prod (project (mci, range (i + 1, size1)), + project (mri, range (i + 1, size2)))); + } +#if BOOST_UBLAS_TYPE_CHECK + swap_rows (pm, cm); + BOOST_UBLAS_CHECK (singular != 0 || + detail::expression_type_check (prod (triangular_adaptor (m), + triangular_adaptor (m)), cm), internal_logic ()); +#endif + return singular; + } + + template + typename M::size_type axpy_lu_factorize (M &m, PM &pm) { + typedef M matrix_type; + typedef typename M::size_type size_type; + typedef typename M::value_type value_type; + typedef vector vector_type; + +#if BOOST_UBLAS_TYPE_CHECK + matrix_type cm (m); +#endif + int singular = 0; + size_type size1 = m.size1 (); + size_type size2 = m.size2 (); + size_type size = (std::min) (size1, size2); +#ifndef BOOST_UBLAS_LU_WITH_INPLACE_SOLVE + matrix_type mr (m); + mr.assign (zero_matrix (size1, size2)); + vector_type v (size1); + for (size_type i = 0; i < size; ++ i) { + matrix_range lrr (project (mr, range (0, i), range (0, i))); + vector_range > urr (project (column (mr, i), range (0, i))); + urr.assign (solve (lrr, project (column (m, i), range (0, i)), unit_lower_tag ())); + project (v, range (i, size1)).assign ( + project (column (m, i), range (i, size1)) - + axpy_prod (project (mr, range (i, size1), range (0, i)), urr)); + size_type i_norm_inf = i + index_norm_inf (project (v, range (i, size1))); + BOOST_UBLAS_CHECK (i_norm_inf < size1, external_logic ()); + if (v (i_norm_inf) != value_type/*zero*/()) { + if (i_norm_inf != i) { + pm (i) = i_norm_inf; + std::swap (v (i_norm_inf), v (i)); + project (row (m, i_norm_inf), range (i + 1, size2)).swap (project (row (m, i), range (i + 1, size2))); + } else { + BOOST_UBLAS_CHECK (pm (i) == i_norm_inf, external_logic ()); + } + project (column (mr, i), range (i + 1, size1)).assign ( + project (v, range (i + 1, size1)) / v (i)); + if (i_norm_inf != i) { + project (row (mr, i_norm_inf), range (0, i)).swap (project (row (mr, i), range (0, i))); + } + } else if (singular == 0) { + singular = i + 1; + } + mr (i, i) = v (i); + } + m.assign (mr); +#else + matrix_type lr (m); + matrix_type ur (m); + lr.assign (identity_matrix (size1, size2)); + ur.assign (zero_matrix (size1, size2)); + vector_type v (size1); + for (size_type i = 0; i < size; ++ i) { + matrix_range lrr (project (lr, range (0, i), range (0, i))); + vector_range > urr (project (column (ur, i), range (0, i))); + urr.assign (project (column (m, i), range (0, i))); + inplace_solve (lrr, urr, unit_lower_tag ()); + project (v, range (i, size1)).assign ( + project (column (m, i), range (i, size1)) - + axpy_prod (project (lr, range (i, size1), range (0, i)), urr)); + size_type i_norm_inf = i + index_norm_inf (project (v, range (i, size1))); + BOOST_UBLAS_CHECK (i_norm_inf < size1, external_logic ()); + if (v (i_norm_inf) != value_type/*zero*/()) { + if (i_norm_inf != i) { + pm (i) = i_norm_inf; + std::swap (v (i_norm_inf), v (i)); + project (row (m, i_norm_inf), range (i + 1, size2)).swap (project (row (m, i), range (i + 1, size2))); + } else { + BOOST_UBLAS_CHECK (pm (i) == i_norm_inf, external_logic ()); + } + project (column (lr, i), range (i + 1, size1)).assign ( + project (v, range (i + 1, size1)) / v (i)); + if (i_norm_inf != i) { + project (row (lr, i_norm_inf), range (0, i)).swap (project (row (lr, i), range (0, i))); + } + } else if (singular == 0) { + singular = i + 1; + } + ur (i, i) = v (i); + } + m.assign (triangular_adaptor (lr) + + triangular_adaptor (ur)); +#endif +#if BOOST_UBLAS_TYPE_CHECK + swap_rows (pm, cm); + BOOST_UBLAS_CHECK (singular != 0 || + detail::expression_type_check (prod (triangular_adaptor (m), + triangular_adaptor (m)), cm), internal_logic ()); +#endif + return singular; + } + + // LU substitution + template + void lu_substitute (const M &m, vector_expression &e) { + typedef const M const_matrix_type; + typedef vector vector_type; + +#if BOOST_UBLAS_TYPE_CHECK + vector_type cv1 (e); +#endif + inplace_solve (m, e, unit_lower_tag ()); +#if BOOST_UBLAS_TYPE_CHECK + BOOST_UBLAS_CHECK (detail::expression_type_check (prod (triangular_adaptor (m), e), cv1), internal_logic ()); + vector_type cv2 (e); +#endif + inplace_solve (m, e, upper_tag ()); +#if BOOST_UBLAS_TYPE_CHECK + BOOST_UBLAS_CHECK (detail::expression_type_check (prod (triangular_adaptor (m), e), cv2), internal_logic ()); +#endif + } + template + void lu_substitute (const M &m, matrix_expression &e) { + typedef const M const_matrix_type; + typedef matrix matrix_type; + +#if BOOST_UBLAS_TYPE_CHECK + matrix_type cm1 (e); +#endif + inplace_solve (m, e, unit_lower_tag ()); +#if BOOST_UBLAS_TYPE_CHECK + BOOST_UBLAS_CHECK (detail::expression_type_check (prod (triangular_adaptor (m), e), cm1), internal_logic ()); + matrix_type cm2 (e); +#endif + inplace_solve (m, e, upper_tag ()); +#if BOOST_UBLAS_TYPE_CHECK + BOOST_UBLAS_CHECK (detail::expression_type_check (prod (triangular_adaptor (m), e), cm2), internal_logic ()); +#endif + } + template + void lu_substitute (const M &m, const permutation_matrix &pm, MV &mv) { + swap_rows (pm, mv); + lu_substitute (m, mv); + } + template + void lu_substitute (vector_expression &e, const M &m) { + typedef const M const_matrix_type; + typedef vector vector_type; + +#if BOOST_UBLAS_TYPE_CHECK + vector_type cv1 (e); +#endif + inplace_solve (e, m, upper_tag ()); +#if BOOST_UBLAS_TYPE_CHECK + BOOST_UBLAS_CHECK (detail::expression_type_check (prod (e, triangular_adaptor (m)), cv1), internal_logic ()); + vector_type cv2 (e); +#endif + inplace_solve (e, m, unit_lower_tag ()); +#if BOOST_UBLAS_TYPE_CHECK + BOOST_UBLAS_CHECK (detail::expression_type_check (prod (e, triangular_adaptor (m)), cv2), internal_logic ()); +#endif + } + template + void lu_substitute (matrix_expression &e, const M &m) { + typedef const M const_matrix_type; + typedef matrix matrix_type; + +#if BOOST_UBLAS_TYPE_CHECK + matrix_type cm1 (e); +#endif + inplace_solve (e, m, upper_tag ()); +#if BOOST_UBLAS_TYPE_CHECK + BOOST_UBLAS_CHECK (detail::expression_type_check (prod (e, triangular_adaptor (m)), cm1), internal_logic ()); + matrix_type cm2 (e); +#endif + inplace_solve (e, m, unit_lower_tag ()); +#if BOOST_UBLAS_TYPE_CHECK + BOOST_UBLAS_CHECK (detail::expression_type_check (prod (e, triangular_adaptor (m)), cm2), internal_logic ()); +#endif + } + template + void lu_substitute (MV &mv, const M &m, const permutation_matrix &pm) { + swap_rows (pm, mv); + lu_substitute (mv, m); + } + +}}} + +#endif