set_difference.hpp 7.4 KB

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