2 Portions of this file are:
3 Copyright Prototronics, 1987
5 Kirkland, Washington 98034
7 Licensed to Digital Mars.
9 June 11, 1987 from Ray Gardner's
10 Denver, Colorado) public domain version
12 Use qsort2.d instead of this file if a redistributable version of
13 _adSort() is required.
19 ** Sorts an array starting at base, of length nbr_elements, each
20 ** element of size width_bytes, ordered via compare_function; which
21 ** is called as (*comp_fp)(ptr_to_element1, ptr_to_element2)
22 ** and returns < 0 if element1 < element2, 0 if element1 = element2,
23 ** > 0 if element1 > element2. Most of the refinements are due to
24 ** R. Sedgewick. See "Implementing Quicksort Programs", Comm. ACM,
25 ** Oct. 1978, and Corrigendum, Comm. ACM, June 1979.
28 //debug=qsort; // uncomment to turn on debugging printf's
38 private const int _maxspan = 7; // subarrays of _maxspan or fewer elements
39 // will be sorted by a simple insertion sort
41 /* Adjust _maxspan according to relative cost of a swap and a compare. Reduce
42 _maxspan (not less than 1) if a swap is very expensive such as when you have
43 an array of large structures to be sorted, rather than an array of pointers to
44 structures. The default value is optimized for a high cost for compares. */
47 extern (C) long _adSort(Array a, TypeInfo ti)
50 byte*[40] stack; // stack
51 byte** sp; // stack pointer
52 byte* i, j, limit; // scan and limit pointers
53 uint thresh; // size of _maxspan elements in bytes
54 uint width = ti.tsize();
56 base = cast(byte *)a.ptr;
57 thresh = _maxspan * width; // init threshold
58 sp = stack.ptr; // init stack pointer
59 limit = base + a.length * width; // pointer past end of array
60 while (1) // repeat until done then return
62 while (limit - base > thresh) // if more than _maxspan elements
65 ti.swap((cast(uint)(limit - base) >> 1) -
66 (((cast(uint)(limit - base) >> 1)) % width) + base, base);
68 i = base + width; // i scans from left to right
69 j = limit - width; // j scans from right to left
71 if (ti.compare(i, j) > 0) // Sedgewick's
72 ti.swap(i, j); // three-element sort
73 if (ti.compare(base, j) > 0) // sets things up
74 ti.swap(base, j); // so that
75 if (ti.compare(i, base) > 0) // *i <= *base <= *j
76 ti.swap(i, base); // *base is the pivot element
80 do // move i right until *i >= pivot
82 while (ti.compare(i, base) < 0);
83 do // move j left until *j <= pivot
85 while (ti.compare(j, base) > 0);
86 if (i > j) // break loop if pointers crossed
88 ti.swap(i, j); // else swap elements, keep scanning
90 ti.swap(base, j); // move pivot into correct place
91 if (j - base > limit - i) // if left subarray is larger...
93 sp[0] = base; // stack left subarray base
94 sp[1] = j; // and limit
95 base = i; // sort the right subarray
97 else // else right subarray is larger
99 sp[0] = i; // stack right subarray base
100 sp[1] = limit; // and limit
101 limit = j; // sort the left subarray
103 sp += 2; // increment stack pointer
104 assert(sp < cast(byte**)stack + stack.length);
107 // Insertion sort on remaining subarray
112 while (j > base && ti.compare(j - width, j) > 0)
114 ti.swap(j - width, j);
120 if (sp > stack.ptr) // if any entries on stack...
122 sp -= 2; // pop the base and limit
126 else // else stack empty, all done
127 return *cast(long*)(&a);
135 debug(qsort) printf("array.sort.unittest()\n");
137 int a[] = new int[10];
152 for (int i = 0; i < a.length - 1; i++)
154 //printf("i = %d", i);
155 //printf(" %d %d\n", a[i], a[i + 1]);
156 assert(a[i] <= a[i + 1]);