aboutsummaryrefslogtreecommitdiffhomepage
path: root/Eigen/src/Eigenvalues/SelfAdjointEigenSolver.h
diff options
context:
space:
mode:
Diffstat (limited to 'Eigen/src/Eigenvalues/SelfAdjointEigenSolver.h')
-rw-r--r--Eigen/src/Eigenvalues/SelfAdjointEigenSolver.h40
1 files changed, 23 insertions, 17 deletions
diff --git a/Eigen/src/Eigenvalues/SelfAdjointEigenSolver.h b/Eigen/src/Eigenvalues/SelfAdjointEigenSolver.h
index 469ea5e4e..a9f56c4f5 100644
--- a/Eigen/src/Eigenvalues/SelfAdjointEigenSolver.h
+++ b/Eigen/src/Eigenvalues/SelfAdjointEigenSolver.h
@@ -414,7 +414,7 @@ SelfAdjointEigenSolver<MatrixType>& SelfAdjointEigenSolver<MatrixType>
if(n==1)
{
- m_eivalues.coeffRef(0,0) = numext::real(matrix(0,0));
+ m_eivalues.coeffRef(0,0) = numext::real(matrix.diagonal()[0]);
if(computeEigenvectors)
m_eivec.setOnes(n,n);
m_info = Success;
@@ -458,7 +458,7 @@ SelfAdjointEigenSolver<MatrixType>& SelfAdjointEigenSolver<MatrixType>
{
m_eivec.setIdentity(diag.size(), diag.size());
}
- m_info = computeFromTridiagonal_impl(m_eivalues, m_subdiag, m_maxIterations, computeEigenvectors, m_eivec);
+ m_info = internal::computeFromTridiagonal_impl(m_eivalues, m_subdiag, m_maxIterations, computeEigenvectors, m_eivec);
m_isInitialized = true;
m_eigenvectorsOk = computeEigenvectors;
@@ -492,15 +492,16 @@ ComputationInfo computeFromTridiagonal_impl(DiagType& diag, SubDiagType& subdiag
typedef typename DiagType::RealScalar RealScalar;
const RealScalar considerAsZero = (std::numeric_limits<RealScalar>::min)();
+ const RealScalar precision = RealScalar(2)*NumTraits<RealScalar>::epsilon();
while (end>0)
{
for (Index i = start; i<end; ++i)
- if (internal::isMuchSmallerThan(abs(subdiag[i]),(abs(diag[i])+abs(diag[i+1]))) || abs(subdiag[i]) <= considerAsZero)
+ if (internal::isMuchSmallerThan(abs(subdiag[i]),(abs(diag[i])+abs(diag[i+1])),precision) || abs(subdiag[i]) <= considerAsZero)
subdiag[i] = 0;
// find the largest unreduced block
- while (end>0 && subdiag[end-1]==0)
+ while (end>0 && subdiag[end-1]==RealScalar(0))
{
end--;
}
@@ -568,8 +569,8 @@ template<typename SolverType> struct direct_selfadjoint_eigenvalues<SolverType,3
EIGEN_USING_STD_MATH(atan2)
EIGEN_USING_STD_MATH(cos)
EIGEN_USING_STD_MATH(sin)
- const Scalar s_inv3 = Scalar(1.0)/Scalar(3.0);
- const Scalar s_sqrt3 = sqrt(Scalar(3.0));
+ const Scalar s_inv3 = Scalar(1)/Scalar(3);
+ const Scalar s_sqrt3 = sqrt(Scalar(3));
// The characteristic equation is x^3 - c2*x^2 + c1*x - c0 = 0. The
// eigenvalues are the roots to this equation, all guaranteed to be
@@ -739,14 +740,18 @@ struct direct_selfadjoint_eigenvalues<SolverType,2,false>
EigenvectorsType& eivecs = solver.m_eivec;
VectorType& eivals = solver.m_eivalues;
- // map the matrix coefficients to [-1:1] to avoid over- and underflow.
- Scalar scale = mat.cwiseAbs().maxCoeff();
- scale = numext::maxi(scale,Scalar(1));
- MatrixType scaledMat = mat / scale;
-
+ // Shift the matrix to the mean eigenvalue and map the matrix coefficients to [-1:1] to avoid over- and underflow.
+ Scalar shift = mat.trace() / Scalar(2);
+ MatrixType scaledMat = mat;
+ scaledMat.coeffRef(0,1) = mat.coeff(1,0);
+ scaledMat.diagonal().array() -= shift;
+ Scalar scale = scaledMat.cwiseAbs().maxCoeff();
+ if(scale > Scalar(0))
+ scaledMat /= scale;
+
// Compute the eigenvalues
computeRoots(scaledMat,eivals);
-
+
// compute the eigen vectors
if(computeEigenvectors)
{
@@ -774,10 +779,11 @@ struct direct_selfadjoint_eigenvalues<SolverType,2,false>
eivecs.col(0) << eivecs.col(1).unitOrthogonal();
}
}
-
+
// Rescale back to the original size.
eivals *= scale;
-
+ eivals.array() += shift;
+
solver.m_info = Success;
solver.m_isInitialized = true;
solver.m_eigenvectorsOk = computeEigenvectors;
@@ -809,14 +815,14 @@ static void tridiagonal_qr_step(RealScalar* diag, RealScalar* subdiag, Index sta
// RealScalar mu = diag[end] - e2 / (td + (td>0 ? 1 : -1) * sqrt(td*td + e2));
// This explain the following, somewhat more complicated, version:
RealScalar mu = diag[end];
- if(td==0)
+ if(td==RealScalar(0))
mu -= abs(e);
else
{
RealScalar e2 = numext::abs2(subdiag[end-1]);
RealScalar h = numext::hypot(td,e);
- if(e2==0) mu -= (e / (td + (td>0 ? 1 : -1))) * (e / h);
- else mu -= e2 / (td + (td>0 ? h : -h));
+ if(e2==RealScalar(0)) mu -= (e / (td + (td>RealScalar(0) ? RealScalar(1) : RealScalar(-1)))) * (e / h);
+ else mu -= e2 / (td + (td>RealScalar(0) ? h : -h));
}
RealScalar x = diag[start] - mu;