VTK  9.1.0
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 #ifndef __VTK_WRAP__
33 
34 // Disable this specialization when iterator debugging is requested:
35 #ifndef VTK_DEBUG_RANGE_ITERATORS
36 
38 
39 namespace vtk
40 {
41 
42 namespace detail
43 {
44 
45 // Forward decs for friends/args
46 template <typename ArrayType, ComponentIdType>
47 struct ConstTupleReference;
48 template <typename ArrayType, ComponentIdType>
49 struct TupleReference;
50 template <typename ArrayType, ComponentIdType>
51 struct ConstTupleIterator;
52 template <typename ArrayType, ComponentIdType>
53 struct TupleIterator;
54 template <typename ArrayType, ComponentIdType>
55 struct TupleRange;
56 
57 //------------------------------------------------------------------------------
58 // Const tuple reference
59 template <typename ValueType, ComponentIdType TupleSize>
60 struct ConstTupleReference<vtkAOSDataArrayTemplate<ValueType>, TupleSize>
61 {
62 private:
65  using APIType = ValueType;
66 
67 public:
69  using value_type = APIType;
70  using const_reference = const ValueType&;
71  using iterator = const ValueType*;
72  using const_iterator = const ValueType*;
73 
76  : Tuple{ nullptr }
77  {
78  }
79 
81  ConstTupleReference(const ValueType* tuple, NumCompsType numComps) noexcept
82  : Tuple(tuple)
83  , NumComps(numComps)
84  {
85  }
86 
89  : Tuple{ o.Tuple }
90  , NumComps{ o.NumComps }
91  {
92  }
93 
95  ConstTupleReference(const ConstTupleReference&) noexcept = default;
98 
99  // Allow this type to masquerade as a pointer, so that tupleIiter->foo works.
101  ConstTupleReference* operator->() noexcept { return this; }
103  const ConstTupleReference* operator->() const noexcept { return this; }
104 
105  // Caller must ensure that there are size() elements in array.
106  VTK_ITER_INLINE void GetTuple(volatile APIType* tuple) const noexcept
107  {
108  // Yes, the tuple argument is marked volatile. No, it's not a mistake.
109  //
110  // `volatile`'s intended usage per the standard is to disable optimizations
111  // when accessing a variable. Without it, GCC 8 will optimize the following
112  // loop to memcpy, but we're usually copying small tuples here, and the
113  // call to memcpy is more expensive than just doing an inline copy. By
114  // disabling the memcpy optimization, benchmarks are 60% faster when
115  // iterating with the Get/SetTuple methods, and are comparable to other
116  // methods of array access.
117  VTK_ITER_ASSUME(this->NumComps.value > 0);
118  for (ComponentIdType i = 0; i < this->NumComps.value; ++i)
119  {
120  tuple[i] = this->Tuple[i];
121  }
122  }
123 
124  // skips some runtime checks when both sizes are fixed:
125  template <typename OArrayType, ComponentIdType OSize>
127  const TupleReference<OArrayType, OSize>& other) const noexcept
128  {
129  // Check that types are convertible:
130  using OAPIType = GetAPIType<OArrayType>;
131  static_assert(
132  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when assigning tuples.");
133 
134  // SFINAE guarantees that the tuple sizes are not dynamic in this overload:
135  static_assert(TupleSize == OSize, "Cannot assign tuples with different sizes.");
136 
137  return std::equal(this->cbegin(), this->cend(), other.cbegin());
138  }
139 
140  // Needs a runtime check:
141  template <typename OArrayType, ComponentIdType OSize>
143  const TupleReference<OArrayType, OSize>& other) const noexcept
144  {
145  // Check that types are convertible:
146  using OAPIType = GetAPIType<OArrayType>;
147  static_assert(
148  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when assigning tuples.");
149 
150  // Need to check the size at runtime :-(
151  if (other.size() != this->NumComps.value)
152  {
153  return false;
154  }
155 
156  return std::equal(this->cbegin(), this->cend(), other.cbegin());
157  }
158 
159  // skips some runtime checks when both sizes are fixed:
160  template <typename OArrayType, ComponentIdType OSize>
162  const ConstTupleReference<OArrayType, OSize>& other) const noexcept
163  {
164  // Check that types are convertible:
165  using OAPIType = GetAPIType<OArrayType>;
166  static_assert(
167  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when assigning tuples.");
168 
169  // SFINAE guarantees that the tuple sizes are not dynamic in this overload:
170  static_assert(TupleSize == OSize, "Cannot assign tuples with different sizes.");
171 
172  return std::equal(this->cbegin(), this->cend(), other.cbegin());
173  }
174 
175  // Needs a runtime check:
176  template <typename OArrayType, ComponentIdType OSize>
178  const ConstTupleReference<OArrayType, OSize>& other) const noexcept
179  {
180  // Check that types are convertible:
181  using OAPIType = GetAPIType<OArrayType>;
182  static_assert(
183  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when assigning tuples.");
184 
185  // Need to check the size at runtime :-(
186  if (other.size() != this->NumComps.value)
187  {
188  return false;
189  }
190 
191  return std::equal(this->cbegin(), this->cend(), other.cbegin());
192  }
193 
194  template <typename OArrayType, ComponentIdType OSize>
196  {
197  return !(*this == o);
198  }
199 
200  template <typename OArray, ComponentIdType OSize>
202  {
203  return !(*this == o);
204  }
205 
207  const_reference operator[](size_type i) const noexcept { return this->Tuple[i]; }
208 
210  size_type size() const noexcept { return this->NumComps.value; }
211 
213  const_iterator begin() const noexcept { return const_iterator{ this->Tuple }; }
214 
216  const_iterator end() const noexcept
217  {
218  return const_iterator{ this->Tuple + this->NumComps.value };
219  }
220 
222  const_iterator cbegin() const noexcept { return const_iterator{ this->Tuple }; }
223 
225  const_iterator cend() const noexcept
226  {
227  return const_iterator{ this->Tuple + this->NumComps.value };
228  }
229 
230  friend struct ConstTupleIterator<ArrayType, TupleSize>;
231 
232 protected:
233  // Intentionally hidden:
235  ConstTupleReference& operator=(const ConstTupleReference&) noexcept = default;
236 
237  const ValueType* Tuple;
239 };
240 
241 //------------------------------------------------------------------------------
242 // Tuple reference
243 template <typename ValueType, ComponentIdType TupleSize>
244 struct TupleReference<vtkAOSDataArrayTemplate<ValueType>, TupleSize>
245 {
246 private:
249  using APIType = ValueType;
250 
251 public:
253  using value_type = APIType;
254  using iterator = ValueType*;
255  using const_iterator = const ValueType*;
256  using reference = ValueType&;
257  using const_reference = ValueType const&;
258 
260  TupleReference() noexcept
261  : Tuple{ nullptr }
262  {
263  }
264 
266  TupleReference(ValueType* tuple, NumCompsType numComps) noexcept
267  : Tuple(tuple)
268  , NumComps(numComps)
269  {
270  }
271 
273  TupleReference(const TupleReference&) noexcept = default;
275  TupleReference(TupleReference&&) noexcept = default;
276 
277  // Allow this type to masquerade as a pointer, so that tupleIiter->foo works.
279  TupleReference* operator->() noexcept { return this; }
281  const TupleReference* operator->() const noexcept { return this; }
282 
283  // Caller must ensure that there are size() elements in array.
285  void GetTuple(volatile APIType* tuple) const noexcept
286  {
287  // Yes, the tuple argument is marked volatile. No, it's not a mistake.
288  //
289  // `volatile`'s intended usage per the standard is to disable optimizations
290  // when accessing a variable. Without it, GCC 8 will optimize the following
291  // loop to memcpy, but we're usually copying small tuples here, and the
292  // call to memcpy is more expensive than just doing an inline copy. By
293  // disabling the memcpy optimization, benchmarks are 60% faster when
294  // iterating with the Get/SetTuple methods, and are comparable to other
295  // methods of array access.
296  VTK_ITER_ASSUME(this->NumComps.value > 0);
297  for (ComponentIdType i = 0; i < this->NumComps.value; ++i)
298  {
299  tuple[i] = this->Tuple[i];
300  }
301  }
302 
303  // Caller must ensure that there are size() elements in array.
305  void SetTuple(const APIType* tuple) noexcept
306  {
307  volatile APIType* out = this->Tuple;
308  // Yes, this variable argument is marked volatile. See the explanation in
309  // GetTuple.
310  VTK_ITER_ASSUME(this->NumComps.value > 0);
311  for (ComponentIdType i = 0; i < this->NumComps.value; ++i)
312  {
313  out[i] = tuple[i];
314  }
315  }
316 
318  TupleReference& operator=(const TupleReference& other) noexcept
319  {
320  std::copy_n(other.cbegin(), this->NumComps.value, this->begin());
321  return *this;
322  }
323 
324  template <typename OArrayType, ComponentIdType OSize>
326  const TupleReference<OArrayType, OSize>& other) noexcept
327  {
328  // Check that types are convertible:
329  using OAPIType = GetAPIType<OArrayType>;
330  static_assert(
331  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when assigning tuples.");
332 
333  // SFINAE guarantees that the tuple sizes are not dynamic in this overload:
334  static_assert(TupleSize == OSize, "Cannot assign tuples with different sizes.");
335 
336  std::copy_n(other.cbegin(), OSize, this->begin());
337  return *this;
338  }
339 
340  template <typename OArrayType, ComponentIdType OSize>
342  const TupleReference<OArrayType, OSize>& other) noexcept
343  {
344  // Check that types are convertible:
345  using OAPIType = GetAPIType<OArrayType>;
346  static_assert(
347  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when assigning tuples.");
348 
349  // Note that the sizes are not checked here. Enable
350  // VTK_DEBUG_RANGE_ITERATORS to enable check.
351  std::copy_n(other.cbegin(), this->NumComps.value, this->begin());
352  return *this;
353  }
354 
355  template <typename OArrayType, ComponentIdType OSize>
357  const ConstTupleReference<OArrayType, OSize>& other) noexcept
358  {
359  // Check that types are convertible:
360  using OAPIType = GetAPIType<OArrayType>;
361  static_assert(
362  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when assigning tuples.");
363 
364  // SFINAE guarantees that the tuple sizes are not dynamic in this overload:
365  static_assert(TupleSize == OSize, "Cannot assign tuples with different sizes.");
366 
367  std::copy_n(other.cbegin(), OSize, this->begin());
368  return *this;
369  }
370 
371  template <typename OArrayType, ComponentIdType OSize>
373  const ConstTupleReference<OArrayType, OSize>& other) noexcept
374  {
375  // Check that types are convertible:
376  using OAPIType = GetAPIType<OArrayType>;
377  static_assert(
378  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when assigning tuples.");
379 
380  // Note that the sizes are not checked here. Enable
381  // VTK_DEBUG_RANGE_ITERATORS to enable check.
382  std::copy_n(other.cbegin(), this->NumComps.value, this->begin());
383  return *this;
384  }
385 
386  // skips some runtime checks when both sizes are fixed:
387  template <typename OArrayType, ComponentIdType OSize>
389  const TupleReference<OArrayType, OSize>& other) const noexcept
390  {
391  // Check that types are convertible:
392  using OAPIType = GetAPIType<OArrayType>;
393  static_assert(
394  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when assigning tuples.");
395 
396  // SFINAE guarantees that the tuple sizes are not dynamic in this overload:
397  static_assert(TupleSize == OSize, "Cannot assign tuples with different sizes.");
398 
399  return std::equal(this->cbegin(), this->cend(), other.cbegin());
400  }
401 
402  // Needs a runtime check:
403  template <typename OArrayType, ComponentIdType OSize>
405  const TupleReference<OArrayType, OSize>& other) const noexcept
406  {
407  // Check that types are convertible:
408  using OAPIType = GetAPIType<OArrayType>;
409  static_assert(
410  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when assigning tuples.");
411 
412  // Note that the sizes are not checked here. Enable
413  // VTK_DEBUG_RANGE_ITERATORS to enable check.
414  return std::equal(this->cbegin(), this->cend(), other.cbegin());
415  }
416 
417  // skips some runtime checks when both sizes are fixed:
418  template <typename OArrayType, ComponentIdType OSize>
420  const ConstTupleReference<OArrayType, OSize>& other) const noexcept
421  {
422  // Check that types are convertible:
423  using OAPIType = GetAPIType<OArrayType>;
424  static_assert(
425  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when assigning tuples.");
426 
427  // SFINAE guarantees that the tuple sizes are not dynamic in this overload:
428  static_assert(TupleSize == OSize, "Cannot assign tuples with different sizes.");
429 
430  return std::equal(this->cbegin(), this->cend(), other.cbegin());
431  }
432 
433  // Needs a runtime check:
434  template <typename OArrayType, ComponentIdType OSize>
436  const ConstTupleReference<OArrayType, OSize>& other) const noexcept
437  {
438  // Check that types are convertible:
439  using OAPIType = GetAPIType<OArrayType>;
440  static_assert(
441  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when assigning tuples.");
442 
443  // Note that the sizes are not checked here. Enable
444  // VTK_DEBUG_RANGE_ITERATORS to enable check.
445  return std::equal(this->cbegin(), this->cend(), other.cbegin());
446  }
447 
448  template <typename OArrayType, ComponentIdType OSize>
450  {
451  return !(*this == o);
452  }
453 
454  template <typename OArray, ComponentIdType OSize>
456  {
457  return !(*this == o);
458  }
459 
460  // skips some runtime checks:
461  template <typename OArrayType, ComponentIdType OSize>
463  TupleReference<OArrayType, OSize> other) noexcept
464  {
465  // Check that types are convertible:
466  using OAPIType = GetAPIType<OArrayType>;
467  static_assert((std::is_same<OAPIType, APIType>{}), "Incompatible types when swapping tuples.");
468 
469  // SFINAE guarantees that the tuple sizes are not dynamic in this overload:
470  static_assert(TupleSize == OSize, "Cannot swap tuples with different sizes.");
471 
472  std::swap_ranges(this->begin(), this->end(), other.begin());
473  }
474 
475  // Needs a runtime check:
476  template <typename OArrayType, ComponentIdType OSize>
478  TupleReference<OArrayType, OSize> other) noexcept
479  {
480  // Check that types are convertible:
481  using OAPIType = GetAPIType<OArrayType>;
482  static_assert((std::is_same<OAPIType, APIType>{}), "Incompatible types when swapping tuples.");
483 
484  // Note that the sizes are not checked here. Enable
485  // VTK_DEBUG_RANGE_ITERATORS to enable check.
486  std::swap_ranges(this->begin(), this->end(), other.begin());
487  }
488 
489  friend VTK_ITER_INLINE void swap(TupleReference a, TupleReference b) noexcept { a.swap(b); }
490 
491  template <typename OArray, ComponentIdType OSize>
493  {
494  a.swap(b);
495  }
496 
498  reference operator[](size_type i) noexcept { return this->Tuple[i]; }
499 
501  const_reference operator[](size_type i) const noexcept { return this->Tuple[i]; }
502 
504  void fill(const value_type& v) noexcept { std::fill(this->begin(), this->end(), v); }
505 
507  size_type size() const noexcept { return this->NumComps.value; }
508 
510  iterator begin() noexcept { return iterator{ this->Tuple }; }
511 
513  iterator end() noexcept { return iterator{ this->Tuple + this->NumComps.value }; }
514 
516  const_iterator begin() const noexcept { return const_iterator{ this->Tuple }; }
517 
519  const_iterator end() const noexcept
520  {
521  return const_iterator{ this->Tuple + this->NumComps.value };
522  }
523 
525  const_iterator cbegin() const noexcept { return const_iterator{ this->Tuple }; }
526 
528  const_iterator cend() const noexcept
529  {
530  return const_iterator{ this->Tuple + this->NumComps.value };
531  }
532 
533  friend struct ConstTupleReference<ArrayType, TupleSize>;
534  friend struct TupleIterator<ArrayType, TupleSize>;
535 
536 protected:
538  void CopyReference(const TupleReference& o) noexcept
539  {
540  this->Tuple = o.Tuple;
541  this->NumComps = o.NumComps;
542  }
543 
544  ValueType* Tuple;
546 };
547 
548 //------------------------------------------------------------------------------
549 // Const tuple iterator
550 template <typename ValueType, ComponentIdType TupleSize>
551 struct ConstTupleIterator<vtkAOSDataArrayTemplate<ValueType>, TupleSize>
552 {
553 private:
556 
557 public:
558  using iterator_category = std::random_access_iterator_tag;
563 
565  ConstTupleIterator() noexcept = default;
566 
568  ConstTupleIterator(const ValueType* tuple, NumCompsType numComps) noexcept
569  : Ref(tuple, numComps)
570  {
571  }
572 
575  : Ref{ o.Ref }
576  {
577  }
578 
580  ConstTupleIterator(const ConstTupleIterator& o) noexcept = default;
582  ConstTupleIterator& operator=(const ConstTupleIterator& o) noexcept = default;
583 
585  ConstTupleIterator& operator++() noexcept // prefix
586  {
587  this->Ref.Tuple += this->Ref.NumComps.value;
588  return *this;
589  }
590 
592  ConstTupleIterator operator++(int) noexcept // postfix
593  {
594  auto tuple = this->Ref.Tuple;
595  this->Ref.Tuple += this->Ref.NumComps.value;
596  return ConstTupleIterator{ tuple, this->Ref.NumComps };
597  }
598 
600  ConstTupleIterator& operator--() noexcept // prefix
601  {
602  this->Ref.Tuple -= this->Ref.NumComps.value;
603  return *this;
604  }
605 
607  ConstTupleIterator operator--(int) noexcept // postfix
608  {
609  auto tuple = this->Ref.Tuple;
610  this->Ref.Tuple -= this->Ref.NumComps.value;
611  return ConstTupleIterator{ tuple, this->Ref.NumComps };
612  }
613 
616  {
617  return reference{ this->Ref.Tuple + i * this->Ref.NumComps, this->Ref.NumComps };
618  }
619 
621  reference operator*() noexcept { return this->Ref; }
622 
624  pointer& operator->() noexcept { return this->Ref; }
625 
626 #define VTK_TMP_MAKE_OPERATOR(OP) \
627  friend VTK_ITER_INLINE bool operator OP( \
628  const ConstTupleIterator& lhs, const ConstTupleIterator& rhs) noexcept \
629  { \
630  return lhs.GetTuple() OP rhs.GetTuple(); \
631  }
632 
639 
640 #undef VTK_TMP_MAKE_OPERATOR
641 
644  {
645  this->Ref.Tuple += offset * this->Ref.NumComps.value;
646  return *this;
647  }
648 
650  const ConstTupleIterator& it, difference_type offset) noexcept
651  {
652  return ConstTupleIterator{ it.GetTuple() + offset * it.GetNumComps().value, it.GetNumComps() };
653  }
654 
656  difference_type offset, const ConstTupleIterator& it) noexcept
657  {
658  return ConstTupleIterator{ it.GetTuple() + offset * it.GetNumComps().value, it.GetNumComps() };
659  }
660 
663  {
664  this->Ref.Tuple -= offset * this->Ref.NumComps.value;
665  return *this;
666  }
667 
669  const ConstTupleIterator& it, difference_type offset) noexcept
670  {
671  return ConstTupleIterator{ it.GetTuple() - offset * it.GetNumComps().value, it.GetNumComps() };
672  }
673 
675  const ConstTupleIterator& it1, const ConstTupleIterator& it2) noexcept
676  {
677  return static_cast<difference_type>(
678  (it1.GetTuple() - it2.GetTuple()) / it1.GetNumComps().value);
679  }
680 
682  {
683  using std::swap;
684  swap(lhs.GetTuple(), rhs.GetTuple());
685  swap(lhs.GetNumComps(), rhs.GetNumComps());
686  }
687 
688 private:
690  const ValueType*& GetTuple() noexcept { return this->Ref.Tuple; }
692  const ValueType* GetTuple() const noexcept { return this->Ref.Tuple; }
694  NumCompsType& GetNumComps() noexcept { return this->Ref.NumComps; }
696  NumCompsType GetNumComps() const noexcept { return this->Ref.NumComps; }
697 
698  ConstTupleReference<ArrayType, TupleSize> Ref;
699 };
700 
701 //------------------------------------------------------------------------------
702 // Tuple iterator
703 template <typename ValueType, ComponentIdType TupleSize>
704 struct TupleIterator<vtkAOSDataArrayTemplate<ValueType>, TupleSize>
705 {
706 private:
709 
710 public:
711  using iterator_category = std::random_access_iterator_tag;
716 
718  TupleIterator() noexcept = default;
719 
721  TupleIterator(ValueType* tuple, NumCompsType numComps) noexcept
722  : Ref(tuple, numComps)
723  {
724  }
725 
727  TupleIterator(const TupleIterator& o) noexcept = default;
728 
731  {
732  this->Ref.CopyReference(o.Ref);
733  return *this;
734  }
735 
737  TupleIterator& operator++() noexcept // prefix
738  {
739  this->Ref.Tuple += this->Ref.NumComps.value;
740  return *this;
741  }
742 
744  TupleIterator operator++(int) noexcept // postfix
745  {
746  auto tuple = this->Ref.Tuple;
747  this->Ref.Tuple += this->Ref.NumComps.value;
748  return TupleIterator{ tuple, this->Ref.NumComps };
749  }
750 
752  TupleIterator& operator--() noexcept // prefix
753  {
754  this->Ref.Tuple -= this->Ref.NumComps.value;
755  return *this;
756  }
757 
759  TupleIterator operator--(int) noexcept // postfix
760  {
761  auto tuple = this->Ref.Tuple;
762  this->Ref.Tuple -= this->Ref.NumComps.value;
763  return TupleIterator{ tuple, this->Ref.NumComps };
764  }
765 
768  {
769  return reference{ this->Ref.Tuple + i * this->Ref.NumComps.value, this->Ref.NumComps };
770  }
771 
772  reference operator*() noexcept { return this->Ref; }
773 
774  pointer& operator->() noexcept { return this->Ref; }
775 
776 #define VTK_TMP_MAKE_OPERATOR(OP) \
777  friend VTK_ITER_INLINE bool operator OP( \
778  const TupleIterator& lhs, const TupleIterator& rhs) noexcept \
779  { \
780  return lhs.GetTuple() OP rhs.GetTuple(); \
781  }
782 
789 
790 #undef VTK_TMP_MAKE_OPERATOR
791 
794  {
795  this->Ref.Tuple += offset * this->Ref.NumComps.value;
796  return *this;
797  }
798 
800  const TupleIterator& it, difference_type offset) noexcept
801  {
802  return TupleIterator{ it.GetTuple() + offset * it.GetNumComps().value, it.GetNumComps() };
803  }
804 
806  difference_type offset, const TupleIterator& it) noexcept
807  {
808  return TupleIterator{ it.GetTuple() + offset * it.GetNumComps().value, it.GetNumComps() };
809  }
810 
813  {
814  this->Ref.Tuple -= offset * this->Ref.NumComps.value;
815  return *this;
816  }
817 
819  const TupleIterator& it, difference_type offset) noexcept
820  {
821  return TupleIterator{ it.GetTuple() - offset * it.GetNumComps().value, it.GetNumComps() };
822  }
823 
825  const TupleIterator& it1, const TupleIterator& it2) noexcept
826  {
827  return static_cast<difference_type>(
828  (it1.GetTuple() - it2.GetTuple()) / it1.GetNumComps().value);
829  }
830 
831  friend VTK_ITER_INLINE void swap(TupleIterator& lhs, TupleIterator& rhs) noexcept
832  {
833  using std::swap;
834  swap(lhs.GetTuple(), rhs.GetTuple());
835  swap(lhs.GetNumComps(), rhs.GetNumComps());
836  }
837 
838  friend struct ConstTupleIterator<ArrayType, TupleSize>;
839 
840 protected:
842  ValueType* GetTuple() const noexcept { return this->Ref.Tuple; }
844  ValueType*& GetTuple() noexcept { return this->Ref.Tuple; }
846  NumCompsType GetNumComps() const noexcept { return this->Ref.NumComps; }
848  NumCompsType& GetNumComps() noexcept { return this->Ref.NumComps; }
849 
851 };
852 
853 //------------------------------------------------------------------------------
854 // Tuple range
855 template <typename ValueType, ComponentIdType TupleSize>
856 struct TupleRange<vtkAOSDataArrayTemplate<ValueType>, TupleSize>
857 {
860 
861 private:
862  static_assert(IsValidTupleSize<TupleSize>::value, "Invalid tuple size.");
863  static_assert(IsVtkDataArray<ArrayType>::value, "Invalid array type.");
864 
866 
867 public:
877 
883 
884  // May be DynamicTupleSize, or the actual tuple size.
885  constexpr static ComponentIdType TupleSizeTag = TupleSize;
886 
888  TupleRange() noexcept = default;
889 
891  TupleRange(ArrayType* arr, TupleIdType beginTuple, TupleIdType endTuple) noexcept
892  : Array(arr)
893  , NumComps(arr)
894  , BeginTuple(TupleRange::GetTuplePointer(arr, beginTuple))
895  , EndTuple(TupleRange::GetTuplePointer(arr, endTuple))
896  {
897  assert(this->Array);
898  assert(beginTuple >= 0 && beginTuple <= endTuple);
899  assert(endTuple >= 0 && endTuple <= this->Array->GetNumberOfTuples());
900  }
901 
903  TupleRange GetSubRange(TupleIdType beginTuple = 0, TupleIdType endTuple = -1) const noexcept
904  {
905  const TupleIdType curBegin = this->GetTupleId(this->BeginTuple);
906  const TupleIdType realBegin = curBegin + beginTuple;
907  const TupleIdType realEnd =
908  endTuple >= 0 ? curBegin + endTuple : this->GetTupleId(this->EndTuple);
909 
910  return TupleRange{ this->Array, realBegin, realEnd };
911  }
912 
914  ArrayType* GetArray() const noexcept { return this->Array; }
915 
917  ComponentIdType GetTupleSize() const noexcept { return this->NumComps.value; }
918 
920  TupleIdType GetBeginTupleId() const noexcept { return this->GetTupleId(this->BeginTuple); }
921 
923  TupleIdType GetEndTupleId() const noexcept { return this->GetTupleId(this->EndTuple); }
924 
926  size_type size() const noexcept
927  {
928  return static_cast<size_type>(this->EndTuple - this->BeginTuple) /
929  static_cast<size_type>(this->NumComps.value);
930  }
931 
933  iterator begin() noexcept { return iterator(this->BeginTuple, this->NumComps); }
934 
936  iterator end() noexcept { return iterator(this->EndTuple, this->NumComps); }
937 
939  const_iterator begin() const noexcept { return const_iterator(this->BeginTuple, this->NumComps); }
940 
942  const_iterator end() const noexcept { return const_iterator(this->EndTuple, this->NumComps); }
943 
945  const_iterator cbegin() const noexcept
946  {
947  return const_iterator(this->BeginTuple, this->NumComps);
948  }
949 
951  const_iterator cend() const noexcept { return const_iterator(this->EndTuple, this->NumComps); }
952 
955  {
956  return reference{ this->BeginTuple + i * this->NumComps.value, this->NumComps };
957  }
958 
961  {
962  return const_reference{ this->BeginTuple + i * this->NumComps.value, this->NumComps };
963  }
964 
965 private:
967  ValueType* GetTuplePointer(ArrayType* array, vtkIdType tuple) const noexcept
968  {
969  return array->GetPointer(tuple * this->NumComps.value);
970  }
971 
973  TupleIdType GetTupleId(const ValueType* ptr) const noexcept
974  {
975  return static_cast<TupleIdType>((ptr - this->Array->GetPointer(0)) / this->NumComps.value);
976  }
977 
978  mutable ArrayType* Array{ nullptr };
979  NumCompsType NumComps{};
980  ValueType* BeginTuple{ nullptr };
981  ValueType* EndTuple{ nullptr };
982 };
983 
984 // Unimplemented, only used inside decltype in SelectTupleRange:
985 template <typename ArrayType, ComponentIdType TupleSize,
986  // Convenience:
987  typename ValueType = typename ArrayType::ValueType,
988  typename AOSArrayType = vtkAOSDataArrayTemplate<ValueType>,
989  // SFINAE to select AOS arrays:
992 
993 } // end namespace detail
994 } // end namespace vtk
995 
997 
998 #endif // VTK_DEBUG_RANGE_ITERATORS
999 #endif // __VTK_WRAP__
1000 #endif // vtkDataArrayTupleRange_AOS_h
1001 
1002 // VTK-HeaderTest-Exclude: vtkDataArrayTupleRange_AOS.h
Array-Of-Structs implementation of vtkGenericDataArray.
@ value
Definition: vtkX3D.h:226
@ type
Definition: vtkX3D.h:522
@ offset
Definition: vtkX3D.h:444
typename std::enable_if< AreStaticTupleSizes< S1, S2 >::value, T >::type EnableIfStaticTupleSizes
TupleRange< AOSArrayType, TupleSize > DeclareTupleRangeSpecialization(ArrayType *)
typename std::enable_if< IsEitherTupleSizeDynamic< S1, S2 >::value, T >::type EnableIfEitherTupleSizeIsDynamic
Specialization of tuple ranges and iterators for vtkAOSDataArrayTemplate.
typename detail::GetAPITypeImpl< ArrayType >::APIType GetAPIType
vtkIdType TupleIdType
int ComponentIdType
friend VTK_ITER_INLINE void swap(ConstTupleIterator &lhs, ConstTupleIterator &rhs) noexcept
friend VTK_ITER_INLINE ConstTupleIterator operator+(difference_type offset, const ConstTupleIterator &it) noexcept
VTK_ITER_INLINE ConstTupleIterator & operator-=(difference_type offset) noexcept
friend VTK_ITER_INLINE ConstTupleIterator operator+(const ConstTupleIterator &it, difference_type offset) noexcept
friend VTK_ITER_INLINE ConstTupleIterator operator-(const ConstTupleIterator &it, difference_type offset) noexcept
VTK_ITER_INLINE ConstTupleIterator & operator+=(difference_type offset) noexcept
VTK_ITER_INLINE ConstTupleIterator(const TupleIterator< ArrayType, TupleSize > &o) noexcept
friend VTK_ITER_INLINE difference_type operator-(const ConstTupleIterator &it1, const ConstTupleIterator &it2) noexcept
VTK_ITER_INLINE ConstTupleIterator & operator=(const ConstTupleIterator &o) noexcept=default
VTK_ITER_INLINE ConstTupleIterator(const ConstTupleIterator &o) noexcept=default
friend VTK_ITER_INLINE void swap(ConstTupleIterator &lhs, ConstTupleIterator &rhs) noexcept
VTK_ITER_INLINE bool operator!=(const ConstTupleReference< OArray, OSize > &o) const noexcept
VTK_ITER_INLINE EnableIfStaticTupleSizes< TupleSize, OSize, bool > operator==(const TupleReference< OArrayType, OSize > &other) const noexcept
VTK_ITER_INLINE ConstTupleReference(const ConstTupleReference &) noexcept=default
VTK_ITER_INLINE ConstTupleReference(ConstTupleReference &&) noexcept=default
VTK_ITER_INLINE EnableIfEitherTupleSizeIsDynamic< TupleSize, OSize, bool > operator==(const ConstTupleReference< OArrayType, OSize > &other) const noexcept
VTK_ITER_INLINE bool operator!=(const TupleReference< OArrayType, OSize > &o) const noexcept
VTK_ITER_INLINE EnableIfStaticTupleSizes< TupleSize, OSize, bool > operator==(const ConstTupleReference< OArrayType, OSize > &other) const noexcept
VTK_ITER_INLINE ConstTupleReference(const ValueType *tuple, NumCompsType numComps) noexcept
VTK_ITER_INLINE ConstTupleReference & operator=(const ConstTupleReference &) noexcept=default
VTK_ITER_INLINE ConstTupleReference(const TupleReference< ArrayType, TupleSize > &o) noexcept
VTK_ITER_INLINE EnableIfEitherTupleSizeIsDynamic< TupleSize, OSize, bool > operator==(const TupleReference< OArrayType, OSize > &other) const noexcept
VTK_ITER_INLINE const_iterator cbegin() const noexcept
VTK_ITER_INLINE const_iterator cend() const noexcept
VTK_ITER_INLINE TupleIterator & operator+=(difference_type offset) noexcept
VTK_ITER_INLINE TupleIterator & operator-=(difference_type offset) noexcept
friend VTK_ITER_INLINE TupleIterator operator+(const TupleIterator &it, difference_type offset) noexcept
VTK_ITER_INLINE TupleIterator & operator=(const TupleIterator &o) noexcept
friend VTK_ITER_INLINE TupleIterator operator-(const TupleIterator &it, difference_type offset) noexcept
VTK_ITER_INLINE TupleIterator(const TupleIterator &o) noexcept=default
friend VTK_ITER_INLINE TupleIterator operator+(difference_type offset, const TupleIterator &it) noexcept
friend VTK_ITER_INLINE difference_type operator-(const TupleIterator &it1, const TupleIterator &it2) noexcept
friend VTK_ITER_INLINE void swap(TupleIterator &lhs, TupleIterator &rhs) noexcept
TupleReference< ArrayType, TupleSize > Ref
VTK_ITER_INLINE const_reference operator[](size_type i) const noexcept
VTK_ITER_INLINE TupleRange GetSubRange(TupleIdType beginTuple=0, TupleIdType endTuple=-1) const noexcept
TupleIterator< ArrayType, TupleSize > TupleIteratorType
ConstTupleIterator< ArrayType, TupleSize > ConstTupleIteratorType
TupleReference< ArrayType, TupleSize > TupleReferenceType
constexpr static ComponentIdType TupleSizeTag
ConstTupleReference< ArrayType, TupleSize > ConstTupleReferenceType
VTK_ITER_INLINE EnableIfStaticTupleSizes< TupleSize, OSize, bool > operator==(const ConstTupleReference< OArrayType, OSize > &other) const noexcept
VTK_ITER_INLINE EnableIfEitherTupleSizeIsDynamic< TupleSize, OSize, bool > operator==(const ConstTupleReference< OArrayType, OSize > &other) const noexcept
VTK_ITER_INLINE EnableIfStaticTupleSizes< TupleSize, OSize, TupleReference & > operator=(const ConstTupleReference< OArrayType, OSize > &other) noexcept
friend VTK_ITER_INLINE void swap(TupleReference a, TupleReference b) noexcept
VTK_ITER_INLINE void GetTuple(volatile APIType *tuple) const noexcept
VTK_ITER_INLINE TupleReference(ValueType *tuple, NumCompsType numComps) noexcept
VTK_ITER_INLINE EnableIfEitherTupleSizeIsDynamic< TupleSize, OSize, void > swap(TupleReference< OArrayType, OSize > other) noexcept
VTK_ITER_INLINE TupleReference & operator=(const TupleReference &other) noexcept
VTK_ITER_INLINE bool operator!=(const TupleReference< OArrayType, OSize > &o) const noexcept
VTK_ITER_INLINE EnableIfEitherTupleSizeIsDynamic< TupleSize, OSize, TupleReference & > operator=(const ConstTupleReference< OArrayType, OSize > &other) noexcept
VTK_ITER_INLINE EnableIfStaticTupleSizes< TupleSize, OSize, bool > operator==(const TupleReference< OArrayType, OSize > &other) const noexcept
VTK_ITER_INLINE EnableIfEitherTupleSizeIsDynamic< TupleSize, OSize, TupleReference & > operator=(const TupleReference< OArrayType, OSize > &other) noexcept
VTK_ITER_INLINE EnableIfStaticTupleSizes< TupleSize, OSize, TupleReference & > operator=(const TupleReference< OArrayType, OSize > &other) noexcept
VTK_ITER_INLINE const_reference operator[](size_type i) const noexcept
VTK_ITER_INLINE EnableIfEitherTupleSizeIsDynamic< TupleSize, OSize, bool > operator==(const TupleReference< OArrayType, OSize > &other) const noexcept
VTK_ITER_INLINE TupleReference(const TupleReference &) noexcept=default
VTK_ITER_INLINE TupleReference(TupleReference &&) noexcept=default
friend VTK_ITER_INLINE void swap(TupleReference a, TupleReference< OArray, OSize > b) noexcept
VTK_ITER_INLINE EnableIfStaticTupleSizes< TupleSize, OSize, void > swap(TupleReference< OArrayType, OSize > other) noexcept
VTK_ITER_INLINE bool operator!=(const ConstTupleReference< OArray, OSize > &o) const noexcept
VTK_ITER_INLINE const_iterator cbegin() const noexcept
VTK_ITER_INLINE const_iterator cend() const noexcept
VTK_ITER_INLINE iterator begin() noexcept
VTK_ITER_INLINE iterator end() noexcept
This file contains a variety of metaprogramming constructs for working with vtkDataArrays.
#define VTK_ITER_OPTIMIZE_START
#define VTK_ITER_INLINE
#define VTK_ITER_OPTIMIZE_END
#define VTK_ITER_ASSUME
#define VTK_TMP_MAKE_OPERATOR(OP)
int vtkIdType
Definition: vtkType.h:332