The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/libsa/sort.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
    3  *
    4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
    5  * 
    6  * This file contains Original Code and/or Modifications of Original Code
    7  * as defined in and that are subject to the Apple Public Source License
    8  * Version 2.0 (the 'License'). You may not use this file except in
    9  * compliance with the License. The rights granted to you under the License
   10  * may not be used to create, or enable the creation or redistribution of,
   11  * unlawful or unlicensed copies of an Apple operating system, or to
   12  * circumvent, violate, or enable the circumvention or violation of, any
   13  * terms of an Apple operating system software license agreement.
   14  * 
   15  * Please obtain a copy of the License at
   16  * http://www.opensource.apple.com/apsl/ and read it before using this file.
   17  * 
   18  * The Original Code and all software distributed under the License are
   19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
   20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
   21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
   22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
   23  * Please see the License for the specific language governing rights and
   24  * limitations under the License.
   25  * 
   26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
   27  */
   28 /*-
   29  * Copyright (c) 1991, 1993
   30  *      The Regents of the University of California.  All rights reserved.
   31  *
   32  * This code is derived from software contributed to Berkeley by
   33  * Ronnie Kon at Mindcraft Inc., Kevin Lew and Elmer Yglesias.
   34  *
   35  * Redistribution and use in source and binary forms, with or without
   36  * modification, are permitted provided that the following conditions
   37  * are met:
   38  * 1. Redistributions of source code must retain the above copyright
   39  *    notice, this list of conditions and the following disclaimer.
   40  * 2. Redistributions in binary form must reproduce the above copyright
   41  *    notice, this list of conditions and the following disclaimer in the
   42  *    documentation and/or other materials provided with the distribution.
   43  * 3. All advertising materials mentioning features or use of this software
   44  *    must display the following acknowledgement:
   45  *      This product includes software developed by the University of
   46  *      California, Berkeley and its contributors.
   47  * 4. Neither the name of the University nor the names of its contributors
   48  *    may be used to endorse or promote products derived from this software
   49  *    without specific prior written permission.
   50  *
   51  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   52  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   53  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   54  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   55  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   56  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   57  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   58  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   59  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   60  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   61  * SUCH DAMAGE.
   62  */
   63 
   64 #if defined(LIBC_SCCS) && !defined(lint)
   65 static char sccsid[] = "@(#)heapsort.c  8.1 (Berkeley) 6/4/93";
   66 #endif /* LIBC_SCCS and not lint */
   67 
   68 
   69 #include <libsa/stdlib.h>
   70 
   71 
   72 /*
   73  * Swap two areas of size number of bytes.  Although qsort(3) permits random
   74  * blocks of memory to be sorted, sorting pointers is almost certainly the
   75  * common case (and, were it not, could easily be made so).  Regardless, it
   76  * isn't worth optimizing; the SWAP's get sped up by the cache, and pointer
   77  * arithmetic gets lost in the time required for comparison function calls.
   78  */
   79 #define SWAP(a, b, count, size, tmp) { \
   80         count = size; \
   81         do { \
   82                 tmp = *a; \
   83                 *a++ = *b; \
   84                 *b++ = tmp; \
   85         } while (--count); \
   86 }
   87 
   88 /* Copy one block of size size to another. */
   89 #define COPY(a, b, count, size, tmp1, tmp2) { \
   90         count = size; \
   91         tmp1 = a; \
   92         tmp2 = b; \
   93         do { \
   94                 *tmp1++ = *tmp2++; \
   95         } while (--count); \
   96 }
   97 
   98 /*
   99  * Build the list into a heap, where a heap is defined such that for
  100  * the records K1 ... KN, Kj/2 >= Kj for 1 <= j/2 <= j <= N.
  101  *
  102  * There two cases.  If j == nmemb, select largest of Ki and Kj.  If
  103  * j < nmemb, select largest of Ki, Kj and Kj+1.
  104  */
  105 #define CREATE(initval, nmemb, par_i, child_i, par, child, size, count, tmp) { \
  106         for (par_i = initval; (child_i = par_i * 2) <= nmemb; \
  107             par_i = child_i) { \
  108                 child = base + child_i * size; \
  109                 if (child_i < nmemb && compar(child, child + size) < 0) { \
  110                         child += size; \
  111                         ++child_i; \
  112                 } \
  113                 par = base + par_i * size; \
  114                 if (compar(child, par) <= 0) \
  115                         break; \
  116                 SWAP(par, child, count, size, tmp); \
  117         } \
  118 }
  119 
  120 /*
  121  * Select the top of the heap and 'heapify'.  Since by far the most expensive
  122  * action is the call to the compar function, a considerable optimization
  123  * in the average case can be achieved due to the fact that k, the displaced
  124  * elememt, is ususally quite small, so it would be preferable to first
  125  * heapify, always maintaining the invariant that the larger child is copied
  126  * over its parent's record.
  127  *
  128  * Then, starting from the *bottom* of the heap, finding k's correct place,
  129  * again maintianing the invariant.  As a result of the invariant no element
  130  * is 'lost' when k is assigned its correct place in the heap.
  131  *
  132  * The time savings from this optimization are on the order of 15-20% for the
  133  * average case. See Knuth, Vol. 3, page 158, problem 18.
  134  *
  135  * XXX Don't break the #define SELECT line, below.  Reiser cpp gets upset.
  136  */
  137 #define SELECT(par_i, child_i, nmemb, par, child, size, k, count, tmp1, tmp2) { \
  138         for (par_i = 1; (child_i = par_i * 2) <= nmemb; par_i = child_i) { \
  139                 child = base + child_i * size; \
  140                 if (child_i < nmemb && compar(child, child + size) < 0) { \
  141                         child += size; \
  142                         ++child_i; \
  143                 } \
  144                 par = base + par_i * size; \
  145                 COPY(par, child, count, size, tmp1, tmp2); \
  146         } \
  147         for (;;) { \
  148                 child_i = par_i; \
  149                 par_i = child_i / 2; \
  150                 child = base + child_i * size; \
  151                 par = base + par_i * size; \
  152                 if (child_i == 1 || compar(k, par) < 0) { \
  153                         COPY(child, k, count, size, tmp1, tmp2); \
  154                         break; \
  155                 } \
  156                 COPY(child, par, count, size, tmp1, tmp2); \
  157         } \
  158 }
  159 
  160 /* Pass heapsort off as qsort for krld. -- Nik Gervae
  161  *
  162  * Heapsort -- Knuth, Vol. 3, page 145.  Runs in O (N lg N), both average
  163  * and worst.  While heapsort is faster than the worst case of quicksort,
  164  * the BSD quicksort does median selection so that the chance of finding
  165  * a data set that will trigger the worst case is nonexistent.  Heapsort's
  166  * only advantage over quicksort is that it requires little additional memory.
  167  */
  168 __private_extern__
  169 void qsort(void * vbase, size_t nmemb, size_t size,
  170         int (*compar)(const void *, const void *)) {
  171 
  172         register unsigned int cnt, i, j, l;
  173         register char tmp, *tmp1, *tmp2;
  174         char *base, *k, *p, *t;
  175 
  176         if (nmemb <= 1) {
  177             return;
  178         }
  179 
  180         if (!size) {
  181             return;
  182         }
  183 
  184         if ((k = (char *)malloc(size)) == NULL) {
  185 //            panic();
  186             return;
  187         }
  188 
  189         /*
  190          * Items are numbered from 1 to nmemb, so offset from size bytes
  191          * below the starting address.
  192          */
  193         base = (char *)vbase - size;
  194 
  195         for (l = nmemb / 2 + 1; --l;)
  196                 CREATE(l, nmemb, i, j, t, p, size, cnt, tmp);
  197 
  198         /*
  199          * For each element of the heap, save the largest element into its
  200          * final slot, save the displaced element (k), then recreate the
  201          * heap.
  202          */
  203         while (nmemb > 1) {
  204                 COPY(k, base + nmemb * size, cnt, size, tmp1, tmp2);
  205                 COPY(base + nmemb * size, base + size, cnt, size, tmp1, tmp2);
  206                 --nmemb;
  207                 SELECT(i, j, nmemb, t, p, size, k, cnt, tmp1, tmp2);
  208         }
  209         free(k);
  210         return;
  211 }

Cache object: 1afb4bd05e1554d117455b1505d860c3


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.