mirror of
https://gitlab.com/libeigen/eigen.git
synced 2025-03-07 18:27:40 +08:00
bug #793: fix overflow in EigenSolver and add respective regression unit test
This commit is contained in:
parent
91288e9bf9
commit
0587db8bf5
@ -366,6 +366,7 @@ EigenSolver<MatrixType>::compute(const MatrixType& matrix, bool computeEigenvect
|
||||
{
|
||||
using std::sqrt;
|
||||
using std::abs;
|
||||
using std::max;
|
||||
eigen_assert(matrix.cols() == matrix.rows());
|
||||
|
||||
// Reduce to real Schur form.
|
||||
@ -390,7 +391,19 @@ EigenSolver<MatrixType>::compute(const MatrixType& matrix, bool computeEigenvect
|
||||
else
|
||||
{
|
||||
Scalar p = Scalar(0.5) * (m_matT.coeff(i, i) - m_matT.coeff(i+1, i+1));
|
||||
Scalar z = sqrt(abs(p * p + m_matT.coeff(i+1, i) * m_matT.coeff(i, i+1)));
|
||||
Scalar z;
|
||||
// Compute z = sqrt(abs(p * p + m_matT.coeff(i+1, i) * m_matT.coeff(i, i+1)));
|
||||
// without overflow
|
||||
{
|
||||
Scalar t0 = m_matT.coeff(i+1, i);
|
||||
Scalar t1 = m_matT.coeff(i, i+1);
|
||||
Scalar maxval = (max)(abs(p),(max)(abs(t0),abs(t1)));
|
||||
t0 /= maxval;
|
||||
t1 /= maxval;
|
||||
Scalar p0 = p/maxval;
|
||||
z = maxval * sqrt(abs(p0 * p0 + t0 * t1));
|
||||
}
|
||||
|
||||
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);
|
||||
i += 2;
|
||||
|
@ -121,5 +121,18 @@ void test_eigensolver_generic()
|
||||
}
|
||||
);
|
||||
|
||||
// regression test for bug 793
|
||||
#ifdef EIGEN_TEST_PART_2
|
||||
{
|
||||
MatrixXd a(3,3);
|
||||
a << 0, 0, 1,
|
||||
1, 1, 1,
|
||||
1, 1e+200, 1;
|
||||
Eigen::EigenSolver<MatrixXd> eig(a);
|
||||
VERIFY_IS_APPROX(a * eig.pseudoEigenvectors(), eig.pseudoEigenvectors() * eig.pseudoEigenvalueMatrix());
|
||||
VERIFY_IS_APPROX(a * eig.eigenvectors(), eig.eigenvectors() * eig.eigenvalues().asDiagonal());
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST_SET_BUT_UNUSED_VARIABLE(s)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user