11#ifndef EIGEN_PARTIALLU_H
12#define EIGEN_PARTIALLU_H
15#include "./InternalHeaderCheck.h"
20template <
typename MatrixType_,
typename PermutationIndex_>
21struct traits<PartialPivLU<MatrixType_, PermutationIndex_> > : traits<MatrixType_> {
22 typedef MatrixXpr XprKind;
23 typedef SolverStorage StorageKind;
24 typedef PermutationIndex_ StorageIndex;
25 typedef traits<MatrixType_> BaseTraits;
29template <
typename T,
typename Derived>
35template <
typename T,
typename Derived>
36struct enable_if_ref<Ref<T>, Derived> {
76template <
typename MatrixType_,
typename PermutationIndex_>
79 typedef MatrixType_ MatrixType;
85 MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
86 MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime
88 using PermutationIndex = PermutationIndex_;
91 typedef typename MatrixType::PlainObject PlainObject;
116 template <
typename InputType>
126 template <
typename InputType>
129 template <
typename InputType>
143 eigen_assert(m_isInitialized &&
"PartialPivLU is not initialized.");
150 eigen_assert(m_isInitialized &&
"PartialPivLU is not initialized.");
154#ifdef EIGEN_PARSED_BY_DOXYGEN
172 template <
typename Rhs>
180 eigen_assert(m_isInitialized &&
"PartialPivLU is not initialized.");
181 return internal::rcond_estimate_helper(m_l1_norm, *
this);
192 eigen_assert(m_isInitialized &&
"PartialPivLU is not initialized.");
213 EIGEN_CONSTEXPR
inline Index rows() const EIGEN_NOEXCEPT {
return m_lu.rows(); }
214 EIGEN_CONSTEXPR
inline Index cols() const EIGEN_NOEXCEPT {
return m_lu.cols(); }
216#ifndef EIGEN_PARSED_BY_DOXYGEN
217 template <
typename RhsType,
typename DstType>
218 EIGEN_DEVICE_FUNC
void _solve_impl(
const RhsType& rhs, DstType& dst)
const {
230 m_lu.template triangularView<UnitLower>().solveInPlace(dst);
233 m_lu.template triangularView<Upper>().solveInPlace(dst);
236 template <
bool Conjugate,
typename RhsType,
typename DstType>
237 EIGEN_DEVICE_FUNC
void _solve_impl_transposed(
const RhsType& rhs, DstType& dst)
const {
245 eigen_assert(rhs.rows() == m_lu.cols());
248 dst = m_lu.template triangularView<Upper>().transpose().template conjugateIf<Conjugate>().solve(rhs);
250 m_lu.template triangularView<UnitLower>().transpose().template conjugateIf<Conjugate>().solveInPlace(dst);
257 EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar)
263 TranspositionType m_rowsTranspositions;
264 RealScalar m_l1_norm;
266 bool m_isInitialized;
269template <
typename MatrixType,
typename PermutationIndex>
271 : m_lu(), m_p(), m_rowsTranspositions(), m_l1_norm(0), m_det_p(0), m_isInitialized(false) {}
273template <
typename MatrixType,
typename PermutationIndex>
275 : m_lu(size, size), m_p(size), m_rowsTranspositions(size), m_l1_norm(0), m_det_p(0), m_isInitialized(false) {}
277template <
typename MatrixType,
typename PermutationIndex>
278template <
typename InputType>
280 : m_lu(matrix.rows(), matrix.cols()),
282 m_rowsTranspositions(matrix.rows()),
285 m_isInitialized(false) {
289template <
typename MatrixType,
typename PermutationIndex>
290template <
typename InputType>
292 : m_lu(matrix.derived()),
294 m_rowsTranspositions(matrix.rows()),
297 m_isInitialized(false) {
304template <
typename Scalar,
int StorageOrder,
typename PivIndex,
int SizeAtCompileTime = Dynamic>
305struct partial_lu_impl {
306 static constexpr int UnBlockedBound = 16;
307 static constexpr bool UnBlockedAtCompileTime = SizeAtCompileTime !=
Dynamic && SizeAtCompileTime <= UnBlockedBound;
308 static constexpr int ActualSizeAtCompileTime = UnBlockedAtCompileTime ? SizeAtCompileTime :
Dynamic;
310 static constexpr int RRows = SizeAtCompileTime == 2 ? 1 :
Dynamic;
311 static constexpr int RCols = SizeAtCompileTime == 2 ? 1 :
Dynamic;
315 typedef typename MatrixType::RealScalar RealScalar;
327 static Index unblocked_lu(MatrixTypeRef& lu, PivIndex* row_transpositions, PivIndex& nb_transpositions) {
328 typedef scalar_score_coeff_op<Scalar> Scoring;
329 typedef typename Scoring::result_type Score;
330 const Index rows = lu.rows();
331 const Index cols = lu.cols();
332 const Index size = (std::min)(rows, cols);
335 const Index endk = UnBlockedAtCompileTime ? size - 1 : size;
336 nb_transpositions = 0;
337 Index first_zero_pivot = -1;
338 for (
Index k = 0; k < endk; ++k) {
339 int rrows = internal::convert_index<int>(rows - k - 1);
340 int rcols = internal::convert_index<int>(cols - k - 1);
342 Index row_of_biggest_in_col;
343 Score biggest_in_corner = lu.col(k).tail(rows - k).unaryExpr(Scoring()).maxCoeff(&row_of_biggest_in_col);
344 row_of_biggest_in_col += k;
346 row_transpositions[k] = PivIndex(row_of_biggest_in_col);
348 if (!numext::is_exactly_zero(biggest_in_corner)) {
349 if (k != row_of_biggest_in_col) {
350 lu.row(k).swap(lu.row(row_of_biggest_in_col));
354 lu.col(k).tail(fix<RRows>(rrows)) /= lu.coeff(k, k);
355 }
else if (first_zero_pivot == -1) {
358 first_zero_pivot = k;
362 lu.bottomRightCorner(fix<RRows>(rrows), fix<RCols>(rcols)).noalias() -=
363 lu.col(k).tail(fix<RRows>(rrows)) * lu.row(k).tail(fix<RCols>(rcols));
367 if (UnBlockedAtCompileTime) {
369 row_transpositions[k] = PivIndex(k);
370 if (numext::is_exactly_zero(Scoring()(lu(k, k))) && first_zero_pivot == -1) first_zero_pivot = k;
373 return first_zero_pivot;
391 static Index blocked_lu(Index rows, Index cols, Scalar* lu_data, Index luStride, PivIndex* row_transpositions,
392 PivIndex& nb_transpositions, Index maxBlockSize = 256) {
393 MatrixTypeRef lu = MatrixType::Map(lu_data, rows, cols, OuterStride<>(luStride));
395 const Index size = (std::min)(rows, cols);
398 if (UnBlockedAtCompileTime || size <= UnBlockedBound) {
399 return unblocked_lu(lu, row_transpositions, nb_transpositions);
406 blockSize = size / 8;
407 blockSize = (blockSize / 16) * 16;
408 blockSize = (std::min)((std::max)(blockSize,
Index(8)), maxBlockSize);
411 nb_transpositions = 0;
412 Index first_zero_pivot = -1;
413 for (Index k = 0; k < size; k += blockSize) {
414 Index bs = (std::min)(size - k, blockSize);
415 Index trows = rows - k - bs;
416 Index tsize = size - k - bs;
422 BlockType A_0 = lu.block(0, 0, rows, k);
423 BlockType A_2 = lu.block(0, k + bs, rows, tsize);
424 BlockType A11 = lu.block(k, k, bs, bs);
425 BlockType A12 = lu.block(k, k + bs, bs, tsize);
426 BlockType A21 = lu.block(k + bs, k, trows, bs);
427 BlockType A22 = lu.block(k + bs, k + bs, trows, tsize);
429 PivIndex nb_transpositions_in_panel;
432 Index ret = blocked_lu(trows + bs, bs, &lu.coeffRef(k, k), luStride, row_transpositions + k,
433 nb_transpositions_in_panel, 16);
434 if (ret >= 0 && first_zero_pivot == -1) first_zero_pivot = k + ret;
436 nb_transpositions += nb_transpositions_in_panel;
438 for (Index i = k; i < k + bs; ++i) {
439 Index piv = (row_transpositions[i] += internal::convert_index<PivIndex>(k));
440 A_0.row(i).swap(A_0.row(piv));
445 for (Index i = k; i < k + bs; ++i) A_2.row(i).swap(A_2.row(row_transpositions[i]));
448 A11.template triangularView<UnitLower>().solveInPlace(A12);
450 A22.noalias() -= A21 * A12;
453 return first_zero_pivot;
459template <
typename MatrixType,
typename TranspositionType>
460void partial_lu_inplace(MatrixType& lu, TranspositionType& row_transpositions,
461 typename TranspositionType::StorageIndex& nb_transpositions) {
463 if (lu.rows() == 0 || lu.cols() == 0) {
464 nb_transpositions = 0;
467 eigen_assert(lu.cols() == row_transpositions.size());
468 eigen_assert(row_transpositions.size() < 2 ||
469 (&row_transpositions.coeffRef(1) - &row_transpositions.coeffRef(0)) == 1);
472 typename TranspositionType::StorageIndex,
473 internal::min_size_prefer_fixed(MatrixType::RowsAtCompileTime, MatrixType::ColsAtCompileTime)>::
474 blocked_lu(lu.rows(), lu.cols(), &lu.coeffRef(0, 0), lu.outerStride(), &row_transpositions.coeffRef(0),
480template <
typename MatrixType,
typename PermutationIndex>
481void PartialPivLU<MatrixType, PermutationIndex>::compute() {
482 eigen_assert(m_lu.rows() < NumTraits<PermutationIndex>::highest());
485 m_l1_norm = m_lu.cwiseAbs().colwise().sum().maxCoeff();
487 m_l1_norm = RealScalar(0);
489 eigen_assert(m_lu.rows() == m_lu.cols() &&
"PartialPivLU is only for square (and moreover invertible) matrices");
490 const Index size = m_lu.rows();
492 m_rowsTranspositions.resize(size);
494 typename TranspositionType::StorageIndex nb_transpositions;
495 internal::partial_lu_inplace(m_lu, m_rowsTranspositions, nb_transpositions);
496 m_det_p = (nb_transpositions % 2) ? -1 : 1;
498 m_p = m_rowsTranspositions;
500 m_isInitialized =
true;
503template <
typename MatrixType,
typename PermutationIndex>
506 eigen_assert(m_isInitialized &&
"PartialPivLU is not initialized.");
507 return Scalar(m_det_p) * m_lu.diagonal().prod();
513template <
typename MatrixType,
typename PermutationIndex>
515 eigen_assert(m_isInitialized &&
"LU is not initialized.");
517 MatrixType res = m_lu.template triangularView<UnitLower>().toDenseMatrix() * m_lu.template triangularView<Upper>();
520 res = m_p.inverse() * res;
530template <
typename DstXprType,
typename MatrixType,
typename PermutationIndex>
533 internal::assign_op<typename DstXprType::Scalar, typename PartialPivLU<MatrixType, PermutationIndex>::Scalar>,
537 static void run(DstXprType& dst,
const SrcXprType& src,
538 const internal::assign_op<typename DstXprType::Scalar, typename LuType::Scalar>&) {
539 dst = src.nestedExpression().solve(MatrixType::Identity(src.rows(), src.cols()));
552template <
typename Derived>
553template <
typename PermutationIndex>
554inline const PartialPivLU<typename MatrixBase<Derived>::PlainObject, PermutationIndex>
567template <
typename Derived>
568template <
typename PermutationIndex>
Expression of the inverse of another expression.
Definition Inverse.h:43
Base class for all dense matrices, vectors, and expressions.
Definition MatrixBase.h:52
The matrix class, also used for vectors and row-vectors.
Definition Matrix.h:186
LU decomposition of a matrix with partial pivoting, and related features.
Definition PartialPivLU.h:77
MatrixType reconstructedMatrix() const
Definition PartialPivLU.h:514
const MatrixType & matrixLU() const
Definition PartialPivLU.h:142
RealScalar rcond() const
Definition PartialPivLU.h:179
PartialPivLU()
Default Constructor.
Definition PartialPivLU.h:270
const PermutationType & permutationP() const
Definition PartialPivLU.h:149
const Solve< PartialPivLU, Rhs > solve(const MatrixBase< Rhs > &b) const
const Inverse< PartialPivLU > inverse() const
Definition PartialPivLU.h:191
Scalar determinant() const
Definition PartialPivLU.h:504
InverseReturnType transpose() const
Definition PermutationMatrix.h:177
Permutation matrix.
Definition PermutationMatrix.h:280
A matrix or vector expression mapping an existing expression.
Definition Ref.h:264
Pseudo expression representing a solving operation.
Definition Solve.h:62
A base class for matrix decomposition and solvers.
Definition SolverBase.h:72
Represents a sequence of transpositions (row/column interchange)
Definition Transpositions.h:141
@ ColMajor
Definition Constants.h:318
@ RowMajor
Definition Constants.h:320
const unsigned int RowMajorBit
Definition Constants.h:70
Namespace containing all symbols from the Eigen library.
Definition Core:137
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API.
Definition Meta.h:83
const int Dynamic
Definition Constants.h:25
Definition EigenBase.h:33
Derived & derived()
Definition EigenBase.h:49
EIGEN_CONSTEXPR Index size() const EIGEN_NOEXCEPT
Definition EigenBase.h:64