diff --git a/Eigen/src/Eigenvalues/SelfAdjointEigenSolver.h b/Eigen/src/Eigenvalues/SelfAdjointEigenSolver.h index 0af11ba1a..2f302dbae 100644 --- a/Eigen/src/Eigenvalues/SelfAdjointEigenSolver.h +++ b/Eigen/src/Eigenvalues/SelfAdjointEigenSolver.h @@ -500,10 +500,10 @@ template struct direct_selfadjoint_ template struct direct_selfadjoint_eigenvalues { typedef typename SolverType::MatrixType MatrixType; + typedef typename SolverType::RealVectorType VectorType; typedef typename SolverType::Scalar Scalar; - template - inline static void computeRoots(const MatrixType& m, Roots& roots) + inline static void computeRoots(const MatrixType& m, VectorType& roots) { using std::sqrt; using std::atan2; @@ -561,7 +561,7 @@ template struct direct_selfadjoint_eigenvalues struct direct_selfadjoint_eigenvalues struct direct_selfadjoint_eigenvalues +{ + typedef typename SolverType::MatrixType MatrixType; + typedef typename SolverType::RealVectorType VectorType; + typedef typename SolverType::Scalar Scalar; + + inline static void run(SolverType& solver, const MatrixType& mat, int options) + { + eigen_assert(mat.cols() == 2 && mat.cols() == mat.rows()); + eigen_assert((options&~(EigVecMask|GenEigMask))==0 + && (options&EigVecMask)!=EigVecMask + && "invalid option parameter"); + bool computeEigenvectors = (options&ComputeEigenvectors)==ComputeEigenvectors; + + MatrixType& 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 = std::max(scale,Scalar(1)); + MatrixType scaledMat = mat / scale; + + // Compute the eigenvalues + const Scalar xx = scaledMat(0,0); + const Scalar yy = scaledMat(1,1); + const Scalar xy = scaledMat(1,0); + + const Scalar root = std::sqrt((xx-yy)*(xx-yy)+Scalar(4.0)*xy*xy); + const Scalar eig_val1 = Scalar(0.5)*(xx+yy+root); + const Scalar eig_val2 = Scalar(0.5)*(xx+yy-root); + + using std::sqrt; + using std::abs; + + // compute the eigen vectors + if(computeEigenvectors) + { + Scalar nx, ny; + if (xx-yy > 0) + { + Scalar len(1.0); + if (-yy+xx+root != Scalar(0.0)) + { + ny = -Scalar(2.0)*xy/(-yy+xx+root); + len = Scalar(1.0)/sqrt(1+ny*ny); + ny *= len; + } + else + ny = Scalar(0.0); + nx = -len; + } + else + { + Scalar len = Scalar(1.0); + if (-yy+xx-root != Scalar(0.0)) + { + nx = -Scalar(2.0)*xy/(-yy+xx-root); + len = Scalar(1.0)/sqrt(1+nx*nx); + nx *= len; + } + else + nx = Scalar(0.0); + ny = len; + } + + int id0(0), id1(1); + if(eig_val1>eig_val2) + std::swap(id0,id1); + + eivecs.col(id0) << nx, ny; + eivecs.col(id1) << -ny, nx; + eivals(id0) = eig_val1; + eivals(id1) = eig_val2; + } + + // Rescale back to the original size. + eivals *= scale; + + solver.m_info = Success; + solver.m_isInitialized = true; + solver.m_eigenvectorsOk = computeEigenvectors; + } +}; + } template