VTK  9.7.1
vtkDataArrayValueRange_Generic.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
8 #ifndef vtkDataArrayValueRange_Generic_h
9 #define vtkDataArrayValueRange_Generic_h
10 
11 #include "vtkDataArrayMeta.h"
12 
13 #include <algorithm>
14 #include <cassert>
15 #include <iterator>
16 #include <tuple>
17 #include <type_traits>
18 
20 
21 namespace vtk
22 {
23 namespace detail
24 {
25 VTK_ABI_NAMESPACE_BEGIN
26 
27 // Forward decs for friends/args
28 template <typename ArrayType, ComponentIdType, typename ForceValueTypeForVtkDataArray>
30 template <typename ArrayType, ComponentIdType, typename ForceValueTypeForVtkDataArray>
32 template <typename ArrayType, ComponentIdType, typename ForceValueTypeForVtkDataArray>
34 template <typename ArrayType, ComponentIdType, typename ForceValueTypeForVtkDataArray>
36 template <typename ArrayType, ComponentIdType, typename ForceValueTypeForVtkDataArray>
37 struct ValueRange;
38 
39 //------------------------------------------------------------------------------
40 // Helper that converts ValueId <--> { TupleId, ComponentId }
41 // This class stores both representations. Profiling and assembly inspection
42 // show that ValueId is much more efficient for comparing Ids, while Tuple/Comp
43 // ids are much faster for looking up elements (especially when considering
44 // SOA arrays). The overhead of maintaining both is low, and this class is
45 // transparent enough that the compiler will produce efficient ASM with
46 // simple optimizations enabled.
47 template <ComponentIdType TupleSize>
48 struct IdStorage
49 {
51 
53  IdStorage() noexcept
54  : ValueId(0)
55  , TupleId(0)
56  , ComponentId(0)
57  {
58  }
59 
61  IdStorage(ValueIdType valueId, NumCompsType numComps) noexcept
62  : ValueId(valueId)
63  , TupleId(static_cast<TupleIdType>(valueId) / static_cast<TupleIdType>(numComps.value))
64  , ComponentId(static_cast<ComponentIdType>(valueId % static_cast<ValueIdType>(numComps.value)))
65  , NumComps(numComps)
66  {
67  }
68 
70  IdStorage(TupleIdType tupleId, ComponentIdType comp, NumCompsType numComps) noexcept
71  : ValueId(tupleId * numComps.value + comp)
72  , TupleId(tupleId)
73  , ComponentId(comp)
74  , NumComps(numComps)
75  {
76  }
77 
80  ValueIdType valueId, TupleIdType tupleId, ComponentIdType comp, NumCompsType numComps) noexcept
81  : ValueId(valueId)
82  , TupleId(tupleId)
83  , ComponentId(comp)
84  , NumComps(numComps)
85  {
86  }
87 
88  template <typename ArrayType>
89  VTK_ITER_INLINE void DebugAsserts(ArrayType* array) const noexcept
90  {
91  (void)array;
92  VTK_ITER_ASSERT(array != nullptr, "Invalid array.");
93  VTK_ITER_ASSERT(this->ValueId == this->TupleId * this->GetTupleSize() + this->ComponentId,
94  "Inconsistent internal state in IdStorage.");
95  VTK_ITER_ASSERT(this->GetTupleSize() > 0, "Invalid number of components.");
97  this->ValueId >= 0 && this->ValueId <= array->GetNumberOfValues(), "Invalid value id.");
98  VTK_ITER_ASSERT(this->GetTupleId() >= 0 && this->GetTupleId() <= array->GetNumberOfTuples(),
99  "Invalid tuple id.");
100  VTK_ITER_ASSERT(this->GetComponentId() >= 0 &&
101  (this->GetComponentId() < this->GetTupleSize() ||
102  (this->GetComponentId() == this->GetTupleSize() &&
103  this->GetTupleId() == array->GetNumberOfTuples())),
104  "Invalid component id.");
105  VTK_ITER_ASSERT(this->GetValueId() >= 0 && this->GetValueId() <= array->GetNumberOfValues(),
106  "Invalid value id.");
107  }
108 
110  IdStorage& operator++() noexcept // prefix
111  {
112  ++this->ValueId;
113  ++this->ComponentId;
114  if (this->ComponentId == this->GetTupleSize())
115  {
116  this->ComponentId = 0;
117  ++this->TupleId;
118  }
119  return *this;
120  }
121 
123  IdStorage operator++(int) noexcept // postfix
124  {
125  auto v = this->ValueId++;
126  auto t = this->TupleId;
127  auto c = this->ComponentId++;
128  if (this->ComponentId == this->GetTupleSize())
129  {
130  this->ComponentId = 0;
131  ++this->TupleId;
132  }
133  return IdStorage{ v, t, c, this->NumComps };
134  }
135 
137  {
138  IdStorage res = id;
139  res.AddOffset(offset);
140  return res;
141  }
142 
144  IdStorage& operator--() noexcept // prefix
145  {
146  --this->ValueId;
147  --this->ComponentId;
148  if (this->ComponentId < 0)
149  {
150  this->ComponentId = this->GetTupleSize() - 1;
151  --this->TupleId;
152  }
153  return *this;
154  }
155 
157  IdStorage operator--(int) noexcept // postfix
158  {
159  auto v = this->ValueId--;
160  auto t = this->TupleId;
161  auto c = this->ComponentId--;
162  if (this->ComponentId < 0)
163  {
164  this->ComponentId = this->GetTupleSize() - 1;
165  --this->TupleId;
166  }
167  return IdStorage{ v, t, c, this->NumComps };
168  }
169 
171  ValueIdType Convert(TupleIdType tuple, ComponentIdType comp) const noexcept
172  {
173  return static_cast<ValueIdType>(tuple) * this->NumComps.value + comp;
174  }
175 
177  std::pair<TupleIdType, ComponentIdType> Convert(ValueIdType value) const noexcept
178  {
179  return std::make_pair(static_cast<TupleIdType>(value / this->NumComps.value),
180  static_cast<ComponentIdType>(value % this->NumComps.value));
181  }
182 
184  void AddOffset(ValueIdType offset) noexcept
185  {
186  this->ValueId += offset;
187  std::tie(this->TupleId, this->ComponentId) = this->Convert(this->ValueId);
188  }
189 
191  ComponentIdType GetTupleSize() const noexcept { return this->NumComps.value; }
192 
194  TupleIdType GetTupleId() const noexcept { return this->TupleId; }
195 
197  ComponentIdType GetComponentId() const noexcept { return this->ComponentId; }
198 
200  ValueIdType GetValueId() const noexcept { return this->ValueId; }
201 
202  friend VTK_ITER_INLINE void swap(IdStorage& lhs, IdStorage& rhs) noexcept
203  {
204  using std::swap;
205  swap(lhs.ValueId, rhs.ValueId);
206  swap(lhs.TupleId, rhs.TupleId);
207  swap(lhs.ComponentId, rhs.ComponentId);
208  }
209 
210 private:
211  vtk::ValueIdType ValueId;
212  vtk::TupleIdType TupleId;
213  vtk::ComponentIdType ComponentId;
214  NumCompsType NumComps;
215 };
216 
217 //------------------------------------------------------------------------------
218 // Value reference
219 template <typename ArrayType, ComponentIdType TupleSize, typename ForceValueTypeForVtkDataArray>
220 struct ConstValueReference
221 {
222 private:
223  static_assert(IsValidTupleSize<TupleSize>::value, "Invalid tuple size.");
224  static_assert(IsVtkArray<ArrayType>::value, "Invalid array type.");
225 
226  using IdStorageType = IdStorage<TupleSize>;
228 
229 public:
230  using value_type = APIType;
231 
234  : Array{ nullptr }
235  , Id{}
236  {
237  }
238 
240  ConstValueReference(ArrayType* array, IdStorageType id) noexcept
241  : Array{ array }
242  , Id{ id }
243  {
244  this->Id.DebugAsserts(array);
245  }
246 
249  : Array{ o.Array }
250  , Id{ o.Id }
251  {
252  }
253 
255  ConstValueReference(const ConstValueReference& o) noexcept = default;
256 
258  ConstValueReference(ConstValueReference&& o) noexcept = default;
259 
261  ConstValueReference operator=(const ConstValueReference& o) noexcept
262  {
263  VTK_ITER_ASSERT(!this->Array, "Const reference already initialized.");
264  // Initialize the reference.
265  this->Array = o.Array;
266  this->Id = o.Id;
267  return *this;
268  }
269 
272  {
273  VTK_ITER_ASSERT(!this->Array, "Const reference already initialized.");
274  // Initialize the reference.
275  this->Array = std::move(o.Array);
276  this->Id = std::move(o.Id);
277  return *this;
278  }
279 
280  VTK_ITER_INLINE operator APIType() const noexcept
281  {
282  VTK_ITER_ASSUME(this->Id.GetTupleSize() > 0);
283  VTK_ITER_ASSUME(this->Array->GetNumberOfComponents() == this->Id.GetTupleSize());
284  if constexpr (std::is_same_v<ArrayType, vtkDataArray>)
285  {
286  return this->Array->GetComponent(this->Id.GetTupleId(), this->Id.GetComponentId());
287  }
288  else if constexpr (TupleSize == 1)
289  {
290  return this->Array->GetValue(this->Id.GetValueId());
291  }
292  else
293  {
294  return this->Array->GetTypedComponent(this->Id.GetTupleId(), this->Id.GetComponentId());
295  }
296  }
297 
298  mutable ArrayType* Array;
300 };
301 
302 //------------------------------------------------------------------------------
303 // Value reference
304 template <typename ArrayType, ComponentIdType TupleSize, typename ForceValueTypeForVtkDataArray>
305 struct ValueReference
306 {
307 private:
308  static_assert(IsValidTupleSize<TupleSize>::value, "Invalid tuple size.");
309  static_assert(IsVtkArray<ArrayType>::value, "Invalid array type.");
310 
312  using IdStorageType = IdStorage<TupleSize>;
313 
314 public:
315  using value_type = APIType;
316 
318  ValueReference() noexcept
319  : Array{ nullptr }
320  , Id{}
321  {
322  }
323 
325  ValueReference(ArrayType* array, IdStorageType id) noexcept
326  : Array{ array }
327  , Id{ id }
328  {
329  this->Id.DebugAsserts(this->Array);
330  }
331 
333  ValueReference(const ValueReference& o) noexcept = default;
335  ValueReference(ValueReference&& o) noexcept = default;
336 
338  ValueReference operator=(const ValueReference& o) noexcept
339  {
340  if (this->Array)
341  { // Already initialized. Assign the value, not the reference:
342  return *this = static_cast<APIType>(o);
343  }
344  else
345  { // Initialize the reference:
346  this->Array = o.Array;
347  this->Id = o.Id;
348  return *this;
349  }
350  }
351 
354  {
355  if (this->Array)
356  { // Already initialized. Assign the value, not the reference:
357  return *this = static_cast<APIType>(o);
358  }
359  else
360  { // Initialize the reference:
361  this->Array = std::move(o.Array);
362  this->Id = std::move(o.Id);
363  return *this;
364  }
365  }
366 
367  template <typename OArray, ComponentIdType OSize>
370  { // Always copy the value for different reference types:
371  const APIType tmp = o;
372  return *this = std::move(tmp);
373  }
374 
375  VTK_ITER_INLINE operator APIType() const noexcept
376  {
377  VTK_ITER_ASSUME(this->Id.GetTupleSize() > 0);
378  VTK_ITER_ASSUME(this->Array->GetNumberOfComponents() == this->Id.GetTupleSize());
379  if constexpr (std::is_same_v<ArrayType, vtkDataArray>)
380  {
381  return this->Array->GetComponent(this->Id.GetTupleId(), this->Id.GetComponentId());
382  }
383  else if constexpr (TupleSize == 1)
384  {
385  return this->Array->GetValue(this->Id.GetValueId());
386  }
387  else
388  {
389  return this->Array->GetTypedComponent(this->Id.GetTupleId(), this->Id.GetComponentId());
390  }
391  }
392 
394  {
395  VTK_ITER_ASSUME(this->Id.GetTupleSize() > 0);
396  VTK_ITER_ASSUME(this->Array->GetNumberOfComponents() == this->Id.GetTupleSize());
397  if constexpr (std::is_same_v<ArrayType, vtkDataArray>)
398  {
399  this->Array->SetComponent(this->Id.GetTupleId(), this->Id.GetComponentId(), val);
400  }
401  else if constexpr (TupleSize == 1)
402  {
403  this->Array->SetValue(this->Id.GetValueId(), val);
404  }
405  else
406  {
407  this->Array->SetTypedComponent(this->Id.GetTupleId(), this->Id.GetComponentId(), val);
408  }
409  return *this;
410  }
411 
412  friend VTK_ITER_INLINE void swap(ValueReference lhs, ValueReference rhs) noexcept
413  { // Swap values, not references:
414  APIType tmp = static_cast<APIType>(lhs);
415  lhs = static_cast<APIType>(rhs);
416  rhs = std::move(tmp);
417  }
418 
419  template <typename OArray, ComponentIdType OSize>
420  friend VTK_ITER_INLINE void swap(
422  { // Swap values, not references:
423  using OAPIType =
425  static_assert(
426  std::is_same<APIType, OAPIType>::value, "Cannot swap components with different types.");
427 
428  APIType tmp = static_cast<APIType>(lhs);
429  lhs = static_cast<APIType>(rhs);
430  rhs = std::move(tmp);
431  }
432 
433  friend VTK_ITER_INLINE void swap(ValueReference lhs, APIType& rhs) noexcept
434  {
435  APIType tmp = static_cast<APIType>(lhs);
436  lhs = std::move(rhs);
437  rhs = std::move(tmp);
438  }
439 
440  friend VTK_ITER_INLINE void swap(APIType& lhs, ValueReference rhs) noexcept
441  {
442  APIType tmp = std::move(lhs);
443  lhs = static_cast<APIType>(rhs);
444  rhs = std::move(tmp);
445  }
446 
448  ValueReference operator++() noexcept // prefix
449  {
450  const APIType newVal = *this + 1;
451  *this = newVal;
452  return *this;
453  }
454 
456  APIType operator++(int) noexcept // postfix
457  {
458  const APIType retVal = *this;
459  *this = *this + 1;
460  return retVal;
461  }
462 
464  ValueReference operator--() noexcept // prefix
465  {
466  const APIType newVal = *this - 1;
467  *this = newVal;
468  return *this;
469  }
470 
472  APIType operator--(int) noexcept // postfix
473  {
474  const APIType retVal = *this;
475  *this = *this - 1;
476  return retVal;
477  }
478 
479 #define VTK_REF_OP_OVERLOADS(Op, ImplOp) \
480  friend VTK_ITER_INLINE ValueReference operator Op(ValueReference lhs, APIType val) noexcept \
481  { \
482  const APIType newVal = lhs ImplOp val; \
483  lhs = newVal; \
484  return lhs; \
485  } \
486  friend VTK_ITER_INLINE ValueReference operator Op( \
487  ValueReference lhs, ValueReference val) noexcept \
488  { \
489  const APIType newVal = lhs ImplOp val; \
490  lhs = newVal; \
491  return lhs; \
492  } \
493  friend VTK_ITER_INLINE APIType& operator Op(APIType & lhs, ValueReference val) noexcept \
494  { \
495  const APIType newVal = lhs ImplOp val; \
496  lhs = newVal; \
497  return lhs; \
498  }
499 
500  VTK_REF_OP_OVERLOADS(+=, +)
501  VTK_REF_OP_OVERLOADS(-=, -)
502  VTK_REF_OP_OVERLOADS(*=, *)
503  VTK_REF_OP_OVERLOADS(/=, /)
504  VTK_REF_OP_OVERLOADS(|=, |)
505  VTK_REF_OP_OVERLOADS(&=, &)
506  VTK_REF_OP_OVERLOADS(^=, ^)
507 
508 #undef VTK_REF_OP_OVERLOADS
509 
510  friend struct ConstValueReference<ArrayType, TupleSize, ForceValueTypeForVtkDataArray>;
511  friend struct ValueIterator<ArrayType, TupleSize, ForceValueTypeForVtkDataArray>;
512 
513 protected:
514  void CopyReference(const ValueReference& o) noexcept
515  {
516  this->Array = o.Array;
517  this->Id = o.Id;
518  }
519 
520  mutable ArrayType* Array;
522 };
523 
524 //------------------------------------------------------------------------------
525 // Const value iterator
526 template <typename ArrayType, ComponentIdType TupleSize, typename ForceValueTypeForVtkDataArray>
527 struct ConstValueIterator
528 {
529 private:
530  static_assert(IsValidTupleSize<TupleSize>::value, "Invalid tuple size.");
531  static_assert(IsVtkArray<ArrayType>::value, "Invalid array type.");
532 
534  using IdStorageType = IdStorage<TupleSize>;
535 
536 public:
537  using iterator_category = std::random_access_iterator_tag;
538  using value_type = APIType;
540  using pointer = void;
542 
545  : Array(nullptr)
546  , Id()
547  {
548  }
549 
551  ConstValueIterator(ArrayType* array, IdStorageType id) noexcept
552  : Array(array)
553  , Id(id)
554  {
555  this->Id.DebugAsserts(this->Array);
556  }
557 
561  : Array{ o.GetArray() }
562  , Id{ o.GetId() }
563  {
564  }
565 
567  ConstValueIterator(const ConstValueIterator& o) noexcept = default;
569  ConstValueIterator& operator=(const ConstValueIterator& o) noexcept = default;
570 
572  ConstValueIterator& operator++() noexcept // prefix
573  {
574  ++this->Id;
575  this->Id.DebugAsserts(this->Array);
576  return *this;
577  }
578 
580  ConstValueIterator operator++(int) noexcept // postfix
581  {
582  auto ret = this->Id++;
583  this->Id.DebugAsserts(this->Array);
584  return ConstValueIterator{ this->Array, ret };
585  }
586 
588  ConstValueIterator& operator--() noexcept // prefix
589  {
590  --this->Id;
591  this->Id.DebugAsserts(this->Array);
592  return *this;
593  }
594 
596  ConstValueIterator operator--(int) noexcept // postfix
597  {
598  auto ret = this->Id--;
599  this->Id.DebugAsserts(this->Array);
600  return ConstValueIterator{ this->Array, ret };
601  }
602 
605  {
606  return reference{ this->Array, this->Id + i };
607  }
608 
610  reference operator*() const noexcept { return reference{ this->Array, this->Id }; }
611 
612  // Using GetValueType here makes iteration 50% faster by reducing comparisons
613  // and jumps (instead of comparing std::tie(tupleId, compId)).
614 #define VTK_TMP_MAKE_OPERATOR(OP) \
615  friend VTK_ITER_INLINE bool operator OP( \
616  const ConstValueIterator& lhs, const ConstValueIterator& rhs) noexcept \
617  { \
618  VTK_ITER_ASSERT(lhs.Array == rhs.Array, "Mismatched arrays in iterator comparison."); \
619  return lhs.Id.GetValueId() OP rhs.Id.GetValueId(); \
620  }
621 
628 
629 #undef VTK_TMP_MAKE_OPERATOR
630 
633  {
634  this->Id.AddOffset(offset);
635  this->Id.DebugAsserts(this->Array);
636  return *this;
637  }
638 
640  const ConstValueIterator& it, difference_type offset) noexcept
641  {
642  return ConstValueIterator{ it.Array, it.Id + offset };
643  }
644 
646  difference_type offset, const ConstValueIterator& it) noexcept
647  {
648  return ConstValueIterator{ it.Array, it.Id + offset };
649  }
650 
653  {
654  this->Id.AddOffset(-offset);
655  this->Id.DebugAsserts(this->Array);
656  return *this;
657  }
658 
660  const ConstValueIterator& it, difference_type offset) noexcept
661  {
662  return ConstValueIterator{ it.Array, it.Id + (-offset) };
663  }
664 
666  const ConstValueIterator& it1, const ConstValueIterator& it2) noexcept
667  {
668  VTK_ITER_ASSERT(it1.Array == it2.Array, "Cannot do math with iterators from different arrays.");
669  return it1.Id.GetValueId() - it2.Id.GetValueId();
670  }
671 
673  {
674  // Different arrays may use different iterator implementations.
675  VTK_ITER_ASSERT(lhs.Array == rhs.Array, "Cannot swap iterators from different arrays.");
676 
677  using std::swap;
678  swap(lhs.Id, rhs.Id);
679  }
680 
681 private:
682  mutable ArrayType* Array;
683  IdStorageType Id;
684 };
685 
686 //------------------------------------------------------------------------------
687 // Component iterator
688 template <typename ArrayType, ComponentIdType TupleSize, typename ForceValueTypeForVtkDataArray>
689 struct ValueIterator
690 {
691 private:
692  static_assert(IsValidTupleSize<TupleSize>::value, "Invalid tuple size.");
693  static_assert(IsVtkArray<ArrayType>::value, "Invalid array type.");
694 
696  using IdStorageType = IdStorage<TupleSize>;
697 
698 public:
699  using iterator_category = std::random_access_iterator_tag;
704 
706  ValueIterator() noexcept = default;
707 
709  ValueIterator(ArrayType* array, IdStorageType id) noexcept
710  : Ref{ array, id }
711  {
712  this->DebugIdAsserts();
713  }
714 
716  ValueIterator(const ValueIterator& o) noexcept = default;
717 
720  {
721  this->Ref.CopyReference(o.Ref);
722  this->DebugIdAsserts();
723  return *this;
724  }
725 
727  ValueIterator& operator++() noexcept // prefix
728  {
729  ++this->Ref.Id;
730  this->DebugIdAsserts();
731  return *this;
732  }
733 
735  ValueIterator operator++(int) noexcept // postfix
736  {
737  auto ret = this->Ref.Id++;
738  this->DebugIdAsserts();
739  return ValueIterator{ this->Ref.Array, ret };
740  }
741 
743  ValueIterator& operator--() noexcept // prefix
744  {
745  --this->Ref.Id;
746  this->DebugIdAsserts();
747  return *this;
748  }
749 
751  ValueIterator operator--(int) noexcept // postfix
752  {
753  auto ret = this->Ref.Id--;
754  this->DebugIdAsserts();
755  return ValueIterator{ this->Ref.Array, ret };
756  }
757 
760  {
761  return reference{ this->Ref.Array, this->Ref.Id + i };
762  }
763 
765  reference operator*() const noexcept { return this->Ref; }
766 
768  const pointer& operator->() const noexcept { return this->Ref; }
769 
770 #define VTK_TMP_MAKE_OPERATOR(OP) \
771  friend VTK_ITER_INLINE bool operator OP( \
772  const ValueIterator& lhs, const ValueIterator& rhs) noexcept \
773  { \
774  VTK_ITER_ASSERT( \
775  lhs.GetArray() == rhs.GetArray(), "Mismatched arrays in iterator comparison."); \
776  return lhs.GetId().GetValueId() OP rhs.GetId().GetValueId(); \
777  }
778 
785 
786 #undef VTK_TMP_MAKE_OPERATOR
787 
790  {
791  this->Ref.Id.AddOffset(offset);
792  this->DebugIdAsserts();
793  return *this;
794  }
795 
797  const ValueIterator& it, difference_type offset) noexcept
798  {
799  return ValueIterator{ it.GetArray(), it.GetId() + offset };
800  }
801 
803  difference_type offset, const ValueIterator& it) noexcept
804  {
805  return ValueIterator{ it.GetArray(), it.GetId() + offset };
806  }
807 
810  {
811  this->Ref.Id.AddOffset(-offset);
812  this->Ref.Id.DebugAsserts(this->Ref.Array);
813  return *this;
814  }
815 
817  const ValueIterator& it, difference_type offset) noexcept
818  {
819  return ValueIterator{ it.GetArray(), it.GetId() + (-offset) };
820  }
821 
823  const ValueIterator& it1, const ValueIterator& it2) noexcept
824  {
826  it1.Ref.Array == it2.Ref.Array, "Cannot do math with iterators from different arrays.");
827  return it1.GetId().GetValueId() - it2.GetId().GetValueId();
828  }
829 
830  friend VTK_ITER_INLINE void swap(ValueIterator& lhs, ValueIterator& rhs) noexcept
831  {
832  // Different arrays may use different iterator implementations.
834  lhs.GetArray() == rhs.GetArray(), "Cannot swap iterators from different arrays.");
835 
836  using std::swap;
837  swap(lhs.GetId(), rhs.GetId());
838  }
839 
840  friend struct ConstValueIterator<ArrayType, TupleSize, ForceValueTypeForVtkDataArray>;
841 
842 protected:
844  void DebugIdAsserts() const { this->Ref.Id.DebugAsserts(this->Ref.Array); }
845 
846  // Needed for access from friend functions. We could just store the array
847  // and ID here instead of the ref, but meh.
848  ArrayType* GetArray() const noexcept { return this->Ref.Array; }
849  IdStorageType& GetId() noexcept { return this->Ref.Id; }
850  const IdStorageType& GetId() const noexcept { return this->Ref.Id; }
851 
853 };
854 
855 //------------------------------------------------------------------------------
856 // ValueRange
857 template <typename ArrayTypeT, ComponentIdType TupleSize, typename ForceValueTypeForVtkDataArray>
858 struct ValueRange
859 {
860 private:
861  static_assert(IsValidTupleSize<TupleSize>::value, "Invalid tuple size.");
862  static_assert(IsVtkArray<ArrayTypeT>::value, "Invalid array type.");
863 
864  using IdStorageType = IdStorage<TupleSize>;
865  using NumCompsType = GenericTupleSize<TupleSize>;
866 
867 public:
868  using ArrayType = ArrayTypeT;
870 
874  using ConstReferenceType =
876 
877  // May be DynamicTupleSize, or the actual tuple size.
878  constexpr static ComponentIdType TupleSizeTag = TupleSize;
879 
880  // STL-compat
887 
889  ValueRange() noexcept = default;
890 
892  ValueRange(ArrayType* arr, ValueIdType beginValue, ValueIdType endValue) noexcept
893  : Array(arr)
894  , NumComps(arr)
895  , BeginValue(beginValue, this->NumComps)
896  , EndValue(endValue, this->NumComps)
897  {
898  assert(this->Array);
899  assert(beginValue >= 0 && beginValue <= endValue);
900  assert(endValue >= 0 && endValue <= this->Array->GetNumberOfValues());
902  {
903  assert(arr->GetNumberOfComponents() == TupleSize);
904  }
905  }
906 
908  ValueRange GetSubRange(ValueIdType beginValue = 0, ValueIdType endValue = -1) const noexcept
909  {
910  const ValueIdType realBegin = this->BeginValue.GetValueId() + beginValue;
911  const ValueIdType realEnd =
912  endValue >= 0 ? this->BeginValue.GetValueId() + endValue : this->EndValue.GetValueId();
913 
914  return ValueRange{ this->Array, realBegin, realEnd };
915  }
916 
918  ArrayType* GetArray() const noexcept { return this->Array; }
920  ComponentIdType GetTupleSize() const noexcept { return this->NumComps.value; }
921 
923  ValueIdType GetBeginValueId() const noexcept { return this->BeginValue.GetValueId(); }
924 
926  ValueIdType GetEndValueId() const noexcept { return this->EndValue.GetValueId(); }
927 
929  size_type size() const noexcept
930  {
931  return this->EndValue.GetValueId() - this->BeginValue.GetValueId();
932  }
933 
935  iterator begin() noexcept { return this->NewIterator(this->BeginValue); }
937  iterator end() noexcept { return this->NewIterator(this->EndValue); }
938 
940  const_iterator begin() const noexcept { return this->NewConstIterator(this->BeginValue); }
942  const_iterator end() const noexcept { return this->NewConstIterator(this->EndValue); }
943 
945  const_iterator cbegin() const noexcept { return this->NewConstIterator(this->BeginValue); }
947  const_iterator cend() const noexcept { return this->NewConstIterator(this->EndValue); }
948 
951  {
952  return reference{ this->Array, this->BeginValue + i };
953  }
956  {
957  return const_reference{ this->Array, this->BeginValue + i };
958  }
959 
961 
968  VTK_DEPRECATED_IN_9_6_0("Use iterators instead.")
969  value_type* data() noexcept
970  {
971  // NOLINTNEXTLINE(bugprone-unsafe-functions)
972  return reinterpret_cast<value_type*>(this->Array->GetVoidPointer(0));
973  }
974  VTK_DEPRECATED_IN_9_6_0("Use iterators instead.")
975  value_type* data() const noexcept
976  {
977  // NOLINTNEXTLINE(bugprone-unsafe-functions)
978  return reinterpret_cast<value_type*>(this->Array->GetVoidPointer(0));
979  }
981 
982 private:
984  iterator NewIterator(IdStorageType id) const noexcept { return iterator{ this->Array, id }; }
985 
987  const_iterator NewConstIterator(IdStorageType id) const noexcept
988  {
989  return const_iterator{ this->Array, id };
990  }
991 
992  mutable ArrayType* Array{ nullptr };
993  NumCompsType NumComps{};
994  IdStorageType BeginValue{};
995  IdStorageType EndValue{};
996 };
997 
998 // Unimplemented, only used inside decltype in SelectValueRange:
999 template <typename ArrayType, ComponentIdType TupleSize, typename ForceValueTypeForVtkDataArray>
1000 ValueRange<ArrayType, TupleSize, ForceValueTypeForVtkDataArray> DeclareValueRangeSpecialization(
1001  vtkAbstractArray*);
1002 
1003 VTK_ABI_NAMESPACE_END
1004 } // end namespace detail
1005 } // end namespace vtk
1006 
1008 
1009 #endif // vtkDataArrayValueRange_Generic_h
1010 
1011 // VTK-HeaderTest-Exclude: vtkDataArrayValueRange_Generic.h
friend VTK_ITER_INLINE void swap(IdStorage &lhs, IdStorage &rhs) noexcept
VTK_ITER_INLINE ConstValueReference(ArrayType *array, IdStorageType id) noexcept
vtkIdType TupleIdType
int ComponentIdType
VTK_ITER_INLINE ValueIterator operator++(int) noexcept
friend VTK_ITER_INLINE void swap(ValueReference lhs, ValueReference< OArray, OSize, ForceValueTypeForVtkDataArray > rhs) noexcept
friend VTK_ITER_INLINE void swap(ConstValueIterator &lhs, ConstValueIterator &rhs) noexcept
VTK_ITER_INLINE ValueReference operator=(APIType val) noexcept
VTK_ITER_INLINE ConstValueIterator(const ValueIterator< ArrayType, TupleSize, ForceValueTypeForVtkDataArray > &o) noexcept
VTK_ITER_INLINE ValueIdType GetValueId() const noexcept
VTK_ITER_INLINE ArrayType * GetArray() const noexcept
VTK_ITER_INLINE ValueIterator & operator++() noexcept
VTK_ITER_INLINE const pointer & operator->() const noexcept
friend VTK_ITER_INLINE IdStorage operator+(const IdStorage &id, ValueIdType offset) noexcept
VTK_ITER_INLINE ValueReference operator--() noexcept
VTK_ITER_INLINE ValueReference operator++() noexcept
VTK_ITER_INLINE ConstValueReference(const ValueReference< ArrayType, TupleSize, ForceValueTypeForVtkDataArray > &o)
Abstract superclass for all arrays.
typename detail::GetAPITypeImpl< ArrayType, ForceValueTypeForVtkDataArray >::APIType GetAPIType
VTK_ITER_INLINE IdStorage(ValueIdType valueId, NumCompsType numComps) noexcept
#define VTK_REF_OP_OVERLOADS(Op, ImplOp)
VTK_ITER_INLINE ValueIterator & operator=(const ValueIterator &o) noexcept
VTK_ITER_INLINE ConstValueIterator & operator-=(difference_type offset) noexcept
VTK_ITER_INLINE reference operator*() const noexcept
ArrayType * GetArray() const noexcept
VTK_ITER_INLINE IdStorage operator++(int) noexcept
VTK_ITER_INLINE ValueReference operator=(ValueReference &&o) noexcept
Specialization of tuple ranges and iterators for vtkAOSDataArrayTemplate.
GenericTupleSize< TupleSize > NumCompsType
VTK_ITER_INLINE const_reference operator[](size_type i) const noexcept
VTK_ITER_INLINE ConstValueReference operator=(ConstValueReference &&o) noexcept
VTK_ITER_INLINE ValueRange GetSubRange(ValueIdType beginValue=0, ValueIdType endValue=-1) const noexcept
vtkIdType ValueIdType
std::random_access_iterator_tag iterator_category
GetAPIType< ArrayType, ForceValueTypeForVtkDataArray > ValueType
friend VTK_ITER_INLINE difference_type operator-(const ConstValueIterator &it1, const ConstValueIterator &it2) noexcept
VTK_ITER_INLINE IdStorage() noexcept
VTK_ITER_INLINE APIType operator++(int) noexcept
VTK_ITER_INLINE IdStorage & operator++() noexcept
VTK_ITER_INLINE ConstValueIterator & operator++() noexcept
This file contains a variety of metaprogramming constructs for working with vtkDataArrays.
VTK_ITER_INLINE TupleIdType GetTupleId() const noexcept
std::random_access_iterator_tag iterator_category
ValueRange< AOSArrayType, TupleSize, ForceValueTypeForVtkDataArray > DeclareValueRangeSpecialization(ArrayType *)
VTK_ITER_INLINE void AddOffset(ValueIdType offset) noexcept
#define VTK_ITER_INLINE
void CopyReference(const ValueReference &o) noexcept
VTK_ITER_INLINE std::pair< TupleIdType, ComponentIdType > Convert(ValueIdType value) const noexcept
VTK_ITER_INLINE IdStorage & operator--() noexcept
#define VTK_DEPRECATED_IN_9_6_0(reason)
#define VTK_ITER_ASSUME
friend VTK_ITER_INLINE void swap(APIType &lhs, ValueReference rhs) noexcept
VTK_ITER_INLINE ConstValueIterator & operator=(const ConstValueIterator &o) noexcept=default
VTK_ITER_INLINE ValueReference operator=(const ValueReference< OArray, OSize, ForceValueTypeForVtkDataArray > &o) noexcept
VTK_ITER_INLINE IdStorage(TupleIdType tupleId, ComponentIdType comp, NumCompsType numComps) noexcept
VTK_ITER_INLINE ValueIdType GetEndValueId() const noexcept
friend VTK_ITER_INLINE ValueIterator operator+(difference_type offset, const ValueIterator &it) noexcept
#define VTK_ITER_OPTIMIZE_END
VTK_ITER_INLINE ComponentIdType GetComponentId() const noexcept
VTK_ITER_INLINE ValueReference() noexcept
VTK_ITER_INLINE ValueIdType Convert(TupleIdType tuple, ComponentIdType comp) const noexcept
VTK_ITER_INLINE APIType operator--(int) noexcept
friend VTK_ITER_INLINE difference_type operator-(const ValueIterator &it1, const ValueIterator &it2) noexcept
#define VTK_TMP_MAKE_OPERATOR(OP)
VTK_ITER_INLINE ValueIdType GetBeginValueId() const noexcept
friend VTK_ITER_INLINE ConstValueIterator operator-(const ConstValueIterator &it, difference_type offset) noexcept
VTK_ITER_INLINE size_type size() const noexcept
VTK_ITER_INLINE reference operator[](size_type i) noexcept
VTK_ITER_INLINE ConstValueIterator & operator+=(difference_type offset) noexcept
friend VTK_ITER_INLINE void swap(ValueIterator &lhs, ValueIterator &rhs) noexcept
VTK_ITER_INLINE void DebugIdAsserts() const
VTK_ITER_INLINE ValueIterator & operator+=(difference_type offset) noexcept
#define VTK_ITER_ASSERT(x, msg)
ValueReference< ArrayType, TupleSize, ForceValueTypeForVtkDataArray > Ref
VTK_ITER_INLINE iterator end() noexcept
friend VTK_ITER_INLINE void swap(ValueReference lhs, APIType &rhs) noexcept
VTK_ITER_INLINE reference operator*() const noexcept
VTK_ITER_INLINE ConstValueIterator(ArrayType *array, IdStorageType id) noexcept
VTK_ITER_INLINE ValueIterator operator--(int) noexcept
friend VTK_ITER_INLINE ValueIterator operator+(const ValueIterator &it, difference_type offset) noexcept
friend VTK_ITER_INLINE ConstValueIterator operator+(difference_type offset, const ConstValueIterator &it) noexcept
VTK_ITER_INLINE const_iterator begin() const noexcept
VTK_ITER_INLINE ComponentIdType GetTupleSize() const noexcept
friend VTK_ITER_INLINE ValueIterator operator-(const ValueIterator &it, difference_type offset) noexcept
GetAPIType< ArrayType, ForceValueTypeForVtkDataArray > value_type
VTK_ITER_INLINE iterator begin() noexcept
VTK_ITER_INLINE ValueReference(ArrayType *array, IdStorageType id) noexcept
const IdStorageType & GetId() const noexcept
VTK_ITER_INLINE const_iterator end() const noexcept
#define VTK_ITER_OPTIMIZE_START
friend VTK_ITER_INLINE ConstValueIterator operator+(const ConstValueIterator &it, difference_type offset) noexcept
VTK_ITER_INLINE IdStorage(ValueIdType valueId, TupleIdType tupleId, ComponentIdType comp, NumCompsType numComps) noexcept
VTK_ITER_INLINE ComponentIdType GetTupleSize() const noexcept
VTK_ITER_INLINE ValueIterator & operator--() noexcept
VTK_ITER_INLINE const_iterator cend() const noexcept
VTK_ITER_INLINE ValueIterator & operator-=(difference_type offset) noexcept
VTK_ITER_INLINE void DebugAsserts(ArrayType *array) const noexcept
VTK_ITER_INLINE reference operator[](difference_type i) const noexcept
VTK_ITER_INLINE ConstValueIterator operator--(int) noexcept
VTK_ITER_INLINE reference operator[](difference_type i) const noexcept
VTK_ITER_INLINE ConstValueIterator & operator--() noexcept
VTK_ITER_INLINE const_iterator cbegin() const noexcept
VTK_ITER_INLINE IdStorage operator--(int) noexcept
VTK_ITER_INLINE ConstValueIterator operator++(int) noexcept
friend VTK_ITER_INLINE void swap(ValueReference lhs, ValueReference rhs) noexcept