aboutsummaryrefslogtreecommitdiffhomepage
path: root/Eigen/src/Eigenvalues
diff options
context:
space:
mode:
authorGravatar Gael Guennebaud <g.gael@free.fr>2016-06-10 15:05:43 +0200
committerGravatar Gael Guennebaud <g.gael@free.fr>2016-06-10 15:05:43 +0200
commit2e238bafb69ab0ee2ab2e682d5ac1a43376f9496 (patch)
treebfa5314f73460ba24745caf47f901f99cec46b27 /Eigen/src/Eigenvalues
parent2c462f4201365d1ac4872245e81066746f09ac47 (diff)
Big 279: enable mixing types for comparisons, min, and max.
Diffstat (limited to 'Eigen/src/Eigenvalues')
-rw-r--r--Eigen/src/Eigenvalues/GeneralizedEigenSolver.h32
1 files changed, 26 insertions, 6 deletions
diff --git a/Eigen/src/Eigenvalues/GeneralizedEigenSolver.h b/Eigen/src/Eigenvalues/GeneralizedEigenSolver.h
index a9d6790d5..07a9ccf46 100644
--- a/Eigen/src/Eigenvalues/GeneralizedEigenSolver.h
+++ b/Eigen/src/Eigenvalues/GeneralizedEigenSolver.h
@@ -327,13 +327,33 @@ GeneralizedEigenSolver<MatrixType>::compute(const MatrixType& A, const MatrixTyp
}
else
{
- Scalar p = Scalar(0.5) * (m_matS.coeff(i, i) - m_matS.coeff(i+1, i+1));
- Scalar z = sqrt(abs(p * p + m_matS.coeff(i+1, i) * m_matS.coeff(i, i+1)));
- m_alphas.coeffRef(i) = ComplexScalar(m_matS.coeff(i+1, i+1) + p, z);
- m_alphas.coeffRef(i+1) = ComplexScalar(m_matS.coeff(i+1, i+1) + p, -z);
+ // We need to extract the generalized eigenvalues of the pair of a general 2x2 block S and a triangular 2x2 block T
+ // From the eigen decomposition of T = U * E * U^-1,
+ // we can extract the eigenvalues of (U^-1 * S * U) / E
+ // Here, we can take advantage that E = diag(T), and U = [ 1 T_01 ; 0 T_11-T_00], and U^-1 = [1 -T_11/(T_11-T_00) ; 0 1/(T_11-T_00)].
+ // Then taking beta=T_00*T_11*(T_11-T_00), we can avoid any division, and alpha is the eigenvalues of A = (U^-1 * S * U) * diag(T_11,T_00) * (T_11-T_00):
+
+ // T = [a b ; 0 c]
+ // S = [e f ; g h]
+ RealScalar a = m_realQZ.matrixT().coeff(i, i), b = m_realQZ.matrixT().coeff(i, i+1), c = m_realQZ.matrixT().coeff(i+1, i+1);
+ RealScalar e = m_matS.coeff(i, i), f = m_matS.coeff(i, i+1), g = m_matS.coeff(i+1, i), h = m_matS.coeff(i+1, i+1);
+ RealScalar d = c-a;
+ RealScalar gb = g*b;
+ Matrix<RealScalar,2,2> A;
+ A << (e*d-gb)*c, ((e*b+f*d-h*b)*d-gb*b)*a,
+ g*c , (gb+h*d)*a;
+
+ // NOTE, we could also compute the SVD of T's block during the QZ factorization so that the respective T block is guaranteed to be diagonal,
+ // and then we could directly apply the formula below (while taking care of scaling S columns by T11,T00):
+
+ Scalar p = Scalar(0.5) * (A.coeff(i, i) - A.coeff(i+1, i+1));
+ Scalar z = sqrt(abs(p * p + A.coeff(i+1, i) * A.coeff(i, i+1)));
+ m_alphas.coeffRef(i) = ComplexScalar(A.coeff(i+1, i+1) + p, z);
+ m_alphas.coeffRef(i+1) = ComplexScalar(A.coeff(i+1, i+1) + p, -z);
+
+ m_betas.coeffRef(i) =
+ m_betas.coeffRef(i+1) = a*c*d;
- m_betas.coeffRef(i) = m_realQZ.matrixT().coeff(i,i);
- m_betas.coeffRef(i+1) = m_realQZ.matrixT().coeff(i,i);
i += 2;
}
}