mirror of
https://gitlab.com/libeigen/eigen.git
synced 2026-04-10 11:34:33 +08:00
Apply clang-format
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -41,108 +41,119 @@ namespace Eigen {
|
||||
|
||||
#if defined(EIGEN_USE_LAPACKE)
|
||||
|
||||
template<typename Scalar>
|
||||
inline lapack_int call_geqp3(int matrix_layout, lapack_int m, lapack_int n, Scalar* a, lapack_int lda, lapack_int* jpvt, Scalar* tau);
|
||||
template<>
|
||||
inline lapack_int call_geqp3(int matrix_layout, lapack_int m, lapack_int n, float* a, lapack_int lda, lapack_int* jpvt, float* tau)
|
||||
{ return LAPACKE_sgeqp3(matrix_layout, m, n, a, lda, jpvt, tau); }
|
||||
template<>
|
||||
inline lapack_int call_geqp3(int matrix_layout, lapack_int m, lapack_int n, double* a, lapack_int lda, lapack_int* jpvt, double* tau)
|
||||
{ return LAPACKE_dgeqp3(matrix_layout, m, n, a, lda, jpvt, tau); }
|
||||
template<>
|
||||
inline lapack_int call_geqp3(int matrix_layout, lapack_int m, lapack_int n, lapack_complex_float* a, lapack_int lda, lapack_int* jpvt, lapack_complex_float* tau)
|
||||
{ return LAPACKE_cgeqp3(matrix_layout, m, n, a, lda, jpvt, tau); }
|
||||
template<>
|
||||
inline lapack_int call_geqp3(int matrix_layout, lapack_int m, lapack_int n, lapack_complex_double* a, lapack_int lda, lapack_int* jpvt, lapack_complex_double* tau)
|
||||
{ return LAPACKE_zgeqp3(matrix_layout, m, n, a, lda, jpvt, tau); }
|
||||
template <typename Scalar>
|
||||
inline lapack_int call_geqp3(int matrix_layout, lapack_int m, lapack_int n, Scalar* a, lapack_int lda, lapack_int* jpvt,
|
||||
Scalar* tau);
|
||||
template <>
|
||||
inline lapack_int call_geqp3(int matrix_layout, lapack_int m, lapack_int n, float* a, lapack_int lda, lapack_int* jpvt,
|
||||
float* tau) {
|
||||
return LAPACKE_sgeqp3(matrix_layout, m, n, a, lda, jpvt, tau);
|
||||
}
|
||||
template <>
|
||||
inline lapack_int call_geqp3(int matrix_layout, lapack_int m, lapack_int n, double* a, lapack_int lda, lapack_int* jpvt,
|
||||
double* tau) {
|
||||
return LAPACKE_dgeqp3(matrix_layout, m, n, a, lda, jpvt, tau);
|
||||
}
|
||||
template <>
|
||||
inline lapack_int call_geqp3(int matrix_layout, lapack_int m, lapack_int n, lapack_complex_float* a, lapack_int lda,
|
||||
lapack_int* jpvt, lapack_complex_float* tau) {
|
||||
return LAPACKE_cgeqp3(matrix_layout, m, n, a, lda, jpvt, tau);
|
||||
}
|
||||
template <>
|
||||
inline lapack_int call_geqp3(int matrix_layout, lapack_int m, lapack_int n, lapack_complex_double* a, lapack_int lda,
|
||||
lapack_int* jpvt, lapack_complex_double* tau) {
|
||||
return LAPACKE_zgeqp3(matrix_layout, m, n, a, lda, jpvt, tau);
|
||||
}
|
||||
|
||||
template <typename MatrixType>
|
||||
struct ColPivHouseholderQR_LAPACKE_impl {
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
typedef typename MatrixType::RealScalar RealScalar;
|
||||
typedef typename internal::lapacke_helpers::translate_type_imp<Scalar>::type LapackeType;
|
||||
static constexpr int LapackeStorage = MatrixType::IsRowMajor ? (LAPACK_ROW_MAJOR) : (LAPACK_COL_MAJOR);
|
||||
template <typename MatrixType>
|
||||
struct ColPivHouseholderQR_LAPACKE_impl {
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
typedef typename MatrixType::RealScalar RealScalar;
|
||||
typedef typename internal::lapacke_helpers::translate_type_imp<Scalar>::type LapackeType;
|
||||
static constexpr int LapackeStorage = MatrixType::IsRowMajor ? (LAPACK_ROW_MAJOR) : (LAPACK_COL_MAJOR);
|
||||
|
||||
typedef typename internal::plain_diag_type<MatrixType>::type HCoeffsType;
|
||||
typedef PermutationMatrix<Dynamic, Dynamic, lapack_int> PermutationType;
|
||||
typedef typename internal::plain_diag_type<MatrixType>::type HCoeffsType;
|
||||
typedef PermutationMatrix<Dynamic, Dynamic, lapack_int> PermutationType;
|
||||
|
||||
static void run(MatrixType& qr, HCoeffsType& hCoeffs, PermutationType& colsPermutation, Index& nonzero_pivots,
|
||||
RealScalar& maxpivot, bool usePrescribedThreshold, RealScalar prescribedThreshold, Index& det_p,
|
||||
bool& isInitialized) {
|
||||
static void run(MatrixType& qr, HCoeffsType& hCoeffs, PermutationType& colsPermutation, Index& nonzero_pivots,
|
||||
RealScalar& maxpivot, bool usePrescribedThreshold, RealScalar prescribedThreshold, Index& det_p,
|
||||
bool& isInitialized) {
|
||||
isInitialized = false;
|
||||
hCoeffs.resize(qr.diagonalSize());
|
||||
nonzero_pivots = 0;
|
||||
maxpivot = RealScalar(0);
|
||||
colsPermutation.resize(qr.cols());
|
||||
colsPermutation.indices().setZero();
|
||||
|
||||
isInitialized = false;
|
||||
hCoeffs.resize(qr.diagonalSize());
|
||||
nonzero_pivots = 0;
|
||||
maxpivot = RealScalar(0);
|
||||
colsPermutation.resize(qr.cols());
|
||||
colsPermutation.indices().setZero();
|
||||
lapack_int rows = internal::lapacke_helpers::to_lapack(qr.rows());
|
||||
lapack_int cols = internal::lapacke_helpers::to_lapack(qr.cols());
|
||||
LapackeType* qr_data = (LapackeType*)(qr.data());
|
||||
lapack_int lda = internal::lapacke_helpers::to_lapack(qr.outerStride());
|
||||
lapack_int* perm_data = colsPermutation.indices().data();
|
||||
LapackeType* hCoeffs_data = (LapackeType*)(hCoeffs.data());
|
||||
|
||||
lapack_int rows = internal::lapacke_helpers::to_lapack(qr.rows());
|
||||
lapack_int cols = internal::lapacke_helpers::to_lapack(qr.cols());
|
||||
LapackeType* qr_data = (LapackeType*)(qr.data());
|
||||
lapack_int lda = internal::lapacke_helpers::to_lapack(qr.outerStride());
|
||||
lapack_int* perm_data = colsPermutation.indices().data();
|
||||
LapackeType* hCoeffs_data = (LapackeType*)(hCoeffs.data());
|
||||
lapack_int info = call_geqp3(LapackeStorage, rows, cols, qr_data, lda, perm_data, hCoeffs_data);
|
||||
if (info != 0) return;
|
||||
|
||||
lapack_int info = call_geqp3(LapackeStorage, rows, cols, qr_data, lda, perm_data, hCoeffs_data);
|
||||
if (info != 0) return;
|
||||
maxpivot = qr.diagonal().cwiseAbs().maxCoeff();
|
||||
hCoeffs.adjointInPlace();
|
||||
RealScalar defaultThreshold = NumTraits<RealScalar>::epsilon() * RealScalar(qr.diagonalSize());
|
||||
RealScalar threshold = usePrescribedThreshold ? prescribedThreshold : defaultThreshold;
|
||||
RealScalar premultiplied_threshold = maxpivot * threshold;
|
||||
nonzero_pivots = (qr.diagonal().cwiseAbs().array() > premultiplied_threshold).count();
|
||||
colsPermutation.indices().array() -= 1;
|
||||
det_p = colsPermutation.determinant();
|
||||
isInitialized = true;
|
||||
};
|
||||
|
||||
maxpivot = qr.diagonal().cwiseAbs().maxCoeff();
|
||||
hCoeffs.adjointInPlace();
|
||||
RealScalar defaultThreshold = NumTraits<RealScalar>::epsilon() * RealScalar(qr.diagonalSize());
|
||||
RealScalar threshold = usePrescribedThreshold ? prescribedThreshold : defaultThreshold;
|
||||
RealScalar premultiplied_threshold = maxpivot * threshold;
|
||||
nonzero_pivots = (qr.diagonal().cwiseAbs().array() > premultiplied_threshold).count();
|
||||
colsPermutation.indices().array() -= 1;
|
||||
det_p = colsPermutation.determinant();
|
||||
isInitialized = true;
|
||||
};
|
||||
static void init(Index rows, Index cols, HCoeffsType& hCoeffs, PermutationType& colsPermutation,
|
||||
bool& usePrescribedThreshold, bool& isInitialized) {
|
||||
Index diag = numext::mini(rows, cols);
|
||||
hCoeffs.resize(diag);
|
||||
colsPermutation.resize(cols);
|
||||
usePrescribedThreshold = false;
|
||||
isInitialized = false;
|
||||
}
|
||||
};
|
||||
|
||||
static void init(Index rows, Index cols, HCoeffsType& hCoeffs, PermutationType& colsPermutation,
|
||||
bool& usePrescribedThreshold, bool& isInitialized) {
|
||||
#define COLPIVQR_LAPACKE_COMPUTEINPLACE(EIGTYPE) \
|
||||
template <> \
|
||||
inline void ColPivHouseholderQR<EIGTYPE, lapack_int>::computeInPlace() { \
|
||||
ColPivHouseholderQR_LAPACKE_impl<MatrixType>::run(m_qr, m_hCoeffs, m_colsPermutation, m_nonzero_pivots, \
|
||||
m_maxpivot, m_usePrescribedThreshold, m_prescribedThreshold, \
|
||||
m_det_p, m_isInitialized); \
|
||||
}
|
||||
|
||||
Index diag = numext::mini(rows, cols);
|
||||
hCoeffs.resize(diag);
|
||||
colsPermutation.resize(cols);
|
||||
usePrescribedThreshold = false;
|
||||
isInitialized = false;
|
||||
}
|
||||
};
|
||||
#define COLPIVQR_LAPACKE_INIT(EIGTYPE) \
|
||||
template <> \
|
||||
inline void ColPivHouseholderQR<EIGTYPE, lapack_int>::init(Index rows, Index cols) { \
|
||||
ColPivHouseholderQR_LAPACKE_impl<MatrixType>::init(rows, cols, m_hCoeffs, m_colsPermutation, m_isInitialized, \
|
||||
m_usePrescribedThreshold); \
|
||||
}
|
||||
|
||||
#define COLPIVQR_LAPACKE_COMPUTEINPLACE(EIGTYPE) \
|
||||
template <> inline void ColPivHouseholderQR<EIGTYPE, lapack_int>::computeInPlace() { \
|
||||
ColPivHouseholderQR_LAPACKE_impl<MatrixType>::run(m_qr, m_hCoeffs, m_colsPermutation, m_nonzero_pivots, \
|
||||
m_maxpivot, m_usePrescribedThreshold, m_prescribedThreshold, \
|
||||
m_det_p, m_isInitialized); } \
|
||||
#define COLPIVQR_LAPACKE(EIGTYPE) \
|
||||
COLPIVQR_LAPACKE_COMPUTEINPLACE(EIGTYPE) \
|
||||
COLPIVQR_LAPACKE_INIT(EIGTYPE) \
|
||||
COLPIVQR_LAPACKE_COMPUTEINPLACE(Ref<EIGTYPE>) \
|
||||
COLPIVQR_LAPACKE_INIT(Ref<EIGTYPE>)
|
||||
|
||||
#define COLPIVQR_LAPACKE_INIT(EIGTYPE) \
|
||||
template <> inline void ColPivHouseholderQR<EIGTYPE, lapack_int>::init(Index rows, Index cols) { \
|
||||
ColPivHouseholderQR_LAPACKE_impl<MatrixType>::init(rows, cols, m_hCoeffs, m_colsPermutation, m_isInitialized, \
|
||||
m_usePrescribedThreshold); } \
|
||||
typedef Matrix<float, Dynamic, Dynamic, ColMajor> MatrixXfC;
|
||||
typedef Matrix<double, Dynamic, Dynamic, ColMajor> MatrixXdC;
|
||||
typedef Matrix<std::complex<float>, Dynamic, Dynamic, ColMajor> MatrixXcfC;
|
||||
typedef Matrix<std::complex<double>, Dynamic, Dynamic, ColMajor> MatrixXcdC;
|
||||
typedef Matrix<float, Dynamic, Dynamic, RowMajor> MatrixXfR;
|
||||
typedef Matrix<double, Dynamic, Dynamic, RowMajor> MatrixXdR;
|
||||
typedef Matrix<std::complex<float>, Dynamic, Dynamic, RowMajor> MatrixXcfR;
|
||||
typedef Matrix<std::complex<double>, Dynamic, Dynamic, RowMajor> MatrixXcdR;
|
||||
|
||||
#define COLPIVQR_LAPACKE(EIGTYPE) \
|
||||
COLPIVQR_LAPACKE_COMPUTEINPLACE(EIGTYPE) \
|
||||
COLPIVQR_LAPACKE_INIT(EIGTYPE) \
|
||||
COLPIVQR_LAPACKE_COMPUTEINPLACE(Ref<EIGTYPE>) \
|
||||
COLPIVQR_LAPACKE_INIT(Ref<EIGTYPE>) \
|
||||
|
||||
typedef Matrix<float, Dynamic, Dynamic, ColMajor> MatrixXfC;
|
||||
typedef Matrix<double, Dynamic, Dynamic, ColMajor> MatrixXdC;
|
||||
typedef Matrix<std::complex<float>, Dynamic, Dynamic, ColMajor> MatrixXcfC;
|
||||
typedef Matrix<std::complex<double>, Dynamic, Dynamic, ColMajor> MatrixXcdC;
|
||||
typedef Matrix<float, Dynamic, Dynamic, RowMajor> MatrixXfR;
|
||||
typedef Matrix<double, Dynamic, Dynamic, RowMajor> MatrixXdR;
|
||||
typedef Matrix<std::complex<float>, Dynamic, Dynamic, RowMajor> MatrixXcfR;
|
||||
typedef Matrix<std::complex<double>, Dynamic, Dynamic, RowMajor> MatrixXcdR;
|
||||
|
||||
COLPIVQR_LAPACKE(MatrixXfC)
|
||||
COLPIVQR_LAPACKE(MatrixXdC)
|
||||
COLPIVQR_LAPACKE(MatrixXcfC)
|
||||
COLPIVQR_LAPACKE(MatrixXcdC)
|
||||
COLPIVQR_LAPACKE(MatrixXfR)
|
||||
COLPIVQR_LAPACKE(MatrixXdR)
|
||||
COLPIVQR_LAPACKE(MatrixXcfR)
|
||||
COLPIVQR_LAPACKE(MatrixXcdR)
|
||||
COLPIVQR_LAPACKE(MatrixXfC)
|
||||
COLPIVQR_LAPACKE(MatrixXdC)
|
||||
COLPIVQR_LAPACKE(MatrixXcfC)
|
||||
COLPIVQR_LAPACKE(MatrixXcdC)
|
||||
COLPIVQR_LAPACKE(MatrixXfR)
|
||||
COLPIVQR_LAPACKE(MatrixXdR)
|
||||
COLPIVQR_LAPACKE(MatrixXcfR)
|
||||
COLPIVQR_LAPACKE(MatrixXcdR)
|
||||
|
||||
#endif
|
||||
} // end namespace Eigen
|
||||
|
||||
@@ -17,8 +17,7 @@ namespace Eigen {
|
||||
|
||||
namespace internal {
|
||||
template <typename MatrixType_, typename PermutationIndex_>
|
||||
struct traits<CompleteOrthogonalDecomposition<MatrixType_, PermutationIndex_> >
|
||||
: traits<MatrixType_> {
|
||||
struct traits<CompleteOrthogonalDecomposition<MatrixType_, PermutationIndex_>> : traits<MatrixType_> {
|
||||
typedef MatrixXpr XprKind;
|
||||
typedef SolverStorage StorageKind;
|
||||
typedef PermutationIndex_ PermutationIndex;
|
||||
@@ -28,36 +27,36 @@ struct traits<CompleteOrthogonalDecomposition<MatrixType_, PermutationIndex_> >
|
||||
} // end namespace internal
|
||||
|
||||
/** \ingroup QR_Module
|
||||
*
|
||||
* \class CompleteOrthogonalDecomposition
|
||||
*
|
||||
* \brief Complete orthogonal decomposition (COD) of a matrix.
|
||||
*
|
||||
* \tparam MatrixType_ the type of the matrix of which we are computing the COD.
|
||||
*
|
||||
* This class performs a rank-revealing complete orthogonal decomposition of a
|
||||
* matrix \b A into matrices \b P, \b Q, \b T, and \b Z such that
|
||||
* \f[
|
||||
* \mathbf{A} \, \mathbf{P} = \mathbf{Q} \,
|
||||
* \begin{bmatrix} \mathbf{T} & \mathbf{0} \\
|
||||
* \mathbf{0} & \mathbf{0} \end{bmatrix} \, \mathbf{Z}
|
||||
* \f]
|
||||
* by using Householder transformations. Here, \b P is a permutation matrix,
|
||||
* \b Q and \b Z are unitary matrices and \b T an upper triangular matrix of
|
||||
* size rank-by-rank. \b A may be rank deficient.
|
||||
*
|
||||
* This class supports the \link InplaceDecomposition inplace decomposition \endlink mechanism.
|
||||
*
|
||||
* \sa MatrixBase::completeOrthogonalDecomposition()
|
||||
*/
|
||||
template <typename MatrixType_, typename PermutationIndex_> class CompleteOrthogonalDecomposition
|
||||
: public SolverBase<CompleteOrthogonalDecomposition<MatrixType_, PermutationIndex_> >
|
||||
{
|
||||
*
|
||||
* \class CompleteOrthogonalDecomposition
|
||||
*
|
||||
* \brief Complete orthogonal decomposition (COD) of a matrix.
|
||||
*
|
||||
* \tparam MatrixType_ the type of the matrix of which we are computing the COD.
|
||||
*
|
||||
* This class performs a rank-revealing complete orthogonal decomposition of a
|
||||
* matrix \b A into matrices \b P, \b Q, \b T, and \b Z such that
|
||||
* \f[
|
||||
* \mathbf{A} \, \mathbf{P} = \mathbf{Q} \,
|
||||
* \begin{bmatrix} \mathbf{T} & \mathbf{0} \\
|
||||
* \mathbf{0} & \mathbf{0} \end{bmatrix} \, \mathbf{Z}
|
||||
* \f]
|
||||
* by using Householder transformations. Here, \b P is a permutation matrix,
|
||||
* \b Q and \b Z are unitary matrices and \b T an upper triangular matrix of
|
||||
* size rank-by-rank. \b A may be rank deficient.
|
||||
*
|
||||
* This class supports the \link InplaceDecomposition inplace decomposition \endlink mechanism.
|
||||
*
|
||||
* \sa MatrixBase::completeOrthogonalDecomposition()
|
||||
*/
|
||||
template <typename MatrixType_, typename PermutationIndex_>
|
||||
class CompleteOrthogonalDecomposition
|
||||
: public SolverBase<CompleteOrthogonalDecomposition<MatrixType_, PermutationIndex_>> {
|
||||
public:
|
||||
typedef MatrixType_ MatrixType;
|
||||
typedef SolverBase<CompleteOrthogonalDecomposition> Base;
|
||||
|
||||
template<typename Derived>
|
||||
template <typename Derived>
|
||||
friend struct internal::solve_assertion;
|
||||
typedef PermutationIndex_ PermutationIndex;
|
||||
EIGEN_GENERIC_PUBLIC_INTERFACE(CompleteOrthogonalDecomposition)
|
||||
@@ -66,16 +65,11 @@ template <typename MatrixType_, typename PermutationIndex_> class CompleteOrthog
|
||||
MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime
|
||||
};
|
||||
typedef typename internal::plain_diag_type<MatrixType>::type HCoeffsType;
|
||||
typedef PermutationMatrix<ColsAtCompileTime, MaxColsAtCompileTime, PermutationIndex>
|
||||
PermutationType;
|
||||
typedef typename internal::plain_row_type<MatrixType, Index>::type
|
||||
IntRowVectorType;
|
||||
typedef PermutationMatrix<ColsAtCompileTime, MaxColsAtCompileTime, PermutationIndex> PermutationType;
|
||||
typedef typename internal::plain_row_type<MatrixType, Index>::type IntRowVectorType;
|
||||
typedef typename internal::plain_row_type<MatrixType>::type RowVectorType;
|
||||
typedef typename internal::plain_row_type<MatrixType, RealScalar>::type
|
||||
RealRowVectorType;
|
||||
typedef HouseholderSequence<
|
||||
MatrixType, internal::remove_all_t<
|
||||
typename HCoeffsType::ConjugateReturnType>>
|
||||
typedef typename internal::plain_row_type<MatrixType, RealScalar>::type RealRowVectorType;
|
||||
typedef HouseholderSequence<MatrixType, internal::remove_all_t<typename HCoeffsType::ConjugateReturnType>>
|
||||
HouseholderSequenceType;
|
||||
typedef typename MatrixType::PlainObject PlainObject;
|
||||
|
||||
@@ -118,27 +112,24 @@ template <typename MatrixType_, typename PermutationIndex_> class CompleteOrthog
|
||||
explicit CompleteOrthogonalDecomposition(const EigenBase<InputType>& matrix)
|
||||
: m_cpqr(matrix.rows(), matrix.cols()),
|
||||
m_zCoeffs((std::min)(matrix.rows(), matrix.cols())),
|
||||
m_temp(matrix.cols())
|
||||
{
|
||||
m_temp(matrix.cols()) {
|
||||
compute(matrix.derived());
|
||||
}
|
||||
|
||||
/** \brief Constructs a complete orthogonal decomposition from a given matrix
|
||||
*
|
||||
* This overloaded constructor is provided for \link InplaceDecomposition inplace decomposition \endlink when \c MatrixType is a Eigen::Ref.
|
||||
*
|
||||
* \sa CompleteOrthogonalDecomposition(const EigenBase&)
|
||||
*/
|
||||
template<typename InputType>
|
||||
*
|
||||
* This overloaded constructor is provided for \link InplaceDecomposition inplace decomposition \endlink when \c
|
||||
* MatrixType is a Eigen::Ref.
|
||||
*
|
||||
* \sa CompleteOrthogonalDecomposition(const EigenBase&)
|
||||
*/
|
||||
template <typename InputType>
|
||||
explicit CompleteOrthogonalDecomposition(EigenBase<InputType>& matrix)
|
||||
: m_cpqr(matrix.derived()),
|
||||
m_zCoeffs((std::min)(matrix.rows(), matrix.cols())),
|
||||
m_temp(matrix.cols())
|
||||
{
|
||||
: m_cpqr(matrix.derived()), m_zCoeffs((std::min)(matrix.rows(), matrix.cols())), m_temp(matrix.cols()) {
|
||||
computeInPlace();
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef EIGEN_PARSED_BY_DOXYGEN
|
||||
#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.
|
||||
@@ -149,9 +140,8 @@ template <typename MatrixType_, typename PermutationIndex_> class CompleteOrthog
|
||||
*
|
||||
*/
|
||||
template <typename Rhs>
|
||||
inline const Solve<CompleteOrthogonalDecomposition, Rhs> solve(
|
||||
const MatrixBase<Rhs>& b) const;
|
||||
#endif
|
||||
inline const Solve<CompleteOrthogonalDecomposition, Rhs> solve(const MatrixBase<Rhs>& b) const;
|
||||
#endif
|
||||
|
||||
HouseholderSequenceType householderQ(void) const;
|
||||
HouseholderSequenceType matrixQ(void) const { return m_cpqr.householderQ(); }
|
||||
@@ -191,11 +181,9 @@ template <typename MatrixType_, typename PermutationIndex_> class CompleteOrthog
|
||||
}
|
||||
|
||||
/** \returns a const reference to the column permutation matrix */
|
||||
const PermutationType& colsPermutation() const {
|
||||
return m_cpqr.colsPermutation();
|
||||
}
|
||||
const PermutationType& colsPermutation() const { return m_cpqr.colsPermutation(); }
|
||||
|
||||
/** \returns the determinant of the matrix of which
|
||||
/** \returns the determinant of the matrix of which
|
||||
* *this is the complete orthogonal decomposition. It has only linear
|
||||
* complexity (that is, O(n) where n is the dimension of the square matrix)
|
||||
* as the complete orthogonal decomposition has already been computed.
|
||||
@@ -290,8 +278,7 @@ template <typename MatrixType_, typename PermutationIndex_> class CompleteOrthog
|
||||
* \warning: Do not compute \c this->pseudoInverse()*rhs to solve a linear systems.
|
||||
* It is more efficient and numerically stable to call \c this->solve(rhs).
|
||||
*/
|
||||
inline const Inverse<CompleteOrthogonalDecomposition> pseudoInverse() const
|
||||
{
|
||||
inline const Inverse<CompleteOrthogonalDecomposition> pseudoInverse() const {
|
||||
eigen_assert(m_cpqr.m_isInitialized && "CompleteOrthogonalDecomposition is not initialized.");
|
||||
return Inverse<CompleteOrthogonalDecomposition>(*this);
|
||||
}
|
||||
@@ -387,24 +374,25 @@ template <typename MatrixType_, typename PermutationIndex_> class CompleteOrthog
|
||||
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;
|
||||
template <bool Conjugate, typename RhsType, typename DstType>
|
||||
void _solve_impl_transposed(const RhsType& rhs, DstType& dst) const;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar)
|
||||
|
||||
template<bool Transpose_, typename Rhs>
|
||||
template <bool Transpose_, typename Rhs>
|
||||
void _check_solve_assertion(const Rhs& b) const {
|
||||
EIGEN_ONLY_USED_FOR_DEBUG(b);
|
||||
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");
|
||||
EIGEN_ONLY_USED_FOR_DEBUG(b);
|
||||
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
|
||||
* \f$ \mathbf{\overline Z} * \mathbf{rhs} \f$ if \c Conjugate
|
||||
* is set to \c true.
|
||||
*/
|
||||
template <bool Conjugate, typename Rhs>
|
||||
@@ -421,20 +409,18 @@ template <typename MatrixType_, typename PermutationIndex_> class CompleteOrthog
|
||||
};
|
||||
|
||||
template <typename MatrixType, typename PermutationIndex>
|
||||
typename MatrixType::Scalar
|
||||
CompleteOrthogonalDecomposition<MatrixType, PermutationIndex>::determinant() const {
|
||||
typename MatrixType::Scalar CompleteOrthogonalDecomposition<MatrixType, PermutationIndex>::determinant() const {
|
||||
return m_cpqr.determinant();
|
||||
}
|
||||
|
||||
template <typename MatrixType, typename PermutationIndex>
|
||||
typename MatrixType::RealScalar
|
||||
CompleteOrthogonalDecomposition<MatrixType, PermutationIndex>::absDeterminant() const {
|
||||
typename MatrixType::RealScalar CompleteOrthogonalDecomposition<MatrixType, PermutationIndex>::absDeterminant() const {
|
||||
return m_cpqr.absDeterminant();
|
||||
}
|
||||
|
||||
template <typename MatrixType, typename PermutationIndex>
|
||||
typename MatrixType::RealScalar
|
||||
CompleteOrthogonalDecomposition<MatrixType, PermutationIndex>::logAbsDeterminant() const {
|
||||
typename MatrixType::RealScalar CompleteOrthogonalDecomposition<MatrixType, PermutationIndex>::logAbsDeterminant()
|
||||
const {
|
||||
return m_cpqr.logAbsDeterminant();
|
||||
}
|
||||
|
||||
@@ -446,8 +432,7 @@ CompleteOrthogonalDecomposition<MatrixType, PermutationIndex>::logAbsDeterminant
|
||||
* CompleteOrthogonalDecomposition(const MatrixType&)
|
||||
*/
|
||||
template <typename MatrixType, typename PermutationIndex>
|
||||
void CompleteOrthogonalDecomposition<MatrixType, PermutationIndex>::computeInPlace()
|
||||
{
|
||||
void CompleteOrthogonalDecomposition<MatrixType, PermutationIndex>::computeInPlace() {
|
||||
eigen_assert(m_cpqr.cols() <= NumTraits<PermutationIndex>::highest());
|
||||
|
||||
const Index rank = m_cpqr.rank();
|
||||
@@ -473,28 +458,22 @@ void CompleteOrthogonalDecomposition<MatrixType, PermutationIndex>::computeInPla
|
||||
// Given the API for Householder reflectors, it is more convenient if
|
||||
// we swap the leading parts of columns k and r-1 (zero-based) to form
|
||||
// the matrix X_k = [X(0:k, k), X(0:k, r:n)]
|
||||
m_cpqr.m_qr.col(k).head(k + 1).swap(
|
||||
m_cpqr.m_qr.col(rank - 1).head(k + 1));
|
||||
m_cpqr.m_qr.col(k).head(k + 1).swap(m_cpqr.m_qr.col(rank - 1).head(k + 1));
|
||||
}
|
||||
// Construct Householder reflector Z(k) to zero out the last row of X_k,
|
||||
// i.e. choose Z(k) such that
|
||||
// [X(k, k), X(k, r:n)] * Z(k) = [beta, 0, .., 0].
|
||||
RealScalar beta;
|
||||
m_cpqr.m_qr.row(k)
|
||||
.tail(cols - rank + 1)
|
||||
.makeHouseholderInPlace(m_zCoeffs(k), beta);
|
||||
m_cpqr.m_qr.row(k).tail(cols - rank + 1).makeHouseholderInPlace(m_zCoeffs(k), beta);
|
||||
m_cpqr.m_qr(k, rank - 1) = beta;
|
||||
if (k > 0) {
|
||||
// Apply Z(k) to the first k rows of X_k
|
||||
m_cpqr.m_qr.topRightCorner(k, cols - rank + 1)
|
||||
.applyHouseholderOnTheRight(
|
||||
m_cpqr.m_qr.row(k).tail(cols - rank).adjoint(), m_zCoeffs(k),
|
||||
&m_temp(0));
|
||||
.applyHouseholderOnTheRight(m_cpqr.m_qr.row(k).tail(cols - rank).adjoint(), m_zCoeffs(k), &m_temp(0));
|
||||
}
|
||||
if (k != rank - 1) {
|
||||
// Swap X(0:k,k) back to its proper location.
|
||||
m_cpqr.m_qr.col(k).head(k + 1).swap(
|
||||
m_cpqr.m_qr.col(rank - 1).head(k + 1));
|
||||
m_cpqr.m_qr.col(k).head(k + 1).swap(m_cpqr.m_qr.col(rank - 1).head(k + 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -502,20 +481,18 @@ void CompleteOrthogonalDecomposition<MatrixType, PermutationIndex>::computeInPla
|
||||
|
||||
template <typename MatrixType, typename PermutationIndex>
|
||||
template <bool Conjugate, typename Rhs>
|
||||
void CompleteOrthogonalDecomposition<MatrixType, PermutationIndex>::applyZOnTheLeftInPlace(
|
||||
Rhs& rhs) const {
|
||||
void CompleteOrthogonalDecomposition<MatrixType, PermutationIndex>::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) {
|
||||
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));
|
||||
.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));
|
||||
}
|
||||
@@ -524,8 +501,7 @@ void CompleteOrthogonalDecomposition<MatrixType, PermutationIndex>::applyZOnTheL
|
||||
|
||||
template <typename MatrixType, typename PermutationIndex>
|
||||
template <typename Rhs>
|
||||
void CompleteOrthogonalDecomposition<MatrixType, PermutationIndex>::applyZAdjointOnTheLeftInPlace(
|
||||
Rhs& rhs) const {
|
||||
void CompleteOrthogonalDecomposition<MatrixType, PermutationIndex>::applyZAdjointOnTheLeftInPlace(Rhs& rhs) const {
|
||||
const Index cols = this->cols();
|
||||
const Index nrhs = rhs.cols();
|
||||
const Index rank = this->rank();
|
||||
@@ -535,9 +511,7 @@ void CompleteOrthogonalDecomposition<MatrixType, PermutationIndex>::applyZAdjoin
|
||||
rhs.row(k).swap(rhs.row(rank - 1));
|
||||
}
|
||||
rhs.middleRows(rank - 1, cols - rank + 1)
|
||||
.applyHouseholderOnTheLeft(
|
||||
matrixQTZ().row(k).tail(cols - rank).adjoint(), zCoeffs()(k),
|
||||
&temp(0));
|
||||
.applyHouseholderOnTheLeft(matrixQTZ().row(k).tail(cols - rank).adjoint(), zCoeffs()(k), &temp(0));
|
||||
if (k != rank - 1) {
|
||||
rhs.row(k).swap(rhs.row(rank - 1));
|
||||
}
|
||||
@@ -547,8 +521,8 @@ void CompleteOrthogonalDecomposition<MatrixType, PermutationIndex>::applyZAdjoin
|
||||
#ifndef EIGEN_PARSED_BY_DOXYGEN
|
||||
template <typename MatrixType_, typename PermutationIndex_>
|
||||
template <typename RhsType, typename DstType>
|
||||
void CompleteOrthogonalDecomposition<MatrixType_, PermutationIndex_>::_solve_impl(
|
||||
const RhsType& rhs, DstType& dst) const {
|
||||
void CompleteOrthogonalDecomposition<MatrixType_, PermutationIndex_>::_solve_impl(const RhsType& rhs,
|
||||
DstType& dst) const {
|
||||
const Index rank = this->rank();
|
||||
if (rank == 0) {
|
||||
dst.setZero();
|
||||
@@ -560,10 +534,7 @@ void CompleteOrthogonalDecomposition<MatrixType_, PermutationIndex_>::_solve_imp
|
||||
c.applyOnTheLeft(matrixQ().setLength(rank).adjoint());
|
||||
|
||||
// Solve T z = c(1:rank, :)
|
||||
dst.topRows(rank) = matrixT()
|
||||
.topLeftCorner(rank, rank)
|
||||
.template triangularView<Upper>()
|
||||
.solve(c.topRows(rank));
|
||||
dst.topRows(rank) = matrixT().topLeftCorner(rank, rank).template triangularView<Upper>().solve(c.topRows(rank));
|
||||
|
||||
const Index cols = this->cols();
|
||||
if (rank < cols) {
|
||||
@@ -577,10 +548,10 @@ void CompleteOrthogonalDecomposition<MatrixType_, PermutationIndex_>::_solve_imp
|
||||
dst = colsPermutation() * dst;
|
||||
}
|
||||
|
||||
template<typename MatrixType_, typename PermutationIndex_>
|
||||
template<bool Conjugate, typename RhsType, typename DstType>
|
||||
void CompleteOrthogonalDecomposition<MatrixType_, PermutationIndex_>::_solve_impl_transposed(const RhsType &rhs, DstType &dst) const
|
||||
{
|
||||
template <typename MatrixType_, typename PermutationIndex_>
|
||||
template <bool Conjugate, typename RhsType, typename DstType>
|
||||
void CompleteOrthogonalDecomposition<MatrixType_, PermutationIndex_>::_solve_impl_transposed(const RhsType& rhs,
|
||||
DstType& dst) const {
|
||||
const Index rank = this->rank();
|
||||
|
||||
if (rank == 0) {
|
||||
@@ -588,46 +559,51 @@ void CompleteOrthogonalDecomposition<MatrixType_, PermutationIndex_>::_solve_imp
|
||||
return;
|
||||
}
|
||||
|
||||
typename RhsType::PlainObject c(colsPermutation().transpose()*rhs);
|
||||
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));
|
||||
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.bottomRows(rows() - rank).setZero();
|
||||
|
||||
dst.applyOnTheLeft(householderQ().setLength(rank).template conjugateIf<!Conjugate>() );
|
||||
dst.applyOnTheLeft(householderQ().setLength(rank).template conjugateIf<!Conjugate>());
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace internal {
|
||||
|
||||
template<typename MatrixType, typename PermutationIndex>
|
||||
struct traits<Inverse<CompleteOrthogonalDecomposition<MatrixType, PermutationIndex> > >
|
||||
: traits<typename Transpose<typename MatrixType::PlainObject>::PlainObject>
|
||||
{
|
||||
template <typename MatrixType, typename PermutationIndex>
|
||||
struct traits<Inverse<CompleteOrthogonalDecomposition<MatrixType, PermutationIndex>>>
|
||||
: traits<typename Transpose<typename MatrixType::PlainObject>::PlainObject> {
|
||||
enum { Flags = 0 };
|
||||
};
|
||||
|
||||
template<typename DstXprType, typename MatrixType, typename PermutationIndex>
|
||||
struct Assignment<DstXprType, Inverse<CompleteOrthogonalDecomposition<MatrixType, PermutationIndex> >, internal::assign_op<typename DstXprType::Scalar,typename CompleteOrthogonalDecomposition<MatrixType, PermutationIndex>::Scalar>, Dense2Dense>
|
||||
{
|
||||
template <typename DstXprType, typename MatrixType, typename PermutationIndex>
|
||||
struct Assignment<DstXprType, Inverse<CompleteOrthogonalDecomposition<MatrixType, PermutationIndex>>,
|
||||
internal::assign_op<typename DstXprType::Scalar,
|
||||
typename CompleteOrthogonalDecomposition<MatrixType, PermutationIndex>::Scalar>,
|
||||
Dense2Dense> {
|
||||
typedef CompleteOrthogonalDecomposition<MatrixType, PermutationIndex> CodType;
|
||||
typedef Inverse<CodType> SrcXprType;
|
||||
static void run(DstXprType &dst, const SrcXprType &src, const internal::assign_op<typename DstXprType::Scalar,typename CodType::Scalar> &)
|
||||
{
|
||||
typedef Matrix<typename CodType::Scalar, CodType::RowsAtCompileTime, CodType::RowsAtCompileTime, 0, CodType::MaxRowsAtCompileTime, CodType::MaxRowsAtCompileTime> IdentityMatrixType;
|
||||
static void run(DstXprType& dst, const SrcXprType& src,
|
||||
const internal::assign_op<typename DstXprType::Scalar, typename CodType::Scalar>&) {
|
||||
typedef Matrix<typename CodType::Scalar, CodType::RowsAtCompileTime, CodType::RowsAtCompileTime, 0,
|
||||
CodType::MaxRowsAtCompileTime, CodType::MaxRowsAtCompileTime>
|
||||
IdentityMatrixType;
|
||||
dst = src.nestedExpression().solve(IdentityMatrixType::Identity(src.cols(), src.cols()));
|
||||
}
|
||||
};
|
||||
|
||||
} // end namespace internal
|
||||
} // end namespace internal
|
||||
|
||||
/** \returns the matrix Q as a sequence of householder transformations */
|
||||
template <typename MatrixType, typename PermutationIndex>
|
||||
@@ -637,9 +613,9 @@ CompleteOrthogonalDecomposition<MatrixType, PermutationIndex>::householderQ() co
|
||||
}
|
||||
|
||||
/** \return the complete orthogonal decomposition of \c *this.
|
||||
*
|
||||
* \sa class CompleteOrthogonalDecomposition
|
||||
*/
|
||||
*
|
||||
* \sa class CompleteOrthogonalDecomposition
|
||||
*/
|
||||
template <typename Derived>
|
||||
template <typename PermutationIndex>
|
||||
const CompleteOrthogonalDecomposition<typename MatrixBase<Derived>::PlainObject, PermutationIndex>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -15,293 +15,275 @@
|
||||
// IWYU pragma: private
|
||||
#include "./InternalHeaderCheck.h"
|
||||
|
||||
namespace Eigen {
|
||||
namespace Eigen {
|
||||
|
||||
namespace internal {
|
||||
template<typename MatrixType_> struct traits<HouseholderQR<MatrixType_> >
|
||||
: traits<MatrixType_>
|
||||
{
|
||||
template <typename MatrixType_>
|
||||
struct traits<HouseholderQR<MatrixType_>> : traits<MatrixType_> {
|
||||
typedef MatrixXpr XprKind;
|
||||
typedef SolverStorage StorageKind;
|
||||
typedef int StorageIndex;
|
||||
enum { Flags = 0 };
|
||||
};
|
||||
|
||||
} // end namespace internal
|
||||
} // end namespace internal
|
||||
|
||||
/** \ingroup QR_Module
|
||||
*
|
||||
*
|
||||
* \class HouseholderQR
|
||||
*
|
||||
* \brief Householder QR decomposition of a matrix
|
||||
*
|
||||
* \tparam MatrixType_ the type of the matrix of which we are computing the QR decomposition
|
||||
*
|
||||
* This class performs a QR decomposition of a matrix \b A into matrices \b Q and \b R
|
||||
* such that
|
||||
* \f[
|
||||
* \mathbf{A} = \mathbf{Q} \, \mathbf{R}
|
||||
* \f]
|
||||
* by using Householder transformations. Here, \b Q a unitary matrix and \b R an upper triangular matrix.
|
||||
* The result is stored in a compact way compatible with LAPACK.
|
||||
*
|
||||
* Note that no pivoting is performed. This is \b not a rank-revealing decomposition.
|
||||
* If you want that feature, use FullPivHouseholderQR or ColPivHouseholderQR instead.
|
||||
*
|
||||
* This Householder QR decomposition is faster, but less numerically stable and less feature-full than
|
||||
* FullPivHouseholderQR or ColPivHouseholderQR.
|
||||
*
|
||||
* This class supports the \link InplaceDecomposition inplace decomposition \endlink mechanism.
|
||||
*
|
||||
* \sa MatrixBase::householderQr()
|
||||
*/
|
||||
template<typename MatrixType_> class HouseholderQR
|
||||
: public SolverBase<HouseholderQR<MatrixType_> >
|
||||
{
|
||||
public:
|
||||
*
|
||||
*
|
||||
* \class HouseholderQR
|
||||
*
|
||||
* \brief Householder QR decomposition of a matrix
|
||||
*
|
||||
* \tparam MatrixType_ the type of the matrix of which we are computing the QR decomposition
|
||||
*
|
||||
* This class performs a QR decomposition of a matrix \b A into matrices \b Q and \b R
|
||||
* such that
|
||||
* \f[
|
||||
* \mathbf{A} = \mathbf{Q} \, \mathbf{R}
|
||||
* \f]
|
||||
* by using Householder transformations. Here, \b Q a unitary matrix and \b R an upper triangular matrix.
|
||||
* The result is stored in a compact way compatible with LAPACK.
|
||||
*
|
||||
* Note that no pivoting is performed. This is \b not a rank-revealing decomposition.
|
||||
* If you want that feature, use FullPivHouseholderQR or ColPivHouseholderQR instead.
|
||||
*
|
||||
* This Householder QR decomposition is faster, but less numerically stable and less feature-full than
|
||||
* FullPivHouseholderQR or ColPivHouseholderQR.
|
||||
*
|
||||
* This class supports the \link InplaceDecomposition inplace decomposition \endlink mechanism.
|
||||
*
|
||||
* \sa MatrixBase::householderQr()
|
||||
*/
|
||||
template <typename MatrixType_>
|
||||
class HouseholderQR : public SolverBase<HouseholderQR<MatrixType_>> {
|
||||
public:
|
||||
typedef MatrixType_ MatrixType;
|
||||
typedef SolverBase<HouseholderQR> Base;
|
||||
friend class SolverBase<HouseholderQR>;
|
||||
|
||||
typedef MatrixType_ MatrixType;
|
||||
typedef SolverBase<HouseholderQR> Base;
|
||||
friend class SolverBase<HouseholderQR>;
|
||||
EIGEN_GENERIC_PUBLIC_INTERFACE(HouseholderQR)
|
||||
enum {
|
||||
MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
|
||||
MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime
|
||||
};
|
||||
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;
|
||||
typedef HouseholderSequence<MatrixType, internal::remove_all_t<typename HCoeffsType::ConjugateReturnType>>
|
||||
HouseholderSequenceType;
|
||||
|
||||
EIGEN_GENERIC_PUBLIC_INTERFACE(HouseholderQR)
|
||||
enum {
|
||||
MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
|
||||
MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime
|
||||
};
|
||||
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;
|
||||
typedef HouseholderSequence<MatrixType,internal::remove_all_t<typename HCoeffsType::ConjugateReturnType>> HouseholderSequenceType;
|
||||
/**
|
||||
* \brief Default Constructor.
|
||||
*
|
||||
* The default constructor is useful in cases in which the user intends to
|
||||
* perform decompositions via HouseholderQR::compute(const MatrixType&).
|
||||
*/
|
||||
HouseholderQR() : m_qr(), m_hCoeffs(), m_temp(), m_isInitialized(false) {}
|
||||
|
||||
/**
|
||||
* \brief Default Constructor.
|
||||
*
|
||||
* The default constructor is useful in cases in which the user intends to
|
||||
* perform decompositions via HouseholderQR::compute(const MatrixType&).
|
||||
*/
|
||||
HouseholderQR() : m_qr(), m_hCoeffs(), m_temp(), m_isInitialized(false) {}
|
||||
/** \brief Default Constructor with memory preallocation
|
||||
*
|
||||
* Like the default constructor but with preallocation of the internal data
|
||||
* according to the specified problem \a size.
|
||||
* \sa HouseholderQR()
|
||||
*/
|
||||
HouseholderQR(Index rows, Index cols)
|
||||
: m_qr(rows, cols), m_hCoeffs((std::min)(rows, cols)), m_temp(cols), m_isInitialized(false) {}
|
||||
|
||||
/** \brief Default Constructor with memory preallocation
|
||||
*
|
||||
* Like the default constructor but with preallocation of the internal data
|
||||
* according to the specified problem \a size.
|
||||
* \sa HouseholderQR()
|
||||
*/
|
||||
HouseholderQR(Index rows, Index cols)
|
||||
: m_qr(rows, cols),
|
||||
m_hCoeffs((std::min)(rows,cols)),
|
||||
m_temp(cols),
|
||||
m_isInitialized(false) {}
|
||||
|
||||
/** \brief Constructs a QR factorization from a given matrix
|
||||
*
|
||||
* This constructor computes the QR factorization of the matrix \a matrix by calling
|
||||
* the method compute(). It is a short cut for:
|
||||
*
|
||||
* \code
|
||||
* HouseholderQR<MatrixType> qr(matrix.rows(), matrix.cols());
|
||||
* qr.compute(matrix);
|
||||
* \endcode
|
||||
*
|
||||
* \sa compute()
|
||||
*/
|
||||
template<typename InputType>
|
||||
explicit HouseholderQR(const EigenBase<InputType>& matrix)
|
||||
/** \brief Constructs a QR factorization from a given matrix
|
||||
*
|
||||
* This constructor computes the QR factorization of the matrix \a matrix by calling
|
||||
* the method compute(). It is a short cut for:
|
||||
*
|
||||
* \code
|
||||
* HouseholderQR<MatrixType> qr(matrix.rows(), matrix.cols());
|
||||
* qr.compute(matrix);
|
||||
* \endcode
|
||||
*
|
||||
* \sa compute()
|
||||
*/
|
||||
template <typename InputType>
|
||||
explicit HouseholderQR(const EigenBase<InputType>& matrix)
|
||||
: m_qr(matrix.rows(), matrix.cols()),
|
||||
m_hCoeffs((std::min)(matrix.rows(),matrix.cols())),
|
||||
m_hCoeffs((std::min)(matrix.rows(), matrix.cols())),
|
||||
m_temp(matrix.cols()),
|
||||
m_isInitialized(false)
|
||||
{
|
||||
compute(matrix.derived());
|
||||
}
|
||||
m_isInitialized(false) {
|
||||
compute(matrix.derived());
|
||||
}
|
||||
|
||||
|
||||
/** \brief Constructs a QR factorization from a given matrix
|
||||
*
|
||||
* This overloaded constructor is provided for \link InplaceDecomposition inplace decomposition \endlink when
|
||||
* \c MatrixType is a Eigen::Ref.
|
||||
*
|
||||
* \sa HouseholderQR(const EigenBase&)
|
||||
*/
|
||||
template<typename InputType>
|
||||
explicit HouseholderQR(EigenBase<InputType>& matrix)
|
||||
/** \brief Constructs a QR factorization from a given matrix
|
||||
*
|
||||
* This overloaded constructor is provided for \link InplaceDecomposition inplace decomposition \endlink when
|
||||
* \c MatrixType is a Eigen::Ref.
|
||||
*
|
||||
* \sa HouseholderQR(const EigenBase&)
|
||||
*/
|
||||
template <typename InputType>
|
||||
explicit HouseholderQR(EigenBase<InputType>& matrix)
|
||||
: m_qr(matrix.derived()),
|
||||
m_hCoeffs((std::min)(matrix.rows(),matrix.cols())),
|
||||
m_hCoeffs((std::min)(matrix.rows(), matrix.cols())),
|
||||
m_temp(matrix.cols()),
|
||||
m_isInitialized(false)
|
||||
{
|
||||
computeInPlace();
|
||||
}
|
||||
m_isInitialized(false) {
|
||||
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.
|
||||
*
|
||||
* \param b the right-hand-side of the equation to solve.
|
||||
*
|
||||
* \returns a solution.
|
||||
*
|
||||
* \note_about_checking_solutions
|
||||
*
|
||||
* \note_about_arbitrary_choice_of_solution
|
||||
*
|
||||
* Example: \include HouseholderQR_solve.cpp
|
||||
* Output: \verbinclude HouseholderQR_solve.out
|
||||
*/
|
||||
template<typename Rhs>
|
||||
inline const Solve<HouseholderQR, Rhs>
|
||||
solve(const MatrixBase<Rhs>& b) const;
|
||||
#endif
|
||||
#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.
|
||||
*
|
||||
* \param b the right-hand-side of the equation to solve.
|
||||
*
|
||||
* \returns a solution.
|
||||
*
|
||||
* \note_about_checking_solutions
|
||||
*
|
||||
* \note_about_arbitrary_choice_of_solution
|
||||
*
|
||||
* Example: \include HouseholderQR_solve.cpp
|
||||
* Output: \verbinclude HouseholderQR_solve.out
|
||||
*/
|
||||
template <typename Rhs>
|
||||
inline const Solve<HouseholderQR, Rhs> solve(const MatrixBase<Rhs>& b) const;
|
||||
#endif
|
||||
|
||||
/** This method returns an expression of the unitary matrix Q as a sequence of Householder transformations.
|
||||
*
|
||||
* The returned expression can directly be used to perform matrix products. It can also be assigned to a dense Matrix object.
|
||||
* Here is an example showing how to recover the full or thin matrix Q, as well as how to perform matrix products using operator*:
|
||||
*
|
||||
* Example: \include HouseholderQR_householderQ.cpp
|
||||
* Output: \verbinclude HouseholderQR_householderQ.out
|
||||
*/
|
||||
HouseholderSequenceType householderQ() const
|
||||
{
|
||||
eigen_assert(m_isInitialized && "HouseholderQR is not initialized.");
|
||||
return HouseholderSequenceType(m_qr, m_hCoeffs.conjugate());
|
||||
}
|
||||
/** This method returns an expression of the unitary matrix Q as a sequence of Householder transformations.
|
||||
*
|
||||
* The returned expression can directly be used to perform matrix products. It can also be assigned to a dense Matrix
|
||||
* object. Here is an example showing how to recover the full or thin matrix Q, as well as how to perform matrix
|
||||
* products using operator*:
|
||||
*
|
||||
* Example: \include HouseholderQR_householderQ.cpp
|
||||
* Output: \verbinclude HouseholderQR_householderQ.out
|
||||
*/
|
||||
HouseholderSequenceType householderQ() const {
|
||||
eigen_assert(m_isInitialized && "HouseholderQR is not initialized.");
|
||||
return HouseholderSequenceType(m_qr, m_hCoeffs.conjugate());
|
||||
}
|
||||
|
||||
/** \returns a reference to the matrix where the Householder QR decomposition is stored
|
||||
* in a LAPACK-compatible way.
|
||||
*/
|
||||
const MatrixType& matrixQR() const
|
||||
{
|
||||
eigen_assert(m_isInitialized && "HouseholderQR is not initialized.");
|
||||
return m_qr;
|
||||
}
|
||||
/** \returns a reference to the matrix where the Householder QR decomposition is stored
|
||||
* in a LAPACK-compatible way.
|
||||
*/
|
||||
const MatrixType& matrixQR() const {
|
||||
eigen_assert(m_isInitialized && "HouseholderQR is not initialized.");
|
||||
return m_qr;
|
||||
}
|
||||
|
||||
template<typename InputType>
|
||||
HouseholderQR& compute(const EigenBase<InputType>& matrix) {
|
||||
m_qr = matrix.derived();
|
||||
computeInPlace();
|
||||
return *this;
|
||||
}
|
||||
template <typename InputType>
|
||||
HouseholderQR& compute(const EigenBase<InputType>& matrix) {
|
||||
m_qr = matrix.derived();
|
||||
computeInPlace();
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** \returns the determinant of the matrix of which
|
||||
* *this is the QR decomposition. It has only linear complexity
|
||||
* (that is, O(n) where n is the dimension of the square matrix)
|
||||
* as the QR decomposition has already been computed.
|
||||
*
|
||||
* \note This is only for square matrices.
|
||||
*
|
||||
* \warning a determinant can be very big or small, so for matrices
|
||||
* of large enough dimension, there is a risk of overflow/underflow.
|
||||
* One way to work around that is to use logAbsDeterminant() instead.
|
||||
*
|
||||
* \sa absDeterminant(), logAbsDeterminant(), MatrixBase::determinant()
|
||||
*/
|
||||
typename MatrixType::Scalar determinant() const;
|
||||
/** \returns the determinant of the matrix of which
|
||||
* *this is the QR decomposition. It has only linear complexity
|
||||
* (that is, O(n) where n is the dimension of the square matrix)
|
||||
* as the QR decomposition has already been computed.
|
||||
*
|
||||
* \note This is only for square matrices.
|
||||
*
|
||||
* \warning a determinant can be very big or small, so for matrices
|
||||
* of large enough dimension, there is a risk of overflow/underflow.
|
||||
* One way to work around that is to use logAbsDeterminant() instead.
|
||||
*
|
||||
* \sa absDeterminant(), logAbsDeterminant(), MatrixBase::determinant()
|
||||
*/
|
||||
typename MatrixType::Scalar determinant() const;
|
||||
|
||||
/** \returns the absolute value of the determinant of the matrix of which
|
||||
* *this is the QR decomposition. It has only linear complexity
|
||||
* (that is, O(n) where n is the dimension of the square matrix)
|
||||
* as the QR decomposition has already been computed.
|
||||
*
|
||||
* \note This is only for square matrices.
|
||||
*
|
||||
* \warning a determinant can be very big or small, so for matrices
|
||||
* of large enough dimension, there is a risk of overflow/underflow.
|
||||
* One way to work around that is to use logAbsDeterminant() instead.
|
||||
*
|
||||
* \sa determinant(), logAbsDeterminant(), MatrixBase::determinant()
|
||||
*/
|
||||
typename MatrixType::RealScalar absDeterminant() const;
|
||||
/** \returns the absolute value of the determinant of the matrix of which
|
||||
* *this is the QR decomposition. It has only linear complexity
|
||||
* (that is, O(n) where n is the dimension of the square matrix)
|
||||
* as the QR decomposition has already been computed.
|
||||
*
|
||||
* \note This is only for square matrices.
|
||||
*
|
||||
* \warning a determinant can be very big or small, so for matrices
|
||||
* of large enough dimension, there is a risk of overflow/underflow.
|
||||
* One way to work around that is to use logAbsDeterminant() instead.
|
||||
*
|
||||
* \sa determinant(), logAbsDeterminant(), MatrixBase::determinant()
|
||||
*/
|
||||
typename MatrixType::RealScalar absDeterminant() const;
|
||||
|
||||
/** \returns the natural log of the absolute value of the determinant of the matrix of which
|
||||
* *this is the QR decomposition. It has only linear complexity
|
||||
* (that is, O(n) where n is the dimension of the square matrix)
|
||||
* as the QR decomposition has already been computed.
|
||||
*
|
||||
* \note This is only for square matrices.
|
||||
*
|
||||
* \note This method is useful to work around the risk of overflow/underflow that's inherent
|
||||
* to determinant computation.
|
||||
*
|
||||
* \sa determinant(), absDeterminant(), MatrixBase::determinant()
|
||||
*/
|
||||
typename MatrixType::RealScalar logAbsDeterminant() const;
|
||||
/** \returns the natural log of the absolute value of the determinant of the matrix of which
|
||||
* *this is the QR decomposition. It has only linear complexity
|
||||
* (that is, O(n) where n is the dimension of the square matrix)
|
||||
* as the QR decomposition has already been computed.
|
||||
*
|
||||
* \note This is only for square matrices.
|
||||
*
|
||||
* \note This method is useful to work around the risk of overflow/underflow that's inherent
|
||||
* to determinant computation.
|
||||
*
|
||||
* \sa determinant(), absDeterminant(), MatrixBase::determinant()
|
||||
*/
|
||||
typename MatrixType::RealScalar logAbsDeterminant() const;
|
||||
|
||||
inline Index rows() const { return m_qr.rows(); }
|
||||
inline Index cols() const { return m_qr.cols(); }
|
||||
inline Index rows() const { return m_qr.rows(); }
|
||||
inline Index cols() const { return m_qr.cols(); }
|
||||
|
||||
/** \returns a const reference to the vector of Householder coefficients used to represent the factor \c Q.
|
||||
*
|
||||
* For advanced uses only.
|
||||
*/
|
||||
const HCoeffsType& hCoeffs() const { return m_hCoeffs; }
|
||||
/** \returns a const reference to the vector of Householder coefficients used to represent the factor \c Q.
|
||||
*
|
||||
* For advanced uses only.
|
||||
*/
|
||||
const HCoeffsType& hCoeffs() const { return m_hCoeffs; }
|
||||
|
||||
#ifndef EIGEN_PARSED_BY_DOXYGEN
|
||||
template<typename RhsType, typename DstType>
|
||||
void _solve_impl(const RhsType &rhs, DstType &dst) const;
|
||||
#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
|
||||
template <bool Conjugate, typename RhsType, typename DstType>
|
||||
void _solve_impl_transposed(const RhsType& rhs, DstType& dst) const;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
protected:
|
||||
EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar)
|
||||
|
||||
EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar)
|
||||
void computeInPlace();
|
||||
|
||||
void computeInPlace();
|
||||
|
||||
MatrixType m_qr;
|
||||
HCoeffsType m_hCoeffs;
|
||||
RowVectorType m_temp;
|
||||
bool m_isInitialized;
|
||||
MatrixType m_qr;
|
||||
HCoeffsType m_hCoeffs;
|
||||
RowVectorType m_temp;
|
||||
bool m_isInitialized;
|
||||
};
|
||||
|
||||
namespace internal {
|
||||
|
||||
/** \internal */
|
||||
template<typename HCoeffs, typename Scalar, bool IsComplex>
|
||||
struct householder_determinant
|
||||
{
|
||||
static void run(const HCoeffs& hCoeffs, Scalar& out_det)
|
||||
{
|
||||
template <typename HCoeffs, typename Scalar, bool IsComplex>
|
||||
struct householder_determinant {
|
||||
static void run(const HCoeffs& hCoeffs, Scalar& out_det) {
|
||||
out_det = Scalar(1);
|
||||
Index size = hCoeffs.rows();
|
||||
for (Index i = 0; i < size; i ++)
|
||||
{
|
||||
for (Index i = 0; i < size; i++) {
|
||||
// For each valid reflection Q_n,
|
||||
// det(Q_n) = - conj(h_n) / h_n
|
||||
// where h_n is the Householder coefficient.
|
||||
if (hCoeffs(i) != Scalar(0))
|
||||
out_det *= - numext::conj(hCoeffs(i)) / hCoeffs(i);
|
||||
if (hCoeffs(i) != Scalar(0)) out_det *= -numext::conj(hCoeffs(i)) / hCoeffs(i);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/** \internal */
|
||||
template<typename HCoeffs, typename Scalar>
|
||||
struct householder_determinant<HCoeffs, Scalar, false>
|
||||
{
|
||||
static void run(const HCoeffs& hCoeffs, Scalar& out_det)
|
||||
{
|
||||
template <typename HCoeffs, typename Scalar>
|
||||
struct householder_determinant<HCoeffs, Scalar, false> {
|
||||
static void run(const HCoeffs& hCoeffs, Scalar& out_det) {
|
||||
bool negated = false;
|
||||
Index size = hCoeffs.rows();
|
||||
for (Index i = 0; i < size; i ++)
|
||||
{
|
||||
for (Index i = 0; i < size; i++) {
|
||||
// Each valid reflection negates the determinant.
|
||||
if (hCoeffs(i) != Scalar(0))
|
||||
negated ^= true;
|
||||
if (hCoeffs(i) != Scalar(0)) negated ^= true;
|
||||
}
|
||||
out_det = negated ? Scalar(-1) : Scalar(1);
|
||||
}
|
||||
};
|
||||
|
||||
} // end namespace internal
|
||||
} // end namespace internal
|
||||
|
||||
template<typename MatrixType>
|
||||
typename MatrixType::Scalar HouseholderQR<MatrixType>::determinant() const
|
||||
{
|
||||
template <typename MatrixType>
|
||||
typename MatrixType::Scalar HouseholderQR<MatrixType>::determinant() const {
|
||||
eigen_assert(m_isInitialized && "HouseholderQR is not initialized.");
|
||||
eigen_assert(m_qr.rows() == m_qr.cols() && "You can't take the determinant of a non-square matrix!");
|
||||
Scalar detQ;
|
||||
@@ -309,18 +291,16 @@ typename MatrixType::Scalar HouseholderQR<MatrixType>::determinant() const
|
||||
return m_qr.diagonal().prod() * detQ;
|
||||
}
|
||||
|
||||
template<typename MatrixType>
|
||||
typename MatrixType::RealScalar HouseholderQR<MatrixType>::absDeterminant() const
|
||||
{
|
||||
template <typename MatrixType>
|
||||
typename MatrixType::RealScalar HouseholderQR<MatrixType>::absDeterminant() const {
|
||||
using std::abs;
|
||||
eigen_assert(m_isInitialized && "HouseholderQR is not initialized.");
|
||||
eigen_assert(m_qr.rows() == m_qr.cols() && "You can't take the determinant of a non-square matrix!");
|
||||
return abs(m_qr.diagonal().prod());
|
||||
}
|
||||
|
||||
template<typename MatrixType>
|
||||
typename MatrixType::RealScalar HouseholderQR<MatrixType>::logAbsDeterminant() const
|
||||
{
|
||||
template <typename MatrixType>
|
||||
typename MatrixType::RealScalar HouseholderQR<MatrixType>::logAbsDeterminant() const {
|
||||
eigen_assert(m_isInitialized && "HouseholderQR is not initialized.");
|
||||
eigen_assert(m_qr.rows() == m_qr.cols() && "You can't take the determinant of a non-square matrix!");
|
||||
return m_qr.diagonal().cwiseAbs().array().log().sum();
|
||||
@@ -329,37 +309,34 @@ typename MatrixType::RealScalar HouseholderQR<MatrixType>::logAbsDeterminant() c
|
||||
namespace internal {
|
||||
|
||||
/** \internal */
|
||||
template<typename MatrixQR, typename HCoeffs>
|
||||
void householder_qr_inplace_unblocked(MatrixQR& mat, HCoeffs& hCoeffs, typename MatrixQR::Scalar* tempData = 0)
|
||||
{
|
||||
template <typename MatrixQR, typename HCoeffs>
|
||||
void householder_qr_inplace_unblocked(MatrixQR& mat, HCoeffs& hCoeffs, typename MatrixQR::Scalar* tempData = 0) {
|
||||
typedef typename MatrixQR::Scalar Scalar;
|
||||
typedef typename MatrixQR::RealScalar RealScalar;
|
||||
Index rows = mat.rows();
|
||||
Index cols = mat.cols();
|
||||
Index size = (std::min)(rows,cols);
|
||||
Index size = (std::min)(rows, cols);
|
||||
|
||||
eigen_assert(hCoeffs.size() == size);
|
||||
|
||||
typedef Matrix<Scalar,MatrixQR::ColsAtCompileTime,1> TempType;
|
||||
typedef Matrix<Scalar, MatrixQR::ColsAtCompileTime, 1> TempType;
|
||||
TempType tempVector;
|
||||
if(tempData==0)
|
||||
{
|
||||
if (tempData == 0) {
|
||||
tempVector.resize(cols);
|
||||
tempData = tempVector.data();
|
||||
}
|
||||
|
||||
for(Index k = 0; k < size; ++k)
|
||||
{
|
||||
for (Index k = 0; k < size; ++k) {
|
||||
Index remainingRows = rows - k;
|
||||
Index remainingCols = cols - k - 1;
|
||||
|
||||
RealScalar beta;
|
||||
mat.col(k).tail(remainingRows).makeHouseholderInPlace(hCoeffs.coeffRef(k), beta);
|
||||
mat.coeffRef(k,k) = beta;
|
||||
mat.coeffRef(k, k) = beta;
|
||||
|
||||
// apply H to remaining part of m_qr from the left
|
||||
mat.bottomRightCorner(remainingRows, remainingCols)
|
||||
.applyHouseholderOnTheLeft(mat.col(k).tail(remainingRows-1), hCoeffs.coeffRef(k), tempData+k+1);
|
||||
.applyHouseholderOnTheLeft(mat.col(k).tail(remainingRows - 1), hCoeffs.coeffRef(k), tempData + k + 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -401,38 +378,32 @@ void householder_qr_inplace_update(MatrixQR& mat, HCoeffs& hCoeffs, const Vector
|
||||
}
|
||||
|
||||
/** \internal */
|
||||
template<typename MatrixQR, typename HCoeffs,
|
||||
typename MatrixQRScalar = typename MatrixQR::Scalar,
|
||||
bool InnerStrideIsOne = (MatrixQR::InnerStrideAtCompileTime == 1 && HCoeffs::InnerStrideAtCompileTime == 1)>
|
||||
struct householder_qr_inplace_blocked
|
||||
{
|
||||
template <typename MatrixQR, typename HCoeffs, typename MatrixQRScalar = typename MatrixQR::Scalar,
|
||||
bool InnerStrideIsOne = (MatrixQR::InnerStrideAtCompileTime == 1 && HCoeffs::InnerStrideAtCompileTime == 1)>
|
||||
struct householder_qr_inplace_blocked {
|
||||
// This is specialized for LAPACK-supported Scalar types in HouseholderQR_LAPACKE.h
|
||||
static void run(MatrixQR& mat, HCoeffs& hCoeffs, Index maxBlockSize=32,
|
||||
typename MatrixQR::Scalar* tempData = 0)
|
||||
{
|
||||
static void run(MatrixQR& mat, HCoeffs& hCoeffs, Index maxBlockSize = 32, typename MatrixQR::Scalar* tempData = 0) {
|
||||
typedef typename MatrixQR::Scalar Scalar;
|
||||
typedef Block<MatrixQR,Dynamic,Dynamic> BlockType;
|
||||
typedef Block<MatrixQR, Dynamic, Dynamic> BlockType;
|
||||
|
||||
Index rows = mat.rows();
|
||||
Index cols = mat.cols();
|
||||
Index size = (std::min)(rows, cols);
|
||||
|
||||
typedef Matrix<Scalar,Dynamic,1,ColMajor,MatrixQR::MaxColsAtCompileTime,1> TempType;
|
||||
typedef Matrix<Scalar, Dynamic, 1, ColMajor, MatrixQR::MaxColsAtCompileTime, 1> TempType;
|
||||
TempType tempVector;
|
||||
if(tempData==0)
|
||||
{
|
||||
if (tempData == 0) {
|
||||
tempVector.resize(cols);
|
||||
tempData = tempVector.data();
|
||||
}
|
||||
|
||||
Index blockSize = (std::min)(maxBlockSize,size);
|
||||
Index blockSize = (std::min)(maxBlockSize, size);
|
||||
|
||||
Index k = 0;
|
||||
for (k = 0; k < size; k += blockSize)
|
||||
{
|
||||
Index bs = (std::min)(size-k,blockSize); // actual size of the block
|
||||
Index tcols = cols - k - bs; // trailing columns
|
||||
Index brows = rows-k; // rows of the block
|
||||
for (k = 0; k < size; k += blockSize) {
|
||||
Index bs = (std::min)(size - k, blockSize); // actual size of the block
|
||||
Index tcols = cols - k - bs; // trailing columns
|
||||
Index brows = rows - k; // rows of the block
|
||||
|
||||
// partition the matrix:
|
||||
// A00 | A01 | A02
|
||||
@@ -442,73 +413,68 @@ struct householder_qr_inplace_blocked
|
||||
// and update [A21^T A22^T]^T using level 3 operations.
|
||||
// Finally, the algorithm continue on A22
|
||||
|
||||
BlockType A11_21 = mat.block(k,k,brows,bs);
|
||||
Block<HCoeffs,Dynamic,1> hCoeffsSegment = hCoeffs.segment(k,bs);
|
||||
BlockType A11_21 = mat.block(k, k, brows, bs);
|
||||
Block<HCoeffs, Dynamic, 1> hCoeffsSegment = hCoeffs.segment(k, bs);
|
||||
|
||||
householder_qr_inplace_unblocked(A11_21, hCoeffsSegment, tempData);
|
||||
|
||||
if(tcols)
|
||||
{
|
||||
BlockType A21_22 = mat.block(k,k+bs,brows,tcols);
|
||||
apply_block_householder_on_the_left(A21_22,A11_21,hCoeffsSegment, false); // false == backward
|
||||
if (tcols) {
|
||||
BlockType A21_22 = mat.block(k, k + bs, brows, tcols);
|
||||
apply_block_householder_on_the_left(A21_22, A11_21, hCoeffsSegment, false); // false == backward
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // end namespace internal
|
||||
} // end namespace internal
|
||||
|
||||
#ifndef EIGEN_PARSED_BY_DOXYGEN
|
||||
template<typename MatrixType_>
|
||||
template<typename RhsType, typename DstType>
|
||||
void HouseholderQR<MatrixType_>::_solve_impl(const RhsType &rhs, DstType &dst) const
|
||||
{
|
||||
template <typename MatrixType_>
|
||||
template <typename RhsType, typename DstType>
|
||||
void HouseholderQR<MatrixType_>::_solve_impl(const RhsType& rhs, DstType& dst) const {
|
||||
const Index rank = (std::min)(rows(), cols());
|
||||
|
||||
typename RhsType::PlainObject c(rhs);
|
||||
|
||||
c.applyOnTheLeft(householderQ().setLength(rank).adjoint() );
|
||||
c.applyOnTheLeft(householderQ().setLength(rank).adjoint());
|
||||
|
||||
m_qr.topLeftCorner(rank, rank)
|
||||
.template triangularView<Upper>()
|
||||
.solveInPlace(c.topRows(rank));
|
||||
m_qr.topLeftCorner(rank, rank).template triangularView<Upper>().solveInPlace(c.topRows(rank));
|
||||
|
||||
dst.topRows(rank) = c.topRows(rank);
|
||||
dst.bottomRows(cols()-rank).setZero();
|
||||
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
|
||||
{
|
||||
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>()
|
||||
.transpose()
|
||||
.template conjugateIf<Conjugate>()
|
||||
.solveInPlace(c.topRows(rank));
|
||||
|
||||
dst.topRows(rank) = c.topRows(rank);
|
||||
dst.bottomRows(rows()-rank).setZero();
|
||||
dst.bottomRows(rows() - rank).setZero();
|
||||
|
||||
dst.applyOnTheLeft(householderQ().setLength(rank).template conjugateIf<!Conjugate>() );
|
||||
dst.applyOnTheLeft(householderQ().setLength(rank).template conjugateIf<!Conjugate>());
|
||||
}
|
||||
#endif
|
||||
|
||||
/** Performs the QR factorization of the given matrix \a matrix. The result of
|
||||
* the factorization is stored into \c *this, and a reference to \c *this
|
||||
* is returned.
|
||||
*
|
||||
* \sa class HouseholderQR, HouseholderQR(const MatrixType&)
|
||||
*/
|
||||
template<typename MatrixType>
|
||||
void HouseholderQR<MatrixType>::computeInPlace()
|
||||
{
|
||||
* the factorization is stored into \c *this, and a reference to \c *this
|
||||
* is returned.
|
||||
*
|
||||
* \sa class HouseholderQR, HouseholderQR(const MatrixType&)
|
||||
*/
|
||||
template <typename MatrixType>
|
||||
void HouseholderQR<MatrixType>::computeInPlace() {
|
||||
Index rows = m_qr.rows();
|
||||
Index cols = m_qr.cols();
|
||||
Index size = (std::min)(rows,cols);
|
||||
Index size = (std::min)(rows, cols);
|
||||
|
||||
m_hCoeffs.resize(size);
|
||||
|
||||
@@ -520,16 +486,14 @@ void HouseholderQR<MatrixType>::computeInPlace()
|
||||
}
|
||||
|
||||
/** \return the Householder QR decomposition of \c *this.
|
||||
*
|
||||
* \sa class HouseholderQR
|
||||
*/
|
||||
template<typename Derived>
|
||||
const HouseholderQR<typename MatrixBase<Derived>::PlainObject>
|
||||
MatrixBase<Derived>::householderQr() const
|
||||
{
|
||||
*
|
||||
* \sa class HouseholderQR
|
||||
*/
|
||||
template <typename Derived>
|
||||
const HouseholderQR<typename MatrixBase<Derived>::PlainObject> MatrixBase<Derived>::householderQr() const {
|
||||
return HouseholderQR<PlainObject>(eval());
|
||||
}
|
||||
|
||||
} // end namespace Eigen
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // EIGEN_QR_H
|
||||
#endif // EIGEN_QR_H
|
||||
|
||||
@@ -37,17 +37,15 @@
|
||||
// IWYU pragma: private
|
||||
#include "./InternalHeaderCheck.h"
|
||||
|
||||
namespace Eigen {
|
||||
namespace Eigen {
|
||||
|
||||
namespace internal {
|
||||
|
||||
namespace lapacke_helpers {
|
||||
|
||||
template<typename MatrixQR, typename HCoeffs>
|
||||
struct lapacke_hqr
|
||||
{
|
||||
static void run(MatrixQR& mat, HCoeffs& hCoeffs, Index = 32, typename MatrixQR::Scalar* = 0)
|
||||
{
|
||||
template <typename MatrixQR, typename HCoeffs>
|
||||
struct lapacke_hqr {
|
||||
static void run(MatrixQR& mat, HCoeffs& hCoeffs, Index = 32, typename MatrixQR::Scalar* = 0) {
|
||||
lapack_int m = to_lapack(mat.rows());
|
||||
lapack_int n = to_lapack(mat.cols());
|
||||
lapack_int lda = to_lapack(mat.outerStride());
|
||||
@@ -57,12 +55,13 @@ struct lapacke_hqr
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace lapacke_helpers
|
||||
|
||||
/** \internal Specialization for the data types supported by LAPACKe */
|
||||
#define EIGEN_LAPACKE_HH_QR(EIGTYPE) \
|
||||
template<typename MatrixQR, typename HCoeffs> \
|
||||
struct householder_qr_inplace_blocked<MatrixQR, HCoeffs, EIGTYPE, true> : public lapacke_helpers::lapacke_hqr<MatrixQR, HCoeffs> {};
|
||||
#define EIGEN_LAPACKE_HH_QR(EIGTYPE) \
|
||||
template <typename MatrixQR, typename HCoeffs> \
|
||||
struct householder_qr_inplace_blocked<MatrixQR, HCoeffs, EIGTYPE, true> \
|
||||
: public lapacke_helpers::lapacke_hqr<MatrixQR, HCoeffs> {};
|
||||
|
||||
EIGEN_LAPACKE_HH_QR(double)
|
||||
EIGEN_LAPACKE_HH_QR(float)
|
||||
@@ -71,8 +70,8 @@ EIGEN_LAPACKE_HH_QR(std::complex<float>)
|
||||
|
||||
#undef EIGEN_LAPACKE_HH_QR
|
||||
|
||||
} // end namespace internal
|
||||
} // end namespace internal
|
||||
|
||||
} // end namespace Eigen
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // EIGEN_QR_LAPACKE_H
|
||||
#endif // EIGEN_QR_LAPACKE_H
|
||||
|
||||
Reference in New Issue
Block a user