/*-----------------------------------------------------------------------------+ | |
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)); | |
} | |
//============================================================================== | |
//= 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, icl::succ(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; | |
BOOST_ASSERT((numeric_minimum<domain_type, is_numeric<domain_type>::value >::is_less_than(value) )); | |
return interval_traits<Type>::construct(icl::pred(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; | |
BOOST_ASSERT((numeric_minimum<domain_type, is_numeric<domain_type>::value >::is_less_than(value))); | |
return interval_traits<Type>::construct(icl::pred(value), icl::succ(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, icl::succ(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; | |
BOOST_ASSERT((numeric_minimum<domain_type, is_numeric<domain_type>::value >::is_less_than(value) )); | |
return interval_traits<Type>::construct(icl::pred(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; | |
BOOST_ASSERT((numeric_minimum<domain_type, is_numeric<domain_type>::value >::is_less_than(value))); | |
return interval_traits<Type>::construct(icl::pred(value), icl::succ(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, icl::succ(right)); | |
else | |
return construct<Type>(right, icl::succ(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; | |
if(interval_traits<Type>::domain_compare(left,right)) | |
{ | |
BOOST_ASSERT((numeric_minimum<domain_type, is_numeric<domain_type>::value >::is_less_than(left) )); | |
return construct<Type>(icl::pred(left), right); | |
} | |
else | |
{ | |
BOOST_ASSERT((numeric_minimum<domain_type, is_numeric<domain_type>::value >::is_less_than(right) )); | |
return construct<Type>(icl::pred(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; | |
if(interval_traits<Type>::domain_compare(left,right)) | |
{ | |
BOOST_ASSERT((numeric_minimum<domain_type, is_numeric<domain_type>::value >::is_less_than(left) )); | |
return construct<Type>(icl::pred(left), icl::succ(right)); | |
} | |
else | |
{ | |
BOOST_ASSERT((numeric_minimum<domain_type, is_numeric<domain_type>::value >::is_less_than(right) )); | |
return construct<Type>(icl::pred(right), icl::succ(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 icl::succ(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) : | |
icl::succ(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; | |
BOOST_ASSERT((numeric_minimum<domain_type, is_numeric<domain_type>::value> | |
::is_less_than(upper(object)) )); | |
return icl::pred(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; | |
BOOST_ASSERT((numeric_minimum<domain_type, is_numeric<domain_type>::value> | |
::is_less_than_or(upper(object), is_right_closed(object.bounds())) )); | |
return is_right_closed(object.bounds()) ? | |
upper(object) : | |
icl::pred(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 icl::succ(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()) ? | |
icl::succ(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), icl::succ(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), icl::succ(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> | |
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>(icl::succ(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 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 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& object) | |
{ | |
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>(icl::succ(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>(icl::pred(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), icl::pred(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), icl::succ(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>(icl::succ(upper(left)), icl::pred(lower(right))); | |
else if(exclusive_less(right, left)) | |
return construct<Type>(icl::succ(upper(right)), icl::pred(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 | |