// File: BenLangmead[P]bowtie/./blockwise_sa.h
// Function: KarkkainenBlockwiseSA<SString<char>>::suffixCmp(unsigned int, unsigned int, long&, long&, bool&, EList<unsigned int, 128> const&)
inline
bool KarkkainenBlockwiseSA<TStr>::suffixCmp(
	TIndexOffU cmp,
	TIndexOffU i,
	int64_t& j,
	int64_t& k,
	bool& kSoft,
	const EList<TIndexOffU>& z)
{
	const TStr& t = this->text();
	TIndexOffU len = TIndexOffU(t.length());
	// i is not covered by any previous match
	TIndexOffU l;
	if((int64_t)i > k) {
		k = i; // so that i + lHi == kHi
		l = 0; // erase any previous l
		kSoft = false;
		// To be extended
	}
	// i is covered by a previous match
	else /* i <= k */ {
		assert_gt((int64_t)i, j);
		TIndexOffU zIdx = (TIndexOffU)(i-j);
		assert_leq(zIdx, len-cmp);
		if(zIdx < _dcV || _dc == NULL) {
			// Go as far as the Z-box says
			l = lookupSuffixZ(t, zIdx, cmp, z);
			if(i + l > len) {
				l = len-i;
			}
			assert_leq(i + l, len);
			// Possibly to be extended
		} else {
			// But we're past the point of no-more-Z-boxes
			bool ret = tieBreakingLcp(i, cmp, l, kSoft);
			// Sanity-check tie-breaker
			if(this->sanityCheck()) {
				if(ret) assert(sstr_suf_lt(t, i, t, cmp, false));
				else    assert(sstr_suf_gt(t, i, t, cmp, false));
			}
			j = i;
			k = i + l;
			if(this->sanityCheck()) {
				if(kSoft) { assert_leq(l, suffixLcp(t, i, cmp)); }
				else      { assert_eq (l, suffixLcp(t, i, cmp)); }
			}
			return ret;
		}
	}

	// Z box extends exactly as far as previous match (or there
	// is neither a Z box nor a previous match)
	if((int64_t)(i + l) == k) {
		// Extend
		while(l < len-cmp && k < (int64_t)len && t[(size_t)(cmp+l)] == t[(size_t)k]) {
			k++; l++;
		}
		j = i; // update furthest-extending LHS
		kSoft = false;
		assert_eq(l, suffixLcp(t, i, cmp));
	}
	// Z box extends further than previous match
	else if((int64_t)(i + l) > k) {
		l = (TIndexOffU)(k - i); // point to just after previous match
		j = i; // update furthest-extending LHS
		if(kSoft) {
			while(l < len-cmp && k < (int64_t)len && t[(size_t)(cmp+l)] == t[(size_t)k]) {
				k++; l++;
			}
			kSoft = false;
			assert_eq(l, suffixLcp(t, i, cmp));
		} else assert_eq(l, suffixLcp(t, i, cmp));
	}

	// Check that calculated lcp matches actual lcp
	if(this->sanityCheck()) {
		if(!kSoft) {
			// l should exactly match lcp
			assert_eq(l, suffixLcp(t, i, cmp));
		} else {
			// l is an underestimate of LCP
			assert_leq(l, suffixLcp(t, i, cmp));
		}
	}
	assert_leq(l+i, len);
	assert_leq(l, len-cmp);

	// i and cmp should not be the same suffix
	assert(l != len-cmp || i+l != len);

	// Now we're ready to do a comparison on the next char
	if(l+i != len && (
		   l == len-cmp || // departure from paper algorithm:
		   // falling off pattern implies
		   // pattern is *greater* in our case
		   t[i + l] < t[cmp + l]))
	{
		// Case 2: Text suffix is less than upper sample suffix
#ifndef NDEBUG
		if(this->sanityCheck()) {
			assert(sstr_suf_lt(t, i, t, cmp, false));
		}
#endif

		return true; // suffix at i is less than suffix at cmp
	}
	else {
		// Case 3: Text suffix is greater than upper sample suffix
#ifndef NDEBUG
		if(this->sanityCheck()) {
			assert(sstr_suf_gt(t, i, t, cmp, false));
		}
#endif

		return false; // suffix at i is less than suffix at cmp
	}
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x70, %rsp
movq 0x10(%rbp), %rax
movq %rdi, -0x10(%rbp)
movl %esi, -0x14(%rbp)
movl %edx, -0x18(%rbp)
movq %rcx, -0x20(%rbp)
movq %r8, -0x28(%rbp)
movq %r9, -0x30(%rbp)
movq -0x10(%rbp), %rdi
movq %rdi, -0x50(%rbp)
callq 0x271c0
movq %rax, -0x38(%rbp)
movq -0x38(%rbp), %rdi
callq 0x14c10
movl %eax, -0x3c(%rbp)
movl -0x18(%rbp), %eax
movq -0x28(%rbp), %rcx
cmpq (%rcx), %rax
jle 0x3069a
movl -0x18(%rbp), %eax
movl %eax, %ecx
movq -0x28(%rbp), %rax
movq %rcx, (%rax)
movl $0x0, -0x40(%rbp)
movq -0x30(%rbp), %rax
movb $0x0, (%rax)
jmp 0x3076b
movq -0x50(%rbp), %rcx
movl -0x18(%rbp), %eax
movq -0x20(%rbp), %rdx
subq (%rdx), %rax
movl %eax, -0x44(%rbp)
movl -0x44(%rbp), %eax
cmpl 0x74(%rcx), %eax
jb 0x306be
movq -0x50(%rbp), %rax
cmpq $0x0, 0x78(%rax)
jne 0x306ea
movq -0x38(%rbp), %rdi
movl -0x44(%rbp), %esi
movl -0x14(%rbp), %edx
movq 0x10(%rbp), %rcx
callq 0x12b00
movl %eax, -0x40(%rbp)
movl -0x18(%rbp), %eax
addl -0x40(%rbp), %eax
cmpl -0x3c(%rbp), %eax
jbe 0x306e8
movl -0x3c(%rbp), %eax
subl -0x18(%rbp), %eax
movl %eax, -0x40(%rbp)
jmp 0x30769
movq -0x50(%rbp), %rdi
movl -0x18(%rbp), %esi
movl -0x14(%rbp), %edx
movq -0x30(%rbp), %r8
leaq -0x40(%rbp), %rcx
callq 0x30980
movq -0x50(%rbp), %rdi
andb $0x1, %al
movb %al, -0x45(%rbp)
callq 0x27200
testb $0x1, %al
jne 0x30715
jmp 0x30721
testb $0x1, -0x45(%rbp)
je 0x3071d
jmp 0x3071f
jmp 0x3071f
jmp 0x30721
movq -0x50(%rbp), %rdi
movl -0x18(%rbp), %eax
movl %eax, %ecx
movq -0x20(%rbp), %rax
movq %rcx, (%rax)
movl -0x18(%rbp), %eax
addl -0x40(%rbp), %eax
movl %eax, %eax
movl %eax, %ecx
movq -0x28(%rbp), %rax
movq %rcx, (%rax)
callq 0x27200
testb $0x1, %al
jne 0x3074d
jmp 0x3075c
movq -0x30(%rbp), %rax
testb $0x1, (%rax)
je 0x30758
jmp 0x3075a
jmp 0x3075a
jmp 0x3075c
movb -0x45(%rbp), %al
andb $0x1, %al
movb %al, -0x1(%rbp)
jmp 0x30970
jmp 0x3076b
movl -0x18(%rbp), %eax
addl -0x40(%rbp), %eax
movl %eax, %eax
movq -0x28(%rbp), %rcx
cmpq (%rcx), %rax
jne 0x30821
jmp 0x30782
movl -0x40(%rbp), %ecx
movl -0x3c(%rbp), %edx
subl -0x14(%rbp), %edx
xorl %eax, %eax
cmpl %edx, %ecx
movb %al, -0x51(%rbp)
jae 0x307e4
movq -0x28(%rbp), %rax
movq (%rax), %rcx
movl -0x3c(%rbp), %eax
movl %eax, %edx
xorl %eax, %eax
cmpq %rdx, %rcx
movb %al, -0x51(%rbp)
jge 0x307e4
movq -0x38(%rbp), %rdi
movl -0x14(%rbp), %eax
addl -0x40(%rbp), %eax
movl %eax, %eax
movl %eax, %esi
callq 0x14c30
movsbl (%rax), %eax
movl %eax, -0x58(%rbp)
movq -0x38(%rbp), %rdi
movq -0x28(%rbp), %rax
movq (%rax), %rsi
callq 0x14c30
movq %rax, %rcx
movl -0x58(%rbp), %eax
movsbl (%rcx), %ecx
cmpl %ecx, %eax
sete %al
movb %al, -0x51(%rbp)
movb -0x51(%rbp), %al
testb $0x1, %al
jne 0x307ed
jmp 0x30809
movq -0x28(%rbp), %rax
movq (%rax), %rcx
addq $0x1, %rcx
movq %rcx, (%rax)
movl -0x40(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x40(%rbp)
jmp 0x30782
movl -0x18(%rbp), %eax
movl %eax, %ecx
movq -0x20(%rbp), %rax
movq %rcx, (%rax)
movq -0x30(%rbp), %rax
movb $0x0, (%rax)
jmp 0x308f7
movl -0x18(%rbp), %eax
addl -0x40(%rbp), %eax
movl %eax, %eax
movq -0x28(%rbp), %rcx
cmpq (%rcx), %rax
jle 0x308f5
movq -0x28(%rbp), %rax
movq (%rax), %rax
movl -0x18(%rbp), %ecx
subq %rcx, %rax
movl %eax, -0x40(%rbp)
movl -0x18(%rbp), %eax
movl %eax, %ecx
movq -0x20(%rbp), %rax
movq %rcx, (%rax)
movq -0x30(%rbp), %rax
testb $0x1, (%rax)
je 0x308f1
jmp 0x30861
movl -0x40(%rbp), %ecx
movl -0x3c(%rbp), %edx
subl -0x14(%rbp), %edx
xorl %eax, %eax
cmpl %edx, %ecx
movb %al, -0x59(%rbp)
jae 0x308c3
movq -0x28(%rbp), %rax
movq (%rax), %rcx
movl -0x3c(%rbp), %eax
movl %eax, %edx
xorl %eax, %eax
cmpq %rdx, %rcx
movb %al, -0x59(%rbp)
jge 0x308c3
movq -0x38(%rbp), %rdi
movl -0x14(%rbp), %eax
addl -0x40(%rbp), %eax
movl %eax, %eax
movl %eax, %esi
callq 0x14c30
movsbl (%rax), %eax
movl %eax, -0x60(%rbp)
movq -0x38(%rbp), %rdi
movq -0x28(%rbp), %rax
movq (%rax), %rsi
callq 0x14c30
movq %rax, %rcx
movl -0x60(%rbp), %eax
movsbl (%rcx), %ecx
cmpl %ecx, %eax
sete %al
movb %al, -0x59(%rbp)
movb -0x59(%rbp), %al
testb $0x1, %al
jne 0x308cc
jmp 0x308e8
movq -0x28(%rbp), %rax
movq (%rax), %rcx
addq $0x1, %rcx
movq %rcx, (%rax)
movl -0x40(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x40(%rbp)
jmp 0x30861
movq -0x30(%rbp), %rax
movb $0x0, (%rax)
jmp 0x308f3
jmp 0x308f3
jmp 0x308f5
jmp 0x308f7
movq -0x50(%rbp), %rdi
callq 0x27200
testb $0x1, %al
jne 0x30906
jmp 0x30915
movq -0x30(%rbp), %rax
testb $0x1, (%rax)
jne 0x30911
jmp 0x30913
jmp 0x30913
jmp 0x30915
movl -0x40(%rbp), %eax
addl -0x18(%rbp), %eax
cmpl -0x3c(%rbp), %eax
je 0x3096c
movl -0x40(%rbp), %eax
movl -0x3c(%rbp), %ecx
subl -0x14(%rbp), %ecx
cmpl %ecx, %eax
je 0x30966
movq -0x38(%rbp), %rdi
movl -0x18(%rbp), %eax
addl -0x40(%rbp), %eax
movl %eax, %eax
movl %eax, %esi
callq 0x14c30
movsbl (%rax), %eax
movl %eax, -0x64(%rbp)
movq -0x38(%rbp), %rdi
movl -0x14(%rbp), %eax
addl -0x40(%rbp), %eax
movl %eax, %eax
movl %eax, %esi
callq 0x14c30
movq %rax, %rcx
movl -0x64(%rbp), %eax
movsbl (%rcx), %ecx
cmpl %ecx, %eax
jge 0x3096c
movb $0x1, -0x1(%rbp)
jmp 0x30970
movb $0x0, -0x1(%rbp)
movb -0x1(%rbp), %al
andb $0x1, %al
addq $0x70, %rsp
popq %rbp
retq
nopl (%rax,%rax)