$darkmode
Eigen  5.0.1-dev
Visitor.h
1 // This file is part of Eigen, a lightweight C++ template library
2 // for linear algebra.
3 //
4 // Copyright (C) 2008 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_VISITOR_H
11 #define EIGEN_VISITOR_H
12 
13 // IWYU pragma: private
14 #include "./InternalHeaderCheck.h"
15 
16 namespace Eigen {
17 
18 namespace internal {
19 
20 template <typename Visitor, typename Derived, int UnrollCount,
21  bool Vectorize = (Derived::PacketAccess && functor_traits<Visitor>::PacketAccess), bool LinearAccess = false,
22  bool ShortCircuitEvaluation = false>
23 struct visitor_impl;
24 
25 template <typename Visitor, bool ShortCircuitEvaluation = false>
26 struct short_circuit_eval_impl {
27  // if short circuit evaluation is not used, do nothing
28  static constexpr EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool run(const Visitor&) { return false; }
29 };
30 template <typename Visitor>
31 struct short_circuit_eval_impl<Visitor, true> {
32  // if short circuit evaluation is used, check the visitor
33  static constexpr EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool run(const Visitor& visitor) { return visitor.done(); }
34 };
35 
36 // unrolled inner-outer traversal
37 template <typename Visitor, typename Derived, int UnrollCount, bool Vectorize, bool ShortCircuitEvaluation>
38 struct visitor_impl<Visitor, Derived, UnrollCount, Vectorize, false, ShortCircuitEvaluation> {
39  // don't use short circuit evaluation for unrolled version
40  using Scalar = typename Derived::Scalar;
41  using Packet = typename packet_traits<Scalar>::type;
42  static constexpr bool RowMajor = Derived::IsRowMajor;
43  static constexpr int RowsAtCompileTime = Derived::RowsAtCompileTime;
44  static constexpr int ColsAtCompileTime = Derived::ColsAtCompileTime;
45  static constexpr int PacketSize = packet_traits<Scalar>::size;
46 
47  static constexpr bool CanVectorize(int K) {
48  constexpr int InnerSizeAtCompileTime = RowMajor ? ColsAtCompileTime : RowsAtCompileTime;
49  if (InnerSizeAtCompileTime < PacketSize) return false;
50  return Vectorize && (InnerSizeAtCompileTime - (K % InnerSizeAtCompileTime) >= PacketSize);
51  }
52 
53  template <int K = 0, bool Empty = (K == UnrollCount), std::enable_if_t<Empty, bool> = true>
54  static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run(const Derived&, Visitor&) {}
55 
56  template <int K = 0, bool Empty = (K == UnrollCount), bool Initialize = (K == 0), bool DoVectorOp = CanVectorize(K),
57  std::enable_if_t<!Empty && Initialize && !DoVectorOp, bool> = true>
58  static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run(const Derived& mat, Visitor& visitor) {
59  visitor.init(mat.coeff(0, 0), 0, 0);
60  run<1>(mat, visitor);
61  }
62 
63  template <int K = 0, bool Empty = (K == UnrollCount), bool Initialize = (K == 0), bool DoVectorOp = CanVectorize(K),
64  std::enable_if_t<!Empty && !Initialize && !DoVectorOp, bool> = true>
65  static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run(const Derived& mat, Visitor& visitor) {
66  static constexpr int R = RowMajor ? (K / ColsAtCompileTime) : (K % RowsAtCompileTime);
67  static constexpr int C = RowMajor ? (K % ColsAtCompileTime) : (K / RowsAtCompileTime);
68  visitor(mat.coeff(R, C), R, C);
69  run<K + 1>(mat, visitor);
70  }
71 
72  template <int K = 0, bool Empty = (K == UnrollCount), bool Initialize = (K == 0), bool DoVectorOp = CanVectorize(K),
73  std::enable_if_t<!Empty && Initialize && DoVectorOp, bool> = true>
74  static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run(const Derived& mat, Visitor& visitor) {
75  Packet P = mat.template packet<Packet>(0, 0);
76  visitor.initpacket(P, 0, 0);
77  run<PacketSize>(mat, visitor);
78  }
79 
80  template <int K = 0, bool Empty = (K == UnrollCount), bool Initialize = (K == 0), bool DoVectorOp = CanVectorize(K),
81  std::enable_if_t<!Empty && !Initialize && DoVectorOp, bool> = true>
82  static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run(const Derived& mat, Visitor& visitor) {
83  static constexpr int R = RowMajor ? (K / ColsAtCompileTime) : (K % RowsAtCompileTime);
84  static constexpr int C = RowMajor ? (K % ColsAtCompileTime) : (K / RowsAtCompileTime);
85  Packet P = mat.template packet<Packet>(R, C);
86  visitor.packet(P, R, C);
87  run<K + PacketSize>(mat, visitor);
88  }
89 };
90 
91 // unrolled linear traversal
92 template <typename Visitor, typename Derived, int UnrollCount, bool Vectorize, bool ShortCircuitEvaluation>
93 struct visitor_impl<Visitor, Derived, UnrollCount, Vectorize, true, ShortCircuitEvaluation> {
94  // don't use short circuit evaluation for unrolled version
95  using Scalar = typename Derived::Scalar;
96  using Packet = typename packet_traits<Scalar>::type;
97  static constexpr int PacketSize = packet_traits<Scalar>::size;
98 
99  static constexpr bool CanVectorize(int K) { return Vectorize && ((UnrollCount - K) >= PacketSize); }
100 
101  // empty
102  template <int K = 0, bool Empty = (K == UnrollCount), std::enable_if_t<Empty, bool> = true>
103  static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run(const Derived&, Visitor&) {}
104 
105  // scalar initialization
106  template <int K = 0, bool Empty = (K == UnrollCount), bool Initialize = (K == 0), bool DoVectorOp = CanVectorize(K),
107  std::enable_if_t<!Empty && Initialize && !DoVectorOp, bool> = true>
108  static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run(const Derived& mat, Visitor& visitor) {
109  visitor.init(mat.coeff(0), 0);
110  run<1>(mat, visitor);
111  }
112 
113  // scalar iteration
114  template <int K = 0, bool Empty = (K == UnrollCount), bool Initialize = (K == 0), bool DoVectorOp = CanVectorize(K),
115  std::enable_if_t<!Empty && !Initialize && !DoVectorOp, bool> = true>
116  static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run(const Derived& mat, Visitor& visitor) {
117  visitor(mat.coeff(K), K);
118  run<K + 1>(mat, visitor);
119  }
120 
121  // vector initialization
122  template <int K = 0, bool Empty = (K == UnrollCount), bool Initialize = (K == 0), bool DoVectorOp = CanVectorize(K),
123  std::enable_if_t<!Empty && Initialize && DoVectorOp, bool> = true>
124  static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run(const Derived& mat, Visitor& visitor) {
125  Packet P = mat.template packet<Packet>(0);
126  visitor.initpacket(P, 0);
127  run<PacketSize>(mat, visitor);
128  }
129 
130  // vector iteration
131  template <int K = 0, bool Empty = (K == UnrollCount), bool Initialize = (K == 0), bool DoVectorOp = CanVectorize(K),
132  std::enable_if_t<!Empty && !Initialize && DoVectorOp, bool> = true>
133  static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run(const Derived& mat, Visitor& visitor) {
134  Packet P = mat.template packet<Packet>(K);
135  visitor.packet(P, K);
136  run<K + PacketSize>(mat, visitor);
137  }
138 };
139 
140 // dynamic scalar outer-inner traversal
141 template <typename Visitor, typename Derived, bool ShortCircuitEvaluation>
142 struct visitor_impl<Visitor, Derived, Dynamic, /*Vectorize=*/false, /*LinearAccess=*/false, ShortCircuitEvaluation> {
143  using short_circuit = short_circuit_eval_impl<Visitor, ShortCircuitEvaluation>;
144  static constexpr bool RowMajor = Derived::IsRowMajor;
145 
146  static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run(const Derived& mat, Visitor& visitor) {
147  const Index innerSize = RowMajor ? mat.cols() : mat.rows();
148  const Index outerSize = RowMajor ? mat.rows() : mat.cols();
149  if (innerSize == 0 || outerSize == 0) return;
150  {
151  visitor.init(mat.coeff(0, 0), 0, 0);
152  if (short_circuit::run(visitor)) return;
153  for (Index i = 1; i < innerSize; ++i) {
154  Index r = RowMajor ? 0 : i;
155  Index c = RowMajor ? i : 0;
156  visitor(mat.coeff(r, c), r, c);
157  if EIGEN_PREDICT_FALSE (short_circuit::run(visitor)) return;
158  }
159  }
160  for (Index j = 1; j < outerSize; j++) {
161  for (Index i = 0; i < innerSize; ++i) {
162  Index r = RowMajor ? j : i;
163  Index c = RowMajor ? i : j;
164  visitor(mat.coeff(r, c), r, c);
165  if EIGEN_PREDICT_FALSE (short_circuit::run(visitor)) return;
166  }
167  }
168  }
169 };
170 
171 // dynamic vectorized outer-inner traversal
172 template <typename Visitor, typename Derived, bool ShortCircuitEvaluation>
173 struct visitor_impl<Visitor, Derived, Dynamic, /*Vectorize=*/true, /*LinearAccess=*/false, ShortCircuitEvaluation> {
174  using Scalar = typename Derived::Scalar;
175  using Packet = typename packet_traits<Scalar>::type;
176  static constexpr int PacketSize = packet_traits<Scalar>::size;
177  using short_circuit = short_circuit_eval_impl<Visitor, ShortCircuitEvaluation>;
178  static constexpr bool RowMajor = Derived::IsRowMajor;
179 
180  static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run(const Derived& mat, Visitor& visitor) {
181  const Index innerSize = RowMajor ? mat.cols() : mat.rows();
182  const Index outerSize = RowMajor ? mat.rows() : mat.cols();
183  if (innerSize == 0 || outerSize == 0) return;
184  {
185  Index i = 0;
186  if (innerSize < PacketSize) {
187  visitor.init(mat.coeff(0, 0), 0, 0);
188  i = 1;
189  } else {
190  Packet p = mat.template packet<Packet>(0, 0);
191  visitor.initpacket(p, 0, 0);
192  i = PacketSize;
193  }
194  if EIGEN_PREDICT_FALSE (short_circuit::run(visitor)) return;
195  for (; i + PacketSize - 1 < innerSize; i += PacketSize) {
196  Index r = RowMajor ? 0 : i;
197  Index c = RowMajor ? i : 0;
198  Packet p = mat.template packet<Packet>(r, c);
199  visitor.packet(p, r, c);
200  if EIGEN_PREDICT_FALSE (short_circuit::run(visitor)) return;
201  }
202  for (; i < innerSize; ++i) {
203  Index r = RowMajor ? 0 : i;
204  Index c = RowMajor ? i : 0;
205  visitor(mat.coeff(r, c), r, c);
206  if EIGEN_PREDICT_FALSE (short_circuit::run(visitor)) return;
207  }
208  }
209  for (Index j = 1; j < outerSize; j++) {
210  Index i = 0;
211  for (; i + PacketSize - 1 < innerSize; i += PacketSize) {
212  Index r = RowMajor ? j : i;
213  Index c = RowMajor ? i : j;
214  Packet p = mat.template packet<Packet>(r, c);
215  visitor.packet(p, r, c);
216  if EIGEN_PREDICT_FALSE (short_circuit::run(visitor)) return;
217  }
218  for (; i < innerSize; ++i) {
219  Index r = RowMajor ? j : i;
220  Index c = RowMajor ? i : j;
221  visitor(mat.coeff(r, c), r, c);
222  if EIGEN_PREDICT_FALSE (short_circuit::run(visitor)) return;
223  }
224  }
225  }
226 };
227 
228 // dynamic scalar linear traversal
229 template <typename Visitor, typename Derived, bool ShortCircuitEvaluation>
230 struct visitor_impl<Visitor, Derived, Dynamic, /*Vectorize=*/false, /*LinearAccess=*/true, ShortCircuitEvaluation> {
231  using short_circuit = short_circuit_eval_impl<Visitor, ShortCircuitEvaluation>;
232 
233  static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run(const Derived& mat, Visitor& visitor) {
234  const Index size = mat.size();
235  if (size == 0) return;
236  visitor.init(mat.coeff(0), 0);
237  if EIGEN_PREDICT_FALSE (short_circuit::run(visitor)) return;
238  for (Index k = 1; k < size; k++) {
239  visitor(mat.coeff(k), k);
240  if EIGEN_PREDICT_FALSE (short_circuit::run(visitor)) return;
241  }
242  }
243 };
244 
245 // dynamic vectorized linear traversal
246 template <typename Visitor, typename Derived, bool ShortCircuitEvaluation>
247 struct visitor_impl<Visitor, Derived, Dynamic, /*Vectorize=*/true, /*LinearAccess=*/true, ShortCircuitEvaluation> {
248  using Scalar = typename Derived::Scalar;
249  using Packet = typename packet_traits<Scalar>::type;
250  static constexpr int PacketSize = packet_traits<Scalar>::size;
251  using short_circuit = short_circuit_eval_impl<Visitor, ShortCircuitEvaluation>;
252 
253  static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run(const Derived& mat, Visitor& visitor) {
254  const Index size = mat.size();
255  if (size == 0) return;
256  Index k = 0;
257  if (size < PacketSize) {
258  visitor.init(mat.coeff(0), 0);
259  k = 1;
260  } else {
261  Packet p = mat.template packet<Packet>(k);
262  visitor.initpacket(p, k);
263  k = PacketSize;
264  }
265  if EIGEN_PREDICT_FALSE (short_circuit::run(visitor)) return;
266  for (; k + PacketSize - 1 < size; k += PacketSize) {
267  Packet p = mat.template packet<Packet>(k);
268  visitor.packet(p, k);
269  if EIGEN_PREDICT_FALSE (short_circuit::run(visitor)) return;
270  }
271  for (; k < size; k++) {
272  visitor(mat.coeff(k), k);
273  if EIGEN_PREDICT_FALSE (short_circuit::run(visitor)) return;
274  }
275  }
276 };
277 
278 // evaluator adaptor
279 template <typename XprType>
280 class visitor_evaluator {
281  public:
282  typedef evaluator<XprType> Evaluator;
283  typedef typename XprType::Scalar Scalar;
284  using Packet = typename packet_traits<Scalar>::type;
285  typedef std::remove_const_t<typename XprType::CoeffReturnType> CoeffReturnType;
286 
287  static constexpr bool PacketAccess = static_cast<bool>(Evaluator::Flags & PacketAccessBit);
288  static constexpr bool LinearAccess = static_cast<bool>(Evaluator::Flags & LinearAccessBit);
289  static constexpr bool IsRowMajor = static_cast<bool>(XprType::IsRowMajor);
290  static constexpr int RowsAtCompileTime = XprType::RowsAtCompileTime;
291  static constexpr int ColsAtCompileTime = XprType::ColsAtCompileTime;
292  static constexpr int XprAlignment = Evaluator::Alignment;
293  static constexpr int CoeffReadCost = Evaluator::CoeffReadCost;
294 
295  EIGEN_DEVICE_FUNC explicit visitor_evaluator(const XprType& xpr) : m_evaluator(xpr), m_xpr(xpr) {}
296 
297  EIGEN_DEVICE_FUNC constexpr Index rows() const noexcept { return m_xpr.rows(); }
298  EIGEN_DEVICE_FUNC constexpr Index cols() const noexcept { return m_xpr.cols(); }
299  EIGEN_DEVICE_FUNC constexpr Index size() const noexcept { return m_xpr.size(); }
300  // outer-inner access
301  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE CoeffReturnType coeff(Index row, Index col) const {
302  return m_evaluator.coeff(row, col);
303  }
304  template <typename Packet, int Alignment = Unaligned>
305  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet packet(Index row, Index col) const {
306  return m_evaluator.template packet<Alignment, Packet>(row, col);
307  }
308  // linear access
309  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE CoeffReturnType coeff(Index index) const { return m_evaluator.coeff(index); }
310  template <typename Packet, int Alignment = XprAlignment>
311  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet packet(Index index) const {
312  return m_evaluator.template packet<Alignment, Packet>(index);
313  }
314 
315  protected:
316  Evaluator m_evaluator;
317  const XprType& m_xpr;
318 };
319 
320 template <typename Derived, typename Visitor, bool ShortCircuitEvaulation>
321 struct visit_impl {
322  using Evaluator = visitor_evaluator<Derived>;
323  using Scalar = typename DenseBase<Derived>::Scalar;
324 
325  static constexpr bool IsRowMajor = DenseBase<Derived>::IsRowMajor;
326  static constexpr int SizeAtCompileTime = DenseBase<Derived>::SizeAtCompileTime;
327  static constexpr int RowsAtCompileTime = DenseBase<Derived>::RowsAtCompileTime;
328  static constexpr int ColsAtCompileTime = DenseBase<Derived>::ColsAtCompileTime;
329  static constexpr int InnerSizeAtCompileTime = IsRowMajor ? ColsAtCompileTime : RowsAtCompileTime;
330  static constexpr int OuterSizeAtCompileTime = IsRowMajor ? RowsAtCompileTime : ColsAtCompileTime;
331 
332  static constexpr bool LinearAccess =
333  Evaluator::LinearAccess && static_cast<bool>(functor_traits<Visitor>::LinearAccess);
334  static constexpr bool Vectorize = Evaluator::PacketAccess && static_cast<bool>(functor_traits<Visitor>::PacketAccess);
335 
336  static constexpr int PacketSize = packet_traits<Scalar>::size;
337  static constexpr int VectorOps =
338  Vectorize ? (LinearAccess ? (SizeAtCompileTime / PacketSize)
339  : (OuterSizeAtCompileTime * (InnerSizeAtCompileTime / PacketSize)))
340  : 0;
341  static constexpr int ScalarOps = SizeAtCompileTime - (VectorOps * PacketSize);
342  // treat vector op and scalar op as same cost for unroll logic
343  static constexpr int TotalOps = VectorOps + ScalarOps;
344 
345  static constexpr int UnrollCost = int(Evaluator::CoeffReadCost) + int(functor_traits<Visitor>::Cost);
346  static constexpr bool Unroll = (SizeAtCompileTime != Dynamic) && ((TotalOps * UnrollCost) <= EIGEN_UNROLLING_LIMIT);
347  static constexpr int UnrollCount = Unroll ? int(SizeAtCompileTime) : Dynamic;
348 
349  using impl = visitor_impl<Visitor, Evaluator, UnrollCount, Vectorize, LinearAccess, ShortCircuitEvaulation>;
350 
351  static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run(const DenseBase<Derived>& mat, Visitor& visitor) {
352  Evaluator evaluator(mat.derived());
353  impl::run(evaluator, visitor);
354  }
355 };
356 
357 } // end namespace internal
358 
378 template <typename Derived>
379 template <typename Visitor>
380 EIGEN_DEVICE_FUNC void DenseBase<Derived>::visit(Visitor& visitor) const {
381  using impl = internal::visit_impl<Derived, Visitor, /*ShortCircuitEvaulation*/ false>;
382  impl::run(derived(), visitor);
383 }
384 
385 namespace internal {
386 
387 template <typename Scalar>
388 struct all_visitor {
389  using result_type = bool;
390  using Packet = typename packet_traits<Scalar>::type;
391  EIGEN_DEVICE_FUNC inline void init(const Scalar& value, Index, Index) { res = (value != Scalar(0)); }
392  EIGEN_DEVICE_FUNC inline void init(const Scalar& value, Index) { res = (value != Scalar(0)); }
393  EIGEN_DEVICE_FUNC inline bool all_predux(const Packet& p) const { return !predux_any(pcmp_eq(p, pzero(p))); }
394  EIGEN_DEVICE_FUNC inline void initpacket(const Packet& p, Index, Index) { res = all_predux(p); }
395  EIGEN_DEVICE_FUNC inline void initpacket(const Packet& p, Index) { res = all_predux(p); }
396  EIGEN_DEVICE_FUNC inline void operator()(const Scalar& value, Index, Index) { res = res && (value != Scalar(0)); }
397  EIGEN_DEVICE_FUNC inline void operator()(const Scalar& value, Index) { res = res && (value != Scalar(0)); }
398  EIGEN_DEVICE_FUNC inline void packet(const Packet& p, Index, Index) { res = res && all_predux(p); }
399  EIGEN_DEVICE_FUNC inline void packet(const Packet& p, Index) { res = res && all_predux(p); }
400  EIGEN_DEVICE_FUNC inline bool done() const { return !res; }
401  bool res = true;
402 };
403 template <typename Scalar>
404 struct functor_traits<all_visitor<Scalar>> {
405  enum { Cost = NumTraits<Scalar>::ReadCost, LinearAccess = true, PacketAccess = packet_traits<Scalar>::HasCmp };
406 };
407 
408 template <typename Scalar>
409 struct any_visitor {
410  using result_type = bool;
411  using Packet = typename packet_traits<Scalar>::type;
412  EIGEN_DEVICE_FUNC inline void init(const Scalar& value, Index, Index) { res = (value != Scalar(0)); }
413  EIGEN_DEVICE_FUNC inline void init(const Scalar& value, Index) { res = (value != Scalar(0)); }
414  EIGEN_DEVICE_FUNC inline bool any_predux(const Packet& p) const {
415  return predux_any(pandnot(ptrue(p), pcmp_eq(p, pzero(p))));
416  }
417  EIGEN_DEVICE_FUNC inline void initpacket(const Packet& p, Index, Index) { res = any_predux(p); }
418  EIGEN_DEVICE_FUNC inline void initpacket(const Packet& p, Index) { res = any_predux(p); }
419  EIGEN_DEVICE_FUNC inline void operator()(const Scalar& value, Index, Index) { res = res || (value != Scalar(0)); }
420  EIGEN_DEVICE_FUNC inline void operator()(const Scalar& value, Index) { res = res || (value != Scalar(0)); }
421  EIGEN_DEVICE_FUNC inline void packet(const Packet& p, Index, Index) { res = res || any_predux(p); }
422  EIGEN_DEVICE_FUNC inline void packet(const Packet& p, Index) { res = res || any_predux(p); }
423  EIGEN_DEVICE_FUNC inline bool done() const { return res; }
424  bool res = false;
425 };
426 template <typename Scalar>
427 struct functor_traits<any_visitor<Scalar>> {
428  enum { Cost = NumTraits<Scalar>::ReadCost, LinearAccess = true, PacketAccess = packet_traits<Scalar>::HasCmp };
429 };
430 
431 template <typename Scalar>
432 struct count_visitor {
433  using result_type = Index;
434  using Packet = typename packet_traits<Scalar>::type;
435  EIGEN_DEVICE_FUNC inline void init(const Scalar& value, Index, Index) { res = value != Scalar(0) ? 1 : 0; }
436  EIGEN_DEVICE_FUNC inline void init(const Scalar& value, Index) { res = value != Scalar(0) ? 1 : 0; }
437  EIGEN_DEVICE_FUNC inline Index count_redux(const Packet& p) const {
438  const Packet cst_one = pset1<Packet>(Scalar(1));
439  Packet true_vals = pandnot(cst_one, pcmp_eq(p, pzero(p)));
440  Scalar num_true = predux(true_vals);
441  return static_cast<Index>(num_true);
442  }
443  EIGEN_DEVICE_FUNC inline void initpacket(const Packet& p, Index, Index) { res = count_redux(p); }
444  EIGEN_DEVICE_FUNC inline void initpacket(const Packet& p, Index) { res = count_redux(p); }
445  EIGEN_DEVICE_FUNC inline void operator()(const Scalar& value, Index, Index) {
446  if (value != Scalar(0)) res++;
447  }
448  EIGEN_DEVICE_FUNC inline void operator()(const Scalar& value, Index) {
449  if (value != Scalar(0)) res++;
450  }
451  EIGEN_DEVICE_FUNC inline void packet(const Packet& p, Index, Index) { res += count_redux(p); }
452  EIGEN_DEVICE_FUNC inline void packet(const Packet& p, Index) { res += count_redux(p); }
453  Index res = 0;
454 };
455 
456 template <typename Scalar>
457 struct functor_traits<count_visitor<Scalar>> {
458  enum {
459  Cost = NumTraits<Scalar>::AddCost,
460  LinearAccess = true,
461  // predux is problematic for bool
462  PacketAccess = packet_traits<Scalar>::HasCmp && packet_traits<Scalar>::HasAdd && !is_same<Scalar, bool>::value
463  };
464 };
465 
466 template <typename Derived, bool AlwaysTrue = NumTraits<typename traits<Derived>::Scalar>::IsInteger>
467 struct all_finite_impl {
468  static EIGEN_DEVICE_FUNC inline bool run(const Derived& /*derived*/) { return true; }
469 };
470 #if !defined(__FINITE_MATH_ONLY__) || !(__FINITE_MATH_ONLY__)
471 template <typename Derived>
472 struct all_finite_impl<Derived, false> {
473  static EIGEN_DEVICE_FUNC inline bool run(const Derived& derived) { return derived.array().isFiniteTyped().all(); }
474 };
475 #endif
476 
477 } // end namespace internal
478 
486 template <typename Derived>
487 EIGEN_DEVICE_FUNC inline bool DenseBase<Derived>::all() const {
488  using Visitor = internal::all_visitor<Scalar>;
489  using impl = internal::visit_impl<Derived, Visitor, /*ShortCircuitEvaulation*/ true>;
490  Visitor visitor;
491  impl::run(derived(), visitor);
492  return visitor.res;
493 }
494 
499 template <typename Derived>
500 EIGEN_DEVICE_FUNC inline bool DenseBase<Derived>::any() const {
501  using Visitor = internal::any_visitor<Scalar>;
502  using impl = internal::visit_impl<Derived, Visitor, /*ShortCircuitEvaulation*/ true>;
503  Visitor visitor;
504  impl::run(derived(), visitor);
505  return visitor.res;
506 }
507 
512 template <typename Derived>
513 EIGEN_DEVICE_FUNC Index DenseBase<Derived>::count() const {
514  using Visitor = internal::count_visitor<Scalar>;
515  using impl = internal::visit_impl<Derived, Visitor, /*ShortCircuitEvaulation*/ false>;
516  Visitor visitor;
517  impl::run(derived(), visitor);
518  return visitor.res;
519 }
520 
521 template <typename Derived>
522 EIGEN_DEVICE_FUNC inline bool DenseBase<Derived>::hasNaN() const {
523  return derived().cwiseTypedNotEqual(derived()).any();
524 }
525 
530 template <typename Derived>
531 EIGEN_DEVICE_FUNC inline bool DenseBase<Derived>::allFinite() const {
532  return internal::all_finite_impl<Derived>::run(derived());
533 }
534 
535 } // end namespace Eigen
536 
537 #endif // EIGEN_VISITOR_H
internal::traits< Derived >::Scalar Scalar
Definition: DenseBase.h:62
bool allFinite() const
Definition: Visitor.h:531
Namespace containing all symbols from the Eigen library.
Definition: B01_Experimental.dox:1
Index count() const
Definition: Visitor.h:513
Definition: DenseBase.h:102
Eigen::Index Index
The interface type of indices.
Definition: EigenBase.h:43
Base class for all dense matrices, vectors, and arrays.
Definition: DenseBase.h:38
const unsigned int PacketAccessBit
Definition: Constants.h:97
void visit(Visitor &func) const
Definition: Visitor.h:380
bool all() const
Definition: Visitor.h:487
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API.
Definition: Meta.h:82
Definition: DenseBase.h:108
Definition: DenseBase.h:96
bool any() const
Definition: Visitor.h:500
Definition: DenseBase.h:166
Definition: Constants.h:320
const int Dynamic
Definition: Constants.h:25
const unsigned int LinearAccessBit
Definition: Constants.h:133