Changeset 50f4b95 in mainline for kernel/generic/src/lib/sort.c
- Timestamp:
- 2010-06-30T20:36:48Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 99718a2e
- Parents:
- 0a79ad9 (diff), e9f4b59 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/src/lib/sort.c
r0a79ad9 r50f4b95 27 27 */ 28 28 29 /** @addtogroup generic 29 /** @addtogroup generic 30 30 * @{ 31 31 */ … … 33 33 /** 34 34 * @file 35 * @brief 35 * @brief Sorting functions. 36 36 * 37 37 * This files contains functions implementing several sorting 38 * algorithms (e.g. quick sort and bubble sort). 39 */ 40 38 * algorithms (e.g. quick sort and gnome sort). 39 * 40 */ 41 41 42 #include <mm/slab.h> 42 43 #include <memstr.h> 43 44 #include <sort.h> 44 #include <panic.h> 45 46 #define EBUFSIZE 32 47 48 void _qsort(void * data, size_t n, size_t e_size, int (* cmp) (void * a, void * b), void *tmp, void *pivot); 49 void _bubblesort(void * data, size_t n, size_t e_size, int (* cmp) (void * a, void * b), void *slot); 50 51 /** Quicksort wrapper 52 * 53 * This is only a wrapper that takes care of memory allocations for storing 54 * the pivot and temporary elements for generic quicksort algorithm. 55 * 56 * This function _can_ sleep 57 * 58 * @param data Pointer to data to be sorted. 59 * @param n Number of elements to be sorted. 60 * @param e_size Size of one element. 61 * @param cmp Comparator function. 62 * 63 */ 64 void qsort(void * data, size_t n, size_t e_size, int (* cmp) (void * a, void * b)) 65 { 66 uint8_t buf_tmp[EBUFSIZE]; 67 uint8_t buf_pivot[EBUFSIZE]; 68 void * tmp = buf_tmp; 69 void * pivot = buf_pivot; 70 71 if (e_size > EBUFSIZE) { 72 pivot = (void *) malloc(e_size, 0); 73 tmp = (void *) malloc(e_size, 0); 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 */ 73 static 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 printf("exch: %u %u\n", i - 1, i); 87 i--; 88 } else 89 i++; 74 90 } 75 76 _qsort(data, n, e_size, cmp, tmp, pivot);77 78 if (e_size > EBUFSIZE) {79 free(tmp);80 free(pivot);81 }82 91 } 83 92 84 93 /** Quicksort 85 94 * 86 * Apply generic quicksort algorithm on supplied data, using pre-allocated buffers. 87 * 88 * @param data Pointer to data to be sorted. 89 * @param n Number of elements to be sorted. 90 * @param e_size Size of one element. 91 * @param cmp Comparator function. 92 * @param tmp Pointer to scratch memory buffer e_size bytes long. 93 * @param pivot Pointer to scratch memory buffer e_size bytes long. 94 * 95 */ 96 void _qsort(void * data, size_t n, size_t e_size, int (* cmp) (void * a, void * b), void *tmp, void *pivot) 97 { 98 if (n > 4) { 99 unsigned int i = 0, j = n - 1; 100 101 memcpy(pivot, data, e_size); 102 103 while (1) { 104 while ((cmp(data + i * e_size, pivot) < 0) && (i < n)) 95 * Apply generic quicksort algorithm on supplied data, 96 * using pre-allocated buffers. 97 * 98 * @param data Pointer to data to be sorted. 99 * @param cnt Number of elements to be sorted. 100 * @param elem_size Size of one element. 101 * @param cmp Comparator function. 102 * @param arg 3rd argument passed to cmp. 103 * @param slot Pointer to scratch memory buffer 104 * elem_size bytes long. 105 * @param pivot Pointer to scratch memory buffer 106 * elem_size bytes long. 107 * 108 */ 109 static void _qsort(void *data, size_t cnt, size_t elem_size, sort_cmp_t cmp, 110 void *arg, void *slot, void *pivot) 111 { 112 if (cnt > 4) { 113 size_t i = 0; 114 size_t j = cnt - 1; 115 116 memcpy(pivot, data, elem_size); 117 118 while (true) { 119 while ((cmp(INDEX(data, i, elem_size), pivot, arg) < 0) && (i < cnt)) 105 120 i++; 106 while ((cmp(data + j * e_size, pivot) >= 0) && (j > 0)) 121 122 while ((cmp(INDEX(data, j, elem_size), pivot, arg) >= 0) && (j > 0)) 107 123 j--; 108 124 109 125 if (i < j) { 110 memcpy(tmp, data + i * e_size, e_size); 111 memcpy(data + i * e_size, data + j * e_size, e_size); 112 memcpy(data + j * e_size, tmp, e_size); 113 } else { 126 memcpy(slot, INDEX(data, i, elem_size), elem_size); 127 memcpy(INDEX(data, i, elem_size), INDEX(data, j, elem_size), 128 elem_size); 129 memcpy(INDEX(data, j, elem_size), slot, elem_size); 130 } else 114 131 break; 115 }116 132 } 117 118 _qsort(data, j + 1, e_size, cmp, tmp, pivot); 119 _qsort(data + (j + 1) * e_size, n - j - 1, e_size, cmp, tmp, pivot); 133 134 _qsort(data, j + 1, elem_size, cmp, arg, slot, pivot); 135 _qsort(INDEX(data, j + 1, elem_size), cnt - j - 1, elem_size, 136 cmp, arg, slot, pivot); 137 } else 138 _gsort(data, cnt, elem_size, cmp, arg, slot); 139 } 140 141 /** Gnome sort wrapper 142 * 143 * This is only a wrapper that takes care of memory 144 * allocations for storing the slot element for generic 145 * gnome sort algorithm. 146 * 147 * This function can sleep. 148 * 149 * @param data Pointer to data to be sorted. 150 * @param cnt Number of elements to be sorted. 151 * @param elem_size Size of one element. 152 * @param cmp Comparator function. 153 * @param arg 3rd argument passed to cmp. 154 * 155 * @return True if sorting succeeded. 156 * 157 */ 158 bool gsort(void *data, size_t cnt, size_t elem_size, sort_cmp_t cmp, void *arg) 159 { 160 uint8_t ibuf_slot[IBUF_SIZE]; 161 void *slot; 162 163 if (elem_size > IBUF_SIZE) { 164 slot = (void *) malloc(elem_size, 0); 165 if (!slot) 166 return false; 167 } else 168 slot = (void *) ibuf_slot; 169 170 _gsort(data, cnt, elem_size, cmp, arg, slot); 171 172 if (elem_size > IBUF_SIZE) 173 free(slot); 174 175 return true; 176 } 177 178 /** Quicksort wrapper 179 * 180 * This is only a wrapper that takes care of memory 181 * allocations for storing the pivot and temporary elements 182 * for generic quicksort algorithm. 183 * 184 * This function can sleep. 185 * 186 * @param data Pointer to data to be sorted. 187 * @param cnt Number of elements to be sorted. 188 * @param elem_size Size of one element. 189 * @param cmp Comparator function. 190 * @param arg 3rd argument passed to cmp. 191 * 192 * @return True if sorting succeeded. 193 * 194 */ 195 bool qsort(void *data, size_t cnt, size_t elem_size, sort_cmp_t cmp, void *arg) 196 { 197 uint8_t ibuf_slot[IBUF_SIZE]; 198 uint8_t ibuf_pivot[IBUF_SIZE]; 199 void *slot; 200 void *pivot; 201 202 if (elem_size > IBUF_SIZE) { 203 slot = (void *) malloc(elem_size, 0); 204 if (!slot) 205 return false; 206 207 pivot = (void *) malloc(elem_size, 0); 208 if (!pivot) { 209 free(slot); 210 return false; 211 } 120 212 } else { 121 _bubblesort(data, n, e_size, cmp, tmp); 213 slot = (void *) ibuf_slot; 214 pivot = (void *) ibuf_pivot; 122 215 } 123 } 124 125 /** Bubblesort wrapper 126 * 127 * This is only a wrapper that takes care of memory allocation for storing 128 * the slot element for generic bubblesort algorithm. 129 * 130 * @param data Pointer to data to be sorted. 131 * @param n Number of elements to be sorted. 132 * @param e_size Size of one element. 133 * @param cmp Comparator function. 134 * 135 */ 136 void bubblesort(void * data, size_t n, size_t e_size, int (* cmp) (void * a, void * b)) 137 { 138 uint8_t buf_slot[EBUFSIZE]; 139 void * slot = buf_slot; 140 141 if (e_size > EBUFSIZE) { 142 slot = (void *) malloc(e_size, 0); 143 } 144 145 _bubblesort(data, n, e_size, cmp, slot); 146 147 if (e_size > EBUFSIZE) { 216 217 _qsort(data, cnt, elem_size, cmp, arg, slot, pivot); 218 219 if (elem_size > IBUF_SIZE) { 220 free(pivot); 148 221 free(slot); 149 222 } 150 } 151 152 /** Bubblesort 153 * 154 * Apply generic bubblesort algorithm on supplied data, using pre-allocated buffer. 155 * 156 * @param data Pointer to data to be sorted. 157 * @param n Number of elements to be sorted. 158 * @param e_size Size of one element. 159 * @param cmp Comparator function. 160 * @param slot Pointer to scratch memory buffer e_size bytes long. 161 * 162 */ 163 void _bubblesort(void * data, size_t n, size_t e_size, int (* cmp) (void * a, void * b), void *slot) 164 { 165 bool done = false; 166 void * p; 167 168 while (!done) { 169 done = true; 170 for (p = data; p < data + e_size * (n - 1); p = p + e_size) { 171 if (cmp(p, p + e_size) == 1) { 172 memcpy(slot, p, e_size); 173 memcpy(p, p + e_size, e_size); 174 memcpy(p + e_size, slot, e_size); 175 done = false; 176 } 177 } 178 } 179 180 } 181 182 /* 183 * Comparator returns 1 if a > b, 0 if a == b, -1 if a < b 184 */ 185 int int_cmp(void * a, void * b) 186 { 187 return (* (int *) a > * (int*)b) ? 1 : (*(int *)a < * (int *)b) ? -1 : 0; 188 } 189 190 int uint8_t_cmp(void * a, void * b) 191 { 192 return (* (uint8_t *) a > * (uint8_t *)b) ? 1 : (*(uint8_t *)a < * (uint8_t *)b) ? -1 : 0; 193 } 194 195 int uint16_t_cmp(void * a, void * b) 196 { 197 return (* (uint16_t *) a > * (uint16_t *)b) ? 1 : (*(uint16_t *)a < * (uint16_t *)b) ? -1 : 0; 198 } 199 200 int uint32_t_cmp(void * a, void * b) 201 { 202 return (* (uint32_t *) a > * (uint32_t *)b) ? 1 : (*(uint32_t *)a < * (uint32_t *)b) ? -1 : 0; 223 224 return true; 203 225 } 204 226
Note:
See TracChangeset
for help on using the changeset viewer.