Chris@16
|
1 /*-----------------------------------------------------------------------------+
|
Chris@16
|
2 Copyright (c) 2008-2010: Joachim Faulhaber
|
Chris@16
|
3 +------------------------------------------------------------------------------+
|
Chris@16
|
4 Distributed under the Boost Software License, Version 1.0.
|
Chris@16
|
5 (See accompanying file LICENCE.txt or copy at
|
Chris@16
|
6 http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
7 +-----------------------------------------------------------------------------*/
|
Chris@16
|
8 #ifndef BOOST_ICL_INTERVAL_SET_ALGO_HPP_JOFA_081005
|
Chris@16
|
9 #define BOOST_ICL_INTERVAL_SET_ALGO_HPP_JOFA_081005
|
Chris@16
|
10
|
Chris@16
|
11 #include <boost/next_prior.hpp>
|
Chris@16
|
12 #include <boost/icl/detail/notate.hpp>
|
Chris@16
|
13 #include <boost/icl/detail/relation_state.hpp>
|
Chris@16
|
14 #include <boost/icl/type_traits/identity_element.hpp>
|
Chris@16
|
15 #include <boost/icl/type_traits/is_map.hpp>
|
Chris@16
|
16 #include <boost/icl/type_traits/is_total.hpp>
|
Chris@16
|
17 #include <boost/icl/type_traits/is_combinable.hpp>
|
Chris@16
|
18 #include <boost/icl/concept/set_value.hpp>
|
Chris@16
|
19 #include <boost/icl/concept/map_value.hpp>
|
Chris@16
|
20 #include <boost/icl/interval_combining_style.hpp>
|
Chris@16
|
21 #include <boost/icl/detail/element_comparer.hpp>
|
Chris@16
|
22 #include <boost/icl/detail/interval_subset_comparer.hpp>
|
Chris@16
|
23 #include <boost/icl/detail/associated_value.hpp>
|
Chris@16
|
24
|
Chris@16
|
25 namespace boost{namespace icl
|
Chris@16
|
26 {
|
Chris@16
|
27
|
Chris@16
|
28 namespace Interval_Set
|
Chris@16
|
29 {
|
Chris@16
|
30
|
Chris@16
|
31 //------------------------------------------------------------------------------
|
Chris@16
|
32 // Lexicographical comparison on ranges of two interval container
|
Chris@16
|
33 //------------------------------------------------------------------------------
|
Chris@16
|
34
|
Chris@16
|
35 template<class LeftT, class RightT>
|
Chris@16
|
36 bool is_element_equal(const LeftT& left, const RightT& right)
|
Chris@16
|
37 {
|
Chris@16
|
38 return subset_compare
|
Chris@16
|
39 (
|
Chris@16
|
40 left, right,
|
Chris@16
|
41 left.begin(), left.end(),
|
Chris@16
|
42 right.begin(), right.end()
|
Chris@16
|
43 ) == inclusion::equal;
|
Chris@16
|
44 }
|
Chris@16
|
45
|
Chris@16
|
46 template<class LeftT, class RightT>
|
Chris@16
|
47 bool is_element_less(const LeftT& left, const RightT& right)
|
Chris@16
|
48 {
|
Chris@16
|
49 return element_compare
|
Chris@16
|
50 (
|
Chris@16
|
51 left, right,
|
Chris@16
|
52 left.begin(), left.end(),
|
Chris@16
|
53 right.begin(), right.end()
|
Chris@16
|
54 ) == comparison::less;
|
Chris@16
|
55 }
|
Chris@16
|
56
|
Chris@16
|
57 template<class LeftT, class RightT>
|
Chris@16
|
58 bool is_element_greater(const LeftT& left, const RightT& right)
|
Chris@16
|
59 {
|
Chris@16
|
60 return element_compare
|
Chris@16
|
61 (
|
Chris@16
|
62 left, right,
|
Chris@16
|
63 left.begin(), left.end(),
|
Chris@16
|
64 right.begin(), right.end()
|
Chris@16
|
65 ) == comparison::greater;
|
Chris@16
|
66 }
|
Chris@16
|
67
|
Chris@16
|
68 //------------------------------------------------------------------------------
|
Chris@16
|
69 // Subset/superset compare on ranges of two interval container
|
Chris@16
|
70 //------------------------------------------------------------------------------
|
Chris@16
|
71
|
Chris@16
|
72 template<class IntervalContainerT>
|
Chris@16
|
73 bool is_joinable(const IntervalContainerT& container,
|
Chris@16
|
74 typename IntervalContainerT::const_iterator first,
|
Chris@16
|
75 typename IntervalContainerT::const_iterator past)
|
Chris@16
|
76 {
|
Chris@16
|
77 if(first == container.end())
|
Chris@16
|
78 return true;
|
Chris@16
|
79
|
Chris@16
|
80 typename IntervalContainerT::const_iterator it_ = first, next_ = first;
|
Chris@16
|
81 ++next_;
|
Chris@16
|
82
|
Chris@16
|
83 while(next_ != container.end() && it_ != past)
|
Chris@16
|
84 if(!icl::touches(key_value<IntervalContainerT>(it_++),
|
Chris@16
|
85 key_value<IntervalContainerT>(next_++)))
|
Chris@16
|
86 return false;
|
Chris@16
|
87
|
Chris@16
|
88 return true;
|
Chris@16
|
89 }
|
Chris@16
|
90
|
Chris@16
|
91
|
Chris@16
|
92 template<class LeftT, class RightT>
|
Chris@16
|
93 bool is_inclusion_equal(const LeftT& left, const RightT& right)
|
Chris@16
|
94 {
|
Chris@16
|
95 return subset_compare
|
Chris@16
|
96 (
|
Chris@16
|
97 left, right,
|
Chris@16
|
98 left.begin(), left.end(),
|
Chris@16
|
99 right.begin(), right.end()
|
Chris@16
|
100 ) == inclusion::equal;
|
Chris@16
|
101 }
|
Chris@16
|
102
|
Chris@16
|
103 template<class LeftT, class RightT>
|
Chris@16
|
104 typename enable_if<mpl::and_<is_concept_combinable<is_interval_set, is_interval_map, LeftT, RightT>,
|
Chris@16
|
105 is_total<RightT> >,
|
Chris@16
|
106 bool>::type
|
Chris@16
|
107 within(const LeftT&, const RightT&)
|
Chris@16
|
108 {
|
Chris@16
|
109 return true;
|
Chris@16
|
110 }
|
Chris@16
|
111
|
Chris@16
|
112 template<class LeftT, class RightT>
|
Chris@16
|
113 typename enable_if<mpl::and_<is_concept_combinable<is_interval_set, is_interval_map, LeftT, RightT>,
|
Chris@16
|
114 mpl::not_<is_total<RightT> > >,
|
Chris@16
|
115 bool>::type
|
Chris@16
|
116 within(const LeftT& sub, const RightT& super)
|
Chris@16
|
117 {
|
Chris@16
|
118 int result =
|
Chris@16
|
119 subset_compare
|
Chris@16
|
120 (
|
Chris@16
|
121 sub, super,
|
Chris@16
|
122 sub.begin(), sub.end(),
|
Chris@16
|
123 super.begin(), super.end()
|
Chris@16
|
124 );
|
Chris@16
|
125 return result == inclusion::subset || result == inclusion::equal;
|
Chris@16
|
126 }
|
Chris@16
|
127
|
Chris@16
|
128
|
Chris@16
|
129 template<class LeftT, class RightT>
|
Chris@16
|
130 typename enable_if<is_concept_combinable<is_interval_map, is_interval_map, LeftT, RightT>,
|
Chris@16
|
131 bool>::type
|
Chris@16
|
132 within(const LeftT& sub, const RightT& super)
|
Chris@16
|
133 {
|
Chris@16
|
134 int result =
|
Chris@16
|
135 subset_compare
|
Chris@16
|
136 (
|
Chris@16
|
137 sub, super,
|
Chris@16
|
138 sub.begin(), sub.end(),
|
Chris@16
|
139 super.begin(), super.end()
|
Chris@16
|
140 );
|
Chris@16
|
141 return result == inclusion::subset || result == inclusion::equal;
|
Chris@16
|
142 }
|
Chris@16
|
143
|
Chris@16
|
144 template<class LeftT, class RightT>
|
Chris@16
|
145 typename enable_if<is_concept_combinable<is_interval_set, is_interval_set, LeftT, RightT>,
|
Chris@16
|
146 bool>::type
|
Chris@16
|
147 within(const LeftT& sub, const RightT& super)
|
Chris@16
|
148 {
|
Chris@16
|
149 int result =
|
Chris@16
|
150 subset_compare
|
Chris@16
|
151 (
|
Chris@16
|
152 sub, super,
|
Chris@16
|
153 sub.begin(), sub.end(),
|
Chris@16
|
154 super.begin(), super.end()
|
Chris@16
|
155 );
|
Chris@16
|
156 return result == inclusion::subset || result == inclusion::equal;
|
Chris@16
|
157 }
|
Chris@16
|
158
|
Chris@16
|
159
|
Chris@16
|
160
|
Chris@16
|
161 template<class LeftT, class RightT>
|
Chris@16
|
162 typename enable_if<mpl::and_<is_concept_combinable<is_interval_map, is_interval_set, LeftT, RightT>,
|
Chris@16
|
163 is_total<LeftT> >,
|
Chris@16
|
164 bool>::type
|
Chris@16
|
165 contains(const LeftT&, const RightT&)
|
Chris@16
|
166 {
|
Chris@16
|
167 return true;
|
Chris@16
|
168 }
|
Chris@16
|
169
|
Chris@16
|
170 template<class LeftT, class RightT>
|
Chris@16
|
171 typename enable_if<mpl::and_<is_concept_combinable<is_interval_map, is_interval_set, LeftT, RightT>,
|
Chris@16
|
172 mpl::not_<is_total<LeftT> > >,
|
Chris@16
|
173 bool>::type
|
Chris@16
|
174 contains(const LeftT& super, const RightT& sub)
|
Chris@16
|
175 {
|
Chris@16
|
176 int result =
|
Chris@16
|
177 subset_compare
|
Chris@16
|
178 (
|
Chris@16
|
179 super, sub,
|
Chris@16
|
180 super.begin(), super.end(),
|
Chris@16
|
181 sub.begin(), sub.end()
|
Chris@16
|
182 );
|
Chris@16
|
183 return result == inclusion::superset || result == inclusion::equal;
|
Chris@16
|
184 }
|
Chris@16
|
185
|
Chris@16
|
186 template<class LeftT, class RightT>
|
Chris@16
|
187 typename enable_if<is_concept_combinable<is_interval_set, is_interval_set, LeftT, RightT>,
|
Chris@16
|
188 bool>::type
|
Chris@16
|
189 contains(const LeftT& super, const RightT& sub)
|
Chris@16
|
190 {
|
Chris@16
|
191 int result =
|
Chris@16
|
192 subset_compare
|
Chris@16
|
193 (
|
Chris@16
|
194 super, sub,
|
Chris@16
|
195 super.begin(), super.end(),
|
Chris@16
|
196 sub.begin(), sub.end()
|
Chris@16
|
197 );
|
Chris@16
|
198 return result == inclusion::superset || result == inclusion::equal;
|
Chris@16
|
199 }
|
Chris@16
|
200
|
Chris@16
|
201 template<class IntervalContainerT>
|
Chris@16
|
202 bool is_dense(const IntervalContainerT& container,
|
Chris@16
|
203 typename IntervalContainerT::const_iterator first,
|
Chris@16
|
204 typename IntervalContainerT::const_iterator past)
|
Chris@16
|
205 {
|
Chris@16
|
206 if(first == container.end())
|
Chris@16
|
207 return true;
|
Chris@16
|
208
|
Chris@16
|
209 typename IntervalContainerT::const_iterator it_ = first, next_ = first;
|
Chris@16
|
210 ++next_;
|
Chris@16
|
211
|
Chris@16
|
212 while(next_ != container.end() && it_ != past)
|
Chris@16
|
213 if(!icl::touches(key_value<IntervalContainerT>(it_++),
|
Chris@16
|
214 key_value<IntervalContainerT>(next_++)))
|
Chris@16
|
215 return false;
|
Chris@16
|
216
|
Chris@16
|
217 return true;
|
Chris@16
|
218 }
|
Chris@16
|
219
|
Chris@16
|
220 } // namespace Interval_Set
|
Chris@16
|
221
|
Chris@16
|
222 namespace segmental
|
Chris@16
|
223 {
|
Chris@16
|
224
|
Chris@16
|
225 template<class Type>
|
Chris@16
|
226 inline bool joinable(const Type& _Type, typename Type::iterator& some, typename Type::iterator& next)
|
Chris@16
|
227 {
|
Chris@16
|
228 // assert: next != end && some++ == next
|
Chris@16
|
229 return touches(key_value<Type>(some), key_value<Type>(next))
|
Chris@16
|
230 && co_equal(some, next, &_Type, &_Type);
|
Chris@16
|
231 }
|
Chris@16
|
232
|
Chris@16
|
233 template<class Type>
|
Chris@16
|
234 inline void join_nodes(Type& object, typename Type::iterator& left_,
|
Chris@16
|
235 typename Type::iterator& right_)
|
Chris@16
|
236 {
|
Chris@16
|
237 typedef typename Type::interval_type interval_type;
|
Chris@16
|
238 interval_type right_interval = key_value<Type>(right_);
|
Chris@16
|
239 object.erase(right_);
|
Chris@16
|
240 const_cast<interval_type&>(key_value<Type>(left_))
|
Chris@16
|
241 = hull(key_value<Type>(left_), right_interval);
|
Chris@16
|
242 }
|
Chris@16
|
243
|
Chris@16
|
244 template<class Type>
|
Chris@16
|
245 inline typename Type::iterator
|
Chris@16
|
246 join_on_left(Type& object, typename Type::iterator& left_,
|
Chris@16
|
247 typename Type::iterator& right_)
|
Chris@16
|
248 {
|
Chris@16
|
249 typedef typename Type::interval_type interval_type;
|
Chris@16
|
250 // both left and right are in the set and they are neighbours
|
Chris@16
|
251 BOOST_ASSERT(exclusive_less(key_value<Type>(left_), key_value<Type>(right_)));
|
Chris@16
|
252 BOOST_ASSERT(joinable(object, left_, right_));
|
Chris@16
|
253
|
Chris@16
|
254 join_nodes(object, left_, right_);
|
Chris@16
|
255 return left_;
|
Chris@16
|
256 }
|
Chris@16
|
257
|
Chris@16
|
258 template<class Type>
|
Chris@16
|
259 inline typename Type::iterator
|
Chris@16
|
260 join_on_right(Type& object, typename Type::iterator& left_,
|
Chris@16
|
261 typename Type::iterator& right_)
|
Chris@16
|
262 {
|
Chris@16
|
263 typedef typename Type::interval_type interval_type;
|
Chris@16
|
264 // both left and right are in the map and they are neighbours
|
Chris@16
|
265 BOOST_ASSERT(exclusive_less(key_value<Type>(left_), key_value<Type>(right_)));
|
Chris@16
|
266 BOOST_ASSERT(joinable(object, left_, right_));
|
Chris@16
|
267
|
Chris@16
|
268 join_nodes(object, left_, right_);
|
Chris@16
|
269 right_ = left_;
|
Chris@16
|
270 return right_;
|
Chris@16
|
271 }
|
Chris@16
|
272
|
Chris@16
|
273 template<class Type>
|
Chris@16
|
274 typename Type::iterator join_left(Type& object, typename Type::iterator& it_)
|
Chris@16
|
275 {
|
Chris@16
|
276 typedef typename Type::iterator iterator;
|
Chris@16
|
277
|
Chris@16
|
278 if(it_ == object.begin())
|
Chris@16
|
279 return it_;
|
Chris@16
|
280
|
Chris@16
|
281 // there is a predecessor
|
Chris@16
|
282 iterator pred_ = it_;
|
Chris@16
|
283 if(joinable(object, --pred_, it_))
|
Chris@16
|
284 return join_on_right(object, pred_, it_);
|
Chris@16
|
285
|
Chris@16
|
286 return it_;
|
Chris@16
|
287 }
|
Chris@16
|
288
|
Chris@16
|
289 template<class Type>
|
Chris@16
|
290 typename Type::iterator join_right(Type& object, typename Type::iterator& it_)
|
Chris@16
|
291 {
|
Chris@16
|
292 typedef typename Type::iterator iterator;
|
Chris@16
|
293
|
Chris@16
|
294 if(it_ == object.end())
|
Chris@16
|
295 return it_;
|
Chris@16
|
296
|
Chris@16
|
297 // there is a successor
|
Chris@16
|
298 iterator succ_ = it_;
|
Chris@16
|
299
|
Chris@16
|
300 if(++succ_ != object.end() && joinable(object, it_, succ_))
|
Chris@16
|
301 return join_on_left(object, it_, succ_);
|
Chris@16
|
302
|
Chris@16
|
303 return it_;
|
Chris@16
|
304 }
|
Chris@16
|
305
|
Chris@16
|
306 template<class Type>
|
Chris@16
|
307 typename Type::iterator join_neighbours(Type& object, typename Type::iterator& it_)
|
Chris@16
|
308 {
|
Chris@16
|
309 join_left (object, it_);
|
Chris@16
|
310 return join_right(object, it_);
|
Chris@16
|
311 }
|
Chris@16
|
312
|
Chris@16
|
313 template<class Type>
|
Chris@16
|
314 inline typename Type::iterator
|
Chris@16
|
315 join_under(Type& object, const typename Type::value_type& addend)
|
Chris@16
|
316 {
|
Chris@16
|
317 //ASSERT: There is at least one interval in object that overlaps with addend
|
Chris@16
|
318 typedef typename Type::iterator iterator;
|
Chris@16
|
319 typedef typename Type::interval_type interval_type;
|
Chris@16
|
320 typedef typename Type::value_type value_type;
|
Chris@16
|
321
|
Chris@16
|
322 std::pair<iterator,iterator> overlap = object.equal_range(addend);
|
Chris@16
|
323 iterator first_ = overlap.first,
|
Chris@16
|
324 end_ = overlap.second,
|
Chris@16
|
325 last_ = end_; --last_;
|
Chris@16
|
326
|
Chris@16
|
327 iterator second_= first_; ++second_;
|
Chris@16
|
328
|
Chris@16
|
329 interval_type left_resid = right_subtract(key_value<Type>(first_), addend);
|
Chris@16
|
330 interval_type right_resid = left_subtract(key_value<Type>(last_) , addend);
|
Chris@16
|
331
|
Chris@16
|
332 object.erase(second_, end_);
|
Chris@16
|
333
|
Chris@16
|
334 const_cast<value_type&>(key_value<Type>(first_))
|
Chris@16
|
335 = hull(hull(left_resid, addend), right_resid);
|
Chris@16
|
336 return first_;
|
Chris@16
|
337 }
|
Chris@16
|
338
|
Chris@16
|
339 template<class Type>
|
Chris@16
|
340 inline typename Type::iterator
|
Chris@16
|
341 join_under(Type& object, const typename Type::value_type& addend,
|
Chris@16
|
342 typename Type::iterator last_)
|
Chris@16
|
343 {
|
Chris@16
|
344 //ASSERT: There is at least one interval in object that overlaps with addend
|
Chris@16
|
345 typedef typename Type::iterator iterator;
|
Chris@16
|
346 typedef typename Type::interval_type interval_type;
|
Chris@16
|
347 typedef typename Type::value_type value_type;
|
Chris@16
|
348
|
Chris@16
|
349 iterator first_ = object.lower_bound(addend);
|
Chris@16
|
350 //BOOST_ASSERT(next(last_) == this->_set.upper_bound(inter_val));
|
Chris@16
|
351 iterator second_= boost::next(first_), end_ = boost::next(last_);
|
Chris@16
|
352
|
Chris@16
|
353 interval_type left_resid = right_subtract(key_value<Type>(first_), addend);
|
Chris@16
|
354 interval_type right_resid = left_subtract(key_value<Type>(last_) , addend);
|
Chris@16
|
355
|
Chris@16
|
356 object.erase(second_, end_);
|
Chris@16
|
357
|
Chris@16
|
358 const_cast<value_type&>(key_value<Type>(first_))
|
Chris@16
|
359 = hull(hull(left_resid, addend), right_resid);
|
Chris@16
|
360 return first_;
|
Chris@16
|
361 }
|
Chris@16
|
362
|
Chris@16
|
363 } // namespace segmental
|
Chris@16
|
364
|
Chris@16
|
365 namespace Interval_Set
|
Chris@16
|
366 {
|
Chris@16
|
367 using namespace segmental;
|
Chris@16
|
368
|
Chris@16
|
369 template<class Type, int combining_style>
|
Chris@16
|
370 struct on_style;
|
Chris@16
|
371
|
Chris@16
|
372 template<class Type>
|
Chris@16
|
373 struct on_style<Type, interval_combine::joining>
|
Chris@16
|
374 {
|
Chris@16
|
375 typedef on_style type;
|
Chris@16
|
376 typedef typename Type::interval_type interval_type;
|
Chris@16
|
377 typedef typename Type::iterator iterator;
|
Chris@16
|
378
|
Chris@16
|
379 inline static iterator handle_inserted(Type& object, iterator inserted_)
|
Chris@16
|
380 { return join_neighbours(object, inserted_); }
|
Chris@16
|
381
|
Chris@16
|
382 inline static iterator add_over
|
Chris@16
|
383 (Type& object, const interval_type& addend, iterator last_)
|
Chris@16
|
384 {
|
Chris@16
|
385 iterator joined_ = join_under(object, addend, last_);
|
Chris@16
|
386 return join_neighbours(object, joined_);
|
Chris@16
|
387 }
|
Chris@16
|
388
|
Chris@16
|
389 inline static iterator add_over
|
Chris@16
|
390 (Type& object, const interval_type& addend)
|
Chris@16
|
391 {
|
Chris@16
|
392 iterator joined_ = join_under(object, addend);
|
Chris@16
|
393 return join_neighbours(object, joined_);
|
Chris@16
|
394 }
|
Chris@16
|
395 };
|
Chris@16
|
396
|
Chris@16
|
397 template<class Type>
|
Chris@16
|
398 struct on_style<Type, interval_combine::separating>
|
Chris@16
|
399 {
|
Chris@16
|
400 typedef on_style type;
|
Chris@16
|
401 typedef typename Type::interval_type interval_type;
|
Chris@16
|
402 typedef typename Type::iterator iterator;
|
Chris@16
|
403
|
Chris@16
|
404 inline static iterator handle_inserted(Type&, iterator inserted_)
|
Chris@16
|
405 { return inserted_; }
|
Chris@16
|
406
|
Chris@16
|
407 inline static iterator add_over
|
Chris@16
|
408 (Type& object, const interval_type& addend, iterator last_)
|
Chris@16
|
409 {
|
Chris@16
|
410 return join_under(object, addend, last_);
|
Chris@16
|
411 }
|
Chris@16
|
412
|
Chris@16
|
413 inline static iterator add_over
|
Chris@16
|
414 (Type& object, const interval_type& addend)
|
Chris@16
|
415 {
|
Chris@16
|
416 return join_under(object, addend);
|
Chris@16
|
417 }
|
Chris@16
|
418 };
|
Chris@16
|
419
|
Chris@16
|
420 template<class Type>
|
Chris@16
|
421 struct on_style<Type, interval_combine::splitting>
|
Chris@16
|
422 {
|
Chris@16
|
423 typedef on_style type;
|
Chris@16
|
424 typedef typename Type::interval_type interval_type;
|
Chris@16
|
425 typedef typename Type::iterator iterator;
|
Chris@16
|
426
|
Chris@16
|
427 inline static iterator handle_inserted(Type&, iterator inserted_)
|
Chris@16
|
428 { return inserted_; }
|
Chris@16
|
429
|
Chris@16
|
430 inline static iterator add_over
|
Chris@16
|
431 (Type& object, const interval_type& addend, iterator last_)
|
Chris@16
|
432 {
|
Chris@16
|
433 iterator first_ = object.lower_bound(addend);
|
Chris@16
|
434 //BOOST_ASSERT(next(last_) == this->_set.upper_bound(inter_val));
|
Chris@16
|
435
|
Chris@16
|
436 iterator it_ = first_;
|
Chris@16
|
437 interval_type rest_interval = addend;
|
Chris@16
|
438
|
Chris@16
|
439 add_front(object, rest_interval, it_);
|
Chris@16
|
440 add_main (object, rest_interval, it_, last_);
|
Chris@16
|
441 add_rear (object, rest_interval, it_);
|
Chris@16
|
442 return it_;
|
Chris@16
|
443 }
|
Chris@16
|
444
|
Chris@16
|
445 inline static iterator add_over
|
Chris@16
|
446 (Type& object, const interval_type& addend)
|
Chris@16
|
447 {
|
Chris@16
|
448 std::pair<iterator,iterator> overlap = object.equal_range(addend);
|
Chris@16
|
449 iterator first_ = overlap.first,
|
Chris@16
|
450 end_ = overlap.second,
|
Chris@16
|
451 last_ = end_; --last_;
|
Chris@16
|
452
|
Chris@16
|
453 iterator it_ = first_;
|
Chris@16
|
454 interval_type rest_interval = addend;
|
Chris@16
|
455
|
Chris@16
|
456 add_front(object, rest_interval, it_);
|
Chris@16
|
457 add_main (object, rest_interval, it_, last_);
|
Chris@16
|
458 add_rear (object, rest_interval, it_);
|
Chris@16
|
459
|
Chris@16
|
460 return it_;
|
Chris@16
|
461 }
|
Chris@16
|
462 };
|
Chris@16
|
463
|
Chris@16
|
464
|
Chris@16
|
465 template<class Type>
|
Chris@16
|
466 void add_front(Type& object, const typename Type::interval_type& inter_val,
|
Chris@16
|
467 typename Type::iterator& first_)
|
Chris@16
|
468 {
|
Chris@16
|
469 typedef typename Type::interval_type interval_type;
|
Chris@16
|
470 typedef typename Type::iterator iterator;
|
Chris@16
|
471 // If the collision sequence has a left residual 'left_resid' it will
|
Chris@16
|
472 // be split, to provide a standardized start of algorithms:
|
Chris@16
|
473 // The addend interval 'inter_val' covers the beginning of the collision sequence.
|
Chris@16
|
474
|
Chris@16
|
475 // only for the first there can be a left_resid: a part of *first_ left of inter_val
|
Chris@16
|
476 interval_type left_resid = right_subtract(key_value<Type>(first_), inter_val);
|
Chris@16
|
477
|
Chris@16
|
478 if(!icl::is_empty(left_resid))
|
Chris@16
|
479 { // [------------ . . .
|
Chris@16
|
480 // [left_resid---first_ --- . . .
|
Chris@16
|
481 iterator prior_ = cyclic_prior(object, first_);
|
Chris@16
|
482 const_cast<interval_type&>(key_value<Type>(first_))
|
Chris@16
|
483 = left_subtract(key_value<Type>(first_), left_resid);
|
Chris@16
|
484 //NOTE: Only splitting
|
Chris@16
|
485 object._insert(prior_, icl::make_value<Type>(left_resid, co_value<Type>(first_)));
|
Chris@16
|
486 }
|
Chris@16
|
487
|
Chris@16
|
488 //POST:
|
Chris@16
|
489 // [----- inter_val ---- . . .
|
Chris@16
|
490 // ...[-- first_ --...
|
Chris@16
|
491 }
|
Chris@16
|
492
|
Chris@16
|
493
|
Chris@16
|
494 template<class Type>
|
Chris@16
|
495 void add_segment(Type& object, const typename Type::interval_type& inter_val,
|
Chris@16
|
496 typename Type::iterator& it_ )
|
Chris@16
|
497 {
|
Chris@16
|
498 typedef typename Type::interval_type interval_type;
|
Chris@16
|
499 interval_type lead_gap = right_subtract(inter_val, *it_);
|
Chris@16
|
500 if(!icl::is_empty(lead_gap))
|
Chris@16
|
501 // [lead_gap--- . . .
|
Chris@16
|
502 // [prior_) [-- it_ ...
|
Chris@16
|
503 object._insert(prior(it_), lead_gap);
|
Chris@16
|
504
|
Chris@16
|
505 // . . . --------- . . . addend interval
|
Chris@16
|
506 // [-- it_ --) has a common part with the first overval
|
Chris@16
|
507 ++it_;
|
Chris@16
|
508 }
|
Chris@16
|
509
|
Chris@16
|
510
|
Chris@16
|
511 template<class Type>
|
Chris@16
|
512 void add_main(Type& object, typename Type::interval_type& rest_interval,
|
Chris@16
|
513 typename Type::iterator& it_,
|
Chris@16
|
514 const typename Type::iterator& last_)
|
Chris@16
|
515 {
|
Chris@16
|
516 typedef typename Type::interval_type interval_type;
|
Chris@16
|
517 interval_type cur_interval;
|
Chris@16
|
518 while(it_ != last_)
|
Chris@16
|
519 {
|
Chris@16
|
520 cur_interval = *it_ ;
|
Chris@16
|
521 add_segment(object, rest_interval, it_);
|
Chris@16
|
522 // shrink interval
|
Chris@16
|
523 rest_interval = left_subtract(rest_interval, cur_interval);
|
Chris@16
|
524 }
|
Chris@16
|
525 }
|
Chris@16
|
526
|
Chris@16
|
527
|
Chris@16
|
528 template<class Type>
|
Chris@16
|
529 void add_rear(Type& object, const typename Type::interval_type& inter_val,
|
Chris@16
|
530 typename Type::iterator& it_ )
|
Chris@16
|
531 {
|
Chris@16
|
532 typedef typename Type::interval_type interval_type;
|
Chris@16
|
533 typedef typename Type::iterator iterator;
|
Chris@16
|
534
|
Chris@16
|
535 iterator prior_ = cyclic_prior(object, it_);
|
Chris@16
|
536 interval_type cur_itv = *it_;
|
Chris@16
|
537
|
Chris@16
|
538 interval_type lead_gap = right_subtract(inter_val, cur_itv);
|
Chris@16
|
539 if(!icl::is_empty(lead_gap))
|
Chris@16
|
540 // [lead_gap--- . . .
|
Chris@16
|
541 // [prior_) [-- it_ ...
|
Chris@16
|
542 object._insert(prior_, lead_gap);
|
Chris@16
|
543
|
Chris@16
|
544 interval_type end_gap = left_subtract(inter_val, cur_itv);
|
Chris@16
|
545 if(!icl::is_empty(end_gap))
|
Chris@16
|
546 // [---------------end_gap)
|
Chris@16
|
547 // [-- it_ --)
|
Chris@16
|
548 it_ = object._insert(it_, end_gap);
|
Chris@16
|
549 else
|
Chris@16
|
550 {
|
Chris@16
|
551 // only for the last there can be a right_resid: a part of *it_ right of addend
|
Chris@16
|
552 interval_type right_resid = left_subtract(cur_itv, inter_val);
|
Chris@16
|
553
|
Chris@16
|
554 if(!icl::is_empty(right_resid))
|
Chris@16
|
555 {
|
Chris@16
|
556 // [--------------)
|
Chris@16
|
557 // [-- it_ --right_resid)
|
Chris@16
|
558 const_cast<interval_type&>(*it_) = right_subtract(*it_, right_resid);
|
Chris@16
|
559 it_ = object._insert(it_, right_resid);
|
Chris@16
|
560 }
|
Chris@16
|
561 }
|
Chris@16
|
562 }
|
Chris@16
|
563
|
Chris@16
|
564
|
Chris@16
|
565 //==============================================================================
|
Chris@16
|
566 //= Addition
|
Chris@16
|
567 //==============================================================================
|
Chris@16
|
568 template<class Type>
|
Chris@16
|
569 typename Type::iterator
|
Chris@16
|
570 add(Type& object, const typename Type::value_type& addend)
|
Chris@16
|
571 {
|
Chris@16
|
572 typedef typename Type::interval_type interval_type;
|
Chris@16
|
573 typedef typename Type::iterator iterator;
|
Chris@16
|
574 typedef typename on_style<Type, Type::fineness>::type on_style_;
|
Chris@16
|
575
|
Chris@16
|
576 if(icl::is_empty(addend))
|
Chris@16
|
577 return object.end();
|
Chris@16
|
578
|
Chris@16
|
579 std::pair<iterator,bool> insertion = object._insert(addend);
|
Chris@16
|
580
|
Chris@16
|
581 if(insertion.second)
|
Chris@16
|
582 return on_style_::handle_inserted(object, insertion.first);
|
Chris@16
|
583 else
|
Chris@16
|
584 return on_style_::add_over(object, addend, insertion.first);
|
Chris@16
|
585 }
|
Chris@16
|
586
|
Chris@16
|
587
|
Chris@16
|
588 template<class Type>
|
Chris@16
|
589 typename Type::iterator
|
Chris@16
|
590 add(Type& object, typename Type::iterator prior_,
|
Chris@16
|
591 const typename Type::value_type& addend)
|
Chris@16
|
592 {
|
Chris@16
|
593 typedef typename Type::interval_type interval_type;
|
Chris@16
|
594 typedef typename Type::iterator iterator;
|
Chris@16
|
595 typedef typename on_style<Type, Type::fineness>::type on_style_;
|
Chris@16
|
596
|
Chris@16
|
597 if(icl::is_empty(addend))
|
Chris@16
|
598 return prior_;
|
Chris@16
|
599
|
Chris@16
|
600 iterator insertion = object._insert(prior_, addend);
|
Chris@16
|
601
|
Chris@16
|
602 if(*insertion == addend)
|
Chris@16
|
603 return on_style_::handle_inserted(object, insertion);
|
Chris@16
|
604 else
|
Chris@16
|
605 return on_style_::add_over(object, addend);
|
Chris@16
|
606 }
|
Chris@16
|
607
|
Chris@16
|
608
|
Chris@16
|
609 //==============================================================================
|
Chris@16
|
610 //= Subtraction
|
Chris@16
|
611 //==============================================================================
|
Chris@16
|
612 template<class Type>
|
Chris@16
|
613 void subtract(Type& object, const typename Type::value_type& minuend)
|
Chris@16
|
614 {
|
Chris@16
|
615 typedef typename Type::iterator iterator;
|
Chris@16
|
616 typedef typename Type::interval_type interval_type;
|
Chris@16
|
617 typedef typename Type::value_type value_type;
|
Chris@16
|
618
|
Chris@16
|
619 if(icl::is_empty(minuend)) return;
|
Chris@16
|
620
|
Chris@16
|
621 std::pair<iterator, iterator> exterior = object.equal_range(minuend);
|
Chris@16
|
622 if(exterior.first == exterior.second) return;
|
Chris@16
|
623
|
Chris@16
|
624 iterator first_ = exterior.first;
|
Chris@16
|
625 iterator end_ = exterior.second;
|
Chris@16
|
626 iterator last_ = end_; --last_;
|
Chris@16
|
627
|
Chris@16
|
628 interval_type leftResid = right_subtract(*first_, minuend);
|
Chris@16
|
629 interval_type rightResid;
|
Chris@16
|
630 if(first_ != end_ )
|
Chris@16
|
631 rightResid = left_subtract(*last_ , minuend);
|
Chris@16
|
632
|
Chris@16
|
633 object.erase(first_, end_);
|
Chris@16
|
634
|
Chris@16
|
635 if(!icl::is_empty(leftResid))
|
Chris@16
|
636 object._insert(leftResid);
|
Chris@16
|
637
|
Chris@16
|
638 if(!icl::is_empty(rightResid))
|
Chris@16
|
639 object._insert(rightResid);
|
Chris@16
|
640 }
|
Chris@16
|
641
|
Chris@16
|
642
|
Chris@16
|
643 } // namespace Interval_Set
|
Chris@16
|
644
|
Chris@16
|
645 }} // namespace icl boost
|
Chris@16
|
646
|
Chris@16
|
647 #endif
|
Chris@16
|
648
|