1 /******************************************************************************
2  * src/SortAlgo.cpp
3  *
4  * Implementations is many sorting algorithms.
5  *
6  * Note that these implementations may not be as good/fast as possible. Some
7  * are modified so that the visualization is more instructive.
8  *
9  * Futhermore, some algorithms are annotated using the mark() and watch()
10  * functions from SortArray. These functions add colors to the illustratation
11  * and thereby makes the algorithm's visualization easier to explain.
12  *
13  ******************************************************************************
14  * The algorithms in this file are copyrighted by the original authors. All
15  * code is freely available.
16  *
17  * The source code added by myself (Timo Bingmann) and all modifications are
18  * copyright (C) 2013-2014 Timo Bingmann <tb@panthema.net>
19  *
20  * This program is free software: you can redistribute it and/or modify it
21  * under the terms of the GNU General Public License as published by the Free
22  * Software Foundation, either version 3 of the License, or (at your option)
23  * any later version.
24  *
25  * This program is distributed in the hope that it will be useful, but WITHOUT
26  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
27  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
28  * more details.
29  *
30  * You should have received a copy of the GNU General Public License along with
31  * this program.  If not, see <http://www.gnu.org/licenses/>.
32  *****************************************************************************/
33 
34 #include "SortAlgo.h"
35 
36 #include <algorithm>
37 #include <numeric>
38 #include <limits>
39 #include <inttypes.h>
40 
41 typedef ArrayItem value_type;
42 
43 // inversion count limit for iterator instrumented algorithms
44 const unsigned int inversion_count_instrumented = 512;
45 
46 const struct AlgoEntry g_algolist[] =
47 {
48     { _("Selection Sort"), &SelectionSort, UINT_MAX, UINT_MAX,
49       wxEmptyString },
50     { _("Insertion Sort"), &InsertionSort, UINT_MAX, UINT_MAX,
51       wxEmptyString },
52     { _("Binary Insertion Sort"), &BinaryInsertionSort, UINT_MAX, UINT_MAX,
53       wxEmptyString },
54     { _("Merge Sort"), &MergeSort, UINT_MAX, 512,
55       _("Merge sort which merges two sorted sequences into a shadow array,"
56         "and then copies it back to the shown array.") },
57     { _("Merge Sort (iterative)"), &MergeSortIterative, UINT_MAX, 512,
58       _("Merge sort variant which iteratively merges "
59         "subarrays of sizes of powers of two.") },
60     { _("Quick Sort (LR ptrs)"), &QuickSortLR, UINT_MAX, UINT_MAX,
61       _("Quick sort variant with left and right pointers.") },
62     { _("Quick Sort (LL ptrs)"), &QuickSortLL, UINT_MAX, UINT_MAX,
63       _("Quick sort variant from 3rd edition of CLRS: two pointers on left.") },
64     { _("Quick Sort (ternary, LR ptrs)"), &QuickSortTernaryLR, UINT_MAX, UINT_MAX,
65       _("Ternary-split quick sort variant, adapted from multikey quicksort by "
66         "Bentley & Sedgewick: partitions \"=<?>=\" using two pairs of pointers "
67         "at left and right, then copied to middle.") },
68     { _("Quick Sort (ternary, LL ptrs)"), &QuickSortTernaryLL, UINT_MAX, UINT_MAX,
69       _("Ternary-split quick sort variant: partitions \"<>?=\" using two "
70         "pointers at left and one at right. Afterwards copies the \"=\" to middle.") },
71     { _("Quick Sort (dual pivot)"), &QuickSortDualPivot, UINT_MAX, UINT_MAX,
72       _("Dual pivot quick sort variant: partitions \"<1<2?>\" using three pointers, "
73         "two at left and one at right.") },
74     { _("Bubble Sort"), &BubbleSort, UINT_MAX, UINT_MAX,
75       wxEmptyString },
76     { _("Cocktail Shaker Sort"), &CocktailShakerSort, UINT_MAX, UINT_MAX,
77       wxEmptyString },
78     { _("Gnome Sort"), &GnomeSort, UINT_MAX, UINT_MAX,
79       wxEmptyString },
80     { _("Comb Sort"), &CombSort, UINT_MAX, UINT_MAX,
81       wxEmptyString },
82     { _("Shell Sort"), &ShellSort, UINT_MAX, 1024,
83       wxEmptyString },
84     { _("Heap Sort"), &HeapSort, UINT_MAX, UINT_MAX,
85       wxEmptyString },
86     { _("Smooth Sort"), &SmoothSort, UINT_MAX, 1024,
87       wxEmptyString },
88     { _("Odd-Even Sort"), &OddEvenSort, UINT_MAX, 1024,
89       wxEmptyString },
90     // older sequential implementation, which really makes little sense to do
91     //{ _("Bitonic Sort"), &BitonicSort, UINT_MAX, UINT_MAX, wxEmptyString },
92     { _("Batcher's Bitonic Sort"), &BitonicSortNetwork, UINT_MAX, UINT_MAX,
93       wxEmptyString },
94     { _("Batcher's Odd-Even Merge Sort"), &BatcherSortNetwork, UINT_MAX, UINT_MAX,
95       wxEmptyString },
96     { _("Cycle Sort"), &CycleSort, 512, UINT_MAX,
97       wxEmptyString },
98     { _("Radix Sort (LSD)"), &RadixSortLSD, UINT_MAX, 512,
99       _("Least significant digit radix sort, which copies item into a shadow "
100         "array during counting.") },
101     { _("Radix Sort (MSD)"), &RadixSortMSD, UINT_MAX, UINT_MAX,
102       _("Most significant digit radix sort, which permutes items in-place by walking cycles.") },
103     { _("std::sort (gcc)"), &StlSort, UINT_MAX, inversion_count_instrumented,
104       wxEmptyString },
105     { _("std::stable_sort (gcc)"), &StlStableSort, UINT_MAX, inversion_count_instrumented,
106       wxEmptyString },
107     { _("std::sort_heap (gcc)"), &StlHeapSort, UINT_MAX, inversion_count_instrumented,
108       wxEmptyString },
109     { _("Tim Sort"), &TimSort, UINT_MAX, inversion_count_instrumented,
110       wxEmptyString },
111     { _("Block Merge Sort (WikiSort)"), &WikiSort, UINT_MAX, inversion_count_instrumented,
112       _("An O(1) place O(n log n) time stable merge sort.") },
113     { _("Bogo Sort"), &BogoSort, 10, UINT_MAX,
114       wxEmptyString },
115     { _("Bozo Sort"), &BozoSort, 10, UINT_MAX,
116       wxEmptyString },
117     { _("Stooge Sort"), &StoogeSort, 256, inversion_count_instrumented,
118       wxEmptyString },
119     { _("Slow Sort"), &SlowSort, 128, inversion_count_instrumented,
120       wxEmptyString }
121 };
122 
123 const size_t g_algolist_size = sizeof(g_algolist) / sizeof(g_algolist[0]);
124 
125 const struct AlgoEntry* g_algolist_end = g_algolist + g_algolist_size;
126 
127 // ****************************************************************************
128 // *** Selection Sort
129 
SelectionSort(SortArray & A)130 void SelectionSort(SortArray& A)
131 {
132     volatile ssize_t jMin = 0;
133     A.watch(&jMin, 3);
134 
135     for (size_t i = 0; i < A.size()-1; ++i)
136     {
137         jMin = i;
138 
139         for (size_t j = i+1; j < A.size(); ++j)
140         {
141             if (A[j] < A[jMin]) {
142                 A.mark_swap(j, jMin);
143                 jMin = j;
144             }
145         }
146 
147         A.swap(i, jMin);
148 
149         // mark the last good element
150         if (i > 0) A.unmark(i-1);
151         A.mark(i);
152     }
153     A.unwatch_all();
154 }
155 
156 // ****************************************************************************
157 // *** Insertion Sort
158 
159 // swaps every time (keeps all values visible)
InsertionSort(SortArray & A)160 void InsertionSort(SortArray& A)
161 {
162     for (size_t i = 1; i < A.size(); ++i)
163     {
164         value_type key = A[i];
165         A.mark(i);
166 
167         ssize_t j = i - 1;
168         while (j >= 0 && A[j] > key)
169         {
170             A.swap(j, j+1);
171             j--;
172         }
173 
174         A.unmark(i);
175     }
176 }
177 
178 // with extra item on stack
InsertionSort2(SortArray & A)179 void InsertionSort2(SortArray& A)
180 {
181     for (size_t i = 1; i < A.size(); ++i)
182     {
183         value_type tmp, key = A[i];
184         A.mark(i);
185 
186         ssize_t j = i - 1;
187         while (j >= 0 && (tmp = A[j]) > key)
188         {
189             A.set(j + 1, tmp);
190             j--;
191         }
192         A.set(j + 1, key);
193 
194         A.unmark(i);
195     }
196 }
197 
198 // swaps every time (keeps all values visible)
BinaryInsertionSort(SortArray & A)199 void BinaryInsertionSort(SortArray& A)
200 {
201     for (size_t i = 1; i < A.size(); ++i)
202     {
203         value_type key = A[i];
204         A.mark(i);
205 
206         int lo = 0, hi = i;
207         while (lo < hi) {
208             int mid = (lo + hi) / 2;
209             if (key <= A[mid])
210                 hi = mid;
211             else
212                 lo = mid + 1;
213         }
214 
215         // item has to go into position lo
216 
217         ssize_t j = i - 1;
218         while (j >= lo)
219         {
220             A.swap(j, j+1);
221             j--;
222         }
223 
224         A.unmark(i);
225     }
226 }
227 
228 // ****************************************************************************
229 // *** Merge Sort (out-of-place with sentinels)
230 
231 // by myself (Timo Bingmann)
232 
Merge(SortArray & A,size_t lo,size_t mid,size_t hi)233 void Merge(SortArray& A, size_t lo, size_t mid, size_t hi)
234 {
235     // mark merge boundaries
236     A.mark(lo);
237     A.mark(mid,3);
238     A.mark(hi-1);
239 
240     // allocate output
241     std::vector<value_type> out(hi-lo);
242 
243     // merge
244     size_t i = lo, j = mid, o = 0; // first and second halves
245     while (i < mid && j < hi)
246     {
247         // copy out for fewer time steps
248         value_type ai = A[i], aj = A[j];
249 
250         out[o++] = (ai < aj ? (++i, ai) : (++j, aj));
251     }
252 
253     // copy rest
254     while (i < mid) out[o++] = A[i++];
255     while (j < hi) out[o++] = A[j++];
256 
257     ASSERT(o == hi-lo);
258 
259     A.unmark(mid);
260 
261     // copy back
262     for (i = 0; i < hi-lo; ++i)
263         A.set(lo + i, out[i]);
264 
265     A.unmark(lo);
266     A.unmark(hi-1);
267 }
268 
MergeSort(SortArray & A,size_t lo,size_t hi)269 void MergeSort(SortArray& A, size_t lo, size_t hi)
270 {
271     if (lo + 1 < hi)
272     {
273         size_t mid = (lo + hi) / 2;
274 
275         MergeSort(A, lo, mid);
276         MergeSort(A, mid, hi);
277 
278         Merge(A, lo, mid, hi);
279     }
280 }
281 
MergeSort(SortArray & A)282 void MergeSort(SortArray& A)
283 {
284     return MergeSort(A, 0, A.size());
285 }
286 
MergeSortIterative(SortArray & A)287 void MergeSortIterative(SortArray& A)
288 {
289     for (size_t s = 1; s < A.size(); s *= 2)
290     {
291         for (size_t i = 0; i + s < A.size(); i += 2 * s)
292         {
293             Merge(A, i, i + s,
294                   std::min(i + 2 * s, A.size()));
295         }
296     }
297 }
298 
299 // ****************************************************************************
300 // *** Quick Sort Pivot Selection
301 
302 QuickSortPivotType g_quicksort_pivot = PIVOT_FIRST;
303 
304 // some quicksort variants use hi inclusive and some exclusive, we require it
305 // to be _exclusive_. hi == array.end()!
QuickSortSelectPivot(SortArray & A,ssize_t lo,ssize_t hi)306 ssize_t QuickSortSelectPivot(SortArray& A, ssize_t lo, ssize_t hi)
307 {
308     if (g_quicksort_pivot == PIVOT_FIRST)
309         return lo;
310 
311     if (g_quicksort_pivot == PIVOT_LAST)
312         return hi-1;
313 
314     if (g_quicksort_pivot == PIVOT_MID)
315         return (lo + hi) / 2;
316 
317     if (g_quicksort_pivot == PIVOT_RANDOM)
318         return lo + (rand() % (hi - lo));
319 
320     if (g_quicksort_pivot == PIVOT_MEDIAN3)
321     {
322         ssize_t mid = (lo + hi) / 2;
323 
324         // cases if two are equal
325         if (A[lo] == A[mid]) return lo;
326         if (A[lo] == A[hi-1] || A[mid] == A[hi-1]) return hi-1;
327 
328         // cases if three are different
329         return A[lo] < A[mid]
330             ? (A[mid] < A[hi-1] ? mid : (A[lo] < A[hi-1] ? hi-1 : lo))
331             : (A[mid] > A[hi-1] ? mid : (A[lo] < A[hi-1] ? lo : hi-1));
332     }
333 
334     return lo;
335 }
336 
QuickSortPivotText()337 wxArrayString QuickSortPivotText()
338 {
339     wxArrayString sl;
340 
341     sl.Add( _("First Item") );
342     sl.Add( _("Last Item") );
343     sl.Add( _("Middle Item") );
344     sl.Add( _("Random Item") );
345     sl.Add( _("Median of Three") );
346 
347     return sl;
348 }
349 
350 // ****************************************************************************
351 // *** Quick Sort LR (in-place, pointers at left and right, pivot is middle element)
352 
353 // by myself (Timo Bingmann), based on Hoare's original code
354 
QuickSortLR(SortArray & A,ssize_t lo,ssize_t hi)355 void QuickSortLR(SortArray& A, ssize_t lo, ssize_t hi)
356 {
357     // pick pivot and watch
358     volatile ssize_t p = QuickSortSelectPivot(A, lo, hi+1);
359 
360     value_type pivot = A[p];
361     A.watch(&p, 2);
362 
363     volatile ssize_t i = lo, j = hi;
364     A.watch(&i, 3);
365     A.watch(&j, 3);
366 
367     while (i <= j)
368     {
369         while (A[i] < pivot)
370             i++;
371 
372         while (A[j] > pivot)
373             j--;
374 
375         if (i <= j)
376         {
377             A.swap(i,j);
378 
379             // follow pivot if it is swapped
380             if (p == i) p = j;
381             else if (p == j) p = i;
382 
383             i++, j--;
384         }
385     }
386 
387     A.unwatch_all();
388 
389     if (lo < j)
390         QuickSortLR(A, lo, j);
391 
392     if (i < hi)
393         QuickSortLR(A, i, hi);
394 }
395 
QuickSortLR(SortArray & A)396 void QuickSortLR(SortArray& A)
397 {
398     return QuickSortLR(A, 0, A.size()-1);
399 }
400 
401 // ****************************************************************************
402 // *** Quick Sort LL (in-place, two pointers at left, pivot is first element and moved to right)
403 
404 // by myself (Timo Bingmann), based on CLRS' 3rd edition
405 
PartitionLL(SortArray & A,size_t lo,size_t hi)406 size_t PartitionLL(SortArray& A, size_t lo, size_t hi)
407 {
408     // pick pivot and move to back
409     size_t p = QuickSortSelectPivot(A, lo, hi);
410 
411     value_type pivot = A[p];
412     A.swap(p, hi-1);
413     A.mark(hi-1);
414 
415     volatile ssize_t i = lo;
416     A.watch(&i, 3);
417 
418     for (size_t j = lo; j < hi-1; ++j)
419     {
420         if (A[j] <= pivot) {
421             A.swap(i, j);
422             ++i;
423         }
424     }
425 
426     A.swap(i, hi-1);
427     A.unmark(hi-1);
428     A.unwatch_all();
429 
430     return i;
431 }
432 
QuickSortLL(SortArray & A,size_t lo,size_t hi)433 void QuickSortLL(SortArray& A, size_t lo, size_t hi)
434 {
435     if (lo + 1 < hi)
436     {
437         size_t mid = PartitionLL(A, lo, hi);
438 
439         QuickSortLL(A, lo, mid);
440         QuickSortLL(A, mid+1, hi);
441     }
442 }
443 
QuickSortLL(SortArray & A)444 void QuickSortLL(SortArray& A)
445 {
446     return QuickSortLL(A, 0, A.size());
447 }
448 
449 // ****************************************************************************
450 // *** Quick Sort Ternary (in-place, two pointers at left, pivot is first element and moved to right)
451 
452 // by myself (Timo Bingmann), loosely based on multikey quicksort by B&S
453 
QuickSortTernaryLR(SortArray & A,ssize_t lo,ssize_t hi)454 void QuickSortTernaryLR(SortArray& A, ssize_t lo, ssize_t hi)
455 {
456     if (hi <= lo) return;
457 
458     int cmp;
459 
460     // pick pivot and swap to back
461     ssize_t piv = QuickSortSelectPivot(A, lo, hi+1);
462     A.swap(piv, hi);
463     A.mark(hi);
464 
465     const value_type& pivot = A[hi];
466 
467     // schema: |p ===  |i <<< | ??? |j >>> |q === |piv
468     volatile ssize_t i = lo, j = hi-1;
469     volatile ssize_t p = lo, q = hi-1;
470 
471     A.watch(&i, 3);
472     A.watch(&j, 3);
473 
474     for (;;)
475     {
476         // partition on left
477         while (i <= j && (cmp = A[i].cmp(pivot)) <= 0)
478         {
479             if (cmp == 0) {
480                 A.mark(p,4);
481                 A.swap(i, p++);
482             }
483             ++i;
484         }
485 
486         // partition on right
487         while (i <= j && (cmp = A[j].cmp(pivot)) >= 0)
488         {
489             if (cmp == 0) {
490                 A.mark(q,4);
491                 A.swap(j, q--);
492             }
493             --j;
494         }
495 
496         if (i > j) break;
497 
498         // swap item between < > regions
499         A.swap(i++, j--);
500     }
501 
502     // swap pivot to right place
503     A.swap(i,hi);
504     A.mark_swap(i,hi);
505 
506     ssize_t num_less = i - p;
507     ssize_t num_greater = q - j;
508 
509     // swap equal ranges into center, but avoid swapping equal elements
510     j = i-1; i = i+1;
511 
512     ssize_t pe = lo + std::min(p-lo, num_less);
513     for (ssize_t k = lo; k < pe; k++, j--) {
514         A.swap(k,j);
515         A.mark_swap(k,j);
516     }
517 
518     ssize_t qe = hi-1 - std::min(hi-1-q, num_greater-1); // one already greater at end
519     for (ssize_t k = hi-1; k > qe; k--, i++) {
520         A.swap(i,k);
521         A.mark_swap(i,k);
522     }
523 
524     A.unwatch_all();
525     A.unmark_all();
526 
527     QuickSortTernaryLR(A, lo, lo + num_less - 1);
528     QuickSortTernaryLR(A, hi - num_greater + 1, hi);
529 }
530 
QuickSortTernaryLR(SortArray & A)531 void QuickSortTernaryLR(SortArray& A)
532 {
533     return QuickSortTernaryLR(A, 0, A.size()-1);
534 }
535 
536 // ****************************************************************************
537 // *** Quick Sort LL (in-place, two pointers at left, pivot is first element and moved to right)
538 
539 // by myself (Timo Bingmann)
540 
PartitionTernaryLL(SortArray & A,ssize_t lo,ssize_t hi)541 std::pair<ssize_t,ssize_t> PartitionTernaryLL(SortArray& A, ssize_t lo, ssize_t hi)
542 {
543     // pick pivot and swap to back
544     ssize_t p = QuickSortSelectPivot(A, lo, hi);
545 
546     value_type pivot = A[p];
547     A.swap(p, hi-1);
548     A.mark(hi-1);
549 
550     volatile ssize_t i = lo, k = hi-1;
551     A.watch(&i, 3);
552 
553     for (ssize_t j = lo; j < k; ++j)
554     {
555         int cmp = A[j].cmp(pivot); // ternary comparison
556         if (cmp == 0) {
557             A.swap(--k, j);
558             --j; // reclassify A[j]
559             A.mark(k,4);
560         }
561         else if (cmp < 0) {
562             A.swap(i++, j);
563         }
564     }
565 
566     // unwatch i, because the pivot is swapped there
567     // in the first step of the following swap loop.
568     A.unwatch_all();
569 
570     ssize_t j = i + (hi-k);
571 
572     for (ssize_t s = 0; s < hi-k; ++s) {
573         A.swap(i+s, hi-1-s);
574         A.mark_swap(i+s, hi-1-s);
575     }
576     A.unmark_all();
577 
578     return std::make_pair(i,j);
579 }
580 
QuickSortTernaryLL(SortArray & A,size_t lo,size_t hi)581 void QuickSortTernaryLL(SortArray& A, size_t lo, size_t hi)
582 {
583     if (lo + 1 < hi)
584     {
585         std::pair<ssize_t,ssize_t> mid = PartitionTernaryLL(A, lo, hi);
586 
587         QuickSortTernaryLL(A, lo, mid.first);
588         QuickSortTernaryLL(A, mid.second, hi);
589     }
590 }
591 
QuickSortTernaryLL(SortArray & A)592 void QuickSortTernaryLL(SortArray& A)
593 {
594     return QuickSortTernaryLL(A, 0, A.size());
595 }
596 
597 // ****************************************************************************
598 // *** Dual-Pivot Quick Sort
599 
600 // by Sebastian Wild
601 
dualPivotYaroslavskiy(class SortArray & a,int left,int right)602 void dualPivotYaroslavskiy(class SortArray& a, int left, int right)
603 {
604     if (right > left)
605     {
606         if (a[left] > a[right]) {
607             a.swap(left, right);
608         }
609 
610         const value_type p = a[left];
611         const value_type q = a[right];
612 
613         a.mark(left);
614         a.mark(right);
615 
616         volatile ssize_t l = left + 1;
617         volatile ssize_t g = right - 1;
618         volatile ssize_t k = l;
619 
620         a.watch(&l, 3);
621         a.watch(&g, 3);
622         a.watch(&k, 3);
623 
624         while (k <= g)
625         {
626             if (a[k] < p) {
627                 a.swap(k, l);
628                 ++l;
629             }
630             else if (a[k] >= q) {
631                 while (a[g] > q && k < g)  --g;
632                 a.swap(k, g);
633                 --g;
634 
635                 if (a[k] < p) {
636                     a.swap(k, l);
637                     ++l;
638                 }
639             }
640             ++k;
641         }
642         --l;
643         ++g;
644         a.swap(left, l);
645         a.swap(right, g);
646 
647         a.unmark_all();
648         a.unwatch_all();
649 
650         dualPivotYaroslavskiy(a, left, l - 1);
651         dualPivotYaroslavskiy(a, l + 1, g - 1);
652         dualPivotYaroslavskiy(a, g + 1, right);
653     }
654 }
655 
QuickSortDualPivot(class SortArray & a)656 void QuickSortDualPivot(class SortArray& a)
657 {
658     return dualPivotYaroslavskiy(a, 0, a.size()-1);
659 }
660 
661 // ****************************************************************************
662 // *** Bubble Sort
663 
BubbleSort(SortArray & A)664 void BubbleSort(SortArray& A)
665 {
666     for (size_t i = 0; i < A.size()-1; ++i)
667     {
668         for (size_t j = 0; j < A.size()-1 - i; ++j)
669         {
670             if (A[j] > A[j + 1])
671             {
672                 A.swap(j, j+1);
673             }
674         }
675     }
676 }
677 
678 // ****************************************************************************
679 // *** Cocktail Shaker Sort
680 
681 // from http://de.wikibooks.org/wiki/Algorithmen_und_Datenstrukturen_in_C/_Shakersort
682 
CocktailShakerSort(SortArray & A)683 void CocktailShakerSort(SortArray& A)
684 {
685     size_t lo = 0, hi = A.size()-1, mov = lo;
686 
687     while (lo < hi)
688     {
689         for (size_t i = hi; i > lo; --i)
690         {
691             if (A[i-1] > A[i])
692             {
693                 A.swap(i-1, i);
694                 mov = i;
695             }
696         }
697 
698         lo = mov;
699 
700         for (size_t i = lo; i < hi; ++i)
701         {
702             if (A[i] > A[i+1])
703             {
704                 A.swap(i, i+1);
705                 mov = i;
706             }
707         }
708 
709         hi = mov;
710     }
711 }
712 
713 // ****************************************************************************
714 // *** Gnome Sort
715 
716 // from http://en.wikipediA.org/wiki/Gnome_sort
717 
GnomeSort(SortArray & A)718 void GnomeSort(SortArray& A)
719 {
720     for (size_t i = 1; i < A.size(); )
721     {
722         if (A[i] >= A[i-1])
723         {
724             ++i;
725         }
726         else
727         {
728             A.swap(i, i-1);
729             if (i > 1) --i;
730         }
731     }
732 }
733 
734 // ****************************************************************************
735 // *** Comb Sort
736 
737 // from http://en.wikipediA.org/wiki/Comb_sort
738 
CombSort(SortArray & A)739 void CombSort(SortArray& A)
740 {
741     const double shrink = 1.3;
742 
743     bool swapped = false;
744     size_t gap = A.size();
745 
746     while ((gap > 1) || swapped)
747     {
748         if (gap > 1) {
749             gap = (size_t)((float)gap / shrink);
750         }
751 
752         swapped = false;
753 
754         for (size_t i = 0; gap + i < A.size(); ++i)
755         {
756             if (A[i] > A[i + gap])
757             {
758                 A.swap(i, i+gap);
759                 swapped = true;
760             }
761         }
762     }
763 }
764 
765 // ****************************************************************************
766 // *** Odd-Even Sort
767 
768 // from http://en.wikipediA.org/wiki/Odd%E2%80%93even_sort
769 
OddEvenSort(SortArray & A)770 void OddEvenSort(SortArray& A)
771 {
772     bool sorted = false;
773 
774     while (!sorted)
775     {
776         sorted = true;
777 
778         for (size_t i = 1; i < A.size()-1; i += 2)
779         {
780             if(A[i] > A[i+1])
781             {
782                 A.swap(i, i+1);
783                 sorted = false;
784             }
785         }
786 
787         for (size_t i = 0; i < A.size()-1; i += 2)
788         {
789             if(A[i] > A[i+1])
790             {
791                 A.swap(i, i+1);
792                 sorted = false;
793             }
794         }
795     }
796 }
797 
798 // ****************************************************************************
799 // *** Shell Sort
800 
801 // with gaps by Robert Sedgewick from http://www.cs.princeton.edu/~rs/shell/shell.c
802 
ShellSort(SortArray & A)803 void ShellSort(SortArray& A)
804 {
805     size_t incs[16] = { 1391376, 463792, 198768, 86961, 33936,
806                         13776, 4592, 1968, 861, 336,
807                         112, 48, 21, 7, 3, 1 };
808 
809     for (size_t k = 0; k < 16; k++)
810     {
811         for (size_t h = incs[k], i = h; i < A.size(); i++)
812         {
813             value_type v = A[i];
814             size_t j = i;
815 
816             while (j >= h && A[j-h] > v)
817             {
818                 A.set(j, A[j-h]);
819                 j -= h;
820             }
821 
822             A.set(j, v);
823         }
824     }
825 }
826 
827 // ****************************************************************************
828 // *** Heap Sort
829 
830 // heavily adapted from http://www.codecodex.com/wiki/Heapsort
831 
isPowerOfTwo(size_t x)832 bool isPowerOfTwo(size_t x)
833 {
834     return ((x != 0) && !(x & (x - 1)));
835 }
836 
prevPowerOfTwo(uint32_t x)837 uint32_t prevPowerOfTwo(uint32_t x)
838 {
839     x |= x >> 1; x |= x >> 2; x |= x >> 4;
840     x |= x >> 8; x |= x >> 16;
841     return x - (x >> 1);
842 }
843 
largestPowerOfTwoLessThan(int n)844 int largestPowerOfTwoLessThan(int n)
845 {
846     int k = 1;
847     while (k < n) k = k << 1;
848     return k >> 1;
849 }
850 
HeapSort(SortArray & A)851 void HeapSort(SortArray& A)
852 {
853     size_t n = A.size(), i = n / 2;
854 
855     // mark heap levels with different colors
856     for (size_t j = i; j < n; ++j)
857         A.mark(j, log(prevPowerOfTwo(j+1)) / log(2) + 4);
858 
859     while (1)
860     {
861         if (i > 0) {
862             // build heap, sift A[i] down the heap
863             i--;
864         }
865         else {
866             // pop largest element from heap: swap front to back, and sift
867             // front A[0] down the heap
868             n--;
869             if (n == 0) return;
870             A.swap(0,n);
871 
872             A.mark(n);
873             if (n+1 < A.size()) A.unmark(n+1);
874         }
875 
876         size_t parent = i;
877         size_t child = i*2 + 1;
878 
879         // sift operation - push the value of A[i] down the heap
880         while (child < n)
881         {
882             if (child + 1 < n && A[child + 1] > A[child]) {
883                 child++;
884             }
885             if (A[child] > A[parent]) {
886                 A.swap(parent, child);
887                 parent = child;
888                 child = parent*2+1;
889             }
890             else {
891                 break;
892             }
893         }
894 
895         // mark heap levels with different colors
896         A.mark(i, log(prevPowerOfTwo(i+1)) / log(2) + 4);
897     }
898 
899 }
900 
901 // ****************************************************************************
902 // *** Radix Sort (counting sort, most significant digit (MSD) first, in-place redistribute)
903 
904 // by myself (Timo Bingmann)
905 
RadixSortMSD(SortArray & A,size_t lo,size_t hi,size_t depth)906 void RadixSortMSD(SortArray& A, size_t lo, size_t hi, size_t depth)
907 {
908     A.mark(lo); A.mark(hi-1);
909 
910     // radix and base calculations
911     const unsigned int RADIX = 4;
912 
913     unsigned int pmax = floor( log(A.array_max()+1) / log(RADIX) );
914     ASSERT(depth <= pmax);
915 
916     size_t base = pow(RADIX, pmax - depth);
917 
918     // count digits
919     std::vector<size_t> count(RADIX, 0);
920 
921     for (size_t i = lo; i < hi; ++i)
922     {
923         size_t r = A[i].get() / base % RADIX;
924         ASSERT(r < RADIX);
925         count[r]++;
926     }
927 
928     // inclusive prefix sum
929     std::vector<size_t> bkt(RADIX, 0);
930     std::partial_sum(count.begin(), count.end(), bkt.begin());
931 
932     // mark bucket boundaries
933     for (size_t i = 0; i < bkt.size(); ++i) {
934         if (bkt[i] == 0) continue;
935         A.mark(lo + bkt[i]-1, 3);
936     }
937 
938     // reorder items in-place by walking cycles
939     for (size_t i=0, j; i < (hi-lo); )
940     {
941         while ( (j = --bkt[ (A[lo+i].get() / base % RADIX) ]) > i )
942         {
943             A.swap(lo + i, lo + j);
944         }
945         i += count[ (A[lo+i].get() / base % RADIX) ];
946     }
947 
948     A.unmark_all();
949 
950     // no more depth to sort?
951     if (depth+1 > pmax) return;
952 
953     // recurse on buckets
954     size_t sum = lo;
955     for (size_t i = 0; i < RADIX; ++i)
956     {
957         if (count[i] > 1)
958             RadixSortMSD(A, sum, sum+count[i], depth+1);
959         sum += count[i];
960     }
961 }
962 
RadixSortMSD(SortArray & A)963 void RadixSortMSD(SortArray& A)
964 {
965     return RadixSortMSD(A, 0, A.size(), 0);
966 }
967 
968 // ****************************************************************************
969 // *** Radix Sort (counting sort, least significant digit (LSD) first, out-of-place redistribute)
970 
971 // by myself (Timo Bingmann)
972 
RadixSortLSD(SortArray & A)973 void RadixSortLSD(SortArray& A)
974 {
975     // radix and base calculations
976     const unsigned int RADIX = 4;
977 
978     unsigned int pmax = ceil( log(A.array_max()+1) / log(RADIX) );
979 
980     for (unsigned int p = 0; p < pmax; ++p)
981     {
982         size_t base = pow(RADIX, p);
983 
984         // count digits and copy data
985         std::vector<size_t> count(RADIX, 0);
986         std::vector<value_type> copy(A.size());
987 
988         for (size_t i = 0; i < A.size(); ++i)
989         {
990             size_t r = (copy[i] = A[i]).get() / base % RADIX;
991             ASSERT(r < RADIX);
992             count[r]++;
993         }
994 
995         // exclusive prefix sum
996         std::vector<size_t> bkt(RADIX+1, 0);
997         std::partial_sum(count.begin(), count.end(), bkt.begin()+1);
998 
999         // mark bucket boundaries
1000         for (size_t i = 0; i < bkt.size()-1; ++i) {
1001             if (bkt[i] >= A.size()) continue;
1002             A.mark(bkt[i], 3);
1003         }
1004 
1005         // redistribute items back into array (stable)
1006         for (size_t i=0; i < A.size(); ++i)
1007         {
1008             size_t r = copy[i].get() / base % RADIX;
1009             A.set( bkt[r]++, copy[i] );
1010         }
1011 
1012         A.unmark_all();
1013     }
1014 }
1015 
1016 // ****************************************************************************
1017 // *** Use STL Sorts via Iterator Adapters
1018 
StlSort(SortArray & A)1019 void StlSort(SortArray& A)
1020 {
1021     std::sort(MyIterator(&A,0), MyIterator(&A,A.size()));
1022 }
1023 
StlStableSort(SortArray & A)1024 void StlStableSort(SortArray& A)
1025 {
1026     std::stable_sort(MyIterator(&A,0), MyIterator(&A,A.size()));
1027 }
1028 
StlHeapSort(SortArray & A)1029 void StlHeapSort(SortArray& A)
1030 {
1031     std::make_heap(MyIterator(&A,0), MyIterator(&A,A.size()));
1032     std::sort_heap(MyIterator(&A,0), MyIterator(&A,A.size()));
1033 }
1034 
1035 // ****************************************************************************
1036 // *** BogoSort and more slow sorts
1037 
1038 // by myself (Timo Bingmann)
1039 
BogoCheckSorted(SortArray & A)1040 bool BogoCheckSorted(SortArray& A)
1041 {
1042     size_t i;
1043     value_type prev = A[0];
1044     A.mark(0);
1045     for (i = 1; i < A.size(); ++i)
1046     {
1047         value_type val = A[i];
1048         if (prev > val) break;
1049         prev = val;
1050         A.mark(i);
1051     }
1052 
1053     if (i == A.size()) {
1054         // this is amazing.
1055         return true;
1056     }
1057 
1058     // unmark
1059     while (i > 0) A.unmark(i--);
1060     A.unmark(0);
1061 
1062     return false;
1063 }
1064 
BogoSort(SortArray & A)1065 void BogoSort(SortArray& A)
1066 {
1067     // keep a permutation of [0,size)
1068     std::vector<size_t> perm(A.size());
1069 
1070     for (size_t i = 0; i < A.size(); ++i)
1071         perm[i] = i;
1072 
1073     while (1)
1074     {
1075         // check if array is sorted
1076         if (BogoCheckSorted(A)) break;
1077 
1078         // pick a random permutation of indexes
1079         std::random_shuffle(perm.begin(), perm.end());
1080 
1081         // permute array in-place
1082         std::vector<char> pmark(A.size(), 0);
1083 
1084         for (size_t i = 0; i < A.size(); ++i)
1085         {
1086             if (pmark[i]) continue;
1087 
1088             // walk a cycle
1089             size_t j = i;
1090 
1091             //std::cout << "cycle start " << j << " -> " << perm[j] << "\n";
1092 
1093             while ( perm[j] != i )
1094             {
1095                 ASSERT(!pmark[j]);
1096                 A.swap(j, perm[j]);
1097                 pmark[j] = 1;
1098 
1099                 j = perm[j];
1100                 //std::cout << "cycle step " << j << " -> " << perm[j] << "\n";
1101             }
1102             //std::cout << "cycle end\n";
1103 
1104             ASSERT(!pmark[j]);
1105             pmark[j] = 1;
1106         }
1107 
1108         //std::cout << "permute end\n";
1109 
1110         for (size_t i = 0; i < A.size(); ++i)
1111             ASSERT(pmark[i]);
1112     }
1113 }
1114 
BozoSort(SortArray & A)1115 void BozoSort(SortArray& A)
1116 {
1117     srand(time(NULL));
1118 
1119     while (1)
1120     {
1121         // check if array is sorted
1122         if (BogoCheckSorted(A)) break;
1123 
1124         // swap two random items
1125         A.swap(rand() % A.size(), rand() % A.size());
1126     }
1127 }
1128 
1129 // ****************************************************************************
1130 // *** Bitonic Sort
1131 
1132 // from http://www.iti.fh-flensburg.de/lang/algorithmen/sortieren/bitonic/oddn.htm
1133 
1134 namespace BitonicSortNS {
1135 
1136 static const bool ASCENDING = true;    // sorting direction
1137 
compare(SortArray & A,int i,int j,bool dir)1138 static void compare(SortArray& A, int i, int j, bool dir)
1139 {
1140     if (dir == (A[i] > A[j]))
1141         A.swap(i, j);
1142 }
1143 
bitonicMerge(SortArray & A,int lo,int n,bool dir)1144 static void bitonicMerge(SortArray& A, int lo, int n, bool dir)
1145 {
1146     if (n > 1)
1147     {
1148         int m = largestPowerOfTwoLessThan(n);
1149 
1150         for (int i = lo; i < lo + n - m; i++)
1151             compare(A, i, i+m, dir);
1152 
1153         bitonicMerge(A, lo, m, dir);
1154         bitonicMerge(A, lo + m, n - m, dir);
1155     }
1156 }
1157 
bitonicSort(SortArray & A,int lo,int n,bool dir)1158 static void bitonicSort(SortArray& A, int lo, int n, bool dir)
1159 {
1160     if (n > 1)
1161     {
1162         int m = n / 2;
1163         bitonicSort(A, lo, m, !dir);
1164         bitonicSort(A, lo + m, n - m, dir);
1165         bitonicMerge(A, lo, n, dir);
1166     }
1167 }
1168 
1169 } // namespace BitonicSortNS
1170 
BitonicSort(SortArray & A)1171 void BitonicSort(SortArray& A)
1172 {
1173     BitonicSortNS::bitonicSort(A, 0, A.size(), BitonicSortNS::ASCENDING);
1174 }
1175 
1176 // ****************************************************************************
1177 // *** Bitonic Sort as "Parallel" Sorting Network
1178 
1179 // from http://www.iti.fh-flensburg.de/lang/algorithmen/sortieren/bitonic/oddn.htm
1180 
1181 // modified to first record the recursively generated swap sequence, and then
1182 // sort it back into the order a parallel sorting network would perform the
1183 // swaps in
1184 
1185 namespace BitonicSortNetworkNS {
1186 
1187 struct swappair_type
1188 {
1189     // swapped positions
1190     unsigned int i,j;
1191 
1192     // depth of recursions: sort / merge
1193     unsigned int sort_depth, merge_depth;
1194 
swappair_typeBitonicSortNetworkNS::swappair_type1195     swappair_type(unsigned int _i, unsigned int _j,
1196                   unsigned int _sort_depth, unsigned int _merge_depth)
1197         : i(_i), j(_j),
1198           sort_depth(_sort_depth), merge_depth(_merge_depth)
1199     { }
1200 
1201     // order relation for sorting swaps
operator <BitonicSortNetworkNS::swappair_type1202     bool operator < (const swappair_type& b) const
1203     {
1204         if (sort_depth != b.sort_depth)
1205             return sort_depth > b.sort_depth;
1206 
1207         if (merge_depth != b.merge_depth)
1208             return merge_depth < b.merge_depth;
1209 
1210         return i < b.i;
1211     }
1212 };
1213 
1214 typedef std::vector<swappair_type> sequence_type;
1215 std::vector<swappair_type> sequence;
1216 
replay(SortArray & A)1217 void replay(SortArray& A)
1218 {
1219     for (sequence_type::const_iterator si = sequence.begin();
1220          si != sequence.end(); ++si)
1221     {
1222         if (A[si->i] > A[si->j])
1223             A.swap(si->i, si->j);
1224     }
1225 }
1226 
1227 static const bool ASCENDING = true; // sorting direction
1228 
compare(SortArray &,unsigned int i,unsigned int j,bool dir,unsigned int sort_depth,unsigned int merge_depth)1229 static void compare(SortArray& /* A */, unsigned int i, unsigned int j, bool dir,
1230                     unsigned int sort_depth, unsigned int merge_depth)
1231 {
1232     // if (dir == (A[i] > A[j])) A.swap(i, j);
1233 
1234     if (dir)
1235         sequence.push_back( swappair_type(i,j, sort_depth, merge_depth) );
1236     else
1237         sequence.push_back( swappair_type(j,i, sort_depth, merge_depth) );
1238 }
1239 
bitonicMerge(SortArray & A,unsigned int lo,unsigned int n,bool dir,unsigned int sort_depth,unsigned int merge_depth)1240 static void bitonicMerge(SortArray& A, unsigned int lo, unsigned int n, bool dir,
1241                          unsigned int sort_depth, unsigned int merge_depth)
1242 {
1243     if (n > 1)
1244     {
1245         unsigned int m = largestPowerOfTwoLessThan(n);
1246 
1247         for (unsigned int i = lo; i < lo + n - m; i++)
1248             compare(A, i, i + m, dir, sort_depth, merge_depth);
1249 
1250         bitonicMerge(A, lo, m, dir, sort_depth, merge_depth+1);
1251         bitonicMerge(A, lo + m, n - m, dir, sort_depth, merge_depth+1);
1252     }
1253 }
1254 
bitonicSort(SortArray & A,unsigned int lo,unsigned int n,bool dir,unsigned int sort_depth)1255 static void bitonicSort(SortArray& A, unsigned int lo, unsigned int n, bool dir,
1256                         unsigned int sort_depth)
1257 {
1258     if (n > 1)
1259     {
1260         unsigned int m = n / 2;
1261         bitonicSort(A, lo, m, !dir, sort_depth+1);
1262         bitonicSort(A, lo + m, n - m, dir, sort_depth+1);
1263         bitonicMerge(A, lo, n, dir, sort_depth, 0);
1264     }
1265 }
1266 
sort(SortArray & A)1267 void sort(SortArray& A)
1268 {
1269     sequence.clear();
1270     bitonicSort(A, 0, A.size(), BitonicSortNS::ASCENDING, 0);
1271     std::sort(sequence.begin(), sequence.end());
1272     replay(A);
1273     sequence.clear();
1274 }
1275 
1276 } // namespace BitonicSortNS
1277 
BitonicSortNetwork(SortArray & A)1278 void BitonicSortNetwork(SortArray& A)
1279 {
1280     BitonicSortNetworkNS::sort(A);
1281 }
1282 
1283 // ****************************************************************************
1284 // *** Batcher's Odd-Even Merge Sort as "Parallel" Sorting Network
1285 
1286 // from http://www.iti.fh-flensburg.de/lang/algorithmen/sortieren/networks/oemen.htm
1287 
1288 // modified to first record the recursively generated swap sequence, and then
1289 // sort it back into the order a parallel sorting network would perform the
1290 // swaps in
1291 
1292 namespace BatcherSortNetworkNS {
1293 
1294 struct swappair_type
1295 {
1296     // swapped positions
1297     unsigned int i,j;
1298 
1299     // depth of recursions: sort / merge
1300     unsigned int sort_depth, merge_depth;
1301 
swappair_typeBatcherSortNetworkNS::swappair_type1302     swappair_type(unsigned int _i, unsigned int _j,
1303                   unsigned int _sort_depth, unsigned int _merge_depth)
1304         : i(_i), j(_j),
1305           sort_depth(_sort_depth), merge_depth(_merge_depth)
1306     { }
1307 
1308     // order relation for sorting swaps
operator <BatcherSortNetworkNS::swappair_type1309     bool operator < (const swappair_type& b) const
1310     {
1311         if (sort_depth != b.sort_depth)
1312             return sort_depth > b.sort_depth;
1313 
1314         if (merge_depth != b.merge_depth)
1315             return merge_depth > b.merge_depth;
1316 
1317         return i < b.i;
1318     }
1319 };
1320 
1321 typedef std::vector<swappair_type> sequence_type;
1322 std::vector<swappair_type> sequence;
1323 
replay(SortArray & A)1324 void replay(SortArray& A)
1325 {
1326     for (sequence_type::const_iterator si = sequence.begin();
1327          si != sequence.end(); ++si)
1328     {
1329         if (A[si->i] > A[si->j])
1330             A.swap(si->i, si->j);
1331     }
1332 }
1333 
compare(SortArray & A,unsigned int i,unsigned int j,unsigned int sort_depth,unsigned int merge_depth)1334 static void compare(SortArray& A, unsigned int i, unsigned int j,
1335                     unsigned int sort_depth, unsigned int merge_depth)
1336 {
1337     // skip all swaps beyond end of array
1338     ASSERT(i < j);
1339     if (j >= A.size()) return;
1340 
1341     sequence.push_back( swappair_type(i,j, sort_depth, merge_depth) );
1342 
1343     //if (A[i] > A[j]) A.swap(i, j);
1344 }
1345 
1346 // lo is the starting position and n is the length of the piece to be merged, r
1347 // is the distance of the elements to be compared
oddEvenMerge(SortArray & A,unsigned int lo,unsigned int n,unsigned int r,unsigned int sort_depth,unsigned int merge_depth)1348 static void oddEvenMerge(SortArray& A, unsigned int lo, unsigned int n, unsigned int r,
1349                          unsigned int sort_depth, unsigned int merge_depth)
1350 {
1351     unsigned int m = r * 2;
1352     if (m < n)
1353     {
1354         // even subsequence
1355         oddEvenMerge(A, lo, n, m, sort_depth, merge_depth+1);
1356         // odd subsequence
1357         oddEvenMerge(A, lo + r, n, m, sort_depth, merge_depth+1);
1358 
1359         for (unsigned int i = lo + r; i + r < lo + n; i += m)
1360             compare(A, i, i + r, sort_depth, merge_depth);
1361     }
1362     else {
1363         compare(A, lo, lo + r, sort_depth, merge_depth);
1364     }
1365 }
1366 
1367 // sorts a piece of length n of the array starting at position lo
oddEvenMergeSort(SortArray & A,unsigned int lo,unsigned int n,unsigned int sort_depth)1368 static void oddEvenMergeSort(SortArray& A, unsigned int lo, unsigned int n,
1369                              unsigned int sort_depth)
1370 {
1371     if (n > 1)
1372     {
1373         unsigned int m = n / 2;
1374         oddEvenMergeSort(A, lo, m, sort_depth+1);
1375         oddEvenMergeSort(A, lo + m, m, sort_depth+1);
1376         oddEvenMerge(A, lo, n, 1, sort_depth, 0);
1377     }
1378 }
1379 
sort(SortArray & A)1380 void sort(SortArray& A)
1381 {
1382     sequence.clear();
1383 
1384     unsigned int n = largestPowerOfTwoLessThan(A.size());
1385     if (n != A.size()) n *= 2;
1386 
1387     oddEvenMergeSort(A, 0, n, 0);
1388     std::sort(sequence.begin(), sequence.end());
1389     replay(A);
1390     sequence.clear();
1391 }
1392 
1393 } // namespace BatcherSortNetworkNS
1394 
BatcherSortNetwork(SortArray & A)1395 void BatcherSortNetwork(SortArray& A)
1396 {
1397     BatcherSortNetworkNS::sort(A);
1398 }
1399 
1400 // ****************************************************************************
1401 // *** Smooth Sort
1402 
1403 // from http://en.wikipediA.org/wiki/Smoothsort
1404 
1405 namespace SmoothSortNS {
1406 
1407 static const int LP[] = {
1408     1, 1, 3, 5, 9, 15, 25, 41, 67, 109,
1409     177, 287, 465, 753, 1219, 1973, 3193, 5167, 8361, 13529, 21891,
1410     35421, 57313, 92735, 150049, 242785, 392835, 635621, 1028457,
1411     1664079, 2692537, 4356617, 7049155, 11405773, 18454929, 29860703,
1412     48315633, 78176337, 126491971, 204668309, 331160281, 535828591,
1413     866988873 // the next number is > 31 bits.
1414 };
1415 
sift(SortArray & A,int pshift,int head)1416 static void sift(SortArray& A, int pshift, int head)
1417 {
1418     // we do not use Floyd's improvements to the heapsort sift, because we
1419     // are not doing what heapsort does - always moving nodes from near
1420     // the bottom of the tree to the root.
1421 
1422     value_type val = A[head];
1423 
1424     while (pshift > 1)
1425     {
1426         int rt = head - 1;
1427         int lf = head - 1 - LP[pshift - 2];
1428 
1429         if (val.cmp(A[lf]) >= 0 && val.cmp(A[rt]) >= 0)
1430             break;
1431 
1432         if (A[lf].cmp(A[rt]) >= 0) {
1433             A.set(head, A[lf]);
1434             head = lf;
1435             pshift -= 1;
1436         }
1437         else {
1438             A.set(head, A[rt]);
1439             head = rt;
1440             pshift -= 2;
1441         }
1442     }
1443 
1444     A.set(head, val);
1445 }
1446 
trinkle(SortArray & A,int p,int pshift,int head,bool isTrusty)1447 static void trinkle(SortArray& A, int p, int pshift, int head, bool isTrusty)
1448 {
1449     value_type val = A[head];
1450 
1451     while (p != 1)
1452     {
1453         int stepson = head - LP[pshift];
1454 
1455         if (A[stepson].cmp(val) <= 0)
1456             break; // current node is greater than head. sift.
1457 
1458         // no need to check this if we know the current node is trusty,
1459         // because we just checked the head (which is val, in the first
1460         // iteration)
1461         if (!isTrusty && pshift > 1) {
1462             int rt = head - 1;
1463             int lf = head - 1 - LP[pshift - 2];
1464             if (A[rt].cmp(A[stepson]) >= 0 ||
1465                 A[lf].cmp(A[stepson]) >= 0)
1466                 break;
1467         }
1468 
1469         A.set(head, A[stepson]);
1470 
1471         head = stepson;
1472         //int trail = Integer.numberOfTrailingZeros(p & ~1);
1473         int trail = __builtin_ctz(p & ~1);
1474         p >>= trail;
1475         pshift += trail;
1476         isTrusty = false;
1477     }
1478 
1479     if (!isTrusty) {
1480         A.set(head, val);
1481         sift(A, pshift, head);
1482     }
1483 }
1484 
sort(SortArray & A,int lo,int hi)1485 void sort(SortArray& A, int lo, int hi)
1486 {
1487     int head = lo; // the offset of the first element of the prefix into m
1488 
1489     // These variables need a little explaining. If our string of heaps
1490     // is of length 38, then the heaps will be of size 25+9+3+1, which are
1491     // Leonardo numbers 6, 4, 2, 1.
1492     // Turning this into a binary number, we get b01010110 = 0x56. We represent
1493     // this number as a pair of numbers by right-shifting all the zeros and
1494     // storing the mantissa and exponent as "p" and "pshift".
1495     // This is handy, because the exponent is the index into L[] giving the
1496     // size of the rightmost heap, and because we can instantly find out if
1497     // the rightmost two heaps are consecutive Leonardo numbers by checking
1498     // (p&3)==3
1499 
1500     int p = 1; // the bitmap of the current standard concatenation >> pshift
1501     int pshift = 1;
1502 
1503     while (head < hi)
1504     {
1505         if ((p & 3) == 3) {
1506             // Add 1 by merging the first two blocks into a larger one.
1507             // The next Leonardo number is one bigger.
1508             sift(A, pshift, head);
1509             p >>= 2;
1510             pshift += 2;
1511         }
1512         else {
1513             // adding a new block of length 1
1514             if (LP[pshift - 1] >= hi - head) {
1515                 // this block is its final size.
1516                 trinkle(A, p, pshift, head, false);
1517             } else {
1518                 // this block will get merged. Just make it trusty.
1519                 sift(A, pshift, head);
1520             }
1521 
1522             if (pshift == 1) {
1523                 // LP[1] is being used, so we add use LP[0]
1524                 p <<= 1;
1525                 pshift--;
1526             } else {
1527                 // shift out to position 1, add LP[1]
1528                 p <<= (pshift - 1);
1529                 pshift = 1;
1530             }
1531         }
1532         p |= 1;
1533         head++;
1534     }
1535 
1536     trinkle(A, p, pshift, head, false);
1537 
1538     while (pshift != 1 || p != 1)
1539     {
1540         if (pshift <= 1) {
1541             // block of length 1. No fiddling needed
1542             //int trail = Integer.numberOfTrailingZeros(p & ~1);
1543             int trail = __builtin_ctz(p & ~1);
1544             p >>= trail;
1545             pshift += trail;
1546         }
1547         else {
1548             p <<= 2;
1549             p ^= 7;
1550             pshift -= 2;
1551 
1552             // This block gets broken into three bits. The rightmost bit is a
1553             // block of length 1. The left hand part is split into two, a block
1554             // of length LP[pshift+1] and one of LP[pshift].  Both these two
1555             // are appropriately heapified, but the root nodes are not
1556             // necessarily in order. We therefore semitrinkle both of them
1557 
1558             trinkle(A, p >> 1, pshift + 1, head - LP[pshift] - 1, true);
1559             trinkle(A, p, pshift, head - 1, true);
1560         }
1561 
1562         head--;
1563     }
1564 }
1565 
1566 } // namespace SmoothSortNS
1567 
SmoothSort(SortArray & A)1568 void SmoothSort(SortArray& A)
1569 {
1570     return SmoothSortNS::sort(A, 0, A.size()-1);
1571 }
1572 
1573 // ****************************************************************************
1574 // *** Stooge Sort
1575 
StoogeSort(SortArray & A,int i,int j)1576 void StoogeSort(SortArray& A, int i, int j)
1577 {
1578     if (A[i] > A[j])
1579     {
1580         A.swap(i, j);
1581     }
1582 
1583     if (j - i + 1 >= 3)
1584     {
1585         int t = (j - i + 1) / 3;
1586 
1587         A.mark(i, 3);
1588         A.mark(j, 3);
1589 
1590         StoogeSort(A, i, j-t);
1591         StoogeSort(A, i+t, j);
1592         StoogeSort(A, i, j-t);
1593 
1594         A.unmark(i);
1595         A.unmark(j);
1596     }
1597 }
1598 
StoogeSort(SortArray & A)1599 void StoogeSort(SortArray& A)
1600 {
1601     StoogeSort(A, 0, A.size()-1);
1602 }
1603 
1604 // ****************************************************************************
1605 // *** Slow Sort
1606 
SlowSort(SortArray & A,int i,int j)1607 void SlowSort(SortArray& A, int i, int j)
1608 {
1609     if (i >= j) return;
1610 
1611     int m = (i + j) / 2;
1612 
1613     SlowSort(A, i, m);
1614     SlowSort(A, m+1, j);
1615 
1616     if (A[m] > A[j])
1617         A.swap(m, j);
1618 
1619     A.mark(j, 2);
1620 
1621     SlowSort(A, i, j-1);
1622 
1623     A.unmark(j);
1624 }
1625 
SlowSort(SortArray & A)1626 void SlowSort(SortArray& A)
1627 {
1628     SlowSort(A, 0, A.size()-1);
1629 }
1630 
1631 // ****************************************************************************
1632 // *** Cycle Sort
1633 
1634 // Adapted from http://en.wikipedia.org/wiki/Cycle_sort
1635 
CycleSort(SortArray & array,ssize_t n)1636 void CycleSort(SortArray& array, ssize_t n)
1637 {
1638     volatile ssize_t cycleStart = 0;
1639     array.watch(&cycleStart, 16);
1640 
1641     volatile ssize_t rank = 0;
1642     array.watch(&rank, 3);
1643 
1644     // Loop through the array to find cycles to rotate.
1645     for (cycleStart = 0; cycleStart < n - 1; ++cycleStart)
1646     {
1647         value_type& item = array.get_mutable(cycleStart);
1648 
1649         do {
1650             // Find where to put the item.
1651             rank = cycleStart;
1652             for (ssize_t i = cycleStart + 1; i < n; ++i)
1653             {
1654                 if (array[i] < item)
1655                     rank++;
1656             }
1657 
1658             // If the item is already there, this is a 1-cycle.
1659             if (rank == cycleStart) {
1660                 array.mark(rank, 2);
1661                 break;
1662             }
1663 
1664             // Otherwise, put the item after any duplicates.
1665             while (item == array[rank])
1666                 rank++;
1667 
1668             // Put item into right place and colorize
1669             std::swap(array.get_mutable(rank), item);
1670             array.mark(rank, 2);
1671 
1672             // Continue for rest of the cycle.
1673         }
1674         while (rank != cycleStart);
1675     }
1676 
1677     array.unwatch_all();
1678 }
1679 
CycleSort(SortArray & A)1680 void CycleSort(SortArray& A)
1681 {
1682     CycleSort(A, A.size());
1683 }
1684 
1685 // ****************************************************************************
1686