ruby-minigraph 0.0.20.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 (89) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +21 -0
  3. data/README.md +62 -0
  4. data/ext/Rakefile +56 -0
  5. data/ext/cmappy/cmappy.c +7 -0
  6. data/ext/cmappy/cmappy.h +8 -0
  7. data/ext/minigraph/LICENSE.txt +23 -0
  8. data/ext/minigraph/Makefile +66 -0
  9. data/ext/minigraph/NEWS.md +317 -0
  10. data/ext/minigraph/README.md +207 -0
  11. data/ext/minigraph/algo.c +194 -0
  12. data/ext/minigraph/algo.h +33 -0
  13. data/ext/minigraph/asm-call.c +147 -0
  14. data/ext/minigraph/bseq.c +133 -0
  15. data/ext/minigraph/bseq.h +76 -0
  16. data/ext/minigraph/cal_cov.c +139 -0
  17. data/ext/minigraph/doc/example1.png +0 -0
  18. data/ext/minigraph/doc/example2.png +0 -0
  19. data/ext/minigraph/doc/examples.graffle +0 -0
  20. data/ext/minigraph/format.c +241 -0
  21. data/ext/minigraph/galign.c +140 -0
  22. data/ext/minigraph/gchain1.c +532 -0
  23. data/ext/minigraph/gcmisc.c +223 -0
  24. data/ext/minigraph/gfa-aug.c +260 -0
  25. data/ext/minigraph/gfa-base.c +526 -0
  26. data/ext/minigraph/gfa-bbl.c +372 -0
  27. data/ext/minigraph/gfa-ed.c +617 -0
  28. data/ext/minigraph/gfa-io.c +395 -0
  29. data/ext/minigraph/gfa-priv.h +154 -0
  30. data/ext/minigraph/gfa.h +166 -0
  31. data/ext/minigraph/ggen.c +182 -0
  32. data/ext/minigraph/ggen.h +21 -0
  33. data/ext/minigraph/ggsimple.c +570 -0
  34. data/ext/minigraph/gmap.c +211 -0
  35. data/ext/minigraph/index.c +230 -0
  36. data/ext/minigraph/kalloc.c +224 -0
  37. data/ext/minigraph/kalloc.h +82 -0
  38. data/ext/minigraph/kavl.h +414 -0
  39. data/ext/minigraph/kdq.h +134 -0
  40. data/ext/minigraph/ketopt.h +116 -0
  41. data/ext/minigraph/khashl.h +348 -0
  42. data/ext/minigraph/krmq.h +474 -0
  43. data/ext/minigraph/kseq.h +256 -0
  44. data/ext/minigraph/ksort.h +164 -0
  45. data/ext/minigraph/kstring.h +165 -0
  46. data/ext/minigraph/kthread.c +159 -0
  47. data/ext/minigraph/kthread.h +15 -0
  48. data/ext/minigraph/kvec-km.h +105 -0
  49. data/ext/minigraph/kvec.h +110 -0
  50. data/ext/minigraph/lchain.c +441 -0
  51. data/ext/minigraph/main.c +301 -0
  52. data/ext/minigraph/map-algo.c +500 -0
  53. data/ext/minigraph/mgpriv.h +128 -0
  54. data/ext/minigraph/minigraph.1 +359 -0
  55. data/ext/minigraph/minigraph.h +176 -0
  56. data/ext/minigraph/miniwfa.c +834 -0
  57. data/ext/minigraph/miniwfa.h +95 -0
  58. data/ext/minigraph/misc/mgutils.js +1451 -0
  59. data/ext/minigraph/misc.c +12 -0
  60. data/ext/minigraph/options.c +134 -0
  61. data/ext/minigraph/shortk.c +251 -0
  62. data/ext/minigraph/sketch.c +109 -0
  63. data/ext/minigraph/sys.c +147 -0
  64. data/ext/minigraph/sys.h +20 -0
  65. data/ext/minigraph/test/MT-chimp.fa +277 -0
  66. data/ext/minigraph/test/MT-human.fa +239 -0
  67. data/ext/minigraph/test/MT-orangA.fa +276 -0
  68. data/ext/minigraph/test/MT.gfa +19 -0
  69. data/ext/minigraph/tex/Makefile +13 -0
  70. data/ext/minigraph/tex/minigraph.bib +676 -0
  71. data/ext/minigraph/tex/minigraph.tex +986 -0
  72. data/ext/minigraph/tex/plots/CHM13-f1-90.bb.anno.gp +42 -0
  73. data/ext/minigraph/tex/plots/CHM13-f1-90.bb.anno.tbl +13 -0
  74. data/ext/minigraph/tex/plots/CHM13-f1-90.bb.mini-inter-none.win.gp +269 -0
  75. data/ext/minigraph/tex/plots/CHM13-f1-90.bb.mini-inter-none.win.sh +7 -0
  76. data/ext/minigraph/tex/plots/CHM13v1.cen.bed +23 -0
  77. data/ext/minigraph/tex/plots/CHM13v1.size +23 -0
  78. data/ext/minigraph/tex/plots/anno2tbl.js +40 -0
  79. data/ext/minigraph/tex/plots/bedutils.js +367 -0
  80. data/ext/minigraph/tex/plots/chr-plot.js +130 -0
  81. data/ext/minigraph/tex/plots/gen-anno.mak +24 -0
  82. data/ext/minigraph.patch +21 -0
  83. data/lib/minigraph/ffi/constants.rb +230 -0
  84. data/lib/minigraph/ffi/functions.rb +70 -0
  85. data/lib/minigraph/ffi/mappy.rb +8 -0
  86. data/lib/minigraph/ffi.rb +27 -0
  87. data/lib/minigraph/version.rb +5 -0
  88. data/lib/minigraph.rb +72 -0
  89. metadata +159 -0
@@ -0,0 +1,834 @@
1
+ #include <string.h>
2
+ #include <assert.h>
3
+ #include <stdlib.h>
4
+ #include <stdio.h>
5
+ #include "miniwfa.h"
6
+ #include "kalloc.h"
7
+
8
+ /*
9
+ * Default setting
10
+ */
11
+ void mwf_opt_init(mwf_opt_t *opt)
12
+ {
13
+ memset(opt, 0, sizeof(*opt));
14
+ opt->x = 4; // corresponding SW score: m=1, x=3, o1=4, e1=3/2, o2=15, e2=1/2
15
+ opt->o1 = 4, opt->e1 = 2;
16
+ opt->o2 = 15, opt->e2 = 1;
17
+ opt->kmer = 13, opt->max_occ = 2, opt->min_len = 30;
18
+ }
19
+
20
+ /*
21
+ * Structs and simple functions for traceback
22
+ */
23
+ typedef struct {
24
+ int32_t lo, hi;
25
+ uint8_t *x;
26
+ } wf_tb1_t;
27
+
28
+ typedef struct {
29
+ int32_t m, n;
30
+ wf_tb1_t *a;
31
+ } wf_tb_t;
32
+
33
+ static wf_tb1_t *wf_tb_add(void *km, wf_tb_t *tb, int32_t lo, int32_t hi)
34
+ {
35
+ wf_tb1_t *p;
36
+ if (tb->n == tb->m) {
37
+ tb->m += (tb->m>>1) + 4;
38
+ tb->a = Krealloc(km, wf_tb1_t, tb->a, tb->m);
39
+ }
40
+ p = &tb->a[tb->n++];
41
+ p->lo = lo, p->hi = hi;
42
+ p->x = Kcalloc(km, uint8_t, hi - lo + 1);
43
+ return p;
44
+ }
45
+
46
+ typedef struct {
47
+ int32_t m, n;
48
+ uint32_t *cigar;
49
+ } wf_cigar_t;
50
+
51
+ static void wf_cigar_push1(void *km, wf_cigar_t *c, int32_t op, int32_t len)
52
+ {
53
+ if (c->n && op == (c->cigar[c->n-1]&0xf)) {
54
+ c->cigar[c->n-1] += len<<4;
55
+ } else {
56
+ if (c->n == c->m) {
57
+ c->m = c->m + (c->m>>1) + 4;
58
+ c->cigar = Krealloc(km, uint32_t, c->cigar, c->m);
59
+ }
60
+ c->cigar[c->n++] = len<<4 | op;
61
+ }
62
+ }
63
+
64
+ /*
65
+ * The stripe data structure
66
+ */
67
+ #define WF_NEG_INF (-0x40000000)
68
+
69
+ typedef struct {
70
+ int32_t lo, hi;
71
+ int32_t *mem, *H, *E1, *E2, *F1, *F2;
72
+ } wf_slice_t;
73
+
74
+ typedef struct {
75
+ int32_t s, top, n, max_pen, lo, hi;
76
+ wf_slice_t *a;
77
+ } wf_stripe_t;
78
+
79
+ void wf_stripe_add(void *km, wf_stripe_t *wf, int32_t lo, int32_t hi)
80
+ {
81
+ int32_t i, n, m1 = wf->max_pen + 1, m2 = m1 * 2;
82
+ wf_slice_t *f;
83
+ ++wf->s;
84
+ ++wf->top;
85
+ if (wf->top == wf->n) wf->top = 0;
86
+ f = &wf->a[wf->top];
87
+ f->lo = lo, f->hi = hi;
88
+ n = hi - lo + 1;
89
+ kfree(km, f->mem);
90
+ f->mem = Kmalloc(km, int32_t, 5 * (n + m2));
91
+ f->H = f->mem + m1;
92
+ f->E1 = f->H + n + m2;
93
+ f->F1 = f->E1 + n + m2;
94
+ f->E2 = f->F1 + n + m2;
95
+ f->F2 = f->E2 + n + m2;
96
+ for (i = -m1; i < 0; ++i)
97
+ f->H[i] = f->E1[i] = f->E2[i] = f->F1[i] = f->F2[i] = WF_NEG_INF;
98
+ for (i = n; i < n + m1; ++i)
99
+ f->H[i] = f->E1[i] = f->E2[i] = f->F1[i] = f->F2[i] = WF_NEG_INF;
100
+ f->H -= lo, f->E1 -= lo, f->E2 -= lo, f->F1 -= lo, f->F2 -= lo; // such that f->H[lo] points to 0
101
+ }
102
+
103
+ static wf_stripe_t *wf_stripe_init(void *km, int32_t max_pen)
104
+ {
105
+ int32_t i;
106
+ wf_stripe_t *wf;
107
+ wf = Kcalloc(km, wf_stripe_t, 1);
108
+ wf->max_pen = max_pen;
109
+ wf->n = max_pen + 1;
110
+ wf->a = Kcalloc(km, wf_slice_t, wf->n);
111
+ wf->lo = wf->hi = 0;
112
+ for (i = 0; i < wf->n; ++i) {
113
+ wf_slice_t *f;
114
+ wf_stripe_add(km, wf, 0, 0);
115
+ f = &wf->a[wf->top];
116
+ f->H[0] = f->E1[0] = f->E2[0] = f->F1[0] = f->F2[0] = WF_NEG_INF;
117
+ }
118
+ wf->s = 0;
119
+ wf->a[wf->top].H[0] = -1;
120
+ return wf;
121
+ }
122
+
123
+ static void wf_stripe_destroy(void *km, wf_stripe_t *wf)
124
+ {
125
+ int32_t i;
126
+ for (i = 0; i < wf->n; ++i)
127
+ kfree(km, wf->a[i].mem);
128
+ kfree(km, wf->a);
129
+ kfree(km, wf);
130
+ }
131
+
132
+ static inline wf_slice_t *wf_stripe_get(const wf_stripe_t *wf, int32_t x)
133
+ {
134
+ int32_t y = wf->top - x;
135
+ if (y < 0) y += wf->n;
136
+ return &wf->a[y];
137
+ }
138
+
139
+ static inline int good_diag(int32_t d, int32_t k, int32_t tl, int32_t ql) // check if (d,k) falls within the DP matrix
140
+ {
141
+ return ((k >= -1 && k < tl) && (d + k >= -1 && d + k < ql));
142
+ }
143
+
144
+ static void wf_stripe_shrink(wf_stripe_t *wf, int32_t tl, int32_t ql)
145
+ {
146
+ int32_t j, d;
147
+ for (d = wf->lo; d <= wf->hi; ++d) {
148
+ for (j = 0; j < wf->n; ++j) {
149
+ wf_slice_t *p = &wf->a[(wf->top + 1 + j) % wf->n];
150
+ if (d < p->lo || d > p->hi) continue;
151
+ if (good_diag(d, p->H[d], tl, ql)) break;
152
+ if (good_diag(d, p->E1[d], tl, ql) || good_diag(d, p->F1[d], tl, ql)) break;
153
+ if (good_diag(d, p->E2[d], tl, ql) || good_diag(d, p->F2[d], tl, ql)) break;
154
+ }
155
+ if (j < wf->n) break; // stop when we see a "good diagonal" in the stripe
156
+ }
157
+ assert(d <= wf->hi); // should never happen
158
+ wf->lo = d;
159
+ for (d = wf->hi; d >= wf->lo; --d) {
160
+ for (j = 0; j < wf->n; ++j) {
161
+ wf_slice_t *p = &wf->a[(wf->top + 1 + j) % wf->n];
162
+ if (d < p->lo || d > p->hi) continue;
163
+ if (good_diag(d, p->H[d], tl, ql)) break;
164
+ if (good_diag(d, p->E1[d], tl, ql) || good_diag(d, p->F1[d], tl, ql)) break;
165
+ if (good_diag(d, p->E2[d], tl, ql) || good_diag(d, p->F2[d], tl, ql)) break;
166
+ }
167
+ if (j < wf->n) break;
168
+ }
169
+ assert(d >= wf->lo);
170
+ wf->hi = d;
171
+ }
172
+
173
+ typedef struct {
174
+ int32_t s, d;
175
+ } wf_chkpt_t;
176
+
177
+ /*
178
+ * Extend a diagonal along exact matches
179
+ */
180
+
181
+ // pad strings with distinct characters
182
+ static void wf_pad_str(void *km, int32_t tl, const char *ts, int32_t ql, const char *qs, char **pts, char **pqs)
183
+ {
184
+ uint8_t t[256];
185
+ int32_t i, c1 = -1, c2 = -1;
186
+ char *s1, *s2;
187
+ *pts = *pqs = 0;
188
+ // collect all used characters
189
+ memset(t, 0, 256);
190
+ for (i = 0; i < tl; ++i)
191
+ if (t[(uint8_t)ts[i]] == 0)
192
+ t[(uint8_t)ts[i]] = 1;
193
+ for (i = 0; i < ql; ++i)
194
+ if (t[(uint8_t)qs[i]] == 0)
195
+ t[(uint8_t)qs[i]] = 1;
196
+ for (i = 0; i < 256; ++i)
197
+ if (t[i] == 0) {
198
+ if (c1 < 0) c1 = i;
199
+ else if (c2 < 0) c2 = i;
200
+ }
201
+ if (c1 < 0 || c2 < 0) return; // The two strings use >=255 characters. Unlikely for bio strings.
202
+ s1 = Kmalloc(km, char, tl + ql + 16); // the two strings are allocated together
203
+ s2 = s1 + tl + 8;
204
+ memcpy(s1, ts, tl);
205
+ for (i = tl; i < tl + 8; ++i) s1[i] = c1; // pad with c1
206
+ memcpy(s2, qs, ql);
207
+ for (i = ql; i < ql + 8; ++i) s2[i] = c2; // pad with c2
208
+ *pts = s1, *pqs = s2;
209
+ }
210
+
211
+ // Extend a diagonal along exact matches.
212
+ static inline int32_t wf_extend1_padded(const char *ts, const char *qs, int32_t k, int32_t d)
213
+ {
214
+ uint64_t cmp = 0;
215
+ const char *ts_ = ts + 1;
216
+ const char *qs_ = qs + d + 1;
217
+ while (1) {
218
+ uint64_t x = *(uint64_t*)(ts_ + k); // warning: unaligned memory access
219
+ uint64_t y = *(uint64_t*)(qs_ + k);
220
+ cmp = x ^ y;
221
+ if (cmp == 0) k += 8;
222
+ else break;
223
+ }
224
+ k += __builtin_ctzl(cmp) >> 3;
225
+ return k;
226
+ }
227
+
228
+ /*
229
+ * Core wf_next() routines
230
+ */
231
+
232
+ // Force loop vectorization. Learned from WFA.
233
+ #if defined(__clang__)
234
+ #define PRAGMA_LOOP_VECTORIZE _Pragma("clang loop vectorize(enable)")
235
+ #elif defined(__GNUC__)
236
+ #define PRAGMA_LOOP_VECTORIZE _Pragma("GCC ivdep")
237
+ #else
238
+ #define PRAGMA_LOOP_VECTORIZE _Pragma("ivdep")
239
+ #endif
240
+
241
+ #define wf_max(a, b) ((a) >= (b)? (a) : (b))
242
+
243
+ static void wf_next_prep(void *km, const mwf_opt_t *opt, wf_stripe_t *wf, int32_t lo, int32_t hi,
244
+ int32_t **H, int32_t **E1, int32_t **F1, int32_t **E2, int32_t **F2,
245
+ const int32_t **pHx, const int32_t **pHo1, const int32_t **pHo2,
246
+ const int32_t **pE1, const int32_t **pF1, const int32_t **pE2, const int32_t **pF2)
247
+ {
248
+ const wf_slice_t *fx, *fo1, *fo2, *fe1, *fe2;
249
+ wf_slice_t *ft;
250
+ wf_stripe_add(km, wf, lo, hi);
251
+ ft = &wf->a[wf->top];
252
+ fx = wf_stripe_get(wf, opt->x);
253
+ fo1 = wf_stripe_get(wf, opt->o1 + opt->e1);
254
+ fo2 = wf_stripe_get(wf, opt->o2 + opt->e2);
255
+ fe1 = wf_stripe_get(wf, opt->e1);
256
+ fe2 = wf_stripe_get(wf, opt->e2);
257
+ *pHx = fx->H, *pHo1 = fo1->H, *pHo2 = fo2->H, *pE1 = fe1->E1, *pE2 = fe2->E2, *pF1 = fe1->F1, *pF2 = fe2->F2;
258
+ *H = ft->H, *E1 = ft->E1, *E2 = ft->E2, *F1 = ft->F1, *F2 = ft->F2;
259
+ }
260
+
261
+ static void wf_next_score(int32_t lo, int32_t hi, int32_t *H, int32_t *E1, int32_t *F1, int32_t *E2, int32_t *F2,
262
+ const int32_t *pHx, const int32_t *pHo1, const int32_t *pHo2,
263
+ const int32_t *pE1, const int32_t *pF1, const int32_t *pE2, const int32_t *pF2)
264
+ {
265
+ int32_t d;
266
+ PRAGMA_LOOP_VECTORIZE
267
+ for (d = lo; d <= hi; ++d) {
268
+ int32_t h, f, e;
269
+ E1[d] = wf_max(pHo1[d-1], pE1[d-1]);
270
+ E2[d] = wf_max(pHo2[d-1], pE2[d-1]);
271
+ e = wf_max(E1[d], E2[d]);
272
+ F1[d] = wf_max(pHo1[d+1], pF1[d+1]) + 1;
273
+ F2[d] = wf_max(pHo2[d+1], pF2[d+1]) + 1;
274
+ f = wf_max(F1[d], F2[d]);
275
+ h = wf_max(e, f);
276
+ H[d] = wf_max(pHx[d] + 1, h);
277
+ // if (H[d] >= -1) fprintf(stderr, "s=%d, d=%d, k=%d, (%d,%d)\n", wf->s, d, H[d], E1[d], F1[d]);
278
+ }
279
+ }
280
+
281
+ static void wf_next_tb(int32_t lo, int32_t hi, int32_t *H, int32_t *E1, int32_t *F1, int32_t *E2, int32_t *F2, uint8_t *ax,
282
+ const int32_t *pHx, const int32_t *pHo1, const int32_t *pHo2,
283
+ const int32_t *pE1, const int32_t *pF1, const int32_t *pE2, const int32_t *pF2)
284
+ {
285
+ int32_t d;
286
+ PRAGMA_LOOP_VECTORIZE
287
+ for (d = lo; d <= hi; ++d) {
288
+ int32_t h, f, e;
289
+ uint8_t x = 0, ze, zf, z;
290
+ x |= pHo1[d-1] >= pE1[d-1]? 0 : 0x08;
291
+ E1[d] = wf_max(pHo1[d-1], pE1[d-1]);
292
+ x |= pHo2[d-1] >= pE2[d-1]? 0 : 0x20;
293
+ E2[d] = wf_max(pHo2[d-1], pE2[d-1]);
294
+ ze = E1[d] >= E2[d]? 1 : 3;
295
+ e = wf_max(E1[d], E2[d]);
296
+ x |= pHo1[d+1] >= pF1[d+1]? 0 : 0x10;
297
+ F1[d] = wf_max(pHo1[d+1], pF1[d+1]) + 1;
298
+ x |= pHo2[d+1] >= pF2[d+1]? 0 : 0x40;
299
+ F2[d] = wf_max(pHo2[d+1], pF2[d+1]) + 1;
300
+ zf = F1[d] >= F2[d]? 2 : 4;
301
+ f = wf_max(F1[d], F2[d]);
302
+ z = e >= f? ze : zf;
303
+ h = wf_max(e, f);
304
+ z = pHx[d] + 1 >= h? 0 : z;
305
+ H[d] = wf_max(pHx[d] + 1, h);
306
+ ax[d] = x | z;
307
+ }
308
+ }
309
+
310
+ /*
311
+ * Core algorithm
312
+ */
313
+ static void wf_next_basic(void *km, void *km_tb, const mwf_opt_t *opt, wf_stripe_t *wf, wf_tb_t *tb, int32_t lo, int32_t hi)
314
+ {
315
+ int32_t *H, *E1, *E2, *F1, *F2;
316
+ const int32_t *pHx, *pHo1, *pHo2, *pE1, *pE2, *pF1, *pF2;
317
+ wf_next_prep(km, opt, wf, lo, hi, &H, &E1, &F1, &E2, &F2, &pHx, &pHo1, &pHo2, &pE1, &pF1, &pE2, &pF2);
318
+ if (tb) {
319
+ uint8_t *ax;
320
+ ax = wf_tb_add(km_tb, tb, lo, hi)->x - lo;
321
+ wf_next_tb(lo, hi, H, E1, F1, E2, F2, ax, pHx, pHo1, pHo2, pE1, pF1, pE2, pF2);
322
+ } else {
323
+ wf_next_score(lo, hi, H, E1, F1, E2, F2, pHx, pHo1, pHo2, pE1, pF1, pE2, pF2);
324
+ }
325
+ if (H[lo] >= -1 || E1[lo] >= -1 || F1[lo] >= -1 || E2[lo] >= -1 || F2[lo] >= -1) wf->lo = lo;
326
+ if (H[hi] >= -1 || E1[hi] >= -1 || F1[hi] >= -1 || E2[hi] >= -1 || F2[hi] >= -1) wf->hi = hi;
327
+ }
328
+
329
+ static uint32_t *wf_traceback(void *km, const mwf_opt_t *opt, wf_tb_t *tb, int32_t t_end, const char *ts, int32_t q_end, const char *qs, int32_t last, int32_t *n_cigar)
330
+ {
331
+ wf_cigar_t cigar = {0,0,0};
332
+ int32_t i = q_end, k = t_end, s = tb->n - 1;
333
+ while (i >= 0 && k >= 0) {
334
+ int32_t k0 = k, j, x, state, ext;
335
+ if (last == 0) { // if the previous state is 0, check exact matches
336
+ while (i >= 0 && k >= 0 && qs[i] == ts[k])
337
+ --i, --k;
338
+ if (k0 - k > 0)
339
+ wf_cigar_push1(km, &cigar, 7, k0 - k);
340
+ if (i < 0 || k < 0) break;
341
+ }
342
+ assert(s >= 0);
343
+ j = i - k - tb->a[s].lo;
344
+ assert(j <= tb->a[s].hi - tb->a[s].lo);
345
+ x = tb->a[s].x[j];
346
+ state = last == 0? x&7 : last;
347
+ ext = state > 0? x>>(state+2)&1 : 0; // whether an extension
348
+ //fprintf(stderr, "s=%d, %d->%d, ext=%d%d%d%d, i=%d, k=%d\n", s, last, state, x>>3&1, x>>4&1, x>>5&1, x>>6&1, i, k);
349
+ if (state == 0) {
350
+ wf_cigar_push1(km, &cigar, 8, 1);
351
+ --i, --k, s -= opt->x;
352
+ } else if (state == 1) {
353
+ wf_cigar_push1(km, &cigar, 1, 1);
354
+ --i, s -= ext? opt->e1 : opt->o1 + opt->e1;
355
+ } else if (state == 3) {
356
+ wf_cigar_push1(km, &cigar, 1, 1);
357
+ --i, s -= ext? opt->e2 : opt->o2 + opt->e2;
358
+ } else if (state == 2) {
359
+ wf_cigar_push1(km, &cigar, 2, 1);
360
+ --k, s -= ext? opt->e1 : opt->o1 + opt->e1;
361
+ } else if (state == 4) {
362
+ wf_cigar_push1(km, &cigar, 2, 1);
363
+ --k, s -= ext? opt->e2 : opt->o2 + opt->e2;
364
+ } else abort();
365
+ last = state > 0 && ext? state : 0;
366
+ }
367
+ if (opt->flag&MWF_F_DEBUG) fprintf(stderr, "s0=%d, s=%d, i=%d, k=%d\n", tb->n-1, s, i, k);
368
+ if (i >= 0) wf_cigar_push1(km, &cigar, 1, i + 1);
369
+ else if (k >= 0) wf_cigar_push1(km, &cigar, 2, k + 1);
370
+ for (i = 0; i < cigar.n>>1; ++i) { // reverse to the input order
371
+ uint32_t t = cigar.cigar[i];
372
+ cigar.cigar[i] = cigar.cigar[cigar.n - i - 1];
373
+ cigar.cigar[cigar.n - i - 1] = t;
374
+ }
375
+ *n_cigar = cigar.n;
376
+ return cigar.cigar;
377
+ }
378
+
379
+ // pts and pqs MUST BE padded with wf_pad_str()
380
+ static void mwf_wfa_core(void *km, const mwf_opt_t *opt, int32_t tl, const char *pts, int32_t ql, const char *pqs, int32_t n_seg, wf_chkpt_t *seg, mwf_rst_t *r)
381
+ {
382
+ int32_t max_pen, sid, is_tb = !!(opt->flag&MWF_F_CIGAR), last_state = 0, stopped = 0;
383
+ wf_stripe_t *wf;
384
+ wf_tb_t tb = {0,0,0};
385
+ void *km_tb, *km_st;
386
+
387
+ memset(r, 0, sizeof(*r));
388
+ km_tb = is_tb && !(opt->flag&MWF_F_NO_KALLOC)? km_init2(km, 0) : 0;
389
+ km_st = !(opt->flag&MWF_F_NO_KALLOC)? km_init2(km, 0) : 0;
390
+ max_pen = opt->x;
391
+ max_pen = max_pen > opt->o1 + opt->e1? max_pen : opt->o1 + opt->e1;
392
+ max_pen = max_pen > opt->o2 + opt->e2? max_pen : opt->o2 + opt->e2;
393
+ wf = wf_stripe_init(km_st, max_pen);
394
+ assert(pts);
395
+
396
+ sid = 0;
397
+ while (1) {
398
+ wf_slice_t *p = &wf->a[wf->top];
399
+ int32_t d, lo, hi, *H = p->H;
400
+ for (d = p->lo; d <= p->hi; ++d) {
401
+ int32_t k = 0;
402
+ if (H[d] < -1 || d + H[d] < -1 || H[d] >= tl || d + H[d] >= ql) continue;
403
+ k = wf_extend1_padded(pts, pqs, H[d], d);
404
+ //fprintf(stderr, "[s=%d] [%d,%d]:%d %d->%d,%d,%d,%d,%d\n", wf->s, p->lo, p->hi, d, H[d], k, wf->a[wf->top].E1[d], wf->a[wf->top].F1[d], wf->a[wf->top].E2[d], wf->a[wf->top].F2[d]);
405
+ if (k == tl - 1 && d + k == ql - 1) {
406
+ if (k == H[d] && is_tb)
407
+ last_state = tb.a[tb.n-1].x[d - tb.a[tb.n-1].lo] & 7;
408
+ break;
409
+ }
410
+ H[d] = k;
411
+ }
412
+ if (d <= p->hi) break;
413
+ if (is_tb && seg && sid < n_seg && seg[sid].s == wf->s) {
414
+ assert(seg[sid].d >= wf->lo && seg[sid].d <= wf->hi);
415
+ wf->lo = wf->hi = seg[sid++].d;
416
+ }
417
+ lo = wf->lo > -tl? wf->lo - 1 : -tl;
418
+ hi = wf->hi < ql? wf->hi + 1 : ql;
419
+ wf_next_basic(km_st, km_tb, opt, wf, is_tb? &tb : 0, lo, hi);
420
+ if ((wf->s&0xff) == 0) wf_stripe_shrink(wf, tl, ql);
421
+ r->n_iter += hi - lo + 1;
422
+ if ((opt->max_iter > 0 && r->n_iter > opt->max_iter) || (opt->max_s > 0 && wf->s > opt->max_s)) {
423
+ stopped = 1;
424
+ break;
425
+ }
426
+ }
427
+ r->s = stopped? -1 : wf->s;
428
+ if (is_tb && !stopped)
429
+ r->cigar = wf_traceback(km, opt, &tb, tl-1, pts, ql-1, pqs, last_state, &r->n_cigar);
430
+ if (km_st == 0) wf_stripe_destroy(km_st, wf);
431
+ else km_destroy(km_st);
432
+ km_destroy(km_tb);
433
+ if (is_tb && !stopped)
434
+ r->cigar = (uint32_t*)krelocate(km, r->cigar, r->n_cigar * sizeof(*r->cigar));
435
+ }
436
+
437
+ /*
438
+ * Low-memory mode
439
+ */
440
+ typedef struct {
441
+ int32_t n, n_intv, max_s;
442
+ int32_t *x;
443
+ uint64_t *intv;
444
+ } wf_ss_t; // snapshot
445
+
446
+ typedef struct {
447
+ int32_t n, m;
448
+ wf_ss_t *a;
449
+ } wf_sss_t;
450
+
451
+ static void wf_snapshot1(void *km, wf_stripe_t *sf, wf_ss_t *ss)
452
+ {
453
+ int32_t j, k, t;
454
+ ss->n = 0, ss->max_s = sf->s;
455
+ for (j = 0; j < sf->n; ++j)
456
+ ss->n += 5 * (sf->a[j].hi - sf->a[j].lo + 1);
457
+ ss->x = Kmalloc(km, int32_t, ss->n);
458
+ ss->n_intv = sf->n;
459
+ ss->intv = Kmalloc(km, uint64_t, ss->n_intv);
460
+ for (j = 0, t = 0; j < sf->n; ++j) {
461
+ wf_slice_t *p;
462
+ k = (sf->top + 1 + j) % sf->n;
463
+ p = &sf->a[k];
464
+ ss->intv[j] = (uint64_t)p->lo << 32 | (p->hi - p->lo + 1) * 5;
465
+ for (k = p->lo; k <= p->hi; ++k) {
466
+ ss->x[t] = p->H[k], p->H[k] = t++;
467
+ ss->x[t] = p->E1[k], p->E1[k] = t++;
468
+ ss->x[t] = p->F1[k], p->F1[k] = t++;
469
+ ss->x[t] = p->E2[k], p->E2[k] = t++;
470
+ ss->x[t] = p->F2[k], p->F2[k] = t++;
471
+ }
472
+ }
473
+ assert(t == ss->n);
474
+ }
475
+
476
+ static void wf_snapshot(void *km, wf_sss_t *sss, wf_stripe_t *sf)
477
+ {
478
+ if (sss->n == sss->m) {
479
+ sss->m += (sss->m>>1) + 8;
480
+ sss->a = Krealloc(km, wf_ss_t, sss->a, sss->m);
481
+ }
482
+ wf_snapshot1(km, sf, &sss->a[sss->n++]);
483
+ }
484
+
485
+ static void wf_snapshot_free(void *km, wf_sss_t *sss)
486
+ {
487
+ int32_t j;
488
+ for (j = 0; j < sss->n; ++j) {
489
+ kfree(km, sss->a[j].x);
490
+ kfree(km, sss->a[j].intv);
491
+ }
492
+ kfree(km, sss->a);
493
+ }
494
+
495
+ static void wf_next_seg(void *km, const mwf_opt_t *opt, uint8_t *xbuf, wf_stripe_t *wf, wf_stripe_t *sf, int32_t lo, int32_t hi)
496
+ {
497
+ int32_t d, *H, *E1, *E2, *F1, *F2;
498
+ const int32_t *pHx, *pHo1, *pHo2, *pE1, *pE2, *pF1, *pF2;
499
+ uint8_t *ax = xbuf - lo;
500
+
501
+ wf_next_prep(km, opt, wf, lo, hi, &H, &E1, &F1, &E2, &F2, &pHx, &pHo1, &pHo2, &pE1, &pF1, &pE2, &pF2);
502
+ wf_next_tb(lo, hi, H, E1, F1, E2, F2, ax, pHx, pHo1, pHo2, pE1, pF1, pE2, pF2);
503
+ wf_next_prep(km, opt, sf, lo, hi, &H, &E1, &F1, &E2, &F2, &pHx, &pHo1, &pHo2, &pE1, &pF1, &pE2, &pF2);
504
+ PRAGMA_LOOP_VECTORIZE
505
+ for (d = lo; d <= hi; ++d) { // FIXME: merge this loop into the loop in wf_next_tb(). I tried but couldn't make clang vectorize.
506
+ uint8_t x = ax[d];
507
+ int32_t a, b, e1, f1, e2, f2, h;
508
+ a = pHo1[d-1], b = pE1[d-1];
509
+ e1 = E1[d] = (x&0x08) == 0? a : b;
510
+ a = pHo1[d+1], b = pF1[d+1];
511
+ f1 = F1[d] = (x&0x10) == 0? a : b;
512
+ a = pHo2[d-1], b = pE2[d-1];
513
+ e2 = E2[d] = (x&0x20) == 0? a : b;
514
+ a = pHo2[d+1], b = pF2[d+1];
515
+ f2 = F2[d] = (x&0x40) == 0? a : b;
516
+ x &= 7;
517
+ h = pHx[d];
518
+ h = x == 1? e1 : h;
519
+ h = x == 2? f1 : h;
520
+ h = x == 3? e2 : h;
521
+ h = x == 4? f2 : h;
522
+ H[d] = h;
523
+ }
524
+ if (H[lo] >= -1 || E1[lo] >= -1 || F1[lo] >= -1 || E2[lo] >= -1 || F2[lo] >= -1) wf->lo = lo;
525
+ if (H[hi] >= -1 || E1[hi] >= -1 || F1[hi] >= -1 || E2[hi] >= -1 || F2[hi] >= -1) wf->hi = hi;
526
+ }
527
+
528
+ static wf_chkpt_t *wf_traceback_seg(void *km, wf_sss_t *sss, int32_t last, int32_t *n_seg)
529
+ {
530
+ int32_t j;
531
+ wf_chkpt_t *seg;
532
+ *n_seg = sss->n;
533
+ seg = Kmalloc(km, wf_chkpt_t, sss->n);
534
+ for (j = sss->n - 1; j >= 0; --j) {
535
+ int32_t k, m;
536
+ wf_ss_t *p = &sss->a[j];
537
+ for (k = 0, m = 0; k < p->n_intv; ++k) {
538
+ if (last >= m && last < m + (int32_t)p->intv[k])
539
+ break;
540
+ m += (int32_t)p->intv[k];
541
+ }
542
+ assert(k < p->n_intv);
543
+ seg[j].s = p->max_s - (p->n_intv - k - 1);
544
+ seg[j].d = (int32_t)(p->intv[k]>>32) + (last - m) / 5;
545
+ last = p->x[last];
546
+ }
547
+ assert(last == -1);
548
+ return seg;
549
+ }
550
+
551
+ wf_chkpt_t *mwf_wfa_seg(void *km, const mwf_opt_t *opt, int32_t tl, const char *pts, int32_t ql, const char *pqs, int32_t *n_seg_)
552
+ {
553
+ int32_t max_pen, last, n_seg;
554
+ wf_stripe_t *wf, *sf;
555
+ wf_sss_t sss = {0,0,0};
556
+ uint8_t *xbuf;
557
+ wf_chkpt_t *seg;
558
+ void *km_st;
559
+
560
+ km_st = !(opt->flag&MWF_F_NO_KALLOC)? km_init2(km, 0) : 0;
561
+ max_pen = opt->x;
562
+ max_pen = max_pen > opt->o1 + opt->e1? max_pen : opt->o1 + opt->e1;
563
+ max_pen = max_pen > opt->o2 + opt->e2? max_pen : opt->o2 + opt->e2;
564
+ xbuf = Kcalloc(km_st, uint8_t, tl + ql + 1);
565
+ wf = wf_stripe_init(km_st, max_pen);
566
+ sf = wf_stripe_init(km_st, max_pen);
567
+ assert(pts);
568
+
569
+ while (1) {
570
+ wf_slice_t *p = &wf->a[wf->top];
571
+ int32_t d, lo, hi, *H = p->H;
572
+ for (d = p->lo; d <= p->hi; ++d) {
573
+ int32_t k;
574
+ if (H[d] < -1 || d + H[d] < -1 || H[d] >= tl || d + H[d] >= ql) continue;
575
+ k = wf_extend1_padded(pts, pqs, H[d], d);
576
+ if (k == tl - 1 && d + k == ql - 1) {
577
+ last = sf->a[sf->top].H[d];
578
+ break;
579
+ }
580
+ H[d] = k;
581
+ }
582
+ if (d <= p->hi) break;
583
+ lo = wf->lo > -tl? wf->lo - 1 : -tl;
584
+ hi = wf->hi < ql? wf->hi + 1 : ql;
585
+ if ((wf->s + 1) % opt->step == 0)
586
+ wf_snapshot(km_st, &sss, sf);
587
+ wf_next_seg(km_st, opt, xbuf, wf, sf, lo, hi);
588
+ if ((wf->s&0xff) == 0) wf_stripe_shrink(wf, tl, ql);
589
+ }
590
+ seg = wf_traceback_seg(km, &sss, last, &n_seg);
591
+ if (km_st == 0) {
592
+ wf_snapshot_free(km_st, &sss);
593
+ wf_stripe_destroy(km_st, wf);
594
+ wf_stripe_destroy(km_st, sf);
595
+ kfree(km_st, xbuf);
596
+ } else km_destroy(km_st);
597
+
598
+ seg = (wf_chkpt_t*)krelocate(km, seg, n_seg * sizeof(*seg));
599
+ *n_seg_ = n_seg;
600
+ return seg;
601
+ }
602
+
603
+ void mwf_wfa_exact(void *km, const mwf_opt_t *opt, int32_t tl, const char *ts, int32_t ql, const char *qs, mwf_rst_t *r)
604
+ {
605
+ int32_t n_seg = 0;
606
+ wf_chkpt_t *seg = 0;
607
+ char *pts, *pqs;
608
+
609
+ wf_pad_str(km, tl, ts, ql, qs, &pts, &pqs);
610
+ if (opt->step > 0)
611
+ seg = mwf_wfa_seg(km, opt, tl, pts, ql, pqs, &n_seg);
612
+ mwf_wfa_core(km, opt, tl, pts, ql, pqs, n_seg, seg, r);
613
+ kfree(km, seg);
614
+ kfree(km, pts);
615
+ }
616
+
617
+ /*
618
+ * Heuristics
619
+ */
620
+ static int32_t mg_lis_64(void *km, int32_t n, const uint64_t *a, int32_t *b)
621
+ {
622
+ int32_t i, k, L = 0, *M, *P = b;
623
+ KMALLOC(km, M, n+1);
624
+ for (i = 0; i < n; ++i) {
625
+ int32_t lo = 1, hi = L, newL;
626
+ while (lo <= hi) {
627
+ int32_t mid = (lo + hi + 1) >> 1;
628
+ if (a[M[mid]] < a[i]) lo = mid + 1;
629
+ else hi = mid - 1;
630
+ }
631
+ newL = lo, P[i] = M[newL - 1], M[newL] = i;
632
+ if (newL > L) L = newL;
633
+ }
634
+ k = M[L];
635
+ memcpy(M, P, n * sizeof(int32_t));
636
+ for (i = L - 1; i >= 0; --i) b[i] = k, k = M[k];
637
+ kfree(km, M);
638
+ return L;
639
+ }
640
+
641
+ extern void radix_sort_gfa64(uint64_t*, uint64_t*);
642
+ extern unsigned char seq_nt4_table[256];
643
+
644
+ static int32_t mg_fc_kmer(int32_t len, const char *seq, int32_t rid, int32_t k, uint64_t *a)
645
+ {
646
+ int32_t i, l, n;
647
+ uint64_t x, mask = (1ULL<<k*2) - 1;
648
+ for (i = l = 0, x = 0, n = 0; i < len; ++i) {
649
+ int32_t c = seq_nt4_table[(uint8_t)seq[i]];
650
+ if (c < 4) {
651
+ x = (x << 2 | c) & mask;
652
+ if (++l >= k) a[n++] = (x<<1|rid) << 32 | i;
653
+ } else l = 0, x = 0;
654
+ }
655
+ return n;
656
+ }
657
+
658
+ static uint64_t *mg_chain(void *km, int32_t l1, const char *s1, int32_t l2, const char *s2, int32_t k, int32_t max_occ, int32_t *n_lis_)
659
+ {
660
+ int32_t i, n_a, n_b, m_b, i0, n_lis, *lis;
661
+ uint64_t *a, *b;
662
+
663
+ *n_lis_ = 0;
664
+ if (l1 < k || l2 < k) return 0;
665
+ assert(k >= 2 && k <= 15);
666
+
667
+ // collect k-mers
668
+ KMALLOC(km, a, l1 + l2);
669
+ n_a = mg_fc_kmer(l1, s1, 0, k, a);
670
+ n_a += mg_fc_kmer(l2, s2, 1, k, &a[n_a]);
671
+ radix_sort_gfa64(a, a + n_a);
672
+
673
+ // collect k-mer matches
674
+ n_b = m_b = 0, b = 0;
675
+ for (i0 = 0, i = 1; i <= n_a; ++i) {
676
+ if (i == n_a || a[i0]>>33 != a[i]>>33) {
677
+ if (i - i0 >= 2) {
678
+ int32_t j, s, t;
679
+ for (j = i0; j < i && (a[j]>>32&1) == 0; ++j) {}
680
+ if (j > i0 && j < i && j - i0 <= max_occ && i - j <= max_occ) {
681
+ for (s = i0; s < j; ++s)
682
+ for (t = j; t < i; ++t) {
683
+ if (n_b == m_b) KEXPAND(km, b, m_b);
684
+ b[n_b++] = a[s]<<32 | (uint32_t)a[t];
685
+ }
686
+ }
687
+ }
688
+ i0 = i;
689
+ }
690
+ }
691
+ kfree(km, a);
692
+
693
+ // find co-linear chain with LIS
694
+ radix_sort_gfa64(b, b + n_b);
695
+ for (i = 0; i < n_b; ++i)
696
+ b[i] = b[i]>>32 | b[i]<<32;
697
+ KMALLOC(km, lis, n_b);
698
+ n_lis = mg_lis_64(km, n_b, b, lis);
699
+ a = Kmalloc(km, uint64_t, n_lis);
700
+ for (i = 0; i < n_lis; ++i) a[i] = b[lis[i]];
701
+ kfree(km, lis);
702
+ kfree(km, b);
703
+ b = Kmalloc(km, uint64_t, n_lis);
704
+ memcpy(b, a, sizeof(uint64_t) * n_lis);
705
+ kfree(km, a);
706
+ *n_lis_ = n_lis;
707
+ for (i = 0; i < n_lis; ++i) // switch back, such that seq1 on the high bits
708
+ b[i] = b[i]>>32 | b[i]<<32;
709
+ return b;
710
+ }
711
+
712
+ static double mwf_ksim(void *km, int32_t l1, const char *s1, int32_t l2, const char *s2, int32_t k)
713
+ {
714
+ int32_t i, i0, j, n_a, n1 = 0, n2 = 0, t1 = 0, t2 = 0;
715
+ double p1, p2;
716
+ uint64_t *a;
717
+ if (l1 < k || l2 < k) return 0;
718
+ assert(k >= 2 && k <= 15);
719
+ KMALLOC(km, a, l1 + l2);
720
+ n_a = mg_fc_kmer(l1, s1, 0, k, a);
721
+ n_a += mg_fc_kmer(l2, s2, 1, k, &a[n_a]);
722
+ radix_sort_gfa64(a, a + n_a);
723
+ for (i0 = 0, i = 1; i <= n_a; ++i) {
724
+ if (i == n_a || a[i0]>>33 != a[i]>>33) {
725
+ int32_t m1, m2, min;
726
+ for (j = i0; j < i && (a[j]>>32&1) == 0; ++j) {}
727
+ m1 = j - i0, m2 = i - j;
728
+ min = m1 < m2? m1 : m2;
729
+ n1 += m1, n2 += m2;
730
+ if (m1 > 0 && m2 > 0)
731
+ t1 += min, t2 += min;
732
+ i0 = i;
733
+ }
734
+ }
735
+ kfree(km, a);
736
+ p1 = (double)t1 / n1, p2 = (double)t2 / n2;
737
+ return p1 > p2? p1 : p2;
738
+ }
739
+
740
+ #define kroundup32(x) (--(x), (x)|=(x)>>1, (x)|=(x)>>2, (x)|=(x)>>4, (x)|=(x)>>8, (x)|=(x)>>16, ++(x))
741
+
742
+ static void wf_cigar_push(void *km, wf_cigar_t *c, int32_t n_cigar, const uint32_t *cigar)
743
+ {
744
+ if (n_cigar == 0) return;
745
+ wf_cigar_push1(km, c, cigar[0]&0xf, cigar[0]>>4);
746
+ if (c->n + n_cigar - 1 > c->m) {
747
+ c->m = c->n + n_cigar - 1;
748
+ kroundup32(c->m);
749
+ c->cigar = Krealloc(km, uint32_t, c->cigar, c->m);
750
+ }
751
+ memcpy(&c->cigar[c->n], &cigar[1], sizeof(*cigar) * (n_cigar - 1));
752
+ c->n += n_cigar - 1;
753
+ }
754
+
755
+ static int32_t wf_anchor_filter(int32_t n, uint64_t *a, int32_t tl, int32_t ql, int32_t k, int32_t min_l)
756
+ {
757
+ int32_t i, st, x0, y0, x1, y1, j, l, m;
758
+ for (i = 0, x0 = y0 = x1 = y1 = 0, st = -1, l = 0; i <= n; ++i) {
759
+ int32_t x, y;
760
+ if (i == n) x = tl, y = ql;
761
+ else x = (int32_t)(a[i]>>32) + 1, y = (int32_t)a[i] + 1;
762
+ if (x - x0 != y - y0) {
763
+ //fprintf(stderr, "X\t%d\t(%d,%d) -> (%d,%d)\n", l, x0, y0, x, y);
764
+ if (l < min_l)
765
+ for (j = st > 0? st : 0; j < i; ++j)
766
+ a[j] = 0;
767
+ x0 = x, y0 = y, st = i, l = k;
768
+ } else l += x - x1;
769
+ x1 = x, y1 = y;
770
+ }
771
+ for (i = 0, m = 0; i < n; ++i)
772
+ if (a[i] != 0) a[m++] = a[i];
773
+ return m;
774
+ }
775
+
776
+ void mwf_wfa_chain(void *km, const mwf_opt_t *opt, int32_t tl, const char *ts, int32_t ql, const char *qs, mwf_rst_t *r)
777
+ {
778
+ int32_t n_a, i, x0, y0;
779
+ uint64_t *a;
780
+ void *km_wfa;
781
+ wf_cigar_t c = {0,0,0};
782
+
783
+ km_wfa = !(opt->flag&MWF_F_NO_KALLOC)? km_init2(km, 0) : 0;
784
+ a = mg_chain(km_wfa, tl, ts, ql, qs, opt->kmer, opt->max_occ, &n_a);
785
+ n_a = wf_anchor_filter(n_a, a, tl, ql, opt->kmer, opt->min_len);
786
+ r->s = 0;
787
+ for (i = 0, x0 = y0 = 0; i <= n_a; ++i) {
788
+ int32_t x1, y1;
789
+ if (i == n_a) x1 = tl, y1 = ql;
790
+ else x1 = (int32_t)(a[i]>>32) + 1, y1 = (int32_t)a[i] + 1;
791
+ if (i < n_a && x1 - x0 == y1 - y0 && x1 - x0 <= opt->kmer) {
792
+ if (opt->flag&MWF_F_CIGAR)
793
+ wf_cigar_push1(km, &c, 7, x1 - x0);
794
+ } else if (x0 < x1 && y0 < y1) {
795
+ if (x1 - x0 >= 10000 && y1 - y0 >= 10000 && mwf_ksim(km, x1 - x0, &ts[x0], y1 - y0, &qs[y0], opt->kmer) < 0.02) {
796
+ if (opt->flag&MWF_F_CIGAR) {
797
+ wf_cigar_push1(km, &c, 2, x1 - x0);
798
+ wf_cigar_push1(km, &c, 1, y1 - y0);
799
+ }
800
+ r->s += opt->o2 * 2 + opt->e2 * ((x1 - x0) + (y1 - y0));
801
+ } else {
802
+ mwf_rst_t q;
803
+ mwf_wfa_exact(km_wfa, opt, x1 - x0, &ts[x0], y1 - y0, &qs[y0], &q);
804
+ if (opt->flag&MWF_F_CIGAR)
805
+ wf_cigar_push(km, &c, q.n_cigar, q.cigar);
806
+ r->s += q.s;
807
+ kfree(km_wfa, q.cigar);
808
+ }
809
+ } else if (x0 < x1) {
810
+ wf_cigar_push1(km, &c, 2, x1 - x0);
811
+ r->s += opt->o2 + (x1 - x0) * opt->e2 < opt->o1 + (x1 - x0) * opt->e1? opt->o2 + (x1 - x0) * opt->e2 : opt->o1 + (x1 - x0) * opt->e1;
812
+ } else if (y0 < y1) {
813
+ wf_cigar_push1(km, &c, 1, y1 - y0);
814
+ r->s += opt->o2 + (y1 - y0) * opt->e2 < opt->o1 + (y1 - y0) * opt->e1? opt->o2 + (y1 - y0) * opt->e2 : opt->o1 + (y1 - y0) * opt->e1;
815
+ }
816
+ x0 = x1, y0 = y1;
817
+ }
818
+ if (km_wfa == 0) kfree(km_wfa, a);
819
+ km_destroy(km_wfa);
820
+ r->n_cigar = c.n, r->cigar = c.cigar;
821
+ r->cigar = (uint32_t*)krelocate(km, r->cigar, r->n_cigar * sizeof(*r->cigar));
822
+ }
823
+
824
+ void mwf_wfa_auto(void *km, const mwf_opt_t *opt0, int32_t tl, const char *ts, int32_t ql, const char *qs, mwf_rst_t *r)
825
+ {
826
+ mwf_opt_t opt = *opt0;
827
+ opt.step = 0, opt.max_iter = 100000000;
828
+ mwf_wfa_exact(km, &opt, tl, ts, ql, qs, r);
829
+ if (r->s < 0) {
830
+ if (opt.flag & MWF_F_CIGAR) opt.step = 5000;
831
+ opt.max_iter = -1;
832
+ mwf_wfa_chain(km, &opt, tl, ts, ql, qs, r);
833
+ }
834
+ }