Generated on for Gecode by doxygen 1.17.0
ranges-inter.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 Inter : public MinMax {
45 protected:
47 I i;
49 J j;
50 public:
52
53
54 Inter(void);
56 Inter(I& i, J& j);
58 void init(I& i, J& j);
60
62
63
64 void operator ++(void);
66 };
67
68
74 class NaryInter : public RangeListIter {
75 protected:
78 public:
80
81
82 NaryInter(void);
84 template<class I>
85 NaryInter(Region& r, I& i);
87 template<class I, class J>
88 NaryInter(Region& r, I& i, J& j);
90 template<class I>
91 NaryInter(Region& r, I* i, int n);
93 NaryInter(const NaryInter&) = default;
95 template<class I>
96 void init(Region& r, I& i);
98 template<class I, class J>
99 void init(Region& r, I& i, J& j);
101 template<class I>
102 void init(Region& r, I* i, int n);
104 template<class I>
105 void operator &=(I& i);
107 NaryInter& operator =(const NaryInter& m);
109 };
110
111
112
113 /*
114 * Binary intersection
115 *
116 */
117
118 template<class I, class J>
119 inline void
121 if (!i() || !j()) goto done;
122 do {
123 while (i() && (i.max() < j.min())) ++i;
124 if (!i()) goto done;
125 while (j() && (j.max() < i.min())) ++j;
126 if (!j()) goto done;
127 } while (i.max() < j.min());
128 // Now the intervals overlap: consume the smaller interval
129 ma = std::min(i.max(),j.max());
130 mi = std::max(i.min(),j.min());
131 if (i.max() < j.max()) ++i; else ++j;
132 return;
133 done:
134 finish();
135 }
136
137 template<class I, class J>
138 forceinline
140
141 template<class I, class J>
142 forceinline
143 Inter<I,J>::Inter(I& i0, J& j0)
144 : i(i0), j(j0) {
145 operator ++();
146 }
147
148 template<class I, class J>
149 forceinline void
150 Inter<I,J>::init(I& i0, J& j0) {
151 i = i0; j = j0;
152 operator ++();
153 }
154
155
156 /*
157 * Nary intersection
158 *
159 */
160
161 forceinline
163
164 template<class I>
165 forceinline void
168 f = nullptr;
169 set(copy(i));
170 }
171
172 template<class I, class J>
173 forceinline void
174 NaryInter::init(Region& r, I& i, J& j) {
176 f = nullptr;
177 RangeList* h;
178 RangeList** c = &h;
179 while (i() && j()) {
180 do {
181 while (i() && (i.max() < j.min())) ++i;
182 if (!i()) goto done;
183 while (j() && (j.max() < i.min())) ++j;
184 if (!j()) goto done;
185 } while (i.max() < j.min());
186 // Now the intervals overlap: consume the smaller interval
187 RangeList* t = range(std::max(i.min(),j.min()),
188 std::min(i.max(),j.max()));
189 *c = t; c = &t->next;
190 if (i.max() < j.max()) ++i; else ++j;
191 }
192 done:
193 *c = nullptr;
194 set(h);
195 }
196
197 template<class I>
198 forceinline void
199 NaryInter::init(Region& r, I* i, int n) {
201 f = nullptr;
202 if ((n > 0) && i[0]()) {
203 RangeList* h;
204 RangeList** c = &h;
205
206 int min = i[0].min();
207 while (i[0]()) {
208 // Initialize with last interval
209 int max = i[0].max();
210 // Intersect with all other intervals
211 restart:
212 for (int j=n; j--;) {
213 // Skip intervals that are too small
214 while (i[j]() && (i[j].max() < min))
215 ++i[j];
216 if (!i[j]())
217 goto done;
218 if (i[j].min() > max) {
219 min=i[j].min();
220 max=i[j].max();
221 goto restart;
222 }
223 // Now the intervals overlap
224 if (min < i[j].min())
225 min = i[j].min();
226 if (max > i[j].max())
227 max = i[j].max();
228 }
229 RangeList* t = range(min,max);
230 *c = t; c = &t->next;
231 // The next interval must be at least two elements away
232 min = max + 2;
233 }
234 done:
235 *c = nullptr;
236 set(h);
237 }
238 }
239
240 template<class I>
241 forceinline
243 init(r, i);
244 }
245 template<class I, class J>
246 forceinline
247 NaryInter::NaryInter(Region& r, I& i, J& j) {
248 init(r, i, j);
249 }
250 template<class I>
251 forceinline
252 NaryInter::NaryInter(Region& r, I* i, int n) {
253 init(r, i, n);
254 }
255
256 template<class I>
257 forceinline void
259 RangeList* j = get();
260 // The new rangelist
261 RangeList* h;
262 RangeList** c = &h;
263 while (i() && (j != nullptr)) {
264 do {
265 while (i() && (i.max() < j->min))
266 ++i;
267 if (!i()) goto done;
268 while ((j != nullptr) && (j->max < i.min())) {
269 RangeList* t = j->next;
270 j->next = f; f = j;
271 j = t;
272 }
273 if (j == nullptr) goto done;
274 } while (i.max() < j->min);
275 // Now the intervals overlap: consume the smaller interval
276 RangeList* t = range(std::max(i.min(),j->min),
277 std::min(i.max(),j->max),f);
278 *c = t; c = &t->next;
279 if (i.max() < j->max) {
280 ++i;
281 } else {
282 RangeList* tn = j->next;
283 j->next = f; f = j;
284 j = tn;
285 }
286 }
287 done:
288 // Put remaining elements into freelist
289 while (j != nullptr) {
290 RangeList* t = j->next;
291 j->next = f; f = j;
292 j = t;
293 }
294 *c = nullptr;
295 set(h);
296 }
297
298 forceinline NaryInter&
300 f = nullptr;
301 return static_cast<NaryInter&>(RangeListIter::operator =(m));
302 }
303
304}}}
305
306// STATISTICS: iter-any
307
void operator++(void)
Move iterator to next range (if possible).
void init(I &i, J &j)
Initialize with iterator i and j.
Inter(void)
Default constructor.
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 intersection of iterators.
NaryInter & operator=(const NaryInter &m)
Assignment operator (both iterators must be allocated from the same region).
NaryInter(void)
Default constructor.
NaryInter(const NaryInter &)=default
Copy constructor.
void init(Region &r, I &i)
Initialize with single iterator i.
void operator&=(I &i)
Add iterator i.
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.
Handle to region.
Definition region.hpp:55
Range iterators.
Definition iter.hh:43
Range and value iterators.
Definition iter.hh:41
Gecode toplevel namespace