Warning, file /include/eigen3/Eigen/src/Eigenvalues/Tridiagonalization.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 #ifndef EIGEN_TRIDIAGONALIZATION_H
0012 #define EIGEN_TRIDIAGONALIZATION_H
0013
0014 namespace Eigen {
0015
0016 namespace internal {
0017
0018 template<typename MatrixType> struct TridiagonalizationMatrixTReturnType;
0019 template<typename MatrixType>
0020 struct traits<TridiagonalizationMatrixTReturnType<MatrixType> >
0021 : public traits<typename MatrixType::PlainObject>
0022 {
0023 typedef typename MatrixType::PlainObject ReturnType;
0024 enum { Flags = 0 };
0025 };
0026
0027 template<typename MatrixType, typename CoeffVectorType>
0028 EIGEN_DEVICE_FUNC
0029 void tridiagonalization_inplace(MatrixType& matA, CoeffVectorType& hCoeffs);
0030 }
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064 template<typename _MatrixType> class Tridiagonalization
0065 {
0066 public:
0067
0068
0069 typedef _MatrixType MatrixType;
0070
0071 typedef typename MatrixType::Scalar Scalar;
0072 typedef typename NumTraits<Scalar>::Real RealScalar;
0073 typedef Eigen::Index Index;
0074
0075 enum {
0076 Size = MatrixType::RowsAtCompileTime,
0077 SizeMinusOne = Size == Dynamic ? Dynamic : (Size > 1 ? Size - 1 : 1),
0078 Options = MatrixType::Options,
0079 MaxSize = MatrixType::MaxRowsAtCompileTime,
0080 MaxSizeMinusOne = MaxSize == Dynamic ? Dynamic : (MaxSize > 1 ? MaxSize - 1 : 1)
0081 };
0082
0083 typedef Matrix<Scalar, SizeMinusOne, 1, Options & ~RowMajor, MaxSizeMinusOne, 1> CoeffVectorType;
0084 typedef typename internal::plain_col_type<MatrixType, RealScalar>::type DiagonalType;
0085 typedef Matrix<RealScalar, SizeMinusOne, 1, Options & ~RowMajor, MaxSizeMinusOne, 1> SubDiagonalType;
0086 typedef typename internal::remove_all<typename MatrixType::RealReturnType>::type MatrixTypeRealView;
0087 typedef internal::TridiagonalizationMatrixTReturnType<MatrixTypeRealView> MatrixTReturnType;
0088
0089 typedef typename internal::conditional<NumTraits<Scalar>::IsComplex,
0090 typename internal::add_const_on_value_type<typename Diagonal<const MatrixType>::RealReturnType>::type,
0091 const Diagonal<const MatrixType>
0092 >::type DiagonalReturnType;
0093
0094 typedef typename internal::conditional<NumTraits<Scalar>::IsComplex,
0095 typename internal::add_const_on_value_type<typename Diagonal<const MatrixType, -1>::RealReturnType>::type,
0096 const Diagonal<const MatrixType, -1>
0097 >::type SubDiagonalReturnType;
0098
0099
0100 typedef HouseholderSequence<MatrixType,typename internal::remove_all<typename CoeffVectorType::ConjugateReturnType>::type> HouseholderSequenceType;
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114 explicit Tridiagonalization(Index size = Size==Dynamic ? 2 : Size)
0115 : m_matrix(size,size),
0116 m_hCoeffs(size > 1 ? size-1 : 1),
0117 m_isInitialized(false)
0118 {}
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130 template<typename InputType>
0131 explicit Tridiagonalization(const EigenBase<InputType>& matrix)
0132 : m_matrix(matrix.derived()),
0133 m_hCoeffs(matrix.cols() > 1 ? matrix.cols()-1 : 1),
0134 m_isInitialized(false)
0135 {
0136 internal::tridiagonalization_inplace(m_matrix, m_hCoeffs);
0137 m_isInitialized = true;
0138 }
0139
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156
0157 template<typename InputType>
0158 Tridiagonalization& compute(const EigenBase<InputType>& matrix)
0159 {
0160 m_matrix = matrix.derived();
0161 m_hCoeffs.resize(matrix.rows()-1, 1);
0162 internal::tridiagonalization_inplace(m_matrix, m_hCoeffs);
0163 m_isInitialized = true;
0164 return *this;
0165 }
0166
0167
0168
0169
0170
0171
0172
0173
0174
0175
0176
0177
0178
0179
0180
0181
0182
0183 inline CoeffVectorType householderCoefficients() const
0184 {
0185 eigen_assert(m_isInitialized && "Tridiagonalization is not initialized.");
0186 return m_hCoeffs;
0187 }
0188
0189
0190
0191
0192
0193
0194
0195
0196
0197
0198
0199
0200
0201
0202
0203
0204
0205
0206
0207
0208
0209
0210
0211
0212
0213
0214
0215
0216
0217
0218
0219
0220 inline const MatrixType& packedMatrix() const
0221 {
0222 eigen_assert(m_isInitialized && "Tridiagonalization is not initialized.");
0223 return m_matrix;
0224 }
0225
0226
0227
0228
0229
0230
0231
0232
0233
0234
0235
0236
0237
0238
0239
0240
0241 HouseholderSequenceType matrixQ() const
0242 {
0243 eigen_assert(m_isInitialized && "Tridiagonalization is not initialized.");
0244 return HouseholderSequenceType(m_matrix, m_hCoeffs.conjugate())
0245 .setLength(m_matrix.rows() - 1)
0246 .setShift(1);
0247 }
0248
0249
0250
0251
0252
0253
0254
0255
0256
0257
0258
0259
0260
0261
0262
0263
0264
0265
0266 MatrixTReturnType matrixT() const
0267 {
0268 eigen_assert(m_isInitialized && "Tridiagonalization is not initialized.");
0269 return MatrixTReturnType(m_matrix.real());
0270 }
0271
0272
0273
0274
0275
0276
0277
0278
0279
0280
0281
0282
0283
0284
0285 DiagonalReturnType diagonal() const;
0286
0287
0288
0289
0290
0291
0292
0293
0294
0295
0296
0297 SubDiagonalReturnType subDiagonal() const;
0298
0299 protected:
0300
0301 MatrixType m_matrix;
0302 CoeffVectorType m_hCoeffs;
0303 bool m_isInitialized;
0304 };
0305
0306 template<typename MatrixType>
0307 typename Tridiagonalization<MatrixType>::DiagonalReturnType
0308 Tridiagonalization<MatrixType>::diagonal() const
0309 {
0310 eigen_assert(m_isInitialized && "Tridiagonalization is not initialized.");
0311 return m_matrix.diagonal().real();
0312 }
0313
0314 template<typename MatrixType>
0315 typename Tridiagonalization<MatrixType>::SubDiagonalReturnType
0316 Tridiagonalization<MatrixType>::subDiagonal() const
0317 {
0318 eigen_assert(m_isInitialized && "Tridiagonalization is not initialized.");
0319 return m_matrix.template diagonal<-1>().real();
0320 }
0321
0322 namespace internal {
0323
0324
0325
0326
0327
0328
0329
0330
0331
0332
0333
0334
0335
0336
0337
0338
0339
0340
0341
0342
0343
0344
0345
0346
0347 template<typename MatrixType, typename CoeffVectorType>
0348 EIGEN_DEVICE_FUNC
0349 void tridiagonalization_inplace(MatrixType& matA, CoeffVectorType& hCoeffs)
0350 {
0351 using numext::conj;
0352 typedef typename MatrixType::Scalar Scalar;
0353 typedef typename MatrixType::RealScalar RealScalar;
0354 Index n = matA.rows();
0355 eigen_assert(n==matA.cols());
0356 eigen_assert(n==hCoeffs.size()+1 || n==1);
0357
0358 for (Index i = 0; i<n-1; ++i)
0359 {
0360 Index remainingSize = n-i-1;
0361 RealScalar beta;
0362 Scalar h;
0363 matA.col(i).tail(remainingSize).makeHouseholderInPlace(h, beta);
0364
0365
0366
0367 matA.col(i).coeffRef(i+1) = 1;
0368
0369 hCoeffs.tail(n-i-1).noalias() = (matA.bottomRightCorner(remainingSize,remainingSize).template selfadjointView<Lower>()
0370 * (conj(h) * matA.col(i).tail(remainingSize)));
0371
0372 hCoeffs.tail(n-i-1) += (conj(h)*RealScalar(-0.5)*(hCoeffs.tail(remainingSize).dot(matA.col(i).tail(remainingSize)))) * matA.col(i).tail(n-i-1);
0373
0374 matA.bottomRightCorner(remainingSize, remainingSize).template selfadjointView<Lower>()
0375 .rankUpdate(matA.col(i).tail(remainingSize), hCoeffs.tail(remainingSize), Scalar(-1));
0376
0377 matA.col(i).coeffRef(i+1) = beta;
0378 hCoeffs.coeffRef(i) = h;
0379 }
0380 }
0381
0382
0383 template<typename MatrixType,
0384 int Size=MatrixType::ColsAtCompileTime,
0385 bool IsComplex=NumTraits<typename MatrixType::Scalar>::IsComplex>
0386 struct tridiagonalization_inplace_selector;
0387
0388
0389
0390
0391
0392
0393
0394
0395
0396
0397
0398
0399
0400
0401
0402
0403
0404
0405
0406
0407
0408
0409
0410
0411
0412
0413
0414
0415
0416
0417
0418
0419
0420
0421
0422
0423
0424
0425
0426
0427
0428 template<typename MatrixType, typename DiagonalType, typename SubDiagonalType, typename CoeffVectorType>
0429 EIGEN_DEVICE_FUNC
0430 void tridiagonalization_inplace(MatrixType& mat, DiagonalType& diag, SubDiagonalType& subdiag,
0431 CoeffVectorType& hcoeffs, bool extractQ)
0432 {
0433 eigen_assert(mat.cols()==mat.rows() && diag.size()==mat.rows() && subdiag.size()==mat.rows()-1);
0434 tridiagonalization_inplace_selector<MatrixType>::run(mat, diag, subdiag, hcoeffs, extractQ);
0435 }
0436
0437
0438
0439
0440 template<typename MatrixType, int Size, bool IsComplex>
0441 struct tridiagonalization_inplace_selector
0442 {
0443 typedef typename Tridiagonalization<MatrixType>::CoeffVectorType CoeffVectorType;
0444 typedef typename Tridiagonalization<MatrixType>::HouseholderSequenceType HouseholderSequenceType;
0445 template<typename DiagonalType, typename SubDiagonalType>
0446 static EIGEN_DEVICE_FUNC
0447 void run(MatrixType& mat, DiagonalType& diag, SubDiagonalType& subdiag, CoeffVectorType& hCoeffs, bool extractQ)
0448 {
0449 tridiagonalization_inplace(mat, hCoeffs);
0450 diag = mat.diagonal().real();
0451 subdiag = mat.template diagonal<-1>().real();
0452 if(extractQ)
0453 mat = HouseholderSequenceType(mat, hCoeffs.conjugate())
0454 .setLength(mat.rows() - 1)
0455 .setShift(1);
0456 }
0457 };
0458
0459
0460
0461
0462
0463 template<typename MatrixType>
0464 struct tridiagonalization_inplace_selector<MatrixType,3,false>
0465 {
0466 typedef typename MatrixType::Scalar Scalar;
0467 typedef typename MatrixType::RealScalar RealScalar;
0468
0469 template<typename DiagonalType, typename SubDiagonalType, typename CoeffVectorType>
0470 static void run(MatrixType& mat, DiagonalType& diag, SubDiagonalType& subdiag, CoeffVectorType&, bool extractQ)
0471 {
0472 using std::sqrt;
0473 const RealScalar tol = (std::numeric_limits<RealScalar>::min)();
0474 diag[0] = mat(0,0);
0475 RealScalar v1norm2 = numext::abs2(mat(2,0));
0476 if(v1norm2 <= tol)
0477 {
0478 diag[1] = mat(1,1);
0479 diag[2] = mat(2,2);
0480 subdiag[0] = mat(1,0);
0481 subdiag[1] = mat(2,1);
0482 if (extractQ)
0483 mat.setIdentity();
0484 }
0485 else
0486 {
0487 RealScalar beta = sqrt(numext::abs2(mat(1,0)) + v1norm2);
0488 RealScalar invBeta = RealScalar(1)/beta;
0489 Scalar m01 = mat(1,0) * invBeta;
0490 Scalar m02 = mat(2,0) * invBeta;
0491 Scalar q = RealScalar(2)*m01*mat(2,1) + m02*(mat(2,2) - mat(1,1));
0492 diag[1] = mat(1,1) + m02*q;
0493 diag[2] = mat(2,2) - m02*q;
0494 subdiag[0] = beta;
0495 subdiag[1] = mat(2,1) - m01 * q;
0496 if (extractQ)
0497 {
0498 mat << 1, 0, 0,
0499 0, m01, m02,
0500 0, m02, -m01;
0501 }
0502 }
0503 }
0504 };
0505
0506
0507
0508
0509 template<typename MatrixType, bool IsComplex>
0510 struct tridiagonalization_inplace_selector<MatrixType,1,IsComplex>
0511 {
0512 typedef typename MatrixType::Scalar Scalar;
0513
0514 template<typename DiagonalType, typename SubDiagonalType, typename CoeffVectorType>
0515 static EIGEN_DEVICE_FUNC
0516 void run(MatrixType& mat, DiagonalType& diag, SubDiagonalType&, CoeffVectorType&, bool extractQ)
0517 {
0518 diag(0,0) = numext::real(mat(0,0));
0519 if(extractQ)
0520 mat(0,0) = Scalar(1);
0521 }
0522 };
0523
0524
0525
0526
0527
0528
0529
0530
0531 template<typename MatrixType> struct TridiagonalizationMatrixTReturnType
0532 : public ReturnByValue<TridiagonalizationMatrixTReturnType<MatrixType> >
0533 {
0534 public:
0535
0536
0537
0538
0539 TridiagonalizationMatrixTReturnType(const MatrixType& mat) : m_matrix(mat) { }
0540
0541 template <typename ResultType>
0542 inline void evalTo(ResultType& result) const
0543 {
0544 result.setZero();
0545 result.template diagonal<1>() = m_matrix.template diagonal<-1>().conjugate();
0546 result.diagonal() = m_matrix.diagonal();
0547 result.template diagonal<-1>() = m_matrix.template diagonal<-1>();
0548 }
0549
0550 EIGEN_CONSTEXPR Index rows() const EIGEN_NOEXCEPT { return m_matrix.rows(); }
0551 EIGEN_CONSTEXPR Index cols() const EIGEN_NOEXCEPT { return m_matrix.cols(); }
0552
0553 protected:
0554 typename MatrixType::Nested m_matrix;
0555 };
0556
0557 }
0558
0559 }
0560
0561 #endif