// File: /workspace/github_c_makefile_star2_O2/ToniWestbrook[P]paladin/ksw.c
// Function: ksw_global2
int ksw_global2(int qlen, const uint8_t *query, int tlen, const uint8_t *target, int m, const int8_t *mat, int o_del, int e_del, int o_ins, int e_ins, int w, int *n_cigar_, uint32_t **cigar_)
{
	eh_t *eh;
	int8_t *qp; // query profile
	int i, j, k, oe_del = o_del + e_del, oe_ins = o_ins + e_ins, score, n_col;
	uint8_t *z; // backtrack matrix; in each cell: f<<4|e<<2|h; in principle, we can halve the memory, but backtrack will be a little more complex
	if (n_cigar_) *n_cigar_ = 0;
	// allocate memory
	n_col = qlen < 2*w+1? qlen : 2*w+1; // maximum #columns of the backtrack matrix
	z = n_cigar_ && cigar_? malloc((long)n_col * tlen) : 0;
	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 = 0; eh[0].e = MINUS_INF;
	for (j = 1; j <= qlen && j <= w; ++j)
		eh[j].h = -(o_ins + e_ins * j), eh[j].e = MINUS_INF;
	for (; j <= qlen; ++j) eh[j].h = eh[j].e = MINUS_INF; // everything is -inf outside the band
	// DP loop
	for (i = 0; LIKELY(i < tlen); ++i) { // target sequence is in the outer loop
		int32_t f = MINUS_INF, h1, beg, end, t;
		int8_t *q = &qp[target[i] * qlen];
		beg = i > w? i - w : 0;
		end = i + w + 1 < qlen? i + w + 1 : qlen; // only loop through [beg,end) of the query sequence
		h1 = beg == 0? -(o_del + e_del * (i + 1)) : MINUS_INF;
		if (n_cigar_ && cigar_) {
			uint8_t *zi = &z[(long)i * n_col];
			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)
				// Cells are computed in the following order:
				//   M(i,j)   = H(i-1,j-1) + S(i,j)
				//   H(i,j)   = max{M(i,j), E(i,j), F(i,j)}
				//   E(i+1,j) = max{M(i,j)-gapo, E(i,j)} - gape
				//   F(i,j+1) = max{M(i,j)-gapo, F(i,j)} - gape
				// We have to separate M(i,j); otherwise the direction may not be recorded correctly.
				// However, a CIGAR like "10M3I3D10M" allowed by local() is disallowed by global().
				// Such a CIGAR may occur, in theory, if mismatch_penalty > 2*gap_ext_penalty + 2*gap_open_penalty/k.
				// In practice, this should happen very rarely given a reasonable scoring system.
				eh_t *p = &eh[j];
				int32_t h, m = p->h, e = p->e;
				uint8_t d; // direction
				p->h = h1;
				m += q[j];
				d = m >= e? 0 : 1;
				h = m >= e? m : e;
				d = h >= f? d : 2;
				h = h >= f? h : f;
				h1 = h;
				t = m - oe_del;
				e -= e_del;
				d |= e > t? 1<<2 : 0;
				e  = e > t? e    : t;
				p->e = e;
				t = m - oe_ins;
				f -= e_ins;
				d |= f > t? 2<<4 : 0; // if we want to halve the memory, use one bit only, instead of two
				f  = f > t? f    : t;
				zi[j - beg] = d; // z[i,j] keeps h for the current cell and e/f for the next cell
			}
		} else {
			for (j = beg; LIKELY(j < end); ++j) {
				eh_t *p = &eh[j];
				int32_t h, m = p->h, e = p->e;
				p->h = h1;
				m += q[j];
				h = m >= e? m : e;
				h = h >= f? h : f;
				h1 = h;
				t = m - oe_del;
				e -= e_del;
				e  = e > t? e : t;
				p->e = e;
				t = m - oe_ins;
				f -= e_ins;
				f  = f > t? f : t;
			}
		}
		eh[end].h = h1; eh[end].e = MINUS_INF;
	}
	score = eh[qlen].h;
	if (n_cigar_ && cigar_) { // backtrack
		int n_cigar = 0, m_cigar = 0, which = 0;
		uint32_t *cigar = 0, tmp;
		i = tlen - 1; k = (i + w + 1 < qlen? i + w + 1 : qlen) - 1; // (i,k) points to the last cell
		while (i >= 0 && k >= 0) {
			which = z[(long)i * n_col + (k - (i > w? i - w : 0))] >> (which<<1) & 3;
			if (which == 0)      cigar = push_cigar(&n_cigar, &m_cigar, cigar, 0, 1), --i, --k;
			else if (which == 1) cigar = push_cigar(&n_cigar, &m_cigar, cigar, 2, 1), --i;
			else                 cigar = push_cigar(&n_cigar, &m_cigar, cigar, 1, 1), --k;
		}
		if (i >= 0) cigar = push_cigar(&n_cigar, &m_cigar, cigar, 2, i + 1);
		if (k >= 0) cigar = push_cigar(&n_cigar, &m_cigar, cigar, 1, k + 1);
		for (i = 0; i < n_cigar>>1; ++i) // reverse CIGAR
			tmp = cigar[i], cigar[i] = cigar[n_cigar-1-i], cigar[n_cigar-1-i] = tmp;
		*n_cigar_ = n_cigar, *cigar_ = cigar;
	}
	free(eh); free(qp); free(z);
	return score;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x78, %rsp
movq %r9, 0x18(%rsp)
movl %r8d, %ebp
movq %rcx, 0x70(%rsp)
movq 0xd8(%rsp), %rax
movl 0xd0(%rsp), %r9d
testq %rax, %rax
je 0x1f63d
andl $0x0, (%rax)
movl 0xb8(%rsp), %r14d
testq %rax, %rax
setne %al
leal 0x1(,%r9,2), %ecx
cmpl %edi, %ecx
cmovgel %edi, %ecx
cmpq $0x0, 0xe0(%rsp)
setne %r8b
andb %al, %r8b
movslq %ecx, %rax
movb %r8b, 0x7(%rsp)
cmpb $0x1, %r8b
movq %rdx, 0x40(%rsp)
movq %rdi, 0x10(%rsp)
movq %rax, 0x48(%rsp)
movq %rsi, 0x38(%rsp)
jne 0x1f6bf
movslq %edx, %rdi
imulq %rax, %rdi
leaq 0x5030(%rip), %rsi      # 0x246c8
leaq 0x50f7(%rip), %rcx      # 0x24796
movl $0x209, %edx            # imm = 0x209
callq 0x1e045
movq 0x10(%rsp), %rdi
movl 0xd0(%rsp), %esi
movq %rsi, %r9
movq %rax, 0x28(%rsp)
jmp 0x1f6c8
movq $0x0, 0x28(%rsp)
movl 0xb0(%rsp), %eax
leal (%r14,%rax), %r15d
movl 0xc0(%rsp), %ebx
addl 0xc8(%rsp), %ebx
leal (%r9,%r9), %eax
movl %eax, 0x20(%rsp)
movl %ebp, %eax
imull %edi, %eax
movslq %eax, %rdi
leaq 0x4fd0(%rip), %r12      # 0x246c8
leaq 0x5097(%rip), %rcx      # 0x24796
movq %r12, %rsi
movl $0x20a, %edx            # imm = 0x20A
callq 0x1e045
movq %rax, %r13
movq 0x10(%rsp), %rax
incl %eax
movslq %eax, %rdi
pushq $0x8
popq %rsi
movq %r12, %rdx
movl $0x20b, %ecx            # imm = 0x20B
leaq 0x506b(%rip), %r8       # 0x24796
callq 0x1dfd0
movq 0x10(%rsp), %r10
movq %rax, %r12
testl %r10d, %r10d
movl $0x0, %eax
cmovgl %r10d, %eax
movslq %ebp, %rcx
testl %ecx, %ecx
movl $0x0, %edx
cmovgl %ecx, %edx
xorl %esi, %esi
movq 0x38(%rsp), %r11
xorl %edi, %edi
cmpq %rdx, %rdi
je 0x1f794
movq %rdi, %rbp
imulq %rcx, %rdi
addq 0x18(%rsp), %rdi
movslq %esi, %rsi
xorl %r8d, %r8d
cmpq %r8, %rax
je 0x1f78c
movzbl (%r11,%r8), %r9d
movb (%rdi,%r9), %r9b
movb %r9b, (%r13,%rsi)
incq %rsi
incq %r8
jmp 0x1f771
movq %rbp, %rdi
incq %rdi
jmp 0x1f75a
movabsq $-0x4000000000000000, %rax # imm = 0xC000000000000000
movl 0xd0(%rsp), %r11d
cmpl %r11d, %r10d
movl %r11d, %ecx
cmovll %r10d, %ecx
xorl %edx, %edx
testl %ecx, %ecx
cmovlel %edx, %ecx
movq %rax, (%r12)
leal 0x1(%rcx), %eax
movl %ebx, %esi
negl %esi
cmpq %rdx, %rcx
je 0x1f7e1
movl %esi, 0x8(%r12,%rdx,8)
movl $0xc0000000, 0xc(%r12,%rdx,8) # imm = 0xC0000000
subl 0xc8(%rsp), %esi
incq %rdx
jmp 0x1f7c2
movslq %r10d, %rcx
movq %rcx, 0x30(%rsp)
movabsq $-0x3fffffff40000000, %rcx # imm = 0xC0000000C0000000
cmpq 0x30(%rsp), %rax
jg 0x1f803
movq %rcx, (%r12,%rax,8)
incq %rax
jmp 0x1f7f3
leal 0x1(%r11), %eax
movq %rax, 0x68(%rsp)
movslq %r11d, %rax
movq %rax, 0x60(%rsp)
movq 0x40(%rsp), %rax
testl %eax, %eax
movl $0x0, %ecx
cmovgl %eax, %ecx
movq %rcx, 0x38(%rsp)
movslq 0x20(%rsp), %rcx
incq %rcx
movq 0x30(%rsp), %rax
cmpq %rax, %rcx
cmovgeq %rax, %rcx
movq %rcx, 0x58(%rsp)
movq 0x28(%rsp), %r8
xorl %edi, %edi
movq %r13, 0x50(%rsp)
pushq $0x2
popq %rbp
cmpl %edi, %r11d
movl %edi, %eax
cmovgl %r11d, %eax
cmpq 0x38(%rsp), %rdi
je 0x1f9e6
subl %r11d, %eax
movslq %eax, %rsi
movq 0x70(%rsp), %rax
movzbl (%rax,%rdi), %eax
imull %r10d, %eax
movslq %eax, %r9
addq %r13, %r9
movl %edi, %ecx
subl %r11d, %ecx
cmpq 0x60(%rsp), %rdi
movl $0x0, %eax
cmovlel %eax, %ecx
movq 0x68(%rsp), %rax
leal (%rax,%rdi), %edx
cmpl %r10d, %edx
cmovgel %r10d, %edx
movq %rdi, 0x20(%rsp)
movl %edi, %eax
notl %eax
imull %r14d, %eax
movl 0xb0(%rsp), %edi
subl %edi, %eax
testl %ecx, %ecx
movl $0xc0000000, %edi       # imm = 0xC0000000
cmovnel %edi, %eax
cmpb $0x0, 0x7(%rsp)
movq %r8, 0x18(%rsp)
movslq %edx, %rdx
je 0x1f98c
movslq %ecx, %rcx
movq %r8, %r11
subq %rcx, %r11
movl $0xc0000000, %r8d       # imm = 0xC0000000
cmpq %rdx, %rsi
jge 0x1f956
movl (%r12,%rsi,8), %r13d
movl 0x4(%r12,%rsi,8), %ecx
movl %eax, (%r12,%rsi,8)
movsbl (%r9,%rsi), %edi
addl %r13d, %edi
xorl %r13d, %r13d
cmpl %ecx, %edi
setl %r13b
movl %ecx, %eax
cmovgl %edi, %eax
movl %edi, %r10d
subl %r15d, %r10d
subl %r14d, %ecx
cmpl %r10d, %ecx
cmovlel %r10d, %ecx
setg %r10b
shlb $0x2, %r10b
cmpl %r8d, %eax
cmovlel %r8d, %eax
cmovll %ebp, %r13d
movl %ecx, 0x4(%r12,%rsi,8)
orb %r10b, %r13b
subl %ebx, %edi
subl 0xc8(%rsp), %r8d
cmpl %edi, %r8d
cmovlel %edi, %r8d
setg %cl
shlb $0x5, %cl
orb %r13b, %cl
movb %cl, (%r11,%rsi)
incq %rsi
jmp 0x1f8e0
movq 0x50(%rsp), %r13
movl 0xd0(%rsp), %r11d
movl %eax, (%r12,%rdx,8)
movl $0xc0000000, 0x4(%r12,%rdx,8) # imm = 0xC0000000
movq 0x20(%rsp), %rdi
incq %rdi
movq 0x18(%rsp), %r8
addq 0x58(%rsp), %r8
movq 0x10(%rsp), %r10
jmp 0x1f850
movl $0xc0000000, %r8d       # imm = 0xC0000000
cmpq %rdx, %rsi
jge 0x1f963
movl (%r12,%rsi,8), %ecx
movl 0x4(%r12,%rsi,8), %edi
movl %eax, (%r12,%rsi,8)
movsbl (%r9,%rsi), %r10d
addl %ecx, %r10d
cmpl %edi, %r10d
movl %edi, %eax
cmovgl %r10d, %eax
cmpl %r8d, %eax
cmovlel %r8d, %eax
movl %r10d, %ecx
subl %r15d, %ecx
subl %r14d, %edi
cmpl %ecx, %edi
cmovlel %ecx, %edi
movl %edi, 0x4(%r12,%rsi,8)
subl %ebx, %r10d
subl 0xc8(%rsp), %r8d
cmpl %r10d, %r8d
cmovlel %r10d, %r8d
incq %rsi
jmp 0x1f992
movq 0x30(%rsp), %rax
movl (%r12,%rax,8), %ebx
cmpb $0x0, 0x7(%rsp)
je 0x1fb87
movl %ebx, 0x10(%rsp)
leaq 0x8(%rsp), %rax
andl $0x0, (%rax)
leaq 0xc(%rsp), %rax
andl $0x0, (%rax)
movq 0x40(%rsp), %r13
leal (%r11,%r13), %eax
decl %r13d
cmpl %r10d, %eax
cmovll %eax, %r10d
leal -0x1(%r10), %ebx
xorl %r15d, %r15d
pushq $0x1
popq %rbp
xorl %eax, %eax
movq 0x48(%rsp), %r14
leal -0x1(%r10), %ecx
movl %ecx, 0x20(%rsp)
movl %ebx, 0x18(%rsp)
subl %r13d, %ebx
cmpl %r13d, %r11d
movl %r13d, %ecx
cmovll %r11d, %ecx
testl %r13d, %r13d
js 0x1faf4
testl %r10d, %r10d
jle 0x1faf4
addl %ebx, %ecx
movl %r13d, %edx
imulq %r14, %rdx
movslq %ecx, %rcx
addq %rdx, %rcx
movq 0x28(%rsp), %rdx
movzbl (%rdx,%rcx), %edx
addl %r15d, %r15d
movl %r15d, %ecx
shrl %cl, %edx
movl %edx, %r15d
andl $0x3, %r15d
leaq 0x8(%rsp), %rdi
leaq 0xc(%rsp), %rsi
movq %rax, %rdx
cmpl $0x1, %r15d
jne 0x1fabc
pushq $0x2
popq %rcx
movl %ebp, %r8d
movq %r10, %r14
callq 0x1fbb4
movq %r14, %r10
movq 0x48(%rsp), %r14
movl 0xd0(%rsp), %r11d
decl %r13d
incl %ebx
jmp 0x1fa41
testl %r15d, %r15d
jne 0x1fad0
xorl %ecx, %ecx
movl %ebp, %r8d
callq 0x1fbb4
decl %r13d
jmp 0x1fada
movl %ebp, %ecx
movl %ebp, %r8d
callq 0x1fbb4
movl 0x18(%rsp), %ebx
decl %ebx
movl 0x20(%rsp), %ecx
movl %ecx, %r10d
movl 0xd0(%rsp), %r11d
jmp 0x1fa32
testl %r13d, %r13d
js 0x1fb1a
incl %r13d
leaq 0x8(%rsp), %rdi
leaq 0xc(%rsp), %rsi
pushq $0x2
popq %rcx
movq %rax, %rdx
movl %r13d, %r8d
movq %r10, %rbx
callq 0x1fbb4
movq %rbx, %r10
movl 0x10(%rsp), %ebx
testl %r10d, %r10d
jle 0x1fb3b
leaq 0x8(%rsp), %rdi
leaq 0xc(%rsp), %rsi
pushq $0x1
popq %rcx
movq %rax, %rdx
movl %r10d, %r8d
callq 0x1fbb4
movq 0xe0(%rsp), %r8
movq 0xd8(%rsp), %r9
pushq $-0x1
popq %rcx
xorl %edx, %edx
movl 0x8(%rsp), %esi
movl %esi, %edi
sarl %edi
movslq %edi, %rdi
cmpq %rdi, %rdx
jge 0x1fb81
movl (%rax,%rdx,4), %edi
addl %ecx, %esi
movslq %esi, %rsi
movl (%rax,%rsi,4), %esi
movl %esi, (%rax,%rdx,4)
movl 0x8(%rsp), %esi
addl %ecx, %esi
movslq %esi, %rsi
movl %edi, (%rax,%rsi,4)
incq %rdx
decl %ecx
jmp 0x1fb50
movl %esi, (%r9)
movq %rax, (%r8)
movq %r12, %rdi
callq 0x3390
movq 0x50(%rsp), %rdi
callq 0x3390
movq 0x28(%rsp), %rdi
callq 0x3390
movl %ebx, %eax
addq $0x78, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq