// File: readmapping[P]alfalfa/src/ksw.c
// Function: ksw_extend
int ksw_extend(int qlen, const uint8_t *query, int tlen, const uint8_t *target, int m, const int8_t *mat, int gapo, int gape, int w, int zdrop, int h0, int *_qle, int *_tle, int *_gtle, int *_gscore, int *_max_off)
{
	eh_t *eh; // score array
	int8_t *qp; // query profile
	int i, j, k, gapoe = gapo + gape, beg, end, max, max_i, max_j, max_gap, max_ie, gscore, max_off;
	if (h0 < 0) h0 = 0;
	// allocate memory
	qp = malloc(qlen * m);
	eh = calloc(qlen + 1, 8);
	// generate the query profile
	for (k = i = 0; k < m; ++k) {
		const int8_t *p = &mat[k * m];
		for (j = 0; j < qlen; ++j) qp[i++] = p[query[j]];
	}
	// fill the first row
	eh[0].h = h0; eh[1].h = h0 > gapoe? h0 - gapoe : 0;
	for (j = 2; j <= qlen && eh[j-1].h > gape; ++j)
		eh[j].h = eh[j-1].h - gape;
	// adjust $w if it is too large
	k = m * m;
	for (i = 0, max = 0; i < k; ++i) // get the max score
		max = max > mat[i]? max : mat[i];
	max_gap = (int)((double)(qlen * max - gapo) / gape + 1.);
	max_gap = max_gap > 1? max_gap : 1;
	w = w < max_gap? w : max_gap;
	// DP loop
	max = h0, max_i = max_j = -1; max_ie = -1, gscore = -1;
	max_off = 0;
	beg = 0, end = qlen;
	for (i = 0; LIKELY(i < tlen); ++i) {
		int f = 0, h1, m = 0, mj = -1;
		int8_t *q = &qp[target[i] * qlen];
		// compute the first column
		h1 = h0 - (gapo + gape * (i + 1));
		if (h1 < 0) h1 = 0;
		// apply the band and the constraint (if provided)
		if (beg < i - w) beg = i - w;
		if (end > i + w + 1) end = i + w + 1;
		if (end > qlen) end = qlen;
		for (j = beg; LIKELY(j < end); ++j) {
			// At the beginning of the loop: eh[j] = { H(i-1,j-1), E(i,j) }, f = F(i,j) and h1 = H(i,j-1)
			// Similar to SSE2-SW, cells are computed in the following order:
			//   H(i,j)   = max{H(i-1,j-1)+S(i,j), E(i,j), F(i,j)}
			//   E(i+1,j) = max{H(i,j)-gapo, E(i,j)} - gape
			//   F(i,j+1) = max{H(i,j)-gapo, F(i,j)} - gape
			eh_t *p = &eh[j];
			int h = p->h, e = p->e; // get H(i-1,j-1) and E(i-1,j)
			p->h = h1;          // set H(i,j-1) for the next row
			h += q[j];
			h = h > e? h : e;
			h = h > f? h : f;
			h1 = h;             // save H(i,j) to h1 for the next column
			mj = m > h? mj : j; // record the position where max score is achieved
			m = m > h? m : h;   // m is stored at eh[mj+1]
			h -= gapoe;
			h = h > 0? h : 0;
			e -= gape;
			e = e > h? e : h;   // computed E(i+1,j)
			p->e = e;           // save E(i+1,j) for the next row
			f -= gape;
			f = f > h? f : h;   // computed F(i,j+1)
		}
		eh[end].h = h1; eh[end].e = 0;
		if (j == qlen) {
			max_ie = gscore > h1? max_ie : i;
			gscore = gscore > h1? gscore : h1;
		}
		if (m == 0 || (zdrop > 0 && max - m - abs((i - max_i) - (j - max_j)) * gape > zdrop)) break; // drop to zero, or below Z-dropoff
		if (m > max) {
			max = m, max_i = i, max_j = mj;
			max_off = max_off > abs(mj - i)? max_off : abs(mj - i);
		}
		// update beg and end for the next round
		for (j = mj; j >= beg && eh[j].h; --j);
		beg = j + 1;
		for (j = mj + 2; j <= end && eh[j].h; ++j);
		end = j;
		//beg = 0; end = qlen; // uncomment this line for debugging
	}
	free(eh); free(qp);
	if (_qle) *_qle = max_j + 1;
	if (_tle) *_tle = max_i + 1;
	if (_gtle) *_gtle = max_ie + 1;
	if (_gscore) *_gscore = gscore;
	if (_max_off) *_max_off = max_off;
	return max;
}

// Assembly:
subq $0xe8, %rsp
movq 0x138(%rsp), %rax
movq 0x130(%rsp), %rax
movq 0x128(%rsp), %rax
movq 0x120(%rsp), %rax
movq 0x118(%rsp), %rax
movl 0x110(%rsp), %eax
movl 0x108(%rsp), %eax
movl 0x100(%rsp), %eax
movl 0xf8(%rsp), %eax
movl 0xf0(%rsp), %eax
movl %edi, 0xe4(%rsp)
movq %rsi, 0xd8(%rsp)
movl %edx, 0xd4(%rsp)
movq %rcx, 0xc8(%rsp)
movl %r8d, 0xc4(%rsp)
movq %r9, 0xb8(%rsp)
movl 0xf0(%rsp), %eax
addl 0xf8(%rsp), %eax
movl %eax, 0x98(%rsp)
cmpl $0x0, 0x110(%rsp)
jge 0x766ea
movl $0x0, 0x110(%rsp)
movl 0xe4(%rsp), %eax
imull 0xc4(%rsp), %eax
movslq %eax, %rdi
callq 0x8560
movq %rax, 0xa8(%rsp)
movl 0xe4(%rsp), %eax
addl $0x1, %eax
movslq %eax, %rdi
movl $0x8, %esi
callq 0x8220
movq %rax, 0xb0(%rsp)
movl $0x0, 0xa4(%rsp)
movl $0x0, 0x9c(%rsp)
movl 0x9c(%rsp), %eax
cmpl 0xc4(%rsp), %eax
jge 0x767f7
movq 0xb8(%rsp), %rax
movl 0x9c(%rsp), %ecx
imull 0xc4(%rsp), %ecx
movslq %ecx, %rcx
addq %rcx, %rax
movq %rax, 0x68(%rsp)
movl $0x0, 0xa0(%rsp)
movl 0xa0(%rsp), %eax
cmpl 0xe4(%rsp), %eax
jge 0x767df
movq 0x68(%rsp), %rax
movq 0xd8(%rsp), %rcx
movslq 0xa0(%rsp), %rdx
movzbl (%rcx,%rdx), %ecx
movb (%rax,%rcx), %dl
movq 0xa8(%rsp), %rax
movl 0xa4(%rsp), %ecx
movl %ecx, %esi
addl $0x1, %esi
movl %esi, 0xa4(%rsp)
movslq %ecx, %rcx
movb %dl, (%rax,%rcx)
movl 0xa0(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xa0(%rsp)
jmp 0x7677f
jmp 0x767e1
movl 0x9c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x9c(%rsp)
jmp 0x7673e
movl 0x110(%rsp), %ecx
movq 0xb0(%rsp), %rax
movl %ecx, (%rax)
movl 0x110(%rsp), %eax
cmpl 0x98(%rsp), %eax
jle 0x7682c
movl 0x110(%rsp), %eax
subl 0x98(%rsp), %eax
movl %eax, 0x3c(%rsp)
jmp 0x76834
xorl %eax, %eax
movl %eax, 0x3c(%rsp)
jmp 0x76834
movl 0x3c(%rsp), %ecx
movq 0xb0(%rsp), %rax
movl %ecx, 0x8(%rax)
movl $0x2, 0xa0(%rsp)
movl 0xa0(%rsp), %ecx
xorl %eax, %eax
cmpl 0xe4(%rsp), %ecx
movb %al, 0x3b(%rsp)
jg 0x7688a
movq 0xb0(%rsp), %rax
movl 0xa0(%rsp), %ecx
subl $0x1, %ecx
movslq %ecx, %rcx
movl (%rax,%rcx,8), %eax
cmpl 0xf8(%rsp), %eax
setg %al
movb %al, 0x3b(%rsp)
movb 0x3b(%rsp), %al
testb $0x1, %al
jne 0x76894
jmp 0x768dc
movq 0xb0(%rsp), %rax
movl 0xa0(%rsp), %ecx
subl $0x1, %ecx
movslq %ecx, %rcx
movl (%rax,%rcx,8), %edx
subl 0xf8(%rsp), %edx
movq 0xb0(%rsp), %rax
movslq 0xa0(%rsp), %rcx
movl %edx, (%rax,%rcx,8)
movl 0xa0(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xa0(%rsp)
jmp 0x7684e
movl 0xc4(%rsp), %eax
imull 0xc4(%rsp), %eax
movl %eax, 0x9c(%rsp)
movl $0x0, 0xa4(%rsp)
movl $0x0, 0x8c(%rsp)
movl 0xa4(%rsp), %eax
cmpl 0x9c(%rsp), %eax
jge 0x7697a
movl 0x8c(%rsp), %eax
movq 0xb8(%rsp), %rcx
movslq 0xa4(%rsp), %rdx
movsbl (%rcx,%rdx), %ecx
cmpl %ecx, %eax
jle 0x76944
movl 0x8c(%rsp), %eax
movl %eax, 0x34(%rsp)
jmp 0x7695c
movq 0xb8(%rsp), %rax
movslq 0xa4(%rsp), %rcx
movsbl (%rax,%rcx), %eax
movl %eax, 0x34(%rsp)
movl 0x34(%rsp), %eax
movl %eax, 0x8c(%rsp)
movl 0xa4(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xa4(%rsp)
jmp 0x76908
movl 0xe4(%rsp), %eax
imull 0x8c(%rsp), %eax
subl 0xf0(%rsp), %eax
cvtsi2sd %eax, %xmm0
cvtsi2sdl 0xf8(%rsp), %xmm1
divsd %xmm1, %xmm0
movsd 0x2f37(%rip), %xmm1     # 0x798e0
addsd %xmm1, %xmm0
cvttsd2si %xmm0, %eax
movl %eax, 0x80(%rsp)
cmpl $0x1, 0x80(%rsp)
jle 0x769cf
movl 0x80(%rsp), %eax
movl %eax, 0x30(%rsp)
jmp 0x769da
movl $0x1, %eax
movl %eax, 0x30(%rsp)
jmp 0x769da
movl 0x30(%rsp), %eax
movl %eax, 0x80(%rsp)
movl 0x100(%rsp), %eax
cmpl 0x80(%rsp), %eax
jge 0x76a02
movl 0x100(%rsp), %eax
movl %eax, 0x2c(%rsp)
jmp 0x76a0d
movl 0x80(%rsp), %eax
movl %eax, 0x2c(%rsp)
movl 0x2c(%rsp), %eax
movl %eax, 0x100(%rsp)
movl 0x110(%rsp), %eax
movl %eax, 0x8c(%rsp)
movl $0xffffffff, 0x84(%rsp) # imm = 0xFFFFFFFF
movl $0xffffffff, 0x88(%rsp) # imm = 0xFFFFFFFF
movl $0xffffffff, 0x7c(%rsp) # imm = 0xFFFFFFFF
movl $0xffffffff, 0x78(%rsp) # imm = 0xFFFFFFFF
movl $0x0, 0x74(%rsp)
movl $0x0, 0x94(%rsp)
movl 0xe4(%rsp), %eax
movl %eax, 0x90(%rsp)
movl $0x0, 0xa4(%rsp)
movl 0xa4(%rsp), %eax
cmpl 0xd4(%rsp), %eax
setl %al
andb $0x1, %al
movzbl %al, %eax
cltq
cmpq $0x0, %rax
je 0x76fbe
movl $0x0, 0x64(%rsp)
movl $0x0, 0x5c(%rsp)
movl $0xffffffff, 0x58(%rsp) # imm = 0xFFFFFFFF
movq 0xa8(%rsp), %rax
movq 0xc8(%rsp), %rcx
movslq 0xa4(%rsp), %rdx
movzbl (%rcx,%rdx), %ecx
imull 0xe4(%rsp), %ecx
movslq %ecx, %rcx
addq %rcx, %rax
movq %rax, 0x50(%rsp)
movl 0x110(%rsp), %eax
movl 0xf0(%rsp), %ecx
movl 0xf8(%rsp), %edx
movl 0xa4(%rsp), %esi
addl $0x1, %esi
imull %esi, %edx
addl %edx, %ecx
subl %ecx, %eax
movl %eax, 0x60(%rsp)
cmpl $0x0, 0x60(%rsp)
jge 0x76b1a
movl $0x0, 0x60(%rsp)
movl 0x94(%rsp), %eax
movl 0xa4(%rsp), %ecx
subl 0x100(%rsp), %ecx
cmpl %ecx, %eax
jge 0x76b48
movl 0xa4(%rsp), %eax
subl 0x100(%rsp), %eax
movl %eax, 0x94(%rsp)
movl 0x90(%rsp), %eax
movl 0xa4(%rsp), %ecx
addl 0x100(%rsp), %ecx
addl $0x1, %ecx
cmpl %ecx, %eax
jle 0x76b7c
movl 0xa4(%rsp), %eax
addl 0x100(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x90(%rsp)
movl 0x90(%rsp), %eax
cmpl 0xe4(%rsp), %eax
jle 0x76b9a
movl 0xe4(%rsp), %eax
movl %eax, 0x90(%rsp)
movl 0x94(%rsp), %eax
movl %eax, 0xa0(%rsp)
movl 0xa0(%rsp), %eax
cmpl 0x90(%rsp), %eax
setl %al
andb $0x1, %al
movzbl %al, %eax
cltq
cmpq $0x0, %rax
je 0x76d7a
movq 0xb0(%rsp), %rax
movslq 0xa0(%rsp), %rcx
shlq $0x3, %rcx
addq %rcx, %rax
movq %rax, 0x48(%rsp)
movq 0x48(%rsp), %rax
movl (%rax), %eax
movl %eax, 0x44(%rsp)
movq 0x48(%rsp), %rax
movl 0x4(%rax), %eax
movl %eax, 0x40(%rsp)
movl 0x60(%rsp), %ecx
movq 0x48(%rsp), %rax
movl %ecx, (%rax)
movq 0x50(%rsp), %rax
movslq 0xa0(%rsp), %rcx
movsbl (%rax,%rcx), %eax
addl 0x44(%rsp), %eax
movl %eax, 0x44(%rsp)
movl 0x44(%rsp), %eax
cmpl 0x40(%rsp), %eax
jle 0x76c35
movl 0x44(%rsp), %eax
movl %eax, 0x28(%rsp)
jmp 0x76c3d
movl 0x40(%rsp), %eax
movl %eax, 0x28(%rsp)
movl 0x28(%rsp), %eax
movl %eax, 0x44(%rsp)
movl 0x44(%rsp), %eax
cmpl 0x64(%rsp), %eax
jle 0x76c59
movl 0x44(%rsp), %eax
movl %eax, 0x24(%rsp)
jmp 0x76c61
movl 0x64(%rsp), %eax
movl %eax, 0x24(%rsp)
movl 0x24(%rsp), %eax
movl %eax, 0x44(%rsp)
movl 0x44(%rsp), %eax
movl %eax, 0x60(%rsp)
movl 0x5c(%rsp), %eax
cmpl 0x44(%rsp), %eax
jle 0x76c85
movl 0x58(%rsp), %eax
movl %eax, 0x20(%rsp)
jmp 0x76c90
movl 0xa0(%rsp), %eax
movl %eax, 0x20(%rsp)
movl 0x20(%rsp), %eax
movl %eax, 0x58(%rsp)
movl 0x5c(%rsp), %eax
cmpl 0x44(%rsp), %eax
jle 0x76cac
movl 0x5c(%rsp), %eax
movl %eax, 0x1c(%rsp)
jmp 0x76cb4
movl 0x44(%rsp), %eax
movl %eax, 0x1c(%rsp)
movl 0x1c(%rsp), %eax
movl %eax, 0x5c(%rsp)
movl 0x98(%rsp), %ecx
movl 0x44(%rsp), %eax
subl %ecx, %eax
movl %eax, 0x44(%rsp)
cmpl $0x0, 0x44(%rsp)
jle 0x76cde
movl 0x44(%rsp), %eax
movl %eax, 0x18(%rsp)
jmp 0x76ce6
xorl %eax, %eax
movl %eax, 0x18(%rsp)
jmp 0x76ce6
movl 0x18(%rsp), %eax
movl %eax, 0x44(%rsp)
movl 0xf8(%rsp), %ecx
movl 0x40(%rsp), %eax
subl %ecx, %eax
movl %eax, 0x40(%rsp)
movl 0x40(%rsp), %eax
cmpl 0x44(%rsp), %eax
jle 0x76d13
movl 0x40(%rsp), %eax
movl %eax, 0x14(%rsp)
jmp 0x76d1b
movl 0x44(%rsp), %eax
movl %eax, 0x14(%rsp)
movl 0x14(%rsp), %eax
movl %eax, 0x40(%rsp)
movl 0x40(%rsp), %ecx
movq 0x48(%rsp), %rax
movl %ecx, 0x4(%rax)
movl 0xf8(%rsp), %ecx
movl 0x64(%rsp), %eax
subl %ecx, %eax
movl %eax, 0x64(%rsp)
movl 0x64(%rsp), %eax
cmpl 0x44(%rsp), %eax
jle 0x76d54
movl 0x64(%rsp), %eax
movl %eax, 0x10(%rsp)
jmp 0x76d5c
movl 0x44(%rsp), %eax
movl %eax, 0x10(%rsp)
movl 0x10(%rsp), %eax
movl %eax, 0x64(%rsp)
movl 0xa0(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xa0(%rsp)
jmp 0x76ba8
movl 0x60(%rsp), %edx
movq 0xb0(%rsp), %rax
movslq 0x90(%rsp), %rcx
movl %edx, (%rax,%rcx,8)
movq 0xb0(%rsp), %rax
movslq 0x90(%rsp), %rcx
movl $0x0, 0x4(%rax,%rcx,8)
movl 0xa0(%rsp), %eax
cmpl 0xe4(%rsp), %eax
jne 0x76e04
movl 0x78(%rsp), %eax
cmpl 0x60(%rsp), %eax
jle 0x76dcd
movl 0x7c(%rsp), %eax
movl %eax, 0xc(%rsp)
jmp 0x76dd8
movl 0xa4(%rsp), %eax
movl %eax, 0xc(%rsp)
movl 0xc(%rsp), %eax
movl %eax, 0x7c(%rsp)
movl 0x78(%rsp), %eax
cmpl 0x60(%rsp), %eax
jle 0x76df4
movl 0x78(%rsp), %eax
movl %eax, 0x8(%rsp)
jmp 0x76dfc
movl 0x60(%rsp), %eax
movl %eax, 0x8(%rsp)
movl 0x8(%rsp), %eax
movl %eax, 0x78(%rsp)
cmpl $0x0, 0x5c(%rsp)
je 0x76e58
cmpl $0x0, 0x108(%rsp)
jle 0x76e5d
movl 0x8c(%rsp), %eax
subl 0x5c(%rsp), %eax
movl 0xa4(%rsp), %ecx
subl 0x88(%rsp), %ecx
movl 0xa0(%rsp), %edx
subl 0x84(%rsp), %edx
subl %edx, %ecx
movl %ecx, %edx
negl %edx
cmovnsl %edx, %ecx
imull 0xf8(%rsp), %ecx
subl %ecx, %eax
cmpl 0x108(%rsp), %eax
jle 0x76e5d
jmp 0x76fbe
movl 0x5c(%rsp), %eax
cmpl 0x8c(%rsp), %eax
jle 0x76ed0
movl 0x5c(%rsp), %eax
movl %eax, 0x8c(%rsp)
movl 0xa4(%rsp), %eax
movl %eax, 0x88(%rsp)
movl 0x58(%rsp), %eax
movl %eax, 0x84(%rsp)
movl 0x74(%rsp), %eax
movl 0x58(%rsp), %ecx
subl 0xa4(%rsp), %ecx
movl %ecx, %edx
negl %edx
cmovnsl %edx, %ecx
cmpl %ecx, %eax
jle 0x76eb2
movl 0x74(%rsp), %eax
movl %eax, 0x4(%rsp)
jmp 0x76ec8
movl 0x58(%rsp), %eax
subl 0xa4(%rsp), %eax
movl %eax, %ecx
negl %ecx
cmovnsl %ecx, %eax
movl %eax, 0x4(%rsp)
movl 0x4(%rsp), %eax
movl %eax, 0x74(%rsp)
movl 0x58(%rsp), %eax
movl %eax, 0xa0(%rsp)
movl 0xa0(%rsp), %ecx
xorl %eax, %eax
cmpl 0x94(%rsp), %ecx
movb %al, 0x3(%rsp)
jl 0x76f0c
movq 0xb0(%rsp), %rax
movslq 0xa0(%rsp), %rcx
cmpl $0x0, (%rax,%rcx,8)
setne %al
movb %al, 0x3(%rsp)
movb 0x3(%rsp), %al
testb $0x1, %al
jne 0x76f16
jmp 0x76f2b
jmp 0x76f18
movl 0xa0(%rsp), %eax
addl $-0x1, %eax
movl %eax, 0xa0(%rsp)
jmp 0x76edb
movl 0xa0(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x94(%rsp)
movl 0x58(%rsp), %eax
addl $0x2, %eax
movl %eax, 0xa0(%rsp)
movl 0xa0(%rsp), %ecx
xorl %eax, %eax
cmpl 0x90(%rsp), %ecx
movb %al, 0x2(%rsp)
jg 0x76f7b
movq 0xb0(%rsp), %rax
movslq 0xa0(%rsp), %rcx
cmpl $0x0, (%rax,%rcx,8)
setne %al
movb %al, 0x2(%rsp)
movb 0x2(%rsp), %al
testb $0x1, %al
jne 0x76f85
jmp 0x76f9a
jmp 0x76f87
movl 0xa0(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xa0(%rsp)
jmp 0x76f4a
movl 0xa0(%rsp), %eax
movl %eax, 0x90(%rsp)
movl 0xa4(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xa4(%rsp)
jmp 0x76a78
movq 0xb0(%rsp), %rdi
callq 0x8470
movq 0xa8(%rsp), %rdi
callq 0x8470
cmpq $0x0, 0x118(%rsp)
je 0x76ff7
movl 0x84(%rsp), %ecx
addl $0x1, %ecx
movq 0x118(%rsp), %rax
movl %ecx, (%rax)
cmpq $0x0, 0x120(%rsp)
je 0x77016
movl 0x88(%rsp), %ecx
addl $0x1, %ecx
movq 0x120(%rsp), %rax
movl %ecx, (%rax)
cmpq $0x0, 0x128(%rsp)
je 0x77032
movl 0x7c(%rsp), %ecx
addl $0x1, %ecx
movq 0x128(%rsp), %rax
movl %ecx, (%rax)
cmpq $0x0, 0x130(%rsp)
je 0x7704b
movl 0x78(%rsp), %ecx
movq 0x130(%rsp), %rax
movl %ecx, (%rax)
cmpq $0x0, 0x138(%rsp)
je 0x77064
movl 0x74(%rsp), %ecx
movq 0x138(%rsp), %rax
movl %ecx, (%rax)
movl 0x8c(%rsp), %eax
addq $0xe8, %rsp
retq
nopw %cs:(%rax,%rax)