set_difference.hpp 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // (C) Copyright Ion Gaztanaga 2017-2017.
  4. // Distributed under the Boost Software License, Version 1.0.
  5. // (See accompanying file LICENSE_1_0.txt or copy at
  6. // http://www.boost.org/LICENSE_1_0.txt)
  7. //
  8. // See http://www.boost.org/libs/move for documentation.
  9. //
  10. //////////////////////////////////////////////////////////////////////////////
  11. #ifndef BOOST_MOVE_SET_DIFFERENCE_HPP
  12. #define BOOST_MOVE_SET_DIFFERENCE_HPP
  13. #include <boost/move/algo/move.hpp>
  14. #include <boost/move/iterator.hpp>
  15. #include <boost/move/utility_core.hpp>
  16. namespace boost {
  17. namespace move_detail{
  18. template<class InputIt, class OutputIt>
  19. OutputIt copy(InputIt first, InputIt last, OutputIt result)
  20. {
  21. while (first != last) {
  22. *result++ = *first;
  23. ++result;
  24. ++first;
  25. }
  26. return result;
  27. }
  28. } //namespace move_detail{
  29. namespace movelib {
  30. //Moves the elements from the sorted range [first1, last1) which are not found in the sorted
  31. //range [first2, last2) to the range beginning at result.
  32. //The resulting range is also sorted. Equivalent elements are treated individually,
  33. //that is, if some element is found m times in [first1, last1) and n times in [first2, last2),
  34. //it will be moved to result exactly max(m-n, 0) times.
  35. //The resulting range cannot overlap with either of the input ranges.
  36. template<class InputIt1, class InputIt2,
  37. class OutputIt, class Compare>
  38. OutputIt set_difference
  39. (InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2, OutputIt result, Compare comp)
  40. {
  41. while (first1 != last1) {
  42. if (first2 == last2)
  43. return boost::move_detail::copy(first1, last1, result);
  44. if (comp(*first1, *first2)) {
  45. *result = *first1;
  46. ++result;
  47. ++first1;
  48. }
  49. else {
  50. if (!comp(*first2, *first1)) {
  51. ++first1;
  52. }
  53. ++first2;
  54. }
  55. }
  56. return result;
  57. }
  58. //Moves the elements from the sorted range [first1, last1) which are not found in the sorted
  59. //range [first2, last2) to the range beginning at first1 (in place operation in range1).
  60. //The resulting range is also sorted. Equivalent elements are treated individually,
  61. //that is, if some element is found m times in [first1, last1) and n times in [first2, last2),
  62. //it will be moved to result exactly max(m-n, 0) times.
  63. template<class InputOutputIt1, class InputIt2, class Compare>
  64. InputOutputIt1 inplace_set_difference
  65. (InputOutputIt1 first1, InputOutputIt1 last1, InputIt2 first2, InputIt2 last2, Compare comp )
  66. {
  67. while (first1 != last1) {
  68. //Skip copying from range 1 if no element has to be skipped
  69. if (first2 == last2){
  70. return last1;
  71. }
  72. else if (comp(*first1, *first2)){
  73. ++first1;
  74. }
  75. else{
  76. if (!comp(*first2, *first1)) {
  77. InputOutputIt1 result = first1;
  78. //An element from range 1 must be skipped, no longer an inplace operation
  79. return boost::movelib::set_difference
  80. ( boost::make_move_iterator(++first1)
  81. , boost::make_move_iterator(last1)
  82. , ++first2, last2, result, comp);
  83. }
  84. ++first2;
  85. }
  86. }
  87. return first1;
  88. }
  89. //Moves the elements from the sorted range [first1, last1) which are not found in the sorted
  90. //range [first2, last2) to the range beginning at first1.
  91. //The resulting range is also sorted. Equivalent elements from range 1 are moved past to end
  92. //of the result,
  93. //that is, if some element is found m times in [first1, last1) and n times in [first2, last2),
  94. //it will be moved to result exactly max(m-n, 0) times.
  95. //The resulting range cannot overlap with either of the input ranges.
  96. template<class ForwardIt1, class InputIt2,
  97. class OutputIt, class Compare>
  98. OutputIt set_unique_difference
  99. (ForwardIt1 first1, ForwardIt1 last1, InputIt2 first2, InputIt2 last2, OutputIt result, Compare comp)
  100. {
  101. while (first1 != last1) {
  102. if (first2 == last2){
  103. //unique_copy-like sequence with forward iterators but don't write i
  104. //to result before comparing as moving *i could alter the value in i.
  105. ForwardIt1 i = first1;
  106. while (++first1 != last1) {
  107. if (comp(*i, *first1)) {
  108. *result = *i;
  109. ++result;
  110. i = first1;
  111. }
  112. }
  113. *result = *i;
  114. ++result;
  115. break;
  116. }
  117. if (comp(*first1, *first2)) {
  118. //Skip equivalent elements in range1 but don't write i
  119. //to result before comparing as moving *i could alter the value in i.
  120. ForwardIt1 i = first1;
  121. while (++first1 != last1) {
  122. if (comp(*i, *first1)) {
  123. break;
  124. }
  125. }
  126. *result = *i;
  127. ++result;
  128. }
  129. else {
  130. if (comp(*first2, *first1)) {
  131. ++first2;
  132. }
  133. else{
  134. ++first1;
  135. }
  136. }
  137. }
  138. return result;
  139. }
  140. //Moves the elements from the sorted range [first1, last1) which are not found in the sorted
  141. //range [first2, last2) to the range beginning at first1 (in place operation in range1).
  142. //The resulting range is also sorted. Equivalent elements are treated individually,
  143. //that is, if some element is found m times in [first1, last1) and n times in [first2, last2),
  144. //it will be moved to result exactly max(m-n, 0) times.
  145. template<class ForwardOutputIt1, class ForwardIt2, class Compare>
  146. ForwardOutputIt1 inplace_set_unique_difference
  147. (ForwardOutputIt1 first1, ForwardOutputIt1 last1, ForwardIt2 first2, ForwardIt2 last2, Compare comp )
  148. {
  149. while (first1 != last1) {
  150. //Skip copying from range 1 if no element has to be skipped
  151. if (first2 == last2){
  152. //unique-like algorithm for the remaining range 1
  153. ForwardOutputIt1 result = first1;
  154. while (++first1 != last1) {
  155. if (comp(*result, *first1) && ++result != first1) {
  156. *result = boost::move(*first1);
  157. }
  158. }
  159. return ++result;
  160. }
  161. else if (comp(*first2, *first1)) {
  162. ++first2;
  163. }
  164. else if (comp(*first1, *first2)){
  165. //skip any adjacent equivalent element in range 1
  166. ForwardOutputIt1 result = first1;
  167. if (++first1 != last1 && !comp(*result, *first1)) {
  168. //Some elements from range 1 must be skipped, no longer an inplace operation
  169. while (++first1 != last1 && !comp(*result, *first1)){}
  170. return boost::movelib::set_unique_difference
  171. ( boost::make_move_iterator(first1)
  172. , boost::make_move_iterator(last1)
  173. , first2, last2, ++result, comp);
  174. }
  175. }
  176. else{
  177. ForwardOutputIt1 result = first1;
  178. //Some elements from range 1 must be skipped, no longer an inplace operation
  179. while (++first1 != last1 && !comp(*result, *first1)){}
  180. //An element from range 1 must be skipped, no longer an inplace operation
  181. return boost::movelib::set_unique_difference
  182. ( boost::make_move_iterator(first1)
  183. , boost::make_move_iterator(last1)
  184. , first2, last2, result, comp);
  185. }
  186. }
  187. return first1;
  188. }
  189. } //namespace movelib {
  190. } //namespace boost {
  191. #endif //#define BOOST_MOVE_SET_DIFFERENCE_HPP