Chris@16
|
1 /*-----------------------------------------------------------------------------+
|
Chris@16
|
2 Copyright (c) 2010-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_CONCEPT_INTERVAL_SET_HPP_JOFA_100920
|
Chris@16
|
9 #define BOOST_ICL_CONCEPT_INTERVAL_SET_HPP_JOFA_100920
|
Chris@16
|
10
|
Chris@16
|
11 #include <boost/icl/type_traits/is_combinable.hpp>
|
Chris@16
|
12 #include <boost/icl/type_traits/interval_type_of.hpp>
|
Chris@16
|
13 #include <boost/icl/detail/set_algo.hpp>
|
Chris@16
|
14 #include <boost/icl/detail/interval_set_algo.hpp>
|
Chris@16
|
15 #include <boost/icl/concept/interval.hpp>
|
Chris@16
|
16
|
Chris@16
|
17 namespace boost{ namespace icl
|
Chris@16
|
18 {
|
Chris@16
|
19
|
Chris@16
|
20 //==============================================================================
|
Chris@16
|
21 //= Containedness<IntervalSet>
|
Chris@16
|
22 //==============================================================================
|
Chris@16
|
23 //------------------------------------------------------------------------------
|
Chris@16
|
24 //- bool contains(c T&, c P&) T:{S} P:{e i S} fragment_types
|
Chris@16
|
25 //------------------------------------------------------------------------------
|
Chris@16
|
26 template<class Type>
|
Chris@16
|
27 typename enable_if<is_interval_set<Type>, bool>::type
|
Chris@16
|
28 contains(const Type& super, const typename Type::element_type& element)
|
Chris@16
|
29 {
|
Chris@16
|
30 return !(icl::find(super, element) == super.end());
|
Chris@16
|
31 }
|
Chris@16
|
32
|
Chris@16
|
33 template<class Type>
|
Chris@16
|
34 typename enable_if<is_interval_set<Type>, bool>::type
|
Chris@16
|
35 contains(const Type& super, const typename Type::segment_type& inter_val)
|
Chris@16
|
36 {
|
Chris@16
|
37 typedef typename Type::const_iterator const_iterator;
|
Chris@16
|
38 if(icl::is_empty(inter_val))
|
Chris@16
|
39 return true;
|
Chris@16
|
40
|
Chris@16
|
41 std::pair<const_iterator, const_iterator> exterior
|
Chris@16
|
42 = super.equal_range(inter_val);
|
Chris@16
|
43 if(exterior.first == exterior.second)
|
Chris@16
|
44 return false;
|
Chris@16
|
45
|
Chris@16
|
46 const_iterator last_overlap = cyclic_prior(super, exterior.second);
|
Chris@16
|
47
|
Chris@16
|
48 return
|
Chris@16
|
49 icl::contains(hull(*(exterior.first), *last_overlap), inter_val)
|
Chris@16
|
50 && Interval_Set::is_joinable(super, exterior.first, last_overlap);
|
Chris@16
|
51 }
|
Chris@16
|
52
|
Chris@16
|
53 template<class Type, class OperandT>
|
Chris@16
|
54 typename enable_if<has_same_concept<is_interval_set, Type, OperandT>,
|
Chris@16
|
55 bool>::type
|
Chris@16
|
56 contains(const Type& super, const OperandT& sub)
|
Chris@16
|
57 {
|
Chris@16
|
58 return Interval_Set::contains(super, sub);
|
Chris@16
|
59 }
|
Chris@16
|
60
|
Chris@16
|
61 //==============================================================================
|
Chris@16
|
62 //= Addition<IntervalSet>
|
Chris@16
|
63 //==============================================================================
|
Chris@16
|
64 //------------------------------------------------------------------------------
|
Chris@16
|
65 //- T& add(T&, c P&) T:{S} P:{e i} fragment_types
|
Chris@16
|
66 //------------------------------------------------------------------------------
|
Chris@16
|
67 template<class Type>
|
Chris@16
|
68 typename enable_if<is_interval_set<Type>, Type>::type&
|
Chris@16
|
69 add(Type& object, const typename Type::segment_type& operand)
|
Chris@16
|
70 {
|
Chris@16
|
71 return object.add(operand);
|
Chris@16
|
72 }
|
Chris@16
|
73
|
Chris@16
|
74 template<class Type>
|
Chris@16
|
75 inline typename enable_if<is_interval_set<Type>, Type>::type&
|
Chris@16
|
76 add(Type& object, const typename Type::element_type& operand)
|
Chris@16
|
77 {
|
Chris@16
|
78 typedef typename Type::segment_type segment_type;
|
Chris@16
|
79 return icl::add(object, icl::singleton<segment_type>(operand));
|
Chris@16
|
80 }
|
Chris@16
|
81
|
Chris@16
|
82 //------------------------------------------------------------------------------
|
Chris@16
|
83 //- T& add(T&, J, c P&) T:{S} P:{i} interval_type
|
Chris@16
|
84 //------------------------------------------------------------------------------
|
Chris@16
|
85 template<class Type>
|
Chris@16
|
86 inline typename enable_if<is_interval_set<Type>, typename Type::iterator>::type
|
Chris@16
|
87 add(Type& object, typename Type::iterator prior,
|
Chris@16
|
88 const typename Type::segment_type& operand)
|
Chris@16
|
89 {
|
Chris@16
|
90 return object.add(prior, operand);
|
Chris@16
|
91 }
|
Chris@16
|
92
|
Chris@16
|
93 //==============================================================================
|
Chris@16
|
94 //= Insertion<IntervalSet>
|
Chris@16
|
95 //==============================================================================
|
Chris@16
|
96 //------------------------------------------------------------------------------
|
Chris@16
|
97 //- T& insert(T&, c P&) T:{S} P:{e i} fragment_types
|
Chris@16
|
98 //------------------------------------------------------------------------------
|
Chris@16
|
99 template<class Type>
|
Chris@16
|
100 inline typename enable_if<is_interval_set<Type>, Type>::type&
|
Chris@16
|
101 insert(Type& object, const typename Type::segment_type& operand)
|
Chris@16
|
102 {
|
Chris@16
|
103 return icl::add(object, operand);
|
Chris@16
|
104 }
|
Chris@16
|
105
|
Chris@16
|
106 template<class Type>
|
Chris@16
|
107 inline typename enable_if<is_interval_set<Type>, Type>::type&
|
Chris@16
|
108 insert(Type& object, const typename Type::element_type& operand)
|
Chris@16
|
109 {
|
Chris@16
|
110 return icl::add(object, operand);
|
Chris@16
|
111 }
|
Chris@16
|
112
|
Chris@16
|
113 //------------------------------------------------------------------------------
|
Chris@16
|
114 //- T& insert(T&, J, c P&) T:{S} P:{i} with hint
|
Chris@16
|
115 //------------------------------------------------------------------------------
|
Chris@16
|
116 template<class Type>
|
Chris@16
|
117 inline typename enable_if<is_interval_set<Type>, typename Type::iterator>::type
|
Chris@16
|
118 insert(Type& object, typename Type::iterator prior,
|
Chris@16
|
119 const typename Type::segment_type& operand)
|
Chris@16
|
120 {
|
Chris@16
|
121 return icl::add(object, prior, operand);
|
Chris@16
|
122 }
|
Chris@16
|
123
|
Chris@16
|
124 //==============================================================================
|
Chris@16
|
125 //= Subtraction<IntervalSet>
|
Chris@16
|
126 //==============================================================================
|
Chris@16
|
127 //------------------------------------------------------------------------------
|
Chris@16
|
128 //- T& subtract(T&, c P&) T:{S} P:{e i} fragment_type
|
Chris@16
|
129 //------------------------------------------------------------------------------
|
Chris@16
|
130 template<class Type>
|
Chris@16
|
131 typename enable_if<is_interval_set<Type>, Type>::type&
|
Chris@16
|
132 subtract(Type& object, const typename Type::segment_type& operand)
|
Chris@16
|
133 {
|
Chris@16
|
134 return object.subtract(operand);
|
Chris@16
|
135 }
|
Chris@16
|
136
|
Chris@16
|
137 template<class Type>
|
Chris@16
|
138 inline typename enable_if<is_interval_set<Type>, Type>::type&
|
Chris@16
|
139 subtract(Type& object, const typename Type::element_type& operand)
|
Chris@16
|
140 {
|
Chris@16
|
141 typedef typename Type::segment_type segment_type;
|
Chris@16
|
142 return icl::subtract(object, icl::singleton<segment_type>(operand));
|
Chris@16
|
143 }
|
Chris@16
|
144
|
Chris@16
|
145 //==============================================================================
|
Chris@16
|
146 //= Erasure<IntervalSet>
|
Chris@16
|
147 //==============================================================================
|
Chris@16
|
148 //------------------------------------------------------------------------------
|
Chris@16
|
149 //- T& erase(T&, c P&) T:{S} P:{e i} fragment_types
|
Chris@16
|
150 //------------------------------------------------------------------------------
|
Chris@16
|
151 template<class Type>
|
Chris@16
|
152 typename enable_if<is_interval_set<Type>, Type>::type&
|
Chris@16
|
153 erase(Type& object, const typename Type::segment_type& minuend)
|
Chris@16
|
154 {
|
Chris@16
|
155 return icl::subtract(object, minuend);
|
Chris@16
|
156 }
|
Chris@16
|
157
|
Chris@16
|
158 template<class Type>
|
Chris@16
|
159 typename enable_if<is_interval_set<Type>, Type>::type&
|
Chris@16
|
160 erase(Type& object, const typename Type::element_type& minuend)
|
Chris@16
|
161 {
|
Chris@16
|
162 return icl::subtract(object, minuend);
|
Chris@16
|
163 }
|
Chris@16
|
164
|
Chris@16
|
165 //==============================================================================
|
Chris@16
|
166 //= Intersection
|
Chris@16
|
167 //==============================================================================
|
Chris@16
|
168 //------------------------------------------------------------------------------
|
Chris@16
|
169 //- void add_intersection(T&, c T&, c P&) T:{S} P:{e i} fragment_types
|
Chris@16
|
170 //------------------------------------------------------------------------------
|
Chris@16
|
171 template<class Type>
|
Chris@16
|
172 typename enable_if<is_interval_set<Type>, void>::type
|
Chris@16
|
173 add_intersection(Type& section, const Type& object,
|
Chris@16
|
174 const typename Type::element_type& operand)
|
Chris@16
|
175 {
|
Chris@16
|
176 typedef typename Type::const_iterator const_iterator;
|
Chris@16
|
177 const_iterator found = icl::find(object, operand);
|
Chris@16
|
178 if(found != object.end())
|
Chris@16
|
179 icl::add(section, operand);
|
Chris@16
|
180 }
|
Chris@16
|
181
|
Chris@16
|
182
|
Chris@16
|
183 template<class Type>
|
Chris@16
|
184 typename enable_if<is_interval_set<Type>, void>::type
|
Chris@16
|
185 add_intersection(Type& section, const Type& object,
|
Chris@16
|
186 const typename Type::segment_type& segment)
|
Chris@16
|
187 {
|
Chris@16
|
188 typedef typename Type::const_iterator const_iterator;
|
Chris@16
|
189 typedef typename Type::iterator iterator;
|
Chris@16
|
190 typedef typename Type::interval_type interval_type;
|
Chris@16
|
191
|
Chris@16
|
192 if(icl::is_empty(segment))
|
Chris@16
|
193 return;
|
Chris@16
|
194
|
Chris@16
|
195 std::pair<const_iterator, const_iterator> exterior
|
Chris@16
|
196 = object.equal_range(segment);
|
Chris@16
|
197 if(exterior.first == exterior.second)
|
Chris@16
|
198 return;
|
Chris@16
|
199
|
Chris@16
|
200 iterator prior_ = section.end();
|
Chris@16
|
201 for(const_iterator it_=exterior.first; it_ != exterior.second; it_++)
|
Chris@16
|
202 {
|
Chris@16
|
203 interval_type common_interval = key_value<Type>(it_) & segment;
|
Chris@16
|
204 if(!icl::is_empty(common_interval))
|
Chris@16
|
205 prior_ = section.insert(prior_, common_interval);
|
Chris@16
|
206 }
|
Chris@16
|
207 }
|
Chris@16
|
208
|
Chris@16
|
209 //==============================================================================
|
Chris@16
|
210 //= Symmetric difference<IntervalSet>
|
Chris@16
|
211 //==============================================================================
|
Chris@16
|
212 //------------------------------------------------------------------------------
|
Chris@16
|
213 //- T& flip(T&, c P&) T:{S} P:{e i S'} fragment_types
|
Chris@16
|
214 //------------------------------------------------------------------------------
|
Chris@16
|
215 template<class Type>
|
Chris@16
|
216 typename enable_if<is_interval_set<Type>, Type>::type&
|
Chris@16
|
217 flip(Type& object, const typename Type::element_type& operand)
|
Chris@16
|
218 {
|
Chris@16
|
219 if(icl::contains(object, operand))
|
Chris@16
|
220 return object -= operand;
|
Chris@16
|
221 else
|
Chris@16
|
222 return object += operand;
|
Chris@16
|
223 }
|
Chris@16
|
224
|
Chris@16
|
225 template<class Type>
|
Chris@16
|
226 typename enable_if<is_interval_set<Type>, Type>::type&
|
Chris@16
|
227 flip(Type& object, const typename Type::segment_type& segment)
|
Chris@16
|
228 {
|
Chris@16
|
229 typedef typename Type::const_iterator const_iterator;
|
Chris@16
|
230 typedef typename Type::interval_type interval_type;
|
Chris@16
|
231 // That which is common shall be subtracted
|
Chris@16
|
232 // That which is not shall be added
|
Chris@16
|
233 // So x has to be 'complementary added' or flipped
|
Chris@16
|
234 interval_type span = segment;
|
Chris@16
|
235 std::pair<const_iterator, const_iterator> exterior
|
Chris@16
|
236 = object.equal_range(span);
|
Chris@16
|
237
|
Chris@16
|
238 const_iterator fst_ = exterior.first;
|
Chris@16
|
239 const_iterator end_ = exterior.second;
|
Chris@16
|
240
|
Chris@16
|
241 interval_type covered, left_over;
|
Chris@16
|
242 const_iterator it_ = fst_;
|
Chris@16
|
243 while(it_ != end_)
|
Chris@16
|
244 {
|
Chris@16
|
245 covered = *it_++;
|
Chris@16
|
246 //[a ... : span
|
Chris@16
|
247 // [b ... : covered
|
Chris@16
|
248 //[a b) : left_over
|
Chris@16
|
249 left_over = right_subtract(span, covered);
|
Chris@16
|
250 icl::subtract(object, span & covered); //That which is common shall be subtracted
|
Chris@16
|
251 icl::add(object, left_over); //That which is not shall be added
|
Chris@16
|
252
|
Chris@16
|
253 //... d) : span
|
Chris@16
|
254 //... c) : covered
|
Chris@16
|
255 // [c d) : span'
|
Chris@16
|
256 span = left_subtract(span, covered);
|
Chris@16
|
257 }
|
Chris@16
|
258
|
Chris@16
|
259 //If span is not empty here, it_ is not in the set so it_ shall be added
|
Chris@16
|
260 icl::add(object, span);
|
Chris@16
|
261 return object;
|
Chris@16
|
262 }
|
Chris@16
|
263
|
Chris@16
|
264
|
Chris@16
|
265 template<class Type, class OperandT>
|
Chris@16
|
266 typename enable_if<is_concept_compatible<is_interval_set, Type, OperandT>, Type>::type&
|
Chris@16
|
267 flip(Type& object, const OperandT& operand)
|
Chris@16
|
268 {
|
Chris@16
|
269 typedef typename OperandT::const_iterator const_iterator;
|
Chris@16
|
270
|
Chris@16
|
271 if(operand.empty())
|
Chris@16
|
272 return object;
|
Chris@16
|
273
|
Chris@16
|
274 const_iterator common_lwb, common_upb;
|
Chris@16
|
275
|
Chris@16
|
276 if(!Set::common_range(common_lwb, common_upb, operand, object))
|
Chris@16
|
277 return object += operand;
|
Chris@16
|
278
|
Chris@16
|
279 const_iterator it_ = operand.begin();
|
Chris@16
|
280
|
Chris@16
|
281 // All elements of operand left of the common range are added
|
Chris@16
|
282 while(it_ != common_lwb)
|
Chris@16
|
283 icl::add(object, *it_++);
|
Chris@16
|
284 // All elements of operand in the common range are symmertrically subtracted
|
Chris@16
|
285 while(it_ != common_upb)
|
Chris@16
|
286 icl::flip(object, *it_++);
|
Chris@16
|
287 // All elements of operand right of the common range are added
|
Chris@16
|
288 while(it_ != operand.end())
|
Chris@16
|
289 icl::add(object, *it_++);
|
Chris@16
|
290
|
Chris@16
|
291 return object;
|
Chris@16
|
292 }
|
Chris@16
|
293
|
Chris@16
|
294 //==============================================================================
|
Chris@16
|
295 //= Set selection
|
Chris@16
|
296 //==============================================================================
|
Chris@16
|
297 template<class Type>
|
Chris@16
|
298 typename enable_if<is_interval_set<Type>, Type>::type&
|
Chris@16
|
299 domain(Type& dom, const Type& object)
|
Chris@16
|
300 {
|
Chris@16
|
301 typedef typename Type::const_iterator const_iterator;
|
Chris@16
|
302 typedef typename Type::iterator iterator;
|
Chris@16
|
303 dom.clear();
|
Chris@16
|
304 const_iterator it_ = object.begin();
|
Chris@16
|
305 iterator prior_ = dom.end();
|
Chris@16
|
306
|
Chris@16
|
307 while(it_ != object.end())
|
Chris@16
|
308 prior_ = icl::insert(dom, prior_, *it_++);
|
Chris@16
|
309
|
Chris@16
|
310 return dom;
|
Chris@16
|
311 }
|
Chris@16
|
312
|
Chris@16
|
313 template<class Type>
|
Chris@16
|
314 typename enable_if<is_interval_set<Type>, Type>::type&
|
Chris@16
|
315 between(Type& in_between, const Type& object)
|
Chris@16
|
316 {
|
Chris@16
|
317 typedef typename Type::const_iterator const_iterator;
|
Chris@16
|
318 typedef typename Type::iterator iterator;
|
Chris@16
|
319 in_between.clear();
|
Chris@16
|
320 const_iterator it_ = object.begin(), pred_;
|
Chris@16
|
321 iterator prior_ = in_between.end();
|
Chris@16
|
322
|
Chris@16
|
323 if(it_ != object.end())
|
Chris@16
|
324 pred_ = it_++;
|
Chris@16
|
325
|
Chris@16
|
326 while(it_ != object.end())
|
Chris@16
|
327 prior_ = icl::insert(in_between, prior_,
|
Chris@16
|
328 icl::between(*pred_++, *it_++));
|
Chris@16
|
329
|
Chris@16
|
330 return in_between;
|
Chris@16
|
331 }
|
Chris@16
|
332
|
Chris@16
|
333
|
Chris@16
|
334 //==============================================================================
|
Chris@16
|
335 //= Streaming
|
Chris@16
|
336 //==============================================================================
|
Chris@16
|
337 template<class CharType, class CharTraits, class Type>
|
Chris@16
|
338 typename enable_if<is_interval_set<Type>,
|
Chris@16
|
339 std::basic_ostream<CharType, CharTraits> >::type&
|
Chris@16
|
340 operator << (std::basic_ostream<CharType, CharTraits>& stream, const Type& object)
|
Chris@16
|
341 {
|
Chris@16
|
342 stream << "{";
|
Chris@16
|
343 ICL_const_FORALL(typename Type, it_, object)
|
Chris@16
|
344 stream << (*it_);
|
Chris@16
|
345
|
Chris@16
|
346 return stream << "}";
|
Chris@16
|
347 }
|
Chris@16
|
348
|
Chris@16
|
349
|
Chris@16
|
350 }} // namespace boost icl
|
Chris@16
|
351
|
Chris@16
|
352 #endif
|
Chris@16
|
353
|
Chris@16
|
354
|