source: trunk/libs/newlib/src/newlib/libc/search/qsort.c @ 543

Last change on this file since 543 was 444, checked in by satin@…, 6 years ago

add newlib,libalmos-mkh, restructure shared_syscalls.h and mini-libc

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