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