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.
- checksums.yaml +7 -0
- data/LICENSE.txt +21 -0
- data/README.md +119 -0
- data/ext/minibwa/extconf.rb +105 -0
- data/ext/minibwa/mb_buffer.c +113 -0
- data/ext/minibwa/mb_hit.c +192 -0
- data/ext/minibwa/mb_index.c +462 -0
- data/ext/minibwa/mb_index_build.c +174 -0
- data/ext/minibwa/mb_options.c +301 -0
- data/ext/minibwa/minibwa/LICENSE.txt +37 -0
- data/ext/minibwa/minibwa/align.c +930 -0
- data/ext/minibwa/minibwa/bseq.h +45 -0
- data/ext/minibwa/minibwa/bwt.c +715 -0
- data/ext/minibwa/minibwa/bwt.h +86 -0
- data/ext/minibwa/minibwa/cs.c +161 -0
- data/ext/minibwa/minibwa/format.c +356 -0
- data/ext/minibwa/minibwa/index.c +342 -0
- data/ext/minibwa/minibwa/kalloc.c +224 -0
- data/ext/minibwa/minibwa/kalloc.h +54 -0
- data/ext/minibwa/minibwa/ketopt.h +123 -0
- data/ext/minibwa/minibwa/kommon.c +374 -0
- data/ext/minibwa/minibwa/kommon.h +85 -0
- data/ext/minibwa/minibwa/kseq.h +256 -0
- data/ext/minibwa/minibwa/ksort.h +163 -0
- data/ext/minibwa/minibwa/ksw2.h +220 -0
- data/ext/minibwa/minibwa/ksw2_extd2_sse.c +403 -0
- data/ext/minibwa/minibwa/ksw2_extz2_sse.c +296 -0
- data/ext/minibwa/minibwa/ksw2_ll_sse.c +341 -0
- data/ext/minibwa/minibwa/kthread.h +15 -0
- data/ext/minibwa/minibwa/l2bit.c +479 -0
- data/ext/minibwa/minibwa/l2bit.h +72 -0
- data/ext/minibwa/minibwa/lchain.c +231 -0
- data/ext/minibwa/minibwa/libsais.c +6985 -0
- data/ext/minibwa/minibwa/libsais.h +106 -0
- data/ext/minibwa/minibwa/libsais64.c +7064 -0
- data/ext/minibwa/minibwa/libsais64.h +81 -0
- data/ext/minibwa/minibwa/map-algo.c +769 -0
- data/ext/minibwa/minibwa/mbpriv.h +148 -0
- data/ext/minibwa/minibwa/minibwa.h +176 -0
- data/ext/minibwa/minibwa/options.c +116 -0
- data/ext/minibwa/minibwa/pe.c +559 -0
- data/ext/minibwa/minibwa/s2n-lite.h +59 -0
- data/ext/minibwa/minibwa/seed.c +354 -0
- data/ext/minibwa/minibwa.c +67 -0
- data/ext/minibwa/minibwa.h +51 -0
- data/lib/minibwa/hit.rb +110 -0
- data/lib/minibwa/index.rb +77 -0
- data/lib/minibwa/options.rb +235 -0
- data/lib/minibwa/sam.rb +85 -0
- data/lib/minibwa/version.rb +6 -0
- data/lib/minibwa.rb +11 -0
- metadata +88 -0
|
@@ -0,0 +1,296 @@
|
|
|
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
|
+
void ksw_extz2_sse(void *km, int qlen, const uint8_t *query, int tlen, const uint8_t *target, int8_t m, const int8_t *mat, int8_t q, int8_t e, int w, int zdrop, int end_bonus, int flag, ksw_extz_t *ez)
|
|
17
|
+
{
|
|
18
|
+
#define __dp_code_block1 \
|
|
19
|
+
z = _mm_add_epi8(_mm_load_si128(&s[t]), qe2_); \
|
|
20
|
+
xt1 = _mm_load_si128(&x[t]); /* xt1 <- x[r-1][t..t+15] */ \
|
|
21
|
+
tmp = _mm_srli_si128(xt1, 15); /* tmp <- x[r-1][t+15] */ \
|
|
22
|
+
xt1 = _mm_or_si128(_mm_slli_si128(xt1, 1), x1_); /* xt1 <- x[r-1][t-1..t+14] */ \
|
|
23
|
+
x1_ = tmp; \
|
|
24
|
+
vt1 = _mm_load_si128(&v[t]); /* vt1 <- v[r-1][t..t+15] */ \
|
|
25
|
+
tmp = _mm_srli_si128(vt1, 15); /* tmp <- v[r-1][t+15] */ \
|
|
26
|
+
vt1 = _mm_or_si128(_mm_slli_si128(vt1, 1), v1_); /* vt1 <- v[r-1][t-1..t+14] */ \
|
|
27
|
+
v1_ = tmp; \
|
|
28
|
+
a = _mm_add_epi8(xt1, vt1); /* a <- x[r-1][t-1..t+14] + v[r-1][t-1..t+14] */ \
|
|
29
|
+
ut = _mm_load_si128(&u[t]); /* ut <- u[t..t+15] */ \
|
|
30
|
+
b = _mm_add_epi8(_mm_load_si128(&y[t]), ut); /* b <- y[r-1][t..t+15] + u[r-1][t..t+15] */
|
|
31
|
+
|
|
32
|
+
#define __dp_code_block2 \
|
|
33
|
+
z = _mm_max_epu8(z, b); /* z = max(z, b); this works because both are non-negative */ \
|
|
34
|
+
z = _mm_min_epu8(z, max_sc_); \
|
|
35
|
+
_mm_store_si128(&u[t], _mm_sub_epi8(z, vt1)); /* u[r][t..t+15] <- z - v[r-1][t-1..t+14] */ \
|
|
36
|
+
_mm_store_si128(&v[t], _mm_sub_epi8(z, ut)); /* v[r][t..t+15] <- z - u[r-1][t..t+15] */ \
|
|
37
|
+
z = _mm_sub_epi8(z, q_); \
|
|
38
|
+
a = _mm_sub_epi8(a, z); \
|
|
39
|
+
b = _mm_sub_epi8(b, z);
|
|
40
|
+
|
|
41
|
+
int r, t, qe = q + e, n_col_, *off = 0, *off_end = 0, tlen_, qlen_, last_st, last_en, wl, wr, max_sc, min_sc;
|
|
42
|
+
int with_cigar = !(flag&KSW_EZ_SCORE_ONLY), approx_max = !!(flag&KSW_EZ_APPROX_MAX);
|
|
43
|
+
int32_t *H = 0, H0 = 0, last_H0_t = 0;
|
|
44
|
+
uint8_t *qr, *sf, *mem, *mem2 = 0;
|
|
45
|
+
__m128i q_, qe2_, zero_, flag1_, flag2_, flag8_, flag16_, sc_mch_, sc_mis_, sc_N_, m1_, max_sc_;
|
|
46
|
+
__m128i *u, *v, *x, *y, *s, *p = 0;
|
|
47
|
+
|
|
48
|
+
ksw_reset_extz(ez);
|
|
49
|
+
if (m <= 0 || qlen <= 0 || tlen <= 0) return;
|
|
50
|
+
|
|
51
|
+
zero_ = _mm_set1_epi8(0);
|
|
52
|
+
q_ = _mm_set1_epi8(q);
|
|
53
|
+
qe2_ = _mm_set1_epi8((q + e) * 2);
|
|
54
|
+
flag1_ = _mm_set1_epi8(1);
|
|
55
|
+
flag2_ = _mm_set1_epi8(2);
|
|
56
|
+
flag8_ = _mm_set1_epi8(0x08);
|
|
57
|
+
flag16_ = _mm_set1_epi8(0x10);
|
|
58
|
+
sc_mch_ = _mm_set1_epi8(mat[0]);
|
|
59
|
+
sc_mis_ = _mm_set1_epi8(mat[1]);
|
|
60
|
+
sc_N_ = mat[m*m-1] == 0? _mm_set1_epi8(-e) : _mm_set1_epi8(mat[m*m-1]);
|
|
61
|
+
m1_ = _mm_set1_epi8(m - 1); // wildcard
|
|
62
|
+
max_sc_ = _mm_set1_epi8(mat[0] + (q + e) * 2);
|
|
63
|
+
|
|
64
|
+
if (w < 0) w = tlen > qlen? tlen : qlen;
|
|
65
|
+
wl = wr = w;
|
|
66
|
+
tlen_ = (tlen + 15) / 16;
|
|
67
|
+
n_col_ = qlen < tlen? qlen : tlen;
|
|
68
|
+
n_col_ = ((n_col_ < w + 1? n_col_ : w + 1) + 15) / 16 + 1;
|
|
69
|
+
qlen_ = (qlen + 15) / 16;
|
|
70
|
+
for (t = 1, max_sc = mat[0], min_sc = mat[1]; t < m * m; ++t) {
|
|
71
|
+
max_sc = max_sc > mat[t]? max_sc : mat[t];
|
|
72
|
+
min_sc = min_sc < mat[t]? min_sc : mat[t];
|
|
73
|
+
}
|
|
74
|
+
if (-min_sc > 2 * (q + e)) return; // otherwise, we won't see any mismatches
|
|
75
|
+
|
|
76
|
+
mem = (uint8_t*)kcalloc(km, tlen_ * 6 + qlen_ + 1, 16);
|
|
77
|
+
u = (__m128i*)(((size_t)mem + 15) >> 4 << 4); // 16-byte aligned
|
|
78
|
+
v = u + tlen_, x = v + tlen_, y = x + tlen_, s = y + tlen_, sf = (uint8_t*)(s + tlen_), qr = sf + tlen_ * 16;
|
|
79
|
+
if (!approx_max) {
|
|
80
|
+
H = (int32_t*)kmalloc(km, tlen_ * 16 * 4);
|
|
81
|
+
for (t = 0; t < tlen_ * 16; ++t) H[t] = KSW_NEG_INF;
|
|
82
|
+
}
|
|
83
|
+
if (with_cigar) {
|
|
84
|
+
mem2 = (uint8_t*)kmalloc(km, ((size_t)(qlen + tlen - 1) * n_col_ + 1) * 16);
|
|
85
|
+
p = (__m128i*)(((size_t)mem2 + 15) >> 4 << 4);
|
|
86
|
+
off = (int*)kmalloc(km, (qlen + tlen - 1) * sizeof(int) * 2);
|
|
87
|
+
off_end = off + qlen + tlen - 1;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
for (t = 0; t < qlen; ++t) qr[t] = query[qlen - 1 - t];
|
|
91
|
+
memcpy(sf, target, tlen);
|
|
92
|
+
|
|
93
|
+
for (r = 0, last_st = last_en = -1; r < qlen + tlen - 1; ++r) {
|
|
94
|
+
int st = 0, en = tlen - 1, st0, en0, st_, en_;
|
|
95
|
+
int8_t x1, v1;
|
|
96
|
+
uint8_t *qrr = qr + (qlen - 1 - r), *u8 = (uint8_t*)u, *v8 = (uint8_t*)v;
|
|
97
|
+
__m128i x1_, v1_;
|
|
98
|
+
// find the boundaries
|
|
99
|
+
if (st < r - qlen + 1) st = r - qlen + 1;
|
|
100
|
+
if (en > r) en = r;
|
|
101
|
+
if (st < (r-wr+1)>>1) st = (r-wr+1)>>1; // take the ceil
|
|
102
|
+
if (en > (r+wl)>>1) en = (r+wl)>>1; // take the floor
|
|
103
|
+
if (st > en) {
|
|
104
|
+
ez->zdropped = 1;
|
|
105
|
+
break;
|
|
106
|
+
}
|
|
107
|
+
st0 = st, en0 = en;
|
|
108
|
+
st = st / 16 * 16, en = (en + 16) / 16 * 16 - 1;
|
|
109
|
+
// set boundary conditions
|
|
110
|
+
if (st > 0) {
|
|
111
|
+
if (st - 1 >= last_st && st - 1 <= last_en)
|
|
112
|
+
x1 = ((uint8_t*)x)[st - 1], v1 = v8[st - 1]; // (r-1,s-1) calculated in the last round
|
|
113
|
+
else x1 = v1 = 0; // not calculated; set to zeros
|
|
114
|
+
} else x1 = 0, v1 = r? q : 0;
|
|
115
|
+
if (en >= r) ((uint8_t*)y)[r] = 0, u8[r] = r? q : 0;
|
|
116
|
+
// loop fission: set scores first
|
|
117
|
+
if (!(flag & KSW_EZ_GENERIC_SC)) {
|
|
118
|
+
for (t = st0; t <= en0; t += 16) {
|
|
119
|
+
__m128i sq, st, tmp, mask;
|
|
120
|
+
sq = _mm_loadu_si128((__m128i*)&sf[t]);
|
|
121
|
+
st = _mm_loadu_si128((__m128i*)&qrr[t]);
|
|
122
|
+
mask = _mm_or_si128(_mm_cmpeq_epi8(sq, m1_), _mm_cmpeq_epi8(st, m1_));
|
|
123
|
+
tmp = _mm_cmpeq_epi8(sq, st);
|
|
124
|
+
#ifdef __SSE4_1__
|
|
125
|
+
tmp = _mm_blendv_epi8(sc_mis_, sc_mch_, tmp);
|
|
126
|
+
tmp = _mm_blendv_epi8(tmp, sc_N_, mask);
|
|
127
|
+
#else
|
|
128
|
+
tmp = _mm_or_si128(_mm_andnot_si128(tmp, sc_mis_), _mm_and_si128(tmp, sc_mch_));
|
|
129
|
+
tmp = _mm_or_si128(_mm_andnot_si128(mask, tmp), _mm_and_si128(mask, sc_N_));
|
|
130
|
+
#endif
|
|
131
|
+
_mm_storeu_si128((__m128i*)((uint8_t*)s + t), tmp);
|
|
132
|
+
}
|
|
133
|
+
} else {
|
|
134
|
+
for (t = st0; t <= en0; ++t)
|
|
135
|
+
((uint8_t*)s)[t] = mat[sf[t] * m + qrr[t]];
|
|
136
|
+
}
|
|
137
|
+
// core loop
|
|
138
|
+
x1_ = _mm_cvtsi32_si128(x1);
|
|
139
|
+
v1_ = _mm_cvtsi32_si128(v1);
|
|
140
|
+
st_ = st / 16, en_ = en / 16;
|
|
141
|
+
assert(en_ - st_ + 1 <= n_col_);
|
|
142
|
+
if (!with_cigar) { // score only
|
|
143
|
+
for (t = st_; t <= en_; ++t) {
|
|
144
|
+
__m128i z, a, b, xt1, vt1, ut, tmp;
|
|
145
|
+
__dp_code_block1;
|
|
146
|
+
#ifdef __SSE4_1__
|
|
147
|
+
z = _mm_max_epi8(z, a); // z = z > a? z : a (signed)
|
|
148
|
+
#else // we need to emulate SSE4.1 intrinsics _mm_max_epi8()
|
|
149
|
+
z = _mm_and_si128(z, _mm_cmpgt_epi8(z, zero_)); // z = z > 0? z : 0;
|
|
150
|
+
z = _mm_max_epu8(z, a); // z = max(z, a); this works because both are non-negative
|
|
151
|
+
#endif
|
|
152
|
+
__dp_code_block2;
|
|
153
|
+
#ifdef __SSE4_1__
|
|
154
|
+
_mm_store_si128(&x[t], _mm_max_epi8(a, zero_));
|
|
155
|
+
_mm_store_si128(&y[t], _mm_max_epi8(b, zero_));
|
|
156
|
+
#else
|
|
157
|
+
tmp = _mm_cmpgt_epi8(a, zero_);
|
|
158
|
+
_mm_store_si128(&x[t], _mm_and_si128(a, tmp));
|
|
159
|
+
tmp = _mm_cmpgt_epi8(b, zero_);
|
|
160
|
+
_mm_store_si128(&y[t], _mm_and_si128(b, tmp));
|
|
161
|
+
#endif
|
|
162
|
+
}
|
|
163
|
+
} else if (!(flag&KSW_EZ_RIGHT)) { // gap left-alignment
|
|
164
|
+
__m128i *pr = p + (size_t)r * n_col_ - st_;
|
|
165
|
+
off[r] = st, off_end[r] = en;
|
|
166
|
+
for (t = st_; t <= en_; ++t) {
|
|
167
|
+
__m128i d, z, a, b, xt1, vt1, ut, tmp;
|
|
168
|
+
__dp_code_block1;
|
|
169
|
+
d = _mm_and_si128(_mm_cmpgt_epi8(a, z), flag1_); // d = a > z? 1 : 0
|
|
170
|
+
#ifdef __SSE4_1__
|
|
171
|
+
z = _mm_max_epi8(z, a); // z = z > a? z : a (signed)
|
|
172
|
+
tmp = _mm_cmpgt_epi8(b, z);
|
|
173
|
+
d = _mm_blendv_epi8(d, flag2_, tmp); // d = b > z? 2 : d
|
|
174
|
+
#else // we need to emulate SSE4.1 intrinsics _mm_max_epi8() and _mm_blendv_epi8()
|
|
175
|
+
z = _mm_and_si128(z, _mm_cmpgt_epi8(z, zero_)); // z = z > 0? z : 0;
|
|
176
|
+
z = _mm_max_epu8(z, a); // z = max(z, a); this works because both are non-negative
|
|
177
|
+
tmp = _mm_cmpgt_epi8(b, z);
|
|
178
|
+
d = _mm_or_si128(_mm_andnot_si128(tmp, d), _mm_and_si128(tmp, flag2_)); // d = b > z? 2 : d; emulating blendv
|
|
179
|
+
#endif
|
|
180
|
+
__dp_code_block2;
|
|
181
|
+
tmp = _mm_cmpgt_epi8(a, zero_);
|
|
182
|
+
_mm_store_si128(&x[t], _mm_and_si128(tmp, a));
|
|
183
|
+
d = _mm_or_si128(d, _mm_and_si128(tmp, flag8_)); // d = a > 0? 0x08 : 0
|
|
184
|
+
tmp = _mm_cmpgt_epi8(b, zero_);
|
|
185
|
+
_mm_store_si128(&y[t], _mm_and_si128(tmp, b));
|
|
186
|
+
d = _mm_or_si128(d, _mm_and_si128(tmp, flag16_)); // d = b > 0? 0x10 : 0
|
|
187
|
+
_mm_store_si128(&pr[t], d);
|
|
188
|
+
}
|
|
189
|
+
} else { // gap right-alignment
|
|
190
|
+
__m128i *pr = p + (size_t)r * n_col_ - st_;
|
|
191
|
+
off[r] = st, off_end[r] = en;
|
|
192
|
+
for (t = st_; t <= en_; ++t) {
|
|
193
|
+
__m128i d, z, a, b, xt1, vt1, ut, tmp;
|
|
194
|
+
__dp_code_block1;
|
|
195
|
+
d = _mm_andnot_si128(_mm_cmpgt_epi8(z, a), flag1_); // d = z > a? 0 : 1
|
|
196
|
+
#ifdef __SSE4_1__
|
|
197
|
+
z = _mm_max_epi8(z, a); // z = z > a? z : a (signed)
|
|
198
|
+
tmp = _mm_cmpgt_epi8(z, b);
|
|
199
|
+
d = _mm_blendv_epi8(flag2_, d, tmp); // d = z > b? d : 2
|
|
200
|
+
#else // we need to emulate SSE4.1 intrinsics _mm_max_epi8() and _mm_blendv_epi8()
|
|
201
|
+
z = _mm_and_si128(z, _mm_cmpgt_epi8(z, zero_)); // z = z > 0? z : 0;
|
|
202
|
+
z = _mm_max_epu8(z, a); // z = max(z, a); this works because both are non-negative
|
|
203
|
+
tmp = _mm_cmpgt_epi8(z, b);
|
|
204
|
+
d = _mm_or_si128(_mm_andnot_si128(tmp, flag2_), _mm_and_si128(tmp, d)); // d = z > b? d : 2; emulating blendv
|
|
205
|
+
#endif
|
|
206
|
+
__dp_code_block2;
|
|
207
|
+
tmp = _mm_cmpgt_epi8(zero_, a);
|
|
208
|
+
_mm_store_si128(&x[t], _mm_andnot_si128(tmp, a));
|
|
209
|
+
d = _mm_or_si128(d, _mm_andnot_si128(tmp, flag8_)); // d = 0 > a? 0 : 0x08
|
|
210
|
+
tmp = _mm_cmpgt_epi8(zero_, b);
|
|
211
|
+
_mm_store_si128(&y[t], _mm_andnot_si128(tmp, b));
|
|
212
|
+
d = _mm_or_si128(d, _mm_andnot_si128(tmp, flag16_)); // d = 0 > b? 0 : 0x10
|
|
213
|
+
_mm_store_si128(&pr[t], d);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
if (!approx_max) { // find the exact max with a 32-bit score array
|
|
217
|
+
int32_t max_H, max_t;
|
|
218
|
+
// compute H[], max_H and max_t
|
|
219
|
+
if (r > 0) {
|
|
220
|
+
int32_t HH[4], tt[4], en1 = st0 + (en0 - st0) / 4 * 4, i;
|
|
221
|
+
__m128i max_H_, max_t_, qe_;
|
|
222
|
+
max_H = H[en0] = en0 > 0? H[en0-1] + u8[en0] - qe : H[en0] + v8[en0] - qe; // special casing the last element
|
|
223
|
+
max_t = en0;
|
|
224
|
+
max_H_ = _mm_set1_epi32(max_H);
|
|
225
|
+
max_t_ = _mm_set1_epi32(max_t);
|
|
226
|
+
qe_ = _mm_set1_epi32(q + e);
|
|
227
|
+
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;
|
|
228
|
+
__m128i H1, tmp, t_;
|
|
229
|
+
H1 = _mm_loadu_si128((__m128i*)&H[t]);
|
|
230
|
+
t_ = _mm_setr_epi32(v8[t], v8[t+1], v8[t+2], v8[t+3]);
|
|
231
|
+
H1 = _mm_add_epi32(H1, t_);
|
|
232
|
+
H1 = _mm_sub_epi32(H1, qe_);
|
|
233
|
+
_mm_storeu_si128((__m128i*)&H[t], H1);
|
|
234
|
+
t_ = _mm_set1_epi32(t);
|
|
235
|
+
tmp = _mm_cmpgt_epi32(H1, max_H_);
|
|
236
|
+
#ifdef __SSE4_1__
|
|
237
|
+
max_H_ = _mm_blendv_epi8(max_H_, H1, tmp);
|
|
238
|
+
max_t_ = _mm_blendv_epi8(max_t_, t_, tmp);
|
|
239
|
+
#else
|
|
240
|
+
max_H_ = _mm_or_si128(_mm_and_si128(tmp, H1), _mm_andnot_si128(tmp, max_H_));
|
|
241
|
+
max_t_ = _mm_or_si128(_mm_and_si128(tmp, t_), _mm_andnot_si128(tmp, max_t_));
|
|
242
|
+
#endif
|
|
243
|
+
}
|
|
244
|
+
_mm_storeu_si128((__m128i*)HH, max_H_);
|
|
245
|
+
_mm_storeu_si128((__m128i*)tt, max_t_);
|
|
246
|
+
for (i = 0; i < 4; ++i)
|
|
247
|
+
if (max_H < HH[i]) max_H = HH[i], max_t = tt[i] + i;
|
|
248
|
+
for (; t < en0; ++t) { // for the rest of values that haven't been computed with SSE
|
|
249
|
+
H[t] += (int32_t)v8[t] - qe;
|
|
250
|
+
if (H[t] > max_H)
|
|
251
|
+
max_H = H[t], max_t = t;
|
|
252
|
+
}
|
|
253
|
+
} else H[0] = v8[0] - qe - qe, max_H = H[0], max_t = 0; // special casing r==0
|
|
254
|
+
// update ez
|
|
255
|
+
if (en0 == tlen - 1 && H[en0] > ez->mte)
|
|
256
|
+
ez->mte = H[en0], ez->mte_q = r - en0;
|
|
257
|
+
if (r - st0 == qlen - 1 && H[st0] > ez->mqe)
|
|
258
|
+
ez->mqe = H[st0], ez->mqe_t = st0;
|
|
259
|
+
if (ksw_apply_zdrop(ez, 1, max_H, r, max_t, zdrop, e)) break;
|
|
260
|
+
if (r == qlen + tlen - 2 && en0 == tlen - 1)
|
|
261
|
+
ez->score = H[tlen - 1];
|
|
262
|
+
} else { // find approximate max; Z-drop might be inaccurate, too.
|
|
263
|
+
if (r > 0) {
|
|
264
|
+
if (last_H0_t >= st0 && last_H0_t <= en0 && last_H0_t + 1 >= st0 && last_H0_t + 1 <= en0) {
|
|
265
|
+
int32_t d0 = v8[last_H0_t] - qe;
|
|
266
|
+
int32_t d1 = u8[last_H0_t + 1] - qe;
|
|
267
|
+
if (d0 > d1) H0 += d0;
|
|
268
|
+
else H0 += d1, ++last_H0_t;
|
|
269
|
+
} else if (last_H0_t >= st0 && last_H0_t <= en0) {
|
|
270
|
+
H0 += v8[last_H0_t] - qe;
|
|
271
|
+
} else {
|
|
272
|
+
++last_H0_t, H0 += u8[last_H0_t] - qe;
|
|
273
|
+
}
|
|
274
|
+
if ((flag & KSW_EZ_APPROX_DROP) && ksw_apply_zdrop(ez, 1, H0, r, last_H0_t, zdrop, e)) break;
|
|
275
|
+
} else H0 = v8[0] - qe - qe, last_H0_t = 0;
|
|
276
|
+
if (r == qlen + tlen - 2 && en0 == tlen - 1)
|
|
277
|
+
ez->score = H0;
|
|
278
|
+
}
|
|
279
|
+
last_st = st, last_en = en;
|
|
280
|
+
//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
|
|
281
|
+
}
|
|
282
|
+
kfree(km, mem);
|
|
283
|
+
if (!approx_max) kfree(km, H);
|
|
284
|
+
if (with_cigar) { // backtrack
|
|
285
|
+
int rev_cigar = !!(flag & KSW_EZ_REV_CIGAR);
|
|
286
|
+
if (!ez->zdropped && !(flag&KSW_EZ_EXTZ_ONLY)) {
|
|
287
|
+
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);
|
|
288
|
+
} else if ((flag&KSW_EZ_EXTZ_ONLY) && ez->mqe + end_bonus > (int)ez->max) {
|
|
289
|
+
ez->reach_end = 1;
|
|
290
|
+
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);
|
|
291
|
+
} else if (ez->max_t >= 0 && ez->max_q >= 0) {
|
|
292
|
+
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);
|
|
293
|
+
}
|
|
294
|
+
kfree(km, mem2); kfree(km, off);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
#include <stdlib.h>
|
|
2
|
+
#include <stdint.h>
|
|
3
|
+
#include <string.h>
|
|
4
|
+
#include "ksw2.h"
|
|
5
|
+
|
|
6
|
+
#if defined(__ARM_NEON)
|
|
7
|
+
#include "s2n-lite.h"
|
|
8
|
+
#elif defined(__SSE2__)
|
|
9
|
+
#include <xmmintrin.h>
|
|
10
|
+
#else
|
|
11
|
+
#error "Missing SSE2 or NEON intrinsics"
|
|
12
|
+
#endif
|
|
13
|
+
|
|
14
|
+
#ifdef __GNUC__
|
|
15
|
+
#define LIKELY(x) __builtin_expect((x),1)
|
|
16
|
+
#define UNLIKELY(x) __builtin_expect((x),0)
|
|
17
|
+
#else
|
|
18
|
+
#define LIKELY(x) (x)
|
|
19
|
+
#define UNLIKELY(x) (x)
|
|
20
|
+
#endif
|
|
21
|
+
|
|
22
|
+
#ifndef Kgrow
|
|
23
|
+
#define Kgrow(km, type, ptr, __i, __m) do { \
|
|
24
|
+
if ((__i) >= (__m)) { \
|
|
25
|
+
(__m) = (__i) + 1; \
|
|
26
|
+
(__m) += ((__m)>>1) + 16; \
|
|
27
|
+
(ptr) = (type*)krealloc(km, ptr, (__m) * sizeof(type)); \
|
|
28
|
+
} \
|
|
29
|
+
} while (0)
|
|
30
|
+
#endif
|
|
31
|
+
|
|
32
|
+
typedef struct {
|
|
33
|
+
int qlen, slen;
|
|
34
|
+
uint8_t shift, mdiff, max, size;
|
|
35
|
+
__m128i *qp, *H0, *H1, *E, *Hmax;
|
|
36
|
+
void *km;
|
|
37
|
+
} kswq_t;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Initialize the query data structure
|
|
41
|
+
*
|
|
42
|
+
* @param size Number of bytes used to store a score; valid valures are 1 or 2
|
|
43
|
+
* @param qlen Length of the query sequence
|
|
44
|
+
* @param query Query sequence
|
|
45
|
+
* @param m Size of the alphabet
|
|
46
|
+
* @param mat Scoring matrix in a one-dimension array
|
|
47
|
+
*
|
|
48
|
+
* @return Query data structure
|
|
49
|
+
*/
|
|
50
|
+
void *ksw_ll_qinit(void *km, int size, int qlen, const uint8_t *query, int m, const int8_t *mat)
|
|
51
|
+
{
|
|
52
|
+
kswq_t *q;
|
|
53
|
+
int slen, a, tmp, p;
|
|
54
|
+
|
|
55
|
+
size = size > 1? 2 : 1;
|
|
56
|
+
p = 8 * (3 - size); // # values per __m128i
|
|
57
|
+
slen = (qlen + p - 1) / p; // segmented length
|
|
58
|
+
q = (kswq_t*)kmalloc(km, sizeof(kswq_t) + 256 + 16 * slen * (m + 4)); // a single block of memory
|
|
59
|
+
q->qp = (__m128i*)(((size_t)q + sizeof(kswq_t) + 15) >> 4 << 4); // align memory
|
|
60
|
+
q->H0 = q->qp + slen * m;
|
|
61
|
+
q->H1 = q->H0 + slen;
|
|
62
|
+
q->E = q->H1 + slen;
|
|
63
|
+
q->Hmax = q->E + slen;
|
|
64
|
+
q->slen = slen; q->qlen = qlen; q->size = size;
|
|
65
|
+
q->km = km;
|
|
66
|
+
// compute shift
|
|
67
|
+
tmp = m * m;
|
|
68
|
+
for (a = 0, q->shift = 127, q->mdiff = 0; a < tmp; ++a) { // find the minimum and maximum score
|
|
69
|
+
if (mat[a] < (int8_t)q->shift) q->shift = mat[a];
|
|
70
|
+
if (mat[a] > (int8_t)q->mdiff) q->mdiff = mat[a];
|
|
71
|
+
}
|
|
72
|
+
q->max = q->mdiff;
|
|
73
|
+
q->shift = 256 - q->shift; // NB: q->shift is uint8_t
|
|
74
|
+
q->mdiff += q->shift; // this is the difference between the min and max scores
|
|
75
|
+
// An example: p=8, qlen=19, slen=3 and segmentation:
|
|
76
|
+
// {{0,3,6,9,12,15,18,-1},{1,4,7,10,13,16,-1,-1},{2,5,8,11,14,17,-1,-1}}
|
|
77
|
+
if (size == 1) {
|
|
78
|
+
int8_t *t = (int8_t*)q->qp;
|
|
79
|
+
for (a = 0; a < m; ++a) {
|
|
80
|
+
int i, k, nlen = slen * p;
|
|
81
|
+
const int8_t *ma = mat + a * m;
|
|
82
|
+
for (i = 0; i < slen; ++i)
|
|
83
|
+
for (k = i; k < nlen; k += slen) // p iterations
|
|
84
|
+
*t++ = (k >= qlen? -1 : ma[query[k]]) + q->shift;
|
|
85
|
+
}
|
|
86
|
+
} else {
|
|
87
|
+
int16_t *t = (int16_t*)q->qp;
|
|
88
|
+
for (a = 0; a < m; ++a) {
|
|
89
|
+
int i, k, nlen = slen * p;
|
|
90
|
+
const int8_t *ma = mat + a * m;
|
|
91
|
+
for (i = 0; i < slen; ++i)
|
|
92
|
+
for (k = i; k < nlen; k += slen) // p iterations
|
|
93
|
+
*t++ = (k >= qlen? -1 : ma[query[k]]);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return q;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
static inline int ksw_le_u8(__m128i a, __m128i b)
|
|
100
|
+
{
|
|
101
|
+
#if defined(__ARM_NEON)
|
|
102
|
+
return vmaxvq_u8(vqsubq_u8(a, b)) == 0;
|
|
103
|
+
#elif defined(__SSE2__)
|
|
104
|
+
return _mm_movemask_epi8(_mm_cmpeq_epi8(_mm_subs_epu8(a, b), _mm_setzero_si128())) == 0xffff;
|
|
105
|
+
#endif
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
static inline int ksw_max_u8(__m128i x)
|
|
109
|
+
{
|
|
110
|
+
#if defined(__ARM_NEON)
|
|
111
|
+
return vmaxvq_u8(x);
|
|
112
|
+
#elif defined(__SSE2__)
|
|
113
|
+
x = _mm_max_epu8(x, _mm_srli_si128(x, 8));
|
|
114
|
+
x = _mm_max_epu8(x, _mm_srli_si128(x, 4));
|
|
115
|
+
x = _mm_max_epu8(x, _mm_srli_si128(x, 2));
|
|
116
|
+
x = _mm_max_epu8(x, _mm_srli_si128(x, 1));
|
|
117
|
+
return _mm_extract_epi16(x, 0) & 0x00ff;
|
|
118
|
+
#endif
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
ksw_llrst_t ksw_ll_u8_core(void *q_, int tlen, const uint8_t *target, int _gapo, int _gape, int xtra)
|
|
122
|
+
{
|
|
123
|
+
kswq_t *q = (kswq_t*)q_;
|
|
124
|
+
int slen, i, m_b, n_b, te = -1, gmax = 0, minsc, endsc;
|
|
125
|
+
uint64_t *b;
|
|
126
|
+
__m128i gapoe, gape, shift, *H0, *H1, *E, *Hmax;
|
|
127
|
+
ksw_llrst_t r = { 0, -1, -1, -1, -1 };
|
|
128
|
+
|
|
129
|
+
// initialization
|
|
130
|
+
minsc = (xtra&KSW_LL_SUBO)? xtra&0xffff : 0x10000;
|
|
131
|
+
endsc = (xtra&KSW_LL_STOP)? xtra&0xffff : 0x10000;
|
|
132
|
+
m_b = n_b = 0; b = 0;
|
|
133
|
+
gapoe = _mm_set1_epi8(_gapo + _gape);
|
|
134
|
+
gape = _mm_set1_epi8(_gape);
|
|
135
|
+
shift = _mm_set1_epi8(q->shift);
|
|
136
|
+
H0 = q->H0; H1 = q->H1; E = q->E; Hmax = q->Hmax;
|
|
137
|
+
slen = q->slen;
|
|
138
|
+
memset(E, 0, slen * sizeof(__m128i));
|
|
139
|
+
memset(H0, 0, slen * sizeof(__m128i));
|
|
140
|
+
memset(Hmax, 0, slen * sizeof(__m128i));
|
|
141
|
+
// the core loop
|
|
142
|
+
for (i = 0; i < tlen; ++i) {
|
|
143
|
+
int j, k, imax;
|
|
144
|
+
__m128i e, h, t, f, max, *S = q->qp + target[i] * slen; // s is the 1st score vector
|
|
145
|
+
f = max = _mm_setzero_si128();
|
|
146
|
+
h = _mm_load_si128(H0 + slen - 1); // h={2,5,8,11,14,17,-1,-1} in the above example
|
|
147
|
+
h = _mm_slli_si128(h, 1); // h=H(i-1,-1); << instead of >> because x64 is little-endian
|
|
148
|
+
for (j = 0; LIKELY(j < slen); ++j) {
|
|
149
|
+
/* SW cells are computed in the following order:
|
|
150
|
+
* H(i,j) = max{H(i-1,j-1)+S(i,j), E(i,j), F(i,j)}
|
|
151
|
+
* E(i+1,j) = max{H(i,j)-q, E(i,j)-r}
|
|
152
|
+
* F(i,j+1) = max{H(i,j)-q, F(i,j)-r}
|
|
153
|
+
*/
|
|
154
|
+
// compute H'(i,j); note that at the beginning, h=H'(i-1,j-1)
|
|
155
|
+
h = _mm_adds_epu8(h, _mm_load_si128(S + j));
|
|
156
|
+
h = _mm_subs_epu8(h, shift); // h=H'(i-1,j-1)+S(i,j)
|
|
157
|
+
e = _mm_load_si128(E + j); // e=E'(i,j)
|
|
158
|
+
h = _mm_max_epu8(h, e);
|
|
159
|
+
h = _mm_max_epu8(h, f); // h=H'(i,j)
|
|
160
|
+
max = _mm_max_epu8(max, h); // set max
|
|
161
|
+
_mm_store_si128(H1 + j, h); // save to H'(i,j)
|
|
162
|
+
// now compute E'(i+1,j)
|
|
163
|
+
e = _mm_subs_epu8(e, gape); // e=E'(i,j) - e_del
|
|
164
|
+
t = _mm_subs_epu8(h, gapoe); // h=H'(i,j) - o_del - e_del
|
|
165
|
+
e = _mm_max_epu8(e, t); // e=E'(i+1,j)
|
|
166
|
+
_mm_store_si128(E + j, e); // save to E'(i+1,j)
|
|
167
|
+
// now compute F'(i,j+1)
|
|
168
|
+
f = _mm_subs_epu8(f, gape);
|
|
169
|
+
t = _mm_subs_epu8(h, gapoe); // h=H'(i,j) - o_ins - e_ins
|
|
170
|
+
f = _mm_max_epu8(f, t);
|
|
171
|
+
// get H'(i-1,j) and prepare for the next j
|
|
172
|
+
h = _mm_load_si128(H0 + j); // h=H'(i-1,j)
|
|
173
|
+
}
|
|
174
|
+
// NB: we do not need to set E(i,j) as we disallow adjecent insertion and then deletion
|
|
175
|
+
for (k = 0; LIKELY(k < 16); ++k) { // this block mimics SWPS3; NB: H(i,j) updated in the lazy-F loop cannot exceed max
|
|
176
|
+
f = _mm_slli_si128(f, 1);
|
|
177
|
+
for (j = 0; LIKELY(j < slen); ++j) {
|
|
178
|
+
h = _mm_load_si128(H1 + j);
|
|
179
|
+
h = _mm_max_epu8(h, f); // h=H'(i,j)
|
|
180
|
+
_mm_store_si128(H1 + j, h);
|
|
181
|
+
h = _mm_subs_epu8(h, gapoe);
|
|
182
|
+
f = _mm_subs_epu8(f, gape);
|
|
183
|
+
if (UNLIKELY(ksw_le_u8(f, h))) goto end_loop_u8;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
end_loop_u8:
|
|
187
|
+
imax = ksw_max_u8(max); // imax is the maximum number in max
|
|
188
|
+
if (imax >= minsc) { // write the b array; this condition adds branching unfornately
|
|
189
|
+
if (n_b == 0 || (int32_t)b[n_b-1] + 1 != i) { // then append
|
|
190
|
+
if (n_b == m_b) Kgrow(q->km, uint64_t, b, n_b, m_b);
|
|
191
|
+
b[n_b++] = (uint64_t)imax<<32 | i;
|
|
192
|
+
} else if ((int)(b[n_b-1]>>32) < imax) b[n_b-1] = (uint64_t)imax<<32 | i; // modify the last
|
|
193
|
+
}
|
|
194
|
+
if (imax > gmax) {
|
|
195
|
+
gmax = imax; te = i; // te is the end position on the target
|
|
196
|
+
for (j = 0; LIKELY(j < slen); ++j) // keep the H1 vector
|
|
197
|
+
_mm_store_si128(Hmax + j, _mm_load_si128(H1 + j));
|
|
198
|
+
if (gmax + q->shift >= 255 || gmax >= endsc) break;
|
|
199
|
+
}
|
|
200
|
+
S = H1; H1 = H0; H0 = S; // swap H0 and H1
|
|
201
|
+
}
|
|
202
|
+
r.score = gmax + q->shift < 255? gmax : 255;
|
|
203
|
+
r.te = te;
|
|
204
|
+
if (r.score != 255) { // get a->qe, the end of query match; find the 2nd best score
|
|
205
|
+
int max = -1, tmp, low, high, qlen = slen * 16;
|
|
206
|
+
uint8_t *t = (uint8_t*)Hmax;
|
|
207
|
+
for (i = 0; i < qlen; ++i, ++t)
|
|
208
|
+
if ((int)*t > max) max = *t, r.qe = i / 16 + i % 16 * slen;
|
|
209
|
+
else if ((int)*t == max && (tmp = i / 16 + i % 16 * slen) < r.qe) r.qe = tmp;
|
|
210
|
+
if (b) {
|
|
211
|
+
i = (r.score + q->max - 1) / q->max;
|
|
212
|
+
low = te - i; high = te + i;
|
|
213
|
+
for (i = 0; i < n_b; ++i) {
|
|
214
|
+
int e = (int32_t)b[i];
|
|
215
|
+
if ((e < low || e > high) && (int)(b[i]>>32) > r.score2)
|
|
216
|
+
r.score2 = b[i]>>32, r.te2 = e;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
kfree(q->km, b);
|
|
221
|
+
return r;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
static inline int ksw_le_epi16(__m128i a, __m128i b)
|
|
225
|
+
{
|
|
226
|
+
#if defined(__ARM_NEON)
|
|
227
|
+
return vmaxvq_u16(vcgtq_s16(vreinterpretq_s16_u8(a), vreinterpretq_s16_u8(b))) == 0;
|
|
228
|
+
#elif defined(__SSE2__)
|
|
229
|
+
return _mm_movemask_epi8(_mm_cmpgt_epi16(a, b)) == 0;
|
|
230
|
+
#endif
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
static inline int ksw_max_i16(__m128i x)
|
|
234
|
+
{
|
|
235
|
+
#if defined(__ARM_NEON)
|
|
236
|
+
return vmaxvq_s16(vreinterpretq_s16_u8(x));
|
|
237
|
+
#elif defined(__SSE2__)
|
|
238
|
+
x = _mm_max_epi16(x, _mm_srli_si128(x, 8));
|
|
239
|
+
x = _mm_max_epi16(x, _mm_srli_si128(x, 4));
|
|
240
|
+
x = _mm_max_epi16(x, _mm_srli_si128(x, 2));
|
|
241
|
+
return _mm_extract_epi16(x, 0);
|
|
242
|
+
#endif
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
ksw_llrst_t ksw_ll_i16_core(void *q_, int tlen, const uint8_t *target, int _gapo, int _gape, int xtra)
|
|
246
|
+
{
|
|
247
|
+
kswq_t *q = (kswq_t*)q_;
|
|
248
|
+
int slen, i, m_b, n_b, te = -1, gmax = 0, minsc, endsc;
|
|
249
|
+
uint64_t *b;
|
|
250
|
+
__m128i gapoe, gape, *H0, *H1, *E, *Hmax;
|
|
251
|
+
ksw_llrst_t r = { 0, -1, -1, -1, -1 };
|
|
252
|
+
|
|
253
|
+
// initialization
|
|
254
|
+
minsc = (xtra&KSW_LL_SUBO)? xtra&0xffff : 0x10000;
|
|
255
|
+
endsc = (xtra&KSW_LL_STOP)? xtra&0xffff : 0x10000;
|
|
256
|
+
m_b = n_b = 0; b = 0;
|
|
257
|
+
gapoe = _mm_set1_epi16(_gapo + _gape);
|
|
258
|
+
gape = _mm_set1_epi16(_gape);
|
|
259
|
+
H0 = q->H0; H1 = q->H1; E = q->E; Hmax = q->Hmax;
|
|
260
|
+
slen = q->slen;
|
|
261
|
+
memset(E, 0, slen * sizeof(__m128i));
|
|
262
|
+
memset(H0, 0, slen * sizeof(__m128i));
|
|
263
|
+
memset(Hmax, 0, slen * sizeof(__m128i));
|
|
264
|
+
// the core loop
|
|
265
|
+
for (i = 0; i < tlen; ++i) {
|
|
266
|
+
int j, k, imax;
|
|
267
|
+
__m128i e, t, h, f, max, *S = q->qp + target[i] * slen; // s is the 1st score vector
|
|
268
|
+
f = max = _mm_setzero_si128();
|
|
269
|
+
h = _mm_load_si128(H0 + slen - 1); // h={2,5,8,11,14,17,-1,-1} in the above example
|
|
270
|
+
h = _mm_slli_si128(h, 2);
|
|
271
|
+
for (j = 0; LIKELY(j < slen); ++j) {
|
|
272
|
+
h = _mm_adds_epi16(h, _mm_load_si128(S++));
|
|
273
|
+
e = _mm_load_si128(E + j);
|
|
274
|
+
h = _mm_max_epi16(h, e);
|
|
275
|
+
h = _mm_max_epi16(h, f);
|
|
276
|
+
max = _mm_max_epi16(max, h);
|
|
277
|
+
_mm_store_si128(H1 + j, h);
|
|
278
|
+
e = _mm_subs_epu16(e, gape);
|
|
279
|
+
t = _mm_subs_epu16(h, gapoe);
|
|
280
|
+
e = _mm_max_epi16(e, t);
|
|
281
|
+
_mm_store_si128(E + j, e);
|
|
282
|
+
f = _mm_subs_epu16(f, gape);
|
|
283
|
+
t = _mm_subs_epu16(h, gapoe);
|
|
284
|
+
f = _mm_max_epi16(f, t);
|
|
285
|
+
h = _mm_load_si128(H0 + j);
|
|
286
|
+
}
|
|
287
|
+
for (k = 0; LIKELY(k < 16); ++k) {
|
|
288
|
+
f = _mm_slli_si128(f, 2);
|
|
289
|
+
for (j = 0; LIKELY(j < slen); ++j) {
|
|
290
|
+
h = _mm_load_si128(H1 + j);
|
|
291
|
+
h = _mm_max_epi16(h, f);
|
|
292
|
+
_mm_store_si128(H1 + j, h);
|
|
293
|
+
h = _mm_subs_epu16(h, gapoe);
|
|
294
|
+
f = _mm_subs_epu16(f, gape);
|
|
295
|
+
if (UNLIKELY(ksw_le_epi16(f, h))) goto end_loop_i16;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
end_loop_i16:
|
|
299
|
+
imax = ksw_max_i16(max);
|
|
300
|
+
if (imax >= minsc) {
|
|
301
|
+
if (n_b == 0 || (int32_t)b[n_b-1] + 1 != i) {
|
|
302
|
+
if (n_b == m_b) Kgrow(q->km, uint64_t, b, n_b, m_b);
|
|
303
|
+
b[n_b++] = (uint64_t)imax<<32 | i;
|
|
304
|
+
} else if ((int)(b[n_b-1]>>32) < imax) b[n_b-1] = (uint64_t)imax<<32 | i; // modify the last
|
|
305
|
+
}
|
|
306
|
+
if (imax > gmax) {
|
|
307
|
+
gmax = imax; te = i;
|
|
308
|
+
for (j = 0; LIKELY(j < slen); ++j)
|
|
309
|
+
_mm_store_si128(Hmax + j, _mm_load_si128(H1 + j));
|
|
310
|
+
if (gmax >= endsc) break;
|
|
311
|
+
}
|
|
312
|
+
S = H1; H1 = H0; H0 = S;
|
|
313
|
+
}
|
|
314
|
+
r.score = gmax; r.te = te;
|
|
315
|
+
{
|
|
316
|
+
int max = -1, tmp, low, high, qlen = slen * 8;
|
|
317
|
+
uint16_t *t = (uint16_t*)Hmax;
|
|
318
|
+
for (i = 0, r.qe = -1; i < qlen; ++i, ++t)
|
|
319
|
+
if ((int)*t > max) max = *t, r.qe = i / 8 + i % 8 * slen;
|
|
320
|
+
else if ((int)*t == max && (tmp = i / 8 + i % 8 * slen) < r.qe) r.qe = tmp;
|
|
321
|
+
if (b) {
|
|
322
|
+
i = (r.score + q->max - 1) / q->max;
|
|
323
|
+
low = te - i; high = te + i;
|
|
324
|
+
for (i = 0; i < n_b; ++i) {
|
|
325
|
+
int e = (int32_t)b[i];
|
|
326
|
+
if ((e < low || e > high) && (int)(b[i]>>32) > r.score2)
|
|
327
|
+
r.score2 = b[i]>>32, r.te2 = e;
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
kfree(q->km, b);
|
|
332
|
+
return r;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
int ksw_ll_i16(void *q_, int tlen, const uint8_t *target, int _gapo, int _gape, int *qe, int *te)
|
|
336
|
+
{
|
|
337
|
+
ksw_llrst_t r;
|
|
338
|
+
r = ksw_ll_i16_core(q_, tlen, target, _gapo, _gape, 0);
|
|
339
|
+
*qe = r.qe, *te = r.te;
|
|
340
|
+
return r.score;
|
|
341
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#ifndef KTHREAD_H
|
|
2
|
+
#define KTHREAD_H
|
|
3
|
+
|
|
4
|
+
#ifdef __cplusplus
|
|
5
|
+
extern "C" {
|
|
6
|
+
#endif
|
|
7
|
+
|
|
8
|
+
void kt_for(int n_threads, void (*func)(void*,long,int), void *data, long n);
|
|
9
|
+
void kt_pipeline(int n_threads, void *(*func)(void*, int, void*), void *shared_data, int n_steps);
|
|
10
|
+
|
|
11
|
+
#ifdef __cplusplus
|
|
12
|
+
}
|
|
13
|
+
#endif
|
|
14
|
+
|
|
15
|
+
#endif
|