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