123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648 |
- /*-----------------------------------------------------------------------------+
- Copyright (c) 2008-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_INTERVAL_SET_ALGO_HPP_JOFA_081005
- #define BOOST_ICL_INTERVAL_SET_ALGO_HPP_JOFA_081005
- #include <boost/next_prior.hpp>
- #include <boost/icl/detail/notate.hpp>
- #include <boost/icl/detail/relation_state.hpp>
- #include <boost/icl/type_traits/identity_element.hpp>
- #include <boost/icl/type_traits/is_map.hpp>
- #include <boost/icl/type_traits/is_total.hpp>
- #include <boost/icl/type_traits/is_combinable.hpp>
- #include <boost/icl/concept/set_value.hpp>
- #include <boost/icl/concept/map_value.hpp>
- #include <boost/icl/interval_combining_style.hpp>
- #include <boost/icl/detail/element_comparer.hpp>
- #include <boost/icl/detail/interval_subset_comparer.hpp>
- #include <boost/icl/detail/associated_value.hpp>
- namespace boost{namespace icl
- {
- namespace Interval_Set
- {
- //------------------------------------------------------------------------------
- // Lexicographical comparison on ranges of two interval container
- //------------------------------------------------------------------------------
- template<class LeftT, class RightT>
- bool is_element_equal(const LeftT& left, const RightT& right)
- {
- return subset_compare
- (
- left, right,
- left.begin(), left.end(),
- right.begin(), right.end()
- ) == inclusion::equal;
- }
- template<class LeftT, class RightT>
- bool is_element_less(const LeftT& left, const RightT& right)
- {
- return element_compare
- (
- left, right,
- left.begin(), left.end(),
- right.begin(), right.end()
- ) == comparison::less;
- }
- template<class LeftT, class RightT>
- bool is_element_greater(const LeftT& left, const RightT& right)
- {
- return element_compare
- (
- left, right,
- left.begin(), left.end(),
- right.begin(), right.end()
- ) == comparison::greater;
- }
- //------------------------------------------------------------------------------
- // Subset/superset compare on ranges of two interval container
- //------------------------------------------------------------------------------
- template<class IntervalContainerT>
- bool is_joinable(const IntervalContainerT& container,
- typename IntervalContainerT::const_iterator first,
- typename IntervalContainerT::const_iterator past)
- {
- if(first == container.end())
- return true;
- typename IntervalContainerT::const_iterator it_ = first, next_ = first;
- ++next_;
- while(next_ != container.end() && it_ != past)
- if(!icl::touches(key_value<IntervalContainerT>(it_++),
- key_value<IntervalContainerT>(next_++)))
- return false;
- return true;
- }
- template<class LeftT, class RightT>
- bool is_inclusion_equal(const LeftT& left, const RightT& right)
- {
- return subset_compare
- (
- left, right,
- left.begin(), left.end(),
- right.begin(), right.end()
- ) == inclusion::equal;
- }
- template<class LeftT, class RightT>
- typename enable_if<mpl::and_<is_concept_combinable<is_interval_set, is_interval_map, LeftT, RightT>,
- is_total<RightT> >,
- bool>::type
- within(const LeftT&, const RightT&)
- {
- return true;
- }
- template<class LeftT, class RightT>
- typename enable_if<mpl::and_<is_concept_combinable<is_interval_set, is_interval_map, LeftT, RightT>,
- mpl::not_<is_total<RightT> > >,
- bool>::type
- within(const LeftT& sub, const RightT& super)
- {
- int result =
- subset_compare
- (
- sub, super,
- sub.begin(), sub.end(),
- super.begin(), super.end()
- );
- return result == inclusion::subset || result == inclusion::equal;
- }
- template<class LeftT, class RightT>
- typename enable_if<is_concept_combinable<is_interval_map, is_interval_map, LeftT, RightT>,
- bool>::type
- within(const LeftT& sub, const RightT& super)
- {
- int result =
- subset_compare
- (
- sub, super,
- sub.begin(), sub.end(),
- super.begin(), super.end()
- );
- return result == inclusion::subset || result == inclusion::equal;
- }
- template<class LeftT, class RightT>
- typename enable_if<is_concept_combinable<is_interval_set, is_interval_set, LeftT, RightT>,
- bool>::type
- within(const LeftT& sub, const RightT& super)
- {
- int result =
- subset_compare
- (
- sub, super,
- sub.begin(), sub.end(),
- super.begin(), super.end()
- );
- return result == inclusion::subset || result == inclusion::equal;
- }
- template<class LeftT, class RightT>
- typename enable_if<mpl::and_<is_concept_combinable<is_interval_map, is_interval_set, LeftT, RightT>,
- is_total<LeftT> >,
- bool>::type
- contains(const LeftT&, const RightT&)
- {
- return true;
- }
- template<class LeftT, class RightT>
- typename enable_if<mpl::and_<is_concept_combinable<is_interval_map, is_interval_set, LeftT, RightT>,
- mpl::not_<is_total<LeftT> > >,
- bool>::type
- contains(const LeftT& super, const RightT& sub)
- {
- int result =
- subset_compare
- (
- super, sub,
- super.begin(), super.end(),
- sub.begin(), sub.end()
- );
- return result == inclusion::superset || result == inclusion::equal;
- }
- template<class LeftT, class RightT>
- typename enable_if<is_concept_combinable<is_interval_set, is_interval_set, LeftT, RightT>,
- bool>::type
- contains(const LeftT& super, const RightT& sub)
- {
- int result =
- subset_compare
- (
- super, sub,
- super.begin(), super.end(),
- sub.begin(), sub.end()
- );
- return result == inclusion::superset || result == inclusion::equal;
- }
- template<class IntervalContainerT>
- bool is_dense(const IntervalContainerT& container,
- typename IntervalContainerT::const_iterator first,
- typename IntervalContainerT::const_iterator past)
- {
- if(first == container.end())
- return true;
- typename IntervalContainerT::const_iterator it_ = first, next_ = first;
- ++next_;
- while(next_ != container.end() && it_ != past)
- if(!icl::touches(key_value<IntervalContainerT>(it_++),
- key_value<IntervalContainerT>(next_++)))
- return false;
- return true;
- }
- } // namespace Interval_Set
- namespace segmental
- {
- template<class Type>
- inline bool joinable(const Type& _Type, typename Type::iterator& some, typename Type::iterator& next)
- {
- // assert: next != end && some++ == next
- return touches(key_value<Type>(some), key_value<Type>(next))
- && co_equal(some, next, &_Type, &_Type);
- }
- template<class Type>
- inline void join_nodes(Type& object, typename Type::iterator& left_,
- typename Type::iterator& right_)
- {
- typedef typename Type::interval_type interval_type;
- interval_type right_interval = key_value<Type>(right_);
- object.erase(right_);
- const_cast<interval_type&>(key_value<Type>(left_))
- = hull(key_value<Type>(left_), right_interval);
- }
- template<class Type>
- inline typename Type::iterator
- join_on_left(Type& object, typename Type::iterator& left_,
- typename Type::iterator& right_)
- {
- //CL typedef typename Type::interval_type interval_type;
- // both left and right are in the set and they are neighbours
- BOOST_ASSERT(exclusive_less(key_value<Type>(left_), key_value<Type>(right_)));
- BOOST_ASSERT(joinable(object, left_, right_));
- join_nodes(object, left_, right_);
- return left_;
- }
- template<class Type>
- inline typename Type::iterator
- join_on_right(Type& object, typename Type::iterator& left_,
- typename Type::iterator& right_)
- {
- //CL typedef typename Type::interval_type interval_type;
- // both left and right are in the map and they are neighbours
- BOOST_ASSERT(exclusive_less(key_value<Type>(left_), key_value<Type>(right_)));
- BOOST_ASSERT(joinable(object, left_, right_));
- join_nodes(object, left_, right_);
- right_ = left_;
- return right_;
- }
- template<class Type>
- typename Type::iterator join_left(Type& object, typename Type::iterator& it_)
- {
- typedef typename Type::iterator iterator;
- if(it_ == object.begin())
- return it_;
- // there is a predecessor
- iterator pred_ = it_;
- if(joinable(object, --pred_, it_))
- return join_on_right(object, pred_, it_);
- return it_;
- }
- template<class Type>
- typename Type::iterator join_right(Type& object, typename Type::iterator& it_)
- {
- typedef typename Type::iterator iterator;
- if(it_ == object.end())
- return it_;
- // there is a successor
- iterator succ_ = it_;
- if(++succ_ != object.end() && joinable(object, it_, succ_))
- return join_on_left(object, it_, succ_);
- return it_;
- }
- template<class Type>
- typename Type::iterator join_neighbours(Type& object, typename Type::iterator& it_)
- {
- join_left (object, it_);
- return join_right(object, it_);
- }
- template<class Type>
- inline typename Type::iterator
- join_under(Type& object, const typename Type::value_type& addend)
- {
- //ASSERT: There is at least one interval in object that overlaps with addend
- typedef typename Type::iterator iterator;
- typedef typename Type::interval_type interval_type;
- typedef typename Type::value_type value_type;
- std::pair<iterator,iterator> overlap = object.equal_range(addend);
- iterator first_ = overlap.first,
- end_ = overlap.second,
- last_ = end_; --last_;
- iterator second_= first_; ++second_;
- interval_type left_resid = right_subtract(key_value<Type>(first_), addend);
- interval_type right_resid = left_subtract(key_value<Type>(last_) , addend);
- object.erase(second_, end_);
- const_cast<value_type&>(key_value<Type>(first_))
- = hull(hull(left_resid, addend), right_resid);
- return first_;
- }
- template<class Type>
- inline typename Type::iterator
- join_under(Type& object, const typename Type::value_type& addend,
- typename Type::iterator last_)
- {
- //ASSERT: There is at least one interval in object that overlaps with addend
- typedef typename Type::iterator iterator;
- typedef typename Type::interval_type interval_type;
- typedef typename Type::value_type value_type;
- iterator first_ = object.lower_bound(addend);
- //BOOST_ASSERT(next(last_) == this->_set.upper_bound(inter_val));
- iterator second_= boost::next(first_), end_ = boost::next(last_);
- interval_type left_resid = right_subtract(key_value<Type>(first_), addend);
- interval_type right_resid = left_subtract(key_value<Type>(last_) , addend);
- object.erase(second_, end_);
- const_cast<value_type&>(key_value<Type>(first_))
- = hull(hull(left_resid, addend), right_resid);
- return first_;
- }
- } // namespace segmental
- namespace Interval_Set
- {
- using namespace segmental;
- template<class Type, int combining_style>
- struct on_style;
- template<class Type>
- struct on_style<Type, interval_combine::joining>
- {
- typedef on_style type;
- typedef typename Type::interval_type interval_type;
- typedef typename Type::iterator iterator;
- inline static iterator handle_inserted(Type& object, iterator inserted_)
- { return join_neighbours(object, inserted_); }
- inline static iterator add_over
- (Type& object, const interval_type& addend, iterator last_)
- {
- iterator joined_ = join_under(object, addend, last_);
- return join_neighbours(object, joined_);
- }
- inline static iterator add_over
- (Type& object, const interval_type& addend)
- {
- iterator joined_ = join_under(object, addend);
- return join_neighbours(object, joined_);
- }
- };
- template<class Type>
- struct on_style<Type, interval_combine::separating>
- {
- typedef on_style type;
- typedef typename Type::interval_type interval_type;
- typedef typename Type::iterator iterator;
- inline static iterator handle_inserted(Type&, iterator inserted_)
- { return inserted_; }
- inline static iterator add_over
- (Type& object, const interval_type& addend, iterator last_)
- {
- return join_under(object, addend, last_);
- }
- inline static iterator add_over
- (Type& object, const interval_type& addend)
- {
- return join_under(object, addend);
- }
- };
- template<class Type>
- struct on_style<Type, interval_combine::splitting>
- {
- typedef on_style type;
- typedef typename Type::interval_type interval_type;
- typedef typename Type::iterator iterator;
- inline static iterator handle_inserted(Type&, iterator inserted_)
- { return inserted_; }
- inline static iterator add_over
- (Type& object, const interval_type& addend, iterator last_)
- {
- iterator first_ = object.lower_bound(addend);
- //BOOST_ASSERT(next(last_) == this->_set.upper_bound(inter_val));
- iterator it_ = first_;
- interval_type rest_interval = addend;
- add_front(object, rest_interval, it_);
- add_main (object, rest_interval, it_, last_);
- add_rear (object, rest_interval, it_);
- return it_;
- }
- inline static iterator add_over
- (Type& object, const interval_type& addend)
- {
- std::pair<iterator,iterator> overlap = object.equal_range(addend);
- iterator first_ = overlap.first,
- end_ = overlap.second,
- last_ = end_; --last_;
- iterator it_ = first_;
- interval_type rest_interval = addend;
- add_front(object, rest_interval, it_);
- add_main (object, rest_interval, it_, last_);
- add_rear (object, rest_interval, it_);
- return it_;
- }
- };
- template<class Type>
- void add_front(Type& object, const typename Type::interval_type& inter_val,
- typename Type::iterator& first_)
- {
- typedef typename Type::interval_type interval_type;
- typedef typename Type::iterator iterator;
- // If the collision sequence has a left residual 'left_resid' it will
- // be split, to provide a standardized start of algorithms:
- // The addend interval 'inter_val' covers the beginning of the collision sequence.
- // only for the first there can be a left_resid: a part of *first_ left of inter_val
- interval_type left_resid = right_subtract(key_value<Type>(first_), inter_val);
- if(!icl::is_empty(left_resid))
- { // [------------ . . .
- // [left_resid---first_ --- . . .
- iterator prior_ = cyclic_prior(object, first_);
- const_cast<interval_type&>(key_value<Type>(first_))
- = left_subtract(key_value<Type>(first_), left_resid);
- //NOTE: Only splitting
- object._insert(prior_, icl::make_value<Type>(left_resid, co_value<Type>(first_)));
- }
- //POST:
- // [----- inter_val ---- . . .
- // ...[-- first_ --...
- }
- template<class Type>
- void add_segment(Type& object, const typename Type::interval_type& inter_val,
- typename Type::iterator& it_ )
- {
- typedef typename Type::interval_type interval_type;
- interval_type lead_gap = right_subtract(inter_val, *it_);
- if(!icl::is_empty(lead_gap))
- // [lead_gap--- . . .
- // [prior_) [-- it_ ...
- object._insert(prior(it_), lead_gap);
- // . . . --------- . . . addend interval
- // [-- it_ --) has a common part with the first overval
- ++it_;
- }
- template<class Type>
- void add_main(Type& object, typename Type::interval_type& rest_interval,
- typename Type::iterator& it_,
- const typename Type::iterator& last_)
- {
- typedef typename Type::interval_type interval_type;
- interval_type cur_interval;
- while(it_ != last_)
- {
- cur_interval = *it_ ;
- add_segment(object, rest_interval, it_);
- // shrink interval
- rest_interval = left_subtract(rest_interval, cur_interval);
- }
- }
- template<class Type>
- void add_rear(Type& object, const typename Type::interval_type& inter_val,
- typename Type::iterator& it_ )
- {
- typedef typename Type::interval_type interval_type;
- typedef typename Type::iterator iterator;
- iterator prior_ = cyclic_prior(object, it_);
- interval_type cur_itv = *it_;
- interval_type lead_gap = right_subtract(inter_val, cur_itv);
- if(!icl::is_empty(lead_gap))
- // [lead_gap--- . . .
- // [prior_) [-- it_ ...
- object._insert(prior_, lead_gap);
-
- interval_type end_gap = left_subtract(inter_val, cur_itv);
- if(!icl::is_empty(end_gap))
- // [---------------end_gap)
- // [-- it_ --)
- it_ = object._insert(it_, end_gap);
- else
- {
- // only for the last there can be a right_resid: a part of *it_ right of addend
- interval_type right_resid = left_subtract(cur_itv, inter_val);
- if(!icl::is_empty(right_resid))
- {
- // [--------------)
- // [-- it_ --right_resid)
- const_cast<interval_type&>(*it_) = right_subtract(*it_, right_resid);
- it_ = object._insert(it_, right_resid);
- }
- }
- }
- //==============================================================================
- //= Addition
- //==============================================================================
- template<class Type>
- typename Type::iterator
- add(Type& object, const typename Type::value_type& addend)
- {
- //CL typedef typename Type::interval_type interval_type;
- typedef typename Type::iterator iterator;
- typedef typename on_style<Type, Type::fineness>::type on_style_;
- if(icl::is_empty(addend))
- return object.end();
- std::pair<iterator,bool> insertion = object._insert(addend);
- if(insertion.second)
- return on_style_::handle_inserted(object, insertion.first);
- else
- return on_style_::add_over(object, addend, insertion.first);
- }
- template<class Type>
- typename Type::iterator
- add(Type& object, typename Type::iterator prior_,
- const typename Type::value_type& addend)
- {
- //CL typedef typename Type::interval_type interval_type;
- typedef typename Type::iterator iterator;
- typedef typename on_style<Type, Type::fineness>::type on_style_;
- if(icl::is_empty(addend))
- return prior_;
- iterator insertion = object._insert(prior_, addend);
- if(*insertion == addend)
- return on_style_::handle_inserted(object, insertion);
- else
- return on_style_::add_over(object, addend);
- }
- //==============================================================================
- //= Subtraction
- //==============================================================================
- template<class Type>
- void subtract(Type& object, const typename Type::value_type& minuend)
- {
- typedef typename Type::iterator iterator;
- typedef typename Type::interval_type interval_type;
- //CL typedef typename Type::value_type value_type;
- if(icl::is_empty(minuend)) return;
- std::pair<iterator, iterator> exterior = object.equal_range(minuend);
- if(exterior.first == exterior.second) return;
- iterator first_ = exterior.first;
- iterator end_ = exterior.second;
- iterator last_ = end_; --last_;
- interval_type leftResid = right_subtract(*first_, minuend);
- interval_type rightResid;
- if(first_ != end_ )
- rightResid = left_subtract(*last_ , minuend);
- object.erase(first_, end_);
- if(!icl::is_empty(leftResid))
- object._insert(leftResid);
- if(!icl::is_empty(rightResid))
- object._insert(rightResid);
- }
- } // namespace Interval_Set
- }} // namespace icl boost
- #endif
|