366 if (x <= RealScalar(0))
return j;
367 RealScalar nLjj =
sqrt(x);
368 mat.coeffRef(j, j) = nLjj;
372 Index rs = n - j - 1;
374 temp.tail(rs) -= (wj / Ljj) * mat.col(j).tail(rs);
375 if (!numext::is_exactly_zero(gamma))
376 mat.col(j).tail(rs) =
377 (nLjj / Ljj) * mat.col(j).tail(rs) + (nLjj * sigma * numext::conj(wj) / gamma) * temp.tail(rs);
384template <
typename Scalar>
385struct llt_inplace<Scalar,
Lower> {
386 using RealScalar =
typename NumTraits<Scalar>::Real;
387 template <
typename MatrixType>
388 static Index unblocked(MatrixType& mat) {
391 eigen_assert(mat.rows() == mat.cols());
392 const Index size = mat.rows();
393 for (Index k = 0; k < size; ++k) {
394 Index rs = size - k - 1;
396 Block<MatrixType, Dynamic, 1> A21(mat, k + 1, k, rs, 1);
397 Block<MatrixType, 1, Dynamic> A10(mat, k, 0, 1, k);
398 Block<MatrixType, Dynamic, Dynamic> A20(mat, k + 1, 0, rs, k);
400 RealScalar x = numext::real(mat.coeff(k, k));
401 if (k > 0) x -= A10.squaredNorm();
402 if (x <= RealScalar(0))
return k;
403 mat.coeffRef(k, k) = x = sqrt(x);
404 if (k > 0 && rs > 0) A21.noalias() -= A20 * A10.adjoint();
405 if (rs > 0) A21 /= x;
410 template <
typename MatrixType>
411 static Index blocked(MatrixType& m) {
412 eigen_assert(m.rows() == m.cols());
413 Index size = m.rows();
416 if (size <= 48)
return unblocked(m);
418 Index blockSize = size / 8;
419 blockSize = (blockSize / 16) * 16;
420 blockSize = (std::min)((std::max)(blockSize, Index(16)), Index(128));
422 for (Index k = 0; k < size; k += blockSize) {
427 Index bs = (std::min)(blockSize, size - k);
428 Index rs = size - k - bs;
429 Block<MatrixType, Dynamic, Dynamic> A11(m, k, k, bs, bs);
430 Block<MatrixType, Dynamic, Dynamic> A21(m, k + bs, k, rs, bs);
431 Block<MatrixType, Dynamic, Dynamic> A22(m, k + bs, k + bs, rs, rs);
434 if ((ret = unblocked(A11)) >= 0)
return k + ret;
435 if (rs > 0) A11.adjoint().template triangularView<Upper>().template solveInPlace<OnTheRight>(A21);
437 A22.template selfadjointView<Lower>().rankUpdate(A21,
438 typename NumTraits<RealScalar>::Literal(-1));
443 template <
typename MatrixType,
typename VectorType>
444 static Index rankUpdate(MatrixType& mat,
const VectorType& vec,
const RealScalar& sigma) {
445 return Eigen::internal::llt_rank_update_lower(mat, vec, sigma);
449template <
typename Scalar>
450struct llt_inplace<Scalar,
Upper> {
451 using RealScalar =
typename NumTraits<Scalar>::Real;
453 template <
typename MatrixType>
454 static EIGEN_STRONG_INLINE Index unblocked(MatrixType& mat) {
455 Transpose<MatrixType> matt(mat);
456 return llt_inplace<Scalar, Lower>::unblocked(matt);
458 template <
typename MatrixType>
459 static EIGEN_STRONG_INLINE Index blocked(MatrixType& mat) {
460 Transpose<MatrixType> matt(mat);
461 return llt_inplace<Scalar, Lower>::blocked(matt);
463 template <
typename MatrixType,
typename VectorType>
464 static Index rankUpdate(MatrixType& mat,
const VectorType& vec,
const RealScalar& sigma) {
465 Transpose<MatrixType> matt(mat);
466 return llt_inplace<Scalar, Lower>::rankUpdate(matt, vec.conjugate(), sigma);
470template <
typename MatrixType>
471struct LLT_Traits<MatrixType,
Lower> {
472 using MatrixL =
const TriangularView<const MatrixType, Lower>;
473 using MatrixU =
const TriangularView<const typename MatrixType::AdjointReturnType, Upper>;
474 static inline MatrixL getL(
const MatrixType& m) {
return MatrixL(m); }
475 static inline MatrixU getU(
const MatrixType& m) {
return MatrixU(m.adjoint()); }
476 static bool inplace_decomposition(MatrixType& m) {
477 return llt_inplace<typename MatrixType::Scalar, Lower>::blocked(m) == -1;
481template <
typename MatrixType>
482struct LLT_Traits<MatrixType,
Upper> {
483 using MatrixL =
const TriangularView<const typename MatrixType::AdjointReturnType, Lower>;
484 using MatrixU =
const TriangularView<const MatrixType, Upper>;
485 static inline MatrixL getL(
const MatrixType& m) {
return MatrixL(m.adjoint()); }
486 static inline MatrixU getU(
const MatrixType& m) {
return MatrixU(m); }
487 static bool inplace_decomposition(MatrixType& m) {
488 return llt_inplace<typename MatrixType::Scalar, Upper>::blocked(m) == -1;
501template <
typename MatrixType,
int UpLo_>
502template <
typename InputType>
504 eigen_assert(a.rows() == a.cols());
505 const Index
size = a.rows();
507 if (!internal::is_same_dense(m_matrix, a.derived())) m_matrix = a.derived();
510 m_l1_norm = m_matrix.template selfadjointView<UpLo_>().l1Norm();
512 m_isInitialized =
true;
513 bool ok = Traits::inplace_decomposition(m_matrix);
524template <
typename MatrixType_,
int UpLo_>
525template <
typename VectorType>
527 EIGEN_STATIC_ASSERT_VECTOR_ONLY(VectorType);
528 eigen_assert(v.size() == m_matrix.cols());
529 eigen_assert(m_isInitialized);
530 if (internal::llt_inplace<typename MatrixType::Scalar, UpLo>::rankUpdate(m_matrix, v, sigma) >= 0)
540template <
typename MatrixType_,
int UpLo_>
545template <
typename MatrixType_,
int UpLo_>
547 eigen_assert(m_isInitialized &&
"LLT is not initialized.");
548 eigen_assert(m_info ==
Success &&
"LLT failed because matrix appears to be negative");
549 return numext::abs2(m_matrix.diagonal().real().prod());
552template <
typename MatrixType_,
int UpLo_>
554 eigen_assert(m_isInitialized &&
"LLT is not initialized.");
555 eigen_assert(m_info ==
Success &&
"LLT failed because matrix appears to be negative");
556 return RealScalar(2) * m_matrix.diagonal().real().array().log().sum();
559template <
typename MatrixType_,
int UpLo_>
561 eigen_assert(m_isInitialized &&
"LLT is not initialized.");
562 eigen_assert(m_info ==
Success &&
"LLT failed because matrix appears to be negative");
566#ifndef EIGEN_PARSED_BY_DOXYGEN
567template <
typename MatrixType_,
int UpLo_>
568template <
typename RhsType,
typename DstType>
570 _solve_impl_transposed<true>(rhs, dst);
573template <
typename MatrixType_,
int UpLo_>
574template <
bool Conjugate,
typename RhsType,
typename DstType>
575void LLT<MatrixType_, UpLo_>::_solve_impl_transposed(
const RhsType& rhs, DstType& dst)
const {
578 matrixL().template conjugateIf<!Conjugate>().solveInPlace(dst);
579 matrixU().template conjugateIf<!Conjugate>().solveInPlace(dst);
596template <
typename MatrixType,
int UpLo_>
597template <
typename Derived>
599 eigen_assert(m_isInitialized &&
"LLT is not initialized.");
600 eigen_assert(m_matrix.rows() == bAndX.rows());
601 matrixL().solveInPlace(bAndX);
602 matrixU().solveInPlace(bAndX);
608template <
typename DstXprType,
typename MatrixType,
int UpLo_>
609struct Assignment<DstXprType, Inverse<LLT<MatrixType, UpLo_> >,
610 internal::assign_op<typename DstXprType::Scalar, typename LLT<MatrixType, UpLo_>::Scalar>,
612 using LltType = LLT<MatrixType, UpLo_>;
613 using SrcXprType = Inverse<LltType>;
615 static void run(DstXprType& dst,
const SrcXprType& src,
616 const internal::assign_op<typename DstXprType::Scalar, typename LltType::Scalar>&) {
617 const LltType& llt = src.nestedExpression();
618 eigen_assert(llt.info() ==
Success &&
"LLT::inverse(): the factorization failed.");
619 const Index size = llt.rows();
620 if ((dst.rows() != size) || (dst.cols() != size)) dst.resize(size, size);
623 constexpr Index kPotriThreshold =
624 NumTraits<typename LltType::Scalar>::IsComplex ? Index(0) : Index(EIGEN_LLT_INVERSE_POTRI_THRESHOLD);
629 const typename DstXprType::Scalar* dst_data = extract_data(dst);
630 const bool overwrites_factor = dst_data ==
nullptr || dst_data == llt.matrixLLT().data();
631 if (overwrites_factor || size >= kPotriThreshold) {
633 dst.template triangularView<UpLo_>() = llt.matrixLLT().template triangularView<UpLo_>();
634 dst.template triangularView<UpLo_>().inverseInPlace();
635 internal::triangular_adjoint_square_in_place<UpLo_>(dst);
638 llt.solveInPlace(dst);
643 dst.template triangularView<kMirrorMode>() = dst.adjoint();
652template <
typename MatrixType,
int UpLo_>
654 eigen_assert(m_isInitialized &&
"LLT is not initialized.");
662template <
typename Derived>