11 #ifndef EIGEN_SELFADJOINTEIGENSOLVER_H 12 #define EIGEN_SELFADJOINTEIGENSOLVER_H 14 #include "./Tridiagonalization.h" 18 template<
typename _MatrixType>
19 class GeneralizedSelfAdjointEigenSolver;
23 template<
typename MatrixType,
typename DiagType,
typename SubDiagType>
24 ComputationInfo computeFromTridiagonal_impl(DiagType& diag, SubDiagType& subdiag,
const Index maxIterations,
bool computeEigenvectors, MatrixType& eivec);
74 typedef _MatrixType MatrixType;
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;
357 static void check_template_parameters()
359 EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar);
362 EigenvectorsType m_eivec;
366 bool m_isInitialized;
367 bool m_eigenvectorsOk;
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());
407 eigen_assert(matrix.cols() == matrix.rows());
408 eigen_assert((options&~(EigVecMask|GenEigMask))==0
409 && (options&EigVecMask)!=EigVecMask
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;
436 internal::tridiagonalization_inplace(mat, diag, m_subdiag, computeEigenvectors);
438 m_info = internal::computeFromTridiagonal_impl(diag, m_subdiag, m_maxIterations, computeEigenvectors, m_eivec);
443 m_isInitialized =
true;
444 m_eigenvectorsOk = computeEigenvectors;
448 template<
typename MatrixType>
457 if (computeEigenvectors)
459 m_eivec.setIdentity(diag.size(), diag.size());
461 m_info = internal::computeFromTridiagonal_impl(m_eivalues, m_subdiag, m_maxIterations, computeEigenvectors, m_eivec);
463 m_isInitialized =
true;
464 m_eigenvectorsOk = computeEigenvectors;
480 template<
typename MatrixType,
typename DiagType,
typename SubDiagType>
481 ComputationInfo computeFromTridiagonal_impl(DiagType& diag, SubDiagType& subdiag,
const Index maxIterations,
bool computeEigenvectors, MatrixType& eivec)
486 typedef typename MatrixType::Scalar
Scalar;
488 Index n = diag.size();
493 typedef typename DiagType::RealScalar
RealScalar;
494 const RealScalar considerAsZero = (std::numeric_limits<RealScalar>::min)();
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);
537 std::swap(diag[i], diag[k+i]);
538 if(computeEigenvectors)
539 eivec.col(i).swap(eivec.col(k+i));
546 template<
typename SolverType,
int Size,
bool IsComplex>
struct direct_selfadjoint_eigenvalues
549 static inline void run(SolverType& eig,
const typename SolverType::MatrixType&
A,
int options)
550 { eig.compute(A,options); }
555 typedef typename SolverType::MatrixType MatrixType;
556 typedef typename SolverType::RealVectorType
VectorType;
557 typedef typename SolverType::Scalar Scalar;
558 typedef typename SolverType::EigenvectorsType EigenvectorsType;
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));
594 Scalar rho = sqrt(a_over_3);
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();
618 if(n0>n1) res = c0/std::sqrt(n0);
619 else res = c1/std::sqrt(n1);
625 static inline void run(SolverType& solver,
const MatrixType& mat,
int options)
627 eigen_assert(mat.cols() == 3 && mat.cols() == mat.rows());
628 eigen_assert((options&~(EigVecMask|GenEigMask))==0
629 && (options&EigVecMask)!=EigVecMask
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>
713 typedef typename SolverType::MatrixType MatrixType;
714 typedef typename SolverType::RealVectorType
VectorType;
715 typedef typename SolverType::Scalar Scalar;
716 typedef typename SolverType::EigenvectorsType EigenvectorsType;
719 static inline void computeRoots(
const MatrixType& m, VectorType& roots)
722 const Scalar t0 = Scalar(0.5) * sqrt( numext::abs2(m(0,0)-m(1,1)) + Scalar(4)*numext::abs2(m(1,0)));
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());
735 eigen_assert((options&~(EigVecMask|GenEigMask))==0
736 && (options&EigVecMask)!=EigVecMask
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);
765 Scalar a2 = numext::abs2(scaledMat(0,0));
766 Scalar c2 = numext::abs2(scaledMat(1,1));
767 Scalar b2 = numext::abs2(scaledMat(1,0));
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>
825 else mu -= e2 / (td + (td>RealScalar(0) ? h : -h));
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 EIGEN_DEVICE_FUNC SelfAdjointEigenSolver & computeDirect(const MatrixType &matrix, int options=ComputeEigenvectors)
Computes eigendecomposition of given matrix using a closed-form algorithm.
Definition: SelfAdjointEigenSolver.h:798
MatrixType::Scalar Scalar
Scalar type for matrices of type _MatrixType.
Definition: SelfAdjointEigenSolver.h:83
EIGEN_DEVICE_FUNC ComputationInfo info() const
Reports whether previous computation was successful.
Definition: SelfAdjointEigenSolver.h:343
void makeGivens(const Scalar &p, const Scalar &q, Scalar *z=0)
Makes *this as a Givens rotation G such that applying to the left of the vector yields: ...
Definition: Jacobi.h:149
A matrix or vector expression mapping an existing array of data.
Definition: Map.h:88
EIGEN_DEVICE_FUNC SelfAdjointEigenSolver & compute(const EigenBase< InputType > &matrix, int options=ComputeEigenvectors)
Computes eigendecomposition of given matrix.
Definition: SelfAdjointEigenSolver.h:70
Namespace containing all symbols from the Eigen library.
Definition: bench_norm.cpp:85
Definition: ForwardDeclarations.h:263
Holds information about the various numeric (i.e.
Definition: NumTraits.h:150
Definition: Tridiagonalization.h:63
Common base class for all classes T such that MatrixBase has an operator=(T) and a constructor Matrix...
Definition: EigenBase.h:28
Eigen::Index Index
Definition: SelfAdjointEigenSolver.h:84
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void resize(Index rows, Index cols)
Resizes *this to a rows x cols matrix.
Definition: PlainObjectBase.h:273
Used in SelfAdjointEigenSolver and GeneralizedSelfAdjointEigenSolver to specify that both the eigenva...
Definition: Constants.h:395
EIGEN_DEVICE_FUNC SelfAdjointEigenSolver(const EigenBase< InputType > &matrix, int options=ComputeEigenvectors)
Constructor; computes eigendecomposition of given matrix.
Definition: SelfAdjointEigenSolver.h:162
EIGEN_DEVICE_FUNC const RealVectorType & eigenvalues() const
Returns the eigenvalues of given matrix.
Definition: SelfAdjointEigenSolver.h:282
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API.
Definition: Meta.h:33
SelfAdjointEigenSolver & computeFromTridiagonal(const RealVectorType &diag, const SubDiagonalType &subdiag, int options=ComputeEigenvectors)
Computes the eigen decomposition from a tridiagonal symmetric matrix.
Definition: SelfAdjointEigenSolver.h:450
internal::plain_col_type< MatrixType, RealScalar >::type RealVectorType
Type for vector of eigenvalues as returned by eigenvalues().
Definition: SelfAdjointEigenSolver.h:103
NumTraits< Scalar >::Real RealScalar
Real scalar type for _MatrixType.
Definition: SelfAdjointEigenSolver.h:94
Computation was successful.
Definition: Constants.h:432
A matrix or vector expression mapping an existing expression.
Definition: Ref.h:190
Definition: BandTriangularSolver.h:13
Definition: XprHelper.h:585
EIGEN_DEVICE_FUNC SelfAdjointEigenSolver(Index size)
Constructor, pre-allocates memory for dynamic-size matrices.
Definition: SelfAdjointEigenSolver.h:138
EIGEN_DEVICE_FUNC MatrixType operatorInverseSqrt() const
Computes the inverse square root of the matrix.
Definition: SelfAdjointEigenSolver.h:331
EIGEN_DEVICE_FUNC const EigenvectorsType & eigenvectors() const
Returns the eigenvectors of given matrix.
Definition: SelfAdjointEigenSolver.h:259
ComputationInfo
Enum for reporting the status of a computation.
Definition: Constants.h:430
Definition: SelfAdjointEigenSolver.h:22
EIGEN_DEVICE_FUNC MatrixType operatorSqrt() const
Computes the positive-definite square root of the matrix.
Definition: SelfAdjointEigenSolver.h:306
EIGEN_DEVICE_FUNC Derived & derived()
Definition: EigenBase.h:44
Iterative procedure did not converge.
Definition: Constants.h:436