Apply clang-format

This commit is contained in:
Tobias Wood
2023-11-29 11:12:48 +00:00
parent 9ea520fc45
commit f38e16c193
534 changed files with 103368 additions and 116934 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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