mirror of
https://github.com/yuzu-emu/ext-boost
synced 2024-11-25 09:08:47 +00:00
1475 lines
52 KiB
C++
1475 lines
52 KiB
C++
/*-----------------------------------------------------------------------------+
|
|
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
|
|
|