11 #ifndef EIGEN_SELFADJOINTEIGENSOLVER_H    12 #define EIGEN_SELFADJOINTEIGENSOLVER_H    18 template<
typename _MatrixType>
    19 class GeneralizedSelfAdjointEigenSolver;
    23 template<
typename MatrixType, 
typename DiagType, 
typename SubDiagType>
    76       Size = MatrixType::RowsAtCompileTime,
    77       ColsAtCompileTime = MatrixType::ColsAtCompileTime,
    78       Options = MatrixType::Options,
    79       MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime
    83     typedef typename MatrixType::Scalar 
Scalar;
   122           m_isInitialized(false)
   139         : m_eivec(size, size),
   141           m_subdiag(size > 1 ? size - 1 : 1),
   142           m_isInitialized(false)
   160     template<
typename InputType>
   163       : m_eivec(matrix.rows(), matrix.cols()),
   164         m_eivalues(matrix.cols()),
   165         m_subdiag(matrix.rows() > 1 ? matrix.rows() - 1 : 1),
   166         m_isInitialized(false)
   168       compute(matrix.
derived(), options);
   201     template<
typename InputType>
   261       eigen_assert(m_isInitialized && 
"SelfAdjointEigenSolver is not initialized.");
   262       eigen_assert(m_eigenvectorsOk && 
"The eigenvectors have not been computed together with the eigenvalues.");
   284       eigen_assert(m_isInitialized && 
"SelfAdjointEigenSolver is not initialized.");
   308       eigen_assert(m_isInitialized && 
"SelfAdjointEigenSolver is not initialized.");
   309       eigen_assert(m_eigenvectorsOk && 
"The eigenvectors have not been computed together with the eigenvalues.");
   310       return m_eivec * m_eivalues.cwiseSqrt().asDiagonal() * m_eivec.adjoint();
   333       eigen_assert(m_isInitialized && 
"SelfAdjointEigenSolver is not initialized.");
   334       eigen_assert(m_eigenvectorsOk && 
"The eigenvectors have not been computed together with the eigenvalues.");
   335       return m_eivec * m_eivalues.cwiseInverse().cwiseSqrt().asDiagonal() * m_eivec.adjoint();
   345       eigen_assert(m_isInitialized && 
"SelfAdjointEigenSolver is not initialized.");
   354     static const int m_maxIterations = 30;
   391 template<
int StorageOrder,
typename RealScalar, 
typename Scalar, 
typename Index>
   396 template<
typename MatrixType>
   397 template<
typename InputType>
   402   check_template_parameters();
   404   const InputType &matrix(a_matrix.
derived());
   410           && 
"invalid option parameter");
   412   Index n = matrix.cols();
   413   m_eivalues.resize(n,1);
   417     m_eivalues.coeffRef(0,0) = 
numext::real(matrix.diagonal()[0]);
   418     if(computeEigenvectors)
   419       m_eivec.setOnes(n,n);
   421     m_isInitialized = 
true;
   422     m_eigenvectorsOk = computeEigenvectors;
   431   mat = matrix.template triangularView<Lower>();
   434   mat.template triangularView<Lower>() /= scale;
   443   m_isInitialized = 
true;
   444   m_eigenvectorsOk = computeEigenvectors;
   448 template<
typename MatrixType>
   457   if (computeEigenvectors)
   459     m_eivec.setIdentity(diag.size(), diag.size());
   463   m_isInitialized = 
true;
   464   m_eigenvectorsOk = computeEigenvectors;
   480 template<
typename MatrixType, 
typename DiagType, 
typename SubDiagType>
   486   typedef typename MatrixType::Scalar Scalar;
   488   Index n = diag.size();
   493   typedef typename DiagType::RealScalar RealScalar;
   499     for (
Index i = start; i<end; ++i)
   500       if (internal::isMuchSmallerThan(
abs(subdiag[i]),(
abs(diag[i])+
abs(diag[i+1])),precision) || 
abs(subdiag[i]) <= considerAsZero)
   504     while (end>0 && subdiag[end-1]==RealScalar(0))
   513     if(iter > maxIterations * n) 
break;
   516     while (start>0 && subdiag[start-1]!=0)
   519     internal::tridiagonal_qr_step<MatrixType::Flags&RowMajorBit ? RowMajor : ColMajor>(diag.data(), subdiag.data(), start, end, computeEigenvectors ? eivec.data() : (Scalar*)0, n);
   521   if (iter <= maxIterations * n)
   531     for (
Index i = 0; i < n-1; ++i)
   534       diag.segment(i,n-i).minCoeff(&k);
   538         if(computeEigenvectors)
   539           eivec.col(i).swap(eivec.col(k+i));
   549   static inline void run(SolverType& eig, 
const typename SolverType::MatrixType& A, 
int options)
   550   { eig.compute(A,options); }
   557   typedef typename SolverType::Scalar 
Scalar;
   566   static inline void computeRoots(
const MatrixType& m, VectorType& roots)
   568     EIGEN_USING_STD_MATH(
sqrt)
   569     EIGEN_USING_STD_MATH(atan2)
   570     EIGEN_USING_STD_MATH(
cos)
   571     EIGEN_USING_STD_MATH(
sin)
   572     const Scalar s_inv3 = Scalar(1)/Scalar(3);
   573     const Scalar s_sqrt3 = 
sqrt(Scalar(3));
   578     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);
   579     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);
   580     Scalar c2 = m(0,0) + m(1,1) + m(2,2);
   584     Scalar c2_over_3 = c2*s_inv3;
   585     Scalar a_over_3 = (c2*c2_over_3 - c1)*s_inv3;
   586     a_over_3 = numext::maxi(a_over_3, Scalar(0));
   588     Scalar half_b = Scalar(0.5)*(c0 + c2_over_3*(Scalar(2)*c2_over_3*c2_over_3 - c1));
   590     Scalar q = a_over_3*a_over_3*a_over_3 - half_b*half_b;
   591     q = numext::maxi(q, Scalar(0));
   595     Scalar theta = atan2(
sqrt(q),half_b)*s_inv3;  
   596     Scalar cos_theta = 
cos(theta);
   597     Scalar sin_theta = 
sin(theta);
   599     roots(0) = c2_over_3 - rho*(cos_theta + s_sqrt3*sin_theta); 
   600     roots(1) = c2_over_3 - rho*(cos_theta - s_sqrt3*sin_theta); 
   601     roots(2) = c2_over_3 + Scalar(2)*rho*cos_theta;
   610     mat.diagonal().cwiseAbs().maxCoeff(&i0);
   613     representative = mat.col(i0);
   616     n0 = (c0 = representative.cross(mat.col((i0+1)%3))).squaredNorm();
   617     n1 = (c1 = representative.cross(mat.col((i0+2)%3))).squaredNorm();
   625   static inline void run(SolverType& solver, 
const MatrixType& mat, 
int options)
   627     eigen_assert(mat.cols() == 3 && mat.cols() == mat.rows());
   630             && 
"invalid option parameter");
   633     EigenvectorsType& eivecs = solver.m_eivec;
   634     VectorType& eivals = solver.m_eivalues;
   637     Scalar shift = mat.trace() / Scalar(3);
   639     MatrixType scaledMat = mat.template selfadjointView<Lower>();
   640     scaledMat.diagonal().array() -= shift;
   641     Scalar scale = scaledMat.cwiseAbs().maxCoeff();
   642     if(scale > 0) scaledMat /= scale;   
   645     computeRoots(scaledMat,eivals);
   648     if(computeEigenvectors)
   653         eivecs.setIdentity();
   661         Scalar d0 = eivals(2) - eivals(1);
   662         Scalar d1 = eivals(1) - eivals(0);
   672           tmp.diagonal().array () -= eivals(k);
   674           extract_kernel(tmp, eivecs.col(k), eivecs.col(l));
   682           eivecs.col(l) -= eivecs.col(k).dot(eivecs.col(l))*eivecs.col(l);
   683           eivecs.col(l).normalize();
   688           tmp.diagonal().array () -= eivals(l);
   691           extract_kernel(tmp, eivecs.col(l), dummy);
   695         eivecs.col(1) = eivecs.col(2).cross(eivecs.col(0)).normalized();
   701     eivals.array() += shift;
   704     solver.m_isInitialized = 
true;
   705     solver.m_eigenvectorsOk = computeEigenvectors;
   710 template<
typename SolverType> 
   715   typedef typename SolverType::Scalar 
Scalar;
   719   static inline void computeRoots(
const MatrixType& m, VectorType& roots)
   723     const Scalar t1 = Scalar(0.5) * (m(0,0) + m(1,1));
   729   static inline void run(SolverType& solver, 
const MatrixType& mat, 
int options)
   731     EIGEN_USING_STD_MATH(
sqrt);
   732     EIGEN_USING_STD_MATH(
abs);
   734     eigen_assert(mat.cols() == 2 && mat.cols() == mat.rows());
   737             && 
"invalid option parameter");
   740     EigenvectorsType& eivecs = solver.m_eivec;
   741     VectorType& eivals = solver.m_eivalues;
   744     Scalar shift = mat.trace() / Scalar(2);
   745     MatrixType scaledMat = mat;
   746     scaledMat.coeffRef(0,1) = mat.coeff(1,0);
   747     scaledMat.diagonal().array() -= shift;
   748     Scalar scale = scaledMat.cwiseAbs().maxCoeff();
   749     if(scale > Scalar(0))
   753     computeRoots(scaledMat,eivals);
   756     if(computeEigenvectors)
   760         eivecs.setIdentity();
   764         scaledMat.diagonal().array () -= eivals(1);
   770           eivecs.col(1) << -scaledMat(1,0), scaledMat(0,0);
   771           eivecs.col(1) /= 
sqrt(a2+b2);
   775           eivecs.col(1) << -scaledMat(1,1), scaledMat(1,0);
   776           eivecs.col(1) /= 
sqrt(c2+b2);
   779         eivecs.col(0) << eivecs.col(1).unitOrthogonal();
   785     eivals.array() += shift;
   788     solver.m_isInitialized = 
true;
   789     solver.m_eigenvectorsOk = computeEigenvectors;
   795 template<
typename MatrixType>
   805 template<
int StorageOrder,
typename RealScalar, 
typename Scalar, 
typename Index>
   810   RealScalar td = (diag[end-1] - diag[end])*RealScalar(0.5);
   811   RealScalar e = subdiag[end-1];
   817   RealScalar mu = diag[end];
   818   if(td==RealScalar(0))
   823     RealScalar h = numext::hypot(td,e);
   824     if(e2==RealScalar(0)) mu -= (e / (td + (td>RealScalar(0) ? RealScalar(1) : RealScalar(-1)))) * (e / h);
   825     else                  mu -= e2 / (td + (td>RealScalar(0) ? h : -h));
   828   RealScalar x = diag[start] - mu;
   829   RealScalar z = subdiag[start];
   830   for (
Index k = start; k < end; ++k)
   836     RealScalar sdk = rot.
s() * diag[k] + rot.
c() * subdiag[k];
   837     RealScalar dkp1 = rot.
s() * subdiag[k] + rot.
c() * diag[k+1];
   839     diag[k] = rot.
c() * (rot.
c() * diag[k] - rot.
s() * subdiag[k]) - rot.
s() * (rot.
c() * subdiag[k] - rot.
s() * diag[k+1]);
   840     diag[k+1] = rot.
s() * sdk + rot.
c() * dkp1;
   841     subdiag[k] = rot.
c() * sdk - rot.
s() * dkp1;
   845       subdiag[k - 1] = rot.
c() * subdiag[k-1] - rot.
s() * z;
   851       z = -rot.
s() * subdiag[k+1];
   852       subdiag[k + 1] = rot.
c() * subdiag[k+1];
   860       q.applyOnTheRight(k,k+1,rot);
   869 #endif // EIGEN_SELFADJOINTEIGENSOLVER_H 
static EIGEN_DEVICE_FUNC void run(SolverType &solver, const MatrixType &mat, int options)
EIGEN_DEVICE_FUNC SelfAdjointEigenSolver & computeDirect(const MatrixType &matrix, int options=ComputeEigenvectors)
Computes eigendecomposition of given matrix using a closed-form algorithm. 
EIGEN_DEVICE_FUNC const CosReturnType cos() const
EIGEN_DEVICE_FUNC RealReturnType real() const
SolverType::RealVectorType VectorType
MatrixType::Scalar Scalar
Scalar type for matrices of type _MatrixType. 
EIGEN_DEVICE_FUNC ComputationInfo info() const
Reports whether previous computation was successful. 
SolverType::EigenvectorsType EigenvectorsType
SolverType::RealVectorType VectorType
void makeGivens(const Scalar &p, const Scalar &q, Scalar *z=0)
SolverType::MatrixType MatrixType
A matrix or vector expression mapping an existing array of data. 
EIGEN_DEVICE_FUNC SelfAdjointEigenSolver & compute(const EigenBase< InputType > &matrix, int options=ComputeEigenvectors)
Computes eigendecomposition of given matrix. 
Computes eigenvalues and eigenvectors of selfadjoint matrices. 
static EIGEN_DEVICE_FUNC bool extract_kernel(MatrixType &mat, Ref< VectorType > res, Ref< VectorType > representative)
SolverType::Scalar Scalar
EIGEN_DEVICE_FUNC const SqrtReturnType sqrt() const
SolverType::EigenvectorsType EigenvectorsType
Rotation given by a cosine-sine pair. 
static EIGEN_DEVICE_FUNC void computeRoots(const MatrixType &m, VectorType &roots)
Holds information about the various numeric (i.e. scalar) types allowed by Eigen. ...
Tridiagonal decomposition of a selfadjoint matrix. 
double rho(Eigen::Vector2d xy)
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const AbsReturnType abs() const
EIGEN_STRONG_INLINE void swap(T &a, T &b)
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Abs2ReturnType abs2() const
SolverType::MatrixType MatrixType
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void resize(Index rows, Index cols)
static EIGEN_DEVICE_FUNC void tridiagonal_qr_step(RealScalar *diag, RealScalar *subdiag, Index start, Index end, Scalar *matrixQ, Index n)
EIGEN_DEVICE_FUNC SelfAdjointEigenSolver(const EigenBase< InputType > &matrix, int options=ComputeEigenvectors)
Constructor; computes eigendecomposition of given matrix. 
static EIGEN_DEVICE_FUNC void computeRoots(const MatrixType &m, VectorType &roots)
static EIGEN_DEVICE_FUNC void run(SolverType &eig, const typename SolverType::MatrixType &A, int options)
EIGEN_DEVICE_FUNC const RealVectorType & eigenvalues() const
Returns the eigenvalues of given matrix. 
ComputationInfo computeFromTridiagonal_impl(DiagType &diag, SubDiagType &subdiag, const Index maxIterations, bool computeEigenvectors, MatrixType &eivec)
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API. 
SelfAdjointEigenSolver & computeFromTridiagonal(const RealVectorType &diag, const SubDiagonalType &subdiag, int options=ComputeEigenvectors)
Computes the eigen decomposition from a tridiagonal symmetric matrix. 
#define EIGEN_STATIC_ASSERT_NON_INTEGER(TYPE)
RealVectorType m_eivalues
NumTraits< Scalar >::Real RealScalar
Real scalar type for _MatrixType. 
A matrix or vector expression mapping an existing expression. 
void tridiagonalization_inplace(MatrixType &matA, CoeffVectorType &hCoeffs)
static EIGEN_DEVICE_FUNC void run(SolverType &solver, const MatrixType &mat, int options)
static void check_template_parameters()
EIGEN_DEVICE_FUNC SelfAdjointEigenSolver(Index size)
Constructor, pre-allocates memory for dynamic-size matrices. 
EIGEN_DEVICE_FUNC MatrixType operatorInverseSqrt() const
Computes the inverse square root of the matrix. 
EIGEN_DEVICE_FUNC const EigenvectorsType & eigenvectors() const
Returns the eigenvectors of given matrix. 
SolverType::Scalar Scalar
TridiagonalizationType::SubDiagonalType m_subdiag
EIGEN_DEVICE_FUNC MatrixType operatorSqrt() const
Computes the positive-definite square root of the matrix. 
EIGEN_DEVICE_FUNC Derived & derived()
Matrix< Scalar, Size, Size, ColMajor, MaxColsAtCompileTime, MaxColsAtCompileTime > EigenvectorsType
void swap(scoped_array< T > &a, scoped_array< T > &b)
EIGEN_DEVICE_FUNC const SinReturnType sin() const