1 //////////////////////////////////////////////////////////////////////////////
3 // (C) Copyright Ion Gaztanaga 2015-2016.
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)
8 // See http://www.boost.org/libs/move for documentation.
10 //////////////////////////////////////////////////////////////////////////////
14 #ifndef BOOST_MOVE_DETAIL_MERGE_SORT_HPP
15 #define BOOST_MOVE_DETAIL_MERGE_SORT_HPP
17 #ifndef BOOST_CONFIG_HPP
18 # include <boost/config.hpp>
21 #if defined(BOOST_HAS_PRAGMA_ONCE)
25 #include <boost/move/detail/config_begin.hpp>
26 #include <boost/move/detail/workaround.hpp>
28 #include <boost/move/utility_core.hpp>
29 #include <boost/move/algo/move.hpp>
30 #include <boost/move/algo/detail/merge.hpp>
31 #include <boost/move/detail/iterator_traits.hpp>
32 #include <boost/move/adl_move_swap.hpp>
33 #include <boost/move/detail/destruct_n.hpp>
34 #include <boost/move/algo/detail/insertion_sort.hpp>
37 #if defined(BOOST_CLANG) || (defined(BOOST_GCC) && (BOOST_GCC >= 40600))
38 #pragma GCC diagnostic push
39 #pragma GCC diagnostic ignored "-Wsign-conversion"
47 static const unsigned MergeSortInsertionSortThreshold = 16;
49 template <class RandIt, class Compare>
50 void inplace_stable_sort(RandIt first, RandIt last, Compare comp)
52 typedef typename iter_size<RandIt>::type size_type;
53 if (size_type(last - first) <= size_type(MergeSortInsertionSortThreshold)) {
54 insertion_sort(first, last, comp);
57 RandIt middle = first + (last - first) / 2;
58 inplace_stable_sort(first, middle, comp);
59 inplace_stable_sort(middle, last, comp);
60 merge_bufferless_ONlogN_recursive
61 (first, middle, last, size_type(middle - first), size_type(last - middle), comp);
66 template<class RandIt, class RandIt2, class Compare>
67 void merge_sort_copy( RandIt first, RandIt last
68 , RandIt2 dest, Compare comp)
70 typedef typename iter_size<RandIt>::type size_type;
72 size_type const count = size_type(last - first);
73 if(count <= MergeSortInsertionSortThreshold){
74 insertion_sort_copy(first, last, dest, comp);
77 size_type const half = size_type(count/2u);
78 merge_sort_copy(first + half, last , dest+half , comp);
79 merge_sort_copy(first , first + half, first + half, comp);
80 merge_with_right_placed
81 ( first + half, first + half + half
82 , dest, dest+half, dest + count
87 template<class RandIt, class RandItRaw, class Compare>
88 void merge_sort_uninitialized_copy( RandIt first, RandIt last
89 , RandItRaw uninitialized
92 typedef typename iter_size<RandIt>::type size_type;
93 typedef typename iterator_traits<RandIt>::value_type value_type;
95 size_type const count = size_type(last - first);
96 if(count <= MergeSortInsertionSortThreshold){
97 insertion_sort_uninitialized_copy(first, last, uninitialized, comp);
100 size_type const half = count/2;
101 merge_sort_uninitialized_copy(first + half, last, uninitialized + half, comp);
102 destruct_n<value_type, RandItRaw> d(uninitialized+half);
103 d.incr(size_type(count-half));
104 merge_sort_copy(first, first + half, first + half, comp);
105 uninitialized_merge_with_right_placed
106 ( first + half, first + half + half
107 , uninitialized, uninitialized+half, uninitialized+count
113 template<class RandIt, class RandItRaw, class Compare>
114 void merge_sort( RandIt first, RandIt last, Compare comp
115 , RandItRaw uninitialized)
117 typedef typename iter_size<RandIt>::type size_type;
118 typedef typename iterator_traits<RandIt>::value_type value_type;
120 size_type const count = size_type(last - first);
121 if(count <= MergeSortInsertionSortThreshold){
122 insertion_sort(first, last, comp);
125 size_type const half = size_type(count/2u);
126 size_type const rest = size_type(count - half);
127 RandIt const half_it = first + half;
128 RandIt const rest_it = first + rest;
130 merge_sort_uninitialized_copy(half_it, last, uninitialized, comp);
131 destruct_n<value_type, RandItRaw> d(uninitialized);
133 merge_sort_copy(first, half_it, rest_it, comp);
134 merge_with_right_placed
135 ( uninitialized, uninitialized + rest
136 , first, rest_it, last, antistable<Compare>(comp));
142 template<class RandIt, class RandItRaw, class Compare>
143 void merge_sort_with_constructed_buffer( RandIt first, RandIt last, Compare comp, RandItRaw buffer)
145 typedef typename iter_size<RandIt>::type size_type;
147 size_type const count = size_type(last - first);
148 if(count <= MergeSortInsertionSortThreshold){
149 insertion_sort(first, last, comp);
152 size_type const half = size_type(count/2);
153 size_type const rest = size_type(count - half);
154 RandIt const half_it = first + half;
155 RandIt const rest_it = first + rest;
157 merge_sort_copy(half_it, last, buffer, comp);
158 merge_sort_copy(first, half_it, rest_it, comp);
159 merge_with_right_placed
160 (buffer, buffer + rest
161 , first, rest_it, last, antistable<Compare>(comp));
165 template<typename RandIt, typename Pointer,
166 typename Distance, typename Compare>
167 void stable_sort_ONlogN_recursive(RandIt first, RandIt last, Pointer buffer, Distance buffer_size, Compare comp)
169 typedef typename iter_size<RandIt>::type size_type;
170 if (size_type(last - first) <= size_type(MergeSortInsertionSortThreshold)) {
171 insertion_sort(first, last, comp);
174 const size_type len = size_type(last - first) / 2u;
175 const RandIt middle = first + len;
176 if (len > ((buffer_size+1)/2)){
177 stable_sort_ONlogN_recursive(first, middle, buffer, buffer_size, comp);
178 stable_sort_ONlogN_recursive(middle, last, buffer, buffer_size, comp);
181 merge_sort_with_constructed_buffer(first, middle, comp, buffer);
182 merge_sort_with_constructed_buffer(middle, last, comp, buffer);
184 merge_adaptive_ONlogN_recursive(first, middle, last,
185 size_type(middle - first),
186 size_type(last - middle),
192 template<typename BidirectionalIterator, typename Compare, typename RandRawIt>
193 void stable_sort_adaptive_ONlogN2(BidirectionalIterator first,
194 BidirectionalIterator last,
196 RandRawIt uninitialized,
197 std::size_t uninitialized_len)
199 typedef typename iterator_traits<BidirectionalIterator>::value_type value_type;
201 ::boost::movelib::adaptive_xbuf<value_type, RandRawIt> xbuf(uninitialized, uninitialized_len);
202 xbuf.initialize_until(uninitialized_len, *first);
203 stable_sort_ONlogN_recursive(first, last, uninitialized, uninitialized_len, comp);
208 }} //namespace boost { namespace movelib{
210 #if defined(BOOST_CLANG) || (defined(BOOST_GCC) && (BOOST_GCC >= 40600))
211 #pragma GCC diagnostic pop
214 #include <boost/move/detail/config_end.hpp>
216 #endif //#ifndef BOOST_MOVE_DETAIL_MERGE_SORT_HPP