source: mainline/kernel/generic/src/lib/sort.c@ dc12262

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since dc12262 was 75c9852, checked in by Martin Decky <martin@…>, 15 years ago

remove forgotten debugging output

  • Property mode set to 100644
File size: 6.0 KB
Line 
1/*
2 * Copyright (c) 2005 Sergey Bondari
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup generic
30 * @{
31 */
32
33/**
34 * @file
35 * @brief Sorting functions.
36 *
37 * This files contains functions implementing several sorting
38 * algorithms (e.g. quick sort and gnome sort).
39 *
40 */
41
42#include <mm/slab.h>
43#include <memstr.h>
44#include <sort.h>
45
46/** Immediate buffer size.
47 *
48 * For small buffer sizes avoid doing malloc()
49 * and use the stack.
50 *
51 */
52#define IBUF_SIZE 32
53
54/** Array accessor.
55 *
56 */
57#define INDEX(buf, i, elem_size) ((buf) + (i) * (elem_size))
58
59/** Gnome sort
60 *
61 * Apply generic gnome sort algorithm on supplied data,
62 * using pre-allocated buffer.
63 *
64 * @param data Pointer to data to be sorted.
65 * @param cnt Number of elements to be sorted.
66 * @param elem_size Size of one element.
67 * @param cmp Comparator function.
68 * @param arg 3rd argument passed to cmp.
69 * @param slot Pointer to scratch memory buffer
70 * elem_size bytes long.
71 *
72 */
73static void _gsort(void *data, size_t cnt, size_t elem_size, sort_cmp_t cmp,
74 void *arg, void *slot)
75{
76 size_t i = 0;
77
78 while (i < cnt) {
79 if ((i > 0) &&
80 (cmp(INDEX(data, i, elem_size),
81 INDEX(data, i - 1, elem_size), arg) == -1)) {
82 memcpy(slot, INDEX(data, i, elem_size), elem_size);
83 memcpy(INDEX(data, i, elem_size), INDEX(data, i - 1, elem_size),
84 elem_size);
85 memcpy(INDEX(data, i - 1, elem_size), slot, elem_size);
86 i--;
87 } else
88 i++;
89 }
90}
91
92/** Quicksort
93 *
94 * Apply generic quicksort algorithm on supplied data,
95 * using pre-allocated buffers.
96 *
97 * @param data Pointer to data to be sorted.
98 * @param cnt Number of elements to be sorted.
99 * @param elem_size Size of one element.
100 * @param cmp Comparator function.
101 * @param arg 3rd argument passed to cmp.
102 * @param slot Pointer to scratch memory buffer
103 * elem_size bytes long.
104 * @param pivot Pointer to scratch memory buffer
105 * elem_size bytes long.
106 *
107 */
108static void _qsort(void *data, size_t cnt, size_t elem_size, sort_cmp_t cmp,
109 void *arg, void *slot, void *pivot)
110{
111 if (cnt > 4) {
112 size_t i = 0;
113 size_t j = cnt - 1;
114
115 memcpy(pivot, data, elem_size);
116
117 while (true) {
118 while ((cmp(INDEX(data, i, elem_size), pivot, arg) < 0) && (i < cnt))
119 i++;
120
121 while ((cmp(INDEX(data, j, elem_size), pivot, arg) >= 0) && (j > 0))
122 j--;
123
124 if (i < j) {
125 memcpy(slot, INDEX(data, i, elem_size), elem_size);
126 memcpy(INDEX(data, i, elem_size), INDEX(data, j, elem_size),
127 elem_size);
128 memcpy(INDEX(data, j, elem_size), slot, elem_size);
129 } else
130 break;
131 }
132
133 _qsort(data, j + 1, elem_size, cmp, arg, slot, pivot);
134 _qsort(INDEX(data, j + 1, elem_size), cnt - j - 1, elem_size,
135 cmp, arg, slot, pivot);
136 } else
137 _gsort(data, cnt, elem_size, cmp, arg, slot);
138}
139
140/** Gnome sort wrapper
141 *
142 * This is only a wrapper that takes care of memory
143 * allocations for storing the slot element for generic
144 * gnome sort algorithm.
145 *
146 * This function can sleep.
147 *
148 * @param data Pointer to data to be sorted.
149 * @param cnt Number of elements to be sorted.
150 * @param elem_size Size of one element.
151 * @param cmp Comparator function.
152 * @param arg 3rd argument passed to cmp.
153 *
154 * @return True if sorting succeeded.
155 *
156 */
157bool gsort(void *data, size_t cnt, size_t elem_size, sort_cmp_t cmp, void *arg)
158{
159 uint8_t ibuf_slot[IBUF_SIZE];
160 void *slot;
161
162 if (elem_size > IBUF_SIZE) {
163 slot = (void *) malloc(elem_size, 0);
164 if (!slot)
165 return false;
166 } else
167 slot = (void *) ibuf_slot;
168
169 _gsort(data, cnt, elem_size, cmp, arg, slot);
170
171 if (elem_size > IBUF_SIZE)
172 free(slot);
173
174 return true;
175}
176
177/** Quicksort wrapper
178 *
179 * This is only a wrapper that takes care of memory
180 * allocations for storing the pivot and temporary elements
181 * for generic quicksort algorithm.
182 *
183 * This function can sleep.
184 *
185 * @param data Pointer to data to be sorted.
186 * @param cnt Number of elements to be sorted.
187 * @param elem_size Size of one element.
188 * @param cmp Comparator function.
189 * @param arg 3rd argument passed to cmp.
190 *
191 * @return True if sorting succeeded.
192 *
193 */
194bool qsort(void *data, size_t cnt, size_t elem_size, sort_cmp_t cmp, void *arg)
195{
196 uint8_t ibuf_slot[IBUF_SIZE];
197 uint8_t ibuf_pivot[IBUF_SIZE];
198 void *slot;
199 void *pivot;
200
201 if (elem_size > IBUF_SIZE) {
202 slot = (void *) malloc(elem_size, 0);
203 if (!slot)
204 return false;
205
206 pivot = (void *) malloc(elem_size, 0);
207 if (!pivot) {
208 free(slot);
209 return false;
210 }
211 } else {
212 slot = (void *) ibuf_slot;
213 pivot = (void *) ibuf_pivot;
214 }
215
216 _qsort(data, cnt, elem_size, cmp, arg, slot, pivot);
217
218 if (elem_size > IBUF_SIZE) {
219 free(pivot);
220 free(slot);
221 }
222
223 return true;
224}
225
226/** @}
227 */
Note: See TracBrowser for help on using the repository browser.