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