Generated on for Gecode by doxygen 1.17.0
ranges-union.hpp
Go to the documentation of this file.
1/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
2/*
3 * Main authors:
4 * Christian Schulte <schulte@gecode.dev>
5 *
6 * Copyright:
7 * Christian Schulte, 2004
8 *
9 * This file is part of Gecode, the generic constraint
10 * development environment:
11 * http://www.gecode.dev
12 *
13 * Permission is hereby granted, free of charge, to any person obtaining
14 * a copy of this software and associated documentation files (the
15 * "Software"), to deal in the Software without restriction, including
16 * without limitation the rights to use, copy, modify, merge, publish,
17 * distribute, sublicense, and/or sell copies of the Software, and to
18 * permit persons to whom the Software is furnished to do so, subject to
19 * the following conditions:
20 *
21 * The above copyright notice and this permission notice shall be
22 * included in all copies or substantial portions of the Software.
23 *
24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 *
32 */
33
34#include <algorithm>
35
36namespace Gecode { namespace Iter { namespace Ranges {
37
43 template<class I, class J>
44 class Union : public MinMax {
45 protected:
47 I i;
49 J j;
50 public:
52
53
54 Union(void);
56 Union(I& i, J& j);
58 void init(I& i, J& j);
60
62
63
64 void operator ++(void);
66 };
67
68
74 class NaryUnion : public RangeListIter {
75 protected:
79 template<class I, class J>
80 RangeList* two(I& i, J& j);
82 template<class I>
83 void insert(I& i, RangeList*& u);
84 public:
86
87
88 NaryUnion(void);
90 template<class I>
91 NaryUnion(Region& r, I& i);
93 template<class I, class J>
94 NaryUnion(Region& r, I& i, J& j);
96 template<class I>
97 NaryUnion(Region& r, I* i, int n);
99 NaryUnion(const NaryUnion&) = default;
101 template<class I>
102 void init(Region& r, I& i);
104 template<class I, class J>
105 void init(Region& r, I& i, J& j);
107 template<class I>
108 void init(Region& r, I* i, int n);
110 template<class I>
111 void operator |=(I& i);
113 NaryUnion& operator =(const NaryUnion& m);
115 };
116
117
118
119 /*
120 * Binary union
121 *
122 */
123
124 template<class I, class J>
125 inline void
127 if (!i() && !j()) {
128 finish(); return;
129 }
130
131 if (!i() || (j() && (j.max()+1 < i.min()))) {
132 mi = j.min(); ma = j.max(); ++j; return;
133 }
134 if (!j() || (i() && (i.max()+1 < j.min()))) {
135 mi = i.min(); ma = i.max(); ++i; return;
136 }
137
138 mi = std::min(i.min(),j.min());
139 ma = std::max(i.max(),j.max());
140
141 ++i; ++j;
142
143 next:
144 if (i() && (i.min() <= ma+1)) {
145 ma = std::max(ma,i.max()); ++i;
146 goto next;
147 }
148 if (j() && (j.min() <= ma+1)) {
149 ma = std::max(ma,j.max()); ++j;
150 goto next;
151 }
152 }
153
154
155 template<class I, class J>
156 forceinline
158
159 template<class I, class J>
160 forceinline
161 Union<I,J>::Union(I& i0, J& j0)
162 : i(i0), j(j0) {
163 operator ++();
164 }
165
166 template<class I, class J>
167 forceinline void
168 Union<I,J>::init(I& i0, J& j0) {
169 i = i0; j = j0;
170 operator ++();
171 }
172
173
174
175 /*
176 * Nary union
177 *
178 */
179
180 template<class I, class J>
182 NaryUnion::two(I& i, J& j) {
183 RangeList* h;
184 RangeList** c = &h;
185
186 while (i() && j())
187 if (i.max()+1 < j.min()) {
188 RangeList* t = range(i); ++i;
189 *c = t; c = &t->next;
190 } else if (j.max()+1 < i.min()) {
191 RangeList* t = range(j); ++j;
192 *c = t; c = &t->next;
193 } else {
194 int min = std::min(i.min(),j.min());
195 int max = std::max(i.max(),j.max());
196 ++i; ++j;
197
198 nexta:
199 if (i() && (i.min() <= max+1)) {
200 max = std::max(max,i.max()); ++i;
201 goto nexta;
202 }
203 if (j() && (j.min() <= max+1)) {
204 max = std::max(max,j.max()); ++j;
205 goto nexta;
206 }
207
208 RangeList* t = range(min,max);
209 *c = t; c = &t->next;
210 }
211 for ( ; i(); ++i) {
212 RangeList* t = range(i);
213 *c = t; c = &t->next;
214 }
215 for ( ; j(); ++j) {
216 RangeList* t = range(j);
217 *c = t; c = &t->next;
218 }
219 *c = nullptr;
220 return h;
221 }
222
223 template<class I>
224 void
226 // The current rangelist
227 RangeList** c = &u;
228
229 while ((*c != nullptr) && i())
230 if ((*c)->max+1 < i.min()) {
231 // Keep range from union
232 c = &(*c)->next;
233 } else if (i.max()+1 < (*c)->min) {
234 // Copy range from iterator
235 RangeList* t = range(i,f); ++i;
236 // Insert
237 t->next = *c; *c = t; c = &t->next;
238 } else {
239 // Ranges overlap
240 // Compute new minimum
241 (*c)->min = std::min((*c)->min,i.min());
242 // Compute new maximum
243 int max = std::max((*c)->max,i.max());
244
245 // Scan from the next range in the union
246 RangeList* s = (*c)->next;
247 ++i;
248
249 nextb:
250 if ((s != nullptr) && (s->min <= max+1)) {
251 max = std::max(max,s->max);
252 RangeList* t = s;
253 s = s->next;
254 // Put deleted element into freelist
255 t->next = f; f = t;
256 goto nextb;
257 }
258 if (i() && (i.min() <= max+1)) {
259 max = std::max(max,i.max()); ++i;
260 goto nextb;
261 }
262 // Store computed max and shunt skipped ranges from union
263 (*c)->max = max; (*c)->next = s;
264 }
265 if (*c == nullptr) {
266 // Copy remaining ranges from iterator
267 for ( ; i(); ++i) {
268 RangeList* t = range(i,f);
269 *c = t; c = &t->next;
270 }
271 *c = nullptr;
272 }
273 }
274
275
276 forceinline
278 : f(nullptr) {}
279
280 template<class I>
281 forceinline void
284 f = nullptr;
285 set(copy(i));
286 }
287
288 template<class I, class J>
289 forceinline void
290 NaryUnion::init(Region& r, I& i, J& j) {
292 f = nullptr;
293 set(two(i,j));
294 }
295
296 template<class I>
297 forceinline void
298 NaryUnion::init(Region& r, I* i, int n) {
299 f = nullptr;
301
302 int m = 0;
303 while ((m < n) && !i[m]())
304 m++;
305
306 // Union is empty
307 if (m >= n)
308 return;
309
310 n--;
311 while (!i[n]())
312 n--;
313
314 if (m == n) {
315 // Union is just a single iterator
316 set(copy(i[m]));
317 } else {
318 // At least two iterators
319 RangeList* u = two(i[m++],i[n--]);
320 // Insert the remaining iterators
321 for ( ; m<=n; m++)
322 insert(i[m], u);
323 set(u);
324 }
325 }
326
327 template<class I>
328 forceinline
330 init(r, i);
331 }
332 template<class I, class J>
333 forceinline
334 NaryUnion::NaryUnion(Region& r, I& i, J& j) {
335 init(r, i, j);
336 }
337 template<class I>
338 forceinline
339 NaryUnion::NaryUnion(Region& r, I* i, int n) {
340 init(r, i, n);
341 }
342
343 template<class I>
344 forceinline void
346 RangeList* u = get();
347 insert(i, u);
348 set(u);
349 }
350
351 forceinline NaryUnion&
353 f = nullptr;
354 return static_cast<NaryUnion&>(RangeListIter::operator =(m));
355 }
356
357}}}
358
359// STATISTICS: iter-any
360
int ma
Maximum of current range.
int mi
Minimum of current range.
MinMax(void)
Default constructor.
void finish(void)
Set range such that iteration stops
Range iterator for union of iterators.
RangeList * f
Freelist used for allocation.
NaryUnion & operator=(const NaryUnion &m)
Assignment operator (both iterators must be allocated from the same region).
void insert(I &i, RangeList *&u)
Insert ranges from i into u.
RangeList * two(I &i, J &j)
Return range list for union of two iterators.
NaryUnion(void)
Default constructor.
void operator|=(I &i)
Add iterator i.
void init(Region &r, I &i)
Initialize with single iterator i.
NaryUnion(const NaryUnion &)=default
Copy constructor.
int min
Minimum and maximum of a range.
RangeList * copy(I &i)
Copy the iterator i to a range list.
int max(void) const
Return largest value of range.
RangeList * get(void) const
Get head of current range list.
void init(Region &r)
Initialize.
RangeListIter(void)
Default constructor.
RangeListIter & operator=(const RangeListIter &i)
Assignment operator.
RangeList * range(int min, int max, RangeList *&f)
Create new range possibly from freelist f and init.
void set(RangeList *l)
Set range lists.
RangeList * c
Current list element.
RangeList * h
Head of range list.
int min(void) const
Return smallest value of range.
Union(void)
Default constructor.
void operator++(void)
Move iterator to next range (if possible).
void init(I &i, J &j)
Initialize with iterator i and j.
Handle to region.
Definition region.hpp:55
Range iterators.
Definition iter.hh:43
Range and value iterators.
Definition iter.hh:41
Gecode toplevel namespace