11#ifndef EIGEN_SPARSE_DIAGONAL_PRODUCT_H
12#define EIGEN_SPARSE_DIAGONAL_PRODUCT_H
15#include "./InternalHeaderCheck.h"
33enum { SDP_AsScalarProduct, SDP_AsCwiseProduct };
35template <
typename SparseXprType,
typename DiagonalCoeffType,
int SDP_Tag>
36struct sparse_diagonal_product_evaluator;
38template <
typename Lhs,
typename Rhs,
int ProductTag>
39struct product_evaluator<Product<Lhs, Rhs, DefaultProduct>, ProductTag, DiagonalShape, SparseShape>
40 :
public sparse_diagonal_product_evaluator<Rhs, typename Lhs::DiagonalVectorType,
41 Rhs::Flags & RowMajorBit ? SDP_AsScalarProduct : SDP_AsCwiseProduct> {
42 using XprType = Product<Lhs, Rhs, DefaultProduct>;
44 CoeffReadCost = HugeCost,
49 using Base = sparse_diagonal_product_evaluator<Rhs,
typename Lhs::DiagonalVectorType,
50 Rhs::Flags &
RowMajorBit ? SDP_AsScalarProduct : SDP_AsCwiseProduct>;
51 explicit product_evaluator(
const XprType& xpr) : Base(xpr.rhs(), xpr.lhs().diagonal()) {}
54template <
typename Lhs,
typename Rhs,
int ProductTag>
55struct product_evaluator<Product<Lhs, Rhs, DefaultProduct>, ProductTag, SparseShape, DiagonalShape>
56 :
public sparse_diagonal_product_evaluator<Lhs, Transpose<const typename Rhs::DiagonalVectorType>,
57 Lhs::Flags & RowMajorBit ? SDP_AsCwiseProduct : SDP_AsScalarProduct> {
58 using XprType = Product<Lhs, Rhs, DefaultProduct>;
60 CoeffReadCost = HugeCost,
65 using Base = sparse_diagonal_product_evaluator<Lhs, Transpose<const typename Rhs::DiagonalVectorType>,
66 Lhs::Flags &
RowMajorBit ? SDP_AsCwiseProduct : SDP_AsScalarProduct>;
67 explicit product_evaluator(
const XprType& xpr) : Base(xpr.lhs(), xpr.rhs().diagonal().transpose()) {}
72template <
int Mode,
int ProductOrder,
typename SelfAdjo
intViewType,
typename DiagonalType,
typename Dest>
73struct sparse_selfadjoint_diagonal_product_impl {
74 using MatrixType =
typename SelfAdjointViewType::MatrixTypeNested_;
75 using MatrixEvaluator = evaluator<MatrixType>;
76 using MatrixIterator =
typename MatrixEvaluator::InnerIterator;
77 using StorageIndex =
typename Dest::StorageIndex;
78 using VectorI = Matrix<StorageIndex, Dynamic, 1>;
79 enum { IsFullMode = Mode == int(
Upper |
Lower), IsLowerMode = (Mode & int(
Lower)) ==
int(
Lower) };
81 static void run(Dest& dest,
const SelfAdjointViewType& selfadjoint,
const DiagonalType& diagonal) {
82 MatrixEvaluator matrixEval(selfadjoint.matrix());
83 const Index size = selfadjoint.rows();
86 dest.resize(size, size);
88 for (Index outer = 0; outer < selfadjoint.matrix().outerSize(); ++outer) {
89 for (MatrixIterator it(matrixEval, outer); it; ++it) countEntry(count, it.row(), it.col());
92 Index nnz = count.sum();
93 dest.resizeNonZeros(nnz);
94 dest.outerIndexPtr()[0] = 0;
95 for (Index outer = 0; outer < size; ++outer)
96 dest.outerIndexPtr()[outer + 1] = dest.outerIndexPtr()[outer] + count[outer];
97 for (Index outer = 0; outer < size; ++outer) count[outer] = dest.outerIndexPtr()[outer];
99 for (Index outer = 0; outer < selfadjoint.matrix().outerSize(); ++outer) {
100 for (MatrixIterator it(matrixEval, outer); it; ++it) {
101 const Index row = it.row();
102 const Index col = it.col();
103 if (isStored(row, col)) {
104 insertEntry(dest, count, diagonal, row, col, it.value());
106 if (mirrorsStoredEntry(row, col)) {
107 insertEntry(dest, count, diagonal, col, row, numext::conj(it.value()));
114 static EIGEN_STRONG_INLINE
bool isStored(Index row, Index col) {
115 return IsFullMode || row == col || (IsLowerMode ? row > col : row < col);
118 static EIGEN_STRONG_INLINE
bool mirrorsStoredEntry(Index row, Index col) {
119 return !IsFullMode && row != col && (IsLowerMode ? row > col : row < col);
122 static void countEntry(VectorI& count, Index row, Index col) {
123 if (isStored(row, col)) {
124 ++count[outerIndex(row, col)];
126 if (mirrorsStoredEntry(row, col)) {
127 ++count[outerIndex(col, row)];
131 static EIGEN_STRONG_INLINE StorageIndex outerIndex(Index row, Index col) {
132 return internal::convert_index<StorageIndex>(Dest::IsRowMajor ? row : col);
135 static EIGEN_STRONG_INLINE StorageIndex innerIndex(Index row, Index col) {
136 return internal::convert_index<StorageIndex>(Dest::IsRowMajor ? col : row);
139 template <
typename Coeff>
140 static void insertEntry(Dest& dest, VectorI& count,
const DiagonalType& diagonal, Index row, Index col,
141 const Coeff& coeff) {
142 const StorageIndex outer = outerIndex(row, col);
143 const Index k = count[outer]++;
144 dest.innerIndexPtr()[k] = innerIndex(row, col);
145 EIGEN_IF_CONSTEXPR (ProductOrder ==
OnTheLeft) {
146 dest.valuePtr()[k] = diagonal.coeff(row) * coeff;
148 dest.valuePtr()[k] = coeff * diagonal.coeff(col);
153template <
typename Lhs,
typename Rhs>
154struct materialized_left_sparse_product_evaluator_base
155 :
public evaluator<typename Product<Lhs, typename Rhs::PlainObject, DefaultProduct>::PlainObject> {
156 using XprType = Product<Lhs, Rhs, DefaultProduct>;
157 using PlainObject =
typename XprType::PlainObject;
158 using Base = evaluator<PlainObject>;
160 explicit materialized_left_sparse_product_evaluator_base(
const XprType& xpr) : m_result(xpr.rows(), xpr.cols()) {
161 internal::construct_at<Base>(
this, m_result);
162 sparse_selfadjoint_diagonal_product_impl<Rhs::Mode,
OnTheLeft, Rhs,
typename Lhs::DiagonalVectorType,
163 PlainObject>::run(m_result, xpr.rhs(), xpr.lhs().diagonal());
167 PlainObject m_result;
170template <
typename Lhs,
typename Rhs>
171struct materialized_right_sparse_product_evaluator_base
172 :
public evaluator<typename Product<typename Lhs::PlainObject, Rhs, DefaultProduct>::PlainObject> {
173 using XprType = Product<Lhs, Rhs, DefaultProduct>;
174 using PlainObject =
typename XprType::PlainObject;
175 using Base = evaluator<PlainObject>;
177 explicit materialized_right_sparse_product_evaluator_base(
const XprType& xpr) : m_result(xpr.rows(), xpr.cols()) {
178 internal::construct_at<Base>(
this, m_result);
179 sparse_selfadjoint_diagonal_product_impl<Lhs::Mode,
OnTheRight, Lhs,
typename Rhs::DiagonalVectorType,
180 PlainObject>::run(m_result, xpr.lhs(), xpr.rhs().diagonal());
184 PlainObject m_result;
187template <
typename Lhs,
typename Rhs,
int ProductTag>
188struct product_evaluator<Product<Lhs, Rhs, DefaultProduct>, ProductTag, DiagonalShape, SparseTriangularShape>
189 : product_evaluator<Product<Lhs, Rhs, DefaultProduct>, ProductTag, DiagonalShape, SparseShape> {
190 using Base = product_evaluator<Product<Lhs, Rhs, DefaultProduct>, ProductTag, DiagonalShape, SparseShape>;
194template <
typename Lhs,
typename Rhs,
int ProductTag>
195struct product_evaluator<Product<Lhs, Rhs, DefaultProduct>, ProductTag, DiagonalShape, SparseSelfAdjointShape>
196 : materialized_left_sparse_product_evaluator_base<Lhs, Rhs> {
197 using materialized_left_sparse_product_evaluator_base<Lhs, Rhs>::materialized_left_sparse_product_evaluator_base;
200template <
typename Lhs,
typename Rhs,
int ProductTag>
201struct product_evaluator<Product<Lhs, Rhs, DefaultProduct>, ProductTag, SparseTriangularShape, DiagonalShape>
202 : product_evaluator<Product<Lhs, Rhs, DefaultProduct>, ProductTag, SparseShape, DiagonalShape> {
203 using Base = product_evaluator<Product<Lhs, Rhs, DefaultProduct>, ProductTag, SparseShape, DiagonalShape>;
207template <
typename Lhs,
typename Rhs,
int ProductTag>
208struct product_evaluator<Product<Lhs, Rhs, DefaultProduct>, ProductTag, SparseSelfAdjointShape, DiagonalShape>
209 : materialized_right_sparse_product_evaluator_base<Lhs, Rhs> {
210 using materialized_right_sparse_product_evaluator_base<Lhs, Rhs>::materialized_right_sparse_product_evaluator_base;
213template <
typename SparseXprType,
typename DiagonalCoeffType>
214struct sparse_diagonal_product_evaluator<SparseXprType, DiagonalCoeffType, SDP_AsScalarProduct> {
216 using SparseXprInnerIterator =
typename evaluator<SparseXprType>::InnerIterator;
217 using Scalar =
typename SparseXprType::Scalar;
220 class InnerIterator :
public SparseXprInnerIterator {
222 InnerIterator(
const sparse_diagonal_product_evaluator& xprEval, Index outer)
223 : SparseXprInnerIterator(xprEval.m_sparseXprImpl, outer), m_coeff(xprEval.m_diagCoeffImpl.coeff(outer)) {}
225 EIGEN_STRONG_INLINE Scalar value()
const {
return m_coeff * SparseXprInnerIterator::value(); }
228 typename DiagonalCoeffType::Scalar m_coeff;
231 sparse_diagonal_product_evaluator(
const SparseXprType& sparseXpr,
const DiagonalCoeffType& diagCoeff)
232 : m_sparseXprImpl(sparseXpr), m_diagCoeffImpl(diagCoeff) {}
234 Index nonZerosEstimate()
const {
return m_sparseXprImpl.nonZerosEstimate(); }
237 evaluator<SparseXprType> m_sparseXprImpl;
238 evaluator<DiagonalCoeffType> m_diagCoeffImpl;
241template <
typename SparseXprType,
typename DiagCoeffType>
242struct sparse_diagonal_product_evaluator<SparseXprType, DiagCoeffType, SDP_AsCwiseProduct> {
243 using Scalar =
typename SparseXprType::Scalar;
244 using StorageIndex =
typename SparseXprType::StorageIndex;
246 using DiagCoeffNested =
247 typename nested_eval<DiagCoeffType, SparseXprType::IsRowMajor ? SparseXprType::RowsAtCompileTime
248 : SparseXprType::ColsAtCompileTime>::type;
250 class InnerIterator {
251 using SparseXprIter =
typename evaluator<SparseXprType>::InnerIterator;
254 InnerIterator(
const sparse_diagonal_product_evaluator& xprEval, Index outer)
255 : m_sparseIter(xprEval.m_sparseXprEval, outer), m_diagCoeffNested(xprEval.m_diagCoeffNested) {}
257 inline Scalar value()
const {
return m_sparseIter.value() * m_diagCoeffNested.coeff(index()); }
258 inline StorageIndex index()
const {
return m_sparseIter.index(); }
259 inline Index outer()
const {
return m_sparseIter.outer(); }
260 inline Index col()
const {
return SparseXprType::IsRowMajor ? m_sparseIter.index() : m_sparseIter.outer(); }
261 inline Index row()
const {
return SparseXprType::IsRowMajor ? m_sparseIter.outer() : m_sparseIter.index(); }
263 EIGEN_STRONG_INLINE InnerIterator& operator++() {
267 inline operator bool()
const {
return m_sparseIter; }
270 SparseXprIter m_sparseIter;
271 DiagCoeffNested m_diagCoeffNested;
274 sparse_diagonal_product_evaluator(
const SparseXprType& sparseXpr,
const DiagCoeffType& diagCoeff)
275 : m_sparseXprEval(sparseXpr), m_diagCoeffNested(diagCoeff) {}
277 Index nonZerosEstimate()
const {
return m_sparseXprEval.nonZerosEstimate(); }
280 evaluator<SparseXprType> m_sparseXprEval;
281 DiagCoeffNested m_diagCoeffNested;
@ Lower
Definition Constants.h:212
@ Upper
Definition Constants.h:214
@ OnTheLeft
Definition Constants.h:332
@ OnTheRight
Definition Constants.h:334
constexpr unsigned int RowMajorBit
Definition Constants.h:71