heap_comparison.hpp 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. // boost heap: heap node helper classes
  2. //
  3. // Copyright (C) 2010 Tim Blechmann
  4. //
  5. // Distributed under the Boost Software License, Version 1.0. (See
  6. // accompanying file LICENSE_1_0.txt or copy at
  7. // http://www.boost.org/LICENSE_1_0.txt)
  8. #ifndef BOOST_HEAP_DETAIL_HEAP_COMPARISON_HPP
  9. #define BOOST_HEAP_DETAIL_HEAP_COMPARISON_HPP
  10. #include <boost/assert.hpp>
  11. #include <boost/concept/assert.hpp>
  12. #include <boost/heap/heap_concepts.hpp>
  13. #include <boost/static_assert.hpp>
  14. #include <boost/type_traits/conditional.hpp>
  15. #ifdef BOOST_HEAP_SANITYCHECKS
  16. # define BOOST_HEAP_ASSERT BOOST_ASSERT
  17. #else
  18. # define BOOST_HEAP_ASSERT( expression ) static_assert( true, "force semicolon" )
  19. #endif
  20. namespace boost { namespace heap { namespace detail {
  21. template < typename Heap1, typename Heap2 >
  22. bool value_equality( Heap1 const& lhs, Heap2 const& rhs, typename Heap1::value_type lval, typename Heap2::value_type rval )
  23. {
  24. (void)rhs;
  25. typename Heap1::value_compare const& cmp = lhs.value_comp();
  26. bool ret = !( cmp( lval, rval ) ) && !( cmp( rval, lval ) );
  27. // if this assertion is triggered, the value_compare objects of lhs and rhs return different values
  28. BOOST_ASSERT( ( ret == ( !( rhs.value_comp()( lval, rval ) ) && !( rhs.value_comp()( rval, lval ) ) ) ) );
  29. return ret;
  30. }
  31. template < typename Heap1, typename Heap2 >
  32. bool value_compare( Heap1 const& lhs, Heap2 const& rhs, typename Heap1::value_type lval, typename Heap2::value_type rval )
  33. {
  34. (void)rhs;
  35. typename Heap1::value_compare const& cmp = lhs.value_comp();
  36. bool ret = cmp( lval, rval );
  37. // if this assertion is triggered, the value_compare objects of lhs and rhs return different values
  38. BOOST_ASSERT( ( ret == rhs.value_comp()( lval, rval ) ) );
  39. return ret;
  40. }
  41. struct heap_equivalence_copy
  42. {
  43. template < typename Heap1, typename Heap2 >
  44. bool operator()( Heap1 const& lhs, Heap2 const& rhs )
  45. {
  46. BOOST_CONCEPT_ASSERT( (boost::heap::PriorityQueue< Heap1 >));
  47. BOOST_CONCEPT_ASSERT( (boost::heap::PriorityQueue< Heap2 >));
  48. // if this assertion is triggered, the value_compare types are incompatible
  49. BOOST_STATIC_ASSERT( ( std::is_same< typename Heap1::value_compare, typename Heap2::value_compare >::value ) );
  50. if ( Heap1::constant_time_size && Heap2::constant_time_size )
  51. if ( lhs.size() != rhs.size() )
  52. return false;
  53. if ( lhs.empty() && rhs.empty() )
  54. return true;
  55. Heap1 lhs_copy( lhs );
  56. Heap2 rhs_copy( rhs );
  57. while ( true ) {
  58. if ( !value_equality( lhs_copy, rhs_copy, lhs_copy.top(), rhs_copy.top() ) )
  59. return false;
  60. lhs_copy.pop();
  61. rhs_copy.pop();
  62. if ( lhs_copy.empty() && rhs_copy.empty() )
  63. return true;
  64. if ( lhs_copy.empty() )
  65. return false;
  66. if ( rhs_copy.empty() )
  67. return false;
  68. }
  69. }
  70. };
  71. struct heap_equivalence_iteration
  72. {
  73. template < typename Heap1, typename Heap2 >
  74. bool operator()( Heap1 const& lhs, Heap2 const& rhs )
  75. {
  76. BOOST_CONCEPT_ASSERT( (boost::heap::PriorityQueue< Heap1 >));
  77. BOOST_CONCEPT_ASSERT( (boost::heap::PriorityQueue< Heap2 >));
  78. // if this assertion is triggered, the value_compare types are incompatible
  79. BOOST_STATIC_ASSERT( ( std::is_same< typename Heap1::value_compare, typename Heap2::value_compare >::value ) );
  80. if ( Heap1::constant_time_size && Heap2::constant_time_size )
  81. if ( lhs.size() != rhs.size() )
  82. return false;
  83. if ( lhs.empty() && rhs.empty() )
  84. return true;
  85. typename Heap1::ordered_iterator it1 = lhs.ordered_begin();
  86. typename Heap1::ordered_iterator it1_end = lhs.ordered_end();
  87. typename Heap1::ordered_iterator it2 = rhs.ordered_begin();
  88. typename Heap1::ordered_iterator it2_end = rhs.ordered_end();
  89. while ( true ) {
  90. if ( !value_equality( lhs, rhs, *it1, *it2 ) )
  91. return false;
  92. ++it1;
  93. ++it2;
  94. if ( it1 == it1_end && it2 == it2_end )
  95. return true;
  96. if ( it1 == it1_end || it2 == it2_end )
  97. return false;
  98. }
  99. }
  100. };
  101. template < typename Heap1, typename Heap2 >
  102. bool heap_equality( Heap1 const& lhs, Heap2 const& rhs )
  103. {
  104. const bool use_ordered_iterators = Heap1::has_ordered_iterators && Heap2::has_ordered_iterators;
  105. typedef typename std::conditional< use_ordered_iterators, heap_equivalence_iteration, heap_equivalence_copy >::type
  106. equivalence_check;
  107. equivalence_check eq_check;
  108. return eq_check( lhs, rhs );
  109. }
  110. struct heap_compare_iteration
  111. {
  112. template < typename Heap1, typename Heap2 >
  113. bool operator()( Heap1 const& lhs, Heap2 const& rhs )
  114. {
  115. typename Heap1::size_type left_size = lhs.size();
  116. typename Heap2::size_type right_size = rhs.size();
  117. if ( left_size < right_size )
  118. return true;
  119. if ( left_size > right_size )
  120. return false;
  121. typename Heap1::ordered_iterator it1 = lhs.ordered_begin();
  122. typename Heap1::ordered_iterator it1_end = lhs.ordered_end();
  123. typename Heap1::ordered_iterator it2 = rhs.ordered_begin();
  124. typename Heap1::ordered_iterator it2_end = rhs.ordered_end();
  125. while ( true ) {
  126. if ( value_compare( lhs, rhs, *it1, *it2 ) )
  127. return true;
  128. if ( value_compare( lhs, rhs, *it2, *it1 ) )
  129. return false;
  130. ++it1;
  131. ++it2;
  132. if ( it1 == it1_end && it2 == it2_end )
  133. return true;
  134. if ( it1 == it1_end || it2 == it2_end )
  135. return false;
  136. }
  137. }
  138. };
  139. struct heap_compare_copy
  140. {
  141. template < typename Heap1, typename Heap2 >
  142. bool operator()( Heap1 const& lhs, Heap2 const& rhs )
  143. {
  144. typename Heap1::size_type left_size = lhs.size();
  145. typename Heap2::size_type right_size = rhs.size();
  146. if ( left_size < right_size )
  147. return true;
  148. if ( left_size > right_size )
  149. return false;
  150. Heap1 lhs_copy( lhs );
  151. Heap2 rhs_copy( rhs );
  152. while ( true ) {
  153. if ( value_compare( lhs_copy, rhs_copy, lhs_copy.top(), rhs_copy.top() ) )
  154. return true;
  155. if ( value_compare( lhs_copy, rhs_copy, rhs_copy.top(), lhs_copy.top() ) )
  156. return false;
  157. lhs_copy.pop();
  158. rhs_copy.pop();
  159. if ( lhs_copy.empty() && rhs_copy.empty() )
  160. return false;
  161. }
  162. }
  163. };
  164. template < typename Heap1, typename Heap2 >
  165. bool heap_compare( Heap1 const& lhs, Heap2 const& rhs )
  166. {
  167. const bool use_ordered_iterators = Heap1::has_ordered_iterators && Heap2::has_ordered_iterators;
  168. typedef
  169. typename std::conditional< use_ordered_iterators, heap_compare_iteration, heap_compare_copy >::type compare_check;
  170. compare_check check_object;
  171. return check_object( lhs, rhs );
  172. }
  173. }}} // namespace boost::heap::detail
  174. #undef BOOST_HEAP_ASSERT
  175. #endif // BOOST_HEAP_DETAIL_HEAP_COMPARISON_HPP