SparseCwiseBinaryOp.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_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>
39  : public SparseMatrixBase<CwiseBinaryOp<BinaryOp, Lhs, Rhs> >
40 {
41  public:
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 // The default evaluator performs an "arithmetic" operation on two input arrays.
55 // Given input arrays 'lhs' and 'rhs' and binary functor 'func',
56 // the sparse destination array 'dst' is evaluated as follows:
57 // if lhs(i,j) and rhs(i,j) are present, dst(i,j) = func(lhs(i,j), rhs(i,j))
58 // if lhs(i,j) is present and rhs(i,j) is null, dst(i,j) = func(lhs(i,j), 0)
59 // if lhs(i,j) is null and rhs(i,j) is present, dst(i,j) = func(0, rhs(i,j))
60 
61 // Generic "sparse OP sparse"
62 template<typename XprType> struct binary_sparse_evaluator;
63 
64 template<typename BinaryOp, typename Lhs, typename Rhs>
65 struct binary_evaluator<CwiseBinaryOp<BinaryOp, Lhs, Rhs>, IteratorBased, IteratorBased>
66  : evaluator_base<CwiseBinaryOp<BinaryOp, Lhs, Rhs> >
67 {
68 protected:
69  typedef typename evaluator<Lhs>::InnerIterator LhsIterator;
70  typedef typename evaluator<Rhs>::InnerIterator RhsIterator;
71  typedef CwiseBinaryOp<BinaryOp, Lhs, Rhs> XprType;
72  typedef typename traits<XprType>::Scalar Scalar;
73  typedef typename XprType::StorageIndex StorageIndex;
74 public:
75 
76  class InnerIterator
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), m_value(Scalar(0))
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_id = -1;
110  }
111  return *this;
112  }
113 
114  EIGEN_STRONG_INLINE Scalar value() const { return m_value; }
115 
116  EIGEN_STRONG_INLINE StorageIndex index() const { return m_id; }
117  EIGEN_STRONG_INLINE Index outer() const { return m_lhsIter.outer(); }
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 {
133  CoeffReadCost = int(evaluator<Lhs>::CoeffReadCost) + int(evaluator<Rhs>::CoeffReadCost) + int(functor_traits<BinaryOp>::Cost),
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 
150 protected:
151  const BinaryOp m_functor;
152  evaluator<Lhs> m_lhsImpl;
153  evaluator<Rhs> m_rhsImpl;
154 };
155 
156 // dense op sparse
157 template<typename BinaryOp, typename Lhs, typename Rhs>
158 struct binary_evaluator<CwiseBinaryOp<BinaryOp, Lhs, Rhs>, IndexBased, IteratorBased>
159  : evaluator_base<CwiseBinaryOp<BinaryOp, Lhs, Rhs> >
160 {
161 protected:
162  typedef typename evaluator<Rhs>::InnerIterator RhsIterator;
163  typedef CwiseBinaryOp<BinaryOp, Lhs, Rhs> XprType;
164  typedef typename traits<XprType>::Scalar Scalar;
165  typedef typename XprType::StorageIndex StorageIndex;
166 public:
167 
168  class InnerIterator
169  {
170  enum { IsRowMajor = (int(Rhs::Flags)&RowMajorBit)==RowMajorBit };
171  public:
172 
173  EIGEN_STRONG_INLINE InnerIterator(const binary_evaluator& aEval, Index outer)
174  : 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())
175  {
176  this->operator++();
177  }
178 
179  EIGEN_STRONG_INLINE InnerIterator& operator++()
180  {
181  ++m_id;
182  if(m_id<m_innerSize)
183  {
184  Scalar lhsVal = m_lhsEval.coeff(IsRowMajor?m_rhsIter.outer():m_id,
185  IsRowMajor?m_id:m_rhsIter.outer());
186  if(m_rhsIter && m_rhsIter.index()==m_id)
187  {
188  m_value = m_functor(lhsVal, m_rhsIter.value());
189  ++m_rhsIter;
190  }
191  else
192  m_value = m_functor(lhsVal, Scalar(0));
193  }
194 
195  return *this;
196  }
197 
198  EIGEN_STRONG_INLINE Scalar value() const { eigen_internal_assert(m_id<m_innerSize); return m_value; }
199 
200  EIGEN_STRONG_INLINE StorageIndex index() const { return m_id; }
201  EIGEN_STRONG_INLINE Index outer() const { return m_rhsIter.outer(); }
202  EIGEN_STRONG_INLINE Index row() const { return IsRowMajor ? m_rhsIter.outer() : m_id; }
203  EIGEN_STRONG_INLINE Index col() const { return IsRowMajor ? m_id : m_rhsIter.outer(); }
204 
205  EIGEN_STRONG_INLINE operator bool() const { return m_id<m_innerSize; }
206 
207  protected:
208  const evaluator<Lhs> &m_lhsEval;
209  RhsIterator m_rhsIter;
210  const BinaryOp& m_functor;
211  Scalar m_value;
212  StorageIndex m_id;
213  StorageIndex m_innerSize;
214  };
215 
216 
217  enum {
218  CoeffReadCost = int(evaluator<Lhs>::CoeffReadCost) + int(evaluator<Rhs>::CoeffReadCost) + int(functor_traits<BinaryOp>::Cost),
219  Flags = XprType::Flags
220  };
221 
222  explicit binary_evaluator(const XprType& xpr)
223  : m_functor(xpr.functor()),
224  m_lhsImpl(xpr.lhs()),
225  m_rhsImpl(xpr.rhs()),
226  m_expr(xpr)
227  {
228  EIGEN_INTERNAL_CHECK_COST_VALUE(functor_traits<BinaryOp>::Cost);
229  EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
230  }
231 
232  inline Index nonZerosEstimate() const {
233  return m_expr.size();
234  }
235 
236 protected:
237  const BinaryOp m_functor;
238  evaluator<Lhs> m_lhsImpl;
239  evaluator<Rhs> m_rhsImpl;
240  const XprType &m_expr;
241 };
242 
243 // sparse op dense
244 template<typename BinaryOp, typename Lhs, typename Rhs>
245 struct binary_evaluator<CwiseBinaryOp<BinaryOp, Lhs, Rhs>, IteratorBased, IndexBased>
246  : evaluator_base<CwiseBinaryOp<BinaryOp, Lhs, Rhs> >
247 {
248 protected:
249  typedef typename evaluator<Lhs>::InnerIterator LhsIterator;
250  typedef CwiseBinaryOp<BinaryOp, Lhs, Rhs> XprType;
251  typedef typename traits<XprType>::Scalar Scalar;
252  typedef typename XprType::StorageIndex StorageIndex;
253 public:
254 
255  class InnerIterator
256  {
257  enum { IsRowMajor = (int(Lhs::Flags)&RowMajorBit)==RowMajorBit };
258  public:
259 
260  EIGEN_STRONG_INLINE InnerIterator(const binary_evaluator& aEval, Index outer)
261  : 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())
262  {
263  this->operator++();
264  }
265 
266  EIGEN_STRONG_INLINE InnerIterator& operator++()
267  {
268  ++m_id;
269  if(m_id<m_innerSize)
270  {
271  Scalar rhsVal = m_rhsEval.coeff(IsRowMajor?m_lhsIter.outer():m_id,
272  IsRowMajor?m_id:m_lhsIter.outer());
273  if(m_lhsIter && m_lhsIter.index()==m_id)
274  {
275  m_value = m_functor(m_lhsIter.value(), rhsVal);
276  ++m_lhsIter;
277  }
278  else
279  m_value = m_functor(Scalar(0),rhsVal);
280  }
281 
282  return *this;
283  }
284 
285  EIGEN_STRONG_INLINE Scalar value() const { eigen_internal_assert(m_id<m_innerSize); return m_value; }
286 
287  EIGEN_STRONG_INLINE StorageIndex index() const { return m_id; }
288  EIGEN_STRONG_INLINE Index outer() const { return m_lhsIter.outer(); }
289  EIGEN_STRONG_INLINE Index row() const { return IsRowMajor ? m_lhsIter.outer() : m_id; }
290  EIGEN_STRONG_INLINE Index col() const { return IsRowMajor ? m_id : m_lhsIter.outer(); }
291 
292  EIGEN_STRONG_INLINE operator bool() const { return m_id<m_innerSize; }
293 
294  protected:
295  LhsIterator m_lhsIter;
296  const evaluator<Rhs> &m_rhsEval;
297  const BinaryOp& m_functor;
298  Scalar m_value;
299  StorageIndex m_id;
300  StorageIndex m_innerSize;
301  };
302 
303 
304  enum {
305  CoeffReadCost = int(evaluator<Lhs>::CoeffReadCost) + int(evaluator<Rhs>::CoeffReadCost) + int(functor_traits<BinaryOp>::Cost),
306  Flags = XprType::Flags
307  };
308 
309  explicit binary_evaluator(const XprType& xpr)
310  : m_functor(xpr.functor()),
311  m_lhsImpl(xpr.lhs()),
312  m_rhsImpl(xpr.rhs()),
313  m_expr(xpr)
314  {
315  EIGEN_INTERNAL_CHECK_COST_VALUE(functor_traits<BinaryOp>::Cost);
316  EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
317  }
318 
319  inline Index nonZerosEstimate() const {
320  return m_expr.size();
321  }
322 
323 protected:
324  const BinaryOp m_functor;
325  evaluator<Lhs> m_lhsImpl;
326  evaluator<Rhs> m_rhsImpl;
327  const XprType &m_expr;
328 };
329 
330 template<typename T,
331  typename LhsKind = typename evaluator_traits<typename T::Lhs>::Kind,
332  typename RhsKind = typename evaluator_traits<typename T::Rhs>::Kind,
333  typename LhsScalar = typename traits<typename T::Lhs>::Scalar,
334  typename RhsScalar = typename traits<typename T::Rhs>::Scalar> struct sparse_conjunction_evaluator;
335 
336 // "sparse .* sparse"
337 template<typename T1, typename T2, typename Lhs, typename Rhs>
338 struct binary_evaluator<CwiseBinaryOp<scalar_product_op<T1,T2>, Lhs, Rhs>, IteratorBased, IteratorBased>
339  : sparse_conjunction_evaluator<CwiseBinaryOp<scalar_product_op<T1,T2>, Lhs, Rhs> >
340 {
341  typedef CwiseBinaryOp<scalar_product_op<T1,T2>, Lhs, Rhs> XprType;
342  typedef sparse_conjunction_evaluator<XprType> Base;
343  explicit binary_evaluator(const XprType& xpr) : Base(xpr) {}
344 };
345 // "dense .* sparse"
346 template<typename T1, typename T2, typename Lhs, typename Rhs>
347 struct binary_evaluator<CwiseBinaryOp<scalar_product_op<T1,T2>, Lhs, Rhs>, IndexBased, IteratorBased>
348  : sparse_conjunction_evaluator<CwiseBinaryOp<scalar_product_op<T1,T2>, Lhs, Rhs> >
349 {
350  typedef CwiseBinaryOp<scalar_product_op<T1,T2>, Lhs, Rhs> XprType;
351  typedef sparse_conjunction_evaluator<XprType> Base;
352  explicit binary_evaluator(const XprType& xpr) : Base(xpr) {}
353 };
354 // "sparse .* dense"
355 template<typename T1, typename T2, typename Lhs, typename Rhs>
356 struct binary_evaluator<CwiseBinaryOp<scalar_product_op<T1,T2>, Lhs, Rhs>, IteratorBased, IndexBased>
357  : sparse_conjunction_evaluator<CwiseBinaryOp<scalar_product_op<T1,T2>, Lhs, Rhs> >
358 {
359  typedef CwiseBinaryOp<scalar_product_op<T1,T2>, Lhs, Rhs> XprType;
360  typedef sparse_conjunction_evaluator<XprType> Base;
361  explicit binary_evaluator(const XprType& xpr) : Base(xpr) {}
362 };
363 
364 // "sparse ./ dense"
365 template<typename T1, typename T2, typename Lhs, typename Rhs>
366 struct binary_evaluator<CwiseBinaryOp<scalar_quotient_op<T1,T2>, Lhs, Rhs>, IteratorBased, IndexBased>
367  : sparse_conjunction_evaluator<CwiseBinaryOp<scalar_quotient_op<T1,T2>, Lhs, Rhs> >
368 {
369  typedef CwiseBinaryOp<scalar_quotient_op<T1,T2>, Lhs, Rhs> XprType;
370  typedef sparse_conjunction_evaluator<XprType> Base;
371  explicit binary_evaluator(const XprType& xpr) : Base(xpr) {}
372 };
373 
374 // "sparse && sparse"
375 template<typename Lhs, typename Rhs>
376 struct binary_evaluator<CwiseBinaryOp<scalar_boolean_and_op<bool>, Lhs, Rhs>, IteratorBased, IteratorBased>
377  : sparse_conjunction_evaluator<CwiseBinaryOp<scalar_boolean_and_op<bool>, Lhs, Rhs> >
378 {
379  typedef CwiseBinaryOp<scalar_boolean_and_op<bool>, Lhs, Rhs> XprType;
380  typedef sparse_conjunction_evaluator<XprType> Base;
381  explicit binary_evaluator(const XprType& xpr) : Base(xpr) {}
382 };
383 // "dense && sparse"
384 template<typename Lhs, typename Rhs>
385 struct binary_evaluator<CwiseBinaryOp<scalar_boolean_and_op<bool>, Lhs, Rhs>, IndexBased, IteratorBased>
386  : sparse_conjunction_evaluator<CwiseBinaryOp<scalar_boolean_and_op<bool>, Lhs, Rhs> >
387 {
388  typedef CwiseBinaryOp<scalar_boolean_and_op<bool>, Lhs, Rhs> XprType;
389  typedef sparse_conjunction_evaluator<XprType> Base;
390  explicit binary_evaluator(const XprType& xpr) : Base(xpr) {}
391 };
392 // "sparse && dense"
393 template<typename Lhs, typename Rhs>
394 struct binary_evaluator<CwiseBinaryOp<scalar_boolean_and_op<bool>, Lhs, Rhs>, IteratorBased, IndexBased>
395  : sparse_conjunction_evaluator<CwiseBinaryOp<scalar_boolean_and_op<bool>, Lhs, Rhs> >
396 {
397  typedef CwiseBinaryOp<scalar_boolean_and_op<bool>, Lhs, Rhs> XprType;
398  typedef sparse_conjunction_evaluator<XprType> Base;
399  explicit binary_evaluator(const XprType& xpr) : Base(xpr) {}
400 };
401 
402 // The conjunction "^" evaluator performs a logical "and" or set "intersection" operation on two input arrays.
403 // Given input arrays 'lhs' and 'rhs' and binary functor 'func',
404 // the sparse destination array 'dst' is evaluated as follows:
405 // if lhs(i,j) and rhs(i,j) are present, dst(i,j) = func(lhs(i,j), rhs(i,j))
406 // if lhs(i,j) is present and rhs(i,j) is null, dst(i,j) is null
407 // if lhs(i,j) is null and rhs(i,j) is present, dst(i,j) is null
408 
409 // "sparse ^ sparse"
410 template<typename XprType>
411 struct sparse_conjunction_evaluator<XprType, IteratorBased, IteratorBased>
412  : evaluator_base<XprType>
413 {
414 protected:
415  typedef typename XprType::Functor BinaryOp;
416  typedef typename XprType::Lhs LhsArg;
417  typedef typename XprType::Rhs RhsArg;
418  typedef typename evaluator<LhsArg>::InnerIterator LhsIterator;
419  typedef typename evaluator<RhsArg>::InnerIterator RhsIterator;
420  typedef typename XprType::StorageIndex StorageIndex;
421  typedef typename traits<XprType>::Scalar Scalar;
422 public:
423 
424  class InnerIterator
425  {
426  public:
427 
428  EIGEN_STRONG_INLINE InnerIterator(const sparse_conjunction_evaluator& aEval, Index outer)
429  : m_lhsIter(aEval.m_lhsImpl,outer), m_rhsIter(aEval.m_rhsImpl,outer), m_functor(aEval.m_functor)
430  {
431  while (m_lhsIter && m_rhsIter && (m_lhsIter.index() != m_rhsIter.index()))
432  {
433  if (m_lhsIter.index() < m_rhsIter.index())
434  ++m_lhsIter;
435  else
436  ++m_rhsIter;
437  }
438  }
439 
440  EIGEN_STRONG_INLINE InnerIterator& operator++()
441  {
442  ++m_lhsIter;
443  ++m_rhsIter;
444  while (m_lhsIter && m_rhsIter && (m_lhsIter.index() != m_rhsIter.index()))
445  {
446  if (m_lhsIter.index() < m_rhsIter.index())
447  ++m_lhsIter;
448  else
449  ++m_rhsIter;
450  }
451  return *this;
452  }
453 
454  EIGEN_STRONG_INLINE Scalar value() const { return m_functor(m_lhsIter.value(), m_rhsIter.value()); }
455 
456  EIGEN_STRONG_INLINE StorageIndex index() const { return m_lhsIter.index(); }
457  EIGEN_STRONG_INLINE Index outer() const { return m_lhsIter.outer(); }
458  EIGEN_STRONG_INLINE Index row() const { return m_lhsIter.row(); }
459  EIGEN_STRONG_INLINE Index col() const { return m_lhsIter.col(); }
460 
461  EIGEN_STRONG_INLINE operator bool() const { return (m_lhsIter && m_rhsIter); }
462 
463  protected:
464  LhsIterator m_lhsIter;
465  RhsIterator m_rhsIter;
466  const BinaryOp& m_functor;
467  };
468 
469 
470  enum {
471  CoeffReadCost = int(evaluator<LhsArg>::CoeffReadCost) + int(evaluator<RhsArg>::CoeffReadCost) + int(functor_traits<BinaryOp>::Cost),
472  Flags = XprType::Flags
473  };
474 
475  explicit sparse_conjunction_evaluator(const XprType& xpr)
476  : m_functor(xpr.functor()),
477  m_lhsImpl(xpr.lhs()),
478  m_rhsImpl(xpr.rhs())
479  {
480  EIGEN_INTERNAL_CHECK_COST_VALUE(functor_traits<BinaryOp>::Cost);
481  EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
482  }
483 
484  inline Index nonZerosEstimate() const {
485  return (std::min)(m_lhsImpl.nonZerosEstimate(), m_rhsImpl.nonZerosEstimate());
486  }
487 
488 protected:
489  const BinaryOp m_functor;
490  evaluator<LhsArg> m_lhsImpl;
491  evaluator<RhsArg> m_rhsImpl;
492 };
493 
494 // "dense ^ sparse"
495 template<typename XprType>
496 struct sparse_conjunction_evaluator<XprType, IndexBased, IteratorBased>
497  : evaluator_base<XprType>
498 {
499 protected:
500  typedef typename XprType::Functor BinaryOp;
501  typedef typename XprType::Lhs LhsArg;
502  typedef typename XprType::Rhs RhsArg;
503  typedef evaluator<LhsArg> LhsEvaluator;
504  typedef typename evaluator<RhsArg>::InnerIterator RhsIterator;
505  typedef typename XprType::StorageIndex StorageIndex;
506  typedef typename traits<XprType>::Scalar Scalar;
507 public:
508 
509  class InnerIterator
510  {
511  enum { IsRowMajor = (int(RhsArg::Flags)&RowMajorBit)==RowMajorBit };
512 
513  public:
514 
515  EIGEN_STRONG_INLINE InnerIterator(const sparse_conjunction_evaluator& aEval, Index outer)
516  : m_lhsEval(aEval.m_lhsImpl), m_rhsIter(aEval.m_rhsImpl,outer), m_functor(aEval.m_functor), m_outer(outer)
517  {}
518 
519  EIGEN_STRONG_INLINE InnerIterator& operator++()
520  {
521  ++m_rhsIter;
522  return *this;
523  }
524 
525  EIGEN_STRONG_INLINE Scalar value() const
526  { return m_functor(m_lhsEval.coeff(IsRowMajor?m_outer:m_rhsIter.index(),IsRowMajor?m_rhsIter.index():m_outer), m_rhsIter.value()); }
527 
528  EIGEN_STRONG_INLINE StorageIndex index() const { return m_rhsIter.index(); }
529  EIGEN_STRONG_INLINE Index outer() const { return m_rhsIter.outer(); }
530  EIGEN_STRONG_INLINE Index row() const { return m_rhsIter.row(); }
531  EIGEN_STRONG_INLINE Index col() const { return m_rhsIter.col(); }
532 
533  EIGEN_STRONG_INLINE operator bool() const { return m_rhsIter; }
534 
535  protected:
536  const LhsEvaluator &m_lhsEval;
537  RhsIterator m_rhsIter;
538  const BinaryOp& m_functor;
539  const Index m_outer;
540  };
541 
542 
543  enum {
544  CoeffReadCost = int(evaluator<LhsArg>::CoeffReadCost) + int(evaluator<RhsArg>::CoeffReadCost) + int(functor_traits<BinaryOp>::Cost),
545  Flags = XprType::Flags
546  };
547 
548  explicit sparse_conjunction_evaluator(const XprType& xpr)
549  : m_functor(xpr.functor()),
550  m_lhsImpl(xpr.lhs()),
551  m_rhsImpl(xpr.rhs())
552  {
553  EIGEN_INTERNAL_CHECK_COST_VALUE(functor_traits<BinaryOp>::Cost);
554  EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
555  }
556 
557  inline Index nonZerosEstimate() const {
558  return m_rhsImpl.nonZerosEstimate();
559  }
560 
561 protected:
562  const BinaryOp m_functor;
563  evaluator<LhsArg> m_lhsImpl;
564  evaluator<RhsArg> m_rhsImpl;
565 };
566 
567 // "sparse ^ dense"
568 template<typename XprType>
569 struct sparse_conjunction_evaluator<XprType, IteratorBased, IndexBased>
570  : evaluator_base<XprType>
571 {
572 protected:
573  typedef typename XprType::Functor BinaryOp;
574  typedef typename XprType::Lhs LhsArg;
575  typedef typename XprType::Rhs RhsArg;
576  typedef typename evaluator<LhsArg>::InnerIterator LhsIterator;
577  typedef evaluator<RhsArg> RhsEvaluator;
578  typedef typename XprType::StorageIndex StorageIndex;
579  typedef typename traits<XprType>::Scalar Scalar;
580 public:
581 
582  class InnerIterator
583  {
584  enum { IsRowMajor = (int(LhsArg::Flags)&RowMajorBit)==RowMajorBit };
585 
586  public:
587 
588  EIGEN_STRONG_INLINE InnerIterator(const sparse_conjunction_evaluator& aEval, Index outer)
589  : m_lhsIter(aEval.m_lhsImpl,outer), m_rhsEval(aEval.m_rhsImpl), m_functor(aEval.m_functor), m_outer(outer)
590  {}
591 
592  EIGEN_STRONG_INLINE InnerIterator& operator++()
593  {
594  ++m_lhsIter;
595  return *this;
596  }
597 
598  EIGEN_STRONG_INLINE Scalar value() const
599  { return m_functor(m_lhsIter.value(),
600  m_rhsEval.coeff(IsRowMajor?m_outer:m_lhsIter.index(),IsRowMajor?m_lhsIter.index():m_outer)); }
601 
602  EIGEN_STRONG_INLINE StorageIndex index() const { return m_lhsIter.index(); }
603  EIGEN_STRONG_INLINE Index outer() const { return m_lhsIter.outer(); }
604  EIGEN_STRONG_INLINE Index row() const { return m_lhsIter.row(); }
605  EIGEN_STRONG_INLINE Index col() const { return m_lhsIter.col(); }
606 
607  EIGEN_STRONG_INLINE operator bool() const { return m_lhsIter; }
608 
609  protected:
610  LhsIterator m_lhsIter;
611  const evaluator<RhsArg> &m_rhsEval;
612  const BinaryOp& m_functor;
613  const Index m_outer;
614  };
615 
616 
617  enum {
618  CoeffReadCost = int(evaluator<LhsArg>::CoeffReadCost) + int(evaluator<RhsArg>::CoeffReadCost) + int(functor_traits<BinaryOp>::Cost),
619  Flags = XprType::Flags
620  };
621 
622  explicit sparse_conjunction_evaluator(const XprType& xpr)
623  : m_functor(xpr.functor()),
624  m_lhsImpl(xpr.lhs()),
625  m_rhsImpl(xpr.rhs())
626  {
627  EIGEN_INTERNAL_CHECK_COST_VALUE(functor_traits<BinaryOp>::Cost);
628  EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
629  }
630 
631  inline Index nonZerosEstimate() const {
632  return m_lhsImpl.nonZerosEstimate();
633  }
634 
635 protected:
636  const BinaryOp m_functor;
637  evaluator<LhsArg> m_lhsImpl;
638  evaluator<RhsArg> m_rhsImpl;
639 };
640 
641 template<typename T,
642  typename LhsKind = typename evaluator_traits<typename T::Lhs>::Kind,
643  typename RhsKind = typename evaluator_traits<typename T::Rhs>::Kind,
644  typename LhsScalar = typename traits<typename T::Lhs>::Scalar,
645  typename RhsScalar = typename traits<typename T::Rhs>::Scalar> struct sparse_disjunction_evaluator;
646 
647 // The disjunction "v" evaluator performs a logical "or" or set "union" operation on two input arrays.
648 // Given input arrays 'lhs' and 'rhs' and binary functor 'func',
649 // the sparse destination array 'dst' is evaluated as follows:
650 // if lhs(i,j) and rhs(i,j) are present, dst(i,j) = func(lhs(i,j), rhs(i,j))
651 // if lhs(i,j) is present and rhs(i,j) is null, dst(i,j) = lhs(i,j)
652 // if lhs(i,j) is null and rhs(i,j) is present, dst(i,j) = rhs(i,j)
653 
654 // "sparse v sparse"
655 template <typename XprType>
656 struct sparse_disjunction_evaluator<XprType, IteratorBased, IteratorBased> : evaluator_base<XprType> {
657  protected:
658  typedef typename XprType::Functor BinaryOp;
659  typedef typename XprType::Lhs LhsArg;
660  typedef typename XprType::Rhs RhsArg;
661  typedef typename evaluator<LhsArg>::InnerIterator LhsIterator;
662  typedef typename evaluator<RhsArg>::InnerIterator RhsIterator;
663  typedef typename XprType::StorageIndex StorageIndex;
664  typedef typename traits<XprType>::Scalar Scalar;
665 
666  public:
667  class InnerIterator {
668  public:
669  EIGEN_STRONG_INLINE InnerIterator(const sparse_disjunction_evaluator& aEval, Index outer)
670  : m_lhsIter(aEval.m_lhsImpl, outer),
671  m_rhsIter(aEval.m_rhsImpl, outer),
672  m_functor(aEval.m_functor),
673  m_value(Scalar(0)) {
674  this->operator++();
675  }
676 
677  EIGEN_STRONG_INLINE InnerIterator& operator++() {
678  if (m_lhsIter && m_rhsIter && (m_lhsIter.index() == m_rhsIter.index())) {
679  m_id = m_lhsIter.index();
680  m_value = m_functor(m_lhsIter.value(), m_rhsIter.value());
681  ++m_lhsIter;
682  ++m_rhsIter;
683  } else if (m_lhsIter && (!m_rhsIter || (m_lhsIter.index() < m_rhsIter.index()))) {
684  m_id = m_lhsIter.index();
685  m_value = m_lhsIter.value();
686  ++m_lhsIter;
687  } else if (m_rhsIter && (!m_lhsIter || (m_lhsIter.index() > m_rhsIter.index()))) {
688  m_id = m_rhsIter.index();
689  m_value = m_rhsIter.value();
690  ++m_rhsIter;
691  } else {
692  m_id = -1;
693  }
694  return *this;
695  }
696 
697  EIGEN_STRONG_INLINE Scalar value() const { return m_value; }
698 
699  EIGEN_STRONG_INLINE StorageIndex index() const { return m_id; }
700  EIGEN_STRONG_INLINE Index outer() const { return m_lhsIter.outer(); }
701  EIGEN_STRONG_INLINE Index row() const { return LhsArg::IsRowMajor ? m_lhsIter.row() : index(); }
702  EIGEN_STRONG_INLINE Index col() const { return LhsArg::IsRowMajor ? index() : m_lhsIter.col(); }
703 
704  EIGEN_STRONG_INLINE operator bool() const { return m_id >= 0; }
705 
706  protected:
707  LhsIterator m_lhsIter;
708  RhsIterator m_rhsIter;
709  const BinaryOp& m_functor;
710  Scalar m_value;
711  StorageIndex m_id;
712  };
713 
714  enum {
715  CoeffReadCost = int(evaluator<LhsArg>::CoeffReadCost) + int(evaluator<RhsArg>::CoeffReadCost) +
716  int(functor_traits<BinaryOp>::Cost),
717  Flags = XprType::Flags
718  };
719 
720  explicit sparse_disjunction_evaluator(const XprType& xpr)
721  : m_functor(xpr.functor()), m_lhsImpl(xpr.lhs()), m_rhsImpl(xpr.rhs()) {
722  EIGEN_INTERNAL_CHECK_COST_VALUE(functor_traits<BinaryOp>::Cost);
723  EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
724  }
725 
726  inline Index nonZerosEstimate() const { return m_lhsImpl.nonZerosEstimate() + m_rhsImpl.nonZerosEstimate(); }
727 
728  protected:
729  const BinaryOp m_functor;
730  evaluator<LhsArg> m_lhsImpl;
731  evaluator<RhsArg> m_rhsImpl;
732 };
733 
734 // "dense v sparse"
735 template <typename XprType>
736 struct sparse_disjunction_evaluator<XprType, IndexBased, IteratorBased> : evaluator_base<XprType> {
737  protected:
738  typedef typename XprType::Functor BinaryOp;
739  typedef typename XprType::Lhs LhsArg;
740  typedef typename XprType::Rhs RhsArg;
741  typedef evaluator<LhsArg> LhsEvaluator;
742  typedef typename evaluator<RhsArg>::InnerIterator RhsIterator;
743  typedef typename XprType::StorageIndex StorageIndex;
744  typedef typename traits<XprType>::Scalar Scalar;
745 
746  public:
747  class InnerIterator {
748  enum { IsRowMajor = (int(RhsArg::Flags) & RowMajorBit) == RowMajorBit };
749 
750  public:
751  EIGEN_STRONG_INLINE InnerIterator(const sparse_disjunction_evaluator& aEval, Index outer)
752  : m_lhsEval(aEval.m_lhsImpl),
753  m_rhsIter(aEval.m_rhsImpl, outer),
754  m_functor(aEval.m_functor),
755  m_value(0),
756  m_id(-1),
757  m_innerSize(aEval.m_expr.rhs().innerSize()) {
758  this->operator++();
759  }
760 
761  EIGEN_STRONG_INLINE InnerIterator& operator++() {
762  ++m_id;
763  if (m_id < m_innerSize) {
764  Scalar lhsVal = m_lhsEval.coeff(IsRowMajor ? m_rhsIter.outer() : m_id, IsRowMajor ? m_id : m_rhsIter.outer());
765  if (m_rhsIter && m_rhsIter.index() == m_id) {
766  m_value = m_functor(lhsVal, m_rhsIter.value());
767  ++m_rhsIter;
768  } else
769  m_value = lhsVal;
770  }
771 
772  return *this;
773  }
774 
775  EIGEN_STRONG_INLINE Scalar value() const {
776  eigen_internal_assert(m_id < m_innerSize);
777  return m_value;
778  }
779 
780  EIGEN_STRONG_INLINE StorageIndex index() const { return m_id; }
781  EIGEN_STRONG_INLINE Index outer() const { return m_rhsIter.outer(); }
782  EIGEN_STRONG_INLINE Index row() const { return IsRowMajor ? m_rhsIter.outer() : m_id; }
783  EIGEN_STRONG_INLINE Index col() const { return IsRowMajor ? m_id : m_rhsIter.outer(); }
784 
785  EIGEN_STRONG_INLINE operator bool() const { return m_id < m_innerSize; }
786 
787  protected:
788  const evaluator<LhsArg>& m_lhsEval;
789  RhsIterator m_rhsIter;
790  const BinaryOp& m_functor;
791  Scalar m_value;
792  StorageIndex m_id;
793  StorageIndex m_innerSize;
794  };
795 
796  enum {
797  CoeffReadCost = int(evaluator<LhsArg>::CoeffReadCost) + int(evaluator<RhsArg>::CoeffReadCost) +
798  int(functor_traits<BinaryOp>::Cost),
799  Flags = XprType::Flags
800  };
801 
802  explicit sparse_disjunction_evaluator(const XprType& xpr)
803  : m_functor(xpr.functor()), m_lhsImpl(xpr.lhs()), m_rhsImpl(xpr.rhs()), m_expr(xpr) {
804  EIGEN_INTERNAL_CHECK_COST_VALUE(functor_traits<BinaryOp>::Cost);
805  EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
806  }
807 
808  inline Index nonZerosEstimate() const { return m_expr.size(); }
809 
810  protected:
811  const BinaryOp m_functor;
812  evaluator<LhsArg> m_lhsImpl;
813  evaluator<RhsArg> m_rhsImpl;
814  const XprType& m_expr;
815 };
816 
817 // "sparse v dense"
818 template <typename XprType>
819 struct sparse_disjunction_evaluator<XprType, IteratorBased, IndexBased> : evaluator_base<XprType> {
820  protected:
821  typedef typename XprType::Functor BinaryOp;
822  typedef typename XprType::Lhs LhsArg;
823  typedef typename XprType::Rhs RhsArg;
824  typedef typename evaluator<LhsArg>::InnerIterator LhsIterator;
825  typedef evaluator<RhsArg> RhsEvaluator;
826  typedef typename XprType::StorageIndex StorageIndex;
827  typedef typename traits<XprType>::Scalar Scalar;
828 
829  public:
830  class InnerIterator {
831  enum { IsRowMajor = (int(LhsArg::Flags) & RowMajorBit) == RowMajorBit };
832 
833  public:
834  EIGEN_STRONG_INLINE InnerIterator(const sparse_disjunction_evaluator& aEval, Index outer)
835  : m_lhsIter(aEval.m_lhsImpl, outer),
836  m_rhsEval(aEval.m_rhsImpl),
837  m_functor(aEval.m_functor),
838  m_value(0),
839  m_id(-1),
840  m_innerSize(aEval.m_expr.lhs().innerSize()) {
841  this->operator++();
842  }
843 
844  EIGEN_STRONG_INLINE InnerIterator& operator++() {
845  ++m_id;
846  if (m_id < m_innerSize) {
847  Scalar rhsVal = m_rhsEval.coeff(IsRowMajor ? m_lhsIter.outer() : m_id, IsRowMajor ? m_id : m_lhsIter.outer());
848  if (m_lhsIter && m_lhsIter.index() == m_id) {
849  m_value = m_functor(m_lhsIter.value(), rhsVal);
850  ++m_lhsIter;
851  } else
852  m_value = rhsVal;
853  }
854 
855  return *this;
856  }
857 
858  EIGEN_STRONG_INLINE Scalar value() const {
859  eigen_internal_assert(m_id < m_innerSize);
860  return m_value;
861  }
862 
863  EIGEN_STRONG_INLINE StorageIndex index() const { return m_id; }
864  EIGEN_STRONG_INLINE Index outer() const { return m_lhsIter.outer(); }
865  EIGEN_STRONG_INLINE Index row() const { return IsRowMajor ? m_lhsIter.outer() : m_id; }
866  EIGEN_STRONG_INLINE Index col() const { return IsRowMajor ? m_id : m_lhsIter.outer(); }
867 
868  EIGEN_STRONG_INLINE operator bool() const { return m_id < m_innerSize; }
869 
870  protected:
871  LhsIterator m_lhsIter;
872  const evaluator<RhsArg>& m_rhsEval;
873  const BinaryOp& m_functor;
874  Scalar m_value;
875  StorageIndex m_id;
876  StorageIndex m_innerSize;
877  };
878 
879  enum {
880  CoeffReadCost = int(evaluator<LhsArg>::CoeffReadCost) + int(evaluator<RhsArg>::CoeffReadCost) +
881  int(functor_traits<BinaryOp>::Cost),
882  Flags = XprType::Flags
883  };
884 
885  explicit sparse_disjunction_evaluator(const XprType& xpr)
886  : m_functor(xpr.functor()), m_lhsImpl(xpr.lhs()), m_rhsImpl(xpr.rhs()), m_expr(xpr) {
887  EIGEN_INTERNAL_CHECK_COST_VALUE(functor_traits<BinaryOp>::Cost);
888  EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
889  }
890 
891  inline Index nonZerosEstimate() const { return m_expr.size(); }
892 
893  protected:
894  const BinaryOp m_functor;
895  evaluator<LhsArg> m_lhsImpl;
896  evaluator<RhsArg> m_rhsImpl;
897  const XprType& m_expr;
898 };
899 
900 // when DupFunc is wrapped with scalar_dup_op, use disjunction evaulator
901 template <typename T1, typename T2, typename DupFunc, typename Lhs, typename Rhs>
902 struct binary_evaluator<CwiseBinaryOp<scalar_disjunction_op<DupFunc, T1, T2>, Lhs, Rhs>, IteratorBased, IteratorBased>
903  : sparse_disjunction_evaluator<CwiseBinaryOp<scalar_disjunction_op<DupFunc, T1, T2>, Lhs, Rhs> > {
904  typedef CwiseBinaryOp<scalar_disjunction_op<DupFunc, T1, T2>, Lhs, Rhs> XprType;
905  typedef sparse_disjunction_evaluator<XprType> Base;
906  explicit binary_evaluator(const XprType& xpr) : Base(xpr) {}
907 };
908 }
909 
910 
914 template<typename Derived>
915 template<typename OtherDerived>
917 {
918  call_assignment(derived(), other.derived(), internal::add_assign_op<Scalar,typename OtherDerived::Scalar>());
919  return derived();
920 }
921 
922 template<typename Derived>
923 template<typename OtherDerived>
925 {
926  call_assignment(derived(), other.derived(), internal::assign_op<Scalar,typename OtherDerived::Scalar>());
927  return derived();
928 }
929 
930 template<typename Derived>
931 template<typename OtherDerived>
932 EIGEN_STRONG_INLINE Derived &
934 {
935  return derived() = derived() - other.derived();
936 }
937 
938 template<typename Derived>
939 template<typename OtherDerived>
940 EIGEN_STRONG_INLINE Derived &
942 {
943  return derived() = derived() + other.derived();
944 }
945 
946 template<typename Derived>
947 template<typename OtherDerived>
949 {
950  call_assignment_no_alias(derived(), other.derived(), internal::add_assign_op<Scalar,typename OtherDerived::Scalar>());
951  return derived();
952 }
953 
954 template<typename Derived>
955 template<typename OtherDerived>
957 {
958  call_assignment_no_alias(derived(), other.derived(), internal::sub_assign_op<Scalar,typename OtherDerived::Scalar>());
959  return derived();
960 }
961 
962 template<typename Derived>
963 template<typename OtherDerived>
966 {
967  return typename CwiseProductDenseReturnType<OtherDerived>::Type(derived(), other.derived());
968 }
969 
970 template<typename DenseDerived, typename SparseDerived>
971 EIGEN_STRONG_INLINE const CwiseBinaryOp<internal::scalar_sum_op<typename DenseDerived::Scalar,typename SparseDerived::Scalar>, const DenseDerived, const SparseDerived>
973 {
974  return CwiseBinaryOp<internal::scalar_sum_op<typename DenseDerived::Scalar,typename SparseDerived::Scalar>, const DenseDerived, const SparseDerived>(a.derived(), b.derived());
975 }
976 
977 template<typename SparseDerived, typename DenseDerived>
978 EIGEN_STRONG_INLINE const CwiseBinaryOp<internal::scalar_sum_op<typename SparseDerived::Scalar,typename DenseDerived::Scalar>, const SparseDerived, const DenseDerived>
980 {
981  return CwiseBinaryOp<internal::scalar_sum_op<typename SparseDerived::Scalar,typename DenseDerived::Scalar>, const SparseDerived, const DenseDerived>(a.derived(), b.derived());
982 }
983 
984 template<typename DenseDerived, typename SparseDerived>
985 EIGEN_STRONG_INLINE const CwiseBinaryOp<internal::scalar_difference_op<typename DenseDerived::Scalar,typename SparseDerived::Scalar>, const DenseDerived, const SparseDerived>
987 {
989 }
990 
991 template<typename SparseDerived, typename DenseDerived>
992 EIGEN_STRONG_INLINE const CwiseBinaryOp<internal::scalar_difference_op<typename SparseDerived::Scalar,typename DenseDerived::Scalar>, const SparseDerived, const DenseDerived>
994 {
996 }
997 
998 } // end namespace Eigen
999 
1000 #endif // EIGEN_SPARSE_CWISE_BINARY_OP_H
Array< int, 3, 1 > b
RowXpr row(Index i)
This is the const version of row(). *‍/.
ColXpr col(Index i)
This is the const version of col().
#define eigen_internal_assert(x)
Definition: Macros.h:908
#define EIGEN_SPARSE_PUBLIC_INTERFACE(Derived)
Definition: SparseUtil.h:45
#define EIGEN_STATIC_ASSERT(X, MSG)
Definition: StaticAssert.h:26
#define EIGEN_INTERNAL_CHECK_COST_VALUE(C)
Definition: StaticAssert.h:112
Eigen::Triplet< double > T
Generic expression where a coefficient-wise binary operator is applied to two expressions.
Definition: CwiseBinaryOp.h:86
Base class for diagonal matrices and expressions.
const Derived & derived() const
Base class for all dense matrices, vectors, and expressions.
Definition: MatrixBase.h:52
Base class of any sparse matrices or sparse expressions.
internal::traits< Block< SparseMatrixType, BlockRows, BlockCols, true > >::Scalar Scalar
Derived & operator-=(const SparseMatrixBase< OtherDerived > &other)
Derived & operator+=(const SparseMatrixBase< OtherDerived > &other)
const CwiseProductDenseReturnType< OtherDerived >::Type cwiseProduct(const MatrixBase< OtherDerived > &other) const
const unsigned int RowMajorBit
Definition: Constants.h:68
bfloat16 operator++(bfloat16 &a)
Definition: BFloat16.h:298
bfloat16() min(const bfloat16 &a, const bfloat16 &b)
Definition: BFloat16.h:684
void call_assignment(Dst &dst, const Src &src)
EIGEN_CONSTEXPR void call_assignment_no_alias(Dst &dst, const Src &src, const Func &func)
: InteropHeaders
Definition: Core:139
const CwiseBinaryOp< internal::scalar_difference_op< typename DenseDerived::Scalar, typename SparseDerived::Scalar >, const DenseDerived, const SparseDerived > operator-(const MatrixBase< DenseDerived > &a, const SparseMatrixBase< SparseDerived > &b)
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API.
Definition: Meta.h:82
const CwiseBinaryOp< internal::scalar_sum_op< typename DenseDerived::Scalar, typename SparseDerived::Scalar >, const DenseDerived, const SparseDerived > operator+(const MatrixBase< DenseDerived > &a, const SparseMatrixBase< SparseDerived > &b)
Derived & derived()
Definition: EigenBase.h:48