VTK  9.3.1
vtkDataArrayTupleRange_AOS.h
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
2 // SPDX-License-Identifier: BSD-3-Clause
7 #ifndef vtkDataArrayTupleRange_AOS_h
8 #define vtkDataArrayTupleRange_AOS_h
9 
11 #include "vtkDataArrayMeta.h"
13 #include "vtkDebugRangeIterators.h"
14 
15 #include <algorithm>
16 #include <cassert>
17 #include <iterator>
18 #include <type_traits>
19 
20 // Disable this specialization when iterator debugging is requested:
21 #ifndef VTK_DEBUG_RANGE_ITERATORS
22 
24 
25 namespace vtk
26 {
27 namespace detail
28 {
29 VTK_ABI_NAMESPACE_BEGIN
30 
31 // Forward decs for friends/args
32 template <typename ArrayType, ComponentIdType>
34 template <typename ArrayType, ComponentIdType>
36 template <typename ArrayType, ComponentIdType>
38 template <typename ArrayType, ComponentIdType>
40 template <typename ArrayType, ComponentIdType>
41 struct TupleRange;
42 
43 //------------------------------------------------------------------------------
44 // Const tuple reference
45 template <typename ValueType, ComponentIdType TupleSize>
46 struct ConstTupleReference<vtkAOSDataArrayTemplate<ValueType>, TupleSize>
47 {
48 private:
51  using APIType = ValueType;
52 
53 public:
55  using value_type = APIType;
56  using const_reference = const ValueType&;
57  using iterator = const ValueType*;
58  using const_iterator = const ValueType*;
59 
62  : Tuple{ nullptr }
63  {
64  }
65 
67  ConstTupleReference(const ValueType* tuple, NumCompsType numComps) noexcept
68  : Tuple(tuple)
69  , NumComps(numComps)
70  {
71  }
72 
75  : Tuple{ o.Tuple }
76  , NumComps{ o.NumComps }
77  {
78  }
79 
81  ConstTupleReference(const ConstTupleReference&) noexcept = default;
83  ConstTupleReference(ConstTupleReference&&) noexcept = default;
84 
85  // Allow this type to masquerade as a pointer, so that tupleIiter->foo works.
87  ConstTupleReference* operator->() noexcept { return this; }
89  const ConstTupleReference* operator->() const noexcept { return this; }
90 
91  // Caller must ensure that there are size() elements in array.
92  VTK_ITER_INLINE void GetTuple(volatile APIType* tuple) const noexcept
93  {
94  // Yes, the tuple argument is marked volatile. No, it's not a mistake.
95  //
96  // `volatile`'s intended usage per the standard is to disable optimizations
97  // when accessing a variable. Without it, GCC 8 will optimize the following
98  // loop to memcpy, but we're usually copying small tuples here, and the
99  // call to memcpy is more expensive than just doing an inline copy. By
100  // disabling the memcpy optimization, benchmarks are 60% faster when
101  // iterating with the Get/SetTuple methods, and are comparable to other
102  // methods of array access.
103  VTK_ITER_ASSUME(this->NumComps.value > 0);
104  for (ComponentIdType i = 0; i < this->NumComps.value; ++i)
105  {
106  tuple[i] = this->Tuple[i];
107  }
108  }
109 
110  // skips some runtime checks when both sizes are fixed:
111  template <typename OArrayType, ComponentIdType OSize>
113  const TupleReference<OArrayType, OSize>& other) const noexcept
114  {
115  // Check that types are convertible:
116  using OAPIType = GetAPIType<OArrayType>;
117  static_assert(
118  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when assigning tuples.");
119 
120  // SFINAE guarantees that the tuple sizes are not dynamic in this overload:
121  static_assert(TupleSize == OSize, "Cannot assign tuples with different sizes.");
122 
123  return std::equal(this->cbegin(), this->cend(), other.cbegin());
124  }
125 
126  // Needs a runtime check:
127  template <typename OArrayType, ComponentIdType OSize>
129  const TupleReference<OArrayType, OSize>& other) const noexcept
130  {
131  // Check that types are convertible:
132  using OAPIType = GetAPIType<OArrayType>;
133  static_assert(
134  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when assigning tuples.");
135 
136  // Need to check the size at runtime :-(
137  if (other.size() != this->NumComps.value)
138  {
139  return false;
140  }
141 
142  return std::equal(this->cbegin(), this->cend(), other.cbegin());
143  }
144 
145  // skips some runtime checks when both sizes are fixed:
146  template <typename OArrayType, ComponentIdType OSize>
148  const ConstTupleReference<OArrayType, OSize>& other) const noexcept
149  {
150  // Check that types are convertible:
151  using OAPIType = GetAPIType<OArrayType>;
152  static_assert(
153  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when assigning tuples.");
154 
155  // SFINAE guarantees that the tuple sizes are not dynamic in this overload:
156  static_assert(TupleSize == OSize, "Cannot assign tuples with different sizes.");
157 
158  return std::equal(this->cbegin(), this->cend(), other.cbegin());
159  }
160 
161  // Needs a runtime check:
162  template <typename OArrayType, ComponentIdType OSize>
164  const ConstTupleReference<OArrayType, OSize>& other) const noexcept
165  {
166  // Check that types are convertible:
167  using OAPIType = GetAPIType<OArrayType>;
168  static_assert(
169  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when assigning tuples.");
170 
171  // Need to check the size at runtime :-(
172  if (other.size() != this->NumComps.value)
173  {
174  return false;
175  }
176 
177  return std::equal(this->cbegin(), this->cend(), other.cbegin());
178  }
179 
180  template <typename OArrayType, ComponentIdType OSize>
182  {
183  return !(*this == o);
184  }
185 
186  template <typename OArray, ComponentIdType OSize>
188  {
189  return !(*this == o);
190  }
191 
193  const_reference operator[](size_type i) const noexcept { return this->Tuple[i]; }
194 
196  size_type size() const noexcept { return this->NumComps.value; }
197 
199  const_iterator begin() const noexcept { return const_iterator{ this->Tuple }; }
200 
202  const_iterator end() const noexcept
203  {
204  return const_iterator{ this->Tuple + this->NumComps.value };
205  }
206 
208  const_iterator cbegin() const noexcept { return const_iterator{ this->Tuple }; }
209 
211  const_iterator cend() const noexcept
212  {
213  return const_iterator{ this->Tuple + this->NumComps.value };
214  }
215 
216  friend struct ConstTupleIterator<ArrayType, TupleSize>;
217 
218 protected:
219  // Intentionally hidden:
221  ConstTupleReference& operator=(const ConstTupleReference&) noexcept = default;
222 
223  const ValueType* Tuple;
225 };
226 
227 //------------------------------------------------------------------------------
228 // Tuple reference
229 template <typename ValueType, ComponentIdType TupleSize>
230 struct TupleReference<vtkAOSDataArrayTemplate<ValueType>, TupleSize>
231 {
232 private:
235  using APIType = ValueType;
236 
237 public:
239  using value_type = APIType;
240  using iterator = ValueType*;
241  using const_iterator = const ValueType*;
242  using reference = ValueType&;
243  using const_reference = ValueType const&;
244 
246  TupleReference() noexcept
247  : Tuple{ nullptr }
248  {
249  }
250 
252  TupleReference(ValueType* tuple, NumCompsType numComps) noexcept
253  : Tuple(tuple)
254  , NumComps(numComps)
255  {
256  }
257 
259  TupleReference(const TupleReference&) noexcept = default;
261  TupleReference(TupleReference&&) noexcept = default;
262 
263  // Allow this type to masquerade as a pointer, so that tupleIiter->foo works.
265  TupleReference* operator->() noexcept { return this; }
267  const TupleReference* operator->() const noexcept { return this; }
268 
269  // Caller must ensure that there are size() elements in array.
271  void GetTuple(volatile APIType* tuple) const noexcept
272  {
273  // Yes, the tuple argument is marked volatile. No, it's not a mistake.
274  //
275  // `volatile`'s intended usage per the standard is to disable optimizations
276  // when accessing a variable. Without it, GCC 8 will optimize the following
277  // loop to memcpy, but we're usually copying small tuples here, and the
278  // call to memcpy is more expensive than just doing an inline copy. By
279  // disabling the memcpy optimization, benchmarks are 60% faster when
280  // iterating with the Get/SetTuple methods, and are comparable to other
281  // methods of array access.
282  VTK_ITER_ASSUME(this->NumComps.value > 0);
283  for (ComponentIdType i = 0; i < this->NumComps.value; ++i)
284  {
285  tuple[i] = this->Tuple[i];
286  }
287  }
288 
289  // Caller must ensure that there are size() elements in array.
291  void SetTuple(const APIType* tuple) noexcept
292  {
293  volatile APIType* out = this->Tuple;
294  // Yes, this variable argument is marked volatile. See the explanation in
295  // GetTuple.
296  VTK_ITER_ASSUME(this->NumComps.value > 0);
297  for (ComponentIdType i = 0; i < this->NumComps.value; ++i)
298  {
299  out[i] = tuple[i];
300  }
301  }
302 
304  TupleReference& operator=(const TupleReference& other) noexcept
305  {
306  std::copy_n(other.cbegin(), this->NumComps.value, this->begin());
307  return *this;
308  }
309 
310  template <typename OArrayType, ComponentIdType OSize>
312  const TupleReference<OArrayType, OSize>& other) noexcept
313  {
314  // Check that types are convertible:
315  using OAPIType = GetAPIType<OArrayType>;
316  static_assert(
317  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when assigning tuples.");
318 
319  // SFINAE guarantees that the tuple sizes are not dynamic in this overload:
320  static_assert(TupleSize == OSize, "Cannot assign tuples with different sizes.");
321 
322  std::copy_n(other.cbegin(), OSize, this->begin());
323  return *this;
324  }
325 
326  template <typename OArrayType, ComponentIdType OSize>
328  const TupleReference<OArrayType, OSize>& other) noexcept
329  {
330  // Check that types are convertible:
331  using OAPIType = GetAPIType<OArrayType>;
332  static_assert(
333  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when assigning tuples.");
334 
335  // Note that the sizes are not checked here. Enable
336  // VTK_DEBUG_RANGE_ITERATORS to enable check.
337  std::copy_n(other.cbegin(), this->NumComps.value, this->begin());
338  return *this;
339  }
340 
341  template <typename OArrayType, ComponentIdType OSize>
343  const ConstTupleReference<OArrayType, OSize>& other) noexcept
344  {
345  // Check that types are convertible:
346  using OAPIType = GetAPIType<OArrayType>;
347  static_assert(
348  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when assigning tuples.");
349 
350  // SFINAE guarantees that the tuple sizes are not dynamic in this overload:
351  static_assert(TupleSize == OSize, "Cannot assign tuples with different sizes.");
352 
353  std::copy_n(other.cbegin(), OSize, this->begin());
354  return *this;
355  }
356 
357  template <typename OArrayType, ComponentIdType OSize>
359  const ConstTupleReference<OArrayType, OSize>& other) noexcept
360  {
361  // Check that types are convertible:
362  using OAPIType = GetAPIType<OArrayType>;
363  static_assert(
364  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when assigning tuples.");
365 
366  // Note that the sizes are not checked here. Enable
367  // VTK_DEBUG_RANGE_ITERATORS to enable check.
368  std::copy_n(other.cbegin(), this->NumComps.value, this->begin());
369  return *this;
370  }
371 
372  // skips some runtime checks when both sizes are fixed:
373  template <typename OArrayType, ComponentIdType OSize>
375  const TupleReference<OArrayType, OSize>& other) const noexcept
376  {
377  // Check that types are convertible:
378  using OAPIType = GetAPIType<OArrayType>;
379  static_assert(
380  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when assigning tuples.");
381 
382  // SFINAE guarantees that the tuple sizes are not dynamic in this overload:
383  static_assert(TupleSize == OSize, "Cannot assign tuples with different sizes.");
384 
385  return std::equal(this->cbegin(), this->cend(), other.cbegin());
386  }
387 
388  // Needs a runtime check:
389  template <typename OArrayType, ComponentIdType OSize>
391  const TupleReference<OArrayType, OSize>& other) const noexcept
392  {
393  // Check that types are convertible:
394  using OAPIType = GetAPIType<OArrayType>;
395  static_assert(
396  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when assigning tuples.");
397 
398  // Note that the sizes are not checked here. Enable
399  // VTK_DEBUG_RANGE_ITERATORS to enable check.
400  return std::equal(this->cbegin(), this->cend(), other.cbegin());
401  }
402 
403  // skips some runtime checks when both sizes are fixed:
404  template <typename OArrayType, ComponentIdType OSize>
406  const ConstTupleReference<OArrayType, OSize>& other) const noexcept
407  {
408  // Check that types are convertible:
409  using OAPIType = GetAPIType<OArrayType>;
410  static_assert(
411  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when assigning tuples.");
412 
413  // SFINAE guarantees that the tuple sizes are not dynamic in this overload:
414  static_assert(TupleSize == OSize, "Cannot assign tuples with different sizes.");
415 
416  return std::equal(this->cbegin(), this->cend(), other.cbegin());
417  }
418 
419  // Needs a runtime check:
420  template <typename OArrayType, ComponentIdType OSize>
422  const ConstTupleReference<OArrayType, OSize>& other) const noexcept
423  {
424  // Check that types are convertible:
425  using OAPIType = GetAPIType<OArrayType>;
426  static_assert(
427  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when assigning tuples.");
428 
429  // Note that the sizes are not checked here. Enable
430  // VTK_DEBUG_RANGE_ITERATORS to enable check.
431  return std::equal(this->cbegin(), this->cend(), other.cbegin());
432  }
433 
434  template <typename OArrayType, ComponentIdType OSize>
436  {
437  return !(*this == o);
438  }
439 
440  template <typename OArray, ComponentIdType OSize>
442  {
443  return !(*this == o);
444  }
445 
446  // skips some runtime checks:
447  template <typename OArrayType, ComponentIdType OSize>
449  TupleReference<OArrayType, OSize> other) noexcept
450  {
451  // Check that types are convertible:
452  using OAPIType = GetAPIType<OArrayType>;
453  static_assert((std::is_same<OAPIType, APIType>{}), "Incompatible types when swapping tuples.");
454 
455  // SFINAE guarantees that the tuple sizes are not dynamic in this overload:
456  static_assert(TupleSize == OSize, "Cannot swap tuples with different sizes.");
457 
458  std::swap_ranges(this->begin(), this->end(), other.begin());
459  }
460 
461  // Needs a runtime check:
462  template <typename OArrayType, ComponentIdType OSize>
464  TupleReference<OArrayType, OSize> other) noexcept
465  {
466  // Check that types are convertible:
467  using OAPIType = GetAPIType<OArrayType>;
468  static_assert((std::is_same<OAPIType, APIType>{}), "Incompatible types when swapping tuples.");
469 
470  // Note that the sizes are not checked here. Enable
471  // VTK_DEBUG_RANGE_ITERATORS to enable check.
472  std::swap_ranges(this->begin(), this->end(), other.begin());
473  }
474 
475  friend VTK_ITER_INLINE void swap(TupleReference a, TupleReference b) noexcept { a.swap(b); }
476 
477  template <typename OArray, ComponentIdType OSize>
479  {
480  a.swap(b);
481  }
482 
484  reference operator[](size_type i) noexcept { return this->Tuple[i]; }
485 
487  const_reference operator[](size_type i) const noexcept { return this->Tuple[i]; }
488 
490  void fill(const value_type& v) noexcept { std::fill(this->begin(), this->end(), v); }
491 
493  size_type size() const noexcept { return this->NumComps.value; }
494 
496  iterator begin() noexcept { return iterator{ this->Tuple }; }
497 
499  iterator end() noexcept { return iterator{ this->Tuple + this->NumComps.value }; }
500 
502  const_iterator begin() const noexcept { return const_iterator{ this->Tuple }; }
503 
505  const_iterator end() const noexcept
506  {
507  return const_iterator{ this->Tuple + this->NumComps.value };
508  }
509 
511  const_iterator cbegin() const noexcept { return const_iterator{ this->Tuple }; }
512 
514  const_iterator cend() const noexcept
515  {
516  return const_iterator{ this->Tuple + this->NumComps.value };
517  }
518 
519  friend struct ConstTupleReference<ArrayType, TupleSize>;
520  friend struct TupleIterator<ArrayType, TupleSize>;
521 
522 protected:
524  void CopyReference(const TupleReference& o) noexcept
525  {
526  this->Tuple = o.Tuple;
527  this->NumComps = o.NumComps;
528  }
529 
530  ValueType* Tuple;
532 };
533 
534 //------------------------------------------------------------------------------
535 // Const tuple iterator
536 template <typename ValueType, ComponentIdType TupleSize>
537 struct ConstTupleIterator<vtkAOSDataArrayTemplate<ValueType>, TupleSize>
538 {
539 private:
542 
543 public:
544  using iterator_category = std::random_access_iterator_tag;
549 
551  ConstTupleIterator() noexcept = default;
552 
554  ConstTupleIterator(const ValueType* tuple, NumCompsType numComps) noexcept
555  : Ref(tuple, numComps)
556  {
557  }
558 
561  : Ref{ o.Ref }
562  {
563  }
564 
566  ConstTupleIterator(const ConstTupleIterator& o) noexcept = default;
568  ConstTupleIterator& operator=(const ConstTupleIterator& o) noexcept = default;
569 
571  ConstTupleIterator& operator++() noexcept // prefix
572  {
573  this->Ref.Tuple += this->Ref.NumComps.value;
574  return *this;
575  }
576 
578  ConstTupleIterator operator++(int) noexcept // postfix
579  {
580  auto tuple = this->Ref.Tuple;
581  this->Ref.Tuple += this->Ref.NumComps.value;
582  return ConstTupleIterator{ tuple, this->Ref.NumComps };
583  }
584 
586  ConstTupleIterator& operator--() noexcept // prefix
587  {
588  this->Ref.Tuple -= this->Ref.NumComps.value;
589  return *this;
590  }
591 
593  ConstTupleIterator operator--(int) noexcept // postfix
594  {
595  auto tuple = this->Ref.Tuple;
596  this->Ref.Tuple -= this->Ref.NumComps.value;
597  return ConstTupleIterator{ tuple, this->Ref.NumComps };
598  }
599 
602  {
603  return reference{ this->Ref.Tuple + i * this->Ref.NumComps, this->Ref.NumComps };
604  }
605 
607  reference operator*() noexcept { return this->Ref; }
608 
610  pointer& operator->() noexcept { return this->Ref; }
611 
612 #define VTK_TMP_MAKE_OPERATOR(OP) \
613  friend VTK_ITER_INLINE bool operator OP( \
614  const ConstTupleIterator& lhs, const ConstTupleIterator& rhs) noexcept \
615  { \
616  return lhs.GetTuple() OP rhs.GetTuple(); \
617  }
618 
625 
626 #undef VTK_TMP_MAKE_OPERATOR
627 
630  {
631  this->Ref.Tuple += offset * this->Ref.NumComps.value;
632  return *this;
633  }
634 
636  const ConstTupleIterator& it, difference_type offset) noexcept
637  {
638  return ConstTupleIterator{ it.GetTuple() + offset * it.GetNumComps().value, it.GetNumComps() };
639  }
640 
642  difference_type offset, const ConstTupleIterator& it) noexcept
643  {
644  return ConstTupleIterator{ it.GetTuple() + offset * it.GetNumComps().value, it.GetNumComps() };
645  }
646 
649  {
650  this->Ref.Tuple -= offset * this->Ref.NumComps.value;
651  return *this;
652  }
653 
655  const ConstTupleIterator& it, difference_type offset) noexcept
656  {
657  return ConstTupleIterator{ it.GetTuple() - offset * it.GetNumComps().value, it.GetNumComps() };
658  }
659 
661  const ConstTupleIterator& it1, const ConstTupleIterator& it2) noexcept
662  {
663  return static_cast<difference_type>(
664  (it1.GetTuple() - it2.GetTuple()) / it1.GetNumComps().value);
665  }
666 
668  {
669  using std::swap;
670  swap(lhs.GetTuple(), rhs.GetTuple());
671  swap(lhs.GetNumComps(), rhs.GetNumComps());
672  }
673 
674 private:
676  const ValueType*& GetTuple() noexcept { return this->Ref.Tuple; }
678  const ValueType* GetTuple() const noexcept { return this->Ref.Tuple; }
680  NumCompsType& GetNumComps() noexcept { return this->Ref.NumComps; }
682  NumCompsType GetNumComps() const noexcept { return this->Ref.NumComps; }
683 
684  ConstTupleReference<ArrayType, TupleSize> Ref;
685 };
686 
687 //------------------------------------------------------------------------------
688 // Tuple iterator
689 template <typename ValueType, ComponentIdType TupleSize>
690 struct TupleIterator<vtkAOSDataArrayTemplate<ValueType>, TupleSize>
691 {
692 private:
695 
696 public:
697  using iterator_category = std::random_access_iterator_tag;
702 
704  TupleIterator() noexcept = default;
705 
707  TupleIterator(ValueType* tuple, NumCompsType numComps) noexcept
708  : Ref(tuple, numComps)
709  {
710  }
711 
713  TupleIterator(const TupleIterator& o) noexcept = default;
714 
717  {
718  this->Ref.CopyReference(o.Ref);
719  return *this;
720  }
721 
723  TupleIterator& operator++() noexcept // prefix
724  {
725  this->Ref.Tuple += this->Ref.NumComps.value;
726  return *this;
727  }
728 
730  TupleIterator operator++(int) noexcept // postfix
731  {
732  auto tuple = this->Ref.Tuple;
733  this->Ref.Tuple += this->Ref.NumComps.value;
734  return TupleIterator{ tuple, this->Ref.NumComps };
735  }
736 
738  TupleIterator& operator--() noexcept // prefix
739  {
740  this->Ref.Tuple -= this->Ref.NumComps.value;
741  return *this;
742  }
743 
745  TupleIterator operator--(int) noexcept // postfix
746  {
747  auto tuple = this->Ref.Tuple;
748  this->Ref.Tuple -= this->Ref.NumComps.value;
749  return TupleIterator{ tuple, this->Ref.NumComps };
750  }
751 
754  {
755  return reference{ this->Ref.Tuple + i * this->Ref.NumComps.value, this->Ref.NumComps };
756  }
757 
758  reference operator*() noexcept { return this->Ref; }
759 
760  pointer& operator->() noexcept { return this->Ref; }
761 
762 #define VTK_TMP_MAKE_OPERATOR(OP) \
763  friend VTK_ITER_INLINE bool operator OP( \
764  const TupleIterator& lhs, const TupleIterator& rhs) noexcept \
765  { \
766  return lhs.GetTuple() OP rhs.GetTuple(); \
767  }
768 
775 
776 #undef VTK_TMP_MAKE_OPERATOR
777 
780  {
781  this->Ref.Tuple += offset * this->Ref.NumComps.value;
782  return *this;
783  }
784 
786  const TupleIterator& it, difference_type offset) noexcept
787  {
788  return TupleIterator{ it.GetTuple() + offset * it.GetNumComps().value, it.GetNumComps() };
789  }
790 
792  difference_type offset, const TupleIterator& it) noexcept
793  {
794  return TupleIterator{ it.GetTuple() + offset * it.GetNumComps().value, it.GetNumComps() };
795  }
796 
799  {
800  this->Ref.Tuple -= offset * this->Ref.NumComps.value;
801  return *this;
802  }
803 
805  const TupleIterator& it, difference_type offset) noexcept
806  {
807  return TupleIterator{ it.GetTuple() - offset * it.GetNumComps().value, it.GetNumComps() };
808  }
809 
811  const TupleIterator& it1, const TupleIterator& it2) noexcept
812  {
813  return static_cast<difference_type>(
814  (it1.GetTuple() - it2.GetTuple()) / it1.GetNumComps().value);
815  }
816 
817  friend VTK_ITER_INLINE void swap(TupleIterator& lhs, TupleIterator& rhs) noexcept
818  {
819  using std::swap;
820  swap(lhs.GetTuple(), rhs.GetTuple());
821  swap(lhs.GetNumComps(), rhs.GetNumComps());
822  }
823 
824  friend struct ConstTupleIterator<ArrayType, TupleSize>;
825 
826 protected:
828  ValueType* GetTuple() const noexcept { return this->Ref.Tuple; }
830  ValueType*& GetTuple() noexcept { return this->Ref.Tuple; }
832  NumCompsType GetNumComps() const noexcept { return this->Ref.NumComps; }
834  NumCompsType& GetNumComps() noexcept { return this->Ref.NumComps; }
835 
837 };
838 
839 //------------------------------------------------------------------------------
840 // Tuple range
841 template <typename ValueType, ComponentIdType TupleSize>
842 struct TupleRange<vtkAOSDataArrayTemplate<ValueType>, TupleSize>
843 {
846 
847 private:
848  static_assert(IsValidTupleSize<TupleSize>::value, "Invalid tuple size.");
849  static_assert(IsVtkDataArray<ArrayType>::value, "Invalid array type.");
850 
852 
853 public:
863 
869 
870  // May be DynamicTupleSize, or the actual tuple size.
871  constexpr static ComponentIdType TupleSizeTag = TupleSize;
872 
874  TupleRange() noexcept = default;
875 
877  TupleRange(ArrayType* arr, TupleIdType beginTuple, TupleIdType endTuple) noexcept
878  : Array(arr)
879  , NumComps(arr)
880  , BeginTuple(TupleRange::GetTuplePointer(arr, beginTuple))
881  , EndTuple(TupleRange::GetTuplePointer(arr, endTuple))
882  {
883  assert(this->Array);
884  assert(beginTuple >= 0 && beginTuple <= endTuple);
885  assert(endTuple >= 0 && endTuple <= this->Array->GetNumberOfTuples());
886  }
887 
889  TupleRange GetSubRange(TupleIdType beginTuple = 0, TupleIdType endTuple = -1) const noexcept
890  {
891  const TupleIdType curBegin = this->GetTupleId(this->BeginTuple);
892  const TupleIdType realBegin = curBegin + beginTuple;
893  const TupleIdType realEnd =
894  endTuple >= 0 ? curBegin + endTuple : this->GetTupleId(this->EndTuple);
895 
896  return TupleRange{ this->Array, realBegin, realEnd };
897  }
898 
900  ArrayType* GetArray() const noexcept { return this->Array; }
901 
903  ComponentIdType GetTupleSize() const noexcept { return this->NumComps.value; }
904 
906  TupleIdType GetBeginTupleId() const noexcept { return this->GetTupleId(this->BeginTuple); }
907 
909  TupleIdType GetEndTupleId() const noexcept { return this->GetTupleId(this->EndTuple); }
910 
912  size_type size() const noexcept
913  {
914  return static_cast<size_type>(this->EndTuple - this->BeginTuple) /
915  static_cast<size_type>(this->NumComps.value);
916  }
917 
919  iterator begin() noexcept { return iterator(this->BeginTuple, this->NumComps); }
920 
922  iterator end() noexcept { return iterator(this->EndTuple, this->NumComps); }
923 
925  const_iterator begin() const noexcept { return const_iterator(this->BeginTuple, this->NumComps); }
926 
928  const_iterator end() const noexcept { return const_iterator(this->EndTuple, this->NumComps); }
929 
931  const_iterator cbegin() const noexcept
932  {
933  return const_iterator(this->BeginTuple, this->NumComps);
934  }
935 
937  const_iterator cend() const noexcept { return const_iterator(this->EndTuple, this->NumComps); }
938 
941  {
942  return reference{ this->BeginTuple + i * this->NumComps.value, this->NumComps };
943  }
944 
947  {
948  return const_reference{ this->BeginTuple + i * this->NumComps.value, this->NumComps };
949  }
950 
951 private:
953  ValueType* GetTuplePointer(ArrayType* array, vtkIdType tuple) const noexcept
954  {
955  return array->GetPointer(tuple * this->NumComps.value);
956  }
957 
959  TupleIdType GetTupleId(const ValueType* ptr) const noexcept
960  {
961  return static_cast<TupleIdType>((ptr - this->Array->GetPointer(0)) / this->NumComps.value);
962  }
963 
964  mutable ArrayType* Array{ nullptr };
965  NumCompsType NumComps{};
966  ValueType* BeginTuple{ nullptr };
967  ValueType* EndTuple{ nullptr };
968 };
969 
970 // Unimplemented, only used inside decltype in SelectTupleRange:
971 template <typename ArrayType, ComponentIdType TupleSize,
972  // Convenience:
973  typename ValueType = typename ArrayType::ValueType,
974  typename AOSArrayType = vtkAOSDataArrayTemplate<ValueType>,
975  // SFINAE to select AOS arrays:
977 TupleRange<AOSArrayType, TupleSize> DeclareTupleRangeSpecialization(ArrayType*);
978 
979 VTK_ABI_NAMESPACE_END
980 } // end namespace detail
981 } // end namespace vtk
982 
984 
985 #endif // VTK_DEBUG_RANGE_ITERATORS
986 #endif // vtkDataArrayTupleRange_AOS_h
987 
988 // VTK-HeaderTest-Exclude: vtkDataArrayTupleRange_AOS.h
vtkIdType TupleIdType
#define VTK_TMP_MAKE_OPERATOR(OP)
friend VTK_ITER_INLINE ConstTupleIterator operator+(difference_type offset, const ConstTupleIterator &it) noexcept
int ComponentIdType
VTK_ITER_INLINE EnableIfEitherTupleSizeIsDynamic< TupleSize, OSize, bool > operator==(const ConstTupleReference< OArrayType, OSize > &other) const noexcept
VTK_ITER_INLINE TupleIterator & operator+=(difference_type offset) noexcept
VTK_ITER_INLINE TupleIterator & operator=(const TupleIterator &o) noexcept
VTK_ITER_INLINE EnableIfStaticTupleSizes< TupleSize, OSize, TupleReference & > operator=(const ConstTupleReference< OArrayType, OSize > &other) noexcept
VTK_ITER_INLINE ConstTupleIterator & operator+=(difference_type offset) noexcept
VTK_ITER_INLINE const_iterator begin() const noexcept
VTK_ITER_INLINE void GetTuple(APIType *tuple) const noexcept
VTK_ITER_INLINE EnableIfStaticTupleSizes< TupleSize, OSize, bool > operator==(const TupleReference< OArrayType, OSize > &other) const noexcept
VTK_ITER_INLINE bool operator!=(const TupleReference< OArrayType, OSize > &o) const noexcept
friend VTK_ITER_INLINE difference_type operator-(const TupleIterator &it1, const TupleIterator &it2) noexcept
VTK_ITER_INLINE EnableIfEitherTupleSizeIsDynamic< TupleSize, OSize, TupleReference & > operator=(const TupleReference< OArrayType, OSize > &other) noexcept
typename std::enable_if< IsEitherTupleSizeDynamic< S1, S2 >::value, T >::type EnableIfEitherTupleSizeIsDynamic
VTK_ITER_INLINE bool operator!=(const ConstTupleReference< OArray, OSize > &o) const noexcept
VTK_ITER_INLINE EnableIfEitherTupleSizeIsDynamic< TupleSize, OSize, TupleReference & > operator=(const ConstTupleReference< OArrayType, OSize > &other) noexcept
ConstComponentIterator< ArrayType, TupleSize > const_iterator
VTK_ITER_INLINE EnableIfStaticTupleSizes< TupleSize, OSize, bool > operator==(const ConstTupleReference< OArrayType, OSize > &other) const noexcept
Specialization of tuple ranges and iterators for vtkAOSDataArrayTemplate.
friend VTK_ITER_INLINE void swap(TupleReference a, TupleReference< OArray, OSize > b) noexcept
int vtkIdType
Definition: vtkType.h:315
VTK_ITER_INLINE EnableIfEitherTupleSizeIsDynamic< TupleSize, OSize, bool > operator==(const ConstTupleReference< OArrayType, OSize > &other) const noexcept
friend VTK_ITER_INLINE difference_type operator-(const ConstTupleIterator &it1, const ConstTupleIterator &it2) noexcept
VTK_ITER_INLINE EnableIfEitherTupleSizeIsDynamic< TupleSize, OSize, bool > operator==(const TupleReference< OArrayType, OSize > &other) const noexcept
This file contains a variety of metaprogramming constructs for working with vtkDataArrays.
VTK_ITER_INLINE ConstTupleIterator & operator-=(difference_type offset) noexcept
VTK_ITER_INLINE ConstTupleReference(const TupleReference< ArrayType, TupleSize > &o) noexcept
VTK_ITER_INLINE const_iterator cbegin() const noexcept
#define VTK_ITER_INLINE
VTK_ITER_INLINE const_reference operator[](size_type i) const noexcept
#define VTK_ITER_ASSUME
VTK_ITER_INLINE const_reference operator[](size_type i) const noexcept
Array-Of-Structs implementation of vtkGenericDataArray.
#define VTK_ITER_OPTIMIZE_END
VTK_ITER_INLINE void GetTuple(volatile APIType *tuple) const noexcept
friend VTK_ITER_INLINE TupleIterator operator+(difference_type offset, const TupleIterator &it) noexcept
friend VTK_ITER_INLINE void swap(TupleIterator &lhs, TupleIterator &rhs) noexcept
friend VTK_ITER_INLINE void swap(TupleReference a, TupleReference b) noexcept
VTK_ITER_INLINE EnableIfStaticTupleSizes< TupleSize, OSize, TupleReference & > operator=(const TupleReference< OArrayType, OSize > &other) noexcept
friend VTK_ITER_INLINE TupleIterator operator-(const TupleIterator &it, difference_type offset) noexcept
VTK_ITER_INLINE const_iterator cend() const noexcept
friend VTK_ITER_INLINE TupleIterator operator+(const TupleIterator &it, difference_type offset) noexcept
ConstComponentIterator< ArrayType, TupleSize > iterator
friend VTK_ITER_INLINE ConstTupleIterator operator-(const ConstTupleIterator &it, difference_type offset) noexcept
TupleRange< AOSArrayType, TupleSize > DeclareTupleRangeSpecialization(ArrayType *)
VTK_ITER_INLINE EnableIfEitherTupleSizeIsDynamic< TupleSize, OSize, void > swap(TupleReference< OArrayType, OSize > other) noexcept
VTK_ITER_INLINE EnableIfEitherTupleSizeIsDynamic< TupleSize, OSize, bool > operator==(const TupleReference< OArrayType, OSize > &other) const noexcept
VTK_ITER_INLINE bool operator!=(const TupleReference< OArrayType, OSize > &o) const noexcept
VTK_ITER_INLINE const_iterator end() const noexcept
typename detail::GetAPITypeImpl< ArrayType >::APIType GetAPIType
friend VTK_ITER_INLINE ConstTupleIterator operator+(const ConstTupleIterator &it, difference_type offset) noexcept
VTK_ITER_INLINE TupleReference & operator=(const TupleReference &other) noexcept
VTK_ITER_INLINE EnableIfStaticTupleSizes< TupleSize, OSize, bool > operator==(const ConstTupleReference< OArrayType, OSize > &other) const noexcept
VTK_ITER_INLINE EnableIfStaticTupleSizes< TupleSize, OSize, bool > operator==(const TupleReference< OArrayType, OSize > &other) const noexcept
VTK_ITER_INLINE ConstTupleReference(const ValueType *tuple, NumCompsType numComps) noexcept
#define VTK_ITER_OPTIMIZE_START
VTK_ITER_INLINE ConstTupleReference & operator=(const ConstTupleReference &) noexcept=default
VTK_ITER_INLINE TupleIterator & operator-=(difference_type offset) noexcept
VTK_ITER_INLINE bool operator!=(const ConstTupleReference< OArray, OSize > &o) const noexcept
VTK_ITER_INLINE TupleRange GetSubRange(TupleIdType beginTuple=0, TupleIdType endTuple=-1) const noexcept
VTK_ITER_INLINE ConstTupleIterator(const TupleIterator< ArrayType, TupleSize > &o) noexcept
friend VTK_ITER_INLINE void swap(ConstTupleIterator &lhs, ConstTupleIterator &rhs) noexcept
VTK_ITER_INLINE TupleReference(ValueType *tuple, NumCompsType numComps) noexcept
VTK_ITER_INLINE EnableIfStaticTupleSizes< TupleSize, OSize, void > swap(TupleReference< OArrayType, OSize > other) noexcept
typename std::enable_if< AreStaticTupleSizes< S1, S2 >::value, T >::type EnableIfStaticTupleSizes