VTK  9.4.20250206
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
25namespace vtk
26{
27namespace detail
28{
29VTK_ABI_NAMESPACE_BEGIN
30
31// Forward decs for friends/args
32template <typename ArrayType, ComponentIdType>
33struct ConstTupleReference;
34template <typename ArrayType, ComponentIdType>
35struct TupleReference;
36template <typename ArrayType, ComponentIdType>
37struct ConstTupleIterator;
38template <typename ArrayType, ComponentIdType>
39struct TupleIterator;
40template <typename ArrayType, ComponentIdType>
41struct TupleRange;
42
43//------------------------------------------------------------------------------
44// Const tuple reference
45template <typename ValueType, ComponentIdType TupleSize>
46struct ConstTupleReference<vtkAOSDataArrayTemplate<ValueType>, TupleSize>
47{
48private:
51 using APIType = ValueType;
52
53public:
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>
111 typename std::enable_if<!std::is_same<VT, double>::value>::type VTK_ITER_INLINE GetTuple(
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
230protected:
231 // Intentionally hidden:
234
235 const ValueType* Tuple;
237};
238
239//------------------------------------------------------------------------------
240// Tuple reference
241template <typename ValueType, ComponentIdType TupleSize>
242struct TupleReference<vtkAOSDataArrayTemplate<ValueType>, TupleSize>
243{
244private:
247 using APIType = ValueType;
248
249public:
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>
302 typename std::enable_if<!std::is_same<VT, double>::value>::type VTK_ITER_INLINE GetTuple(
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>
327 typename std::enable_if<!std::is_same<VT, double>::value>::type VTK_ITER_INLINE SetTuple(
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
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>
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>
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
558protected:
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
572template <typename ValueType, ComponentIdType TupleSize>
573struct ConstTupleIterator<vtkAOSDataArrayTemplate<ValueType>, TupleSize>
574{
575private:
578
579public:
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
710private:
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
725template <typename ValueType, ComponentIdType TupleSize>
726struct TupleIterator<vtkAOSDataArrayTemplate<ValueType>, TupleSize>
727{
728private:
731
732public:
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
862protected:
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
877template <typename ValueType, ComponentIdType TupleSize>
878struct TupleRange<vtkAOSDataArrayTemplate<ValueType>, TupleSize>
879{
882
883private:
884 static_assert(IsValidTupleSize<TupleSize>::value, "Invalid tuple size.");
885 static_assert(IsVtkDataArray<ArrayType>::value, "Invalid array type.");
886
888
889public:
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
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>
1024 typename std::enable_if<!std::is_same<VT, double>::value>::type VTK_ITER_INLINE GetTuple(
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>
1046 typename std::enable_if<!std::is_same<VT, double>::value>::type VTK_ITER_INLINE SetTuple(
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
1057private:
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:
1077template <typename ArrayType, ComponentIdType TupleSize,
1078 // Convenience:
1079 typename ValueType = typename ArrayType::ValueType,
1080 typename AOSArrayType = vtkAOSDataArrayTemplate<ValueType>,
1081 // SFINAE to select AOS arrays:
1082 typename = typename std::enable_if<IsAOSDataArray<ArrayType>::value>::type>
1084
1085VTK_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.
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
VTK_ITER_INLINE ConstTupleIterator & operator-=(difference_type offset) noexcept
friend VTK_ITER_INLINE ConstTupleIterator operator+(difference_type offset, const ConstTupleIterator &it) 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 ConstTupleReference(const ConstTupleReference &) noexcept=default
VTK_ITER_INLINE EnableIfStaticTupleSizes< TupleSize, OSize, bool > operator==(const TupleReference< OArrayType, OSize > &other) const noexcept
std::enable_if<!std::is_same< VT, double >::value >::type VTK_ITER_INLINE GetTuple(volatile double *tuple) const noexcept
VTK_ITER_INLINE ConstTupleReference(ConstTupleReference &&) noexcept=default
VTK_ITER_INLINE EnableIfStaticTupleSizes< TupleSize, OSize, bool > operator==(const ConstTupleReference< OArrayType, OSize > &other) const noexcept
VTK_ITER_INLINE bool operator!=(const TupleReference< OArrayType, OSize > &o) const noexcept
VTK_ITER_INLINE ConstTupleReference & operator=(const ConstTupleReference &) noexcept=default
VTK_ITER_INLINE EnableIfEitherTupleSizeIsDynamic< TupleSize, OSize, bool > operator==(const ConstTupleReference< OArrayType, OSize > &other) const noexcept
VTK_ITER_INLINE EnableIfEitherTupleSizeIsDynamic< TupleSize, OSize, bool > operator==(const TupleReference< OArrayType, OSize > &other) const noexcept
VTK_ITER_INLINE ConstTupleReference(const ValueType *tuple, NumCompsType numComps) noexcept
VTK_ITER_INLINE ConstTupleReference(const TupleReference< ArrayType, TupleSize > &o) noexcept
VTK_ITER_INLINE const_iterator cbegin() const noexcept
VTK_ITER_INLINE const_iterator cend() const noexcept
friend VTK_ITER_INLINE TupleIterator operator+(const TupleIterator &it, 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
VTK_ITER_INLINE TupleIterator(const TupleIterator &o) noexcept=default
friend VTK_ITER_INLINE TupleIterator operator+(difference_type offset, const TupleIterator &it) noexcept
VTK_ITER_INLINE TupleIterator & operator-=(difference_type offset) noexcept
VTK_ITER_INLINE TupleIterator & operator+=(difference_type offset) 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
static constexpr ComponentIdType TupleSizeTag
TupleIterator< ArrayType, TupleSize > TupleIteratorType
ConstTupleIterator< ArrayType, TupleSize > ConstTupleIteratorType
TupleReference< ArrayType, TupleSize > TupleReferenceType
ConstTupleReference< ArrayType, TupleSize > ConstTupleReferenceType
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, TupleReference & > operator=(const ConstTupleReference< 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 TupleReference & operator=(const TupleReference &other) noexcept
VTK_ITER_INLINE EnableIfEitherTupleSizeIsDynamic< TupleSize, OSize, void > swap(TupleReference< OArrayType, OSize > other) noexcept
VTK_ITER_INLINE EnableIfStaticTupleSizes< TupleSize, OSize, void > swap(TupleReference< 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 EnableIfStaticTupleSizes< TupleSize, OSize, TupleReference & > operator=(const TupleReference< OArrayType, OSize > &other) noexcept
VTK_ITER_INLINE bool operator!=(const TupleReference< OArrayType, OSize > &o) const noexcept
VTK_ITER_INLINE EnableIfStaticTupleSizes< TupleSize, OSize, bool > operator==(const ConstTupleReference< OArrayType, OSize > &other) const noexcept
VTK_ITER_INLINE EnableIfEitherTupleSizeIsDynamic< TupleSize, OSize, bool > operator==(const TupleReference< OArrayType, OSize > &other) const noexcept
VTK_ITER_INLINE EnableIfStaticTupleSizes< TupleSize, OSize, bool > operator==(const TupleReference< OArrayType, OSize > &other) const noexcept
VTK_ITER_INLINE EnableIfEitherTupleSizeIsDynamic< TupleSize, OSize, bool > operator==(const ConstTupleReference< OArrayType, OSize > &other) const noexcept
VTK_ITER_INLINE EnableIfEitherTupleSizeIsDynamic< TupleSize, OSize, TupleReference & > operator=(const TupleReference< OArrayType, OSize > &other) noexcept
VTK_ITER_INLINE EnableIfEitherTupleSizeIsDynamic< TupleSize, OSize, TupleReference & > operator=(const ConstTupleReference< OArrayType, OSize > &other) noexcept
VTK_ITER_INLINE TupleReference(const TupleReference &) noexcept=default
VTK_ITER_INLINE TupleReference(TupleReference &&) noexcept=default
friend VTK_ITER_INLINE void swap(TupleReference a, TupleReference< OArray, OSize > b) noexcept
VTK_ITER_INLINE 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