Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2024-11-15 09:14:05

0001 /*-----------------------------------------------------------------------------+
0002 Copyright (c) 2010-2010: Joachim Faulhaber
0003 +------------------------------------------------------------------------------+
0004    Distributed under the Boost Software License, Version 1.0.
0005       (See accompanying file LICENCE.txt or copy at
0006            http://www.boost.org/LICENSE_1_0.txt)
0007 +-----------------------------------------------------------------------------*/
0008 #ifndef BOOST_ICL_CONCEPT_INTERVAL_HPP_JOFA_100323
0009 #define BOOST_ICL_CONCEPT_INTERVAL_HPP_JOFA_100323
0010 
0011 #include <boost/assert.hpp>
0012 #include <boost/core/ignore_unused.hpp>
0013 #include <boost/utility/enable_if.hpp>
0014 #include <boost/mpl/and.hpp>
0015 #include <boost/mpl/or.hpp>
0016 #include <boost/mpl/not.hpp>
0017 #include <boost/icl/detail/design_config.hpp>
0018 #include <boost/icl/type_traits/unit_element.hpp>
0019 #include <boost/icl/type_traits/identity_element.hpp>
0020 #include <boost/icl/type_traits/infinity.hpp>
0021 #include <boost/icl/type_traits/succ_pred.hpp>
0022 #include <boost/icl/type_traits/is_numeric.hpp>
0023 #include <boost/icl/type_traits/is_discrete.hpp>
0024 #include <boost/icl/type_traits/is_continuous.hpp>
0025 #include <boost/icl/type_traits/is_asymmetric_interval.hpp>
0026 #include <boost/icl/type_traits/is_discrete_interval.hpp>
0027 #include <boost/icl/type_traits/is_continuous_interval.hpp>
0028 
0029 #include <boost/icl/concept/interval_bounds.hpp>
0030 #include <boost/icl/interval_traits.hpp>
0031 #include <boost/icl/dynamic_interval_traits.hpp>
0032 
0033 #include <algorithm>
0034 
0035 namespace boost{namespace icl
0036 {
0037 
0038 //==============================================================================
0039 //= Ordering
0040 //==============================================================================
0041 template<class Type>
0042 inline typename enable_if<is_interval<Type>, bool>::type
0043 domain_less(const typename interval_traits<Type>::domain_type& left,
0044             const typename interval_traits<Type>::domain_type& right)
0045 {
0046     return typename interval_traits<Type>::domain_compare()(left, right);
0047 }
0048 
0049 template<class Type>
0050 inline typename enable_if<is_interval<Type>, bool>::type
0051 domain_less_equal(const typename interval_traits<Type>::domain_type& left,
0052                   const typename interval_traits<Type>::domain_type& right)
0053 {
0054     return !(typename interval_traits<Type>::domain_compare()(right, left));
0055 }
0056 
0057 template<class Type>
0058 inline typename enable_if<is_interval<Type>, bool>::type
0059 domain_equal(const typename interval_traits<Type>::domain_type& left,
0060              const typename interval_traits<Type>::domain_type& right)
0061 {
0062     typedef typename interval_traits<Type>::domain_compare domain_compare;
0063     return !(domain_compare()(left, right)) && !(domain_compare()(right, left));
0064 }
0065 
0066 template<class Type>
0067 inline typename enable_if< is_interval<Type>
0068                          , typename interval_traits<Type>::domain_type>::type
0069 domain_next(const typename interval_traits<Type>::domain_type value)
0070 {
0071     typedef typename interval_traits<Type>::domain_type domain_type;
0072     typedef typename interval_traits<Type>::domain_compare domain_compare;
0073     return icl::successor<domain_type,domain_compare>::apply(value);
0074 }
0075 
0076 template<class Type>
0077 inline typename enable_if< is_interval<Type>
0078                          , typename interval_traits<Type>::domain_type>::type
0079 domain_prior(const typename interval_traits<Type>::domain_type value)
0080 {
0081     typedef typename interval_traits<Type>::domain_type domain_type;
0082     typedef typename interval_traits<Type>::domain_compare domain_compare;
0083     return icl::predecessor<domain_type,domain_compare>::apply(value);
0084 }
0085 
0086 //==============================================================================
0087 //= Construct<Interval> singleton
0088 //==============================================================================
0089 template<class Type>
0090 typename enable_if
0091 <
0092     mpl::and_< is_static_right_open<Type>
0093              , is_discrete<typename interval_traits<Type>::domain_type> >
0094   , Type
0095 >::type
0096 singleton(const typename interval_traits<Type>::domain_type& value)
0097 {
0098     //ASSERT: This always creates an interval with exactly one element
0099     return interval_traits<Type>::construct(value, domain_next<Type>(value));
0100 }
0101 
0102 template<class Type>
0103 typename enable_if
0104 <
0105     mpl::and_< is_static_left_open<Type>
0106              , is_discrete<typename interval_traits<Type>::domain_type> >
0107   , Type
0108 >::type
0109 singleton(const typename interval_traits<Type>::domain_type& value)
0110 {
0111     //ASSERT: This always creates an interval with exactly one element
0112     typedef typename interval_traits<Type>::domain_type    domain_type;
0113     typedef typename interval_traits<Type>::domain_compare domain_compare;
0114     BOOST_ASSERT((numeric_minimum<domain_type, domain_compare, is_numeric<domain_type>::value>
0115                                  ::is_less_than(value) ));
0116     boost::ignore_unused<domain_type, domain_compare>();
0117 
0118     return interval_traits<Type>::construct(domain_prior<Type>(value), value);
0119 }
0120 
0121 template<class Type>
0122 typename enable_if<is_discrete_static_open<Type>, Type>::type
0123 singleton(const typename interval_traits<Type>::domain_type& value)
0124 {
0125     //ASSERT: This always creates an interval with exactly one element
0126     typedef typename interval_traits<Type>::domain_type    domain_type;
0127     typedef typename interval_traits<Type>::domain_compare domain_compare;
0128     BOOST_ASSERT((numeric_minimum<domain_type, domain_compare, is_numeric<domain_type>::value>
0129                                  ::is_less_than(value)));
0130     boost::ignore_unused<domain_type, domain_compare>();
0131 
0132     return interval_traits<Type>::construct( domain_prior<Type>(value)
0133                                            , domain_next<Type>(value));
0134 }
0135 
0136 template<class Type>
0137 typename enable_if<is_discrete_static_closed<Type>, Type>::type
0138 singleton(const typename interval_traits<Type>::domain_type& value)
0139 {
0140     //ASSERT: This always creates an interval with exactly one element
0141     return interval_traits<Type>::construct(value, value);
0142 }
0143 
0144 template<class Type>
0145 typename enable_if<has_dynamic_bounds<Type>, Type>::type
0146 singleton(const typename interval_traits<Type>::domain_type& value)
0147 {
0148     return dynamic_interval_traits<Type>::construct(value, value, interval_bounds::closed());
0149 }
0150 
0151 namespace detail
0152 {
0153 
0154 //==============================================================================
0155 //= Construct<Interval> unit_trail == generalized singleton
0156 // The smallest interval on an incrementable (and decrementable) type that can
0157 // be constructed using ++ and -- and such that it contains a given value.
0158 // If 'Type' is discrete, 'unit_trail' and 'singleton' are identical. So we
0159 // can view 'unit_trail' as a generalized singleton for static intervals of
0160 // continuous types.
0161 //==============================================================================
0162 template<class Type>
0163 typename enable_if
0164 <
0165     mpl::and_< is_static_right_open<Type>
0166              , boost::detail::is_incrementable<typename interval_traits<Type>::domain_type> >
0167   , Type
0168 >::type
0169 unit_trail(const typename interval_traits<Type>::domain_type& value)
0170 {
0171     return interval_traits<Type>::construct(value, domain_next<Type>(value));
0172 }
0173 
0174 template<class Type>
0175 typename enable_if
0176 <
0177     mpl::and_< is_static_left_open<Type>
0178              , boost::detail::is_incrementable<typename interval_traits<Type>::domain_type> >
0179   , Type
0180 >::type
0181 unit_trail(const typename interval_traits<Type>::domain_type& value)
0182 {
0183     typedef typename interval_traits<Type>::domain_type    domain_type;
0184     typedef typename interval_traits<Type>::domain_compare domain_compare;
0185     BOOST_ASSERT((numeric_minimum<domain_type, domain_compare, is_numeric<domain_type>::value>
0186                                  ::is_less_than(value) ));
0187     boost::ignore_unused<domain_type, domain_compare>();
0188 
0189     return interval_traits<Type>::construct(domain_prior<Type>(value), value);
0190 }
0191 
0192 template<class Type>
0193 typename enable_if
0194 <
0195     mpl::and_< is_static_open<Type>
0196              , is_discrete<typename interval_traits<Type>::domain_type> >
0197   , Type
0198 >::type
0199 unit_trail(const typename interval_traits<Type>::domain_type& value)
0200 {
0201     typedef typename interval_traits<Type>::domain_type    domain_type;
0202     typedef typename interval_traits<Type>::domain_compare domain_compare;
0203     BOOST_ASSERT((numeric_minimum<domain_type, domain_compare, is_numeric<domain_type>::value>
0204                                  ::is_less_than(value)));
0205     boost::ignore_unused<domain_type, domain_compare>();
0206 
0207     return interval_traits<Type>::construct( domain_prior<Type>(value)
0208                                            ,  domain_next<Type>(value));
0209 }
0210 
0211 template<class Type>
0212 typename enable_if
0213 <
0214     mpl::and_< is_static_closed<Type>
0215              , is_discrete<typename interval_traits<Type>::domain_type> >
0216   , Type
0217 >::type
0218 unit_trail(const typename interval_traits<Type>::domain_type& value)
0219 {
0220     return interval_traits<Type>::construct(value, value);
0221 }
0222 
0223 //NOTE: statically bounded closed or open intervals of continuous domain types
0224 // are NOT supported by ICL. They can not be used with interval containers
0225 // consistently.
0226 
0227 
0228 template<class Type>
0229 typename enable_if<has_dynamic_bounds<Type>, Type>::type
0230 unit_trail(const typename interval_traits<Type>::domain_type& value)
0231 {
0232     return dynamic_interval_traits<Type>::construct(value, value, interval_bounds::closed());
0233 }
0234 
0235 } //namespace detail
0236 
0237 //==============================================================================
0238 //= Construct<Interval> multon
0239 //==============================================================================
0240 template<class Type>
0241 typename enable_if<has_static_bounds<Type>, Type>::type
0242 construct(const typename interval_traits<Type>::domain_type& low,
0243           const typename interval_traits<Type>::domain_type& up  )
0244 {
0245     return interval_traits<Type>::construct(low, up);
0246 }
0247 
0248 template<class Type>
0249 typename enable_if<has_dynamic_bounds<Type>, Type>::type
0250 construct(const typename interval_traits<Type>::domain_type& low,
0251           const typename interval_traits<Type>::domain_type& up,
0252           interval_bounds bounds = interval_bounds::right_open())
0253 {
0254     return dynamic_interval_traits<Type>::construct(low, up, bounds);
0255 }
0256 
0257 
0258 //- construct form bounded values ----------------------------------------------
0259 template<class Type>
0260 typename enable_if<has_dynamic_bounds<Type>, Type>::type
0261 construct(const typename Type::bounded_domain_type& low,
0262           const typename Type::bounded_domain_type& up)
0263 {
0264     return dynamic_interval_traits<Type>::construct_bounded(low, up);
0265 }
0266 
0267 template<class Type>
0268 typename enable_if<is_interval<Type>, Type>::type
0269 span(const typename interval_traits<Type>::domain_type& left,
0270      const typename interval_traits<Type>::domain_type& right)
0271 {
0272     typedef typename interval_traits<Type>::domain_compare domain_compare;
0273     if(domain_compare()(left,right))
0274         return construct<Type>(left, right);
0275     else
0276         return construct<Type>(right, left);
0277 }
0278 
0279 
0280 //==============================================================================
0281 template<class Type>
0282 typename enable_if<is_static_right_open<Type>, Type>::type
0283 hull(const typename interval_traits<Type>::domain_type& left,
0284      const typename interval_traits<Type>::domain_type& right)
0285 {
0286     typedef typename interval_traits<Type>::domain_compare domain_compare;
0287     if(domain_compare()(left,right))
0288         return construct<Type>(left, domain_next<Type>(right));
0289     else
0290         return construct<Type>(right, domain_next<Type>(left));
0291 }
0292 
0293 template<class Type>
0294 typename enable_if<is_static_left_open<Type>, Type>::type
0295 hull(const typename interval_traits<Type>::domain_type& left,
0296      const typename interval_traits<Type>::domain_type& right)
0297 {
0298     typedef typename interval_traits<Type>::domain_type    domain_type;
0299     typedef typename interval_traits<Type>::domain_compare domain_compare;
0300     boost::ignore_unused<domain_type>();
0301 
0302     if(domain_compare()(left,right))
0303     {
0304         BOOST_ASSERT((numeric_minimum<domain_type, domain_compare, is_numeric<domain_type>::value>
0305                                      ::is_less_than(left) ));
0306         return construct<Type>(domain_prior<Type>(left), right);
0307     }
0308     else
0309     {
0310         BOOST_ASSERT((numeric_minimum<domain_type, domain_compare, is_numeric<domain_type>::value>
0311                                      ::is_less_than(right) ));
0312         return construct<Type>(domain_prior<Type>(right), left);
0313     }
0314 }
0315 
0316 template<class Type>
0317 typename enable_if<is_static_closed<Type>, Type>::type
0318 hull(const typename interval_traits<Type>::domain_type& left,
0319      const typename interval_traits<Type>::domain_type& right)
0320 {
0321     typedef typename interval_traits<Type>::domain_compare domain_compare;
0322     if(domain_compare()(left,right))
0323         return construct<Type>(left, right);
0324     else
0325         return construct<Type>(right, left);
0326 }
0327 
0328 template<class Type>
0329 typename enable_if<is_static_open<Type>, Type>::type
0330 hull(const typename interval_traits<Type>::domain_type& left,
0331      const typename interval_traits<Type>::domain_type& right)
0332 {
0333     typedef typename interval_traits<Type>::domain_type    domain_type;
0334     typedef typename interval_traits<Type>::domain_compare domain_compare;
0335     boost::ignore_unused<domain_type>();
0336 
0337     if(domain_compare()(left,right))
0338     {
0339         BOOST_ASSERT((numeric_minimum<domain_type, domain_compare, is_numeric<domain_type>::value>
0340                                      ::is_less_than(left) ));
0341         return construct<Type>( domain_prior<Type>(left)
0342                               ,  domain_next<Type>(right));
0343     }
0344     else
0345     {
0346         BOOST_ASSERT((numeric_minimum<domain_type, domain_compare, is_numeric<domain_type>::value>
0347                                      ::is_less_than(right) ));
0348         return construct<Type>( domain_prior<Type>(right)
0349                               ,  domain_next<Type>(left));
0350     }
0351 }
0352 
0353 template<class Type>
0354 typename enable_if<has_dynamic_bounds<Type>, Type>::type
0355 hull(const typename interval_traits<Type>::domain_type& left,
0356      const typename interval_traits<Type>::domain_type& right)
0357 {
0358     typedef typename interval_traits<Type>::domain_compare domain_compare;
0359     if(domain_compare()(left,right))
0360         return construct<Type>(left, right, interval_bounds::closed());
0361     else
0362         return construct<Type>(right, left, interval_bounds::closed());
0363 }
0364 
0365 //==============================================================================
0366 //= Selection
0367 //==============================================================================
0368 
0369 template<class Type>
0370 inline typename enable_if<is_interval<Type>,
0371                           typename interval_traits<Type>::domain_type>::type
0372 lower(const Type& object)
0373 {
0374     return interval_traits<Type>::lower(object);
0375 }
0376 
0377 template<class Type>
0378 inline typename enable_if<is_interval<Type>,
0379                           typename interval_traits<Type>::domain_type>::type
0380 upper(const Type& object)
0381 {
0382     return interval_traits<Type>::upper(object);
0383 }
0384 
0385 
0386 //- first ----------------------------------------------------------------------
0387 template<class Type>
0388 inline typename
0389 enable_if< mpl::or_<is_static_right_open<Type>, is_static_closed<Type> >
0390          , typename interval_traits<Type>::domain_type>::type
0391 first(const Type& object)
0392 {
0393     return lower(object);
0394 }
0395 
0396 template<class Type>
0397 inline typename
0398 enable_if< mpl::and_< mpl::or_<is_static_left_open<Type>, is_static_open<Type> >
0399                     , is_discrete<typename interval_traits<Type>::domain_type> >
0400          , typename interval_traits<Type>::domain_type>::type
0401 first(const Type& object)
0402 {
0403     return domain_next<Type>(lower(object));
0404 }
0405 
0406 template<class Type>
0407 inline typename enable_if<is_discrete_interval<Type>,
0408                           typename interval_traits<Type>::domain_type>::type
0409 first(const Type& object)
0410 {
0411     return is_left_closed(object.bounds()) ?
0412                                  lower(object) :
0413                domain_next<Type>(lower(object));
0414 }
0415 
0416 //- last -----------------------------------------------------------------------
0417 template<class Type>
0418 inline typename
0419 enable_if< mpl::or_<is_static_left_open<Type>, is_static_closed<Type> >
0420          , typename interval_traits<Type>::domain_type>::type
0421 last(const Type& object)
0422 {
0423     return upper(object);
0424 }
0425 
0426 template<class Type>
0427 inline typename
0428 enable_if< mpl::and_< mpl::or_<is_static_right_open<Type>, is_static_open<Type> >
0429                     , is_discrete<typename interval_traits<Type>::domain_type>  >
0430          , typename interval_traits<Type>::domain_type>::type
0431 last(const Type& object)
0432 {
0433     typedef typename interval_traits<Type>::domain_type    domain_type;
0434     typedef typename interval_traits<Type>::domain_compare domain_compare;
0435     BOOST_ASSERT((numeric_minimum<domain_type, domain_compare, is_numeric<domain_type>::value>
0436                                  ::is_less_than(upper(object)) ));
0437     boost::ignore_unused<domain_type, domain_compare>();
0438 
0439     return domain_prior<Type>(upper(object));
0440 }
0441 
0442 template<class Type>
0443 inline typename enable_if<is_discrete_interval<Type>,
0444                           typename interval_traits<Type>::domain_type>::type
0445 last(const Type& object)
0446 {
0447     typedef typename interval_traits<Type>::domain_type    domain_type;
0448     typedef typename interval_traits<Type>::domain_compare domain_compare;
0449     BOOST_ASSERT((numeric_minimum<domain_type, domain_compare, is_numeric<domain_type>::value>
0450                                  ::is_less_than_or(upper(object), is_right_closed(object.bounds())) ));
0451     boost::ignore_unused<domain_type, domain_compare>();
0452 
0453     return is_right_closed(object.bounds()) ?
0454                                   upper(object) :
0455                domain_prior<Type>(upper(object));
0456 }
0457 
0458 //- last_next ------------------------------------------------------------------
0459 template<class Type>
0460 inline typename
0461 enable_if< mpl::and_< mpl::or_<is_static_left_open<Type>, is_static_closed<Type> >
0462                     , is_discrete<typename interval_traits<Type>::domain_type>  >
0463          , typename interval_traits<Type>::domain_type>::type
0464 last_next(const Type& object)
0465 {
0466     return domain_next<Type>(upper(object));
0467 }
0468 
0469 template<class Type>
0470 inline typename
0471 enable_if< mpl::and_< mpl::or_<is_static_right_open<Type>, is_static_open<Type> >
0472                     , is_discrete<typename interval_traits<Type>::domain_type>  >
0473          , typename interval_traits<Type>::domain_type>::type
0474 last_next(const Type& object)
0475 {
0476     //CL typedef typename interval_traits<Type>::domain_type domain_type;
0477     return upper(object); // NOTE: last_next is implemented to avoid calling pred(object)
0478 }                         // For unsigned integral types this may cause underflow.
0479 
0480 template<class Type>
0481 inline typename enable_if<is_discrete_interval<Type>,
0482                           typename interval_traits<Type>::domain_type>::type
0483 last_next(const Type& object)
0484 {
0485     return is_right_closed(object.bounds()) ?
0486                domain_next<Type>(upper(object)):
0487                                  upper(object) ;
0488 }
0489 
0490 //------------------------------------------------------------------------------
0491 template<class Type>
0492 typename enable_if<has_dynamic_bounds<Type>,
0493                    typename Type::bounded_domain_type>::type
0494 bounded_lower(const Type& object)
0495 {
0496     return typename
0497         Type::bounded_domain_type(lower(object), object.bounds().left());
0498 }
0499 
0500 template<class Type>
0501 typename enable_if<has_dynamic_bounds<Type>,
0502                    typename Type::bounded_domain_type>::type
0503 reverse_bounded_lower(const Type& object)
0504 {
0505     return typename
0506         Type::bounded_domain_type(lower(object),
0507                                   object.bounds().reverse_left());
0508 }
0509 
0510 template<class Type>
0511 typename enable_if<has_dynamic_bounds<Type>,
0512                    typename Type::bounded_domain_type>::type
0513 bounded_upper(const Type& object)
0514 {
0515     return typename
0516         Type::bounded_domain_type(upper(object),
0517                                   object.bounds().right());
0518 }
0519 
0520 template<class Type>
0521 typename enable_if<has_dynamic_bounds<Type>,
0522                    typename Type::bounded_domain_type>::type
0523 reverse_bounded_upper(const Type& object)
0524 {
0525     return typename
0526         Type::bounded_domain_type(upper(object),
0527                                   object.bounds().reverse_right());
0528 }
0529 
0530 //- bounds ---------------------------------------------------------------------
0531 template<class Type>
0532 inline typename enable_if<has_dynamic_bounds<Type>, interval_bounds>::type
0533 bounds(const Type& object)
0534 {
0535     return object.bounds();
0536 }
0537 
0538 template<class Type>
0539 inline typename enable_if<has_static_bounds<Type>, interval_bounds>::type
0540 bounds(const Type&)
0541 {
0542     return interval_bounds(interval_bound_type<Type>::value);
0543 }
0544 
0545 
0546 //==============================================================================
0547 //= Emptieness
0548 //==============================================================================
0549 /** Is the interval empty? */
0550 template<class Type>
0551 typename boost::enable_if<is_asymmetric_interval<Type>, bool>::type
0552 is_empty(const Type& object)
0553 {
0554     return domain_less_equal<Type>(upper(object), lower(object));
0555 }
0556 
0557 template<class Type>
0558 typename boost::enable_if<is_static_closed<Type>, bool>::type
0559 is_empty(const Type& object)
0560 {
0561     return domain_less<Type>(upper(object), lower(object));
0562 }
0563 
0564 template<class Type>
0565 typename boost::enable_if<is_static_open<Type>, bool>::type
0566 is_empty(const Type& object)
0567 {
0568     return domain_less_equal<Type>(upper(object),                   lower(object) )
0569         || domain_less_equal<Type>(upper(object), domain_next<Type>(lower(object)));
0570 }
0571 
0572 template<class Type>
0573 typename boost::enable_if<is_discrete_interval<Type>, bool>::type
0574 is_empty(const Type& object)
0575 {
0576     if(object.bounds() == interval_bounds::closed())
0577         return domain_less<Type>(upper(object), lower(object));
0578     else if(object.bounds() == interval_bounds::open())
0579         return domain_less_equal<Type>(upper(object),                   lower(object) )
0580             || domain_less_equal<Type>(upper(object), domain_next<Type>(lower(object)));
0581     else
0582         return domain_less_equal<Type>(upper(object), lower(object));
0583 }
0584 
0585 template<class Type>
0586 typename boost::enable_if<is_continuous_interval<Type>, bool>::type
0587 is_empty(const Type& object)
0588 {
0589     return     domain_less<Type>(upper(object), lower(object))
0590         || (   domain_equal<Type>(upper(object), lower(object))
0591             && object.bounds() != interval_bounds::closed()    );
0592 }
0593 
0594 //==============================================================================
0595 //= Equivalences and Orderings
0596 //==============================================================================
0597 //- exclusive_less -------------------------------------------------------------
0598 /** Maximal element of <tt>left</tt> is less than the minimal element of
0599     <tt>right</tt> */
0600 template<class Type>
0601 inline typename boost::enable_if<is_asymmetric_interval<Type>, bool>::type
0602 exclusive_less(const Type& left, const Type& right)
0603 {
0604     return icl::is_empty(left) || icl::is_empty(right)
0605         || domain_less_equal<Type>(upper(left), lower(right));
0606 }
0607 
0608 template<class Type>
0609 inline typename boost::enable_if<is_discrete_interval<Type>, bool>::type
0610 exclusive_less(const Type& left, const Type& right)
0611 {
0612     return icl::is_empty(left) || icl::is_empty(right)
0613         || domain_less<Type>(last(left), first(right));
0614 }
0615 
0616 template<class Type>
0617 inline typename boost::
0618 enable_if<has_symmetric_bounds<Type>, bool>::type
0619 exclusive_less(const Type& left, const Type& right)
0620 {
0621     return icl::is_empty(left) || icl::is_empty(right)
0622         || domain_less<Type>(last(left), first(right));
0623 }
0624 
0625 template<class Type>
0626 inline typename boost::enable_if<is_continuous_interval<Type>, bool>::type
0627 exclusive_less(const Type& left, const Type& right)
0628 {
0629     return     icl::is_empty(left) || icl::is_empty(right)
0630         ||     domain_less<Type>(upper(left), lower(right))
0631         || (   domain_equal<Type>(upper(left), lower(right))
0632             && inner_bounds(left,right) != interval_bounds::open() );
0633 }
0634 
0635 
0636 //------------------------------------------------------------------------------
0637 template<class Type>
0638 typename boost::enable_if<has_static_bounds<Type>, bool>::type
0639 lower_less(const Type& left, const Type& right)
0640 {
0641     return domain_less<Type>(lower(left), lower(right));
0642 }
0643 
0644 template<class Type>
0645 typename boost::enable_if<is_discrete_interval<Type>, bool>::type
0646 lower_less(const Type& left, const Type& right)
0647 {
0648     return domain_less<Type>(first(left), first(right));
0649 }
0650 
0651 template<class Type>
0652 typename boost::enable_if<is_continuous_interval<Type>, bool>::type
0653 lower_less(const Type& left, const Type& right)
0654 {
0655     if(left_bounds(left,right) == interval_bounds::right_open())  //'[(' == 10
0656         return domain_less_equal<Type>(lower(left), lower(right));
0657     else
0658         return domain_less<Type>(lower(left), lower(right));
0659 }
0660 
0661 
0662 //------------------------------------------------------------------------------
0663 template<class Type>
0664 typename boost::enable_if<has_static_bounds<Type>, bool>::type
0665 upper_less(const Type& left, const Type& right)
0666 {
0667     return domain_less<Type>(upper(left), upper(right));
0668 }
0669 
0670 template<class Type>
0671 typename boost::enable_if<is_discrete_interval<Type>, bool>::type
0672 upper_less(const Type& left, const Type& right)
0673 {
0674     return domain_less<Type>(last(left), last(right));
0675 }
0676 
0677 template<class Type>
0678 typename boost::enable_if<is_continuous_interval<Type>, bool>::type
0679 upper_less(const Type& left, const Type& right)
0680 {
0681     if(right_bounds(left,right) == interval_bounds::left_open())
0682         return domain_less_equal<Type>(upper(left), upper(right));
0683     else
0684         return domain_less<Type>(upper(left), upper(right));
0685 }
0686 
0687 //------------------------------------------------------------------------------
0688 template<class Type>
0689 typename boost::enable_if<has_dynamic_bounds<Type>,
0690                           typename Type::bounded_domain_type   >::type
0691 lower_min(const Type& left, const Type& right)
0692 {
0693     return lower_less(left, right) ? bounded_lower(left) : bounded_lower(right);
0694 }
0695 
0696 //------------------------------------------------------------------------------
0697 template<class Type>
0698 typename boost::enable_if<has_dynamic_bounds<Type>,
0699                           typename Type::bounded_domain_type   >::type
0700 lower_max(const Type& left, const Type& right)
0701 {
0702     return lower_less(left, right) ? bounded_lower(right) : bounded_lower(left);
0703 }
0704 
0705 //------------------------------------------------------------------------------
0706 template<class Type>
0707 typename boost::enable_if<has_dynamic_bounds<Type>,
0708                           typename Type::bounded_domain_type   >::type
0709 upper_max(const Type& left, const Type& right)
0710 {
0711     return upper_less(left, right) ? bounded_upper(right) : bounded_upper(left);
0712 }
0713 
0714 //------------------------------------------------------------------------------
0715 template<class Type>
0716 typename boost::enable_if<has_dynamic_bounds<Type>,
0717                           typename Type::bounded_domain_type   >::type
0718 upper_min(const Type& left, const Type& right)
0719 {
0720     return upper_less(left, right) ? bounded_upper(left) : bounded_upper(right);
0721 }
0722 
0723 
0724 //------------------------------------------------------------------------------
0725 template<class Type>
0726 typename boost::enable_if<is_asymmetric_interval<Type>, bool>::type
0727 lower_equal(const Type& left, const Type& right)
0728 {
0729     return domain_equal<Type>(lower(left), lower(right));
0730 }
0731 
0732 template<class Type>
0733 typename boost::enable_if<has_symmetric_bounds<Type>, bool>::type
0734 lower_equal(const Type& left, const Type& right)
0735 {
0736     return domain_equal<Type>(first(left), first(right));
0737 }
0738 
0739 template<class Type>
0740 typename boost::enable_if<is_discrete_interval<Type>, bool>::type
0741 lower_equal(const Type& left, const Type& right)
0742 {
0743     return domain_equal<Type>(first(left), first(right));
0744 }
0745 
0746 template<class Type>
0747 typename boost::enable_if<is_continuous_interval<Type>, bool>::type
0748 lower_equal(const Type& left, const Type& right)
0749 {
0750     return (left.bounds().left()==right.bounds().left())
0751         && domain_equal<Type>(lower(left), lower(right));
0752 }
0753 
0754 
0755 //------------------------------------------------------------------------------
0756 template<class Type>
0757 typename boost::enable_if<is_asymmetric_interval<Type>, bool>::type
0758 upper_equal(const Type& left, const Type& right)
0759 {
0760     return domain_equal<Type>(upper(left), upper(right));
0761 }
0762 
0763 template<class Type>
0764 typename boost::enable_if<has_symmetric_bounds<Type>, bool>::type
0765 upper_equal(const Type& left, const Type& right)
0766 {
0767     return domain_equal<Type>(last(left), last(right));
0768 }
0769 
0770 template<class Type>
0771 typename boost::enable_if<is_discrete_interval<Type>, bool>::type
0772 upper_equal(const Type& left, const Type& right)
0773 {
0774     return domain_equal<Type>(last(left), last(right));
0775 }
0776 
0777 template<class Type>
0778 typename boost::enable_if<is_continuous_interval<Type>, bool>::type
0779 upper_equal(const Type& left, const Type& right)
0780 {
0781     return (left.bounds().right()==right.bounds().right())
0782         && domain_equal<Type>(upper(left), upper(right));
0783 }
0784 
0785 //------------------------------------------------------------------------------
0786 template<class Type>
0787 typename boost::enable_if<is_interval<Type>, bool>::type
0788 lower_less_equal(const Type& left, const Type& right)
0789 {
0790     return lower_less(left,right) || lower_equal(left,right);
0791 }
0792 
0793 template<class Type>
0794 typename boost::enable_if<is_interval<Type>, bool>::type
0795 upper_less_equal(const Type& left, const Type& right)
0796 {
0797     return upper_less(left,right) || upper_equal(left,right);
0798 }
0799 
0800 //==============================================================================
0801 //= Orderings, containedness (non empty)
0802 //==============================================================================
0803 namespace non_empty
0804 {
0805 
0806     template<class Type>
0807     inline typename boost::enable_if<is_asymmetric_interval<Type>, bool>::type
0808     exclusive_less(const Type& left, const Type& right)
0809     {
0810         BOOST_ASSERT(!(icl::is_empty(left) || icl::is_empty(right)));
0811         return domain_less_equal<Type>(upper(left), lower(right));
0812     }
0813 
0814     template<class Type>
0815     inline typename boost::enable_if<is_discrete_interval<Type>, bool>::type
0816     exclusive_less(const Type& left, const Type& right)
0817     {
0818         BOOST_ASSERT(!(icl::is_empty(left) || icl::is_empty(right)));
0819         return domain_less<Type>(last(left), first(right));
0820     }
0821 
0822     template<class Type>
0823     inline typename boost::
0824     enable_if<has_symmetric_bounds<Type>, bool>::type
0825     exclusive_less(const Type& left, const Type& right)
0826     {
0827         BOOST_ASSERT(!(icl::is_empty(left) || icl::is_empty(right)));
0828         return domain_less<Type>(last(left), first(right));
0829     }
0830 
0831     template<class Type>
0832     inline typename boost::enable_if<is_continuous_interval<Type>, bool>::type
0833     exclusive_less(const Type& left, const Type& right)
0834     {
0835         BOOST_ASSERT(!(icl::is_empty(left) || icl::is_empty(right)));
0836         return     domain_less <Type>(upper(left), lower(right))
0837             || (   domain_equal<Type>(upper(left), lower(right))
0838                 && inner_bounds(left,right) != interval_bounds::open() );
0839     }
0840 
0841     template<class Type>
0842     inline typename boost::enable_if<is_interval<Type>, bool>::type
0843     contains(const Type& super, const Type& sub)
0844     {
0845         return lower_less_equal(super,sub) && upper_less_equal(sub,super);
0846     }
0847 
0848 } //namespace non_empty
0849 
0850 //- contains -------------------------------------------------------------------
0851 template<class Type>
0852 inline typename boost::enable_if<is_interval<Type>, bool>::type
0853 contains(const Type& super, const Type& sub)
0854 {
0855     return icl::is_empty(sub) || non_empty::contains(super, sub);
0856 }
0857 
0858 template<class Type>
0859 typename boost::enable_if<is_discrete_static<Type>, bool>::type
0860 contains(const Type& super, const typename interval_traits<Type>::domain_type& element)
0861 {
0862     return domain_less_equal<Type>(icl::first(super), element                  )
0863         && domain_less_equal<Type>(                   element, icl::last(super));
0864 }
0865 
0866 template<class Type>
0867 typename boost::enable_if<is_continuous_left_open<Type>, bool>::type
0868 contains(const Type& super, const typename interval_traits<Type>::domain_type& element)
0869 {
0870     return domain_less      <Type>(icl::lower(super), element                   )
0871         && domain_less_equal<Type>(                   element, icl::upper(super));
0872 }
0873 
0874 template<class Type>
0875 typename boost::enable_if<is_continuous_right_open<Type>, bool>::type
0876 contains(const Type& super, const typename interval_traits<Type>::domain_type& element)
0877 {
0878     return domain_less_equal<Type>(icl::lower(super), element                   )
0879         && domain_less      <Type>(                   element, icl::upper(super));
0880 }
0881 
0882 template<class Type>
0883 typename boost::enable_if<has_dynamic_bounds<Type>, bool>::type
0884 contains(const Type& super, const typename interval_traits<Type>::domain_type& element)
0885 {
0886     return
0887         (is_left_closed(super.bounds())
0888             ? domain_less_equal<Type>(lower(super), element)
0889             :       domain_less<Type>(lower(super), element))
0890     &&
0891         (is_right_closed(super.bounds())
0892             ? domain_less_equal<Type>(element, upper(super))
0893             :       domain_less<Type>(element, upper(super)));
0894 }
0895 
0896 //- within ---------------------------------------------------------------------
0897 template<class Type>
0898 inline typename boost::enable_if<is_interval<Type>, bool>::type
0899 within(const Type& sub, const Type& super)
0900 {
0901     return contains(super,sub);
0902 }
0903 
0904 //- operator == ----------------------------------------------------------------
0905 template<class Type>
0906 typename boost::enable_if<is_interval<Type>, bool>::type
0907 operator == (const Type& left, const Type& right)
0908 {
0909     return (icl::is_empty(left) && icl::is_empty(right))
0910         || (lower_equal(left,right) && upper_equal(left,right));
0911 }
0912 
0913 template<class Type>
0914 typename boost::enable_if<is_interval<Type>, bool>::type
0915 operator != (const Type& left, const Type& right)
0916 {
0917     return !(left == right);
0918 }
0919 
0920 //- operator < -----------------------------------------------------------------
0921 template<class Type>
0922 typename boost::enable_if<is_interval<Type>, bool>::type
0923 operator < (const Type& left, const Type& right)
0924 {
0925     return (!icl::is_empty(left) && !icl::is_empty(right))
0926         && (     lower_less(left,right)
0927              || (lower_equal(left,right) && upper_less(left,right)) );
0928 }
0929 
0930 template<class Type>
0931 inline typename boost::enable_if<is_interval<Type>, bool>::type
0932 operator > (const Type& left, const Type& right)
0933 {
0934     return right < left;
0935 }
0936 
0937 //- operator <= ----------------------------------------------------------------
0938 template<class Type>
0939 inline typename boost::enable_if<is_interval<Type>, bool>::type
0940 operator <= (const Type& left, const Type& right)
0941 {
0942     if(icl::is_empty(left) || icl::is_empty(right))
0943         return false;
0944 
0945     return !(left > right);
0946 }
0947 
0948 template<class Type>
0949 inline typename boost::enable_if<is_interval<Type>, bool>::type
0950 operator >= (const Type& left, const Type& right)
0951 {
0952     if(icl::is_empty(left) || icl::is_empty(right))
0953         return false;
0954 
0955     return !(left < right);
0956 }
0957 
0958 
0959 
0960 //------------------------------------------------------------------------------
0961 template<class Type>
0962 typename boost::enable_if<is_asymmetric_interval<Type>, bool>::type
0963 touches(const Type& left, const Type& right)
0964 {
0965     return domain_equal<Type>(upper(left), lower(right));
0966 }
0967 
0968 template<class Type>
0969 typename boost::enable_if<has_symmetric_bounds<Type>, bool>::type
0970 touches(const Type& left, const Type& right)
0971 {
0972     return domain_equal<Type>(last_next(left), first(right));
0973 }
0974 
0975 template<class Type>
0976 typename boost::enable_if<is_discrete_interval<Type>, bool>::type
0977 touches(const Type& left, const Type& right)
0978 {
0979     return domain_equal<Type>(domain_next<Type>(last(left)), first(right));
0980 }
0981 
0982 template<class Type>
0983 typename boost::enable_if<is_continuous_interval<Type>, bool>::type
0984 touches(const Type& left, const Type& right)
0985 {
0986     return is_complementary(inner_bounds(left,right))
0987         && domain_equal<Type>(upper(left), lower(right));
0988 }
0989 
0990 
0991 //==============================================================================
0992 //= Size
0993 //==============================================================================
0994 //- cardinality ----------------------------------------------------------------
0995 
0996 template<class Type>
0997 typename boost::enable_if<is_continuous_interval<Type>,
0998     typename size_type_of<interval_traits<Type> >::type>::type
0999 cardinality(const Type& object)
1000 {
1001     typedef typename size_type_of<interval_traits<Type> >::type SizeT;
1002     if(icl::is_empty(object))
1003         return icl::identity_element<SizeT>::value();
1004     else if(   object.bounds() == interval_bounds::closed()
1005             && domain_equal<Type>(lower(object), upper(object)))
1006         return icl::unit_element<SizeT>::value();
1007     else
1008         return icl::infinity<SizeT>::value();
1009 }
1010 
1011 template<class Type>
1012 typename boost::enable_if<is_discrete_interval<Type>,
1013     typename size_type_of<interval_traits<Type> >::type>::type
1014 cardinality(const Type& object)
1015 {
1016     typedef typename size_type_of<interval_traits<Type> >::type SizeT;
1017     return icl::is_empty(object) ? identity_element<SizeT>::value()
1018                                  : static_cast<SizeT>(last_next(object) - first(object));
1019 }
1020 
1021 template<class Type>
1022 typename boost::enable_if<is_continuous_asymmetric<Type>,
1023     typename size_type_of<interval_traits<Type> >::type>::type
1024 cardinality(const Type& object)
1025 {
1026     typedef typename size_type_of<interval_traits<Type> >::type SizeT;
1027     if(icl::is_empty(object))
1028         return icl::identity_element<SizeT>::value();
1029     else
1030         return icl::infinity<SizeT>::value();
1031 }
1032 
1033 template<class Type>
1034 typename boost::enable_if<is_discrete_asymmetric<Type>,
1035     typename size_type_of<interval_traits<Type> >::type>::type
1036 cardinality(const Type& object)
1037 {
1038     typedef typename size_type_of<interval_traits<Type> >::type SizeT;
1039     return icl::is_empty(object) ? identity_element<SizeT>::value()
1040                                  : static_cast<SizeT>(last_next(object) - first(object));
1041 }
1042 
1043 template<class Type>
1044 typename boost::enable_if<has_symmetric_bounds<Type>,
1045     typename size_type_of<interval_traits<Type> >::type>::type
1046 cardinality(const Type& object)
1047 {
1048     typedef typename size_type_of<interval_traits<Type> >::type SizeT;
1049     return icl::is_empty(object) ? identity_element<SizeT>::value()
1050                                  : static_cast<SizeT>(last_next(object) - first(object));
1051 }
1052 
1053 
1054 
1055 //- size -----------------------------------------------------------------------
1056 template<class Type>
1057 inline typename enable_if<is_interval<Type>,
1058     typename size_type_of<interval_traits<Type> >::type>::type
1059 size(const Type& object)
1060 {
1061     return cardinality(object);
1062 }
1063 
1064 //- length ---------------------------------------------------------------------
1065 template<class Type>
1066 inline typename boost::enable_if<is_continuous_interval<Type>,
1067     typename difference_type_of<interval_traits<Type> >::type>::type
1068 length(const Type& object)
1069 {
1070     typedef typename difference_type_of<interval_traits<Type> >::type DiffT;
1071     return icl::is_empty(object) ? identity_element<DiffT>::value()
1072                                  : upper(object) - lower(object);
1073 }
1074 
1075 template<class Type>
1076 inline typename boost::enable_if<is_discrete_interval<Type>,
1077     typename difference_type_of<interval_traits<Type> >::type>::type
1078 length(const Type& object)
1079 {
1080     typedef typename difference_type_of<interval_traits<Type> >::type DiffT;
1081     return icl::is_empty(object) ? identity_element<DiffT>::value()
1082                                  : last_next(object) - first(object);
1083 }
1084 
1085 template<class Type>
1086 typename boost::enable_if<is_continuous_asymmetric<Type>,
1087     typename difference_type_of<interval_traits<Type> >::type>::type
1088 length(const Type& object)
1089 {
1090     typedef typename difference_type_of<interval_traits<Type> >::type DiffT;
1091     return icl::is_empty(object) ? identity_element<DiffT>::value()
1092                                  : upper(object) - lower(object);
1093 }
1094 
1095 template<class Type>
1096 inline typename boost::enable_if<is_discrete_static<Type>,
1097     typename difference_type_of<interval_traits<Type> >::type>::type
1098 length(const Type& object)
1099 {
1100     typedef typename difference_type_of<interval_traits<Type> >::type DiffT;
1101     return icl::is_empty(object) ? identity_element<DiffT>::value()
1102                                  : last_next(object) - first(object);
1103 }
1104 
1105 //- iterative_size -------------------------------------------------------------
1106 template<class Type>
1107 inline typename enable_if<is_interval<Type>,
1108     typename size_type_of<interval_traits<Type> >::type>::type
1109 iterative_size(const Type&)
1110 {
1111     return 2;
1112 }
1113 
1114 
1115 //==============================================================================
1116 //= Addition
1117 //==============================================================================
1118 //- hull -----------------------------------------------------------------------
1119 /** \c hull returns the smallest interval containing \c left and \c right. */
1120 template<class Type>
1121 typename boost::enable_if<has_static_bounds<Type>, Type>::type
1122 hull(Type left, const Type& right)
1123 {
1124     typedef typename interval_traits<Type>::domain_compare domain_compare;
1125 
1126     if(icl::is_empty(right))
1127         return left;
1128     else if(icl::is_empty(left))
1129         return right;
1130 
1131     return
1132         construct<Type>
1133         (
1134             (std::min)(lower(left), lower(right), domain_compare()),
1135             (std::max)(upper(left), upper(right), domain_compare())
1136         );
1137 }
1138 
1139 template<class Type>
1140 typename boost::enable_if<has_dynamic_bounds<Type>, Type>::type
1141 hull(Type left, const Type& right)
1142 {
1143     if(icl::is_empty(right))
1144         return left;
1145     else if(icl::is_empty(left))
1146         return right;
1147 
1148     return  dynamic_interval_traits<Type>::construct_bounded
1149             (
1150                 lower_min(left, right),
1151                 upper_max(left, right)
1152             );
1153 }
1154 
1155 //==============================================================================
1156 //= Subtraction
1157 //==============================================================================
1158 //- left_subtract --------------------------------------------------------------
1159 /** subtract \c left_minuend from the \c right interval on it's left side.
1160     Return the difference: The part of \c right right of \c left_minuend.
1161 \code
1162 right_over = right - left_minuend; //on the left.
1163 ...      d) : right
1164 ... c)      : left_minuend
1165      [c  d) : right_over
1166 \endcode
1167 */
1168 template<class Type>
1169 typename boost::enable_if<is_asymmetric_interval<Type>, Type>::type
1170 left_subtract(Type right, const Type& left_minuend)
1171 {
1172     if(exclusive_less(left_minuend, right))
1173         return right;
1174 
1175     return construct<Type>(upper(left_minuend), upper(right));
1176 }
1177 
1178 template<class Type>
1179 typename boost::enable_if<is_static_closed<Type>, Type>::type
1180 left_subtract(Type right, const Type& left_minuend)
1181 {
1182     if(exclusive_less(left_minuend, right))
1183         return right;
1184     else if(upper_less_equal(right, left_minuend))
1185         return identity_element<Type>::value();
1186 
1187     return construct<Type>(domain_next<Type>(upper(left_minuend)), upper(right));
1188 }
1189 
1190 template<class Type>
1191 typename boost::enable_if<is_static_open<Type>, Type>::type
1192 left_subtract(Type right, const Type& left_minuend)
1193 {
1194     if(exclusive_less(left_minuend, right))
1195         return right;
1196 
1197     return construct<Type>(domain_prior<Type>(upper(left_minuend)), upper(right));
1198 }
1199 
1200 template<class Type>
1201 typename boost::enable_if<has_dynamic_bounds<Type>, Type>::type
1202 left_subtract(Type right, const Type& left_minuend)
1203 {
1204     if(exclusive_less(left_minuend, right))
1205         return right;
1206     return  dynamic_interval_traits<Type>::construct_bounded
1207             ( reverse_bounded_upper(left_minuend), bounded_upper(right) );
1208 }
1209 
1210 
1211 //- right_subtract -------------------------------------------------------------
1212 /** subtract \c right_minuend from the \c left interval on it's right side.
1213     Return the difference: The part of \c left left of \c right_minuend.
1214 \code
1215 left_over = left - right_minuend; //on the right side.
1216 [a      ...  : left
1217      [b ...  : right_minuend
1218 [a  b)       : left_over
1219 \endcode
1220 */
1221 template<class Type>
1222 typename boost::enable_if<is_asymmetric_interval<Type>, Type>::type
1223 right_subtract(Type left, const Type& right_minuend)
1224 {
1225     if(exclusive_less(left, right_minuend))
1226         return left;
1227     return construct<Type>(lower(left), lower(right_minuend));
1228 }
1229 
1230 template<class Type>
1231 typename boost::enable_if<is_static_closed<Type>, Type>::type
1232 right_subtract(Type left, const Type& right_minuend)
1233 {
1234     if(exclusive_less(left, right_minuend))
1235         return left;
1236     else if(lower_less_equal(right_minuend, left))
1237         return identity_element<Type>::value();
1238 
1239     return construct<Type>(lower(left), domain_prior<Type>(lower(right_minuend)));
1240 }
1241 
1242 template<class Type>
1243 typename boost::enable_if<is_static_open<Type>, Type>::type
1244 right_subtract(Type left, const Type& right_minuend)
1245 {
1246     if(exclusive_less(left, right_minuend))
1247         return left;
1248 
1249     return construct<Type>(lower(left), domain_next<Type>(lower(right_minuend)));
1250 }
1251 
1252 template<class Type>
1253 typename boost::enable_if<has_dynamic_bounds<Type>, Type>::type
1254 right_subtract(Type left, const Type& right_minuend)
1255 {
1256     if(exclusive_less(left, right_minuend))
1257         return left;
1258 
1259     return  dynamic_interval_traits<Type>::construct_bounded
1260             ( bounded_lower(left), reverse_bounded_lower(right_minuend) );
1261 }
1262 
1263 //==============================================================================
1264 //= Intersection
1265 //==============================================================================
1266 //- operator & -----------------------------------------------------------------
1267 /** Returns the intersection of \c left and \c right interval. */
1268 template<class Type>
1269 typename boost::enable_if<is_asymmetric_interval<Type>, Type>::type
1270 operator & (Type left, const Type& right)
1271 {
1272     typedef typename interval_traits<Type>::domain_compare domain_compare;
1273 
1274     if(icl::is_empty(left) || icl::is_empty(right))
1275         return identity_element<Type>::value();
1276     else
1277         return
1278         construct<Type>
1279         (
1280             (std::max)(icl::lower(left), icl::lower(right), domain_compare()),
1281             (std::min)(icl::upper(left), icl::upper(right), domain_compare())
1282         );
1283 }
1284 
1285 template<class Type>
1286 typename boost::enable_if<has_symmetric_bounds<Type>, Type>::type
1287 operator & (Type left, const Type& right)
1288 {
1289     typedef typename interval_traits<Type>::domain_compare domain_compare;
1290 
1291     if(icl::is_empty(left) || icl::is_empty(right))
1292         return identity_element<Type>::value();
1293     else
1294         return
1295         construct<Type>
1296         (
1297             (std::max)(icl::lower(left), icl::lower(right), domain_compare()),
1298             (std::min)(icl::upper(left), icl::upper(right), domain_compare())
1299         );
1300 }
1301 
1302 template<class Type>
1303 typename boost::enable_if<has_dynamic_bounds<Type>, Type>::type
1304 operator & (Type left, const Type& right)
1305 {
1306     if(icl::is_empty(left) || icl::is_empty(right))
1307         return identity_element<Type>::value();
1308     else
1309         return  dynamic_interval_traits<Type>::construct_bounded
1310                 (
1311                     lower_max(left, right),
1312                     upper_min(left, right)
1313                 );
1314 }
1315 
1316 
1317 //- intersects -----------------------------------------------------------------
1318 template<class Type>
1319 typename boost::enable_if<is_interval<Type>, bool>::type
1320 intersects(const Type& left, const Type& right)
1321 {
1322     return !(   icl::is_empty(left) || icl::is_empty(right)
1323              || exclusive_less(left,right) || exclusive_less(right,left));
1324 }
1325 
1326 //- disjoint -------------------------------------------------------------------
1327 template<class Type>
1328 typename boost::enable_if<is_interval<Type>, bool>::type
1329 disjoint(const Type& left, const Type& right)
1330 {
1331     return icl::is_empty(left) || icl::is_empty(right)
1332         || exclusive_less(left,right) || exclusive_less(right,left);
1333 }
1334 
1335 //==============================================================================
1336 //= Complement
1337 //==============================================================================
1338 
1339 template<class Type>
1340 typename boost::enable_if<is_asymmetric_interval<Type>, Type>::type
1341 inner_complement(const Type& left, const Type& right)
1342 {
1343     if(icl::is_empty(left) || icl::is_empty(right))
1344         return  identity_element<Type>::value();
1345     else if(exclusive_less(left, right))
1346         return construct<Type>(upper(left), lower(right));
1347     else if(exclusive_less(right, left))
1348         return construct<Type>(upper(right), lower(left));
1349     else
1350         return identity_element<Type>::value();
1351 }
1352 
1353 template<class Type>
1354 typename boost::enable_if<is_discrete_static_closed<Type>, Type>::type
1355 inner_complement(const Type& left, const Type& right)
1356 {
1357     if(icl::is_empty(left) || icl::is_empty(right))
1358         return  identity_element<Type>::value();
1359     else if(exclusive_less(left, right))
1360         return construct<Type>(domain_next<Type>(upper(left)), domain_prior<Type>(lower(right)));
1361     else if(exclusive_less(right, left))
1362         return construct<Type>(domain_next<Type>(upper(right)), domain_prior<Type>(lower(left)));
1363     else
1364         return identity_element<Type>::value();
1365 }
1366 
1367 template<class Type>
1368 typename boost::enable_if<is_discrete_static_open<Type>, Type>::type
1369 inner_complement(const Type& left, const Type& right)
1370 {
1371     if(icl::is_empty(left) || icl::is_empty(right))
1372         return  identity_element<Type>::value();
1373     else if(exclusive_less(left, right))
1374         return construct<Type>(last(left), first(right));
1375     else if(exclusive_less(right, left))
1376         return construct<Type>(last(right), first(left));
1377     else
1378         return identity_element<Type>::value();
1379 }
1380 
1381 template<class Type>
1382 typename boost::enable_if<has_dynamic_bounds<Type>, Type>::type
1383 inner_complement(const Type& left, const Type& right)
1384 {
1385     if(icl::is_empty(left) || icl::is_empty(right))
1386         return  identity_element<Type>::value();
1387     else if(exclusive_less(left, right))
1388         return right_subtract(left_subtract(hull(left, right), left), right);
1389     else if(exclusive_less(right, left))
1390         return right_subtract(left_subtract(hull(right, left), right), left);
1391     else
1392         return identity_element<Type>::value();
1393 }
1394 
1395 template<class Type>
1396 inline typename boost::enable_if<is_interval<Type>, Type>::type
1397 between(const Type& left, const Type& right)
1398 {
1399     return inner_complement(left, right);
1400 }
1401 
1402 
1403 
1404 //==============================================================================
1405 //= Distance
1406 //==============================================================================
1407 template<class Type>
1408 typename boost::
1409 enable_if< mpl::and_< is_interval<Type>
1410                     , has_difference<typename interval_traits<Type>::domain_type>
1411                     , is_discrete<typename interval_traits<Type>::domain_type>
1412                     >
1413          , typename difference_type_of<interval_traits<Type> >::type>::type
1414 distance(const Type& x1, const Type& x2)
1415 {
1416     typedef typename difference_type_of<interval_traits<Type> >::type difference_type;
1417 
1418     if(icl::is_empty(x1) || icl::is_empty(x2))
1419         return icl::identity_element<difference_type>::value();
1420     else if(domain_less<Type>(last(x1), first(x2)))
1421         return static_cast<difference_type>(icl::pred(first(x2) - last(x1)));
1422     else if(domain_less<Type>(last(x2), first(x1)))
1423         return static_cast<difference_type>(icl::pred(first(x1) - last(x2)));
1424     else
1425         return icl::identity_element<difference_type>::value();
1426 }
1427 
1428 template<class Type>
1429 typename boost::
1430 enable_if< mpl::and_< is_interval<Type>
1431                     , has_difference<typename interval_traits<Type>::domain_type>
1432                     , is_continuous<typename interval_traits<Type>::domain_type>
1433                     >
1434          , typename difference_type_of<interval_traits<Type> >::type>::type
1435 distance(const Type& x1, const Type& x2)
1436 {
1437     typedef typename difference_type_of<interval_traits<Type> >::type DiffT;
1438 
1439     if(icl::is_empty(x1) || icl::is_empty(x2))
1440         return icl::identity_element<DiffT>::value();
1441     else if(domain_less<Type>(upper(x1), lower(x2)))
1442         return lower(x2) - upper(x1);
1443     else if(domain_less<Type>(upper(x2), lower(x1)))
1444         return lower(x1) - upper(x2);
1445     else
1446         return icl::identity_element<DiffT>::value();
1447 }
1448 
1449 //==============================================================================
1450 //= Streaming, representation
1451 //==============================================================================
1452 template<class Type>
1453 typename boost::
1454     enable_if< mpl::or_< is_static_left_open<Type>
1455                        , is_static_open<Type>    >, std::string>::type
1456 left_bracket(const Type&) { return "("; }
1457 
1458 template<class Type>
1459 typename boost::
1460     enable_if< mpl::or_< is_static_right_open<Type>
1461                        , is_static_closed<Type>   >, std::string>::type
1462 left_bracket(const Type&) { return "["; }
1463 
1464 template<class Type>
1465 typename boost::enable_if<has_dynamic_bounds<Type>, std::string>::type
1466 left_bracket(const Type& object)
1467 {
1468     return left_bracket(object.bounds());
1469 }
1470 
1471 //------------------------------------------------------------------------------
1472 template<class Type>
1473 typename boost::
1474     enable_if< mpl::or_< is_static_right_open<Type>
1475                        , is_static_open<Type>     >, std::string>::type
1476 right_bracket(const Type&) { return ")"; }
1477 
1478 template<class Type>
1479 typename boost::
1480     enable_if< mpl::or_< is_static_left_open<Type>
1481                        , is_static_closed<Type>    >, std::string>::type
1482 right_bracket(const Type&) { return "]"; }
1483 
1484 template<class Type>
1485 typename boost::enable_if<has_dynamic_bounds<Type>, std::string>::type
1486 right_bracket(const Type& object)
1487 {
1488     return right_bracket(object.bounds());
1489 }
1490 
1491 //------------------------------------------------------------------------------
1492 template<class CharType, class CharTraits, class Type>
1493 typename boost::enable_if<is_interval<Type>,
1494                           std::basic_ostream<CharType, CharTraits> >::type&
1495 operator << (std::basic_ostream<CharType, CharTraits> &stream, Type const& object)
1496 {
1497     if(boost::icl::is_empty(object))
1498         return stream << left_bracket<Type>(object) << right_bracket<Type>(object);
1499     else
1500         return stream << left_bracket<Type>(object)
1501                       << interval_traits<Type>::lower(object)
1502                       << ","
1503                       << interval_traits<Type>::upper(object)
1504                       << right_bracket<Type>(object) ;
1505 }
1506 
1507 }} // namespace icl boost
1508 
1509 #endif