VTK  9.2.6
vtkDataArrayTupleRange_AOS.h
Go to the documentation of this file.
1 /*=========================================================================
2 
3  Program: Visualization Toolkit
4  Module: vtkDataArrayTupleRange_AOS.h
5 
6  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7  All rights reserved.
8  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9 
10  This software is distributed WITHOUT ANY WARRANTY; without even
11  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12  PURPOSE. See the above copyright notice for more information.
13 
14 =========================================================================*/
19 #ifndef vtkDataArrayTupleRange_AOS_h
20 #define vtkDataArrayTupleRange_AOS_h
21 
23 #include "vtkDataArrayMeta.h"
25 #include "vtkDebugRangeIterators.h"
26 
27 #include <algorithm>
28 #include <cassert>
29 #include <iterator>
30 #include <type_traits>
31 
32 // Disable this specialization when iterator debugging is requested:
33 #ifndef VTK_DEBUG_RANGE_ITERATORS
34 
36 
37 namespace vtk
38 {
39 
40 namespace detail
41 {
42 
43 // Forward decs for friends/args
44 template <typename ArrayType, ComponentIdType>
46 template <typename ArrayType, ComponentIdType>
48 template <typename ArrayType, ComponentIdType>
50 template <typename ArrayType, ComponentIdType>
52 template <typename ArrayType, ComponentIdType>
53 struct TupleRange;
54 
55 //------------------------------------------------------------------------------
56 // Const tuple reference
57 template <typename ValueType, ComponentIdType TupleSize>
58 struct ConstTupleReference<vtkAOSDataArrayTemplate<ValueType>, TupleSize>
59 {
60 private:
63  using APIType = ValueType;
64 
65 public:
67  using value_type = APIType;
68  using const_reference = const ValueType&;
69  using iterator = const ValueType*;
70  using const_iterator = const ValueType*;
71 
74  : Tuple{ nullptr }
75  {
76  }
77 
79  ConstTupleReference(const ValueType* tuple, NumCompsType numComps) noexcept
80  : Tuple(tuple)
81  , NumComps(numComps)
82  {
83  }
84 
87  : Tuple{ o.Tuple }
88  , NumComps{ o.NumComps }
89  {
90  }
91 
93  ConstTupleReference(const ConstTupleReference&) noexcept = default;
95  ConstTupleReference(ConstTupleReference&&) noexcept = default;
96 
97  // Allow this type to masquerade as a pointer, so that tupleIiter->foo works.
99  ConstTupleReference* operator->() noexcept { return this; }
101  const ConstTupleReference* operator->() const noexcept { return this; }
102 
103  // Caller must ensure that there are size() elements in array.
104  VTK_ITER_INLINE void GetTuple(volatile APIType* tuple) const noexcept
105  {
106  // Yes, the tuple argument is marked volatile. No, it's not a mistake.
107  //
108  // `volatile`'s intended usage per the standard is to disable optimizations
109  // when accessing a variable. Without it, GCC 8 will optimize the following
110  // loop to memcpy, but we're usually copying small tuples here, and the
111  // call to memcpy is more expensive than just doing an inline copy. By
112  // disabling the memcpy optimization, benchmarks are 60% faster when
113  // iterating with the Get/SetTuple methods, and are comparable to other
114  // methods of array access.
115  VTK_ITER_ASSUME(this->NumComps.value > 0);
116  for (ComponentIdType i = 0; i < this->NumComps.value; ++i)
117  {
118  tuple[i] = this->Tuple[i];
119  }
120  }
121 
122  // skips some runtime checks when both sizes are fixed:
123  template <typename OArrayType, ComponentIdType OSize>
125  const TupleReference<OArrayType, OSize>& other) const noexcept
126  {
127  // Check that types are convertible:
128  using OAPIType = GetAPIType<OArrayType>;
129  static_assert(
130  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when assigning tuples.");
131 
132  // SFINAE guarantees that the tuple sizes are not dynamic in this overload:
133  static_assert(TupleSize == OSize, "Cannot assign tuples with different sizes.");
134 
135  return std::equal(this->cbegin(), this->cend(), other.cbegin());
136  }
137 
138  // Needs a runtime check:
139  template <typename OArrayType, ComponentIdType OSize>
141  const TupleReference<OArrayType, OSize>& other) const noexcept
142  {
143  // Check that types are convertible:
144  using OAPIType = GetAPIType<OArrayType>;
145  static_assert(
146  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when assigning tuples.");
147 
148  // Need to check the size at runtime :-(
149  if (other.size() != this->NumComps.value)
150  {
151  return false;
152  }
153 
154  return std::equal(this->cbegin(), this->cend(), other.cbegin());
155  }
156 
157  // skips some runtime checks when both sizes are fixed:
158  template <typename OArrayType, ComponentIdType OSize>
160  const ConstTupleReference<OArrayType, OSize>& other) const noexcept
161  {
162  // Check that types are convertible:
163  using OAPIType = GetAPIType<OArrayType>;
164  static_assert(
165  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when assigning tuples.");
166 
167  // SFINAE guarantees that the tuple sizes are not dynamic in this overload:
168  static_assert(TupleSize == OSize, "Cannot assign tuples with different sizes.");
169 
170  return std::equal(this->cbegin(), this->cend(), other.cbegin());
171  }
172 
173  // Needs a runtime check:
174  template <typename OArrayType, ComponentIdType OSize>
176  const ConstTupleReference<OArrayType, OSize>& other) const noexcept
177  {
178  // Check that types are convertible:
179  using OAPIType = GetAPIType<OArrayType>;
180  static_assert(
181  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when assigning tuples.");
182 
183  // Need to check the size at runtime :-(
184  if (other.size() != this->NumComps.value)
185  {
186  return false;
187  }
188 
189  return std::equal(this->cbegin(), this->cend(), other.cbegin());
190  }
191 
192  template <typename OArrayType, ComponentIdType OSize>
194  {
195  return !(*this == o);
196  }
197 
198  template <typename OArray, ComponentIdType OSize>
200  {
201  return !(*this == o);
202  }
203 
205  const_reference operator[](size_type i) const noexcept { return this->Tuple[i]; }
206 
208  size_type size() const noexcept { return this->NumComps.value; }
209 
211  const_iterator begin() const noexcept { return const_iterator{ this->Tuple }; }
212 
214  const_iterator end() const noexcept
215  {
216  return const_iterator{ this->Tuple + this->NumComps.value };
217  }
218 
220  const_iterator cbegin() const noexcept { return const_iterator{ this->Tuple }; }
221 
223  const_iterator cend() const noexcept
224  {
225  return const_iterator{ this->Tuple + this->NumComps.value };
226  }
227 
228  friend struct ConstTupleIterator<ArrayType, TupleSize>;
229 
230 protected:
231  // Intentionally hidden:
233  ConstTupleReference& operator=(const ConstTupleReference&) noexcept = default;
234 
235  const ValueType* Tuple;
237 };
238 
239 //------------------------------------------------------------------------------
240 // Tuple reference
241 template <typename ValueType, ComponentIdType TupleSize>
242 struct TupleReference<vtkAOSDataArrayTemplate<ValueType>, TupleSize>
243 {
244 private:
247  using APIType = ValueType;
248 
249 public:
251  using value_type = APIType;
252  using iterator = ValueType*;
253  using const_iterator = const ValueType*;
254  using reference = ValueType&;
255  using const_reference = ValueType const&;
256 
258  TupleReference() noexcept
259  : Tuple{ nullptr }
260  {
261  }
262 
264  TupleReference(ValueType* tuple, NumCompsType numComps) noexcept
265  : Tuple(tuple)
266  , NumComps(numComps)
267  {
268  }
269 
271  TupleReference(const TupleReference&) noexcept = default;
273  TupleReference(TupleReference&&) noexcept = default;
274 
275  // Allow this type to masquerade as a pointer, so that tupleIiter->foo works.
277  TupleReference* operator->() noexcept { return this; }
279  const TupleReference* operator->() const noexcept { return this; }
280 
281  // Caller must ensure that there are size() elements in array.
283  void GetTuple(volatile APIType* tuple) const noexcept
284  {
285  // Yes, the tuple argument is marked volatile. No, it's not a mistake.
286  //
287  // `volatile`'s intended usage per the standard is to disable optimizations
288  // when accessing a variable. Without it, GCC 8 will optimize the following
289  // loop to memcpy, but we're usually copying small tuples here, and the
290  // call to memcpy is more expensive than just doing an inline copy. By
291  // disabling the memcpy optimization, benchmarks are 60% faster when
292  // iterating with the Get/SetTuple methods, and are comparable to other
293  // methods of array access.
294  VTK_ITER_ASSUME(this->NumComps.value > 0);
295  for (ComponentIdType i = 0; i < this->NumComps.value; ++i)
296  {
297  tuple[i] = this->Tuple[i];
298  }
299  }
300 
301  // Caller must ensure that there are size() elements in array.
303  void SetTuple(const APIType* tuple) noexcept
304  {
305  volatile APIType* out = this->Tuple;
306  // Yes, this variable argument is marked volatile. See the explanation in
307  // GetTuple.
308  VTK_ITER_ASSUME(this->NumComps.value > 0);
309  for (ComponentIdType i = 0; i < this->NumComps.value; ++i)
310  {
311  out[i] = tuple[i];
312  }
313  }
314 
316  TupleReference& operator=(const TupleReference& other) noexcept
317  {
318  std::copy_n(other.cbegin(), this->NumComps.value, this->begin());
319  return *this;
320  }
321 
322  template <typename OArrayType, ComponentIdType OSize>
324  const TupleReference<OArrayType, OSize>& other) noexcept
325  {
326  // Check that types are convertible:
327  using OAPIType = GetAPIType<OArrayType>;
328  static_assert(
329  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when assigning tuples.");
330 
331  // SFINAE guarantees that the tuple sizes are not dynamic in this overload:
332  static_assert(TupleSize == OSize, "Cannot assign tuples with different sizes.");
333 
334  std::copy_n(other.cbegin(), OSize, this->begin());
335  return *this;
336  }
337 
338  template <typename OArrayType, ComponentIdType OSize>
340  const TupleReference<OArrayType, OSize>& other) noexcept
341  {
342  // Check that types are convertible:
343  using OAPIType = GetAPIType<OArrayType>;
344  static_assert(
345  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when assigning tuples.");
346 
347  // Note that the sizes are not checked here. Enable
348  // VTK_DEBUG_RANGE_ITERATORS to enable check.
349  std::copy_n(other.cbegin(), this->NumComps.value, this->begin());
350  return *this;
351  }
352 
353  template <typename OArrayType, ComponentIdType OSize>
355  const ConstTupleReference<OArrayType, OSize>& other) noexcept
356  {
357  // Check that types are convertible:
358  using OAPIType = GetAPIType<OArrayType>;
359  static_assert(
360  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when assigning tuples.");
361 
362  // SFINAE guarantees that the tuple sizes are not dynamic in this overload:
363  static_assert(TupleSize == OSize, "Cannot assign tuples with different sizes.");
364 
365  std::copy_n(other.cbegin(), OSize, this->begin());
366  return *this;
367  }
368 
369  template <typename OArrayType, ComponentIdType OSize>
371  const ConstTupleReference<OArrayType, OSize>& other) noexcept
372  {
373  // Check that types are convertible:
374  using OAPIType = GetAPIType<OArrayType>;
375  static_assert(
376  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when assigning tuples.");
377 
378  // Note that the sizes are not checked here. Enable
379  // VTK_DEBUG_RANGE_ITERATORS to enable check.
380  std::copy_n(other.cbegin(), this->NumComps.value, this->begin());
381  return *this;
382  }
383 
384  // skips some runtime checks when both sizes are fixed:
385  template <typename OArrayType, ComponentIdType OSize>
387  const TupleReference<OArrayType, OSize>& other) const noexcept
388  {
389  // Check that types are convertible:
390  using OAPIType = GetAPIType<OArrayType>;
391  static_assert(
392  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when assigning tuples.");
393 
394  // SFINAE guarantees that the tuple sizes are not dynamic in this overload:
395  static_assert(TupleSize == OSize, "Cannot assign tuples with different sizes.");
396 
397  return std::equal(this->cbegin(), this->cend(), other.cbegin());
398  }
399 
400  // Needs a runtime check:
401  template <typename OArrayType, ComponentIdType OSize>
403  const TupleReference<OArrayType, OSize>& other) const noexcept
404  {
405  // Check that types are convertible:
406  using OAPIType = GetAPIType<OArrayType>;
407  static_assert(
408  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when assigning tuples.");
409 
410  // Note that the sizes are not checked here. Enable
411  // VTK_DEBUG_RANGE_ITERATORS to enable check.
412  return std::equal(this->cbegin(), this->cend(), other.cbegin());
413  }
414 
415  // skips some runtime checks when both sizes are fixed:
416  template <typename OArrayType, ComponentIdType OSize>
418  const ConstTupleReference<OArrayType, OSize>& other) const noexcept
419  {
420  // Check that types are convertible:
421  using OAPIType = GetAPIType<OArrayType>;
422  static_assert(
423  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when assigning tuples.");
424 
425  // SFINAE guarantees that the tuple sizes are not dynamic in this overload:
426  static_assert(TupleSize == OSize, "Cannot assign tuples with different sizes.");
427 
428  return std::equal(this->cbegin(), this->cend(), other.cbegin());
429  }
430 
431  // Needs a runtime check:
432  template <typename OArrayType, ComponentIdType OSize>
434  const ConstTupleReference<OArrayType, OSize>& other) const noexcept
435  {
436  // Check that types are convertible:
437  using OAPIType = GetAPIType<OArrayType>;
438  static_assert(
439  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when assigning tuples.");
440 
441  // Note that the sizes are not checked here. Enable
442  // VTK_DEBUG_RANGE_ITERATORS to enable check.
443  return std::equal(this->cbegin(), this->cend(), other.cbegin());
444  }
445 
446  template <typename OArrayType, ComponentIdType OSize>
448  {
449  return !(*this == o);
450  }
451 
452  template <typename OArray, ComponentIdType OSize>
454  {
455  return !(*this == o);
456  }
457 
458  // skips some runtime checks:
459  template <typename OArrayType, ComponentIdType OSize>
461  TupleReference<OArrayType, OSize> other) noexcept
462  {
463  // Check that types are convertible:
464  using OAPIType = GetAPIType<OArrayType>;
465  static_assert((std::is_same<OAPIType, APIType>{}), "Incompatible types when swapping tuples.");
466 
467  // SFINAE guarantees that the tuple sizes are not dynamic in this overload:
468  static_assert(TupleSize == OSize, "Cannot swap tuples with different sizes.");
469 
470  std::swap_ranges(this->begin(), this->end(), other.begin());
471  }
472 
473  // Needs a runtime check:
474  template <typename OArrayType, ComponentIdType OSize>
476  TupleReference<OArrayType, OSize> other) noexcept
477  {
478  // Check that types are convertible:
479  using OAPIType = GetAPIType<OArrayType>;
480  static_assert((std::is_same<OAPIType, APIType>{}), "Incompatible types when swapping tuples.");
481 
482  // Note that the sizes are not checked here. Enable
483  // VTK_DEBUG_RANGE_ITERATORS to enable check.
484  std::swap_ranges(this->begin(), this->end(), other.begin());
485  }
486 
487  friend VTK_ITER_INLINE void swap(TupleReference a, TupleReference b) noexcept { a.swap(b); }
488 
489  template <typename OArray, ComponentIdType OSize>
491  {
492  a.swap(b);
493  }
494 
496  reference operator[](size_type i) noexcept { return this->Tuple[i]; }
497 
499  const_reference operator[](size_type i) const noexcept { return this->Tuple[i]; }
500 
502  void fill(const value_type& v) noexcept { std::fill(this->begin(), this->end(), v); }
503 
505  size_type size() const noexcept { return this->NumComps.value; }
506 
508  iterator begin() noexcept { return iterator{ this->Tuple }; }
509 
511  iterator end() noexcept { return iterator{ this->Tuple + this->NumComps.value }; }
512 
514  const_iterator begin() const noexcept { return const_iterator{ this->Tuple }; }
515 
517  const_iterator end() const noexcept
518  {
519  return const_iterator{ this->Tuple + this->NumComps.value };
520  }
521 
523  const_iterator cbegin() const noexcept { return const_iterator{ this->Tuple }; }
524 
526  const_iterator cend() const noexcept
527  {
528  return const_iterator{ this->Tuple + this->NumComps.value };
529  }
530 
531  friend struct ConstTupleReference<ArrayType, TupleSize>;
532  friend struct TupleIterator<ArrayType, TupleSize>;
533 
534 protected:
536  void CopyReference(const TupleReference& o) noexcept
537  {
538  this->Tuple = o.Tuple;
539  this->NumComps = o.NumComps;
540  }
541 
542  ValueType* Tuple;
544 };
545 
546 //------------------------------------------------------------------------------
547 // Const tuple iterator
548 template <typename ValueType, ComponentIdType TupleSize>
549 struct ConstTupleIterator<vtkAOSDataArrayTemplate<ValueType>, TupleSize>
550 {
551 private:
554 
555 public:
556  using iterator_category = std::random_access_iterator_tag;
561 
563  ConstTupleIterator() noexcept = default;
564 
566  ConstTupleIterator(const ValueType* tuple, NumCompsType numComps) noexcept
567  : Ref(tuple, numComps)
568  {
569  }
570 
573  : Ref{ o.Ref }
574  {
575  }
576 
578  ConstTupleIterator(const ConstTupleIterator& o) noexcept = default;
580  ConstTupleIterator& operator=(const ConstTupleIterator& o) noexcept = default;
581 
583  ConstTupleIterator& operator++() noexcept // prefix
584  {
585  this->Ref.Tuple += this->Ref.NumComps.value;
586  return *this;
587  }
588 
590  ConstTupleIterator operator++(int) noexcept // postfix
591  {
592  auto tuple = this->Ref.Tuple;
593  this->Ref.Tuple += this->Ref.NumComps.value;
594  return ConstTupleIterator{ tuple, this->Ref.NumComps };
595  }
596 
598  ConstTupleIterator& operator--() noexcept // prefix
599  {
600  this->Ref.Tuple -= this->Ref.NumComps.value;
601  return *this;
602  }
603 
605  ConstTupleIterator operator--(int) noexcept // postfix
606  {
607  auto tuple = this->Ref.Tuple;
608  this->Ref.Tuple -= this->Ref.NumComps.value;
609  return ConstTupleIterator{ tuple, this->Ref.NumComps };
610  }
611 
614  {
615  return reference{ this->Ref.Tuple + i * this->Ref.NumComps, this->Ref.NumComps };
616  }
617 
619  reference operator*() noexcept { return this->Ref; }
620 
622  pointer& operator->() noexcept { return this->Ref; }
623 
624 #define VTK_TMP_MAKE_OPERATOR(OP) \
625  friend VTK_ITER_INLINE bool operator OP( \
626  const ConstTupleIterator& lhs, const ConstTupleIterator& rhs) noexcept \
627  { \
628  return lhs.GetTuple() OP rhs.GetTuple(); \
629  }
630 
637 
638 #undef VTK_TMP_MAKE_OPERATOR
639 
642  {
643  this->Ref.Tuple += offset * this->Ref.NumComps.value;
644  return *this;
645  }
646 
648  const ConstTupleIterator& it, difference_type offset) noexcept
649  {
650  return ConstTupleIterator{ it.GetTuple() + offset * it.GetNumComps().value, it.GetNumComps() };
651  }
652 
654  difference_type offset, const ConstTupleIterator& it) noexcept
655  {
656  return ConstTupleIterator{ it.GetTuple() + offset * it.GetNumComps().value, it.GetNumComps() };
657  }
658 
661  {
662  this->Ref.Tuple -= offset * this->Ref.NumComps.value;
663  return *this;
664  }
665 
667  const ConstTupleIterator& it, difference_type offset) noexcept
668  {
669  return ConstTupleIterator{ it.GetTuple() - offset * it.GetNumComps().value, it.GetNumComps() };
670  }
671 
673  const ConstTupleIterator& it1, const ConstTupleIterator& it2) noexcept
674  {
675  return static_cast<difference_type>(
676  (it1.GetTuple() - it2.GetTuple()) / it1.GetNumComps().value);
677  }
678 
680  {
681  using std::swap;
682  swap(lhs.GetTuple(), rhs.GetTuple());
683  swap(lhs.GetNumComps(), rhs.GetNumComps());
684  }
685 
686 private:
688  const ValueType*& GetTuple() noexcept { return this->Ref.Tuple; }
690  const ValueType* GetTuple() const noexcept { return this->Ref.Tuple; }
692  NumCompsType& GetNumComps() noexcept { return this->Ref.NumComps; }
694  NumCompsType GetNumComps() const noexcept { return this->Ref.NumComps; }
695 
696  ConstTupleReference<ArrayType, TupleSize> Ref;
697 };
698 
699 //------------------------------------------------------------------------------
700 // Tuple iterator
701 template <typename ValueType, ComponentIdType TupleSize>
702 struct TupleIterator<vtkAOSDataArrayTemplate<ValueType>, TupleSize>
703 {
704 private:
707 
708 public:
709  using iterator_category = std::random_access_iterator_tag;
714 
716  TupleIterator() noexcept = default;
717 
719  TupleIterator(ValueType* tuple, NumCompsType numComps) noexcept
720  : Ref(tuple, numComps)
721  {
722  }
723 
725  TupleIterator(const TupleIterator& o) noexcept = default;
726 
729  {
730  this->Ref.CopyReference(o.Ref);
731  return *this;
732  }
733 
735  TupleIterator& operator++() noexcept // prefix
736  {
737  this->Ref.Tuple += this->Ref.NumComps.value;
738  return *this;
739  }
740 
742  TupleIterator operator++(int) noexcept // postfix
743  {
744  auto tuple = this->Ref.Tuple;
745  this->Ref.Tuple += this->Ref.NumComps.value;
746  return TupleIterator{ tuple, this->Ref.NumComps };
747  }
748 
750  TupleIterator& operator--() noexcept // prefix
751  {
752  this->Ref.Tuple -= this->Ref.NumComps.value;
753  return *this;
754  }
755 
757  TupleIterator operator--(int) noexcept // postfix
758  {
759  auto tuple = this->Ref.Tuple;
760  this->Ref.Tuple -= this->Ref.NumComps.value;
761  return TupleIterator{ tuple, this->Ref.NumComps };
762  }
763 
766  {
767  return reference{ this->Ref.Tuple + i * this->Ref.NumComps.value, this->Ref.NumComps };
768  }
769 
770  reference operator*() noexcept { return this->Ref; }
771 
772  pointer& operator->() noexcept { return this->Ref; }
773 
774 #define VTK_TMP_MAKE_OPERATOR(OP) \
775  friend VTK_ITER_INLINE bool operator OP( \
776  const TupleIterator& lhs, const TupleIterator& rhs) noexcept \
777  { \
778  return lhs.GetTuple() OP rhs.GetTuple(); \
779  }
780 
787 
788 #undef VTK_TMP_MAKE_OPERATOR
789 
792  {
793  this->Ref.Tuple += offset * this->Ref.NumComps.value;
794  return *this;
795  }
796 
798  const TupleIterator& it, difference_type offset) noexcept
799  {
800  return TupleIterator{ it.GetTuple() + offset * it.GetNumComps().value, it.GetNumComps() };
801  }
802 
804  difference_type offset, const TupleIterator& it) noexcept
805  {
806  return TupleIterator{ it.GetTuple() + offset * it.GetNumComps().value, it.GetNumComps() };
807  }
808 
811  {
812  this->Ref.Tuple -= offset * this->Ref.NumComps.value;
813  return *this;
814  }
815 
817  const TupleIterator& it, difference_type offset) noexcept
818  {
819  return TupleIterator{ it.GetTuple() - offset * it.GetNumComps().value, it.GetNumComps() };
820  }
821 
823  const TupleIterator& it1, const TupleIterator& it2) noexcept
824  {
825  return static_cast<difference_type>(
826  (it1.GetTuple() - it2.GetTuple()) / it1.GetNumComps().value);
827  }
828 
829  friend VTK_ITER_INLINE void swap(TupleIterator& lhs, TupleIterator& rhs) noexcept
830  {
831  using std::swap;
832  swap(lhs.GetTuple(), rhs.GetTuple());
833  swap(lhs.GetNumComps(), rhs.GetNumComps());
834  }
835 
836  friend struct ConstTupleIterator<ArrayType, TupleSize>;
837 
838 protected:
840  ValueType* GetTuple() const noexcept { return this->Ref.Tuple; }
842  ValueType*& GetTuple() noexcept { return this->Ref.Tuple; }
844  NumCompsType GetNumComps() const noexcept { return this->Ref.NumComps; }
846  NumCompsType& GetNumComps() noexcept { return this->Ref.NumComps; }
847 
849 };
850 
851 //------------------------------------------------------------------------------
852 // Tuple range
853 template <typename ValueType, ComponentIdType TupleSize>
854 struct TupleRange<vtkAOSDataArrayTemplate<ValueType>, TupleSize>
855 {
858 
859 private:
860  static_assert(IsValidTupleSize<TupleSize>::value, "Invalid tuple size.");
861  static_assert(IsVtkDataArray<ArrayType>::value, "Invalid array type.");
862 
864 
865 public:
875 
881 
882  // May be DynamicTupleSize, or the actual tuple size.
883  constexpr static ComponentIdType TupleSizeTag = TupleSize;
884 
886  TupleRange() noexcept = default;
887 
889  TupleRange(ArrayType* arr, TupleIdType beginTuple, TupleIdType endTuple) noexcept
890  : Array(arr)
891  , NumComps(arr)
892  , BeginTuple(TupleRange::GetTuplePointer(arr, beginTuple))
893  , EndTuple(TupleRange::GetTuplePointer(arr, endTuple))
894  {
895  assert(this->Array);
896  assert(beginTuple >= 0 && beginTuple <= endTuple);
897  assert(endTuple >= 0 && endTuple <= this->Array->GetNumberOfTuples());
898  }
899 
901  TupleRange GetSubRange(TupleIdType beginTuple = 0, TupleIdType endTuple = -1) const noexcept
902  {
903  const TupleIdType curBegin = this->GetTupleId(this->BeginTuple);
904  const TupleIdType realBegin = curBegin + beginTuple;
905  const TupleIdType realEnd =
906  endTuple >= 0 ? curBegin + endTuple : this->GetTupleId(this->EndTuple);
907 
908  return TupleRange{ this->Array, realBegin, realEnd };
909  }
910 
912  ArrayType* GetArray() const noexcept { return this->Array; }
913 
915  ComponentIdType GetTupleSize() const noexcept { return this->NumComps.value; }
916 
918  TupleIdType GetBeginTupleId() const noexcept { return this->GetTupleId(this->BeginTuple); }
919 
921  TupleIdType GetEndTupleId() const noexcept { return this->GetTupleId(this->EndTuple); }
922 
924  size_type size() const noexcept
925  {
926  return static_cast<size_type>(this->EndTuple - this->BeginTuple) /
927  static_cast<size_type>(this->NumComps.value);
928  }
929 
931  iterator begin() noexcept { return iterator(this->BeginTuple, this->NumComps); }
932 
934  iterator end() noexcept { return iterator(this->EndTuple, this->NumComps); }
935 
937  const_iterator begin() const noexcept { return const_iterator(this->BeginTuple, this->NumComps); }
938 
940  const_iterator end() const noexcept { return const_iterator(this->EndTuple, this->NumComps); }
941 
943  const_iterator cbegin() const noexcept
944  {
945  return const_iterator(this->BeginTuple, this->NumComps);
946  }
947 
949  const_iterator cend() const noexcept { return const_iterator(this->EndTuple, this->NumComps); }
950 
953  {
954  return reference{ this->BeginTuple + i * this->NumComps.value, this->NumComps };
955  }
956 
959  {
960  return const_reference{ this->BeginTuple + i * this->NumComps.value, this->NumComps };
961  }
962 
963 private:
965  ValueType* GetTuplePointer(ArrayType* array, vtkIdType tuple) const noexcept
966  {
967  return array->GetPointer(tuple * this->NumComps.value);
968  }
969 
971  TupleIdType GetTupleId(const ValueType* ptr) const noexcept
972  {
973  return static_cast<TupleIdType>((ptr - this->Array->GetPointer(0)) / this->NumComps.value);
974  }
975 
976  mutable ArrayType* Array{ nullptr };
977  NumCompsType NumComps{};
978  ValueType* BeginTuple{ nullptr };
979  ValueType* EndTuple{ nullptr };
980 };
981 
982 // Unimplemented, only used inside decltype in SelectTupleRange:
983 template <typename ArrayType, ComponentIdType TupleSize,
984  // Convenience:
985  typename ValueType = typename ArrayType::ValueType,
986  typename AOSArrayType = vtkAOSDataArrayTemplate<ValueType>,
987  // SFINAE to select AOS arrays:
989 TupleRange<AOSArrayType, TupleSize> DeclareTupleRangeSpecialization(ArrayType*);
990 
991 } // end namespace detail
992 } // end namespace vtk
993 
995 
996 #endif // VTK_DEBUG_RANGE_ITERATORS
997 #endif // vtkDataArrayTupleRange_AOS_h
998 
999 // 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:332
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