00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifndef _CHOLESKY_DECOMPOSITION_H
00020 #define _CHOLESKY_DECOMPOSITION_H
00021
00022 #include <limits>
00023
00024 #include <boost/numeric/ublas/matrix.hpp>
00025 #include <boost/numeric/ublas/matrix_proxy.hpp>
00026 #include <boost/numeric/ublas/banded.hpp>
00027 #include <boost/numeric/ublas/triangular.hpp>
00028 #include <boost/numeric/ublas/vector_proxy.hpp>
00029
00030 using namespace boost::numeric::ublas;
00031
00032 namespace lsp{
00033
00034
00057 template<class M> void cholesky_decomposition( M& m, const upper_tag& ){
00058 typedef M matrix_type;
00059 typedef typename matrix_type::value_type value_type;
00060 typedef typename matrix_type::size_type size_type;
00061 typedef triangular_adaptor< matrix_type, upper > triangular_type;
00062
00063 assert( m.size1() == m.size2() );
00064
00065 triangular_type R(m);
00066 value_type v;
00067 for( size_type i=0; i < m.size1(); ++i ) {
00068 v = m(i,i) - inner_prod( project( column(R,i), range(0,i) ), project( column(R,i), range(0,i) ) );
00069 if( std::abs(v) < ( ( 1 + 2 * i ) + 2 ) * std::numeric_limits< value_type >::epsilon() || v < value_type(0) ) {
00070 R(i,i) = 0;
00071 for( size_type j=i+1; j < m.size2(); ++j ) {
00072 R(i,j) = 0;
00073 }
00074 continue;
00075 }
00076 R(i,i) = sqrt(v);
00077 for( size_type j=i+1; j < m.size2(); ++j ) {
00078 R(i,j) = ( m(i,j) - inner_prod( project( column(R,i), range(0,i) ), project( column(R,j), range(0,i) ) ) ) / R(i,i);
00079 }
00080 }
00081 }
00104 template<class M> void cholesky_decomposition( M& m, const unit_upper_tag& ){
00105 typedef M matrix_type;
00106 typedef typename matrix_type::value_type value_type;
00107 typedef typename matrix_type::size_type size_type;
00108 typedef triangular_adaptor< matrix_type, unit_upper > triangular_type;
00109 typedef banded_adaptor< matrix_type > diagonal_type;
00110
00111 assert( m.size1() == m.size2() );
00112
00113 triangular_type R(m);
00114 diagonal_type D(m);
00115 for( size_type i=0; i < m.size1(); ++i ) {
00116 D(i,i) = m(i,i);
00117 if( D(i,i) == value_type(0) ) {
00118 for( size_type j=i+1; j < m.size2(); ++j ) {
00119 R(i,j) = 0;
00120 }
00121 continue;
00122 }
00123 for( size_type j=i+1; j < m.size2(); ++j ) {
00124 R(i,j)=m(i,j) / D(i,i);
00125 for( size_type k=i+1; k < j; ++k ){
00126 m(k,j) -= R(i,j)*D(i,i)*R(i,k);
00127 }
00128 }
00129 }
00130 }
00138 template<class M> void cholesky_decomposition( M& m, const lower_tag& ){
00139 cholesky_decomposition( trans(m), upper_tag() );
00140 }
00141 template<class M> void cholesky_decomposition( M& m ){
00142 cholesky_decomposition( m, upper_tag() );
00143 }
00151 template<class M> void cholesky_decomposition( M& m, const unit_lower_tag& ){
00152 cholesky_decomposition( trans(m), unit_upper_tag() );
00153 }
00154 };
00155 #endif // _CHOLESKY_DECOMPOSITION_H
00156