// File: /workspace/github_cpp_makefile_star2_O1/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), %ebx
incl %ebx
movl 0x18(%rdi), %r8d
movq 0x8(%rdx), %r14
movq 0x8(%rdi), %r10
movl $0x0, -0xc(%rsp)
xorl %edx, %edx
xorl %r15d, %r15d
movq %r14, -0x8(%rsp)
leal (%r15,%rbx), %ecx
movl %ecx, %r12d
shrl %r12d
cmpl %r15d, %r12d
jne 0x2b3a1
cmpl $0x2, %ecx
jb 0x2b397
movl %r12d, %ecx
cmpl %esi, -0x4(%r14,%rcx,4)
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
cmovel %eax, %r12d
xorl %ecx, %ecx
movl %r12d, %eax
jmp 0x2b50f
leal -0x1(%r12), %ecx
movl (%r14,%rcx,4), %r11d
cmpl %esi, %r11d
jne 0x2b3bb
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
xorl %ecx, %ecx
jmp 0x2b50f
movl %eax, -0x14(%rsp)
movl -0xc(%rsp), %eax
cmpl %edx, %eax
movl %edx, -0x10(%rsp)
movl %edx, %r13d
cmovbl %eax, %r13d
leal (%r11,%r13), %edi
cmpl %r8d, %edi
setae %cl
leal (%rsi,%r13), %edx
cmpl %r8d, %edx
setae %r9b
orb %cl, %r9b
jne 0x2b455
addl %edx, %edx
addl %edi, %edi
movl %edi, %r9d
movl %edx, %r14d
leal (%rsi,%r13), %edx
leal (%r11,%r13), %edi
movl %edi, %ecx
shrl $0x4, %ecx
movl (%r10,%rcx,4), %ebp
movl %r9d, %ecx
andb $0x1e, %cl
shrl %cl, %ebp
movl %edx, %ecx
shrl $0x4, %ecx
movl (%r10,%rcx,4), %eax
movl %r14d, %ecx
andb $0x1e, %cl
shrl %cl, %eax
xorl %ebp, %eax
testb $0x3, %al
jne 0x2b45a
movl %r13d, %ebp
incl %ebp
leal (%r11,%r13), %eax
incl %eax
cmpl %r8d, %eax
jae 0x2b44a
addl $0x2, %r14d
addl $0x2, %r9d
leal (%rsi,%r13), %eax
incl %eax
movl %ebp, %r13d
cmpl %r8d, %eax
jb 0x2b3f4
leal (%rsi,%rbp), %edx
addl %ebp, %r11d
movl %r11d, %edi
jmp 0x2b45d
movl %r13d, %ebp
jmp 0x2b462
movl %r13d, %ebp
movq -0x8(%rsp), %r14
cmpl %r8d, %edi
sete %al
cmpl %r8d, %edx
sete %r9b
orb %al, %r9b
cmpb $0x1, %r9b
jne 0x2b47f
cmpl %r8d, %edx
je 0x2b4a7
jmp 0x2b4be
movl %edi, %eax
shrl $0x4, %eax
movl (%r10,%rax,4), %eax
leal (%rdi,%rdi), %ecx
shrl %cl, %eax
movl %edx, %ecx
shrl $0x4, %ecx
movl (%r10,%rcx,4), %r11d
leal (%rdx,%rdx), %ecx
shrl %cl, %r11d
andb $0x3, %al
andb $0x3, %r11b
cmpb %r11b, %al
jae 0x2b4b9
movl -0x10(%rsp), %eax
cmpl %ebp, %eax
cmoval %eax, %ebp
movb $0x1, %cl
movl %ebp, %edx
movl %r12d, %r15d
jmp 0x2b50b
testb %r9b, %r9b
je 0x2b4ca
cmpl %r8d, %edi
je 0x2b4f5
movb $0x1, %cl
testb %r9b, %r9b
jne 0x2b507
movl %edi, %eax
shrl $0x4, %eax
movl (%r10,%rax,4), %eax
addl %edi, %edi
movl %edi, %ecx
shrl %cl, %eax
movl %edx, %ecx
shrl $0x4, %ecx
movl (%r10,%rcx,4), %edi
addl %edx, %edx
movl %edx, %ecx
shrl %cl, %edi
andb $0x3, %al
andb $0x3, %dil
movb $0x1, %cl
cmpb %dil, %al
jbe 0x2b507
movl -0xc(%rsp), %eax
cmpl %ebp, %eax
cmoval %eax, %ebp
movb $0x1, %cl
movl %ebp, -0xc(%rsp)
movl %r12d, %ebx
movl -0x10(%rsp), %edx
movl -0x14(%rsp), %eax
testb %cl, %cl
jne 0x2b372
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq