bux API Reference 1.9.0
Static library of whatever are seen required in general purpose but not directly supported from Modern C++. Or whatever reusable originated from my side projects.
Loading...
Searching...
No Matches
Intervals.h
Go to the documentation of this file.
1#pragma once
2
3#include "XException.h" // RUNTIME_ERROR()
4#include <concepts> // std::integral<>
5#include <iterator> // std::input_iterator<>
6#include <limits> // std::numeric_limits<>
7#include <ostream> // std::basic_ostream<>
8#include <utility> // std::cmp_less_equal()
9#include <vector> // std::vector<>
10
11namespace bux {
12
13//
14// Types
15//
16template<class T>
17concept IntervalPt = std::integral<T> && !std::same_as<char,T>;
18
19template<IntervalPt T>
21{
22public:
23
24 // Types
25 typedef std::pair<T,T> value_type;
26 typedef typename std::vector<value_type>::const_iterator const_iterator;
27
28 // Ctors
30 C_Intervals(const C_Intervals &other): m_Intervals(other.m_Intervals) {}
31 C_Intervals(C_Intervals &&other) { swap(other); }
32 C_Intervals(T id);
34 C_Intervals(T start, T end): C_Intervals(value_type(start, end)) {}
35 template<std::input_iterator I>
36 C_Intervals(I start, I end) requires std::same_as<char, std::remove_cvref_t<decltype(*start)>>
37 {
38 while (start != end)
39 operator|=(T(*start++)); // The cast can be an undefined behavior but I don't care for now.
40 }
41 template<std::input_iterator I>
42 C_Intervals(I start, I end) requires
43 std::same_as<value_type, std::remove_cvref_t<decltype(*start)>> ||
44 (
45 !std::same_as<char,std::remove_cvref_t<decltype(*start)>> &&
46 std::integral<std::remove_cvref_t<decltype(*start)>> &&
47 std::cmp_less_equal(std::numeric_limits<T>::min(), std::numeric_limits<std::remove_cvref_t<decltype(*start)>>::min()) &&
48 std::cmp_less_equal(std::numeric_limits<std::remove_cvref_t<decltype(*start)>>::max(), std::numeric_limits<T>::max())
49 )
50 {
51 while (start != end)
52 operator|=(*start++);
53 }
54
55 // Nonvirtuals - Assignments
56 void operator=(const C_Intervals &other) { m_Intervals =other.m_Intervals; }
57 void operator=(C_Intervals &&other) { swap(other); }
58 void operator|=(const C_Intervals &other);
59 void operator&=(const C_Intervals &other);
60 void operator-=(const C_Intervals &other);
61 bool operator==(const C_Intervals &other) const { return m_Intervals == other.m_Intervals; }
62
63 // Nonvirtuals - Immutables
64 const_iterator begin() const { return m_Intervals.begin(); }
65 const_iterator end() const { return m_Intervals.end(); }
66 bool empty() const { return m_Intervals.empty(); }
67 size_t size() const { return m_Intervals.size(); }
68
69 // Nonvirtuals - Mutables
70 void complement();
71 void swap(C_Intervals &other) { m_Intervals.swap(other.m_Intervals); }
72
73private:
74
75 // Data
76 std::vector<value_type> m_Intervals;
77};
78
79//
80// Function Templates
81//
82template<IntervalPt T, class charT, class traits=std::char_traits<charT>>
83std::basic_ostream<charT,traits> &
84operator<<(std::basic_ostream<charT,traits> &out, const C_Intervals<T> &x)
85{
86 bool first =true;
87 for (auto i: x)
88 {
89 out <<(first?"{[":", [") <<i.first <<',' <<i.second <<']';
90 first =false;
91 }
92 if (first)
93 out <<'{';
94
95 return out <<'}';
96}
97
98//
99// Implement Class Templates
100//
101template<IntervalPt T>
103{
104 m_Intervals.emplace_back(id, id);
105}
106
107template<IntervalPt T>
109{
110 if (i.first > i.second)
111 RUNTIME_ERROR("({},{})", i.first, i.second);
112
113 m_Intervals.emplace_back(i);
114}
115
116template<IntervalPt T>
118{
119 decltype(m_Intervals) dst;
121 ia =other.m_Intervals.begin(), ea =other.m_Intervals.end(),
122 ib =m_Intervals.begin(), eb =m_Intervals.end();
123
124 value_type temp;
125 bool tempInUse =false;
126 while (ia != ea && ib != eb)
127 {
128 if (ia->first > ib->first)
129 {
130 std::swap(ia, ib);
131 std::swap(ea, eb);
132 }
133 // ia->first <= ib->first for sure
134 if (ia->second >= ib->second)
135 // (*ib) devoured
136 ++ib;
137 else if (ia->second < ib->first && ia->second +1 < ib->first)
138 // (*ia) and (*ib) disjointed
139 {
140 if (!tempInUse)
141 dst.emplace_back(*ia);
142 else
143 // Pending is over
144 {
145 if (temp.second +1 >= ia->first)
146 {
147 temp.second = ia->second;
148 dst.emplace_back(temp);
149 }
150 else
151 {
152 dst.emplace_back(temp);
153 dst.emplace_back(*ia);
154 }
155 tempInUse =false;
156 }
157 ++ia;
158 }
159 else
160 // Pending interval
161 {
162 if (!tempInUse)
163 {
164 temp.first = ia->first;
165 tempInUse =true;
166 }
167 temp.second = ib->second;
168 ++ia;
169 ++ib;
170 }
171 }
172
173 if (ib != eb)
174 {
175 ia =ib;
176 ea =eb;
177 }
178 if (tempInUse)
179 {
180 while (ia != ea)
181 {
182 if (temp.second < ia->first && temp.second +1 < ia->first)
183 break;
184
185 temp.second = ia->second;
186 ++ia;
187 }
188 dst.emplace_back(temp);
189 }
190 dst.insert(dst.end(), ia, ea);
191 dst.swap(m_Intervals);
192}
193
194template<IntervalPt T>
196{
197 decltype(m_Intervals) dst;
198 const_iterator ia = other.m_Intervals.begin();
199 const_iterator ea =other.m_Intervals.end();
200 const_iterator ib =m_Intervals.begin();
201 const_iterator eb =m_Intervals.end();
202
203 while (ia != ea && ib != eb)
204 {
205 if (ia->first > ib->first)
206 {
207 std::swap(ia, ib);
208 std::swap(ea, eb);
209 }
210 // ia->first <= ib->first for sure
211 if (ia->second >= ib->second)
212 // (*ib) devoured
213 dst.emplace_back(*ib++);
214 else if (ia->second < ib->first)
215 // (*ia) and (*ib) disjointed
216 ++ia;
217 else
218 // ia->first <= ib->first <= ia->second < ib->second
219 {
220 dst.emplace_back(ib->first, ia->second);
221 ++ia;
222 }
223 }
224 dst.swap(m_Intervals);
225}
226
227template<IntervalPt T>
229{
230 auto ib =other.m_Intervals.begin(),
231 eb =other.m_Intervals.end();
232
233 for (auto ia =m_Intervals.begin(); ia != m_Intervals.end() && ib != eb;)
234 {
235 if (ib->second < ia->first)
236 {
237 ++ib;
238 continue;
239 }
240
241 // ib->first <= ib->second
242 // ia->first <= ib->second
243 // ia->first <= ia->second
244 if (ib->first <= ia->first)
245 {
246 if (ia->second <= ib->second)
247 // (*ia) devoured by (*ib)
248 ia = m_Intervals.erase(ia);
249 else
250 // LB of (*ia) is increased
251 {
252 ia->first = ib->second +1;
253 ++ib;
254 }
255 }
256 else // ib->first > ia->first
257 {
258 if (ia->second <= ib->second)
259 {
260 if (ia->second >= ib->first)
261 ia->second = ib->first -1;
262
263 ++ia;
264 }
265 else // ia->second > ib->second
266 {
267 ia = m_Intervals.insert(ia, value_type(ia->first, ib->first-1));
268 (++ia)->first = ib->second +1;
269 ++ib;
270 }
271 }
272 } // for (auto ia =m_Intervals.begin(); ia != m_Intervals.end() && ib != eb;)
273}
274
275template<IntervalPt T>
277{
278 if (m_Intervals.empty())
279 {
280 m_Intervals.emplace_back(std::numeric_limits<T>::min(), std::numeric_limits<T>::max());
281 return;
282 }
283 decltype(m_Intervals) dst;
284 value_type t;
285 t.first = std::numeric_limits<T>::min();
286 for (const auto &i: m_Intervals)
287 {
288 if (i.first > std::numeric_limits<T>::min())
289 {
290 t.second = i.first -1;
291 dst.emplace_back(t);
292 }
293 t.first = i.second +1;
294 }
295 if (t.first < std::numeric_limits<T>::max())
296 {
297 t.second = std::numeric_limits<T>::max();
298 dst.emplace_back(t);
299 }
300 dst.swap(m_Intervals);
301}
302
303} // namespace bux
#define RUNTIME_ERROR(fmtStr,...)
Wrap FILE(DATE)#__LINE__ FUNCTION: msg into std::runtime_error.
Definition XException.h:32
void operator=(const C_Intervals &other)
Definition Intervals.h:56
C_Intervals(const C_Intervals &other)
Definition Intervals.h:30
C_Intervals(T start, T end)
Definition Intervals.h:34
void operator=(C_Intervals &&other)
Definition Intervals.h:57
C_Intervals(I start, I end)
Definition Intervals.h:42
void operator-=(const C_Intervals &other)
Definition Intervals.h:228
C_Intervals(C_Intervals &&other)
Definition Intervals.h:31
void swap(C_Intervals &other)
Definition Intervals.h:71
size_t size() const
Definition Intervals.h:67
std::pair< T, T > value_type
Definition Intervals.h:25
std::vector< value_type >::const_iterator const_iterator
Definition Intervals.h:26
C_Intervals(I start, I end)
Definition Intervals.h:36
const_iterator end() const
Definition Intervals.h:65
void operator|=(const C_Intervals &other)
Definition Intervals.h:117
bool empty() const
Definition Intervals.h:66
const_iterator begin() const
Definition Intervals.h:64
void operator&=(const C_Intervals &other)
Definition Intervals.h:195
bool operator==(const C_Intervals &other) const
Definition Intervals.h:61
THE common namespace of bux library.
Definition AtomiX.cpp:3
std::basic_ostream< charT, traits > & operator<<(std::basic_ostream< charT, traits > &out, const C_Intervals< T > &x)
Definition Intervals.h:84