Stroika Library 3.0d16
 
Loading...
Searching...
No Matches
DisjointDiscreteRange.inl
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2025. All rights reserved
3 */
5
6namespace Stroika::Foundation::Traversal {
7
8 /*
9 ********************************************************************************
10 ************* DisjointDiscreteRange<T, RANGE_TYPE>::FindHints ******************
11 ********************************************************************************
12 */
13 template <typename T, typename RANGE_TYPE>
14 inline DisjointDiscreteRange<T, RANGE_TYPE>::FindHints::FindHints (value_type seedPosition, bool forwardFirst)
15 : fSeedPosition{seedPosition}
16 , fForwardFirst{forwardFirst}
17 {
18 }
19
20 /*
21 ********************************************************************************
22 ********************* DisjointDiscreteRange<T, RANGE_TYPE> *********************
23 ********************************************************************************
24 */
25 template <typename T, typename RANGE_TYPE>
26 inline DisjointDiscreteRange<T, RANGE_TYPE>::DisjointDiscreteRange (const RangeType& from)
27 : inherited{from}
28 {
29 }
30 template <typename T, typename RANGE_TYPE>
31 inline DisjointDiscreteRange<T, RANGE_TYPE>::DisjointDiscreteRange (const initializer_list<RangeType>& from)
32 : inherited{from}
33 {
34 }
35 template <typename T, typename RANGE_TYPE>
36 template <IIterableOfTo<RANGE_TYPE> RANGES_OF_T>
37 inline DisjointDiscreteRange<T, RANGE_TYPE>::DisjointDiscreteRange (RANGES_OF_T&& from)
38 : DisjointDiscreteRange{begin (forward<RANGES_OF_T> (from)), end (forward<RANGES_OF_T> (from))}
39 {
40 }
41 template <typename T, typename RANGE_TYPE>
42 template <IIterableOfTo<T> TS>
43 inline DisjointDiscreteRange<T, RANGE_TYPE>::DisjointDiscreteRange (TS&& from)
44 : DisjointDiscreteRange{begin (forward<TS> (from)), end (forward<TS> (from))}
45 {
46 }
47 template <typename T, typename RANGE_TYPE>
48 template <IInputIterator<RANGE_TYPE> ITERATOR_OF_RANGE_OF_T, sentinel_for<remove_cvref_t<ITERATOR_OF_RANGE_OF_T>> ITERATOR_OF_RANGE_OF_T2>
49 inline DisjointDiscreteRange<T, RANGE_TYPE>::DisjointDiscreteRange (ITERATOR_OF_RANGE_OF_T&& start, ITERATOR_OF_RANGE_OF_T2&& end)
50 : inherited{forward<ITERATOR_OF_RANGE_OF_T> (start), forward<ITERATOR_OF_RANGE_OF_T2> (end)}
51 {
52 }
53 template <typename T, typename RANGE_TYPE>
54 template <IInputIterator<T> ITERATOR_OF_T, sentinel_for<remove_cvref_t<ITERATOR_OF_T>> ITERATOR_OF_T2>
55 DisjointDiscreteRange<T, RANGE_TYPE>::DisjointDiscreteRange (ITERATOR_OF_T&& start, ITERATOR_OF_T2&& end)
56 {
57 static_assert (is_convertible_v<Common::ExtractValueType_t<ITERATOR_OF_T>, value_type>);
58 Containers::Sequence<RangeType> srs{};
59 Containers::SortedSet<value_type> ss{forward<ITERATOR_OF_T> (start), forward<ITERATOR_OF_T2> (end)};
60 value_type startAt{};
61 optional<value_type> endAt;
62 for (const value_type& i : ss) {
63 if (not endAt.has_value ()) {
64 startAt = i;
65 endAt = i;
66 }
67 else if (RangeType::TraitsType::GetNext (*endAt) == i) {
68 endAt = i;
69 }
70 else {
71 Assert (startAt <= *endAt);
72 srs.Append (RangeType{startAt, *endAt});
73 startAt = i;
74 endAt = i;
75 }
76 }
77 if (endAt) {
78 Assert (startAt <= *endAt);
79 srs.Append (RangeType{startAt, *endAt});
80 }
81 *this = move (THIS_CLASS_{srs});
82 }
83 template <typename T, typename RANGE_TYPE>
84 void DisjointDiscreteRange<T, RANGE_TYPE>::Add (const value_type& elt)
85 {
86 Containers::Sequence<RangeType> srs{this->SubRanges ()};
87 // Walk list, and if new item < than a given, either extend or insert. If contained, we have nothing todo
88 for (Iterator<RangeType> i = srs.begin (); i != srs.end (); ++i) {
89 if (i->Contains (elt)) {
90 return;
91 }
92 else if (elt == i->GetLowerBound () - 1) {
93 srs.Update (i, DiscreteRange<value_type>{elt, i->GetUpperBound ()});
94 // No need to check for merge adjacent cuz done by constructor
95 *this = move (THIS_CLASS_{srs});
96 return;
97 }
98 else if (elt == i->GetUpperBound () + 1) {
99 srs.Update (i, DiscreteRange<value_type>{i->GetLowerBound (), elt});
100 // No need to check for merge adjacent cuz done by constructor
101 *this = move (THIS_CLASS_{srs});
102 return;
103 }
104 else if (elt < i->GetLowerBound ()) {
105 // wont be found later, so break now, and add the point
106 break;
107 }
108 }
109 // if not less than any there, we must append new item
110 srs.push_back (DiscreteRange<value_type>{elt, elt});
111 *this = move (THIS_CLASS_{srs});
112 }
113 template <typename T, typename RANGE_TYPE>
114 auto DisjointDiscreteRange<T, RANGE_TYPE>::Intersection (const RangeType& rhs) const -> DisjointDiscreteRange
115 {
116 // @todo could do more efficiently
117 return DisjointDiscreteRange{inherited::Intersection (rhs).SubRanges ()};
118 }
119 template <typename T, typename RANGE_TYPE>
120 auto DisjointDiscreteRange<T, RANGE_TYPE>::Intersection (const DisjointDiscreteRange& rhs) const -> DisjointDiscreteRange
121 {
122 // @todo could do more efficiently
123 return DisjointDiscreteRange{inherited::Intersection (rhs).SubRanges ()};
124 }
125 template <typename T, typename RANGE_TYPE>
126 auto DisjointDiscreteRange<T, RANGE_TYPE>::GetNext (value_type elt) const -> optional<value_type>
127 {
128 Containers::Sequence<RangeType> subRanges{this->SubRanges ()};
129 // Find the first subrange which might contain elt, or successors
130 value_type next = RANGE_TYPE::TraitsType::GetNext (elt);
131 Iterator<RangeType> i{subRanges.Find ([next] (const RangeType& r) -> bool { return r.GetUpperBound () >= next; })};
132 if (i) {
133 return max (next, i->GetLowerBound ());
134 }
135 return nullopt;
136 }
137 template <typename T, typename RANGE_TYPE>
138 auto DisjointDiscreteRange<T, RANGE_TYPE>::GetPrevious (value_type elt) const -> optional<value_type>
139 {
140 Containers::Sequence<RangeType> subRanges{this->SubRanges ()};
141 // Find the first subrange which might contain elt, or predecessors
142 value_type prev = RANGE_TYPE::TraitsType::GetPrevious (elt);
143 Iterator<RangeType> i{subRanges.Find ([prev] (const RangeType& r) -> bool { return r.GetUpperBound () >= prev; })};
144 if (i) {
145 if (i->Contains (prev)) {
146 return prev;
147 }
148 }
149
150 // tmphack - need random-access iterators !!! for sequence at least!
151 auto prevOfIterator = [&subRanges] (const Iterator<RangeType>& pOfI) -> Iterator<RangeType> {
152 Iterator<RangeType> result = Iterator<RangeType>::GetEmptyIterator ();
153 for (Iterator<RangeType> i = subRanges.begin (); i != subRanges.end (); ++i) {
154 if (i == pOfI) {
155 return result;
156 }
157 result = i;
158 }
159 return result;
160 };
161
162 // if none contain next, find the last before we pass prev
163 i = prevOfIterator (subRanges.Find ([prev] (const RangeType& r) -> bool { return r.GetUpperBound () > prev; }));
164 if (i) {
165 Ensure (i->GetUpperBound () < prev);
166 return i->GetUpperBound ();
167 }
168 return nullopt;
169 }
170 template <typename T, typename RANGE_TYPE>
172 {
173 using UnsignedDifferenceType = typename RANGE_TYPE::UnsignedDifferenceType;
174 Containers::Sequence<RangeType> subRanges{this->SubRanges ()};
175 struct context_ {
177 size_t fSubRangeIdx{};
178 UnsignedDifferenceType fCurrentSubRangeIteratorAt{};
179 context_ () = delete;
180 context_ (const Containers::Sequence<RangeType>& sr)
181 : fSubRanges{sr}
182 {
183 }
184 context_ (const context_& from) = default;
185 };
186 auto myContext = make_shared<context_> (context_{subRanges});
187 auto getNext = [myContext] () -> optional<value_type> {
188 if (myContext->fSubRangeIdx < myContext->fSubRanges.size ()) {
189 RangeType curRange{myContext->fSubRanges[myContext->fSubRangeIdx]};
190 UnsignedDifferenceType nEltsPerRange{curRange.GetDistanceSpanned ()};
191 Assert (myContext->fCurrentSubRangeIteratorAt <= nEltsPerRange);
192 value_type result = curRange.GetLowerBound () + myContext->fCurrentSubRangeIteratorAt;
193 if (myContext->fCurrentSubRangeIteratorAt == nEltsPerRange) {
194 ++myContext->fSubRangeIdx;
195 myContext->fCurrentSubRangeIteratorAt = 0;
196 }
197 else {
198 ++myContext->fCurrentSubRangeIteratorAt;
199 }
200 return result;
201 }
202 return nullopt;
203 };
204 return Traversal::CreateGenerator<value_type> (getNext);
205 }
206 template <typename T, typename RANGE_TYPE>
207 auto DisjointDiscreteRange<T, RANGE_TYPE>::Find (const function<bool (value_type)>& that) const -> optional<value_type>
208 {
209 return this->empty () ? optional<value_type>{} : Find (that, FindHints (this->GetBounds ().GetLowerBound (), true));
210 }
211 template <typename T, typename RANGE_TYPE>
212 auto DisjointDiscreteRange<T, RANGE_TYPE>::Find (const function<bool (value_type)>& that, const FindHints& hints) const -> optional<value_type>
213 {
214 Require (this->Contains (hints.fSeedPosition));
215 optional<value_type> o = ScanFindAny_ (that, hints.fSeedPosition, hints.fForwardFirst);
216 if (o) {
217 // If we found any, then there is a first, so find scan back to find it...
218 value_type firstTrueFor{*o};
219 value_type i{firstTrueFor};
220 while (that (i)) {
221 firstTrueFor = i;
222 optional<value_type> o = GetPrevious (i);
223 if (o) {
224 i = *o;
225 }
226 else {
227 break;
228 }
229 }
230 return firstTrueFor;
231 }
232 else {
233 return nullopt;
234 }
235 }
236 template <typename T, typename RANGE_TYPE>
237 auto DisjointDiscreteRange<T, RANGE_TYPE>::FindLastThat (const function<bool (value_type)>& testF) const -> optional<value_type>
238 {
239 return this->empty () ? optional<value_type>{} : FindLastThat (testF, FindHints (this->GetBounds ().GetUpperBound (), false));
240 }
241 template <typename T, typename RANGE_TYPE>
242 auto DisjointDiscreteRange<T, RANGE_TYPE>::FindLastThat (const function<bool (value_type)>& testF, const FindHints& hints) const
243 -> optional<value_type>
244 {
245 Require (this->Contains (hints.fSeedPosition));
246 optional<value_type> o = ScanFindAny_ (testF, hints.fSeedPosition, hints.fForwardFirst);
247 if (o) {
248 // If we found any, then there is a last, so find scan forwards to find it...
249 value_type lastTrueFor{*o};
250 value_type i{lastTrueFor};
251 while (testF (i)) {
252 lastTrueFor = i;
253 optional<value_type> o = GetNext (i);
254 if (o) {
255 i = *o;
256 }
257 else {
258 break;
259 }
260 }
261 return lastTrueFor;
262 }
263 else {
264 return nullopt;
265 }
266 }
267 template <typename T, typename RANGE_TYPE>
268 auto DisjointDiscreteRange<T, RANGE_TYPE>::ScanTil_ (const function<bool (value_type)>& testF,
269 const function<optional<value_type> (value_type)>& iterNext, value_type seedPosition) const
270 -> optional<value_type>
271 {
272 value_type i{seedPosition};
273 while (not testF (i)) {
274 optional<value_type> o = iterNext (i);
275 if (o) {
276 i = *o;
277 }
278 else {
279 return nullopt;
280 }
281 }
282 Ensure (testF (i));
283 return i;
284 }
285 template <typename T, typename RANGE_TYPE>
286 auto DisjointDiscreteRange<T, RANGE_TYPE>::ScanFindAny_ (const function<bool (value_type)>& testF, value_type seedPosition, bool forwardFirst) const
287 -> optional<value_type>
288 {
289 /*
290 * First we must find a value/position where testF is true. It could be forward or backward from our start hint.
291 * Try one direction, and then the other.
292 *
293 * Only return 'IsIMissing()' if there are no values from which testF is true.
294 */
295 function<optional<value_type> (value_type)> backwardNext = [this] (value_type i) { return GetPrevious (i); };
296 function<optional<value_type> (value_type)> forwardNext = [this] (value_type i) { return GetNext (i); };
297 value_type i{seedPosition};
298 optional<value_type> o{ScanTil_ (testF, forwardFirst ? forwardNext : backwardNext, i)};
299 if (o) {
300 // then we found a value scanning back for which testF is true
301 i = *o;
302 }
303 else {
304 // scan the other way and see if its found
305 o = ScanTil_ (testF, forwardFirst ? backwardNext : forwardNext, i);
306 if (o) {
307 i = *o;
308 }
309 else {
310 // if not found scanning forward, or backward, its not there!
311 return nullopt;
312 }
313 }
314 Assert (testF (i));
315 return i;
316 }
317
318}
A generalization of a vector: a container whose elements are keyed by the natural numbers.
Definition Sequence.h:187
Iterable<T> is a base class for containers which easily produce an Iterator<T> to traverse them.
Definition Iterable.h:237