File indexing completed on 2026-06-29 07:57:33
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038 #ifndef BOOST_MOVE_ALGO_PDQSORT_HPP
0039 #define BOOST_MOVE_ALGO_PDQSORT_HPP
0040
0041 #ifndef BOOST_CONFIG_HPP
0042 # include <boost/config.hpp>
0043 #endif
0044 0045 ">#
0046 #if defined(BOOST_HAS_PRAGMA_ONCE)
0047 # pragma once
0048 #endif
0049
0050 #include <boost/move/detail/config_begin.hpp>
0051
0052 #include <boost/move/detail/workaround.hpp>
0053 #include <boost/move/utility_core.hpp>
0054 #include <boost/move/algo/detail/insertion_sort.hpp>
0055 #include <boost/move/algo/detail/heap_sort.hpp>
0056 #include <boost/move/detail/iterator_traits.hpp>
0057
0058 #include <boost/move/adl_move_swap.hpp>
0059 #include <cstddef>
0060
0061 #if defined(BOOST_CLANG) || (defined(BOOST_GCC) && (BOOST_GCC >= 40600))
0062 #pragma GCC diagnostic push
0063 #pragma GCC diagnostic ignored "-Wsign-conversion"
0064 #endif
0065
0066 namespace boost {
0067 namespace movelib {
0068
0069 namespace pdqsort_detail {
0070
0071
0072 template<class T1, class T2>
0073 struct pair
0074 {
0075 pair()
0076 {}
0077
0078 pair(const T1 &t1, const T2 &t2)
0079 : first(t1), second(t2)
0080 {}
0081
0082 T1 first;
0083 T2 second;
0084 };
0085
0086 enum {
0087
0088 insertion_sort_threshold = 24,
0089
0090
0091 ninther_threshold = 128,
0092
0093
0094
0095 partial_insertion_sort_limit = 8,
0096
0097
0098 block_size = 64,
0099
0100
0101 cacheline_size = 64
0102
0103 };
0104
0105
0106 template<class Unsigned>
0107 Unsigned log2(Unsigned n) {
0108 Unsigned log = 0;
0109 while (n >>= 1) ++log;
0110 return log;
0111 }
0112
0113
0114
0115
0116 template<class Iter, class Compare>
0117 inline bool partial_insertion_sort(Iter begin, Iter end, Compare comp) {
0118 typedef typename boost::movelib::iterator_traits<Iter>::value_type T;
0119 typedef typename boost::movelib:: iter_size<Iter>::type size_type;
0120 if (begin == end) return true;
0121
0122 size_type limit = 0;
0123 for (Iter cur = begin + 1; cur != end; ++cur) {
0124 if (limit > partial_insertion_sort_limit) return false;
0125
0126 Iter sift = cur;
0127 Iter sift_1 = cur - 1;
0128
0129
0130 if (comp(*sift, *sift_1)) {
0131 T tmp = boost::move(*sift);
0132
0133 do { *sift-- = boost::move(*sift_1); }
0134 while (sift != begin && comp(tmp, *--sift_1));
0135
0136 *sift = boost::move(tmp);
0137 limit += size_type(cur - sift);
0138 }
0139 }
0140
0141 return true;
0142 }
0143
0144 template<class Iter, class Compare>
0145 inline void sort2(Iter a, Iter b, Compare comp) {
0146 if (comp(*b, *a)) boost::adl_move_iter_swap(a, b);
0147 }
0148
0149
0150 template<class Iter, class Compare>
0151 inline void sort3(Iter a, Iter b, Iter c, Compare comp) {
0152 sort2(a, b, comp);
0153 sort2(b, c, comp);
0154 sort2(a, b, comp);
0155 }
0156
0157
0158
0159
0160
0161
0162 template<class Iter, class Compare>
0163 pdqsort_detail::pair<Iter, bool> partition_right(Iter begin, Iter end, Compare comp) {
0164 typedef typename boost::movelib::iterator_traits<Iter>::value_type T;
0165
0166
0167 T pivot(boost::move(*begin));
0168
0169 Iter first = begin;
0170 Iter last = end;
0171
0172
0173
0174 while (comp(*++first, pivot));
0175
0176
0177
0178 if (first - 1 == begin) while (first < last && !comp(*--last, pivot));
0179 else while ( !comp(*--last, pivot));
0180
0181
0182
0183 bool already_partitioned = first >= last;
0184
0185
0186
0187
0188 while (first < last) {
0189 boost::adl_move_iter_swap(first, last);
0190 while (comp(*++first, pivot));
0191 while (!comp(*--last, pivot));
0192 }
0193
0194
0195 Iter pivot_pos = first - 1;
0196 if(begin != pivot_pos)
0197 *begin = boost::move(*pivot_pos);
0198 *pivot_pos = boost::move(pivot);
0199
0200 return pdqsort_detail::pair<Iter, bool>(pivot_pos, already_partitioned);
0201 }
0202
0203
0204
0205
0206
0207 template<class Iter, class Compare>
0208 inline Iter partition_left(Iter begin, Iter end, Compare comp) {
0209 typedef typename boost::movelib::iterator_traits<Iter>::value_type T;
0210
0211 T pivot(boost::move(*begin));
0212 Iter first = begin;
0213 Iter last = end;
0214
0215 while (comp(pivot, *--last));
0216
0217 if (last + 1 == end) while (first < last && !comp(pivot, *++first));
0218 else while ( !comp(pivot, *++first));
0219
0220 while (first < last) {
0221 boost::adl_move_iter_swap(first, last);
0222 while (comp(pivot, *--last));
0223 while (!comp(pivot, *++first));
0224 }
0225
0226 Iter pivot_pos = last;
0227 *begin = boost::move(*pivot_pos);
0228 *pivot_pos = boost::move(pivot);
0229
0230 return pivot_pos;
0231 }
0232
0233
0234 template<class Iter, class Compare>
0235 void pdqsort_loop( Iter begin, Iter end, Compare comp
0236 , typename boost::movelib:: iter_size<Iter>::type bad_allowed
0237 , bool leftmost = true)
0238 {
0239 typedef typename boost::movelib:: iter_size<Iter>::type size_type;
0240
0241
0242 while (true) {
0243 size_type size = size_type(end - begin);
0244
0245
0246 if (size < insertion_sort_threshold) {
0247 insertion_sort(begin, end, comp);
0248 return;
0249 }
0250
0251
0252 size_type s2 = size / 2;
0253 if (size > ninther_threshold) {
0254 sort3(begin, begin + s2, end - 1, comp);
0255 sort3(begin + 1, begin + (s2 - 1), end - 2, comp);
0256 sort3(begin + 2, begin + (s2 + 1), end - 3, comp);
0257 sort3(begin + (s2 - 1), begin + s2, begin + (s2 + 1), comp);
0258 boost::adl_move_iter_swap(begin, begin + s2);
0259 } else sort3(begin + s2, begin, end - 1, comp);
0260
0261
0262
0263
0264
0265
0266 if (!leftmost && !comp(*(begin - 1), *begin)) {
0267 begin = partition_left(begin, end, comp) + 1;
0268 continue;
0269 }
0270
0271
0272 pdqsort_detail::pair<Iter, bool> part_result = partition_right(begin, end, comp);
0273 Iter pivot_pos = part_result.first;
0274 bool already_partitioned = part_result.second;
0275
0276
0277 size_type l_size = size_type(pivot_pos - begin);
0278 size_type r_size = size_type(end - (pivot_pos + 1));
0279 bool highly_unbalanced = l_size < size / 8 || r_size < size / 8;
0280
0281
0282 if (highly_unbalanced) {
0283
0284 if (--bad_allowed == 0) {
0285 boost::movelib::heap_sort(begin, end, comp);
0286 return;
0287 }
0288
0289 if (l_size >= insertion_sort_threshold) {
0290 boost::adl_move_iter_swap(begin, begin + l_size / 4);
0291 boost::adl_move_iter_swap(pivot_pos - 1, pivot_pos - l_size / 4);
0292
0293 if (l_size > ninther_threshold) {
0294 boost::adl_move_iter_swap(begin + 1, begin + (l_size / 4 + 1));
0295 boost::adl_move_iter_swap(begin + 2, begin + (l_size / 4 + 2));
0296 boost::adl_move_iter_swap(pivot_pos - 2, pivot_pos - (l_size / 4 + 1));
0297 boost::adl_move_iter_swap(pivot_pos - 3, pivot_pos - (l_size / 4 + 2));
0298 }
0299 }
0300
0301 if (r_size >= insertion_sort_threshold) {
0302 boost::adl_move_iter_swap(pivot_pos + 1, pivot_pos + (1 + r_size / 4));
0303 boost::adl_move_iter_swap(end - 1, end - r_size / 4);
0304
0305 if (r_size > ninther_threshold) {
0306 boost::adl_move_iter_swap(pivot_pos + 2, pivot_pos + (2 + r_size / 4));
0307 boost::adl_move_iter_swap(pivot_pos + 3, pivot_pos + (3 + r_size / 4));
0308 boost::adl_move_iter_swap(end - 2, end - (1 + r_size / 4));
0309 boost::adl_move_iter_swap(end - 3, end - (2 + r_size / 4));
0310 }
0311 }
0312 } else {
0313
0314
0315 if (already_partitioned && partial_insertion_sort(begin, pivot_pos, comp)
0316 && partial_insertion_sort(pivot_pos + 1, end, comp)) return;
0317 }
0318
0319
0320
0321 pdqsort_loop<Iter, Compare>(begin, pivot_pos, comp, bad_allowed, leftmost);
0322 begin = pivot_pos + 1;
0323 leftmost = false;
0324 }
0325 }
0326 }
0327
0328
0329 template<class Iter, class Compare>
0330 void pdqsort(Iter begin, Iter end, Compare comp)
0331 {
0332 if (begin == end) return;
0333 typedef typename boost::movelib:: iter_size<Iter>::type size_type;
0334 pdqsort_detail::pdqsort_loop<Iter, Compare>(begin, end, comp, pdqsort_detail::log2(size_type(end - begin)));
0335 }
0336
0337 }
0338 }
0339
0340 #if defined(BOOST_CLANG) || (defined(BOOST_GCC) && (BOOST_GCC >= 40600))
0341 #pragma GCC diagnostic pop
0342 #endif
0343
0344 #include <boost/move/detail/config_end.hpp>
0345
0346 #endif