20 #ifndef GALOIS_TWOLEVELITERATORA_H
21 #define GALOIS_TWOLEVELITERATORA_H
25 #include <type_traits>
28 #include <boost/iterator/iterator_adaptor.hpp>
30 #include "galois/config.h"
38 template <
class OuterIter,
class InnerIter,
class CategoryOrTraversal,
39 class InnerBeginFn,
class InnerEndFn>
41 :
public boost::iterator_adaptor<
42 TwoLevelIteratorA<OuterIter, InnerIter, CategoryOrTraversal,
43 InnerBeginFn, InnerEndFn>,
44 InnerIter, boost::use_default, CategoryOrTraversal> {
46 typedef typename TwoLevelIteratorA::iterator_adaptor_::difference_type
50 OuterIter m_outer_begin;
52 OuterIter m_outer_end;
54 InnerBeginFn m_inner_begin_fn;
55 InnerEndFn m_inner_end_fn;
57 #if __cplusplus >= 201103L
59 std::is_convertible<
typename std::result_of<InnerBeginFn(
60 decltype(*std::declval<OuterIter>()))>::type,
62 "Result of InnerBeginFn(*OuterIter) should be convertable to InnerIter");
64 std::is_convertible<
typename std::result_of<InnerEndFn(
65 decltype(*std::declval<OuterIter>()))>::type,
67 "Result of InnerEndFn(*OuterIter) should be convertable to InnerIter");
77 if (this->base_reference() != m_inner_end_fn(*m_outer))
82 for (; m_outer != m_outer_end; ++m_outer) {
83 this->base_reference() = m_inner_begin_fn(*m_outer);
85 if (this->base_reference() != m_inner_end_fn(*m_outer))
91 void safe_decrement_dispatch(std::forward_iterator_tag, Iter& it,
95 for (; begin != it; ++begin)
100 void safe_decrement_dispatch(std::bidirectional_iterator_tag, Iter& it,
106 template <
class Iter>
107 bool safe_decrement(Iter& it,
const Iter& begin) {
110 safe_decrement_dispatch(
111 typename std::iterator_traits<Iter>::iterator_category(), it, begin);
115 template <
class Iter>
116 typename std::iterator_traits<Iter>::difference_type
117 safe_difference_dispatch(Iter it1, Iter it2, Iter end,
118 std::input_iterator_tag)
const {
125 typename std::iterator_traits<Iter>::difference_type count1 = 0;
126 typename std::iterator_traits<Iter>::difference_type count2 = 0;
131 if (++it1 == it2_orig)
136 if (++it2 == it1_orig)
142 template <
class Iter>
143 typename std::iterator_traits<Iter>::difference_type
144 safe_difference_dispatch(Iter it1, Iter it2, Iter,
145 std::random_access_iterator_tag)
const {
146 return std::distance(it1, it2);
153 template <
class Iter>
154 typename std::iterator_traits<Iter>::difference_type
155 safe_distance(Iter it1, Iter it2, Iter end)
const {
156 return safe_difference_dispatch(
158 typename std::iterator_traits<Iter>::iterator_category());
165 void seek_backward() {
168 for (end = m_inner_end_fn(*m_outer); m_inner_begin_fn(*m_outer) == end;) {
169 bool too_far __attribute__((unused)) =
170 safe_decrement(m_outer, m_outer_begin);
172 end = m_inner_end_fn(*m_outer);
175 this->base_reference() = end;
179 ++this->base_reference();
184 if (m_outer == m_outer_end) {
185 bool too_far __attribute__((unused)) =
186 safe_decrement(m_outer, m_outer_begin);
189 }
else if (!safe_decrement(this->base_reference(),
190 m_inner_begin_fn(*m_outer))) {
195 bool too_far __attribute__((unused)) =
196 safe_decrement(m_outer, m_outer_begin);
201 bool too_far __attribute__((unused)) =
202 safe_decrement(this->base_reference(), m_inner_begin_fn(*m_outer));
206 template <
class DiffType = difference_type>
207 void advance_dispatch(DiffType n, std::input_iterator_tag) {
217 template <
class DiffType = difference_type>
218 void jump_forward(DiffType n) {
222 std::distance(this->base_reference(), m_inner_end_fn(*m_outer));
225 std::advance(this->base_reference(), m);
231 template <
class DiffType = difference_type>
232 void jump_backward(DiffType n) {
236 if (n && m_outer == m_outer_end) {
243 std::distance(m_inner_begin_fn(*m_outer), this->base_reference()) + 1;
251 std::advance(this->base_reference(), -n);
257 template <
class DiffType = difference_type>
258 void advance_dispatch(DiffType n, std::random_access_iterator_tag) {
271 n,
typename std::iterator_traits<InnerIter>::iterator_category());
274 template <
class Other>
276 std::input_iterator_tag)
const {
290 if (it1.m_outer != it1.m_outer_end) {
292 if (++it1 == it2_orig)
295 if (it2.m_outer != it2.m_outer_end) {
303 template <
class Other>
305 std::random_access_iterator_tag)
const {
308 else if (m_outer == x.m_outer)
309 return safe_distance(this->base_reference(), x.base_reference(),
310 m_inner_end_fn(*m_outer));
311 else if (safe_distance(m_outer, x.m_outer, m_outer_end) < 0)
312 return -x.distance_to(*
this);
318 while (me.m_outer != me.m_outer_end) {
320 if (me.m_outer != x.m_outer)
321 d = std::distance(me.base_reference(), me.m_inner_end_fn(*me.m_outer));
323 d = std::distance(me.base_reference(), x.base_reference());
330 GALOIS_DIE(
"invalid iterator ", std::distance(m_outer, x.m_outer));
334 template <
class OtherOuterIter,
class OtherInnerIter,
class C,
class BF,
337 const TwoLevelIteratorA<OtherOuterIter, OtherInnerIter, C, BF, EF>& x)
339 return distance_to_dispatch(
340 x,
typename std::iterator_traits<InnerIter>::iterator_category());
343 template <
class OtherOuterIter,
class OtherInnerIter,
class C,
class BF,
346 equal(
const TwoLevelIteratorA<OtherOuterIter, OtherInnerIter, C, BF, EF>& x)
348 if (m_outer == m_outer_end && m_outer == x.m_outer)
351 return m_outer == x.m_outer && this->base_reference() == x.base_reference();
358 InnerBeginFn inner_begin_fn, InnerEndFn inner_end_fn)
359 : m_outer_begin(outer_begin), m_outer_end(outer_end), m_outer(outer),
360 m_inner_begin_fn(inner_begin_fn), m_inner_end_fn(inner_end_fn) {
361 if (m_outer != m_outer_end) {
362 this->base_reference() = m_inner_begin_fn(*m_outer);
368 InnerIter inner, InnerBeginFn inner_begin_fn,
369 InnerEndFn inner_end_fn)
370 : m_outer_begin(outer_begin), m_outer_end(outer_end), m_outer(outer),
371 m_inner_begin_fn(inner_begin_fn), m_inner_end_fn(inner_end_fn) {
372 this->base_reference() = inner;
378 return this->base_reference();
385 auto operator()(T&& x) const -> decltype(std::forward<T>(x).begin()) {
386 return std::forward<T>(x).begin();
393 auto operator()(T&& x) const -> decltype(std::forward<T>(x).end()) {
394 return std::forward<T>(x).end();
398 #if __cplusplus >= 201103L
400 class CategoryOrTraversal = std::forward_iterator_tag,
class OuterIter,
401 class InnerIter = decltype(std::declval<OuterIter>()->begin()),
402 class InnerBeginFn = GetBegin,
class InnerEndFn = GetEnd,
403 class Iter = TwoLevelIteratorA<OuterIter, InnerIter, CategoryOrTraversal,
404 InnerBeginFn, InnerEndFn>>
406 OuterIter outer_end) {
407 return std::make_pair(
408 Iter(outer_begin, outer_end, outer_begin, InnerBeginFn(), InnerEndFn()),
409 Iter(outer_begin, outer_end, outer_end, InnerBeginFn(), InnerEndFn()));
414 template <
class CategoryOrTraversal,
class OuterIter,
class InnerIter,
415 class InnerBeginFn,
class InnerEndFn>
416 std::pair<TwoLevelIteratorA<OuterIter, InnerIter, CategoryOrTraversal,
417 InnerBeginFn, InnerEndFn>,
418 TwoLevelIteratorA<OuterIter, InnerIter, CategoryOrTraversal,
419 InnerBeginFn, InnerEndFn>>
421 return std::make_pair(
423 InnerEndFn>(outer_begin, outer_end, outer_begin,
424 InnerBeginFn(), InnerEndFn()),
426 InnerEndFn>(outer_begin, outer_end, outer_end,
427 InnerBeginFn(), InnerEndFn()));
Alternate implementation of ChooseTwoLevelIterator.
Definition: TwoLevelIteratorA.h:40
friend class boost::iterator_core_access
Definition: TwoLevelIteratorA.h:70
Helper functor, returns t.end()
Definition: TwoLevelIteratorA.h:383
TwoLevelIteratorA(OuterIter outer_begin, OuterIter outer_end, OuterIter outer, InnerIter inner, InnerBeginFn inner_begin_fn, InnerEndFn inner_end_fn)
Definition: TwoLevelIteratorA.h:367
TwoLevelIteratorA()
Definition: TwoLevelIteratorA.h:355
#define GALOIS_DIE(...)
Definition: gIO.h:96
auto operator()(T &&x) const -> decltype(std::forward< T >(x).begin())
Definition: TwoLevelIteratorA.h:385
TwoLevelIteratorA(OuterIter outer_begin, OuterIter outer_end, OuterIter outer, InnerBeginFn inner_begin_fn, InnerEndFn inner_end_fn)
Definition: TwoLevelIteratorA.h:357
const OuterIter & get_outer_reference() const
Definition: TwoLevelIteratorA.h:375
std::pair< TwoLevelIteratorA< OuterIter, InnerIter, CategoryOrTraversal, InnerBeginFn, InnerEndFn >, TwoLevelIteratorA< OuterIter, InnerIter, CategoryOrTraversal, InnerBeginFn, InnerEndFn > > make_two_level_iterator(OuterIter outer_begin, OuterIter outer_end)
Definition: TwoLevelIteratorA.h:420
const InnerIter & get_inner_reference() const
Definition: TwoLevelIteratorA.h:377
const Ty min(std::atomic< Ty > &a, const Ty &b)
Definition: AtomicHelpers.h:70
auto operator()(T &&x) const -> decltype(std::forward< T >(x).end())
Definition: TwoLevelIteratorA.h:393
TwoLevelIteratorA::iterator_adaptor_::difference_type difference_type
Definition: TwoLevelIteratorA.h:47
Helper functor, returns t.end()
Definition: TwoLevelIteratorA.h:391