// File: /workspace/github_cpp_makefile_star2_O1/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:
cmpq %rsi, 0x98(%rdi)
jle 0x416df5
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x38, %rsp
movq %rdi, %rbx
xorl %eax, %eax
cmpq %rdx, %rsi
jle 0x416dfc
xorl %r11d, %r11d
xorl %eax, %eax
jmp 0x416ee8
xorl %eax, %eax
jmp 0x416fca
movq %r8, 0x18(%rsp)
movq 0x60(%rbx), %rdi
movq %rdi, 0x28(%rsp)
movl 0xac(%rbx), %r9d
movzbl 0xc(%rcx), %edi
addl 0x84(%rbx), %edi
addl %edi, %edi
movl %edi, 0xc(%rsp)
movq %rbx, 0x20(%rsp)
movl 0xa8(%rbx), %r14d
movq (%rcx), %r12
movabsq $-0x100000000000000, %r13 # imm = 0xFF00000000000000
movq $0x0, 0x10(%rsp)
xorl %ebp, %ebp
leaq (%rsi,%rdx), %rcx
movq %rcx, %rbx
shrq $0x3f, %rbx
addq %rcx, %rbx
sarq %rbx
movq %rbx, %r11
imulq %r9, %r11
addq 0x28(%rsp), %r11
testq %r14, %r14
je 0x416ea8
xorl %r8d, %r8d
xorl %r10d, %r10d
movl 0xc(%rsp), %ecx
movl %r10d, %r15d
movq (%r12,%r15,8), %r15
shlq %cl, %r15
andq %r13, %r15
movzbl (%r11,%r8), %ebp
shlq $0x38, %rbp
cmpq %rbp, %r15
jne 0x416eab
addl $0x8, %ecx
xorl %edi, %edi
cmpl $0x40, %ecx
cmovel %eax, %ecx
sete %dil
addl %edi, %r10d
incq %r8
cmpl %r8d, %r14d
jne 0x416e71
jmp 0x416eab
xorl %r15d, %r15d
cmpq %rbp, %r15
jne 0x416eb9
movb $0x1, %cl
movq %rcx, 0x10(%rsp)
jmp 0x416ecb
leaq 0x1(%rbx), %rcx
decq %rbx
cmpq %r15, %rbp
cmovaeq %rbx, %rdx
cmovbq %rcx, %rsi
cmpq %rbp, %r15
je 0x416ed9
cmpq %rdx, %rsi
jle 0x416e45
movq 0x20(%rsp), %rbx
movq 0x18(%rsp), %r8
movq 0x10(%rsp), %rax
testb $0x1, %al
je 0x416f77
movl 0xa8(%rbx), %ecx
movzbl (%r11,%rcx), %eax
movq %rax, (%r8)
movl 0x80(%rbx), %edx
cmpq $0x2, %rdx
jb 0x416f3e
leaq (%rcx,%r11), %rsi
incq %rsi
leaq (,%rdx,8), %rdi
movl $0x8, %r10d
movzbl (%rsi), %r9d
movl %r10d, %ecx
andb $-0x8, %cl
shlq %cl, %r9
orq %r9, %rax
movq %rax, (%r8)
addq $0x8, %r10
incq %rsi
cmpq %r10, %rdi
jne 0x416f1f
cmpl $0x0, 0x7c(%rbx)
je 0x416f7b
leaq 0x34(%rsp), %r14
movq %r14, %rdi
movq %r8, %rsi
callq 0x401080
movl 0x8c(%rbx), %eax
cvtsi2ss %rax, %xmm0
movss (%r14), %xmm1
movq 0x90(%rbx), %rax
testq %rax, %rax
js 0x416f98
cvtsi2ss %rax, %xmm2
jmp 0x416fad
xorl %eax, %eax
jmp 0x416fbc
movq (%r8), %rax
movl 0x8c(%rbx), %ecx
cmpq %rcx, %rax
setae %cl
cmpq 0x90(%rbx), %rax
setbe %al
andb %cl, %al
jmp 0x416fbc
movq %rax, %rcx
shrq %rcx
andl $0x1, %eax
orq %rcx, %rax
cvtsi2ss %rax, %xmm2
addss %xmm2, %xmm2
cmpleps %xmm1, %xmm0
cmpleps %xmm2, %xmm1
andps %xmm0, %xmm1
movd %xmm1, %eax
addq $0x38, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
andb $0x1, %al
retq
nop