00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifndef _BIDIAGONAL_TRANSFORM_H
00020 #define _BIDIAGONAL_TRANSFORM_H
00021
00022 #include <lsp/householder_transform.h>
00023
00024 #include <limits>
00025
00026 #include <boost/numeric/ublas/matrix.hpp>
00027 #include <boost/numeric/ublas/matrix_proxy.hpp>
00028 #include <boost/numeric/ublas/vector.hpp>
00029
00030 namespace lsp{
00031
00050 template<class T> class bidiagonal_transform {
00051 public:
00052 typedef T matrix_type;
00053 typedef typename matrix_type::value_type value_type;
00054 typedef typename matrix_type::size_type size_type;
00055
00056 private:
00057 matrix_type& m_matrix;
00058 size_type m_min_size;
00059 size_type m_max_size;
00060
00061 public:
00069 bidiagonal_transform( matrix_type& matrix ):
00070 m_matrix( matrix ),
00071 m_min_size( std::min( matrix.size1(), matrix.size2() ) ),
00072 m_max_size( std::max( matrix.size1(), matrix.size2() ) ) {
00073
00074 }
00075
00091 template<class M1, class M2> void apply( M1& left, M2& right ) const {
00092 typedef vector< value_type > vector_type;
00093 typedef householder_transform< vector_type > householder_transform_type;
00094
00095 assert( left.size1() == m_matrix.size1() );
00096 assert( right.size1() == m_matrix.size2() );
00097
00098 size_type i = 0;
00099
00100 if( m_min_size == 0 )
00101 return ;
00102
00103 for( i = 0; i < m_min_size - 1; ++i ){
00104 householder_transform_type hleft( i+1, i, column(m_matrix,i) );
00105 hleft.apply( left, row_major_tag() );
00106 hleft.apply( m_matrix, row_major_tag() );
00107
00108 householder_transform_type hright( i+2, i+1, row(m_matrix,i) );
00109 hright.apply( right, column_major_tag() );
00110 hright.apply( m_matrix, column_major_tag() );
00111 }
00112
00113 householder_transform_type hleft( i+1, i, column(m_matrix,i) );
00114 hleft.apply( left, row_major_tag() );
00115 hleft.apply( m_matrix, row_major_tag() );
00116 }
00117
00124 value_type left_error() const {
00125 return std::abs( ( 4 * m_matrix.size1() + 32 ) * ( 2 * m_min_size - 1 ) * std::numeric_limits< value_type >::epsilon() );
00126 }
00127
00134 value_type right_error() const {
00135 return std::abs( ( 4 * m_matrix.size2() + 32 ) * ( 2 * m_min_size - 1 ) * std::numeric_limits< value_type >::epsilon() );
00136 }
00137
00144 value_type matrix_error() const {
00145 return std::abs( ( 6 * m_matrix.size1() - 3 * m_min_size + 40 ) * ( 2 * m_min_size - 1 ) * std::numeric_limits< value_type >::epsilon() );
00146 }
00147 };
00148
00149 };
00150
00151 #endif // _BIDIAGONAL_TRANSFORM_H