• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src/router/samba-3.5.8/source4/lib/ldb/common/
1/* Copyright (C) 1991,1992,1996,1997,1999,2004 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 Lesser General Public
7   License as published by the Free Software Foundation; either
8   version 2.1 of the License, or (at your option) any later version.
9
10   The GNU C Library is distributed in the hope that it will be useful,
11   but WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13   Lesser General Public License for more details.
14
15   You should have received a copy of the GNU Lesser General Public
16   License along with the GNU C Library; if not, see <http://www.gnu.org/licenses/>. */
17
18/* If you consider tuning this algorithm, you should consult first:
19   Engineering a sort function; Jon Bentley and M. Douglas McIlroy;
20   Software - Practice and Experience; Vol. 23 (11), 1249-1265, 1993.  */
21
22/* Modified to be used in samba4 by
23 * Simo Sorce <idra@samba.org>		2005
24 */
25
26#include "ldb_private.h"
27
28/* Byte-wise swap two items of size SIZE. */
29#define SWAP(a, b, size)						      \
30  do									      \
31    {									      \
32      register size_t __size = (size);					      \
33      register char *__a = (a), *__b = (b);				      \
34      do								      \
35	{								      \
36	  char __tmp = *__a;						      \
37	  *__a++ = *__b;						      \
38	  *__b++ = __tmp;						      \
39	} while (--__size > 0);						      \
40    } while (0)
41
42/* Discontinue quicksort algorithm when partition gets below this size.
43   This particular magic number was chosen to work best on a Sun 4/260. */
44#define MAX_THRESH 4
45
46/* Stack node declarations used to store unfulfilled partition obligations. */
47typedef struct
48  {
49    char *lo;
50    char *hi;
51  } stack_node;
52
53/* The next 4 #defines implement a very fast in-line stack abstraction. */
54/* The stack needs log (total_elements) entries (we could even subtract
55   log(MAX_THRESH)).  Since total_elements has type size_t, we get as
56   upper bound for log (total_elements):
57   bits per byte (CHAR_BIT) * sizeof(size_t).  */
58#ifndef CHAR_BIT
59#define CHAR_BIT 8
60#endif
61#define STACK_SIZE	(CHAR_BIT * sizeof(size_t))
62#define PUSH(low, high)	((void) ((top->lo = (low)), (top->hi = (high)), ++top))
63#define	POP(low, high)	((void) (--top, (low = top->lo), (high = top->hi)))
64#define	STACK_NOT_EMPTY	(stack < top)
65
66
67/* Order size using quicksort.  This implementation incorporates
68   four optimizations discussed in Sedgewick:
69
70   1. Non-recursive, using an explicit stack of pointer that store the
71      next array partition to sort.  To save time, this maximum amount
72      of space required to store an array of SIZE_MAX is allocated on the
73      stack.  Assuming a 32-bit (64 bit) integer for size_t, this needs
74      only 32 * sizeof(stack_node) == 256 bytes (for 64 bit: 1024 bytes).
75      Pretty cheap, actually.
76
77   2. Chose the pivot element using a median-of-three decision tree.
78      This reduces the probability of selecting a bad pivot value and
79      eliminates certain extraneous comparisons.
80
81   3. Only quicksorts TOTAL_ELEMS / MAX_THRESH partitions, leaving
82      insertion sort to order the MAX_THRESH items within each partition.
83      This is a big win, since insertion sort is faster for small, mostly
84      sorted array segments.
85
86   4. The larger of the two sub-partitions is always pushed onto the
87      stack first, with the algorithm then concentrating on the
88      smaller partition.  This *guarantees* no more than log (total_elems)
89      stack size is needed (actually O(1) in this case)!  */
90
91void ldb_qsort (void *const pbase, size_t total_elems, size_t size,
92		void *opaque, ldb_qsort_cmp_fn_t cmp)
93{
94  register char *base_ptr = (char *) pbase;
95
96  const size_t max_thresh = MAX_THRESH * size;
97
98  if (total_elems == 0)
99    /* Avoid lossage with unsigned arithmetic below.  */
100    return;
101
102  if (total_elems > MAX_THRESH)
103    {
104      char *lo = base_ptr;
105      char *hi = &lo[size * (total_elems - 1)];
106      stack_node stack[STACK_SIZE];
107      stack_node *top = stack;
108
109      PUSH (NULL, NULL);
110
111      while (STACK_NOT_EMPTY)
112        {
113          char *left_ptr;
114          char *right_ptr;
115
116	  /* Select median value from among LO, MID, and HI. Rearrange
117	     LO and HI so the three values are sorted. This lowers the
118	     probability of picking a pathological pivot value and
119	     skips a comparison for both the LEFT_PTR and RIGHT_PTR in
120	     the while loops. */
121
122	  char *mid = lo + size * ((hi - lo) / size >> 1);
123
124	  if ((*cmp) ((void *) mid, (void *) lo, opaque) < 0)
125	    SWAP (mid, lo, size);
126	  if ((*cmp) ((void *) hi, (void *) mid, opaque) < 0)
127	    SWAP (mid, hi, size);
128	  else
129	    goto jump_over;
130	  if ((*cmp) ((void *) mid, (void *) lo, opaque) < 0)
131	    SWAP (mid, lo, size);
132	jump_over:;
133
134	  left_ptr  = lo + size;
135	  right_ptr = hi - size;
136
137	  /* Here's the famous ``collapse the walls'' section of quicksort.
138	     Gotta like those tight inner loops!  They are the main reason
139	     that this algorithm runs much faster than others. */
140	  do
141	    {
142	      while ((*cmp) ((void *) left_ptr, (void *) mid, opaque) < 0)
143		left_ptr += size;
144
145	      while ((*cmp) ((void *) mid, (void *) right_ptr, opaque) < 0)
146		right_ptr -= size;
147
148	      if (left_ptr < right_ptr)
149		{
150		  SWAP (left_ptr, right_ptr, size);
151		  if (mid == left_ptr)
152		    mid = right_ptr;
153		  else if (mid == right_ptr)
154		    mid = left_ptr;
155		  left_ptr += size;
156		  right_ptr -= size;
157		}
158	      else if (left_ptr == right_ptr)
159		{
160		  left_ptr += size;
161		  right_ptr -= size;
162		  break;
163		}
164	    }
165	  while (left_ptr <= right_ptr);
166
167          /* Set up pointers for next iteration.  First determine whether
168             left and right partitions are below the threshold size.  If so,
169             ignore one or both.  Otherwise, push the larger partition's
170             bounds on the stack and continue sorting the smaller one. */
171
172          if ((size_t) (right_ptr - lo) <= max_thresh)
173            {
174              if ((size_t) (hi - left_ptr) <= max_thresh)
175		/* Ignore both small partitions. */
176                POP (lo, hi);
177              else
178		/* Ignore small left partition. */
179                lo = left_ptr;
180            }
181          else if ((size_t) (hi - left_ptr) <= max_thresh)
182	    /* Ignore small right partition. */
183            hi = right_ptr;
184          else if ((right_ptr - lo) > (hi - left_ptr))
185            {
186	      /* Push larger left partition indices. */
187              PUSH (lo, right_ptr);
188              lo = left_ptr;
189            }
190          else
191            {
192	      /* Push larger right partition indices. */
193              PUSH (left_ptr, hi);
194              hi = right_ptr;
195            }
196        }
197    }
198
199  /* Once the BASE_PTR array is partially sorted by quicksort the rest
200     is completely sorted using insertion sort, since this is efficient
201     for partitions below MAX_THRESH size. BASE_PTR points to the beginning
202     of the array to sort, and END_PTR points at the very last element in
203     the array (*not* one beyond it!). */
204
205#define min(x, y) ((x) < (y) ? (x) : (y))
206
207  {
208    char *const end_ptr = &base_ptr[size * (total_elems - 1)];
209    char *tmp_ptr = base_ptr;
210    char *thresh = min(end_ptr, base_ptr + max_thresh);
211    register char *run_ptr;
212
213    /* Find smallest element in first threshold and place it at the
214       array's beginning.  This is the smallest array element,
215       and the operation speeds up insertion sort's inner loop. */
216
217    for (run_ptr = tmp_ptr + size; run_ptr <= thresh; run_ptr += size)
218      if ((*cmp) ((void *) run_ptr, (void *) tmp_ptr, opaque) < 0)
219        tmp_ptr = run_ptr;
220
221    if (tmp_ptr != base_ptr)
222      SWAP (tmp_ptr, base_ptr, size);
223
224    /* Insertion sort, running from left-hand-side up to right-hand-side.  */
225
226    run_ptr = base_ptr + size;
227    while ((run_ptr += size) <= end_ptr)
228      {
229	tmp_ptr = run_ptr - size;
230	while ((*cmp) ((void *) run_ptr, (void *) tmp_ptr, opaque) < 0)
231	  tmp_ptr -= size;
232
233	tmp_ptr += size;
234        if (tmp_ptr != run_ptr)
235          {
236            char *trav;
237
238	    trav = run_ptr + size;
239	    while (--trav >= run_ptr)
240              {
241                char c = *trav;
242                char *hi, *lo;
243
244                for (hi = lo = trav; (lo -= size) >= tmp_ptr; hi = lo)
245                  *hi = *lo;
246                *hi = c;
247              }
248          }
249      }
250  }
251}
252