Subversion Repositories freemyipod

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
71 theseven 1
/*
2
FUNCTION
3
<<qsort>>---sort an array
4
 
5
INDEX
6
        qsort
7
 
8
ANSI_SYNOPSIS
9
        #include <stdlib.h>
10
        void qsort(void *<[base]>, size_t <[nmemb]>, size_t <[size]>,
11
                   int (*<[compar]>)(const void *, const void *) );
12
 
13
TRAD_SYNOPSIS
14
        #include <stdlib.h>
15
        qsort(<[base]>, <[nmemb]>, <[size]>, <[compar]> )
16
        char *<[base]>;
17
        size_t <[nmemb]>;
18
        size_t <[size]>;
19
        int (*<[compar]>)();
20
 
21
DESCRIPTION
22
<<qsort>> sorts an array (beginning at <[base]>) of <[nmemb]> objects.
23
<[size]> describes the size of each element of the array.
24
 
25
You must supply a pointer to a comparison function, using the argument
26
shown as <[compar]>.  (This permits sorting objects of unknown
27
properties.)  Define the comparison function to accept two arguments,
28
each a pointer to an element of the array starting at <[base]>.  The
29
result of <<(*<[compar]>)>> must be negative if the first argument is
30
less than the second, zero if the two arguments match, and positive if
31
the first argument is greater than the second (where ``less than'' and
32
``greater than'' refer to whatever arbitrary ordering is appropriate).
33
 
34
The array is sorted in place; that is, when <<qsort>> returns, the
35
array elements beginning at <[base]> have been reordered.
36
 
37
RETURNS
38
<<qsort>> does not return a result.
39
 
40
PORTABILITY
41
<<qsort>> is required by ANSI (without specifying the sorting algorithm).
42
*/
43
 
44
/*-
45
 * Copyright (c) 1992, 1993
46
 *      The Regents of the University of California.  All rights reserved.
47
 *
48
 * Redistribution and use in source and binary forms, with or without
49
 * modification, are permitted provided that the following conditions
50
 * are met:
51
 * 1. Redistributions of source code must retain the above copyright
52
 *    notice, this list of conditions and the following disclaimer.
53
 * 2. Redistributions in binary form must reproduce the above copyright
54
 *    notice, this list of conditions and the following disclaimer in the
55
 *    documentation and/or other materials provided with the distribution.
56
 * 3. All advertising materials mentioning features or use of this software
57
 *    must display the following acknowledgement:
58
 *      This product includes software developed by the University of
59
 *      California, Berkeley and its contributors.
60
 * 4. Neither the name of the University nor the names of its contributors
61
 *    may be used to endorse or promote products derived from this software
62
 *    without specific prior written permission.
63
 *
64
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
65
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
66
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
67
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
68
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
69
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
70
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
71
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
72
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
73
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
74
 * SUCH DAMAGE.
75
 */
76
 
77
#include "global.h"
113 theseven 78
#include "include/_ansi.h"
79
#include "include/stdlib.h"
71 theseven 80
 
81
#ifndef __GNUC__
82
#define inline
83
#endif
84
 
85
static inline char      *med3 _PARAMS((char *, char *, char *, int (*cmp)(const _PTR,const _PTR)));
86
static inline void       swapfunc _PARAMS((char *, char *, int, int));
87
 
88
#define min(a, b)       (a) < (b) ? a : b
89
 
90
/*
91
 * Qsort routine from Bentley & McIlroy's "Engineering a Sort Function".
92
 */
93
#define swapcode(TYPE, parmi, parmj, n) {               \
94
        long i = (n) / sizeof (TYPE);                   \
95
        register TYPE *pi = (TYPE *) (parmi);           \
96
        register TYPE *pj = (TYPE *) (parmj);           \
97
        do {                                            \
98
                register TYPE   t = *pi;                \
99
                *pi++ = *pj;                            \
100
                *pj++ = t;                              \
101
        } while (--i > 0);                              \
102
}
103
 
104
#define SWAPINIT(a, es) swaptype = ((char *)a - (char *)0) % sizeof(long) || \
105
        es % sizeof(long) ? 2 : es == sizeof(long)? 0 : 1;
106
 
107
static inline void
108
_DEFUN(swapfunc, (a, b, n, swaptype),
109
        char *a _AND
110
        char *b _AND
111
        int n _AND
112
        int swaptype)
113
{
114
        if(swaptype <= 1) 
115
                swapcode(long, a, b, n)
116
        else
117
                swapcode(char, a, b, n)
118
}
119
 
120
#define swap(a, b)                                      \
121
        if (swaptype == 0) {                            \
122
                long t = *(long *)(a);                  \
123
                *(long *)(a) = *(long *)(b);            \
124
                *(long *)(b) = t;                       \
125
        } else                                          \
126
                swapfunc(a, b, es, swaptype)
127
 
128
#define vecswap(a, b, n)        if ((n) > 0) swapfunc(a, b, n, swaptype)
129
 
130
static inline char *
131
_DEFUN(med3, (a, b, c, cmp),
132
        char *a _AND
133
        char *b _AND
134
        char *c _AND
135
        int (*cmp)(const _PTR,const _PTR))
136
{
137
        return cmp(a, b) < 0 ?
138
               (cmp(b, c) < 0 ? b : (cmp(a, c) < 0 ? c : a ))
139
              :(cmp(b, c) > 0 ? b : (cmp(a, c) < 0 ? a : c ));
140
}
141
 
142
void
143
_DEFUN(qsort, (a, n, es, cmp),
144
        void *a _AND
145
        size_t n _AND
146
        size_t es _AND
147
        int (*cmp)(const _PTR,const _PTR))
148
{
149
        char *pa, *pb, *pc, *pd, *pl, *pm, *pn;
150
        int d, r, swaptype, swap_cnt;
151
 
152
loop:   SWAPINIT(a, es);
153
        swap_cnt = 0;
154
        if (n < 7) {
155
                for (pm = (char *) a + es; pm < (char *) a + n * es; pm += es)
156
                        for (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0;
157
                             pl -= es)
158
                                swap(pl, pl - es);
159
                return;
160
        }
161
        pm = (char *) a + (n / 2) * es;
162
        if (n > 7) {
163
                pl = a;
164
                pn = (char *) a + (n - 1) * es;
165
                if (n > 40) {
166
                        d = (n / 8) * es;
167
                        pl = med3(pl, pl + d, pl + 2 * d, cmp);
168
                        pm = med3(pm - d, pm, pm + d, cmp);
169
                        pn = med3(pn - 2 * d, pn - d, pn, cmp);
170
                }
171
                pm = med3(pl, pm, pn, cmp);
172
        }
173
        swap(a, pm);
174
        pa = pb = (char *) a + es;
175
 
176
        pc = pd = (char *) a + (n - 1) * es;
177
        for (;;) {
178
                while (pb <= pc && (r = cmp(pb, a)) <= 0) {
179
                        if (r == 0) {
180
                                swap_cnt = 1;
181
                                swap(pa, pb);
182
                                pa += es;
183
                        }
184
                        pb += es;
185
                }
186
                while (pb <= pc && (r = cmp(pc, a)) >= 0) {
187
                        if (r == 0) {
188
                                swap_cnt = 1;
189
                                swap(pc, pd);
190
                                pd -= es;
191
                        }
192
                        pc -= es;
193
                }
194
                if (pb > pc)
195
                        break;
196
                swap(pb, pc);
197
                swap_cnt = 1;
198
                pb += es;
199
                pc -= es;
200
        }
201
        if (swap_cnt == 0) {  /* Switch to insertion sort */
202
                for (pm = (char *) a + es; pm < (char *) a + n * es; pm += es)
203
                        for (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0; 
204
                             pl -= es)
205
                                swap(pl, pl - es);
206
                return;
207
        }
208
 
209
        pn = (char *) a + n * es;
210
        r = min(pa - (char *)a, pb - pa);
211
        vecswap(a, pb - r, r);
212
        r = min((unsigned int)(pd - pc), pn - pd - es);
213
        vecswap(pb, pn - r, r);
214
        if ((unsigned int)(r = pb - pa) > es)
215
                qsort(a, r / es, es, cmp);
216
        if ((unsigned int)(r = pd - pc) > es) { 
217
                /* Iterate rather than recurse to save stack space */
218
                a = pn - r;
219
                n = r / es;
220
                goto loop;
221
        }
222
/*              qsort(pn - r, r / es, es, cmp);*/
223
}