00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #ifndef EIGEN_HESSENBERGDECOMPOSITION_H
00026 #define EIGEN_HESSENBERGDECOMPOSITION_H
00027
00042 template<typename _MatrixType> class HessenbergDecomposition
00043 {
00044 public:
00045
00046 typedef _MatrixType MatrixType;
00047 typedef typename MatrixType::Scalar Scalar;
00048 typedef typename NumTraits<Scalar>::Real RealScalar;
00049
00050 enum {
00051 Size = MatrixType::RowsAtCompileTime,
00052 SizeMinusOne = MatrixType::RowsAtCompileTime==Dynamic
00053 ? Dynamic
00054 : MatrixType::RowsAtCompileTime-1
00055 };
00056
00057 typedef Matrix<Scalar, SizeMinusOne, 1> CoeffVectorType;
00058 typedef Matrix<RealScalar, Size, 1> DiagonalType;
00059 typedef Matrix<RealScalar, SizeMinusOne, 1> SubDiagonalType;
00060
00061 typedef typename NestByValue<DiagonalCoeffs<MatrixType> >::RealReturnType DiagonalReturnType;
00062
00063 typedef typename NestByValue<DiagonalCoeffs<
00064 NestByValue<Block<MatrixType,SizeMinusOne,SizeMinusOne> > > >::RealReturnType SubDiagonalReturnType;
00065
00069 HessenbergDecomposition(int size = Size==Dynamic ? 2 : Size)
00070 : m_matrix(size,size), m_hCoeffs(size-1)
00071 {}
00072
00073 HessenbergDecomposition(const MatrixType& matrix)
00074 : m_matrix(matrix),
00075 m_hCoeffs(matrix.cols()-1)
00076 {
00077 _compute(m_matrix, m_hCoeffs);
00078 }
00079
00084 void compute(const MatrixType& matrix)
00085 {
00086 m_matrix = matrix;
00087 m_hCoeffs.resize(matrix.rows()-1,1);
00088 _compute(m_matrix, m_hCoeffs);
00089 }
00090
00096 CoeffVectorType householderCoefficients(void) const { return m_hCoeffs; }
00097
00113 const MatrixType& packedMatrix(void) const { return m_matrix; }
00114
00115 MatrixType matrixQ(void) const;
00116 MatrixType matrixH(void) const;
00117
00118 private:
00119
00120 static void _compute(MatrixType& matA, CoeffVectorType& hCoeffs);
00121
00122 protected:
00123 MatrixType m_matrix;
00124 CoeffVectorType m_hCoeffs;
00125 };
00126
00127 #ifndef EIGEN_HIDE_HEAVY_CODE
00128
00141 template<typename MatrixType>
00142 void HessenbergDecomposition<MatrixType>::_compute(MatrixType& matA, CoeffVectorType& hCoeffs)
00143 {
00144 assert(matA.rows()==matA.cols());
00145 int n = matA.rows();
00146 for (int i = 0; i<n-2; ++i)
00147 {
00148
00149
00150
00151
00152 RealScalar v1norm2 = matA.col(i).end(n-(i+2)).squaredNorm();
00153
00154 if (ei_isMuchSmallerThan(v1norm2,static_cast<Scalar>(1)))
00155 {
00156 hCoeffs.coeffRef(i) = 0.;
00157 }
00158 else
00159 {
00160 Scalar v0 = matA.col(i).coeff(i+1);
00161 RealScalar beta = ei_sqrt(ei_abs2(v0)+v1norm2);
00162 if (ei_real(v0)>=0.)
00163 beta = -beta;
00164 matA.col(i).end(n-(i+2)) *= (Scalar(1)/(v0-beta));
00165 matA.col(i).coeffRef(i+1) = beta;
00166 Scalar h = (beta - v0) / beta;
00167
00168
00169
00170
00171 matA.col(i).coeffRef(i+1) = 1;
00172
00173
00174 matA.corner(BottomRight,n-i-1,n-i-1) -= ((ei_conj(h) * matA.col(i).end(n-i-1)) *
00175 (matA.col(i).end(n-i-1).adjoint() * matA.corner(BottomRight,n-i-1,n-i-1))).lazy();
00176
00177
00178 matA.corner(BottomRight,n,n-i-1) -= ((matA.corner(BottomRight,n,n-i-1) * matA.col(i).end(n-i-1))
00179 * (h * matA.col(i).end(n-i-1).adjoint())).lazy();
00180
00181 matA.col(i).coeffRef(i+1) = beta;
00182 hCoeffs.coeffRef(i) = h;
00183 }
00184 }
00185 if (NumTraits<Scalar>::IsComplex)
00186 {
00187
00188 int i = n-2;
00189 Scalar v0 = matA.coeff(i+1,i);
00190
00191 RealScalar beta = ei_sqrt(ei_abs2(v0));
00192 if (ei_real(v0)>=0.)
00193 beta = -beta;
00194 Scalar h = (beta - v0) / beta;
00195 hCoeffs.coeffRef(i) = h;
00196
00197
00198 matA.corner(BottomRight,n-i-1,n-i) -= ei_conj(h) * matA.corner(BottomRight,n-i-1,n-i);
00199
00200
00201 matA.col(n-1) -= h * matA.col(n-1);
00202 }
00203 else
00204 {
00205 hCoeffs.coeffRef(n-2) = 0;
00206 }
00207 }
00208
00210 template<typename MatrixType>
00211 typename HessenbergDecomposition<MatrixType>::MatrixType
00212 HessenbergDecomposition<MatrixType>::matrixQ(void) const
00213 {
00214 int n = m_matrix.rows();
00215 MatrixType matQ = MatrixType::Identity(n,n);
00216 for (int i = n-2; i>=0; i--)
00217 {
00218 Scalar tmp = m_matrix.coeff(i+1,i);
00219 m_matrix.const_cast_derived().coeffRef(i+1,i) = 1;
00220
00221 matQ.corner(BottomRight,n-i-1,n-i-1) -=
00222 ((m_hCoeffs.coeff(i) * m_matrix.col(i).end(n-i-1)) *
00223 (m_matrix.col(i).end(n-i-1).adjoint() * matQ.corner(BottomRight,n-i-1,n-i-1)).lazy()).lazy();
00224
00225 m_matrix.const_cast_derived().coeffRef(i+1,i) = tmp;
00226 }
00227 return matQ;
00228 }
00229
00230 #endif // EIGEN_HIDE_HEAVY_CODE
00231
00237 template<typename MatrixType>
00238 typename HessenbergDecomposition<MatrixType>::MatrixType
00239 HessenbergDecomposition<MatrixType>::matrixH(void) const
00240 {
00241
00242
00243 int n = m_matrix.rows();
00244 MatrixType matH = m_matrix;
00245 if (n>2)
00246 matH.corner(BottomLeft,n-2, n-2).template part<LowerTriangular>().setZero();
00247 return matH;
00248 }
00249
00250 #endif // EIGEN_HESSENBERGDECOMPOSITION_H