Ultra 0.9.4
Loading...
Searching...
No Matches
individual_iterator.tcc
Go to the documentation of this file.
1
12
13#if !defined(ULTRA_GP_INDIVIDUAL_EXON_VIEW_TCC)
14# error "Don't include this file directly, include the specific .h instead"
15#endif
16
17#if !defined(ULTRA_GP_INDIVIDUAL_ITERATOR_TCC)
18#define ULTRA_GP_INDIVIDUAL_ITERATOR_TCC
19
20class individual;
21
22namespace internal
23{
24
34template<bool is_const>
35class basic_exon_iterator
36{
37public:
39 using iterator_concept = std::input_iterator_tag;
41 using iterator_category = std::input_iterator_tag;
42
43 using difference_type = std::ptrdiff_t;
44 using value_type = gene;
45 using pointer = value_type *;
46 using const_pointer = const value_type *;
47 using reference = value_type &;
48 using const_reference = const value_type &;
49
50 using ptr= std::conditional_t<is_const, const_pointer, pointer>;
51 using ref= std::conditional_t<is_const, const_reference, reference>;
52 using ind= std::conditional_t<is_const, const gp::individual, gp::individual>;
53
57 explicit basic_exon_iterator(ind &id) : ind_(std::addressof(id))
58 {
59 if (!id.empty())
60 loci_.insert(id.start());
61 }
62
69 basic_exon_iterator &operator++()
70 {
71 if (!loci_.empty())
72 {
73 const auto &g(operator*()); // must be evaluated before erase()
74
75 // Erasing first makes the tree shallower and reduces comparison work
76 // during subsequent insertions: we remove the comparison hotspot and
77 // the erased element was the one most likely to be compared against.
78 loci_.erase(loci_.begin());
79
80 for (const auto &a : g.args)
81 if (a.index() == d_address)
82 loci_.insert(g.locus_of_argument(a));
83 }
84
85 return *this;
86 }
87
89 basic_exon_iterator operator++(int)
90 {
91 const auto tmp(*this);
92 operator++();
93 return tmp;
94 }
95
103 [[nodiscard]] bool operator==(std::default_sentinel_t) const noexcept
104 {
105 return loci_.empty();
106 }
107
111 [[nodiscard]] ref &operator*() const
112 {
113 return ind_->genome_(locus());
114 }
115
119 [[nodiscard]] ptr operator->() const
120 {
121 return &operator*();
122 }
123
125 [[nodiscard]] ultra::locus locus() const
126 {
127 return *loci_.cbegin();
128 }
129
130private:
131 // For different implementation see `test/speed_gp_individual_iterator.cc`.
132
133 // Ordered frontier of active loci.
134 std::set<ultra::locus, std::greater<ultra::locus>> loci_ {};
135
136 // Pointer to the individual being iterated.
137 ind *ind_ {nullptr};
138};
139
140} // namespace internal
141
142#endif // include guard