Eigen  3.2.92
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 namespace 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 
32 template<typename BinaryOp, typename Lhs, typename Rhs>
33 class CwiseBinaryOpImpl<BinaryOp, Lhs, Rhs, Sparse>
34  : public SparseMatrixBase<CwiseBinaryOp<BinaryOp, Lhs, Rhs> >
35 {
36  public:
37  typedef CwiseBinaryOp<BinaryOp, Lhs, Rhs> Derived;
38  typedef SparseMatrixBase<Derived> Base;
39  EIGEN_SPARSE_PUBLIC_INTERFACE(Derived)
40  CwiseBinaryOpImpl()
41  {
42  EIGEN_STATIC_ASSERT((
43  (!internal::is_same<typename internal::traits<Lhs>::StorageKind,
44  typename internal::traits<Rhs>::StorageKind>::value)
45  || ((Lhs::Flags&RowMajorBit) == (Rhs::Flags&RowMajorBit))),
46  THE_STORAGE_ORDER_OF_BOTH_SIDES_MUST_MATCH);
47  }
48 };
49 
50 namespace internal {
51 
52 template<typename BinaryOp, typename Lhs, typename Rhs, typename Derived,
53  typename _LhsStorageMode = typename traits<Lhs>::StorageKind,
54  typename _RhsStorageMode = typename traits<Rhs>::StorageKind>
55 class sparse_cwise_binary_op_inner_iterator_selector;
56 
57 } // end namespace internal
58 
59 namespace internal {
60 
61 
62 // Generic "sparse OP sparse"
63 template<typename BinaryOp, typename Lhs, typename Rhs>
64 struct binary_evaluator<CwiseBinaryOp<BinaryOp, Lhs, Rhs>, IteratorBased, IteratorBased>
65  : evaluator_base<CwiseBinaryOp<BinaryOp, Lhs, Rhs> >
66 {
67 protected:
68  typedef typename evaluator<Lhs>::InnerIterator LhsIterator;
69  typedef typename evaluator<Rhs>::InnerIterator RhsIterator;
70  typedef CwiseBinaryOp<BinaryOp, Lhs, Rhs> XprType;
71  typedef typename traits<XprType>::Scalar Scalar;
72  typedef typename XprType::StorageIndex StorageIndex;
73 public:
74 
75  class ReverseInnerIterator;
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)
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 {
133  CoeffReadCost = evaluator<Lhs>::CoeffReadCost + evaluator<Rhs>::CoeffReadCost + 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 // "sparse .* sparse"
157 template<typename T, typename Lhs, typename Rhs>
158 struct binary_evaluator<CwiseBinaryOp<scalar_product_op<T>, Lhs, Rhs>, IteratorBased, IteratorBased>
159  : evaluator_base<CwiseBinaryOp<scalar_product_op<T>, Lhs, Rhs> >
160 {
161 protected:
162  typedef scalar_product_op<T> BinaryOp;
163  typedef typename evaluator<Lhs>::InnerIterator LhsIterator;
164  typedef typename evaluator<Rhs>::InnerIterator RhsIterator;
165  typedef CwiseBinaryOp<BinaryOp, Lhs, Rhs> XprType;
166  typedef typename XprType::StorageIndex StorageIndex;
167  typedef typename traits<XprType>::Scalar Scalar;
168 public:
169 
170  class ReverseInnerIterator;
171  class InnerIterator
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 {
217  CoeffReadCost = evaluator<Lhs>::CoeffReadCost + evaluator<Rhs>::CoeffReadCost + functor_traits<BinaryOp>::Cost,
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 
234 protected:
235  const BinaryOp m_functor;
236  evaluator<Lhs> m_lhsImpl;
237  evaluator<Rhs> m_rhsImpl;
238 };
239 
240 // "dense .* sparse"
241 template<typename T, typename Lhs, typename Rhs>
242 struct binary_evaluator<CwiseBinaryOp<scalar_product_op<T>, Lhs, Rhs>, IndexBased, IteratorBased>
243  : evaluator_base<CwiseBinaryOp<scalar_product_op<T>, Lhs, Rhs> >
244 {
245 protected:
246  typedef scalar_product_op<T> BinaryOp;
247  typedef evaluator<Lhs> LhsEvaluator;
248  typedef typename evaluator<Rhs>::InnerIterator RhsIterator;
249  typedef CwiseBinaryOp<BinaryOp, Lhs, Rhs> XprType;
250  typedef typename XprType::StorageIndex StorageIndex;
251  typedef typename traits<XprType>::Scalar Scalar;
252 public:
253 
254  class ReverseInnerIterator;
255  class InnerIterator
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 {
289  CoeffReadCost = evaluator<Lhs>::CoeffReadCost + evaluator<Rhs>::CoeffReadCost + functor_traits<BinaryOp>::Cost,
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 
306 protected:
307  const BinaryOp m_functor;
308  evaluator<Lhs> m_lhsImpl;
309  evaluator<Rhs> m_rhsImpl;
310 };
311 
312 // "sparse .* dense"
313 template<typename T, typename Lhs, typename Rhs>
314 struct binary_evaluator<CwiseBinaryOp<scalar_product_op<T>, Lhs, Rhs>, IteratorBased, IndexBased>
315  : evaluator_base<CwiseBinaryOp<scalar_product_op<T>, Lhs, Rhs> >
316 {
317 protected:
318  typedef scalar_product_op<T> BinaryOp;
319  typedef typename evaluator<Lhs>::InnerIterator LhsIterator;
320  typedef evaluator<Rhs> RhsEvaluator;
321  typedef CwiseBinaryOp<BinaryOp, Lhs, Rhs> XprType;
322  typedef typename XprType::StorageIndex StorageIndex;
323  typedef typename traits<XprType>::Scalar Scalar;
324 public:
325 
326  class ReverseInnerIterator;
327  class InnerIterator
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 {
362  CoeffReadCost = evaluator<Lhs>::CoeffReadCost + evaluator<Rhs>::CoeffReadCost + functor_traits<BinaryOp>::Cost,
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 
379 protected:
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 
391 template<typename Derived>
392 template<typename OtherDerived>
393 EIGEN_STRONG_INLINE Derived &
394 SparseMatrixBase<Derived>::operator-=(const SparseMatrixBase<OtherDerived> &other)
395 {
396  return derived() = derived() - other.derived();
397 }
398 
399 template<typename Derived>
400 template<typename OtherDerived>
401 EIGEN_STRONG_INLINE Derived &
402 SparseMatrixBase<Derived>::operator+=(const SparseMatrixBase<OtherDerived>& other)
403 {
404  return derived() = derived() + other.derived();
405 }
406 
407 template<typename Derived>
408 template<typename OtherDerived>
409 Derived& 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 
415 template<typename Derived>
416 template<typename OtherDerived>
417 Derived& 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 
423 template<typename Derived>
424 template<typename OtherDerived>
425 EIGEN_STRONG_INLINE const typename SparseMatrixBase<Derived>::template CwiseProductDenseReturnType<OtherDerived>::Type
426 SparseMatrixBase<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
const CwiseBinaryOp< internal::scalar_product_op< typename Derived::Scalar, typename OtherDerived::Scalar >, const Derived, const OtherDerived > cwiseProduct(const Eigen::SparseMatrixBase< OtherDerived > &other) const
Definition: SparseMatrixBase.h:24
Definition: LDLT.h:16
const unsigned int RowMajorBit
Definition: Constants.h:61
Definition: Eigen_Colamd.h:54