1 module rt.compiler.gdc.rt.qsortg;
2 struct Array
3 {
4     size_t length;
5     void*  ptr;
6 }
7 
8 extern (C) Array _adSort(Array a, TypeInfo ti)
9 {
10     static const uint Qsort_Threshold = 7;
11 
12     struct StackEntry {
13         byte *l;
14         byte *r;
15     }
16 
17     size_t elem_size = ti.tsize();
18     size_t qsort_limit = elem_size * Qsort_Threshold;
19 
20     static assert(ubyte.sizeof == 1);
21     static assert(ubyte.max == 255);
22 
23     StackEntry[size_t.sizeof * 8] stack; // log2( size_t.max )
24     StackEntry * sp = stack.ptr;
25     byte* lbound = cast(byte *) a.ptr;
26     byte* rbound = cast(byte *) a.ptr + a.length * elem_size;
27     byte* li = void;
28     byte* ri = void;
29 
30     while (1)
31     {
32         if (rbound - lbound > qsort_limit)
33         {
34             ti.swap(lbound,
35                 lbound + (
36                           ((rbound - lbound) >>> 1) -
37                           (((rbound - lbound) >>> 1) % elem_size)
38                           ));
39 
40             li = lbound + elem_size;
41             ri = rbound - elem_size;
42 
43             if (ti.compare(li, ri) > 0)
44                 ti.swap(li, ri);
45             if (ti.compare(lbound, ri) > 0)
46                 ti.swap(lbound, ri);
47             if (ti.compare(li, lbound) > 0)
48                 ti.swap(li, lbound);
49 
50             while (1)
51             {
52                 do
53                     li += elem_size;
54                 while (ti.compare(li, lbound) < 0);
55                 do
56                     ri -= elem_size;
57                 while (ti.compare(ri, lbound) > 0);
58                 if (li > ri)
59                     break;
60                 ti.swap(li, ri);
61             }
62             ti.swap(lbound, ri);
63             if (ri - lbound > rbound - li)
64             {
65                 sp.l = lbound;
66                 sp.r = ri;
67                 lbound = li;
68             }
69             else
70             {
71                 sp.l = li;
72                 sp.r = rbound;
73                 rbound = ri;
74             }
75             ++sp;
76         } else {
77             // Use insertion sort
78             for (ri = lbound, li = lbound + elem_size;
79                  li < rbound;
80                  ri = li, li += elem_size)
81             {
82                 for ( ; ti.compare(ri, ri + elem_size) > 0;
83                       ri -= elem_size)
84                 {
85                     ti.swap(ri, ri + elem_size);
86                     if (ri == lbound)
87                         break;
88                 }
89             }
90             if (sp != stack.ptr)
91             {
92                 --sp;
93                 lbound = sp.l;
94                 rbound = sp.r;
95             }
96             else
97                 return a;
98         }
99     }
100 }
101 
102 unittest
103 {
104     static void check(int[] a) {
105         for (uint i = 1; i < a.length; i++)
106             assert(a[i-1] <= a[i]);
107     }
108 
109     static int[] t1 = [ 4, 3, 19, 7, 6, 20, 11, 1, 2, 5 ];
110     int[] a;
111 
112     a = t1;
113     a.sort;
114     check(a);
115 }