Warning, file /include/eigen3/Eigen/src/Eigenvalues/ComplexSchur.h was not indexed
or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #ifndef EIGEN_COMPLEX_SCHUR_H
0013 #define EIGEN_COMPLEX_SCHUR_H
0014
0015 #include "./HessenbergDecomposition.h"
0016
0017 namespace Eigen {
0018
0019 namespace internal {
0020 template<typename MatrixType, bool IsComplex> struct complex_schur_reduce_to_hessenberg;
0021 }
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051 template<typename _MatrixType> class ComplexSchur
0052 {
0053 public:
0054 typedef _MatrixType MatrixType;
0055 enum {
0056 RowsAtCompileTime = MatrixType::RowsAtCompileTime,
0057 ColsAtCompileTime = MatrixType::ColsAtCompileTime,
0058 Options = MatrixType::Options,
0059 MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
0060 MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime
0061 };
0062
0063
0064 typedef typename MatrixType::Scalar Scalar;
0065 typedef typename NumTraits<Scalar>::Real RealScalar;
0066 typedef Eigen::Index Index;
0067
0068
0069
0070
0071
0072
0073
0074 typedef std::complex<RealScalar> ComplexScalar;
0075
0076
0077
0078
0079
0080
0081 typedef Matrix<ComplexScalar, RowsAtCompileTime, ColsAtCompileTime, Options, MaxRowsAtCompileTime, MaxColsAtCompileTime> ComplexMatrixType;
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094 explicit ComplexSchur(Index size = RowsAtCompileTime==Dynamic ? 1 : RowsAtCompileTime)
0095 : m_matT(size,size),
0096 m_matU(size,size),
0097 m_hess(size),
0098 m_isInitialized(false),
0099 m_matUisUptodate(false),
0100 m_maxIters(-1)
0101 {}
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112 template<typename InputType>
0113 explicit ComplexSchur(const EigenBase<InputType>& matrix, bool computeU = true)
0114 : m_matT(matrix.rows(),matrix.cols()),
0115 m_matU(matrix.rows(),matrix.cols()),
0116 m_hess(matrix.rows()),
0117 m_isInitialized(false),
0118 m_matUisUptodate(false),
0119 m_maxIters(-1)
0120 {
0121 compute(matrix.derived(), computeU);
0122 }
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138 const ComplexMatrixType& matrixU() const
0139 {
0140 eigen_assert(m_isInitialized && "ComplexSchur is not initialized.");
0141 eigen_assert(m_matUisUptodate && "The matrix U has not been computed during the ComplexSchur decomposition.");
0142 return m_matU;
0143 }
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156
0157
0158
0159
0160
0161
0162 const ComplexMatrixType& matrixT() const
0163 {
0164 eigen_assert(m_isInitialized && "ComplexSchur is not initialized.");
0165 return m_matT;
0166 }
0167
0168
0169
0170
0171
0172
0173
0174
0175
0176
0177
0178
0179
0180
0181
0182
0183
0184
0185
0186
0187
0188
0189
0190 template<typename InputType>
0191 ComplexSchur& compute(const EigenBase<InputType>& matrix, bool computeU = true);
0192
0193
0194
0195
0196
0197
0198
0199
0200
0201
0202
0203
0204
0205
0206
0207
0208
0209
0210 template<typename HessMatrixType, typename OrthMatrixType>
0211 ComplexSchur& computeFromHessenberg(const HessMatrixType& matrixH, const OrthMatrixType& matrixQ, bool computeU=true);
0212
0213
0214
0215
0216
0217 ComputationInfo info() const
0218 {
0219 eigen_assert(m_isInitialized && "ComplexSchur is not initialized.");
0220 return m_info;
0221 }
0222
0223
0224
0225
0226
0227
0228 ComplexSchur& setMaxIterations(Index maxIters)
0229 {
0230 m_maxIters = maxIters;
0231 return *this;
0232 }
0233
0234
0235 Index getMaxIterations()
0236 {
0237 return m_maxIters;
0238 }
0239
0240
0241
0242
0243
0244
0245 static const int m_maxIterationsPerRow = 30;
0246
0247 protected:
0248 ComplexMatrixType m_matT, m_matU;
0249 HessenbergDecomposition<MatrixType> m_hess;
0250 ComputationInfo m_info;
0251 bool m_isInitialized;
0252 bool m_matUisUptodate;
0253 Index m_maxIters;
0254
0255 private:
0256 bool subdiagonalEntryIsNeglegible(Index i);
0257 ComplexScalar computeShift(Index iu, Index iter);
0258 void reduceToTriangularForm(bool computeU);
0259 friend struct internal::complex_schur_reduce_to_hessenberg<MatrixType, NumTraits<Scalar>::IsComplex>;
0260 };
0261
0262
0263
0264
0265 template<typename MatrixType>
0266 inline bool ComplexSchur<MatrixType>::subdiagonalEntryIsNeglegible(Index i)
0267 {
0268 RealScalar d = numext::norm1(m_matT.coeff(i,i)) + numext::norm1(m_matT.coeff(i+1,i+1));
0269 RealScalar sd = numext::norm1(m_matT.coeff(i+1,i));
0270 if (internal::isMuchSmallerThan(sd, d, NumTraits<RealScalar>::epsilon()))
0271 {
0272 m_matT.coeffRef(i+1,i) = ComplexScalar(0);
0273 return true;
0274 }
0275 return false;
0276 }
0277
0278
0279
0280 template<typename MatrixType>
0281 typename ComplexSchur<MatrixType>::ComplexScalar ComplexSchur<MatrixType>::computeShift(Index iu, Index iter)
0282 {
0283 using std::abs;
0284 if (iter == 10 || iter == 20)
0285 {
0286
0287 return abs(numext::real(m_matT.coeff(iu,iu-1))) + abs(numext::real(m_matT.coeff(iu-1,iu-2)));
0288 }
0289
0290
0291
0292 Matrix<ComplexScalar,2,2> t = m_matT.template block<2,2>(iu-1,iu-1);
0293 RealScalar normt = t.cwiseAbs().sum();
0294 t /= normt;
0295
0296 ComplexScalar b = t.coeff(0,1) * t.coeff(1,0);
0297 ComplexScalar c = t.coeff(0,0) - t.coeff(1,1);
0298 ComplexScalar disc = sqrt(c*c + RealScalar(4)*b);
0299 ComplexScalar det = t.coeff(0,0) * t.coeff(1,1) - b;
0300 ComplexScalar trace = t.coeff(0,0) + t.coeff(1,1);
0301 ComplexScalar eival1 = (trace + disc) / RealScalar(2);
0302 ComplexScalar eival2 = (trace - disc) / RealScalar(2);
0303 RealScalar eival1_norm = numext::norm1(eival1);
0304 RealScalar eival2_norm = numext::norm1(eival2);
0305
0306
0307 if(eival1_norm > eival2_norm)
0308 eival2 = det / eival1;
0309 else if(eival2_norm!=RealScalar(0))
0310 eival1 = det / eival2;
0311
0312
0313 if(numext::norm1(eival1-t.coeff(1,1)) < numext::norm1(eival2-t.coeff(1,1)))
0314 return normt * eival1;
0315 else
0316 return normt * eival2;
0317 }
0318
0319
0320 template<typename MatrixType>
0321 template<typename InputType>
0322 ComplexSchur<MatrixType>& ComplexSchur<MatrixType>::compute(const EigenBase<InputType>& matrix, bool computeU)
0323 {
0324 m_matUisUptodate = false;
0325 eigen_assert(matrix.cols() == matrix.rows());
0326
0327 if(matrix.cols() == 1)
0328 {
0329 m_matT = matrix.derived().template cast<ComplexScalar>();
0330 if(computeU) m_matU = ComplexMatrixType::Identity(1,1);
0331 m_info = Success;
0332 m_isInitialized = true;
0333 m_matUisUptodate = computeU;
0334 return *this;
0335 }
0336
0337 internal::complex_schur_reduce_to_hessenberg<MatrixType, NumTraits<Scalar>::IsComplex>::run(*this, matrix.derived(), computeU);
0338 computeFromHessenberg(m_matT, m_matU, computeU);
0339 return *this;
0340 }
0341
0342 template<typename MatrixType>
0343 template<typename HessMatrixType, typename OrthMatrixType>
0344 ComplexSchur<MatrixType>& ComplexSchur<MatrixType>::computeFromHessenberg(const HessMatrixType& matrixH, const OrthMatrixType& matrixQ, bool computeU)
0345 {
0346 m_matT = matrixH;
0347 if(computeU)
0348 m_matU = matrixQ;
0349 reduceToTriangularForm(computeU);
0350 return *this;
0351 }
0352 namespace internal {
0353
0354
0355 template<typename MatrixType, bool IsComplex>
0356 struct complex_schur_reduce_to_hessenberg
0357 {
0358
0359 static void run(ComplexSchur<MatrixType>& _this, const MatrixType& matrix, bool computeU)
0360 {
0361 _this.m_hess.compute(matrix);
0362 _this.m_matT = _this.m_hess.matrixH();
0363 if(computeU) _this.m_matU = _this.m_hess.matrixQ();
0364 }
0365 };
0366
0367 template<typename MatrixType>
0368 struct complex_schur_reduce_to_hessenberg<MatrixType, false>
0369 {
0370 static void run(ComplexSchur<MatrixType>& _this, const MatrixType& matrix, bool computeU)
0371 {
0372 typedef typename ComplexSchur<MatrixType>::ComplexScalar ComplexScalar;
0373
0374
0375 _this.m_hess.compute(matrix);
0376 _this.m_matT = _this.m_hess.matrixH().template cast<ComplexScalar>();
0377 if(computeU)
0378 {
0379
0380 MatrixType Q = _this.m_hess.matrixQ();
0381 _this.m_matU = Q.template cast<ComplexScalar>();
0382 }
0383 }
0384 };
0385
0386 }
0387
0388
0389 template<typename MatrixType>
0390 void ComplexSchur<MatrixType>::reduceToTriangularForm(bool computeU)
0391 {
0392 Index maxIters = m_maxIters;
0393 if (maxIters == -1)
0394 maxIters = m_maxIterationsPerRow * m_matT.rows();
0395
0396
0397
0398
0399
0400 Index iu = m_matT.cols() - 1;
0401 Index il;
0402 Index iter = 0;
0403 Index totalIter = 0;
0404
0405 while(true)
0406 {
0407
0408 while(iu > 0)
0409 {
0410 if(!subdiagonalEntryIsNeglegible(iu-1)) break;
0411 iter = 0;
0412 --iu;
0413 }
0414
0415
0416 if(iu==0) break;
0417
0418
0419 iter++;
0420 totalIter++;
0421 if(totalIter > maxIters) break;
0422
0423
0424 il = iu-1;
0425 while(il > 0 && !subdiagonalEntryIsNeglegible(il-1))
0426 {
0427 --il;
0428 }
0429
0430
0431
0432
0433
0434 ComplexScalar shift = computeShift(iu, iter);
0435 JacobiRotation<ComplexScalar> rot;
0436 rot.makeGivens(m_matT.coeff(il,il) - shift, m_matT.coeff(il+1,il));
0437 m_matT.rightCols(m_matT.cols()-il).applyOnTheLeft(il, il+1, rot.adjoint());
0438 m_matT.topRows((std::min)(il+2,iu)+1).applyOnTheRight(il, il+1, rot);
0439 if(computeU) m_matU.applyOnTheRight(il, il+1, rot);
0440
0441 for(Index i=il+1 ; i<iu ; i++)
0442 {
0443 rot.makeGivens(m_matT.coeffRef(i,i-1), m_matT.coeffRef(i+1,i-1), &m_matT.coeffRef(i,i-1));
0444 m_matT.coeffRef(i+1,i-1) = ComplexScalar(0);
0445 m_matT.rightCols(m_matT.cols()-i).applyOnTheLeft(i, i+1, rot.adjoint());
0446 m_matT.topRows((std::min)(i+2,iu)+1).applyOnTheRight(i, i+1, rot);
0447 if(computeU) m_matU.applyOnTheRight(i, i+1, rot);
0448 }
0449 }
0450
0451 if(totalIter <= maxIters)
0452 m_info = Success;
0453 else
0454 m_info = NoConvergence;
0455
0456 m_isInitialized = true;
0457 m_matUisUptodate = computeU;
0458 }
0459
0460 }
0461
0462 #endif