// File: /workspace/github_cpp_makefile_star2_O2/BenLangmead[P]bowtie/./binary_sa_search.h
// Function: unsigned int binarySASearch<S2bDnaString, unsigned int>(S2bDnaString const&, unsigned int, EList<unsigned int, 128> const&)
inline
TIndexOffU binarySASearch(const TStr& host,
			  TIndexOffU qry,
			  const EList<TSufElt>& sa)
{
	TIndexOffU lLcp = 0, rLcp = 0; // greatest observed LCPs on left and right
	TIndexOffU l = 0, r = (TIndexOffU)sa.size()+1; // binary-search window
	TIndexOffU hostLen = TIndexOffU(host.length());
	while(true) {
		assert_gt(r, l);
		TIndexOffU m = (l+r) >> 1;
		if(m == l) {
			// Binary-search window has closed: we have an answer
			if(m > 0 && sa[m-1] == qry) return std::numeric_limits<TIndexOffU>::max(); // qry matches
			assert_leq(m, sa.size());
			return m; // Return index of right-hand suffix
		}
		assert_gt(m, 0);
		TIndexOffU suf = sa[m-1];
		if(suf == qry) return std::numeric_limits<TIndexOffU>::max(); // query matches an elt of sa
		TIndexOffU lcp = min(lLcp, rLcp);
#ifndef NDEBUG
                if (sstr_suf_upto_neq(host, qry, host, suf, lcp)) {
			assert(0);
                }
#endif
		// Keep advancing lcp, but stop when query mismatches host or
		// when the counter falls off either the query or the suffix
		while(suf+lcp < hostLen && qry+lcp < hostLen && host[suf+lcp] == host[qry+lcp]) {
			lcp++;
		}
		// Fell off the end of either the query or the sa elt?
		bool fell = (suf+lcp == hostLen || qry+lcp == hostLen);
		if((fell && qry+lcp == hostLen) || (!fell && host[suf+lcp] < host[qry+lcp])) {
			// Query is greater than sa elt
			l = m;                 // update left bound
			lLcp = max(lLcp, lcp); // update left lcp
		}
		else if((fell && suf+lcp == hostLen) || (!fell && host[suf+lcp] > host[qry+lcp])) {
			// Query is less than sa elt
			r = m;                 // update right bound
			rLcp = max(rLcp, lcp); // update right lcp
		} else {
			assert(false); // Must be one or the other!
		}
	}
	// Shouldn't get here
	assert(false);
	return std::numeric_limits<TIndexOffU>::max();
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
movl 0x18(%rdx), %r13d
incl %r13d
movl 0x18(%rdi), %r9d
movq 0x8(%rdx), %rax
movq %rax, -0x20(%rsp)
movq 0x8(%rdi), %r10
movl %r9d, %eax
negl %eax
movl %eax, -0x24(%rsp)
movl %esi, %eax
subl %r9d, %eax
movq %rax, -0x10(%rsp)
xorl %ecx, %ecx
xorl %edx, %edx
movq $0x0, -0x38(%rsp)
movq %r13, -0x18(%rsp)
movl %ecx, -0x30(%rsp)
movq -0x38(%rsp), %rax
addl %r13d, %eax
movl %eax, -0x28(%rsp)
movl %eax, %r13d
shrl %r13d
leal -0x1(%r13), %eax
movq %rax, -0x8(%rsp)
cmpl %edx, %ecx
movl %edx, -0x2c(%rsp)
movl %edx, %r12d
cmovbl %ecx, %r12d
leal (%rsi,%r12), %ebp
addl %ebp, %ebp
cmpl -0x38(%rsp), %r13d
je 0x21ede
movq -0x20(%rsp), %rax
movq -0x8(%rsp), %rcx
movl (%rax,%rcx,4), %r8d
cmpl %esi, %r8d
je 0x21eec
leal (%r12,%r8), %edi
addl %edi, %edi
movl %ebp, %edx
movl %r12d, %ebx
leal (%r8,%rbx), %r14d
leal (%rsi,%rbx), %r11d
cmpl %r9d, %r14d
jae 0x21e54
cmpl %r9d, %r11d
jae 0x21e54
movl %r14d, %ecx
shrl $0x4, %ecx
movl (%r10,%rcx,4), %r15d
movl %edi, %ecx
andb $0x1e, %cl
shrl %cl, %r15d
movl %r11d, %ecx
shrl $0x4, %ecx
movl (%r10,%rcx,4), %eax
movl %edx, %ecx
andb $0x1e, %cl
shrl %cl, %eax
xorl %r15d, %eax
testb $0x3, %al
jne 0x21e54
incl %ebx
addl $0x2, %edx
addl $0x2, %edi
jmp 0x21e0e
movq -0x10(%rsp), %rax
leal (%rax,%rbx), %r8d
movl %r14d, %ecx
addl -0x24(%rsp), %ecx
je 0x21e9d
testl %r8d, %r8d
je 0x21e9d
shrl $0x4, %r14d
movl (%r10,%r14,4), %eax
andb $0x1e, %dil
movl %edi, %ecx
shrl %cl, %eax
shrl $0x4, %r11d
movl (%r10,%r11,4), %edi
andb $0x1e, %dl
movl %edx, %ecx
shrl %cl, %edi
andb $0x3, %al
andb $0x3, %dil
cmpb %dil, %al
jb 0x21eac
jbe 0x21de1
jmp 0x21eca
testl %r8d, %r8d
je 0x21eac
testl %ecx, %ecx
jne 0x21de1
jmp 0x21eca
movl -0x2c(%rsp), %eax
cmpl %ebx, %eax
cmoval %eax, %ebx
movl %ebx, %edx
movq %r13, -0x38(%rsp)
movq -0x18(%rsp), %r13
movl -0x30(%rsp), %ecx
jmp 0x21db3
movl -0x30(%rsp), %eax
cmpl %ebx, %eax
cmoval %eax, %ebx
movl %ebx, %ecx
movl -0x2c(%rsp), %edx
jmp 0x21daa
cmpl $0x2, -0x28(%rsp)
jae 0x21ef3
movq -0x38(%rsp), %rax
jmp 0x21f0b
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
jmp 0x21f0b
movq -0x38(%rsp), %rdx
movl %edx, %eax
movq -0x20(%rsp), %rcx
cmpl %esi, -0x4(%rcx,%rax,4)
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
cmovnel %edx, %eax
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq