29#ifndef EIGEN_STRUCTURED_DIAGONAL_PLUS_LOW_RANK_H
30#define EIGEN_STRUCTURED_DIAGONAL_PLUS_LOW_RANK_H
33#include "./InternalHeaderCheck.h"
37template <
typename Scalar_,
int Size_ = Dynamic,
int Rank_ = Dynamic>
42template <
typename Scalar_,
int Size_,
int Rank_>
43struct traits<DiagonalPlusLowRank<Scalar_, Size_, Rank_>> {
44 using Scalar = Scalar_;
45 using StorageKind = Dense;
46 using XprKind = MatrixXpr;
47 using StorageIndex = int;
48 static constexpr int RowsAtCompileTime = Size_;
49 static constexpr int ColsAtCompileTime = Size_;
50 static constexpr int MaxRowsAtCompileTime = Size_;
51 static constexpr int MaxColsAtCompileTime = Size_;
56 static constexpr unsigned int Flags = 0;
59template <
typename Scalar_,
int Size_,
int Rank_>
60struct evaluator_traits<DiagonalPlusLowRank<Scalar_, Size_, Rank_>> {
61 using Kind = IndexBased;
62 using Shape = StructuredShape;
68struct dplr_capacitance_impl {
71 template <
typename Op,
typename Dinv,
typename Workspace>
72 static void subtractSolveCorrection(
const Op& op,
const Dinv& dinv, Workspace& x) {
73 if (op.correctionRank() == 0 || x.size() == 0)
return;
74 PartialPivLU<typename Op::CapacitanceType> cap(op.capacitance());
75 x.noalias() -= dinv.asDiagonal() * (op.factorU() * cap.solve(op.factorV().adjoint() * x));
78 template <
typename Op,
typename Dinv,
typename Factor>
79 static void inverseFactor(
const Op& op,
const Dinv& dinv, Factor& Up) {
80 if (op.correctionRank() == 0)
return;
81 PartialPivLU<typename Op::CapacitanceType> cap(op.capacitance());
82 const typename Op::CapacitanceType K = cap.inverse();
83 Up.noalias() = -(dinv.asDiagonal() * op.factorU() * K);
89 template <
typename Op>
90 static typename Op::Scalar balancedCapacitanceDeterminant(
const Op& op, Index& exponent) {
91 using Scalar =
typename Op::Scalar;
92 if (op.correctionRank() == 0)
return Scalar(1);
93 const PartialPivLU<typename Op::CapacitanceType> lu(op.capacitance());
94 Scalar det(
static_cast<typename Op::RealScalar
>(lu.permutationP().determinant()));
95 for (Index i = 0; i < lu.matrixLU().rows(); ++i)
96 det = structured_balance(det * structured_balance(lu.matrixLU().coeff(i, i), exponent), exponent);
102struct dplr_capacitance_impl<0> {
103 template <
typename Op,
typename Dinv,
typename Workspace>
104 static void subtractSolveCorrection(
const Op&,
const Dinv&, Workspace&) {}
105 template <
typename Op,
typename Dinv,
typename Factor>
106 static void inverseFactor(
const Op&,
const Dinv&, Factor&) {}
107 template <
typename Op>
108 static typename Op::Scalar balancedCapacitanceDeterminant(
const Op&, Index&) {
109 return typename Op::Scalar(1);
148template <
typename Scalar_,
int Size_,
int Rank_>
151 using Scalar = Scalar_;
153 using StorageIndex = int;
158 static constexpr int RowsAtCompileTime = Size_;
159 static constexpr int ColsAtCompileTime = Size_;
160 static constexpr int MaxRowsAtCompileTime = Size_;
161 static constexpr int MaxColsAtCompileTime = Size_;
162 static constexpr int SizeAtCompileTime = internal::size_at_compile_time(Size_, Size_);
163 static constexpr int MaxSizeAtCompileTime = SizeAtCompileTime;
164 static constexpr bool IsRowMajor =
false;
172 template <
typename DDerived,
typename UDerived,
typename VDerived>
174 : m_d(d), m_U(U), m_V(V) {
175 EIGEN_STATIC_ASSERT_VECTOR_ONLY(DDerived)
176 eigen_assert(m_d.size() > 0 &&
"DiagonalPlusLowRank must be non-empty");
177 eigen_assert(m_U.rows() == m_d.size() && m_V.rows() == m_d.size() && m_U.cols() == m_V.cols() &&
178 "factor dimensions do not match");
181 EIGEN_DEVICE_FUNC Index rows()
const {
return m_d.size(); }
182 EIGEN_DEVICE_FUNC Index cols()
const {
return m_d.size(); }
187 const DiagonalVector&
diagonal()
const {
return m_d; }
189 const FactorType&
factorU()
const {
return m_U; }
191 const FactorType&
factorV()
const {
return m_V; }
195 Scalar r = m_V.row(col).dot(m_U.row(row));
196 if (row == col) r += m_d.coeff(row);
222 CapacitanceType c = CapacitanceType::Identity(k, k);
223 if (k == 0)
return c;
224 const DiagonalVector dinv = m_d.cwiseInverse();
225 c.noalias() += m_V.adjoint() * dinv.asDiagonal() * m_U;
239 template <
typename Rhs>
241 EIGEN_STATIC_ASSERT(RowsAtCompileTime == Dynamic || Rhs::RowsAtCompileTime == Dynamic ||
242 int(RowsAtCompileTime) ==
int(Rhs::RowsAtCompileTime),
243 YOU_MIXED_MATRICES_OF_DIFFERENT_SIZES)
244 eigen_assert(b.rows() == rows() &&
"right-hand side has the wrong number of rows");
245 const DiagonalVector dinv = m_d.cwiseInverse();
247 internal::dplr_capacitance_impl<Rank_>::subtractSolveCorrection(*
this, dinv, x);
256 const DiagonalVector dinv = m_d.cwiseInverse();
258 internal::dplr_capacitance_impl<Rank_>::inverseFactor(*
this, dinv, Up);
259 FactorType Vp = dinv.conjugate().asDiagonal() * m_V;
285 for (
Index i = 0; i < rows(); ++i)
286 det = internal::structured_balance(det * internal::structured_balance(m_d.coeff(i), exponent), exponent);
287 const Scalar capDet = internal::dplr_capacitance_impl<Rank_>::balancedCapacitanceDeterminant(*
this, exponent);
288 det = internal::structured_balance(det * capDet, exponent);
289 return internal::structured_ldexp_clamped(det, exponent);
294 template <
typename Dest>
295 void evalTo(Dest& dst)
const {
296 dst.noalias() = m_U * m_V.adjoint();
297 dst.diagonal() += m_d;
301 template <
typename Dest>
302 void addTo(Dest& dst)
const {
303 dst.noalias() += m_U * m_V.adjoint();
304 dst.diagonal() += m_d;
308 template <
typename Dest>
309 void subTo(Dest& dst)
const {
310 dst.noalias() -= m_U * m_V.adjoint();
311 dst.diagonal() -= m_d;
319 template <
typename Rhs>
321 EIGEN_STATIC_ASSERT(ColsAtCompileTime == Dynamic || Rhs::RowsAtCompileTime == Dynamic ||
322 int(ColsAtCompileTime) ==
int(Rhs::RowsAtCompileTime),
323 INVALID_MATRIX_PRODUCT)
324 eigen_assert(v.rows() == cols() &&
"invalid product: dimensions do not match");
332 template <
typename Dest,
typename Rhs,
typename ProductScalar>
333 void addProduct(Dest& dst,
const Rhs& rhs,
const ProductScalar& alpha)
const {
334 eigen_assert(rhs.rows() == rows() &&
"invalid product: dimensions do not match");
336 dst += alpha * (m_d.asDiagonal() * r);
339 dst.noalias() += alpha * (m_U * t);
352template <
typename DDerived,
typename UDerived,
typename VDerived>
363template <
typename Scalar_,
int Size_,
int Rank_,
typename Rhs,
int ProductTag>
364struct generic_product_impl<DiagonalPlusLowRank<Scalar_, Size_, Rank_>, Rhs, StructuredShape, DenseShape, ProductTag>
365 : structured_product_impl<DiagonalPlusLowRank<Scalar_, Size_, Rank_>, Rhs> {};
An n x n operator : a diagonal matrix plus a rank-k correction, stored as its diagonal and the two n ...
Definition DiagonalPlusLowRank.h:149
const FactorType & factorV() const
Definition DiagonalPlusLowRank.h:191
Scalar coeff(Index row, Index col) const
Definition DiagonalPlusLowRank.h:194
Matrix< Scalar, Size_, Rhs::ColsAtCompileTime > solve(const MatrixBase< Rhs > &b) const
Definition DiagonalPlusLowRank.h:240
DiagonalPlusLowRank conjugate() const
Definition DiagonalPlusLowRank.h:206
DiagonalPlusLowRank adjoint() const
Definition DiagonalPlusLowRank.h:212
const FactorType & factorU() const
Definition DiagonalPlusLowRank.h:189
Product< DiagonalPlusLowRank, Rhs > operator*(const MatrixBase< Rhs > &v) const
Definition DiagonalPlusLowRank.h:320
DiagonalPlusLowRank inverse() const
Definition DiagonalPlusLowRank.h:255
const DiagonalVector & diagonal() const
Definition DiagonalPlusLowRank.h:187
DiagonalPlusLowRank(const MatrixBase< DDerived > &d, const MatrixBase< UDerived > &U, const MatrixBase< VDerived > &V)
Definition DiagonalPlusLowRank.h:173
CapacitanceType capacitance() const
Definition DiagonalPlusLowRank.h:220
DiagonalPlusLowRank transpose() const
Definition DiagonalPlusLowRank.h:202
Index correctionRank() const
Definition DiagonalPlusLowRank.h:184
Scalar determinant() const
Definition DiagonalPlusLowRank.h:282
DiagonalPlusLowRank< typename DDerived::Scalar, DDerived::SizeAtCompileTime, UDerived::ColsAtCompileTime > makeDiagonalPlusLowRank(const MatrixBase< DDerived > &d, const MatrixBase< UDerived > &U, const MatrixBase< VDerived > &V)
Definition DiagonalPlusLowRank.h:354
Namespace containing all symbols from the Eigen library.