34 template<
class It,
class Pred>
37 for( It j=begin+1; j<end; j++ )
39 typename std::iterator_traits<It>::value_type e = *j;
40 for( It i=j; begin<i; *i=e )
48 template<
typename T,
class Pred>
49 inline T
median(
const T& a,
const T& b,
const T& c, Pred comp)
67 template<
class B
idIt,
class T,
class Pred>
68 inline BidIt
partition(BidIt begin, BidIt end, T pivot, Pred comp)
72 for( ; comp(*begin,pivot); ++begin );
73 for( --end; comp(pivot,*end); --end );
76 std::iter_swap(begin, end);
81 template<
class RanIt,
class Pred>
82 inline void quicksort(RanIt First, RanIt Last, Pred comp)
84 typename std::iterator_traits<RanIt>::difference_type Count = Last-First;
87 RanIt part =
partition(First, Last,
median(*First,*(First+(Last-First)/2),*(Last-1),comp),comp);
88 if( part-First < Last-part )
89 quicksort(First, part, comp), First = part;
102 for(
order_t i=k-1; i; h++, i/=2 );
106 template<
class RanIt,
class Pred>
109 typedef typename std::iterator_traits<RanIt>::difference_type ItDiff;
110 ItDiff t =
logc(end-begin)-1;
115 for( i=begin; i<end-p-p; i+=p )
119 if( comp(*(i+p),*i) )
120 std::iter_swap(i+p, i);
122 for( ; i<end-p; i++ )
123 if( comp(*(i+p),*i) )
124 std::iter_swap(i+p, i);
130 for( i=begin+p; i<end-d-p; i+=p )
134 if( comp(*(i+d),*i) )
135 std::iter_swap(i+d, i);
137 for( ; i<end-d; i++ )
138 if( comp(*(i+d),*i) )
139 std::iter_swap(i+d, i);
144 for( RanIt i=begin; i<end-1; i+=2 )
145 if( comp(*(i+1),*i) )
146 std::iter_swap(i+1, i);
152 for( RanIt i=begin+1; i<end-d; i+=2 )
153 if( comp(*(i+d),*i) )
154 std::iter_swap(i+d, i);
159 template<
class RanIt,
class Pred>
171 template<
class RanIt,
class Splitter>
174 typedef typename std::iterator_traits<RanIt>::difference_type diff;
176 class iterator :
public std::iterator<std::bidirectional_iterator_tag, std::pair<RanIt,RanIt>, diff>
184 if( --big_runs == 0 )
191 begin = end-run_size;
192 if( ++big_runs == 0 )
197 {
return make_pair(begin,end); }
199 {
return begin == rhs.begin; }
201 inline iterator(RanIt begin, diff run_size,
size_t big_runs) : begin(begin), run_size(run_size), big_runs(big_runs)
205 end = begin+run_size;
211 stream_slices(RanIt begin, RanIt end) : b(begin), e(end), order_(Splitter::prefered_order_output(end-begin))
214 throw std::logic_error(
"Splitter::prefered_order_output returned less than two");
215 run_size = (end-begin)/order_;
216 size_t rem =
static_cast<size_t>((end-begin) % order_);
217 run_size += rem/order_;
218 big_runs = rem % order_;
223 {
return iterator(b, run_size, big_runs); }
225 {
return iterator(e, run_size, big_runs); }
229 size_t order_, big_runs;
232 template<
class Splitter,
class Diff>
235 size_t order = Splitter::prefered_order_output(d);
236 Diff run_size = d/order;
237 size_t rem =
static_cast<size_t>(d % order);
238 run_size += rem/order;
239 size_t big_runs = rem % order;
245 template<
class Merger,
class Splitter,
class Diff,
class MAlloc,
class TAlloc>
246 inline std::pair<Merger*,Merger*>
build_cache_(Diff run_size, MAlloc& malloc, TAlloc& talloc)
248 Merger *begin_cache, *end_cache;
250 for( Diff d=run_size; d>
static_cast<Diff
>(Splitter::switch_to_cache_aware()); d=run_size_<Splitter>(d), ++rec_calls );
251 begin_cache = end_cache = malloc.allocate(rec_calls);
252 for( Diff d=run_size; d>
static_cast<Diff
>(Splitter::switch_to_cache_aware()); d=run_size_<Splitter>(d), ++end_cache )
253 new(end_cache) Merger(Splitter::prefered_order_output(d), talloc);
254 return make_pair(begin_cache,end_cache);
257 template<
class Merger,
class Splitter,
class It,
class OutIt,
class Alloc>
258 void merge_sort_(It begin, It end, OutIt dest, Merger* cache, Alloc alloc);
260 template<
class Merger,
class Splitter,
class MPtr,
class It,
class Alloc>
261 inline void sort_streams_(MPtr cache, It begin,
size_t order,
size_t run_size,
size_t big_runs, Alloc alloc)
263 typedef typename std::iterator_traits<It>::value_type T;
264 typename Alloc::template rebind<T>::other talloc(alloc);
265 typedef typename Alloc::template rebind<T>::other::pointer TPtr;
266 TPtr tmp = talloc.allocate((
size_t)(run_size));
271 merge_sort_<Merger,Splitter>(last, last+run_size, std::raw_storage_iterator<TPtr,T>(tmp), cache, alloc);
272 for( i=1, last+=run_size; i!=big_runs; i++, last+=run_size )
273 merge_sort_<Merger,Splitter>(last, last+run_size, last-run_size, cache, alloc);
275 for( ; i!=order; i++, last+=run_size )
276 merge_sort_<Merger,Splitter>(last, last+run_size, last-run_size-1, cache, alloc);
281 merge_sort_<Merger,Splitter>(last, last+run_size, tmp, cache, alloc);
282 for( --order, last+=run_size; order; --order, last+=run_size )
283 merge_sort_<Merger,Splitter>(last, last+run_size, last-run_size, cache, alloc);
285 std::copy(tmp, tmp+run_size, last-run_size);
286 for( TPtr p=tmp+run_size-1; p>=tmp; --p )
288 talloc.deallocate(tmp,static_cast<size_t>(run_size));
291 template<
class MPtr,
class It>
296 merger->add_stream(end-run_size, end);
298 --run_size, --big_runs;
299 for( --order; order!=big_runs; --order, end-=run_size )
300 merger->add_stream(end-run_size, end);
302 for( ; order; --order, end-=run_size )
303 merger->add_stream(end-run_size, end);
306 for( ; order; --order, end-=run_size )
307 merger->add_stream(end-run_size, end);
310 template<
class MPtr,
class It,
class Pred>
311 inline void add_streams_(MPtr merger, It begin,
size_t order,
size_t run_size,
size_t big_runs, Pred comp)
314 for( i=0; i!=order-big_runs; ++i, begin+=run_size )
317 for( ; i!=order; ++i, begin+=run_size )
320 for( ; i!=order-big_runs; --i, begin-=run_size )
321 merger->add_stream(begin-run_size, begin);
323 for( ; i; --i, begin-=run_size )
324 merger->add_stream(begin-run_size, begin);
327 template<
class Merger,
class Splitter,
class It,
class OutIt,
class Alloc>
328 void merge_sort_(It begin, It end, OutIt dest, Merger* cache, Alloc alloc)
330 typedef typename std::iterator_traits<It>::value_type T;
331 typedef typename std::iterator_traits<It>::difference_type ItDiff;
332 typedef typename Merger::stream Stream;
334 order_t order = Splitter::prefered_order_output(end-begin);
336 throw std::logic_error(
"Splitter::prefered_order_output returned less than two");
337 ItDiff run_size = (end-begin)/order;
338 size_t rem = (size_t)((end-begin) % order);
339 run_size += rem/order;
340 size_t big_runs = rem % order;
343 if( run_size > static_cast<ItDiff>(Splitter::switch_to_cache_aware()) )
347 sort_streams_<Merger,Splitter>(cache+1,begin,order,run_size,big_runs,alloc);
351 add_streams_(cache,begin,order,run_size,big_runs,
typename Merger::predicate());
355 template<
class Merger,
class Splitter,
class It,
class OutIt>
356 inline void merge_sort(It begin, It end, OutIt dest,
const typename Merger::allocator& alloc)
358 typedef typename std::iterator_traits<It>::difference_type ItDiff;
359 if( end-begin > static_cast<ItDiff>(Splitter::switch_to_cache_aware()) )
361 order_t order = Splitter::prefered_order_output(end-begin);
363 throw std::logic_error(
"Splitter::prefered_order_output returned less than two");
364 ItDiff run_size = (end-begin)/order;
365 size_t rem = (size_t)((end-begin) % order);
366 run_size += rem/order;
367 size_t big_runs = rem % order;
368 if( run_size > static_cast<ItDiff>(Splitter::switch_to_cache_aware()) )
372 typename Merger::allocator::template rebind<Merger>::other malloc(alloc);
373 std::pair<Merger*,Merger*> cache = build_cache_<Merger,Splitter>(run_size, malloc, alloc);
374 sort_streams_<Merger,Splitter>(cache.first, begin, order, run_size, big_runs, alloc);
375 for( Merger *pm=cache.second-1; pm>=cache.first; --pm )
377 malloc.deallocate(cache.first, cache.second-cache.first);
379 Merger merger(order,alloc);
380 if( run_size > static_cast<ItDiff>(Splitter::switch_to_cache_aware()) )
383 add_streams_(&merger, begin, order, run_size, big_runs,
typename Merger::predicate());
385 OutIt e = merger(dest, dest+(end-begin));
386 merger.empty(dest, dest+(end-begin));
388 for(
typename Merger::stream_iterator i=merger.begin(); i!=merger.end(); ++i )
389 N += (*i).end()-(*i).begin();
390 assert( e == dest+(end-begin) );
398 std::copy(begin, end, dest);
void merge_sort_(It begin, It end, OutIt dest, Merger *cache, Alloc alloc)
void inplace_base_sort(RanIt begin, RanIt end, Pred comp)
void add_sorted_streams_(MPtr merger, It end, size_t order, size_t run_size, size_t big_runs)
T median(const T &a, const T &b, const T &c, Pred comp)
void insertion_sort(It begin, It end, Pred comp)
void batcher_sort(RanIt begin, RanIt end, Pred comp)
std::pair< RanIt, RanIt > operator*()
void quicksort(RanIt First, RanIt Last, Pred comp)
std::pair< Merger *, Merger * > build_cache_(Diff run_size, MAlloc &malloc, TAlloc &talloc)
bool operator==(const iterator &rhs)
stream_slices(RanIt begin, RanIt end)
void sort_streams_(MPtr cache, It begin, size_t order, size_t run_size, size_t big_runs, Alloc alloc)
void merge_sort(It begin, It end, OutIt dest, const typename Merger::allocator &alloc)
void add_streams_(MPtr merger, It begin, size_t order, size_t run_size, size_t big_runs, Pred comp)
BidIt partition(BidIt begin, BidIt end, T pivot, Pred comp)