diff options
author | Gael Guennebaud <g.gael@free.fr> | 2014-04-14 11:43:08 +0200 |
---|---|---|
committer | Gael Guennebaud <g.gael@free.fr> | 2014-04-14 11:43:08 +0200 |
commit | 0587db8bf5ca5d5eb6fb8df1c02abddd5b5718ba (patch) | |
tree | f1e8f6b479cf96e4454b6bdc78a5c1b5efb6e245 /Eigen/src/Eigenvalues/EigenSolver.h | |
parent | 91288e9bf9d6a9c3d63a9152e863b4390d0a40c7 (diff) |
bug #793: fix overflow in EigenSolver and add respective regression unit test
Diffstat (limited to 'Eigen/src/Eigenvalues/EigenSolver.h')
-rw-r--r-- | Eigen/src/Eigenvalues/EigenSolver.h | 15 |
1 files changed, 14 insertions, 1 deletions
diff --git a/Eigen/src/Eigenvalues/EigenSolver.h b/Eigen/src/Eigenvalues/EigenSolver.h index bf20e03ef..739466949 100644 --- a/Eigen/src/Eigenvalues/EigenSolver.h +++ b/Eigen/src/Eigenvalues/EigenSolver.h @@ -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; |