Mercurial > hg > vamp-build-and-test
diff DEPENDENCIES/generic/include/boost/icl/concept/interval.hpp @ 16:2665513ce2d3
Add boost headers
author | Chris Cannam |
---|---|
date | Tue, 05 Aug 2014 11:11:38 +0100 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DEPENDENCIES/generic/include/boost/icl/concept/interval.hpp Tue Aug 05 11:11:38 2014 +0100 @@ -0,0 +1,1475 @@ +/*-----------------------------------------------------------------------------+ +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), lower(object) ) + || 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), lower(object) ) + || 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>(upper(left), lower(right)) + || ( domain_equal<Type>(upper(left), lower(right)) + && 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>(lower(super), element) + : domain_less<Type>(lower(super), element)) + && + (is_right_closed(super.bounds()) + ? domain_less_equal<Type>(element, upper(super)) + : domain_less<Type>(element, upper(super))); +} + +//- 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>(upper(left), lower(right)) + || ( domain_equal<Type>(upper(left), lower(right)) + && 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>(lower(left), lower(right)); +} + +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>(lower(left), lower(right)); + else + return domain_less<Type>(lower(left), lower(right)); +} + + +//------------------------------------------------------------------------------ +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>(upper(left), upper(right)); +} + +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>(upper(left), upper(right)); + else + return domain_less<Type>(upper(left), upper(right)); +} + +//------------------------------------------------------------------------------ +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>(lower(left), lower(right)); +} + +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>(lower(left), lower(right)); +} + + +//------------------------------------------------------------------------------ +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>(upper(left), upper(right)); +} + +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>(upper(left), upper(right)); +} + +//------------------------------------------------------------------------------ +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>(upper(left), lower(right)); +} + + +//============================================================================== +//= 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 lower(x2) - upper(x1); + 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 +