diff --git a/Eigen/src/Eigenvalues/SelfAdjointEigenSolver.h b/Eigen/src/Eigenvalues/SelfAdjointEigenSolver.h index f84da9139..161e6b572 100644 --- a/Eigen/src/Eigenvalues/SelfAdjointEigenSolver.h +++ b/Eigen/src/Eigenvalues/SelfAdjointEigenSolver.h @@ -325,6 +325,22 @@ class SelfAdjointEigenSolver { return m_eivec * m_eivalues.cwiseSqrt().asDiagonal() * m_eivec.adjoint(); } + /** \brief Computes the matrix exponential the matrix. + * + * \returns the matrix exponential the matrix. + * + * \pre The eigenvalues and eigenvectors of a positive-definite matrix + * have been computed before. + * + * \sa operatorInverseSqrt(), operatorSqrt(), + * MatrixFunctions Module + */ + EIGEN_DEVICE_FUNC MatrixType operatorExp() const { + eigen_assert(m_isInitialized && "SelfAdjointEigenSolver is not initialized."); + eigen_assert(m_eigenvectorsOk && "The eigenvectors have not been computed together with the eigenvalues."); + return m_eivec * m_eivalues.array().exp().matrix().asDiagonal() * m_eivec.adjoint(); + } + /** \brief Computes the inverse square root of the matrix. * * \returns the inverse positive-definite square root of the matrix diff --git a/test/eigensolver_selfadjoint.cpp b/test/eigensolver_selfadjoint.cpp index 04e727d83..12bc3b1f7 100644 --- a/test/eigensolver_selfadjoint.cpp +++ b/test/eigensolver_selfadjoint.cpp @@ -13,6 +13,7 @@ #include #include #include +#include template void selfadjointeigensolver_essential_check(const MatrixType& m) { @@ -135,11 +136,13 @@ void selfadjointeigensolver(const MatrixType& m) { VERIFY_RAISES_ASSERT(eiSymmUninitialized.eigenvectors()); VERIFY_RAISES_ASSERT(eiSymmUninitialized.operatorSqrt()); VERIFY_RAISES_ASSERT(eiSymmUninitialized.operatorInverseSqrt()); + VERIFY_RAISES_ASSERT(eiSymmUninitialized.operatorExp()); eiSymmUninitialized.compute(symmA, false); VERIFY_RAISES_ASSERT(eiSymmUninitialized.eigenvectors()); VERIFY_RAISES_ASSERT(eiSymmUninitialized.operatorSqrt()); VERIFY_RAISES_ASSERT(eiSymmUninitialized.operatorInverseSqrt()); + VERIFY_RAISES_ASSERT(eiSymmUninitialized.operatorExp()); // test Tridiagonalization's methods Tridiagonalization tridiag(symmC); @@ -167,6 +170,14 @@ void selfadjointeigensolver(const MatrixType& m) { eiSymmTridiag.eigenvectors().real().transpose()); } + // Test matrix expponential from eigendecomposition. + // First scale to avoid overflow. + symmB = symmB / symmB.norm(); + eiSymm.compute(symmB); + MatrixType expSymmB = eiSymm.operatorExp(); + symmB = symmB.template selfadjointView(); + VERIFY_IS_APPROX(expSymmB, symmB.exp()); + if (rows > 1 && rows < 20) { // Test matrix with NaN symmC(0, 0) = std::numeric_limits::quiet_NaN();