00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifndef _HOUSEHOLDER_TRANSFORM_H
00020 #define _HOUSEHOLDER_TRANSFORM_H
00021
00022 #include <lsp/utils.h>
00023
00024 #include <algorithm>
00025 #include <limits>
00026
00027 #include <boost/numeric/ublas/vector.hpp>
00028 #include <boost/numeric/ublas/matrix.hpp>
00029
00030 using namespace boost::numeric::ublas;
00031
00032 namespace lsp{
00033
00057 template< class T > class householder_transform {
00058 public:
00059 typedef T vector_type;
00060 typedef typename vector_type::value_type value_type;
00061 typedef typename vector_type::size_type size_type;
00062
00063 private:
00064 size_type m_l;
00065 size_type m_p;
00066 value_type m_s;
00067 value_type m_h;
00068 vector_type m_v;
00069
00070 public:
00081 householder_transform( size_type l, size_type p, vector_type v ):
00082 m_l( l ), m_p( p ), m_s( 0 ), m_v(v) {
00083 const size_type m = v.size();
00084
00085 assert( p < l );
00086 assert( p >= 0 );
00087 assert( p < m );
00088
00089 value_type w;
00090
00091 if( l < m )
00092 w = std::abs( std::max( v(p), *( std::max_element( v.begin() + l, v.end(), less_abs< value_type >() ) ), less_abs< value_type >() ) );
00093 else {
00094 m_h = 2 * v(p);
00095 m_s = -v(p);
00096 return;
00097 }
00098
00099 if( w != 0 ){
00100 m_s += ( v(p)/w )*( v(p)/w );
00101 for( size_type i = l; i < m; ++i )
00102 m_s += ( v(i)/w )*( v(i)/w );
00103 m_s = ( v(p) < 0 ? 1 : -1 ) * w * std::pow( m_s, 0.5 );
00104 } else {
00105 m_s = 0;
00106 }
00107
00108 m_h = v(p) - m_s;
00109 }
00110
00111 template<class M> void apply ( matrix_row<M> v ) const {
00112 apply( v, vector_tag() );
00113 }
00114 template<class M> void apply ( matrix_column<M> v ) const {
00115 apply( v, vector_tag() );
00116 }
00117 template<class U> void apply ( U& v ) const {
00118 apply( v, vector_tag() );
00119 }
00120 template<class U> void apply ( U v, vector_tag ) const {
00121 typedef U vector2_type;
00122
00123 assert( m_v.size() == v.size() );
00124
00125 const value_type b = m_s * m_h;
00126 if( b == 0 )
00127 return;
00128
00129 value_type s = v(m_p) * m_h;
00130 for( size_type i = m_l; i < v.size(); i++ )
00131 s += v(i) * m_v(i);
00132 s = s / b;
00133
00134 v(m_p) += s * m_h;
00135 for( size_type i = m_l; i < v.size(); i++ )
00136 v(i) += s * m_v(i);
00137 }
00146 template<class U> void apply ( U& w, row_major_tag ) const {
00147 for( size_type i = 0; i < w.size2(); ++i )
00148 apply( column( w, i ) );
00149 }
00150 template<class U> void apply ( U& w, column_major_tag ) const {
00151 for( size_type i = 0; i < w.size1(); ++i )
00152 apply( row( w, i ) );
00153 }
00154
00158 inline const value_type s() const { return m_s; }
00162 inline const value_type h() const { return m_h; }
00163 };
00164
00165 };
00166
00167 #endif // _HOUSEHOLDER_TRANSFORM_H