bio-bwa 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. data/.document +5 -0
  2. data/Gemfile +15 -0
  3. data/Gemfile.lock +28 -0
  4. data/LICENSE.txt +35 -0
  5. data/README.rdoc +33 -0
  6. data/Rakefile +56 -0
  7. data/VERSION +1 -0
  8. data/bio-bwa.gemspec +152 -0
  9. data/doc/Bio.html +93 -0
  10. data/doc/Bio/BWA.html +2884 -0
  11. data/doc/Bio/BWA/Library.html +229 -0
  12. data/doc/_index.html +119 -0
  13. data/doc/class_list.html +36 -0
  14. data/doc/css/common.css +1 -0
  15. data/doc/css/full_list.css +53 -0
  16. data/doc/css/style.css +310 -0
  17. data/doc/file.LICENSE.html +88 -0
  18. data/doc/file.README.html +119 -0
  19. data/doc/file_list.html +41 -0
  20. data/doc/frames.html +13 -0
  21. data/doc/index.html +119 -0
  22. data/doc/js/app.js +203 -0
  23. data/doc/js/full_list.js +149 -0
  24. data/doc/js/jquery.js +154 -0
  25. data/doc/method_list.html +171 -0
  26. data/doc/top-level-namespace.html +88 -0
  27. data/ext/COPYING +674 -0
  28. data/ext/ChangeLog +3864 -0
  29. data/ext/NEWS +555 -0
  30. data/ext/README +29 -0
  31. data/ext/bamlite.c +155 -0
  32. data/ext/bamlite.h +94 -0
  33. data/ext/bntseq.c +303 -0
  34. data/ext/bntseq.h +80 -0
  35. data/ext/bwa.1 +562 -0
  36. data/ext/bwape.c +807 -0
  37. data/ext/bwase.c +686 -0
  38. data/ext/bwase.h +27 -0
  39. data/ext/bwaseqio.c +222 -0
  40. data/ext/bwt.c +250 -0
  41. data/ext/bwt.h +105 -0
  42. data/ext/bwt_gen/Makefile +23 -0
  43. data/ext/bwt_gen/QSufSort.c +496 -0
  44. data/ext/bwt_gen/QSufSort.h +40 -0
  45. data/ext/bwt_gen/bwt_gen.c +1547 -0
  46. data/ext/bwt_gen/bwt_gen.h +105 -0
  47. data/ext/bwt_lite.c +94 -0
  48. data/ext/bwt_lite.h +29 -0
  49. data/ext/bwtaln.c +345 -0
  50. data/ext/bwtaln.h +150 -0
  51. data/ext/bwtgap.c +264 -0
  52. data/ext/bwtgap.h +38 -0
  53. data/ext/bwtindex.c +186 -0
  54. data/ext/bwtio.c +77 -0
  55. data/ext/bwtmisc.c +269 -0
  56. data/ext/bwtsw2.h +51 -0
  57. data/ext/bwtsw2_aux.c +650 -0
  58. data/ext/bwtsw2_chain.c +107 -0
  59. data/ext/bwtsw2_core.c +594 -0
  60. data/ext/bwtsw2_main.c +100 -0
  61. data/ext/cs2nt.c +191 -0
  62. data/ext/is.c +218 -0
  63. data/ext/khash.h +506 -0
  64. data/ext/kseq.h +208 -0
  65. data/ext/ksort.h +269 -0
  66. data/ext/kstring.c +35 -0
  67. data/ext/kstring.h +46 -0
  68. data/ext/kvec.h +90 -0
  69. data/ext/main.c +63 -0
  70. data/ext/main.h +29 -0
  71. data/ext/mkrf_conf.rb +49 -0
  72. data/ext/qualfa2fq.pl +27 -0
  73. data/ext/simple_dp.c +162 -0
  74. data/ext/simpletest.c +23 -0
  75. data/ext/solid2fastq.pl +111 -0
  76. data/ext/stdaln.c +1072 -0
  77. data/ext/stdaln.h +162 -0
  78. data/ext/utils.c +82 -0
  79. data/ext/utils.h +54 -0
  80. data/lib/bio-bwa.rb +7 -0
  81. data/lib/bio/bwa.rb +312 -0
  82. data/lib/bio/bwa/library.rb +42 -0
  83. data/test/data/testdata.fa +602 -0
  84. data/test/data/testdata.long.fa +175 -0
  85. data/test/data/testdata.short.fa +2 -0
  86. data/test/helper.rb +18 -0
  87. data/test/test_bio-bwa_basic.rb +62 -0
  88. data/test/test_bio-bwa_make_index.rb +42 -0
  89. data/test/test_bio-bwa_run_aln.rb +49 -0
  90. data/test/test_bio-bwa_sam_conversion.rb +49 -0
  91. metadata +218 -0
data/ext/kseq.h ADDED
@@ -0,0 +1,208 @@
1
+ /* The MIT License
2
+
3
+ Copyright (c) 2008, by Heng Li <lh3@sanger.ac.uk>
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
+ #ifndef AC_KSEQ_H
27
+ #define AC_KSEQ_H
28
+
29
+ #include <ctype.h>
30
+ #include <string.h>
31
+ #include <stdlib.h>
32
+
33
+ #define __KS_TYPE(type_t) \
34
+ typedef struct __kstream_t { \
35
+ char *buf; \
36
+ int begin, end, is_eof; \
37
+ type_t f; \
38
+ } kstream_t;
39
+
40
+ #define ks_eof(ks) ((ks)->is_eof && (ks)->begin >= (ks)->end)
41
+ #define ks_rewind(ks) ((ks)->is_eof = (ks)->begin = (ks)->end = 0)
42
+
43
+ #define __KS_BASIC(type_t, __bufsize) \
44
+ static inline kstream_t *ks_init(type_t f) \
45
+ { \
46
+ kstream_t *ks = (kstream_t*)calloc(1, sizeof(kstream_t)); \
47
+ ks->f = f; \
48
+ ks->buf = (char*)malloc(__bufsize); \
49
+ return ks; \
50
+ } \
51
+ static inline void ks_destroy(kstream_t *ks) \
52
+ { \
53
+ if (ks) { \
54
+ free(ks->buf); \
55
+ free(ks); \
56
+ } \
57
+ }
58
+
59
+ #define __KS_GETC(__read, __bufsize) \
60
+ static inline int ks_getc(kstream_t *ks) \
61
+ { \
62
+ if (ks->is_eof && ks->begin >= ks->end) return -1; \
63
+ if (ks->begin >= ks->end) { \
64
+ ks->begin = 0; \
65
+ ks->end = __read(ks->f, ks->buf, __bufsize); \
66
+ if (ks->end < __bufsize) ks->is_eof = 1; \
67
+ if (ks->end == 0) return -1; \
68
+ } \
69
+ return (int)ks->buf[ks->begin++]; \
70
+ }
71
+
72
+ #ifndef KSTRING_T
73
+ #define KSTRING_T kstring_t
74
+ typedef struct __kstring_t {
75
+ size_t l, m;
76
+ char *s;
77
+ } kstring_t;
78
+ #endif
79
+
80
+ #ifndef kroundup32
81
+ #define kroundup32(x) (--(x), (x)|=(x)>>1, (x)|=(x)>>2, (x)|=(x)>>4, (x)|=(x)>>8, (x)|=(x)>>16, ++(x))
82
+ #endif
83
+
84
+ #define __KS_GETUNTIL(__read, __bufsize) \
85
+ static int ks_getuntil(kstream_t *ks, int delimiter, kstring_t *str, int *dret) \
86
+ { \
87
+ if (dret) *dret = 0; \
88
+ str->l = 0; \
89
+ if (ks->begin >= ks->end && ks->is_eof) return -1; \
90
+ for (;;) { \
91
+ int i; \
92
+ if (ks->begin >= ks->end) { \
93
+ if (!ks->is_eof) { \
94
+ ks->begin = 0; \
95
+ ks->end = __read(ks->f, ks->buf, __bufsize); \
96
+ if (ks->end < __bufsize) ks->is_eof = 1; \
97
+ if (ks->end == 0) break; \
98
+ } else break; \
99
+ } \
100
+ if (delimiter) { \
101
+ for (i = ks->begin; i < ks->end; ++i) \
102
+ if (ks->buf[i] == delimiter) break; \
103
+ } else { \
104
+ for (i = ks->begin; i < ks->end; ++i) \
105
+ if (isspace(ks->buf[i])) break; \
106
+ } \
107
+ if (str->m - str->l < i - ks->begin + 1) { \
108
+ str->m = str->l + (i - ks->begin) + 1; \
109
+ kroundup32(str->m); \
110
+ str->s = (char*)realloc(str->s, str->m); \
111
+ } \
112
+ memcpy(str->s + str->l, ks->buf + ks->begin, i - ks->begin); \
113
+ str->l = str->l + (i - ks->begin); \
114
+ ks->begin = i + 1; \
115
+ if (i < ks->end) { \
116
+ if (dret) *dret = ks->buf[i]; \
117
+ break; \
118
+ } \
119
+ } \
120
+ str->s[str->l] = '\0'; \
121
+ return str->l; \
122
+ }
123
+
124
+ #define KSTREAM_INIT(type_t, __read, __bufsize) \
125
+ __KS_TYPE(type_t) \
126
+ __KS_BASIC(type_t, __bufsize) \
127
+ __KS_GETC(__read, __bufsize) \
128
+ __KS_GETUNTIL(__read, __bufsize)
129
+
130
+ #define __KSEQ_BASIC(type_t) \
131
+ static inline kseq_t *kseq_init(type_t fd) \
132
+ { \
133
+ kseq_t *s = (kseq_t*)calloc(1, sizeof(kseq_t)); \
134
+ s->f = ks_init(fd); \
135
+ return s; \
136
+ } \
137
+ static inline void kseq_rewind(kseq_t *ks) \
138
+ { \
139
+ ks->last_char = 0; \
140
+ ks->f->is_eof = ks->f->begin = ks->f->end = 0; \
141
+ } \
142
+ static inline void kseq_destroy(kseq_t *ks) \
143
+ { \
144
+ if (!ks) return; \
145
+ free(ks->name.s); free(ks->comment.s); free(ks->seq.s); free(ks->qual.s); \
146
+ ks_destroy(ks->f); \
147
+ free(ks); \
148
+ }
149
+
150
+ /* Return value:
151
+ >=0 length of the sequence (normal)
152
+ -1 end-of-file
153
+ -2 truncated quality string
154
+ */
155
+ #define __KSEQ_READ \
156
+ static int kseq_read(kseq_t *seq) \
157
+ { \
158
+ int c; \
159
+ kstream_t *ks = seq->f; \
160
+ if (seq->last_char == 0) { /* then jump to the next header line */ \
161
+ while ((c = ks_getc(ks)) != -1 && c != '>' && c != '@'); \
162
+ if (c == -1) return -1; /* end of file */ \
163
+ seq->last_char = c; \
164
+ } /* the first header char has been read */ \
165
+ seq->comment.l = seq->seq.l = seq->qual.l = 0; \
166
+ if (ks_getuntil(ks, 0, &seq->name, &c) < 0) return -1; \
167
+ if (c != '\n') ks_getuntil(ks, '\n', &seq->comment, 0); \
168
+ while ((c = ks_getc(ks)) != -1 && c != '>' && c != '+' && c != '@') { \
169
+ if (isgraph(c)) { /* printable non-space character */ \
170
+ if (seq->seq.l + 1 >= seq->seq.m) { /* double the memory */ \
171
+ seq->seq.m = seq->seq.l + 2; \
172
+ kroundup32(seq->seq.m); /* rounded to next closest 2^k */ \
173
+ seq->seq.s = (char*)realloc(seq->seq.s, seq->seq.m); \
174
+ } \
175
+ seq->seq.s[seq->seq.l++] = (char)c; \
176
+ } \
177
+ } \
178
+ if (c == '>' || c == '@') seq->last_char = c; /* the first header char has been read */ \
179
+ seq->seq.s[seq->seq.l] = 0; /* null terminated string */ \
180
+ if (c != '+') return seq->seq.l; /* FASTA */ \
181
+ if (seq->qual.m < seq->seq.m) { /* allocate enough memory */ \
182
+ seq->qual.m = seq->seq.m; \
183
+ seq->qual.s = (char*)realloc(seq->qual.s, seq->qual.m); \
184
+ } \
185
+ while ((c = ks_getc(ks)) != -1 && c != '\n'); /* skip the rest of '+' line */ \
186
+ if (c == -1) return -2; /* we should not stop here */ \
187
+ while ((c = ks_getc(ks)) != -1 && seq->qual.l < seq->seq.l) \
188
+ if (c >= 33 && c <= 127) seq->qual.s[seq->qual.l++] = (unsigned char)c; \
189
+ seq->qual.s[seq->qual.l] = 0; /* null terminated string */ \
190
+ seq->last_char = 0; /* we have not come to the next header line */ \
191
+ if (seq->seq.l != seq->qual.l) return -2; /* qual string is shorter than seq string */ \
192
+ return seq->seq.l; \
193
+ }
194
+
195
+ #define __KSEQ_TYPE(type_t) \
196
+ typedef struct { \
197
+ kstring_t name, comment, seq, qual; \
198
+ int last_char; \
199
+ kstream_t *f; \
200
+ } kseq_t;
201
+
202
+ #define KSEQ_INIT(type_t, __read) \
203
+ KSTREAM_INIT(type_t, __read, 4096) \
204
+ __KSEQ_TYPE(type_t) \
205
+ __KSEQ_BASIC(type_t) \
206
+ __KSEQ_READ
207
+
208
+ #endif
data/ext/ksort.h ADDED
@@ -0,0 +1,269 @@
1
+ /* The MIT License
2
+
3
+ Copyright (c) 2008, by Attractive Chaos <attractivechaos@aol.co.uk>
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
+ /*
27
+ 2008-11-16 (0.1.4):
28
+
29
+ * Fixed a bug in introsort() that happens in rare cases.
30
+
31
+ 2008-11-05 (0.1.3):
32
+
33
+ * Fixed a bug in introsort() for complex comparisons.
34
+
35
+ * Fixed a bug in mergesort(). The previous version is not stable.
36
+
37
+ 2008-09-15 (0.1.2):
38
+
39
+ * Accelerated introsort. On my Mac (not on another Linux machine),
40
+ my implementation is as fast as std::sort on random input.
41
+
42
+ * Added combsort and in introsort, switch to combsort if the
43
+ recursion is too deep.
44
+
45
+ 2008-09-13 (0.1.1):
46
+
47
+ * Added k-small algorithm
48
+
49
+ 2008-09-05 (0.1.0):
50
+
51
+ * Initial version
52
+
53
+ */
54
+
55
+ #ifndef AC_KSORT_H
56
+ #define AC_KSORT_H
57
+
58
+ #include <stdlib.h>
59
+ #include <string.h>
60
+
61
+ typedef struct {
62
+ void *left, *right;
63
+ int depth;
64
+ } ks_isort_stack_t;
65
+
66
+ #define KSORT_SWAP(type_t, a, b) { register type_t t=(a); (a)=(b); (b)=t; }
67
+
68
+ #define KSORT_INIT(name, type_t, __sort_lt) \
69
+ void ks_mergesort_##name(size_t n, type_t array[], type_t temp[]) \
70
+ { \
71
+ type_t *a2[2], *a, *b; \
72
+ int curr, shift; \
73
+ \
74
+ a2[0] = array; \
75
+ a2[1] = temp? temp : (type_t*)malloc(sizeof(type_t) * n); \
76
+ for (curr = 0, shift = 0; (1ul<<shift) < n; ++shift) { \
77
+ a = a2[curr]; b = a2[1-curr]; \
78
+ if (shift == 0) { \
79
+ type_t *p = b, *i, *eb = a + n; \
80
+ for (i = a; i < eb; i += 2) { \
81
+ if (i == eb - 1) *p++ = *i; \
82
+ else { \
83
+ if (__sort_lt(*(i+1), *i)) { \
84
+ *p++ = *(i+1); *p++ = *i; \
85
+ } else { \
86
+ *p++ = *i; *p++ = *(i+1); \
87
+ } \
88
+ } \
89
+ } \
90
+ } else { \
91
+ size_t i, step = 1ul<<shift; \
92
+ for (i = 0; i < n; i += step<<1) { \
93
+ type_t *p, *j, *k, *ea, *eb; \
94
+ if (n < i + step) { \
95
+ ea = a + n; eb = a; \
96
+ } else { \
97
+ ea = a + i + step; \
98
+ eb = a + (n < i + (step<<1)? n : i + (step<<1)); \
99
+ } \
100
+ j = a + i; k = a + i + step; p = b + i; \
101
+ while (j < ea && k < eb) { \
102
+ if (__sort_lt(*k, *j)) *p++ = *k++; \
103
+ else *p++ = *j++; \
104
+ } \
105
+ while (j < ea) *p++ = *j++; \
106
+ while (k < eb) *p++ = *k++; \
107
+ } \
108
+ } \
109
+ curr = 1 - curr; \
110
+ } \
111
+ if (curr == 1) { \
112
+ type_t *p = a2[0], *i = a2[1], *eb = array + n; \
113
+ for (; p < eb; ++i) *p++ = *i; \
114
+ } \
115
+ if (temp == 0) free(a2[1]); \
116
+ } \
117
+ void ks_heapadjust_##name(size_t i, size_t n, type_t l[]) \
118
+ { \
119
+ size_t k = i; \
120
+ type_t tmp = l[i]; \
121
+ while ((k = (k << 1) + 1) < n) { \
122
+ if (k != n - 1 && __sort_lt(l[k], l[k+1])) ++k; \
123
+ if (__sort_lt(l[k], tmp)) break; \
124
+ l[i] = l[k]; i = k; \
125
+ } \
126
+ l[i] = tmp; \
127
+ } \
128
+ void ks_heapmake_##name(size_t lsize, type_t l[]) \
129
+ { \
130
+ size_t i; \
131
+ for (i = (lsize >> 1) - 1; i != (size_t)(-1); --i) \
132
+ ks_heapadjust_##name(i, lsize, l); \
133
+ } \
134
+ void ks_heapsort_##name(size_t lsize, type_t l[]) \
135
+ { \
136
+ size_t i; \
137
+ for (i = lsize - 1; i > 0; --i) { \
138
+ type_t tmp; \
139
+ tmp = *l; *l = l[i]; l[i] = tmp; ks_heapadjust_##name(0, i, l); \
140
+ } \
141
+ } \
142
+ inline void __ks_insertsort_##name(type_t *s, type_t *t) \
143
+ { \
144
+ type_t *i, *j, swap_tmp; \
145
+ for (i = s + 1; i < t; ++i) \
146
+ for (j = i; j > s && __sort_lt(*j, *(j-1)); --j) { \
147
+ swap_tmp = *j; *j = *(j-1); *(j-1) = swap_tmp; \
148
+ } \
149
+ } \
150
+ void ks_combsort_##name(size_t n, type_t a[]) \
151
+ { \
152
+ const double shrink_factor = 1.2473309501039786540366528676643; \
153
+ int do_swap; \
154
+ size_t gap = n; \
155
+ type_t tmp, *i, *j; \
156
+ do { \
157
+ if (gap > 2) { \
158
+ gap = (size_t)(gap / shrink_factor); \
159
+ if (gap == 9 || gap == 10) gap = 11; \
160
+ } \
161
+ do_swap = 0; \
162
+ for (i = a; i < a + n - gap; ++i) { \
163
+ j = i + gap; \
164
+ if (__sort_lt(*j, *i)) { \
165
+ tmp = *i; *i = *j; *j = tmp; \
166
+ do_swap = 1; \
167
+ } \
168
+ } \
169
+ } while (do_swap || gap > 2); \
170
+ if (gap != 1) __ks_insertsort_##name(a, a + n); \
171
+ } \
172
+ void ks_introsort_##name(size_t n, type_t a[]) \
173
+ { \
174
+ int d; \
175
+ ks_isort_stack_t *top, *stack; \
176
+ type_t rp, swap_tmp; \
177
+ type_t *s, *t, *i, *j, *k; \
178
+ \
179
+ if (n < 1) return; \
180
+ else if (n == 2) { \
181
+ if (__sort_lt(a[1], a[0])) { swap_tmp = a[0]; a[0] = a[1]; a[1] = swap_tmp; } \
182
+ return; \
183
+ } \
184
+ for (d = 2; 1ul<<d < n; ++d); \
185
+ stack = (ks_isort_stack_t*)malloc(sizeof(ks_isort_stack_t) * ((sizeof(size_t)*d)+2)); \
186
+ top = stack; s = a; t = a + (n-1); d <<= 1; \
187
+ while (1) { \
188
+ if (s < t) { \
189
+ if (--d == 0) { \
190
+ ks_combsort_##name(t - s + 1, s); \
191
+ t = s; \
192
+ continue; \
193
+ } \
194
+ i = s; j = t; k = i + ((j-i)>>1) + 1; \
195
+ if (__sort_lt(*k, *i)) { \
196
+ if (__sort_lt(*k, *j)) k = j; \
197
+ } else k = __sort_lt(*j, *i)? i : j; \
198
+ rp = *k; \
199
+ if (k != t) { swap_tmp = *k; *k = *t; *t = swap_tmp; } \
200
+ for (;;) { \
201
+ do ++i; while (__sort_lt(*i, rp)); \
202
+ do --j; while (i <= j && __sort_lt(rp, *j)); \
203
+ if (j <= i) break; \
204
+ swap_tmp = *i; *i = *j; *j = swap_tmp; \
205
+ } \
206
+ swap_tmp = *i; *i = *t; *t = swap_tmp; \
207
+ if (i-s > t-i) { \
208
+ if (i-s > 16) { top->left = s; top->right = i-1; top->depth = d; ++top; } \
209
+ s = t-i > 16? i+1 : t; \
210
+ } else { \
211
+ if (t-i > 16) { top->left = i+1; top->right = t; top->depth = d; ++top; } \
212
+ t = i-s > 16? i-1 : s; \
213
+ } \
214
+ } else { \
215
+ if (top == stack) { \
216
+ free(stack); \
217
+ __ks_insertsort_##name(a, a+n); \
218
+ return; \
219
+ } else { --top; s = (type_t*)top->left; t = (type_t*)top->right; d = top->depth; } \
220
+ } \
221
+ } \
222
+ } \
223
+ /* This function is adapted from: http://ndevilla.free.fr/median/ */ \
224
+ /* 0 <= kk < n */ \
225
+ type_t ks_ksmall_##name(size_t n, type_t arr[], size_t kk) \
226
+ { \
227
+ type_t *low, *high, *k, *ll, *hh, *mid; \
228
+ low = arr; high = arr + n - 1; k = arr + kk; \
229
+ for (;;) { \
230
+ if (high <= low) return *k; \
231
+ if (high == low + 1) { \
232
+ if (__sort_lt(*high, *low)) KSORT_SWAP(type_t, *low, *high); \
233
+ return *k; \
234
+ } \
235
+ mid = low + (high - low) / 2; \
236
+ if (__sort_lt(*high, *mid)) KSORT_SWAP(type_t, *mid, *high); \
237
+ if (__sort_lt(*high, *low)) KSORT_SWAP(type_t, *low, *high); \
238
+ if (__sort_lt(*low, *mid)) KSORT_SWAP(type_t, *mid, *low); \
239
+ KSORT_SWAP(type_t, *mid, *(low+1)); \
240
+ ll = low + 1; hh = high; \
241
+ for (;;) { \
242
+ do ++ll; while (__sort_lt(*ll, *low)); \
243
+ do --hh; while (__sort_lt(*low, *hh)); \
244
+ if (hh < ll) break; \
245
+ KSORT_SWAP(type_t, *ll, *hh); \
246
+ } \
247
+ KSORT_SWAP(type_t, *low, *hh); \
248
+ if (hh <= k) low = ll; \
249
+ if (hh >= k) high = hh - 1; \
250
+ } \
251
+ }
252
+
253
+ #define ks_mergesort(name, n, a, t) ks_mergesort_##name(n, a, t)
254
+ #define ks_introsort(name, n, a) ks_introsort_##name(n, a)
255
+ #define ks_combsort(name, n, a) ks_combsort_##name(n, a)
256
+ #define ks_heapsort(name, n, a) ks_heapsort_##name(n, a)
257
+ #define ks_heapmake(name, n, a) ks_heapmake_##name(n, a)
258
+ #define ks_heapadjust(name, i, n, a) ks_heapadjust_##name(i, n, a)
259
+ #define ks_ksmall(name, n, a, k) ks_ksmall_##name(n, a, k)
260
+
261
+ #define ks_lt_generic(a, b) ((a) < (b))
262
+ #define ks_lt_str(a, b) (strcmp((a), (b)) < 0)
263
+
264
+ typedef const char *ksstr_t;
265
+
266
+ #define KSORT_INIT_GENERIC(type_t) KSORT_INIT(type_t, type_t, ks_lt_generic)
267
+ #define KSORT_INIT_STR KSORT_INIT(str, ksstr_t, ks_lt_str)
268
+
269
+ #endif