VTK  9.3.20240224
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 "vtkDataArrayAccessor.h"
12 #include "vtkDataArrayMeta.h"
13 
14 #include <algorithm>
15 #include <cassert>
16 #include <iterator>
17 #include <tuple>
18 #include <type_traits>
19 
21 
22 namespace vtk
23 {
24 namespace detail
25 {
26 VTK_ABI_NAMESPACE_BEGIN
27 
28 // Forward decs for friends/args
29 template <typename ArrayType, ComponentIdType, typename ForceValueTypeForVtkDataArray>
30 struct ValueReference;
31 template <typename ArrayType, ComponentIdType, typename ForceValueTypeForVtkDataArray>
32 struct ConstValueReference;
33 template <typename ArrayType, ComponentIdType, typename ForceValueTypeForVtkDataArray>
34 struct ValueIterator;
35 template <typename ArrayType, ComponentIdType, typename ForceValueTypeForVtkDataArray>
36 struct ConstValueIterator;
37 template <typename ArrayType, ComponentIdType, typename ForceValueTypeForVtkDataArray>
38 struct ValueRange;
39 
40 //------------------------------------------------------------------------------
41 // Helper that converts ValueId <--> { TupleId, ComponentId }
42 // This class stores both representations. Profiling and assembly inspection
43 // show that ValueId is much more efficient for comparing Ids, while Tuple/Comp
44 // ids are much faster for looking up elements (especially when considering
45 // SOA arrays). The overhead of maintaining both is low, and this class is
46 // transparent enough that the compiler will produce efficient ASM with
47 // simple optimizations enabled.
48 template <ComponentIdType TupleSize>
49 struct IdStorage
50 {
52 
54  IdStorage() noexcept
55  : ValueId(0)
56  , TupleId(0)
57  , ComponentId(0)
58  {
59  }
60 
62  IdStorage(ValueIdType valueId, NumCompsType numComps) noexcept
63  : ValueId(valueId)
64  , TupleId(static_cast<TupleIdType>(valueId) / static_cast<TupleIdType>(numComps.value))
65  , ComponentId(static_cast<ComponentIdType>(valueId % static_cast<ValueIdType>(numComps.value)))
66  , NumComps(numComps)
67  {
68  }
69 
71  IdStorage(TupleIdType tupleId, ComponentIdType comp, NumCompsType numComps) noexcept
72  : ValueId(tupleId * numComps.value + comp)
73  , TupleId(tupleId)
74  , ComponentId(comp)
75  , NumComps(numComps)
76  {
77  }
78 
81  ValueIdType valueId, TupleIdType tupleId, ComponentIdType comp, NumCompsType numComps) noexcept
82  : ValueId(valueId)
83  , TupleId(tupleId)
84  , ComponentId(comp)
85  , NumComps(numComps)
86  {
87  }
88 
89  template <typename ArrayType>
90  VTK_ITER_INLINE void DebugAsserts(ArrayType* array) const noexcept
91  {
92  (void)array;
93  VTK_ITER_ASSERT(array != nullptr, "Invalid array.");
94  VTK_ITER_ASSERT(this->ValueId == this->TupleId * this->GetTupleSize() + this->ComponentId,
95  "Inconsistent internal state in IdStorage.");
96  VTK_ITER_ASSERT(this->GetTupleSize() > 0, "Invalid number of components.");
98  this->ValueId >= 0 && this->ValueId <= array->GetNumberOfValues(), "Invalid value id.");
99  VTK_ITER_ASSERT(this->GetTupleId() >= 0 && this->GetTupleId() <= array->GetNumberOfTuples(),
100  "Invalid tuple id.");
101  VTK_ITER_ASSERT(this->GetComponentId() >= 0 &&
102  (this->GetComponentId() < this->GetTupleSize() ||
103  (this->GetComponentId() == this->GetTupleSize() &&
104  this->GetTupleId() == array->GetNumberOfTuples())),
105  "Invalid component id.");
106  VTK_ITER_ASSERT(this->GetValueId() >= 0 && this->GetValueId() <= array->GetNumberOfValues(),
107  "Invalid value id.");
108  }
109 
111  IdStorage& operator++() noexcept // prefix
112  {
113  ++this->ValueId;
114  ++this->ComponentId;
115  if (this->ComponentId == this->GetTupleSize())
116  {
117  this->ComponentId = 0;
118  ++this->TupleId;
119  }
120  return *this;
121  }
122 
124  IdStorage operator++(int) noexcept // postfix
125  {
126  auto v = this->ValueId++;
127  auto t = this->TupleId;
128  auto c = this->ComponentId++;
129  if (this->ComponentId == this->GetTupleSize())
130  {
131  this->ComponentId = 0;
132  ++this->TupleId;
133  }
134  return IdStorage{ v, t, c, this->NumComps };
135  }
136 
138  {
139  IdStorage res = id;
140  res.AddOffset(offset);
141  return res;
142  }
143 
145  IdStorage& operator--() noexcept // prefix
146  {
147  --this->ValueId;
148  --this->ComponentId;
149  if (this->ComponentId < 0)
150  {
151  this->ComponentId = this->GetTupleSize() - 1;
152  --this->TupleId;
153  }
154  return *this;
155  }
156 
158  IdStorage operator--(int) noexcept // postfix
159  {
160  auto v = this->ValueId--;
161  auto t = this->TupleId;
162  auto c = this->ComponentId--;
163  if (this->ComponentId < 0)
164  {
165  this->ComponentId = this->GetTupleSize() - 1;
166  --this->TupleId;
167  }
168  return IdStorage{ v, t, c, this->NumComps };
169  }
170 
172  ValueIdType Convert(TupleIdType tuple, ComponentIdType comp) const noexcept
173  {
174  return static_cast<ValueIdType>(tuple) * this->NumComps.value + comp;
175  }
176 
178  std::pair<TupleIdType, ComponentIdType> Convert(ValueIdType value) const noexcept
179  {
180  return std::make_pair(static_cast<TupleIdType>(value / this->NumComps.value),
181  static_cast<ComponentIdType>(value % this->NumComps.value));
182  }
183 
185  void AddOffset(ValueIdType offset) noexcept
186  {
187  this->ValueId += offset;
188  std::tie(this->TupleId, this->ComponentId) = this->Convert(this->ValueId);
189  }
190 
192  ComponentIdType GetTupleSize() const noexcept { return this->NumComps.value; }
193 
195  TupleIdType GetTupleId() const noexcept { return this->TupleId; }
196 
198  ComponentIdType GetComponentId() const noexcept { return this->ComponentId; }
199 
201  ValueIdType GetValueId() const noexcept { return this->ValueId; }
202 
203  friend VTK_ITER_INLINE void swap(IdStorage& lhs, IdStorage& rhs) noexcept
204  {
205  using std::swap;
206  swap(lhs.ValueId, rhs.ValueId);
207  swap(lhs.TupleId, rhs.TupleId);
208  swap(lhs.ComponentId, rhs.ComponentId);
209  }
210 
211 private:
212  vtk::ValueIdType ValueId;
213  vtk::TupleIdType TupleId;
214  vtk::ComponentIdType ComponentId;
215  NumCompsType NumComps;
216 };
217 
218 //------------------------------------------------------------------------------
219 // Value reference
220 template <typename ArrayType, ComponentIdType TupleSize, typename ForceValueTypeForVtkDataArray>
222 {
223 private:
224  static_assert(IsValidTupleSize<TupleSize>::value, "Invalid tuple size.");
225  static_assert(IsVtkDataArray<ArrayType>::value, "Invalid array type.");
226 
229 
230 public:
231  using value_type = APIType;
232 
235  : Array{ nullptr }
236  , Id{}
237  {
238  }
239 
241  ConstValueReference(ArrayType* array, IdStorageType id) noexcept
242  : Array{ array }
243  , Id{ id }
244  {
245  this->Id.DebugAsserts(array);
246  }
247 
250  : Array{ o.Array }
251  , Id{ o.Id }
252  {
253  }
254 
256  ConstValueReference(const ConstValueReference& o) noexcept = default;
257 
259  ConstValueReference(ConstValueReference&& o) noexcept = default;
260 
263  {
264  VTK_ITER_ASSERT(!this->Array, "Const reference already initialized.");
265  // Initialize the reference.
266  this->Array = o.Array;
267  this->Id = o.Id;
268  return *this;
269  }
270 
273  {
274  VTK_ITER_ASSERT(!this->Array, "Const reference already initialized.");
275  // Initialize the reference.
276  this->Array = std::move(o.Array);
277  this->Id = std::move(o.Id);
278  return *this;
279  }
280 
281  VTK_ITER_INLINE operator APIType() const noexcept { return this->castOperator(); }
282 
283 protected:
284  template <typename AT = ArrayType>
286  castOperator() const noexcept
287  {
288  VTK_ITER_ASSUME(this->Id.GetTupleSize() > 0);
289  VTK_ITER_ASSUME(this->Array->GetNumberOfComponents() == this->Id.GetTupleSize());
290  return this->Array->GetComponent(this->Id.GetTupleId(), this->Id.GetComponentId());
291  }
292 
293  template <typename AT = ArrayType>
295  castOperator() const noexcept
296  {
297  VTK_ITER_ASSUME(this->Id.GetTupleSize() > 0);
298  VTK_ITER_ASSUME(this->Array->GetNumberOfComponents() == this->Id.GetTupleSize());
299  return this->Array->GetTypedComponent(this->Id.GetTupleId(), this->Id.GetComponentId());
300  }
301 
302  mutable ArrayType* Array;
304 };
305 
306 //------------------------------------------------------------------------------
307 // Value reference
308 template <typename ArrayType, ComponentIdType TupleSize, typename ForceValueTypeForVtkDataArray>
310 {
311 private:
312  static_assert(IsValidTupleSize<TupleSize>::value, "Invalid tuple size.");
313  static_assert(IsVtkDataArray<ArrayType>::value, "Invalid array type.");
314 
317 
318 public:
319  using value_type = APIType;
320 
322  ValueReference() noexcept
323  : Array{ nullptr }
324  , Id{}
325  {
326  }
327 
329  ValueReference(ArrayType* array, IdStorageType id) noexcept
330  : Array{ array }
331  , Id{ id }
332  {
333  this->Id.DebugAsserts(this->Array);
334  }
335 
337  ValueReference(const ValueReference& o) noexcept = default;
339  ValueReference(ValueReference&& o) noexcept = default;
340 
343  {
344  if (this->Array)
345  { // Already initialized. Assign the value, not the reference:
346  return *this = static_cast<APIType>(o);
347  }
348  else
349  { // Initialize the reference:
350  this->Array = o.Array;
351  this->Id = o.Id;
352  return *this;
353  }
354  }
355 
358  {
359  if (this->Array)
360  { // Already initialized. Assign the value, not the reference:
361  return *this = static_cast<APIType>(o);
362  }
363  else
364  { // Initialize the reference:
365  this->Array = std::move(o.Array);
366  this->Id = std::move(o.Id);
367  return *this;
368  }
369  }
370 
371  template <typename OArray, ComponentIdType OSize>
374  { // Always copy the value for different reference types:
375  const APIType tmp = o;
376  return *this = std::move(tmp);
377  }
378 
379  VTK_ITER_INLINE operator APIType() const noexcept { return this->castOperator(); }
380 
381  template <typename AT = ArrayType>
384  operator=(APIType val) noexcept
385  {
386  VTK_ITER_ASSUME(this->Id.GetTupleSize() > 0);
387  VTK_ITER_ASSUME(this->Array->GetNumberOfComponents() == this->Id.GetTupleSize());
388  this->Array->SetComponent(this->Id.GetTupleId(), this->Id.GetComponentId(), val);
389  return *this;
390  }
391 
392  template <typename AT = ArrayType>
395  operator=(APIType val) noexcept
396  {
397  VTK_ITER_ASSUME(this->Id.GetTupleSize() > 0);
398  VTK_ITER_ASSUME(this->Array->GetNumberOfComponents() == this->Id.GetTupleSize());
399  this->Array->SetTypedComponent(this->Id.GetTupleId(), this->Id.GetComponentId(), val);
400  return *this;
401  }
402 
403  friend VTK_ITER_INLINE void swap(ValueReference lhs, ValueReference rhs) noexcept
404  { // Swap values, not references:
405  APIType tmp = std::move(static_cast<APIType>(lhs));
406  lhs = std::move(static_cast<APIType>(rhs));
407  rhs = std::move(tmp);
408  }
409 
410  template <typename OArray, ComponentIdType OSize>
411  friend VTK_ITER_INLINE void swap(
413  { // Swap values, not references:
414  using OAPIType =
416  static_assert(
417  std::is_same<APIType, OAPIType>::value, "Cannot swap components with different types.");
418 
419  APIType tmp = std::move(static_cast<APIType>(lhs));
420  lhs = std::move(static_cast<APIType>(rhs));
421  rhs = std::move(tmp);
422  }
423 
424  friend VTK_ITER_INLINE void swap(ValueReference lhs, APIType& rhs) noexcept
425  {
426  APIType tmp = std::move(static_cast<APIType>(lhs));
427  lhs = std::move(rhs);
428  rhs = std::move(tmp);
429  }
430 
431  friend VTK_ITER_INLINE void swap(APIType& lhs, ValueReference rhs) noexcept
432  {
433  APIType tmp = std::move(lhs);
434  lhs = std::move(static_cast<APIType>(rhs));
435  rhs = std::move(tmp);
436  }
437 
439  ValueReference operator++() noexcept // prefix
440  {
441  const APIType newVal = *this + 1;
442  *this = newVal;
443  return *this;
444  }
445 
447  APIType operator++(int) noexcept // postfix
448  {
449  const APIType retVal = *this;
450  *this = *this + 1;
451  return retVal;
452  }
453 
455  ValueReference operator--() noexcept // prefix
456  {
457  const APIType newVal = *this - 1;
458  *this = newVal;
459  return *this;
460  }
461 
463  APIType operator--(int) noexcept // postfix
464  {
465  const APIType retVal = *this;
466  *this = *this - 1;
467  return retVal;
468  }
469 
470 #define VTK_REF_OP_OVERLOADS(Op, ImplOp) \
471  friend VTK_ITER_INLINE ValueReference operator Op(ValueReference lhs, APIType val) noexcept \
472  { \
473  const APIType newVal = lhs ImplOp val; \
474  lhs = newVal; \
475  return lhs; \
476  } \
477  friend VTK_ITER_INLINE ValueReference operator Op( \
478  ValueReference lhs, ValueReference val) noexcept \
479  { \
480  const APIType newVal = lhs ImplOp val; \
481  lhs = newVal; \
482  return lhs; \
483  } \
484  friend VTK_ITER_INLINE APIType& operator Op(APIType& lhs, ValueReference val) noexcept \
485  { \
486  const APIType newVal = lhs ImplOp val; \
487  lhs = newVal; \
488  return lhs; \
489  }
490 
491  VTK_REF_OP_OVERLOADS(+=, +)
492  VTK_REF_OP_OVERLOADS(-=, -)
493  VTK_REF_OP_OVERLOADS(*=, *)
494  VTK_REF_OP_OVERLOADS(/=, /)
495 
496 #undef VTK_REF_OP_OVERLOADS
497 
498  friend struct ConstValueReference<ArrayType, TupleSize, ForceValueTypeForVtkDataArray>;
499  friend struct ValueIterator<ArrayType, TupleSize, ForceValueTypeForVtkDataArray>;
500 
501 protected:
502  template <typename AT = ArrayType>
504  castOperator() const noexcept
505  {
506  VTK_ITER_ASSUME(this->Id.GetTupleSize() > 0);
507  VTK_ITER_ASSUME(this->Array->GetNumberOfComponents() == this->Id.GetTupleSize());
508  return this->Array->GetComponent(this->Id.GetTupleId(), this->Id.GetComponentId());
509  }
510 
511  template <typename AT = ArrayType>
513  castOperator() const noexcept
514  {
515  VTK_ITER_ASSUME(this->Id.GetTupleSize() > 0);
516  VTK_ITER_ASSUME(this->Array->GetNumberOfComponents() == this->Id.GetTupleSize());
517  return this->Array->GetTypedComponent(this->Id.GetTupleId(), this->Id.GetComponentId());
518  }
519 
520  void CopyReference(const ValueReference& o) noexcept
521  {
522  this->Array = o.Array;
523  this->Id = o.Id;
524  }
525 
526  mutable ArrayType* Array;
528 };
529 
530 //------------------------------------------------------------------------------
531 // Const value iterator
532 template <typename ArrayType, ComponentIdType TupleSize, typename ForceValueTypeForVtkDataArray>
534 {
535 private:
536  static_assert(IsValidTupleSize<TupleSize>::value, "Invalid tuple size.");
537  static_assert(IsVtkDataArray<ArrayType>::value, "Invalid array type.");
538 
541 
542 public:
543  using iterator_category = std::random_access_iterator_tag;
544  using value_type = APIType;
546  using pointer = void;
548 
551  : Array(nullptr)
552  , Id()
553  {
554  }
555 
557  ConstValueIterator(ArrayType* array, IdStorageType id) noexcept
558  : Array(array)
559  , Id(id)
560  {
561  this->Id.DebugAsserts(this->Array);
562  }
563 
567  : Array{ o.GetArray() }
568  , Id{ o.GetId() }
569  {
570  }
571 
573  ConstValueIterator(const ConstValueIterator& o) noexcept = default;
575  ConstValueIterator& operator=(const ConstValueIterator& o) noexcept = default;
576 
578  ConstValueIterator& operator++() noexcept // prefix
579  {
580  ++this->Id;
581  this->Id.DebugAsserts(this->Array);
582  return *this;
583  }
584 
586  ConstValueIterator operator++(int) noexcept // postfix
587  {
588  auto ret = this->Id++;
589  this->Id.DebugAsserts(this->Array);
590  return ConstValueIterator{ this->Array, ret };
591  }
592 
594  ConstValueIterator& operator--() noexcept // prefix
595  {
596  --this->Id;
597  this->Id.DebugAsserts(this->Array);
598  return *this;
599  }
600 
602  ConstValueIterator operator--(int) noexcept // postfix
603  {
604  auto ret = this->Id--;
605  this->Id.DebugAsserts(this->Array);
606  return ConstValueIterator{ this->Array, ret };
607  }
608 
611  {
612  return reference{ this->Array, this->Id + i };
613  }
614 
616  reference operator*() const noexcept { return reference{ this->Array, this->Id }; }
617 
618  // Using GetValueType here makes iteration 50% faster by reducing comparisons
619  // and jumps (instead of comparing std::tie(tupleId, compId)).
620 #define VTK_TMP_MAKE_OPERATOR(OP) \
621  friend VTK_ITER_INLINE bool operator OP( \
622  const ConstValueIterator& lhs, const ConstValueIterator& rhs) noexcept \
623  { \
624  VTK_ITER_ASSERT(lhs.Array == rhs.Array, "Mismatched arrays in iterator comparison."); \
625  return lhs.Id.GetValueId() OP rhs.Id.GetValueId(); \
626  }
627 
634 
635 #undef VTK_TMP_MAKE_OPERATOR
636 
639  {
640  this->Id.AddOffset(offset);
641  this->Id.DebugAsserts(this->Array);
642  return *this;
643  }
644 
646  const ConstValueIterator& it, difference_type offset) noexcept
647  {
648  return ConstValueIterator{ it.Array, it.Id + offset };
649  }
650 
652  difference_type offset, const ConstValueIterator& it) noexcept
653  {
654  return ConstValueIterator{ it.Array, it.Id + offset };
655  }
656 
659  {
660  this->Id.AddOffset(-offset);
661  this->Id.DebugAsserts(this->Array);
662  return *this;
663  }
664 
666  const ConstValueIterator& it, difference_type offset) noexcept
667  {
668  return ConstValueIterator{ it.Array, it.Id + (-offset) };
669  }
670 
672  const ConstValueIterator& it1, const ConstValueIterator& it2) noexcept
673  {
674  VTK_ITER_ASSERT(it1.Array == it2.Array, "Cannot do math with iterators from different arrays.");
675  return it1.Id.GetValueId() - it2.Id.GetValueId();
676  }
677 
679  {
680  // Different arrays may use different iterator implementations.
681  VTK_ITER_ASSERT(lhs.Array == rhs.Array, "Cannot swap iterators from different arrays.");
682 
683  using std::swap;
684  swap(lhs.Id, rhs.Id);
685  }
686 
687 private:
688  mutable ArrayType* Array;
689  IdStorageType Id;
690 };
691 
692 //------------------------------------------------------------------------------
693 // Component iterator
694 template <typename ArrayType, ComponentIdType TupleSize, typename ForceValueTypeForVtkDataArray>
696 {
697 private:
698  static_assert(IsValidTupleSize<TupleSize>::value, "Invalid tuple size.");
699  static_assert(IsVtkDataArray<ArrayType>::value, "Invalid array type.");
700 
703 
704 public:
705  using iterator_category = std::random_access_iterator_tag;
710 
712  ValueIterator() noexcept = default;
713 
715  ValueIterator(ArrayType* array, IdStorageType id) noexcept
716  : Ref{ array, id }
717  {
718  this->DebugIdAsserts();
719  }
720 
722  ValueIterator(const ValueIterator& o) noexcept = default;
723 
726  {
727  this->Ref.CopyReference(o.Ref);
728  this->DebugIdAsserts();
729  return *this;
730  }
731 
733  ValueIterator& operator++() noexcept // prefix
734  {
735  ++this->Ref.Id;
736  this->DebugIdAsserts();
737  return *this;
738  }
739 
741  ValueIterator operator++(int) noexcept // postfix
742  {
743  auto ret = this->Ref.Id++;
744  this->DebugIdAsserts();
745  return ValueIterator{ this->Ref.Array, ret };
746  }
747 
749  ValueIterator& operator--() noexcept // prefix
750  {
751  --this->Ref.Id;
752  this->DebugIdAsserts();
753  return *this;
754  }
755 
757  ValueIterator operator--(int) noexcept // postfix
758  {
759  auto ret = this->Ref.Id--;
760  this->DebugIdAsserts();
761  return ValueIterator{ this->Ref.Array, ret };
762  }
763 
766  {
767  return reference{ this->Ref.Array, this->Ref.Id + i };
768  }
769 
771  reference operator*() const noexcept { return this->Ref; }
772 
774  const pointer& operator->() const noexcept { return this->Ref; }
775 
776 #define VTK_TMP_MAKE_OPERATOR(OP) \
777  friend VTK_ITER_INLINE bool operator OP( \
778  const ValueIterator& lhs, const ValueIterator& rhs) noexcept \
779  { \
780  VTK_ITER_ASSERT( \
781  lhs.GetArray() == rhs.GetArray(), "Mismatched arrays in iterator comparison."); \
782  return lhs.GetId().GetValueId() OP rhs.GetId().GetValueId(); \
783  }
784 
791 
792 #undef VTK_TMP_MAKE_OPERATOR
793 
796  {
797  this->Ref.Id.AddOffset(offset);
798  this->DebugIdAsserts();
799  return *this;
800  }
801 
803  const ValueIterator& it, difference_type offset) noexcept
804  {
805  return ValueIterator{ it.GetArray(), it.GetId() + offset };
806  }
807 
809  difference_type offset, const ValueIterator& it) noexcept
810  {
811  return ValueIterator{ it.GetArray(), it.GetId() + offset };
812  }
813 
816  {
817  this->Ref.Id.AddOffset(-offset);
818  this->Ref.Id.DebugAsserts(this->Ref.Array);
819  return *this;
820  }
821 
823  const ValueIterator& it, difference_type offset) noexcept
824  {
825  return ValueIterator{ it.GetArray(), it.GetId() + (-offset) };
826  }
827 
829  const ValueIterator& it1, const ValueIterator& it2) noexcept
830  {
832  it1.Ref.Array == it2.Ref.Array, "Cannot do math with iterators from different arrays.");
833  return it1.GetId().GetValueId() - it2.GetId().GetValueId();
834  }
835 
836  friend VTK_ITER_INLINE void swap(ValueIterator& lhs, ValueIterator& rhs) noexcept
837  {
838  // Different arrays may use different iterator implementations.
840  lhs.GetArray() == rhs.GetArray(), "Cannot swap iterators from different arrays.");
841 
842  using std::swap;
843  swap(lhs.GetId(), rhs.GetId());
844  }
845 
846  friend struct ConstValueIterator<ArrayType, TupleSize, ForceValueTypeForVtkDataArray>;
847 
848 protected:
850  void DebugIdAsserts() const { this->Ref.Id.DebugAsserts(this->Ref.Array); }
851 
852  // Needed for access from friend functions. We could just store the array
853  // and ID here instead of the ref, but meh.
854  ArrayType* GetArray() const noexcept { return this->Ref.Array; }
855  IdStorageType& GetId() noexcept { return this->Ref.Id; }
856  const IdStorageType& GetId() const noexcept { return this->Ref.Id; }
857 
859 };
860 
861 //------------------------------------------------------------------------------
862 // ValueRange
863 template <typename ArrayTypeT, ComponentIdType TupleSize, typename ForceValueTypeForVtkDataArray>
865 {
866 private:
867  static_assert(IsValidTupleSize<TupleSize>::value, "Invalid tuple size.");
868  static_assert(IsVtkDataArray<ArrayTypeT>::value, "Invalid array type.");
869 
872 
873 public:
874  using ArrayType = ArrayTypeT;
876 
882 
883  // May be DynamicTupleSize, or the actual tuple size.
884  constexpr static ComponentIdType TupleSizeTag = TupleSize;
885 
886  // STL-compat
893 
895  ValueRange() noexcept = default;
896 
898  ValueRange(ArrayType* arr, ValueIdType beginValue, ValueIdType endValue) noexcept
899  : Array(arr)
900  , NumComps(arr)
901  , BeginValue(beginValue, this->NumComps)
902  , EndValue(endValue, this->NumComps)
903  {
904  assert(this->Array);
905  assert(beginValue >= 0 && beginValue <= endValue);
906  assert(endValue >= 0 && endValue <= this->Array->GetNumberOfValues());
907  }
908 
910  ValueRange GetSubRange(ValueIdType beginValue = 0, ValueIdType endValue = -1) const noexcept
911  {
912  const ValueIdType realBegin = this->BeginValue.GetValueId() + beginValue;
913  const ValueIdType realEnd =
914  endValue >= 0 ? this->BeginValue.GetValueId() + endValue : this->EndValue.GetValueId();
915 
916  return ValueRange{ this->Array, realBegin, realEnd };
917  }
918 
920  ArrayType* GetArray() const noexcept { return this->Array; }
922  ComponentIdType GetTupleSize() const noexcept { return this->NumComps.value; }
923 
925  ValueIdType GetBeginValueId() const noexcept { return this->BeginValue.GetValueId(); }
926 
928  ValueIdType GetEndValueId() const noexcept { return this->EndValue.GetValueId(); }
929 
931  size_type size() const noexcept
932  {
933  return this->EndValue.GetValueId() - this->BeginValue.GetValueId();
934  }
935 
937  iterator begin() noexcept { return this->NewIterator(this->BeginValue); }
939  iterator end() noexcept { return this->NewIterator(this->EndValue); }
940 
942  const_iterator begin() const noexcept { return this->NewConstIterator(this->BeginValue); }
944  const_iterator end() const noexcept { return this->NewConstIterator(this->EndValue); }
945 
947  const_iterator cbegin() const noexcept { return this->NewConstIterator(this->BeginValue); }
949  const_iterator cend() const noexcept { return this->NewConstIterator(this->EndValue); }
950 
953  {
954  return reference{ this->Array, this->BeginValue + i };
955  }
958  {
959  return const_reference{ this->Array, this->BeginValue + i };
960  }
961 
963 
970  value_type* data() noexcept
971  {
972  return reinterpret_cast<value_type*>(this->Array->GetVoidPointer(0));
973  }
974  value_type* data() const noexcept
975  {
976  return reinterpret_cast<value_type*>(this->Array->GetVoidPointer(0));
977  }
979 
980 private:
982  iterator NewIterator(IdStorageType id) const noexcept { return iterator{ this->Array, id }; }
983 
985  const_iterator NewConstIterator(IdStorageType id) const noexcept
986  {
987  return const_iterator{ this->Array, id };
988  }
989 
990  mutable ArrayType* Array{ nullptr };
991  NumCompsType NumComps{};
992  IdStorageType BeginValue{};
993  IdStorageType EndValue{};
994 };
995 
996 // Unimplemented, only used inside decltype in SelectValueRange:
997 template <typename ArrayType, ComponentIdType TupleSize, typename ForceValueTypeForVtkDataArray>
999  vtkDataArray*);
1000 
1001 VTK_ABI_NAMESPACE_END
1002 } // end namespace detail
1003 } // end namespace vtk
1004 
1006 
1007 #endif // vtkDataArrayValueRange_Generic_h
1008 
1009 // VTK-HeaderTest-Exclude: vtkDataArrayValueRange_Generic.h
abstract superclass for arrays of numeric data
Definition: vtkDataArray.h:154
@ value
Definition: vtkX3D.h:220
@ type
Definition: vtkX3D.h:516
@ offset
Definition: vtkX3D.h:438
ValueRange< AOSArrayType, TupleSize, ForceValueTypeForVtkDataArray > DeclareValueRangeSpecialization(ArrayType *)
Specialization of tuple ranges and iterators for vtkAOSDataArrayTemplate.
vtkIdType ValueIdType
typename detail::GetAPITypeImpl< ArrayType, ForceValueTypeForVtkDataArray >::APIType GetAPIType
vtkIdType TupleIdType
int ComponentIdType
VTK_ITER_INLINE ConstValueIterator & operator+=(difference_type offset) noexcept
friend VTK_ITER_INLINE void swap(ConstValueIterator &lhs, ConstValueIterator &rhs) noexcept
VTK_ITER_INLINE reference operator*() const noexcept
VTK_ITER_INLINE ConstValueIterator & operator++() noexcept
VTK_ITER_INLINE ConstValueIterator(const ValueIterator< ArrayType, TupleSize, ForceValueTypeForVtkDataArray > &o) noexcept
VTK_ITER_INLINE ConstValueIterator operator++(int) noexcept
friend VTK_ITER_INLINE ConstValueIterator operator-(const ConstValueIterator &it, difference_type offset) noexcept
std::random_access_iterator_tag iterator_category
VTK_ITER_INLINE reference operator[](difference_type i) const noexcept
friend VTK_ITER_INLINE difference_type operator-(const ConstValueIterator &it1, const ConstValueIterator &it2) noexcept
VTK_ITER_INLINE ConstValueIterator operator--(int) noexcept
VTK_ITER_INLINE ConstValueIterator & operator=(const ConstValueIterator &o) noexcept=default
friend VTK_ITER_INLINE ConstValueIterator operator+(const ConstValueIterator &it, difference_type offset) noexcept
VTK_ITER_INLINE ConstValueIterator & operator-=(difference_type offset) noexcept
VTK_ITER_INLINE ConstValueIterator(const ConstValueIterator &o) noexcept=default
VTK_ITER_INLINE ConstValueIterator(ArrayType *array, IdStorageType id) noexcept
friend VTK_ITER_INLINE ConstValueIterator operator+(difference_type offset, const ConstValueIterator &it) noexcept
VTK_ITER_INLINE ConstValueIterator & operator--() noexcept
VTK_ITER_INLINE ConstValueReference(const ConstValueReference &o) noexcept=default
VTK_ITER_INLINE ConstValueReference(const ValueReference< ArrayType, TupleSize, ForceValueTypeForVtkDataArray > &o)
VTK_ITER_INLINE ConstValueReference(ArrayType *array, IdStorageType id) noexcept
std::enable_if< std::is_same< AT, vtkDataArray >::value, APIType >::type VTK_ITER_INLINE castOperator() const noexcept
std::enable_if<!std::is_same< AT, vtkDataArray >::value, APIType >::type VTK_ITER_INLINE castOperator() const noexcept
VTK_ITER_INLINE ConstValueReference(ConstValueReference &&o) noexcept=default
VTK_ITER_INLINE ConstValueReference operator=(const ConstValueReference &o) noexcept
VTK_ITER_INLINE ConstValueReference operator=(ConstValueReference &&o) noexcept
GenericTupleSize< TupleSize > NumCompsType
VTK_ITER_INLINE ComponentIdType GetComponentId() const noexcept
VTK_ITER_INLINE IdStorage & operator++() noexcept
VTK_ITER_INLINE IdStorage operator--(int) noexcept
VTK_ITER_INLINE IdStorage(ValueIdType valueId, NumCompsType numComps) noexcept
VTK_ITER_INLINE void DebugAsserts(ArrayType *array) const noexcept
VTK_ITER_INLINE void AddOffset(ValueIdType offset) noexcept
VTK_ITER_INLINE IdStorage operator++(int) noexcept
VTK_ITER_INLINE std::pair< TupleIdType, ComponentIdType > Convert(ValueIdType value) const noexcept
VTK_ITER_INLINE IdStorage() noexcept
VTK_ITER_INLINE ComponentIdType GetTupleSize() const noexcept
friend VTK_ITER_INLINE void swap(IdStorage &lhs, IdStorage &rhs) noexcept
friend VTK_ITER_INLINE IdStorage operator+(const IdStorage &id, ValueIdType offset) noexcept
VTK_ITER_INLINE ValueIdType GetValueId() const noexcept
VTK_ITER_INLINE IdStorage(TupleIdType tupleId, ComponentIdType comp, NumCompsType numComps) noexcept
VTK_ITER_INLINE ValueIdType Convert(TupleIdType tuple, ComponentIdType comp) const noexcept
VTK_ITER_INLINE TupleIdType GetTupleId() const noexcept
VTK_ITER_INLINE IdStorage(ValueIdType valueId, TupleIdType tupleId, ComponentIdType comp, NumCompsType numComps) noexcept
VTK_ITER_INLINE IdStorage & operator--() noexcept
friend VTK_ITER_INLINE ValueIterator operator+(const ValueIterator &it, difference_type offset) noexcept
VTK_ITER_INLINE reference operator*() const noexcept
std::random_access_iterator_tag iterator_category
const IdStorageType & GetId() const noexcept
VTK_ITER_INLINE ValueIterator operator--(int) noexcept
VTK_ITER_INLINE void DebugIdAsserts() const
ValueReference< ArrayType, TupleSize, ForceValueTypeForVtkDataArray > Ref
ArrayType * GetArray() const noexcept
friend VTK_ITER_INLINE ValueIterator operator+(difference_type offset, const ValueIterator &it) noexcept
VTK_ITER_INLINE ValueIterator & operator+=(difference_type offset) noexcept
GetAPIType< ArrayType, ForceValueTypeForVtkDataArray > value_type
VTK_ITER_INLINE ValueIterator() noexcept=default
friend VTK_ITER_INLINE ValueIterator operator-(const ValueIterator &it, difference_type offset) noexcept
VTK_ITER_INLINE ValueIterator operator++(int) noexcept
friend VTK_ITER_INLINE void swap(ValueIterator &lhs, ValueIterator &rhs) noexcept
VTK_ITER_INLINE ValueIterator & operator-=(difference_type offset) noexcept
VTK_ITER_INLINE ValueIterator & operator--() noexcept
VTK_ITER_INLINE reference operator[](difference_type i) const noexcept
VTK_ITER_INLINE const pointer & operator->() const noexcept
VTK_ITER_INLINE ValueIterator & operator++() noexcept
VTK_ITER_INLINE ValueIterator & operator=(const ValueIterator &o) noexcept
friend VTK_ITER_INLINE difference_type operator-(const ValueIterator &it1, const ValueIterator &it2) noexcept
VTK_ITER_INLINE ValueIterator(const ValueIterator &o) noexcept=default
VTK_ITER_INLINE const_iterator begin() const noexcept
GetAPIType< ArrayType, ForceValueTypeForVtkDataArray > ValueType
VTK_ITER_INLINE const_iterator cend() const noexcept
VTK_ITER_INLINE ValueRange GetSubRange(ValueIdType beginValue=0, ValueIdType endValue=-1) const noexcept
VTK_ITER_INLINE iterator begin() noexcept
ConstValueReference< ArrayType, TupleSize, ForceValueTypeForVtkDataArray > ConstReferenceType
VTK_ITER_INLINE const_iterator end() const noexcept
VTK_ITER_INLINE ValueIdType GetBeginValueId() const noexcept
VTK_ITER_INLINE ValueRange() noexcept=default
VTK_ITER_INLINE ArrayType * GetArray() const noexcept
constexpr static ComponentIdType TupleSizeTag
VTK_ITER_INLINE size_type size() const noexcept
VTK_ITER_INLINE reference operator[](size_type i) noexcept
VTK_ITER_INLINE const_reference operator[](size_type i) const noexcept
ValueReference< ArrayType, TupleSize, ForceValueTypeForVtkDataArray > ReferenceType
VTK_ITER_INLINE iterator end() noexcept
VTK_ITER_INLINE ComponentIdType GetTupleSize() const noexcept
ConstValueIterator< ArrayType, TupleSize, ForceValueTypeForVtkDataArray > ConstIteratorType
ValueIterator< ArrayType, TupleSize, ForceValueTypeForVtkDataArray > IteratorType
value_type * data() const noexcept
VTK_ITER_INLINE const_iterator cbegin() const noexcept
VTK_ITER_INLINE ValueIdType GetEndValueId() const noexcept
VTK_ITER_INLINE ValueReference operator++() noexcept
VTK_ITER_INLINE ValueReference operator=(ValueReference &&o) noexcept
VTK_ITER_INLINE ValueReference operator--() noexcept
std::enable_if<!std::is_same< AT, vtkDataArray >::value, ValueReference >::type VTK_ITER_INLINE operator=(APIType val) noexcept
std::enable_if< std::is_same< AT, vtkDataArray >::value, APIType >::type VTK_ITER_INLINE castOperator() const noexcept
VTK_ITER_INLINE ValueReference operator=(const ValueReference< OArray, OSize, ForceValueTypeForVtkDataArray > &o) noexcept
void CopyReference(const ValueReference &o) noexcept
VTK_ITER_INLINE ValueReference operator=(const ValueReference &o) noexcept
VTK_ITER_INLINE ValueReference(const ValueReference &o) noexcept=default
std::enable_if< std::is_same< AT, vtkDataArray >::value, ValueReference >::type VTK_ITER_INLINE operator=(APIType val) noexcept
friend VTK_ITER_INLINE void swap(ValueReference lhs, APIType &rhs) noexcept
VTK_ITER_INLINE ValueReference() noexcept
friend VTK_ITER_INLINE void swap(ValueReference lhs, ValueReference< OArray, OSize, ForceValueTypeForVtkDataArray > rhs) noexcept
friend VTK_ITER_INLINE void swap(APIType &lhs, ValueReference rhs) noexcept
VTK_ITER_INLINE APIType operator++(int) noexcept
VTK_ITER_INLINE ValueReference(ValueReference &&o) noexcept=default
VTK_ITER_INLINE ValueReference(ArrayType *array, IdStorageType id) noexcept
friend VTK_ITER_INLINE void swap(ValueReference lhs, ValueReference rhs) noexcept
std::enable_if<!std::is_same< AT, vtkDataArray >::value, APIType >::type VTK_ITER_INLINE castOperator() const 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_ASSERT(x, msg)
#define VTK_ITER_ASSUME
#define VTK_TMP_MAKE_OPERATOR(OP)
#define VTK_REF_OP_OVERLOADS(Op, ImplOp)