00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #ifndef MTL_MATRIX_HESSENBERG_INCLUDE
00015 #define MTL_MATRIX_HESSENBERG_INCLUDE
00016
00017 #include <cmath>
00018 #include <boost/numeric/linear_algebra/identity.hpp>
00019 #include <boost/numeric/mtl/utility/exception.hpp>
00020 #include <boost/numeric/mtl/utility/irange.hpp>
00021 #include <boost/numeric/mtl/concept/collection.hpp>
00022 #include <boost/numeric/mtl/concept/magnitude.hpp>
00023 #include <boost/numeric/mtl/operation/householder.hpp>
00024 #include <boost/numeric/mtl/operation/rank_one_update.hpp>
00025 #include <boost/numeric/mtl/operation/trans.hpp>
00026
00027
00028 namespace mtl { namespace matrix {
00029
00031
00032 template <typename Matrix>
00033 Matrix inline hessenberg_factors(const Matrix& A)
00034 {
00035 using mtl::imax;
00036 typedef typename Collection<Matrix>::value_type value_type;
00037 typedef typename Collection<Matrix>::size_type size_type;
00038 size_type ncols = num_cols(A), nrows = num_rows(A);
00039 value_type zero= math::zero(A[0][0]), beta;
00040 Matrix B(A);
00041
00042 MTL_THROW_IF(num_rows(A) < 3, matrix_too_small());
00043
00044 for(size_type i= 0; i < ncols-2; i++){
00045
00046 dense_vector<value_type> v(nrows-i-1), w(nrows-i);
00047 for (size_type j = 0; j < size(v); j++)
00048 v[j]= B[j+i+1][i];
00049
00050 beta= householder(v).second;
00051 v= householder(v).first;
00052 if( beta != zero){
00053 w= beta * A[irange(0,imax)][irange(i+1,imax)] * v;
00054
00055 for(size_type row = 0; row < nrows; row++){
00056 for(size_type col = i+1; col < ncols; col++){
00057 B[row][col] -= w[row] * v[col-1];
00058 }
00059 }
00060
00061 for(size_type k=0; k < size(w); k++){
00062 w[k]= zero;
00063 for(size_type j = 0; j < size(v); j++){
00064 w[k] += beta * v[j] * B[j+i+1][k+i];
00065 }
00066 }
00067
00068 for(size_type row = i+1; row < nrows; row++){
00069 for(size_type col = 0; col < ncols; col++){
00070 B[row][col] -= v[row-1] * w[col];
00071 }
00072 }
00073
00074 for(size_type row = i+2; row < nrows; row++){
00075 B[row][i] = v[row-i-1];
00076 }
00077 }
00078 }
00079 return B;
00080 }
00081
00082
00084 template <typename Matrix>
00085 Matrix inline extract_householder_hessenberg(const Matrix& H)
00086 {
00087 return Matrix(tril(H, -2));
00088 }
00089
00091 template <typename Matrix>
00092 Matrix inline householder_hessenberg(const Matrix& A)
00093 {
00094 return Matrix(tril(hessenberg_factors(A), -2));
00095 }
00096
00097
00099 template <typename Matrix>
00100 Matrix inline extract_hessenberg(const Matrix& H)
00101 {
00102 return Matrix(triu(H, -1));
00103 }
00104
00106 template <typename Matrix>
00107 Matrix inline hessenberg(const Matrix& A)
00108 {
00109
00110
00111
00112 typedef typename Collection<Matrix>::value_type value_type;
00113 typedef typename Magnitude<value_type>::type magnitude_type;
00114 typedef typename Collection<Matrix>::size_type size_type;
00115 size_type ncols = num_cols(A), nrows = num_rows(A);
00116 value_type zero= math::zero(A[0][0]);
00117 Matrix H(nrows,ncols);
00118
00119 MTL_THROW_IF(num_rows(A) < 3, matrix_too_small());
00120 H= hessenberg_factors(A);
00121
00122
00123 for(size_type row = 2; row < nrows; row++){
00124 for(size_type col = 0; col < row-1; col++){
00125 H[row][col]= zero;
00126 }
00127 }
00128
00129 return H;
00130 }
00131
00132
00134 template <typename Matrix>
00135 Matrix inline hessenberg_q(const Matrix& A)
00136 {
00137 typedef typename Collection<Matrix>::value_type value_type;
00138 typedef typename Magnitude<value_type>::type magnitude_type;
00139 typedef typename Collection<Matrix>::size_type size_type;
00140 size_type ncols = num_cols(A), nrows = num_rows(A), mini;
00141 value_type zero= math::zero(A[0][0]), one= math::one(A[0][0]);
00142 const magnitude_type two(2);
00143 Matrix Q(nrows,ncols);
00144
00145 MTL_THROW_IF(num_rows(A) < 3, matrix_too_small());
00146
00147 Q= one;
00148
00149
00150 for(size_type i = 0; i < nrows-2; i++){
00151 dense_vector<value_type> v(nrows-i-1), w(nrows-i);
00152 v[0]= one;
00153 for(size_type k = 1; k < size(v); k++)
00154 v[k]= A[nrows-k][i];
00155
00156 magnitude_type beta= two / abs(dot(v, v));
00157 if (beta != two) {
00158
00159 for(size_type k = 0; k < size(w); k++) {
00160 w[k]= zero;
00161 for(size_type j = 0; j < size(v); j++)
00162 w[k]+= beta * v[j] * Q[j+i+1][k+i];
00163 }
00164
00165 for(size_type row = i+1; row < nrows; row++)
00166 for(size_type col = 0; col < ncols; col++)
00167 Q[row][col] -= v[row-1] * w[col];
00168 }
00169
00170 }
00171 return Q;
00172 }
00173
00174
00175 }}
00176
00177 #endif // MTL_MATRIX_HESSENBERG_INCLUDE
00178