VTK  9.3.20240419
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>
33 struct ConstTupleReference;
34 template <typename ArrayType, ComponentIdType>
35 struct TupleReference;
36 template <typename ArrayType, ComponentIdType>
37 struct ConstTupleIterator;
38 template <typename ArrayType, ComponentIdType>
39 struct TupleIterator;
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;
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  template <typename VT = ValueType>
112  volatile double* tuple) const noexcept
113  {
114  // Yes, this variable argument is marked volatile. See the explanation in GetTuple.
115  VTK_ITER_ASSUME(this->NumComps.value > 0);
116  for (ComponentIdType i = 0; i < this->NumComps.value; ++i)
117  {
118  tuple[i] = static_cast<double>(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  template <typename VT = ValueType>
303  volatile double* tuple) const noexcept
304  {
305  // Yes, this variable argument is marked volatile. See the explanation in GetTuple.
306  VTK_ITER_ASSUME(this->NumComps.value > 0);
307  for (ComponentIdType i = 0; i < this->NumComps.value; ++i)
308  {
309  tuple[i] = static_cast<double>(this->Tuple[i]);
310  }
311  }
312 
313  // Caller must ensure that there are size() elements in array.
315  void SetTuple(const APIType* tuple) noexcept
316  {
317  volatile APIType* out = this->Tuple;
318  // Yes, this variable argument is marked volatile. See the explanation in GetTuple.
319  VTK_ITER_ASSUME(this->NumComps.value > 0);
320  for (ComponentIdType i = 0; i < this->NumComps.value; ++i)
321  {
322  out[i] = tuple[i];
323  }
324  }
325 
326  template <typename VT = ValueType>
328  const double* tuple) noexcept
329  {
330  volatile APIType* out = this->Tuple;
331  // Yes, this variable argument is marked volatile. See the explanation in GetTuple.
332  VTK_ITER_ASSUME(this->NumComps.value > 0);
333  for (ComponentIdType i = 0; i < this->NumComps.value; ++i)
334  {
335  out[i] = static_cast<APIType>(tuple[i]);
336  }
337  }
338 
340  TupleReference& operator=(const TupleReference& other) noexcept
341  {
342  std::copy_n(other.cbegin(), this->NumComps.value, this->begin());
343  return *this;
344  }
345 
346  template <typename OArrayType, ComponentIdType OSize>
348  const TupleReference<OArrayType, OSize>& other) noexcept
349  {
350  // Check that types are convertible:
351  using OAPIType = GetAPIType<OArrayType>;
352  static_assert(
353  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when assigning tuples.");
354 
355  // SFINAE guarantees that the tuple sizes are not dynamic in this overload:
356  static_assert(TupleSize == OSize, "Cannot assign tuples with different sizes.");
357 
358  std::copy_n(other.cbegin(), OSize, this->begin());
359  return *this;
360  }
361 
362  template <typename OArrayType, ComponentIdType OSize>
364  const TupleReference<OArrayType, OSize>& other) noexcept
365  {
366  // Check that types are convertible:
367  using OAPIType = GetAPIType<OArrayType>;
368  static_assert(
369  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when assigning tuples.");
370 
371  // Note that the sizes are not checked here. Enable
372  // VTK_DEBUG_RANGE_ITERATORS to enable check.
373  std::copy_n(other.cbegin(), this->NumComps.value, this->begin());
374  return *this;
375  }
376 
377  template <typename OArrayType, ComponentIdType OSize>
379  const ConstTupleReference<OArrayType, OSize>& other) noexcept
380  {
381  // Check that types are convertible:
382  using OAPIType = GetAPIType<OArrayType>;
383  static_assert(
384  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when assigning tuples.");
385 
386  // SFINAE guarantees that the tuple sizes are not dynamic in this overload:
387  static_assert(TupleSize == OSize, "Cannot assign tuples with different sizes.");
388 
389  std::copy_n(other.cbegin(), OSize, this->begin());
390  return *this;
391  }
392 
393  template <typename OArrayType, ComponentIdType OSize>
395  const ConstTupleReference<OArrayType, OSize>& other) noexcept
396  {
397  // Check that types are convertible:
398  using OAPIType = GetAPIType<OArrayType>;
399  static_assert(
400  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when assigning tuples.");
401 
402  // Note that the sizes are not checked here. Enable
403  // VTK_DEBUG_RANGE_ITERATORS to enable check.
404  std::copy_n(other.cbegin(), this->NumComps.value, this->begin());
405  return *this;
406  }
407 
408  // skips some runtime checks when both sizes are fixed:
409  template <typename OArrayType, ComponentIdType OSize>
411  const TupleReference<OArrayType, OSize>& other) const noexcept
412  {
413  // Check that types are convertible:
414  using OAPIType = GetAPIType<OArrayType>;
415  static_assert(
416  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when assigning tuples.");
417 
418  // SFINAE guarantees that the tuple sizes are not dynamic in this overload:
419  static_assert(TupleSize == OSize, "Cannot assign tuples with different sizes.");
420 
421  return std::equal(this->cbegin(), this->cend(), other.cbegin());
422  }
423 
424  // Needs a runtime check:
425  template <typename OArrayType, ComponentIdType OSize>
427  const TupleReference<OArrayType, OSize>& other) const noexcept
428  {
429  // Check that types are convertible:
430  using OAPIType = GetAPIType<OArrayType>;
431  static_assert(
432  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when assigning tuples.");
433 
434  // Note that the sizes are not checked here. Enable
435  // VTK_DEBUG_RANGE_ITERATORS to enable check.
436  return std::equal(this->cbegin(), this->cend(), other.cbegin());
437  }
438 
439  // skips some runtime checks when both sizes are fixed:
440  template <typename OArrayType, ComponentIdType OSize>
442  const ConstTupleReference<OArrayType, OSize>& other) const noexcept
443  {
444  // Check that types are convertible:
445  using OAPIType = GetAPIType<OArrayType>;
446  static_assert(
447  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when assigning tuples.");
448 
449  // SFINAE guarantees that the tuple sizes are not dynamic in this overload:
450  static_assert(TupleSize == OSize, "Cannot assign tuples with different sizes.");
451 
452  return std::equal(this->cbegin(), this->cend(), other.cbegin());
453  }
454 
455  // Needs a runtime check:
456  template <typename OArrayType, ComponentIdType OSize>
458  const ConstTupleReference<OArrayType, OSize>& other) const noexcept
459  {
460  // Check that types are convertible:
461  using OAPIType = GetAPIType<OArrayType>;
462  static_assert(
463  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when assigning tuples.");
464 
465  // Note that the sizes are not checked here. Enable
466  // VTK_DEBUG_RANGE_ITERATORS to enable check.
467  return std::equal(this->cbegin(), this->cend(), other.cbegin());
468  }
469 
470  template <typename OArrayType, ComponentIdType OSize>
472  {
473  return !(*this == o);
474  }
475 
476  template <typename OArray, ComponentIdType OSize>
478  {
479  return !(*this == o);
480  }
481 
482  // skips some runtime checks:
483  template <typename OArrayType, ComponentIdType OSize>
485  TupleReference<OArrayType, OSize> other) noexcept
486  {
487  // Check that types are convertible:
488  using OAPIType = GetAPIType<OArrayType>;
489  static_assert((std::is_same<OAPIType, APIType>{}), "Incompatible types when swapping tuples.");
490 
491  // SFINAE guarantees that the tuple sizes are not dynamic in this overload:
492  static_assert(TupleSize == OSize, "Cannot swap tuples with different sizes.");
493 
494  std::swap_ranges(this->begin(), this->end(), other.begin());
495  }
496 
497  // Needs a runtime check:
498  template <typename OArrayType, ComponentIdType OSize>
500  TupleReference<OArrayType, OSize> other) noexcept
501  {
502  // Check that types are convertible:
503  using OAPIType = GetAPIType<OArrayType>;
504  static_assert((std::is_same<OAPIType, APIType>{}), "Incompatible types when swapping tuples.");
505 
506  // Note that the sizes are not checked here. Enable
507  // VTK_DEBUG_RANGE_ITERATORS to enable check.
508  std::swap_ranges(this->begin(), this->end(), other.begin());
509  }
510 
511  friend VTK_ITER_INLINE void swap(TupleReference a, TupleReference b) noexcept { a.swap(b); }
512 
513  template <typename OArray, ComponentIdType OSize>
515  {
516  a.swap(b);
517  }
518 
520  reference operator[](size_type i) noexcept { return this->Tuple[i]; }
521 
523  const_reference operator[](size_type i) const noexcept { return this->Tuple[i]; }
524 
526  void fill(const value_type& v) noexcept { std::fill(this->begin(), this->end(), v); }
527 
529  size_type size() const noexcept { return this->NumComps.value; }
530 
532  iterator begin() noexcept { return iterator{ this->Tuple }; }
533 
535  iterator end() noexcept { return iterator{ this->Tuple + this->NumComps.value }; }
536 
538  const_iterator begin() const noexcept { return const_iterator{ this->Tuple }; }
539 
541  const_iterator end() const noexcept
542  {
543  return const_iterator{ this->Tuple + this->NumComps.value };
544  }
545 
547  const_iterator cbegin() const noexcept { return const_iterator{ this->Tuple }; }
548 
550  const_iterator cend() const noexcept
551  {
552  return const_iterator{ this->Tuple + this->NumComps.value };
553  }
554 
555  friend struct ConstTupleReference<ArrayType, TupleSize>;
556  friend struct TupleIterator<ArrayType, TupleSize>;
557 
558 protected:
560  void CopyReference(const TupleReference& o) noexcept
561  {
562  this->Tuple = o.Tuple;
563  this->NumComps = o.NumComps;
564  }
565 
566  ValueType* Tuple;
568 };
569 
570 //------------------------------------------------------------------------------
571 // Const tuple iterator
572 template <typename ValueType, ComponentIdType TupleSize>
573 struct ConstTupleIterator<vtkAOSDataArrayTemplate<ValueType>, TupleSize>
574 {
575 private:
578 
579 public:
580  using iterator_category = std::random_access_iterator_tag;
585 
587  ConstTupleIterator() noexcept = default;
588 
590  ConstTupleIterator(const ValueType* tuple, NumCompsType numComps) noexcept
591  : Ref(tuple, numComps)
592  {
593  }
594 
597  : Ref{ o.Ref }
598  {
599  }
600 
602  ConstTupleIterator(const ConstTupleIterator& o) noexcept = default;
604  ConstTupleIterator& operator=(const ConstTupleIterator& o) noexcept = default;
605 
607  ConstTupleIterator& operator++() noexcept // prefix
608  {
609  this->Ref.Tuple += this->Ref.NumComps.value;
610  return *this;
611  }
612 
614  ConstTupleIterator operator++(int) noexcept // postfix
615  {
616  auto tuple = this->Ref.Tuple;
617  this->Ref.Tuple += this->Ref.NumComps.value;
618  return ConstTupleIterator{ tuple, this->Ref.NumComps };
619  }
620 
622  ConstTupleIterator& operator--() noexcept // prefix
623  {
624  this->Ref.Tuple -= this->Ref.NumComps.value;
625  return *this;
626  }
627 
629  ConstTupleIterator operator--(int) noexcept // postfix
630  {
631  auto tuple = this->Ref.Tuple;
632  this->Ref.Tuple -= this->Ref.NumComps.value;
633  return ConstTupleIterator{ tuple, this->Ref.NumComps };
634  }
635 
638  {
639  return reference{ this->Ref.Tuple + i * this->Ref.NumComps, this->Ref.NumComps };
640  }
641 
643  reference operator*() noexcept { return this->Ref; }
644 
646  pointer& operator->() noexcept { return this->Ref; }
647 
648 #define VTK_TMP_MAKE_OPERATOR(OP) \
649  friend VTK_ITER_INLINE bool operator OP( \
650  const ConstTupleIterator& lhs, const ConstTupleIterator& rhs) noexcept \
651  { \
652  return lhs.GetTuple() OP rhs.GetTuple(); \
653  }
654 
661 
662 #undef VTK_TMP_MAKE_OPERATOR
663 
666  {
667  this->Ref.Tuple += offset * this->Ref.NumComps.value;
668  return *this;
669  }
670 
672  const ConstTupleIterator& it, difference_type offset) noexcept
673  {
674  return ConstTupleIterator{ it.GetTuple() + offset * it.GetNumComps().value, it.GetNumComps() };
675  }
676 
678  difference_type offset, const ConstTupleIterator& it) noexcept
679  {
680  return ConstTupleIterator{ it.GetTuple() + offset * it.GetNumComps().value, it.GetNumComps() };
681  }
682 
685  {
686  this->Ref.Tuple -= offset * this->Ref.NumComps.value;
687  return *this;
688  }
689 
691  const ConstTupleIterator& it, difference_type offset) noexcept
692  {
693  return ConstTupleIterator{ it.GetTuple() - offset * it.GetNumComps().value, it.GetNumComps() };
694  }
695 
697  const ConstTupleIterator& it1, const ConstTupleIterator& it2) noexcept
698  {
699  return static_cast<difference_type>(
700  (it1.GetTuple() - it2.GetTuple()) / it1.GetNumComps().value);
701  }
702 
704  {
705  using std::swap;
706  swap(lhs.GetTuple(), rhs.GetTuple());
707  swap(lhs.GetNumComps(), rhs.GetNumComps());
708  }
709 
710 private:
712  const ValueType*& GetTuple() noexcept { return this->Ref.Tuple; }
714  const ValueType* GetTuple() const noexcept { return this->Ref.Tuple; }
716  NumCompsType& GetNumComps() noexcept { return this->Ref.NumComps; }
718  NumCompsType GetNumComps() const noexcept { return this->Ref.NumComps; }
719 
720  ConstTupleReference<ArrayType, TupleSize> Ref;
721 };
722 
723 //------------------------------------------------------------------------------
724 // Tuple iterator
725 template <typename ValueType, ComponentIdType TupleSize>
726 struct TupleIterator<vtkAOSDataArrayTemplate<ValueType>, TupleSize>
727 {
728 private:
731 
732 public:
733  using iterator_category = std::random_access_iterator_tag;
738 
740  TupleIterator() noexcept = default;
741 
743  TupleIterator(ValueType* tuple, NumCompsType numComps) noexcept
744  : Ref(tuple, numComps)
745  {
746  }
747 
749  TupleIterator(const TupleIterator& o) noexcept = default;
750 
753  {
754  this->Ref.CopyReference(o.Ref);
755  return *this;
756  }
757 
759  TupleIterator& operator++() noexcept // prefix
760  {
761  this->Ref.Tuple += this->Ref.NumComps.value;
762  return *this;
763  }
764 
766  TupleIterator operator++(int) noexcept // postfix
767  {
768  auto tuple = this->Ref.Tuple;
769  this->Ref.Tuple += this->Ref.NumComps.value;
770  return TupleIterator{ tuple, this->Ref.NumComps };
771  }
772 
774  TupleIterator& operator--() noexcept // prefix
775  {
776  this->Ref.Tuple -= this->Ref.NumComps.value;
777  return *this;
778  }
779 
781  TupleIterator operator--(int) noexcept // postfix
782  {
783  auto tuple = this->Ref.Tuple;
784  this->Ref.Tuple -= this->Ref.NumComps.value;
785  return TupleIterator{ tuple, this->Ref.NumComps };
786  }
787 
790  {
791  return reference{ this->Ref.Tuple + i * this->Ref.NumComps.value, this->Ref.NumComps };
792  }
793 
794  reference operator*() noexcept { return this->Ref; }
795 
796  pointer& operator->() noexcept { return this->Ref; }
797 
798 #define VTK_TMP_MAKE_OPERATOR(OP) \
799  friend VTK_ITER_INLINE bool operator OP( \
800  const TupleIterator& lhs, const TupleIterator& rhs) noexcept \
801  { \
802  return lhs.GetTuple() OP rhs.GetTuple(); \
803  }
804 
811 
812 #undef VTK_TMP_MAKE_OPERATOR
813 
816  {
817  this->Ref.Tuple += offset * this->Ref.NumComps.value;
818  return *this;
819  }
820 
822  const TupleIterator& it, difference_type offset) noexcept
823  {
824  return TupleIterator{ it.GetTuple() + offset * it.GetNumComps().value, it.GetNumComps() };
825  }
826 
828  difference_type offset, const TupleIterator& it) noexcept
829  {
830  return TupleIterator{ it.GetTuple() + offset * it.GetNumComps().value, it.GetNumComps() };
831  }
832 
835  {
836  this->Ref.Tuple -= offset * this->Ref.NumComps.value;
837  return *this;
838  }
839 
841  const TupleIterator& it, difference_type offset) noexcept
842  {
843  return TupleIterator{ it.GetTuple() - offset * it.GetNumComps().value, it.GetNumComps() };
844  }
845 
847  const TupleIterator& it1, const TupleIterator& it2) noexcept
848  {
849  return static_cast<difference_type>(
850  (it1.GetTuple() - it2.GetTuple()) / it1.GetNumComps().value);
851  }
852 
853  friend VTK_ITER_INLINE void swap(TupleIterator& lhs, TupleIterator& rhs) noexcept
854  {
855  using std::swap;
856  swap(lhs.GetTuple(), rhs.GetTuple());
857  swap(lhs.GetNumComps(), rhs.GetNumComps());
858  }
859 
860  friend struct ConstTupleIterator<ArrayType, TupleSize>;
861 
862 protected:
864  ValueType* GetTuple() const noexcept { return this->Ref.Tuple; }
866  ValueType*& GetTuple() noexcept { return this->Ref.Tuple; }
868  NumCompsType GetNumComps() const noexcept { return this->Ref.NumComps; }
870  NumCompsType& GetNumComps() noexcept { return this->Ref.NumComps; }
871 
873 };
874 
875 //------------------------------------------------------------------------------
876 // Tuple range
877 template <typename ValueType, ComponentIdType TupleSize>
878 struct TupleRange<vtkAOSDataArrayTemplate<ValueType>, TupleSize>
879 {
882 
883 private:
884  static_assert(IsValidTupleSize<TupleSize>::value, "Invalid tuple size.");
885  static_assert(IsVtkDataArray<ArrayType>::value, "Invalid array type.");
886 
888 
889 public:
899 
905 
906  // May be DynamicTupleSize, or the actual tuple size.
907  constexpr static ComponentIdType TupleSizeTag = TupleSize;
908 
910  TupleRange() noexcept = default;
911 
913  TupleRange(ArrayType* arr, TupleIdType beginTuple, TupleIdType endTuple) noexcept
914  : Array(arr)
915  , NumComps(arr)
916  , BeginTuple(beginTuple)
917  , EndTuple(endTuple)
918  {
919  assert(this->Array);
920  assert(beginTuple >= 0 && beginTuple <= endTuple);
921  assert(endTuple >= 0 && endTuple <= this->Array->GetNumberOfTuples());
922  }
923 
925  TupleRange GetSubRange(TupleIdType beginTuple = 0, TupleIdType endTuple = -1) const noexcept
926  {
927  const TupleIdType curBegin = this->GetTupleId(this->GetTuplePointer(this->BeginTuple));
928  const TupleIdType realBegin = curBegin + beginTuple;
929  const TupleIdType realEnd =
930  endTuple >= 0 ? curBegin + endTuple : this->GetTupleId(this->GetTuplePointer(this->EndTuple));
931 
932  return TupleRange{ this->Array, realBegin, realEnd };
933  }
934 
936  ArrayType* GetArray() const noexcept { return this->Array; }
937 
939  ComponentIdType GetTupleSize() const noexcept { return this->NumComps.value; }
940 
942  TupleIdType GetBeginTupleId() const noexcept
943  {
944  return this->GetTupleId(this->GetTuplePointer(this->BeginTuple));
945  }
946 
948  TupleIdType GetEndTupleId() const noexcept
949  {
950  return this->GetTupleId(this->GetTuplePointer(this->EndTuple));
951  }
952 
954  size_type size() const noexcept
955  {
956  return static_cast<size_type>(
957  this->GetTuplePointer(this->EndTuple) - this->GetTuplePointer(this->BeginTuple)) /
958  static_cast<size_type>(this->NumComps.value);
959  }
960 
962  iterator begin() noexcept
963  {
964  return iterator(this->GetTuplePointer(this->BeginTuple), this->NumComps);
965  }
966 
968  iterator end() noexcept
969  {
970  return iterator(this->GetTuplePointer(this->EndTuple), this->NumComps);
971  }
972 
974  const_iterator begin() const noexcept
975  {
976  return const_iterator(this->GetTuplePointer(this->BeginTuple), this->NumComps);
977  }
978 
980  const_iterator end() const noexcept
981  {
982  return const_iterator(this->GetTuplePointer(this->EndTuple), this->NumComps);
983  }
984 
986  const_iterator cbegin() const noexcept
987  {
988  return const_iterator(this->GetTuplePointer(this->BeginTuple), this->NumComps);
989  }
990 
992  const_iterator cend() const noexcept
993  {
994  return const_iterator(this->GetTuplePointer(this->EndTuple), this->NumComps);
995  }
996 
999  {
1000  return reference{ this->Array->Buffer->GetBuffer() +
1001  (this->BeginTuple + i) * this->NumComps.value,
1002  this->NumComps };
1003  }
1004 
1007  {
1008  return const_reference{ this->Array->Buffer->GetBuffer() +
1009  (this->BeginTuple + i) * this->NumComps.value,
1010  this->NumComps };
1011  }
1012 
1013  VTK_ITER_INLINE void GetTuple(size_type i, ValueType* tuple) const noexcept
1014  {
1015  const ValueType* tuplePtr =
1016  this->Array->Buffer->GetBuffer() + (this->BeginTuple + i) * this->NumComps.value;
1017  for (ComponentIdType c = 0; c < this->NumComps.value; ++c)
1018  {
1019  tuple[c] = tuplePtr[c];
1020  }
1021  }
1022 
1023  template <typename VT = ValueType>
1025  size_type i, double* tuple) const noexcept
1026  {
1027  const ValueType* tuplePtr =
1028  this->Array->Buffer->GetBuffer() + (this->BeginTuple + i) * this->NumComps.value;
1029  for (ComponentIdType c = 0; c < this->NumComps.value; ++c)
1030  {
1031  tuple[c] = static_cast<double>(tuplePtr[c]);
1032  }
1033  }
1034 
1035  VTK_ITER_INLINE void SetTuple(size_type i, const ValueType* tuple) noexcept
1036  {
1037  ValueType* tuplePtr =
1038  this->Array->Buffer->GetBuffer() + (this->BeginTuple + i) * this->NumComps.value;
1039  for (ComponentIdType c = 0; c < this->NumComps.value; ++c)
1040  {
1041  tuplePtr[c] = tuple[c];
1042  }
1043  }
1044 
1045  template <typename VT = ValueType>
1047  size_type i, const double* tuple) noexcept
1048  {
1049  ValueType* tuplePtr =
1050  this->Array->Buffer->GetBuffer() + (this->BeginTuple + i) * this->NumComps.value;
1051  for (ComponentIdType c = 0; c < this->NumComps.value; ++c)
1052  {
1053  tuplePtr[c] = static_cast<ValueType>(tuple[c]);
1054  }
1055  }
1056 
1057 private:
1059  ValueType* GetTuplePointer(vtkIdType tuple) const noexcept
1060  {
1061  return this->Array->Buffer->GetBuffer() + (tuple * this->NumComps.value);
1062  }
1063 
1065  TupleIdType GetTupleId(const ValueType* ptr) const noexcept
1066  {
1067  return static_cast<TupleIdType>((ptr - this->Array->GetPointer(0)) / this->NumComps.value);
1068  }
1069 
1070  mutable ArrayType* Array{ nullptr };
1071  NumCompsType NumComps{};
1072  TupleIdType BeginTuple{ 0 };
1073  TupleIdType EndTuple{ 0 };
1074 };
1075 
1076 // Unimplemented, only used inside decltype in SelectTupleRange:
1077 template <typename ArrayType, ComponentIdType TupleSize,
1078  // Convenience:
1079  typename ValueType = typename ArrayType::ValueType,
1080  typename AOSArrayType = vtkAOSDataArrayTemplate<ValueType>,
1081  // SFINAE to select AOS arrays:
1084 
1085 VTK_ABI_NAMESPACE_END
1086 } // end namespace detail
1087 } // end namespace vtk
1088 
1090 
1091 #endif // VTK_DEBUG_RANGE_ITERATORS
1092 #endif // vtkDataArrayTupleRange_AOS_h
1093 
1094 // VTK-HeaderTest-Exclude: vtkDataArrayTupleRange_AOS.h
Array-Of-Structs implementation of vtkGenericDataArray.
@ value
Definition: vtkX3D.h:220
@ type
Definition: vtkX3D.h:516
@ offset
Definition: vtkX3D.h:438
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, ForceValueTypeForVtkDataArray >::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
std::enable_if<!std::is_same< VT, double >::value >::type VTK_ITER_INLINE GetTuple(volatile double *tuple) 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
std::enable_if<!std::is_same< VT, double >::value >::type VTK_ITER_INLINE GetTuple(size_type i, double *tuple) const noexcept
VTK_ITER_INLINE void GetTuple(size_type i, ValueType *tuple) const noexcept
VTK_ITER_INLINE TupleRange GetSubRange(TupleIdType beginTuple=0, TupleIdType endTuple=-1) const noexcept
VTK_ITER_INLINE void SetTuple(size_type i, const ValueType *tuple) noexcept
std::enable_if<!std::is_same< VT, double >::value >::type VTK_ITER_INLINE SetTuple(size_type i, const double *tuple) 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
std::enable_if<!std::is_same< VT, double >::value >::type VTK_ITER_INLINE SetTuple(const double *tuple) 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
std::enable_if<!std::is_same< VT, double >::value >::type VTK_ITER_INLINE GetTuple(volatile double *tuple) const noexcept
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:315