1 | // This file is part of Eigen, a lightweight C++ template library |
---|
2 | // for linear algebra. |
---|
3 | // |
---|
4 | // Copyright (C) 2008-2010 Gael Guennebaud <gael.guennebaud@inria.fr> |
---|
5 | // Copyright (C) 2010 Jitse Niesen <jitse@maths.leeds.ac.uk> |
---|
6 | // |
---|
7 | // This Source Code Form is subject to the terms of the Mozilla |
---|
8 | // Public License v. 2.0. If a copy of the MPL was not distributed |
---|
9 | // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. |
---|
10 | |
---|
11 | #ifndef EIGEN_SELFADJOINTEIGENSOLVER_H |
---|
12 | #define EIGEN_SELFADJOINTEIGENSOLVER_H |
---|
13 | |
---|
14 | #include "./Tridiagonalization.h" |
---|
15 | |
---|
16 | namespace Eigen { |
---|
17 | |
---|
18 | template<typename _MatrixType> |
---|
19 | class GeneralizedSelfAdjointEigenSolver; |
---|
20 | |
---|
21 | namespace internal { |
---|
22 | template<typename SolverType,int Size,bool IsComplex> struct direct_selfadjoint_eigenvalues; |
---|
23 | } |
---|
24 | |
---|
25 | /** \eigenvalues_module \ingroup Eigenvalues_Module |
---|
26 | * |
---|
27 | * |
---|
28 | * \class SelfAdjointEigenSolver |
---|
29 | * |
---|
30 | * \brief Computes eigenvalues and eigenvectors of selfadjoint matrices |
---|
31 | * |
---|
32 | * \tparam _MatrixType the type of the matrix of which we are computing the |
---|
33 | * eigendecomposition; this is expected to be an instantiation of the Matrix |
---|
34 | * class template. |
---|
35 | * |
---|
36 | * A matrix \f$ A \f$ is selfadjoint if it equals its adjoint. For real |
---|
37 | * matrices, this means that the matrix is symmetric: it equals its |
---|
38 | * transpose. This class computes the eigenvalues and eigenvectors of a |
---|
39 | * selfadjoint matrix. These are the scalars \f$ \lambda \f$ and vectors |
---|
40 | * \f$ v \f$ such that \f$ Av = \lambda v \f$. The eigenvalues of a |
---|
41 | * selfadjoint matrix are always real. If \f$ D \f$ is a diagonal matrix with |
---|
42 | * the eigenvalues on the diagonal, and \f$ V \f$ is a matrix with the |
---|
43 | * eigenvectors as its columns, then \f$ A = V D V^{-1} \f$ (for selfadjoint |
---|
44 | * matrices, the matrix \f$ V \f$ is always invertible). This is called the |
---|
45 | * eigendecomposition. |
---|
46 | * |
---|
47 | * The algorithm exploits the fact that the matrix is selfadjoint, making it |
---|
48 | * faster and more accurate than the general purpose eigenvalue algorithms |
---|
49 | * implemented in EigenSolver and ComplexEigenSolver. |
---|
50 | * |
---|
51 | * Only the \b lower \b triangular \b part of the input matrix is referenced. |
---|
52 | * |
---|
53 | * Call the function compute() to compute the eigenvalues and eigenvectors of |
---|
54 | * a given matrix. Alternatively, you can use the |
---|
55 | * SelfAdjointEigenSolver(const MatrixType&, int) constructor which computes |
---|
56 | * the eigenvalues and eigenvectors at construction time. Once the eigenvalue |
---|
57 | * and eigenvectors are computed, they can be retrieved with the eigenvalues() |
---|
58 | * and eigenvectors() functions. |
---|
59 | * |
---|
60 | * The documentation for SelfAdjointEigenSolver(const MatrixType&, int) |
---|
61 | * contains an example of the typical use of this class. |
---|
62 | * |
---|
63 | * To solve the \em generalized eigenvalue problem \f$ Av = \lambda Bv \f$ and |
---|
64 | * the likes, see the class GeneralizedSelfAdjointEigenSolver. |
---|
65 | * |
---|
66 | * \sa MatrixBase::eigenvalues(), class EigenSolver, class ComplexEigenSolver |
---|
67 | */ |
---|
68 | template<typename _MatrixType> class SelfAdjointEigenSolver |
---|
69 | { |
---|
70 | public: |
---|
71 | |
---|
72 | typedef _MatrixType MatrixType; |
---|
73 | enum { |
---|
74 | Size = MatrixType::RowsAtCompileTime, |
---|
75 | ColsAtCompileTime = MatrixType::ColsAtCompileTime, |
---|
76 | Options = MatrixType::Options, |
---|
77 | MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime |
---|
78 | }; |
---|
79 | |
---|
80 | /** \brief Scalar type for matrices of type \p _MatrixType. */ |
---|
81 | typedef typename MatrixType::Scalar Scalar; |
---|
82 | typedef typename MatrixType::Index Index; |
---|
83 | |
---|
84 | /** \brief Real scalar type for \p _MatrixType. |
---|
85 | * |
---|
86 | * This is just \c Scalar if #Scalar is real (e.g., \c float or |
---|
87 | * \c double), and the type of the real part of \c Scalar if #Scalar is |
---|
88 | * complex. |
---|
89 | */ |
---|
90 | typedef typename NumTraits<Scalar>::Real RealScalar; |
---|
91 | |
---|
92 | friend struct internal::direct_selfadjoint_eigenvalues<SelfAdjointEigenSolver,Size,NumTraits<Scalar>::IsComplex>; |
---|
93 | |
---|
94 | /** \brief Type for vector of eigenvalues as returned by eigenvalues(). |
---|
95 | * |
---|
96 | * This is a column vector with entries of type #RealScalar. |
---|
97 | * The length of the vector is the size of \p _MatrixType. |
---|
98 | */ |
---|
99 | typedef typename internal::plain_col_type<MatrixType, RealScalar>::type RealVectorType; |
---|
100 | typedef Tridiagonalization<MatrixType> TridiagonalizationType; |
---|
101 | |
---|
102 | /** \brief Default constructor for fixed-size matrices. |
---|
103 | * |
---|
104 | * The default constructor is useful in cases in which the user intends to |
---|
105 | * perform decompositions via compute(). This constructor |
---|
106 | * can only be used if \p _MatrixType is a fixed-size matrix; use |
---|
107 | * SelfAdjointEigenSolver(Index) for dynamic-size matrices. |
---|
108 | * |
---|
109 | * Example: \include SelfAdjointEigenSolver_SelfAdjointEigenSolver.cpp |
---|
110 | * Output: \verbinclude SelfAdjointEigenSolver_SelfAdjointEigenSolver.out |
---|
111 | */ |
---|
112 | SelfAdjointEigenSolver() |
---|
113 | : m_eivec(), |
---|
114 | m_eivalues(), |
---|
115 | m_subdiag(), |
---|
116 | m_isInitialized(false) |
---|
117 | { } |
---|
118 | |
---|
119 | /** \brief Constructor, pre-allocates memory for dynamic-size matrices. |
---|
120 | * |
---|
121 | * \param [in] size Positive integer, size of the matrix whose |
---|
122 | * eigenvalues and eigenvectors will be computed. |
---|
123 | * |
---|
124 | * This constructor is useful for dynamic-size matrices, when the user |
---|
125 | * intends to perform decompositions via compute(). The \p size |
---|
126 | * parameter is only used as a hint. It is not an error to give a wrong |
---|
127 | * \p size, but it may impair performance. |
---|
128 | * |
---|
129 | * \sa compute() for an example |
---|
130 | */ |
---|
131 | SelfAdjointEigenSolver(Index size) |
---|
132 | : m_eivec(size, size), |
---|
133 | m_eivalues(size), |
---|
134 | m_subdiag(size > 1 ? size - 1 : 1), |
---|
135 | m_isInitialized(false) |
---|
136 | {} |
---|
137 | |
---|
138 | /** \brief Constructor; computes eigendecomposition of given matrix. |
---|
139 | * |
---|
140 | * \param[in] matrix Selfadjoint matrix whose eigendecomposition is to |
---|
141 | * be computed. Only the lower triangular part of the matrix is referenced. |
---|
142 | * \param[in] options Can be #ComputeEigenvectors (default) or #EigenvaluesOnly. |
---|
143 | * |
---|
144 | * This constructor calls compute(const MatrixType&, int) to compute the |
---|
145 | * eigenvalues of the matrix \p matrix. The eigenvectors are computed if |
---|
146 | * \p options equals #ComputeEigenvectors. |
---|
147 | * |
---|
148 | * Example: \include SelfAdjointEigenSolver_SelfAdjointEigenSolver_MatrixType.cpp |
---|
149 | * Output: \verbinclude SelfAdjointEigenSolver_SelfAdjointEigenSolver_MatrixType.out |
---|
150 | * |
---|
151 | * \sa compute(const MatrixType&, int) |
---|
152 | */ |
---|
153 | SelfAdjointEigenSolver(const MatrixType& matrix, int options = ComputeEigenvectors) |
---|
154 | : m_eivec(matrix.rows(), matrix.cols()), |
---|
155 | m_eivalues(matrix.cols()), |
---|
156 | m_subdiag(matrix.rows() > 1 ? matrix.rows() - 1 : 1), |
---|
157 | m_isInitialized(false) |
---|
158 | { |
---|
159 | compute(matrix, options); |
---|
160 | } |
---|
161 | |
---|
162 | /** \brief Computes eigendecomposition of given matrix. |
---|
163 | * |
---|
164 | * \param[in] matrix Selfadjoint matrix whose eigendecomposition is to |
---|
165 | * be computed. Only the lower triangular part of the matrix is referenced. |
---|
166 | * \param[in] options Can be #ComputeEigenvectors (default) or #EigenvaluesOnly. |
---|
167 | * \returns Reference to \c *this |
---|
168 | * |
---|
169 | * This function computes the eigenvalues of \p matrix. The eigenvalues() |
---|
170 | * function can be used to retrieve them. If \p options equals #ComputeEigenvectors, |
---|
171 | * then the eigenvectors are also computed and can be retrieved by |
---|
172 | * calling eigenvectors(). |
---|
173 | * |
---|
174 | * This implementation uses a symmetric QR algorithm. The matrix is first |
---|
175 | * reduced to tridiagonal form using the Tridiagonalization class. The |
---|
176 | * tridiagonal matrix is then brought to diagonal form with implicit |
---|
177 | * symmetric QR steps with Wilkinson shift. Details can be found in |
---|
178 | * Section 8.3 of Golub \& Van Loan, <i>%Matrix Computations</i>. |
---|
179 | * |
---|
180 | * The cost of the computation is about \f$ 9n^3 \f$ if the eigenvectors |
---|
181 | * are required and \f$ 4n^3/3 \f$ if they are not required. |
---|
182 | * |
---|
183 | * This method reuses the memory in the SelfAdjointEigenSolver object that |
---|
184 | * was allocated when the object was constructed, if the size of the |
---|
185 | * matrix does not change. |
---|
186 | * |
---|
187 | * Example: \include SelfAdjointEigenSolver_compute_MatrixType.cpp |
---|
188 | * Output: \verbinclude SelfAdjointEigenSolver_compute_MatrixType.out |
---|
189 | * |
---|
190 | * \sa SelfAdjointEigenSolver(const MatrixType&, int) |
---|
191 | */ |
---|
192 | SelfAdjointEigenSolver& compute(const MatrixType& matrix, int options = ComputeEigenvectors); |
---|
193 | |
---|
194 | /** \brief Computes eigendecomposition of given matrix using a direct algorithm |
---|
195 | * |
---|
196 | * This is a variant of compute(const MatrixType&, int options) which |
---|
197 | * directly solves the underlying polynomial equation. |
---|
198 | * |
---|
199 | * Currently only 3x3 matrices for which the sizes are known at compile time are supported (e.g., Matrix3d). |
---|
200 | * |
---|
201 | * This method is usually significantly faster than the QR algorithm |
---|
202 | * but it might also be less accurate. It is also worth noting that |
---|
203 | * for 3x3 matrices it involves trigonometric operations which are |
---|
204 | * not necessarily available for all scalar types. |
---|
205 | * |
---|
206 | * \sa compute(const MatrixType&, int options) |
---|
207 | */ |
---|
208 | SelfAdjointEigenSolver& computeDirect(const MatrixType& matrix, int options = ComputeEigenvectors); |
---|
209 | |
---|
210 | /** \brief Returns the eigenvectors of given matrix. |
---|
211 | * |
---|
212 | * \returns A const reference to the matrix whose columns are the eigenvectors. |
---|
213 | * |
---|
214 | * \pre The eigenvectors have been computed before. |
---|
215 | * |
---|
216 | * Column \f$ k \f$ of the returned matrix is an eigenvector corresponding |
---|
217 | * to eigenvalue number \f$ k \f$ as returned by eigenvalues(). The |
---|
218 | * eigenvectors are normalized to have (Euclidean) norm equal to one. If |
---|
219 | * this object was used to solve the eigenproblem for the selfadjoint |
---|
220 | * matrix \f$ A \f$, then the matrix returned by this function is the |
---|
221 | * matrix \f$ V \f$ in the eigendecomposition \f$ A = V D V^{-1} \f$. |
---|
222 | * |
---|
223 | * Example: \include SelfAdjointEigenSolver_eigenvectors.cpp |
---|
224 | * Output: \verbinclude SelfAdjointEigenSolver_eigenvectors.out |
---|
225 | * |
---|
226 | * \sa eigenvalues() |
---|
227 | */ |
---|
228 | const MatrixType& eigenvectors() const |
---|
229 | { |
---|
230 | eigen_assert(m_isInitialized && "SelfAdjointEigenSolver is not initialized."); |
---|
231 | eigen_assert(m_eigenvectorsOk && "The eigenvectors have not been computed together with the eigenvalues."); |
---|
232 | return m_eivec; |
---|
233 | } |
---|
234 | |
---|
235 | /** \brief Returns the eigenvalues of given matrix. |
---|
236 | * |
---|
237 | * \returns A const reference to the column vector containing the eigenvalues. |
---|
238 | * |
---|
239 | * \pre The eigenvalues have been computed before. |
---|
240 | * |
---|
241 | * The eigenvalues are repeated according to their algebraic multiplicity, |
---|
242 | * so there are as many eigenvalues as rows in the matrix. The eigenvalues |
---|
243 | * are sorted in increasing order. |
---|
244 | * |
---|
245 | * Example: \include SelfAdjointEigenSolver_eigenvalues.cpp |
---|
246 | * Output: \verbinclude SelfAdjointEigenSolver_eigenvalues.out |
---|
247 | * |
---|
248 | * \sa eigenvectors(), MatrixBase::eigenvalues() |
---|
249 | */ |
---|
250 | const RealVectorType& eigenvalues() const |
---|
251 | { |
---|
252 | eigen_assert(m_isInitialized && "SelfAdjointEigenSolver is not initialized."); |
---|
253 | return m_eivalues; |
---|
254 | } |
---|
255 | |
---|
256 | /** \brief Computes the positive-definite square root of the matrix. |
---|
257 | * |
---|
258 | * \returns the positive-definite square root of the matrix |
---|
259 | * |
---|
260 | * \pre The eigenvalues and eigenvectors of a positive-definite matrix |
---|
261 | * have been computed before. |
---|
262 | * |
---|
263 | * The square root of a positive-definite matrix \f$ A \f$ is the |
---|
264 | * positive-definite matrix whose square equals \f$ A \f$. This function |
---|
265 | * uses the eigendecomposition \f$ A = V D V^{-1} \f$ to compute the |
---|
266 | * square root as \f$ A^{1/2} = V D^{1/2} V^{-1} \f$. |
---|
267 | * |
---|
268 | * Example: \include SelfAdjointEigenSolver_operatorSqrt.cpp |
---|
269 | * Output: \verbinclude SelfAdjointEigenSolver_operatorSqrt.out |
---|
270 | * |
---|
271 | * \sa operatorInverseSqrt(), |
---|
272 | * \ref MatrixFunctions_Module "MatrixFunctions Module" |
---|
273 | */ |
---|
274 | MatrixType operatorSqrt() const |
---|
275 | { |
---|
276 | eigen_assert(m_isInitialized && "SelfAdjointEigenSolver is not initialized."); |
---|
277 | eigen_assert(m_eigenvectorsOk && "The eigenvectors have not been computed together with the eigenvalues."); |
---|
278 | return m_eivec * m_eivalues.cwiseSqrt().asDiagonal() * m_eivec.adjoint(); |
---|
279 | } |
---|
280 | |
---|
281 | /** \brief Computes the inverse square root of the matrix. |
---|
282 | * |
---|
283 | * \returns the inverse positive-definite square root of the matrix |
---|
284 | * |
---|
285 | * \pre The eigenvalues and eigenvectors of a positive-definite matrix |
---|
286 | * have been computed before. |
---|
287 | * |
---|
288 | * This function uses the eigendecomposition \f$ A = V D V^{-1} \f$ to |
---|
289 | * compute the inverse square root as \f$ V D^{-1/2} V^{-1} \f$. This is |
---|
290 | * cheaper than first computing the square root with operatorSqrt() and |
---|
291 | * then its inverse with MatrixBase::inverse(). |
---|
292 | * |
---|
293 | * Example: \include SelfAdjointEigenSolver_operatorInverseSqrt.cpp |
---|
294 | * Output: \verbinclude SelfAdjointEigenSolver_operatorInverseSqrt.out |
---|
295 | * |
---|
296 | * \sa operatorSqrt(), MatrixBase::inverse(), |
---|
297 | * \ref MatrixFunctions_Module "MatrixFunctions Module" |
---|
298 | */ |
---|
299 | MatrixType operatorInverseSqrt() const |
---|
300 | { |
---|
301 | eigen_assert(m_isInitialized && "SelfAdjointEigenSolver is not initialized."); |
---|
302 | eigen_assert(m_eigenvectorsOk && "The eigenvectors have not been computed together with the eigenvalues."); |
---|
303 | return m_eivec * m_eivalues.cwiseInverse().cwiseSqrt().asDiagonal() * m_eivec.adjoint(); |
---|
304 | } |
---|
305 | |
---|
306 | /** \brief Reports whether previous computation was successful. |
---|
307 | * |
---|
308 | * \returns \c Success if computation was succesful, \c NoConvergence otherwise. |
---|
309 | */ |
---|
310 | ComputationInfo info() const |
---|
311 | { |
---|
312 | eigen_assert(m_isInitialized && "SelfAdjointEigenSolver is not initialized."); |
---|
313 | return m_info; |
---|
314 | } |
---|
315 | |
---|
316 | /** \brief Maximum number of iterations. |
---|
317 | * |
---|
318 | * The algorithm terminates if it does not converge within m_maxIterations * n iterations, where n |
---|
319 | * denotes the size of the matrix. This value is currently set to 30 (copied from LAPACK). |
---|
320 | */ |
---|
321 | static const int m_maxIterations = 30; |
---|
322 | |
---|
323 | #ifdef EIGEN2_SUPPORT |
---|
324 | SelfAdjointEigenSolver(const MatrixType& matrix, bool computeEigenvectors) |
---|
325 | : m_eivec(matrix.rows(), matrix.cols()), |
---|
326 | m_eivalues(matrix.cols()), |
---|
327 | m_subdiag(matrix.rows() > 1 ? matrix.rows() - 1 : 1), |
---|
328 | m_isInitialized(false) |
---|
329 | { |
---|
330 | compute(matrix, computeEigenvectors); |
---|
331 | } |
---|
332 | |
---|
333 | SelfAdjointEigenSolver(const MatrixType& matA, const MatrixType& matB, bool computeEigenvectors = true) |
---|
334 | : m_eivec(matA.cols(), matA.cols()), |
---|
335 | m_eivalues(matA.cols()), |
---|
336 | m_subdiag(matA.cols() > 1 ? matA.cols() - 1 : 1), |
---|
337 | m_isInitialized(false) |
---|
338 | { |
---|
339 | static_cast<GeneralizedSelfAdjointEigenSolver<MatrixType>*>(this)->compute(matA, matB, computeEigenvectors ? ComputeEigenvectors : EigenvaluesOnly); |
---|
340 | } |
---|
341 | |
---|
342 | void compute(const MatrixType& matrix, bool computeEigenvectors) |
---|
343 | { |
---|
344 | compute(matrix, computeEigenvectors ? ComputeEigenvectors : EigenvaluesOnly); |
---|
345 | } |
---|
346 | |
---|
347 | void compute(const MatrixType& matA, const MatrixType& matB, bool computeEigenvectors = true) |
---|
348 | { |
---|
349 | compute(matA, matB, computeEigenvectors ? ComputeEigenvectors : EigenvaluesOnly); |
---|
350 | } |
---|
351 | #endif // EIGEN2_SUPPORT |
---|
352 | |
---|
353 | protected: |
---|
354 | MatrixType m_eivec; |
---|
355 | RealVectorType m_eivalues; |
---|
356 | typename TridiagonalizationType::SubDiagonalType m_subdiag; |
---|
357 | ComputationInfo m_info; |
---|
358 | bool m_isInitialized; |
---|
359 | bool m_eigenvectorsOk; |
---|
360 | }; |
---|
361 | |
---|
362 | /** \internal |
---|
363 | * |
---|
364 | * \eigenvalues_module \ingroup Eigenvalues_Module |
---|
365 | * |
---|
366 | * Performs a QR step on a tridiagonal symmetric matrix represented as a |
---|
367 | * pair of two vectors \a diag and \a subdiag. |
---|
368 | * |
---|
369 | * \param matA the input selfadjoint matrix |
---|
370 | * \param hCoeffs returned Householder coefficients |
---|
371 | * |
---|
372 | * For compilation efficiency reasons, this procedure does not use eigen expression |
---|
373 | * for its arguments. |
---|
374 | * |
---|
375 | * Implemented from Golub's "Matrix Computations", algorithm 8.3.2: |
---|
376 | * "implicit symmetric QR step with Wilkinson shift" |
---|
377 | */ |
---|
378 | namespace internal { |
---|
379 | template<int StorageOrder,typename RealScalar, typename Scalar, typename Index> |
---|
380 | static void tridiagonal_qr_step(RealScalar* diag, RealScalar* subdiag, Index start, Index end, Scalar* matrixQ, Index n); |
---|
381 | } |
---|
382 | |
---|
383 | template<typename MatrixType> |
---|
384 | SelfAdjointEigenSolver<MatrixType>& SelfAdjointEigenSolver<MatrixType> |
---|
385 | ::compute(const MatrixType& matrix, int options) |
---|
386 | { |
---|
387 | eigen_assert(matrix.cols() == matrix.rows()); |
---|
388 | eigen_assert((options&~(EigVecMask|GenEigMask))==0 |
---|
389 | && (options&EigVecMask)!=EigVecMask |
---|
390 | && "invalid option parameter"); |
---|
391 | bool computeEigenvectors = (options&ComputeEigenvectors)==ComputeEigenvectors; |
---|
392 | Index n = matrix.cols(); |
---|
393 | m_eivalues.resize(n,1); |
---|
394 | |
---|
395 | if(n==1) |
---|
396 | { |
---|
397 | m_eivalues.coeffRef(0,0) = internal::real(matrix.coeff(0,0)); |
---|
398 | if(computeEigenvectors) |
---|
399 | m_eivec.setOnes(n,n); |
---|
400 | m_info = Success; |
---|
401 | m_isInitialized = true; |
---|
402 | m_eigenvectorsOk = computeEigenvectors; |
---|
403 | return *this; |
---|
404 | } |
---|
405 | |
---|
406 | // declare some aliases |
---|
407 | RealVectorType& diag = m_eivalues; |
---|
408 | MatrixType& mat = m_eivec; |
---|
409 | |
---|
410 | // map the matrix coefficients to [-1:1] to avoid over- and underflow. |
---|
411 | RealScalar scale = matrix.cwiseAbs().maxCoeff(); |
---|
412 | if(scale==RealScalar(0)) scale = RealScalar(1); |
---|
413 | mat = matrix / scale; |
---|
414 | m_subdiag.resize(n-1); |
---|
415 | internal::tridiagonalization_inplace(mat, diag, m_subdiag, computeEigenvectors); |
---|
416 | |
---|
417 | Index end = n-1; |
---|
418 | Index start = 0; |
---|
419 | Index iter = 0; // total number of iterations |
---|
420 | |
---|
421 | while (end>0) |
---|
422 | { |
---|
423 | for (Index i = start; i<end; ++i) |
---|
424 | if (internal::isMuchSmallerThan(internal::abs(m_subdiag[i]),(internal::abs(diag[i])+internal::abs(diag[i+1])))) |
---|
425 | m_subdiag[i] = 0; |
---|
426 | |
---|
427 | // find the largest unreduced block |
---|
428 | while (end>0 && m_subdiag[end-1]==0) |
---|
429 | { |
---|
430 | end--; |
---|
431 | } |
---|
432 | if (end<=0) |
---|
433 | break; |
---|
434 | |
---|
435 | // if we spent too many iterations, we give up |
---|
436 | iter++; |
---|
437 | if(iter > m_maxIterations * n) break; |
---|
438 | |
---|
439 | start = end - 1; |
---|
440 | while (start>0 && m_subdiag[start-1]!=0) |
---|
441 | start--; |
---|
442 | |
---|
443 | internal::tridiagonal_qr_step<MatrixType::Flags&RowMajorBit ? RowMajor : ColMajor>(diag.data(), m_subdiag.data(), start, end, computeEigenvectors ? m_eivec.data() : (Scalar*)0, n); |
---|
444 | } |
---|
445 | |
---|
446 | if (iter <= m_maxIterations * n) |
---|
447 | m_info = Success; |
---|
448 | else |
---|
449 | m_info = NoConvergence; |
---|
450 | |
---|
451 | // Sort eigenvalues and corresponding vectors. |
---|
452 | // TODO make the sort optional ? |
---|
453 | // TODO use a better sort algorithm !! |
---|
454 | if (m_info == Success) |
---|
455 | { |
---|
456 | for (Index i = 0; i < n-1; ++i) |
---|
457 | { |
---|
458 | Index k; |
---|
459 | m_eivalues.segment(i,n-i).minCoeff(&k); |
---|
460 | if (k > 0) |
---|
461 | { |
---|
462 | std::swap(m_eivalues[i], m_eivalues[k+i]); |
---|
463 | if(computeEigenvectors) |
---|
464 | m_eivec.col(i).swap(m_eivec.col(k+i)); |
---|
465 | } |
---|
466 | } |
---|
467 | } |
---|
468 | |
---|
469 | // scale back the eigen values |
---|
470 | m_eivalues *= scale; |
---|
471 | |
---|
472 | m_isInitialized = true; |
---|
473 | m_eigenvectorsOk = computeEigenvectors; |
---|
474 | return *this; |
---|
475 | } |
---|
476 | |
---|
477 | |
---|
478 | namespace internal { |
---|
479 | |
---|
480 | template<typename SolverType,int Size,bool IsComplex> struct direct_selfadjoint_eigenvalues |
---|
481 | { |
---|
482 | static inline void run(SolverType& eig, const typename SolverType::MatrixType& A, int options) |
---|
483 | { eig.compute(A,options); } |
---|
484 | }; |
---|
485 | |
---|
486 | template<typename SolverType> struct direct_selfadjoint_eigenvalues<SolverType,3,false> |
---|
487 | { |
---|
488 | typedef typename SolverType::MatrixType MatrixType; |
---|
489 | typedef typename SolverType::RealVectorType VectorType; |
---|
490 | typedef typename SolverType::Scalar Scalar; |
---|
491 | |
---|
492 | static inline void computeRoots(const MatrixType& m, VectorType& roots) |
---|
493 | { |
---|
494 | using std::sqrt; |
---|
495 | using std::atan2; |
---|
496 | using std::cos; |
---|
497 | using std::sin; |
---|
498 | const Scalar s_inv3 = Scalar(1.0)/Scalar(3.0); |
---|
499 | const Scalar s_sqrt3 = sqrt(Scalar(3.0)); |
---|
500 | |
---|
501 | // The characteristic equation is x^3 - c2*x^2 + c1*x - c0 = 0. The |
---|
502 | // eigenvalues are the roots to this equation, all guaranteed to be |
---|
503 | // real-valued, because the matrix is symmetric. |
---|
504 | Scalar c0 = m(0,0)*m(1,1)*m(2,2) + Scalar(2)*m(1,0)*m(2,0)*m(2,1) - m(0,0)*m(2,1)*m(2,1) - m(1,1)*m(2,0)*m(2,0) - m(2,2)*m(1,0)*m(1,0); |
---|
505 | Scalar c1 = m(0,0)*m(1,1) - m(1,0)*m(1,0) + m(0,0)*m(2,2) - m(2,0)*m(2,0) + m(1,1)*m(2,2) - m(2,1)*m(2,1); |
---|
506 | Scalar c2 = m(0,0) + m(1,1) + m(2,2); |
---|
507 | |
---|
508 | // Construct the parameters used in classifying the roots of the equation |
---|
509 | // and in solving the equation for the roots in closed form. |
---|
510 | Scalar c2_over_3 = c2*s_inv3; |
---|
511 | Scalar a_over_3 = (c1 - c2*c2_over_3)*s_inv3; |
---|
512 | if (a_over_3 > Scalar(0)) |
---|
513 | a_over_3 = Scalar(0); |
---|
514 | |
---|
515 | Scalar half_b = Scalar(0.5)*(c0 + c2_over_3*(Scalar(2)*c2_over_3*c2_over_3 - c1)); |
---|
516 | |
---|
517 | Scalar q = half_b*half_b + a_over_3*a_over_3*a_over_3; |
---|
518 | if (q > Scalar(0)) |
---|
519 | q = Scalar(0); |
---|
520 | |
---|
521 | // Compute the eigenvalues by solving for the roots of the polynomial. |
---|
522 | Scalar rho = sqrt(-a_over_3); |
---|
523 | Scalar theta = atan2(sqrt(-q),half_b)*s_inv3; |
---|
524 | Scalar cos_theta = cos(theta); |
---|
525 | Scalar sin_theta = sin(theta); |
---|
526 | roots(0) = c2_over_3 + Scalar(2)*rho*cos_theta; |
---|
527 | roots(1) = c2_over_3 - rho*(cos_theta + s_sqrt3*sin_theta); |
---|
528 | roots(2) = c2_over_3 - rho*(cos_theta - s_sqrt3*sin_theta); |
---|
529 | |
---|
530 | // Sort in increasing order. |
---|
531 | if (roots(0) >= roots(1)) |
---|
532 | std::swap(roots(0),roots(1)); |
---|
533 | if (roots(1) >= roots(2)) |
---|
534 | { |
---|
535 | std::swap(roots(1),roots(2)); |
---|
536 | if (roots(0) >= roots(1)) |
---|
537 | std::swap(roots(0),roots(1)); |
---|
538 | } |
---|
539 | } |
---|
540 | |
---|
541 | static inline void run(SolverType& solver, const MatrixType& mat, int options) |
---|
542 | { |
---|
543 | using std::sqrt; |
---|
544 | eigen_assert(mat.cols() == 3 && mat.cols() == mat.rows()); |
---|
545 | eigen_assert((options&~(EigVecMask|GenEigMask))==0 |
---|
546 | && (options&EigVecMask)!=EigVecMask |
---|
547 | && "invalid option parameter"); |
---|
548 | bool computeEigenvectors = (options&ComputeEigenvectors)==ComputeEigenvectors; |
---|
549 | |
---|
550 | MatrixType& eivecs = solver.m_eivec; |
---|
551 | VectorType& eivals = solver.m_eivalues; |
---|
552 | |
---|
553 | // map the matrix coefficients to [-1:1] to avoid over- and underflow. |
---|
554 | Scalar scale = mat.cwiseAbs().maxCoeff(); |
---|
555 | MatrixType scaledMat = mat / scale; |
---|
556 | |
---|
557 | // compute the eigenvalues |
---|
558 | computeRoots(scaledMat,eivals); |
---|
559 | |
---|
560 | // compute the eigen vectors |
---|
561 | if(computeEigenvectors) |
---|
562 | { |
---|
563 | Scalar safeNorm2 = Eigen::NumTraits<Scalar>::epsilon(); |
---|
564 | safeNorm2 *= safeNorm2; |
---|
565 | if((eivals(2)-eivals(0))<=Eigen::NumTraits<Scalar>::epsilon()) |
---|
566 | { |
---|
567 | eivecs.setIdentity(); |
---|
568 | } |
---|
569 | else |
---|
570 | { |
---|
571 | scaledMat = scaledMat.template selfadjointView<Lower>(); |
---|
572 | MatrixType tmp; |
---|
573 | tmp = scaledMat; |
---|
574 | |
---|
575 | Scalar d0 = eivals(2) - eivals(1); |
---|
576 | Scalar d1 = eivals(1) - eivals(0); |
---|
577 | int k = d0 > d1 ? 2 : 0; |
---|
578 | d0 = d0 > d1 ? d1 : d0; |
---|
579 | |
---|
580 | tmp.diagonal().array () -= eivals(k); |
---|
581 | VectorType cross; |
---|
582 | Scalar n; |
---|
583 | n = (cross = tmp.row(0).cross(tmp.row(1))).squaredNorm(); |
---|
584 | |
---|
585 | if(n>safeNorm2) |
---|
586 | eivecs.col(k) = cross / sqrt(n); |
---|
587 | else |
---|
588 | { |
---|
589 | n = (cross = tmp.row(0).cross(tmp.row(2))).squaredNorm(); |
---|
590 | |
---|
591 | if(n>safeNorm2) |
---|
592 | eivecs.col(k) = cross / sqrt(n); |
---|
593 | else |
---|
594 | { |
---|
595 | n = (cross = tmp.row(1).cross(tmp.row(2))).squaredNorm(); |
---|
596 | |
---|
597 | if(n>safeNorm2) |
---|
598 | eivecs.col(k) = cross / sqrt(n); |
---|
599 | else |
---|
600 | { |
---|
601 | // the input matrix and/or the eigenvaues probably contains some inf/NaN, |
---|
602 | // => exit |
---|
603 | // scale back to the original size. |
---|
604 | eivals *= scale; |
---|
605 | |
---|
606 | solver.m_info = NumericalIssue; |
---|
607 | solver.m_isInitialized = true; |
---|
608 | solver.m_eigenvectorsOk = computeEigenvectors; |
---|
609 | return; |
---|
610 | } |
---|
611 | } |
---|
612 | } |
---|
613 | |
---|
614 | tmp = scaledMat; |
---|
615 | tmp.diagonal().array() -= eivals(1); |
---|
616 | |
---|
617 | if(d0<=Eigen::NumTraits<Scalar>::epsilon()) |
---|
618 | eivecs.col(1) = eivecs.col(k).unitOrthogonal(); |
---|
619 | else |
---|
620 | { |
---|
621 | n = (cross = eivecs.col(k).cross(tmp.row(0).normalized())).squaredNorm(); |
---|
622 | if(n>safeNorm2) |
---|
623 | eivecs.col(1) = cross / sqrt(n); |
---|
624 | else |
---|
625 | { |
---|
626 | n = (cross = eivecs.col(k).cross(tmp.row(1))).squaredNorm(); |
---|
627 | if(n>safeNorm2) |
---|
628 | eivecs.col(1) = cross / sqrt(n); |
---|
629 | else |
---|
630 | { |
---|
631 | n = (cross = eivecs.col(k).cross(tmp.row(2))).squaredNorm(); |
---|
632 | if(n>safeNorm2) |
---|
633 | eivecs.col(1) = cross / sqrt(n); |
---|
634 | else |
---|
635 | { |
---|
636 | // we should never reach this point, |
---|
637 | // if so the last two eigenvalues are likely to ve very closed to each other |
---|
638 | eivecs.col(1) = eivecs.col(k).unitOrthogonal(); |
---|
639 | } |
---|
640 | } |
---|
641 | } |
---|
642 | |
---|
643 | // make sure that eivecs[1] is orthogonal to eivecs[2] |
---|
644 | Scalar d = eivecs.col(1).dot(eivecs.col(k)); |
---|
645 | eivecs.col(1) = (eivecs.col(1) - d * eivecs.col(k)).normalized(); |
---|
646 | } |
---|
647 | |
---|
648 | eivecs.col(k==2 ? 0 : 2) = eivecs.col(k).cross(eivecs.col(1)).normalized(); |
---|
649 | } |
---|
650 | } |
---|
651 | // Rescale back to the original size. |
---|
652 | eivals *= scale; |
---|
653 | |
---|
654 | solver.m_info = Success; |
---|
655 | solver.m_isInitialized = true; |
---|
656 | solver.m_eigenvectorsOk = computeEigenvectors; |
---|
657 | } |
---|
658 | }; |
---|
659 | |
---|
660 | // 2x2 direct eigenvalues decomposition, code from Hauke Heibel |
---|
661 | template<typename SolverType> struct direct_selfadjoint_eigenvalues<SolverType,2,false> |
---|
662 | { |
---|
663 | typedef typename SolverType::MatrixType MatrixType; |
---|
664 | typedef typename SolverType::RealVectorType VectorType; |
---|
665 | typedef typename SolverType::Scalar Scalar; |
---|
666 | |
---|
667 | static inline void computeRoots(const MatrixType& m, VectorType& roots) |
---|
668 | { |
---|
669 | using std::sqrt; |
---|
670 | const Scalar t0 = Scalar(0.5) * sqrt( abs2(m(0,0)-m(1,1)) + Scalar(4)*m(1,0)*m(1,0)); |
---|
671 | const Scalar t1 = Scalar(0.5) * (m(0,0) + m(1,1)); |
---|
672 | roots(0) = t1 - t0; |
---|
673 | roots(1) = t1 + t0; |
---|
674 | } |
---|
675 | |
---|
676 | static inline void run(SolverType& solver, const MatrixType& mat, int options) |
---|
677 | { |
---|
678 | eigen_assert(mat.cols() == 2 && mat.cols() == mat.rows()); |
---|
679 | eigen_assert((options&~(EigVecMask|GenEigMask))==0 |
---|
680 | && (options&EigVecMask)!=EigVecMask |
---|
681 | && "invalid option parameter"); |
---|
682 | bool computeEigenvectors = (options&ComputeEigenvectors)==ComputeEigenvectors; |
---|
683 | |
---|
684 | MatrixType& eivecs = solver.m_eivec; |
---|
685 | VectorType& eivals = solver.m_eivalues; |
---|
686 | |
---|
687 | // map the matrix coefficients to [-1:1] to avoid over- and underflow. |
---|
688 | Scalar scale = mat.cwiseAbs().maxCoeff(); |
---|
689 | scale = (std::max)(scale,Scalar(1)); |
---|
690 | MatrixType scaledMat = mat / scale; |
---|
691 | |
---|
692 | // Compute the eigenvalues |
---|
693 | computeRoots(scaledMat,eivals); |
---|
694 | |
---|
695 | // compute the eigen vectors |
---|
696 | if(computeEigenvectors) |
---|
697 | { |
---|
698 | scaledMat.diagonal().array () -= eivals(1); |
---|
699 | Scalar a2 = abs2(scaledMat(0,0)); |
---|
700 | Scalar c2 = abs2(scaledMat(1,1)); |
---|
701 | Scalar b2 = abs2(scaledMat(1,0)); |
---|
702 | if(a2>c2) |
---|
703 | { |
---|
704 | eivecs.col(1) << -scaledMat(1,0), scaledMat(0,0); |
---|
705 | eivecs.col(1) /= sqrt(a2+b2); |
---|
706 | } |
---|
707 | else |
---|
708 | { |
---|
709 | eivecs.col(1) << -scaledMat(1,1), scaledMat(1,0); |
---|
710 | eivecs.col(1) /= sqrt(c2+b2); |
---|
711 | } |
---|
712 | |
---|
713 | eivecs.col(0) << eivecs.col(1).unitOrthogonal(); |
---|
714 | } |
---|
715 | |
---|
716 | // Rescale back to the original size. |
---|
717 | eivals *= scale; |
---|
718 | |
---|
719 | solver.m_info = Success; |
---|
720 | solver.m_isInitialized = true; |
---|
721 | solver.m_eigenvectorsOk = computeEigenvectors; |
---|
722 | } |
---|
723 | }; |
---|
724 | |
---|
725 | } |
---|
726 | |
---|
727 | template<typename MatrixType> |
---|
728 | SelfAdjointEigenSolver<MatrixType>& SelfAdjointEigenSolver<MatrixType> |
---|
729 | ::computeDirect(const MatrixType& matrix, int options) |
---|
730 | { |
---|
731 | internal::direct_selfadjoint_eigenvalues<SelfAdjointEigenSolver,Size,NumTraits<Scalar>::IsComplex>::run(*this,matrix,options); |
---|
732 | return *this; |
---|
733 | } |
---|
734 | |
---|
735 | namespace internal { |
---|
736 | template<int StorageOrder,typename RealScalar, typename Scalar, typename Index> |
---|
737 | static void tridiagonal_qr_step(RealScalar* diag, RealScalar* subdiag, Index start, Index end, Scalar* matrixQ, Index n) |
---|
738 | { |
---|
739 | RealScalar td = (diag[end-1] - diag[end])*RealScalar(0.5); |
---|
740 | RealScalar e = subdiag[end-1]; |
---|
741 | // Note that thanks to scaling, e^2 or td^2 cannot overflow, however they can still |
---|
742 | // underflow thus leading to inf/NaN values when using the following commented code: |
---|
743 | // RealScalar e2 = abs2(subdiag[end-1]); |
---|
744 | // RealScalar mu = diag[end] - e2 / (td + (td>0 ? 1 : -1) * sqrt(td*td + e2)); |
---|
745 | // This explain the following, somewhat more complicated, version: |
---|
746 | RealScalar mu = diag[end]; |
---|
747 | if(td==0) |
---|
748 | mu -= abs(e); |
---|
749 | else |
---|
750 | { |
---|
751 | RealScalar e2 = abs2(subdiag[end-1]); |
---|
752 | RealScalar h = hypot(td,e); |
---|
753 | if(e2==0) mu -= (e / (td + (td>0 ? 1 : -1))) * (e / h); |
---|
754 | else mu -= e2 / (td + (td>0 ? h : -h)); |
---|
755 | } |
---|
756 | |
---|
757 | RealScalar x = diag[start] - mu; |
---|
758 | RealScalar z = subdiag[start]; |
---|
759 | for (Index k = start; k < end; ++k) |
---|
760 | { |
---|
761 | JacobiRotation<RealScalar> rot; |
---|
762 | rot.makeGivens(x, z); |
---|
763 | |
---|
764 | // do T = G' T G |
---|
765 | RealScalar sdk = rot.s() * diag[k] + rot.c() * subdiag[k]; |
---|
766 | RealScalar dkp1 = rot.s() * subdiag[k] + rot.c() * diag[k+1]; |
---|
767 | |
---|
768 | diag[k] = rot.c() * (rot.c() * diag[k] - rot.s() * subdiag[k]) - rot.s() * (rot.c() * subdiag[k] - rot.s() * diag[k+1]); |
---|
769 | diag[k+1] = rot.s() * sdk + rot.c() * dkp1; |
---|
770 | subdiag[k] = rot.c() * sdk - rot.s() * dkp1; |
---|
771 | |
---|
772 | |
---|
773 | if (k > start) |
---|
774 | subdiag[k - 1] = rot.c() * subdiag[k-1] - rot.s() * z; |
---|
775 | |
---|
776 | x = subdiag[k]; |
---|
777 | |
---|
778 | if (k < end - 1) |
---|
779 | { |
---|
780 | z = -rot.s() * subdiag[k+1]; |
---|
781 | subdiag[k + 1] = rot.c() * subdiag[k+1]; |
---|
782 | } |
---|
783 | |
---|
784 | // apply the givens rotation to the unit matrix Q = Q * G |
---|
785 | if (matrixQ) |
---|
786 | { |
---|
787 | // FIXME if StorageOrder == RowMajor this operation is not very efficient |
---|
788 | Map<Matrix<Scalar,Dynamic,Dynamic,StorageOrder> > q(matrixQ,n,n); |
---|
789 | q.applyOnTheRight(k,k+1,rot); |
---|
790 | } |
---|
791 | } |
---|
792 | } |
---|
793 | |
---|
794 | } // end namespace internal |
---|
795 | |
---|
796 | } // end namespace Eigen |
---|
797 | |
---|
798 | #endif // EIGEN_SELFADJOINTEIGENSOLVER_H |
---|