source: mainline/generic/src/lib/sort.c@ 169c408

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 169c408 was 169c408, checked in by Jakub Jermar <jakub@…>, 20 years ago

Move src/ and include/ to generic.

  • Property mode set to 100644
File size: 5.5 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#include <mm/heap.h>
30#include <memstr.h>
31#include <sort.h>
32#include <panic.h>
33
34#define EBUFSIZE 32
35
36void _qsort(void * data, count_t n, size_t e_size, int (* cmp) (void * a, void * b), void *tmp, void *pivot);
37void _bubblesort(void * data, count_t n, size_t e_size, int (* cmp) (void * a, void * b), void *slot);
38
39/** Quicksort wrapper
40 *
41 * This is only a wrapper that takes care of memory allocations for storing
42 * the pivot and temporary elements for generic quicksort algorithm.
43 *
44 * @param data Pointer to data to be sorted.
45 * @param n Number of elements to be sorted.
46 * @param e_size Size of one element.
47 * @param cmp Comparator function.
48 *
49 */
50void qsort(void * data, count_t n, size_t e_size, int (* cmp) (void * a, void * b))
51{
52 __u8 buf_tmp[EBUFSIZE];
53 __u8 buf_pivot[EBUFSIZE];
54 void * tmp = buf_tmp;
55 void * pivot = buf_pivot;
56
57 if (e_size > EBUFSIZE) {
58 pivot = (void *) malloc(e_size);
59 tmp = (void *) malloc(e_size);
60
61 if (!tmp || !pivot) {
62 panic("Cannot allocate memory\n");
63 }
64 }
65
66 _qsort(data, n, e_size, cmp, tmp, pivot);
67
68 if (e_size > EBUFSIZE) {
69 free(tmp);
70 free(pivot);
71 }
72}
73
74/** Quicksort
75 *
76 * Apply generic quicksort algorithm on supplied data, using pre-allocated buffers.
77 *
78 * @param data Pointer to data to be sorted.
79 * @param n Number of elements to be sorted.
80 * @param e_size Size of one element.
81 * @param cmp Comparator function.
82 * @param tmp Pointer to scratch memory buffer e_size bytes long.
83 * @param pivot Pointer to scratch memory buffer e_size bytes long.
84 *
85 */
86void _qsort(void * data, count_t n, size_t e_size, int (* cmp) (void * a, void * b), void *tmp, void *pivot)
87{
88 if (n > 4) {
89 int i = 0, j = n - 1;
90
91 memcpy(pivot, data, e_size);
92
93 while (1) {
94 while ((cmp(data + i * e_size, pivot) < 0) && i < n) i++;
95 while ((cmp(data + j * e_size, pivot) >=0) && j > 0) j--;
96 if (i<j) {
97 memcpy(tmp, data + i * e_size, e_size);
98 memcpy(data + i * e_size, data + j * e_size, e_size);
99 memcpy(data + j * e_size, tmp, e_size);
100 } else {
101 break;
102 }
103 }
104
105 _qsort(data, j + 1, e_size, cmp, tmp, pivot);
106 _qsort(data + (j + 1) * e_size, n - j - 1, e_size, cmp, tmp, pivot);
107 } else {
108 _bubblesort(data, n, e_size, cmp, tmp);
109 }
110}
111
112/** Bubblesort wrapper
113 *
114 * This is only a wrapper that takes care of memory allocation for storing
115 * the slot element for generic bubblesort algorithm.
116 *
117 * @param data Pointer to data to be sorted.
118 * @param n Number of elements to be sorted.
119 * @param e_size Size of one element.
120 * @param cmp Comparator function.
121 *
122 */
123void bubblesort(void * data, count_t n, size_t e_size, int (* cmp) (void * a, void * b))
124{
125 __u8 buf_slot[EBUFSIZE];
126 void * slot = buf_slot;
127
128 if (e_size > EBUFSIZE) {
129 slot = (void *) malloc(e_size);
130
131 if (!slot) {
132 panic("Cannot allocate memory\n");
133 }
134 }
135
136 _bubblesort(data, n, e_size, cmp, slot);
137
138 if (e_size > EBUFSIZE) {
139 free(slot);
140 }
141}
142
143/** Bubblesort
144 *
145 * Apply generic bubblesort algorithm on supplied data, using pre-allocated buffer.
146 *
147 * @param data Pointer to data to be sorted.
148 * @param n Number of elements to be sorted.
149 * @param e_size Size of one element.
150 * @param cmp Comparator function.
151 * @param slot Pointer to scratch memory buffer e_size bytes long.
152 *
153 */
154void _bubblesort(void * data, count_t n, size_t e_size, int (* cmp) (void * a, void * b), void *slot)
155{
156 bool done = false;
157 void * p;
158
159 while (!done) {
160 done = true;
161 for (p = data; p < data + e_size * (n - 1); p = p + e_size) {
162 if (cmp(p, p + e_size) == 1) {
163 memcpy(slot, p, e_size);
164 memcpy(p, p + e_size, e_size);
165 memcpy(p + e_size, slot, e_size);
166 done = false;
167 }
168 }
169 }
170
171}
172
173/*
174 * Comparator returns 1 if a > b, 0 if a == b, -1 if a < b
175 */
176int int_cmp(void * a, void * b)
177{
178 return (* (int *) a > * (int*)b) ? 1 : (*(int *)a < * (int *)b) ? -1 : 0;
179}
180
181int __u8_cmp(void * a, void * b)
182{
183 return (* (__u8 *) a > * (__u8 *)b) ? 1 : (*(__u8 *)a < * (__u8 *)b) ? -1 : 0;
184}
185
186int __u16_cmp(void * a, void * b)
187{
188 return (* (__u16 *) a > * (__u16 *)b) ? 1 : (*(__u16 *)a < * (__u16 *)b) ? -1 : 0;
189}
190
191int __u32_cmp(void * a, void * b)
192{
193 return (* (__u32 *) a > * (__u32 *)b) ? 1 : (*(__u32 *)a < * (__u32 *)b) ? -1 : 0;
194}
Note: See TracBrowser for help on using the repository browser.