mirror of
https://gitlab.com/libeigen/eigen.git
synced 2025-05-07 03:39:04 +08:00
RealSchur: use makeHouseholder() to construct the transformation.
This commit is contained in:
parent
cc57df9bea
commit
b6829e1d5b
@ -93,11 +93,13 @@ template<typename _MatrixType> class RealSchur
|
|||||||
EigenvalueType m_eivalues;
|
EigenvalueType m_eivalues;
|
||||||
bool m_isInitialized;
|
bool m_isInitialized;
|
||||||
|
|
||||||
|
typedef Matrix<Scalar,3,1> Vector3s;
|
||||||
|
|
||||||
Scalar computeNormOfT();
|
Scalar computeNormOfT();
|
||||||
int findSmallSubdiagEntry(int n, Scalar norm);
|
int findSmallSubdiagEntry(int n, Scalar norm);
|
||||||
void computeShift(Scalar& x, Scalar& y, Scalar& w, int iu, Scalar& exshift, int iter);
|
void computeShift(Scalar& x, Scalar& y, Scalar& w, int iu, Scalar& exshift, int iter);
|
||||||
void findTwoSmallSubdiagEntries(Scalar x, Scalar y, Scalar w, int l, int& m, int iu, Scalar& p, Scalar& q, Scalar& r);
|
void findTwoSmallSubdiagEntries(Scalar x, Scalar y, Scalar w, int il, int& m, int iu, Vector3s& firstHouseholderVector);
|
||||||
void doFrancisStep(int l, int m, int iu, Scalar p, Scalar q, Scalar r, Scalar x, Scalar* workspace);
|
void doFrancisStep(int il, int m, int iu, const Vector3s& firstHouseholderVector, Scalar* workspace);
|
||||||
void splitOffTwoRows(int iu, Scalar exshift);
|
void splitOffTwoRows(int iu, Scalar exshift);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -147,12 +149,13 @@ void RealSchur<MatrixType>::compute(const MatrixType& matrix)
|
|||||||
}
|
}
|
||||||
else // No convergence yet
|
else // No convergence yet
|
||||||
{
|
{
|
||||||
Scalar p = 0, q = 0, r = 0, x, y, w;
|
Scalar x, y, w;
|
||||||
|
Vector3s firstHouseholderVector;
|
||||||
computeShift(x, y, w, iu, exshift, iter);
|
computeShift(x, y, w, iu, exshift, iter);
|
||||||
iter = iter + 1; // (Could check iteration count here.)
|
iter = iter + 1; // (Could check iteration count here.)
|
||||||
int m;
|
int m;
|
||||||
findTwoSmallSubdiagEntries(x, y, w, il, m, iu, p, q, r);
|
findTwoSmallSubdiagEntries(x, y, w, il, m, iu, firstHouseholderVector);
|
||||||
doFrancisStep(il, m, iu, p, q, r, x, workspace);
|
doFrancisStep(il, m, iu, firstHouseholderVector, workspace);
|
||||||
} // check convergence
|
} // check convergence
|
||||||
} // while (iu >= 0)
|
} // while (iu >= 0)
|
||||||
|
|
||||||
@ -265,8 +268,10 @@ inline void RealSchur<MatrixType>::computeShift(Scalar& x, Scalar& y, Scalar& w,
|
|||||||
|
|
||||||
// Look for two consecutive small sub-diagonal elements
|
// Look for two consecutive small sub-diagonal elements
|
||||||
template<typename MatrixType>
|
template<typename MatrixType>
|
||||||
inline void RealSchur<MatrixType>::findTwoSmallSubdiagEntries(Scalar x, Scalar y, Scalar w, int il, int& m, int iu, Scalar& p, Scalar& q, Scalar& r)
|
inline void RealSchur<MatrixType>::findTwoSmallSubdiagEntries(Scalar x, Scalar y, Scalar w, int il, int& m, int iu, Vector3s& firstHouseholderVector)
|
||||||
{
|
{
|
||||||
|
Scalar p = 0, q = 0, r = 0;
|
||||||
|
|
||||||
m = iu-2;
|
m = iu-2;
|
||||||
while (m >= il)
|
while (m >= il)
|
||||||
{
|
{
|
||||||
@ -298,64 +303,59 @@ inline void RealSchur<MatrixType>::findTwoSmallSubdiagEntries(Scalar x, Scalar y
|
|||||||
if (i > m+2)
|
if (i > m+2)
|
||||||
m_matT.coeffRef(i,i-3) = 0.0;
|
m_matT.coeffRef(i,i-3) = 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
firstHouseholderVector << p, q, r;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Double QR step involving rows il:iu and columns m:iu
|
// Double QR step involving rows il:iu and columns m:iu
|
||||||
template<typename MatrixType>
|
template<typename MatrixType>
|
||||||
inline void RealSchur<MatrixType>::doFrancisStep(int il, int m, int iu, Scalar p, Scalar q, Scalar r, Scalar x, Scalar* workspace)
|
inline void RealSchur<MatrixType>::doFrancisStep(int il, int m, int iu, const Vector3s& firstHouseholderVector, Scalar* workspace)
|
||||||
{
|
{
|
||||||
|
assert(m >= il);
|
||||||
|
assert(m <= iu-2);
|
||||||
|
|
||||||
const int size = m_matU.cols();
|
const int size = m_matU.cols();
|
||||||
|
|
||||||
for (int k = m; k <= iu-1; ++k)
|
for (int k = m; k <= iu-2; ++k)
|
||||||
{
|
{
|
||||||
int notlast = (k != iu-1);
|
bool firstIteration = (k == m);
|
||||||
if (k != m) {
|
|
||||||
p = m_matT.coeff(k,k-1);
|
|
||||||
q = m_matT.coeff(k+1,k-1);
|
|
||||||
r = notlast ? m_matT.coeff(k+2,k-1) : Scalar(0);
|
|
||||||
x = ei_abs(p) + ei_abs(q) + ei_abs(r);
|
|
||||||
if (x != 0.0)
|
|
||||||
{
|
|
||||||
p = p / x;
|
|
||||||
q = q / x;
|
|
||||||
r = r / x;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (x == 0.0)
|
Vector3s v;
|
||||||
break;
|
if (firstIteration)
|
||||||
|
v = firstHouseholderVector;
|
||||||
|
else
|
||||||
|
v = m_matT.template block<3,1>(k,k-1);
|
||||||
|
|
||||||
Scalar s = ei_sqrt(p * p + q * q + r * r);
|
Scalar tau, beta;
|
||||||
|
Matrix<Scalar, 2, 1> ess;
|
||||||
if (p < 0)
|
v.makeHouseholder(ess, tau, beta);
|
||||||
s = -s;
|
|
||||||
|
if (beta != Scalar(0)) // if v is not zero
|
||||||
if (s != 0)
|
|
||||||
{
|
{
|
||||||
if (k != m)
|
if (firstIteration && k > il)
|
||||||
m_matT.coeffRef(k,k-1) = -s * x;
|
|
||||||
else if (il != m)
|
|
||||||
m_matT.coeffRef(k,k-1) = -m_matT.coeff(k,k-1);
|
m_matT.coeffRef(k,k-1) = -m_matT.coeff(k,k-1);
|
||||||
|
else if (!firstIteration)
|
||||||
|
m_matT.coeffRef(k,k-1) = beta;
|
||||||
|
|
||||||
p = p + s;
|
// These Householder transformations form the O(n^3) part of the algorithm
|
||||||
|
m_matT.block(k, k, 3, size-k).applyHouseholderOnTheLeft(ess, tau, workspace);
|
||||||
|
m_matT.block(0, k, std::min(iu,k+3) + 1, 3).applyHouseholderOnTheRight(ess, tau, workspace);
|
||||||
|
m_matU.block(0, k, size, 3).applyHouseholderOnTheRight(ess, tau, workspace);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (notlast)
|
Matrix<Scalar, 2, 1> v = m_matT.template block<2,1>(iu-1, iu-2);
|
||||||
{
|
Scalar tau, beta;
|
||||||
Matrix<Scalar, 2, 1> ess(q/p, r/p);
|
Matrix<Scalar, 1, 1> ess;
|
||||||
m_matT.block(k, k, 3, size-k).applyHouseholderOnTheLeft(ess, p/s, workspace);
|
v.makeHouseholder(ess, tau, beta);
|
||||||
m_matT.block(0, k, std::min(iu,k+3) + 1, 3).applyHouseholderOnTheRight(ess, p/s, workspace);
|
|
||||||
m_matU.block(0, k, size, 3).applyHouseholderOnTheRight(ess, p/s, workspace);
|
if (beta != Scalar(0)) // if v is not zero
|
||||||
}
|
{
|
||||||
else
|
m_matT.coeffRef(iu-1, iu-2) = beta;
|
||||||
{
|
m_matT.block(iu-1, iu-1, 2, size-iu+1).applyHouseholderOnTheLeft(ess, tau, workspace);
|
||||||
Matrix<Scalar, 1, 1> ess;
|
m_matT.block(0, iu-1, iu+1, 2).applyHouseholderOnTheRight(ess, tau, workspace);
|
||||||
ess.coeffRef(0) = q/p;
|
m_matU.block(0, iu-1, size, 2).applyHouseholderOnTheRight(ess, tau, workspace);
|
||||||
m_matT.block(k, k, 2, size-k).applyHouseholderOnTheLeft(ess, p/s, workspace);
|
}
|
||||||
m_matT.block(0, k, std::min(iu,k+3) + 1, 2).applyHouseholderOnTheRight(ess, p/s, workspace);
|
|
||||||
m_matU.block(0, k, size, 2).applyHouseholderOnTheRight(ess, p/s, workspace);
|
|
||||||
}
|
|
||||||
} // (s != 0)
|
|
||||||
} // k loop
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // EIGEN_REAL_SCHUR_H
|
#endif // EIGEN_REAL_SCHUR_H
|
||||||
|
Loading…
x
Reference in New Issue
Block a user