SPH
IteratorAdapters.h
Go to the documentation of this file.
1 #pragma once
2 
7 
10 
12 
13 //-----------------------------------------------------------------------------------------------------------
14 // ReverseIterator
15 //-----------------------------------------------------------------------------------------------------------
16 
18 template <typename TIterator>
20 protected:
21  TIterator iter;
22 
23 public:
24  ReverseIterator() = default;
25 
26  explicit ReverseIterator(TIterator iter)
27  : iter(iter) {}
28 
29  decltype(auto) operator*() const {
30  return *iter;
31  }
32  decltype(auto) operator*() {
33  return *iter;
34  }
36  --iter;
37  return *this;
38  }
40  ReverseIterator tmp(*this);
41  operator++();
42  return tmp;
43  }
45  ++iter;
46  return *this;
47  }
49  ReverseIterator tmp(*this);
50  operator--();
51  return tmp;
52  }
53  bool operator==(const ReverseIterator& other) const {
54  return iter == other.iter;
55  }
56  bool operator!=(const ReverseIterator& other) const {
57  return iter != other.iter;
58  }
59 };
60 
62 template <typename TIterator>
64  return ReverseIterator<TIterator>(iter);
65 }
66 
67 
70 template <typename TContainer>
72 private:
73  TContainer container;
74 
75  using Iterator = decltype(std::declval<std::decay_t<TContainer>>().begin());
76 
77 public:
78  template <typename T>
79  explicit ReverseAdapter(T&& container)
80  : container(std::forward<T>(container)) {}
81 
84  if (Iterator iter = container.end()) {
85  --iter;
86  return reverseIterator(iter);
87  } else {
88  return ReverseIterator<Iterator>(nullptr);
89  }
90  }
91 
94  if (Iterator iter = container.begin()) {
95  --iter;
96  return reverseIterator(iter);
97  } else {
98  return ReverseIterator<Iterator>(nullptr);
99  }
100  }
101 
102  Size size() const {
103  return container.size();
104  }
105 };
106 
114 template <typename TContainer>
115 ReverseAdapter<TContainer> reverse(TContainer&& container) {
116  return ReverseAdapter<TContainer>(std::forward<TContainer>(container));
117 }
118 
119 //-----------------------------------------------------------------------------------------------------------
120 // ComponentIterator
121 //-----------------------------------------------------------------------------------------------------------
122 
125 template <typename TIterator>
127 private:
128  TIterator iterator;
129  Size component;
130 
131  using T = decltype((*std::declval<TIterator>())[std::declval<Size>()]);
132  using RawT = std::decay_t<T>;
133 
134 public:
135  using iterator_category = typename TIterator::iterator_category;
136  using value_type = RawT;
137  using difference_type = std::ptrdiff_t;
138  using pointer = RawT*;
139  using reference = RawT&;
140 
141  ComponentIterator() = default;
142 
143  ComponentIterator(const TIterator& iterator, const int component)
144  : iterator(iterator)
145  , component(component) {}
146 
147  const RawT& operator*() const {
148  return (*iterator)[component];
149  }
150 
151  RawT& operator*() {
152  return (*iterator)[component];
153  }
154 
156  ++iterator;
157  return *this;
158  }
160  ComponentIterator tmp(*this);
161  operator++();
162  return tmp;
163  }
165  --iterator;
166  return *this;
167  }
169  ComponentIterator tmp(*this);
170  operator--();
171  return tmp;
172  }
173 
174 
175  ComponentIterator operator+(const int n) const {
176  return ComponentIterator(iterator + n, component);
177  }
178  ComponentIterator operator-(const int n) const {
179  return ComponentIterator(iterator - n, component);
180  }
181  void operator+=(const int n) {
182  iterator += n;
183  }
184  void operator-=(const int n) {
185  iterator -= n;
186  }
187 
188  Size operator-(const ComponentIterator& other) const {
189  return iterator - other.iterator;
190  }
191  bool operator<(const ComponentIterator& other) const {
192  return iterator < other.iterator;
193  }
194  bool operator>(const ComponentIterator& other) const {
195  return iterator > other.iterator;
196  }
197  bool operator<=(const ComponentIterator& other) const {
198  return iterator <= other.iterator;
199  }
200  bool operator>=(const ComponentIterator& other) const {
201  return iterator >= other.iterator;
202  }
203  bool operator==(const ComponentIterator& other) {
204  return iterator == other.iterator;
205  }
206  bool operator!=(const ComponentIterator& other) {
207  return iterator != other.iterator;
208  }
209 };
210 
211 
213 template <typename TBuffer>
215  TBuffer data;
217 
218  using TIterator = decltype(std::declval<TBuffer>().begin());
219 
221  : data(std::forward<TBuffer>(data))
222  , component(component) {}
223 
224  auto begin() {
226  }
227 
228  auto end() {
230  }
231 };
232 
240 template <typename TBuffer>
241 auto componentAdapter(TBuffer&& buffer, const Size component) {
242  return VectorComponentAdapter<TBuffer>(std::forward<TBuffer>(buffer), component);
243 }
244 
245 //-----------------------------------------------------------------------------------------------------------
246 // TupleIterator
247 //-----------------------------------------------------------------------------------------------------------
248 
252 template <typename TElement, typename... TIterator>
254 private:
255  Tuple<TIterator...> iterators;
256 
257 public:
258  explicit TupleIterator(const TIterator&... iters)
259  : iterators(iters...) {}
260 
262  forEach(iterators, [](auto& iter) { ++iter; });
263  return *this;
264  }
265 
266  TElement operator*() {
267  return apply(iterators, [](auto&... values) -> TElement { return { *values... }; });
268  }
269 
270  const TElement operator*() const {
271  return apply(iterators, [](const auto&... values) -> TElement { return { *values... }; });
272  }
273 
274  bool operator==(const TupleIterator& other) const {
275  const bool result = iterators.template get<0>() == other.iterators.template get<0>();
276  // check that all iterators return the same result (all containers have the same size)
277  SPH_ASSERT(checkEqual(result, other, std::index_sequence_for<TIterator...>{}));
278  return result;
279  }
280 
281  bool operator!=(const TupleIterator& other) const {
282  const bool result = iterators.template get<0>() != other.iterators.template get<0>();
283  // check that all iterators return the same result (all containers have the same size)
284  SPH_ASSERT(checkEqual(!result, other, std::index_sequence_for<TIterator...>{}));
285  return result;
286  }
287 
288 private:
289  template <std::size_t First, std::size_t... Rest>
290  bool checkEqual(const bool equal, const TupleIterator& other, std::index_sequence<First, Rest...>) const {
291  if (equal != (iterators.template get<First>() == other.iterators.template get<First>())) {
292  // different size
293  return false;
294  }
295  return checkEqual(equal, other, std::index_sequence<Rest...>{});
296  }
297 
298  // last step to end the recursion
299  bool checkEqual(const bool, const TupleIterator&, std::index_sequence<>) const {
300  return true;
301  }
302 };
303 
305 template <typename TElement, typename... TIterators>
306 TupleIterator<TElement, TIterators...> makeTupleIterator(const TIterators&... iterators) {
307  return TupleIterator<TElement, TIterators...>(iterators...);
308 }
309 
312 template <typename TElement, typename... TContainers>
314 private:
315  Tuple<TContainers...> tuple;
316 
317 public:
318  explicit TupleAdapter(TContainers&&... containers)
319  : tuple(std::forward<TContainers>(containers)...) {
320  SPH_ASSERT(tuple.size() > 1);
321  }
322 
323  auto begin() {
324  return apply(tuple, [](auto&... containers) { //
325  return makeTupleIterator<TElement>(containers.begin()...);
326  });
327  }
328 
329  auto begin() const {
330  return apply(tuple, [](const auto&... containers) { //
331  return makeTupleIterator<TElement>(containers.begin()...);
332  });
333  }
334 
335  auto end() {
336  return apply(tuple, [](auto&... containers) { //
337  return makeTupleIterator<TElement>(containers.end()...);
338  });
339  }
340 
341  auto end() const {
342  return apply(tuple, [](const auto&... containers) { //
343  return makeTupleIterator<TElement>(containers.end()...);
344  });
345  }
346 
347  Size size() const {
348  return tuple.template get<0>().size();
349  }
350 };
351 
352 template <typename TElement, typename... TContainers>
353 TupleAdapter<TElement, TContainers...> iterateTuple(TContainers&&... containers) {
354  return TupleAdapter<TElement, TContainers...>(std::forward<TContainers>(containers)...);
355 }
356 
357 //-----------------------------------------------------------------------------------------------------------
358 // IteratorWithIndex
359 //-----------------------------------------------------------------------------------------------------------
360 
361 template <typename TValue>
363 private:
364  TValue data;
365  Size idx;
366 
367 public:
368  ElementWithIndex(TValue&& value, const Size index)
369  : data(std::forward<TValue>(value))
370  , idx(index) {}
371 
372  INLINE TValue& value() {
373  return data;
374  }
375 
376  INLINE const TValue& value() const {
377  return data;
378  }
379 
380  INLINE operator TValue&() {
381  return value();
382  }
383 
384  INLINE operator const TValue&() const {
385  return value();
386  }
387 
388  INLINE Size index() const {
389  return idx;
390  }
391 };
392 
393 template <typename TValue>
394 ElementWithIndex<TValue> makeElementWithIndex(TValue&& value, const Size index) {
395  return ElementWithIndex<TValue>(std::forward<TValue>(value), index);
396 }
397 
399 template <typename TIterator>
401 private:
402  TIterator iterator;
403  Size index;
404 
405  using TValue = decltype(*std::declval<TIterator>());
406 
407 public:
408  IteratorWithIndex(const TIterator iterator, const Size index)
409  : iterator(iterator)
410  , index(index) {}
411 
413  return makeElementWithIndex(*iterator, index);
414  }
415 
417  return makeElementWithIndex(*iterator, index);
418  }
419 
421  ++iterator;
422  ++index;
423  return *this;
424  }
425 
426  bool operator!=(const IteratorWithIndex& other) const {
427  return iterator != other.iterator;
428  }
429 };
430 
431 template <typename TIterator>
432 IteratorWithIndex<TIterator> makeIteratorWithIndex(TIterator&& iterator, const Size index) {
433  return IteratorWithIndex<TIterator>(std::forward<TIterator>(iterator), index);
434 }
435 
436 
437 template <typename TContainer>
439 private:
440  TContainer container;
441 
442 public:
443  explicit IndexAdapter(TContainer&& container)
444  : container(std::forward<TContainer>(container)) {}
445 
446  auto begin() {
447  return makeIteratorWithIndex(container.begin(), 0);
448  }
449 
450  auto end() {
451  return makeIteratorWithIndex(container.end(), container.size());
452  }
453 };
454 
455 template <typename TContainer>
457  return IndexAdapter<TContainer>(std::forward<TContainer>(container));
458 }
459 
460 //-----------------------------------------------------------------------------------------------------------
461 // Subrange
462 //-----------------------------------------------------------------------------------------------------------
463 
464 template <typename TIterator>
465 struct SubRange : public Noncopyable {
466 private:
467  TIterator first;
468  TIterator last;
469 
470 public:
471  template <typename TContainer>
472  explicit SubRange(const TContainer& container, const Size firstIdx, const Size lastIdx) {
473  SPH_ASSERT(lastIdx <= container.size());
474  first = container.begin() + firstIdx;
475  last = container.begin() + lastIdx;
476  }
477 
478  INLINE TIterator begin() const {
479  return first;
480  }
481 
482  INLINE TIterator end() const {
483  return last;
484  }
485 };
486 
487 template <typename TContainer>
488 INLINE auto subrange(const TContainer& container, const Size firstIdx, const Size lastIdx) {
489  return SubRange<TContainer>(container, firstIdx, lastIdx);
490 }
491 
492 //-----------------------------------------------------------------------------------------------------------
493 // SubsetIterator
494 //-----------------------------------------------------------------------------------------------------------
495 
497 template <typename TIterator, typename TCondition>
499 private:
500  TIterator iter;
501  TIterator end;
502  TCondition condition;
503 
504 public:
505  SubsetIterator(const TIterator& iterator, const TIterator& end, TCondition&& condition)
506  : iter(iterator)
507  , end(end)
508  , condition(std::forward<TCondition>(condition)) {
509  // move to first element of the subset
510  while (iter != end && !condition(*iter)) {
511  ++iter;
512  }
513  }
514 
516  do {
517  ++iter;
518  } while (iter != end && !condition(*iter));
519  return *this;
520  }
521 
522  INLINE decltype(auto) operator*() {
523  SPH_ASSERT(iter != end);
524  return *iter;
525  }
526 
527  INLINE decltype(auto) operator*() const {
528  SPH_ASSERT(iter != end);
529  return *iter;
530  }
531 
532  INLINE bool operator==(const SubsetIterator& other) const {
533  return iter == other.iter;
534  }
535 
536  INLINE bool operator!=(const SubsetIterator& other) const {
537  return iter != other.iter;
538  }
539 };
540 
542 template <typename TIterator, typename TCondition>
543 INLINE auto makeSubsetIterator(const TIterator& iterator, const TIterator& end, TCondition&& condition) {
544  return SubsetIterator<TIterator, TCondition>(iterator, end, std::forward<TCondition>(condition));
545 }
546 
548 template <typename TContainer, typename TCondition>
550 private:
551  TContainer container;
552  TCondition condition;
553 
554 public:
555  SubsetAdapter(TContainer&& container, TCondition&& condition)
556  : container(std::forward<TContainer>(container))
557  , condition(std::forward<TCondition>(condition)) {}
558 
559  auto begin() {
560  return makeSubsetIterator(container.begin(), container.end(), condition);
561  }
562 
563  auto end() {
564  return makeSubsetIterator(container.end(), container.end(), condition);
565  }
566 };
567 
569 template <typename TContainer, typename TCondition>
570 auto subset(TContainer&& container, TCondition&& condition) {
572  std::forward<TContainer>(container), std::forward<TCondition>(condition));
573 }
574 
575 //-----------------------------------------------------------------------------------------------------------
576 // IndexIterator
577 //-----------------------------------------------------------------------------------------------------------
578 
580 protected:
582 
583 public:
584  INLINE explicit IndexIterator(const Size idx)
585  : idx(idx) {}
586 
588  return idx;
589  }
590 
592  ++idx;
593  return *this;
594  }
595 
596  INLINE bool operator!=(const IndexIterator other) const {
597  return idx != other.idx;
598  }
599 };
600 
602 protected:
605 
606 public:
608  : from(from)
609  , to(to) {
610  SPH_ASSERT(from <= to);
611  }
612 
614  return IndexIterator(from);
615  }
616 
618  return IndexIterator(to);
619  }
620 
621  INLINE Size size() const {
622  return to - from;
623  }
624 
625  INLINE bool operator==(const IndexSequence& other) const {
626  return from == other.from && to == other.to;
627  }
628 
629  friend std::ostream& operator<<(std::ostream& ofs, const IndexSequence& sequence) {
630  ofs << sequence.from << " - " << sequence.to;
631  return ofs;
632  }
633 };
634 
#define SPH_ASSERT(x,...)
Definition: Assert.h:94
NAMESPACE_SPH_BEGIN
Definition: BarnesHut.cpp:13
uint32_t Size
Integral type used to index arrays (by default).
Definition: Globals.h:16
ReverseAdapter< TContainer > reverse(TContainer &&container)
TupleAdapter< TElement, TContainers... > iterateTuple(TContainers &&... containers)
TupleIterator< TElement, TIterators... > makeTupleIterator(const TIterators &... iterators)
Creates TupleIterator from individual iterators, utilizing type deduction.
INLINE auto subrange(const TContainer &container, const Size firstIdx, const Size lastIdx)
IndexAdapter< TContainer > iterateWithIndex(TContainer &&container)
IteratorWithIndex< TIterator > makeIteratorWithIndex(TIterator &&iterator, const Size index)
INLINE auto makeSubsetIterator(const TIterator &iterator, const TIterator &end, TCondition &&condition)
ReverseIterator< TIterator > reverseIterator(const TIterator iter)
Creates reverse iterator by wrapping forward iterator, utilizes type deduction.
ElementWithIndex< TValue > makeElementWithIndex(TValue &&value, const Size index)
auto subset(TContainer &&container, TCondition &&condition)
auto componentAdapter(TBuffer &&buffer, const Size component)
Ordinary iterator for custom containers.
#define INLINE
Macros for conditional compilation based on selected compiler.
Definition: Object.h:31
#define NAMESPACE_SPH_END
Definition: Object.h:12
Re-implementation of std::tuple with some additional functionality.
decltype(auto) INLINE apply(Tuple< TArgs... > &tuple, TFunctor &&functor)
Expands arguments stored in tuple into parameter pack of a functor.
Definition: Tuple.h:480
INLINE void forEach(Tuple< TArgs... > &tuple, TFunctor &&functor)
Definition: Tuple.h:433
std::ptrdiff_t difference_type
Size operator-(const ComponentIterator &other) const
ComponentIterator(const TIterator &iterator, const int component)
ComponentIterator operator--(int)
typename TIterator::iterator_category iterator_category
bool operator>(const ComponentIterator &other) const
ComponentIterator operator++(int)
bool operator!=(const ComponentIterator &other)
bool operator<=(const ComponentIterator &other) const
void operator-=(const int n)
ComponentIterator operator+(const int n) const
ComponentIterator & operator++()
bool operator<(const ComponentIterator &other) const
bool operator>=(const ComponentIterator &other) const
const RawT & operator*() const
void operator+=(const int n)
ComponentIterator()=default
ComponentIterator & operator--()
bool operator==(const ComponentIterator &other)
ComponentIterator operator-(const int n) const
INLINE const TValue & value() const
INLINE Size index() const
INLINE TValue & value()
ElementWithIndex(TValue &&value, const Size index)
IndexAdapter(TContainer &&container)
INLINE bool operator!=(const IndexIterator other) const
INLINE IndexIterator(const Size idx)
INLINE Size operator*() const
INLINE IndexIterator & operator++()
INLINE bool operator==(const IndexSequence &other) const
INLINE IndexIterator begin() const
INLINE IndexIterator end() const
INLINE Size size() const
INLINE IndexSequence(const Size from, const Size to)
friend std::ostream & operator<<(std::ostream &ofs, const IndexSequence &sequence)
Wrapper of iterator keeping also an index of current element.
ElementWithIndex< const TValue > operator*() const
IteratorWithIndex(const TIterator iterator, const Size index)
ElementWithIndex< TValue > operator*()
bool operator!=(const IteratorWithIndex &other) const
IteratorWithIndex & operator++()
Simple (forward) iterator over continuous array of objects of type T.
Definition: Iterator.h:18
ReverseAdapter(T &&container)
Size size() const
ReverseIterator< Iterator > begin()
Returns iterator pointing to the last element in container.
ReverseIterator< Iterator > end()
Returns iterator pointiing to one before the first element.
Generic reverse iterator over continuous array of objects of type T.
bool operator!=(const ReverseIterator &other) const
ReverseIterator & operator--()
ReverseIterator(TIterator iter)
ReverseIterator operator--(int)
ReverseIterator operator++(int)
ReverseIterator()=default
bool operator==(const ReverseIterator &other) const
ReverseIterator & operator++()
Non-owning view to access and iterate over subset of container.
SubsetAdapter(TContainer &&container, TCondition &&condition)
Allows to iterate over a given subset of a container, given by condition functor.
SubsetIterator(const TIterator &iterator, const TIterator &end, TCondition &&condition)
INLINE SubsetIterator & operator++()
INLINE bool operator==(const SubsetIterator &other) const
INLINE bool operator!=(const SubsetIterator &other) const
TupleAdapter(TContainers &&... containers)
Size size() const
auto end() const
auto begin() const
Holds multiple iterators, advancing all of them at the same time.
TupleIterator(const TIterator &... iters)
bool operator==(const TupleIterator &other) const
TupleIterator & operator++()
TElement operator*()
bool operator!=(const TupleIterator &other) const
const TElement operator*() const
Heterogeneous container capable of storing a fixed number of values.
Definition: Tuple.h:146
static constexpr INLINE std::size_t size() noexcept
Returns the number of elements in tuple.
Definition: Tuple.h:268
Overload of std::swap for Sph::Array.
Definition: Array.h:578
Object with deleted copy constructor and copy operator.
Definition: Object.h:54
INLINE TIterator begin() const
SubRange(const TContainer &container, const Size firstIdx, const Size lastIdx)
INLINE TIterator end() const
Wraps a vector container, providing means to iterate over given component of vector elements.
decltype(std::declval< TBuffer >().begin()) TIterator
VectorComponentAdapter(TBuffer &&data, const Size component)