mirror of
https://gitlab.com/libeigen/eigen.git
synced 2026-04-10 11:34:33 +08:00
PR 567: makes all dense solvers inherit SoverBase (LU,Cholesky,QR,SVD).
This changeset also includes: * add HouseholderSequence::conjugateIf * define int as the StorageIndex type for all dense solvers * dedicated unit tests, including assertion checking * _check_solve_assertion(): this method can be implemented in derived solver classes to implement custom checks * CompleteOrthogonalDecompositions: add applyZOnTheLeftInPlace, fix scalar type in applyZAdjointOnTheLeftInPlace(), add missing assertions * Cholesky: add missing assertions * FullPivHouseholderQR: Corrected Scalar type in _solve_impl() * BDCSVD: Unambiguous return type for ternary operator * SVDBase: Corrected Scalar type in _solve_impl()
This commit is contained in:
@@ -17,6 +17,9 @@ namespace internal {
|
||||
template<typename _MatrixType> struct traits<ColPivHouseholderQR<_MatrixType> >
|
||||
: traits<_MatrixType>
|
||||
{
|
||||
typedef MatrixXpr XprKind;
|
||||
typedef SolverStorage StorageKind;
|
||||
typedef int StorageIndex;
|
||||
enum { Flags = 0 };
|
||||
};
|
||||
|
||||
@@ -46,20 +49,19 @@ template<typename _MatrixType> struct traits<ColPivHouseholderQR<_MatrixType> >
|
||||
* \sa MatrixBase::colPivHouseholderQr()
|
||||
*/
|
||||
template<typename _MatrixType> class ColPivHouseholderQR
|
||||
: public SolverBase<ColPivHouseholderQR<_MatrixType> >
|
||||
{
|
||||
public:
|
||||
|
||||
typedef _MatrixType MatrixType;
|
||||
typedef SolverBase<ColPivHouseholderQR> Base;
|
||||
friend class SolverBase<ColPivHouseholderQR>;
|
||||
|
||||
EIGEN_GENERIC_PUBLIC_INTERFACE(ColPivHouseholderQR)
|
||||
enum {
|
||||
RowsAtCompileTime = MatrixType::RowsAtCompileTime,
|
||||
ColsAtCompileTime = MatrixType::ColsAtCompileTime,
|
||||
MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
|
||||
MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime
|
||||
};
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
typedef typename MatrixType::RealScalar RealScalar;
|
||||
// FIXME should be int
|
||||
typedef typename MatrixType::StorageIndex StorageIndex;
|
||||
typedef typename internal::plain_diag_type<MatrixType>::type HCoeffsType;
|
||||
typedef PermutationMatrix<ColsAtCompileTime, MaxColsAtCompileTime> PermutationType;
|
||||
typedef typename internal::plain_row_type<MatrixType, Index>::type IntRowVectorType;
|
||||
@@ -156,6 +158,7 @@ template<typename _MatrixType> class ColPivHouseholderQR
|
||||
computeInPlace();
|
||||
}
|
||||
|
||||
#ifdef EIGEN_PARSED_BY_DOXYGEN
|
||||
/** This method finds a solution x to the equation Ax=b, where A is the matrix of which
|
||||
* *this is the QR decomposition, if any exists.
|
||||
*
|
||||
@@ -172,11 +175,8 @@ template<typename _MatrixType> class ColPivHouseholderQR
|
||||
*/
|
||||
template<typename Rhs>
|
||||
inline const Solve<ColPivHouseholderQR, Rhs>
|
||||
solve(const MatrixBase<Rhs>& b) const
|
||||
{
|
||||
eigen_assert(m_isInitialized && "ColPivHouseholderQR is not initialized.");
|
||||
return Solve<ColPivHouseholderQR, Rhs>(*this, b.derived());
|
||||
}
|
||||
solve(const MatrixBase<Rhs>& b) const;
|
||||
#endif
|
||||
|
||||
HouseholderSequenceType householderQ() const;
|
||||
HouseholderSequenceType matrixQ() const
|
||||
@@ -417,6 +417,9 @@ template<typename _MatrixType> class ColPivHouseholderQR
|
||||
#ifndef EIGEN_PARSED_BY_DOXYGEN
|
||||
template<typename RhsType, typename DstType>
|
||||
void _solve_impl(const RhsType &rhs, DstType &dst) const;
|
||||
|
||||
template<bool Conjugate, typename RhsType, typename DstType>
|
||||
void _solve_impl_transposed(const RhsType &rhs, DstType &dst) const;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
@@ -583,8 +586,6 @@ template<typename _MatrixType>
|
||||
template<typename RhsType, typename DstType>
|
||||
void ColPivHouseholderQR<_MatrixType>::_solve_impl(const RhsType &rhs, DstType &dst) const
|
||||
{
|
||||
eigen_assert(rhs.rows() == rows());
|
||||
|
||||
const Index nonzero_pivots = nonzeroPivots();
|
||||
|
||||
if(nonzero_pivots == 0)
|
||||
@@ -604,6 +605,31 @@ void ColPivHouseholderQR<_MatrixType>::_solve_impl(const RhsType &rhs, DstType &
|
||||
for(Index i = 0; i < nonzero_pivots; ++i) dst.row(m_colsPermutation.indices().coeff(i)) = c.row(i);
|
||||
for(Index i = nonzero_pivots; i < cols(); ++i) dst.row(m_colsPermutation.indices().coeff(i)).setZero();
|
||||
}
|
||||
|
||||
template<typename _MatrixType>
|
||||
template<bool Conjugate, typename RhsType, typename DstType>
|
||||
void ColPivHouseholderQR<_MatrixType>::_solve_impl_transposed(const RhsType &rhs, DstType &dst) const
|
||||
{
|
||||
const Index nonzero_pivots = nonzeroPivots();
|
||||
|
||||
if(nonzero_pivots == 0)
|
||||
{
|
||||
dst.setZero();
|
||||
return;
|
||||
}
|
||||
|
||||
typename RhsType::PlainObject c(m_colsPermutation.transpose()*rhs);
|
||||
|
||||
m_qr.topLeftCorner(nonzero_pivots, nonzero_pivots)
|
||||
.template triangularView<Upper>()
|
||||
.transpose().template conjugateIf<Conjugate>()
|
||||
.solveInPlace(c.topRows(nonzero_pivots));
|
||||
|
||||
dst.topRows(nonzero_pivots) = c.topRows(nonzero_pivots);
|
||||
dst.bottomRows(rows()-nonzero_pivots).setZero();
|
||||
|
||||
dst.applyOnTheLeft(householderQ().setLength(nonzero_pivots).template conjugateIf<!Conjugate>() );
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace internal {
|
||||
|
||||
@@ -16,6 +16,9 @@ namespace internal {
|
||||
template <typename _MatrixType>
|
||||
struct traits<CompleteOrthogonalDecomposition<_MatrixType> >
|
||||
: traits<_MatrixType> {
|
||||
typedef MatrixXpr XprKind;
|
||||
typedef SolverStorage StorageKind;
|
||||
typedef int StorageIndex;
|
||||
enum { Flags = 0 };
|
||||
};
|
||||
|
||||
@@ -44,19 +47,21 @@ struct traits<CompleteOrthogonalDecomposition<_MatrixType> >
|
||||
*
|
||||
* \sa MatrixBase::completeOrthogonalDecomposition()
|
||||
*/
|
||||
template <typename _MatrixType>
|
||||
class CompleteOrthogonalDecomposition {
|
||||
template <typename _MatrixType> class CompleteOrthogonalDecomposition
|
||||
: public SolverBase<CompleteOrthogonalDecomposition<_MatrixType> >
|
||||
{
|
||||
public:
|
||||
typedef _MatrixType MatrixType;
|
||||
typedef SolverBase<CompleteOrthogonalDecomposition> Base;
|
||||
|
||||
template<typename Derived>
|
||||
friend struct internal::solve_assertion;
|
||||
|
||||
EIGEN_GENERIC_PUBLIC_INTERFACE(CompleteOrthogonalDecomposition)
|
||||
enum {
|
||||
RowsAtCompileTime = MatrixType::RowsAtCompileTime,
|
||||
ColsAtCompileTime = MatrixType::ColsAtCompileTime,
|
||||
MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
|
||||
MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime
|
||||
};
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
typedef typename MatrixType::RealScalar RealScalar;
|
||||
typedef typename MatrixType::StorageIndex StorageIndex;
|
||||
typedef typename internal::plain_diag_type<MatrixType>::type HCoeffsType;
|
||||
typedef PermutationMatrix<ColsAtCompileTime, MaxColsAtCompileTime>
|
||||
PermutationType;
|
||||
@@ -131,9 +136,9 @@ class CompleteOrthogonalDecomposition {
|
||||
m_temp(matrix.cols())
|
||||
{
|
||||
computeInPlace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#ifdef EIGEN_PARSED_BY_DOXYGEN
|
||||
/** This method computes the minimum-norm solution X to a least squares
|
||||
* problem \f[\mathrm{minimize} \|A X - B\|, \f] where \b A is the matrix of
|
||||
* which \c *this is the complete orthogonal decomposition.
|
||||
@@ -145,11 +150,8 @@ class CompleteOrthogonalDecomposition {
|
||||
*/
|
||||
template <typename Rhs>
|
||||
inline const Solve<CompleteOrthogonalDecomposition, Rhs> solve(
|
||||
const MatrixBase<Rhs>& b) const {
|
||||
eigen_assert(m_cpqr.m_isInitialized &&
|
||||
"CompleteOrthogonalDecomposition is not initialized.");
|
||||
return Solve<CompleteOrthogonalDecomposition, Rhs>(*this, b.derived());
|
||||
}
|
||||
const MatrixBase<Rhs>& b) const;
|
||||
#endif
|
||||
|
||||
HouseholderSequenceType householderQ(void) const;
|
||||
HouseholderSequenceType matrixQ(void) const { return m_cpqr.householderQ(); }
|
||||
@@ -158,8 +160,8 @@ class CompleteOrthogonalDecomposition {
|
||||
*/
|
||||
MatrixType matrixZ() const {
|
||||
MatrixType Z = MatrixType::Identity(m_cpqr.cols(), m_cpqr.cols());
|
||||
applyZAdjointOnTheLeftInPlace(Z);
|
||||
return Z.adjoint();
|
||||
applyZOnTheLeftInPlace<false>(Z);
|
||||
return Z;
|
||||
}
|
||||
|
||||
/** \returns a reference to the matrix where the complete orthogonal
|
||||
@@ -275,6 +277,7 @@ class CompleteOrthogonalDecomposition {
|
||||
*/
|
||||
inline const Inverse<CompleteOrthogonalDecomposition> pseudoInverse() const
|
||||
{
|
||||
eigen_assert(m_cpqr.m_isInitialized && "CompleteOrthogonalDecomposition is not initialized.");
|
||||
return Inverse<CompleteOrthogonalDecomposition>(*this);
|
||||
}
|
||||
|
||||
@@ -368,6 +371,9 @@ class CompleteOrthogonalDecomposition {
|
||||
#ifndef EIGEN_PARSED_BY_DOXYGEN
|
||||
template <typename RhsType, typename DstType>
|
||||
void _solve_impl(const RhsType& rhs, DstType& dst) const;
|
||||
|
||||
template<bool Conjugate, typename RhsType, typename DstType>
|
||||
void _solve_impl_transposed(const RhsType &rhs, DstType &dst) const;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
@@ -375,8 +381,21 @@ class CompleteOrthogonalDecomposition {
|
||||
EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar);
|
||||
}
|
||||
|
||||
template<bool Transpose_, typename Rhs>
|
||||
void _check_solve_assertion(const Rhs& b) const {
|
||||
eigen_assert(m_cpqr.m_isInitialized && "CompleteOrthogonalDecomposition is not initialized.");
|
||||
eigen_assert((Transpose_?derived().cols():derived().rows())==b.rows() && "CompleteOrthogonalDecomposition::solve(): invalid number of rows of the right hand side matrix b");
|
||||
}
|
||||
|
||||
void computeInPlace();
|
||||
|
||||
/** Overwrites \b rhs with \f$ \mathbf{Z} * \mathbf{rhs} \f$ or
|
||||
* \f$ \mathbf{\overline Z} * \mathbf{rhs} \f$ if \c Conjugate
|
||||
* is set to \c true.
|
||||
*/
|
||||
template <bool Conjugate, typename Rhs>
|
||||
void applyZOnTheLeftInPlace(Rhs& rhs) const;
|
||||
|
||||
/** Overwrites \b rhs with \f$ \mathbf{Z}^* * \mathbf{rhs} \f$.
|
||||
*/
|
||||
template <typename Rhs>
|
||||
@@ -464,6 +483,28 @@ void CompleteOrthogonalDecomposition<MatrixType>::computeInPlace()
|
||||
}
|
||||
}
|
||||
|
||||
template <typename MatrixType>
|
||||
template <bool Conjugate, typename Rhs>
|
||||
void CompleteOrthogonalDecomposition<MatrixType>::applyZOnTheLeftInPlace(
|
||||
Rhs& rhs) const {
|
||||
const Index cols = this->cols();
|
||||
const Index nrhs = rhs.cols();
|
||||
const Index rank = this->rank();
|
||||
Matrix<typename Rhs::Scalar, Dynamic, 1> temp((std::max)(cols, nrhs));
|
||||
for (Index k = rank-1; k >= 0; --k) {
|
||||
if (k != rank - 1) {
|
||||
rhs.row(k).swap(rhs.row(rank - 1));
|
||||
}
|
||||
rhs.middleRows(rank - 1, cols - rank + 1)
|
||||
.applyHouseholderOnTheLeft(
|
||||
matrixQTZ().row(k).tail(cols - rank).transpose().template conjugateIf<!Conjugate>(), zCoeffs().template conjugateIf<Conjugate>()(k),
|
||||
&temp(0));
|
||||
if (k != rank - 1) {
|
||||
rhs.row(k).swap(rhs.row(rank - 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename MatrixType>
|
||||
template <typename Rhs>
|
||||
void CompleteOrthogonalDecomposition<MatrixType>::applyZAdjointOnTheLeftInPlace(
|
||||
@@ -471,7 +512,7 @@ void CompleteOrthogonalDecomposition<MatrixType>::applyZAdjointOnTheLeftInPlace(
|
||||
const Index cols = this->cols();
|
||||
const Index nrhs = rhs.cols();
|
||||
const Index rank = this->rank();
|
||||
Matrix<typename MatrixType::Scalar, Dynamic, 1> temp((std::max)(cols, nrhs));
|
||||
Matrix<typename Rhs::Scalar, Dynamic, 1> temp((std::max)(cols, nrhs));
|
||||
for (Index k = 0; k < rank; ++k) {
|
||||
if (k != rank - 1) {
|
||||
rhs.row(k).swap(rhs.row(rank - 1));
|
||||
@@ -491,8 +532,6 @@ template <typename _MatrixType>
|
||||
template <typename RhsType, typename DstType>
|
||||
void CompleteOrthogonalDecomposition<_MatrixType>::_solve_impl(
|
||||
const RhsType& rhs, DstType& dst) const {
|
||||
eigen_assert(rhs.rows() == this->rows());
|
||||
|
||||
const Index rank = this->rank();
|
||||
if (rank == 0) {
|
||||
dst.setZero();
|
||||
@@ -520,6 +559,34 @@ void CompleteOrthogonalDecomposition<_MatrixType>::_solve_impl(
|
||||
// Undo permutation to get x = P^{-1} * y.
|
||||
dst = colsPermutation() * dst;
|
||||
}
|
||||
|
||||
template<typename _MatrixType>
|
||||
template<bool Conjugate, typename RhsType, typename DstType>
|
||||
void CompleteOrthogonalDecomposition<_MatrixType>::_solve_impl_transposed(const RhsType &rhs, DstType &dst) const
|
||||
{
|
||||
const Index rank = this->rank();
|
||||
|
||||
if (rank == 0) {
|
||||
dst.setZero();
|
||||
return;
|
||||
}
|
||||
|
||||
typename RhsType::PlainObject c(colsPermutation().transpose()*rhs);
|
||||
|
||||
if (rank < cols()) {
|
||||
applyZOnTheLeftInPlace<!Conjugate>(c);
|
||||
}
|
||||
|
||||
matrixT().topLeftCorner(rank, rank)
|
||||
.template triangularView<Upper>()
|
||||
.transpose().template conjugateIf<Conjugate>()
|
||||
.solveInPlace(c.topRows(rank));
|
||||
|
||||
dst.topRows(rank) = c.topRows(rank);
|
||||
dst.bottomRows(rows()-rank).setZero();
|
||||
|
||||
dst.applyOnTheLeft(householderQ().setLength(rank).template conjugateIf<!Conjugate>() );
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace internal {
|
||||
|
||||
@@ -18,6 +18,9 @@ namespace internal {
|
||||
template<typename _MatrixType> struct traits<FullPivHouseholderQR<_MatrixType> >
|
||||
: traits<_MatrixType>
|
||||
{
|
||||
typedef MatrixXpr XprKind;
|
||||
typedef SolverStorage StorageKind;
|
||||
typedef int StorageIndex;
|
||||
enum { Flags = 0 };
|
||||
};
|
||||
|
||||
@@ -55,20 +58,19 @@ struct traits<FullPivHouseholderQRMatrixQReturnType<MatrixType> >
|
||||
* \sa MatrixBase::fullPivHouseholderQr()
|
||||
*/
|
||||
template<typename _MatrixType> class FullPivHouseholderQR
|
||||
: public SolverBase<FullPivHouseholderQR<_MatrixType> >
|
||||
{
|
||||
public:
|
||||
|
||||
typedef _MatrixType MatrixType;
|
||||
typedef SolverBase<FullPivHouseholderQR> Base;
|
||||
friend class SolverBase<FullPivHouseholderQR>;
|
||||
|
||||
EIGEN_GENERIC_PUBLIC_INTERFACE(FullPivHouseholderQR)
|
||||
enum {
|
||||
RowsAtCompileTime = MatrixType::RowsAtCompileTime,
|
||||
ColsAtCompileTime = MatrixType::ColsAtCompileTime,
|
||||
MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
|
||||
MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime
|
||||
};
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
typedef typename MatrixType::RealScalar RealScalar;
|
||||
// FIXME should be int
|
||||
typedef typename MatrixType::StorageIndex StorageIndex;
|
||||
typedef internal::FullPivHouseholderQRMatrixQReturnType<MatrixType> MatrixQReturnType;
|
||||
typedef typename internal::plain_diag_type<MatrixType>::type HCoeffsType;
|
||||
typedef Matrix<StorageIndex, 1,
|
||||
@@ -156,6 +158,7 @@ template<typename _MatrixType> class FullPivHouseholderQR
|
||||
computeInPlace();
|
||||
}
|
||||
|
||||
#ifdef EIGEN_PARSED_BY_DOXYGEN
|
||||
/** This method finds a solution x to the equation Ax=b, where A is the matrix of which
|
||||
* \c *this is the QR decomposition.
|
||||
*
|
||||
@@ -173,11 +176,8 @@ template<typename _MatrixType> class FullPivHouseholderQR
|
||||
*/
|
||||
template<typename Rhs>
|
||||
inline const Solve<FullPivHouseholderQR, Rhs>
|
||||
solve(const MatrixBase<Rhs>& b) const
|
||||
{
|
||||
eigen_assert(m_isInitialized && "FullPivHouseholderQR is not initialized.");
|
||||
return Solve<FullPivHouseholderQR, Rhs>(*this, b.derived());
|
||||
}
|
||||
solve(const MatrixBase<Rhs>& b) const;
|
||||
#endif
|
||||
|
||||
/** \returns Expression object representing the matrix Q
|
||||
*/
|
||||
@@ -396,6 +396,9 @@ template<typename _MatrixType> class FullPivHouseholderQR
|
||||
#ifndef EIGEN_PARSED_BY_DOXYGEN
|
||||
template<typename RhsType, typename DstType>
|
||||
void _solve_impl(const RhsType &rhs, DstType &dst) const;
|
||||
|
||||
template<bool Conjugate, typename RhsType, typename DstType>
|
||||
void _solve_impl_transposed(const RhsType &rhs, DstType &dst) const;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
@@ -498,15 +501,15 @@ void FullPivHouseholderQR<MatrixType>::computeInPlace()
|
||||
m_nonzero_pivots = k;
|
||||
for(Index i = k; i < size; i++)
|
||||
{
|
||||
m_rows_transpositions.coeffRef(i) = i;
|
||||
m_cols_transpositions.coeffRef(i) = i;
|
||||
m_rows_transpositions.coeffRef(i) = internal::convert_index<StorageIndex>(i);
|
||||
m_cols_transpositions.coeffRef(i) = internal::convert_index<StorageIndex>(i);
|
||||
m_hCoeffs.coeffRef(i) = Scalar(0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
m_rows_transpositions.coeffRef(k) = row_of_biggest_in_corner;
|
||||
m_cols_transpositions.coeffRef(k) = col_of_biggest_in_corner;
|
||||
m_rows_transpositions.coeffRef(k) = internal::convert_index<StorageIndex>(row_of_biggest_in_corner);
|
||||
m_cols_transpositions.coeffRef(k) = internal::convert_index<StorageIndex>(col_of_biggest_in_corner);
|
||||
if(k != row_of_biggest_in_corner) {
|
||||
m_qr.row(k).tail(cols-k).swap(m_qr.row(row_of_biggest_in_corner).tail(cols-k));
|
||||
++number_of_transpositions;
|
||||
@@ -540,7 +543,6 @@ template<typename _MatrixType>
|
||||
template<typename RhsType, typename DstType>
|
||||
void FullPivHouseholderQR<_MatrixType>::_solve_impl(const RhsType &rhs, DstType &dst) const
|
||||
{
|
||||
eigen_assert(rhs.rows() == rows());
|
||||
const Index l_rank = rank();
|
||||
|
||||
// FIXME introduce nonzeroPivots() and use it here. and more generally,
|
||||
@@ -553,7 +555,7 @@ void FullPivHouseholderQR<_MatrixType>::_solve_impl(const RhsType &rhs, DstType
|
||||
|
||||
typename RhsType::PlainObject c(rhs);
|
||||
|
||||
Matrix<Scalar,1,RhsType::ColsAtCompileTime> temp(rhs.cols());
|
||||
Matrix<typename RhsType::Scalar,1,RhsType::ColsAtCompileTime> temp(rhs.cols());
|
||||
for (Index k = 0; k < l_rank; ++k)
|
||||
{
|
||||
Index remainingSize = rows()-k;
|
||||
@@ -570,6 +572,42 @@ void FullPivHouseholderQR<_MatrixType>::_solve_impl(const RhsType &rhs, DstType
|
||||
for(Index i = 0; i < l_rank; ++i) dst.row(m_cols_permutation.indices().coeff(i)) = c.row(i);
|
||||
for(Index i = l_rank; i < cols(); ++i) dst.row(m_cols_permutation.indices().coeff(i)).setZero();
|
||||
}
|
||||
|
||||
template<typename _MatrixType>
|
||||
template<bool Conjugate, typename RhsType, typename DstType>
|
||||
void FullPivHouseholderQR<_MatrixType>::_solve_impl_transposed(const RhsType &rhs, DstType &dst) const
|
||||
{
|
||||
const Index l_rank = rank();
|
||||
|
||||
if(l_rank == 0)
|
||||
{
|
||||
dst.setZero();
|
||||
return;
|
||||
}
|
||||
|
||||
typename RhsType::PlainObject c(m_cols_permutation.transpose()*rhs);
|
||||
|
||||
m_qr.topLeftCorner(l_rank, l_rank)
|
||||
.template triangularView<Upper>()
|
||||
.transpose().template conjugateIf<Conjugate>()
|
||||
.solveInPlace(c.topRows(l_rank));
|
||||
|
||||
dst.topRows(l_rank) = c.topRows(l_rank);
|
||||
dst.bottomRows(rows()-l_rank).setZero();
|
||||
|
||||
Matrix<Scalar, 1, DstType::ColsAtCompileTime> temp(dst.cols());
|
||||
const Index size = (std::min)(rows(), cols());
|
||||
for (Index k = size-1; k >= 0; --k)
|
||||
{
|
||||
Index remainingSize = rows()-k;
|
||||
|
||||
dst.bottomRightCorner(remainingSize, dst.cols())
|
||||
.applyHouseholderOnTheLeft(m_qr.col(k).tail(remainingSize-1).template conjugateIf<!Conjugate>(),
|
||||
m_hCoeffs.template conjugateIf<Conjugate>().coeff(k), &temp.coeffRef(0));
|
||||
|
||||
dst.row(k).swap(dst.row(m_rows_transpositions.coeff(k)));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace internal {
|
||||
|
||||
@@ -14,6 +14,18 @@
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
namespace internal {
|
||||
template<typename _MatrixType> struct traits<HouseholderQR<_MatrixType> >
|
||||
: traits<_MatrixType>
|
||||
{
|
||||
typedef MatrixXpr XprKind;
|
||||
typedef SolverStorage StorageKind;
|
||||
typedef int StorageIndex;
|
||||
enum { Flags = 0 };
|
||||
};
|
||||
|
||||
} // end namespace internal
|
||||
|
||||
/** \ingroup QR_Module
|
||||
*
|
||||
*
|
||||
@@ -42,20 +54,19 @@ namespace Eigen {
|
||||
* \sa MatrixBase::householderQr()
|
||||
*/
|
||||
template<typename _MatrixType> class HouseholderQR
|
||||
: public SolverBase<HouseholderQR<_MatrixType> >
|
||||
{
|
||||
public:
|
||||
|
||||
typedef _MatrixType MatrixType;
|
||||
typedef SolverBase<HouseholderQR> Base;
|
||||
friend class SolverBase<HouseholderQR>;
|
||||
|
||||
EIGEN_GENERIC_PUBLIC_INTERFACE(HouseholderQR)
|
||||
enum {
|
||||
RowsAtCompileTime = MatrixType::RowsAtCompileTime,
|
||||
ColsAtCompileTime = MatrixType::ColsAtCompileTime,
|
||||
MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
|
||||
MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime
|
||||
};
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
typedef typename MatrixType::RealScalar RealScalar;
|
||||
// FIXME should be int
|
||||
typedef typename MatrixType::StorageIndex StorageIndex;
|
||||
typedef Matrix<Scalar, RowsAtCompileTime, RowsAtCompileTime, (MatrixType::Flags&RowMajorBit) ? RowMajor : ColMajor, MaxRowsAtCompileTime, MaxRowsAtCompileTime> MatrixQType;
|
||||
typedef typename internal::plain_diag_type<MatrixType>::type HCoeffsType;
|
||||
typedef typename internal::plain_row_type<MatrixType>::type RowVectorType;
|
||||
@@ -121,6 +132,7 @@ template<typename _MatrixType> class HouseholderQR
|
||||
computeInPlace();
|
||||
}
|
||||
|
||||
#ifdef EIGEN_PARSED_BY_DOXYGEN
|
||||
/** This method finds a solution x to the equation Ax=b, where A is the matrix of which
|
||||
* *this is the QR decomposition, if any exists.
|
||||
*
|
||||
@@ -137,11 +149,8 @@ template<typename _MatrixType> class HouseholderQR
|
||||
*/
|
||||
template<typename Rhs>
|
||||
inline const Solve<HouseholderQR, Rhs>
|
||||
solve(const MatrixBase<Rhs>& b) const
|
||||
{
|
||||
eigen_assert(m_isInitialized && "HouseholderQR is not initialized.");
|
||||
return Solve<HouseholderQR, Rhs>(*this, b.derived());
|
||||
}
|
||||
solve(const MatrixBase<Rhs>& b) const;
|
||||
#endif
|
||||
|
||||
/** This method returns an expression of the unitary matrix Q as a sequence of Householder transformations.
|
||||
*
|
||||
@@ -214,6 +223,9 @@ template<typename _MatrixType> class HouseholderQR
|
||||
#ifndef EIGEN_PARSED_BY_DOXYGEN
|
||||
template<typename RhsType, typename DstType>
|
||||
void _solve_impl(const RhsType &rhs, DstType &dst) const;
|
||||
|
||||
template<bool Conjugate, typename RhsType, typename DstType>
|
||||
void _solve_impl_transposed(const RhsType &rhs, DstType &dst) const;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
@@ -349,7 +361,6 @@ template<typename RhsType, typename DstType>
|
||||
void HouseholderQR<_MatrixType>::_solve_impl(const RhsType &rhs, DstType &dst) const
|
||||
{
|
||||
const Index rank = (std::min)(rows(), cols());
|
||||
eigen_assert(rhs.rows() == rows());
|
||||
|
||||
typename RhsType::PlainObject c(rhs);
|
||||
|
||||
@@ -362,6 +373,25 @@ void HouseholderQR<_MatrixType>::_solve_impl(const RhsType &rhs, DstType &dst) c
|
||||
dst.topRows(rank) = c.topRows(rank);
|
||||
dst.bottomRows(cols()-rank).setZero();
|
||||
}
|
||||
|
||||
template<typename _MatrixType>
|
||||
template<bool Conjugate, typename RhsType, typename DstType>
|
||||
void HouseholderQR<_MatrixType>::_solve_impl_transposed(const RhsType &rhs, DstType &dst) const
|
||||
{
|
||||
const Index rank = (std::min)(rows(), cols());
|
||||
|
||||
typename RhsType::PlainObject c(rhs);
|
||||
|
||||
m_qr.topLeftCorner(rank, rank)
|
||||
.template triangularView<Upper>()
|
||||
.transpose().template conjugateIf<Conjugate>()
|
||||
.solveInPlace(c.topRows(rank));
|
||||
|
||||
dst.topRows(rank) = c.topRows(rank);
|
||||
dst.bottomRows(rows()-rank).setZero();
|
||||
|
||||
dst.applyOnTheLeft(householderQ().setLength(rank).template conjugateIf<!Conjugate>() );
|
||||
}
|
||||
#endif
|
||||
|
||||
/** Performs the QR factorization of the given matrix \a matrix. The result of
|
||||
|
||||
Reference in New Issue
Block a user