From 68f35d76b8bcdb19c99b2566d54b63fdb34be75d Mon Sep 17 00:00:00 2001 From: Arthur Date: Thu, 25 Aug 2022 22:05:04 +0000 Subject: [PATCH] Fix GeneralizedEigenSolver::info() and Asserts (cherry picked from commit a7c1cac18bfef26ec61a73c1619ccf0f9b734745) --- .../src/Eigenvalues/GeneralizedEigenSolver.h | 33 ++++++++--------- test/eigensolver_generalized_real.cpp | 37 +++++++++++++++++++ 2 files changed, 53 insertions(+), 17 deletions(-) diff --git a/Eigen/src/Eigenvalues/GeneralizedEigenSolver.h b/Eigen/src/Eigenvalues/GeneralizedEigenSolver.h index 87d789b3f..f9a7627d0 100644 --- a/Eigen/src/Eigenvalues/GeneralizedEigenSolver.h +++ b/Eigen/src/Eigenvalues/GeneralizedEigenSolver.h @@ -119,8 +119,8 @@ template class GeneralizedEigenSolver : m_eivec(), m_alphas(), m_betas(), - m_valuesOkay(false), - m_vectorsOkay(false), + m_computeEigenvectors(false), + m_isInitialized(false), m_realQZ() {} @@ -134,8 +134,8 @@ template class GeneralizedEigenSolver : m_eivec(size, size), m_alphas(size), m_betas(size), - m_valuesOkay(false), - m_vectorsOkay(false), + m_computeEigenvectors(false), + m_isInitialized(false), m_realQZ(size), m_tmp(size) {} @@ -156,8 +156,8 @@ template class GeneralizedEigenSolver : m_eivec(A.rows(), A.cols()), m_alphas(A.cols()), m_betas(A.cols()), - m_valuesOkay(false), - m_vectorsOkay(false), + m_computeEigenvectors(false), + m_isInitialized(false), m_realQZ(A.cols()), m_tmp(A.cols()) { @@ -177,7 +177,8 @@ template class GeneralizedEigenSolver * \sa eigenvalues() */ EigenvectorsType eigenvectors() const { - eigen_assert(m_vectorsOkay && "Eigenvectors for GeneralizedEigenSolver were not calculated."); + eigen_assert(info() == Success && "GeneralizedEigenSolver failed to compute eigenvectors") + eigen_assert(m_computeEigenvectors && "Eigenvectors for GeneralizedEigenSolver were not calculated"); return m_eivec; } @@ -201,7 +202,7 @@ template class GeneralizedEigenSolver */ EigenvalueType eigenvalues() const { - eigen_assert(m_valuesOkay && "GeneralizedEigenSolver is not initialized."); + eigen_assert(info() == Success && "GeneralizedEigenSolver failed to compute eigenvalues."); return EigenvalueType(m_alphas,m_betas); } @@ -212,7 +213,7 @@ template class GeneralizedEigenSolver * \sa betas(), eigenvalues() */ ComplexVectorType alphas() const { - eigen_assert(m_valuesOkay && "GeneralizedEigenSolver is not initialized."); + eigen_assert(info() == Success && "GeneralizedEigenSolver failed to compute alphas."); return m_alphas; } @@ -223,7 +224,7 @@ template class GeneralizedEigenSolver * \sa alphas(), eigenvalues() */ VectorType betas() const { - eigen_assert(m_valuesOkay && "GeneralizedEigenSolver is not initialized."); + eigen_assert(info() == Success && "GeneralizedEigenSolver failed to compute betas."); return m_betas; } @@ -254,7 +255,7 @@ template class GeneralizedEigenSolver ComputationInfo info() const { - eigen_assert(m_valuesOkay && "EigenSolver is not initialized."); + eigen_assert(m_isInitialized && "EigenSolver is not initialized."); return m_realQZ.info(); } @@ -277,7 +278,8 @@ template class GeneralizedEigenSolver EigenvectorsType m_eivec; ComplexVectorType m_alphas; VectorType m_betas; - bool m_valuesOkay, m_vectorsOkay; + bool m_computeEigenvectors; + bool m_isInitialized; RealQZ m_realQZ; ComplexVectorType m_tmp; }; @@ -292,8 +294,6 @@ GeneralizedEigenSolver::compute(const MatrixType& A, const MatrixTyp using std::abs; eigen_assert(A.cols() == A.rows() && B.cols() == A.rows() && B.cols() == B.rows()); Index size = A.cols(); - m_valuesOkay = false; - m_vectorsOkay = false; // Reduce to generalized real Schur form: // A = Q S Z and B = Q T Z m_realQZ.compute(A, B, computeEigenvectors); @@ -406,10 +406,9 @@ GeneralizedEigenSolver::compute(const MatrixType& A, const MatrixTyp i += 2; } } - - m_valuesOkay = true; - m_vectorsOkay = computeEigenvectors; } + m_computeEigenvectors = computeEigenvectors; + m_isInitialized = true; return *this; } diff --git a/test/eigensolver_generalized_real.cpp b/test/eigensolver_generalized_real.cpp index 95ed431db..a0c99b18a 100644 --- a/test/eigensolver_generalized_real.cpp +++ b/test/eigensolver_generalized_real.cpp @@ -85,6 +85,42 @@ template void generalized_eigensolver_real(const MatrixType } } +template +void generalized_eigensolver_assert() { + GeneralizedEigenSolver eig; + // all raise assert if uninitialized + VERIFY_RAISES_ASSERT(eig.info()); + VERIFY_RAISES_ASSERT(eig.eigenvectors()); + VERIFY_RAISES_ASSERT(eig.eigenvalues()); + VERIFY_RAISES_ASSERT(eig.alphas()); + VERIFY_RAISES_ASSERT(eig.betas()); + + // none raise assert after compute called + eig.compute(MatrixType::Random(20, 20), MatrixType::Random(20, 20)); + VERIFY(eig.info() == Success); + eig.eigenvectors(); + eig.eigenvalues(); + eig.alphas(); + eig.betas(); + + // eigenvectors() raises assert, if eigenvectors were not requested + eig.compute(MatrixType::Random(20, 20), MatrixType::Random(20, 20), false); + VERIFY(eig.info() == Success); + VERIFY_RAISES_ASSERT(eig.eigenvectors()); + eig.eigenvalues(); + eig.alphas(); + eig.betas(); + + // all except info raise assert if realQZ did not converge + eig.setMaxIterations(0); // force real QZ to fail. + eig.compute(MatrixType::Random(20, 20), MatrixType::Random(20, 20)); + VERIFY(eig.info() == NoConvergence); + VERIFY_RAISES_ASSERT(eig.eigenvectors()); + VERIFY_RAISES_ASSERT(eig.eigenvalues()); + VERIFY_RAISES_ASSERT(eig.alphas()); + VERIFY_RAISES_ASSERT(eig.betas()); +} + EIGEN_DECLARE_TEST(eigensolver_generalized_real) { for(int i = 0; i < g_repeat; i++) { @@ -98,6 +134,7 @@ EIGEN_DECLARE_TEST(eigensolver_generalized_real) CALL_SUBTEST_2( generalized_eigensolver_real(MatrixXd(2,2)) ); CALL_SUBTEST_3( generalized_eigensolver_real(Matrix()) ); CALL_SUBTEST_4( generalized_eigensolver_real(Matrix2d()) ); + CALL_SUBTEST_5( generalized_eigensolver_assert() ); TEST_SET_BUT_UNUSED_VARIABLE(s) } }