Medial Code Documentation
Loading...
Searching...
No Matches
SparseCwiseBinaryOp.h
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_SPARSE_CWISE_BINARY_OP_H
11#define EIGEN_SPARSE_CWISE_BINARY_OP_H
12
13namespace Eigen {
14
15// Here we have to handle 3 cases:
16// 1 - sparse op dense
17// 2 - dense op sparse
18// 3 - sparse op sparse
19// We also need to implement a 4th iterator for:
20// 4 - dense op dense
21// Finally, we also need to distinguish between the product and other operations :
22// configuration returned mode
23// 1 - sparse op dense product sparse
24// generic dense
25// 2 - dense op sparse product sparse
26// generic dense
27// 3 - sparse op sparse product sparse
28// generic sparse
29// 4 - dense op dense product dense
30// generic dense
31
32template<typename BinaryOp, typename Lhs, typename Rhs>
33class CwiseBinaryOpImpl<BinaryOp, Lhs, Rhs, Sparse>
34 : public SparseMatrixBase<CwiseBinaryOp<BinaryOp, Lhs, Rhs> >
35{
36 public:
39 EIGEN_SPARSE_PUBLIC_INTERFACE(Derived)
41 {
42 EIGEN_STATIC_ASSERT((
45 || ((Lhs::Flags&RowMajorBit) == (Rhs::Flags&RowMajorBit))),
46 THE_STORAGE_ORDER_OF_BOTH_SIDES_MUST_MATCH);
47 }
48};
49
50namespace internal {
51
52template<typename BinaryOp, typename Lhs, typename Rhs, typename Derived,
53 typename _LhsStorageMode = typename traits<Lhs>::StorageKind,
54 typename _RhsStorageMode = typename traits<Rhs>::StorageKind>
56
57} // end namespace internal
58
59namespace internal {
60
61
62// Generic "sparse OP sparse"
63template<typename BinaryOp, typename Lhs, typename Rhs>
65 : evaluator_base<CwiseBinaryOp<BinaryOp, Lhs, Rhs> >
66{
67protected:
71 typedef typename traits<XprType>::Scalar Scalar;
72 typedef typename XprType::StorageIndex StorageIndex;
73public:
74
75 class ReverseInnerIterator;
77 {
78 public:
79
80 EIGEN_STRONG_INLINE InnerIterator(const binary_evaluator& aEval, Index outer)
81 : m_lhsIter(aEval.m_lhsImpl,outer), m_rhsIter(aEval.m_rhsImpl,outer), m_functor(aEval.m_functor)
82 {
83 this->operator++();
84 }
85
86 EIGEN_STRONG_INLINE InnerIterator& operator++()
87 {
88 if (m_lhsIter && m_rhsIter && (m_lhsIter.index() == m_rhsIter.index()))
89 {
90 m_id = m_lhsIter.index();
91 m_value = m_functor(m_lhsIter.value(), m_rhsIter.value());
92 ++m_lhsIter;
93 ++m_rhsIter;
94 }
95 else if (m_lhsIter && (!m_rhsIter || (m_lhsIter.index() < m_rhsIter.index())))
96 {
97 m_id = m_lhsIter.index();
98 m_value = m_functor(m_lhsIter.value(), Scalar(0));
99 ++m_lhsIter;
100 }
101 else if (m_rhsIter && (!m_lhsIter || (m_lhsIter.index() > m_rhsIter.index())))
102 {
103 m_id = m_rhsIter.index();
104 m_value = m_functor(Scalar(0), m_rhsIter.value());
105 ++m_rhsIter;
106 }
107 else
108 {
109 m_value = 0; // this is to avoid a compilation warning
110 m_id = -1;
111 }
112 return *this;
113 }
114
115 EIGEN_STRONG_INLINE Scalar value() const { return m_value; }
116
117 EIGEN_STRONG_INLINE StorageIndex index() const { return m_id; }
118 EIGEN_STRONG_INLINE Index row() const { return Lhs::IsRowMajor ? m_lhsIter.row() : index(); }
119 EIGEN_STRONG_INLINE Index col() const { return Lhs::IsRowMajor ? index() : m_lhsIter.col(); }
120
121 EIGEN_STRONG_INLINE operator bool() const { return m_id>=0; }
122
123 protected:
124 LhsIterator m_lhsIter;
125 RhsIterator m_rhsIter;
126 const BinaryOp& m_functor;
127 Scalar m_value;
128 StorageIndex m_id;
129 };
130
131
132 enum {
134 Flags = XprType::Flags
135 };
136
137 explicit binary_evaluator(const XprType& xpr)
138 : m_functor(xpr.functor()),
139 m_lhsImpl(xpr.lhs()),
140 m_rhsImpl(xpr.rhs())
141 {
142 EIGEN_INTERNAL_CHECK_COST_VALUE(functor_traits<BinaryOp>::Cost);
143 EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
144 }
145
146 inline Index nonZerosEstimate() const {
147 return m_lhsImpl.nonZerosEstimate() + m_rhsImpl.nonZerosEstimate();
148 }
149
150protected:
151 const BinaryOp m_functor;
152 evaluator<Lhs> m_lhsImpl;
153 evaluator<Rhs> m_rhsImpl;
154};
155
156// "sparse .* sparse"
157template<typename T, typename Lhs, typename Rhs>
159 : evaluator_base<CwiseBinaryOp<scalar_product_op<T>, Lhs, Rhs> >
160{
161protected:
166 typedef typename XprType::StorageIndex StorageIndex;
167 typedef typename traits<XprType>::Scalar Scalar;
168public:
169
170 class ReverseInnerIterator;
172 {
173 public:
174
175 EIGEN_STRONG_INLINE InnerIterator(const binary_evaluator& aEval, Index outer)
176 : m_lhsIter(aEval.m_lhsImpl,outer), m_rhsIter(aEval.m_rhsImpl,outer), m_functor(aEval.m_functor)
177 {
178 while (m_lhsIter && m_rhsIter && (m_lhsIter.index() != m_rhsIter.index()))
179 {
180 if (m_lhsIter.index() < m_rhsIter.index())
181 ++m_lhsIter;
182 else
183 ++m_rhsIter;
184 }
185 }
186
187 EIGEN_STRONG_INLINE InnerIterator& operator++()
188 {
189 ++m_lhsIter;
190 ++m_rhsIter;
191 while (m_lhsIter && m_rhsIter && (m_lhsIter.index() != m_rhsIter.index()))
192 {
193 if (m_lhsIter.index() < m_rhsIter.index())
194 ++m_lhsIter;
195 else
196 ++m_rhsIter;
197 }
198 return *this;
199 }
200
201 EIGEN_STRONG_INLINE Scalar value() const { return m_functor(m_lhsIter.value(), m_rhsIter.value()); }
202
203 EIGEN_STRONG_INLINE StorageIndex index() const { return m_lhsIter.index(); }
204 EIGEN_STRONG_INLINE Index row() const { return m_lhsIter.row(); }
205 EIGEN_STRONG_INLINE Index col() const { return m_lhsIter.col(); }
206
207 EIGEN_STRONG_INLINE operator bool() const { return (m_lhsIter && m_rhsIter); }
208
209 protected:
210 LhsIterator m_lhsIter;
211 RhsIterator m_rhsIter;
212 const BinaryOp& m_functor;
213 };
214
215
216 enum {
218 Flags = XprType::Flags
219 };
220
221 explicit binary_evaluator(const XprType& xpr)
222 : m_functor(xpr.functor()),
223 m_lhsImpl(xpr.lhs()),
224 m_rhsImpl(xpr.rhs())
225 {
226 EIGEN_INTERNAL_CHECK_COST_VALUE(functor_traits<BinaryOp>::Cost);
227 EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
228 }
229
230 inline Index nonZerosEstimate() const {
231 return (std::min)(m_lhsImpl.nonZerosEstimate(), m_rhsImpl.nonZerosEstimate());
232 }
233
234protected:
235 const BinaryOp m_functor;
236 evaluator<Lhs> m_lhsImpl;
237 evaluator<Rhs> m_rhsImpl;
238};
239
240// "dense .* sparse"
241template<typename T, typename Lhs, typename Rhs>
243 : evaluator_base<CwiseBinaryOp<scalar_product_op<T>, Lhs, Rhs> >
244{
245protected:
250 typedef typename XprType::StorageIndex StorageIndex;
251 typedef typename traits<XprType>::Scalar Scalar;
252public:
253
254 class ReverseInnerIterator;
256 {
257 enum { IsRowMajor = (int(Rhs::Flags)&RowMajorBit)==RowMajorBit };
258
259 public:
260
261 EIGEN_STRONG_INLINE InnerIterator(const binary_evaluator& aEval, Index outer)
262 : m_lhsEval(aEval.m_lhsImpl), m_rhsIter(aEval.m_rhsImpl,outer), m_functor(aEval.m_functor), m_outer(outer)
263 {}
264
265 EIGEN_STRONG_INLINE InnerIterator& operator++()
266 {
267 ++m_rhsIter;
268 return *this;
269 }
270
271 EIGEN_STRONG_INLINE Scalar value() const
272 { return m_functor(m_lhsEval.coeff(IsRowMajor?m_outer:m_rhsIter.index(),IsRowMajor?m_rhsIter.index():m_outer), m_rhsIter.value()); }
273
274 EIGEN_STRONG_INLINE StorageIndex index() const { return m_rhsIter.index(); }
275 EIGEN_STRONG_INLINE Index row() const { return m_rhsIter.row(); }
276 EIGEN_STRONG_INLINE Index col() const { return m_rhsIter.col(); }
277
278 EIGEN_STRONG_INLINE operator bool() const { return m_rhsIter; }
279
280 protected:
281 const LhsEvaluator &m_lhsEval;
282 RhsIterator m_rhsIter;
283 const BinaryOp& m_functor;
284 const Index m_outer;
285 };
286
287
288 enum {
290 Flags = XprType::Flags
291 };
292
293 explicit binary_evaluator(const XprType& xpr)
294 : m_functor(xpr.functor()),
295 m_lhsImpl(xpr.lhs()),
296 m_rhsImpl(xpr.rhs())
297 {
298 EIGEN_INTERNAL_CHECK_COST_VALUE(functor_traits<BinaryOp>::Cost);
299 EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
300 }
301
302 inline Index nonZerosEstimate() const {
303 return m_rhsImpl.nonZerosEstimate();
304 }
305
306protected:
307 const BinaryOp m_functor;
308 evaluator<Lhs> m_lhsImpl;
309 evaluator<Rhs> m_rhsImpl;
310};
311
312// "sparse .* dense"
313template<typename T, typename Lhs, typename Rhs>
315 : evaluator_base<CwiseBinaryOp<scalar_product_op<T>, Lhs, Rhs> >
316{
317protected:
322 typedef typename XprType::StorageIndex StorageIndex;
323 typedef typename traits<XprType>::Scalar Scalar;
324public:
325
326 class ReverseInnerIterator;
328 {
329 enum { IsRowMajor = (int(Lhs::Flags)&RowMajorBit)==RowMajorBit };
330
331 public:
332
333 EIGEN_STRONG_INLINE InnerIterator(const binary_evaluator& aEval, Index outer)
334 : m_lhsIter(aEval.m_lhsImpl,outer), m_rhsEval(aEval.m_rhsImpl), m_functor(aEval.m_functor), m_outer(outer)
335 {}
336
337 EIGEN_STRONG_INLINE InnerIterator& operator++()
338 {
339 ++m_lhsIter;
340 return *this;
341 }
342
343 EIGEN_STRONG_INLINE Scalar value() const
344 { return m_functor(m_lhsIter.value(),
345 m_rhsEval.coeff(IsRowMajor?m_outer:m_lhsIter.index(),IsRowMajor?m_lhsIter.index():m_outer)); }
346
347 EIGEN_STRONG_INLINE StorageIndex index() const { return m_lhsIter.index(); }
348 EIGEN_STRONG_INLINE Index row() const { return m_lhsIter.row(); }
349 EIGEN_STRONG_INLINE Index col() const { return m_lhsIter.col(); }
350
351 EIGEN_STRONG_INLINE operator bool() const { return m_lhsIter; }
352
353 protected:
354 LhsIterator m_lhsIter;
355 const evaluator<Rhs> &m_rhsEval;
356 const BinaryOp& m_functor;
357 const Index m_outer;
358 };
359
360
361 enum {
363 Flags = XprType::Flags
364 };
365
366 explicit binary_evaluator(const XprType& xpr)
367 : m_functor(xpr.functor()),
368 m_lhsImpl(xpr.lhs()),
369 m_rhsImpl(xpr.rhs())
370 {
371 EIGEN_INTERNAL_CHECK_COST_VALUE(functor_traits<BinaryOp>::Cost);
372 EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
373 }
374
375 inline Index nonZerosEstimate() const {
376 return m_lhsImpl.nonZerosEstimate();
377 }
378
379protected:
380 const BinaryOp m_functor;
381 evaluator<Lhs> m_lhsImpl;
382 evaluator<Rhs> m_rhsImpl;
383};
384
385}
386
387/***************************************************************************
388* Implementation of SparseMatrixBase and SparseCwise functions/operators
389***************************************************************************/
390
391template<typename Derived>
392template<typename OtherDerived>
393EIGEN_STRONG_INLINE Derived &
394SparseMatrixBase<Derived>::operator-=(const SparseMatrixBase<OtherDerived> &other)
395{
396 return derived() = derived() - other.derived();
397}
398
399template<typename Derived>
400template<typename OtherDerived>
401EIGEN_STRONG_INLINE Derived &
402SparseMatrixBase<Derived>::operator+=(const SparseMatrixBase<OtherDerived>& other)
403{
404 return derived() = derived() + other.derived();
405}
406
407template<typename Derived>
408template<typename OtherDerived>
409Derived& SparseMatrixBase<Derived>::operator+=(const DiagonalBase<OtherDerived>& other)
410{
411 call_assignment_no_alias(derived(), other.derived(), internal::add_assign_op<Scalar>());
412 return derived();
413}
414
415template<typename Derived>
416template<typename OtherDerived>
417Derived& SparseMatrixBase<Derived>::operator-=(const DiagonalBase<OtherDerived>& other)
418{
419 call_assignment_no_alias(derived(), other.derived(), internal::sub_assign_op<Scalar>());
420 return derived();
421}
422
423template<typename Derived>
424template<typename OtherDerived>
425EIGEN_STRONG_INLINE const typename SparseMatrixBase<Derived>::template CwiseProductDenseReturnType<OtherDerived>::Type
426SparseMatrixBase<Derived>::cwiseProduct(const MatrixBase<OtherDerived> &other) const
427{
428 return typename CwiseProductDenseReturnType<OtherDerived>::Type(derived(), other.derived());
429}
430
431} // end namespace Eigen
432
433#endif // EIGEN_SPARSE_CWISE_BINARY_OP_H
Definition CwiseBinaryOp.h:150
Generic expression where a coefficient-wise binary operator is applied to two expressions.
Definition CwiseBinaryOp.h:85
An InnerIterator allows to loop over the element of any matrix expression.
Definition CoreIterators.h:34
EIGEN_STRONG_INLINE Index index() const
Definition CoreIterators.h:52
Pseudo expression representing a solving operation.
Definition Solve.h:63
Base class of any sparse matrices or sparse expressions.
Definition SparseMatrixBase.h:34
const unsigned int RowMajorBit
for a matrix, this means that the storage order is row-major.
Definition Constants.h:61
The type used to identify a general sparse storage.
Definition Constants.h:493
Definition Constants.h:525
Definition Constants.h:528
Definition CoreEvaluators.h:52
Definition CoreEvaluators.h:101
Definition CoreEvaluators.h:82
Definition XprHelper.h:107
Definition Meta.h:39
Definition BinaryFunctors.h:59
Definition ForwardDeclarations.h:17