Rev 9013 | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 9013 | Rev 9765 | ||
---|---|---|---|
Line 50... | Line 50... | ||
50 | * and cleaning up with an insertion sort (in our caller) is a huge win. |
50 | * and cleaning up with an insertion sort (in our caller) is a huge win. |
51 | * All data swaps are done in-line, which is space-losing but time-saving. |
51 | * All data swaps are done in-line, which is space-losing but time-saving. |
52 | * (And there are only three places where this is done). |
52 | * (And there are only three places where this is done). |
53 | */ |
53 | */ |
Line 54... | Line -... | ||
54 | - | ||
55 | static void |
54 | |
56 | qst(char *base, char *max) |
55 | static void qst(char* base, char* max) |
57 | { |
56 | { |
58 | char c, *i, *j, *jj; |
57 | char c, *i, *j, *jj; |
59 | int ii; |
58 | int ii; |
60 | char *mid, *tmp; |
59 | char *mid, *tmp; |
Line 70... | Line 69... | ||
70 | * prefer the middle, then the first in case of ties. |
69 | * prefer the middle, then the first in case of ties. |
71 | */ |
70 | */ |
72 | lo = max - base; /* number of elements as chars */ |
71 | lo = max - base; /* number of elements as chars */ |
73 | do { |
72 | do { |
74 | mid = i = base + qsz * ((lo / qsz) >> 1); |
73 | mid = i = base + qsz * ((lo / qsz) >> 1); |
75 | if (lo >= mthresh) |
74 | if (lo >= mthresh) { |
76 | { |
- | |
77 | j = (qcmp((jj = base), i) > 0 ? jj : i); |
75 | j = (qcmp((jj = base), i) > 0 ? jj : i); |
78 | if (qcmp(j, (tmp = max - qsz)) > 0) |
76 | if (qcmp(j, (tmp = max - qsz)) > 0) { |
79 | { |
- | |
80 | /* switch to first loser */ |
77 | /* switch to first loser */ |
81 | j = (j == jj ? i : jj); |
78 | j = (j == jj ? i : jj); |
82 | if (qcmp(j, tmp) < 0) |
79 | if (qcmp(j, tmp) < 0) |
83 | j = tmp; |
80 | j = tmp; |
84 | } |
81 | } |
85 | if (j != i) |
82 | if (j != i) { |
86 | { |
- | |
87 | ii = qsz; |
83 | ii = qsz; |
88 | do { |
84 | do { |
89 | c = *i; |
85 | c = *i; |
90 | *i++ = *j; |
86 | *i++ = *j; |
91 | *j++ = c; |
87 | *j++ = c; |
Line 93... | Line 89... | ||
93 | } |
89 | } |
94 | } |
90 | } |
95 | /* |
91 | /* |
96 | * Semi-standard quicksort partitioning/swapping |
92 | * Semi-standard quicksort partitioning/swapping |
97 | */ |
93 | */ |
98 | for (i = base, j = max - qsz; ; ) |
94 | for (i = base, j = max - qsz;;) { |
99 | { |
- | |
100 | while (i < mid && qcmp(i, mid) <= 0) |
95 | while (i < mid && qcmp(i, mid) <= 0) |
101 | i += qsz; |
96 | i += qsz; |
102 | while (j > mid) |
97 | while (j > mid) { |
103 | { |
- | |
104 | if (qcmp(mid, j) <= 0) |
98 | if (qcmp(mid, j) <= 0) { |
105 | { |
- | |
106 | j -= qsz; |
99 | j -= qsz; |
107 | continue; |
100 | continue; |
108 | } |
101 | } |
109 | tmp = i + qsz; /* value of i after swap */ |
102 | tmp = i + qsz; /* value of i after swap */ |
110 | if (i == mid) |
103 | if (i == mid) { |
111 | { |
- | |
112 | /* j <-> mid, new mid is j */ |
104 | /* j <-> mid, new mid is j */ |
113 | mid = jj = j; |
105 | mid = jj = j; |
114 | } |
- | |
115 | else |
106 | } else { |
116 | { |
- | |
117 | /* i <-> j */ |
107 | /* i <-> j */ |
118 | jj = j; |
108 | jj = j; |
119 | j -= qsz; |
109 | j -= qsz; |
120 | } |
110 | } |
121 | goto swap; |
111 | goto swap; |
122 | } |
112 | } |
123 | if (i == mid) |
113 | if (i == mid) { |
124 | { |
- | |
125 | break; |
114 | break; |
126 | } |
- | |
127 | else |
115 | } else { |
128 | { |
- | |
129 | /* i <-> mid, new mid is i */ |
116 | /* i <-> mid, new mid is i */ |
130 | jj = mid; |
117 | jj = mid; |
131 | tmp = mid = i; /* value of i after swap */ |
118 | tmp = mid = i; /* value of i after swap */ |
132 | j -= qsz; |
119 | j -= qsz; |
133 | } |
120 | } |
Line 147... | Line 134... | ||
147 | * correctly, and branching back. But only repeat |
134 | * correctly, and branching back. But only repeat |
148 | * (recursively or by branching) if the partition is |
135 | * (recursively or by branching) if the partition is |
149 | * of at least size THRESH. |
136 | * of at least size THRESH. |
150 | */ |
137 | */ |
151 | i = (j = mid) + qsz; |
138 | i = (j = mid) + qsz; |
152 | if ((lo = j - base) <= (hi = max - i)) |
139 | if ((lo = j - base) <= (hi = max - i)) { |
153 | { |
- | |
154 | if (lo >= thresh) |
140 | if (lo >= thresh) |
155 | qst(base, j); |
141 | qst(base, j); |
156 | base = i; |
142 | base = i; |
157 | lo = hi; |
143 | lo = hi; |
158 | } |
- | |
159 | else |
144 | } else { |
160 | { |
- | |
161 | if (hi >= thresh) |
145 | if (hi >= thresh) |
162 | qst(i, max); |
146 | qst(i, max); |
163 | max = j; |
147 | max = j; |
164 | } |
148 | } |
165 | } while (lo >= thresh); |
149 | } while (lo >= thresh); |
Line 170... | Line 154... | ||
170 | * First, set up some global parameters for qst to share. Then, quicksort |
154 | * First, set up some global parameters for qst to share. Then, quicksort |
171 | * with qst(), and then a cleanup insertion sort ourselves. Sound simple? |
155 | * with qst(), and then a cleanup insertion sort ourselves. Sound simple? |
172 | * It's not... |
156 | * It's not... |
173 | */ |
157 | */ |
Line 174... | Line -... | ||
174 | - | ||
175 | void |
158 | |
176 | qsort(void *base0, size_t n, size_t size, int (*compar)(const void *, const void *)) |
159 | void qsort(void* base0, size_t n, size_t size, int (*compar)(const void*, const void*)) |
177 | { |
160 | { |
178 | char *base = (char *)base0; |
161 | char* base = (char*)base0; |
179 | char c, *i, *j, *lo, *hi; |
162 | char c, *i, *j, *lo, *hi; |
Line 184... | Line 167... | ||
184 | qsz = size; |
167 | qsz = size; |
185 | qcmp = compar; |
168 | qcmp = compar; |
186 | thresh = qsz * THRESH; |
169 | thresh = qsz * THRESH; |
187 | mthresh = qsz * MTHRESH; |
170 | mthresh = qsz * MTHRESH; |
188 | max = base + n * qsz; |
171 | max = base + n * qsz; |
189 | if (n >= THRESH) |
172 | if (n >= THRESH) { |
190 | { |
- | |
191 | qst(base, max); |
173 | qst(base, max); |
192 | hi = base + thresh; |
174 | hi = base + thresh; |
193 | } |
- | |
194 | else |
175 | } else { |
195 | { |
- | |
196 | hi = max; |
176 | hi = max; |
197 | } |
177 | } |
198 | /* |
178 | /* |
199 | * First put smallest element, which must be in the first THRESH, in |
179 | * First put smallest element, which must be in the first THRESH, in |
200 | * the first position as a sentinel. This is done just by searching |
180 | * the first position as a sentinel. This is done just by searching |
Line 202... | Line 182... | ||
202 | * the min, and swapping it into the first position. |
182 | * the min, and swapping it into the first position. |
203 | */ |
183 | */ |
204 | for (j = lo = base; (lo += qsz) < hi; ) |
184 | for (j = lo = base; (lo += qsz) < hi;) |
205 | if (qcmp(j, lo) > 0) |
185 | if (qcmp(j, lo) > 0) |
206 | j = lo; |
186 | j = lo; |
207 | if (j != base) |
187 | if (j != base) { |
208 | { |
- | |
209 | /* swap j into place */ |
188 | /* swap j into place */ |
210 | for (i = base, hi = base + qsz; i < hi; ) |
189 | for (i = base, hi = base + qsz; i < hi;) { |
211 | { |
- | |
212 | c = *j; |
190 | c = *j; |
213 | *j++ = *i; |
191 | *j++ = *i; |
214 | *i++ = c; |
192 | *i++ = c; |
215 | } |
193 | } |
216 | } |
194 | } |
Line 219... | Line 197... | ||
219 | * insertion sort. For each remaining element, min, from [1] to [n-1], |
197 | * insertion sort. For each remaining element, min, from [1] to [n-1], |
220 | * set hi to the index of the element AFTER which this one goes. |
198 | * set hi to the index of the element AFTER which this one goes. |
221 | * Then, do the standard insertion sort shift on a character at a time |
199 | * Then, do the standard insertion sort shift on a character at a time |
222 | * basis for each element in the frob. |
200 | * basis for each element in the frob. |
223 | */ |
201 | */ |
224 | for (min = base; (hi = min += qsz) < max; ) |
202 | for (min = base; (hi = min += qsz) < max;) { |
225 | { |
- | |
226 | while (qcmp(hi -= qsz, min) > 0) |
203 | while (qcmp(hi -= qsz, min) > 0) |
227 | /* void */; |
204 | /* void */; |
228 | if ((hi += qsz) != min) { |
205 | if ((hi += qsz) != min) { |
229 | for (lo = min + qsz; --lo >= min; ) |
206 | for (lo = min + qsz; --lo >= min;) { |
230 | { |
- | |
231 | c = *lo; |
207 | c = *lo; |
232 | for (i = j = lo; (j -= qsz) >= hi; i = j) |
208 | for (i = j = lo; (j -= qsz) >= hi; i = j) |
233 | *i = *j; |
209 | *i = *j; |
234 | *i = c; |
210 | *i = c; |
235 | } |
211 | } |