Eigen  3.4.90 (git rev 67eeba6e720c5745abc77ae6c92ce0a44aa7b7ae)
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 
15 namespace 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 
37 template<typename BinaryOp, typename Lhs, typename Rhs>
38 class 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 
52 namespace internal {
53 
54 
55 // Generic "sparse OP sparse"
56 template<typename XprType> struct binary_sparse_evaluator;
57 
58 template<typename BinaryOp, typename Lhs, typename Rhs>
59 struct binary_evaluator<CwiseBinaryOp<BinaryOp, Lhs, Rhs>, IteratorBased, IteratorBased>
60  : evaluator_base<CwiseBinaryOp<BinaryOp, Lhs, Rhs> >
61 {
62 protected:
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;
68 public:
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 
145 protected:
146  const BinaryOp m_functor;
147  evaluator<Lhs> m_lhsImpl;
148  evaluator<Rhs> m_rhsImpl;
149 };
150 
151 // dense op sparse
152 template<typename BinaryOp, typename Lhs, typename Rhs>
153 struct binary_evaluator<CwiseBinaryOp<BinaryOp, Lhs, Rhs>, IndexBased, IteratorBased>
154  : evaluator_base<CwiseBinaryOp<BinaryOp, Lhs, Rhs> >
155 {
156 protected:
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;
161 public:
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 
231 protected:
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
239 template<typename BinaryOp, typename Lhs, typename Rhs>
240 struct binary_evaluator<CwiseBinaryOp<BinaryOp, Lhs, Rhs>, IteratorBased, IndexBased>
241  : evaluator_base<CwiseBinaryOp<BinaryOp, Lhs, Rhs> >
242 {
243 protected:
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;
248 public:
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 
318 protected:
319  const BinaryOp m_functor;
320  evaluator<Lhs> m_lhsImpl;
321  evaluator<Rhs> m_rhsImpl;
322  const XprType &m_expr;
323 };
324 
325 template<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"
332 template<typename T1, typename T2, typename Lhs, typename Rhs>
333 struct 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"
341 template<typename T1, typename T2, typename Lhs, typename Rhs>
342 struct 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"
350 template<typename T1, typename T2, typename Lhs, typename Rhs>
351 struct 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"
360 template<typename T1, typename T2, typename Lhs, typename Rhs>
361 struct 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"
370 template<typename Lhs, typename Rhs>
371 struct 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"
379 template<typename Lhs, typename Rhs>
380 struct 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"
388 template<typename Lhs, typename Rhs>
389 struct 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"
398 template<typename XprType>
399 struct sparse_conjunction_evaluator<XprType, IteratorBased, IteratorBased>
400  : evaluator_base<XprType>
401 {
402 protected:
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;
410 public:
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 
476 protected:
477  const BinaryOp m_functor;
478  evaluator<LhsArg> m_lhsImpl;
479  evaluator<RhsArg> m_rhsImpl;
480 };
481 
482 // "dense ^ sparse"
483 template<typename XprType>
484 struct sparse_conjunction_evaluator<XprType, IndexBased, IteratorBased>
485  : evaluator_base<XprType>
486 {
487 protected:
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;
495 public:
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 
549 protected:
550  const BinaryOp m_functor;
551  evaluator<LhsArg> m_lhsImpl;
552  evaluator<RhsArg> m_rhsImpl;
553 };
554 
555 // "sparse ^ dense"
556 template<typename XprType>
557 struct sparse_conjunction_evaluator<XprType, IteratorBased, IndexBased>
558  : evaluator_base<XprType>
559 {
560 protected:
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;
568 public:
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 
623 protected:
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 
635 template<typename Derived>
636 template<typename OtherDerived>
637 Derived& 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 
643 template<typename Derived>
644 template<typename OtherDerived>
645 Derived& 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 
651 template<typename Derived>
652 template<typename OtherDerived>
653 EIGEN_STRONG_INLINE Derived &
654 SparseMatrixBase<Derived>::operator-=(const SparseMatrixBase<OtherDerived> &other)
655 {
656  return derived() = derived() - other.derived();
657 }
658 
659 template<typename Derived>
660 template<typename OtherDerived>
661 EIGEN_STRONG_INLINE Derived &
662 SparseMatrixBase<Derived>::operator+=(const SparseMatrixBase<OtherDerived>& other)
663 {
664  return derived() = derived() + other.derived();
665 }
666 
667 template<typename Derived>
668 template<typename OtherDerived>
669 Derived& 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 
675 template<typename Derived>
676 template<typename OtherDerived>
677 Derived& 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 
683 template<typename Derived>
684 template<typename OtherDerived>
685 EIGEN_STRONG_INLINE const typename SparseMatrixBase<Derived>::template CwiseProductDenseReturnType<OtherDerived>::Type
686 SparseMatrixBase<Derived>::cwiseProduct(const MatrixBase<OtherDerived> &other) const
687 {
688  return typename CwiseProductDenseReturnType<OtherDerived>::Type(derived(), other.derived());
689 }
690 
691 template<typename DenseDerived, typename SparseDerived>
692 EIGEN_STRONG_INLINE const CwiseBinaryOp<internal::scalar_sum_op<typename DenseDerived::Scalar,typename SparseDerived::Scalar>, const DenseDerived, const SparseDerived>
693 operator+(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 
698 template<typename SparseDerived, typename DenseDerived>
699 EIGEN_STRONG_INLINE const CwiseBinaryOp<internal::scalar_sum_op<typename SparseDerived::Scalar,typename DenseDerived::Scalar>, const SparseDerived, const DenseDerived>
700 operator+(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 
705 template<typename DenseDerived, typename SparseDerived>
706 EIGEN_STRONG_INLINE const CwiseBinaryOp<internal::scalar_difference_op<typename DenseDerived::Scalar,typename SparseDerived::Scalar>, const DenseDerived, const SparseDerived>
707 operator-(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 
712 template<typename SparseDerived, typename DenseDerived>
713 EIGEN_STRONG_INLINE const CwiseBinaryOp<internal::scalar_difference_op<typename SparseDerived::Scalar,typename DenseDerived::Scalar>, const SparseDerived, const DenseDerived>
714 operator-(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: Core:139
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API.
Definition: Meta.h:59