// File: /workspace/github_c_makefile_star2_O3/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 $0xd8, %rsp
movl %r9d, 0x14(%rsp)
movq %r8, 0x28(%rsp)
movq %rcx, %r11
movq %rdx, 0xb0(%rsp)
movq 0x118(%rsp), %rax
movd 0x68(%rcx), %xmm0
movd 0x48(%rcx), %xmm1
punpckldq %xmm0, %xmm1    # xmm1 = xmm1[0],xmm0[0],xmm1[1],xmm0[1]
movd 0x28(%rcx), %xmm0
movd 0x8(%rcx), %xmm2
punpckldq %xmm0, %xmm2    # xmm2 = xmm2[0],xmm0[0],xmm2[1],xmm0[1]
punpcklqdq %xmm1, %xmm2    # xmm2 = xmm2[0],xmm1[0]
pxor %xmm0, %xmm0
pcmpeqd %xmm2, %xmm0
pandn 0x9229(%rip), %xmm0     # 0x29330
movq %rsi, 0xa8(%rsp)
movq (%rsi), %r12
movdqa %xmm0, 0x80(%rsp)
movq (%rax), %rax
testq %rax, %rax
je 0x201b7
movq 0x28(%rsp), %rcx
movq (%rcx), %rcx
movq 0x118(%rsp), %rdx
movq 0x18(%rdx), %rdx
leaq (%r12,%r12), %rsi
cmpq %r12, %rcx
setge %r10b
movq (%rdx), %r8
cmpq %r12, %r8
setl %r9b
xorb %r10b, %r9b
movq %r8, %r10
notq %r10
addq %rsi, %r10
testb %r9b, %r9b
cmovneq %r8, %r10
xorl %r8d, %r8d
subq %rcx, %r10
setle %r8b
movq %r10, %rbx
negq %rbx
cmovsq %r10, %rbx
leaq (%r8,%r8,2), %r10
xorb $0x1, %r9b
movzbl %r9b, %r8d
xorq %r10, %r8
movl %r8d, %r9d
shll $0x5, %r9d
movslq (%r11,%r9), %r10
cmpq %r10, %rbx
jl 0x201ae
addq %r11, %r9
movslq 0x4(%r9), %r9
cmpq %r9, %rbx
jg 0x201ae
movl $0x1, 0x80(%rsp,%r8,4)
addq $0x60, %rdx
decq %rax
jne 0x2013f
movq %rdi, 0x50(%rsp)
movq %r11, 0x40(%rsp)
movdqa 0x80(%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
movl $0x0, 0x10(%rsp)
cmpl $0x4, %eax
je 0x207d8
movq 0x110(%rsp), %r8
movslq 0x14(%rsp), %rcx
addq %r12, %r12
movq 0x50(%rsp), %rax
addq $0xc4, %rax
movq %rax, 0x90(%rsp)
movl %ecx, %r13d
movq %rcx, 0x48(%rsp)
leaq -0x1(%rcx), %rax
movq %rax, 0x98(%rsp)
xorl %r14d, %r14d
movl $0x0, 0x10(%rsp)
movq %r13, 0xa0(%rsp)
cmpl $0x0, 0x80(%rsp,%r14,4)
jne 0x207cb
movl %r14d, %ebp
shrl %ebp
movl %r14d, %r15d
andl $0x1, %r15d
cmpl %r15d, %ebp
jne 0x20295
movq 0x28(%rsp), %rax
movq (%rax), %rdx
cmpq $0x1, %r14
movq 0x118(%rsp), %rbx
movq %r14, %rcx
ja 0x2033d
shlq $0x5, %rcx
movq 0x40(%rsp), %rsi
movslq (%rsi,%rcx), %rax
addq %rdx, %rax
movslq 0x4(%rsi,%rcx), %rcx
addq %rdx, %rcx
jmp 0x2035b
movq 0x48(%rsp), %rbx
movq %rbx, %rdi
leaq 0x90cc(%rip), %rsi      # 0x29370
movl $0x86, %edx
leaq 0x92a6(%rip), %rcx      # 0x29556
callq 0x23213
movq 0x110(%rsp), %rdi
movq %rax, %r9
testl %ebx, %ebx
movq 0x118(%rsp), %rbx
movl $0x4, %r8d
jle 0x20300
movq 0x98(%rsp), %rax
addq %r9, %rax
xorl %ecx, %ecx
movb (%rdi,%rcx), %dl
movb $0x3, %sil
subb %dl, %sil
cmpb $0x4, %dl
movzbl %sil, %edx
cmovael %r8d, %edx
movb %dl, (%rax)
incq %rcx
decq %rax
cmpq %rcx, %r13
jne 0x202df
movq 0x28(%rsp), %rax
movq (%rax), %rdx
movq %r14, %rcx
shlq $0x5, %rcx
cmpq $0x1, %r14
ja 0x20373
movq 0x40(%rsp), %rdi
movslq (%rdi,%rcx), %rsi
movq %rdx, %rax
subq 0x48(%rsp), %rax
addq %rsi, %rax
movq %rax, 0x20(%rsp)
movslq 0x4(%rdi,%rcx), %rcx
addq %rdx, %rcx
movq %r9, 0x58(%rsp)
jmp 0x2039c
shlq $0x5, %rcx
movq 0x40(%rsp), %rdi
movslq 0x4(%rdi,%rcx), %rsi
movq %rdx, %rax
subq %rsi, %rax
movslq (%rdi,%rcx), %rcx
subq %rcx, %rdx
movq %rdx, %rcx
movq %rax, 0x20(%rsp)
addq 0x48(%rsp), %rcx
movq %r8, %r9
movq $0x0, 0x58(%rsp)
jmp 0x2039c
movq 0x40(%rsp), %rdi
movslq 0x4(%rdi,%rcx), %rsi
addq 0x48(%rsp), %rsi
movq %rdx, %rax
subq %rsi, %rax
movq %rax, 0x20(%rsp)
movslq (%rdi,%rcx), %rcx
subq %rcx, %rdx
movq %r9, 0x58(%rsp)
movq %rdx, %rcx
movq %rcx, 0x68(%rsp)
testq %rax, %rax
jns 0x203b1
movq $0x0, 0x20(%rsp)
xorl %eax, %eax
cmpq %r12, %rcx
jle 0x203be
movq %r12, 0x68(%rsp)
movq %r12, %rcx
cmpq %rcx, %rax
jge 0x2041a
addq %rax, %rcx
shrq %rcx
movq 0xa8(%rsp), %rdi
movq 0xb0(%rsp), %rsi
leaq 0x20(%rsp), %rdx
leaq 0x68(%rsp), %r8
movl %r15d, %r13d
movl %ebp, %r15d
movq %r12, %rbp
movq %rbx, %r12
movq %r9, %rbx
leaq 0x7c(%rsp), %r9
callq 0x116eb
movq %rbx, %r9
movq %r12, %rbx
movq %rbp, %r12
movl %r15d, %ebp
movl %r13d, %r15d
movq 0xa0(%rsp), %r13
movq %rax, 0x60(%rsp)
jmp 0x20423
movq $0x0, 0x60(%rsp)
movq 0x28(%rsp), %rax
movl 0x18(%rax), %eax
cmpl 0x7c(%rsp), %eax
jne 0x20787
movq 0x68(%rsp), %rcx
subq 0x20(%rsp), %rcx
movq 0x50(%rsp), %rbx
movslq 0x78(%rbx), %rax
cmpq %rax, %rcx
jge 0x2045a
movq 0x118(%rsp), %rbx
jmp 0x20787
movl (%rbx), %edx
movl %edx, %r8d
movl 0x14(%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(%rbx), %edx
movq %rdx, 0x38(%rsp)
movl 0xc(%rbx), %edx
movq %rdx, 0x18(%rsp)
movl 0x10(%rbx), %r10d
movl 0x14(%rbx), %r11d
subq $0x8, %rsp
leaq 0xc4(%rsp), %rdi
movq %r9, %rdx
movq 0x68(%rsp), %r8
movl $0x5, %r9d
pushq $0x0
pushq %rax
pushq %r11
pushq %r10
pushq 0x40(%rsp)
pushq 0x68(%rsp)
pushq 0xc8(%rsp)
callq 0x23f4d
addq $0x40, %rsp
movl 0xbc(%rsp), %r10d
movl 0xd4(%rsp), %ecx
cmpl 0x78(%rbx), %r10d
setge %al
testl %ecx, %ecx
setns %dl
andb %al, %dl
cmpb $0x1, %dl
movq 0x118(%rsp), %rbx
jne 0x20783
movl 0xc4(%rsp), %r11d
movslq 0xc0(%rsp), %r8
movslq 0xd0(%rsp), %rax
movl %r11d, %edi
notl %edi
movl 0x14(%rsp), %esi
addl %esi, %edi
subl %ecx, %esi
incl %r11d
movq 0x20(%rsp), %rdx
cmpl %r15d, %ebp
movl %edi, %ebp
cmovel %ecx, %ebp
cmovnel %esi, %r11d
jne 0x2054a
addq %rdx, %rax
leaq (%r8,%rdx), %rdi
incq %rdi
movq %rax, %r8
jmp 0x2055c
addq %rdx, %r8
notq %r8
addq %r12, %r8
addq %rdx, %rax
movq %r12, %rdi
subq %rax, %rdi
movl 0xc8(%rsp), %r9d
movq 0x28(%rsp), %rax
movl 0x48(%rax), %esi
movl $0xc0000000, %ecx       # imm = 0xC0000000
andl %ecx, %esi
movl 0x18(%rax), %eax
movl %eax, 0x38(%rsp)
movq %rdi, %r15
subq %r8, %r15
movl %r11d, %eax
subl %ebp, %eax
cltq
cmpq %rax, %r15
cmovgeq %rax, %r15
movq (%rbx), %rcx
movq 0x18(%rbx), %rax
cmpq 0x8(%rbx), %rcx
movq %r8, 0x18(%rsp)
movl %esi, 0xc(%rsp)
movq %rdi, 0x30(%rsp)
movl %r9d, 0x8(%rsp)
jne 0x20617
leaq (%rcx,%rcx), %rdx
testq %rcx, %rcx
movl $0x2, %ecx
cmoveq %rcx, %rdx
movq %rdx, 0x8(%rbx)
shlq $0x5, %rdx
leaq (%rdx,%rdx,2), %rsi
movq %rax, %rdi
leaq 0x8d9c(%rip), %rdx      # 0x29370
movl $0xa6, %ecx
leaq 0x8f76(%rip), %r8       # 0x29556
movl %r10d, 0x78(%rsp)
movl %ebp, 0x74(%rsp)
movl %r11d, %ebp
callq 0x2324c
movl 0x8(%rsp), %r9d
movq 0x30(%rsp), %rdi
movl 0xc(%rsp), %esi
movq 0x18(%rsp), %r8
movl %ebp, %r11d
movl 0x74(%rsp), %ebp
movl 0x78(%rsp), %r10d
movq %rax, 0x18(%rbx)
movq (%rbx), %rcx
shrq %r15
leaq 0x1(%rcx), %rdx
movq %rdx, (%rbx)
leaq (%rcx,%rcx,2), %rcx
shlq $0x5, %rcx
movq %r8, (%rax,%rcx)
movq %rdi, 0x8(%rax,%rcx)
movl %ebp, 0x10(%rax,%rcx)
movl %r11d, 0x14(%rax,%rcx)
movl 0x38(%rsp), %edx
movl %edx, 0x18(%rax,%rcx)
movl %r10d, 0x1c(%rax,%rcx)
xorl %edx, %edx
movq %rdx, 0x20(%rax,%rcx)
movl %edx, 0x28(%rax,%rcx)
movl %r9d, 0x2c(%rax,%rcx)
movq %rdx, 0x30(%rax,%rcx)
movl %r15d, 0x38(%rax,%rcx)
movl $0xffffffff, 0x3c(%rax,%rcx) # imm = 0xFFFFFFFF
movq %rdx, 0x40(%rax,%rcx)
movl %esi, 0x48(%rax,%rcx)
pxor %xmm0, %xmm0
movdqu %xmm0, 0x4c(%rax,%rcx)
movl %edx, 0x5c(%rax,%rcx)
movq (%rbx), %rcx
cmpq $0x1, %rcx
je 0x2071c
movq 0x18(%rbx), %rsi
leal -0x1(%rcx), %edx
addq $0x1c, %rsi
leaq -0x1(%rcx), %rdi
xorl %eax, %eax
xorl %r8d, %r8d
cmpl %r10d, (%rsi)
jl 0x206c2
incq %r8
movabsq $0x100000000, %r9       # imm = 0x100000000
addq %r9, %rax
addq $0x60, %rsi
cmpq %r8, %rdi
jne 0x206a2
jmp 0x20709
cmpl %r8d, %edx
jle 0x20709
movslq %edx, %rdx
sarq $0x20, %rax
movq %rdx, %rsi
shlq $0x5, %rsi
leaq (%rsi,%rsi,2), %r8
movq 0x18(%rbx), %r9
addl $-0x2, %ecx
movslq %ecx, %rcx
leaq (%r9,%r8), %rdi
leaq (%rcx,%rcx,2), %rsi
shlq $0x5, %rsi
addq %r9, %rsi
movl $0xc, %ecx
rep  movsq (%rsi), %es:(%rdi)
movq %rdx, %rcx
decq %rdx
addq $-0x60, %r8
cmpq %rax, %rdx
jg 0x206d9
movq 0x18(%rsp), %r8
movl 0xc(%rsp), %esi
movq 0x30(%rsp), %rdi
movl 0x8(%rsp), %r9d
movq 0x18(%rbx), %rax
movslq %edx, %rcx
leaq (%rcx,%rcx,2), %rcx
shlq $0x5, %rcx
movq %r8, (%rax,%rcx)
movq %rdi, 0x8(%rax,%rcx)
movl %ebp, 0x10(%rax,%rcx)
movl %r11d, 0x14(%rax,%rcx)
movl 0x38(%rsp), %edx
movl %edx, 0x18(%rax,%rcx)
movl %r10d, 0x1c(%rax,%rcx)
xorl %edx, %edx
movq %rdx, 0x20(%rax,%rcx)
movl %edx, 0x28(%rax,%rcx)
movl %r9d, 0x2c(%rax,%rcx)
movq %rdx, 0x30(%rax,%rcx)
movl %r15d, 0x38(%rax,%rcx)
movl $0xffffffff, 0x3c(%rax,%rcx) # imm = 0xFFFFFFFF
movq %rdx, 0x40(%rax,%rcx)
movl %esi, 0x48(%rax,%rcx)
pxor %xmm0, %xmm0
movdqu %xmm0, 0x4c(%rax,%rcx)
movl %edx, 0x5c(%rax,%rcx)
incl 0x10(%rsp)
cmpl $0x0, 0x10(%rsp)
je 0x207aa
movl (%rbx), %r8d
movq 0x18(%rbx), %r9
movq 0x50(%rsp), %rdi
xorl %esi, %esi
xorl %edx, %edx
xorl %ecx, %ecx
callq 0x1a266
cltq
movq %rax, (%rbx)
movq 0x58(%rsp), %rdi
testq %rdi, %rdi
je 0x207b9
callq 0x3390
movq 0x60(%rsp), %rdi
callq 0x3390
movq 0x110(%rsp), %r8
incq %r14
cmpq $0x4, %r14
jne 0x2023b
movl 0x10(%rsp), %eax
addq $0xd8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq