11#ifndef EIGEN_CONSERVATIVESPARSESPARSEPRODUCT_H
12#define EIGEN_CONSERVATIVESPARSESPARSEPRODUCT_H
15#include "./InternalHeaderCheck.h"
21template <
typename Lhs,
typename Rhs,
typename ResultType>
22static void conservative_sparse_sparse_product_impl(
const Lhs& lhs,
const Rhs& rhs, ResultType& res,
23 bool sortedInsertion =
false) {
24 using LhsScalar =
typename remove_all_t<Lhs>::Scalar;
25 using RhsScalar =
typename remove_all_t<Rhs>::Scalar;
26 using ResScalar =
typename remove_all_t<ResultType>::Scalar;
29 Index rows = lhs.innerSize();
30 Index cols = rhs.outerSize();
31 eigen_assert(lhs.outerSize() == rhs.innerSize());
33 ei_declare_aligned_stack_constructed_variable(
bool, mask, rows, 0);
34 ei_declare_aligned_stack_constructed_variable(ResScalar, values, rows, 0);
35 ei_declare_aligned_stack_constructed_variable(Index, indices, rows, 0);
37 std::fill_n(mask, rows,
false);
39 evaluator<Lhs> lhsEval(lhs);
40 evaluator<Rhs> rhsEval(rhs);
48 Index estimated_nnz_prod = lhsEval.nonZerosEstimate() + rhsEval.nonZerosEstimate();
51 res.reserve(Index(estimated_nnz_prod));
53 for (Index j = 0; j < cols; ++j) {
56 for (
typename evaluator<Rhs>::InnerIterator rhsIt(rhsEval, j); rhsIt; ++rhsIt) {
57 RhsScalar y = rhsIt.value();
58 Index k = rhsIt.index();
59 for (
typename evaluator<Lhs>::InnerIterator lhsIt(lhsEval, k); lhsIt; ++lhsIt) {
60 Index i = lhsIt.index();
61 LhsScalar x = lhsIt.value();
71 if (!sortedInsertion) {
73 for (Index k = 0; k < nnz; ++k) {
75 res.insertBackByOuterInnerUnordered(j, i) = values[i];
80 const Index t200 = rows / 11;
81 const Index t = (rows * 100) / 139;
87 if ((nnz < 200 && nnz < t200) || nnz * numext::log2(
int(nnz)) < t) {
88 if (nnz > 1) std::sort(indices, indices + nnz);
89 for (Index k = 0; k < nnz; ++k) {
91 res.insertBackByOuterInner(j, i) = values[i];
96 for (Index i = 0; i < rows; ++i) {
99 res.insertBackByOuterInner(j, i) = values[i];
109template <
class Source,
int Order>
110using WithStorageOrder = SparseMatrix<typename Source::Scalar, Order, typename Source::StorageIndex>;
112template <
typename Lhs,
typename Rhs,
typename ResultType,
116struct conservative_sparse_sparse_product_selector;
118template <
typename Lhs,
typename Rhs,
typename ResultType>
119struct conservative_sparse_sparse_product_selector<Lhs, Rhs, ResultType, ColMajor, ColMajor, ColMajor> {
120 static void run(
const Lhs& lhs,
const Rhs& rhs, ResultType& res) {
121 using RowMajorMatrix = WithStorageOrder<ResultType, RowMajor>;
122 using ColMajorMatrixAux = WithStorageOrder<ResultType, ColMajor>;
128 if (lhs.rows() > rhs.cols()) {
129 using ColMajorMatrix =
typename sparse_eval<ColMajorMatrixAux, ResultType::RowsAtCompileTime,
130 ResultType::ColsAtCompileTime, ColMajorMatrixAux::Flags>::type;
131 ColMajorMatrix resCol(lhs.rows(), rhs.cols());
133 internal::conservative_sparse_sparse_product_impl<Lhs, Rhs, ColMajorMatrix>(lhs, rhs, resCol,
true);
134 res = resCol.markAsRValue();
136 ColMajorMatrixAux resCol(lhs.rows(), rhs.cols());
138 internal::conservative_sparse_sparse_product_impl<Lhs, Rhs, ColMajorMatrixAux>(lhs, rhs, resCol,
false);
139 RowMajorMatrix resRow(resCol);
140 res = resRow.markAsRValue();
145template <
typename Lhs,
typename Rhs,
typename ResultType>
147 static void run(
const Lhs& lhs,
const Rhs& rhs, ResultType& res) {
148 using RowMajorRhs = WithStorageOrder<Rhs, RowMajor>;
149 using RowMajorRes = WithStorageOrder<ResultType, RowMajor>;
150 RowMajorRhs rhsRow = rhs;
151 RowMajorRes resRow(lhs.rows(), rhs.cols());
152 internal::conservative_sparse_sparse_product_impl<RowMajorRhs, Lhs, RowMajorRes>(rhsRow, lhs, resRow);
157template <
typename Lhs,
typename Rhs,
typename ResultType>
159 static void run(
const Lhs& lhs,
const Rhs& rhs, ResultType& res) {
160 using RowMajorLhs = WithStorageOrder<Lhs, RowMajor>;
161 using RowMajorRes = WithStorageOrder<ResultType, RowMajor>;
162 RowMajorLhs lhsRow = lhs;
163 RowMajorRes resRow(lhs.rows(), rhs.cols());
164 internal::conservative_sparse_sparse_product_impl<Rhs, RowMajorLhs, RowMajorRes>(rhs, lhsRow, resRow);
169template <
typename Lhs,
typename Rhs,
typename ResultType>
171 static void run(
const Lhs& lhs,
const Rhs& rhs, ResultType& res) {
172 using RowMajorRes = WithStorageOrder<ResultType, RowMajor>;
173 RowMajorRes resRow(lhs.rows(), rhs.cols());
174 internal::conservative_sparse_sparse_product_impl<Rhs, Lhs, RowMajorRes>(rhs, lhs, resRow);
179template <
typename Lhs,
typename Rhs,
typename ResultType>
181 static void run(
const Lhs& lhs,
const Rhs& rhs, ResultType& res) {
182 using ColMajorRes = WithStorageOrder<ResultType, ColMajor>;
183 ColMajorRes resCol(lhs.rows(), rhs.cols());
184 internal::conservative_sparse_sparse_product_impl<Lhs, Rhs, ColMajorRes>(lhs, rhs, resCol);
189template <
typename Lhs,
typename Rhs,
typename ResultType>
191 static void run(
const Lhs& lhs,
const Rhs& rhs, ResultType& res) {
192 using ColMajorLhs = WithStorageOrder<Lhs, ColMajor>;
193 using ColMajorRes = WithStorageOrder<ResultType, ColMajor>;
194 ColMajorLhs lhsCol = lhs;
195 ColMajorRes resCol(lhs.rows(), rhs.cols());
196 internal::conservative_sparse_sparse_product_impl<ColMajorLhs, Rhs, ColMajorRes>(lhsCol, rhs, resCol);
201template <
typename Lhs,
typename Rhs,
typename ResultType>
203 static void run(
const Lhs& lhs,
const Rhs& rhs, ResultType& res) {
204 using ColMajorRhs = WithStorageOrder<Rhs, ColMajor>;
205 using ColMajorRes = WithStorageOrder<ResultType, ColMajor>;
206 ColMajorRhs rhsCol = rhs;
207 ColMajorRes resCol(lhs.rows(), rhs.cols());
208 internal::conservative_sparse_sparse_product_impl<Lhs, ColMajorRhs, ColMajorRes>(lhs, rhsCol, resCol);
213template <
typename Lhs,
typename Rhs,
typename ResultType>
215 static void run(
const Lhs& lhs,
const Rhs& rhs, ResultType& res) {
216 using ColMajorRes = WithStorageOrder<ResultType, ColMajor>;
217 using RowMajorRes = WithStorageOrder<ResultType, RowMajor>;
218 RowMajorRes resRow(lhs.rows(), rhs.cols());
219 internal::conservative_sparse_sparse_product_impl<Rhs, Lhs, RowMajorRes>(rhs, lhs, resRow);
221 ColMajorRes resCol(resRow);
226template <
typename Lhs,
typename Rhs,
typename ResultType>
227static void sparse_sparse_to_dense_product_impl(
const Lhs& lhs,
const Rhs& rhs, ResultType& res) {
228 using LhsScalar =
typename remove_all_t<Lhs>::Scalar;
229 using RhsScalar =
typename remove_all_t<Rhs>::Scalar;
230 Index cols = rhs.outerSize();
231 eigen_assert(lhs.outerSize() == rhs.innerSize());
233 evaluator<Lhs> lhsEval(lhs);
234 evaluator<Rhs> rhsEval(rhs);
236 for (Index j = 0; j < cols; ++j) {
237 for (
typename evaluator<Rhs>::InnerIterator rhsIt(rhsEval, j); rhsIt; ++rhsIt) {
238 RhsScalar y = rhsIt.value();
239 Index k = rhsIt.index();
240 for (
typename evaluator<Lhs>::InnerIterator lhsIt(lhsEval, k); lhsIt; ++lhsIt) {
241 Index i = lhsIt.index();
242 LhsScalar x = lhsIt.value();
243 res.coeffRef(i, j) += x * y;
253template <
typename Lhs,
typename Rhs,
typename ResultType,
256struct sparse_sparse_to_dense_product_selector;
258template <
typename Lhs,
typename Rhs,
typename ResultType>
259struct sparse_sparse_to_dense_product_selector<Lhs, Rhs, ResultType, ColMajor, ColMajor> {
260 static void run(
const Lhs& lhs,
const Rhs& rhs, ResultType& res) {
261 internal::sparse_sparse_to_dense_product_impl<Lhs, Rhs, ResultType>(lhs, rhs, res);
265template <
typename Lhs,
typename Rhs,
typename ResultType>
266struct sparse_sparse_to_dense_product_selector<Lhs, Rhs, ResultType, RowMajor, ColMajor> {
267 static void run(
const Lhs& lhs,
const Rhs& rhs, ResultType& res) {
268 using ColMajorLhs = WithStorageOrder<Lhs, ColMajor>;
269 ColMajorLhs lhsCol(lhs);
270 internal::sparse_sparse_to_dense_product_impl<ColMajorLhs, Rhs, ResultType>(lhsCol, rhs, res);
274template <
typename Lhs,
typename Rhs,
typename ResultType>
275struct sparse_sparse_to_dense_product_selector<Lhs, Rhs, ResultType, ColMajor, RowMajor> {
276 static void run(
const Lhs& lhs,
const Rhs& rhs, ResultType& res) {
277 using ColMajorRhs = WithStorageOrder<Rhs, ColMajor>;
278 ColMajorRhs rhsCol(rhs);
279 internal::sparse_sparse_to_dense_product_impl<Lhs, ColMajorRhs, ResultType>(lhs, rhsCol, res);
283template <
typename Lhs,
typename Rhs,
typename ResultType>
284struct sparse_sparse_to_dense_product_selector<Lhs, Rhs, ResultType, RowMajor, RowMajor> {
285 static void run(
const Lhs& lhs,
const Rhs& rhs, ResultType& res) {
286 Transpose<ResultType> trRes(res);
287 internal::sparse_sparse_to_dense_product_impl<Rhs, Lhs, Transpose<ResultType>>(rhs, lhs, trRes);
@ ColMajor
Definition Constants.h:319
@ RowMajor
Definition Constants.h:321
constexpr unsigned int RowMajorBit
Definition Constants.h:71