1 /* $Id: qsort.c,v 1.2 2003/07/11 01:23:15 royce Exp $
3 * FILE: ntoskrnl/rtl/qsort.c
4 * NOTE: Adapted from CygWin newlib 2000-03-12.
8 <<qsort>>---sort an array
15 void qsort(void *<[base]>, size_t <[nmemb]>, size_t <[size]>,
16 int (*<[compar]>)(const void *, const void *) );
20 qsort(<[base]>, <[nmemb]>, <[size]>, <[compar]> )
27 <<qsort>> sorts an array (beginning at <[base]>) of <[nmemb]> objects.
28 <[size]> describes the size of each element of the array.
30 You must supply a pointer to a comparison function, using the argument
31 shown as <[compar]>. (This permits sorting objects of unknown
32 properties.) Define the comparison function to accept two arguments,
33 each a pointer to an element of the array starting at <[base]>. The
34 result of <<(*<[compar]>)>> must be negative if the first argument is
35 less than the second, zero if the two arguments match, and positive if
36 the first argument is greater than the second (where ``less than'' and
37 ``greater than'' refer to whatever arbitrary ordering is appropriate).
39 The array is sorted in place; that is, when <<qsort>> returns, the
40 array elements beginning at <[base]> have been reordered.
43 <<qsort>> does not return a result.
46 <<qsort>> is required by ANSI (without specifying the sorting algorithm).
50 * Copyright (c) 1992, 1993
51 * The Regents of the University of California. All rights reserved.
53 * Redistribution and use in source and binary forms, with or without
54 * modification, are permitted provided that the following conditions
56 * 1. Redistributions of source code must retain the above copyright
57 * notice, this list of conditions and the following disclaimer.
58 * 2. Redistributions in binary form must reproduce the above copyright
59 * notice, this list of conditions and the following disclaimer in the
60 * documentation and/or other materials provided with the distribution.
61 * 3. All advertising materials mentioning features or use of this software
62 * must display the following acknowledgement:
63 * This product includes software developed by the University of
64 * California, Berkeley and its contributors.
65 * 4. Neither the name of the University nor the names of its contributors
66 * may be used to endorse or promote products derived from this software
67 * without specific prior written permission.
69 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
70 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
71 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
72 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
73 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
74 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
75 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
76 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
77 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
78 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
86 /* FIXME: these types should be from the default includes */
88 typedef int (* _pfunccmp_t
) (char *, char *);
91 #define min(a,b) ((a)<(b)?(a):(b))
94 * Qsort routine from Bentley & McIlroy's "Engineering a Sort Function".
96 #define swapcode(TYPE, parmi, parmj, n) { \
97 long i = (n) / sizeof (TYPE); \
98 register TYPE *pi = (TYPE *) (parmi); \
99 register TYPE *pj = (TYPE *) (parmj); \
101 register TYPE t = *pi; \
107 #define SWAPINIT(a, es) swaptype = ((char *)a - (char *)0) % sizeof(long) || \
108 es % sizeof(long) ? 2 : es == sizeof(long)? 0 : 1;
119 swapcode(long, a
, b
, n
)
121 swapcode(char, a
, b
, n
)
125 if (swaptype == 0) { \
126 long t = *(long *)(a); \
127 *(long *)(a) = *(long *)(b); \
130 swapfunc(a, b, es, swaptype)
132 #define vecswap(a, b, n) if ((n) > 0) swapfunc(a, b, n, swaptype)
142 return cmp(a
, b
) < 0 ?
143 (cmp(b
, c
) < 0 ? b
: (cmp(a
, c
) < 0 ? c
: a
))
144 :(cmp(b
, c
) > 0 ? b
: (cmp(a
, c
) < 0 ? a
: c
));
160 char *pa
, *pb
, *pc
, *pd
, *pl
, *pm
, *pn
;
161 int d
, r
, swaptype
, swap_cnt
;
163 loop
: SWAPINIT(a
, es
);
167 for ( pm
= (char *) a
+ es
;
168 pm
< (char *) a
+ n
* es
;
173 pl
> (char *) a
&& cmp(pl
- es
, pl
) > 0;
182 pm
= (char *) a
+ (n
/ 2) * es
;
186 pn
= (char *) a
+ (n
- 1) * es
;
190 pl
= med3(pl
, pl
+ d
, pl
+ 2 * d
, cmp
);
191 pm
= med3(pm
- d
, pm
, pm
+ d
, cmp
);
192 pn
= med3(pn
- 2 * d
, pn
- d
, pn
, cmp
);
194 pm
= med3(pl
, pm
, pn
, cmp
);
197 pa
= pb
= (char *) a
+ es
;
199 pc
= pd
= (char *) a
+ (n
- 1) * es
;
202 while (pb
<= pc
&& (r
= cmp(pb
, a
)) <= 0)
212 while (pb
<= pc
&& (r
= cmp(pc
, a
)) >= 0)
231 if (swap_cnt
== 0) /* Switch to insertion sort */
233 for ( pm
= (char *) a
+ es
;
234 pm
< (char *) a
+ n
* es
;
239 pl
> (char *) a
&& cmp(pl
- es
, pl
) > 0;
249 pn
= (char *) a
+ n
* es
;
250 r
= min(pa
- (char *)a
, pb
- pa
);
251 vecswap(a
, pb
- r
, r
);
252 r
= min(pd
- pc
, pn
- pd
- es
);
253 vecswap(pb
, pn
- r
, r
);
254 if ((r
= pb
- pa
) > es
)
256 qsort(a
, r
/ es
, es
, cmp
);
258 if ((r
= pd
- pc
) > es
)
260 /* Iterate rather than recurse to save stack space */
265 /* qsort(pn - r, r / es, es, cmp);*/