11 #ifndef EIGEN_SELFADJOINTEIGENSOLVER_H    12 #define EIGEN_SELFADJOINTEIGENSOLVER_H    18 template<
typename _MatrixType>
    19 class GeneralizedSelfAdjointEigenSolver;
    74       Size = MatrixType::RowsAtCompileTime,
    75       ColsAtCompileTime = MatrixType::ColsAtCompileTime,
    76       Options = MatrixType::Options,
    77       MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime
    81     typedef typename MatrixType::Scalar 
Scalar;
    82     typedef typename MatrixType::Index 
Index;
   116           m_isInitialized(false)
   132         : m_eivec(size, size),
   134           m_subdiag(size > 1 ? size - 1 : 1),
   135           m_isInitialized(false)
   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)
   230       eigen_assert(m_isInitialized && 
"SelfAdjointEigenSolver is not initialized.");
   231       eigen_assert(m_eigenvectorsOk && 
"The eigenvectors have not been computed together with the eigenvalues.");
   252       eigen_assert(m_isInitialized && 
"SelfAdjointEigenSolver is not initialized.");
   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();
   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();
   312       eigen_assert(m_isInitialized && 
"SelfAdjointEigenSolver is not initialized.");
   321     static const int m_maxIterations = 30;
   323     #ifdef EIGEN2_SUPPORT   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)
   330       compute(matrix, computeEigenvectors);
   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)
   342     void compute(
const MatrixType& matrix, 
bool computeEigenvectors)
   347     void compute(
const MatrixType& matA, 
const MatrixType& matB, 
bool computeEigenvectors = 
true)
   351     #endif // EIGEN2_SUPPORT   379 template<
int StorageOrder,
typename RealScalar, 
typename Scalar, 
typename Index>
   383 template<
typename MatrixType>
   391           && 
"invalid option parameter");
   393   Index n = matrix.cols();
   394   m_eivalues.resize(n,1);
   398     m_eivalues.coeffRef(0,0) = 
numext::real(matrix.coeff(0,0));
   399     if(computeEigenvectors)
   400       m_eivec.setOnes(n,n);
   402     m_isInitialized = 
true;
   403     m_eigenvectorsOk = computeEigenvectors;
   412   mat = matrix.template triangularView<Lower>();
   415   mat.template triangularView<Lower>() /= scale;
   416   m_subdiag.resize(n-1);
   425     for (
Index i = start; i<end; ++i)
   430     while (end>0 && m_subdiag[end-1]==0)
   439     if(iter > m_maxIterations * n) 
break;
   442     while (start>0 && m_subdiag[start-1]!=0)
   445     internal::tridiagonal_qr_step<MatrixType::Flags&RowMajorBit ? RowMajor : ColMajor>(diag.data(), m_subdiag.data(), start, end, computeEigenvectors ? m_eivec.data() : (
Scalar*)0, n);
   448   if (iter <= m_maxIterations * n)
   458     for (
Index i = 0; i < n-1; ++i)
   461       m_eivalues.segment(i,n-i).minCoeff(&k);
   464         std::swap(m_eivalues[i], m_eivalues[k+i]);
   465         if(computeEigenvectors)
   466           m_eivec.col(i).swap(m_eivec.col(k+i));
   474   m_isInitialized = 
true;
   475   m_eigenvectorsOk = computeEigenvectors;
   482 template<
typename SolverType,
int Size,
bool IsComplex> 
struct direct_selfadjoint_eigenvalues
   484   static inline void run(SolverType& eig, 
const typename SolverType::MatrixType& A, 
int options)
   485   { eig.compute(A,options); }
   492   typedef typename SolverType::Scalar 
Scalar;
   494   static inline void computeRoots(
const MatrixType& m, VectorType& roots)
   500     const Scalar s_inv3 = Scalar(1.0)/Scalar(3.0);
   501     const Scalar s_sqrt3 = 
sqrt(Scalar(3.0));
   506     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);
   507     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);
   508     Scalar c2 = m(0,0) + m(1,1) + m(2,2);
   512     Scalar c2_over_3 = c2*s_inv3;
   513     Scalar a_over_3 = (c1 - c2*c2_over_3)*s_inv3;
   514     if (a_over_3 > Scalar(0))
   515       a_over_3 = Scalar(0);
   517     Scalar half_b = Scalar(0.5)*(c0 + c2_over_3*(Scalar(2)*c2_over_3*c2_over_3 - c1));
   519     Scalar q = half_b*half_b + a_over_3*a_over_3*a_over_3;
   524     Scalar rho = 
sqrt(-a_over_3);
   525     Scalar theta = atan2(
sqrt(-q),half_b)*s_inv3;
   526     Scalar cos_theta = 
cos(theta);
   527     Scalar sin_theta = 
sin(theta);
   528     roots(0) = c2_over_3 + Scalar(2)*rho*cos_theta;
   529     roots(1) = c2_over_3 - rho*(cos_theta + s_sqrt3*sin_theta);
   530     roots(2) = c2_over_3 - rho*(cos_theta - s_sqrt3*sin_theta);
   533     if (roots(0) >= roots(1))
   534       std::swap(roots(0),roots(1));
   535     if (roots(1) >= roots(2))
   537       std::swap(roots(1),roots(2));
   538       if (roots(0) >= roots(1))
   539         std::swap(roots(0),roots(1));
   543   static inline void run(SolverType& solver, 
const MatrixType& mat, 
int options)
   546     eigen_assert(mat.cols() == 3 && mat.cols() == mat.rows());
   549             && 
"invalid option parameter");
   552     MatrixType& eivecs = solver.m_eivec;
   553     VectorType& eivals = solver.m_eivalues;
   556     Scalar scale = mat.cwiseAbs().maxCoeff();
   557     MatrixType scaledMat = mat / scale;
   560     computeRoots(scaledMat,eivals);
   563     if(computeEigenvectors)
   566       safeNorm2 *= safeNorm2;
   569         eivecs.setIdentity();
   573         scaledMat = scaledMat.template selfadjointView<Lower>();
   577         Scalar d0 = eivals(2) - eivals(1);
   578         Scalar d1 = eivals(1) - eivals(0);
   579         int k =  d0 > d1 ? 2 : 0;
   580         d0 = d0 > d1 ? d1 : d0;
   582         tmp.diagonal().array () -= eivals(k);
   585         n = (cross = tmp.row(0).cross(tmp.row(1))).squaredNorm();
   588           eivecs.col(k) = cross / 
sqrt(n);
   591           n = (cross = tmp.row(0).cross(tmp.row(2))).squaredNorm();
   594             eivecs.col(k) = cross / 
sqrt(n);
   597             n = (cross = tmp.row(1).cross(tmp.row(2))).squaredNorm();
   600               eivecs.col(k) = cross / 
sqrt(n);
   609               solver.m_isInitialized = 
true;
   610               solver.m_eigenvectorsOk = computeEigenvectors;
   617         tmp.diagonal().array() -= eivals(1);
   620           eivecs.col(1) = eivecs.col(k).unitOrthogonal();
   623           n = (cross = eivecs.col(k).cross(tmp.row(0).normalized())).squaredNorm();
   625             eivecs.col(1) = cross / 
sqrt(n);
   628             n = (cross = eivecs.col(k).cross(tmp.row(1))).squaredNorm();
   630               eivecs.col(1) = cross / 
sqrt(n);
   633               n = (cross = eivecs.col(k).cross(tmp.row(2))).squaredNorm();
   635                 eivecs.col(1) = cross / 
sqrt(n);
   640                 eivecs.col(1) = eivecs.col(k).unitOrthogonal();
   646           Scalar 
d = eivecs.col(1).dot(eivecs.col(k));
   647           eivecs.col(1) = (eivecs.col(1) - d * eivecs.col(k)).
normalized();
   650         eivecs.col(k==2 ? 0 : 2) = eivecs.col(k).cross(eivecs.col(1)).
normalized();
   657     solver.m_isInitialized = 
true;
   658     solver.m_eigenvectorsOk = computeEigenvectors;
   667   typedef typename SolverType::Scalar 
Scalar;
   669   static inline void computeRoots(
const MatrixType& m, VectorType& roots)
   672     const Scalar t0 = Scalar(0.5) * 
sqrt( 
numext::abs2(m(0,0)-m(1,1)) + Scalar(4)*m(1,0)*m(1,0));
   673     const Scalar t1 = Scalar(0.5) * (m(0,0) + m(1,1));
   678   static inline void run(SolverType& solver, 
const MatrixType& mat, 
int options)
   681     eigen_assert(mat.cols() == 2 && mat.cols() == mat.rows());
   684             && 
"invalid option parameter");
   687     MatrixType& eivecs = solver.m_eivec;
   688     VectorType& eivals = solver.m_eivalues;
   691     Scalar scale = mat.cwiseAbs().maxCoeff();
   692     scale = (std::max)(scale,Scalar(1));
   693     MatrixType scaledMat = mat / scale;
   696     computeRoots(scaledMat,eivals);
   699     if(computeEigenvectors)
   701       scaledMat.diagonal().array () -= eivals(1);
   707         eivecs.col(1) << -scaledMat(1,0), scaledMat(0,0);
   708         eivecs.col(1) /= 
sqrt(a2+b2);
   712         eivecs.col(1) << -scaledMat(1,1), scaledMat(1,0);
   713         eivecs.col(1) /= 
sqrt(c2+b2);
   716       eivecs.col(0) << eivecs.col(1).unitOrthogonal();
   723     solver.m_isInitialized = 
true;
   724     solver.m_eigenvectorsOk = computeEigenvectors;
   730 template<
typename MatrixType>
   739 template<
int StorageOrder,
typename RealScalar, 
typename Scalar, 
typename Index>
   740 static void tridiagonal_qr_step(RealScalar* diag, RealScalar* subdiag, Index start, Index end, Scalar* matrixQ, Index n)
   743   RealScalar td = (diag[end-1] - diag[end])*RealScalar(0.5);
   744   RealScalar e = subdiag[end-1];
   750   RealScalar mu = diag[end];
   756     RealScalar h = numext::hypot(td,e);
   757     if(e2==0)  mu -= (e / (td + (td>0 ? 1 : -1))) * (e / h);
   758     else       mu -= e2 / (td + (td>0 ? h : -h));
   761   RealScalar 
x = diag[start] - mu;
   762   RealScalar 
z = subdiag[start];
   763   for (Index k = start; k < end; ++k)
   769     RealScalar sdk = rot.
s() * diag[k] + rot.
c() * subdiag[k];
   770     RealScalar dkp1 = rot.
s() * subdiag[k] + rot.
c() * diag[k+1];
   772     diag[k] = rot.
c() * (rot.
c() * diag[k] - rot.
s() * subdiag[k]) - rot.
s() * (rot.
c() * subdiag[k] - rot.
s() * diag[k+1]);
   773     diag[k+1] = rot.
s() * sdk + rot.
c() * dkp1;
   774     subdiag[k] = rot.
c() * sdk - rot.
s() * dkp1;
   778       subdiag[k - 1] = rot.
c() * subdiag[k-1] - rot.
s() * z;
   784       z = -rot.
s() * subdiag[k+1];
   785       subdiag[k + 1] = rot.
c() * subdiag[k+1];
   793       q.applyOnTheRight(k,k+1,rot);
   802 #endif // EIGEN_SELFADJOINTEIGENSOLVER_H 
static void computeRoots(const MatrixType &m, VectorType &roots)
MatrixType operatorSqrt() const 
Computes the positive-definite square root of the matrix. 
SolverType::RealVectorType VectorType
static void run(SolverType &solver, const MatrixType &mat, int options)
MatrixType::Scalar Scalar
Scalar type for matrices of type _MatrixType. 
SolverType::RealVectorType VectorType
void makeGivens(const Scalar &p, const Scalar &q, Scalar *z=0)
SolverType::MatrixType MatrixType
TFSIMD_FORCE_INLINE Vector3 cross(const Vector3 &v) const 
A matrix or vector expression mapping an existing array of data. 
static void run(SolverType &solver, const MatrixType &mat, int options)
Computes eigenvalues and eigenvectors of selfadjoint matrices. 
SolverType::Scalar Scalar
SelfAdjointEigenSolver(const MatrixType &matrix, int options=ComputeEigenvectors)
Constructor; computes eigendecomposition of given matrix. 
Rotation given by a cosine-sine pair. 
Holds information about the various numeric (i.e. scalar) types allowed by Eigen. ...
Tridiagonal decomposition of a selfadjoint matrix. 
bool isMuchSmallerThan(const Scalar &x, const OtherScalar &y, typename NumTraits< Scalar >::Real precision=NumTraits< Scalar >::dummy_precision())
EIGEN_STRONG_INLINE const CwiseUnaryOp< internal::scalar_abs2_op< Scalar >, const Derived > abs2() const 
EIGEN_STRONG_INLINE const CwiseUnaryOp< internal::scalar_abs_op< Scalar >, const Derived > abs() const 
RealReturnType real() const 
TFSIMD_FORCE_INLINE Vector3 normalized() const 
SolverType::MatrixType MatrixType
ComputationInfo info() const 
Reports whether previous computation was successful. 
Computes eigenvalues and eigenvectors of the generalized selfadjoint eigen problem. 
MatrixType operatorInverseSqrt() const 
Computes the inverse square root of the matrix. 
static void tridiagonal_qr_step(RealScalar *diag, RealScalar *subdiag, Index start, Index end, Scalar *matrixQ, Index n)
RealVectorType m_eivalues
TFSIMD_FORCE_INLINE const tfScalar & x() const 
const MatrixType & eigenvectors() const 
Returns the eigenvectors of given matrix. 
const CwiseUnaryOp< internal::scalar_sin_op< Scalar >, const Derived > sin() const 
NumTraits< Scalar >::Real RealScalar
Real scalar type for _MatrixType. 
SelfAdjointEigenSolver(Index size)
Constructor, pre-allocates memory for dynamic-size matrices. 
TFSIMD_FORCE_INLINE const tfScalar & z() const 
void tridiagonalization_inplace(MatrixType &matA, CoeffVectorType &hCoeffs)
SelfAdjointEigenSolver & compute(const MatrixType &matrix, int options=ComputeEigenvectors)
Computes eigendecomposition of given matrix. 
static void computeRoots(const MatrixType &m, VectorType &roots)
SelfAdjointEigenSolver & computeDirect(const MatrixType &matrix, int options=ComputeEigenvectors)
Computes eigendecomposition of given matrix using a direct algorithm. 
const CwiseUnaryOp< internal::scalar_cos_op< Scalar >, const Derived > cos() const 
static void run(SolverType &eig, const typename SolverType::MatrixType &A, int options)
const CwiseUnaryOp< internal::scalar_sqrt_op< Scalar >, const Derived > sqrt() const 
SolverType::Scalar Scalar
The matrix class, also used for vectors and row-vectors. 
TridiagonalizationType::SubDiagonalType m_subdiag
const RealVectorType & eigenvalues() const 
Returns the eigenvalues of given matrix.