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 // IWYU pragma: private
14 #include "./InternalHeaderCheck.h"
15 
16 namespace Eigen {
17 
18 // Here we have to handle 3 cases:
19 // 1 - sparse op dense
20 // 2 - dense op sparse
21 // 3 - sparse op sparse
22 // We also need to implement a 4th iterator for:
23 // 4 - dense op dense
24 // Finally, we also need to distinguish between the product and other operations :
25 // configuration returned mode
26 // 1 - sparse op dense product sparse
27 // generic dense
28 // 2 - dense op sparse product sparse
29 // generic dense
30 // 3 - sparse op sparse product sparse
31 // generic sparse
32 // 4 - dense op dense product dense
33 // generic dense
34 //
35 // TODO to ease compiler job, we could specialize product/quotient with a scalar
36 // and fallback to cwise-unary evaluator using bind1st_op and bind2nd_op.
37 
38 template <typename BinaryOp, typename Lhs, typename Rhs>
39 class CwiseBinaryOpImpl<BinaryOp, Lhs, Rhs, Sparse> : public SparseMatrixBase<CwiseBinaryOp<BinaryOp, Lhs, Rhs> > {
40  public:
48  THE_STORAGE_ORDER_OF_BOTH_SIDES_MUST_MATCH)
49 };
50 
51 namespace internal {
52 
53 // The default evaluator performs an "arithmetic" operation on two input arrays.
54 // Given input arrays 'lhs' and 'rhs' and binary functor 'func',
55 // the sparse destination array 'dst' is evaluated as follows:
56 // if lhs(i,j) and rhs(i,j) are present, dst(i,j) = func(lhs(i,j), rhs(i,j))
57 // if lhs(i,j) is present and rhs(i,j) is null, dst(i,j) = func(lhs(i,j), 0)
58 // if lhs(i,j) is null and rhs(i,j) is present, dst(i,j) = func(0, rhs(i,j))
59 
60 // Generic "sparse OP sparse"
61 template <typename XprType>
63 
64 template <typename BinaryOp, typename Lhs, typename Rhs>
66  : evaluator_base<CwiseBinaryOp<BinaryOp, Lhs, Rhs> > {
67  protected:
71  typedef typename traits<XprType>::Scalar Scalar;
72  typedef typename XprType::StorageIndex StorageIndex;
73 
74  public:
75  class InnerIterator {
76  public:
78  : m_lhsIter(aEval.m_lhsImpl, outer),
79  m_rhsIter(aEval.m_rhsImpl, outer),
80  m_functor(aEval.m_functor),
81  m_value(Scalar(0)) {
82  this->operator++();
83  }
84 
86  if (m_lhsIter && m_rhsIter && (m_lhsIter.index() == m_rhsIter.index())) {
87  m_id = m_lhsIter.index();
88  m_value = m_functor(m_lhsIter.value(), m_rhsIter.value());
89  ++m_lhsIter;
90  ++m_rhsIter;
91  } else if (m_lhsIter && (!m_rhsIter || (m_lhsIter.index() < m_rhsIter.index()))) {
92  m_id = m_lhsIter.index();
93  m_value = m_functor(m_lhsIter.value(), Scalar(0));
94  ++m_lhsIter;
95  } else if (m_rhsIter && (!m_lhsIter || (m_lhsIter.index() > m_rhsIter.index()))) {
96  m_id = m_rhsIter.index();
97  m_value = m_functor(Scalar(0), m_rhsIter.value());
98  ++m_rhsIter;
99  } else {
100  m_id = -1;
101  }
102  return *this;
103  }
104 
105  EIGEN_STRONG_INLINE Scalar value() const { return m_value; }
106 
107  EIGEN_STRONG_INLINE StorageIndex index() const { return m_id; }
108  EIGEN_STRONG_INLINE Index outer() const { return m_lhsIter.outer(); }
109  EIGEN_STRONG_INLINE Index row() const { return Lhs::IsRowMajor ? m_lhsIter.row() : index(); }
110  EIGEN_STRONG_INLINE Index col() const { return Lhs::IsRowMajor ? index() : m_lhsIter.col(); }
111 
112  EIGEN_STRONG_INLINE operator bool() const { return m_id >= 0; }
113 
114  protected:
117  const BinaryOp& m_functor;
120  };
121 
122  enum {
123  CoeffReadCost =
125  Flags = XprType::Flags
126  };
127 
128  explicit binary_evaluator(const XprType& xpr) : m_functor(xpr.functor()), m_lhsImpl(xpr.lhs()), m_rhsImpl(xpr.rhs()) {
130  EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
131  }
132 
133  inline Index nonZerosEstimate() const { return m_lhsImpl.nonZerosEstimate() + m_rhsImpl.nonZerosEstimate(); }
134 
135  protected:
136  const BinaryOp m_functor;
139 };
140 
141 // dense op sparse
142 template <typename BinaryOp, typename Lhs, typename Rhs>
144  : evaluator_base<CwiseBinaryOp<BinaryOp, Lhs, Rhs> > {
145  protected:
148  typedef typename traits<XprType>::Scalar Scalar;
149  typedef typename XprType::StorageIndex StorageIndex;
150 
151  public:
153  enum { IsRowMajor = (int(Rhs::Flags) & RowMajorBit) == RowMajorBit };
154 
155  public:
157  : m_lhsEval(aEval.m_lhsImpl),
158  m_rhsIter(aEval.m_rhsImpl, outer),
159  m_functor(aEval.m_functor),
160  m_value(0),
161  m_id(-1),
162  m_innerSize(aEval.m_expr.rhs().innerSize()) {
163  this->operator++();
164  }
165 
167  ++m_id;
168  if (m_id < m_innerSize) {
169  Scalar lhsVal = m_lhsEval.coeff(IsRowMajor ? m_rhsIter.outer() : m_id, IsRowMajor ? m_id : m_rhsIter.outer());
170  if (m_rhsIter && m_rhsIter.index() == m_id) {
171  m_value = m_functor(lhsVal, m_rhsIter.value());
172  ++m_rhsIter;
173  } else
174  m_value = m_functor(lhsVal, Scalar(0));
175  }
176 
177  return *this;
178  }
179 
181  eigen_internal_assert(m_id < m_innerSize);
182  return m_value;
183  }
184 
185  EIGEN_STRONG_INLINE StorageIndex index() const { return m_id; }
186  EIGEN_STRONG_INLINE Index outer() const { return m_rhsIter.outer(); }
187  EIGEN_STRONG_INLINE Index row() const { return IsRowMajor ? m_rhsIter.outer() : m_id; }
188  EIGEN_STRONG_INLINE Index col() const { return IsRowMajor ? m_id : m_rhsIter.outer(); }
189 
190  EIGEN_STRONG_INLINE operator bool() const { return m_id < m_innerSize; }
191 
192  protected:
195  const BinaryOp& m_functor;
199  };
200 
201  enum {
202  CoeffReadCost =
204  Flags = XprType::Flags
205  };
206 
207  explicit binary_evaluator(const XprType& xpr)
208  : m_functor(xpr.functor()), m_lhsImpl(xpr.lhs()), m_rhsImpl(xpr.rhs()), m_expr(xpr) {
210  EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
211  }
212 
213  inline Index nonZerosEstimate() const { return m_expr.size(); }
214 
215  protected:
216  const BinaryOp m_functor;
219  const XprType& m_expr;
220 };
221 
222 // sparse op dense
223 template <typename BinaryOp, typename Lhs, typename Rhs>
225  : evaluator_base<CwiseBinaryOp<BinaryOp, Lhs, Rhs> > {
226  protected:
229  typedef typename traits<XprType>::Scalar Scalar;
230  typedef typename XprType::StorageIndex StorageIndex;
231 
232  public:
234  enum { IsRowMajor = (int(Lhs::Flags) & RowMajorBit) == RowMajorBit };
235 
236  public:
238  : m_lhsIter(aEval.m_lhsImpl, outer),
239  m_rhsEval(aEval.m_rhsImpl),
240  m_functor(aEval.m_functor),
241  m_value(0),
242  m_id(-1),
243  m_innerSize(aEval.m_expr.lhs().innerSize()) {
244  this->operator++();
245  }
246 
248  ++m_id;
249  if (m_id < m_innerSize) {
250  Scalar rhsVal = m_rhsEval.coeff(IsRowMajor ? m_lhsIter.outer() : m_id, IsRowMajor ? m_id : m_lhsIter.outer());
251  if (m_lhsIter && m_lhsIter.index() == m_id) {
252  m_value = m_functor(m_lhsIter.value(), rhsVal);
253  ++m_lhsIter;
254  } else
255  m_value = m_functor(Scalar(0), rhsVal);
256  }
257 
258  return *this;
259  }
260 
262  eigen_internal_assert(m_id < m_innerSize);
263  return m_value;
264  }
265 
266  EIGEN_STRONG_INLINE StorageIndex index() const { return m_id; }
267  EIGEN_STRONG_INLINE Index outer() const { return m_lhsIter.outer(); }
268  EIGEN_STRONG_INLINE Index row() const { return IsRowMajor ? m_lhsIter.outer() : m_id; }
269  EIGEN_STRONG_INLINE Index col() const { return IsRowMajor ? m_id : m_lhsIter.outer(); }
270 
271  EIGEN_STRONG_INLINE operator bool() const { return m_id < m_innerSize; }
272 
273  protected:
276  const BinaryOp& m_functor;
280  };
281 
282  enum {
283  CoeffReadCost =
285  Flags = XprType::Flags
286  };
287 
288  explicit binary_evaluator(const XprType& xpr)
289  : m_functor(xpr.functor()), m_lhsImpl(xpr.lhs()), m_rhsImpl(xpr.rhs()), m_expr(xpr) {
291  EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
292  }
293 
294  inline Index nonZerosEstimate() const { return m_expr.size(); }
295 
296  protected:
297  const BinaryOp m_functor;
300  const XprType& m_expr;
301 };
302 
303 template <typename T, typename LhsKind = typename evaluator_traits<typename T::Lhs>::Kind,
304  typename RhsKind = typename evaluator_traits<typename T::Rhs>::Kind,
305  typename LhsScalar = typename traits<typename T::Lhs>::Scalar,
306  typename RhsScalar = typename traits<typename T::Rhs>::Scalar>
308 
309 // "sparse .* sparse"
310 template <typename T1, typename T2, typename Lhs, typename Rhs>
312  : sparse_conjunction_evaluator<CwiseBinaryOp<scalar_product_op<T1, T2>, Lhs, Rhs> > {
315  explicit binary_evaluator(const XprType& xpr) : Base(xpr) {}
316 };
317 // "dense .* sparse"
318 template <typename T1, typename T2, typename Lhs, typename Rhs>
320  : sparse_conjunction_evaluator<CwiseBinaryOp<scalar_product_op<T1, T2>, Lhs, Rhs> > {
323  explicit binary_evaluator(const XprType& xpr) : Base(xpr) {}
324 };
325 // "sparse .* dense"
326 template <typename T1, typename T2, typename Lhs, typename Rhs>
328  : sparse_conjunction_evaluator<CwiseBinaryOp<scalar_product_op<T1, T2>, Lhs, Rhs> > {
331  explicit binary_evaluator(const XprType& xpr) : Base(xpr) {}
332 };
333 
334 // "sparse ./ dense"
335 template <typename T1, typename T2, typename Lhs, typename Rhs>
337  : sparse_conjunction_evaluator<CwiseBinaryOp<scalar_quotient_op<T1, T2>, Lhs, Rhs> > {
340  explicit binary_evaluator(const XprType& xpr) : Base(xpr) {}
341 };
342 
343 // "sparse && sparse"
344 template <typename Lhs, typename Rhs>
346  : sparse_conjunction_evaluator<CwiseBinaryOp<scalar_boolean_and_op<bool>, Lhs, Rhs> > {
349  explicit binary_evaluator(const XprType& xpr) : Base(xpr) {}
350 };
351 // "dense && sparse"
352 template <typename Lhs, typename Rhs>
354  : sparse_conjunction_evaluator<CwiseBinaryOp<scalar_boolean_and_op<bool>, Lhs, Rhs> > {
357  explicit binary_evaluator(const XprType& xpr) : Base(xpr) {}
358 };
359 // "sparse && dense"
360 template <typename Lhs, typename Rhs>
362  : sparse_conjunction_evaluator<CwiseBinaryOp<scalar_boolean_and_op<bool>, Lhs, Rhs> > {
365  explicit binary_evaluator(const XprType& xpr) : Base(xpr) {}
366 };
367 
368 // The conjunction "^" evaluator performs a logical "and" or set "intersection" operation on two input arrays.
369 // Given input arrays 'lhs' and 'rhs' and binary functor 'func',
370 // the sparse destination array 'dst' is evaluated as follows:
371 // if lhs(i,j) and rhs(i,j) are present, dst(i,j) = func(lhs(i,j), rhs(i,j))
372 // if lhs(i,j) is present and rhs(i,j) is null, dst(i,j) is null
373 // if lhs(i,j) is null and rhs(i,j) is present, dst(i,j) is null
374 
375 // "sparse ^ sparse"
376 template <typename XprType>
378  protected:
379  typedef typename XprType::Functor BinaryOp;
380  typedef typename XprType::Lhs LhsArg;
381  typedef typename XprType::Rhs RhsArg;
384  typedef typename XprType::StorageIndex StorageIndex;
385  typedef typename traits<XprType>::Scalar Scalar;
386 
387  public:
389  public:
391  : m_lhsIter(aEval.m_lhsImpl, outer), m_rhsIter(aEval.m_rhsImpl, outer), m_functor(aEval.m_functor) {
392  while (m_lhsIter && m_rhsIter && (m_lhsIter.index() != m_rhsIter.index())) {
393  if (m_lhsIter.index() < m_rhsIter.index())
394  ++m_lhsIter;
395  else
396  ++m_rhsIter;
397  }
398  }
399 
401  ++m_lhsIter;
402  ++m_rhsIter;
403  while (m_lhsIter && m_rhsIter && (m_lhsIter.index() != m_rhsIter.index())) {
404  if (m_lhsIter.index() < m_rhsIter.index())
405  ++m_lhsIter;
406  else
407  ++m_rhsIter;
408  }
409  return *this;
410  }
411 
412  EIGEN_STRONG_INLINE Scalar value() const { return m_functor(m_lhsIter.value(), m_rhsIter.value()); }
413 
414  EIGEN_STRONG_INLINE StorageIndex index() const { return m_lhsIter.index(); }
415  EIGEN_STRONG_INLINE Index outer() const { return m_lhsIter.outer(); }
416  EIGEN_STRONG_INLINE Index row() const { return m_lhsIter.row(); }
417  EIGEN_STRONG_INLINE Index col() const { return m_lhsIter.col(); }
418 
419  EIGEN_STRONG_INLINE operator bool() const { return (m_lhsIter && m_rhsIter); }
420 
421  protected:
425  };
426 
427  enum {
430  Flags = XprType::Flags
431  };
432 
434  : m_functor(xpr.functor()), m_lhsImpl(xpr.lhs()), m_rhsImpl(xpr.rhs()) {
436  EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
437  }
438 
439  inline Index nonZerosEstimate() const {
440  return (std::min)(m_lhsImpl.nonZerosEstimate(), m_rhsImpl.nonZerosEstimate());
441  }
442 
443  protected:
447 };
448 
449 // "dense ^ sparse"
450 template <typename XprType>
452  protected:
453  typedef typename XprType::Functor BinaryOp;
454  typedef typename XprType::Lhs LhsArg;
455  typedef typename XprType::Rhs RhsArg;
458  typedef typename XprType::StorageIndex StorageIndex;
459  typedef typename traits<XprType>::Scalar Scalar;
460 
461  public:
463  enum { IsRowMajor = (int(RhsArg::Flags) & RowMajorBit) == RowMajorBit };
464 
465  public:
467  : m_lhsEval(aEval.m_lhsImpl), m_rhsIter(aEval.m_rhsImpl, outer), m_functor(aEval.m_functor), m_outer(outer) {}
468 
470  ++m_rhsIter;
471  return *this;
472  }
473 
475  return m_functor(
476  m_lhsEval.coeff(IsRowMajor ? m_outer : m_rhsIter.index(), IsRowMajor ? m_rhsIter.index() : m_outer),
477  m_rhsIter.value());
478  }
479 
480  EIGEN_STRONG_INLINE StorageIndex index() const { return m_rhsIter.index(); }
481  EIGEN_STRONG_INLINE Index outer() const { return m_rhsIter.outer(); }
482  EIGEN_STRONG_INLINE Index row() const { return m_rhsIter.row(); }
483  EIGEN_STRONG_INLINE Index col() const { return m_rhsIter.col(); }
484 
485  EIGEN_STRONG_INLINE operator bool() const { return m_rhsIter; }
486 
487  protected:
491  const Index m_outer;
492  };
493 
494  enum {
497  Flags = XprType::Flags
498  };
499 
501  : m_functor(xpr.functor()), m_lhsImpl(xpr.lhs()), m_rhsImpl(xpr.rhs()) {
503  EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
504  }
505 
506  inline Index nonZerosEstimate() const { return m_rhsImpl.nonZerosEstimate(); }
507 
508  protected:
512 };
513 
514 // "sparse ^ dense"
515 template <typename XprType>
517  protected:
518  typedef typename XprType::Functor BinaryOp;
519  typedef typename XprType::Lhs LhsArg;
520  typedef typename XprType::Rhs RhsArg;
523  typedef typename XprType::StorageIndex StorageIndex;
524  typedef typename traits<XprType>::Scalar Scalar;
525 
526  public:
528  enum { IsRowMajor = (int(LhsArg::Flags) & RowMajorBit) == RowMajorBit };
529 
530  public:
532  : m_lhsIter(aEval.m_lhsImpl, outer), m_rhsEval(aEval.m_rhsImpl), m_functor(aEval.m_functor), m_outer(outer) {}
533 
535  ++m_lhsIter;
536  return *this;
537  }
538 
540  return m_functor(m_lhsIter.value(), m_rhsEval.coeff(IsRowMajor ? m_outer : m_lhsIter.index(),
541  IsRowMajor ? m_lhsIter.index() : m_outer));
542  }
543 
544  EIGEN_STRONG_INLINE StorageIndex index() const { return m_lhsIter.index(); }
545  EIGEN_STRONG_INLINE Index outer() const { return m_lhsIter.outer(); }
546  EIGEN_STRONG_INLINE Index row() const { return m_lhsIter.row(); }
547  EIGEN_STRONG_INLINE Index col() const { return m_lhsIter.col(); }
548 
549  EIGEN_STRONG_INLINE operator bool() const { return m_lhsIter; }
550 
551  protected:
555  const Index m_outer;
556  };
557 
558  enum {
561  Flags = XprType::Flags
562  };
563 
565  : m_functor(xpr.functor()), m_lhsImpl(xpr.lhs()), m_rhsImpl(xpr.rhs()) {
567  EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
568  }
569 
570  inline Index nonZerosEstimate() const { return m_lhsImpl.nonZerosEstimate(); }
571 
572  protected:
576 };
577 
578 template <typename T, typename LhsKind = typename evaluator_traits<typename T::Lhs>::Kind,
579  typename RhsKind = typename evaluator_traits<typename T::Rhs>::Kind,
580  typename LhsScalar = typename traits<typename T::Lhs>::Scalar,
581  typename RhsScalar = typename traits<typename T::Rhs>::Scalar>
583 
584 // The disjunction "v" evaluator performs a logical "or" or set "union" operation on two input arrays.
585 // Given input arrays 'lhs' and 'rhs' and binary functor 'func',
586 // the sparse destination array 'dst' is evaluated as follows:
587 // if lhs(i,j) and rhs(i,j) are present, dst(i,j) = func(lhs(i,j), rhs(i,j))
588 // if lhs(i,j) is present and rhs(i,j) is null, dst(i,j) = lhs(i,j)
589 // if lhs(i,j) is null and rhs(i,j) is present, dst(i,j) = rhs(i,j)
590 
591 // "sparse v sparse"
592 template <typename XprType>
594  protected:
595  typedef typename XprType::Functor BinaryOp;
596  typedef typename XprType::Lhs LhsArg;
597  typedef typename XprType::Rhs RhsArg;
600  typedef typename XprType::StorageIndex StorageIndex;
601  typedef typename traits<XprType>::Scalar Scalar;
602 
603  public:
605  public:
607  : m_lhsIter(aEval.m_lhsImpl, outer),
608  m_rhsIter(aEval.m_rhsImpl, outer),
609  m_functor(aEval.m_functor),
610  m_value(Scalar(0)) {
611  this->operator++();
612  }
613 
615  if (m_lhsIter && m_rhsIter && (m_lhsIter.index() == m_rhsIter.index())) {
616  m_id = m_lhsIter.index();
617  m_value = m_functor(m_lhsIter.value(), m_rhsIter.value());
618  ++m_lhsIter;
619  ++m_rhsIter;
620  } else if (m_lhsIter && (!m_rhsIter || (m_lhsIter.index() < m_rhsIter.index()))) {
621  m_id = m_lhsIter.index();
622  m_value = m_lhsIter.value();
623  ++m_lhsIter;
624  } else if (m_rhsIter && (!m_lhsIter || (m_lhsIter.index() > m_rhsIter.index()))) {
625  m_id = m_rhsIter.index();
626  m_value = m_rhsIter.value();
627  ++m_rhsIter;
628  } else {
629  m_id = -1;
630  }
631  return *this;
632  }
633 
634  EIGEN_STRONG_INLINE Scalar value() const { return m_value; }
635 
636  EIGEN_STRONG_INLINE StorageIndex index() const { return m_id; }
637  EIGEN_STRONG_INLINE Index outer() const { return m_lhsIter.outer(); }
638  EIGEN_STRONG_INLINE Index row() const { return LhsArg::IsRowMajor ? m_lhsIter.row() : index(); }
639  EIGEN_STRONG_INLINE Index col() const { return LhsArg::IsRowMajor ? index() : m_lhsIter.col(); }
640 
641  EIGEN_STRONG_INLINE operator bool() const { return m_id >= 0; }
642 
643  protected:
649  };
650 
651  enum {
654  Flags = XprType::Flags
655  };
656 
658  : m_functor(xpr.functor()), m_lhsImpl(xpr.lhs()), m_rhsImpl(xpr.rhs()) {
660  EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
661  }
662 
663  inline Index nonZerosEstimate() const { return m_lhsImpl.nonZerosEstimate() + m_rhsImpl.nonZerosEstimate(); }
664 
665  protected:
669 };
670 
671 // "dense v sparse"
672 template <typename XprType>
674  protected:
675  typedef typename XprType::Functor BinaryOp;
676  typedef typename XprType::Lhs LhsArg;
677  typedef typename XprType::Rhs RhsArg;
680  typedef typename XprType::StorageIndex StorageIndex;
681  typedef typename traits<XprType>::Scalar Scalar;
682 
683  public:
685  enum { IsRowMajor = (int(RhsArg::Flags) & RowMajorBit) == RowMajorBit };
686 
687  public:
689  : m_lhsEval(aEval.m_lhsImpl),
690  m_rhsIter(aEval.m_rhsImpl, outer),
691  m_functor(aEval.m_functor),
692  m_value(0),
693  m_id(-1),
694  m_innerSize(aEval.m_expr.rhs().innerSize()) {
695  this->operator++();
696  }
697 
699  ++m_id;
700  if (m_id < m_innerSize) {
701  Scalar lhsVal = m_lhsEval.coeff(IsRowMajor ? m_rhsIter.outer() : m_id, IsRowMajor ? m_id : m_rhsIter.outer());
702  if (m_rhsIter && m_rhsIter.index() == m_id) {
703  m_value = m_functor(lhsVal, m_rhsIter.value());
704  ++m_rhsIter;
705  } else
706  m_value = lhsVal;
707  }
708 
709  return *this;
710  }
711 
713  eigen_internal_assert(m_id < m_innerSize);
714  return m_value;
715  }
716 
717  EIGEN_STRONG_INLINE StorageIndex index() const { return m_id; }
718  EIGEN_STRONG_INLINE Index outer() const { return m_rhsIter.outer(); }
719  EIGEN_STRONG_INLINE Index row() const { return IsRowMajor ? m_rhsIter.outer() : m_id; }
720  EIGEN_STRONG_INLINE Index col() const { return IsRowMajor ? m_id : m_rhsIter.outer(); }
721 
722  EIGEN_STRONG_INLINE operator bool() const { return m_id < m_innerSize; }
723 
724  protected:
731  };
732 
733  enum {
736  Flags = XprType::Flags
737  };
738 
740  : m_functor(xpr.functor()), m_lhsImpl(xpr.lhs()), m_rhsImpl(xpr.rhs()), m_expr(xpr) {
742  EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
743  }
744 
745  inline Index nonZerosEstimate() const { return m_expr.size(); }
746 
747  protected:
751  const XprType& m_expr;
752 };
753 
754 // "sparse v dense"
755 template <typename XprType>
757  protected:
758  typedef typename XprType::Functor BinaryOp;
759  typedef typename XprType::Lhs LhsArg;
760  typedef typename XprType::Rhs RhsArg;
763  typedef typename XprType::StorageIndex StorageIndex;
764  typedef typename traits<XprType>::Scalar Scalar;
765 
766  public:
768  enum { IsRowMajor = (int(LhsArg::Flags) & RowMajorBit) == RowMajorBit };
769 
770  public:
772  : m_lhsIter(aEval.m_lhsImpl, outer),
773  m_rhsEval(aEval.m_rhsImpl),
774  m_functor(aEval.m_functor),
775  m_value(0),
776  m_id(-1),
777  m_innerSize(aEval.m_expr.lhs().innerSize()) {
778  this->operator++();
779  }
780 
782  ++m_id;
783  if (m_id < m_innerSize) {
784  Scalar rhsVal = m_rhsEval.coeff(IsRowMajor ? m_lhsIter.outer() : m_id, IsRowMajor ? m_id : m_lhsIter.outer());
785  if (m_lhsIter && m_lhsIter.index() == m_id) {
786  m_value = m_functor(m_lhsIter.value(), rhsVal);
787  ++m_lhsIter;
788  } else
789  m_value = rhsVal;
790  }
791 
792  return *this;
793  }
794 
796  eigen_internal_assert(m_id < m_innerSize);
797  return m_value;
798  }
799 
800  EIGEN_STRONG_INLINE StorageIndex index() const { return m_id; }
801  EIGEN_STRONG_INLINE Index outer() const { return m_lhsIter.outer(); }
802  EIGEN_STRONG_INLINE Index row() const { return IsRowMajor ? m_lhsIter.outer() : m_id; }
803  EIGEN_STRONG_INLINE Index col() const { return IsRowMajor ? m_id : m_lhsIter.outer(); }
804 
805  EIGEN_STRONG_INLINE operator bool() const { return m_id < m_innerSize; }
806 
807  protected:
814  };
815 
816  enum {
819  Flags = XprType::Flags
820  };
821 
823  : m_functor(xpr.functor()), m_lhsImpl(xpr.lhs()), m_rhsImpl(xpr.rhs()), m_expr(xpr) {
825  EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
826  }
827 
828  inline Index nonZerosEstimate() const { return m_expr.size(); }
829 
830  protected:
834  const XprType& m_expr;
835 };
836 
837 // when DupFunc is wrapped with scalar_dup_op, use disjunction evaluator
838 template <typename T1, typename T2, typename DupFunc, typename Lhs, typename Rhs>
840  : sparse_disjunction_evaluator<CwiseBinaryOp<scalar_disjunction_op<DupFunc, T1, T2>, Lhs, Rhs> > {
843  explicit binary_evaluator(const XprType& xpr) : Base(xpr) {}
844 };
845 } // namespace internal
846 
847 /***************************************************************************
848  * Implementation of SparseMatrixBase and SparseCwise functions/operators
849  ***************************************************************************/
850 
851 template <typename Derived>
852 template <typename OtherDerived>
855  return derived();
856 }
857 
858 template <typename Derived>
859 template <typename OtherDerived>
862  return derived();
863 }
864 
865 template <typename Derived>
866 template <typename OtherDerived>
868  return derived() = derived() - other.derived();
869 }
870 
871 template <typename Derived>
872 template <typename OtherDerived>
874  return derived() = derived() + other.derived();
875 }
876 
877 template <typename Derived>
878 template <typename OtherDerived>
880  call_assignment_no_alias(derived(), other.derived(),
882  return derived();
883 }
884 
885 template <typename Derived>
886 template <typename OtherDerived>
888  call_assignment_no_alias(derived(), other.derived(),
890  return derived();
891 }
892 
893 template <typename Derived>
894 template <typename OtherDerived>
897  return typename CwiseProductDenseReturnType<OtherDerived>::Type(derived(), other.derived());
898 }
899 
900 template <typename DenseDerived, typename SparseDerived>
903  const DenseDerived, const SparseDerived>
906  const DenseDerived, const SparseDerived>(a.derived(), b.derived());
907 }
908 
909 template <typename SparseDerived, typename DenseDerived>
911  CwiseBinaryOp<internal::scalar_sum_op<typename SparseDerived::Scalar, typename DenseDerived::Scalar>,
912  const SparseDerived, const DenseDerived>
915  const SparseDerived, const DenseDerived>(a.derived(), b.derived());
916 }
917 
918 template <typename DenseDerived, typename SparseDerived>
920  CwiseBinaryOp<internal::scalar_difference_op<typename DenseDerived::Scalar, typename SparseDerived::Scalar>,
921  const DenseDerived, const SparseDerived>
924  const DenseDerived, const SparseDerived>(a.derived(), b.derived());
925 }
926 
927 template <typename SparseDerived, typename DenseDerived>
929  CwiseBinaryOp<internal::scalar_difference_op<typename SparseDerived::Scalar, typename DenseDerived::Scalar>,
930  const SparseDerived, const DenseDerived>
933  const SparseDerived, const DenseDerived>(a.derived(), b.derived());
934 }
935 
936 } // end namespace Eigen
937 
938 #endif // EIGEN_SPARSE_CWISE_BINARY_OP_H
#define eigen_internal_assert(x)
Definition: Macros.h:916
#define EIGEN_STRONG_INLINE
Definition: Macros.h:834
#define EIGEN_SPARSE_PUBLIC_INTERFACE(Derived)
Definition: SparseUtil.h:39
#define EIGEN_STATIC_ASSERT(X, MSG)
Definition: StaticAssert.h:26
#define EIGEN_INTERNAL_CHECK_COST_VALUE(C)
Definition: StaticAssert.h:101
Scalar * b
Definition: benchVecAdd.cpp:17
SCALAR Scalar
Definition: bench_gemm.cpp:45
CwiseBinaryOp< BinaryOp, Lhs, Rhs > Derived
Definition: SparseCwiseBinaryOp.h:41
SparseMatrixBase< Derived > Base
Definition: SparseCwiseBinaryOp.h:42
Definition: CwiseBinaryOp.h:137
Generic expression where a coefficient-wise binary operator is applied to two expressions.
Definition: CwiseBinaryOp.h:79
internal::remove_all_t< LhsType > Lhs
Definition: CwiseBinaryOp.h:82
internal::remove_all_t< RhsType > Rhs
Definition: CwiseBinaryOp.h:83
internal::remove_all_t< BinaryOp > Functor
Definition: CwiseBinaryOp.h:81
Base class for diagonal matrices and expressions.
Definition: DiagonalMatrix.h:33
EIGEN_DEVICE_FUNC const Derived & derived() const
Definition: DiagonalMatrix.h:57
An InnerIterator allows to loop over the element of any matrix expression.
Definition: CoreIterators.h:37
EIGEN_STRONG_INLINE Index index() const
Definition: CoreIterators.h:67
Base class for all dense matrices, vectors, and expressions.
Definition: MatrixBase.h:52
Base class of any sparse matrices or sparse expressions.
Definition: SparseMatrixBase.h:30
Derived & operator-=(const SparseMatrixBase< OtherDerived > &other)
Derived & operator+=(const SparseMatrixBase< OtherDerived > &other)
EIGEN_STRONG_INLINE const CwiseProductDenseReturnType< OtherDerived >::Type cwiseProduct(const MatrixBase< OtherDerived > &other) const
const Derived & derived() const
Definition: SparseMatrixBase.h:144
EIGEN_STRONG_INLINE InnerIterator(const binary_evaluator &aEval, Index outer)
Definition: SparseCwiseBinaryOp.h:156
EIGEN_STRONG_INLINE InnerIterator & operator++()
Definition: SparseCwiseBinaryOp.h:166
EIGEN_STRONG_INLINE StorageIndex index() const
Definition: SparseCwiseBinaryOp.h:185
EIGEN_STRONG_INLINE StorageIndex index() const
Definition: SparseCwiseBinaryOp.h:107
EIGEN_STRONG_INLINE InnerIterator(const binary_evaluator &aEval, Index outer)
Definition: SparseCwiseBinaryOp.h:77
EIGEN_STRONG_INLINE InnerIterator(const binary_evaluator &aEval, Index outer)
Definition: SparseCwiseBinaryOp.h:237
EIGEN_STRONG_INLINE InnerIterator & operator++()
Definition: SparseCwiseBinaryOp.h:247
EIGEN_STRONG_INLINE StorageIndex index() const
Definition: SparseCwiseBinaryOp.h:266
EIGEN_STRONG_INLINE StorageIndex index() const
Definition: SparseCwiseBinaryOp.h:480
EIGEN_STRONG_INLINE Index outer() const
Definition: SparseCwiseBinaryOp.h:481
EIGEN_STRONG_INLINE InnerIterator(const sparse_conjunction_evaluator &aEval, Index outer)
Definition: SparseCwiseBinaryOp.h:466
EIGEN_STRONG_INLINE Index row() const
Definition: SparseCwiseBinaryOp.h:482
EIGEN_STRONG_INLINE Index col() const
Definition: SparseCwiseBinaryOp.h:483
EIGEN_STRONG_INLINE InnerIterator & operator++()
Definition: SparseCwiseBinaryOp.h:469
EIGEN_STRONG_INLINE Scalar value() const
Definition: SparseCwiseBinaryOp.h:474
EIGEN_STRONG_INLINE Index col() const
Definition: SparseCwiseBinaryOp.h:547
EIGEN_STRONG_INLINE StorageIndex index() const
Definition: SparseCwiseBinaryOp.h:544
EIGEN_STRONG_INLINE Index row() const
Definition: SparseCwiseBinaryOp.h:546
EIGEN_STRONG_INLINE InnerIterator(const sparse_conjunction_evaluator &aEval, Index outer)
Definition: SparseCwiseBinaryOp.h:531
const evaluator< RhsArg > & m_rhsEval
Definition: SparseCwiseBinaryOp.h:553
EIGEN_STRONG_INLINE Scalar value() const
Definition: SparseCwiseBinaryOp.h:539
EIGEN_STRONG_INLINE InnerIterator & operator++()
Definition: SparseCwiseBinaryOp.h:534
EIGEN_STRONG_INLINE Index outer() const
Definition: SparseCwiseBinaryOp.h:545
EIGEN_STRONG_INLINE Scalar value() const
Definition: SparseCwiseBinaryOp.h:412
EIGEN_STRONG_INLINE Index col() const
Definition: SparseCwiseBinaryOp.h:417
EIGEN_STRONG_INLINE Index outer() const
Definition: SparseCwiseBinaryOp.h:415
EIGEN_STRONG_INLINE InnerIterator & operator++()
Definition: SparseCwiseBinaryOp.h:400
EIGEN_STRONG_INLINE StorageIndex index() const
Definition: SparseCwiseBinaryOp.h:414
EIGEN_STRONG_INLINE InnerIterator(const sparse_conjunction_evaluator &aEval, Index outer)
Definition: SparseCwiseBinaryOp.h:390
EIGEN_STRONG_INLINE Index row() const
Definition: SparseCwiseBinaryOp.h:416
EIGEN_STRONG_INLINE InnerIterator & operator++()
Definition: SparseCwiseBinaryOp.h:698
const evaluator< LhsArg > & m_lhsEval
Definition: SparseCwiseBinaryOp.h:725
EIGEN_STRONG_INLINE InnerIterator(const sparse_disjunction_evaluator &aEval, Index outer)
Definition: SparseCwiseBinaryOp.h:688
EIGEN_STRONG_INLINE Scalar value() const
Definition: SparseCwiseBinaryOp.h:712
EIGEN_STRONG_INLINE Index col() const
Definition: SparseCwiseBinaryOp.h:720
EIGEN_STRONG_INLINE Index outer() const
Definition: SparseCwiseBinaryOp.h:718
EIGEN_STRONG_INLINE Index row() const
Definition: SparseCwiseBinaryOp.h:719
EIGEN_STRONG_INLINE StorageIndex index() const
Definition: SparseCwiseBinaryOp.h:717
EIGEN_STRONG_INLINE StorageIndex index() const
Definition: SparseCwiseBinaryOp.h:800
EIGEN_STRONG_INLINE Scalar value() const
Definition: SparseCwiseBinaryOp.h:795
EIGEN_STRONG_INLINE InnerIterator & operator++()
Definition: SparseCwiseBinaryOp.h:781
const evaluator< RhsArg > & m_rhsEval
Definition: SparseCwiseBinaryOp.h:809
EIGEN_STRONG_INLINE Index row() const
Definition: SparseCwiseBinaryOp.h:802
EIGEN_STRONG_INLINE Index col() const
Definition: SparseCwiseBinaryOp.h:803
EIGEN_STRONG_INLINE InnerIterator(const sparse_disjunction_evaluator &aEval, Index outer)
Definition: SparseCwiseBinaryOp.h:771
EIGEN_STRONG_INLINE Index outer() const
Definition: SparseCwiseBinaryOp.h:801
EIGEN_STRONG_INLINE Index outer() const
Definition: SparseCwiseBinaryOp.h:637
EIGEN_STRONG_INLINE Index col() const
Definition: SparseCwiseBinaryOp.h:639
EIGEN_STRONG_INLINE Index row() const
Definition: SparseCwiseBinaryOp.h:638
EIGEN_STRONG_INLINE InnerIterator(const sparse_disjunction_evaluator &aEval, Index outer)
Definition: SparseCwiseBinaryOp.h:606
EIGEN_STRONG_INLINE Scalar value() const
Definition: SparseCwiseBinaryOp.h:634
EIGEN_STRONG_INLINE StorageIndex index() const
Definition: SparseCwiseBinaryOp.h:636
EIGEN_STRONG_INLINE InnerIterator & operator++()
Definition: SparseCwiseBinaryOp.h:614
#define min(a, b)
Definition: datatypes.h:22
const unsigned int RowMajorBit
Definition: Constants.h:70
return int(ret)+1
const Scalar * a
Definition: level2_cplx_impl.h:32
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bfloat16 operator++(bfloat16 &a)
Definition: BFloat16.h:307
@ Lhs
Definition: TensorContractionMapper.h:20
@ Rhs
Definition: TensorContractionMapper.h:20
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void call_assignment(Dst &dst, const Src &src)
Definition: AssignEvaluator.h:781
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR void call_assignment_no_alias(Dst &dst, const Src &src, const Func &func)
Definition: AssignEvaluator.h:812
Namespace containing all symbols from the Eigen library.
Definition: bench_norm.cpp:70
squared absolute value
Definition: GlobalFunctions.h:87
EIGEN_STRONG_INLINE 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)
Definition: SparseCwiseBinaryOp.h:922
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API.
Definition: Meta.h:83
EIGEN_STRONG_INLINE 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)
Definition: SparseCwiseBinaryOp.h:904
Extend namespace for flags.
Definition: fsi_chan_precond_driver.cc:56
Definition: Eigen_Colamd.h:49
Type
Type of JSON value.
Definition: rapidjson.h:513
Definition: EigenBase.h:33
constexpr EIGEN_DEVICE_FUNC Derived & derived()
Definition: EigenBase.h:49
Definition: Constants.h:522
Definition: Constants.h:577
Definition: Constants.h:580
Template functor for scalar/packet assignment with addition.
Definition: AssignmentFunctors.h:52
Template functor for scalar/packet assignment.
Definition: AssignmentFunctors.h:25
CwiseBinaryOp< BinaryOp, Lhs, Rhs > XprType
Definition: SparseCwiseBinaryOp.h:147
evaluator< Rhs >::InnerIterator RhsIterator
Definition: SparseCwiseBinaryOp.h:146
evaluator< Rhs >::InnerIterator RhsIterator
Definition: SparseCwiseBinaryOp.h:69
evaluator< Lhs >::InnerIterator LhsIterator
Definition: SparseCwiseBinaryOp.h:68
CwiseBinaryOp< BinaryOp, Lhs, Rhs > XprType
Definition: SparseCwiseBinaryOp.h:70
evaluator< Lhs >::InnerIterator LhsIterator
Definition: SparseCwiseBinaryOp.h:227
CwiseBinaryOp< BinaryOp, Lhs, Rhs > XprType
Definition: SparseCwiseBinaryOp.h:228
CwiseBinaryOp< scalar_boolean_and_op< bool >, Lhs, Rhs > XprType
Definition: SparseCwiseBinaryOp.h:347
CwiseBinaryOp< scalar_boolean_and_op< bool >, Lhs, Rhs > XprType
Definition: SparseCwiseBinaryOp.h:363
CwiseBinaryOp< scalar_boolean_and_op< bool >, Lhs, Rhs > XprType
Definition: SparseCwiseBinaryOp.h:355
CwiseBinaryOp< scalar_disjunction_op< DupFunc, T1, T2 >, Lhs, Rhs > XprType
Definition: SparseCwiseBinaryOp.h:841
CwiseBinaryOp< scalar_product_op< T1, T2 >, Lhs, Rhs > XprType
Definition: SparseCwiseBinaryOp.h:329
CwiseBinaryOp< scalar_product_op< T1, T2 >, Lhs, Rhs > XprType
Definition: SparseCwiseBinaryOp.h:313
CwiseBinaryOp< scalar_product_op< T1, T2 >, Lhs, Rhs > XprType
Definition: SparseCwiseBinaryOp.h:321
CwiseBinaryOp< scalar_quotient_op< T1, T2 >, Lhs, Rhs > XprType
Definition: SparseCwiseBinaryOp.h:338
Definition: CoreEvaluators.h:78
Definition: SparseCwiseBinaryOp.h:62
Definition: CoreEvaluators.h:118
Definition: CoreEvaluators.h:104
Definition: XprHelper.h:205
Definition: Meta.h:205
Template functor to compute the and of two scalars as if they were booleans.
Definition: BinaryFunctors.h:461
Definition: SparseMatrix.h:1240
Template functor to compute the product of two scalars.
Definition: BinaryFunctors.h:73
Template functor to compute the quotient of two scalars.
Definition: BinaryFunctors.h:430
XprType::Functor BinaryOp
Definition: SparseCwiseBinaryOp.h:453
sparse_conjunction_evaluator(const XprType &xpr)
Definition: SparseCwiseBinaryOp.h:500
traits< XprType >::Scalar Scalar
Definition: SparseCwiseBinaryOp.h:459
evaluator< RhsArg >::InnerIterator RhsIterator
Definition: SparseCwiseBinaryOp.h:457
evaluator< LhsArg > LhsEvaluator
Definition: SparseCwiseBinaryOp.h:456
evaluator< RhsArg > m_rhsImpl
Definition: SparseCwiseBinaryOp.h:511
evaluator< LhsArg > m_lhsImpl
Definition: SparseCwiseBinaryOp.h:510
XprType::StorageIndex StorageIndex
Definition: SparseCwiseBinaryOp.h:458
evaluator< RhsArg > m_rhsImpl
Definition: SparseCwiseBinaryOp.h:575
sparse_conjunction_evaluator(const XprType &xpr)
Definition: SparseCwiseBinaryOp.h:564
XprType::Functor BinaryOp
Definition: SparseCwiseBinaryOp.h:518
XprType::StorageIndex StorageIndex
Definition: SparseCwiseBinaryOp.h:523
evaluator< LhsArg > m_lhsImpl
Definition: SparseCwiseBinaryOp.h:574
traits< XprType >::Scalar Scalar
Definition: SparseCwiseBinaryOp.h:524
evaluator< RhsArg > RhsEvaluator
Definition: SparseCwiseBinaryOp.h:522
evaluator< LhsArg >::InnerIterator LhsIterator
Definition: SparseCwiseBinaryOp.h:521
sparse_conjunction_evaluator(const XprType &xpr)
Definition: SparseCwiseBinaryOp.h:433
traits< XprType >::Scalar Scalar
Definition: SparseCwiseBinaryOp.h:385
evaluator< RhsArg >::InnerIterator RhsIterator
Definition: SparseCwiseBinaryOp.h:383
evaluator< RhsArg > m_rhsImpl
Definition: SparseCwiseBinaryOp.h:446
XprType::StorageIndex StorageIndex
Definition: SparseCwiseBinaryOp.h:384
evaluator< LhsArg > m_lhsImpl
Definition: SparseCwiseBinaryOp.h:445
evaluator< LhsArg >::InnerIterator LhsIterator
Definition: SparseCwiseBinaryOp.h:382
Definition: SparseCwiseBinaryOp.h:307
XprType::Functor BinaryOp
Definition: SparseCwiseBinaryOp.h:675
evaluator< LhsArg > LhsEvaluator
Definition: SparseCwiseBinaryOp.h:678
traits< XprType >::Scalar Scalar
Definition: SparseCwiseBinaryOp.h:681
XprType::StorageIndex StorageIndex
Definition: SparseCwiseBinaryOp.h:680
evaluator< RhsArg >::InnerIterator RhsIterator
Definition: SparseCwiseBinaryOp.h:679
evaluator< LhsArg > m_lhsImpl
Definition: SparseCwiseBinaryOp.h:749
evaluator< RhsArg > m_rhsImpl
Definition: SparseCwiseBinaryOp.h:750
sparse_disjunction_evaluator(const XprType &xpr)
Definition: SparseCwiseBinaryOp.h:739
evaluator< LhsArg >::InnerIterator LhsIterator
Definition: SparseCwiseBinaryOp.h:761
evaluator< RhsArg > m_rhsImpl
Definition: SparseCwiseBinaryOp.h:833
evaluator< LhsArg > m_lhsImpl
Definition: SparseCwiseBinaryOp.h:832
XprType::StorageIndex StorageIndex
Definition: SparseCwiseBinaryOp.h:763
evaluator< RhsArg > RhsEvaluator
Definition: SparseCwiseBinaryOp.h:762
sparse_disjunction_evaluator(const XprType &xpr)
Definition: SparseCwiseBinaryOp.h:822
traits< XprType >::Scalar Scalar
Definition: SparseCwiseBinaryOp.h:764
XprType::Functor BinaryOp
Definition: SparseCwiseBinaryOp.h:758
evaluator< LhsArg > m_lhsImpl
Definition: SparseCwiseBinaryOp.h:667
evaluator< RhsArg > m_rhsImpl
Definition: SparseCwiseBinaryOp.h:668
evaluator< RhsArg >::InnerIterator RhsIterator
Definition: SparseCwiseBinaryOp.h:599
XprType::StorageIndex StorageIndex
Definition: SparseCwiseBinaryOp.h:600
traits< XprType >::Scalar Scalar
Definition: SparseCwiseBinaryOp.h:601
sparse_disjunction_evaluator(const XprType &xpr)
Definition: SparseCwiseBinaryOp.h:657
evaluator< LhsArg >::InnerIterator LhsIterator
Definition: SparseCwiseBinaryOp.h:598
Definition: SparseCwiseBinaryOp.h:582
Template functor for scalar/packet assignment with subtraction.
Definition: AssignmentFunctors.h:73
Definition: ForwardDeclarations.h:21