mirror of
https://gitlab.com/libeigen/eigen.git
synced 2025-04-22 01:29:35 +08:00
fix HouseholderSequence API, bug #50:
* remove ctors taking more than 2 ints * rename actualVectors to length * add length/shift/trans accessors/mutators
This commit is contained in:
parent
e112ad8124
commit
dbd9c5fd50
@ -245,7 +245,9 @@ template<typename _MatrixType> class HessenbergDecomposition
|
|||||||
HouseholderSequenceType matrixQ() const
|
HouseholderSequenceType matrixQ() const
|
||||||
{
|
{
|
||||||
eigen_assert(m_isInitialized && "HessenbergDecomposition is not initialized.");
|
eigen_assert(m_isInitialized && "HessenbergDecomposition is not initialized.");
|
||||||
return HouseholderSequenceType(m_matrix, m_hCoeffs.conjugate(), false, m_matrix.rows() - 1, 1);
|
return HouseholderSequenceType(m_matrix, m_hCoeffs.conjugate())
|
||||||
|
.setLength(m_matrix.rows() - 1)
|
||||||
|
.setShift(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** \brief Constructs the Hessenberg matrix H in the decomposition
|
/** \brief Constructs the Hessenberg matrix H in the decomposition
|
||||||
|
@ -251,7 +251,9 @@ template<typename _MatrixType> class Tridiagonalization
|
|||||||
HouseholderSequenceType matrixQ() const
|
HouseholderSequenceType matrixQ() const
|
||||||
{
|
{
|
||||||
eigen_assert(m_isInitialized && "Tridiagonalization is not initialized.");
|
eigen_assert(m_isInitialized && "Tridiagonalization is not initialized.");
|
||||||
return HouseholderSequenceType(m_matrix, m_hCoeffs.conjugate(), false, m_matrix.rows() - 1, 1);
|
return HouseholderSequenceType(m_matrix, m_hCoeffs.conjugate())
|
||||||
|
.setLength(m_matrix.rows() - 1)
|
||||||
|
.setShift(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** \brief Returns an expression of the tridiagonal matrix T in the decomposition
|
/** \brief Returns an expression of the tridiagonal matrix T in the decomposition
|
||||||
@ -459,7 +461,9 @@ struct tridiagonalization_inplace_selector
|
|||||||
diag = mat.diagonal().real();
|
diag = mat.diagonal().real();
|
||||||
subdiag = mat.template diagonal<-1>().real();
|
subdiag = mat.template diagonal<-1>().real();
|
||||||
if(extractQ)
|
if(extractQ)
|
||||||
mat = HouseholderSequenceType(mat, hCoeffs.conjugate(), false, mat.rows() - 1, 1);
|
mat = HouseholderSequenceType(mat, hCoeffs.conjugate())
|
||||||
|
.setLength(mat.rows() - 1)
|
||||||
|
.setShift(1);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -129,14 +129,18 @@ template<typename VectorsType, typename CoeffsType, int Side> class HouseholderS
|
|||||||
Side
|
Side
|
||||||
> ConjugateReturnType;
|
> ConjugateReturnType;
|
||||||
|
|
||||||
HouseholderSequence(const VectorsType& v, const CoeffsType& h, bool trans = false)
|
HouseholderSequence(const VectorsType& v, const CoeffsType& h)
|
||||||
: m_vectors(v), m_coeffs(h), m_trans(trans), m_actualVectors(v.diagonalSize()),
|
: m_vectors(v), m_coeffs(h), m_trans(false), m_length(v.diagonalSize()),
|
||||||
m_shift(0)
|
m_shift(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
HouseholderSequence(const VectorsType& v, const CoeffsType& h, bool trans, Index actualVectors, Index shift)
|
HouseholderSequence(const HouseholderSequence& other)
|
||||||
: m_vectors(v), m_coeffs(h), m_trans(trans), m_actualVectors(actualVectors), m_shift(shift)
|
: m_vectors(other.m_vectors),
|
||||||
|
m_coeffs(other.m_coeffs),
|
||||||
|
m_trans(other.m_trans),
|
||||||
|
m_length(other.m_length),
|
||||||
|
m_shift(other.m_shift)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,25 +149,34 @@ template<typename VectorsType, typename CoeffsType, int Side> class HouseholderS
|
|||||||
|
|
||||||
const EssentialVectorType essentialVector(Index k) const
|
const EssentialVectorType essentialVector(Index k) const
|
||||||
{
|
{
|
||||||
eigen_assert(k >= 0 && k < m_actualVectors);
|
eigen_assert(k >= 0 && k < m_length);
|
||||||
return internal::hseq_side_dependent_impl<VectorsType,CoeffsType,Side>::essentialVector(*this, k);
|
return internal::hseq_side_dependent_impl<VectorsType,CoeffsType,Side>::essentialVector(*this, k);
|
||||||
}
|
}
|
||||||
|
|
||||||
HouseholderSequence transpose() const
|
HouseholderSequence transpose() const
|
||||||
{ return HouseholderSequence(m_vectors, m_coeffs, !m_trans, m_actualVectors, m_shift); }
|
{
|
||||||
|
return HouseholderSequence(*this).setTrans(!m_trans);
|
||||||
|
}
|
||||||
|
|
||||||
ConjugateReturnType conjugate() const
|
ConjugateReturnType conjugate() const
|
||||||
{ return ConjugateReturnType(m_vectors, m_coeffs.conjugate(), m_trans, m_actualVectors, m_shift); }
|
{
|
||||||
|
return ConjugateReturnType(m_vectors, m_coeffs.conjugate())
|
||||||
|
.setTrans(m_trans)
|
||||||
|
.setLength(m_length)
|
||||||
|
.setShift(m_shift);
|
||||||
|
}
|
||||||
|
|
||||||
ConjugateReturnType adjoint() const
|
ConjugateReturnType adjoint() const
|
||||||
{ return ConjugateReturnType(m_vectors, m_coeffs.conjugate(), !m_trans, m_actualVectors, m_shift); }
|
{
|
||||||
|
return conjugate().setTrans(!m_trans);
|
||||||
|
}
|
||||||
|
|
||||||
ConjugateReturnType inverse() const { return adjoint(); }
|
ConjugateReturnType inverse() const { return adjoint(); }
|
||||||
|
|
||||||
/** \internal */
|
/** \internal */
|
||||||
template<typename DestType> void evalTo(DestType& dst) const
|
template<typename DestType> void evalTo(DestType& dst) const
|
||||||
{
|
{
|
||||||
Index vecs = m_actualVectors;
|
Index vecs = m_length;
|
||||||
// FIXME find a way to pass this temporary if the user wants to
|
// FIXME find a way to pass this temporary if the user wants to
|
||||||
Matrix<Scalar, DestType::RowsAtCompileTime, 1,
|
Matrix<Scalar, DestType::RowsAtCompileTime, 1,
|
||||||
AutoAlign|ColMajor, DestType::MaxRowsAtCompileTime, 1> temp(rows());
|
AutoAlign|ColMajor, DestType::MaxRowsAtCompileTime, 1> temp(rows());
|
||||||
@ -210,9 +223,9 @@ template<typename VectorsType, typename CoeffsType, int Side> class HouseholderS
|
|||||||
template<typename Dest> inline void applyThisOnTheRight(Dest& dst) const
|
template<typename Dest> inline void applyThisOnTheRight(Dest& dst) const
|
||||||
{
|
{
|
||||||
Matrix<Scalar,1,Dest::RowsAtCompileTime> temp(dst.rows());
|
Matrix<Scalar,1,Dest::RowsAtCompileTime> temp(dst.rows());
|
||||||
for(Index k = 0; k < m_actualVectors; ++k)
|
for(Index k = 0; k < m_length; ++k)
|
||||||
{
|
{
|
||||||
Index actual_k = m_trans ? m_actualVectors-k-1 : k;
|
Index actual_k = m_trans ? m_length-k-1 : k;
|
||||||
dst.rightCols(rows()-m_shift-actual_k)
|
dst.rightCols(rows()-m_shift-actual_k)
|
||||||
.applyHouseholderOnTheRight(essentialVector(actual_k), m_coeffs.coeff(actual_k), &temp.coeffRef(0));
|
.applyHouseholderOnTheRight(essentialVector(actual_k), m_coeffs.coeff(actual_k), &temp.coeffRef(0));
|
||||||
}
|
}
|
||||||
@ -222,9 +235,9 @@ template<typename VectorsType, typename CoeffsType, int Side> class HouseholderS
|
|||||||
template<typename Dest> inline void applyThisOnTheLeft(Dest& dst) const
|
template<typename Dest> inline void applyThisOnTheLeft(Dest& dst) const
|
||||||
{
|
{
|
||||||
Matrix<Scalar,1,Dest::ColsAtCompileTime> temp(dst.cols());
|
Matrix<Scalar,1,Dest::ColsAtCompileTime> temp(dst.cols());
|
||||||
for(Index k = 0; k < m_actualVectors; ++k)
|
for(Index k = 0; k < m_length; ++k)
|
||||||
{
|
{
|
||||||
Index actual_k = m_trans ? k : m_actualVectors-k-1;
|
Index actual_k = m_trans ? k : m_length-k-1;
|
||||||
dst.bottomRows(rows()-m_shift-actual_k)
|
dst.bottomRows(rows()-m_shift-actual_k)
|
||||||
.applyHouseholderOnTheLeft(essentialVector(actual_k), m_coeffs.coeff(actual_k), &temp.coeffRef(0));
|
.applyHouseholderOnTheLeft(essentialVector(actual_k), m_coeffs.coeff(actual_k), &temp.coeffRef(0));
|
||||||
}
|
}
|
||||||
@ -250,40 +263,46 @@ template<typename VectorsType, typename CoeffsType, int Side> class HouseholderS
|
|||||||
|
|
||||||
template<typename _VectorsType, typename _CoeffsType, int _Side> friend struct internal::hseq_side_dependent_impl;
|
template<typename _VectorsType, typename _CoeffsType, int _Side> friend struct internal::hseq_side_dependent_impl;
|
||||||
|
|
||||||
|
HouseholderSequence& setTrans(bool trans)
|
||||||
|
{
|
||||||
|
m_trans = trans;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
HouseholderSequence& setLength(Index length)
|
||||||
|
{
|
||||||
|
m_length = length;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
HouseholderSequence& setShift(Index shift)
|
||||||
|
{
|
||||||
|
m_shift = shift;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool trans() const { return m_trans; }
|
||||||
|
Index length() const { return m_length; }
|
||||||
|
Index shift() const { return m_shift; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
typename VectorsType::Nested m_vectors;
|
typename VectorsType::Nested m_vectors;
|
||||||
typename CoeffsType::Nested m_coeffs;
|
typename CoeffsType::Nested m_coeffs;
|
||||||
bool m_trans;
|
bool m_trans;
|
||||||
Index m_actualVectors;
|
Index m_length;
|
||||||
Index m_shift;
|
Index m_shift;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename VectorsType, typename CoeffsType>
|
template<typename VectorsType, typename CoeffsType>
|
||||||
HouseholderSequence<VectorsType,CoeffsType> householderSequence(const VectorsType& v, const CoeffsType& h, bool trans=false)
|
HouseholderSequence<VectorsType,CoeffsType> householderSequence(const VectorsType& v, const CoeffsType& h)
|
||||||
{
|
{
|
||||||
return HouseholderSequence<VectorsType,CoeffsType,OnTheLeft>(v, h, trans);
|
return HouseholderSequence<VectorsType,CoeffsType,OnTheLeft>(v, h);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename VectorsType, typename CoeffsType>
|
template<typename VectorsType, typename CoeffsType>
|
||||||
HouseholderSequence<VectorsType,CoeffsType> householderSequence
|
HouseholderSequence<VectorsType,CoeffsType,OnTheRight> rightHouseholderSequence(const VectorsType& v, const CoeffsType& h)
|
||||||
(const VectorsType& v, const CoeffsType& h,
|
|
||||||
bool trans, typename VectorsType::Index actualVectors, typename VectorsType::Index shift)
|
|
||||||
{
|
{
|
||||||
return HouseholderSequence<VectorsType,CoeffsType,OnTheLeft>(v, h, trans, actualVectors, shift);
|
return HouseholderSequence<VectorsType,CoeffsType,OnTheRight>(v, h);
|
||||||
}
|
|
||||||
|
|
||||||
template<typename VectorsType, typename CoeffsType>
|
|
||||||
HouseholderSequence<VectorsType,CoeffsType,OnTheRight> rightHouseholderSequence(const VectorsType& v, const CoeffsType& h, bool trans=false)
|
|
||||||
{
|
|
||||||
return HouseholderSequence<VectorsType,CoeffsType,OnTheRight>(v, h, trans);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename VectorsType, typename CoeffsType>
|
|
||||||
HouseholderSequence<VectorsType,CoeffsType,OnTheRight> rightHouseholderSequence
|
|
||||||
(const VectorsType& v, const CoeffsType& h, bool trans,
|
|
||||||
typename VectorsType::Index actualVectors, typename VectorsType::Index shift)
|
|
||||||
{
|
|
||||||
return HouseholderSequence<VectorsType,CoeffsType,OnTheRight>(v, h, trans, actualVectors, shift);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // EIGEN_HOUSEHOLDER_SEQUENCE_H
|
#endif // EIGEN_HOUSEHOLDER_SEQUENCE_H
|
||||||
|
@ -483,13 +483,10 @@ struct solve_retval<ColPivHouseholderQR<_MatrixType>, Rhs>
|
|||||||
typename Rhs::PlainObject c(rhs());
|
typename Rhs::PlainObject c(rhs());
|
||||||
|
|
||||||
// Note that the matrix Q = H_0^* H_1^*... so its inverse is Q^* = (H_0 H_1 ...)^T
|
// Note that the matrix Q = H_0^* H_1^*... so its inverse is Q^* = (H_0 H_1 ...)^T
|
||||||
c.applyOnTheLeft(householderSequence(
|
c.applyOnTheLeft(householderSequence(dec().matrixQR(), dec().hCoeffs())
|
||||||
dec().matrixQR(),
|
.setTrans(true)
|
||||||
dec().hCoeffs(),
|
.setLength(dec().nonzeroPivots())
|
||||||
true,
|
);
|
||||||
dec().nonzeroPivots(),
|
|
||||||
0
|
|
||||||
));
|
|
||||||
|
|
||||||
dec().matrixQR()
|
dec().matrixQR()
|
||||||
.topLeftCorner(nonzero_pivots, nonzero_pivots)
|
.topLeftCorner(nonzero_pivots, nonzero_pivots)
|
||||||
@ -517,7 +514,7 @@ typename ColPivHouseholderQR<MatrixType>::HouseholderSequenceType ColPivHousehol
|
|||||||
::householderQ() const
|
::householderQ() const
|
||||||
{
|
{
|
||||||
eigen_assert(m_isInitialized && "ColPivHouseholderQR is not initialized.");
|
eigen_assert(m_isInitialized && "ColPivHouseholderQR is not initialized.");
|
||||||
return HouseholderSequenceType(m_qr, m_hCoeffs.conjugate(), false, m_nonzero_pivots, 0);
|
return HouseholderSequenceType(m_qr, m_hCoeffs.conjugate()).setLength(m_nonzero_pivots);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** \return the column-pivoting Householder QR decomposition of \c *this.
|
/** \return the column-pivoting Householder QR decomposition of \c *this.
|
||||||
|
@ -87,8 +87,9 @@ template<typename _MatrixType> class UpperBidiagonalization
|
|||||||
const HouseholderVSequenceType householderV() // const here gives nasty errors and i'm lazy
|
const HouseholderVSequenceType householderV() // const here gives nasty errors and i'm lazy
|
||||||
{
|
{
|
||||||
eigen_assert(m_isInitialized && "UpperBidiagonalization is not initialized.");
|
eigen_assert(m_isInitialized && "UpperBidiagonalization is not initialized.");
|
||||||
return HouseholderVSequenceType(m_householder, m_householder.const_derived().template diagonal<1>(),
|
return HouseholderVSequenceType(m_householder, m_householder.const_derived().template diagonal<1>())
|
||||||
false, m_householder.cols()-1, 1);
|
.setLength(m_householder.cols()-1)
|
||||||
|
.setShift(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -102,7 +102,12 @@ template<typename MatrixType> void householder(const MatrixType& m)
|
|||||||
m2 = m1;
|
m2 = m1;
|
||||||
m2.block(shift,0,brows,cols) = qr.matrixQR();
|
m2.block(shift,0,brows,cols) = qr.matrixQR();
|
||||||
HCoeffsVectorType hc = qr.hCoeffs().conjugate();
|
HCoeffsVectorType hc = qr.hCoeffs().conjugate();
|
||||||
HouseholderSequence<MatrixType, HCoeffsVectorType> hseq(m2, hc, false, hc.size(), shift);
|
HouseholderSequence<MatrixType, HCoeffsVectorType> hseq(m2, hc);
|
||||||
|
hseq.setLength(hc.size()).setShift(shift);
|
||||||
|
VERIFY(hseq.trans() == false);
|
||||||
|
VERIFY(hseq.length() == hc.size());
|
||||||
|
VERIFY(hseq.shift() == shift);
|
||||||
|
|
||||||
MatrixType m5 = m2;
|
MatrixType m5 = m2;
|
||||||
m5.block(shift,0,brows,cols).template triangularView<StrictlyLower>().setZero();
|
m5.block(shift,0,brows,cols).template triangularView<StrictlyLower>().setZero();
|
||||||
VERIFY_IS_APPROX(hseq * m5, m1); // test applying hseq directly
|
VERIFY_IS_APPROX(hseq * m5, m1); // test applying hseq directly
|
||||||
@ -112,7 +117,8 @@ template<typename MatrixType> void householder(const MatrixType& m)
|
|||||||
// test householder sequence on the right with a shift
|
// test householder sequence on the right with a shift
|
||||||
|
|
||||||
TMatrixType tm2 = m2.transpose();
|
TMatrixType tm2 = m2.transpose();
|
||||||
HouseholderSequence<TMatrixType, HCoeffsVectorType, OnTheRight> rhseq(tm2, hc, false, hc.size(), shift);
|
HouseholderSequence<TMatrixType, HCoeffsVectorType, OnTheRight> rhseq(tm2, hc);
|
||||||
|
rhseq.setLength(hc.size()).setShift(shift);
|
||||||
VERIFY_IS_APPROX(rhseq * m5, m1); // test applying rhseq directly
|
VERIFY_IS_APPROX(rhseq * m5, m1); // test applying rhseq directly
|
||||||
m3 = rhseq;
|
m3 = rhseq;
|
||||||
VERIFY_IS_APPROX(m3 * m5, m1); // test evaluating rhseq to a dense matrix, then applying
|
VERIFY_IS_APPROX(m3 * m5, m1); // test evaluating rhseq to a dense matrix, then applying
|
||||||
|
Loading…
x
Reference in New Issue
Block a user