// File: /workspace/github_c_makefile_star2_O2/ToniWestbrook[P]paladin/bwamem_pair.c
// Function: mem_matesw
int mem_matesw(const mem_opt_t *opt, const bntseq_t *bns, const uint8_t *pac, const mem_pestat_t pes[4], const mem_alnreg_t *a, int l_ms, const uint8_t *ms, mem_alnreg_v *ma)
{
	extern int mem_sort_dedup_patch(const mem_opt_t *opt, const bntseq_t *bns, const uint8_t *pac, uint8_t *query, int n, mem_alnreg_t *a);
	int64_t l_pac = bns->l_pac;
	int i, r, skip[4], n = 0, rid;
	for (r = 0; r < 4; ++r)
		skip[r] = pes[r].failed? 1 : 0;
	for (i = 0; i < ma->n; ++i) { // check which orinentation has been found
		int64_t dist;
		r = mem_infer_dir(l_pac, a->rb, ma->a[i].rb, &dist);
		if (dist >= pes[r].low && dist <= pes[r].high)
			skip[r] = 1;
	}
	if (skip[0] + skip[1] + skip[2] + skip[3] == 4) return 0; // consistent pair exist; no need to perform SW
	for (r = 0; r < 4; ++r) {
		int is_rev, is_larger;
		uint8_t *seq, *rev = 0, *ref = 0;
		int64_t rb, re;
		if (skip[r]) continue;
		is_rev = (r>>1 != (r&1)); // whether to reverse complement the mate
		is_larger = !(r>>1); // whether the mate has larger coordinate
		if (is_rev) {
			rev = malloc(l_ms); // this is the reverse complement of $ms
			for (i = 0; i < l_ms; ++i) rev[l_ms - 1 - i] = ms[i] < 4? 3 - ms[i] : 4;
			seq = rev;
		} else seq = (uint8_t*)ms;
		if (!is_rev) {
			rb = is_larger? a->rb + pes[r].low : a->rb - pes[r].high;
			re = (is_larger? a->rb + pes[r].high: a->rb - pes[r].low) + l_ms; // if on the same strand, end position should be larger to make room for the seq length
		} else {
			rb = (is_larger? a->rb + pes[r].low : a->rb - pes[r].high) - l_ms; // similarly on opposite strands
			re = is_larger? a->rb + pes[r].high: a->rb - pes[r].low;
		}
		if (rb < 0) rb = 0;
		if (re > l_pac<<1) re = l_pac<<1;
		if (rb < re) ref = bns_fetch_seq(bns, pac, &rb, (rb+re)>>1, &re, &rid);
		if (a->rid == rid && re - rb >= opt->min_seed_len) { // no funny things happening
			kswr_t aln;
			mem_alnreg_t b;
			int tmp, xtra = KSW_XSUBO | KSW_XSTART | (l_ms * opt->a < 250? KSW_XBYTE : 0) | (opt->min_seed_len * opt->a);
			aln = ksw_align2(l_ms, seq, re - rb, ref, 5, opt->mat, opt->o_del, opt->e_del, opt->o_ins, opt->e_ins, xtra, 0);
			memset(&b, 0, sizeof(mem_alnreg_t));
			if (aln.score >= opt->min_seed_len && aln.qb >= 0) { // something goes wrong if aln.qb < 0
				b.rid = a->rid;
				b.is_alt = a->is_alt;
				b.qb = is_rev? l_ms - (aln.qe + 1) : aln.qb;                                                                                                                                                                              
				b.qe = is_rev? l_ms - aln.qb : aln.qe + 1; 
				b.rb = is_rev? (l_pac<<1) - (rb + aln.te + 1) : rb + aln.tb;
				b.re = is_rev? (l_pac<<1) - (rb + aln.tb) : rb + aln.te + 1;
				b.score = aln.score;
				b.csub = aln.score2;
				b.secondary = -1;
				b.seedcov = (b.re - b.rb < b.qe - b.qb? b.re - b.rb : b.qe - b.qb) >> 1;
//				printf("*** %d, [%lld,%lld], %d:%d, (%lld,%lld), (%lld,%lld) == (%lld,%lld)\n", aln.score, rb, re, is_rev, is_larger, a->rb, a->re, ma->a[0].rb, ma->a[0].re, b.rb, b.re);
				kv_push(mem_alnreg_t, *ma, b); // make room for a new element
				// move b s.t. ma is sorted
				for (i = 0; i < ma->n - 1; ++i) // find the insertion point
					if (ma->a[i].score < b.score) break;
				tmp = i;
				for (i = ma->n - 1; i > tmp; --i) ma->a[i] = ma->a[i-1];
				ma->a[i] = b;
			}
			++n;
		}
		if (n) ma->n = mem_sort_dedup_patch(opt, 0, 0, 0, ma->n, ma->a);
		if (rev) free(rev);
		free(ref);
	}
	return n;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xc8, %rsp
movl %r9d, 0x8(%rsp)
movq %r8, %r13
movq %rcx, %r15
movq %rdx, 0xc0(%rsp)
movq %rdi, %rbp
movq 0x108(%rsp), %r9
movq %rsi, 0xb8(%rsp)
movq (%rsi), %rax
movq %rax, 0x10(%rsp)
xorl %eax, %eax
cmpq $0x10, %rax
je 0x1bbe5
xorl %ecx, %ecx
cmpl $0x0, 0x8(%r15,%rax,8)
setne %cl
movl %ecx, 0xa0(%rsp,%rax)
addq $0x4, %rax
jmp 0x1bbc7
movq (%r9), %r14
xorl %r12d, %r12d
leaq 0x80(%rsp), %rbx
subq $0x1, %r14
jb 0x1bc51
movq (%r13), %rsi
movq 0x18(%r9), %rax
movq (%rax,%r12), %rdx
movq 0x10(%rsp), %rdi
movq %rbx, %rcx
callq 0x1bb45
movq 0x80(%rsp), %rcx
movl %eax, %eax
movq %rax, %rdx
shlq $0x5, %rdx
movslq (%r15,%rdx), %rsi
cmpq %rsi, %rcx
jl 0x1bc43
addq %r15, %rdx
movslq 0x4(%rdx), %rdx
cmpq %rdx, %rcx
jg 0x1bc43
movl $0x1, 0xa0(%rsp,%rax,4)
addq $0x60, %r12
movq 0x108(%rsp), %r9
jmp 0x1bbf3
movdqa 0xa0(%rsp), %xmm0
pshufd $0xee, %xmm0, %xmm1     # xmm1 = xmm0[2,3,2,3]
paddd %xmm0, %xmm1
pshufd $0x55, %xmm1, %xmm0     # xmm0 = xmm1[1,1,1,1]
paddd %xmm1, %xmm0
movd %xmm0, %eax
xorl %ebx, %ebx
cmpl $0x4, %eax
jne 0x1bc8b
movl %ebx, %eax
addq $0xc8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %r13, 0x40(%rsp)
movl 0x8(%rsp), %eax
movslq %eax, %rdx
movq 0x10(%rsp), %rcx
addq %rcx, %rcx
movq %rcx, 0x10(%rsp)
movq %rbp, %rcx
xorl %ebp, %ebp
testl %edx, %edx
movl $0x0, %r14d
cmovgl %eax, %r14d
movq %rcx, 0x78(%rsp)
leaq 0xc4(%rcx), %rax
movq %rax, 0xb0(%rsp)
movq %rdx, 0x38(%rsp)
leal -0x1(%rdx), %eax
movl %eax, 0x68(%rsp)
pushq $0x4
popq %r12
xorl %ebx, %ebx
movq 0x100(%rsp), %r13
cmpq $0x4, %rbp
je 0x1bc77
cmpl $0x0, 0xa0(%rsp,%rbp,4)
jne 0x1c208
movl %ebp, %eax
shrl %eax
movl %ebp, %ecx
andl $0x1, %ecx
movl %eax, 0x4(%rsp)
movl %ecx, 0x30(%rsp)
cmpl %ecx, %eax
movl %ebx, 0xc(%rsp)
jne 0x1bd3d
movq 0x40(%rsp), %rax
movq (%rax), %rdx
movq %rbp, %rcx
shlq $0x5, %rcx
cmpq $0x1, %rbp
ja 0x1bdc2
movslq (%r15,%rcx), %rax
addq %rdx, %rax
movslq 0x4(%r15,%rcx), %rcx
addq %rdx, %rcx
jmp 0x1bdd7
movq 0x38(%rsp), %rdi
leaq 0x85a7(%rip), %rsi      # 0x242f0
movl $0x86, %edx
leaq 0x8781(%rip), %rcx      # 0x244d6
callq 0x1e045
movq %rax, %rbx
movl 0x68(%rsp), %eax
xorl %ecx, %ecx
cmpq %rcx, %r14
je 0x1bd8a
movb (%r13,%rcx), %dl
movb $0x3, %sil
subb %dl, %sil
cmpb $0x4, %dl
movzbl %sil, %edx
cmovael %r12d, %edx
cltq
movb %dl, (%rbx,%rax)
incq %rcx
decl %eax
jmp 0x1bd63
movq 0x40(%rsp), %rax
movq (%rax), %rdx
movq %rbp, %rcx
shlq $0x5, %rcx
cmpq $0x1, %rbp
ja 0x1bdef
movslq (%r15,%rcx), %rsi
movq %rdx, %rax
subq 0x38(%rsp), %rax
addq %rsi, %rax
movq %rax, 0x18(%rsp)
movslq 0x4(%r15,%rcx), %rcx
addq %rdx, %rcx
movq %rbx, 0x48(%rsp)
jmp 0x1be13
movslq 0x4(%r15,%rcx), %rsi
movq %rdx, %rax
subq %rsi, %rax
movslq (%r15,%rcx), %rcx
subq %rcx, %rdx
movq %rdx, %rcx
movq %rax, 0x18(%rsp)
addq 0x38(%rsp), %rcx
movq %r13, %rbx
movq $0x0, 0x48(%rsp)
jmp 0x1be1b
movslq 0x4(%r15,%rcx), %rsi
addq 0x38(%rsp), %rsi
movq %rdx, %rax
subq %rsi, %rax
movq %rax, 0x18(%rsp)
movslq (%r15,%rcx), %rcx
subq %rcx, %rdx
movq %rbx, 0x48(%rsp)
movq %rdx, %rcx
movq 0x108(%rsp), %r9
movq %rcx, 0x58(%rsp)
testq %rax, %rax
jns 0x1be2d
andq $0x0, 0x18(%rsp)
xorl %eax, %eax
cmpq 0x10(%rsp), %rcx
jle 0x1be3e
movq 0x10(%rsp), %rcx
movq %rcx, 0x58(%rsp)
cmpq %rcx, %rax
jge 0x1be7c
addq %rax, %rcx
shrq %rcx
movq 0xb8(%rsp), %rdi
movq 0xc0(%rsp), %rsi
leaq 0x18(%rsp), %rdx
leaq 0x58(%rsp), %r8
leaq 0x6c(%rsp), %r9
callq 0xfb6d
movq 0x108(%rsp), %r9
movq %rax, 0x50(%rsp)
jmp 0x1be85
movq $0x0, 0x50(%rsp)
movq 0x40(%rsp), %rax
movl 0x18(%rax), %eax
cmpl 0x6c(%rsp), %eax
jne 0x1beb3
movq 0x58(%rsp), %rcx
subq 0x18(%rsp), %rcx
movq 0x78(%rsp), %r13
movslq 0x78(%r13), %rax
cmpq %rax, %rcx
jge 0x1bebc
movq 0x100(%rsp), %r13
movl 0xc(%rsp), %ebx
jmp 0x1c1bc
movl (%r13), %edx
movl %edx, %r8d
movl 0x8(%rsp), %esi
imull %esi, %r8d
xorl %edi, %edi
cmpl $0xfa, %r8d
setl %dil
shll $0x10, %edi
imull %edx, %eax
orl %edi, %eax
orl $0xc0000, %eax          # imm = 0xC0000
movl 0x8(%r13), %edx
movq %rdx, 0x28(%rsp)
movl 0xc(%r13), %edx
movq %rdx, 0x20(%rsp)
movl 0x10(%r13), %r10d
movl 0x14(%r13), %r11d
subq $0x8, %rsp
leaq 0x88(%rsp), %rdi
movq %rbx, %rdx
movq 0x58(%rsp), %r8
pushq $0x5
popq %r9
pushq $0x0
pushq %rax
pushq %r11
pushq %r10
pushq 0x48(%rsp)
pushq 0x58(%rsp)
pushq 0xe8(%rsp)
callq 0x1edb1
movq 0x148(%rsp), %r9
addq $0x40, %rsp
movl 0x80(%rsp), %ebx
movl 0x98(%rsp), %ecx
cmpl 0x78(%r13), %ebx
setge %al
testl %ecx, %ecx
setns %dl
andb %al, %dl
cmpb $0x1, %dl
jne 0x1c1ae
movl 0x88(%rsp), %r10d
movslq 0x84(%rsp), %r8
movslq 0x94(%rsp), %rax
movl %r10d, %r11d
notl %r11d
movl 0x8(%rsp), %esi
addl %esi, %r11d
subl %ecx, %esi
incl %r10d
movq 0x18(%rsp), %rdx
movl 0x30(%rsp), %edi
cmpl %edi, 0x4(%rsp)
cmovel %ecx, %r11d
cmovnel %esi, %r10d
jne 0x1bfb3
addq %rdx, %rax
leaq (%r8,%rdx), %r13
incq %r13
movq %rax, %rsi
jmp 0x1bfca
addq %rdx, %r8
notq %r8
movq 0x10(%rsp), %r13
addq %r13, %r8
addq %rdx, %rax
subq %rax, %r13
movq %r8, %rsi
movl 0x8c(%rsp), %eax
movl %eax, 0x28(%rsp)
movq 0x40(%rsp), %rax
movl 0x48(%rax), %edx
movl $0xc0000000, %ecx       # imm = 0xC0000000
andl %ecx, %edx
movl %edx, 0x4(%rsp)
movl 0x18(%rax), %eax
movl %eax, 0x20(%rsp)
movq %r13, 0x30(%rsp)
subq %rsi, %r13
movl %r10d, %eax
subl %r11d, %eax
cltq
cmpq %rax, %r13
cmovgeq %rax, %r13
movq (%r9), %rcx
movq 0x18(%r9), %rax
cmpq 0x8(%r9), %rcx
movq %rsi, 0x70(%rsp)
jne 0x1c071
leaq (%rcx,%rcx), %rdx
testq %rcx, %rcx
pushq $0x2
popq %rcx
cmoveq %rcx, %rdx
movq %rdx, 0x8(%r9)
imulq $0x60, %rdx, %rsi
movq %rax, %rdi
leaq 0x82b8(%rip), %rdx      # 0x242f0
movl $0xa6, %ecx
leaq 0x8492(%rip), %r8       # 0x244d6
movl %r10d, 0x64(%rsp)
movl %r11d, 0x60(%rsp)
callq 0x1e0b4
movq 0x70(%rsp), %rsi
movl 0x60(%rsp), %r11d
movl 0x64(%rsp), %r10d
movq 0x108(%rsp), %r9
movq %rax, 0x18(%r9)
movq (%r9), %rcx
leaq 0x1(%rcx), %rdx
movq %rdx, (%r9)
imulq $0x60, %rcx, %rcx
movq %rsi, (%rax,%rcx)
movq 0x30(%rsp), %rdx
movq %rdx, 0x8(%rax,%rcx)
movl %r11d, 0x10(%rax,%rcx)
movl %r10d, 0x14(%rax,%rcx)
movl 0x20(%rsp), %edx
movl %edx, 0x18(%rax,%rcx)
movl %ebx, 0x1c(%rax,%rcx)
andq $0x0, 0x20(%rax,%rcx)
shrq %r13
andl $0x0, 0x28(%rax,%rcx)
movl 0x28(%rsp), %edx
movl %edx, 0x2c(%rax,%rcx)
andq $0x0, 0x30(%rax,%rcx)
movl %r13d, 0x38(%rax,%rcx)
orl $-0x1, 0x3c(%rax,%rcx)
andq $0x0, 0x40(%rax,%rcx)
movl 0x4(%rsp), %edx
movl %edx, 0x48(%rax,%rcx)
pxor %xmm0, %xmm0
movdqu %xmm0, 0x4c(%rax,%rcx)
andl $0x0, 0x5c(%rax,%rcx)
movq (%r9), %rax
leaq -0x1(%rax), %rsi
leal -0x1(%rax), %ecx
pushq $0x1c
popq %rdi
xorl %edx, %edx
cmpq %rdx, %rsi
je 0x1c10a
movq 0x18(%r9), %r8
cmpl %ebx, (%r8,%rdi)
jl 0x1c10c
incq %rdx
addq $0x60, %rdi
jmp 0x1c0f2
movl %ecx, %edx
addl $-0x2, %eax
movslq %ecx, %rcx
imulq $0x60, %rcx, %r8
leal 0x1(%rax), %esi
movq 0x18(%r9), %rcx
cmpl %edx, %esi
jle 0x1c13d
leaq (%rcx,%r8), %rdi
movslq %eax, %rsi
imulq $0x60, %rsi, %rsi
addq %rcx, %rsi
pushq $0xc
popq %rcx
rep  movsq (%rsi), %es:(%rdi)
decl %eax
addq $-0x60, %r8
jmp 0x1c116
movq 0x70(%rsp), %rax
movq %rax, (%rcx,%r8)
movq 0x30(%rsp), %rax
movq %rax, 0x8(%rcx,%r8)
movl %r11d, 0x10(%rcx,%r8)
movl %r10d, 0x14(%rcx,%r8)
movl 0x20(%rsp), %eax
movl %eax, 0x18(%rcx,%r8)
movl %ebx, 0x1c(%rcx,%r8)
andq $0x0, 0x20(%rcx,%r8)
andl $0x0, 0x28(%rcx,%r8)
movl 0x28(%rsp), %eax
movl %eax, 0x2c(%rcx,%r8)
andq $0x0, 0x30(%rcx,%r8)
movl %r13d, 0x38(%rcx,%r8)
orl $-0x1, 0x3c(%rcx,%r8)
andq $0x0, 0x40(%rcx,%r8)
movl 0x4(%rsp), %eax
movl %eax, 0x48(%rcx,%r8)
pxor %xmm0, %xmm0
movdqu %xmm0, 0x4c(%rcx,%r8)
andl $0x0, 0x5c(%rcx,%r8)
movl 0xc(%rsp), %ebx
incl %ebx
movq 0x100(%rsp), %r13
testl %ebx, %ebx
je 0x1c1ec
movl (%r9), %r8d
movq 0x108(%rsp), %rax
movq 0x18(%rax), %r9
movq 0x78(%rsp), %rdi
xorl %esi, %esi
xorl %edx, %edx
xorl %ecx, %ecx
callq 0x17900
cltq
movq 0x108(%rsp), %rcx
movq %rax, (%rcx)
movq 0x48(%rsp), %rdi
callq 0x3390
movq 0x50(%rsp), %rdi
callq 0x3390
movq 0x108(%rsp), %r9
incq %rbp
jmp 0x1bce3