Download Reference Manual
The Developer's Library for D
About Wiki Forums Source Search Contact

root/trunk/lib/compiler/dmd/qsort.d

Revision 1856, 4.9 kB (checked in by sean, 2 years ago)

Merged in final GDC 0.23 changes. These changes have also been applied to the DMD runtime where applicable. As most of these changes were replacing instances of int/uint with ptrdiff_t/size_t, there should be no noticeable difference in DMD behavior from these changes.

Please note that some changes were necessary to the GC as well, and I am trusting that Dave Friedman got things right. Again, most of these were changes from uint to size_t, but things here seem a bit less clear-cut than most of the changes to the GDC runtime itself.

Finally, it is worth being aware that of the GC code, only gcx.d is really pretty much the same between Tango and Phobos/GPhobos. The remaining files are split among the GC directory (gc/basic), and the files lifetime.d and memory.d in the compiler runtime code. The Tango design is far cleaner, but the structural differences complicate merging changes in this area. I've triple-checked all changes for this merge, but if there are any functional problems, I expect them to concern these GC-related files.

  • Property svn:mime-type set to text/x-dsrc
  • Property svn:eol-style set to native
Line 
1 /*
2         Portions of this file are:
3         Copyright Prototronics, 1987
4         Totem Lake P.O. 8117
5         Kirkland, Washington 98034
6         (206) 820-1972
7         Licensed to Digital Mars.
8
9         June 11, 1987 from Ray Gardner's
10         Denver, Colorado) public domain version
11
12         Use qsort2.d instead of this file if a redistributable version of
13         _adSort() is required.
14 */
15
16
17 /*
18 **    Sorts an array starting at base, of length nbr_elements, each
19 **    element of size width_bytes, ordered via compare_function; which
20 **    is called as  (*comp_fp)(ptr_to_element1, ptr_to_element2)
21 **    and returns < 0 if element1 < element2, 0 if element1 = element2,
22 **    > 0 if element1 > element2.  Most of the refinements are due to
23 **    R. Sedgewick.  See "Implementing Quicksort Programs", Comm. ACM,
24 **    Oct. 1978, and Corrigendum, Comm. ACM, June 1979.
25 */
26
27 //debug=qsort;          // uncomment to turn on debugging printf's
28
29
30 struct Array
31 {
32     size_t length;
33     void*  ptr;
34 }
35
36
37 private const int _maxspan = 7; // subarrays of _maxspan or fewer elements
38                                 // will be sorted by a simple insertion sort
39
40 /* Adjust _maxspan according to relative cost of a swap and a compare.  Reduce
41 _maxspan (not less than 1) if a swap is very expensive such as when you have
42 an array of large structures to be sorted, rather than an array of pointers to
43 structures.  The default value is optimized for a high cost for compares. */
44
45
46 extern (C) long _adSort(Array a, TypeInfo ti)
47 {
48   byte* base;
49   byte*[40] stack;              // stack
50   byte** sp;                    // stack pointer
51   byte* i, j, limit;            // scan and limit pointers
52   uint thresh;                  // size of _maxspan elements in bytes
53   uint width = ti.tsize();
54
55   base = cast(byte *)a.ptr;
56   thresh = _maxspan * width;             // init threshold
57   sp = stack.ptr;                        // init stack pointer
58   limit = base + a.length * width;       // pointer past end of array
59   while (1)                              // repeat until done then return
60   {
61     while (limit - base > thresh)        // if more than _maxspan elements
62     {
63       //swap middle, base
64       ti.swap((cast(uint)(limit - base) >> 1) -
65            (((cast(uint)(limit - base) >> 1)) % width) + base, base);
66
67       i = base + width;                 // i scans from left to right
68       j = limit - width;                // j scans from right to left
69
70       if (ti.compare(i, j) > 0)         // Sedgewick's
71         ti.swap(i, j);                  //    three-element sort
72       if (ti.compare(base, j) > 0)      // sets things up
73         ti.swap(base, j);               // so that
74       if (ti.compare(i, base) > 0)      // *i <= *base <= *j
75         ti.swap(i, base);               // *base is the pivot element
76
77       while (1)
78       {
79         do                              // move i right until *i >= pivot
80           i += width;
81         while (ti.compare(i, base) < 0);
82         do                              // move j left until *j <= pivot
83           j -= width;
84         while (ti.compare(j, base) > 0);
85         if (i > j)                      // break loop if pointers crossed
86           break;
87         ti.swap(i, j);                  // else swap elements, keep scanning
88       }
89       ti.swap(base, j);                 // move pivot into correct place
90       if (j - base > limit - i)         // if left subarray is larger...
91       {
92         sp[0] = base;                   // stack left subarray base
93         sp[1] = j;                      //    and limit
94         base = i;                       // sort the right subarray
95       }
96       else                              // else right subarray is larger
97       {
98         sp[0] = i;                      // stack right subarray base
99         sp[1] = limit;                  //    and limit
100         limit = j;                      // sort the left subarray
101       }
102       sp += 2;                          // increment stack pointer
103       assert(sp < cast(byte**)stack + stack.length);
104     }
105
106     // Insertion sort on remaining subarray
107     i = base + width;
108     while (i < limit)
109     {
110       j = i;
111       while (j > base && ti.compare(j - width, j) > 0)
112       {
113         ti.swap(j - width, j);
114         j -= width;
115       }
116       i += width;
117     }
118
119     if (sp > stack.ptr)                 // if any entries on stack...
120     {
121       sp -= 2;                          // pop the base and limit
122       base = sp[0];
123       limit = sp[1];
124     }
125     else                                // else stack empty, all done
126       return *cast(long*)(&a);
127   }
128   assert(0);
129 }
130
131
132 unittest
133 {
134     debug(qsort) printf("array.sort.unittest()\n");
135
136     int a[] = new int[10];
137
138     a[0] = 23;
139     a[1] = 1;
140     a[2] = 64;
141     a[3] = 5;
142     a[4] = 6;
143     a[5] = 5;
144     a[6] = 17;
145     a[7] = 3;
146     a[8] = 0;
147     a[9] = -1;
148
149     a.sort;
150
151     for (int i = 0; i < a.length - 1; i++)
152     {
153         //printf("i = %d", i);
154         //printf(" %d %d\n", a[i], a[i + 1]);
155         assert(a[i] <= a[i + 1]);
156     }
157 }
Note: See TracBrowser for help on using the browser.