Eigen  3.4.90 (git rev a4098ac676528a83cfb73d4d26ce1b42ec05f47c)
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
13#include "./InternalHeaderCheck.h"
14
15namespace Eigen {
16
17// Here we have to handle 3 cases:
18// 1 - sparse op dense
19// 2 - dense op sparse
20// 3 - sparse op sparse
21// We also need to implement a 4th iterator for:
22// 4 - dense op dense
23// Finally, we also need to distinguish between the product and other operations :
24// configuration returned mode
25// 1 - sparse op dense product sparse
26// generic dense
27// 2 - dense op sparse product sparse
28// generic dense
29// 3 - sparse op sparse product sparse
30// generic sparse
31// 4 - dense op dense product dense
32// generic dense
33//
34// TODO to ease compiler job, we could specialize product/quotient with a scalar
35// and fallback to cwise-unary evaluator using bind1st_op and bind2nd_op.
36
37template<typename BinaryOp, typename Lhs, typename Rhs>
38class CwiseBinaryOpImpl<BinaryOp, Lhs, Rhs, Sparse>
39 : public SparseMatrixBase<CwiseBinaryOp<BinaryOp, Lhs, Rhs> >
40{
41 public:
42 typedef CwiseBinaryOp<BinaryOp, Lhs, Rhs> Derived;
43 typedef SparseMatrixBase<Derived> Base;
44 EIGEN_SPARSE_PUBLIC_INTERFACE(Derived)
45 EIGEN_STATIC_ASSERT((
46 (!internal::is_same<typename internal::traits<Lhs>::StorageKind,
47 typename internal::traits<Rhs>::StorageKind>::value)
48 || ((internal::evaluator<Lhs>::Flags&RowMajorBit) == (internal::evaluator<Rhs>::Flags&RowMajorBit))),
49 THE_STORAGE_ORDER_OF_BOTH_SIDES_MUST_MATCH)
50};
51
52namespace internal {
53
54
55// Generic "sparse OP sparse"
56template<typename XprType> struct binary_sparse_evaluator;
57
58template<typename BinaryOp, typename Lhs, typename Rhs>
59struct binary_evaluator<CwiseBinaryOp<BinaryOp, Lhs, Rhs>, IteratorBased, IteratorBased>
60 : evaluator_base<CwiseBinaryOp<BinaryOp, Lhs, Rhs> >
61{
62protected:
63 typedef typename evaluator<Lhs>::InnerIterator LhsIterator;
64 typedef typename evaluator<Rhs>::InnerIterator RhsIterator;
65 typedef CwiseBinaryOp<BinaryOp, Lhs, Rhs> XprType;
66 typedef typename traits<XprType>::Scalar Scalar;
67 typedef typename XprType::StorageIndex StorageIndex;
68public:
69
70 class InnerIterator
71 {
72 public:
73
74 EIGEN_STRONG_INLINE InnerIterator(const binary_evaluator& aEval, Index outer)
75 : m_lhsIter(aEval.m_lhsImpl,outer), m_rhsIter(aEval.m_rhsImpl,outer), m_functor(aEval.m_functor)
76 {
77 this->operator++();
78 }
79
80 EIGEN_STRONG_INLINE InnerIterator& operator++()
81 {
82 if (m_lhsIter && m_rhsIter && (m_lhsIter.index() == m_rhsIter.index()))
83 {
84 m_id = m_lhsIter.index();
85 m_value = m_functor(m_lhsIter.value(), m_rhsIter.value());
86 ++m_lhsIter;
87 ++m_rhsIter;
88 }
89 else if (m_lhsIter && (!m_rhsIter || (m_lhsIter.index() < m_rhsIter.index())))
90 {
91 m_id = m_lhsIter.index();
92 m_value = m_functor(m_lhsIter.value(), Scalar(0));
93 ++m_lhsIter;
94 }
95 else if (m_rhsIter && (!m_lhsIter || (m_lhsIter.index() > m_rhsIter.index())))
96 {
97 m_id = m_rhsIter.index();
98 m_value = m_functor(Scalar(0), m_rhsIter.value());
99 ++m_rhsIter;
100 }
101 else
102 {
103 m_value = Scalar(0); // this is to avoid a compilation warning
104 m_id = -1;
105 }
106 return *this;
107 }
108
109 EIGEN_STRONG_INLINE Scalar value() const { return m_value; }
110
111 EIGEN_STRONG_INLINE StorageIndex index() const { return m_id; }
112 EIGEN_STRONG_INLINE Index outer() const { return m_lhsIter.outer(); }
113 EIGEN_STRONG_INLINE Index row() const { return Lhs::IsRowMajor ? m_lhsIter.row() : index(); }
114 EIGEN_STRONG_INLINE Index col() const { return Lhs::IsRowMajor ? index() : m_lhsIter.col(); }
115
116 EIGEN_STRONG_INLINE operator bool() const { return m_id>=0; }
117
118 protected:
119 LhsIterator m_lhsIter;
120 RhsIterator m_rhsIter;
121 const BinaryOp& m_functor;
122 Scalar m_value;
123 StorageIndex m_id;
124 };
125
126
127 enum {
128 CoeffReadCost = int(evaluator<Lhs>::CoeffReadCost) + int(evaluator<Rhs>::CoeffReadCost) + int(functor_traits<BinaryOp>::Cost),
129 Flags = XprType::Flags
130 };
131
132 explicit binary_evaluator(const XprType& xpr)
133 : m_functor(xpr.functor()),
134 m_lhsImpl(xpr.lhs()),
135 m_rhsImpl(xpr.rhs())
136 {
137 EIGEN_INTERNAL_CHECK_COST_VALUE(functor_traits<BinaryOp>::Cost);
138 EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
139 }
140
141 inline Index nonZerosEstimate() const {
142 return m_lhsImpl.nonZerosEstimate() + m_rhsImpl.nonZerosEstimate();
143 }
144
145protected:
146 const BinaryOp m_functor;
147 evaluator<Lhs> m_lhsImpl;
148 evaluator<Rhs> m_rhsImpl;
149};
150
151// dense op sparse
152template<typename BinaryOp, typename Lhs, typename Rhs>
153struct binary_evaluator<CwiseBinaryOp<BinaryOp, Lhs, Rhs>, IndexBased, IteratorBased>
154 : evaluator_base<CwiseBinaryOp<BinaryOp, Lhs, Rhs> >
155{
156protected:
157 typedef typename evaluator<Rhs>::InnerIterator RhsIterator;
158 typedef CwiseBinaryOp<BinaryOp, Lhs, Rhs> XprType;
159 typedef typename traits<XprType>::Scalar Scalar;
160 typedef typename XprType::StorageIndex StorageIndex;
161public:
162
163 class InnerIterator
164 {
165 enum { IsRowMajor = (int(Rhs::Flags)&RowMajorBit)==RowMajorBit };
166 public:
167
168 EIGEN_STRONG_INLINE InnerIterator(const binary_evaluator& aEval, Index outer)
169 : m_lhsEval(aEval.m_lhsImpl), m_rhsIter(aEval.m_rhsImpl,outer), m_functor(aEval.m_functor), m_value(0), m_id(-1), m_innerSize(aEval.m_expr.rhs().innerSize())
170 {
171 this->operator++();
172 }
173
174 EIGEN_STRONG_INLINE InnerIterator& operator++()
175 {
176 ++m_id;
177 if(m_id<m_innerSize)
178 {
179 Scalar lhsVal = m_lhsEval.coeff(IsRowMajor?m_rhsIter.outer():m_id,
180 IsRowMajor?m_id:m_rhsIter.outer());
181 if(m_rhsIter && m_rhsIter.index()==m_id)
182 {
183 m_value = m_functor(lhsVal, m_rhsIter.value());
184 ++m_rhsIter;
185 }
186 else
187 m_value = m_functor(lhsVal, Scalar(0));
188 }
189
190 return *this;
191 }
192
193 EIGEN_STRONG_INLINE Scalar value() const { eigen_internal_assert(m_id<m_innerSize); return m_value; }
194
195 EIGEN_STRONG_INLINE StorageIndex index() const { return m_id; }
196 EIGEN_STRONG_INLINE Index outer() const { return m_rhsIter.outer(); }
197 EIGEN_STRONG_INLINE Index row() const { return IsRowMajor ? m_rhsIter.outer() : m_id; }
198 EIGEN_STRONG_INLINE Index col() const { return IsRowMajor ? m_id : m_rhsIter.outer(); }
199
200 EIGEN_STRONG_INLINE operator bool() const { return m_id<m_innerSize; }
201
202 protected:
203 const evaluator<Lhs> &m_lhsEval;
204 RhsIterator m_rhsIter;
205 const BinaryOp& m_functor;
206 Scalar m_value;
207 StorageIndex m_id;
208 StorageIndex m_innerSize;
209 };
210
211
212 enum {
213 CoeffReadCost = int(evaluator<Lhs>::CoeffReadCost) + int(evaluator<Rhs>::CoeffReadCost) + int(functor_traits<BinaryOp>::Cost),
214 Flags = XprType::Flags
215 };
216
217 explicit binary_evaluator(const XprType& xpr)
218 : m_functor(xpr.functor()),
219 m_lhsImpl(xpr.lhs()),
220 m_rhsImpl(xpr.rhs()),
221 m_expr(xpr)
222 {
223 EIGEN_INTERNAL_CHECK_COST_VALUE(functor_traits<BinaryOp>::Cost);
224 EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
225 }
226
227 inline Index nonZerosEstimate() const {
228 return m_expr.size();
229 }
230
231protected:
232 const BinaryOp m_functor;
233 evaluator<Lhs> m_lhsImpl;
234 evaluator<Rhs> m_rhsImpl;
235 const XprType &m_expr;
236};
237
238// sparse op dense
239template<typename BinaryOp, typename Lhs, typename Rhs>
240struct binary_evaluator<CwiseBinaryOp<BinaryOp, Lhs, Rhs>, IteratorBased, IndexBased>
241 : evaluator_base<CwiseBinaryOp<BinaryOp, Lhs, Rhs> >
242{
243protected:
244 typedef typename evaluator<Lhs>::InnerIterator LhsIterator;
245 typedef CwiseBinaryOp<BinaryOp, Lhs, Rhs> XprType;
246 typedef typename traits<XprType>::Scalar Scalar;
247 typedef typename XprType::StorageIndex StorageIndex;
248public:
249
250 class InnerIterator
251 {
252 enum { IsRowMajor = (int(Lhs::Flags)&RowMajorBit)==RowMajorBit };
253 public:
254
255 EIGEN_STRONG_INLINE InnerIterator(const binary_evaluator& aEval, Index outer)
256 : m_lhsIter(aEval.m_lhsImpl,outer), m_rhsEval(aEval.m_rhsImpl), m_functor(aEval.m_functor), m_value(0), m_id(-1), m_innerSize(aEval.m_expr.lhs().innerSize())
257 {
258 this->operator++();
259 }
260
261 EIGEN_STRONG_INLINE InnerIterator& operator++()
262 {
263 ++m_id;
264 if(m_id<m_innerSize)
265 {
266 Scalar rhsVal = m_rhsEval.coeff(IsRowMajor?m_lhsIter.outer():m_id,
267 IsRowMajor?m_id:m_lhsIter.outer());
268 if(m_lhsIter && m_lhsIter.index()==m_id)
269 {
270 m_value = m_functor(m_lhsIter.value(), rhsVal);
271 ++m_lhsIter;
272 }
273 else
274 m_value = m_functor(Scalar(0),rhsVal);
275 }
276
277 return *this;
278 }
279
280 EIGEN_STRONG_INLINE Scalar value() const { eigen_internal_assert(m_id<m_innerSize); return m_value; }
281
282 EIGEN_STRONG_INLINE StorageIndex index() const { return m_id; }
283 EIGEN_STRONG_INLINE Index outer() const { return m_lhsIter.outer(); }
284 EIGEN_STRONG_INLINE Index row() const { return IsRowMajor ? m_lhsIter.outer() : m_id; }
285 EIGEN_STRONG_INLINE Index col() const { return IsRowMajor ? m_id : m_lhsIter.outer(); }
286
287 EIGEN_STRONG_INLINE operator bool() const { return m_id<m_innerSize; }
288
289 protected:
290 LhsIterator m_lhsIter;
291 const evaluator<Rhs> &m_rhsEval;
292 const BinaryOp& m_functor;
293 Scalar m_value;
294 StorageIndex m_id;
295 StorageIndex m_innerSize;
296 };
297
298
299 enum {
300 CoeffReadCost = int(evaluator<Lhs>::CoeffReadCost) + int(evaluator<Rhs>::CoeffReadCost) + int(functor_traits<BinaryOp>::Cost),
301 Flags = XprType::Flags
302 };
303
304 explicit binary_evaluator(const XprType& xpr)
305 : m_functor(xpr.functor()),
306 m_lhsImpl(xpr.lhs()),
307 m_rhsImpl(xpr.rhs()),
308 m_expr(xpr)
309 {
310 EIGEN_INTERNAL_CHECK_COST_VALUE(functor_traits<BinaryOp>::Cost);
311 EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
312 }
313
314 inline Index nonZerosEstimate() const {
315 return m_expr.size();
316 }
317
318protected:
319 const BinaryOp m_functor;
320 evaluator<Lhs> m_lhsImpl;
321 evaluator<Rhs> m_rhsImpl;
322 const XprType &m_expr;
323};
324
325template<typename T,
326 typename LhsKind = typename evaluator_traits<typename T::Lhs>::Kind,
327 typename RhsKind = typename evaluator_traits<typename T::Rhs>::Kind,
328 typename LhsScalar = typename traits<typename T::Lhs>::Scalar,
329 typename RhsScalar = typename traits<typename T::Rhs>::Scalar> struct sparse_conjunction_evaluator;
330
331// "sparse .* sparse"
332template<typename T1, typename T2, typename Lhs, typename Rhs>
333struct binary_evaluator<CwiseBinaryOp<scalar_product_op<T1,T2>, Lhs, Rhs>, IteratorBased, IteratorBased>
334 : sparse_conjunction_evaluator<CwiseBinaryOp<scalar_product_op<T1,T2>, Lhs, Rhs> >
335{
336 typedef CwiseBinaryOp<scalar_product_op<T1,T2>, Lhs, Rhs> XprType;
337 typedef sparse_conjunction_evaluator<XprType> Base;
338 explicit binary_evaluator(const XprType& xpr) : Base(xpr) {}
339};
340// "dense .* sparse"
341template<typename T1, typename T2, typename Lhs, typename Rhs>
342struct binary_evaluator<CwiseBinaryOp<scalar_product_op<T1,T2>, Lhs, Rhs>, IndexBased, IteratorBased>
343 : sparse_conjunction_evaluator<CwiseBinaryOp<scalar_product_op<T1,T2>, Lhs, Rhs> >
344{
345 typedef CwiseBinaryOp<scalar_product_op<T1,T2>, Lhs, Rhs> XprType;
346 typedef sparse_conjunction_evaluator<XprType> Base;
347 explicit binary_evaluator(const XprType& xpr) : Base(xpr) {}
348};
349// "sparse .* dense"
350template<typename T1, typename T2, typename Lhs, typename Rhs>
351struct binary_evaluator<CwiseBinaryOp<scalar_product_op<T1,T2>, Lhs, Rhs>, IteratorBased, IndexBased>
352 : sparse_conjunction_evaluator<CwiseBinaryOp<scalar_product_op<T1,T2>, Lhs, Rhs> >
353{
354 typedef CwiseBinaryOp<scalar_product_op<T1,T2>, Lhs, Rhs> XprType;
355 typedef sparse_conjunction_evaluator<XprType> Base;
356 explicit binary_evaluator(const XprType& xpr) : Base(xpr) {}
357};
358
359// "sparse ./ dense"
360template<typename T1, typename T2, typename Lhs, typename Rhs>
361struct binary_evaluator<CwiseBinaryOp<scalar_quotient_op<T1,T2>, Lhs, Rhs>, IteratorBased, IndexBased>
362 : sparse_conjunction_evaluator<CwiseBinaryOp<scalar_quotient_op<T1,T2>, Lhs, Rhs> >
363{
364 typedef CwiseBinaryOp<scalar_quotient_op<T1,T2>, Lhs, Rhs> XprType;
365 typedef sparse_conjunction_evaluator<XprType> Base;
366 explicit binary_evaluator(const XprType& xpr) : Base(xpr) {}
367};
368
369// "sparse && sparse"
370template<typename Lhs, typename Rhs>
371struct binary_evaluator<CwiseBinaryOp<scalar_boolean_and_op, Lhs, Rhs>, IteratorBased, IteratorBased>
372 : sparse_conjunction_evaluator<CwiseBinaryOp<scalar_boolean_and_op, Lhs, Rhs> >
373{
374 typedef CwiseBinaryOp<scalar_boolean_and_op, Lhs, Rhs> XprType;
375 typedef sparse_conjunction_evaluator<XprType> Base;
376 explicit binary_evaluator(const XprType& xpr) : Base(xpr) {}
377};
378// "dense && sparse"
379template<typename Lhs, typename Rhs>
380struct binary_evaluator<CwiseBinaryOp<scalar_boolean_and_op, Lhs, Rhs>, IndexBased, IteratorBased>
381 : sparse_conjunction_evaluator<CwiseBinaryOp<scalar_boolean_and_op, Lhs, Rhs> >
382{
383 typedef CwiseBinaryOp<scalar_boolean_and_op, Lhs, Rhs> XprType;
384 typedef sparse_conjunction_evaluator<XprType> Base;
385 explicit binary_evaluator(const XprType& xpr) : Base(xpr) {}
386};
387// "sparse && dense"
388template<typename Lhs, typename Rhs>
389struct binary_evaluator<CwiseBinaryOp<scalar_boolean_and_op, Lhs, Rhs>, IteratorBased, IndexBased>
390 : sparse_conjunction_evaluator<CwiseBinaryOp<scalar_boolean_and_op, Lhs, Rhs> >
391{
392 typedef CwiseBinaryOp<scalar_boolean_and_op, Lhs, Rhs> XprType;
393 typedef sparse_conjunction_evaluator<XprType> Base;
394 explicit binary_evaluator(const XprType& xpr) : Base(xpr) {}
395};
396
397// "sparse ^ sparse"
398template<typename XprType>
399struct sparse_conjunction_evaluator<XprType, IteratorBased, IteratorBased>
400 : evaluator_base<XprType>
401{
402protected:
403 typedef typename XprType::Functor BinaryOp;
404 typedef typename XprType::Lhs LhsArg;
405 typedef typename XprType::Rhs RhsArg;
406 typedef typename evaluator<LhsArg>::InnerIterator LhsIterator;
407 typedef typename evaluator<RhsArg>::InnerIterator RhsIterator;
408 typedef typename XprType::StorageIndex StorageIndex;
409 typedef typename traits<XprType>::Scalar Scalar;
410public:
411
412 class InnerIterator
413 {
414 public:
415
416 EIGEN_STRONG_INLINE InnerIterator(const sparse_conjunction_evaluator& aEval, Index outer)
417 : m_lhsIter(aEval.m_lhsImpl,outer), m_rhsIter(aEval.m_rhsImpl,outer), m_functor(aEval.m_functor)
418 {
419 while (m_lhsIter && m_rhsIter && (m_lhsIter.index() != m_rhsIter.index()))
420 {
421 if (m_lhsIter.index() < m_rhsIter.index())
422 ++m_lhsIter;
423 else
424 ++m_rhsIter;
425 }
426 }
427
428 EIGEN_STRONG_INLINE InnerIterator& operator++()
429 {
430 ++m_lhsIter;
431 ++m_rhsIter;
432 while (m_lhsIter && m_rhsIter && (m_lhsIter.index() != m_rhsIter.index()))
433 {
434 if (m_lhsIter.index() < m_rhsIter.index())
435 ++m_lhsIter;
436 else
437 ++m_rhsIter;
438 }
439 return *this;
440 }
441
442 EIGEN_STRONG_INLINE Scalar value() const { return m_functor(m_lhsIter.value(), m_rhsIter.value()); }
443
444 EIGEN_STRONG_INLINE StorageIndex index() const { return m_lhsIter.index(); }
445 EIGEN_STRONG_INLINE Index outer() const { return m_lhsIter.outer(); }
446 EIGEN_STRONG_INLINE Index row() const { return m_lhsIter.row(); }
447 EIGEN_STRONG_INLINE Index col() const { return m_lhsIter.col(); }
448
449 EIGEN_STRONG_INLINE operator bool() const { return (m_lhsIter && m_rhsIter); }
450
451 protected:
452 LhsIterator m_lhsIter;
453 RhsIterator m_rhsIter;
454 const BinaryOp& m_functor;
455 };
456
457
458 enum {
459 CoeffReadCost = int(evaluator<LhsArg>::CoeffReadCost) + int(evaluator<RhsArg>::CoeffReadCost) + int(functor_traits<BinaryOp>::Cost),
460 Flags = XprType::Flags
461 };
462
463 explicit sparse_conjunction_evaluator(const XprType& xpr)
464 : m_functor(xpr.functor()),
465 m_lhsImpl(xpr.lhs()),
466 m_rhsImpl(xpr.rhs())
467 {
468 EIGEN_INTERNAL_CHECK_COST_VALUE(functor_traits<BinaryOp>::Cost);
469 EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
470 }
471
472 inline Index nonZerosEstimate() const {
473 return (std::min)(m_lhsImpl.nonZerosEstimate(), m_rhsImpl.nonZerosEstimate());
474 }
475
476protected:
477 const BinaryOp m_functor;
478 evaluator<LhsArg> m_lhsImpl;
479 evaluator<RhsArg> m_rhsImpl;
480};
481
482// "dense ^ sparse"
483template<typename XprType>
484struct sparse_conjunction_evaluator<XprType, IndexBased, IteratorBased>
485 : evaluator_base<XprType>
486{
487protected:
488 typedef typename XprType::Functor BinaryOp;
489 typedef typename XprType::Lhs LhsArg;
490 typedef typename XprType::Rhs RhsArg;
491 typedef evaluator<LhsArg> LhsEvaluator;
492 typedef typename evaluator<RhsArg>::InnerIterator RhsIterator;
493 typedef typename XprType::StorageIndex StorageIndex;
494 typedef typename traits<XprType>::Scalar Scalar;
495public:
496
497 class InnerIterator
498 {
499 enum { IsRowMajor = (int(RhsArg::Flags)&RowMajorBit)==RowMajorBit };
500
501 public:
502
503 EIGEN_STRONG_INLINE InnerIterator(const sparse_conjunction_evaluator& aEval, Index outer)
504 : m_lhsEval(aEval.m_lhsImpl), m_rhsIter(aEval.m_rhsImpl,outer), m_functor(aEval.m_functor), m_outer(outer)
505 {}
506
507 EIGEN_STRONG_INLINE InnerIterator& operator++()
508 {
509 ++m_rhsIter;
510 return *this;
511 }
512
513 EIGEN_STRONG_INLINE Scalar value() const
514 { return m_functor(m_lhsEval.coeff(IsRowMajor?m_outer:m_rhsIter.index(),IsRowMajor?m_rhsIter.index():m_outer), m_rhsIter.value()); }
515
516 EIGEN_STRONG_INLINE StorageIndex index() const { return m_rhsIter.index(); }
517 EIGEN_STRONG_INLINE Index outer() const { return m_rhsIter.outer(); }
518 EIGEN_STRONG_INLINE Index row() const { return m_rhsIter.row(); }
519 EIGEN_STRONG_INLINE Index col() const { return m_rhsIter.col(); }
520
521 EIGEN_STRONG_INLINE operator bool() const { return m_rhsIter; }
522
523 protected:
524 const LhsEvaluator &m_lhsEval;
525 RhsIterator m_rhsIter;
526 const BinaryOp& m_functor;
527 const Index m_outer;
528 };
529
530
531 enum {
532 CoeffReadCost = int(evaluator<LhsArg>::CoeffReadCost) + int(evaluator<RhsArg>::CoeffReadCost) + int(functor_traits<BinaryOp>::Cost),
533 Flags = XprType::Flags
534 };
535
536 explicit sparse_conjunction_evaluator(const XprType& xpr)
537 : m_functor(xpr.functor()),
538 m_lhsImpl(xpr.lhs()),
539 m_rhsImpl(xpr.rhs())
540 {
541 EIGEN_INTERNAL_CHECK_COST_VALUE(functor_traits<BinaryOp>::Cost);
542 EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
543 }
544
545 inline Index nonZerosEstimate() const {
546 return m_rhsImpl.nonZerosEstimate();
547 }
548
549protected:
550 const BinaryOp m_functor;
551 evaluator<LhsArg> m_lhsImpl;
552 evaluator<RhsArg> m_rhsImpl;
553};
554
555// "sparse ^ dense"
556template<typename XprType>
557struct sparse_conjunction_evaluator<XprType, IteratorBased, IndexBased>
558 : evaluator_base<XprType>
559{
560protected:
561 typedef typename XprType::Functor BinaryOp;
562 typedef typename XprType::Lhs LhsArg;
563 typedef typename XprType::Rhs RhsArg;
564 typedef typename evaluator<LhsArg>::InnerIterator LhsIterator;
565 typedef evaluator<RhsArg> RhsEvaluator;
566 typedef typename XprType::StorageIndex StorageIndex;
567 typedef typename traits<XprType>::Scalar Scalar;
568public:
569
570 class InnerIterator
571 {
572 enum { IsRowMajor = (int(LhsArg::Flags)&RowMajorBit)==RowMajorBit };
573
574 public:
575
576 EIGEN_STRONG_INLINE InnerIterator(const sparse_conjunction_evaluator& aEval, Index outer)
577 : m_lhsIter(aEval.m_lhsImpl,outer), m_rhsEval(aEval.m_rhsImpl), m_functor(aEval.m_functor), m_outer(outer)
578 {}
579
580 EIGEN_STRONG_INLINE InnerIterator& operator++()
581 {
582 ++m_lhsIter;
583 return *this;
584 }
585
586 EIGEN_STRONG_INLINE Scalar value() const
587 { return m_functor(m_lhsIter.value(),
588 m_rhsEval.coeff(IsRowMajor?m_outer:m_lhsIter.index(),IsRowMajor?m_lhsIter.index():m_outer)); }
589
590 EIGEN_STRONG_INLINE StorageIndex index() const { return m_lhsIter.index(); }
591 EIGEN_STRONG_INLINE Index outer() const { return m_lhsIter.outer(); }
592 EIGEN_STRONG_INLINE Index row() const { return m_lhsIter.row(); }
593 EIGEN_STRONG_INLINE Index col() const { return m_lhsIter.col(); }
594
595 EIGEN_STRONG_INLINE operator bool() const { return m_lhsIter; }
596
597 protected:
598 LhsIterator m_lhsIter;
599 const evaluator<RhsArg> &m_rhsEval;
600 const BinaryOp& m_functor;
601 const Index m_outer;
602 };
603
604
605 enum {
606 CoeffReadCost = int(evaluator<LhsArg>::CoeffReadCost) + int(evaluator<RhsArg>::CoeffReadCost) + int(functor_traits<BinaryOp>::Cost),
607 Flags = XprType::Flags
608 };
609
610 explicit sparse_conjunction_evaluator(const XprType& xpr)
611 : m_functor(xpr.functor()),
612 m_lhsImpl(xpr.lhs()),
613 m_rhsImpl(xpr.rhs())
614 {
615 EIGEN_INTERNAL_CHECK_COST_VALUE(functor_traits<BinaryOp>::Cost);
616 EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
617 }
618
619 inline Index nonZerosEstimate() const {
620 return m_lhsImpl.nonZerosEstimate();
621 }
622
623protected:
624 const BinaryOp m_functor;
625 evaluator<LhsArg> m_lhsImpl;
626 evaluator<RhsArg> m_rhsImpl;
627};
628
629}
630
631/***************************************************************************
632* Implementation of SparseMatrixBase and SparseCwise functions/operators
633***************************************************************************/
634
635template<typename Derived>
636template<typename OtherDerived>
637Derived& SparseMatrixBase<Derived>::operator+=(const EigenBase<OtherDerived> &other)
638{
639 call_assignment(derived(), other.derived(), internal::add_assign_op<Scalar,typename OtherDerived::Scalar>());
640 return derived();
641}
642
643template<typename Derived>
644template<typename OtherDerived>
645Derived& SparseMatrixBase<Derived>::operator-=(const EigenBase<OtherDerived> &other)
646{
647 call_assignment(derived(), other.derived(), internal::assign_op<Scalar,typename OtherDerived::Scalar>());
648 return derived();
649}
650
651template<typename Derived>
652template<typename OtherDerived>
653EIGEN_STRONG_INLINE Derived &
654SparseMatrixBase<Derived>::operator-=(const SparseMatrixBase<OtherDerived> &other)
655{
656 return derived() = derived() - other.derived();
657}
658
659template<typename Derived>
660template<typename OtherDerived>
661EIGEN_STRONG_INLINE Derived &
662SparseMatrixBase<Derived>::operator+=(const SparseMatrixBase<OtherDerived>& other)
663{
664 return derived() = derived() + other.derived();
665}
666
667template<typename Derived>
668template<typename OtherDerived>
669Derived& SparseMatrixBase<Derived>::operator+=(const DiagonalBase<OtherDerived>& other)
670{
671 call_assignment_no_alias(derived(), other.derived(), internal::add_assign_op<Scalar,typename OtherDerived::Scalar>());
672 return derived();
673}
674
675template<typename Derived>
676template<typename OtherDerived>
677Derived& SparseMatrixBase<Derived>::operator-=(const DiagonalBase<OtherDerived>& other)
678{
679 call_assignment_no_alias(derived(), other.derived(), internal::sub_assign_op<Scalar,typename OtherDerived::Scalar>());
680 return derived();
681}
682
683template<typename Derived>
684template<typename OtherDerived>
685EIGEN_STRONG_INLINE const typename SparseMatrixBase<Derived>::template CwiseProductDenseReturnType<OtherDerived>::Type
686SparseMatrixBase<Derived>::cwiseProduct(const MatrixBase<OtherDerived> &other) const
687{
688 return typename CwiseProductDenseReturnType<OtherDerived>::Type(derived(), other.derived());
689}
690
691template<typename DenseDerived, typename SparseDerived>
692EIGEN_STRONG_INLINE const CwiseBinaryOp<internal::scalar_sum_op<typename DenseDerived::Scalar,typename SparseDerived::Scalar>, const DenseDerived, const SparseDerived>
693operator+(const MatrixBase<DenseDerived> &a, const SparseMatrixBase<SparseDerived> &b)
694{
695 return CwiseBinaryOp<internal::scalar_sum_op<typename DenseDerived::Scalar,typename SparseDerived::Scalar>, const DenseDerived, const SparseDerived>(a.derived(), b.derived());
696}
697
698template<typename SparseDerived, typename DenseDerived>
699EIGEN_STRONG_INLINE const CwiseBinaryOp<internal::scalar_sum_op<typename SparseDerived::Scalar,typename DenseDerived::Scalar>, const SparseDerived, const DenseDerived>
700operator+(const SparseMatrixBase<SparseDerived> &a, const MatrixBase<DenseDerived> &b)
701{
702 return CwiseBinaryOp<internal::scalar_sum_op<typename SparseDerived::Scalar,typename DenseDerived::Scalar>, const SparseDerived, const DenseDerived>(a.derived(), b.derived());
703}
704
705template<typename DenseDerived, typename SparseDerived>
706EIGEN_STRONG_INLINE const CwiseBinaryOp<internal::scalar_difference_op<typename DenseDerived::Scalar,typename SparseDerived::Scalar>, const DenseDerived, const SparseDerived>
707operator-(const MatrixBase<DenseDerived> &a, const SparseMatrixBase<SparseDerived> &b)
708{
709 return CwiseBinaryOp<internal::scalar_difference_op<typename DenseDerived::Scalar,typename SparseDerived::Scalar>, const DenseDerived, const SparseDerived>(a.derived(), b.derived());
710}
711
712template<typename SparseDerived, typename DenseDerived>
713EIGEN_STRONG_INLINE const CwiseBinaryOp<internal::scalar_difference_op<typename SparseDerived::Scalar,typename DenseDerived::Scalar>, const SparseDerived, const DenseDerived>
714operator-(const SparseMatrixBase<SparseDerived> &a, const MatrixBase<DenseDerived> &b)
715{
716 return CwiseBinaryOp<internal::scalar_difference_op<typename SparseDerived::Scalar,typename DenseDerived::Scalar>, const SparseDerived, const DenseDerived>(a.derived(), b.derived());
717}
718
719} // end namespace Eigen
720
721#endif // EIGEN_SPARSE_CWISE_BINARY_OP_H
const unsigned int RowMajorBit
Definition: Constants.h:68
Namespace containing all symbols from the Eigen library.
Definition: B01_Experimental.dox:1
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API.
Definition: Meta.h:59