]> git.ipfire.org Git - thirdparty/glibc.git/blobdiff - stdlib/qsort.c
hurd: Fix build
[thirdparty/glibc.git] / stdlib / qsort.c
index f14acb6abb4948dcb8ae36ecfec12a43bd568f33..264a06b8a924a1627b3c0fd507a3e2ca38dbc8a0 100644 (file)
@@ -1,21 +1,20 @@
-/* Copyright (C) 1991, 1992, 1996, 1997, 1999 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Written by Douglas C. Schmidt (schmidt@ics.uci.edu).
 
    The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Library General Public License as
-   published by the Free Software Foundation; either version 2 of the
-   License, or (at your option) any later version.
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
 
    The GNU C Library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Library General Public License for more details.
+   Lesser General Public License for more details.
 
-   You should have received a copy of the GNU Library General Public
-   License along with the GNU C Library; see the file COPYING.LIB.  If not,
-   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-   Boston, MA 02111-1307, USA.  */
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
 
 /* If you consider tuning this algorithm, you should consult first:
    Engineering a sort function; Jon Bentley and M. Douglas McIlroy;
@@ -30,8 +29,8 @@
 #define SWAP(a, b, size)                                                     \
   do                                                                         \
     {                                                                        \
-      register size_t __size = (size);                                       \
-      register char *__a = (a), *__b = (b);                                  \
+      size_t __size = (size);                                                \
+      char *__a = (a), *__b = (b);                                           \
       do                                                                     \
        {                                                                     \
          char __tmp = *__a;                                                  \
@@ -88,13 +87,10 @@ typedef struct
 
 void
 _quicksort (void *const pbase, size_t total_elems, size_t size,
-           __compar_fn_t cmp)
+           __compar_d_fn_t cmp, void *arg)
 {
-  register char *base_ptr = (char *) pbase;
+  char *base_ptr = (char *) pbase;
 
-  /* Allocating SIZE bytes for a pivot buffer facilitates a better
-     algorithm below since we can do comparisons directly on the pivot. */
-  char *pivot_buffer = (char *) __alloca (size);
   const size_t max_thresh = MAX_THRESH * size;
 
   if (total_elems == 0)
@@ -106,15 +102,15 @@ _quicksort (void *const pbase, size_t total_elems, size_t size,
       char *lo = base_ptr;
       char *hi = &lo[size * (total_elems - 1)];
       stack_node stack[STACK_SIZE];
-      stack_node *top = stack + 1;
+      stack_node *top = stack;
+
+      PUSH (NULL, NULL);
 
       while (STACK_NOT_EMPTY)
         {
           char *left_ptr;
           char *right_ptr;
 
-         char *pivot = pivot_buffer;
-
          /* Select median value from among LO, MID, and HI. Rearrange
             LO and HI so the three values are sorted. This lowers the
             probability of picking a pathological pivot value and
@@ -123,17 +119,15 @@ _quicksort (void *const pbase, size_t total_elems, size_t size,
 
          char *mid = lo + size * ((hi - lo) / size >> 1);
 
-         if ((*cmp) ((void *) mid, (void *) lo) < 0)
+         if ((*cmp) ((void *) mid, (void *) lo, arg) < 0)
            SWAP (mid, lo, size);
-         if ((*cmp) ((void *) hi, (void *) mid) < 0)
+         if ((*cmp) ((void *) hi, (void *) mid, arg) < 0)
            SWAP (mid, hi, size);
          else
            goto jump_over;
-         if ((*cmp) ((void *) mid, (void *) lo) < 0)
+         if ((*cmp) ((void *) mid, (void *) lo, arg) < 0)
            SWAP (mid, lo, size);
        jump_over:;
-         memcpy (pivot, mid, size);
-         pivot = pivot_buffer;
 
          left_ptr  = lo + size;
          right_ptr = hi - size;
@@ -143,15 +137,19 @@ _quicksort (void *const pbase, size_t total_elems, size_t size,
             that this algorithm runs much faster than others. */
          do
            {
-             while ((*cmp) ((void *) left_ptr, (void *) pivot) < 0)
+             while ((*cmp) ((void *) left_ptr, (void *) mid, arg) < 0)
                left_ptr += size;
 
-             while ((*cmp) ((void *) pivot, (void *) right_ptr) < 0)
+             while ((*cmp) ((void *) mid, (void *) right_ptr, arg) < 0)
                right_ptr -= size;
 
              if (left_ptr < right_ptr)
                {
                  SWAP (left_ptr, right_ptr, size);
+                 if (mid == left_ptr)
+                   mid = right_ptr;
+                 else if (mid == right_ptr)
+                   mid = left_ptr;
                  left_ptr += size;
                  right_ptr -= size;
                }
@@ -208,14 +206,14 @@ _quicksort (void *const pbase, size_t total_elems, size_t size,
     char *const end_ptr = &base_ptr[size * (total_elems - 1)];
     char *tmp_ptr = base_ptr;
     char *thresh = min(end_ptr, base_ptr + max_thresh);
-    register char *run_ptr;
+    char *run_ptr;
 
     /* Find smallest element in first threshold and place it at the
        array's beginning.  This is the smallest array element,
        and the operation speeds up insertion sort's inner loop. */
 
     for (run_ptr = tmp_ptr + size; run_ptr <= thresh; run_ptr += size)
-      if ((*cmp) ((void *) run_ptr, (void *) tmp_ptr) < 0)
+      if ((*cmp) ((void *) run_ptr, (void *) tmp_ptr, arg) < 0)
         tmp_ptr = run_ptr;
 
     if (tmp_ptr != base_ptr)
@@ -227,7 +225,7 @@ _quicksort (void *const pbase, size_t total_elems, size_t size,
     while ((run_ptr += size) <= end_ptr)
       {
        tmp_ptr = run_ptr - size;
-       while ((*cmp) ((void *) run_ptr, (void *) tmp_ptr) < 0)
+       while ((*cmp) ((void *) run_ptr, (void *) tmp_ptr, arg) < 0)
          tmp_ptr -= size;
 
        tmp_ptr += size;