11 #ifndef EIGEN_FULLPIVOTINGHOUSEHOLDERQR_H
12 #define EIGEN_FULLPIVOTINGHOUSEHOLDERQR_H
18 template<
typename MatrixType>
struct FullPivHouseholderQRMatrixQReturnType;
20 template<
typename MatrixType>
21 struct traits<FullPivHouseholderQRMatrixQReturnType<MatrixType> >
23 typedef typename MatrixType::PlainObject ReturnType;
49 template<
typename _MatrixType>
class FullPivHouseholderQR
53 typedef _MatrixType MatrixType;
55 RowsAtCompileTime = MatrixType::RowsAtCompileTime,
56 ColsAtCompileTime = MatrixType::ColsAtCompileTime,
57 Options = MatrixType::Options,
58 MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
59 MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime
61 typedef typename MatrixType::Scalar Scalar;
62 typedef typename MatrixType::RealScalar RealScalar;
63 typedef typename MatrixType::Index Index;
64 typedef internal::FullPivHouseholderQRMatrixQReturnType<MatrixType> MatrixQReturnType;
65 typedef typename internal::plain_diag_type<MatrixType>::type HCoeffsType;
66 typedef Matrix<Index, 1, ColsAtCompileTime, RowMajor, 1, MaxColsAtCompileTime> IntRowVectorType;
67 typedef PermutationMatrix<ColsAtCompileTime, MaxColsAtCompileTime> PermutationType;
68 typedef typename internal::plain_col_type<MatrixType, Index>::type IntColVectorType;
69 typedef typename internal::plain_row_type<MatrixType>::type RowVectorType;
70 typedef typename internal::plain_col_type<MatrixType>::type ColVectorType;
80 m_rows_transpositions(),
81 m_cols_transpositions(),
84 m_isInitialized(false),
85 m_usePrescribedThreshold(false) {}
95 m_hCoeffs((std::min)(rows,cols)),
96 m_rows_transpositions(rows),
97 m_cols_transpositions(cols),
98 m_cols_permutation(cols),
99 m_temp((std::min)(rows,cols)),
100 m_isInitialized(false),
101 m_usePrescribedThreshold(false) {}
116 : m_qr(matrix.rows(), matrix.cols()),
117 m_hCoeffs((std::min)(matrix.rows(), matrix.cols())),
118 m_rows_transpositions(matrix.rows()),
119 m_cols_transpositions(matrix.cols()),
120 m_cols_permutation(matrix.cols()),
121 m_temp((std::min)(matrix.rows(), matrix.cols())),
122 m_isInitialized(false),
123 m_usePrescribedThreshold(false)
145 template<
typename Rhs>
146 inline const internal::solve_retval<FullPivHouseholderQR, Rhs>
149 eigen_assert(m_isInitialized &&
"FullPivHouseholderQR is not initialized.");
150 return internal::solve_retval<FullPivHouseholderQR, Rhs>(*
this, b.derived());
155 MatrixQReturnType
matrixQ(
void)
const;
161 eigen_assert(m_isInitialized &&
"FullPivHouseholderQR is not initialized.");
170 eigen_assert(m_isInitialized &&
"FullPivHouseholderQR is not initialized.");
171 return m_cols_permutation;
177 eigen_assert(m_isInitialized &&
"FullPivHouseholderQR is not initialized.");
178 return m_rows_transpositions;
219 eigen_assert(m_isInitialized &&
"FullPivHouseholderQR is not initialized.");
220 RealScalar premultiplied_threshold = abs(m_maxpivot) *
threshold();
222 for(Index i = 0; i < m_nonzero_pivots; ++i)
223 result += (abs(m_qr.coeff(i,i)) > premultiplied_threshold);
235 eigen_assert(m_isInitialized &&
"FullPivHouseholderQR is not initialized.");
236 return cols() -
rank();
248 eigen_assert(m_isInitialized &&
"FullPivHouseholderQR is not initialized.");
249 return rank() == cols();
261 eigen_assert(m_isInitialized &&
"FullPivHouseholderQR is not initialized.");
262 return rank() == rows();
273 eigen_assert(m_isInitialized &&
"FullPivHouseholderQR is not initialized.");
282 internal::solve_retval<FullPivHouseholderQR, typename MatrixType::IdentityReturnType>
285 eigen_assert(m_isInitialized &&
"FullPivHouseholderQR is not initialized.");
286 return internal::solve_retval<FullPivHouseholderQR,typename MatrixType::IdentityReturnType>
287 (*
this, MatrixType::Identity(m_qr.rows(), m_qr.cols()));
290 inline Index rows()
const {
return m_qr.rows(); }
291 inline Index cols()
const {
return m_qr.cols(); }
297 const HCoeffsType&
hCoeffs()
const {
return m_hCoeffs; }
318 m_usePrescribedThreshold =
true;
333 m_usePrescribedThreshold =
false;
343 eigen_assert(m_isInitialized || m_usePrescribedThreshold);
344 return m_usePrescribedThreshold ? m_prescribedThreshold
359 eigen_assert(m_isInitialized &&
"LU is not initialized.");
360 return m_nonzero_pivots;
370 HCoeffsType m_hCoeffs;
371 IntColVectorType m_rows_transpositions;
372 IntRowVectorType m_cols_transpositions;
373 PermutationType m_cols_permutation;
374 RowVectorType m_temp;
375 bool m_isInitialized, m_usePrescribedThreshold;
376 RealScalar m_prescribedThreshold, m_maxpivot;
377 Index m_nonzero_pivots;
378 RealScalar m_precision;
382 template<
typename MatrixType>
386 eigen_assert(m_isInitialized &&
"FullPivHouseholderQR is not initialized.");
387 eigen_assert(m_qr.rows() == m_qr.cols() &&
"You can't take the determinant of a non-square matrix!");
388 return abs(m_qr.diagonal().prod());
391 template<
typename MatrixType>
394 eigen_assert(m_isInitialized &&
"FullPivHouseholderQR is not initialized.");
395 eigen_assert(m_qr.rows() == m_qr.cols() &&
"You can't take the determinant of a non-square matrix!");
396 return m_qr.diagonal().cwiseAbs().array().log().sum();
405 template<
typename MatrixType>
409 Index rows = matrix.rows();
410 Index cols = matrix.cols();
411 Index size = (std::min)(rows,cols);
414 m_hCoeffs.resize(size);
420 m_rows_transpositions.resize(matrix.rows());
421 m_cols_transpositions.resize(matrix.cols());
422 Index number_of_transpositions = 0;
424 RealScalar biggest(0);
426 m_nonzero_pivots = size;
427 m_maxpivot = RealScalar(0);
429 for (Index k = 0; k < size; ++k)
431 Index row_of_biggest_in_corner, col_of_biggest_in_corner;
432 RealScalar biggest_in_corner;
434 biggest_in_corner = m_qr.bottomRightCorner(rows-k, cols-k)
436 .maxCoeff(&row_of_biggest_in_corner, &col_of_biggest_in_corner);
437 row_of_biggest_in_corner += k;
438 col_of_biggest_in_corner += k;
439 if(k==0) biggest = biggest_in_corner;
442 if(internal::isMuchSmallerThan(biggest_in_corner, biggest, m_precision))
444 m_nonzero_pivots = k;
445 for(Index i = k; i < size; i++)
447 m_rows_transpositions.coeffRef(i) = i;
448 m_cols_transpositions.coeffRef(i) = i;
449 m_hCoeffs.coeffRef(i) = Scalar(0);
454 m_rows_transpositions.coeffRef(k) = row_of_biggest_in_corner;
455 m_cols_transpositions.coeffRef(k) = col_of_biggest_in_corner;
456 if(k != row_of_biggest_in_corner) {
457 m_qr.row(k).tail(cols-k).swap(m_qr.row(row_of_biggest_in_corner).tail(cols-k));
458 ++number_of_transpositions;
460 if(k != col_of_biggest_in_corner) {
461 m_qr.col(k).swap(m_qr.col(col_of_biggest_in_corner));
462 ++number_of_transpositions;
466 m_qr.col(k).tail(rows-k).makeHouseholderInPlace(m_hCoeffs.coeffRef(k), beta);
467 m_qr.coeffRef(k,k) = beta;
470 if(abs(beta) > m_maxpivot) m_maxpivot = abs(beta);
472 m_qr.bottomRightCorner(rows-k, cols-k-1)
473 .applyHouseholderOnTheLeft(m_qr.col(k).tail(rows-k-1), m_hCoeffs.coeffRef(k), &m_temp.coeffRef(k+1));
476 m_cols_permutation.setIdentity(cols);
477 for(Index k = 0; k < size; ++k)
478 m_cols_permutation.applyTranspositionOnTheRight(k, m_cols_transpositions.coeff(k));
480 m_det_pq = (number_of_transpositions%2) ? -1 : 1;
481 m_isInitialized =
true;
488 template<
typename _MatrixType,
typename Rhs>
490 : solve_retval_base<FullPivHouseholderQR<_MatrixType>, Rhs>
494 template<typename Dest>
void evalTo(Dest& dst)
const
496 const Index rows = dec().rows(), cols = dec().cols();
497 eigen_assert(rhs().rows() == rows);
507 typename Rhs::PlainObject c(rhs());
509 Matrix<Scalar,1,Rhs::ColsAtCompileTime> temp(rhs().cols());
510 for (Index k = 0; k < dec().rank(); ++k)
512 Index remainingSize = rows-k;
513 c.row(k).swap(c.row(dec().rowsTranspositions().coeff(k)));
514 c.bottomRightCorner(remainingSize, rhs().cols())
515 .applyHouseholderOnTheLeft(dec().matrixQR().col(k).tail(remainingSize-1),
516 dec().hCoeffs().coeff(k), &temp.coeffRef(0));
519 if(!dec().isSurjective())
522 RealScalar biggest_in_upper_part_of_c = c.topRows( dec().rank() ).cwiseAbs().maxCoeff();
523 RealScalar biggest_in_lower_part_of_c = c.bottomRows(rows-dec().rank()).cwiseAbs().maxCoeff();
525 const RealScalar m_precision = NumTraits<Scalar>::epsilon() * (std::min)(rows,cols);
527 if(!internal::isMuchSmallerThan(biggest_in_lower_part_of_c, biggest_in_upper_part_of_c, m_precision))
531 .topLeftCorner(dec().rank(), dec().rank())
532 .template triangularView<Upper>()
533 .solveInPlace(c.topRows(dec().rank()));
535 for(Index i = 0; i < dec().rank(); ++i) dst.row(dec().colsPermutation().indices().coeff(i)) = c.row(i);
536 for(Index i = dec().rank(); i < cols; ++i) dst.row(dec().colsPermutation().indices().coeff(i)).setZero();
546 template<
typename MatrixType>
struct FullPivHouseholderQRMatrixQReturnType
547 :
public ReturnByValue<FullPivHouseholderQRMatrixQReturnType<MatrixType> >
550 typedef typename MatrixType::Index Index;
551 typedef typename internal::plain_col_type<MatrixType, Index>::type IntColVectorType;
552 typedef typename internal::plain_diag_type<MatrixType>::type HCoeffsType;
553 typedef Matrix<
typename MatrixType::Scalar, 1, MatrixType::RowsAtCompileTime,
RowMajor, 1,
554 MatrixType::MaxRowsAtCompileTime> WorkVectorType;
556 FullPivHouseholderQRMatrixQReturnType(
const MatrixType& qr,
557 const HCoeffsType& hCoeffs,
558 const IntColVectorType& rowsTranspositions)
561 m_rowsTranspositions(rowsTranspositions)
564 template <
typename ResultType>
565 void evalTo(ResultType& result)
const
567 const Index rows = m_qr.rows();
568 WorkVectorType workspace(rows);
569 evalTo(result, workspace);
572 template <
typename ResultType>
573 void evalTo(ResultType& result, WorkVectorType& workspace)
const
579 const Index rows = m_qr.rows();
580 const Index cols = m_qr.cols();
581 const Index size = (std::min)(rows, cols);
582 workspace.resize(rows);
583 result.setIdentity(rows, rows);
584 for (Index k = size-1; k >= 0; k--)
586 result.block(k, k, rows-k, rows-k)
587 .applyHouseholderOnTheLeft(m_qr.col(k).tail(rows-k-1), conj(m_hCoeffs.coeff(k)), &workspace.coeffRef(k));
588 result.row(k).swap(result.row(m_rowsTranspositions.coeff(k)));
592 Index rows()
const {
return m_qr.rows(); }
593 Index cols()
const {
return m_qr.rows(); }
596 typename MatrixType::Nested m_qr;
597 typename HCoeffsType::Nested m_hCoeffs;
598 typename IntColVectorType::Nested m_rowsTranspositions;
603 template<
typename MatrixType>
606 eigen_assert(m_isInitialized &&
"FullPivHouseholderQR is not initialized.");
607 return MatrixQReturnType(m_qr, m_hCoeffs, m_rows_transpositions);
614 template<
typename Derived>
623 #endif // EIGEN_FULLPIVOTINGHOUSEHOLDERQR_H