// File: /workspace/github_cpp_makefile_star2_O2/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
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x38, %rsp
xorl %ebp, %ebp
cmpq %rsi, 0x98(%rdi)
jle 0x4108e1
movq %rdx, %r9
movq %r8, 0x10(%rsp)
movq 0x60(%rdi), %rax
movq %rax, 0x28(%rsp)
movl 0xac(%rdi), %eax
movq %rax, 0x20(%rsp)
movzbl 0xc(%rcx), %eax
addl 0x84(%rdi), %eax
addl %eax, %eax
movl %eax, 0xc(%rsp)
movq %rdi, 0x18(%rsp)
movl 0xa8(%rdi), %r14d
movq (%rcx), %r15
pushq $0x2
popq %rdi
movabsq $-0x100000000000000, %r13 # imm = 0xFF00000000000000
xorl %r8d, %r8d
xorl %r12d, %r12d
cmpq %r9, %rsi
jg 0x41081f
leaq (%rsi,%r9), %rax
cqto
idivq %rdi
movq %rax, %rdx
imulq 0x20(%rsp), %rdx
addq 0x28(%rsp), %rdx
xorl %r10d, %r10d
movl 0xc(%rsp), %ecx
xorl %r11d, %r11d
movq %r8, %rbx
cmpq %r10, %r14
je 0x410800
movl %r12d, %r8d
movq (%r15,%r8,8), %r8
shlq %cl, %r8
andq %r13, %r8
movzbl (%rdx,%r10), %ebx
shlq $0x38, %rbx
cmpq %rbx, %r8
jne 0x4107fd
addl $0x8, %ecx
xorl %r11d, %r11d
cmpl $0x40, %ecx
cmovel %ebp, %ecx
sete %r11b
addl %r11d, %r12d
incq %r10
movq %r8, %r11
jmp 0x4107bf
movq %r8, %r11
cmpq %rbx, %r11
je 0x410826
leaq 0x1(%rax), %rcx
decq %rax
cmpq %r11, %rbx
cmovaeq %rax, %r9
cmovbq %rcx, %rsi
movq %rbx, %r8
jmp 0x410792
xorl %ebp, %ebp
jmp 0x4108e1
leaq (%rdx,%r14), %r10
movzbl (%rdx,%r14), %eax
movq 0x10(%rsp), %rsi
movq %rax, (%rsi)
movq 0x18(%rsp), %rbx
movl 0x80(%rbx), %edx
pushq $0x1
popq %rdi
pushq $0x8
popq %r8
cmpq %rdx, %rdi
jae 0x41086b
movzbl (%r10,%rdi), %r9d
movl %r8d, %ecx
andb $-0x8, %cl
shlq %cl, %r9
orq %r9, %rax
movq %rax, (%rsi)
incq %rdi
addq $0x8, %r8
jmp 0x410849
cmpl $0x0, 0x7c(%rbx)
je 0x4108a1
leaq 0x34(%rsp), %r14
movq %r14, %rdi
callq 0x401080
movl 0x8c(%rbx), %eax
cvtsi2ss %rax, %xmm0
movss (%r14), %xmm1
movq 0x90(%rbx), %rax
testq %rax, %rax
js 0x4108bd
cvtsi2ss %rax, %xmm2
jmp 0x4108d2
movl 0x8c(%rbx), %ecx
cmpq %rcx, %rax
setae %cl
cmpq 0x90(%rbx), %rax
setbe %bpl
andb %cl, %bpl
jmp 0x4108e1
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, %ebp
andb $0x1, %bpl
movl %ebp, %eax
addq $0x38, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq