mirror of
https://github.com/yuzu-emu/ext-boost
synced 2024-11-24 22:38:29 +00:00
1211 lines
42 KiB
C++
1211 lines
42 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_ASSOCIATOR_HPP_JOFA_100920
|
|
#define BOOST_ICL_CONCEPT_INTERVAL_ASSOCIATOR_HPP_JOFA_100920
|
|
|
|
#include <boost/icl/type_traits/domain_type_of.hpp>
|
|
#include <boost/icl/type_traits/interval_type_of.hpp>
|
|
#include <boost/icl/type_traits/is_combinable.hpp>
|
|
#include <boost/icl/detail/set_algo.hpp>
|
|
#include <boost/icl/detail/map_algo.hpp>
|
|
#include <boost/icl/detail/interval_set_algo.hpp>
|
|
#include <boost/icl/detail/interval_map_algo.hpp>
|
|
#include <boost/icl/concept/interval.hpp>
|
|
|
|
namespace boost{ namespace icl
|
|
{
|
|
|
|
//==============================================================================
|
|
//= Containedness<IntervalSet|IntervalMap>
|
|
//==============================================================================
|
|
//------------------------------------------------------------------------------
|
|
//- bool within(c T&, c P&) T={Set,Map} P={e i b p S M}
|
|
//------------------------------------------------------------------------------
|
|
template<class SubT, class SuperT>
|
|
typename enable_if<is_interval_container<SuperT>, bool>::type
|
|
within(const SubT& sub, const SuperT& super)
|
|
{
|
|
return icl::contains(super, sub);
|
|
}
|
|
|
|
//==============================================================================
|
|
//= Equivalences and Orderings<IntervalSet|IntervalMap>
|
|
//==============================================================================
|
|
template<class Type>
|
|
inline typename enable_if<is_interval_container<Type>, bool>::type
|
|
operator == (const Type& left, const Type& right)
|
|
{
|
|
return Set::lexicographical_equal(left, right);
|
|
}
|
|
|
|
template<class Type>
|
|
inline typename enable_if<is_interval_container<Type>, bool>::type
|
|
operator < (const Type& left, const Type& right)
|
|
{
|
|
typedef typename Type::segment_compare segment_compare;
|
|
return std::lexicographical_compare(
|
|
left.begin(), left.end(), right.begin(), right.end(),
|
|
segment_compare()
|
|
);
|
|
}
|
|
|
|
/** Returns true, if \c left and \c right contain the same elements.
|
|
Complexity: linear. */
|
|
template<class LeftT, class RightT>
|
|
typename enable_if<is_intra_combinable<LeftT, RightT>, bool>::type
|
|
is_element_equal(const LeftT& left, const RightT& right)
|
|
{
|
|
return Interval_Set::is_element_equal(left, right);
|
|
}
|
|
|
|
/** Returns true, if \c left is lexicographically less than \c right.
|
|
Intervals are interpreted as sequence of elements.
|
|
Complexity: linear. */
|
|
template<class LeftT, class RightT>
|
|
typename enable_if<is_intra_combinable<LeftT, RightT>, bool>::type
|
|
is_element_less(const LeftT& left, const RightT& right)
|
|
{
|
|
return Interval_Set::is_element_less(left, right);
|
|
}
|
|
|
|
/** Returns true, if \c left is lexicographically greater than \c right.
|
|
Intervals are interpreted as sequence of elements.
|
|
Complexity: linear. */
|
|
template<class LeftT, class RightT>
|
|
typename enable_if<is_intra_combinable<LeftT, RightT>, bool>::type
|
|
is_element_greater(const LeftT& left, const RightT& right)
|
|
{
|
|
return Interval_Set::is_element_greater(left, right);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
template<class LeftT, class RightT>
|
|
typename enable_if<is_inter_combinable<LeftT, RightT>, int>::type
|
|
inclusion_compare(const LeftT& left, const RightT& right)
|
|
{
|
|
return Interval_Set::subset_compare(left, right,
|
|
left.begin(), left.end(),
|
|
right.begin(), right.end());
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
template<class LeftT, class RightT>
|
|
typename enable_if< is_concept_compatible<is_interval_map, LeftT, RightT>,
|
|
bool >::type
|
|
is_distinct_equal(const LeftT& left, const RightT& right)
|
|
{
|
|
return Map::lexicographical_distinct_equal(left, right);
|
|
}
|
|
|
|
//==============================================================================
|
|
//= Size<IntervalSet|IntervalMap>
|
|
//==============================================================================
|
|
template<class Type>
|
|
typename enable_if<is_interval_container<Type>, std::size_t>::type
|
|
iterative_size(const Type& object)
|
|
{
|
|
return object.iterative_size();
|
|
}
|
|
|
|
template<class Type>
|
|
typename enable_if
|
|
< mpl::and_< is_interval_container<Type>
|
|
, is_discrete<typename Type::domain_type> >
|
|
, typename Type::size_type
|
|
>::type
|
|
cardinality(const Type& object)
|
|
{
|
|
typedef typename Type::size_type size_type;
|
|
//CL typedef typename Type::interval_type interval_type;
|
|
|
|
size_type size = identity_element<size_type>::value();
|
|
ICL_const_FORALL(typename Type, it, object)
|
|
size += icl::cardinality(key_value<Type>(it));
|
|
return size;
|
|
|
|
}
|
|
|
|
template<class Type>
|
|
typename enable_if
|
|
< mpl::and_< is_interval_container<Type>
|
|
, mpl::not_<is_discrete<typename Type::domain_type> > >
|
|
, typename Type::size_type
|
|
>::type
|
|
cardinality(const Type& object)
|
|
{
|
|
typedef typename Type::size_type size_type;
|
|
//CL typedef typename Type::interval_type interval_type;
|
|
|
|
size_type size = identity_element<size_type>::value();
|
|
size_type interval_size;
|
|
ICL_const_FORALL(typename Type, it, object)
|
|
{
|
|
interval_size = icl::cardinality(key_value<Type>(it));
|
|
if(interval_size == icl::infinity<size_type>::value())
|
|
return interval_size;
|
|
else
|
|
size += interval_size;
|
|
}
|
|
return size;
|
|
}
|
|
|
|
template<class Type>
|
|
inline typename enable_if<is_interval_container<Type>, typename Type::size_type>::type
|
|
size(const Type& object)
|
|
{
|
|
return icl::cardinality(object);
|
|
}
|
|
|
|
template<class Type>
|
|
typename enable_if<is_interval_container<Type>, typename Type::difference_type>::type
|
|
length(const Type& object)
|
|
{
|
|
typedef typename Type::difference_type difference_type;
|
|
typedef typename Type::const_iterator const_iterator;
|
|
difference_type length = identity_element<difference_type>::value();
|
|
const_iterator it_ = object.begin();
|
|
|
|
while(it_ != object.end())
|
|
length += icl::length(key_value<Type>(it_++));
|
|
return length;
|
|
}
|
|
|
|
template<class Type>
|
|
typename enable_if<is_interval_container<Type>, std::size_t>::type
|
|
interval_count(const Type& object)
|
|
{
|
|
return icl::iterative_size(object);
|
|
}
|
|
|
|
|
|
template<class Type>
|
|
typename enable_if< is_interval_container<Type>
|
|
, typename Type::difference_type >::type
|
|
distance(const Type& object)
|
|
{
|
|
typedef typename Type::difference_type DiffT;
|
|
typedef typename Type::const_iterator const_iterator;
|
|
const_iterator it_ = object.begin(), pred_;
|
|
DiffT dist = identity_element<DiffT>::value();
|
|
|
|
if(it_ != object.end())
|
|
pred_ = it_++;
|
|
|
|
while(it_ != object.end())
|
|
dist += icl::distance(key_value<Type>(pred_++), key_value<Type>(it_++));
|
|
|
|
return dist;
|
|
}
|
|
|
|
//==============================================================================
|
|
//= Range<IntervalSet|IntervalMap>
|
|
//==============================================================================
|
|
template<class Type>
|
|
typename enable_if<is_interval_container<Type>,
|
|
typename Type::interval_type>::type
|
|
hull(const Type& object)
|
|
{
|
|
return
|
|
icl::is_empty(object)
|
|
? identity_element<typename Type::interval_type>::value()
|
|
: icl::hull( key_value<Type>(object.begin()),
|
|
key_value<Type>(object.rbegin()) );
|
|
}
|
|
|
|
template<class Type>
|
|
typename enable_if<is_interval_container<Type>,
|
|
typename domain_type_of<Type>::type>::type
|
|
lower(const Type& object)
|
|
{
|
|
typedef typename domain_type_of<Type>::type DomainT;
|
|
return
|
|
icl::is_empty(object)
|
|
? unit_element<DomainT>::value()
|
|
: icl::lower( key_value<Type>(object.begin()) );
|
|
}
|
|
|
|
template<class Type>
|
|
typename enable_if<is_interval_container<Type>,
|
|
typename domain_type_of<Type>::type>::type
|
|
upper(const Type& object)
|
|
{
|
|
typedef typename domain_type_of<Type>::type DomainT;
|
|
return
|
|
icl::is_empty(object)
|
|
? identity_element<DomainT>::value()
|
|
: icl::upper( key_value<Type>(object.rbegin()) );
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
template<class Type>
|
|
typename enable_if
|
|
< mpl::and_< is_interval_container<Type>
|
|
, is_discrete<typename domain_type_of<Type>::type> >
|
|
, typename domain_type_of<Type>::type>::type
|
|
first(const Type& object)
|
|
{
|
|
typedef typename domain_type_of<Type>::type DomainT;
|
|
return
|
|
icl::is_empty(object)
|
|
? unit_element<DomainT>::value()
|
|
: icl::first( key_value<Type>(object.begin()) );
|
|
}
|
|
|
|
template<class Type>
|
|
typename enable_if
|
|
< mpl::and_< is_interval_container<Type>
|
|
, is_discrete<typename domain_type_of<Type>::type> >
|
|
, typename domain_type_of<Type>::type>::type
|
|
last(const Type& object)
|
|
{
|
|
typedef typename domain_type_of<Type>::type DomainT;
|
|
return
|
|
icl::is_empty(object)
|
|
? identity_element<DomainT>::value()
|
|
: icl::last( key_value<Type>(object.rbegin()) );
|
|
}
|
|
|
|
|
|
//==============================================================================
|
|
//= Addition<IntervalSet|IntervalMap>
|
|
//==============================================================================
|
|
//------------------------------------------------------------------------------
|
|
//- T& op +=(T&, c P&) T:{S}|{M} P:{e i}|{b p}
|
|
//------------------------------------------------------------------------------
|
|
/* \par \b Requires: \c OperandT is an addable derivative type of \c Type.
|
|
\b Effects: \c operand is added to \c object.
|
|
\par \b Returns: A reference to \c object.
|
|
\b Complexity:
|
|
\code
|
|
\ OperandT:
|
|
\ element segment
|
|
Type:
|
|
interval container O(log n) O(n)
|
|
|
|
interval_set amortized
|
|
spearate_interval_set O(log n)
|
|
|
|
n = object.interval_count()
|
|
\endcode
|
|
|
|
For the addition of \b elements or \b segments
|
|
complexity is \b logarithmic or \b linear respectively.
|
|
For \c interval_sets and \c separate_interval_sets addition of segments
|
|
is \b amortized \b logarithmic.
|
|
*/
|
|
template<class Type, class OperandT>
|
|
typename enable_if<is_intra_derivative<Type, OperandT>, Type>::type&
|
|
operator += (Type& object, const OperandT& operand)
|
|
{
|
|
return icl::add(object, operand);
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
//- T& op +=(T&, c P&) T:{S}|{M} P:{S'}|{M'}
|
|
//------------------------------------------------------------------------------
|
|
/** \par \b Requires: \c OperandT is an interval container addable to \c Type.
|
|
\b Effects: \c operand is added to \c object.
|
|
\par \b Returns: A reference to \c object.
|
|
\b Complexity: loglinear */
|
|
template<class Type, class OperandT>
|
|
typename enable_if<is_intra_combinable<Type, OperandT>, Type>::type&
|
|
operator += (Type& object, const OperandT& operand)
|
|
{
|
|
typename Type::iterator prior_ = object.end();
|
|
ICL_const_FORALL(typename OperandT, elem_, operand)
|
|
prior_ = icl::add(object, prior_, *elem_);
|
|
|
|
return object;
|
|
}
|
|
|
|
|
|
#ifdef BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
|
|
//------------------------------------------------------------------------------
|
|
//- T op + (T, c P&) T:{S}|{M} P:{e i S}|{b p M}
|
|
//------------------------------------------------------------------------------
|
|
/** \par \b Requires: \c object and \c operand are addable.
|
|
\b Effects: \c operand is added to \c object.
|
|
\par \b Efficieny: There is one additional copy of
|
|
\c Type \c object compared to inplace \c operator \c += */
|
|
template<class Type, class OperandT>
|
|
typename enable_if<is_binary_intra_combinable<Type, OperandT>, Type>::type
|
|
operator + (Type object, const OperandT& operand)
|
|
{
|
|
return object += operand;
|
|
}
|
|
|
|
#else //BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
|
|
|
|
template<class Type, class OperandT>
|
|
typename enable_if<is_binary_intra_combinable<Type, OperandT>, Type>::type
|
|
operator + (const Type& object, const OperandT& operand)
|
|
{
|
|
Type temp = object;
|
|
return boost::move(temp += operand);
|
|
}
|
|
|
|
template<class Type, class OperandT>
|
|
typename enable_if<is_binary_intra_combinable<Type, OperandT>, Type>::type
|
|
operator + (Type&& object, const OperandT& operand)
|
|
{
|
|
return boost::move(object += operand);
|
|
}
|
|
|
|
#endif //BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
|
|
|
|
#ifdef BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
|
|
//------------------------------------------------------------------------------
|
|
//- T op + (c P&, T) T:{S}|{M} P:{e i S'}|{b p M'}
|
|
//------------------------------------------------------------------------------
|
|
/** \par \b Requires: \c object and \c operand are addable.
|
|
\b Effects: \c operand is added to \c object.
|
|
\par \b Efficieny: There is one additional copy of
|
|
\c Type \c object compared to inplace \c operator \c += */
|
|
template<class Type, class OperandT>
|
|
typename enable_if<is_binary_intra_combinable<Type, OperandT>, Type>::type
|
|
operator + (const OperandT& operand, Type object)
|
|
{
|
|
return object += operand;
|
|
}
|
|
|
|
#else //BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
|
|
|
|
template<class Type, class OperandT>
|
|
typename enable_if<is_binary_intra_combinable<Type, OperandT>, Type>::type
|
|
operator + (const OperandT& operand, const Type& object)
|
|
{
|
|
Type temp = object;
|
|
return boost::move(temp += operand);
|
|
}
|
|
|
|
template<class Type, class OperandT>
|
|
typename enable_if<is_binary_intra_combinable<Type, OperandT>, Type>::type
|
|
operator + (const OperandT& operand, Type&& object)
|
|
{
|
|
return boost::move(object += operand);
|
|
}
|
|
|
|
#endif //BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
|
|
|
|
#ifdef BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
|
|
//------------------------------------------------------------------------------
|
|
//- T op + (T, c P&) T:{S}|{M} P:{S}|{M}
|
|
//------------------------------------------------------------------------------
|
|
/** \par \b Requires: \c object and \c operand are addable.
|
|
\b Effects: \c operand is added to \c object.
|
|
\par \b Efficieny: There is one additional copy of
|
|
\c Type \c object compared to inplace \c operator \c += */
|
|
template<class Type>
|
|
typename enable_if<is_interval_container<Type>, Type>::type
|
|
operator + (Type object, const Type& operand)
|
|
{
|
|
return object += operand;
|
|
}
|
|
|
|
#else //BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
|
|
|
|
template<class Type>
|
|
typename enable_if<is_interval_container<Type>, Type>::type
|
|
operator + (const Type& object, const Type& operand)
|
|
{
|
|
Type temp = object;
|
|
return boost::move(temp += operand);
|
|
}
|
|
|
|
template<class Type>
|
|
typename enable_if<is_interval_container<Type>, Type>::type
|
|
operator + (Type&& object, const Type& operand)
|
|
{
|
|
return boost::move(object += operand);
|
|
}
|
|
|
|
template<class Type>
|
|
typename enable_if<is_interval_container<Type>, Type>::type
|
|
operator + (const Type& operand, Type&& object)
|
|
{
|
|
return boost::move(object += operand);
|
|
}
|
|
|
|
template<class Type>
|
|
typename enable_if<is_interval_container<Type>, Type>::type
|
|
operator + (Type&& object, Type&& operand)
|
|
{
|
|
return boost::move(object += operand);
|
|
}
|
|
|
|
#endif //BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
|
|
|
|
//------------------------------------------------------------------------------
|
|
//- Addition |=, |
|
|
//------------------------------------------------------------------------------
|
|
|
|
//------------------------------------------------------------------------------
|
|
//- T& op |=(c P&) T:{S}|{M} P:{e i}|{b p}
|
|
//------------------------------------------------------------------------------
|
|
/** \par \b Requires: Types \c Type and \c OperandT are addable.
|
|
\par \b Effects: \c operand is added to \c object.
|
|
\par \b Returns: A reference to \c object.
|
|
\b Complexity:
|
|
\code
|
|
\ OperandT: interval
|
|
\ element segment container
|
|
Type:
|
|
interval container O(log n) O(n) O(m log(n+m))
|
|
|
|
interval_set amortized
|
|
spearate_interval_set O(log n)
|
|
|
|
n = object.interval_count()
|
|
m = operand.interval_count()
|
|
\endcode
|
|
|
|
For the addition of \b elements, \b segments and \b interval \b containers
|
|
complexity is \b logarithmic, \b linear and \b loglinear respectively.
|
|
For \c interval_sets and \c separate_interval_sets addition of segments
|
|
is \b amortized \b logarithmic.
|
|
*/
|
|
template<class Type, class OperandT>
|
|
typename enable_if<is_right_intra_combinable<Type, OperandT>, Type>::type&
|
|
operator |= (Type& object, const OperandT& operand)
|
|
{
|
|
return object += operand;
|
|
}
|
|
|
|
#ifdef BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
|
|
//------------------------------------------------------------------------------
|
|
//- T op | (T, c P&) T:{S}|{M} P:{e i S}|{b p M}
|
|
//------------------------------------------------------------------------------
|
|
/** \par \b Requires: \c object and \c operand are addable.
|
|
\b Effects: \c operand is added to \c object.
|
|
\par \b Efficieny: There is one additional copy of
|
|
\c Type \c object compared to inplace \c operator \c |= */
|
|
template<class Type, class OperandT>
|
|
typename enable_if<is_binary_intra_combinable<Type, OperandT>, Type>::type
|
|
operator | (Type object, const OperandT& operand)
|
|
{
|
|
return object += operand;
|
|
}
|
|
|
|
#else //BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
|
|
|
|
template<class Type, class OperandT>
|
|
typename enable_if<is_binary_intra_combinable<Type, OperandT>, Type>::type
|
|
operator | (const Type& object, const OperandT& operand)
|
|
{
|
|
Type temp = object;
|
|
return boost::move(temp += operand);
|
|
}
|
|
|
|
template<class Type, class OperandT>
|
|
typename enable_if<is_binary_intra_combinable<Type, OperandT>, Type>::type
|
|
operator | (Type&& object, const OperandT& operand)
|
|
{
|
|
return boost::move(object += operand);
|
|
}
|
|
|
|
#endif //BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
|
|
|
|
#ifdef BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
|
|
//------------------------------------------------------------------------------
|
|
//- T op | (T, c P&) T:{S}|{M} P:{S}|{M}
|
|
//------------------------------------------------------------------------------
|
|
/** \par \b Requires: \c object and \c operand are addable.
|
|
\b Effects: \c operand is added to \c object.
|
|
\par \b Efficieny: There is one additional copy of
|
|
\c Type \c object compared to inplace \c operator \c |= */
|
|
template<class Type, class OperandT>
|
|
typename enable_if<is_binary_intra_combinable<Type, OperandT>, Type>::type
|
|
operator | (const OperandT& operand, Type object)
|
|
{
|
|
return object += operand;
|
|
}
|
|
|
|
#else //BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
|
|
|
|
template<class Type, class OperandT>
|
|
typename enable_if<is_binary_intra_combinable<Type, OperandT>, Type>::type
|
|
operator | (const OperandT& operand, const Type& object)
|
|
{
|
|
Type temp = object;
|
|
return boost::move(temp += operand);
|
|
}
|
|
|
|
template<class Type, class OperandT>
|
|
typename enable_if<is_binary_intra_combinable<Type, OperandT>, Type>::type
|
|
operator | (const OperandT& operand, Type&& object)
|
|
{
|
|
return boost::move(object += operand);
|
|
}
|
|
|
|
#endif //BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
|
|
|
|
#ifdef BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
|
|
//------------------------------------------------------------------------------
|
|
//- T op | (T, c P&) T:{S}|{M} P:{S}|{M}
|
|
//------------------------------------------------------------------------------
|
|
/** \par \b Requires: \c object and \c operand are addable.
|
|
\b Effects: \c operand is added to \c object.
|
|
\par \b Efficieny: There is one additional copy of
|
|
\c Type \c object compared to inplace \c operator \c |= */
|
|
template<class Type>
|
|
typename enable_if<is_interval_container<Type>, Type>::type
|
|
operator | (Type object, const Type& operand)
|
|
{
|
|
return object += operand;
|
|
}
|
|
#else //BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
|
|
|
|
template<class Type>
|
|
typename enable_if<is_interval_container<Type>, Type>::type
|
|
operator | (const Type& object, const Type& operand)
|
|
{
|
|
Type temp = object;
|
|
return boost::move(temp += operand);
|
|
}
|
|
|
|
template<class Type>
|
|
typename enable_if<is_interval_container<Type>, Type>::type
|
|
operator | (Type&& object, const Type& operand)
|
|
{
|
|
return boost::move(object += operand);
|
|
}
|
|
|
|
template<class Type>
|
|
typename enable_if<is_interval_container<Type>, Type>::type
|
|
operator | (const Type& operand, Type&& object)
|
|
{
|
|
return boost::move(object += operand);
|
|
}
|
|
|
|
template<class Type>
|
|
typename enable_if<is_interval_container<Type>, Type>::type
|
|
operator | (Type&& object, Type&& operand)
|
|
{
|
|
return boost::move(object += operand);
|
|
}
|
|
|
|
#endif //BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
|
|
|
|
|
|
//==============================================================================
|
|
//= Insertion<IntervalSet|IntervalSet>
|
|
//==============================================================================
|
|
//------------------------------------------------------------------------------
|
|
//- T& insert(T&, c P&) T:{S}|{M} P:{S'}|{M'}
|
|
//------------------------------------------------------------------------------
|
|
template<class Type, class OperandT>
|
|
typename enable_if<is_intra_combinable<Type, OperandT>, Type>::type&
|
|
insert(Type& object, const OperandT& operand)
|
|
{
|
|
typename Type::iterator prior_ = object.end();
|
|
ICL_const_FORALL(typename OperandT, elem_, operand)
|
|
insert(object, prior_, *elem_);
|
|
|
|
return object;
|
|
}
|
|
|
|
//==============================================================================
|
|
//= Erasure<IntervalSet|IntervalSet>
|
|
//==============================================================================
|
|
//------------------------------------------------------------------------------
|
|
//- T& erase(T&, c P&) T:{S}|{M} P:{S'}|{S' M'}
|
|
//------------------------------------------------------------------------------
|
|
template<class Type, class OperandT>
|
|
typename enable_if<combines_right_to_interval_container<Type, OperandT>,
|
|
Type>::type&
|
|
erase(Type& object, const OperandT& operand)
|
|
{
|
|
typedef typename OperandT::const_iterator const_iterator;
|
|
|
|
if(icl::is_empty(operand))
|
|
return object;
|
|
|
|
const_iterator common_lwb, common_upb;
|
|
if(!Set::common_range(common_lwb, common_upb, operand, object))
|
|
return object;
|
|
|
|
const_iterator it_ = common_lwb;
|
|
while(it_ != common_upb)
|
|
icl::erase(object, *it_++);
|
|
|
|
return object;
|
|
}
|
|
|
|
//==============================================================================
|
|
//= Subtraction<IntervalSet|IntervalSet>
|
|
//==============================================================================
|
|
//------------------------------------------------------------------------------
|
|
//- T& op -= (c P&) T:{M} P:{M'}
|
|
//------------------------------------------------------------------------------
|
|
/** \par \b Requires: Types \c Type and \c OperandT are subtractable.
|
|
\par \b Effects: \c operand is subtracted from \c object.
|
|
\par \b Returns: A reference to \c object.
|
|
\b Complexity:
|
|
\code
|
|
\ OperandT: interval
|
|
\ element segment container
|
|
Type:
|
|
interval container O(log n) O(n) O(m log(n+m))
|
|
|
|
amortized
|
|
interval_sets O(log n)
|
|
|
|
n = object.interval_count()
|
|
m = operand.interval_count()
|
|
\endcode
|
|
|
|
For the subtraction of \em elements, \b segments and \b interval \b containers
|
|
complexity is \b logarithmic, \b linear and \b loglinear respectively.
|
|
For interval sets subtraction of segments
|
|
is \b amortized \b logarithmic.
|
|
*/
|
|
template<class Type, class OperandT>
|
|
typename enable_if<is_concept_compatible<is_interval_map, Type, OperandT>,
|
|
Type>::type&
|
|
operator -=(Type& object, const OperandT& operand)
|
|
{
|
|
ICL_const_FORALL(typename OperandT, elem_, operand)
|
|
icl::subtract(object, *elem_);
|
|
|
|
return object;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
//- T& op -= (c P&) T:{S}|{M} P:{e i}|{b p}
|
|
//------------------------------------------------------------------------------
|
|
template<class Type, class OperandT>
|
|
typename enable_if<is_intra_derivative<Type, OperandT>, Type>::type&
|
|
operator -= (Type& object, const OperandT& operand)
|
|
{
|
|
return icl::subtract(object, operand);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
//- T& op -= (c P&) T:{M} P:{e i}
|
|
//------------------------------------------------------------------------------
|
|
template<class Type, class OperandT>
|
|
typename enable_if<is_cross_derivative<Type, OperandT>, Type>::type&
|
|
operator -= (Type& object, const OperandT& operand)
|
|
{
|
|
return icl::erase(object, operand);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
//- T& op -= (c P&) T:{S M} P:{S'}
|
|
//------------------------------------------------------------------------------
|
|
template<class Type, class IntervalSetT>
|
|
typename enable_if<combines_right_to_interval_set<Type, IntervalSetT>,
|
|
Type>::type&
|
|
operator -= (Type& object, const IntervalSetT& operand)
|
|
{
|
|
return erase(object, operand);
|
|
}
|
|
|
|
#ifdef BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
|
|
//------------------------------------------------------------------------------
|
|
//- T op - (T, c P&) T:{S}|{M} P:{e i S'}|{e i b p S' M'}
|
|
//------------------------------------------------------------------------------
|
|
template<class Type, class OperandT>
|
|
typename enable_if<is_right_inter_combinable<Type, OperandT>, Type>::type
|
|
operator - (Type object, const OperandT& operand)
|
|
{
|
|
return object -= operand;
|
|
}
|
|
|
|
#else //BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
|
|
|
|
template<class Type, class OperandT>
|
|
typename enable_if<is_right_inter_combinable<Type, OperandT>, Type>::type
|
|
operator - (const Type& object, const OperandT& operand)
|
|
{
|
|
Type temp = object;
|
|
return boost::move(temp -= operand);
|
|
}
|
|
|
|
template<class Type, class OperandT>
|
|
typename enable_if<is_right_inter_combinable<Type, OperandT>, Type>::type
|
|
operator - (Type&& object, const OperandT& operand)
|
|
{
|
|
return boost::move(object -= operand);
|
|
}
|
|
|
|
#endif //BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
|
|
|
|
//==============================================================================
|
|
//= Intersection<IntervalSet|IntervalSet>
|
|
//==============================================================================
|
|
//------------------------------------------------------------------------------
|
|
//- void add_intersection(T&, c T&, c P&) T:{S M} P:{S'}
|
|
//------------------------------------------------------------------------------
|
|
template<class Type, class OperandT>
|
|
typename enable_if<mpl::and_<is_interval_set<Type>,
|
|
combines_right_to_interval_set<Type, OperandT> >,
|
|
void>::type
|
|
add_intersection(Type& section, const Type& object, const OperandT& operand)
|
|
{
|
|
typedef typename OperandT::const_iterator const_iterator;
|
|
|
|
if(operand.empty())
|
|
return;
|
|
|
|
const_iterator common_lwb, common_upb;
|
|
if(!Set::common_range(common_lwb, common_upb, operand, object))
|
|
return;
|
|
|
|
const_iterator it_ = common_lwb;
|
|
while(it_ != common_upb)
|
|
icl::add_intersection(section, object, key_value<OperandT>(it_++));
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
//- T& op &=(T&, c P&) T:{S}|{M} P:{e i S'}|{e i b p S' M'}
|
|
//------------------------------------------------------------------------------
|
|
template<class Type, class OperandT>
|
|
typename enable_if<is_right_inter_combinable<Type, OperandT>, Type>::type&
|
|
operator &= (Type& object, const OperandT& operand)
|
|
{
|
|
Type intersection;
|
|
add_intersection(intersection, object, operand);
|
|
object.swap(intersection);
|
|
return object;
|
|
}
|
|
|
|
#ifdef BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
|
|
//------------------------------------------------------------------------------
|
|
//- T op & (T, c P&) T:{S}|{M} P:{e i S'}|{e i b p S' M'} S<S' M<M' <:coarser
|
|
//------------------------------------------------------------------------------
|
|
template<class Type, class OperandT>
|
|
typename enable_if<is_binary_inter_combinable<Type, OperandT>, Type>::type
|
|
operator & (Type object, const OperandT& operand)
|
|
{
|
|
return object &= operand;
|
|
}
|
|
|
|
#else //BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
|
|
|
|
template<class Type, class OperandT>
|
|
typename enable_if<is_binary_inter_combinable<Type, OperandT>, Type>::type
|
|
operator & (const Type& object, const OperandT& operand)
|
|
{
|
|
Type temp = object;
|
|
return boost::move(temp &= operand);
|
|
}
|
|
|
|
template<class Type, class OperandT>
|
|
typename enable_if<is_binary_inter_combinable<Type, OperandT>, Type>::type
|
|
operator & (Type&& object, const OperandT& operand)
|
|
{
|
|
return boost::move(object &= operand);
|
|
}
|
|
|
|
#endif //BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
|
|
|
|
#ifdef BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
|
|
//------------------------------------------------------------------------------
|
|
//- T op & (c P&, T) T:{S}|{M} P:{e i S'}|{e i b p S' M'} S<S' M<M' <:coarser
|
|
//------------------------------------------------------------------------------
|
|
template<class Type, class OperandT>
|
|
typename enable_if<is_binary_inter_combinable<Type, OperandT>, Type>::type
|
|
operator & (const OperandT& operand, Type object)
|
|
{
|
|
return object &= operand;
|
|
}
|
|
|
|
#else //BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
|
|
|
|
template<class Type, class OperandT>
|
|
typename enable_if<is_binary_inter_combinable<Type, OperandT>, Type>::type
|
|
operator & (const OperandT& operand, const Type& object)
|
|
{
|
|
Type temp = object;
|
|
return boost::move(temp &= operand);
|
|
}
|
|
|
|
template<class Type, class OperandT>
|
|
typename enable_if<is_binary_inter_combinable<Type, OperandT>, Type>::type
|
|
operator & (const OperandT& operand, Type&& object)
|
|
{
|
|
return boost::move(object &= operand);
|
|
}
|
|
|
|
#endif //BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
|
|
|
|
#ifdef BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
|
|
//------------------------------------------------------------------------------
|
|
//- T op & (T, c T&) T:{S M}
|
|
//------------------------------------------------------------------------------
|
|
template<class Type>
|
|
typename enable_if<is_interval_container<Type>, Type>::type
|
|
operator & (Type object, const Type& operand)
|
|
{
|
|
return object &= operand;
|
|
}
|
|
|
|
#else //BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
|
|
|
|
template<class Type>
|
|
typename enable_if<is_interval_container<Type>, Type>::type
|
|
operator & (const Type& object, const Type& operand)
|
|
{
|
|
Type temp = object;
|
|
return boost::move(temp &= operand);
|
|
}
|
|
|
|
template<class Type>
|
|
typename enable_if<is_interval_container<Type>, Type>::type
|
|
operator & (Type&& object, const Type& operand)
|
|
{
|
|
return boost::move(object &= operand);
|
|
}
|
|
|
|
template<class Type>
|
|
typename enable_if<is_interval_container<Type>, Type>::type
|
|
operator & (const Type& operand, Type&& object)
|
|
{
|
|
return boost::move(object &= operand);
|
|
}
|
|
|
|
template<class Type>
|
|
typename enable_if<is_interval_container<Type>, Type>::type
|
|
operator & (Type&& object, Type&& operand)
|
|
{
|
|
return boost::move(object &= operand);
|
|
}
|
|
|
|
#endif //BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
|
|
|
|
//------------------------------------------------------------------------------
|
|
//- intersects<IntervalSet|IntervalMap>
|
|
//------------------------------------------------------------------------------
|
|
//------------------------------------------------------------------------------
|
|
//- bool intersects(c T&, c P&) T:{S}|{M} P:{e i}
|
|
//------------------------------------------------------------------------------
|
|
template<class Type, class CoType>
|
|
typename enable_if<mpl::and_< is_interval_container<Type>
|
|
, boost::is_same<CoType, typename domain_type_of<Type>::type> >,
|
|
bool>::type
|
|
intersects(const Type& left, const CoType& right)
|
|
{
|
|
return icl::contains(left, right);
|
|
}
|
|
|
|
template<class Type, class CoType>
|
|
typename enable_if<mpl::and_< is_interval_container<Type>
|
|
, boost::is_same<CoType, typename interval_type_of<Type>::type> >,
|
|
bool>::type
|
|
intersects(const Type& left, const CoType& right)
|
|
{
|
|
return icl::find(left, right) != left.end();
|
|
}
|
|
|
|
|
|
template<class LeftT, class RightT>
|
|
typename enable_if< mpl::and_< is_intra_combinable<LeftT, RightT>
|
|
, mpl::or_<is_total<LeftT>, is_total<RightT> > >
|
|
, bool>::type
|
|
intersects(const LeftT&, const RightT&)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
template<class LeftT, class RightT>
|
|
typename enable_if< mpl::and_< is_intra_combinable<LeftT, RightT>
|
|
, mpl::not_<mpl::or_< is_total<LeftT>
|
|
, is_total<RightT> > > >
|
|
, bool>::type
|
|
intersects(const LeftT& left, const RightT& right)
|
|
{
|
|
typedef typename RightT::const_iterator const_iterator;
|
|
LeftT intersection;
|
|
|
|
const_iterator right_common_lower_, right_common_upper_;
|
|
if(!Set::common_range(right_common_lower_, right_common_upper_, right, left))
|
|
return false;
|
|
|
|
const_iterator it_ = right_common_lower_;
|
|
while(it_ != right_common_upper_)
|
|
{
|
|
icl::add_intersection(intersection, left, *it_++);
|
|
if(!icl::is_empty(intersection))
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
template<class LeftT, class RightT>
|
|
typename enable_if<is_cross_combinable<LeftT, RightT>, bool>::type
|
|
intersects(const LeftT& left, const RightT& right)
|
|
{
|
|
typedef typename RightT::const_iterator const_iterator;
|
|
LeftT intersection;
|
|
|
|
if(icl::is_empty(left) || icl::is_empty(right))
|
|
return false;
|
|
|
|
const_iterator right_common_lower_, right_common_upper_;
|
|
if(!Set::common_range(right_common_lower_, right_common_upper_, right, left))
|
|
return false;
|
|
|
|
typename RightT::const_iterator it_ = right_common_lower_;
|
|
while(it_ != right_common_upper_)
|
|
{
|
|
icl::add_intersection(intersection, left, key_value<RightT>(it_++));
|
|
if(!icl::is_empty(intersection))
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/** \b Returns true, if \c left and \c right have no common elements.
|
|
Intervals are interpreted as sequence of elements.
|
|
\b Complexity: loglinear, if \c left and \c right are interval containers. */
|
|
template<class LeftT, class RightT>
|
|
typename enable_if<is_inter_combinable<LeftT, RightT>, bool>::type
|
|
disjoint(const LeftT& left, const RightT& right)
|
|
{
|
|
return !intersects(left, right);
|
|
}
|
|
|
|
/** \b Returns true, if \c left and \c right have no common elements.
|
|
Intervals are interpreted as sequence of elements.
|
|
\b Complexity: logarithmic, if \c AssociateT is an element type \c Type::element_type.
|
|
linear, if \c AssociateT is a segment type \c Type::segment_type. */
|
|
template<class Type, class AssociateT>
|
|
typename enable_if<is_inter_derivative<Type, AssociateT>, bool>::type
|
|
disjoint(const Type& left, const AssociateT& right)
|
|
{
|
|
return !intersects(left,right);
|
|
}
|
|
|
|
|
|
//==============================================================================
|
|
//= Symmetric difference<IntervalSet|IntervalSet>
|
|
//==============================================================================
|
|
//------------------------------------------------------------------------------
|
|
//- Symmetric difference ^=, ^
|
|
//------------------------------------------------------------------------------
|
|
//------------------------------------------------------------------------------
|
|
//- T& op ^=(T&, c P&) T:{S}|{M} P:{S'}|{M'}
|
|
//------------------------------------------------------------------------------
|
|
template<class Type, class OperandT>
|
|
typename enable_if<is_intra_combinable<Type, OperandT>, Type>::type&
|
|
operator ^= (Type& object, const OperandT& operand)
|
|
{
|
|
return icl::flip(object, operand);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
//- T& op ^=(T&, c P&) T:{S}|{M} P:{e i}|{b p}
|
|
//------------------------------------------------------------------------------
|
|
template<class Type, class OperandT>
|
|
typename enable_if<is_intra_derivative<Type, OperandT>, Type>::type&
|
|
operator ^= (Type& object, const OperandT& operand)
|
|
{
|
|
return icl::flip(object, operand);
|
|
}
|
|
|
|
#ifdef BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
|
|
//------------------------------------------------------------------------------
|
|
//- T op ^ (T, c P&) T:{S}|{M} P:{e i S'}|{b p M'} S<S' M<M' <:coarser
|
|
//------------------------------------------------------------------------------
|
|
template<class Type, class OperandT>
|
|
typename enable_if<is_binary_intra_combinable<Type, OperandT>, Type>::type
|
|
operator ^ (Type object, const OperandT& operand)
|
|
{
|
|
return object ^= operand;
|
|
}
|
|
|
|
#else //BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
|
|
|
|
template<class Type, class OperandT>
|
|
typename enable_if<is_binary_intra_combinable<Type, OperandT>, Type>::type
|
|
operator ^ (const Type& object, const OperandT& operand)
|
|
{
|
|
Type temp = object;
|
|
return boost::move(temp ^= operand);
|
|
}
|
|
|
|
template<class Type, class OperandT>
|
|
typename enable_if<is_binary_intra_combinable<Type, OperandT>, Type>::type
|
|
operator ^ (Type&& object, const OperandT& operand)
|
|
{
|
|
return boost::move(object ^= operand);
|
|
}
|
|
|
|
#endif //BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
|
|
|
|
#ifdef BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
|
|
//------------------------------------------------------------------------------
|
|
//- T op ^ (c P&, T) T:{S}|{M} P:{e i S'}|{b p M'} S<S' M<M' <:coarser
|
|
//------------------------------------------------------------------------------
|
|
template<class Type, class OperandT>
|
|
typename enable_if<is_binary_intra_combinable<Type, OperandT>, Type>::type
|
|
operator ^ (const OperandT& operand, Type object)
|
|
{
|
|
return object ^= operand;
|
|
}
|
|
|
|
#else //BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
|
|
|
|
template<class Type, class OperandT>
|
|
typename enable_if<is_binary_intra_combinable<Type, OperandT>, Type>::type
|
|
operator ^ (const OperandT& operand, const Type& object)
|
|
{
|
|
Type temp = object;
|
|
return boost::move(temp ^= operand);
|
|
}
|
|
|
|
template<class Type, class OperandT>
|
|
typename enable_if<is_binary_intra_combinable<Type, OperandT>, Type>::type
|
|
operator ^ (const OperandT& operand, Type&& object)
|
|
{
|
|
return boost::move(object ^= operand);
|
|
}
|
|
|
|
#endif //BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
|
|
|
|
#ifdef BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
|
|
//------------------------------------------------------------------------------
|
|
//- T op ^ (T, c T&) T:{S M}
|
|
//------------------------------------------------------------------------------
|
|
template<class Type>
|
|
typename enable_if<is_interval_container<Type>, Type>::type
|
|
operator ^ (typename Type::overloadable_type object, const Type& operand)
|
|
{
|
|
return object ^= operand;
|
|
}
|
|
|
|
#else //BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
|
|
|
|
template<class Type>
|
|
typename enable_if<is_interval_container<Type>, Type>::type
|
|
operator ^ (const Type& object, const Type& operand)
|
|
{
|
|
Type temp = object;
|
|
return boost::move(temp ^= operand);
|
|
}
|
|
|
|
template<class Type>
|
|
typename enable_if<is_interval_container<Type>, Type>::type
|
|
operator ^ (Type&& object, const Type& operand)
|
|
{
|
|
return boost::move(object ^= operand);
|
|
}
|
|
|
|
template<class Type>
|
|
typename enable_if<is_interval_container<Type>, Type>::type
|
|
operator ^ (const Type& operand, Type&& object)
|
|
{
|
|
return boost::move(object ^= operand);
|
|
}
|
|
|
|
template<class Type>
|
|
typename enable_if<is_interval_container<Type>, Type>::type
|
|
operator ^ (Type&& object, Type&& operand)
|
|
{
|
|
return boost::move(object ^= operand);
|
|
}
|
|
|
|
#endif //BOOST_ICL_NO_CXX11_RVALUE_REFERENCES
|
|
|
|
//==========================================================================
|
|
//= Element Iteration <IntervalSet|IntervalMap>
|
|
//==========================================================================
|
|
//--------------------------------------------------------------------------
|
|
//- Forward
|
|
//--------------------------------------------------------------------------
|
|
template<class Type>
|
|
typename enable_if
|
|
<mpl::and_< is_interval_container<Type>
|
|
, mpl::not_<is_continuous_interval<typename Type::interval_type> > >,
|
|
typename Type::element_iterator>::type
|
|
elements_begin(Type& object)
|
|
{
|
|
return typename Type::element_iterator(object.begin());
|
|
}
|
|
|
|
template<class Type>
|
|
typename enable_if
|
|
<mpl::and_< is_interval_container<Type>
|
|
, mpl::not_<is_continuous_interval<typename Type::interval_type> > >,
|
|
typename Type::element_iterator>::type
|
|
elements_end(Type& object)
|
|
{
|
|
return typename Type::element_iterator(object.end());
|
|
}
|
|
|
|
template<class Type>
|
|
typename enable_if
|
|
<mpl::and_< is_interval_container<Type>
|
|
, mpl::not_<is_continuous_interval<typename Type::interval_type> > >,
|
|
typename Type::element_const_iterator>::type
|
|
elements_begin(const Type& object)
|
|
{
|
|
return typename Type::element_const_iterator(object.begin());
|
|
}
|
|
|
|
template<class Type>
|
|
typename enable_if
|
|
<mpl::and_< is_interval_container<Type>
|
|
, mpl::not_<is_continuous_interval<typename Type::interval_type> > >,
|
|
typename Type::element_const_iterator>::type
|
|
elements_end(const Type& object)
|
|
{
|
|
return typename Type::element_const_iterator(object.end());
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
//- Reverse
|
|
//--------------------------------------------------------------------------
|
|
template<class Type>
|
|
typename enable_if
|
|
<mpl::and_< is_interval_container<Type>
|
|
, mpl::not_<is_continuous_interval<typename Type::interval_type> > >,
|
|
typename Type::element_reverse_iterator>::type
|
|
elements_rbegin(Type& object)
|
|
{
|
|
return typename Type::element_reverse_iterator(object.rbegin());
|
|
}
|
|
|
|
template<class Type>
|
|
typename enable_if
|
|
<mpl::and_< is_interval_container<Type>
|
|
, mpl::not_<is_continuous_interval<typename Type::interval_type> > >,
|
|
typename Type::element_reverse_iterator>::type
|
|
elements_rend(Type& object)
|
|
{
|
|
return typename Type::element_reverse_iterator(object.rend());
|
|
}
|
|
|
|
template<class Type>
|
|
typename enable_if
|
|
<mpl::and_< is_interval_container<Type>
|
|
, mpl::not_<is_continuous_interval<typename Type::interval_type> > >,
|
|
typename Type::element_const_reverse_iterator>::type
|
|
elements_rbegin(const Type& object)
|
|
{
|
|
return typename Type::element_const_reverse_iterator(object.rbegin());
|
|
}
|
|
|
|
template<class Type>
|
|
typename enable_if
|
|
<mpl::and_< is_interval_container<Type>
|
|
, mpl::not_<is_continuous_interval<typename Type::interval_type> > >,
|
|
typename Type::element_const_reverse_iterator>::type
|
|
elements_rend(const Type& object)
|
|
{
|
|
return typename Type::element_const_reverse_iterator(object.rend());
|
|
}
|
|
|
|
}} // namespace boost icl
|
|
|
|
#endif
|
|
|
|
|