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_HPP_JOFA_100323
|
Chris@16
|
9 #define BOOST_ICL_CONCEPT_INTERVAL_HPP_JOFA_100323
|
Chris@16
|
10
|
Chris@16
|
11 #include <boost/assert.hpp>
|
Chris@16
|
12 #include <boost/utility/enable_if.hpp>
|
Chris@16
|
13 #include <boost/mpl/and.hpp>
|
Chris@16
|
14 #include <boost/mpl/or.hpp>
|
Chris@16
|
15 #include <boost/mpl/not.hpp>
|
Chris@16
|
16 #include <boost/icl/detail/design_config.hpp>
|
Chris@16
|
17 #include <boost/icl/type_traits/unit_element.hpp>
|
Chris@16
|
18 #include <boost/icl/type_traits/identity_element.hpp>
|
Chris@16
|
19 #include <boost/icl/type_traits/infinity.hpp>
|
Chris@16
|
20 #include <boost/icl/type_traits/succ_pred.hpp>
|
Chris@16
|
21 #include <boost/icl/type_traits/is_numeric.hpp>
|
Chris@16
|
22 #include <boost/icl/type_traits/is_discrete.hpp>
|
Chris@16
|
23 #include <boost/icl/type_traits/is_continuous.hpp>
|
Chris@16
|
24 #include <boost/icl/type_traits/is_asymmetric_interval.hpp>
|
Chris@16
|
25 #include <boost/icl/type_traits/is_discrete_interval.hpp>
|
Chris@16
|
26 #include <boost/icl/type_traits/is_continuous_interval.hpp>
|
Chris@16
|
27
|
Chris@16
|
28 #include <boost/icl/concept/interval_bounds.hpp>
|
Chris@16
|
29 #include <boost/icl/interval_traits.hpp>
|
Chris@16
|
30 #include <boost/icl/dynamic_interval_traits.hpp>
|
Chris@16
|
31
|
Chris@16
|
32
|
Chris@16
|
33 namespace boost{namespace icl
|
Chris@16
|
34 {
|
Chris@16
|
35
|
Chris@16
|
36 //==============================================================================
|
Chris@16
|
37 //= Ordering
|
Chris@16
|
38 //==============================================================================
|
Chris@16
|
39 template<class Type>
|
Chris@16
|
40 inline typename enable_if<is_interval<Type>, bool>::type
|
Chris@16
|
41 domain_less(const typename interval_traits<Type>::domain_type& left,
|
Chris@16
|
42 const typename interval_traits<Type>::domain_type& right)
|
Chris@16
|
43 {
|
Chris@16
|
44 return typename interval_traits<Type>::domain_compare()(left, right);
|
Chris@16
|
45 }
|
Chris@16
|
46
|
Chris@16
|
47 template<class Type>
|
Chris@16
|
48 inline typename enable_if<is_interval<Type>, bool>::type
|
Chris@16
|
49 domain_less_equal(const typename interval_traits<Type>::domain_type& left,
|
Chris@16
|
50 const typename interval_traits<Type>::domain_type& right)
|
Chris@16
|
51 {
|
Chris@16
|
52 return !(typename interval_traits<Type>::domain_compare()(right, left));
|
Chris@16
|
53 }
|
Chris@16
|
54
|
Chris@16
|
55 template<class Type>
|
Chris@16
|
56 inline typename enable_if<is_interval<Type>, bool>::type
|
Chris@16
|
57 domain_equal(const typename interval_traits<Type>::domain_type& left,
|
Chris@16
|
58 const typename interval_traits<Type>::domain_type& right)
|
Chris@16
|
59 {
|
Chris@16
|
60 typedef typename interval_traits<Type>::domain_compare domain_compare;
|
Chris@16
|
61 return !(domain_compare()(left, right)) && !(domain_compare()(right, left));
|
Chris@16
|
62 }
|
Chris@16
|
63
|
Chris@16
|
64 template<class Type>
|
Chris@16
|
65 inline typename enable_if< is_interval<Type>
|
Chris@16
|
66 , typename interval_traits<Type>::domain_type>::type
|
Chris@16
|
67 domain_next(const typename interval_traits<Type>::domain_type value)
|
Chris@16
|
68 {
|
Chris@16
|
69 typedef typename interval_traits<Type>::domain_type domain_type;
|
Chris@16
|
70 typedef typename interval_traits<Type>::domain_compare domain_compare;
|
Chris@16
|
71 return icl::successor<domain_type,domain_compare>::apply(value);
|
Chris@16
|
72 }
|
Chris@16
|
73
|
Chris@16
|
74 template<class Type>
|
Chris@16
|
75 inline typename enable_if< is_interval<Type>
|
Chris@16
|
76 , typename interval_traits<Type>::domain_type>::type
|
Chris@16
|
77 domain_prior(const typename interval_traits<Type>::domain_type value)
|
Chris@16
|
78 {
|
Chris@16
|
79 typedef typename interval_traits<Type>::domain_type domain_type;
|
Chris@16
|
80 typedef typename interval_traits<Type>::domain_compare domain_compare;
|
Chris@16
|
81 return icl::predecessor<domain_type,domain_compare>::apply(value);
|
Chris@16
|
82 }
|
Chris@16
|
83
|
Chris@16
|
84 //==============================================================================
|
Chris@16
|
85 //= Construct<Interval> singleton
|
Chris@16
|
86 //==============================================================================
|
Chris@16
|
87 template<class Type>
|
Chris@16
|
88 typename enable_if
|
Chris@16
|
89 <
|
Chris@16
|
90 mpl::and_< is_static_right_open<Type>
|
Chris@16
|
91 , is_discrete<typename interval_traits<Type>::domain_type> >
|
Chris@16
|
92 , Type
|
Chris@16
|
93 >::type
|
Chris@16
|
94 singleton(const typename interval_traits<Type>::domain_type& value)
|
Chris@16
|
95 {
|
Chris@16
|
96 //ASSERT: This always creates an interval with exactly one element
|
Chris@16
|
97 return interval_traits<Type>::construct(value, domain_next<Type>(value));
|
Chris@16
|
98 }
|
Chris@16
|
99
|
Chris@16
|
100 template<class Type>
|
Chris@16
|
101 typename enable_if
|
Chris@16
|
102 <
|
Chris@16
|
103 mpl::and_< is_static_left_open<Type>
|
Chris@16
|
104 , is_discrete<typename interval_traits<Type>::domain_type> >
|
Chris@16
|
105 , Type
|
Chris@16
|
106 >::type
|
Chris@16
|
107 singleton(const typename interval_traits<Type>::domain_type& value)
|
Chris@16
|
108 {
|
Chris@16
|
109 //ASSERT: This always creates an interval with exactly one element
|
Chris@16
|
110 typedef typename interval_traits<Type>::domain_type domain_type;
|
Chris@16
|
111 typedef typename interval_traits<Type>::domain_compare domain_compare;
|
Chris@16
|
112 BOOST_ASSERT((numeric_minimum<domain_type, domain_compare, is_numeric<domain_type>::value>
|
Chris@16
|
113 ::is_less_than(value) ));
|
Chris@16
|
114
|
Chris@16
|
115 return interval_traits<Type>::construct(domain_prior<Type>(value), value);
|
Chris@16
|
116 }
|
Chris@16
|
117
|
Chris@16
|
118 template<class Type>
|
Chris@16
|
119 typename enable_if<is_discrete_static_open<Type>, Type>::type
|
Chris@16
|
120 singleton(const typename interval_traits<Type>::domain_type& value)
|
Chris@16
|
121 {
|
Chris@16
|
122 //ASSERT: This always creates an interval with exactly one element
|
Chris@16
|
123 typedef typename interval_traits<Type>::domain_type domain_type;
|
Chris@16
|
124 typedef typename interval_traits<Type>::domain_compare domain_compare;
|
Chris@16
|
125 BOOST_ASSERT((numeric_minimum<domain_type, domain_compare, is_numeric<domain_type>::value>
|
Chris@16
|
126 ::is_less_than(value)));
|
Chris@16
|
127
|
Chris@16
|
128 return interval_traits<Type>::construct( domain_prior<Type>(value)
|
Chris@16
|
129 , domain_next<Type>(value));
|
Chris@16
|
130 }
|
Chris@16
|
131
|
Chris@16
|
132 template<class Type>
|
Chris@16
|
133 typename enable_if<is_discrete_static_closed<Type>, Type>::type
|
Chris@16
|
134 singleton(const typename interval_traits<Type>::domain_type& value)
|
Chris@16
|
135 {
|
Chris@16
|
136 //ASSERT: This always creates an interval with exactly one element
|
Chris@16
|
137 return interval_traits<Type>::construct(value, value);
|
Chris@16
|
138 }
|
Chris@16
|
139
|
Chris@16
|
140 template<class Type>
|
Chris@16
|
141 typename enable_if<has_dynamic_bounds<Type>, Type>::type
|
Chris@16
|
142 singleton(const typename interval_traits<Type>::domain_type& value)
|
Chris@16
|
143 {
|
Chris@16
|
144 return dynamic_interval_traits<Type>::construct(value, value, interval_bounds::closed());
|
Chris@16
|
145 }
|
Chris@16
|
146
|
Chris@16
|
147 namespace detail
|
Chris@16
|
148 {
|
Chris@16
|
149
|
Chris@16
|
150 //==============================================================================
|
Chris@16
|
151 //= Construct<Interval> unit_trail == generalized singleton
|
Chris@16
|
152 // The smallest interval on an incrementable (and decrementable) type that can
|
Chris@16
|
153 // be constructed using ++ and -- and such that it contains a given value.
|
Chris@16
|
154 // If 'Type' is discrete, 'unit_trail' and 'singleton' are identical. So we
|
Chris@16
|
155 // can view 'unit_trail' as a generalized singleton for static intervals of
|
Chris@16
|
156 // continuous types.
|
Chris@16
|
157 //==============================================================================
|
Chris@16
|
158 template<class Type>
|
Chris@16
|
159 typename enable_if
|
Chris@16
|
160 <
|
Chris@16
|
161 mpl::and_< is_static_right_open<Type>
|
Chris@16
|
162 , boost::detail::is_incrementable<typename interval_traits<Type>::domain_type> >
|
Chris@16
|
163 , Type
|
Chris@16
|
164 >::type
|
Chris@16
|
165 unit_trail(const typename interval_traits<Type>::domain_type& value)
|
Chris@16
|
166 {
|
Chris@16
|
167 return interval_traits<Type>::construct(value, domain_next<Type>(value));
|
Chris@16
|
168 }
|
Chris@16
|
169
|
Chris@16
|
170 template<class Type>
|
Chris@16
|
171 typename enable_if
|
Chris@16
|
172 <
|
Chris@16
|
173 mpl::and_< is_static_left_open<Type>
|
Chris@16
|
174 , boost::detail::is_incrementable<typename interval_traits<Type>::domain_type> >
|
Chris@16
|
175 , Type
|
Chris@16
|
176 >::type
|
Chris@16
|
177 unit_trail(const typename interval_traits<Type>::domain_type& value)
|
Chris@16
|
178 {
|
Chris@16
|
179 typedef typename interval_traits<Type>::domain_type domain_type;
|
Chris@16
|
180 typedef typename interval_traits<Type>::domain_compare domain_compare;
|
Chris@16
|
181 BOOST_ASSERT((numeric_minimum<domain_type, domain_compare, is_numeric<domain_type>::value>
|
Chris@16
|
182 ::is_less_than(value) ));
|
Chris@16
|
183
|
Chris@16
|
184 return interval_traits<Type>::construct(domain_prior<Type>(value), value);
|
Chris@16
|
185 }
|
Chris@16
|
186
|
Chris@16
|
187 template<class Type>
|
Chris@16
|
188 typename enable_if
|
Chris@16
|
189 <
|
Chris@16
|
190 mpl::and_< is_static_open<Type>
|
Chris@16
|
191 , is_discrete<typename interval_traits<Type>::domain_type> >
|
Chris@16
|
192 , Type
|
Chris@16
|
193 >::type
|
Chris@16
|
194 unit_trail(const typename interval_traits<Type>::domain_type& value)
|
Chris@16
|
195 {
|
Chris@16
|
196 typedef typename interval_traits<Type>::domain_type domain_type;
|
Chris@16
|
197 typedef typename interval_traits<Type>::domain_compare domain_compare;
|
Chris@16
|
198 BOOST_ASSERT((numeric_minimum<domain_type, domain_compare, is_numeric<domain_type>::value>
|
Chris@16
|
199 ::is_less_than(value)));
|
Chris@16
|
200
|
Chris@16
|
201 return interval_traits<Type>::construct( domain_prior<Type>(value)
|
Chris@16
|
202 , domain_next<Type>(value));
|
Chris@16
|
203 }
|
Chris@16
|
204
|
Chris@16
|
205 template<class Type>
|
Chris@16
|
206 typename enable_if
|
Chris@16
|
207 <
|
Chris@16
|
208 mpl::and_< is_static_closed<Type>
|
Chris@16
|
209 , is_discrete<typename interval_traits<Type>::domain_type> >
|
Chris@16
|
210 , Type
|
Chris@16
|
211 >::type
|
Chris@16
|
212 unit_trail(const typename interval_traits<Type>::domain_type& value)
|
Chris@16
|
213 {
|
Chris@16
|
214 return interval_traits<Type>::construct(value, value);
|
Chris@16
|
215 }
|
Chris@16
|
216
|
Chris@16
|
217 //NOTE: statically bounded closed or open intervals of continuous domain types
|
Chris@16
|
218 // are NOT supported by ICL. They can not be used with interval containers
|
Chris@16
|
219 // consistently.
|
Chris@16
|
220
|
Chris@16
|
221
|
Chris@16
|
222 template<class Type>
|
Chris@16
|
223 typename enable_if<has_dynamic_bounds<Type>, Type>::type
|
Chris@16
|
224 unit_trail(const typename interval_traits<Type>::domain_type& value)
|
Chris@16
|
225 {
|
Chris@16
|
226 return dynamic_interval_traits<Type>::construct(value, value, interval_bounds::closed());
|
Chris@16
|
227 }
|
Chris@16
|
228
|
Chris@16
|
229 } //namespace detail
|
Chris@16
|
230
|
Chris@16
|
231 //==============================================================================
|
Chris@16
|
232 //= Construct<Interval> multon
|
Chris@16
|
233 //==============================================================================
|
Chris@16
|
234 template<class Type>
|
Chris@16
|
235 typename enable_if<has_static_bounds<Type>, Type>::type
|
Chris@16
|
236 construct(const typename interval_traits<Type>::domain_type& low,
|
Chris@16
|
237 const typename interval_traits<Type>::domain_type& up )
|
Chris@16
|
238 {
|
Chris@16
|
239 return interval_traits<Type>::construct(low, up);
|
Chris@16
|
240 }
|
Chris@16
|
241
|
Chris@16
|
242 template<class Type>
|
Chris@16
|
243 typename enable_if<has_dynamic_bounds<Type>, Type>::type
|
Chris@16
|
244 construct(const typename interval_traits<Type>::domain_type& low,
|
Chris@16
|
245 const typename interval_traits<Type>::domain_type& up,
|
Chris@16
|
246 interval_bounds bounds = interval_bounds::right_open())
|
Chris@16
|
247 {
|
Chris@16
|
248 return dynamic_interval_traits<Type>::construct(low, up, bounds);
|
Chris@16
|
249 }
|
Chris@16
|
250
|
Chris@16
|
251
|
Chris@16
|
252 //- construct form bounded values ----------------------------------------------
|
Chris@16
|
253 template<class Type>
|
Chris@16
|
254 typename enable_if<has_dynamic_bounds<Type>, Type>::type
|
Chris@16
|
255 construct(const typename Type::bounded_domain_type& low,
|
Chris@16
|
256 const typename Type::bounded_domain_type& up)
|
Chris@16
|
257 {
|
Chris@16
|
258 return dynamic_interval_traits<Type>::construct_bounded(low, up);
|
Chris@16
|
259 }
|
Chris@16
|
260
|
Chris@16
|
261 template<class Type>
|
Chris@16
|
262 typename enable_if<is_interval<Type>, Type>::type
|
Chris@16
|
263 span(const typename interval_traits<Type>::domain_type& left,
|
Chris@16
|
264 const typename interval_traits<Type>::domain_type& right)
|
Chris@16
|
265 {
|
Chris@16
|
266 if(interval_traits<Type>::domain_compare()(left,right))
|
Chris@16
|
267 return construct<Type>(left, right);
|
Chris@16
|
268 else
|
Chris@16
|
269 return construct<Type>(right, left);
|
Chris@16
|
270 }
|
Chris@16
|
271
|
Chris@16
|
272
|
Chris@16
|
273 //==============================================================================
|
Chris@16
|
274 template<class Type>
|
Chris@16
|
275 typename enable_if<is_static_right_open<Type>, Type>::type
|
Chris@16
|
276 hull(const typename interval_traits<Type>::domain_type& left,
|
Chris@16
|
277 const typename interval_traits<Type>::domain_type& right)
|
Chris@16
|
278 {
|
Chris@16
|
279 if(interval_traits<Type>::domain_compare()(left,right))
|
Chris@16
|
280 return construct<Type>(left, domain_next<Type>(right));
|
Chris@16
|
281 else
|
Chris@16
|
282 return construct<Type>(right, domain_next<Type>(left));
|
Chris@16
|
283 }
|
Chris@16
|
284
|
Chris@16
|
285 template<class Type>
|
Chris@16
|
286 typename enable_if<is_static_left_open<Type>, Type>::type
|
Chris@16
|
287 hull(const typename interval_traits<Type>::domain_type& left,
|
Chris@16
|
288 const typename interval_traits<Type>::domain_type& right)
|
Chris@16
|
289 {
|
Chris@16
|
290 typedef typename interval_traits<Type>::domain_type domain_type;
|
Chris@16
|
291 typedef typename interval_traits<Type>::domain_compare domain_compare;
|
Chris@16
|
292 if(interval_traits<Type>::domain_compare()(left,right))
|
Chris@16
|
293 {
|
Chris@16
|
294 BOOST_ASSERT((numeric_minimum<domain_type, domain_compare, is_numeric<domain_type>::value>
|
Chris@16
|
295 ::is_less_than(left) ));
|
Chris@16
|
296 return construct<Type>(domain_prior<Type>(left), right);
|
Chris@16
|
297 }
|
Chris@16
|
298 else
|
Chris@16
|
299 {
|
Chris@16
|
300 BOOST_ASSERT((numeric_minimum<domain_type, domain_compare, is_numeric<domain_type>::value>
|
Chris@16
|
301 ::is_less_than(right) ));
|
Chris@16
|
302 return construct<Type>(domain_prior<Type>(right), left);
|
Chris@16
|
303 }
|
Chris@16
|
304 }
|
Chris@16
|
305
|
Chris@16
|
306 template<class Type>
|
Chris@16
|
307 typename enable_if<is_static_closed<Type>, Type>::type
|
Chris@16
|
308 hull(const typename interval_traits<Type>::domain_type& left,
|
Chris@16
|
309 const typename interval_traits<Type>::domain_type& right)
|
Chris@16
|
310 {
|
Chris@16
|
311 if(interval_traits<Type>::domain_compare()(left,right))
|
Chris@16
|
312 return construct<Type>(left, right);
|
Chris@16
|
313 else
|
Chris@16
|
314 return construct<Type>(right, left);
|
Chris@16
|
315 }
|
Chris@16
|
316
|
Chris@16
|
317 template<class Type>
|
Chris@16
|
318 typename enable_if<is_static_open<Type>, Type>::type
|
Chris@16
|
319 hull(const typename interval_traits<Type>::domain_type& left,
|
Chris@16
|
320 const typename interval_traits<Type>::domain_type& right)
|
Chris@16
|
321 {
|
Chris@16
|
322 typedef typename interval_traits<Type>::domain_type domain_type;
|
Chris@16
|
323 typedef typename interval_traits<Type>::domain_compare domain_compare;
|
Chris@16
|
324 if(interval_traits<Type>::domain_compare()(left,right))
|
Chris@16
|
325 {
|
Chris@16
|
326 BOOST_ASSERT((numeric_minimum<domain_type, domain_compare, is_numeric<domain_type>::value>
|
Chris@16
|
327 ::is_less_than(left) ));
|
Chris@16
|
328 return construct<Type>( domain_prior<Type>(left)
|
Chris@16
|
329 , domain_next<Type>(right));
|
Chris@16
|
330 }
|
Chris@16
|
331 else
|
Chris@16
|
332 {
|
Chris@16
|
333 BOOST_ASSERT((numeric_minimum<domain_type, domain_compare, is_numeric<domain_type>::value>
|
Chris@16
|
334 ::is_less_than(right) ));
|
Chris@16
|
335 return construct<Type>( domain_prior<Type>(right)
|
Chris@16
|
336 , domain_next<Type>(left));
|
Chris@16
|
337 }
|
Chris@16
|
338 }
|
Chris@16
|
339
|
Chris@16
|
340 template<class Type>
|
Chris@16
|
341 typename enable_if<has_dynamic_bounds<Type>, Type>::type
|
Chris@16
|
342 hull(const typename interval_traits<Type>::domain_type& left,
|
Chris@16
|
343 const typename interval_traits<Type>::domain_type& right)
|
Chris@16
|
344 {
|
Chris@16
|
345 if(interval_traits<Type>::domain_compare()(left,right))
|
Chris@16
|
346 return construct<Type>(left, right, interval_bounds::closed());
|
Chris@16
|
347 else
|
Chris@16
|
348 return construct<Type>(right, left, interval_bounds::closed());
|
Chris@16
|
349 }
|
Chris@16
|
350
|
Chris@16
|
351 //==============================================================================
|
Chris@16
|
352 //= Selection
|
Chris@16
|
353 //==============================================================================
|
Chris@16
|
354
|
Chris@16
|
355 template<class Type>
|
Chris@16
|
356 inline typename enable_if<is_interval<Type>,
|
Chris@16
|
357 typename interval_traits<Type>::domain_type>::type
|
Chris@16
|
358 lower(const Type& object)
|
Chris@16
|
359 {
|
Chris@16
|
360 return interval_traits<Type>::lower(object);
|
Chris@16
|
361 }
|
Chris@16
|
362
|
Chris@16
|
363 template<class Type>
|
Chris@16
|
364 inline typename enable_if<is_interval<Type>,
|
Chris@16
|
365 typename interval_traits<Type>::domain_type>::type
|
Chris@16
|
366 upper(const Type& object)
|
Chris@16
|
367 {
|
Chris@16
|
368 return interval_traits<Type>::upper(object);
|
Chris@16
|
369 }
|
Chris@16
|
370
|
Chris@16
|
371
|
Chris@16
|
372 //- first ----------------------------------------------------------------------
|
Chris@16
|
373 template<class Type>
|
Chris@16
|
374 inline typename
|
Chris@16
|
375 enable_if< mpl::or_<is_static_right_open<Type>, is_static_closed<Type> >
|
Chris@16
|
376 , typename interval_traits<Type>::domain_type>::type
|
Chris@16
|
377 first(const Type& object)
|
Chris@16
|
378 {
|
Chris@16
|
379 return lower(object);
|
Chris@16
|
380 }
|
Chris@16
|
381
|
Chris@16
|
382 template<class Type>
|
Chris@16
|
383 inline typename
|
Chris@16
|
384 enable_if< mpl::and_< mpl::or_<is_static_left_open<Type>, is_static_open<Type> >
|
Chris@16
|
385 , is_discrete<typename interval_traits<Type>::domain_type> >
|
Chris@16
|
386 , typename interval_traits<Type>::domain_type>::type
|
Chris@16
|
387 first(const Type& object)
|
Chris@16
|
388 {
|
Chris@16
|
389 return domain_next<Type>(lower(object));
|
Chris@16
|
390 }
|
Chris@16
|
391
|
Chris@16
|
392 template<class Type>
|
Chris@16
|
393 inline typename enable_if<is_discrete_interval<Type>,
|
Chris@16
|
394 typename interval_traits<Type>::domain_type>::type
|
Chris@16
|
395 first(const Type& object)
|
Chris@16
|
396 {
|
Chris@16
|
397 return is_left_closed(object.bounds()) ?
|
Chris@16
|
398 lower(object) :
|
Chris@16
|
399 domain_next<Type>(lower(object));
|
Chris@16
|
400 }
|
Chris@16
|
401
|
Chris@16
|
402 //- last -----------------------------------------------------------------------
|
Chris@16
|
403 template<class Type>
|
Chris@16
|
404 inline typename
|
Chris@16
|
405 enable_if< mpl::or_<is_static_left_open<Type>, is_static_closed<Type> >
|
Chris@16
|
406 , typename interval_traits<Type>::domain_type>::type
|
Chris@16
|
407 last(const Type& object)
|
Chris@16
|
408 {
|
Chris@16
|
409 return upper(object);
|
Chris@16
|
410 }
|
Chris@16
|
411
|
Chris@16
|
412 template<class Type>
|
Chris@16
|
413 inline typename
|
Chris@16
|
414 enable_if< mpl::and_< mpl::or_<is_static_right_open<Type>, is_static_open<Type> >
|
Chris@16
|
415 , is_discrete<typename interval_traits<Type>::domain_type> >
|
Chris@16
|
416 , typename interval_traits<Type>::domain_type>::type
|
Chris@16
|
417 last(const Type& object)
|
Chris@16
|
418 {
|
Chris@16
|
419 typedef typename interval_traits<Type>::domain_type domain_type;
|
Chris@16
|
420 typedef typename interval_traits<Type>::domain_compare domain_compare;
|
Chris@16
|
421 BOOST_ASSERT((numeric_minimum<domain_type, domain_compare, is_numeric<domain_type>::value>
|
Chris@16
|
422 ::is_less_than(upper(object)) ));
|
Chris@16
|
423 return domain_prior<Type>(upper(object));
|
Chris@16
|
424 }
|
Chris@16
|
425
|
Chris@16
|
426 template<class Type>
|
Chris@16
|
427 inline typename enable_if<is_discrete_interval<Type>,
|
Chris@16
|
428 typename interval_traits<Type>::domain_type>::type
|
Chris@16
|
429 last(const Type& object)
|
Chris@16
|
430 {
|
Chris@16
|
431 typedef typename interval_traits<Type>::domain_type domain_type;
|
Chris@16
|
432 typedef typename interval_traits<Type>::domain_compare domain_compare;
|
Chris@16
|
433 BOOST_ASSERT((numeric_minimum<domain_type, domain_compare, is_numeric<domain_type>::value>
|
Chris@16
|
434 ::is_less_than_or(upper(object), is_right_closed(object.bounds())) ));
|
Chris@16
|
435 return is_right_closed(object.bounds()) ?
|
Chris@16
|
436 upper(object) :
|
Chris@16
|
437 domain_prior<Type>(upper(object));
|
Chris@16
|
438 }
|
Chris@16
|
439
|
Chris@16
|
440 //- last_next ------------------------------------------------------------------
|
Chris@16
|
441 template<class Type>
|
Chris@16
|
442 inline typename
|
Chris@16
|
443 enable_if< mpl::and_< mpl::or_<is_static_left_open<Type>, is_static_closed<Type> >
|
Chris@16
|
444 , is_discrete<typename interval_traits<Type>::domain_type> >
|
Chris@16
|
445 , typename interval_traits<Type>::domain_type>::type
|
Chris@16
|
446 last_next(const Type& object)
|
Chris@16
|
447 {
|
Chris@16
|
448 return domain_next<Type>(upper(object));
|
Chris@16
|
449 }
|
Chris@16
|
450
|
Chris@16
|
451 template<class Type>
|
Chris@16
|
452 inline typename
|
Chris@16
|
453 enable_if< mpl::and_< mpl::or_<is_static_right_open<Type>, is_static_open<Type> >
|
Chris@16
|
454 , is_discrete<typename interval_traits<Type>::domain_type> >
|
Chris@16
|
455 , typename interval_traits<Type>::domain_type>::type
|
Chris@16
|
456 last_next(const Type& object)
|
Chris@16
|
457 {
|
Chris@16
|
458 typedef typename interval_traits<Type>::domain_type domain_type;
|
Chris@16
|
459 return upper(object); // NOTE: last_next is implemented to avoid calling pred(object)
|
Chris@16
|
460 } // For unsigned integral types this may cause underflow.
|
Chris@16
|
461
|
Chris@16
|
462 template<class Type>
|
Chris@16
|
463 inline typename enable_if<is_discrete_interval<Type>,
|
Chris@16
|
464 typename interval_traits<Type>::domain_type>::type
|
Chris@16
|
465 last_next(const Type& object)
|
Chris@16
|
466 {
|
Chris@16
|
467 return is_right_closed(object.bounds()) ?
|
Chris@16
|
468 domain_next<Type>(upper(object)):
|
Chris@16
|
469 upper(object) ;
|
Chris@16
|
470 }
|
Chris@16
|
471
|
Chris@16
|
472 //------------------------------------------------------------------------------
|
Chris@16
|
473 template<class Type>
|
Chris@16
|
474 typename enable_if<has_dynamic_bounds<Type>,
|
Chris@16
|
475 typename Type::bounded_domain_type>::type
|
Chris@16
|
476 bounded_lower(const Type& object)
|
Chris@16
|
477 {
|
Chris@16
|
478 return typename
|
Chris@16
|
479 Type::bounded_domain_type(lower(object), object.bounds().left());
|
Chris@16
|
480 }
|
Chris@16
|
481
|
Chris@16
|
482 template<class Type>
|
Chris@16
|
483 typename enable_if<has_dynamic_bounds<Type>,
|
Chris@16
|
484 typename Type::bounded_domain_type>::type
|
Chris@16
|
485 reverse_bounded_lower(const Type& object)
|
Chris@16
|
486 {
|
Chris@16
|
487 return typename
|
Chris@16
|
488 Type::bounded_domain_type(lower(object),
|
Chris@16
|
489 object.bounds().reverse_left());
|
Chris@16
|
490 }
|
Chris@16
|
491
|
Chris@16
|
492 template<class Type>
|
Chris@16
|
493 typename enable_if<has_dynamic_bounds<Type>,
|
Chris@16
|
494 typename Type::bounded_domain_type>::type
|
Chris@16
|
495 bounded_upper(const Type& object)
|
Chris@16
|
496 {
|
Chris@16
|
497 return typename
|
Chris@16
|
498 Type::bounded_domain_type(upper(object),
|
Chris@16
|
499 object.bounds().right());
|
Chris@16
|
500 }
|
Chris@16
|
501
|
Chris@16
|
502 template<class Type>
|
Chris@16
|
503 typename enable_if<has_dynamic_bounds<Type>,
|
Chris@16
|
504 typename Type::bounded_domain_type>::type
|
Chris@16
|
505 reverse_bounded_upper(const Type& object)
|
Chris@16
|
506 {
|
Chris@16
|
507 return typename
|
Chris@16
|
508 Type::bounded_domain_type(upper(object),
|
Chris@16
|
509 object.bounds().reverse_right());
|
Chris@16
|
510 }
|
Chris@16
|
511
|
Chris@16
|
512 //- bounds ---------------------------------------------------------------------
|
Chris@16
|
513 template<class Type>
|
Chris@16
|
514 inline typename enable_if<has_dynamic_bounds<Type>, interval_bounds>::type
|
Chris@16
|
515 bounds(const Type& object)
|
Chris@16
|
516 {
|
Chris@16
|
517 return object.bounds();
|
Chris@16
|
518 }
|
Chris@16
|
519
|
Chris@16
|
520 template<class Type>
|
Chris@16
|
521 inline typename enable_if<has_static_bounds<Type>, interval_bounds>::type
|
Chris@16
|
522 bounds(const Type&)
|
Chris@16
|
523 {
|
Chris@16
|
524 return interval_bounds(interval_bound_type<Type>::value);
|
Chris@16
|
525 }
|
Chris@16
|
526
|
Chris@16
|
527
|
Chris@16
|
528 //==============================================================================
|
Chris@16
|
529 //= Emptieness
|
Chris@16
|
530 //==============================================================================
|
Chris@16
|
531 /** Is the interval empty? */
|
Chris@16
|
532 template<class Type>
|
Chris@16
|
533 typename boost::enable_if<is_asymmetric_interval<Type>, bool>::type
|
Chris@16
|
534 is_empty(const Type& object)
|
Chris@16
|
535 {
|
Chris@16
|
536 return domain_less_equal<Type>(upper(object), lower(object));
|
Chris@16
|
537 }
|
Chris@16
|
538
|
Chris@16
|
539 template<class Type>
|
Chris@16
|
540 typename boost::enable_if<is_static_closed<Type>, bool>::type
|
Chris@16
|
541 is_empty(const Type& object)
|
Chris@16
|
542 {
|
Chris@16
|
543 return domain_less<Type>(upper(object), lower(object));
|
Chris@16
|
544 }
|
Chris@16
|
545
|
Chris@16
|
546 template<class Type>
|
Chris@16
|
547 typename boost::enable_if<is_static_open<Type>, bool>::type
|
Chris@16
|
548 is_empty(const Type& object)
|
Chris@16
|
549 {
|
Chris@16
|
550 return domain_less_equal<Type>(upper(object), lower(object) )
|
Chris@16
|
551 || domain_less_equal<Type>(upper(object), domain_next<Type>(lower(object)));
|
Chris@16
|
552 }
|
Chris@16
|
553
|
Chris@16
|
554 template<class Type>
|
Chris@16
|
555 typename boost::enable_if<is_discrete_interval<Type>, bool>::type
|
Chris@16
|
556 is_empty(const Type& object)
|
Chris@16
|
557 {
|
Chris@16
|
558 if(object.bounds() == interval_bounds::closed())
|
Chris@16
|
559 return domain_less<Type>(upper(object), lower(object));
|
Chris@16
|
560 else if(object.bounds() == interval_bounds::open())
|
Chris@16
|
561 return domain_less_equal<Type>(upper(object), lower(object) )
|
Chris@16
|
562 || domain_less_equal<Type>(upper(object), domain_next<Type>(lower(object)));
|
Chris@16
|
563 else
|
Chris@16
|
564 return domain_less_equal<Type>(upper(object), lower(object));
|
Chris@16
|
565 }
|
Chris@16
|
566
|
Chris@16
|
567 template<class Type>
|
Chris@16
|
568 typename boost::enable_if<is_continuous_interval<Type>, bool>::type
|
Chris@16
|
569 is_empty(const Type& object)
|
Chris@16
|
570 {
|
Chris@16
|
571 return domain_less<Type>(upper(object), lower(object))
|
Chris@16
|
572 || ( domain_equal<Type>(upper(object), lower(object))
|
Chris@16
|
573 && object.bounds() != interval_bounds::closed() );
|
Chris@16
|
574 }
|
Chris@16
|
575
|
Chris@16
|
576 //==============================================================================
|
Chris@16
|
577 //= Orderings, containedness (non empty)
|
Chris@16
|
578 //==============================================================================
|
Chris@16
|
579 namespace non_empty
|
Chris@16
|
580 {
|
Chris@16
|
581
|
Chris@16
|
582 template<class Type>
|
Chris@16
|
583 inline typename boost::enable_if<is_asymmetric_interval<Type>, bool>::type
|
Chris@16
|
584 exclusive_less(const Type& left, const Type& right)
|
Chris@16
|
585 {
|
Chris@16
|
586 BOOST_ASSERT(!(icl::is_empty(left) || icl::is_empty(right)));
|
Chris@16
|
587 return domain_less_equal<Type>(upper(left), lower(right));
|
Chris@16
|
588 }
|
Chris@16
|
589
|
Chris@16
|
590 template<class Type>
|
Chris@16
|
591 inline typename boost::enable_if<is_discrete_interval<Type>, bool>::type
|
Chris@16
|
592 exclusive_less(const Type& left, const Type& right)
|
Chris@16
|
593 {
|
Chris@16
|
594 BOOST_ASSERT(!(icl::is_empty(left) || icl::is_empty(right)));
|
Chris@16
|
595 return domain_less<Type>(last(left), first(right));
|
Chris@16
|
596 }
|
Chris@16
|
597
|
Chris@16
|
598 template<class Type>
|
Chris@16
|
599 inline typename boost::
|
Chris@16
|
600 enable_if<has_symmetric_bounds<Type>, bool>::type
|
Chris@16
|
601 exclusive_less(const Type& left, const Type& right)
|
Chris@16
|
602 {
|
Chris@16
|
603 BOOST_ASSERT(!(icl::is_empty(left) || icl::is_empty(right)));
|
Chris@16
|
604 return domain_less<Type>(last(left), first(right));
|
Chris@16
|
605 }
|
Chris@16
|
606
|
Chris@16
|
607 template<class Type>
|
Chris@16
|
608 inline typename boost::enable_if<is_continuous_interval<Type>, bool>::type
|
Chris@16
|
609 exclusive_less(const Type& left, const Type& right)
|
Chris@16
|
610 {
|
Chris@16
|
611 BOOST_ASSERT(!(icl::is_empty(left) || icl::is_empty(right)));
|
Chris@16
|
612 return domain_less <Type>(upper(left), lower(right))
|
Chris@16
|
613 || ( domain_equal<Type>(upper(left), lower(right))
|
Chris@16
|
614 && inner_bounds(left,right) != interval_bounds::open() );
|
Chris@16
|
615 }
|
Chris@16
|
616
|
Chris@16
|
617 template<class Type>
|
Chris@16
|
618 inline typename boost::enable_if<is_interval<Type>, bool>::type
|
Chris@16
|
619 contains(const Type& super, const Type& sub)
|
Chris@16
|
620 {
|
Chris@16
|
621 return lower_less_equal(super,sub) && upper_less_equal(sub,super);
|
Chris@16
|
622 }
|
Chris@16
|
623
|
Chris@16
|
624
|
Chris@16
|
625 } //namespace non_empty
|
Chris@16
|
626
|
Chris@16
|
627
|
Chris@16
|
628 //- contains -------------------------------------------------------------------
|
Chris@16
|
629 template<class Type>
|
Chris@16
|
630 inline typename boost::enable_if<is_interval<Type>, bool>::type
|
Chris@16
|
631 contains(const Type& super, const Type& sub)
|
Chris@16
|
632 {
|
Chris@16
|
633 return icl::is_empty(sub) || non_empty::contains(super, sub);
|
Chris@16
|
634 }
|
Chris@16
|
635
|
Chris@16
|
636 template<class Type>
|
Chris@16
|
637 typename boost::enable_if<is_discrete_static<Type>, bool>::type
|
Chris@16
|
638 contains(const Type& super, const typename interval_traits<Type>::domain_type& element)
|
Chris@16
|
639 {
|
Chris@16
|
640 return domain_less_equal<Type>(icl::first(super), element )
|
Chris@16
|
641 && domain_less_equal<Type>( element, icl::last(super));
|
Chris@16
|
642 }
|
Chris@16
|
643
|
Chris@16
|
644 template<class Type>
|
Chris@16
|
645 typename boost::enable_if<is_continuous_left_open<Type>, bool>::type
|
Chris@16
|
646 contains(const Type& super, const typename interval_traits<Type>::domain_type& element)
|
Chris@16
|
647 {
|
Chris@16
|
648 return domain_less <Type>(icl::lower(super), element )
|
Chris@16
|
649 && domain_less_equal<Type>( element, icl::upper(super));
|
Chris@16
|
650 }
|
Chris@16
|
651
|
Chris@16
|
652 template<class Type>
|
Chris@16
|
653 typename boost::enable_if<is_continuous_right_open<Type>, bool>::type
|
Chris@16
|
654 contains(const Type& super, const typename interval_traits<Type>::domain_type& element)
|
Chris@16
|
655 {
|
Chris@16
|
656 return domain_less_equal<Type>(icl::lower(super), element )
|
Chris@16
|
657 && domain_less <Type>( element, icl::upper(super));
|
Chris@16
|
658 }
|
Chris@16
|
659
|
Chris@16
|
660 template<class Type>
|
Chris@16
|
661 typename boost::enable_if<has_dynamic_bounds<Type>, bool>::type
|
Chris@16
|
662 contains(const Type& super, const typename interval_traits<Type>::domain_type& element)
|
Chris@16
|
663 {
|
Chris@16
|
664 return
|
Chris@16
|
665 (is_left_closed(super.bounds())
|
Chris@16
|
666 ? domain_less_equal<Type>(lower(super), element)
|
Chris@16
|
667 : domain_less<Type>(lower(super), element))
|
Chris@16
|
668 &&
|
Chris@16
|
669 (is_right_closed(super.bounds())
|
Chris@16
|
670 ? domain_less_equal<Type>(element, upper(super))
|
Chris@16
|
671 : domain_less<Type>(element, upper(super)));
|
Chris@16
|
672 }
|
Chris@16
|
673
|
Chris@16
|
674 //- within ---------------------------------------------------------------------
|
Chris@16
|
675 template<class Type>
|
Chris@16
|
676 inline typename boost::enable_if<is_interval<Type>, bool>::type
|
Chris@16
|
677 within(const Type& sub, const Type& super)
|
Chris@16
|
678 {
|
Chris@16
|
679 return contains(super,sub);
|
Chris@16
|
680 }
|
Chris@16
|
681
|
Chris@16
|
682
|
Chris@16
|
683 //==============================================================================
|
Chris@16
|
684 //= Equivalences and Orderings
|
Chris@16
|
685 //==============================================================================
|
Chris@16
|
686 //- exclusive_less -------------------------------------------------------------
|
Chris@16
|
687 /** Maximal element of <tt>left</tt> is less than the minimal element of
|
Chris@16
|
688 <tt>right</tt> */
|
Chris@16
|
689 template<class Type>
|
Chris@16
|
690 inline typename boost::enable_if<is_asymmetric_interval<Type>, bool>::type
|
Chris@16
|
691 exclusive_less(const Type& left, const Type& right)
|
Chris@16
|
692 {
|
Chris@16
|
693 return icl::is_empty(left) || icl::is_empty(right)
|
Chris@16
|
694 || domain_less_equal<Type>(upper(left), lower(right));
|
Chris@16
|
695 }
|
Chris@16
|
696
|
Chris@16
|
697 template<class Type>
|
Chris@16
|
698 inline typename boost::enable_if<is_discrete_interval<Type>, bool>::type
|
Chris@16
|
699 exclusive_less(const Type& left, const Type& right)
|
Chris@16
|
700 {
|
Chris@16
|
701 return icl::is_empty(left) || icl::is_empty(right)
|
Chris@16
|
702 || domain_less<Type>(last(left), first(right));
|
Chris@16
|
703 }
|
Chris@16
|
704
|
Chris@16
|
705 template<class Type>
|
Chris@16
|
706 inline typename boost::
|
Chris@16
|
707 enable_if<has_symmetric_bounds<Type>, bool>::type
|
Chris@16
|
708 exclusive_less(const Type& left, const Type& right)
|
Chris@16
|
709 {
|
Chris@16
|
710 return icl::is_empty(left) || icl::is_empty(right)
|
Chris@16
|
711 || domain_less<Type>(last(left), first(right));
|
Chris@16
|
712 }
|
Chris@16
|
713
|
Chris@16
|
714 template<class Type>
|
Chris@16
|
715 inline typename boost::enable_if<is_continuous_interval<Type>, bool>::type
|
Chris@16
|
716 exclusive_less(const Type& left, const Type& right)
|
Chris@16
|
717 {
|
Chris@16
|
718 return icl::is_empty(left) || icl::is_empty(right)
|
Chris@16
|
719 || domain_less<Type>(upper(left), lower(right))
|
Chris@16
|
720 || ( domain_equal<Type>(upper(left), lower(right))
|
Chris@16
|
721 && inner_bounds(left,right) != interval_bounds::open() );
|
Chris@16
|
722 }
|
Chris@16
|
723
|
Chris@16
|
724
|
Chris@16
|
725 //------------------------------------------------------------------------------
|
Chris@16
|
726 template<class Type>
|
Chris@16
|
727 typename boost::enable_if<has_static_bounds<Type>, bool>::type
|
Chris@16
|
728 lower_less(const Type& left, const Type& right)
|
Chris@16
|
729 {
|
Chris@16
|
730 return domain_less<Type>(lower(left), lower(right));
|
Chris@16
|
731 }
|
Chris@16
|
732
|
Chris@16
|
733 template<class Type>
|
Chris@16
|
734 typename boost::enable_if<is_discrete_interval<Type>, bool>::type
|
Chris@16
|
735 lower_less(const Type& left, const Type& right)
|
Chris@16
|
736 {
|
Chris@16
|
737 return domain_less<Type>(first(left), first(right));
|
Chris@16
|
738 }
|
Chris@16
|
739
|
Chris@16
|
740 template<class Type>
|
Chris@16
|
741 typename boost::enable_if<is_continuous_interval<Type>, bool>::type
|
Chris@16
|
742 lower_less(const Type& left, const Type& right)
|
Chris@16
|
743 {
|
Chris@16
|
744 if(left_bounds(left,right) == interval_bounds::right_open()) //'[(' == 10
|
Chris@16
|
745 return domain_less_equal<Type>(lower(left), lower(right));
|
Chris@16
|
746 else
|
Chris@16
|
747 return domain_less<Type>(lower(left), lower(right));
|
Chris@16
|
748 }
|
Chris@16
|
749
|
Chris@16
|
750
|
Chris@16
|
751 //------------------------------------------------------------------------------
|
Chris@16
|
752 template<class Type>
|
Chris@16
|
753 typename boost::enable_if<has_static_bounds<Type>, bool>::type
|
Chris@16
|
754 upper_less(const Type& left, const Type& right)
|
Chris@16
|
755 {
|
Chris@16
|
756 return domain_less<Type>(upper(left), upper(right));
|
Chris@16
|
757 }
|
Chris@16
|
758
|
Chris@16
|
759 template<class Type>
|
Chris@16
|
760 typename boost::enable_if<is_discrete_interval<Type>, bool>::type
|
Chris@16
|
761 upper_less(const Type& left, const Type& right)
|
Chris@16
|
762 {
|
Chris@16
|
763 return domain_less<Type>(last(left), last(right));
|
Chris@16
|
764 }
|
Chris@16
|
765
|
Chris@16
|
766 template<class Type>
|
Chris@16
|
767 typename boost::enable_if<is_continuous_interval<Type>, bool>::type
|
Chris@16
|
768 upper_less(const Type& left, const Type& right)
|
Chris@16
|
769 {
|
Chris@16
|
770 if(right_bounds(left,right) == interval_bounds::left_open())
|
Chris@16
|
771 return domain_less_equal<Type>(upper(left), upper(right));
|
Chris@16
|
772 else
|
Chris@16
|
773 return domain_less<Type>(upper(left), upper(right));
|
Chris@16
|
774 }
|
Chris@16
|
775
|
Chris@16
|
776 //------------------------------------------------------------------------------
|
Chris@16
|
777 template<class Type>
|
Chris@16
|
778 typename boost::enable_if<has_dynamic_bounds<Type>,
|
Chris@16
|
779 typename Type::bounded_domain_type >::type
|
Chris@16
|
780 lower_min(const Type& left, const Type& right)
|
Chris@16
|
781 {
|
Chris@16
|
782 return lower_less(left, right) ? bounded_lower(left) : bounded_lower(right);
|
Chris@16
|
783 }
|
Chris@16
|
784
|
Chris@16
|
785 //------------------------------------------------------------------------------
|
Chris@16
|
786 template<class Type>
|
Chris@16
|
787 typename boost::enable_if<has_dynamic_bounds<Type>,
|
Chris@16
|
788 typename Type::bounded_domain_type >::type
|
Chris@16
|
789 lower_max(const Type& left, const Type& right)
|
Chris@16
|
790 {
|
Chris@16
|
791 return lower_less(left, right) ? bounded_lower(right) : bounded_lower(left);
|
Chris@16
|
792 }
|
Chris@16
|
793
|
Chris@16
|
794 //------------------------------------------------------------------------------
|
Chris@16
|
795 template<class Type>
|
Chris@16
|
796 typename boost::enable_if<has_dynamic_bounds<Type>,
|
Chris@16
|
797 typename Type::bounded_domain_type >::type
|
Chris@16
|
798 upper_max(const Type& left, const Type& right)
|
Chris@16
|
799 {
|
Chris@16
|
800 return upper_less(left, right) ? bounded_upper(right) : bounded_upper(left);
|
Chris@16
|
801 }
|
Chris@16
|
802
|
Chris@16
|
803 //------------------------------------------------------------------------------
|
Chris@16
|
804 template<class Type>
|
Chris@16
|
805 typename boost::enable_if<has_dynamic_bounds<Type>,
|
Chris@16
|
806 typename Type::bounded_domain_type >::type
|
Chris@16
|
807 upper_min(const Type& left, const Type& right)
|
Chris@16
|
808 {
|
Chris@16
|
809 return upper_less(left, right) ? bounded_upper(left) : bounded_upper(right);
|
Chris@16
|
810 }
|
Chris@16
|
811
|
Chris@16
|
812
|
Chris@16
|
813 //------------------------------------------------------------------------------
|
Chris@16
|
814 template<class Type>
|
Chris@16
|
815 typename boost::enable_if<is_asymmetric_interval<Type>, bool>::type
|
Chris@16
|
816 lower_equal(const Type& left, const Type& right)
|
Chris@16
|
817 {
|
Chris@16
|
818 return domain_equal<Type>(lower(left), lower(right));
|
Chris@16
|
819 }
|
Chris@16
|
820
|
Chris@16
|
821 template<class Type>
|
Chris@16
|
822 typename boost::enable_if<has_symmetric_bounds<Type>, bool>::type
|
Chris@16
|
823 lower_equal(const Type& left, const Type& right)
|
Chris@16
|
824 {
|
Chris@16
|
825 return domain_equal<Type>(first(left), first(right));
|
Chris@16
|
826 }
|
Chris@16
|
827
|
Chris@16
|
828 template<class Type>
|
Chris@16
|
829 typename boost::enable_if<is_discrete_interval<Type>, bool>::type
|
Chris@16
|
830 lower_equal(const Type& left, const Type& right)
|
Chris@16
|
831 {
|
Chris@16
|
832 return domain_equal<Type>(first(left), first(right));
|
Chris@16
|
833 }
|
Chris@16
|
834
|
Chris@16
|
835 template<class Type>
|
Chris@16
|
836 typename boost::enable_if<is_continuous_interval<Type>, bool>::type
|
Chris@16
|
837 lower_equal(const Type& left, const Type& right)
|
Chris@16
|
838 {
|
Chris@16
|
839 return (left.bounds().left()==right.bounds().left())
|
Chris@16
|
840 && domain_equal<Type>(lower(left), lower(right));
|
Chris@16
|
841 }
|
Chris@16
|
842
|
Chris@16
|
843
|
Chris@16
|
844 //------------------------------------------------------------------------------
|
Chris@16
|
845 template<class Type>
|
Chris@16
|
846 typename boost::enable_if<is_asymmetric_interval<Type>, bool>::type
|
Chris@16
|
847 upper_equal(const Type& left, const Type& right)
|
Chris@16
|
848 {
|
Chris@16
|
849 return domain_equal<Type>(upper(left), upper(right));
|
Chris@16
|
850 }
|
Chris@16
|
851
|
Chris@16
|
852 template<class Type>
|
Chris@16
|
853 typename boost::enable_if<has_symmetric_bounds<Type>, bool>::type
|
Chris@16
|
854 upper_equal(const Type& left, const Type& right)
|
Chris@16
|
855 {
|
Chris@16
|
856 return domain_equal<Type>(last(left), last(right));
|
Chris@16
|
857 }
|
Chris@16
|
858
|
Chris@16
|
859 template<class Type>
|
Chris@16
|
860 typename boost::enable_if<is_discrete_interval<Type>, bool>::type
|
Chris@16
|
861 upper_equal(const Type& left, const Type& right)
|
Chris@16
|
862 {
|
Chris@16
|
863 return domain_equal<Type>(last(left), last(right));
|
Chris@16
|
864 }
|
Chris@16
|
865
|
Chris@16
|
866 template<class Type>
|
Chris@16
|
867 typename boost::enable_if<is_continuous_interval<Type>, bool>::type
|
Chris@16
|
868 upper_equal(const Type& left, const Type& right)
|
Chris@16
|
869 {
|
Chris@16
|
870 return (left.bounds().right()==right.bounds().right())
|
Chris@16
|
871 && domain_equal<Type>(upper(left), upper(right));
|
Chris@16
|
872 }
|
Chris@16
|
873
|
Chris@16
|
874 //------------------------------------------------------------------------------
|
Chris@16
|
875 template<class Type>
|
Chris@16
|
876 typename boost::enable_if<is_interval<Type>, bool>::type
|
Chris@16
|
877 lower_less_equal(const Type& left, const Type& right)
|
Chris@16
|
878 {
|
Chris@16
|
879 return lower_less(left,right) || lower_equal(left,right);
|
Chris@16
|
880 }
|
Chris@16
|
881
|
Chris@16
|
882 template<class Type>
|
Chris@16
|
883 typename boost::enable_if<is_interval<Type>, bool>::type
|
Chris@16
|
884 upper_less_equal(const Type& left, const Type& right)
|
Chris@16
|
885 {
|
Chris@16
|
886 return upper_less(left,right) || upper_equal(left,right);
|
Chris@16
|
887 }
|
Chris@16
|
888
|
Chris@16
|
889
|
Chris@16
|
890 //- operator == ----------------------------------------------------------------
|
Chris@16
|
891 template<class Type>
|
Chris@16
|
892 typename boost::enable_if<is_interval<Type>, bool>::type
|
Chris@16
|
893 operator == (const Type& left, const Type& right)
|
Chris@16
|
894 {
|
Chris@16
|
895 return (icl::is_empty(left) && icl::is_empty(right))
|
Chris@16
|
896 || (lower_equal(left,right) && upper_equal(left,right));
|
Chris@16
|
897 }
|
Chris@16
|
898
|
Chris@16
|
899 template<class Type>
|
Chris@16
|
900 typename boost::enable_if<is_interval<Type>, bool>::type
|
Chris@16
|
901 operator != (const Type& left, const Type& right)
|
Chris@16
|
902 {
|
Chris@16
|
903 return !(left == right);
|
Chris@16
|
904 }
|
Chris@16
|
905
|
Chris@16
|
906 //- operator < -----------------------------------------------------------------
|
Chris@16
|
907 template<class Type>
|
Chris@16
|
908 typename boost::enable_if<is_interval<Type>, bool>::type
|
Chris@16
|
909 operator < (const Type& left, const Type& right)
|
Chris@16
|
910 {
|
Chris@16
|
911 if(icl::is_empty(left))
|
Chris@16
|
912 return !icl::is_empty(right);
|
Chris@16
|
913 else
|
Chris@16
|
914 return lower_less(left,right)
|
Chris@16
|
915 || (lower_equal(left,right) && upper_less(left,right));
|
Chris@16
|
916 }
|
Chris@16
|
917
|
Chris@16
|
918 template<class Type>
|
Chris@16
|
919 inline typename boost::enable_if<is_interval<Type>, bool>::type
|
Chris@16
|
920 operator > (const Type& left, const Type& right)
|
Chris@16
|
921 {
|
Chris@16
|
922 return right < left;
|
Chris@16
|
923 }
|
Chris@16
|
924
|
Chris@16
|
925
|
Chris@16
|
926
|
Chris@16
|
927 //------------------------------------------------------------------------------
|
Chris@16
|
928 template<class Type>
|
Chris@16
|
929 typename boost::enable_if<is_asymmetric_interval<Type>, bool>::type
|
Chris@16
|
930 touches(const Type& left, const Type& right)
|
Chris@16
|
931 {
|
Chris@16
|
932 return domain_equal<Type>(upper(left), lower(right));
|
Chris@16
|
933 }
|
Chris@16
|
934
|
Chris@16
|
935 template<class Type>
|
Chris@16
|
936 typename boost::enable_if<has_symmetric_bounds<Type>, bool>::type
|
Chris@16
|
937 touches(const Type& left, const Type& right)
|
Chris@16
|
938 {
|
Chris@16
|
939 return domain_equal<Type>(last_next(left), first(right));
|
Chris@16
|
940 }
|
Chris@16
|
941
|
Chris@16
|
942 template<class Type>
|
Chris@16
|
943 typename boost::enable_if<is_discrete_interval<Type>, bool>::type
|
Chris@16
|
944 touches(const Type& left, const Type& right)
|
Chris@16
|
945 {
|
Chris@16
|
946 return domain_equal<Type>(domain_next<Type>(last(left)), first(right));
|
Chris@16
|
947 }
|
Chris@16
|
948
|
Chris@16
|
949 template<class Type>
|
Chris@16
|
950 typename boost::enable_if<is_continuous_interval<Type>, bool>::type
|
Chris@16
|
951 touches(const Type& left, const Type& right)
|
Chris@16
|
952 {
|
Chris@16
|
953 return is_complementary(inner_bounds(left,right))
|
Chris@16
|
954 && domain_equal<Type>(upper(left), lower(right));
|
Chris@16
|
955 }
|
Chris@16
|
956
|
Chris@16
|
957
|
Chris@16
|
958 //==============================================================================
|
Chris@16
|
959 //= Size
|
Chris@16
|
960 //==============================================================================
|
Chris@16
|
961 //- cardinality ----------------------------------------------------------------
|
Chris@16
|
962
|
Chris@16
|
963 template<class Type>
|
Chris@16
|
964 typename boost::enable_if<is_continuous_interval<Type>,
|
Chris@16
|
965 typename size_type_of<interval_traits<Type> >::type>::type
|
Chris@16
|
966 cardinality(const Type& object)
|
Chris@16
|
967 {
|
Chris@16
|
968 typedef typename size_type_of<interval_traits<Type> >::type SizeT;
|
Chris@16
|
969 if(icl::is_empty(object))
|
Chris@16
|
970 return icl::identity_element<SizeT>::value();
|
Chris@16
|
971 else if( object.bounds() == interval_bounds::closed()
|
Chris@16
|
972 && domain_equal<Type>(lower(object), upper(object)))
|
Chris@16
|
973 return icl::unit_element<SizeT>::value();
|
Chris@16
|
974 else
|
Chris@16
|
975 return icl::infinity<SizeT>::value();
|
Chris@16
|
976 }
|
Chris@16
|
977
|
Chris@16
|
978 template<class Type>
|
Chris@16
|
979 typename boost::enable_if<is_discrete_interval<Type>,
|
Chris@16
|
980 typename size_type_of<interval_traits<Type> >::type>::type
|
Chris@16
|
981 cardinality(const Type& object)
|
Chris@16
|
982 {
|
Chris@16
|
983 typedef typename size_type_of<interval_traits<Type> >::type SizeT;
|
Chris@16
|
984 return icl::is_empty(object) ? identity_element<SizeT>::value()
|
Chris@16
|
985 : static_cast<SizeT>(last_next(object) - first(object));
|
Chris@16
|
986 }
|
Chris@16
|
987
|
Chris@16
|
988 template<class Type>
|
Chris@16
|
989 typename boost::enable_if<is_continuous_asymmetric<Type>,
|
Chris@16
|
990 typename size_type_of<interval_traits<Type> >::type>::type
|
Chris@16
|
991 cardinality(const Type& object)
|
Chris@16
|
992 {
|
Chris@16
|
993 typedef typename size_type_of<interval_traits<Type> >::type SizeT;
|
Chris@16
|
994 if(icl::is_empty(object))
|
Chris@16
|
995 return icl::identity_element<SizeT>::value();
|
Chris@16
|
996 else
|
Chris@16
|
997 return icl::infinity<SizeT>::value();
|
Chris@16
|
998 }
|
Chris@16
|
999
|
Chris@16
|
1000 template<class Type>
|
Chris@16
|
1001 typename boost::enable_if<is_discrete_asymmetric<Type>,
|
Chris@16
|
1002 typename size_type_of<interval_traits<Type> >::type>::type
|
Chris@16
|
1003 cardinality(const Type& object)
|
Chris@16
|
1004 {
|
Chris@16
|
1005 typedef typename size_type_of<interval_traits<Type> >::type SizeT;
|
Chris@16
|
1006 return icl::is_empty(object) ? identity_element<SizeT>::value()
|
Chris@16
|
1007 : static_cast<SizeT>(last_next(object) - first(object));
|
Chris@16
|
1008 }
|
Chris@16
|
1009
|
Chris@16
|
1010 template<class Type>
|
Chris@16
|
1011 typename boost::enable_if<has_symmetric_bounds<Type>,
|
Chris@16
|
1012 typename size_type_of<interval_traits<Type> >::type>::type
|
Chris@16
|
1013 cardinality(const Type& object)
|
Chris@16
|
1014 {
|
Chris@16
|
1015 typedef typename size_type_of<interval_traits<Type> >::type SizeT;
|
Chris@16
|
1016 return icl::is_empty(object) ? identity_element<SizeT>::value()
|
Chris@16
|
1017 : static_cast<SizeT>(last_next(object) - first(object));
|
Chris@16
|
1018 }
|
Chris@16
|
1019
|
Chris@16
|
1020
|
Chris@16
|
1021
|
Chris@16
|
1022 //- size -----------------------------------------------------------------------
|
Chris@16
|
1023 template<class Type>
|
Chris@16
|
1024 inline typename enable_if<is_interval<Type>,
|
Chris@16
|
1025 typename size_type_of<interval_traits<Type> >::type>::type
|
Chris@16
|
1026 size(const Type& object)
|
Chris@16
|
1027 {
|
Chris@16
|
1028 return cardinality(object);
|
Chris@16
|
1029 }
|
Chris@16
|
1030
|
Chris@16
|
1031 //- length ---------------------------------------------------------------------
|
Chris@16
|
1032 template<class Type>
|
Chris@16
|
1033 inline typename boost::enable_if<is_continuous_interval<Type>,
|
Chris@16
|
1034 typename difference_type_of<interval_traits<Type> >::type>::type
|
Chris@16
|
1035 length(const Type& object)
|
Chris@16
|
1036 {
|
Chris@16
|
1037 typedef typename difference_type_of<interval_traits<Type> >::type DiffT;
|
Chris@16
|
1038 return icl::is_empty(object) ? identity_element<DiffT>::value()
|
Chris@16
|
1039 : upper(object) - lower(object);
|
Chris@16
|
1040 }
|
Chris@16
|
1041
|
Chris@16
|
1042 template<class Type>
|
Chris@16
|
1043 inline typename boost::enable_if<is_discrete_interval<Type>,
|
Chris@16
|
1044 typename difference_type_of<interval_traits<Type> >::type>::type
|
Chris@16
|
1045 length(const Type& object)
|
Chris@16
|
1046 {
|
Chris@16
|
1047 typedef typename difference_type_of<interval_traits<Type> >::type DiffT;
|
Chris@16
|
1048 return icl::is_empty(object) ? identity_element<DiffT>::value()
|
Chris@16
|
1049 : last_next(object) - first(object);
|
Chris@16
|
1050 }
|
Chris@16
|
1051
|
Chris@16
|
1052 template<class Type>
|
Chris@16
|
1053 typename boost::enable_if<is_continuous_asymmetric<Type>,
|
Chris@16
|
1054 typename difference_type_of<interval_traits<Type> >::type>::type
|
Chris@16
|
1055 length(const Type& object)
|
Chris@16
|
1056 {
|
Chris@16
|
1057 typedef typename difference_type_of<interval_traits<Type> >::type DiffT;
|
Chris@16
|
1058 return icl::is_empty(object) ? identity_element<DiffT>::value()
|
Chris@16
|
1059 : upper(object) - lower(object);
|
Chris@16
|
1060 }
|
Chris@16
|
1061
|
Chris@16
|
1062 template<class Type>
|
Chris@16
|
1063 inline typename boost::enable_if<is_discrete_static<Type>,
|
Chris@16
|
1064 typename difference_type_of<interval_traits<Type> >::type>::type
|
Chris@16
|
1065 length(const Type& object)
|
Chris@16
|
1066 {
|
Chris@16
|
1067 typedef typename difference_type_of<interval_traits<Type> >::type DiffT;
|
Chris@16
|
1068 return icl::is_empty(object) ? identity_element<DiffT>::value()
|
Chris@16
|
1069 : last_next(object) - first(object);
|
Chris@16
|
1070 }
|
Chris@16
|
1071
|
Chris@16
|
1072 //- iterative_size -------------------------------------------------------------
|
Chris@16
|
1073 template<class Type>
|
Chris@16
|
1074 inline typename enable_if<is_interval<Type>,
|
Chris@16
|
1075 typename size_type_of<interval_traits<Type> >::type>::type
|
Chris@16
|
1076 iterative_size(const Type&)
|
Chris@16
|
1077 {
|
Chris@16
|
1078 return 2;
|
Chris@16
|
1079 }
|
Chris@16
|
1080
|
Chris@16
|
1081
|
Chris@16
|
1082 //==============================================================================
|
Chris@16
|
1083 //= Addition
|
Chris@16
|
1084 //==============================================================================
|
Chris@16
|
1085 //- hull -----------------------------------------------------------------------
|
Chris@16
|
1086 /** \c hull returns the smallest interval containing \c left and \c right. */
|
Chris@16
|
1087 template<class Type>
|
Chris@16
|
1088 typename boost::enable_if<has_static_bounds<Type>, Type>::type
|
Chris@16
|
1089 hull(Type left, const Type& right)
|
Chris@16
|
1090 {
|
Chris@16
|
1091 typedef typename interval_traits<Type>::domain_compare domain_compare;
|
Chris@16
|
1092
|
Chris@16
|
1093 if(icl::is_empty(right))
|
Chris@16
|
1094 return left;
|
Chris@16
|
1095 else if(icl::is_empty(left))
|
Chris@16
|
1096 return right;
|
Chris@16
|
1097
|
Chris@16
|
1098 return
|
Chris@16
|
1099 construct<Type>
|
Chris@16
|
1100 (
|
Chris@16
|
1101 (std::min)(lower(left), lower(right), domain_compare()),
|
Chris@16
|
1102 (std::max)(upper(left), upper(right), domain_compare())
|
Chris@16
|
1103 );
|
Chris@16
|
1104 }
|
Chris@16
|
1105
|
Chris@16
|
1106 template<class Type>
|
Chris@16
|
1107 typename boost::enable_if<has_dynamic_bounds<Type>, Type>::type
|
Chris@16
|
1108 hull(Type left, const Type& right)
|
Chris@16
|
1109 {
|
Chris@16
|
1110 if(icl::is_empty(right))
|
Chris@16
|
1111 return left;
|
Chris@16
|
1112 else if(icl::is_empty(left))
|
Chris@16
|
1113 return right;
|
Chris@16
|
1114
|
Chris@16
|
1115 return dynamic_interval_traits<Type>::construct_bounded
|
Chris@16
|
1116 (
|
Chris@16
|
1117 lower_min(left, right),
|
Chris@16
|
1118 upper_max(left, right)
|
Chris@16
|
1119 );
|
Chris@16
|
1120 }
|
Chris@16
|
1121
|
Chris@16
|
1122 //==============================================================================
|
Chris@16
|
1123 //= Subtraction
|
Chris@16
|
1124 //==============================================================================
|
Chris@16
|
1125 //- left_subtract --------------------------------------------------------------
|
Chris@16
|
1126 /** subtract \c left_minuend from the \c right interval on it's left side.
|
Chris@16
|
1127 Return the difference: The part of \c right right of \c left_minuend.
|
Chris@16
|
1128 \code
|
Chris@16
|
1129 right_over = right - left_minuend; //on the left.
|
Chris@16
|
1130 ... d) : right
|
Chris@16
|
1131 ... c) : left_minuend
|
Chris@16
|
1132 [c d) : right_over
|
Chris@16
|
1133 \endcode
|
Chris@16
|
1134 */
|
Chris@16
|
1135 template<class Type>
|
Chris@16
|
1136 typename boost::enable_if<is_asymmetric_interval<Type>, Type>::type
|
Chris@16
|
1137 left_subtract(Type right, const Type& left_minuend)
|
Chris@16
|
1138 {
|
Chris@16
|
1139 if(exclusive_less(left_minuend, right))
|
Chris@16
|
1140 return right;
|
Chris@16
|
1141
|
Chris@16
|
1142 return construct<Type>(upper(left_minuend), upper(right));
|
Chris@16
|
1143 }
|
Chris@16
|
1144
|
Chris@16
|
1145 template<class Type>
|
Chris@16
|
1146 typename boost::enable_if<is_static_closed<Type>, Type>::type
|
Chris@16
|
1147 left_subtract(Type right, const Type& left_minuend)
|
Chris@16
|
1148 {
|
Chris@16
|
1149 if(exclusive_less(left_minuend, right))
|
Chris@16
|
1150 return right;
|
Chris@16
|
1151
|
Chris@16
|
1152 return construct<Type>(domain_next<Type>(upper(left_minuend)), upper(right));
|
Chris@16
|
1153 }
|
Chris@16
|
1154
|
Chris@16
|
1155 template<class Type>
|
Chris@16
|
1156 typename boost::enable_if<is_static_open<Type>, Type>::type
|
Chris@16
|
1157 left_subtract(Type right, const Type& left_minuend)
|
Chris@16
|
1158 {
|
Chris@16
|
1159 if(exclusive_less(left_minuend, right))
|
Chris@16
|
1160 return right;
|
Chris@16
|
1161
|
Chris@16
|
1162 return construct<Type>(domain_prior<Type>(upper(left_minuend)), upper(right));
|
Chris@16
|
1163 }
|
Chris@16
|
1164
|
Chris@16
|
1165 template<class Type>
|
Chris@16
|
1166 typename boost::enable_if<has_dynamic_bounds<Type>, Type>::type
|
Chris@16
|
1167 left_subtract(Type right, const Type& left_minuend)
|
Chris@16
|
1168 {
|
Chris@16
|
1169 if(exclusive_less(left_minuend, right))
|
Chris@16
|
1170 return right;
|
Chris@16
|
1171 return dynamic_interval_traits<Type>::construct_bounded
|
Chris@16
|
1172 ( reverse_bounded_upper(left_minuend), bounded_upper(right) );
|
Chris@16
|
1173 }
|
Chris@16
|
1174
|
Chris@16
|
1175
|
Chris@16
|
1176 //- right_subtract -------------------------------------------------------------
|
Chris@16
|
1177 /** subtract \c right_minuend from the \c left interval on it's right side.
|
Chris@16
|
1178 Return the difference: The part of \c left right of \c right_minuend.
|
Chris@16
|
1179 \code
|
Chris@16
|
1180 left_over = left - right_minuend; //on the right side.
|
Chris@16
|
1181 [a ... : left
|
Chris@16
|
1182 [b ... : right_minuend
|
Chris@16
|
1183 [a b) : left_over
|
Chris@16
|
1184 \endcode
|
Chris@16
|
1185 */
|
Chris@16
|
1186 template<class Type>
|
Chris@16
|
1187 typename boost::enable_if<is_asymmetric_interval<Type>, Type>::type
|
Chris@16
|
1188 right_subtract(Type left, const Type& right_minuend)
|
Chris@16
|
1189 {
|
Chris@16
|
1190 if(exclusive_less(left, right_minuend))
|
Chris@16
|
1191 return left;
|
Chris@16
|
1192 return construct<Type>(lower(left), lower(right_minuend));
|
Chris@16
|
1193 }
|
Chris@16
|
1194
|
Chris@16
|
1195 template<class Type>
|
Chris@16
|
1196 typename boost::enable_if<is_static_closed<Type>, Type>::type
|
Chris@16
|
1197 right_subtract(Type left, const Type& right_minuend)
|
Chris@16
|
1198 {
|
Chris@16
|
1199 if(exclusive_less(left, right_minuend))
|
Chris@16
|
1200 return left;
|
Chris@16
|
1201 else if(lower_less_equal(right_minuend, left))
|
Chris@16
|
1202 return identity_element<Type>::value();
|
Chris@16
|
1203
|
Chris@16
|
1204 return construct<Type>(lower(left), domain_prior<Type>(lower(right_minuend)));
|
Chris@16
|
1205 }
|
Chris@16
|
1206
|
Chris@16
|
1207 template<class Type>
|
Chris@16
|
1208 typename boost::enable_if<is_static_open<Type>, Type>::type
|
Chris@16
|
1209 right_subtract(Type left, const Type& right_minuend)
|
Chris@16
|
1210 {
|
Chris@16
|
1211 if(exclusive_less(left, right_minuend))
|
Chris@16
|
1212 return left;
|
Chris@16
|
1213
|
Chris@16
|
1214 return construct<Type>(lower(left), domain_next<Type>(lower(right_minuend)));
|
Chris@16
|
1215 }
|
Chris@16
|
1216
|
Chris@16
|
1217 template<class Type>
|
Chris@16
|
1218 typename boost::enable_if<has_dynamic_bounds<Type>, Type>::type
|
Chris@16
|
1219 right_subtract(Type left, const Type& right_minuend)
|
Chris@16
|
1220 {
|
Chris@16
|
1221 if(exclusive_less(left, right_minuend))
|
Chris@16
|
1222 return left;
|
Chris@16
|
1223
|
Chris@16
|
1224 return dynamic_interval_traits<Type>::construct_bounded
|
Chris@16
|
1225 ( bounded_lower(left), reverse_bounded_lower(right_minuend) );
|
Chris@16
|
1226 }
|
Chris@16
|
1227
|
Chris@16
|
1228 //==============================================================================
|
Chris@16
|
1229 //= Intersection
|
Chris@16
|
1230 //==============================================================================
|
Chris@16
|
1231 //- operator & -----------------------------------------------------------------
|
Chris@16
|
1232 /** Returns the intersection of \c left and \c right interval. */
|
Chris@16
|
1233 template<class Type>
|
Chris@16
|
1234 typename boost::enable_if<is_asymmetric_interval<Type>, Type>::type
|
Chris@16
|
1235 operator & (Type left, const Type& right)
|
Chris@16
|
1236 {
|
Chris@16
|
1237 typedef typename interval_traits<Type>::domain_compare domain_compare;
|
Chris@16
|
1238
|
Chris@16
|
1239 if(icl::is_empty(left) || icl::is_empty(right))
|
Chris@16
|
1240 return identity_element<Type>::value();
|
Chris@16
|
1241 else
|
Chris@16
|
1242 return
|
Chris@16
|
1243 construct<Type>
|
Chris@16
|
1244 (
|
Chris@16
|
1245 (std::max)(icl::lower(left), icl::lower(right), domain_compare()),
|
Chris@16
|
1246 (std::min)(icl::upper(left), icl::upper(right), domain_compare())
|
Chris@16
|
1247 );
|
Chris@16
|
1248 }
|
Chris@16
|
1249
|
Chris@16
|
1250 template<class Type>
|
Chris@16
|
1251 typename boost::enable_if<has_symmetric_bounds<Type>, Type>::type
|
Chris@16
|
1252 operator & (Type left, const Type& right)
|
Chris@16
|
1253 {
|
Chris@16
|
1254 typedef typename interval_traits<Type>::domain_compare domain_compare;
|
Chris@16
|
1255
|
Chris@16
|
1256 if(icl::is_empty(left) || icl::is_empty(right))
|
Chris@16
|
1257 return identity_element<Type>::value();
|
Chris@16
|
1258 else
|
Chris@16
|
1259 return
|
Chris@16
|
1260 construct<Type>
|
Chris@16
|
1261 (
|
Chris@16
|
1262 (std::max)(icl::lower(left), icl::lower(right), domain_compare()),
|
Chris@16
|
1263 (std::min)(icl::upper(left), icl::upper(right), domain_compare())
|
Chris@16
|
1264 );
|
Chris@16
|
1265 }
|
Chris@16
|
1266
|
Chris@16
|
1267 template<class Type>
|
Chris@16
|
1268 typename boost::enable_if<has_dynamic_bounds<Type>, Type>::type
|
Chris@16
|
1269 operator & (Type left, const Type& right)
|
Chris@16
|
1270 {
|
Chris@16
|
1271 if(icl::is_empty(left) || icl::is_empty(right))
|
Chris@16
|
1272 return identity_element<Type>::value();
|
Chris@16
|
1273 else
|
Chris@16
|
1274 return dynamic_interval_traits<Type>::construct_bounded
|
Chris@16
|
1275 (
|
Chris@16
|
1276 lower_max(left, right),
|
Chris@16
|
1277 upper_min(left, right)
|
Chris@16
|
1278 );
|
Chris@16
|
1279 }
|
Chris@16
|
1280
|
Chris@16
|
1281
|
Chris@16
|
1282 //- intersects -----------------------------------------------------------------
|
Chris@16
|
1283 template<class Type>
|
Chris@16
|
1284 typename boost::enable_if<is_interval<Type>, bool>::type
|
Chris@16
|
1285 intersects(const Type& left, const Type& right)
|
Chris@16
|
1286 {
|
Chris@16
|
1287 return !( icl::is_empty(left) || icl::is_empty(right)
|
Chris@16
|
1288 || exclusive_less(left,right) || exclusive_less(right,left));
|
Chris@16
|
1289 }
|
Chris@16
|
1290
|
Chris@16
|
1291 //- disjoint -------------------------------------------------------------------
|
Chris@16
|
1292 template<class Type>
|
Chris@16
|
1293 typename boost::enable_if<is_interval<Type>, bool>::type
|
Chris@16
|
1294 disjoint(const Type& left, const Type& right)
|
Chris@16
|
1295 {
|
Chris@16
|
1296 return icl::is_empty(left) || icl::is_empty(right)
|
Chris@16
|
1297 || exclusive_less(left,right) || exclusive_less(right,left);
|
Chris@16
|
1298 }
|
Chris@16
|
1299
|
Chris@16
|
1300 //==============================================================================
|
Chris@16
|
1301 //= Complement
|
Chris@16
|
1302 //==============================================================================
|
Chris@16
|
1303
|
Chris@16
|
1304 template<class Type>
|
Chris@16
|
1305 typename boost::enable_if<is_asymmetric_interval<Type>, Type>::type
|
Chris@16
|
1306 inner_complement(const Type& left, const Type& right)
|
Chris@16
|
1307 {
|
Chris@16
|
1308 if(icl::is_empty(left) || icl::is_empty(right))
|
Chris@16
|
1309 return identity_element<Type>::value();
|
Chris@16
|
1310 else if(exclusive_less(left, right))
|
Chris@16
|
1311 return construct<Type>(upper(left), lower(right));
|
Chris@16
|
1312 else if(exclusive_less(right, left))
|
Chris@16
|
1313 return construct<Type>(upper(right), lower(left));
|
Chris@16
|
1314 else
|
Chris@16
|
1315 return identity_element<Type>::value();
|
Chris@16
|
1316 }
|
Chris@16
|
1317
|
Chris@16
|
1318 template<class Type>
|
Chris@16
|
1319 typename boost::enable_if<is_discrete_static_closed<Type>, Type>::type
|
Chris@16
|
1320 inner_complement(const Type& left, const Type& right)
|
Chris@16
|
1321 {
|
Chris@16
|
1322 if(icl::is_empty(left) || icl::is_empty(right))
|
Chris@16
|
1323 return identity_element<Type>::value();
|
Chris@16
|
1324 else if(exclusive_less(left, right))
|
Chris@16
|
1325 return construct<Type>(domain_next<Type>(upper(left)), domain_prior<Type>(lower(right)));
|
Chris@16
|
1326 else if(exclusive_less(right, left))
|
Chris@16
|
1327 return construct<Type>(domain_next<Type>(upper(right)), domain_prior<Type>(lower(left)));
|
Chris@16
|
1328 else
|
Chris@16
|
1329 return identity_element<Type>::value();
|
Chris@16
|
1330 }
|
Chris@16
|
1331
|
Chris@16
|
1332 template<class Type>
|
Chris@16
|
1333 typename boost::enable_if<is_discrete_static_open<Type>, Type>::type
|
Chris@16
|
1334 inner_complement(const Type& left, const Type& right)
|
Chris@16
|
1335 {
|
Chris@16
|
1336 if(icl::is_empty(left) || icl::is_empty(right))
|
Chris@16
|
1337 return identity_element<Type>::value();
|
Chris@16
|
1338 else if(exclusive_less(left, right))
|
Chris@16
|
1339 return construct<Type>(last(left), first(right));
|
Chris@16
|
1340 else if(exclusive_less(right, left))
|
Chris@16
|
1341 return construct<Type>(last(right), first(left));
|
Chris@16
|
1342 else
|
Chris@16
|
1343 return identity_element<Type>::value();
|
Chris@16
|
1344 }
|
Chris@16
|
1345
|
Chris@16
|
1346 template<class Type>
|
Chris@16
|
1347 typename boost::enable_if<has_dynamic_bounds<Type>, Type>::type
|
Chris@16
|
1348 inner_complement(const Type& left, const Type& right)
|
Chris@16
|
1349 {
|
Chris@16
|
1350 if(icl::is_empty(left) || icl::is_empty(right))
|
Chris@16
|
1351 return identity_element<Type>::value();
|
Chris@16
|
1352 else if(exclusive_less(left, right))
|
Chris@16
|
1353 return right_subtract(left_subtract(hull(left, right), left), right);
|
Chris@16
|
1354 else if(exclusive_less(right, left))
|
Chris@16
|
1355 return right_subtract(left_subtract(hull(right, left), right), left);
|
Chris@16
|
1356 else
|
Chris@16
|
1357 return identity_element<Type>::value();
|
Chris@16
|
1358 }
|
Chris@16
|
1359
|
Chris@16
|
1360 template<class Type>
|
Chris@16
|
1361 inline typename boost::enable_if<is_interval<Type>, Type>::type
|
Chris@16
|
1362 between(const Type& left, const Type& right)
|
Chris@16
|
1363 {
|
Chris@16
|
1364 return inner_complement(left, right);
|
Chris@16
|
1365 }
|
Chris@16
|
1366
|
Chris@16
|
1367
|
Chris@16
|
1368
|
Chris@16
|
1369 //==============================================================================
|
Chris@16
|
1370 //= Distance
|
Chris@16
|
1371 //==============================================================================
|
Chris@16
|
1372 template<class Type>
|
Chris@16
|
1373 typename boost::
|
Chris@16
|
1374 enable_if< mpl::and_< is_interval<Type>
|
Chris@16
|
1375 , has_difference<typename interval_traits<Type>::domain_type>
|
Chris@16
|
1376 , is_discrete<typename interval_traits<Type>::domain_type>
|
Chris@16
|
1377 >
|
Chris@16
|
1378 , typename difference_type_of<interval_traits<Type> >::type>::type
|
Chris@16
|
1379 distance(const Type& x1, const Type& x2)
|
Chris@16
|
1380 {
|
Chris@16
|
1381 typedef typename difference_type_of<interval_traits<Type> >::type difference_type;
|
Chris@16
|
1382
|
Chris@16
|
1383 if(icl::is_empty(x1) || icl::is_empty(x2))
|
Chris@16
|
1384 return icl::identity_element<difference_type>::value();
|
Chris@16
|
1385 else if(domain_less<Type>(last(x1), first(x2)))
|
Chris@16
|
1386 return static_cast<difference_type>(icl::pred(first(x2) - last(x1)));
|
Chris@16
|
1387 else if(domain_less<Type>(last(x2), first(x1)))
|
Chris@16
|
1388 return static_cast<difference_type>(icl::pred(first(x1) - last(x2)));
|
Chris@16
|
1389 else
|
Chris@16
|
1390 return icl::identity_element<difference_type>::value();
|
Chris@16
|
1391 }
|
Chris@16
|
1392
|
Chris@16
|
1393 template<class Type>
|
Chris@16
|
1394 typename boost::
|
Chris@16
|
1395 enable_if< mpl::and_< is_interval<Type>
|
Chris@16
|
1396 , has_difference<typename interval_traits<Type>::domain_type>
|
Chris@16
|
1397 , is_continuous<typename interval_traits<Type>::domain_type>
|
Chris@16
|
1398 >
|
Chris@16
|
1399 , typename difference_type_of<interval_traits<Type> >::type>::type
|
Chris@16
|
1400 distance(const Type& x1, const Type& x2)
|
Chris@16
|
1401 {
|
Chris@16
|
1402 typedef typename difference_type_of<interval_traits<Type> >::type DiffT;
|
Chris@16
|
1403
|
Chris@16
|
1404 if(icl::is_empty(x1) || icl::is_empty(x2))
|
Chris@16
|
1405 return icl::identity_element<DiffT>::value();
|
Chris@16
|
1406 else if(domain_less<Type>(upper(x1), lower(x2)))
|
Chris@16
|
1407 return lower(x2) - upper(x1);
|
Chris@16
|
1408 else if(domain_less<Type>(upper(x2), lower(x1)))
|
Chris@16
|
1409 return lower(x1) - upper(x2);
|
Chris@16
|
1410 else
|
Chris@16
|
1411 return icl::identity_element<DiffT>::value();
|
Chris@16
|
1412 }
|
Chris@16
|
1413
|
Chris@16
|
1414 //==============================================================================
|
Chris@16
|
1415 //= Streaming, representation
|
Chris@16
|
1416 //==============================================================================
|
Chris@16
|
1417 template<class Type>
|
Chris@16
|
1418 typename boost::
|
Chris@16
|
1419 enable_if< mpl::or_< is_static_left_open<Type>
|
Chris@16
|
1420 , is_static_open<Type> >, std::string>::type
|
Chris@16
|
1421 left_bracket(const Type&) { return "("; }
|
Chris@16
|
1422
|
Chris@16
|
1423 template<class Type>
|
Chris@16
|
1424 typename boost::
|
Chris@16
|
1425 enable_if< mpl::or_< is_static_right_open<Type>
|
Chris@16
|
1426 , is_static_closed<Type> >, std::string>::type
|
Chris@16
|
1427 left_bracket(const Type&) { return "["; }
|
Chris@16
|
1428
|
Chris@16
|
1429 template<class Type>
|
Chris@16
|
1430 typename boost::enable_if<has_dynamic_bounds<Type>, std::string>::type
|
Chris@16
|
1431 left_bracket(const Type& object)
|
Chris@16
|
1432 {
|
Chris@16
|
1433 return left_bracket(object.bounds());
|
Chris@16
|
1434 }
|
Chris@16
|
1435
|
Chris@16
|
1436 //------------------------------------------------------------------------------
|
Chris@16
|
1437 template<class Type>
|
Chris@16
|
1438 typename boost::
|
Chris@16
|
1439 enable_if< mpl::or_< is_static_right_open<Type>
|
Chris@16
|
1440 , is_static_open<Type> >, std::string>::type
|
Chris@16
|
1441 right_bracket(const Type&) { return ")"; }
|
Chris@16
|
1442
|
Chris@16
|
1443 template<class Type>
|
Chris@16
|
1444 typename boost::
|
Chris@16
|
1445 enable_if< mpl::or_< is_static_left_open<Type>
|
Chris@16
|
1446 , is_static_closed<Type> >, std::string>::type
|
Chris@16
|
1447 right_bracket(const Type&) { return "]"; }
|
Chris@16
|
1448
|
Chris@16
|
1449 template<class Type>
|
Chris@16
|
1450 typename boost::enable_if<has_dynamic_bounds<Type>, std::string>::type
|
Chris@16
|
1451 right_bracket(const Type& object)
|
Chris@16
|
1452 {
|
Chris@16
|
1453 return right_bracket(object.bounds());
|
Chris@16
|
1454 }
|
Chris@16
|
1455
|
Chris@16
|
1456 //------------------------------------------------------------------------------
|
Chris@16
|
1457 template<class CharType, class CharTraits, class Type>
|
Chris@16
|
1458 typename boost::enable_if<is_interval<Type>,
|
Chris@16
|
1459 std::basic_ostream<CharType, CharTraits> >::type&
|
Chris@16
|
1460 operator << (std::basic_ostream<CharType, CharTraits> &stream, Type const& object)
|
Chris@16
|
1461 {
|
Chris@16
|
1462 if(boost::icl::is_empty(object))
|
Chris@16
|
1463 return stream << left_bracket<Type>(object) << right_bracket<Type>(object);
|
Chris@16
|
1464 else
|
Chris@16
|
1465 return stream << left_bracket<Type>(object)
|
Chris@16
|
1466 << interval_traits<Type>::lower(object)
|
Chris@16
|
1467 << ","
|
Chris@16
|
1468 << interval_traits<Type>::upper(object)
|
Chris@16
|
1469 << right_bracket<Type>(object) ;
|
Chris@16
|
1470 }
|
Chris@16
|
1471
|
Chris@16
|
1472 }} // namespace icl boost
|
Chris@16
|
1473
|
Chris@16
|
1474 #endif
|
Chris@16
|
1475
|