xref: /aosp_15_r20/external/eigen/Eigen/src/Eigenvalues/GeneralizedEigenSolver.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) 2012-2016 Gael Guennebaud <[email protected]>
5*bf2c3715SXin Li // Copyright (C) 2010,2012 Jitse Niesen <[email protected]>
6*bf2c3715SXin Li // Copyright (C) 2016 Tobias Wood <[email protected]>
7*bf2c3715SXin Li //
8*bf2c3715SXin Li // This Source Code Form is subject to the terms of the Mozilla
9*bf2c3715SXin Li // Public License v. 2.0. If a copy of the MPL was not distributed
10*bf2c3715SXin Li // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
11*bf2c3715SXin Li 
12*bf2c3715SXin Li #ifndef EIGEN_GENERALIZEDEIGENSOLVER_H
13*bf2c3715SXin Li #define EIGEN_GENERALIZEDEIGENSOLVER_H
14*bf2c3715SXin Li 
15*bf2c3715SXin Li #include "./RealQZ.h"
16*bf2c3715SXin Li 
17*bf2c3715SXin Li namespace Eigen {
18*bf2c3715SXin Li 
19*bf2c3715SXin Li /** \eigenvalues_module \ingroup Eigenvalues_Module
20*bf2c3715SXin Li   *
21*bf2c3715SXin Li   *
22*bf2c3715SXin Li   * \class GeneralizedEigenSolver
23*bf2c3715SXin Li   *
24*bf2c3715SXin Li   * \brief Computes the generalized eigenvalues and eigenvectors of a pair of general matrices
25*bf2c3715SXin Li   *
26*bf2c3715SXin Li   * \tparam _MatrixType the type of the matrices of which we are computing the
27*bf2c3715SXin Li   * eigen-decomposition; this is expected to be an instantiation of the Matrix
28*bf2c3715SXin Li   * class template. Currently, only real matrices are supported.
29*bf2c3715SXin Li   *
30*bf2c3715SXin Li   * The generalized eigenvalues and eigenvectors of a matrix pair \f$ A \f$ and \f$ B \f$ are scalars
31*bf2c3715SXin Li   * \f$ \lambda \f$ and vectors \f$ v \f$ such that \f$ Av = \lambda Bv \f$.  If
32*bf2c3715SXin Li   * \f$ D \f$ is a diagonal matrix with the eigenvalues on the diagonal, and
33*bf2c3715SXin Li   * \f$ V \f$ is a matrix with the eigenvectors as its columns, then \f$ A V =
34*bf2c3715SXin Li   * B V D \f$. The matrix \f$ V \f$ is almost always invertible, in which case we
35*bf2c3715SXin Li   * have \f$ A = B V D V^{-1} \f$. This is called the generalized eigen-decomposition.
36*bf2c3715SXin Li   *
37*bf2c3715SXin Li   * The generalized eigenvalues and eigenvectors of a matrix pair may be complex, even when the
38*bf2c3715SXin Li   * matrices are real. Moreover, the generalized eigenvalue might be infinite if the matrix B is
39*bf2c3715SXin Li   * singular. To workaround this difficulty, the eigenvalues are provided as a pair of complex \f$ \alpha \f$
40*bf2c3715SXin Li   * and real \f$ \beta \f$ such that: \f$ \lambda_i = \alpha_i / \beta_i \f$. If \f$ \beta_i \f$ is (nearly) zero,
41*bf2c3715SXin Li   * then one can consider the well defined left eigenvalue \f$ \mu = \beta_i / \alpha_i\f$ such that:
42*bf2c3715SXin Li   * \f$ \mu_i A v_i = B v_i \f$, or even \f$ \mu_i u_i^T A  = u_i^T B \f$ where \f$ u_i \f$ is
43*bf2c3715SXin Li   * called the left eigenvector.
44*bf2c3715SXin Li   *
45*bf2c3715SXin Li   * Call the function compute() to compute the generalized eigenvalues and eigenvectors of
46*bf2c3715SXin Li   * a given matrix pair. Alternatively, you can use the
47*bf2c3715SXin Li   * GeneralizedEigenSolver(const MatrixType&, const MatrixType&, bool) constructor which computes the
48*bf2c3715SXin Li   * eigenvalues and eigenvectors at construction time. Once the eigenvalue and
49*bf2c3715SXin Li   * eigenvectors are computed, they can be retrieved with the eigenvalues() and
50*bf2c3715SXin Li   * eigenvectors() functions.
51*bf2c3715SXin Li   *
52*bf2c3715SXin Li   * Here is an usage example of this class:
53*bf2c3715SXin Li   * Example: \include GeneralizedEigenSolver.cpp
54*bf2c3715SXin Li   * Output: \verbinclude GeneralizedEigenSolver.out
55*bf2c3715SXin Li   *
56*bf2c3715SXin Li   * \sa MatrixBase::eigenvalues(), class ComplexEigenSolver, class SelfAdjointEigenSolver
57*bf2c3715SXin Li   */
58*bf2c3715SXin Li template<typename _MatrixType> class GeneralizedEigenSolver
59*bf2c3715SXin Li {
60*bf2c3715SXin Li   public:
61*bf2c3715SXin Li 
62*bf2c3715SXin Li     /** \brief Synonym for the template parameter \p _MatrixType. */
63*bf2c3715SXin Li     typedef _MatrixType MatrixType;
64*bf2c3715SXin Li 
65*bf2c3715SXin Li     enum {
66*bf2c3715SXin Li       RowsAtCompileTime = MatrixType::RowsAtCompileTime,
67*bf2c3715SXin Li       ColsAtCompileTime = MatrixType::ColsAtCompileTime,
68*bf2c3715SXin Li       Options = MatrixType::Options,
69*bf2c3715SXin Li       MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
70*bf2c3715SXin Li       MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime
71*bf2c3715SXin Li     };
72*bf2c3715SXin Li 
73*bf2c3715SXin Li     /** \brief Scalar type for matrices of type #MatrixType. */
74*bf2c3715SXin Li     typedef typename MatrixType::Scalar Scalar;
75*bf2c3715SXin Li     typedef typename NumTraits<Scalar>::Real RealScalar;
76*bf2c3715SXin Li     typedef Eigen::Index Index; ///< \deprecated since Eigen 3.3
77*bf2c3715SXin Li 
78*bf2c3715SXin Li     /** \brief Complex scalar type for #MatrixType.
79*bf2c3715SXin Li       *
80*bf2c3715SXin Li       * This is \c std::complex<Scalar> if #Scalar is real (e.g.,
81*bf2c3715SXin Li       * \c float or \c double) and just \c Scalar if #Scalar is
82*bf2c3715SXin Li       * complex.
83*bf2c3715SXin Li       */
84*bf2c3715SXin Li     typedef std::complex<RealScalar> ComplexScalar;
85*bf2c3715SXin Li 
86*bf2c3715SXin Li     /** \brief Type for vector of real scalar values eigenvalues as returned by betas().
87*bf2c3715SXin Li       *
88*bf2c3715SXin Li       * This is a column vector with entries of type #Scalar.
89*bf2c3715SXin Li       * The length of the vector is the size of #MatrixType.
90*bf2c3715SXin Li       */
91*bf2c3715SXin Li     typedef Matrix<Scalar, ColsAtCompileTime, 1, Options & ~RowMajor, MaxColsAtCompileTime, 1> VectorType;
92*bf2c3715SXin Li 
93*bf2c3715SXin Li     /** \brief Type for vector of complex scalar values eigenvalues as returned by alphas().
94*bf2c3715SXin Li       *
95*bf2c3715SXin Li       * This is a column vector with entries of type #ComplexScalar.
96*bf2c3715SXin Li       * The length of the vector is the size of #MatrixType.
97*bf2c3715SXin Li       */
98*bf2c3715SXin Li     typedef Matrix<ComplexScalar, ColsAtCompileTime, 1, Options & ~RowMajor, MaxColsAtCompileTime, 1> ComplexVectorType;
99*bf2c3715SXin Li 
100*bf2c3715SXin Li     /** \brief Expression type for the eigenvalues as returned by eigenvalues().
101*bf2c3715SXin Li       */
102*bf2c3715SXin Li     typedef CwiseBinaryOp<internal::scalar_quotient_op<ComplexScalar,Scalar>,ComplexVectorType,VectorType> EigenvalueType;
103*bf2c3715SXin Li 
104*bf2c3715SXin Li     /** \brief Type for matrix of eigenvectors as returned by eigenvectors().
105*bf2c3715SXin Li       *
106*bf2c3715SXin Li       * This is a square matrix with entries of type #ComplexScalar.
107*bf2c3715SXin Li       * The size is the same as the size of #MatrixType.
108*bf2c3715SXin Li       */
109*bf2c3715SXin Li     typedef Matrix<ComplexScalar, RowsAtCompileTime, ColsAtCompileTime, Options, MaxRowsAtCompileTime, MaxColsAtCompileTime> EigenvectorsType;
110*bf2c3715SXin Li 
111*bf2c3715SXin Li     /** \brief Default constructor.
112*bf2c3715SXin Li       *
113*bf2c3715SXin Li       * The default constructor is useful in cases in which the user intends to
114*bf2c3715SXin Li       * perform decompositions via EigenSolver::compute(const MatrixType&, bool).
115*bf2c3715SXin Li       *
116*bf2c3715SXin Li       * \sa compute() for an example.
117*bf2c3715SXin Li       */
GeneralizedEigenSolver()118*bf2c3715SXin Li     GeneralizedEigenSolver()
119*bf2c3715SXin Li       : m_eivec(),
120*bf2c3715SXin Li         m_alphas(),
121*bf2c3715SXin Li         m_betas(),
122*bf2c3715SXin Li         m_valuesOkay(false),
123*bf2c3715SXin Li         m_vectorsOkay(false),
124*bf2c3715SXin Li         m_realQZ()
125*bf2c3715SXin Li     {}
126*bf2c3715SXin Li 
127*bf2c3715SXin Li     /** \brief Default constructor with memory preallocation
128*bf2c3715SXin Li       *
129*bf2c3715SXin Li       * Like the default constructor but with preallocation of the internal data
130*bf2c3715SXin Li       * according to the specified problem \a size.
131*bf2c3715SXin Li       * \sa GeneralizedEigenSolver()
132*bf2c3715SXin Li       */
GeneralizedEigenSolver(Index size)133*bf2c3715SXin Li     explicit GeneralizedEigenSolver(Index size)
134*bf2c3715SXin Li       : m_eivec(size, size),
135*bf2c3715SXin Li         m_alphas(size),
136*bf2c3715SXin Li         m_betas(size),
137*bf2c3715SXin Li         m_valuesOkay(false),
138*bf2c3715SXin Li         m_vectorsOkay(false),
139*bf2c3715SXin Li         m_realQZ(size),
140*bf2c3715SXin Li         m_tmp(size)
141*bf2c3715SXin Li     {}
142*bf2c3715SXin Li 
143*bf2c3715SXin Li     /** \brief Constructor; computes the generalized eigendecomposition of given matrix pair.
144*bf2c3715SXin Li       *
145*bf2c3715SXin Li       * \param[in]  A  Square matrix whose eigendecomposition is to be computed.
146*bf2c3715SXin Li       * \param[in]  B  Square matrix whose eigendecomposition is to be computed.
147*bf2c3715SXin Li       * \param[in]  computeEigenvectors  If true, both the eigenvectors and the
148*bf2c3715SXin Li       *    eigenvalues are computed; if false, only the eigenvalues are computed.
149*bf2c3715SXin Li       *
150*bf2c3715SXin Li       * This constructor calls compute() to compute the generalized eigenvalues
151*bf2c3715SXin Li       * and eigenvectors.
152*bf2c3715SXin Li       *
153*bf2c3715SXin Li       * \sa compute()
154*bf2c3715SXin Li       */
155*bf2c3715SXin Li     GeneralizedEigenSolver(const MatrixType& A, const MatrixType& B, bool computeEigenvectors = true)
156*bf2c3715SXin Li       : m_eivec(A.rows(), A.cols()),
157*bf2c3715SXin Li         m_alphas(A.cols()),
158*bf2c3715SXin Li         m_betas(A.cols()),
159*bf2c3715SXin Li         m_valuesOkay(false),
160*bf2c3715SXin Li         m_vectorsOkay(false),
161*bf2c3715SXin Li         m_realQZ(A.cols()),
162*bf2c3715SXin Li         m_tmp(A.cols())
163*bf2c3715SXin Li     {
164*bf2c3715SXin Li       compute(A, B, computeEigenvectors);
165*bf2c3715SXin Li     }
166*bf2c3715SXin Li 
167*bf2c3715SXin Li     /* \brief Returns the computed generalized eigenvectors.
168*bf2c3715SXin Li       *
169*bf2c3715SXin Li       * \returns  %Matrix whose columns are the (possibly complex) right eigenvectors.
170*bf2c3715SXin Li       * i.e. the eigenvectors that solve (A - l*B)x = 0. The ordering matches the eigenvalues.
171*bf2c3715SXin Li       *
172*bf2c3715SXin Li       * \pre Either the constructor
173*bf2c3715SXin Li       * GeneralizedEigenSolver(const MatrixType&,const MatrixType&, bool) or the member function
174*bf2c3715SXin Li       * compute(const MatrixType&, const MatrixType& bool) has been called before, and
175*bf2c3715SXin Li       * \p computeEigenvectors was set to true (the default).
176*bf2c3715SXin Li       *
177*bf2c3715SXin Li       * \sa eigenvalues()
178*bf2c3715SXin Li       */
eigenvectors()179*bf2c3715SXin Li     EigenvectorsType eigenvectors() const {
180*bf2c3715SXin Li       eigen_assert(m_vectorsOkay && "Eigenvectors for GeneralizedEigenSolver were not calculated.");
181*bf2c3715SXin Li       return m_eivec;
182*bf2c3715SXin Li     }
183*bf2c3715SXin Li 
184*bf2c3715SXin Li     /** \brief Returns an expression of the computed generalized eigenvalues.
185*bf2c3715SXin Li       *
186*bf2c3715SXin Li       * \returns An expression of the column vector containing the eigenvalues.
187*bf2c3715SXin Li       *
188*bf2c3715SXin Li       * It is a shortcut for \code this->alphas().cwiseQuotient(this->betas()); \endcode
189*bf2c3715SXin Li       * Not that betas might contain zeros. It is therefore not recommended to use this function,
190*bf2c3715SXin Li       * but rather directly deal with the alphas and betas vectors.
191*bf2c3715SXin Li       *
192*bf2c3715SXin Li       * \pre Either the constructor
193*bf2c3715SXin Li       * GeneralizedEigenSolver(const MatrixType&,const MatrixType&,bool) or the member function
194*bf2c3715SXin Li       * compute(const MatrixType&,const MatrixType&,bool) has been called before.
195*bf2c3715SXin Li       *
196*bf2c3715SXin Li       * The eigenvalues are repeated according to their algebraic multiplicity,
197*bf2c3715SXin Li       * so there are as many eigenvalues as rows in the matrix. The eigenvalues
198*bf2c3715SXin Li       * are not sorted in any particular order.
199*bf2c3715SXin Li       *
200*bf2c3715SXin Li       * \sa alphas(), betas(), eigenvectors()
201*bf2c3715SXin Li       */
eigenvalues()202*bf2c3715SXin Li     EigenvalueType eigenvalues() const
203*bf2c3715SXin Li     {
204*bf2c3715SXin Li       eigen_assert(m_valuesOkay && "GeneralizedEigenSolver is not initialized.");
205*bf2c3715SXin Li       return EigenvalueType(m_alphas,m_betas);
206*bf2c3715SXin Li     }
207*bf2c3715SXin Li 
208*bf2c3715SXin Li     /** \returns A const reference to the vectors containing the alpha values
209*bf2c3715SXin Li       *
210*bf2c3715SXin Li       * This vector permits to reconstruct the j-th eigenvalues as alphas(i)/betas(j).
211*bf2c3715SXin Li       *
212*bf2c3715SXin Li       * \sa betas(), eigenvalues() */
alphas()213*bf2c3715SXin Li     ComplexVectorType alphas() const
214*bf2c3715SXin Li     {
215*bf2c3715SXin Li       eigen_assert(m_valuesOkay && "GeneralizedEigenSolver is not initialized.");
216*bf2c3715SXin Li       return m_alphas;
217*bf2c3715SXin Li     }
218*bf2c3715SXin Li 
219*bf2c3715SXin Li     /** \returns A const reference to the vectors containing the beta values
220*bf2c3715SXin Li       *
221*bf2c3715SXin Li       * This vector permits to reconstruct the j-th eigenvalues as alphas(i)/betas(j).
222*bf2c3715SXin Li       *
223*bf2c3715SXin Li       * \sa alphas(), eigenvalues() */
betas()224*bf2c3715SXin Li     VectorType betas() const
225*bf2c3715SXin Li     {
226*bf2c3715SXin Li       eigen_assert(m_valuesOkay && "GeneralizedEigenSolver is not initialized.");
227*bf2c3715SXin Li       return m_betas;
228*bf2c3715SXin Li     }
229*bf2c3715SXin Li 
230*bf2c3715SXin Li     /** \brief Computes generalized eigendecomposition of given matrix.
231*bf2c3715SXin Li       *
232*bf2c3715SXin Li       * \param[in]  A  Square matrix whose eigendecomposition is to be computed.
233*bf2c3715SXin Li       * \param[in]  B  Square matrix whose eigendecomposition is to be computed.
234*bf2c3715SXin Li       * \param[in]  computeEigenvectors  If true, both the eigenvectors and the
235*bf2c3715SXin Li       *    eigenvalues are computed; if false, only the eigenvalues are
236*bf2c3715SXin Li       *    computed.
237*bf2c3715SXin Li       * \returns    Reference to \c *this
238*bf2c3715SXin Li       *
239*bf2c3715SXin Li       * This function computes the eigenvalues of the real matrix \p matrix.
240*bf2c3715SXin Li       * The eigenvalues() function can be used to retrieve them.  If
241*bf2c3715SXin Li       * \p computeEigenvectors is true, then the eigenvectors are also computed
242*bf2c3715SXin Li       * and can be retrieved by calling eigenvectors().
243*bf2c3715SXin Li       *
244*bf2c3715SXin Li       * The matrix is first reduced to real generalized Schur form using the RealQZ
245*bf2c3715SXin Li       * class. The generalized Schur decomposition is then used to compute the eigenvalues
246*bf2c3715SXin Li       * and eigenvectors.
247*bf2c3715SXin Li       *
248*bf2c3715SXin Li       * The cost of the computation is dominated by the cost of the
249*bf2c3715SXin Li       * generalized Schur decomposition.
250*bf2c3715SXin Li       *
251*bf2c3715SXin Li       * This method reuses of the allocated data in the GeneralizedEigenSolver object.
252*bf2c3715SXin Li       */
253*bf2c3715SXin Li     GeneralizedEigenSolver& compute(const MatrixType& A, const MatrixType& B, bool computeEigenvectors = true);
254*bf2c3715SXin Li 
info()255*bf2c3715SXin Li     ComputationInfo info() const
256*bf2c3715SXin Li     {
257*bf2c3715SXin Li       eigen_assert(m_valuesOkay && "EigenSolver is not initialized.");
258*bf2c3715SXin Li       return m_realQZ.info();
259*bf2c3715SXin Li     }
260*bf2c3715SXin Li 
261*bf2c3715SXin Li     /** Sets the maximal number of iterations allowed.
262*bf2c3715SXin Li     */
setMaxIterations(Index maxIters)263*bf2c3715SXin Li     GeneralizedEigenSolver& setMaxIterations(Index maxIters)
264*bf2c3715SXin Li     {
265*bf2c3715SXin Li       m_realQZ.setMaxIterations(maxIters);
266*bf2c3715SXin Li       return *this;
267*bf2c3715SXin Li     }
268*bf2c3715SXin Li 
269*bf2c3715SXin Li   protected:
270*bf2c3715SXin Li 
check_template_parameters()271*bf2c3715SXin Li     static void check_template_parameters()
272*bf2c3715SXin Li     {
273*bf2c3715SXin Li       EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar);
274*bf2c3715SXin Li       EIGEN_STATIC_ASSERT(!NumTraits<Scalar>::IsComplex, NUMERIC_TYPE_MUST_BE_REAL);
275*bf2c3715SXin Li     }
276*bf2c3715SXin Li 
277*bf2c3715SXin Li     EigenvectorsType m_eivec;
278*bf2c3715SXin Li     ComplexVectorType m_alphas;
279*bf2c3715SXin Li     VectorType m_betas;
280*bf2c3715SXin Li     bool m_valuesOkay, m_vectorsOkay;
281*bf2c3715SXin Li     RealQZ<MatrixType> m_realQZ;
282*bf2c3715SXin Li     ComplexVectorType m_tmp;
283*bf2c3715SXin Li };
284*bf2c3715SXin Li 
285*bf2c3715SXin Li template<typename MatrixType>
286*bf2c3715SXin Li GeneralizedEigenSolver<MatrixType>&
compute(const MatrixType & A,const MatrixType & B,bool computeEigenvectors)287*bf2c3715SXin Li GeneralizedEigenSolver<MatrixType>::compute(const MatrixType& A, const MatrixType& B, bool computeEigenvectors)
288*bf2c3715SXin Li {
289*bf2c3715SXin Li   check_template_parameters();
290*bf2c3715SXin Li 
291*bf2c3715SXin Li   using std::sqrt;
292*bf2c3715SXin Li   using std::abs;
293*bf2c3715SXin Li   eigen_assert(A.cols() == A.rows() && B.cols() == A.rows() && B.cols() == B.rows());
294*bf2c3715SXin Li   Index size = A.cols();
295*bf2c3715SXin Li   m_valuesOkay = false;
296*bf2c3715SXin Li   m_vectorsOkay = false;
297*bf2c3715SXin Li   // Reduce to generalized real Schur form:
298*bf2c3715SXin Li   // A = Q S Z and B = Q T Z
299*bf2c3715SXin Li   m_realQZ.compute(A, B, computeEigenvectors);
300*bf2c3715SXin Li   if (m_realQZ.info() == Success)
301*bf2c3715SXin Li   {
302*bf2c3715SXin Li     // Resize storage
303*bf2c3715SXin Li     m_alphas.resize(size);
304*bf2c3715SXin Li     m_betas.resize(size);
305*bf2c3715SXin Li     if (computeEigenvectors)
306*bf2c3715SXin Li     {
307*bf2c3715SXin Li       m_eivec.resize(size,size);
308*bf2c3715SXin Li       m_tmp.resize(size);
309*bf2c3715SXin Li     }
310*bf2c3715SXin Li 
311*bf2c3715SXin Li     // Aliases:
312*bf2c3715SXin Li     Map<VectorType> v(reinterpret_cast<Scalar*>(m_tmp.data()), size);
313*bf2c3715SXin Li     ComplexVectorType &cv = m_tmp;
314*bf2c3715SXin Li     const MatrixType &mS = m_realQZ.matrixS();
315*bf2c3715SXin Li     const MatrixType &mT = m_realQZ.matrixT();
316*bf2c3715SXin Li 
317*bf2c3715SXin Li     Index i = 0;
318*bf2c3715SXin Li     while (i < size)
319*bf2c3715SXin Li     {
320*bf2c3715SXin Li       if (i == size - 1 || mS.coeff(i+1, i) == Scalar(0))
321*bf2c3715SXin Li       {
322*bf2c3715SXin Li         // Real eigenvalue
323*bf2c3715SXin Li         m_alphas.coeffRef(i) = mS.diagonal().coeff(i);
324*bf2c3715SXin Li         m_betas.coeffRef(i)  = mT.diagonal().coeff(i);
325*bf2c3715SXin Li         if (computeEigenvectors)
326*bf2c3715SXin Li         {
327*bf2c3715SXin Li           v.setConstant(Scalar(0.0));
328*bf2c3715SXin Li           v.coeffRef(i) = Scalar(1.0);
329*bf2c3715SXin Li           // For singular eigenvalues do nothing more
330*bf2c3715SXin Li           if(abs(m_betas.coeffRef(i)) >= (std::numeric_limits<RealScalar>::min)())
331*bf2c3715SXin Li           {
332*bf2c3715SXin Li             // Non-singular eigenvalue
333*bf2c3715SXin Li             const Scalar alpha = real(m_alphas.coeffRef(i));
334*bf2c3715SXin Li             const Scalar beta = m_betas.coeffRef(i);
335*bf2c3715SXin Li             for (Index j = i-1; j >= 0; j--)
336*bf2c3715SXin Li             {
337*bf2c3715SXin Li               const Index st = j+1;
338*bf2c3715SXin Li               const Index sz = i-j;
339*bf2c3715SXin Li               if (j > 0 && mS.coeff(j, j-1) != Scalar(0))
340*bf2c3715SXin Li               {
341*bf2c3715SXin Li                 // 2x2 block
342*bf2c3715SXin Li                 Matrix<Scalar, 2, 1> rhs = (alpha*mT.template block<2,Dynamic>(j-1,st,2,sz) - beta*mS.template block<2,Dynamic>(j-1,st,2,sz)) .lazyProduct( v.segment(st,sz) );
343*bf2c3715SXin Li                 Matrix<Scalar, 2, 2> lhs = beta * mS.template block<2,2>(j-1,j-1) - alpha * mT.template block<2,2>(j-1,j-1);
344*bf2c3715SXin Li                 v.template segment<2>(j-1) = lhs.partialPivLu().solve(rhs);
345*bf2c3715SXin Li                 j--;
346*bf2c3715SXin Li               }
347*bf2c3715SXin Li               else
348*bf2c3715SXin Li               {
349*bf2c3715SXin Li                 v.coeffRef(j) = -v.segment(st,sz).transpose().cwiseProduct(beta*mS.block(j,st,1,sz) - alpha*mT.block(j,st,1,sz)).sum() / (beta*mS.coeffRef(j,j) - alpha*mT.coeffRef(j,j));
350*bf2c3715SXin Li               }
351*bf2c3715SXin Li             }
352*bf2c3715SXin Li           }
353*bf2c3715SXin Li           m_eivec.col(i).real().noalias() = m_realQZ.matrixZ().transpose() * v;
354*bf2c3715SXin Li           m_eivec.col(i).real().normalize();
355*bf2c3715SXin Li           m_eivec.col(i).imag().setConstant(0);
356*bf2c3715SXin Li         }
357*bf2c3715SXin Li         ++i;
358*bf2c3715SXin Li       }
359*bf2c3715SXin Li       else
360*bf2c3715SXin Li       {
361*bf2c3715SXin Li         // We need to extract the generalized eigenvalues of the pair of a general 2x2 block S and a positive diagonal 2x2 block T
362*bf2c3715SXin Li         // Then taking beta=T_00*T_11, we can avoid any division, and alpha is the eigenvalues of A = (U^-1 * S * U) * diag(T_11,T_00):
363*bf2c3715SXin Li 
364*bf2c3715SXin Li         // T =  [a 0]
365*bf2c3715SXin Li         //      [0 b]
366*bf2c3715SXin Li         RealScalar a = mT.diagonal().coeff(i),
367*bf2c3715SXin Li                    b = mT.diagonal().coeff(i+1);
368*bf2c3715SXin Li         const RealScalar beta = m_betas.coeffRef(i) = m_betas.coeffRef(i+1) = a*b;
369*bf2c3715SXin Li 
370*bf2c3715SXin Li         // ^^ NOTE: using diagonal()(i) instead of coeff(i,i) workarounds a MSVC bug.
371*bf2c3715SXin Li         Matrix<RealScalar,2,2> S2 = mS.template block<2,2>(i,i) * Matrix<Scalar,2,1>(b,a).asDiagonal();
372*bf2c3715SXin Li 
373*bf2c3715SXin Li         Scalar p = Scalar(0.5) * (S2.coeff(0,0) - S2.coeff(1,1));
374*bf2c3715SXin Li         Scalar z = sqrt(abs(p * p + S2.coeff(1,0) * S2.coeff(0,1)));
375*bf2c3715SXin Li         const ComplexScalar alpha = ComplexScalar(S2.coeff(1,1) + p, (beta > 0) ? z : -z);
376*bf2c3715SXin Li         m_alphas.coeffRef(i)   = conj(alpha);
377*bf2c3715SXin Li         m_alphas.coeffRef(i+1) = alpha;
378*bf2c3715SXin Li 
379*bf2c3715SXin Li         if (computeEigenvectors) {
380*bf2c3715SXin Li           // Compute eigenvector in position (i+1) and then position (i) is just the conjugate
381*bf2c3715SXin Li           cv.setZero();
382*bf2c3715SXin Li           cv.coeffRef(i+1) = Scalar(1.0);
383*bf2c3715SXin Li           // here, the "static_cast" workaound expression template issues.
384*bf2c3715SXin Li           cv.coeffRef(i) = -(static_cast<Scalar>(beta*mS.coeffRef(i,i+1)) - alpha*mT.coeffRef(i,i+1))
385*bf2c3715SXin Li                           / (static_cast<Scalar>(beta*mS.coeffRef(i,i))   - alpha*mT.coeffRef(i,i));
386*bf2c3715SXin Li           for (Index j = i-1; j >= 0; j--)
387*bf2c3715SXin Li           {
388*bf2c3715SXin Li             const Index st = j+1;
389*bf2c3715SXin Li             const Index sz = i+1-j;
390*bf2c3715SXin Li             if (j > 0 && mS.coeff(j, j-1) != Scalar(0))
391*bf2c3715SXin Li             {
392*bf2c3715SXin Li               // 2x2 block
393*bf2c3715SXin Li               Matrix<ComplexScalar, 2, 1> rhs = (alpha*mT.template block<2,Dynamic>(j-1,st,2,sz) - beta*mS.template block<2,Dynamic>(j-1,st,2,sz)) .lazyProduct( cv.segment(st,sz) );
394*bf2c3715SXin Li               Matrix<ComplexScalar, 2, 2> lhs = beta * mS.template block<2,2>(j-1,j-1) - alpha * mT.template block<2,2>(j-1,j-1);
395*bf2c3715SXin Li               cv.template segment<2>(j-1) = lhs.partialPivLu().solve(rhs);
396*bf2c3715SXin Li               j--;
397*bf2c3715SXin Li             } else {
398*bf2c3715SXin Li               cv.coeffRef(j) =  cv.segment(st,sz).transpose().cwiseProduct(beta*mS.block(j,st,1,sz) - alpha*mT.block(j,st,1,sz)).sum()
399*bf2c3715SXin Li                               / (alpha*mT.coeffRef(j,j) - static_cast<Scalar>(beta*mS.coeffRef(j,j)));
400*bf2c3715SXin Li             }
401*bf2c3715SXin Li           }
402*bf2c3715SXin Li           m_eivec.col(i+1).noalias() = (m_realQZ.matrixZ().transpose() * cv);
403*bf2c3715SXin Li           m_eivec.col(i+1).normalize();
404*bf2c3715SXin Li           m_eivec.col(i) = m_eivec.col(i+1).conjugate();
405*bf2c3715SXin Li         }
406*bf2c3715SXin Li         i += 2;
407*bf2c3715SXin Li       }
408*bf2c3715SXin Li     }
409*bf2c3715SXin Li 
410*bf2c3715SXin Li     m_valuesOkay = true;
411*bf2c3715SXin Li     m_vectorsOkay = computeEigenvectors;
412*bf2c3715SXin Li   }
413*bf2c3715SXin Li   return *this;
414*bf2c3715SXin Li }
415*bf2c3715SXin Li 
416*bf2c3715SXin Li } // end namespace Eigen
417*bf2c3715SXin Li 
418*bf2c3715SXin Li #endif // EIGEN_GENERALIZEDEIGENSOLVER_H
419