element_comparer.hpp 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  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_ELEMENT_COMPARER_HPP_JOFA_090202
  9. #define BOOST_ICL_ELEMENT_COMPARER_HPP_JOFA_090202
  10. #include <boost/mpl/and.hpp>
  11. #include <boost/icl/type_traits/is_map.hpp>
  12. #include <boost/icl/detail/notate.hpp>
  13. #include <boost/icl/type_traits/identity_element.hpp>
  14. namespace boost{namespace icl
  15. {
  16. namespace Interval_Set
  17. {
  18. template<class LeftT, class RightT>
  19. class element_comparer
  20. {
  21. public:
  22. typedef typename LeftT::const_iterator LeftIterT;
  23. typedef typename RightT::const_iterator RightIterT;
  24. BOOST_STATIC_CONSTANT(bool,
  25. _compare_codomain = (mpl::and_<is_map<LeftT>, is_map<RightT> >::value));
  26. element_comparer(const LeftT& left,
  27. const RightT& right,
  28. const LeftIterT& left_end,
  29. const RightIterT& right_end)
  30. : _left(left), _right(right),
  31. _left_end(left_end), _right_end(right_end), _result(equal)
  32. {}
  33. enum{nextboth, nextleft, nextright, stop};
  34. enum
  35. {
  36. less = comparison::less,
  37. equal = comparison::equal,
  38. greater = comparison::greater
  39. };
  40. int result()const{ return _result; }
  41. bool covalues_are_equal(LeftIterT& left, RightIterT& right)
  42. {
  43. if(co_value<LeftT>(left) < co_value<RightT>(right))
  44. _result = less;
  45. if(co_value<RightT>(right) < co_value<LeftT>(left))
  46. _result = greater;
  47. return _result == equal;
  48. }
  49. int proceed(LeftIterT& left, RightIterT& right)
  50. {
  51. if(upper_less(key_value<LeftT>(left), key_value<RightT>(right)))
  52. {
  53. _prior_left = left;
  54. ++left;
  55. return nextleft;
  56. }
  57. else if(upper_less(key_value<RightT>(right), key_value<LeftT>(left)))
  58. {
  59. _prior_right = right;
  60. ++right;
  61. return nextright;
  62. }
  63. else
  64. {
  65. ++left;
  66. ++right;
  67. return nextboth;
  68. }
  69. }
  70. int next_both(LeftIterT& left, RightIterT& right)
  71. {
  72. if(left == _left_end)
  73. {
  74. _result = (right == _right_end) ? equal : less;
  75. return stop;
  76. }
  77. // left != _left_end
  78. if(right == _right_end)
  79. {
  80. _result = greater;
  81. return stop;
  82. }
  83. // The starting intervals have to begin equally
  84. if(lower_less(key_value<LeftT>(left), key_value<RightT>(right)))
  85. { // left: same A... = sameA...
  86. // right:same B.. = sameB...
  87. _result = less;
  88. return stop;
  89. }
  90. if(lower_less(key_value<LeftT>(right), key_value<RightT>(left)))
  91. { // left: same B.. = sameB...
  92. // right:same A... = sameA...
  93. _result = greater;
  94. return stop;
  95. }
  96. if(_compare_codomain && !covalues_are_equal(left, right))
  97. return stop;
  98. return proceed(left, right);
  99. }
  100. int next_left(LeftIterT& left, RightIterT& right)
  101. {
  102. if(left == _left_end)
  103. { // left: same
  104. // right:sameA...
  105. _result = less;
  106. return stop;
  107. }
  108. if(!key_value<LeftT>(_prior_left).touches(key_value<LeftT>(left)))
  109. { // left: same B = sameB...
  110. // right:sameA = sameA...
  111. _result = greater;
  112. return stop;
  113. }
  114. if(_compare_codomain && !covalues_are_equal(left, right))
  115. return stop;
  116. return proceed(left, right);
  117. }
  118. int next_right(LeftIterT& left, RightIterT& right)
  119. {
  120. if(right == _right_end)
  121. { // left: sameA...
  122. // right:same
  123. _result = greater;
  124. return stop;
  125. }
  126. if(!key_value<RightT>(_prior_right).touches(key_value<RightT>(right)))
  127. {
  128. // left: sameA... = sameA...
  129. // right:same B.. = sameB...
  130. _result = less;
  131. return stop;
  132. }
  133. if(_compare_codomain && !covalues_are_equal(left, right))
  134. return stop;
  135. return proceed(left, right);
  136. }
  137. private:
  138. const LeftT& _left;
  139. const RightT& _right;
  140. LeftIterT _left_end;
  141. RightIterT _right_end;
  142. LeftIterT _prior_left;
  143. RightIterT _prior_right;
  144. int _result;
  145. };
  146. template<class LeftT, class RightT>
  147. int element_compare
  148. (
  149. const LeftT& left, //sub
  150. const RightT& right, //super
  151. typename LeftT::const_iterator left_begin,
  152. typename LeftT::const_iterator left_end,
  153. typename RightT::const_iterator right_begin,
  154. typename RightT::const_iterator right_end
  155. )
  156. {
  157. typedef element_comparer<LeftT,RightT> Step;
  158. Step step(left, right, left_end, right_end);
  159. typename LeftT::const_iterator left_ = left_begin;
  160. typename RightT::const_iterator right_ = right_begin;
  161. int state = Step::nextboth;
  162. while(state != Step::stop)
  163. {
  164. switch(state){
  165. case Step::nextboth: state = step.next_both (left_, right_); break;
  166. case Step::nextleft: state = step.next_left (left_, right_); break;
  167. case Step::nextright: state = step.next_right(left_, right_); break;
  168. }
  169. }
  170. return step.result();
  171. }
  172. } // namespace Interval_Set
  173. }} // namespace icl boost
  174. #endif