1
- /* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
2
-
3
- This library is free software; you can redistribute it and/or
4
- modify it under the terms of the GNU Library General Public
5
- License as published by the Free Software Foundation; either
6
- version 2 of the License, or (at your option) any later version.
7
-
8
- This library is distributed in the hope that it will be useful,
1
+ /* Copyright (C) 1991, 1992, 1996, 1997 Free Software Foundation, Inc.
2
+ This file is part of the GNU C Library.
3
+ Written by Douglas C. Schmidt (schmidt@ics.uci.edu).
4
+
5
+ The GNU C Library is free software; you can redistribute it and/or
6
+ modify it under the terms of the GNU Library General Public License as
7
+ published by the Free Software Foundation; either version 2 of the
8
+ License, or (at your option) any later version.
9
+
10
+ The GNU C Library is distributed in the hope that it will be useful,
9
11
but WITHOUT ANY WARRANTY; without even the implied warranty of
10
12
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11
13
Library General Public License for more details.
12
-
13
- You should have received a copy of the GNU Library General Public
14
- License along with this library; if not, write to the Free
15
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
16
- MA 02111-1307, USA */
17
-
18
- /* Plug-compatible replacement for UNIX qsort.
19
- Copyright (C) 1989 Free Software Foundation, Inc.
20
- Written by Douglas C. Schmidt (schmidt@ics.uci.edu)
21
- Optimized and modyfied for mysys by monty.
22
14
23
- This file is part of GNU CC.
24
-
25
- GNU QSORT is free software; you can redistribute it and/or modify
26
- it under the terms of the GNU General Public License as published by
27
- the Free Software Foundation; either version 1, or (at your option)
28
- any later version.
29
-
30
- GNU QSORT is distributed in the hope that it will be useful,
31
- but WITHOUT ANY WARRANTY; without even the implied warranty of
32
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
33
- GNU General Public License for more details.
15
+ You should have received a copy of the GNU Library General Public
16
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
17
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18
+ Boston, MA 02111-1307, USA. */
34
19
35
- You should have received a copy of the GNU General Public License
36
- along with GNU QSORT; see the file COPYING. If not, write to
37
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
20
+ /*
21
+ Modifications by monty:
22
+ - Uses mysys include files
23
+ - Small fixes to make the it a bit faster
24
+ - Can be compiled with a cmp function that takes one extra argument.
25
+ */
38
26
39
27
#include "mysys_priv.h"
40
28
@@ -46,32 +34,36 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
46
34
#endif
47
35
48
36
/* Byte-wise swap two items of size SIZE. */
49
- #define SWAP (A ,B ,SIZE ) do {int sz=(int)(SIZE); char *a = (A); char *b = (B); \
50
- do { char _temp = *a;*a++ = *b;*b++ = _temp;} while (--sz);} while (0)
37
+ #define SWAP (a , b , size ) \
38
+ do \
39
+ { \
40
+ register size_t __size = (size); \
41
+ register char *__a = (a), *__b = (b); \
42
+ do \
43
+ { \
44
+ char __tmp = *__a; \
45
+ *__a++ = *__b; \
46
+ *__b++ = __tmp; \
47
+ } while (--__size > 0); \
48
+ } while (0)
51
49
52
- /* Copy SIZE bytes from item B to item A. */
53
- #define COPY (A ,B ,SIZE ) {int sz = (int) (SIZE); do { *(A)++ = *(B)++; } while (--sz); }
50
+ /* Discontinue quicksort algorithm when partition gets below this size.
51
+ This particular magic number was chosen to work best on a Sun 4/260. */
52
+ #define MAX_THRESH 8
54
53
55
- /* This should be replaced by a standard ANSI macro. */
56
- #define BYTES_PER_WORD 8
54
+ /* Stack node declarations used to store unfulfilled partition obligations. */
55
+ typedef struct
56
+ {
57
+ char * lo ;
58
+ char * hi ;
59
+ } stack_node ;
57
60
58
61
/* The next 4 #defines implement a very fast in-line stack abstraction. */
59
- #define STACK_SIZE (BYTES_PER_WORD * sizeof ( long))
62
+ #define STACK_SIZE (8 * sizeof(unsigned long int ))
60
63
#define PUSH (LOW ,HIGH ) do {top->lo = LOW;top++->hi = HIGH;} while (0)
61
64
#define POP (LOW ,HIGH ) do {LOW = (--top)->lo;HIGH = top->hi;} while (0)
62
65
#define STACK_NOT_EMPTY (stack < top)
63
66
64
- /* Discontinue quicksort algorithm when partition gets below this size.
65
- This particular magic number was chosen to work best on a Sparc SLC. */
66
- #define MAX_THRESH 12
67
-
68
- /* Stack node declarations used to store unfulfilled partition obligations. */
69
- typedef struct
70
- {
71
- char * lo ;
72
- char * hi ;
73
- } stack_node ;
74
-
75
67
/* Order size using quicksort. This implementation incorporates
76
68
four optimizations discussed in Sedgewick:
77
69
@@ -88,7 +80,7 @@ typedef struct
88
80
3. Only quicksorts TOTAL_ELEMS / MAX_THRESH partitions, leaving
89
81
insertion sort to order the MAX_THRESH items within each partition.
90
82
This is a big win, since insertion sort is faster for small, mostly
91
- sorted array segements .
83
+ sorted array segments .
92
84
93
85
4. The larger of the two sub-partitions is always pushed onto the
94
86
stack first, with the algorithm then concentrating on the
@@ -111,100 +103,98 @@ qsort_t qsort(void *base_ptr, size_t total_elems, size_t size, qsort_cmp cmp)
111
103
/* Allocating SIZE bytes for a pivot buffer facilitates a better
112
104
algorithm below since we can do comparisons directly on the pivot.
113
105
*/
114
- int max_thresh = (int ) (MAX_THRESH * size );
106
+ size_t max_thresh = (size_t ) (MAX_THRESH * size );
115
107
if (total_elems <= 1 )
116
108
SORT_RETURN ; /* Crashes on MSDOS if continues */
117
109
118
110
if (total_elems > MAX_THRESH )
119
111
{
120
112
char * lo = base_ptr ;
121
- char * hi = lo + size * (total_elems - 1 );
113
+ char * hi = & lo [ size * (total_elems - 1 )] ;
122
114
stack_node stack [STACK_SIZE ]; /* Largest size needed for 32-bit int!!! */
123
115
stack_node * top = stack + 1 ;
124
- char * pivot_buffer = (char * ) my_alloca ((int ) size );
116
+ char * pivot = (char * ) my_alloca ((int ) size );
125
117
#ifdef HAVE_purify
126
118
stack [0 ].lo = stack [0 ].hi = 0 ;
127
119
#endif
128
120
129
- while ( STACK_NOT_EMPTY )
121
+ do
130
122
{
131
- char * left_ptr ;
132
- char * right_ptr ;
123
+ char * left_ptr ,* right_ptr ;
124
+
125
+ /* Select median value from among LO, MID, and HI. Rearrange
126
+ LO and HI so the three values are sorted. This lowers the
127
+ probability of picking a pathological pivot value and
128
+ skips a comparison for both the LEFT_PTR and RIGHT_PTR. */
129
+
130
+ char * mid = lo + size * (((ulong ) (hi - lo ) / (ulong ) size ) >> 1 );
131
+
132
+ if (CMP (hi ,lo ) < 0 )
133
+ SWAP (hi , lo , size );
134
+ if (CMP (mid , lo ) < 0 )
135
+ SWAP (mid , lo , size );
136
+ else if (CMP (hi , mid ) < 0 )
137
+ SWAP (mid , hi , size );
138
+ memcpy (pivot , mid , size );
139
+
140
+ left_ptr = lo + size ;
141
+ right_ptr = hi - size ;
142
+
143
+ /* Here's the famous ``collapse the walls'' section of quicksort.
144
+ Gotta like those tight inner loops! They are the main reason
145
+ that this algorithm runs much faster than others. */
146
+ do
133
147
{
134
- char * pivot = pivot_buffer ;
148
+ while (CMP (left_ptr , pivot ) < 0 )
149
+ left_ptr += size ;
150
+
151
+ while (CMP (pivot , right_ptr ) < 0 )
152
+ right_ptr -= size ;
153
+
154
+ if (left_ptr < right_ptr )
135
155
{
136
- /* Select median value from among LO, MID, and HI. Rearrange
137
- LO and HI so the three values are sorted. This lowers the
138
- probability of picking a pathological pivot value and
139
- skips a comparison for both the LEFT_PTR and RIGHT_PTR. */
140
-
141
- char * mid = lo + size * (((uint ) (hi - lo ) / (uint ) size ) >> 1 );
142
-
143
- if (CMP (hi ,lo ) < 0 )
144
- SWAP (hi , lo , size );
145
- if (CMP (mid , lo ) < 0 )
146
- SWAP (mid , lo , size );
147
- else if (CMP (hi , mid ) < 0 )
148
- SWAP (mid , hi , size );
149
- COPY (pivot , mid , size );
150
- pivot = pivot_buffer ;
156
+ SWAP (left_ptr , right_ptr , size );
157
+ left_ptr += size ;
158
+ right_ptr -= size ;
151
159
}
152
- left_ptr = lo + size ;
153
- right_ptr = hi - size ;
154
-
155
- /* Here's the famous ``collapse the walls'' section of quicksort.
156
- Gotta like those tight inner loops! They are the main reason
157
- that this algorithm runs much faster than others. */
158
- do
160
+ else if (left_ptr == right_ptr )
159
161
{
160
- while (CMP (left_ptr , pivot ) < 0 )
161
- left_ptr += size ;
162
-
163
- while (CMP (pivot , right_ptr ) < 0 )
164
- right_ptr -= size ;
165
-
166
- if (left_ptr < right_ptr )
167
- {
168
- SWAP (left_ptr , right_ptr , size );
169
- left_ptr += size ;
170
- right_ptr -= size ;
171
- }
172
- else if (left_ptr == right_ptr )
173
- {
174
- left_ptr += size ;
175
- right_ptr -= size ;
176
- break ;
177
- }
162
+ left_ptr += size ;
163
+ right_ptr -= size ;
164
+ break ;
178
165
}
179
- while (left_ptr <= right_ptr );
166
+ else
167
+ break ; /* left_ptr > right_ptr */
180
168
}
169
+ while (left_ptr <= right_ptr );
170
+
181
171
182
172
/* Set up pointers for next iteration. First determine whether
183
173
left and right partitions are below the threshold size. If so,
184
174
ignore one or both. Otherwise, push the larger partition's
185
175
bounds on the stack and continue sorting the smaller one. */
186
176
187
- if ((right_ptr - lo ) <= max_thresh )
177
+ if ((size_t ) ( right_ptr - lo ) <= max_thresh )
188
178
{
189
- if ((hi - left_ptr ) <= max_thresh ) /* Ignore both small parts. */
190
- POP (lo , hi );
191
- else /* Ignore small left part. */
192
- lo = left_ptr ;
179
+ if ((size_t ) ( hi - left_ptr ) <= max_thresh )
180
+ POP (lo , hi ); /* Ignore both small partitions. */
181
+ else
182
+ lo = left_ptr ; /* Ignore small left part. */
193
183
}
194
- else if ((hi - left_ptr ) <= max_thresh ) /* Ignore small right part. */
195
- hi = right_ptr ;
196
- else if ((right_ptr - lo ) > (hi - left_ptr )) /* Push larger left part */
184
+ else if ((size_t ) ( hi - left_ptr ) <= max_thresh )
185
+ hi = right_ptr ; /* Ignore small right partition. */
186
+ else if ((right_ptr - lo ) > (hi - left_ptr ))
197
187
{
198
- PUSH (lo , right_ptr );
188
+ PUSH (lo , right_ptr ); /* Push larger left part */
199
189
lo = left_ptr ;
200
190
}
201
- else /* Push larger right part */
191
+ else
202
192
{
203
- PUSH (left_ptr , hi );
193
+ PUSH (left_ptr , hi ); /* Push larger right part */
204
194
hi = right_ptr ;
205
195
}
206
- }
207
- my_afree (pivot_buffer );
196
+ } while ( STACK_NOT_EMPTY );
197
+ my_afree (pivot );
208
198
}
209
199
210
200
/* Once the BASE_PTR array is partially sorted by quicksort the rest
@@ -215,9 +205,9 @@ qsort_t qsort(void *base_ptr, size_t total_elems, size_t size, qsort_cmp cmp)
215
205
216
206
{
217
207
char * end_ptr = (char * ) base_ptr + size * (total_elems - 1 );
218
- char * run_ptr ;
219
208
char * tmp_ptr = (char * ) base_ptr ;
220
209
char * thresh = min (end_ptr , (char * ) base_ptr + max_thresh );
210
+ register char * run_ptr ;
221
211
222
212
/* Find smallest element in first threshold and place it at the
223
213
array's beginning. This is the smallest array element,
@@ -230,18 +220,18 @@ qsort_t qsort(void *base_ptr, size_t total_elems, size_t size, qsort_cmp cmp)
230
220
if (tmp_ptr != (char * ) base_ptr )
231
221
SWAP (tmp_ptr , (char * ) base_ptr , size );
232
222
233
- /* Insertion sort, running from left-hand-side up to `right-hand-side.'
234
- Pretty much straight out of the original GNU qsort routine. */
223
+ /* Insertion sort, running from left-hand-side up to right-hand-side. */
235
224
236
225
for (run_ptr = (char * ) base_ptr + size ;
237
- (tmp_ptr = run_ptr += size ) <= end_ptr ; )
226
+ (run_ptr += size ) <= end_ptr ; )
238
227
{
239
- while (CMP (run_ptr , tmp_ptr -= size ) < 0 ) ;
240
-
241
- if ((tmp_ptr += size ) != run_ptr )
228
+ if (CMP (run_ptr , (tmp_ptr = run_ptr - size )) < 0 )
242
229
{
243
230
char * trav ;
231
+ while (CMP (run_ptr , tmp_ptr -= size ) < 0 ) ;
232
+ tmp_ptr += size ;
244
233
234
+ /* Shift down all smaller elements, put found element in 'run_ptr' */
245
235
for (trav = run_ptr + size ; -- trav >= run_ptr ;)
246
236
{
247
237
char c = * trav ;
@@ -252,7 +242,6 @@ qsort_t qsort(void *base_ptr, size_t total_elems, size_t size, qsort_cmp cmp)
252
242
* hi = c ;
253
243
}
254
244
}
255
-
256
245
}
257
246
}
258
247
SORT_RETURN ;
0 commit comments