bug #793: detect NaN and INF in EigenSolver instead of aborting with an assert.

This commit is contained in:
Gael Guennebaud 2014-04-14 22:00:27 +02:00
parent 7098e6d976
commit 3c66bb136b

View File

@ -275,10 +275,11 @@ template<typename _MatrixType> class EigenSolver
*/
EigenSolver& compute(const MatrixType& matrix, bool computeEigenvectors = true);
/** \returns NumericalIssue if the input contains INF or NaN values or overflow occured. Returns Success otherwise. */
ComputationInfo info() const
{
eigen_assert(m_isInitialized && "EigenSolver is not initialized.");
return m_realSchur.info();
return m_info;
}
/** \brief Sets the maximum number of iterations allowed. */
@ -302,6 +303,7 @@ template<typename _MatrixType> class EigenSolver
EigenvalueType m_eivalues;
bool m_isInitialized;
bool m_eigenvectorsOk;
ComputationInfo m_info;
RealSchur<MatrixType> m_realSchur;
MatrixType m_matT;
@ -367,12 +369,15 @@ EigenSolver<MatrixType>::compute(const MatrixType& matrix, bool computeEigenvect
using std::sqrt;
using std::abs;
using std::max;
using numext::isfinite;
eigen_assert(matrix.cols() == matrix.rows());
// Reduce to real Schur form.
m_realSchur.compute(matrix, computeEigenvectors);
m_info = m_realSchur.info();
if (m_realSchur.info() == Success)
if (m_info == Success)
{
m_matT = m_realSchur.matrixT();
if (computeEigenvectors)
@ -386,6 +391,13 @@ EigenSolver<MatrixType>::compute(const MatrixType& matrix, bool computeEigenvect
if (i == matrix.cols() - 1 || m_matT.coeff(i+1, i) == Scalar(0))
{
m_eivalues.coeffRef(i) = m_matT.coeff(i, i);
if(!isfinite(m_eivalues.coeffRef(i)))
{
m_isInitialized = true;
m_eigenvectorsOk = false;
m_info = NumericalIssue;
return *this;
}
++i;
}
else
@ -406,6 +418,13 @@ EigenSolver<MatrixType>::compute(const MatrixType& matrix, bool computeEigenvect
m_eivalues.coeffRef(i) = ComplexScalar(m_matT.coeff(i+1, i+1) + p, z);
m_eivalues.coeffRef(i+1) = ComplexScalar(m_matT.coeff(i+1, i+1) + p, -z);
if(!(isfinite(m_eivalues.coeffRef(i)) && isfinite(m_eivalues.coeffRef(i+1))))
{
m_isInitialized = true;
m_eigenvectorsOk = false;
m_info = NumericalIssue;
return *this;
}
i += 2;
}
}
@ -594,7 +613,7 @@ void EigenSolver<MatrixType>::doComputeEigenvectors()
}
else
{
eigen_assert(0 && "Internal bug in EigenSolver"); // this should not happen
eigen_assert(0 && "Internal bug in EigenSolver (INF or NaN has not been detected)"); // this should not happen
}
}