minibwa 0.0.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 (52) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +21 -0
  3. data/README.md +119 -0
  4. data/ext/minibwa/extconf.rb +105 -0
  5. data/ext/minibwa/mb_buffer.c +113 -0
  6. data/ext/minibwa/mb_hit.c +192 -0
  7. data/ext/minibwa/mb_index.c +462 -0
  8. data/ext/minibwa/mb_index_build.c +174 -0
  9. data/ext/minibwa/mb_options.c +301 -0
  10. data/ext/minibwa/minibwa/LICENSE.txt +37 -0
  11. data/ext/minibwa/minibwa/align.c +930 -0
  12. data/ext/minibwa/minibwa/bseq.h +45 -0
  13. data/ext/minibwa/minibwa/bwt.c +715 -0
  14. data/ext/minibwa/minibwa/bwt.h +86 -0
  15. data/ext/minibwa/minibwa/cs.c +161 -0
  16. data/ext/minibwa/minibwa/format.c +356 -0
  17. data/ext/minibwa/minibwa/index.c +342 -0
  18. data/ext/minibwa/minibwa/kalloc.c +224 -0
  19. data/ext/minibwa/minibwa/kalloc.h +54 -0
  20. data/ext/minibwa/minibwa/ketopt.h +123 -0
  21. data/ext/minibwa/minibwa/kommon.c +374 -0
  22. data/ext/minibwa/minibwa/kommon.h +85 -0
  23. data/ext/minibwa/minibwa/kseq.h +256 -0
  24. data/ext/minibwa/minibwa/ksort.h +163 -0
  25. data/ext/minibwa/minibwa/ksw2.h +220 -0
  26. data/ext/minibwa/minibwa/ksw2_extd2_sse.c +403 -0
  27. data/ext/minibwa/minibwa/ksw2_extz2_sse.c +296 -0
  28. data/ext/minibwa/minibwa/ksw2_ll_sse.c +341 -0
  29. data/ext/minibwa/minibwa/kthread.h +15 -0
  30. data/ext/minibwa/minibwa/l2bit.c +479 -0
  31. data/ext/minibwa/minibwa/l2bit.h +72 -0
  32. data/ext/minibwa/minibwa/lchain.c +231 -0
  33. data/ext/minibwa/minibwa/libsais.c +6985 -0
  34. data/ext/minibwa/minibwa/libsais.h +106 -0
  35. data/ext/minibwa/minibwa/libsais64.c +7064 -0
  36. data/ext/minibwa/minibwa/libsais64.h +81 -0
  37. data/ext/minibwa/minibwa/map-algo.c +769 -0
  38. data/ext/minibwa/minibwa/mbpriv.h +148 -0
  39. data/ext/minibwa/minibwa/minibwa.h +176 -0
  40. data/ext/minibwa/minibwa/options.c +116 -0
  41. data/ext/minibwa/minibwa/pe.c +559 -0
  42. data/ext/minibwa/minibwa/s2n-lite.h +59 -0
  43. data/ext/minibwa/minibwa/seed.c +354 -0
  44. data/ext/minibwa/minibwa.c +67 -0
  45. data/ext/minibwa/minibwa.h +51 -0
  46. data/lib/minibwa/hit.rb +110 -0
  47. data/lib/minibwa/index.rb +77 -0
  48. data/lib/minibwa/options.rb +235 -0
  49. data/lib/minibwa/sam.rb +85 -0
  50. data/lib/minibwa/version.rb +6 -0
  51. data/lib/minibwa.rb +11 -0
  52. metadata +88 -0
@@ -0,0 +1,403 @@
1
+ #include <string.h>
2
+ #include <assert.h>
3
+ #include "ksw2.h"
4
+
5
+ #if defined(__ARM_NEON)
6
+ #define __SSE4_1__
7
+ #include "s2n-lite.h"
8
+ #elif defined(__SSE4_1__)
9
+ #include <smmintrin.h>
10
+ #elif defined(__SSE2__)
11
+ #include <xmmintrin.h>
12
+ #else
13
+ #error "Missing SSE2 or NEON intrinsics"
14
+ #endif
15
+
16
+ static inline __m128i ksw_i8x4_to_i32x4(const int8_t *x)
17
+ {
18
+ #if defined(__ARM_NEON)
19
+ return vreinterpretq_u8_s32(vmovl_s16(vget_low_s16(vmovl_s8(vcreate_s8((uint64_t)(uint32_t)*(int32_t*)x)))));
20
+ #elif defined(__SSE4_1__)
21
+ return _mm_cvtepi8_epi32(_mm_cvtsi32_si128(*(int32_t*)x));
22
+ #else
23
+ return _mm_setr_epi32(x[0], x[1], x[2], x[3]);
24
+ #endif
25
+ }
26
+
27
+ void ksw_extd2_sse(void *km, int qlen, const uint8_t *query, int tlen, const uint8_t *target, int8_t m, const int8_t *mat,
28
+ int8_t q, int8_t e, int8_t q2, int8_t e2, int w, int zdrop, int end_bonus, int flag, ksw_extz_t *ez)
29
+ {
30
+ #define __dp_code_block1 \
31
+ z = _mm_load_si128(&s[t]); \
32
+ xt1 = _mm_load_si128(&x[t]); /* xt1 <- x[r-1][t..t+15] */ \
33
+ tmp = _mm_srli_si128(xt1, 15); /* tmp <- x[r-1][t+15] */ \
34
+ xt1 = _mm_or_si128(_mm_slli_si128(xt1, 1), x1_); /* xt1 <- x[r-1][t-1..t+14] */ \
35
+ x1_ = tmp; \
36
+ vt1 = _mm_load_si128(&v[t]); /* vt1 <- v[r-1][t..t+15] */ \
37
+ tmp = _mm_srli_si128(vt1, 15); /* tmp <- v[r-1][t+15] */ \
38
+ vt1 = _mm_or_si128(_mm_slli_si128(vt1, 1), v1_); /* vt1 <- v[r-1][t-1..t+14] */ \
39
+ v1_ = tmp; \
40
+ a = _mm_add_epi8(xt1, vt1); /* a <- x[r-1][t-1..t+14] + v[r-1][t-1..t+14] */ \
41
+ ut = _mm_load_si128(&u[t]); /* ut <- u[t..t+15] */ \
42
+ b = _mm_add_epi8(_mm_load_si128(&y[t]), ut); /* b <- y[r-1][t..t+15] + u[r-1][t..t+15] */ \
43
+ x2t1= _mm_load_si128(&x2[t]); \
44
+ tmp = _mm_srli_si128(x2t1, 15); \
45
+ x2t1= _mm_or_si128(_mm_slli_si128(x2t1, 1), x21_); \
46
+ x21_= tmp; \
47
+ a2= _mm_add_epi8(x2t1, vt1); \
48
+ b2= _mm_add_epi8(_mm_load_si128(&y2[t]), ut);
49
+
50
+ #define __dp_code_block2 \
51
+ _mm_store_si128(&u[t], _mm_sub_epi8(z, vt1)); /* u[r][t..t+15] <- z - v[r-1][t-1..t+14] */ \
52
+ _mm_store_si128(&v[t], _mm_sub_epi8(z, ut)); /* v[r][t..t+15] <- z - u[r-1][t..t+15] */ \
53
+ tmp = _mm_sub_epi8(z, q_); \
54
+ a = _mm_sub_epi8(a, tmp); \
55
+ b = _mm_sub_epi8(b, tmp); \
56
+ tmp = _mm_sub_epi8(z, q2_); \
57
+ a2= _mm_sub_epi8(a2, tmp); \
58
+ b2= _mm_sub_epi8(b2, tmp);
59
+
60
+ int r, t, qe = q + e, n_col_, *off = 0, *off_end = 0, tlen_, qlen_, last_st, last_en, last_max_H = 0, wl, wr, max_sc, min_sc, long_thres, long_diff;
61
+ int with_cigar = !(flag&KSW_EZ_SCORE_ONLY), approx_max = !!(flag&KSW_EZ_APPROX_MAX);
62
+ int32_t *H = 0, H0 = 0, last_H0_t = 0;
63
+ uint8_t *qr, *sf, *mem, *mem2 = 0;
64
+ __m128i q_, q2_, qe_, qe2_, zero_, sc_mch_, sc_mis_, m1_, sc_N_;
65
+ __m128i *u, *v, *x, *y, *x2, *y2, *s, *p = 0;
66
+
67
+ ksw_reset_extz(ez);
68
+ if (m <= 1 || qlen <= 0 || tlen <= 0) return;
69
+
70
+ if (q2 + e2 < q + e) t = q, q = q2, q2 = t, t = e, e = e2, e2 = t; // make sure q+e no larger than q2+e2
71
+
72
+ zero_ = _mm_set1_epi8(0);
73
+ q_ = _mm_set1_epi8(q);
74
+ q2_ = _mm_set1_epi8(q2);
75
+ qe_ = _mm_set1_epi8(q + e);
76
+ qe2_ = _mm_set1_epi8(q2 + e2);
77
+ sc_mch_ = _mm_set1_epi8(mat[0]);
78
+ sc_mis_ = _mm_set1_epi8(mat[1]);
79
+ sc_N_ = mat[m*m-1] == 0? _mm_set1_epi8(-e2) : _mm_set1_epi8(mat[m*m-1]);
80
+ m1_ = _mm_set1_epi8(m - 1); // wildcard
81
+
82
+ if (w < 0) w = tlen > qlen? tlen : qlen;
83
+ wl = wr = w;
84
+ tlen_ = (tlen + 15) / 16;
85
+ n_col_ = qlen < tlen? qlen : tlen;
86
+ n_col_ = ((n_col_ < w + 1? n_col_ : w + 1) + 15) / 16 + 1;
87
+ qlen_ = (qlen + 15) / 16;
88
+ for (t = 1, max_sc = mat[0], min_sc = mat[1]; t < m * m; ++t) {
89
+ max_sc = max_sc > mat[t]? max_sc : mat[t];
90
+ min_sc = min_sc < mat[t]? min_sc : mat[t];
91
+ }
92
+ if (-min_sc > 2 * (q + e)) return; // otherwise, we won't see any mismatches
93
+
94
+ long_thres = e != e2? (q2 - q) / (e - e2) - 1 : 0;
95
+ if (q2 + e2 + long_thres * e2 > q + e + long_thres * e)
96
+ ++long_thres;
97
+ long_diff = long_thres * (e - e2) - (q2 - q) - e2;
98
+
99
+ mem = (uint8_t*)kcalloc(km, tlen_ * 8 + qlen_ + 1, 16);
100
+ u = (__m128i*)(((size_t)mem + 15) >> 4 << 4); // 16-byte aligned
101
+ v = u + tlen_, x = v + tlen_, y = x + tlen_, x2 = y + tlen_, y2 = x2 + tlen_;
102
+ s = y2 + tlen_, sf = (uint8_t*)(s + tlen_), qr = sf + tlen_ * 16;
103
+ memset(u, -q - e, tlen_ * 16);
104
+ memset(v, -q - e, tlen_ * 16);
105
+ memset(x, -q - e, tlen_ * 16);
106
+ memset(y, -q - e, tlen_ * 16);
107
+ memset(x2, -q2 - e2, tlen_ * 16);
108
+ memset(y2, -q2 - e2, tlen_ * 16);
109
+ if (!approx_max) {
110
+ H = (int32_t*)kmalloc(km, tlen_ * 16 * 4);
111
+ for (t = 0; t < tlen_ * 16; ++t) H[t] = KSW_NEG_INF;
112
+ }
113
+ if (with_cigar) {
114
+ mem2 = (uint8_t*)kmalloc(km, ((size_t)(qlen + tlen - 1) * n_col_ + 1) * 16);
115
+ p = (__m128i*)(((size_t)mem2 + 15) >> 4 << 4);
116
+ off = (int*)kmalloc(km, (qlen + tlen - 1) * sizeof(int) * 2);
117
+ off_end = off + qlen + tlen - 1;
118
+ }
119
+
120
+ for (t = 0; t < qlen; ++t) qr[t] = query[qlen - 1 - t];
121
+ memcpy(sf, target, tlen);
122
+
123
+ for (r = 0, last_st = last_en = -1; r < qlen + tlen - 1; ++r) {
124
+ int st = 0, en = tlen - 1, st0, en0, st_, en_;
125
+ int8_t x1, x21, v1;
126
+ uint8_t *qrr = qr + (qlen - 1 - r);
127
+ int8_t *u8 = (int8_t*)u, *v8 = (int8_t*)v, *x8 = (int8_t*)x, *x28 = (int8_t*)x2;
128
+ __m128i x1_, x21_, v1_;
129
+ // find the boundaries
130
+ if (st < r - qlen + 1) st = r - qlen + 1;
131
+ if (en > r) en = r;
132
+ if (st < (r-wr+1)>>1) st = (r-wr+1)>>1; // take the ceil
133
+ if (en > (r+wl)>>1) en = (r+wl)>>1; // take the floor
134
+ if (st > en) {
135
+ ez->zdropped = 1;
136
+ break;
137
+ }
138
+ st0 = st, en0 = en;
139
+ st = st / 16 * 16, en = (en + 16) / 16 * 16 - 1;
140
+ // set boundary conditions
141
+ if (st > 0) {
142
+ if (st - 1 >= last_st && st - 1 <= last_en) {
143
+ x1 = x8[st - 1], x21 = x28[st - 1], v1 = v8[st - 1]; // (r-1,s-1) calculated in the last round
144
+ } else {
145
+ x1 = -q - e, x21 = -q2 - e2;
146
+ v1 = -q - e;
147
+ }
148
+ } else {
149
+ x1 = -q - e, x21 = -q2 - e2;
150
+ v1 = r == 0? -q - e : r < long_thres? -e : r == long_thres? long_diff : -e2;
151
+ }
152
+ if (en >= r) {
153
+ ((int8_t*)y)[r] = -q - e, ((int8_t*)y2)[r] = -q2 - e2;
154
+ u8[r] = r == 0? -q - e : r < long_thres? -e : r == long_thres? long_diff : -e2;
155
+ }
156
+ // loop fission: set scores first
157
+ if (!(flag & KSW_EZ_GENERIC_SC)) {
158
+ for (t = st0; t <= en0; t += 16) {
159
+ __m128i sq, st, tmp, mask;
160
+ sq = _mm_loadu_si128((__m128i*)&sf[t]);
161
+ st = _mm_loadu_si128((__m128i*)&qrr[t]);
162
+ mask = _mm_or_si128(_mm_cmpeq_epi8(sq, m1_), _mm_cmpeq_epi8(st, m1_));
163
+ tmp = _mm_cmpeq_epi8(sq, st);
164
+ #ifdef __SSE4_1__
165
+ tmp = _mm_blendv_epi8(sc_mis_, sc_mch_, tmp);
166
+ tmp = _mm_blendv_epi8(tmp, sc_N_, mask);
167
+ #else
168
+ tmp = _mm_or_si128(_mm_andnot_si128(tmp, sc_mis_), _mm_and_si128(tmp, sc_mch_));
169
+ tmp = _mm_or_si128(_mm_andnot_si128(mask, tmp), _mm_and_si128(mask, sc_N_));
170
+ #endif
171
+ _mm_storeu_si128((__m128i*)((int8_t*)s + t), tmp);
172
+ }
173
+ } else {
174
+ for (t = st0; t <= en0; ++t)
175
+ ((uint8_t*)s)[t] = mat[sf[t] * m + qrr[t]];
176
+ }
177
+ // core loop
178
+ x1_ = _mm_cvtsi32_si128((uint8_t)x1);
179
+ x21_ = _mm_cvtsi32_si128((uint8_t)x21);
180
+ v1_ = _mm_cvtsi32_si128((uint8_t)v1);
181
+ st_ = st / 16, en_ = en / 16;
182
+ assert(en_ - st_ + 1 <= n_col_);
183
+ if (!with_cigar) { // score only
184
+ for (t = st_; t <= en_; ++t) {
185
+ __m128i z, a, b, a2, b2, xt1, x2t1, vt1, ut, tmp;
186
+ __dp_code_block1;
187
+ #ifdef __SSE4_1__
188
+ z = _mm_max_epi8(z, a);
189
+ z = _mm_max_epi8(z, b);
190
+ z = _mm_max_epi8(z, a2);
191
+ z = _mm_max_epi8(z, b2);
192
+ z = _mm_min_epi8(z, sc_mch_);
193
+ __dp_code_block2; // save u[] and v[]; update a, b, a2 and b2
194
+ _mm_store_si128(&x[t], _mm_sub_epi8(_mm_max_epi8(a, zero_), qe_));
195
+ _mm_store_si128(&y[t], _mm_sub_epi8(_mm_max_epi8(b, zero_), qe_));
196
+ _mm_store_si128(&x2[t], _mm_sub_epi8(_mm_max_epi8(a2, zero_), qe2_));
197
+ _mm_store_si128(&y2[t], _mm_sub_epi8(_mm_max_epi8(b2, zero_), qe2_));
198
+ #else
199
+ tmp = _mm_cmpgt_epi8(a, z);
200
+ z = _mm_or_si128(_mm_andnot_si128(tmp, z), _mm_and_si128(tmp, a));
201
+ tmp = _mm_cmpgt_epi8(b, z);
202
+ z = _mm_or_si128(_mm_andnot_si128(tmp, z), _mm_and_si128(tmp, b));
203
+ tmp = _mm_cmpgt_epi8(a2, z);
204
+ z = _mm_or_si128(_mm_andnot_si128(tmp, z), _mm_and_si128(tmp, a2));
205
+ tmp = _mm_cmpgt_epi8(b2, z);
206
+ z = _mm_or_si128(_mm_andnot_si128(tmp, z), _mm_and_si128(tmp, b2));
207
+ tmp = _mm_cmplt_epi8(sc_mch_, z);
208
+ z = _mm_or_si128(_mm_and_si128(tmp, sc_mch_), _mm_andnot_si128(tmp, z));
209
+ __dp_code_block2;
210
+ tmp = _mm_cmpgt_epi8(a, zero_);
211
+ _mm_store_si128(&x[t], _mm_sub_epi8(_mm_and_si128(tmp, a), qe_));
212
+ tmp = _mm_cmpgt_epi8(b, zero_);
213
+ _mm_store_si128(&y[t], _mm_sub_epi8(_mm_and_si128(tmp, b), qe_));
214
+ tmp = _mm_cmpgt_epi8(a2, zero_);
215
+ _mm_store_si128(&x2[t], _mm_sub_epi8(_mm_and_si128(tmp, a2), qe2_));
216
+ tmp = _mm_cmpgt_epi8(b2, zero_);
217
+ _mm_store_si128(&y2[t], _mm_sub_epi8(_mm_and_si128(tmp, b2), qe2_));
218
+ #endif
219
+ }
220
+ } else if (!(flag&KSW_EZ_RIGHT)) { // gap left-alignment
221
+ __m128i *pr = p + (size_t)r * n_col_ - st_;
222
+ off[r] = st, off_end[r] = en;
223
+ for (t = st_; t <= en_; ++t) {
224
+ __m128i d, z, a, b, a2, b2, xt1, x2t1, vt1, ut, tmp;
225
+ __dp_code_block1;
226
+ #ifdef __SSE4_1__
227
+ d = _mm_and_si128(_mm_cmpgt_epi8(a, z), _mm_set1_epi8(1)); // d = a > z? 1 : 0
228
+ z = _mm_max_epi8(z, a);
229
+ d = _mm_blendv_epi8(d, _mm_set1_epi8(2), _mm_cmpgt_epi8(b, z)); // d = b > z? 2 : d
230
+ z = _mm_max_epi8(z, b);
231
+ d = _mm_blendv_epi8(d, _mm_set1_epi8(3), _mm_cmpgt_epi8(a2, z)); // d = a2 > z? 3 : d
232
+ z = _mm_max_epi8(z, a2);
233
+ d = _mm_blendv_epi8(d, _mm_set1_epi8(4), _mm_cmpgt_epi8(b2, z)); // d = a2 > z? 3 : d
234
+ z = _mm_max_epi8(z, b2);
235
+ z = _mm_min_epi8(z, sc_mch_);
236
+ #else // we need to emulate SSE4.1 intrinsics _mm_max_epi8() and _mm_blendv_epi8()
237
+ tmp = _mm_cmpgt_epi8(a, z);
238
+ d = _mm_and_si128(tmp, _mm_set1_epi8(1));
239
+ z = _mm_or_si128(_mm_andnot_si128(tmp, z), _mm_and_si128(tmp, a));
240
+ tmp = _mm_cmpgt_epi8(b, z);
241
+ d = _mm_or_si128(_mm_andnot_si128(tmp, d), _mm_and_si128(tmp, _mm_set1_epi8(2)));
242
+ z = _mm_or_si128(_mm_andnot_si128(tmp, z), _mm_and_si128(tmp, b));
243
+ tmp = _mm_cmpgt_epi8(a2, z);
244
+ d = _mm_or_si128(_mm_andnot_si128(tmp, d), _mm_and_si128(tmp, _mm_set1_epi8(3)));
245
+ z = _mm_or_si128(_mm_andnot_si128(tmp, z), _mm_and_si128(tmp, a2));
246
+ tmp = _mm_cmpgt_epi8(b2, z);
247
+ d = _mm_or_si128(_mm_andnot_si128(tmp, d), _mm_and_si128(tmp, _mm_set1_epi8(4)));
248
+ z = _mm_or_si128(_mm_andnot_si128(tmp, z), _mm_and_si128(tmp, b2));
249
+ tmp = _mm_cmplt_epi8(sc_mch_, z);
250
+ z = _mm_or_si128(_mm_and_si128(tmp, sc_mch_), _mm_andnot_si128(tmp, z));
251
+ #endif
252
+ __dp_code_block2;
253
+ tmp = _mm_cmpgt_epi8(a, zero_);
254
+ _mm_store_si128(&x[t], _mm_sub_epi8(_mm_and_si128(tmp, a), qe_));
255
+ d = _mm_or_si128(d, _mm_and_si128(tmp, _mm_set1_epi8(0x08))); // d = a > 0? 1<<3 : 0
256
+ tmp = _mm_cmpgt_epi8(b, zero_);
257
+ _mm_store_si128(&y[t], _mm_sub_epi8(_mm_and_si128(tmp, b), qe_));
258
+ d = _mm_or_si128(d, _mm_and_si128(tmp, _mm_set1_epi8(0x10))); // d = b > 0? 1<<4 : 0
259
+ tmp = _mm_cmpgt_epi8(a2, zero_);
260
+ _mm_store_si128(&x2[t], _mm_sub_epi8(_mm_and_si128(tmp, a2), qe2_));
261
+ d = _mm_or_si128(d, _mm_and_si128(tmp, _mm_set1_epi8(0x20))); // d = a > 0? 1<<5 : 0
262
+ tmp = _mm_cmpgt_epi8(b2, zero_);
263
+ _mm_store_si128(&y2[t], _mm_sub_epi8(_mm_and_si128(tmp, b2), qe2_));
264
+ d = _mm_or_si128(d, _mm_and_si128(tmp, _mm_set1_epi8(0x40))); // d = b > 0? 1<<6 : 0
265
+ _mm_store_si128(&pr[t], d);
266
+ }
267
+ } else { // gap right-alignment
268
+ __m128i *pr = p + (size_t)r * n_col_ - st_;
269
+ off[r] = st, off_end[r] = en;
270
+ for (t = st_; t <= en_; ++t) {
271
+ __m128i d, z, a, b, a2, b2, xt1, x2t1, vt1, ut, tmp;
272
+ __dp_code_block1;
273
+ #ifdef __SSE4_1__
274
+ d = _mm_andnot_si128(_mm_cmpgt_epi8(z, a), _mm_set1_epi8(1)); // d = z > a? 0 : 1
275
+ z = _mm_max_epi8(z, a);
276
+ d = _mm_blendv_epi8(_mm_set1_epi8(2), d, _mm_cmpgt_epi8(z, b)); // d = z > b? d : 2
277
+ z = _mm_max_epi8(z, b);
278
+ d = _mm_blendv_epi8(_mm_set1_epi8(3), d, _mm_cmpgt_epi8(z, a2)); // d = z > a2? d : 3
279
+ z = _mm_max_epi8(z, a2);
280
+ d = _mm_blendv_epi8(_mm_set1_epi8(4), d, _mm_cmpgt_epi8(z, b2)); // d = z > b2? d : 4
281
+ z = _mm_max_epi8(z, b2);
282
+ z = _mm_min_epi8(z, sc_mch_);
283
+ #else // we need to emulate SSE4.1 intrinsics _mm_max_epi8() and _mm_blendv_epi8()
284
+ tmp = _mm_cmpgt_epi8(z, a);
285
+ d = _mm_andnot_si128(tmp, _mm_set1_epi8(1));
286
+ z = _mm_or_si128(_mm_and_si128(tmp, z), _mm_andnot_si128(tmp, a));
287
+ tmp = _mm_cmpgt_epi8(z, b);
288
+ d = _mm_or_si128(_mm_and_si128(tmp, d), _mm_andnot_si128(tmp, _mm_set1_epi8(2)));
289
+ z = _mm_or_si128(_mm_and_si128(tmp, z), _mm_andnot_si128(tmp, b));
290
+ tmp = _mm_cmpgt_epi8(z, a2);
291
+ d = _mm_or_si128(_mm_and_si128(tmp, d), _mm_andnot_si128(tmp, _mm_set1_epi8(3)));
292
+ z = _mm_or_si128(_mm_and_si128(tmp, z), _mm_andnot_si128(tmp, a2));
293
+ tmp = _mm_cmpgt_epi8(z, b2);
294
+ d = _mm_or_si128(_mm_and_si128(tmp, d), _mm_andnot_si128(tmp, _mm_set1_epi8(4)));
295
+ z = _mm_or_si128(_mm_and_si128(tmp, z), _mm_andnot_si128(tmp, b2));
296
+ tmp = _mm_cmplt_epi8(sc_mch_, z);
297
+ z = _mm_or_si128(_mm_and_si128(tmp, sc_mch_), _mm_andnot_si128(tmp, z));
298
+ #endif
299
+ __dp_code_block2;
300
+ tmp = _mm_cmpgt_epi8(zero_, a);
301
+ _mm_store_si128(&x[t], _mm_sub_epi8(_mm_andnot_si128(tmp, a), qe_));
302
+ d = _mm_or_si128(d, _mm_andnot_si128(tmp, _mm_set1_epi8(0x08))); // d = a > 0? 1<<3 : 0
303
+ tmp = _mm_cmpgt_epi8(zero_, b);
304
+ _mm_store_si128(&y[t], _mm_sub_epi8(_mm_andnot_si128(tmp, b), qe_));
305
+ d = _mm_or_si128(d, _mm_andnot_si128(tmp, _mm_set1_epi8(0x10))); // d = b > 0? 1<<4 : 0
306
+ tmp = _mm_cmpgt_epi8(zero_, a2);
307
+ _mm_store_si128(&x2[t], _mm_sub_epi8(_mm_andnot_si128(tmp, a2), qe2_));
308
+ d = _mm_or_si128(d, _mm_andnot_si128(tmp, _mm_set1_epi8(0x20))); // d = a > 0? 1<<5 : 0
309
+ tmp = _mm_cmpgt_epi8(zero_, b2);
310
+ _mm_store_si128(&y2[t], _mm_sub_epi8(_mm_andnot_si128(tmp, b2), qe2_));
311
+ d = _mm_or_si128(d, _mm_andnot_si128(tmp, _mm_set1_epi8(0x40))); // d = b > 0? 1<<6 : 0
312
+ _mm_store_si128(&pr[t], d);
313
+ }
314
+ }
315
+ if (!approx_max) { // find the exact max with a 32-bit score array
316
+ int32_t max_H, max_t;
317
+ // compute H[], max_H and max_t
318
+ if (r > 0) {
319
+ int32_t HH[4], tt[4], en1 = st0 + (en0 - st0) / 4 * 4, i;
320
+ __m128i max_H_, max_t_, t_, t4_ = _mm_set1_epi32(4);
321
+ max_H = H[en0] = en0 > 0? H[en0-1] + u8[en0] : H[en0] + v8[en0]; // special casing the last element
322
+ max_t = en0;
323
+ max_H_ = _mm_set1_epi32(max_H);
324
+ max_t_ = _mm_set1_epi32(max_t);
325
+ t_ = _mm_set1_epi32(st0);
326
+ for (t = st0; t < en1; t += 4) { // this implements: H[t]+=v8[t]-qe; if(H[t]>max_H) max_H=H[t],max_t=t;
327
+ __m128i H1, tmp, v_;
328
+ H1 = _mm_loadu_si128((__m128i*)&H[t]);
329
+ v_ = ksw_i8x4_to_i32x4(&v8[t]);
330
+ H1 = _mm_add_epi32(H1, v_);
331
+ _mm_storeu_si128((__m128i*)&H[t], H1);
332
+ tmp = _mm_cmpgt_epi32(H1, max_H_);
333
+ #ifdef __SSE4_1__
334
+ max_H_ = _mm_max_epi32(max_H_, H1);
335
+ max_t_ = _mm_blendv_epi8(max_t_, t_, tmp);
336
+ #else
337
+ max_H_ = _mm_or_si128(_mm_and_si128(tmp, H1), _mm_andnot_si128(tmp, max_H_));
338
+ max_t_ = _mm_or_si128(_mm_and_si128(tmp, t_), _mm_andnot_si128(tmp, max_t_));
339
+ #endif
340
+ t_ = _mm_add_epi32(t_, t4_);
341
+ }
342
+ _mm_storeu_si128((__m128i*)HH, max_H_);
343
+ _mm_storeu_si128((__m128i*)tt, max_t_);
344
+ for (i = 0; i < 4; ++i)
345
+ if (max_H < HH[i]) max_H = HH[i], max_t = tt[i] + i;
346
+ for (; t < en0; ++t) { // for the rest of values that haven't been computed with SSE
347
+ H[t] += (int32_t)v8[t];
348
+ if (H[t] > max_H)
349
+ max_H = H[t], max_t = t;
350
+ }
351
+ } else H[0] = v8[0] - qe, max_H = H[0], max_t = 0; // special casing r==0
352
+ // update ez
353
+ if (en0 == tlen - 1 && H[en0] > ez->mte)
354
+ ez->mte = H[en0], ez->mte_q = r - en0;
355
+ if (r - st0 == qlen - 1 && H[st0] > ez->mqe)
356
+ ez->mqe = H[st0], ez->mqe_t = st0;
357
+ if (ksw_apply_zdrop(ez, 1, max_H, r, max_t, zdrop, e2)) break;
358
+ if (r == qlen + tlen - 2 && en0 == tlen - 1)
359
+ ez->score = H[tlen - 1];
360
+ // early stopping in the extension-only mode; this block should not change the alignment
361
+ if (flag & KSW_EZ_EXTZ_ONLY) {
362
+ int32_t rH = last_max_H > max_H? last_max_H : max_H; // NB: if diagonal r is on the optimal path, r-1 or r+1 is not on the optimal path
363
+ int32_t rq = qlen - (r - st0), rt = tlen - en0;
364
+ // 3 conditions: hitting bottom of the DP matrix, hitting the right boundary of the matrix, and bracketing the diagonal
365
+ int32_t rm = rq >= tlen - st0? tlen - st0 : rt >= qlen - (r - en0)? qlen - (r - en0) : tlen + qlen - 1 - r;
366
+ if (rH + rm * max_sc + end_bonus < ez->max) break;
367
+ }
368
+ last_max_H = max_H; // need this for calculating rH
369
+ } else { // find approximate max; Z-drop might be inaccurate, too.
370
+ if (r > 0) {
371
+ if (last_H0_t >= st0 && last_H0_t <= en0 && last_H0_t + 1 >= st0 && last_H0_t + 1 <= en0) {
372
+ int32_t d0 = v8[last_H0_t];
373
+ int32_t d1 = u8[last_H0_t + 1];
374
+ if (d0 > d1) H0 += d0;
375
+ else H0 += d1, ++last_H0_t;
376
+ } else if (last_H0_t >= st0 && last_H0_t <= en0) {
377
+ H0 += v8[last_H0_t];
378
+ } else {
379
+ ++last_H0_t, H0 += u8[last_H0_t];
380
+ }
381
+ } else H0 = v8[0] - qe, last_H0_t = 0;
382
+ if ((flag & KSW_EZ_APPROX_DROP) && ksw_apply_zdrop(ez, 1, H0, r, last_H0_t, zdrop, e2)) break;
383
+ if (r == qlen + tlen - 2 && en0 == tlen - 1)
384
+ ez->score = H0;
385
+ }
386
+ last_st = st, last_en = en;
387
+ //for (t = st0; t <= en0; ++t) printf("(%d,%d)\t(%d,%d,%d,%d)\t%d\n", r, t, ((int8_t*)u)[t], ((int8_t*)v)[t], ((int8_t*)x)[t], ((int8_t*)y)[t], H[t]); // for debugging
388
+ }
389
+ kfree(km, mem);
390
+ if (!approx_max) kfree(km, H);
391
+ if (with_cigar) { // backtrack
392
+ int rev_cigar = !!(flag & KSW_EZ_REV_CIGAR);
393
+ if (!ez->zdropped && !(flag&KSW_EZ_EXTZ_ONLY)) {
394
+ ksw_backtrack(km, 1, rev_cigar, 0, (uint8_t*)p, off, off_end, n_col_*16, tlen-1, qlen-1, &ez->m_cigar, &ez->n_cigar, &ez->cigar);
395
+ } else if ((flag&KSW_EZ_EXTZ_ONLY) && ez->mqe + end_bonus > (int)ez->max) {
396
+ ez->reach_end = 1;
397
+ ksw_backtrack(km, 1, rev_cigar, 0, (uint8_t*)p, off, off_end, n_col_*16, ez->mqe_t, qlen-1, &ez->m_cigar, &ez->n_cigar, &ez->cigar);
398
+ } else if (ez->max_t >= 0 && ez->max_q >= 0) {
399
+ ksw_backtrack(km, 1, rev_cigar, 0, (uint8_t*)p, off, off_end, n_col_*16, ez->max_t, ez->max_q, &ez->m_cigar, &ez->n_cigar, &ez->cigar);
400
+ }
401
+ kfree(km, mem2); kfree(km, off);
402
+ }
403
+ }