interval_subset_comparer.hpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  1. /*-----------------------------------------------------------------------------+
  2. Copyright (c) 2008-2009: Joachim Faulhaber
  3. +------------------------------------------------------------------------------+
  4. Distributed under the Boost Software License, Version 1.0.
  5. (See accompanying file LICENCE.txt or copy at
  6. http://www.boost.org/LICENSE_1_0.txt)
  7. +-----------------------------------------------------------------------------*/
  8. #ifndef BOOST_ICL_INTERVAL_SUBSET_COMPARER_HPP_JOFA_090827
  9. #define BOOST_ICL_INTERVAL_SUBSET_COMPARER_HPP_JOFA_090827
  10. #include <boost/icl/type_traits/is_map.hpp>
  11. #include <boost/icl/detail/notate.hpp>
  12. #include <boost/icl/detail/relation_state.hpp>
  13. #include <boost/icl/type_traits/identity_element.hpp>
  14. #include <boost/icl/type_traits/is_concept_equivalent.hpp>
  15. #include <boost/icl/type_traits/is_interval_container.hpp>
  16. #include <boost/icl/type_traits/is_set.hpp>
  17. #include <boost/icl/concept/interval_set_value.hpp>
  18. namespace boost{namespace icl
  19. {
  20. #ifdef BOOST_MSVC
  21. #pragma warning(push)
  22. #pragma warning(disable:4127) // conditional expression is constant
  23. #endif
  24. namespace Interval_Set
  25. {
  26. //------------------------------------------------------------------------------
  27. template<class LeftT, class RightT>
  28. struct settic_codomain_compare
  29. {
  30. static int apply(typename LeftT::const_iterator& left_, typename RightT::const_iterator& right_)
  31. {
  32. return inclusion_compare( icl::co_value<LeftT>(left_),
  33. icl::co_value<RightT>(right_));
  34. }
  35. };
  36. template<class LeftT, class RightT>
  37. struct atomic_codomain_compare
  38. {
  39. static int apply(typename LeftT::const_iterator& left_, typename RightT::const_iterator& right_)
  40. {
  41. if(icl::co_value<LeftT>(left_) == icl::co_value<RightT>(right_))
  42. return inclusion::equal;
  43. else
  44. return inclusion::unrelated;
  45. }
  46. };
  47. template<class LeftT, class RightT>
  48. struct empty_codomain_compare
  49. {
  50. static int apply(typename LeftT::const_iterator&, typename RightT::const_iterator)
  51. {
  52. return inclusion::equal;
  53. }
  54. };
  55. template<class LeftT, class RightT>
  56. struct map_codomain_compare
  57. {
  58. static int apply(typename LeftT::const_iterator& left_, typename RightT::const_iterator& right_)
  59. {
  60. using namespace boost::mpl;
  61. typedef typename LeftT::codomain_type LeftCodomainT;
  62. typedef typename RightT::codomain_type RightCodomainT;
  63. return
  64. if_<
  65. bool_<is_concept_equivalent<is_set,LeftCodomainT,
  66. RightCodomainT>::value>,
  67. settic_codomain_compare<LeftT,RightT>,
  68. atomic_codomain_compare<LeftT,RightT>
  69. >
  70. ::type::apply(left_, right_);
  71. }
  72. };
  73. //------------------------------------------------------------------------------
  74. template<class LeftT, class RightT>
  75. class subset_comparer
  76. {
  77. private:
  78. subset_comparer& operator = (const subset_comparer&);
  79. public:
  80. typedef typename LeftT::const_iterator LeftIterT;
  81. typedef typename RightT::const_iterator RightIterT;
  82. BOOST_STATIC_CONSTANT(bool,
  83. _compare_codomain = (mpl::and_<is_map<LeftT>, is_map<RightT> >::value));
  84. subset_comparer(const LeftT& left,
  85. const RightT& right,
  86. const LeftIterT& left_end,
  87. const RightIterT& right_end)
  88. : _left(left), _right(right),
  89. _left_end(left_end), _right_end(right_end), _result(equal)
  90. {}
  91. enum{nextboth, nextleft, nextright, stop};
  92. enum
  93. {
  94. unrelated = inclusion::unrelated,
  95. subset = inclusion::subset, // left is_subset_of right
  96. superset = inclusion::superset, // left is_superset_of right
  97. equal = inclusion::equal // equal = subset | superset
  98. };
  99. int result()const{ return _result; }
  100. int co_compare(LeftIterT& left, RightIterT& right)
  101. {
  102. using namespace boost::mpl;
  103. return
  104. if_<
  105. bool_<is_concept_equivalent<is_interval_map,LeftT,RightT>::value>,
  106. map_codomain_compare<LeftT,RightT>,
  107. empty_codomain_compare<LeftT,RightT>
  108. >
  109. ::type::apply(left,right);
  110. }
  111. int restrict_result(int state) { return _result &= state; }
  112. int proceed(LeftIterT& left, RightIterT& right)
  113. {
  114. if(upper_less(key_value<LeftT>(left), key_value<RightT>(right)))
  115. { // left ..)
  116. // right .....)
  117. _prior_left = left;
  118. ++left;
  119. return nextleft;
  120. }
  121. else if(upper_less(key_value<RightT>(right), key_value<LeftT>(left)))
  122. { // left .....)
  123. // right ..)
  124. _prior_right = right;
  125. ++right;
  126. return nextright;
  127. }
  128. else//key_value<LeftT>(left).upper_equal(key_value<RightT>(right))
  129. { // left ..)
  130. // right ..)
  131. ++left;
  132. ++right;
  133. return nextboth;
  134. }
  135. }
  136. int next_both(LeftIterT& left, RightIterT& right)
  137. {
  138. if(left == _left_end && right == _right_end)
  139. return stop;
  140. else if(left == _left_end)
  141. { // left: ....end left could be subset
  142. // right:....[..
  143. restrict_result(subset);
  144. return stop;
  145. }
  146. else if(right == _right_end)
  147. { // left: ....[.. left could be superset
  148. // right:....end
  149. restrict_result(superset);
  150. return stop;
  151. }
  152. else if(exclusive_less(key_value<LeftT>(left), key_value<RightT>(right)))
  153. { // left: [..) . . .[---) left could be superset
  154. // right: [..).... if [---) exists
  155. restrict_result(superset);
  156. if(unrelated == _result)
  157. return stop;
  158. else
  159. {
  160. LeftIterT joint_ = _left.lower_bound(key_value<RightT>(right));
  161. if(joint_ == _left.end())
  162. {
  163. _result = unrelated;
  164. return stop;
  165. }
  166. else
  167. {
  168. left = joint_;
  169. return nextboth;
  170. }
  171. }
  172. }
  173. else if(exclusive_less(key_value<RightT>(right), key_value<LeftT>(left)))
  174. { // left: [.. left could be subset
  175. // right:....) . . .[---) if [---) exists
  176. restrict_result(subset);
  177. if(unrelated == _result)
  178. return stop;
  179. else
  180. {
  181. RightIterT joint_ = _right.lower_bound(key_value<LeftT>(left));
  182. if(joint_ == _right.end())
  183. {
  184. _result = unrelated;
  185. return stop;
  186. }
  187. else
  188. {
  189. right = joint_;
  190. return nextboth;
  191. }
  192. }
  193. }
  194. // left and right have intervals with nonempty intersection:
  195. if(_compare_codomain)
  196. if(unrelated == restrict_result(co_compare(left,right)))
  197. return stop;
  198. // examine left borders only. Right borders are checked in proceed
  199. if(lower_less(key_value<LeftT>(left), key_value<RightT>(right)))
  200. { // left: ....[... left could be superset
  201. // right:.... [..
  202. if(unrelated == restrict_result(superset))
  203. return stop;
  204. }
  205. else if(lower_less(key_value<RightT>(right), key_value<LeftT>(left)))
  206. { // left: .... [.. left can be subset
  207. // right:....[...
  208. if(unrelated == restrict_result(subset))
  209. return stop;
  210. }
  211. //else key_value<LeftT>(right).lower_equal(key_value<RightT>(left))
  212. // left: ....[.. both can be equal
  213. // right:....[..
  214. // nothing to do: proceed
  215. return proceed(left, right);
  216. }
  217. int next_left(LeftIterT& left, RightIterT& right)
  218. {
  219. if(left == _left_end)
  220. { // left: ..)end left could be subset
  221. // right:......)
  222. restrict_result(subset);
  223. return stop;
  224. }
  225. else if(!touches(key_value<LeftT>(_prior_left), key_value<LeftT>(left)))
  226. { // left: ..) [..
  227. // right:.........)
  228. if(lower_less(key_value<RightT>(right), key_value<LeftT>(left)))
  229. { // ..) [.. left could be subset
  230. // ..........)
  231. if(unrelated == restrict_result(subset))
  232. return stop;
  233. }
  234. //else ..) [...
  235. // [..
  236. if(_compare_codomain && intersects(key_value<LeftT>(left),key_value<RightT>(right)) )
  237. if(unrelated == restrict_result(co_compare(left,right)))
  238. return stop;
  239. }
  240. else
  241. { // left: ..)[.. left could be subset
  242. // right:.......)
  243. if(_compare_codomain && intersects(key_value<LeftT>(left), key_value<RightT>(right)) )
  244. if(unrelated == restrict_result(co_compare(left,right)))
  245. return stop;
  246. }
  247. return proceed(left, right);
  248. }
  249. int next_right(LeftIterT& left, RightIterT& right)
  250. {
  251. if(right == _right_end)
  252. { // left: ......) left could be superset
  253. // right:..)end
  254. restrict_result(superset);
  255. return stop;
  256. }
  257. else if(!touches(key_value<RightT>(_prior_right), key_value<RightT>(right)))
  258. { // left: .........)
  259. // right:..) [..
  260. if(lower_less(key_value<LeftT>(left), key_value<RightT>(right)))
  261. { // [....) left could be superset
  262. // ..) [..
  263. if(unrelated == restrict_result(superset))
  264. return stop;
  265. }
  266. //else [....)
  267. // ..) [..
  268. if(_compare_codomain && intersects(key_value<LeftT>(left), key_value<RightT>(right)) )
  269. if(unrelated == restrict_result(co_compare(left,right)))
  270. return stop;
  271. }
  272. else
  273. {
  274. if(_compare_codomain && intersects(key_value<LeftT>(left), key_value<RightT>(right)) )
  275. if(unrelated == restrict_result(co_compare(left,right)))
  276. return stop;
  277. }
  278. return proceed(left, right);
  279. }
  280. private:
  281. const LeftT& _left;
  282. const RightT& _right;
  283. LeftIterT _left_end;
  284. RightIterT _right_end;
  285. LeftIterT _prior_left;
  286. RightIterT _prior_right;
  287. int _result;
  288. };
  289. //------------------------------------------------------------------------------
  290. // Subset/superset comparison on ranges of two interval container
  291. //------------------------------------------------------------------------------
  292. template<class LeftT, class RightT>
  293. int subset_compare
  294. (
  295. const LeftT& left, //sub
  296. const RightT& right, //super
  297. typename LeftT::const_iterator left_begin,
  298. typename LeftT::const_iterator left_end,
  299. typename RightT::const_iterator right_begin,
  300. typename RightT::const_iterator right_end
  301. )
  302. {
  303. typedef subset_comparer<LeftT,RightT> Step;
  304. Step step(left, right, left_end, right_end);
  305. typename LeftT::const_iterator left_ = left_begin;
  306. typename RightT::const_iterator right_ = right_begin;
  307. int state = Step::nextboth;
  308. while(state != Step::stop)
  309. {
  310. switch(state){
  311. case Step::nextboth: state = step.next_both(left_, right_); break;
  312. case Step::nextleft: state = step.next_left(left_, right_); break;
  313. case Step::nextright: state = step.next_right(left_, right_); break;
  314. }
  315. }
  316. return step.result();
  317. }
  318. } // namespace Interval_Set
  319. #ifdef BOOST_MSVC
  320. #pragma warning(pop)
  321. #endif
  322. }} // namespace icl boost
  323. #endif