SparseAssign.h
Go to the documentation of this file.
1 // This file is part of Eigen, a lightweight C++ template library
2 // for linear algebra.
3 //
4 // Copyright (C) 2008-2014 Gael Guennebaud <gael.guennebaud@inria.fr>
5 //
6 // This Source Code Form is subject to the terms of the Mozilla
7 // Public License v. 2.0. If a copy of the MPL was not distributed
8 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 
10 #ifndef EIGEN_SPARSEASSIGN_H
11 #define EIGEN_SPARSEASSIGN_H
12 
13 // IWYU pragma: private
14 #include "./InternalHeaderCheck.h"
15 
16 namespace Eigen {
17 
18 template <typename Derived>
19 template <typename OtherDerived>
21  internal::call_assignment_no_alias(derived(), other.derived());
22  return derived();
23 }
24 
25 template <typename Derived>
26 template <typename OtherDerived>
28  // TODO use the evaluator mechanism
29  other.evalTo(derived());
30  return derived();
31 }
32 
33 template <typename Derived>
34 template <typename OtherDerived>
36  // by default sparse evaluation do not alias, so we can safely bypass the generic call_assignment routine
39  return derived();
40 }
41 
42 template <typename Derived>
43 inline Derived &SparseMatrixBase<Derived>::operator=(const Derived &other) {
44  internal::call_assignment_no_alias(derived(), other.derived());
45  return derived();
46 }
47 
48 namespace internal {
49 
50 template <>
53 };
54 
55 template <>
57  typedef SparseShape Shape;
58 };
59 
60 struct Sparse2Sparse {};
61 struct Sparse2Dense {};
62 
63 template <>
66 };
67 template <>
70 };
71 template <>
73  typedef Sparse2Dense Kind;
74 };
75 template <>
77  typedef Sparse2Dense Kind;
78 };
79 
80 template <typename DstXprType, typename SrcXprType>
81 void assign_sparse_to_sparse(DstXprType &dst, const SrcXprType &src) {
82  typedef typename DstXprType::Scalar Scalar;
83  typedef internal::evaluator<DstXprType> DstEvaluatorType;
84  typedef internal::evaluator<SrcXprType> SrcEvaluatorType;
85 
86  SrcEvaluatorType srcEvaluator(src);
87 
88  constexpr bool transpose = (DstEvaluatorType::Flags & RowMajorBit) != (SrcEvaluatorType::Flags & RowMajorBit);
89  const Index outerEvaluationSize = (SrcEvaluatorType::Flags & RowMajorBit) ? src.rows() : src.cols();
90 
91  Index reserveSize = 0;
92  for (Index j = 0; j < outerEvaluationSize; ++j)
93  for (typename SrcEvaluatorType::InnerIterator it(srcEvaluator, j); it; ++it) reserveSize++;
94 
95  if ((!transpose) && src.isRValue()) {
96  // eval without temporary
97  dst.resize(src.rows(), src.cols());
98  dst.setZero();
99  dst.reserve(reserveSize);
100  for (Index j = 0; j < outerEvaluationSize; ++j) {
101  dst.startVec(j);
102  for (typename SrcEvaluatorType::InnerIterator it(srcEvaluator, j); it; ++it) {
103  Scalar v = it.value();
104  dst.insertBackByOuterInner(j, it.index()) = v;
105  }
106  }
107  dst.finalize();
108  } else {
109  // eval through a temporary
112  (!((DstEvaluatorType::Flags & RowMajorBit) != (SrcEvaluatorType::Flags & RowMajorBit)))) &&
113  "the transpose operation is supposed to be handled in SparseMatrix::operator=");
114 
115  enum { Flip = (DstEvaluatorType::Flags & RowMajorBit) != (SrcEvaluatorType::Flags & RowMajorBit) };
116 
117  DstXprType temp(src.rows(), src.cols());
118 
119  temp.reserve(reserveSize);
120  for (Index j = 0; j < outerEvaluationSize; ++j) {
121  temp.startVec(j);
122  for (typename SrcEvaluatorType::InnerIterator it(srcEvaluator, j); it; ++it) {
123  Scalar v = it.value();
124  temp.insertBackByOuterInner(Flip ? it.index() : j, Flip ? j : it.index()) = v;
125  }
126  }
127  temp.finalize();
128 
129  dst = temp.markAsRValue();
130  }
131 }
132 
133 // Generic Sparse to Sparse assignment
134 template <typename DstXprType, typename SrcXprType, typename Functor>
135 struct Assignment<DstXprType, SrcXprType, Functor, Sparse2Sparse> {
136  static void run(DstXprType &dst, const SrcXprType &src,
138  assign_sparse_to_sparse(dst.derived(), src.derived());
139  }
140 };
141 
142 // Generic Sparse to Dense assignment
143 template <typename DstXprType, typename SrcXprType, typename Functor, typename Weak>
144 struct Assignment<DstXprType, SrcXprType, Functor, Sparse2Dense, Weak> {
145  static void run(DstXprType &dst, const SrcXprType &src, const Functor &func) {
148  dst.setZero();
149 
150  internal::evaluator<SrcXprType> srcEval(src);
151  resize_if_allowed(dst, src, func);
152  internal::evaluator<DstXprType> dstEval(dst);
153 
154  const Index outerEvaluationSize = (internal::evaluator<SrcXprType>::Flags & RowMajorBit) ? src.rows() : src.cols();
155  for (Index j = 0; j < outerEvaluationSize; ++j)
156  for (typename internal::evaluator<SrcXprType>::InnerIterator i(srcEval, j); i; ++i)
157  func.assignCoeff(dstEval.coeffRef(i.row(), i.col()), i.value());
158  }
159 };
160 
161 // Specialization for dense ?= dense +/- sparse and dense ?= sparse +/- dense
162 template <typename DstXprType, typename Func1, typename Func2>
164  template <typename SrcXprType, typename InitialFunc>
165  static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run(DstXprType &dst, const SrcXprType &src,
166  const InitialFunc & /*func*/) {
167 #ifdef EIGEN_SPARSE_ASSIGNMENT_FROM_DENSE_OP_SPARSE_PLUGIN
169 #endif
170 
171  call_assignment_no_alias(dst, src.lhs(), Func1());
172  call_assignment_no_alias(dst, src.rhs(), Func2());
173  }
174 
175  // Specialization for dense1 = sparse + dense2; -> dense1 = dense2; dense1 += sparse;
176  template <typename Lhs, typename Rhs, typename Scalar>
178  std::enable_if_t<internal::is_same<typename internal::evaluator_traits<Rhs>::Shape, DenseShape>::value>
179  run(DstXprType &dst, const CwiseBinaryOp<internal::scalar_sum_op<Scalar, Scalar>, const Lhs, const Rhs> &src,
181 #ifdef EIGEN_SPARSE_ASSIGNMENT_FROM_SPARSE_ADD_DENSE_PLUGIN
183 #endif
184 
185  // Apply the dense matrix first, then the sparse one.
186  call_assignment_no_alias(dst, src.rhs(), Func1());
187  call_assignment_no_alias(dst, src.lhs(), Func2());
188  }
189 
190  // Specialization for dense1 = sparse - dense2; -> dense1 = -dense2; dense1 += sparse;
191  template <typename Lhs, typename Rhs, typename Scalar>
193  std::enable_if_t<internal::is_same<typename internal::evaluator_traits<Rhs>::Shape, DenseShape>::value>
194  run(DstXprType &dst,
197 #ifdef EIGEN_SPARSE_ASSIGNMENT_FROM_SPARSE_SUB_DENSE_PLUGIN
199 #endif
200 
201  // Apply the dense matrix first, then the sparse one.
202  call_assignment_no_alias(dst, -src.rhs(), Func1());
204  }
205 };
206 
207 #define EIGEN_CATCH_ASSIGN_DENSE_OP_SPARSE(ASSIGN_OP, BINOP, ASSIGN_OP2) \
208  template <typename DstXprType, typename Lhs, typename Rhs, typename Scalar> \
209  struct Assignment< \
210  DstXprType, CwiseBinaryOp<internal::BINOP<Scalar, Scalar>, const Lhs, const Rhs>, \
211  internal::ASSIGN_OP<typename DstXprType::Scalar, Scalar>, Sparse2Dense, \
212  std::enable_if_t<internal::is_same<typename internal::evaluator_traits<Lhs>::Shape, DenseShape>::value || \
213  internal::is_same<typename internal::evaluator_traits<Rhs>::Shape, DenseShape>::value>> \
214  : assignment_from_dense_op_sparse<DstXprType, \
215  internal::ASSIGN_OP<typename DstXprType::Scalar, typename Lhs::Scalar>, \
216  internal::ASSIGN_OP2<typename DstXprType::Scalar, typename Rhs::Scalar>> {}
217 
221 
225 
226 // Specialization for "dst = dec.solve(rhs)"
227 // NOTE we need to specialize it for Sparse2Sparse to avoid ambiguous specialization error
228 template <typename DstXprType, typename DecType, typename RhsType, typename Scalar>
229 struct Assignment<DstXprType, Solve<DecType, RhsType>, internal::assign_op<Scalar, Scalar>, Sparse2Sparse> {
231  static void run(DstXprType &dst, const SrcXprType &src, const internal::assign_op<Scalar, Scalar> &) {
232  Index dstRows = src.rows();
233  Index dstCols = src.cols();
234  if ((dst.rows() != dstRows) || (dst.cols() != dstCols)) dst.resize(dstRows, dstCols);
235 
236  src.dec()._solve_impl(src.rhs(), dst);
237  }
238 };
239 
240 struct Diagonal2Sparse {};
241 
242 template <>
245 };
246 
247 template <typename DstXprType, typename SrcXprType, typename Functor>
248 struct Assignment<DstXprType, SrcXprType, Functor, Diagonal2Sparse> {
249  typedef typename DstXprType::StorageIndex StorageIndex;
250  typedef typename DstXprType::Scalar Scalar;
251 
252  template <int Options, typename AssignFunc>
253  static void run(SparseMatrix<Scalar, Options, StorageIndex> &dst, const SrcXprType &src, const AssignFunc &func) {
254  dst.assignDiagonal(src.diagonal(), func);
255  }
256 
257  template <typename DstDerived>
258  static void run(SparseMatrixBase<DstDerived> &dst, const SrcXprType &src,
260  dst.derived().diagonal() = src.diagonal();
261  }
262 
263  template <typename DstDerived>
264  static void run(SparseMatrixBase<DstDerived> &dst, const SrcXprType &src,
266  dst.derived().diagonal() += src.diagonal();
267  }
268 
269  template <typename DstDerived>
270  static void run(SparseMatrixBase<DstDerived> &dst, const SrcXprType &src,
272  dst.derived().diagonal() -= src.diagonal();
273  }
274 };
275 } // end namespace internal
276 
277 } // end namespace Eigen
278 
279 #endif // EIGEN_SPARSEASSIGN_H
Array< int, Dynamic, 1 > v
Definition: Array_initializer_list_vector_cxx11.cpp:1
int i
Definition: BiCGSTAB_step_by_step.cpp:9
#define EIGEN_DEVICE_FUNC
Definition: Macros.h:892
#define eigen_assert(x)
Definition: Macros.h:910
#define EIGEN_STRONG_INLINE
Definition: Macros.h:834
SCALAR Scalar
Definition: bench_gemm.cpp:45
Generic expression where a coefficient-wise binary operator is applied to two expressions.
Definition: CwiseBinaryOp.h:79
Definition: ReturnByValue.h:50
EIGEN_DEVICE_FUNC void evalTo(Dest &dst) const
Definition: ReturnByValue.h:58
Pseudo expression representing a solving operation.
Definition: Solve.h:62
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR Index cols() const EIGEN_NOEXCEPT
Definition: Solve.h:70
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR Index rows() const EIGEN_NOEXCEPT
Definition: Solve.h:69
EIGEN_DEVICE_FUNC const Decomposition & dec() const
Definition: Solve.h:72
EIGEN_DEVICE_FUNC const RhsType & rhs() const
Definition: Solve.h:73
Base class of any sparse matrices or sparse expressions.
Definition: SparseMatrixBase.h:30
Derived & operator=(const EigenBase< OtherDerived > &other)
Definition: SparseAssign.h:20
const Derived & derived() const
Definition: SparseMatrixBase.h:144
A versatible sparse matrix representation.
Definition: SparseMatrix.h:121
void assignDiagonal(const DiagXpr diagXpr, const Func &assignFunc)
Definition: SparseMatrix.h:1005
const unsigned int RowMajorBit
Definition: Constants.h:70
@ Lhs
Definition: TensorContractionMapper.h:20
@ Rhs
Definition: TensorContractionMapper.h:20
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void resize_if_allowed(DstXprType &dst, const SrcXprType &src, const Functor &)
Definition: AssignEvaluator.h:703
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR void call_assignment_no_alias(Dst &dst, const Src &src, const Func &func)
Definition: AssignEvaluator.h:812
void assign_sparse_to_sparse(DstXprType &dst, const SrcXprType &src)
Definition: SparseAssign.h:81
EIGEN_CATCH_ASSIGN_DENSE_OP_SPARSE(assign_op, scalar_sum_op, add_assign_op)
Namespace containing all symbols from the Eigen library.
Definition: bench_norm.cpp:70
auto run(Kernel kernel, Args &&... args) -> decltype(kernel(args...))
Definition: gpu_test_helper.h:414
squared absolute value
Definition: GlobalFunctions.h:87
const int OuterRandomAccessPattern
Definition: SparseUtil.h:43
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API.
Definition: Meta.h:83
void transpose()
Definition: skew_symmetric_matrix3.cpp:135
Definition: Eigen_Colamd.h:49
#define EIGEN_SPARSE_ASSIGNMENT_FROM_DENSE_OP_SPARSE_PLUGIN
Definition: sparse_basic.cpp:17
#define EIGEN_SPARSE_ASSIGNMENT_FROM_SPARSE_ADD_DENSE_PLUGIN
Definition: sparse_basic.cpp:18
#define EIGEN_SPARSE_ASSIGNMENT_FROM_SPARSE_SUB_DENSE_PLUGIN
Definition: sparse_basic.cpp:19
Definition: Constants.h:540
Definition: Constants.h:549
Definition: EigenBase.h:33
constexpr EIGEN_DEVICE_FUNC Derived & derived()
Definition: EigenBase.h:49
Definition: Constants.h:570
Definition: Constants.h:522
Sparse2Dense Kind
Definition: SparseAssign.h:73
Diagonal2Sparse Kind
Definition: SparseAssign.h:244
Sparse2Sparse Kind
Definition: SparseAssign.h:65
Definition: AssignEvaluator.h:760
static void run(DstXprType &dst, const SrcXprType &src, const internal::assign_op< Scalar, Scalar > &)
Definition: SparseAssign.h:231
static void run(SparseMatrixBase< DstDerived > &dst, const SrcXprType &src, const internal::add_assign_op< typename DstXprType::Scalar, typename SrcXprType::Scalar > &)
Definition: SparseAssign.h:264
static void run(SparseMatrixBase< DstDerived > &dst, const SrcXprType &src, const internal::sub_assign_op< typename DstXprType::Scalar, typename SrcXprType::Scalar > &)
Definition: SparseAssign.h:270
DstXprType::StorageIndex StorageIndex
Definition: SparseAssign.h:249
static void run(SparseMatrixBase< DstDerived > &dst, const SrcXprType &src, const internal::assign_op< typename DstXprType::Scalar, typename SrcXprType::Scalar > &)
Definition: SparseAssign.h:258
static void run(SparseMatrix< Scalar, Options, StorageIndex > &dst, const SrcXprType &src, const AssignFunc &func)
Definition: SparseAssign.h:253
static void run(DstXprType &dst, const SrcXprType &src, const Functor &func)
Definition: SparseAssign.h:145
static void run(DstXprType &dst, const SrcXprType &src, const internal::assign_op< typename DstXprType::Scalar, typename SrcXprType::Scalar > &)
Definition: SparseAssign.h:136
Definition: AssignEvaluator.h:773
Definition: SparseAssign.h:240
Definition: Constants.h:580
Definition: SparseAssign.h:61
Definition: SparseAssign.h:60
Definition: SparseUtil.h:152
Template functor for scalar/packet assignment with addition.
Definition: AssignmentFunctors.h:52
Template functor for scalar/packet assignment.
Definition: AssignmentFunctors.h:25
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE std::enable_if_t< internal::is_same< typename internal::evaluator_traits< Rhs >::Shape, DenseShape >::value > run(DstXprType &dst, const CwiseBinaryOp< internal::scalar_sum_op< Scalar, Scalar >, const Lhs, const Rhs > &src, const internal::assign_op< typename DstXprType::Scalar, Scalar > &)
Definition: SparseAssign.h:179
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run(DstXprType &dst, const SrcXprType &src, const InitialFunc &)
Definition: SparseAssign.h:165
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE std::enable_if_t< internal::is_same< typename internal::evaluator_traits< Rhs >::Shape, DenseShape >::value > run(DstXprType &dst, const CwiseBinaryOp< internal::scalar_difference_op< Scalar, Scalar >, const Lhs, const Rhs > &src, const internal::assign_op< typename DstXprType::Scalar, Scalar > &)
Definition: SparseAssign.h:194
Definition: CoreEvaluators.h:104
Definition: Meta.h:205
Template functor to compute the difference of two scalars.
Definition: BinaryFunctors.h:381
Template functor to compute the sum of two scalars.
Definition: BinaryFunctors.h:34
IteratorBased Kind
Definition: SparseAssign.h:52
SparseShape Shape
Definition: SparseAssign.h:57
Definition: CoreEvaluators.h:32
Template functor for scalar/packet assignment with subtraction.
Definition: AssignmentFunctors.h:73
Definition: ForwardDeclarations.h:21
Definition: NonLinearOptimization.cpp:97
Definition: benchGeometry.cpp:21
std::ptrdiff_t j
Definition: tut_arithmetic_redux_minmax.cpp:2