Update.
[glibc.git] / stdlib / msort.c
blobc03f6f2982cae786ba20be6cf8e13c87294e8d4b
1 /* An alternative to qsort, with an identical interface.
2 This file is part of the GNU C Library.
3 Copyright (C) 1992, 1995, 1996, 1997, 1999 Free Software Foundation, Inc.
4 Written by Mike Haertel, September 1988.
6 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public License as
8 published by the Free Software Foundation; either version 2 of the
9 License, or (at your option) any later version.
11 The GNU C Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
16 You should have received a copy of the GNU Library General Public
17 License along with the GNU C Library; see the file COPYING.LIB. If not,
18 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
21 #include <alloca.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <memcopy.h>
25 #include <errno.h>
27 static void msort_with_tmp (void *b, size_t n, size_t s,
28 __compar_fn_t cmp, char *t);
30 static void
31 msort_with_tmp (void *b, size_t n, size_t s, __compar_fn_t cmp,
32 char *t)
34 char *tmp;
35 char *b1, *b2;
36 size_t n1, n2;
38 if (n <= 1)
39 return;
41 n1 = n / 2;
42 n2 = n - n1;
43 b1 = b;
44 b2 = (char *) b + (n1 * s);
46 msort_with_tmp (b1, n1, s, cmp, t);
47 msort_with_tmp (b2, n2, s, cmp, t);
49 tmp = t;
51 if (s == OPSIZ && (b1 - (char *) 0) % OPSIZ == 0)
52 /* We are operating on aligned words. Use direct word stores. */
53 while (n1 > 0 && n2 > 0)
55 if ((*cmp) (b1, b2) <= 0)
57 --n1;
58 *((op_t *) tmp)++ = *((op_t *) b1)++;
60 else
62 --n2;
63 *((op_t *) tmp)++ = *((op_t *) b2)++;
66 else
67 while (n1 > 0 && n2 > 0)
69 if ((*cmp) (b1, b2) <= 0)
71 tmp = (char *) __mempcpy (tmp, b1, s);
72 b1 += s;
73 --n1;
75 else
77 tmp = (char *) __mempcpy (tmp, b2, s);
78 b2 += s;
79 --n2;
82 if (n1 > 0)
83 memcpy (tmp, b1, n1 * s);
84 memcpy (b, t, (n - n2) * s);
87 void
88 qsort (void *b, size_t n, size_t s, __compar_fn_t cmp)
90 const size_t size = n * s;
92 if (size < 1024)
93 /* The temporary array is small, so put it on the stack. */
94 msort_with_tmp (b, n, s, cmp, __alloca (size));
95 else
97 /* It's somewhat large, so malloc it. */
98 int save = errno;
99 char *tmp = malloc (size);
100 if (tmp == NULL)
102 /* Couldn't get space, so use the slower algorithm
103 that doesn't need a temporary array. */
104 _quicksort (b, n, s, cmp);
106 else
108 msort_with_tmp (b, n, s, cmp, tmp);
109 free (tmp);
111 __set_errno (save);