// File: ChnMasterOG[P]KmerGO2/kmc_api/kmc_file.cpp
// Function: CKMCFile::BinarySearch(long long, long long, CKmerAPI const&, unsigned long long&, unsigned int)
bool CKMCFile::BinarySearch(int64 index_start, int64 index_stop, const CKmerAPI& kmer, uint64& counter, uint32 pattern_offset)
{
	if (index_start >= static_cast<int64>(total_kmers))
		return false;
	uchar *sufix_byte_ptr = nullptr;
	uint64 sufix = 0;

	//sufix_offset is always 56
	uint32 sufix_offset = 56;			// the offset of a sufix is for shifting the sufix towards MSB, to compare the sufix with a pattern
	// Bytes of a pattern to search are always shifted towards MSB

	uint32 row_index = 0;				// the number of a current row in an array kmer_data

	bool found = false;

	while (index_start <= index_stop)
	{
		int64 mid_index = (index_start + index_stop) / 2;
		sufix_byte_ptr = &sufix_file_buf[mid_index * sufix_rec_size];

		uint64 pattern = 0;

		pattern_offset = (lut_prefix_length + kmer.byte_alignment) * 2;

		row_index = 0;
		for (uint32 a = 0; a < sufix_size; a++)		//check byte by byte
		{
			pattern = kmer.kmer_data[row_index];
			pattern = pattern << pattern_offset;
			pattern = pattern & 0xff00000000000000;

			sufix = sufix_byte_ptr[a];
			sufix = sufix << sufix_offset;

			if (pattern != sufix)
				break;

			pattern_offset += 8;

			if (pattern_offset == 64)				//the end of a word
			{
				pattern_offset = 0;
				row_index++;
			}
		}

		if (pattern == sufix)
		{
			found = true;
			break;
		}
		if (sufix < pattern)
			index_start = mid_index + 1;
		else
			index_stop = mid_index - 1;
	}

	if (found)
	{
		sufix_byte_ptr += sufix_size;

		counter = *sufix_byte_ptr;

		for (uint32 b = 1; b < counter_size; b++)
		{
			uint64 aux = 0x000000ff & *(sufix_byte_ptr + b);

			aux = aux << 8 * (b);
			counter = aux | counter;
		}
		if (mode != 0)
		{
			float float_counter;
			memcpy(&float_counter, &counter, counter_size);
			return (float_counter >= min_count) && (float_counter <= max_count);
		}
		return (counter >= min_count) && (counter <= max_count);
	}
	return false;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xa0, %rsp
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq %rdx, -0x20(%rbp)
movq %rcx, -0x28(%rbp)
movq %r8, -0x30(%rbp)
movl %r9d, -0x34(%rbp)
movq -0x10(%rbp), %rcx
movq %rcx, -0x88(%rbp)
movq -0x18(%rbp), %rax
cmpq 0x98(%rcx), %rax
jl 0x424794
movb $0x0, -0x1(%rbp)
jmp 0x424abc
movq $0x0, -0x40(%rbp)
movq $0x0, -0x48(%rbp)
movl $0x38, -0x4c(%rbp)
movl $0x0, -0x50(%rbp)
movb $0x0, -0x51(%rbp)
movq -0x18(%rbp), %rax
cmpq -0x20(%rbp), %rax
jg 0x424901
movq -0x18(%rbp), %rax
addq -0x20(%rbp), %rax
movl $0x2, %ecx
cqto
idivq %rcx
movq %rax, %rcx
movq -0x88(%rbp), %rax
movq %rcx, -0x60(%rbp)
movq 0x60(%rax), %rcx
movq -0x60(%rbp), %rdx
movl 0xac(%rax), %esi
imulq %rsi, %rdx
addq %rdx, %rcx
movq %rcx, -0x40(%rbp)
movq $0x0, -0x68(%rbp)
movl 0x84(%rax), %eax
movq -0x28(%rbp), %rcx
movzbl 0xc(%rcx), %ecx
addl %ecx, %eax
shll %eax
movl %eax, -0x34(%rbp)
movl $0x0, -0x50(%rbp)
movl $0x0, -0x6c(%rbp)
movq -0x88(%rbp), %rcx
movl -0x6c(%rbp), %eax
cmpl 0xa8(%rcx), %eax
jae 0x4248c8
movq -0x28(%rbp), %rax
movq (%rax), %rax
movl -0x50(%rbp), %ecx
movq (%rax,%rcx,8), %rax
movq %rax, -0x68(%rbp)
movq -0x68(%rbp), %rax
movl -0x34(%rbp), %ecx
shlq %cl, %rax
movq %rax, -0x68(%rbp)
movabsq $-0x100000000000000, %rax # imm = 0xFF00000000000000
andq -0x68(%rbp), %rax
movq %rax, -0x68(%rbp)
movq -0x40(%rbp), %rax
movl -0x6c(%rbp), %ecx
movzbl (%rax,%rcx), %eax
movq %rax, -0x48(%rbp)
movq -0x48(%rbp), %rax
movl -0x4c(%rbp), %ecx
shlq %cl, %rax
movq %rax, -0x48(%rbp)
movq -0x68(%rbp), %rax
cmpq -0x48(%rbp), %rax
je 0x424899
jmp 0x4248c8
movl -0x34(%rbp), %eax
addl $0x8, %eax
movl %eax, -0x34(%rbp)
cmpl $0x40, -0x34(%rbp)
jne 0x4248b8
movl $0x0, -0x34(%rbp)
movl -0x50(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x50(%rbp)
jmp 0x4248ba
movl -0x6c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x6c(%rbp)
jmp 0x424828
movq -0x68(%rbp), %rax
cmpq -0x48(%rbp), %rax
jne 0x4248d8
movb $0x1, -0x51(%rbp)
jmp 0x424901
movq -0x48(%rbp), %rax
cmpq -0x68(%rbp), %rax
jae 0x4248f0
movq -0x60(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x18(%rbp)
jmp 0x4248fc
movq -0x60(%rbp), %rax
subq $0x1, %rax
movq %rax, -0x20(%rbp)
jmp 0x4247b6
testb $0x1, -0x51(%rbp)
je 0x424ab8
movq -0x88(%rbp), %rax
movl 0xa8(%rax), %ecx
movq -0x40(%rbp), %rax
movl %ecx, %ecx
addq %rcx, %rax
movq %rax, -0x40(%rbp)
movq -0x40(%rbp), %rax
movzbl (%rax), %eax
movl %eax, %ecx
movq -0x30(%rbp), %rax
movq %rcx, (%rax)
movl $0x1, -0x70(%rbp)
movq -0x88(%rbp), %rcx
movl -0x70(%rbp), %eax
cmpl 0x80(%rcx), %eax
jae 0x424994
movq -0x40(%rbp), %rax
movl -0x70(%rbp), %ecx
movzbl (%rax,%rcx), %eax
andl $0xff, %eax
cltq
movq %rax, -0x78(%rbp)
movq -0x78(%rbp), %rax
movl -0x70(%rbp), %ecx
shll $0x3, %ecx
movl %ecx, %ecx
shlq %cl, %rax
movq %rax, -0x78(%rbp)
movq -0x78(%rbp), %rcx
movq -0x30(%rbp), %rax
orq (%rax), %rcx
movq -0x30(%rbp), %rax
movq %rcx, (%rax)
movl -0x70(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x70(%rbp)
jmp 0x42493c
movq -0x88(%rbp), %rax
cmpl $0x0, 0x7c(%rax)
je 0x424a6a
movq -0x88(%rbp), %rax
movq -0x30(%rbp), %rsi
movl 0x80(%rax), %eax
movl %eax, %edx
leaq -0x7c(%rbp), %rdi
callq 0x401080
movq -0x88(%rbp), %rax
movss -0x7c(%rbp), %xmm0
movl 0x8c(%rax), %eax
cvtsi2ss %rax, %xmm1
xorl %eax, %eax
ucomiss %xmm1, %xmm0
movb %al, -0x89(%rbp)
jb 0x424a5d
movq -0x88(%rbp), %rax
movss -0x7c(%rbp), %xmm0
movss %xmm0, -0x98(%rbp)
movq 0x90(%rax), %rax
movq %rax, %rdx
shrq %rdx
movl %eax, %ecx
andl $0x1, %ecx
orq %rdx, %rcx
cvtsi2ss %rcx, %xmm0
addss %xmm0, %xmm0
cvtsi2ss %rax, %xmm1
movss %xmm1, -0x94(%rbp)
testq %rax, %rax
movss %xmm0, -0x90(%rbp)
js 0x424a41
movss -0x94(%rbp), %xmm0
movss %xmm0, -0x90(%rbp)
movss -0x98(%rbp), %xmm1
movss -0x90(%rbp), %xmm0
ucomiss %xmm1, %xmm0
setae %al
movb %al, -0x89(%rbp)
movb -0x89(%rbp), %al
andb $0x1, %al
movb %al, -0x1(%rbp)
jmp 0x424abc
movq -0x88(%rbp), %rax
movq -0x30(%rbp), %rcx
movq (%rcx), %rcx
movl 0x8c(%rax), %eax
movl %eax, %edx
xorl %eax, %eax
cmpq %rdx, %rcx
movb %al, -0x99(%rbp)
jb 0x424aab
movq -0x88(%rbp), %rcx
movq -0x30(%rbp), %rax
movq (%rax), %rax
cmpq 0x90(%rcx), %rax
setbe %al
movb %al, -0x99(%rbp)
movb -0x99(%rbp), %al
andb $0x1, %al
movb %al, -0x1(%rbp)
jmp 0x424abc
movb $0x0, -0x1(%rbp)
movb -0x1(%rbp), %al
andb $0x1, %al
addq $0xa0, %rsp
popq %rbp
retq
nopw (%rax,%rax)