79 using MatrixType = MatrixType_;
85 MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
86 MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime
90 MaxRowsAtCompileTime, MaxRowsAtCompileTime>;
91 using HCoeffsType =
typename internal::plain_diag_type<MatrixType>::type;
92 using RowVectorType =
typename internal::plain_row_type<MatrixType>::type;
93 using HouseholderSequenceType =
103 eigen_assert(m_isInitialized &&
"HouseHolderQR is not initialized.");
122 : m_qr(rows, cols), m_hCoeffs((std::min)(rows, cols)), m_temp(cols), m_isInitialized(false) {}
136 template <
typename InputType>
138 : m_qr(matrix.rows(), matrix.cols()),
139 m_hCoeffs((std::min)(matrix.rows(), matrix.cols())),
140 m_temp(matrix.cols()),
141 m_isInitialized(false) {
152 template <
typename InputType>
155 m_hCoeffs((std::min)(matrix.rows(), matrix.cols())),
156 m_temp(matrix.cols()),
157 m_isInitialized(false) {
161#ifdef EIGEN_PARSED_BY_DOXYGEN
176 template <
typename Rhs>
190 eigen_assert(m_isInitialized &&
"HouseholderQR is not initialized.");
191 return HouseholderSequenceType(m_qr, m_hCoeffs.conjugate());
198 eigen_assert(m_isInitialized &&
"HouseholderQR is not initialized.");
202 template <
typename InputType>
277 inline Index rows()
const {
return m_qr.rows(); }
278 inline Index cols()
const {
return m_qr.cols(); }
284 const HCoeffsType&
hCoeffs()
const {
return m_hCoeffs; }
286#ifndef EIGEN_PARSED_BY_DOXYGEN
287 template <
typename RhsType,
typename DstType>
288 void _solve_impl(
const RhsType& rhs, DstType& dst)
const;
290 template <
bool Conjugate,
typename RhsType,
typename DstType>
291 void _solve_impl_transposed(
const RhsType& rhs, DstType& dst)
const;
295 EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar)
300 HCoeffsType m_hCoeffs;
301 RowVectorType m_temp;
302 bool m_isInitialized;
374template <
typename MatrixQR,
typename HCoeffs>
375void householder_qr_inplace_unblocked(MatrixQR& mat, HCoeffs& hCoeffs,
typename MatrixQR::Scalar* tempData = 0) {
376 using Scalar =
typename MatrixQR::Scalar;
377 using RealScalar =
typename MatrixQR::RealScalar;
378 Index rows = mat.rows();
379 Index cols = mat.cols();
380 Index size = (std::min)(rows, cols);
382 eigen_assert(hCoeffs.size() == size);
387 tempVector.resize(cols);
388 tempData = tempVector.data();
391 for (Index k = 0; k < size; ++k) {
392 Index remainingRows = rows - k;
393 Index remainingCols = cols - k - 1;
396 mat.col(k).tail(remainingRows).makeHouseholderInPlace(hCoeffs.coeffRef(k), beta);
397 mat.coeffRef(k, k) = beta;
400 mat.bottomRightCorner(remainingRows, remainingCols)
401 .applyHouseholderOnTheLeft(mat.col(k).tail(remainingRows - 1), hCoeffs.coeffRef(k), tempData + k + 1);
418template <
typename MatrixQR,
typename HCoeffs,
typename VectorQR>
419void householder_qr_inplace_update(MatrixQR& mat, HCoeffs& hCoeffs,
const VectorQR& newColumn,
420 typename MatrixQR::Index k,
typename MatrixQR::Scalar* tempData) {
421 using Index =
typename MatrixQR::Index;
422 using RealScalar =
typename MatrixQR::RealScalar;
423 Index rows = mat.rows();
425 eigen_assert(k < mat.cols());
426 eigen_assert(k < rows);
427 eigen_assert(hCoeffs.size() == mat.cols());
428 eigen_assert(newColumn.size() == rows);
429 eigen_assert(tempData);
432 mat.col(k) = newColumn;
434 for (Index i = 0; i < k; ++i) {
435 Index remainingRows = rows - i;
438 .applyHouseholderOnTheLeft(mat.col(i).tail(remainingRows - 1), hCoeffs.coeffRef(i), tempData + i + 1);
442 mat.col(k).tail(rows - k).makeHouseholderInPlace(hCoeffs.coeffRef(k), beta);
443 mat.coeffRef(k, k) = beta;
447template <
typename MatrixQR,
typename HCoeffs,
typename MatrixQRScalar =
typename MatrixQR::Scalar,
448 bool InnerStrideIsOne = (MatrixQR::InnerStrideAtCompileTime == 1 && HCoeffs::InnerStrideAtCompileTime == 1)>
449struct householder_qr_inplace_blocked {
451 static void run(MatrixQR& mat, HCoeffs& hCoeffs, Index maxBlockSize = 32,
typename MatrixQR::Scalar* tempData = 0) {
452 using Scalar =
typename MatrixQR::Scalar;
453 using BlockType = Block<MatrixQR, Dynamic, Dynamic>;
455 Index rows = mat.rows();
456 Index cols = mat.cols();
457 Index size = (std::min)(rows, cols);
459 using TempType = Matrix<Scalar, Dynamic, 1, ColMajor, MatrixQR::MaxColsAtCompileTime, 1>;
462 tempVector.resize(cols);
463 tempData = tempVector.data();
466 Index blockSize = (std::min)(maxBlockSize, size);
469 for (k = 0; k < size; k += blockSize) {
470 Index bs = (std::min)(size - k, blockSize);
471 Index tcols = cols - k - bs;
472 Index brows = rows - k;
482 BlockType A11_21 = mat.block(k, k, brows, bs);
483 Block<HCoeffs, Dynamic, 1> hCoeffsSegment = hCoeffs.segment(k, bs);
485 householder_qr_inplace_unblocked(A11_21, hCoeffsSegment, tempData);
488 BlockType A21_22 = mat.block(k, k + bs, brows, tcols);
489 apply_block_householder_on_the_left(A21_22, A11_21, hCoeffsSegment,
false);
507template <
typename Scalar>
508Index householder_qr_panel_width(Index rows, Index cols) {
509 const Index size = numext::mini(rows, cols);
510 const double m = double(rows), n = double(cols), s = double(size);
511 if (m * n * s <= 64.0 * 64.0 * 64.0)
return size;
512 const double P = m * s - s * s / 2;
513 const double Q = m * n * s - (m + n) * s * s / 2 + s * s * s / 3;
514 const double target = numext::sqrt(3 * Q / P);
515 constexpr Index kPacketSize = packet_traits<Scalar>::size;
516 const Index kWidths[] = {8, 16, 24, 32, 48};
517 Index width = kPacketSize;
518 double distance = NumTraits<double>::highest();
519 for (Index w : kWidths) {
520 const double d = numext::maxi(
double(w) / target, target /
double(w));
521 if (w % kPacketSize == 0 && d < distance) {
531#ifndef EIGEN_PARSED_BY_DOXYGEN
532template <
typename MatrixType_>
533template <
typename RhsType,
typename DstType>
535 const Index rank = (std::min)(rows(), cols());
537 typename RhsType::PlainObject c(rhs);
541 m_qr.topLeftCorner(rank, rank).template triangularView<Upper>().solveInPlace(c.topRows(rank));
543 dst.topRows(rank) = c.topRows(rank);
544 dst.bottomRows(cols() - rank).setZero();
547template <
typename MatrixType_>
548template <
bool Conjugate,
typename RhsType,
typename DstType>
550 const Index rank = (std::min)(rows(), cols());
552 typename RhsType::PlainObject c(rhs);
554 m_qr.topLeftCorner(rank, rank)
555 .template triangularView<Upper>()
557 .template conjugateIf<Conjugate>()
558 .solveInPlace(c.topRows(rank));
560 dst.topRows(rank) = c.topRows(rank);
561 dst.bottomRows(rows() - rank).setZero();
563 dst.applyOnTheLeft(
householderQ().setLength(rank).
template conjugateIf<!Conjugate>());
573template <
typename MatrixType>
575 Index rows = m_qr.rows();
576 Index cols = m_qr.cols();
577 Index
size = (std::min)(rows, cols);
579 m_hCoeffs.resize(
size);
583 const Index maxBlockSize = internal::householder_qr_panel_width<Scalar>(rows, cols);
584 internal::householder_qr_inplace_blocked<MatrixType, HCoeffsType>::run(m_qr, m_hCoeffs, maxBlockSize, m_temp.data());
586 m_isInitialized =
true;
593template <
typename Derived>