text: /*-----------------------------------------------------------------------------+
  Copyright (c) 2010-2010: Joachim Faulhaber
  +------------------------------------------------------------------------------+
     Distributed under the Boost Software License, Version 1.0.
        (See accompanying file LICENCE.txt or copy at
             http://www.boost.org/LICENSE_1_0.txt)
  +-----------------------------------------------------------------------------*/
  #ifndef BOOST_ICL_CONCEPT_INTERVAL_HPP_JOFA_100323
  #define BOOST_ICL_CONCEPT_INTERVAL_HPP_JOFA_100323
  
  #include <boost/assert.hpp> 
  #include <boost/utility/enable_if.hpp>
  #include <boost/mpl/and.hpp>
  #include <boost/mpl/or.hpp>
  #include <boost/mpl/not.hpp>
  #include <boost/icl/detail/design_config.hpp>
  #include <boost/icl/type_traits/unit_element.hpp>
  #include <boost/icl/type_traits/identity_element.hpp>
  #include <boost/icl/type_traits/infinity.hpp>
  #include <boost/icl/type_traits/succ_pred.hpp>
  #include <boost/icl/type_traits/is_numeric.hpp>
  #include <boost/icl/type_traits/is_discrete.hpp>
  #include <boost/icl/type_traits/is_continuous.hpp>
  #include <boost/icl/type_traits/is_asymmetric_interval.hpp>
  #include <boost/icl/type_traits/is_discrete_interval.hpp>
  #include <boost/icl/type_traits/is_continuous_interval.hpp>
  
  #include <boost/icl/concept/interval_bounds.hpp>
  #include <boost/icl/interval_traits.hpp>
  #include <boost/icl/dynamic_interval_traits.hpp>
  
  
  namespace boost{namespace icl
  {
  
  //==============================================================================
  //= Ordering
  //==============================================================================
  template<class Type>
  inline typename enable_if<is_interval<Type>, bool>::type
  domain_less(const typename interval_traits<Type>::domain_type& left, 
              const typename interval_traits<Type>::domain_type& right)
  {
      return typename interval_traits<Type>::domain_compare()(left, right);
  }
  
  template<class Type>
  inline typename enable_if<is_interval<Type>, bool>::type
  domain_less_equal(const typename interval_traits<Type>::domain_type& left, 
                    const typename interval_traits<Type>::domain_type& right)
  {
      return !(typename interval_traits<Type>::domain_compare()(right, left));
  }
  
  template<class Type>
  inline typename enable_if<is_interval<Type>, bool>::type
  domain_equal(const typename interval_traits<Type>::domain_type& left, 
               const typename interval_traits<Type>::domain_type& right)
  {
      typedef typename interval_traits<Type>::domain_compare domain_compare;
      return !(domain_compare()(left, right)) && !(domain_compare()(right, left));
  }
  
  template<class Type>
  inline typename enable_if< is_interval<Type>
                           , typename interval_traits<Type>::domain_type>::type
  domain_next(const typename interval_traits<Type>::domain_type value) 
  {
      typedef typename interval_traits<Type>::domain_type domain_type;
      typedef typename interval_traits<Type>::domain_compare domain_compare;
      return icl::successor<domain_type,domain_compare>::apply(value);
  }
  
  template<class Type>
  inline typename enable_if< is_interval<Type>
                           , typename interval_traits<Type>::domain_type>::type
  domain_prior(const typename interval_traits<Type>::domain_type value) 
  {
      typedef typename interval_traits<Type>::domain_type domain_type;
      typedef typename interval_traits<Type>::domain_compare domain_compare;
      return icl::predecessor<domain_type,domain_compare>::apply(value);
  }
  
  //==============================================================================
  //= Construct<Interval> singleton
  //==============================================================================
  template<class Type>
  typename enable_if
  <
      mpl::and_< is_static_right_open<Type>
               , is_discrete<typename interval_traits<Type>::domain_type> >
    , Type
  >::type
  singleton(const typename interval_traits<Type>::domain_type& value)
  {
      //ASSERT: This always creates an interval with exactly one element
      return interval_traits<Type>::construct(value, domain_next<Type>(value));
  }
  
  template<class Type>
  typename enable_if
  <
      mpl::and_< is_static_left_open<Type>
               , is_discrete<typename interval_traits<Type>::domain_type> >
    , Type
  >::type
  singleton(const typename interval_traits<Type>::domain_type& value)
  {
      //ASSERT: This always creates an interval with exactly one element
      typedef typename interval_traits<Type>::domain_type    domain_type;
      typedef typename interval_traits<Type>::domain_compare domain_compare;
      BOOST_ASSERT((numeric_minimum<domain_type, domain_compare, is_numeric<domain_type>::value>
                                   ::is_less_than(value) )); 
  
      return interval_traits<Type>::construct(domain_prior<Type>(value), value);
  }
  
  template<class Type>
  typename enable_if<is_discrete_static_open<Type>, Type>::type
  singleton(const typename interval_traits<Type>::domain_type& value)
  {
      //ASSERT: This always creates an interval with exactly one element
      typedef typename interval_traits<Type>::domain_type    domain_type;
      typedef typename interval_traits<Type>::domain_compare domain_compare;
      BOOST_ASSERT((numeric_minimum<domain_type, domain_compare, is_numeric<domain_type>::value>
                                   ::is_less_than(value))); 
  
      return interval_traits<Type>::construct( domain_prior<Type>(value)
                                             , domain_next<Type>(value));
  }
  
  template<class Type>
  typename enable_if<is_discrete_static_closed<Type>, Type>::type
  singleton(const typename interval_traits<Type>::domain_type& value)
  {
      //ASSERT: This always creates an interval with exactly one element
      return interval_traits<Type>::construct(value, value);
  }
  
  template<class Type>
  typename enable_if<has_dynamic_bounds<Type>, Type>::type
  singleton(const typename interval_traits<Type>::domain_type& value)
  {
      return dynamic_interval_traits<Type>::construct(value, value, interval_bounds::closed());
  }
  
  namespace detail
  {
  
  //==============================================================================
  //= Construct<Interval> unit_trail == generalized singleton
  // The smallest interval on an incrementable (and decrementable) type that can 
  // be constructed using ++ and -- and such that it contains a given value.
  // If 'Type' is discrete, 'unit_trail' and 'singleton' are identical. So we 
  // can view 'unit_trail' as a generalized singleton for static intervals of 
  // continuous types.
  //==============================================================================
  template<class Type>
  typename enable_if
  <
      mpl::and_< is_static_right_open<Type>
               , boost::detail::is_incrementable<typename interval_traits<Type>::domain_type> >
    , Type
  >::type
  unit_trail(const typename interval_traits<Type>::domain_type& value)
  {
      return interval_traits<Type>::construct(value, domain_next<Type>(value));
  }
  
  template<class Type>
  typename enable_if
  <
      mpl::and_< is_static_left_open<Type>
               , boost::detail::is_incrementable<typename interval_traits<Type>::domain_type> >
    , Type
  >::type
  unit_trail(const typename interval_traits<Type>::domain_type& value)
  {
      typedef typename interval_traits<Type>::domain_type    domain_type;
      typedef typename interval_traits<Type>::domain_compare domain_compare;
      BOOST_ASSERT((numeric_minimum<domain_type, domain_compare, is_numeric<domain_type>::value>
                                   ::is_less_than(value) )); 
  
      return interval_traits<Type>::construct(domain_prior<Type>(value), value);
  }
  
  template<class Type>
  typename enable_if
  <
      mpl::and_< is_static_open<Type>
               , is_discrete<typename interval_traits<Type>::domain_type> >
    , Type
  >::type
  unit_trail(const typename interval_traits<Type>::domain_type& value)
  {
      typedef typename interval_traits<Type>::domain_type    domain_type;
      typedef typename interval_traits<Type>::domain_compare domain_compare;
      BOOST_ASSERT((numeric_minimum<domain_type, domain_compare, is_numeric<domain_type>::value>
                                   ::is_less_than(value))); 
  
      return interval_traits<Type>::construct( domain_prior<Type>(value)
                                             ,  domain_next<Type>(value));
  }
  
  template<class Type>
  typename enable_if
  <
      mpl::and_< is_static_closed<Type>
               , is_discrete<typename interval_traits<Type>::domain_type> >
    , Type
  >::type
  unit_trail(const typename interval_traits<Type>::domain_type& value)
  {
      return interval_traits<Type>::construct(value, value);
  }
  
  //NOTE: statically bounded closed or open intervals of continuous domain types
  // are NOT supported by ICL. They can not be used with interval containers
  // consistently.
  
  
  template<class Type>
  typename enable_if<has_dynamic_bounds<Type>, Type>::type
  unit_trail(const typename interval_traits<Type>::domain_type& value)
  {
      return dynamic_interval_traits<Type>::construct(value, value, interval_bounds::closed());
  }
  
  } //namespace detail
  
  //==============================================================================
  //= Construct<Interval> multon
  //==============================================================================
  template<class Type>
  typename enable_if<has_static_bounds<Type>, Type>::type
  construct(const typename interval_traits<Type>::domain_type& low,
            const typename interval_traits<Type>::domain_type& up  )
  {
      return interval_traits<Type>::construct(low, up);
  }
  
  template<class Type>
  typename enable_if<has_dynamic_bounds<Type>, Type>::type
  construct(const typename interval_traits<Type>::domain_type& low,
            const typename interval_traits<Type>::domain_type& up,
            interval_bounds bounds = interval_bounds::right_open())
  {
      return dynamic_interval_traits<Type>::construct(low, up, bounds);
  }
  
  
  //- construct form bounded values ----------------------------------------------
  template<class Type>
  typename enable_if<has_dynamic_bounds<Type>, Type>::type
  construct(const typename Type::bounded_domain_type& low,
            const typename Type::bounded_domain_type& up)
  {
      return dynamic_interval_traits<Type>::construct_bounded(low, up);
  }
  
  template<class Type>
  typename enable_if<is_interval<Type>, Type>::type
  span(const typename interval_traits<Type>::domain_type& left,
       const typename interval_traits<Type>::domain_type& right)
  {
      if(interval_traits<Type>::domain_compare()(left,right))
          return construct<Type>(left, right);
      else
          return construct<Type>(right, left);
  }
  
  
  //==============================================================================
  template<class Type>
  typename enable_if<is_static_right_open<Type>, Type>::type
  hull(const typename interval_traits<Type>::domain_type& left,
       const typename interval_traits<Type>::domain_type& right)
  {
      if(interval_traits<Type>::domain_compare()(left,right))
          return construct<Type>(left, domain_next<Type>(right));
      else
          return construct<Type>(right, domain_next<Type>(left));
  }
  
  template<class Type>
  typename enable_if<is_static_left_open<Type>, Type>::type
  hull(const typename interval_traits<Type>::domain_type& left,
       const typename interval_traits<Type>::domain_type& right)
  {
      typedef typename interval_traits<Type>::domain_type    domain_type;
      typedef typename interval_traits<Type>::domain_compare domain_compare;
      if(interval_traits<Type>::domain_compare()(left,right))
      {
          BOOST_ASSERT((numeric_minimum<domain_type, domain_compare, is_numeric<domain_type>::value>
                                       ::is_less_than(left) )); 
          return construct<Type>(domain_prior<Type>(left), right);
      }
      else
      {
          BOOST_ASSERT((numeric_minimum<domain_type, domain_compare, is_numeric<domain_type>::value>
                                       ::is_less_than(right) )); 
          return construct<Type>(domain_prior<Type>(right), left);
      }
  }
  
  template<class Type>
  typename enable_if<is_static_closed<Type>, Type>::type
  hull(const typename interval_traits<Type>::domain_type& left,
       const typename interval_traits<Type>::domain_type& right)
  {
      if(interval_traits<Type>::domain_compare()(left,right))
          return construct<Type>(left, right);
      else
          return construct<Type>(right, left);
  }
  
  template<class Type>
  typename enable_if<is_static_open<Type>, Type>::type
  hull(const typename interval_traits<Type>::domain_type& left,
       const typename interval_traits<Type>::domain_type& right)
  {
      typedef typename interval_traits<Type>::domain_type    domain_type;
      typedef typename interval_traits<Type>::domain_compare domain_compare;
      if(interval_traits<Type>::domain_compare()(left,right))
      {
          BOOST_ASSERT((numeric_minimum<domain_type, domain_compare, is_numeric<domain_type>::value>
                                       ::is_less_than(left) )); 
          return construct<Type>( domain_prior<Type>(left)
                                ,  domain_next<Type>(right));
      }
      else
      {
          BOOST_ASSERT((numeric_minimum<domain_type, domain_compare, is_numeric<domain_type>::value>
                                       ::is_less_than(right) )); 
          return construct<Type>( domain_prior<Type>(right)
                                ,  domain_next<Type>(left));
      }
  }
  
  template<class Type>
  typename enable_if<has_dynamic_bounds<Type>, Type>::type
  hull(const typename interval_traits<Type>::domain_type& left,
       const typename interval_traits<Type>::domain_type& right)
  {
      if(interval_traits<Type>::domain_compare()(left,right))
          return construct<Type>(left, right, interval_bounds::closed());
      else
          return construct<Type>(right, left, interval_bounds::closed());
  }
  
  //==============================================================================
  //= Selection
  //==============================================================================
  
  template<class Type>
  inline typename enable_if<is_interval<Type>, 
                            typename interval_traits<Type>::domain_type>::type
  lower(const Type& object)
  { 
      return interval_traits<Type>::lower(object);
  }
  
  template<class Type>
  inline typename enable_if<is_interval<Type>, 
                            typename interval_traits<Type>::domain_type>::type
  upper(const Type& object)
  { 
      return interval_traits<Type>::upper(object);
  }
  
  
  //- first ----------------------------------------------------------------------
  template<class Type>
  inline typename 
  enable_if< mpl::or_<is_static_right_open<Type>, is_static_closed<Type> >
           , typename interval_traits<Type>::domain_type>::type
  first(const Type& object)
  { 
      return lower(object);
  }
  
  template<class Type>
  inline typename 
  enable_if< mpl::and_< mpl::or_<is_static_left_open<Type>, is_static_open<Type> >
                      , is_discrete<typename interval_traits<Type>::domain_type> >
           , typename interval_traits<Type>::domain_type>::type
  first(const Type& object)
  { 
      return domain_next<Type>(lower(object));
  }
  
  template<class Type>
  inline typename enable_if<is_discrete_interval<Type>, 
                            typename interval_traits<Type>::domain_type>::type
  first(const Type& object)
  { 
      return is_left_closed(object.bounds()) ? 
                                   lower(object) : 
                 domain_next<Type>(lower(object));
  }
  
  //- last -----------------------------------------------------------------------
  template<class Type>
  inline typename 
  enable_if< mpl::or_<is_static_left_open<Type>, is_static_closed<Type> >
           , typename interval_traits<Type>::domain_type>::type
  last(const Type& object)
  { 
      return upper(object);
  }
  
  template<class Type>
  inline typename 
  enable_if< mpl::and_< mpl::or_<is_static_right_open<Type>, is_static_open<Type> >
                      , is_discrete<typename interval_traits<Type>::domain_type>  >
           , typename interval_traits<Type>::domain_type>::type
  last(const Type& object)
  { 
      typedef typename interval_traits<Type>::domain_type    domain_type;
      typedef typename interval_traits<Type>::domain_compare domain_compare;
      BOOST_ASSERT((numeric_minimum<domain_type, domain_compare, is_numeric<domain_type>::value>
                                   ::is_less_than(upper(object)) )); 
      return domain_prior<Type>(upper(object));
  }
  
  template<class Type>
  inline typename enable_if<is_discrete_interval<Type>, 
                            typename interval_traits<Type>::domain_type>::type
  last(const Type& object)
  { 
      typedef typename interval_traits<Type>::domain_type    domain_type;
      typedef typename interval_traits<Type>::domain_compare domain_compare;
      BOOST_ASSERT((numeric_minimum<domain_type, domain_compare, is_numeric<domain_type>::value>
                                   ::is_less_than_or(upper(object), is_right_closed(object.bounds())) )); 
      return is_right_closed(object.bounds()) ? 
                                    upper(object) : 
                 domain_prior<Type>(upper(object));
  }
  
  //- last_next ------------------------------------------------------------------
  template<class Type>
  inline typename 
  enable_if< mpl::and_< mpl::or_<is_static_left_open<Type>, is_static_closed<Type> >
                      , is_discrete<typename interval_traits<Type>::domain_type>  >
           , typename interval_traits<Type>::domain_type>::type
  last_next(const Type& object)
  { 
      return domain_next<Type>(upper(object));
  }
  
  template<class Type>
  inline typename 
  enable_if< mpl::and_< mpl::or_<is_static_right_open<Type>, is_static_open<Type> >
                      , is_discrete<typename interval_traits<Type>::domain_type>  >
           , typename interval_traits<Type>::domain_type>::type
  last_next(const Type& object)
  { 
      typedef typename interval_traits<Type>::domain_type domain_type;
      return upper(object); // NOTE: last_next is implemented to avoid calling pred(object)
  }                         // For unsigned integral types this may cause underflow.
  
  template<class Type>
  inline typename enable_if<is_discrete_interval<Type>, 
                            typename interval_traits<Type>::domain_type>::type
  last_next(const Type& object)
  { 
      return is_right_closed(object.bounds()) ? 
                 domain_next<Type>(upper(object)): 
                                   upper(object) ;
  }
  
  //------------------------------------------------------------------------------
  template<class Type>
  typename enable_if<has_dynamic_bounds<Type>, 
                     typename Type::bounded_domain_type>::type
  bounded_lower(const Type& object)
  { 
      return typename 
          Type::bounded_domain_type(lower(object), object.bounds().left()); 
  }
  
  template<class Type>
  typename enable_if<has_dynamic_bounds<Type>, 
                     typename Type::bounded_domain_type>::type
  reverse_bounded_lower(const Type& object)
  { 
      return typename 
          Type::bounded_domain_type(lower(object), 
                                    object.bounds().reverse_left()); 
  }
  
  template<class Type>
  typename enable_if<has_dynamic_bounds<Type>, 
                     typename Type::bounded_domain_type>::type
  bounded_upper(const Type& object)
  { 
      return typename 
          Type::bounded_domain_type(upper(object), 
                                    object.bounds().right()); 
  }
  
  template<class Type>
  typename enable_if<has_dynamic_bounds<Type>, 
                     typename Type::bounded_domain_type>::type
  reverse_bounded_upper(const Type& object)
  { 
      return typename 
          Type::bounded_domain_type(upper(object), 
                                    object.bounds().reverse_right()); 
  }
  
  //- bounds ---------------------------------------------------------------------
  template<class Type>
  inline typename enable_if<has_dynamic_bounds<Type>, interval_bounds>::type
  bounds(const Type& object)
  {
      return object.bounds();
  }
  
  template<class Type>
  inline typename enable_if<has_static_bounds<Type>, interval_bounds>::type
  bounds(const Type&)
  {
      return interval_bounds(interval_bound_type<Type>::value);
  }
  
  
  //==============================================================================
  //= Emptieness
  //==============================================================================
  /** Is the interval empty? */
  template<class Type>
  typename boost::enable_if<is_asymmetric_interval<Type>, bool>::type
  is_empty(const Type& object)
  { 
      return domain_less_equal<Type>(upper(object), lower(object)); 
  }
  
  template<class Type>
  typename boost::enable_if<is_static_closed<Type>, bool>::type
  is_empty(const Type& object)
  { 
      return domain_less<Type>(upper(object), lower(object)); 
  }
  
  template<class Type>
  typename boost::enable_if<is_static_open<Type>, bool>::type
  is_empty(const Type& object)
  { 
      return domain_less_equal<Type>(upper(object), domain_next<Type>(lower(object))); 
  }
  
  template<class Type>
  typename boost::enable_if<is_discrete_interval<Type>, bool>::type
  is_empty(const Type& object)
  { 
      if(object.bounds() == interval_bounds::closed())
          return domain_less<Type>(upper(object), lower(object)); 
      else if(object.bounds() == interval_bounds::open())
          return domain_less_equal<Type>(upper(object), domain_next<Type>(lower(object))); 
      else
          return domain_less_equal<Type>(upper(object), lower(object)); 
  }
  
  template<class Type>
  typename boost::enable_if<is_continuous_interval<Type>, bool>::type
  is_empty(const Type& object)
  {
      return     domain_less<Type>(upper(object), lower(object))
          || (   domain_equal<Type>(upper(object), lower(object))
              && object.bounds() != interval_bounds::closed()    );
  }
  
  //==============================================================================
  //= Orderings, containedness (non empty)
  //==============================================================================
  namespace non_empty
  {
  
      template<class Type>
      inline typename boost::enable_if<is_asymmetric_interval<Type>, bool>::type
      exclusive_less(const Type& left, const Type& right)
      { 
          BOOST_ASSERT(!(icl::is_empty(left) || icl::is_empty(right)));
          return domain_less_equal<Type>(upper(left), lower(right)); 
      }
  
      template<class Type>
      inline typename boost::enable_if<is_discrete_interval<Type>, bool>::type
      exclusive_less(const Type& left, const Type& right)
      { 
          BOOST_ASSERT(!(icl::is_empty(left) || icl::is_empty(right)));
          return domain_less<Type>(last(left), first(right)); 
      }
  
      template<class Type>
      inline typename boost::
      enable_if<has_symmetric_bounds<Type>, bool>::type
      exclusive_less(const Type& left, const Type& right)
      { 
          BOOST_ASSERT(!(icl::is_empty(left) || icl::is_empty(right)));
          return domain_less<Type>(last(left), first(right)); 
      }
  
      template<class Type>
      inline typename boost::enable_if<is_continuous_interval<Type>, bool>::type
      exclusive_less(const Type& left, const Type& right)
      { 
          BOOST_ASSERT(!(icl::is_empty(left) || icl::is_empty(right)));
          return     domain_less <Type>(left.upper(), right.lower())
              || (   domain_equal<Type>(left.upper(), right.lower())
                  && inner_bounds(left,right) != interval_bounds::open() );
      }
  
      template<class Type>
      inline typename boost::enable_if<is_interval<Type>, bool>::type
      contains(const Type& super, const Type& sub)
      { 
          return lower_less_equal(super,sub) && upper_less_equal(sub,super);
      }
  
  
  } //namespace non_empty
  
  
  //- contains -------------------------------------------------------------------
  template<class Type>
  inline typename boost::enable_if<is_interval<Type>, bool>::type
  contains(const Type& super, const Type& sub)
  { 
      return icl::is_empty(sub) || non_empty::contains(super, sub);
  }
  
  template<class Type>
  typename boost::enable_if<is_discrete_static<Type>, bool>::type
  contains(const Type& super, const typename interval_traits<Type>::domain_type& element)
  {
      return domain_less_equal<Type>(icl::first(super), element                  ) 
          && domain_less_equal<Type>(                   element, icl::last(super));
  }
  
  template<class Type>
  typename boost::enable_if<is_continuous_left_open<Type>, bool>::type
  contains(const Type& super, const typename interval_traits<Type>::domain_type& element)
  {
      return domain_less      <Type>(icl::lower(super), element                   ) 
          && domain_less_equal<Type>(                   element, icl::upper(super));
  }
  
  template<class Type>
  typename boost::enable_if<is_continuous_right_open<Type>, bool>::type
  contains(const Type& super, const typename interval_traits<Type>::domain_type& element)
  {
      return domain_less_equal<Type>(icl::lower(super), element                   ) 
          && domain_less      <Type>(                   element, icl::upper(super));
  }
  
  template<class Type>
  typename boost::enable_if<has_dynamic_bounds<Type>, bool>::type
  contains(const Type& super, const typename interval_traits<Type>::domain_type& element)
  {
      return
          (is_left_closed(super.bounds())  
              ? domain_less_equal<Type>(super.lower(), element) 
              :       domain_less<Type>(super.lower(), element))
      &&
          (is_right_closed(super.bounds()) 
              ? domain_less_equal<Type>(element, super.upper()) 
              :       domain_less<Type>(element, super.upper()));
  }
  
  //- within ---------------------------------------------------------------------
  template<class Type>
  inline typename boost::enable_if<is_interval<Type>, bool>::type
  within(const Type& sub, const Type& super)
  { 
      return contains(super,sub);
  }
  
  
  //==============================================================================
  //= Equivalences and Orderings
  //==============================================================================
  //- exclusive_less -------------------------------------------------------------
  /** Maximal element of <tt>left</tt> is less than the minimal element of 
      <tt>right</tt> */
  template<class Type>
  inline typename boost::enable_if<is_asymmetric_interval<Type>, bool>::type
  exclusive_less(const Type& left, const Type& right)
  { 
      return icl::is_empty(left) || icl::is_empty(right)
          || domain_less_equal<Type>(upper(left), lower(right)); 
  }
  
  template<class Type>
  inline typename boost::enable_if<is_discrete_interval<Type>, bool>::type
  exclusive_less(const Type& left, const Type& right)
  { 
      return icl::is_empty(left) || icl::is_empty(right)
          || domain_less<Type>(last(left), first(right)); 
  }
  
  template<class Type>
  inline typename boost::
  enable_if<has_symmetric_bounds<Type>, bool>::type
  exclusive_less(const Type& left, const Type& right)
  { 
      return icl::is_empty(left) || icl::is_empty(right)
          || domain_less<Type>(last(left), first(right)); 
  }
  
  template<class Type>
  inline typename boost::enable_if<is_continuous_interval<Type>, bool>::type
  exclusive_less(const Type& left, const Type& right)
  { 
      return     icl::is_empty(left) || icl::is_empty(right)
          ||     domain_less<Type>(left.upper(), right.lower())
          || (   domain_equal<Type>(left.upper(), right.lower())
              && inner_bounds(left,right) != interval_bounds::open() );
  }
  
  
  //------------------------------------------------------------------------------
  template<class Type>
  typename boost::enable_if<has_static_bounds<Type>, bool>::type
  lower_less(const Type& left, const Type& right)
  {
      return domain_less<Type>(left.lower(), right.lower());
  }
      
  template<class Type>
  typename boost::enable_if<is_discrete_interval<Type>, bool>::type
  lower_less(const Type& left, const Type& right)
  {
      return domain_less<Type>(first(left), first(right));
  }
      
  template<class Type>
  typename boost::enable_if<is_continuous_interval<Type>, bool>::type
  lower_less(const Type& left, const Type& right)
  {
      if(left_bounds(left,right) == interval_bounds::right_open())  //'[(' == 10
          return domain_less_equal<Type>(left.lower(), right.lower());
      else 
          return domain_less<Type>(left.lower(), right.lower());
  }
      
  
  //------------------------------------------------------------------------------
  template<class Type>
  typename boost::enable_if<has_static_bounds<Type>, bool>::type
  upper_less(const Type& left, const Type& right)
  {
      return domain_less<Type>(left.upper(), right.upper());
  }
  
  template<class Type>
  typename boost::enable_if<is_discrete_interval<Type>, bool>::type
  upper_less(const Type& left, const Type& right)
  {
      return domain_less<Type>(last(left), last(right));
  }
      
  template<class Type>
  typename boost::enable_if<is_continuous_interval<Type>, bool>::type
  upper_less(const Type& left, const Type& right)
  {
      if(right_bounds(left,right) == interval_bounds::left_open())
          return domain_less_equal<Type>(left.upper(), right.upper());
      else
          return domain_less<Type>(left.upper(), right.upper());
  }
      
  //------------------------------------------------------------------------------
  template<class Type>
  typename boost::enable_if<has_dynamic_bounds<Type>, 
                            typename Type::bounded_domain_type   >::type
  lower_min(const Type& left, const Type& right)
  {
      return lower_less(left, right) ? bounded_lower(left) : bounded_lower(right);
  }
  
  //------------------------------------------------------------------------------
  template<class Type>
  typename boost::enable_if<has_dynamic_bounds<Type>, 
                            typename Type::bounded_domain_type   >::type
  lower_max(const Type& left, const Type& right)
  {
      return lower_less(left, right) ? bounded_lower(right) : bounded_lower(left);
  }
  
  //------------------------------------------------------------------------------
  template<class Type>
  typename boost::enable_if<has_dynamic_bounds<Type>, 
                            typename Type::bounded_domain_type   >::type
  upper_max(const Type& left, const Type& right)
  {
      return upper_less(left, right) ? bounded_upper(right) : bounded_upper(left);
  }
  
  //------------------------------------------------------------------------------
  template<class Type>
  typename boost::enable_if<has_dynamic_bounds<Type>, 
                            typename Type::bounded_domain_type   >::type
  upper_min(const Type& left, const Type& right)
  {
      return upper_less(left, right) ? bounded_upper(left) : bounded_upper(right);
  }
  
  
  //------------------------------------------------------------------------------
  template<class Type>
  typename boost::enable_if<is_asymmetric_interval<Type>, bool>::type
  lower_equal(const Type& left, const Type& right)
  {
      return domain_equal<Type>(left.lower(), right.lower());
  }
  
  template<class Type>
  typename boost::enable_if<has_symmetric_bounds<Type>, bool>::type
  lower_equal(const Type& left, const Type& right)
  {
      return domain_equal<Type>(first(left), first(right));
  }
  
  template<class Type>
  typename boost::enable_if<is_discrete_interval<Type>, bool>::type
  lower_equal(const Type& left, const Type& right)
  {
      return domain_equal<Type>(first(left), first(right));
  }
  
  template<class Type>
  typename boost::enable_if<is_continuous_interval<Type>, bool>::type
  lower_equal(const Type& left, const Type& right)
  {
      return (left.bounds().left()==right.bounds().left())
          && domain_equal<Type>(left.lower(), right.lower());
  }
  
  
  //------------------------------------------------------------------------------
  template<class Type>
  typename boost::enable_if<is_asymmetric_interval<Type>, bool>::type
  upper_equal(const Type& left, const Type& right)
  {
      return domain_equal<Type>(left.upper(), right.upper());
  }
  
  template<class Type>
  typename boost::enable_if<has_symmetric_bounds<Type>, bool>::type
  upper_equal(const Type& left, const Type& right)
  {
      return domain_equal<Type>(last(left), last(right));
  }
  
  template<class Type>
  typename boost::enable_if<is_discrete_interval<Type>, bool>::type
  upper_equal(const Type& left, const Type& right)
  {
      return domain_equal<Type>(last(left), last(right));
  }
  
  template<class Type>
  typename boost::enable_if<is_continuous_interval<Type>, bool>::type
  upper_equal(const Type& left, const Type& right)
  {
      return (left.bounds().right()==right.bounds().right())
          && domain_equal<Type>(left.upper(), right.upper());
  }
  
  //------------------------------------------------------------------------------
  template<class Type>
  typename boost::enable_if<is_interval<Type>, bool>::type
  lower_less_equal(const Type& left, const Type& right)
  {
      return lower_less(left,right) || lower_equal(left,right);
  }
  
  template<class Type>
  typename boost::enable_if<is_interval<Type>, bool>::type
  upper_less_equal(const Type& left, const Type& right)
  {
      return upper_less(left,right) || upper_equal(left,right);
  }
  
  
  //- operator == ----------------------------------------------------------------
  template<class Type>
  typename boost::enable_if<is_interval<Type>, bool>::type
  operator == (const Type& left, const Type& right)
  {
      return (icl::is_empty(left) && icl::is_empty(right)) 
          || (lower_equal(left,right) && upper_equal(left,right));
  }
  
  template<class Type>
  typename boost::enable_if<is_interval<Type>, bool>::type
  operator != (const Type& left, const Type& right)
  {
      return !(left == right);
  }
  
  //- operator < -----------------------------------------------------------------
  template<class Type>
  typename boost::enable_if<is_interval<Type>, bool>::type
  operator < (const Type& left, const Type& right)
  {
      if(icl::is_empty(left)) 
          return !icl::is_empty(right);
      else 
          return lower_less(left,right) 
              || (lower_equal(left,right) && upper_less(left,right)); 
  }
  
  template<class Type>
  inline typename boost::enable_if<is_interval<Type>, bool>::type
  operator > (const Type& left, const Type& right)
  {
      return right < left;
  }
  
  
  
  //------------------------------------------------------------------------------
  template<class Type>
  typename boost::enable_if<is_asymmetric_interval<Type>, bool>::type
  touches(const Type& left, const Type& right)
  { 
      return domain_equal<Type>(upper(left), lower(right)); 
  }
  
  template<class Type>
  typename boost::enable_if<has_symmetric_bounds<Type>, bool>::type
  touches(const Type& left, const Type& right)
  { 
      return domain_equal<Type>(last_next(left), first(right)); 
  }
  
  template<class Type>
  typename boost::enable_if<is_discrete_interval<Type>, bool>::type
  touches(const Type& left, const Type& right)
  {
      return domain_equal<Type>(domain_next<Type>(last(left)), first(right));
  }
  
  template<class Type>
  typename boost::enable_if<is_continuous_interval<Type>, bool>::type
  touches(const Type& left, const Type& right)
  {
      return is_complementary(inner_bounds(left,right))
          && domain_equal<Type>(left.upper(), right.lower());
  }
  
  
  //==============================================================================
  //= Size
  //==============================================================================
  //- cardinality ----------------------------------------------------------------
  
  template<class Type>
  typename boost::enable_if<is_continuous_interval<Type>, 
      typename size_type_of<interval_traits<Type> >::type>::type
  cardinality(const Type& object)
  {
      typedef typename size_type_of<interval_traits<Type> >::type SizeT;
      if(icl::is_empty(object))
          return icl::identity_element<SizeT>::value();
      else if(   object.bounds() == interval_bounds::closed() 
              && domain_equal<Type>(lower(object), upper(object)))
          return icl::unit_element<SizeT>::value();
      else 
          return icl::infinity<SizeT>::value();
  }
  
  template<class Type>
  typename boost::enable_if<is_discrete_interval<Type>, 
      typename size_type_of<interval_traits<Type> >::type>::type
  cardinality(const Type& object)
  {
      typedef typename size_type_of<interval_traits<Type> >::type SizeT;
      return icl::is_empty(object) ? identity_element<SizeT>::value()
                                   : static_cast<SizeT>(last_next(object) - first(object));
  }
  
  template<class Type>
  typename boost::enable_if<is_continuous_asymmetric<Type>, 
      typename size_type_of<interval_traits<Type> >::type>::type
  cardinality(const Type& object)
  {
      typedef typename size_type_of<interval_traits<Type> >::type SizeT;
      if(icl::is_empty(object))
          return icl::identity_element<SizeT>::value();
      else 
          return icl::infinity<SizeT>::value();
  }
  
  template<class Type>
  typename boost::enable_if<is_discrete_asymmetric<Type>, 
      typename size_type_of<interval_traits<Type> >::type>::type
  cardinality(const Type& object)
  {
      typedef typename size_type_of<interval_traits<Type> >::type SizeT;
      return icl::is_empty(object) ? identity_element<SizeT>::value()
                                   : static_cast<SizeT>(last_next(object) - first(object));
  }
  
  template<class Type>
  typename boost::enable_if<has_symmetric_bounds<Type>, 
      typename size_type_of<interval_traits<Type> >::type>::type
  cardinality(const Type& object)
  {
      typedef typename size_type_of<interval_traits<Type> >::type SizeT;
      return icl::is_empty(object) ? identity_element<SizeT>::value()
                                   : static_cast<SizeT>(last_next(object) - first(object));
  }
  
  
  
  //- size -----------------------------------------------------------------------
  template<class Type>
  inline typename enable_if<is_interval<Type>, 
      typename size_type_of<interval_traits<Type> >::type>::type
  size(const Type& object)
  {
      return cardinality(object);
  }
  
  //- length ---------------------------------------------------------------------
  template<class Type>
  inline typename boost::enable_if<is_continuous_interval<Type>, 
      typename difference_type_of<interval_traits<Type> >::type>::type
  length(const Type& object)
  {
      typedef typename difference_type_of<interval_traits<Type> >::type DiffT;
      return icl::is_empty(object) ? identity_element<DiffT>::value()
                                   : upper(object) - lower(object);
  }
  
  template<class Type>
  inline typename boost::enable_if<is_discrete_interval<Type>, 
      typename difference_type_of<interval_traits<Type> >::type>::type
  length(const Type& object)
  {
      typedef typename difference_type_of<interval_traits<Type> >::type DiffT;
      return icl::is_empty(object) ? identity_element<DiffT>::value()
                                   : last_next(object) - first(object);
  }
  
  template<class Type>
  typename boost::enable_if<is_continuous_asymmetric<Type>, 
      typename difference_type_of<interval_traits<Type> >::type>::type
  length(const Type& object)
  {
      typedef typename difference_type_of<interval_traits<Type> >::type DiffT;
      return icl::is_empty(object) ? identity_element<DiffT>::value()
                                   : upper(object) - lower(object);
  }
  
  template<class Type>
  inline typename boost::enable_if<is_discrete_static<Type>, 
      typename difference_type_of<interval_traits<Type> >::type>::type
  length(const Type& object)
  {
      typedef typename difference_type_of<interval_traits<Type> >::type DiffT;
      return icl::is_empty(object) ? identity_element<DiffT>::value()
                                   : last_next(object) - first(object);
  }
  
  //- iterative_size -------------------------------------------------------------
  template<class Type>
  inline typename enable_if<is_interval<Type>, 
      typename size_type_of<interval_traits<Type> >::type>::type
  iterative_size(const Type&)
  {
      return 2;
  }
  
  
  //==============================================================================
  //= Addition
  //==============================================================================
  //- hull -----------------------------------------------------------------------
  /** \c hull returns the smallest interval containing \c left and \c right. */
  template<class Type>
  typename boost::enable_if<has_static_bounds<Type>, Type>::type
  hull(Type left, const Type& right)
  {
      typedef typename interval_traits<Type>::domain_compare domain_compare;
  
      if(icl::is_empty(right))
          return left;
      else if(icl::is_empty(left))
          return right;
  
      return 
          construct<Type>
          (
              (std::min)(lower(left), lower(right), domain_compare()), 
              (std::max)(upper(left), upper(right), domain_compare())
          );
  }
  
  template<class Type>
  typename boost::enable_if<has_dynamic_bounds<Type>, Type>::type
  hull(Type left, const Type& right)
  {
      if(icl::is_empty(right))
          return left;
      else if(icl::is_empty(left))
          return right;
  
      return  dynamic_interval_traits<Type>::construct_bounded
              (
                  lower_min(left, right), 
                  upper_max(left, right)
              );
  }
  
  //==============================================================================
  //= Subtraction
  //==============================================================================
  //- left_subtract --------------------------------------------------------------
  /** subtract \c left_minuend from the \c right interval on it's left side. 
      Return the difference: The part of \c right right of \c left_minuend.
  \code
  right_over = right - left_minuend; //on the left.
  ...      d) : right
  ... c)      : left_minuend
       [c  d) : right_over
  \endcode
  */
  template<class Type>
  typename boost::enable_if<is_asymmetric_interval<Type>, Type>::type
  left_subtract(Type right, const Type& left_minuend)
  {
      if(exclusive_less(left_minuend, right))
          return right; 
  
      return construct<Type>(upper(left_minuend), upper(right));
  }
  
  template<class Type>
  typename boost::enable_if<is_static_closed<Type>, Type>::type
  left_subtract(Type right, const Type& left_minuend)
  {
      if(exclusive_less(left_minuend, right))
          return right; 
  
      return construct<Type>(domain_next<Type>(upper(left_minuend)), upper(right));
  }
  
  template<class Type>
  typename boost::enable_if<is_static_open<Type>, Type>::type
  left_subtract(Type right, const Type& left_minuend)
  {
      if(exclusive_less(left_minuend, right))
          return right; 
  
      return construct<Type>(domain_prior<Type>(upper(left_minuend)), upper(right));
  }
  
  template<class Type>
  typename boost::enable_if<has_dynamic_bounds<Type>, Type>::type
  left_subtract(Type right, const Type& left_minuend)
  {
      if(exclusive_less(left_minuend, right))
          return right; 
      return  dynamic_interval_traits<Type>::construct_bounded
              ( reverse_bounded_upper(left_minuend), bounded_upper(right) );
  }
  
  
  //- right_subtract -------------------------------------------------------------
  /** subtract \c right_minuend from the \c left interval on it's right side. 
      Return the difference: The part of \c left right of \c right_minuend.
  \code
  left_over = left - right_minuend; //on the right side.
  [a      ...  : left
       [b ...  : right_minuend
  [a  b)       : left_over
  \endcode
  */
  template<class Type>
  typename boost::enable_if<is_asymmetric_interval<Type>, Type>::type
  right_subtract(Type left, const Type& right_minuend)
  {
      if(exclusive_less(left, right_minuend))
          return left; 
      return construct<Type>(lower(left), lower(right_minuend));
  }
  
  template<class Type>
  typename boost::enable_if<is_static_closed<Type>, Type>::type
  right_subtract(Type left, const Type& right_minuend)
  {
      if(exclusive_less(left, right_minuend))
          return left;
      else if(lower_less_equal(right_minuend, left))
          return identity_element<Type>::value();
  
      return construct<Type>(lower(left), domain_prior<Type>(lower(right_minuend)));
  }
  
  template<class Type>
  typename boost::enable_if<is_static_open<Type>, Type>::type
  right_subtract(Type left, const Type& right_minuend)
  {
      if(exclusive_less(left, right_minuend))
          return left;
  
      return construct<Type>(lower(left), domain_next<Type>(lower(right_minuend)));
  }
  
  template<class Type>
  typename boost::enable_if<has_dynamic_bounds<Type>, Type>::type
  right_subtract(Type left, const Type& right_minuend)
  {
      if(exclusive_less(left, right_minuend))
          return left; 
  
      return  dynamic_interval_traits<Type>::construct_bounded
              ( bounded_lower(left), reverse_bounded_lower(right_minuend) );
  }
  
  //==============================================================================
  //= Intersection
  //==============================================================================
  //- operator & -----------------------------------------------------------------
  /** Returns the intersection of \c left and \c right interval. */
  template<class Type>
  typename boost::enable_if<is_asymmetric_interval<Type>, Type>::type
  operator & (Type left, const Type& right)
  {
      typedef typename interval_traits<Type>::domain_compare domain_compare;
  
      if(icl::is_empty(left) || icl::is_empty(right))
          return identity_element<Type>::value();
      else
          return
          construct<Type>
          (
              (std::max)(icl::lower(left), icl::lower(right), domain_compare()),
              (std::min)(icl::upper(left), icl::upper(right), domain_compare())
          );
  }
  
  template<class Type>
  typename boost::enable_if<has_symmetric_bounds<Type>, Type>::type
  operator & (Type left, const Type& right)
  {
      typedef typename interval_traits<Type>::domain_compare domain_compare;
  
      if(icl::is_empty(left) || icl::is_empty(right))
          return identity_element<Type>::value();
      else
          return
          construct<Type>
          (
              (std::max)(icl::lower(left), icl::lower(right), domain_compare()),
              (std::min)(icl::upper(left), icl::upper(right), domain_compare())
          );
  }
  
  template<class Type>
  typename boost::enable_if<has_dynamic_bounds<Type>, Type>::type
  operator & (Type left, const Type& right)
  {
      if(icl::is_empty(left) || icl::is_empty(right))
          return identity_element<Type>::value();
      else 
          return  dynamic_interval_traits<Type>::construct_bounded
                  (
                      lower_max(left, right), 
                      upper_min(left, right) 
                  );
  }
  
  
  //- intersects -----------------------------------------------------------------
  template<class Type>
  typename boost::enable_if<is_interval<Type>, bool>::type
  intersects(const Type& left, const Type& right)
  { 
      return !(   icl::is_empty(left) || icl::is_empty(right) 
               || exclusive_less(left,right) || exclusive_less(right,left)); 
  }
  
  //- disjoint -------------------------------------------------------------------
  template<class Type>
  typename boost::enable_if<is_interval<Type>, bool>::type
  disjoint(const Type& left, const Type& right)
  { 
      return icl::is_empty(left) || icl::is_empty(right) 
          || exclusive_less(left,right) || exclusive_less(right,left); 
  }
  
  //==============================================================================
  //= Complement
  //==============================================================================
  
  template<class Type>
  typename boost::enable_if<is_asymmetric_interval<Type>, Type>::type
  inner_complement(const Type& left, const Type& right)
  {
      if(icl::is_empty(left) || icl::is_empty(right))
          return  identity_element<Type>::value();
      else if(exclusive_less(left, right))
          return construct<Type>(upper(left), lower(right));
      else if(exclusive_less(right, left))
          return construct<Type>(upper(right), lower(left));
      else
          return identity_element<Type>::value();
  }
  
  template<class Type>
  typename boost::enable_if<is_discrete_static_closed<Type>, Type>::type
  inner_complement(const Type& left, const Type& right)
  {
      if(icl::is_empty(left) || icl::is_empty(right))
          return  identity_element<Type>::value();
      else if(exclusive_less(left, right))
          return construct<Type>(domain_next<Type>(upper(left)), domain_prior<Type>(lower(right)));
      else if(exclusive_less(right, left))
          return construct<Type>(domain_next<Type>(upper(right)), domain_prior<Type>(lower(left)));
      else
          return identity_element<Type>::value();
  }
  
  template<class Type>
  typename boost::enable_if<is_discrete_static_open<Type>, Type>::type
  inner_complement(const Type& left, const Type& right)
  {
      if(icl::is_empty(left) || icl::is_empty(right))
          return  identity_element<Type>::value();
      else if(exclusive_less(left, right))
          return construct<Type>(last(left), first(right));
      else if(exclusive_less(right, left))
          return construct<Type>(last(right), first(left));
      else
          return identity_element<Type>::value();
  }
  
  template<class Type>
  typename boost::enable_if<has_dynamic_bounds<Type>, Type>::type
  inner_complement(const Type& left, const Type& right)
  {
      if(icl::is_empty(left) || icl::is_empty(right))
          return  identity_element<Type>::value();
      else if(exclusive_less(left, right))
          return right_subtract(left_subtract(hull(left, right), left), right);
      else if(exclusive_less(right, left))
          return right_subtract(left_subtract(hull(right, left), right), left);
      else
          return identity_element<Type>::value();
  }
  
  template<class Type>
  inline typename boost::enable_if<is_interval<Type>, Type>::type
  between(const Type& left, const Type& right)
  { 
      return inner_complement(left, right);
  }
  
  
  
  //==============================================================================
  //= Distance
  //==============================================================================
  template<class Type>
  typename boost::
  enable_if< mpl::and_< is_interval<Type>
                      , has_difference<typename interval_traits<Type>::domain_type>
                      , is_discrete<typename interval_traits<Type>::domain_type>        
                      >
           , typename difference_type_of<interval_traits<Type> >::type>::type
  distance(const Type& x1, const Type& x2)
  {
      typedef typename difference_type_of<interval_traits<Type> >::type difference_type;
  
      if(icl::is_empty(x1) || icl::is_empty(x2))
          return icl::identity_element<difference_type>::value();
      else if(domain_less<Type>(last(x1), first(x2)))
          return static_cast<difference_type>(icl::pred(first(x2) - last(x1)));
      else if(domain_less<Type>(last(x2), first(x1)))
          return static_cast<difference_type>(icl::pred(first(x1) - last(x2)));
      else
          return icl::identity_element<difference_type>::value();
  }
  
  template<class Type>
  typename boost::
  enable_if< mpl::and_< is_interval<Type>
                      , has_difference<typename interval_traits<Type>::domain_type>
                      , is_continuous<typename interval_traits<Type>::domain_type>        
                      >
           , typename difference_type_of<interval_traits<Type> >::type>::type
  distance(const Type& x1, const Type& x2)
  {
      typedef typename difference_type_of<interval_traits<Type> >::type DiffT;
  
      if(icl::is_empty(x1) || icl::is_empty(x2))
          return icl::identity_element<DiffT>::value();
      else if(domain_less<Type>(upper(x1), lower(x2)))
          return x2.lower() - x1.upper();
      else if(domain_less<Type>(upper(x2), lower(x1)))
          return lower(x1) - upper(x2);
      else
          return icl::identity_element<DiffT>::value();
  }
  
  //==============================================================================
  //= Streaming, representation
  //==============================================================================
  template<class Type>
  typename boost::
      enable_if< mpl::or_< is_static_left_open<Type>
                         , is_static_open<Type>    >, std::string>::type
  left_bracket(const Type&) { return "("; }
  
  template<class Type>
  typename boost::
      enable_if< mpl::or_< is_static_right_open<Type>
                         , is_static_closed<Type>   >, std::string>::type
  left_bracket(const Type&) { return "["; }
  
  template<class Type>
  typename boost::enable_if<has_dynamic_bounds<Type>, std::string>::type
  left_bracket(const Type& object) 
  { 
      return left_bracket(object.bounds()); 
  }
  
  //------------------------------------------------------------------------------
  template<class Type>
  typename boost::
      enable_if< mpl::or_< is_static_right_open<Type>
                         , is_static_open<Type>     >, std::string>::type
  right_bracket(const Type&) { return ")"; }
  
  template<class Type>
  typename boost::
      enable_if< mpl::or_< is_static_left_open<Type>
                         , is_static_closed<Type>    >, std::string>::type
  right_bracket(const Type&) { return "]"; }
  
  template<class Type>
  typename boost::enable_if<has_dynamic_bounds<Type>, std::string>::type
  right_bracket(const Type& object) 
  { 
      return right_bracket(object.bounds()); 
  }
  
  //------------------------------------------------------------------------------
  template<class CharType, class CharTraits, class Type>
  typename boost::enable_if<is_interval<Type>, 
                            std::basic_ostream<CharType, CharTraits> >::type&
  operator << (std::basic_ostream<CharType, CharTraits> &stream, Type const& object)
  {
      if(boost::icl::is_empty(object))
          return stream << left_bracket<Type>(object) << right_bracket<Type>(object); 
      else
          return stream << left_bracket<Type>(object) 
                        << interval_traits<Type>::lower(object) 
                        << "," 
                        << interval_traits<Type>::upper(object) 
                        << right_bracket<Type>(object) ;
  }
  
  }} // namespace icl boost
  
  #endif
  
  