Mercurial > repos > lsong10 > psiclass
comparison PsiCLASS-1.0.2/samtools-0.1.19/ksort.h @ 0:903fc43d6227 draft default tip
Uploaded
author | lsong10 |
---|---|
date | Fri, 26 Mar 2021 16:52:45 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:903fc43d6227 |
---|---|
1 /* The MIT License | |
2 | |
3 Copyright (c) 2008 Genome Research Ltd (GRL). | |
4 | |
5 Permission is hereby granted, free of charge, to any person obtaining | |
6 a copy of this software and associated documentation files (the | |
7 "Software"), to deal in the Software without restriction, including | |
8 without limitation the rights to use, copy, modify, merge, publish, | |
9 distribute, sublicense, and/or sell copies of the Software, and to | |
10 permit persons to whom the Software is furnished to do so, subject to | |
11 the following conditions: | |
12 | |
13 The above copyright notice and this permission notice shall be | |
14 included in all copies or substantial portions of the Software. | |
15 | |
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
17 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
18 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |
19 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | |
20 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | |
21 ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |
22 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
23 SOFTWARE. | |
24 */ | |
25 | |
26 /* Contact: Heng Li <lh3@sanger.ac.uk> */ | |
27 | |
28 /* | |
29 2012-12-11 (0.1.4): | |
30 | |
31 * Defined __ks_insertsort_##name as static to compile with C99. | |
32 | |
33 2008-11-16 (0.1.4): | |
34 | |
35 * Fixed a bug in introsort() that happens in rare cases. | |
36 | |
37 2008-11-05 (0.1.3): | |
38 | |
39 * Fixed a bug in introsort() for complex comparisons. | |
40 | |
41 * Fixed a bug in mergesort(). The previous version is not stable. | |
42 | |
43 2008-09-15 (0.1.2): | |
44 | |
45 * Accelerated introsort. On my Mac (not on another Linux machine), | |
46 my implementation is as fast as std::sort on random input. | |
47 | |
48 * Added combsort and in introsort, switch to combsort if the | |
49 recursion is too deep. | |
50 | |
51 2008-09-13 (0.1.1): | |
52 | |
53 * Added k-small algorithm | |
54 | |
55 2008-09-05 (0.1.0): | |
56 | |
57 * Initial version | |
58 | |
59 */ | |
60 | |
61 #ifndef AC_KSORT_H | |
62 #define AC_KSORT_H | |
63 | |
64 #include <stdlib.h> | |
65 #include <string.h> | |
66 | |
67 typedef struct { | |
68 void *left, *right; | |
69 int depth; | |
70 } ks_isort_stack_t; | |
71 | |
72 #define KSORT_SWAP(type_t, a, b) { register type_t t=(a); (a)=(b); (b)=t; } | |
73 | |
74 #define KSORT_INIT(name, type_t, __sort_lt) \ | |
75 void ks_mergesort_##name(size_t n, type_t array[], type_t temp[]) \ | |
76 { \ | |
77 type_t *a2[2], *a, *b; \ | |
78 int curr, shift; \ | |
79 \ | |
80 a2[0] = array; \ | |
81 a2[1] = temp? temp : (type_t*)malloc(sizeof(type_t) * n); \ | |
82 for (curr = 0, shift = 0; (1ul<<shift) < n; ++shift) { \ | |
83 a = a2[curr]; b = a2[1-curr]; \ | |
84 if (shift == 0) { \ | |
85 type_t *p = b, *i, *eb = a + n; \ | |
86 for (i = a; i < eb; i += 2) { \ | |
87 if (i == eb - 1) *p++ = *i; \ | |
88 else { \ | |
89 if (__sort_lt(*(i+1), *i)) { \ | |
90 *p++ = *(i+1); *p++ = *i; \ | |
91 } else { \ | |
92 *p++ = *i; *p++ = *(i+1); \ | |
93 } \ | |
94 } \ | |
95 } \ | |
96 } else { \ | |
97 size_t i, step = 1ul<<shift; \ | |
98 for (i = 0; i < n; i += step<<1) { \ | |
99 type_t *p, *j, *k, *ea, *eb; \ | |
100 if (n < i + step) { \ | |
101 ea = a + n; eb = a; \ | |
102 } else { \ | |
103 ea = a + i + step; \ | |
104 eb = a + (n < i + (step<<1)? n : i + (step<<1)); \ | |
105 } \ | |
106 j = a + i; k = a + i + step; p = b + i; \ | |
107 while (j < ea && k < eb) { \ | |
108 if (__sort_lt(*k, *j)) *p++ = *k++; \ | |
109 else *p++ = *j++; \ | |
110 } \ | |
111 while (j < ea) *p++ = *j++; \ | |
112 while (k < eb) *p++ = *k++; \ | |
113 } \ | |
114 } \ | |
115 curr = 1 - curr; \ | |
116 } \ | |
117 if (curr == 1) { \ | |
118 type_t *p = a2[0], *i = a2[1], *eb = array + n; \ | |
119 for (; p < eb; ++i) *p++ = *i; \ | |
120 } \ | |
121 if (temp == 0) free(a2[1]); \ | |
122 } \ | |
123 void ks_heapadjust_##name(size_t i, size_t n, type_t l[]) \ | |
124 { \ | |
125 size_t k = i; \ | |
126 type_t tmp = l[i]; \ | |
127 while ((k = (k << 1) + 1) < n) { \ | |
128 if (k != n - 1 && __sort_lt(l[k], l[k+1])) ++k; \ | |
129 if (__sort_lt(l[k], tmp)) break; \ | |
130 l[i] = l[k]; i = k; \ | |
131 } \ | |
132 l[i] = tmp; \ | |
133 } \ | |
134 void ks_heapmake_##name(size_t lsize, type_t l[]) \ | |
135 { \ | |
136 size_t i; \ | |
137 for (i = (lsize >> 1) - 1; i != (size_t)(-1); --i) \ | |
138 ks_heapadjust_##name(i, lsize, l); \ | |
139 } \ | |
140 void ks_heapsort_##name(size_t lsize, type_t l[]) \ | |
141 { \ | |
142 size_t i; \ | |
143 for (i = lsize - 1; i > 0; --i) { \ | |
144 type_t tmp; \ | |
145 tmp = *l; *l = l[i]; l[i] = tmp; ks_heapadjust_##name(0, i, l); \ | |
146 } \ | |
147 } \ | |
148 static inline void __ks_insertsort_##name(type_t *s, type_t *t) \ | |
149 { \ | |
150 type_t *i, *j, swap_tmp; \ | |
151 for (i = s + 1; i < t; ++i) \ | |
152 for (j = i; j > s && __sort_lt(*j, *(j-1)); --j) { \ | |
153 swap_tmp = *j; *j = *(j-1); *(j-1) = swap_tmp; \ | |
154 } \ | |
155 } \ | |
156 void ks_combsort_##name(size_t n, type_t a[]) \ | |
157 { \ | |
158 const double shrink_factor = 1.2473309501039786540366528676643; \ | |
159 int do_swap; \ | |
160 size_t gap = n; \ | |
161 type_t tmp, *i, *j; \ | |
162 do { \ | |
163 if (gap > 2) { \ | |
164 gap = (size_t)(gap / shrink_factor); \ | |
165 if (gap == 9 || gap == 10) gap = 11; \ | |
166 } \ | |
167 do_swap = 0; \ | |
168 for (i = a; i < a + n - gap; ++i) { \ | |
169 j = i + gap; \ | |
170 if (__sort_lt(*j, *i)) { \ | |
171 tmp = *i; *i = *j; *j = tmp; \ | |
172 do_swap = 1; \ | |
173 } \ | |
174 } \ | |
175 } while (do_swap || gap > 2); \ | |
176 if (gap != 1) __ks_insertsort_##name(a, a + n); \ | |
177 } \ | |
178 void ks_introsort_##name(size_t n, type_t a[]) \ | |
179 { \ | |
180 int d; \ | |
181 ks_isort_stack_t *top, *stack; \ | |
182 type_t rp, swap_tmp; \ | |
183 type_t *s, *t, *i, *j, *k; \ | |
184 \ | |
185 if (n < 1) return; \ | |
186 else if (n == 2) { \ | |
187 if (__sort_lt(a[1], a[0])) { swap_tmp = a[0]; a[0] = a[1]; a[1] = swap_tmp; } \ | |
188 return; \ | |
189 } \ | |
190 for (d = 2; 1ul<<d < n; ++d); \ | |
191 stack = (ks_isort_stack_t*)malloc(sizeof(ks_isort_stack_t) * ((sizeof(size_t)*d)+2)); \ | |
192 top = stack; s = a; t = a + (n-1); d <<= 1; \ | |
193 while (1) { \ | |
194 if (s < t) { \ | |
195 if (--d == 0) { \ | |
196 ks_combsort_##name(t - s + 1, s); \ | |
197 t = s; \ | |
198 continue; \ | |
199 } \ | |
200 i = s; j = t; k = i + ((j-i)>>1) + 1; \ | |
201 if (__sort_lt(*k, *i)) { \ | |
202 if (__sort_lt(*k, *j)) k = j; \ | |
203 } else k = __sort_lt(*j, *i)? i : j; \ | |
204 rp = *k; \ | |
205 if (k != t) { swap_tmp = *k; *k = *t; *t = swap_tmp; } \ | |
206 for (;;) { \ | |
207 do ++i; while (__sort_lt(*i, rp)); \ | |
208 do --j; while (i <= j && __sort_lt(rp, *j)); \ | |
209 if (j <= i) break; \ | |
210 swap_tmp = *i; *i = *j; *j = swap_tmp; \ | |
211 } \ | |
212 swap_tmp = *i; *i = *t; *t = swap_tmp; \ | |
213 if (i-s > t-i) { \ | |
214 if (i-s > 16) { top->left = s; top->right = i-1; top->depth = d; ++top; } \ | |
215 s = t-i > 16? i+1 : t; \ | |
216 } else { \ | |
217 if (t-i > 16) { top->left = i+1; top->right = t; top->depth = d; ++top; } \ | |
218 t = i-s > 16? i-1 : s; \ | |
219 } \ | |
220 } else { \ | |
221 if (top == stack) { \ | |
222 free(stack); \ | |
223 __ks_insertsort_##name(a, a+n); \ | |
224 return; \ | |
225 } else { --top; s = (type_t*)top->left; t = (type_t*)top->right; d = top->depth; } \ | |
226 } \ | |
227 } \ | |
228 } \ | |
229 /* This function is adapted from: http://ndevilla.free.fr/median/ */ \ | |
230 /* 0 <= kk < n */ \ | |
231 type_t ks_ksmall_##name(size_t n, type_t arr[], size_t kk) \ | |
232 { \ | |
233 type_t *low, *high, *k, *ll, *hh, *mid; \ | |
234 low = arr; high = arr + n - 1; k = arr + kk; \ | |
235 for (;;) { \ | |
236 if (high <= low) return *k; \ | |
237 if (high == low + 1) { \ | |
238 if (__sort_lt(*high, *low)) KSORT_SWAP(type_t, *low, *high); \ | |
239 return *k; \ | |
240 } \ | |
241 mid = low + (high - low) / 2; \ | |
242 if (__sort_lt(*high, *mid)) KSORT_SWAP(type_t, *mid, *high); \ | |
243 if (__sort_lt(*high, *low)) KSORT_SWAP(type_t, *low, *high); \ | |
244 if (__sort_lt(*low, *mid)) KSORT_SWAP(type_t, *mid, *low); \ | |
245 KSORT_SWAP(type_t, *mid, *(low+1)); \ | |
246 ll = low + 1; hh = high; \ | |
247 for (;;) { \ | |
248 do ++ll; while (__sort_lt(*ll, *low)); \ | |
249 do --hh; while (__sort_lt(*low, *hh)); \ | |
250 if (hh < ll) break; \ | |
251 KSORT_SWAP(type_t, *ll, *hh); \ | |
252 } \ | |
253 KSORT_SWAP(type_t, *low, *hh); \ | |
254 if (hh <= k) low = ll; \ | |
255 if (hh >= k) high = hh - 1; \ | |
256 } \ | |
257 } \ | |
258 void ks_shuffle_##name(size_t n, type_t a[]) \ | |
259 { \ | |
260 int i, j; \ | |
261 for (i = n; i > 1; --i) { \ | |
262 type_t tmp; \ | |
263 j = (int)(drand48() * i); \ | |
264 tmp = a[j]; a[j] = a[i-1]; a[i-1] = tmp; \ | |
265 } \ | |
266 } | |
267 | |
268 #define ks_mergesort(name, n, a, t) ks_mergesort_##name(n, a, t) | |
269 #define ks_introsort(name, n, a) ks_introsort_##name(n, a) | |
270 #define ks_combsort(name, n, a) ks_combsort_##name(n, a) | |
271 #define ks_heapsort(name, n, a) ks_heapsort_##name(n, a) | |
272 #define ks_heapmake(name, n, a) ks_heapmake_##name(n, a) | |
273 #define ks_heapadjust(name, i, n, a) ks_heapadjust_##name(i, n, a) | |
274 #define ks_ksmall(name, n, a, k) ks_ksmall_##name(n, a, k) | |
275 #define ks_shuffle(name, n, a) ks_shuffle_##name(n, a) | |
276 | |
277 #define ks_lt_generic(a, b) ((a) < (b)) | |
278 #define ks_lt_str(a, b) (strcmp((a), (b)) < 0) | |
279 | |
280 typedef const char *ksstr_t; | |
281 | |
282 #define KSORT_INIT_GENERIC(type_t) KSORT_INIT(type_t, type_t, ks_lt_generic) | |
283 #define KSORT_INIT_STR KSORT_INIT(str, ksstr_t, ks_lt_str) | |
284 | |
285 #endif |