1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 :
3 : /*-
4 : * Copyright (c) 1992, 1993
5 : * The Regents of the University of California. All rights reserved.
6 : *
7 : * Redistribution and use in source and binary forms, with or without
8 : * modification, are permitted provided that the following conditions
9 : * are met:
10 : * 1. Redistributions of source code must retain the above copyright
11 : * notice, this list of conditions and the following disclaimer.
12 : * 2. Redistributions in binary form must reproduce the above copyright
13 : * notice, this list of conditions and the following disclaimer in the
14 : * documentation and/or other materials provided with the distribution.
15 : * 3. Neither the name of the University nor the names of its contributors
16 : * may be used to endorse or promote products derived from this software
17 : * without specific prior written permission.
18 : *
19 : * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 : * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 : * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 : * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 : * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 : * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 : * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 : * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 : * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 : * SUCH DAMAGE.
30 : */
31 :
32 : /* We need this because Solaris' version of qsort is broken and
33 : * causes array bounds reads.
34 : */
35 :
36 : #include <stdlib.h>
37 : #include "prtypes.h"
38 : #include "nsAlgorithm.h"
39 : #include "nsQuickSort.h"
40 :
41 : PR_BEGIN_EXTERN_C
42 :
43 : #if !defined(DEBUG) && (defined(__cplusplus) || defined(__gcc))
44 : # ifndef INLINE
45 : # define INLINE inline
46 : # endif
47 : #else
48 : # define INLINE
49 : #endif
50 :
51 : typedef int cmp_t(const void *, const void *, void *);
52 : static INLINE char *med3(char *, char *, char *, cmp_t *, void *);
53 : static INLINE void swapfunc(char *, char *, int, int);
54 :
55 : /*
56 : * Qsort routine from Bentley & McIlroy's "Engineering a Sort Function".
57 : */
58 : #define swapcode(TYPE, parmi, parmj, n) { \
59 : long i = (n) / sizeof (TYPE); \
60 : register TYPE *pi = (TYPE *) (parmi); \
61 : register TYPE *pj = (TYPE *) (parmj); \
62 : do { \
63 : register TYPE t = *pi; \
64 : *pi++ = *pj; \
65 : *pj++ = t; \
66 : } while (--i > 0); \
67 : }
68 :
69 : #define SWAPINIT(a, es) swaptype = ((char *)a - (char *)0) % sizeof(long) || \
70 : es % sizeof(long) ? 2 : es == sizeof(long)? 0 : 1;
71 :
72 : static INLINE void
73 141749 : swapfunc(char *a, char *b, int n, int swaptype)
74 : {
75 141749 : if(swaptype <= 1)
76 141749 : swapcode(long, a, b, n)
77 : else
78 0 : swapcode(char, a, b, n)
79 141749 : }
80 :
81 : #define swap(a, b) \
82 : if (swaptype == 0) { \
83 : long t = *(long *)(a); \
84 : *(long *)(a) = *(long *)(b); \
85 : *(long *)(b) = t; \
86 : } else \
87 : swapfunc((char *)a, (char*)b, (int)es, swaptype)
88 :
89 : #define vecswap(a, b, n) if ((n) > 0) swapfunc((char *)a, (char *)b, (int)n, swaptype)
90 :
91 : static INLINE char *
92 14607 : med3(char *a, char *b, char *c, cmp_t* cmp, void *data)
93 : {
94 14607 : return cmp(a, b, data) < 0 ?
95 10040 : (cmp(b, c, data) < 0 ? b : (cmp(a, c, data) < 0 ? c : a ))
96 24647 : :(cmp(b, c, data) > 0 ? b : (cmp(a, c, data) < 0 ? a : c ));
97 : }
98 :
99 29631 : void NS_QuickSort (
100 : void *a,
101 : unsigned int n,
102 : unsigned int es,
103 : cmp_t *cmp,
104 : void *data
105 : )
106 : {
107 : char *pa, *pb, *pc, *pd, *pl, *pm, *pn;
108 : int d, r, swaptype, swap_cnt;
109 :
110 29631 : loop: SWAPINIT(a, es);
111 29631 : swap_cnt = 0;
112 29631 : if (n < 7) {
113 54265 : for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es)
114 88516 : for (pl = pm; pl > (char *)a && cmp(pl - es, pl, data) > 0;
115 52568 : pl -= es)
116 52568 : swap(pl, pl - es);
117 18317 : return;
118 : }
119 11314 : pm = (char *)a + (n / 2) * es;
120 11314 : if (n > 7) {
121 9762 : pl = (char *)a;
122 9762 : pn = (char *)a + (n - 1) * es;
123 9762 : if (n > 40) {
124 1615 : d = (n / 8) * es;
125 1615 : pl = med3(pl, pl + d, pl + 2 * d, cmp, data);
126 1615 : pm = med3(pm - d, pm, pm + d, cmp, data);
127 1615 : pn = med3(pn - 2 * d, pn - d, pn, cmp, data);
128 : }
129 9762 : pm = med3(pl, pm, pn, cmp, data);
130 : }
131 11314 : swap(a, pm);
132 11314 : pa = pb = (char *)a + es;
133 :
134 11314 : pc = pd = (char *)a + (n - 1) * es;
135 51758 : for (;;) {
136 198798 : while (pb <= pc && (r = cmp(pb, a, data)) <= 0) {
137 72654 : if (r == 0) {
138 3240 : swap_cnt = 1;
139 3240 : swap(pa, pb);
140 3240 : pa += es;
141 : }
142 72654 : pb += es;
143 : }
144 173871 : while (pb <= pc && (r = cmp(pc, a, data)) >= 0) {
145 47727 : if (r == 0) {
146 1610 : swap_cnt = 1;
147 1610 : swap(pc, pd);
148 1610 : pd -= es;
149 : }
150 47727 : pc -= es;
151 : }
152 63072 : if (pb > pc)
153 : break;
154 51758 : swap(pb, pc);
155 51758 : swap_cnt = 1;
156 51758 : pb += es;
157 51758 : pc -= es;
158 : }
159 11314 : if (swap_cnt == 0) { /* Switch to insertion sort */
160 26365 : for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es)
161 72774 : for (pl = pm; pl > (char *)a && cmp(pl - es, pl, data) > 0;
162 47916 : pl -= es)
163 47916 : swap(pl, pl - es);
164 1507 : return;
165 : }
166 :
167 9807 : pn = (char *)a + n * es;
168 9807 : r = NS_MIN(pa - (char *)a, pb - pa);
169 9807 : vecswap(a, pb - r, r);
170 9807 : r = NS_MIN<size_t>(pd - pc, pn - pd - es);
171 9807 : vecswap(pb, pn - r, r);
172 9807 : if ((r = pb - pa) > (int)es)
173 9725 : NS_QuickSort(a, r / es, es, cmp, data);
174 9807 : if ((r = pd - pc) > (int)es) {
175 : /* Iterate rather than recurse to save stack space */
176 9757 : a = pn - r;
177 9757 : n = r / es;
178 9757 : goto loop;
179 : }
180 : /* NS_QuickSort(pn - r, r / es, es, cmp, data);*/
181 : }
182 :
183 : PR_END_EXTERN_C
|