// File: /workspace/github_cpp_makefile_star2_O3/ratulSharker[P]Havec/src/vector_with_rehash_8_hash_with_N_detection_5_bytes.cpp
// Function: storeKhmerInMemBlock5Byte(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, khmerInfo5Byte*, unsigned long long, unsigned long long, char, unsigned int)
int storeKhmerInMemBlock5Byte(string sample,struct khmerInfo5Byte * memBlock,unsigned long long blockSize, unsigned long long khmer_h, char next_neucleotide, unsigned int whichHashFunc){

	unsigned long long index;
	unsigned long long qutioned; //this value must be under 12bit
	char neighbour_musk = 0xF0;
	char *p;

	//find the index value in the memBlock
	index = khmer_h % blockSize;
	
	qutioned = khmer_h / blockSize;//this value must be under 10bit

	//std::cout<<"data :: "<<(int)memBlock[index].data[1]<<std::endl;
	//cout<<"sample khmer "<<sample<<" kmer_h "<<khmer_h<<" hash func no "<<whichHashFunc<<endl;

	//now check the specified index is neighbourless or not (which is equivalent to -> is the space occupied)
	if((memBlock[index].data[4] & neighbour_musk) == 0){
		//no one is occupuying here put khmer_h here

		//putting the qutioned
		p = (char*) &qutioned;
		memBlock[index].data[0] = *p;
		p++;
		memBlock[index].data[1] = *p;
		p++;
		memBlock[index].data[2] = *p;
		p++;
		memBlock[index].data[3] = *p;
		p++;
		memBlock[index].data[4] = 0x01 & (*p);

		//putting "which hash value is stored"
		memBlock[index].data[4] = memBlock[index].data[4] | (whichHashFunc << 1);
		
		/*memBlock[index].data[0] = qutioned & 0xFF;
		memBlock[index].data[1] = (qutioned >> 8) & 0x0F;
		*/

		//std::cout<<"putting in the block array"<<std::endl;

		switch(toupper(next_neucleotide)){//putting the neighbour
		case 'A'://1000
			memBlock[index].data[4] = memBlock[index].data[4] | 0x80;
			break;
		case 'T'://0100
			memBlock[index].data[4] = memBlock[index].data[4] | 0x40;
			break;
		case 'C'://0010
			memBlock[index].data[4] = memBlock[index].data[4] | 0x20;
			break;
		case 'G'://0001
			memBlock[index].data[4] = memBlock[index].data[4] | 0x10;
			break;
		}
		//std::cout<<"index "<<index<<" quotioned :: "<< qutioned<< " data[0]=" <<(int)memBlock[index].data[0]<<" data[1]="<<(int)memBlock[index].data[1]<<std::endl;

		
		
		return MEM_BLOCK; //khmer putted in the mem_block so return mem_block
	}
	else if(((memBlock[index].data[4] >> 1) & 0x07) == whichHashFunc && //hash value matched
			(memBlock[index].data[0] == (qutioned & 0xFF)) &&
			(memBlock[index].data[1] == (qutioned & 0xFF00)>>8) &&
			(memBlock[index].data[2] == (qutioned & 0xFF0000)>>16) &&
			(memBlock[index].data[3] == (qutioned & 0xFF000000)>>24) &&
			((memBlock[index].data[4] & 0x01) == ((qutioned & 0x0100000000) >> 32))){
		//someone is sitting on the memBlock index & who is same as the khmer

		//now just update its neighbour
		//std::cout<<"now just update its neighbour"<<std::endl;
		switch(toupper(next_neucleotide)){//putting the neighbour
		case 'A'://1000
			memBlock[index].data[4] = memBlock[index].data[4] | 0x80;
			break;
		case 'T'://0100
			memBlock[index].data[4] = memBlock[index].data[4] | 0x40;
			break;
		case 'C'://0010
			memBlock[index].data[4] = memBlock[index].data[4] | 0x20;
			break;
		case 'G'://0001
			memBlock[index].data[4] = memBlock[index].data[4] | 0x10;
			break;
		}

		return MEM_BLOCK_FOUND; //khmer putted in the mem_block so return mem_block -- simply update the neighbour table
	}
	else if(whichHashFunc == LAST_HASH_FUNC){
		//only for the last time put in the alternative mem
		//neighbour field is not blank -- someone already sitting there
		//and who sitting there is not same as the given khmer
		//and the set pointer is null so it must be initialized
		//std::cout<<"else reached index "<<index<<" quotioned::"<<qutioned<< " data[0]=" <<(int)memBlock[index].data[0]<<" data[1]="<<(int)memBlock[index].data[1]<<std::endl;
		//expand the set pointer & place the khmer in there
		vector<struct vector_trial_5_byte>::iterator it;
		int index_vect=0;
		int index_v=index%num_of_vector;

		for(it=mapPointer5Byte[index_v].begin();it!=mapPointer5Byte[index_v].end();it++)
		{
			if(it->index_val==index)
			{
				//cout<<"existing value found for index "<<index<<" for khmer "<<khmer_h<<endl;
				break;
			}
			index_vect++;
		}


		if(it == mapPointer5Byte[index_v].end()){
			struct vector_trial_5_byte temp_vect;
			temp_vect.index_val=index;
			//temp_vect.vect_pnt=pp;
			mapPointer5Byte[index_v].push_back(temp_vect);
			//cout<<"new value inserted for index "<<index<<" for khmer "<<khmer_h<<" stored in index "<<index_v<<endl;
		}

		struct khmerInfo5Byte kin;//making a demo
		kin.data[0] = kin.data[1] = kin.data[2] = kin.data[3] = kin.data[4] = 0; //cleaning the demo info
		
		//cout<<"New value inserted in list for memblock index "<<index<<" for khmer "<<khmer_h<<" stored in list in index "<<index_v<<" hash func no "<<whichHashFunc<<endl;
		
		switch(toupper(next_neucleotide)){//putting the neighbour
		case 'A'://1000
			kin.data[4] = kin.data[4] | 0x80;
			break;
		case 'T'://0100
			kin.data[4] = kin.data[4] | 0x40;
			break;
		case 'C'://0010
			kin.data[4] = kin.data[4] | 0x20;
			break;
		case 'G'://s
			kin.data[4] = kin.data[4] | 0x10;
			break;
		}

		//putting the hash function data in the newly made khmerInfo5Byte obj
		
		/*****************************************************/
		//problem occur -- limon
		/*****************************************************/
		bool isFound = false;
		for(std::vector<khmerInfo5Byte>::iterator pi = mapPointer5Byte[index_v][index_vect].vect.begin();
				pi != mapPointer5Byte[index_v][index_vect].vect.end() ; pi++)
		{
			if(
				((pi->data[4] >> 1) & 0x07) == whichHashFunc && //hash value matched
				(pi->data[0] == (qutioned & 0xFF)) &&
				(pi->data[1] == (qutioned & 0xFF00)>>8) &&
				(pi->data[2] == (qutioned & 0xFF0000)>>16) &&
				(pi->data[3] == (qutioned & 0xFF000000)>>24) &&
				((pi->data[4] & 0x01) == ((qutioned & 0x0100000000) >> 32))){
			//(pi->data[0] == (qutioned & 0xFF)) && ((pi->data[1] & 0x0F) == ((qutioned & 0x0F00) >> 8))){
				pi->data[4] = pi->data[4] | kin.data[4];
				isFound = true;
				//cout<<"isFound true"<<endl;
				break;
			}
		}
		if(isFound == false){
		
			//putting the qutioned
			p = (char*) &qutioned;
			kin.data[0] = *p;
			p++;
			kin.data[1] = *p;
			p++;
			kin.data[2] = *p;
			p++;
			kin.data[3] = *p;
			p++;
			kin.data[4] = 0x01 & (*p);
			
			//putting "which hash value is stored"
			kin.data[4] = kin.data[4] | (whichHashFunc << 1); //--optimization		

			(mapPointer5Byte[index_v])[index_vect].vect.push_back(kin);
			
			return LIST;//new entry in the list
		}

		return LIST_FOUND; //khmer found in the list so return LIST_FOUND
	}

	//none of the if-else block is reached so it caused error
	//this means that particular khmer couldn't be placed inside the memblock
	//it will basically return for hash func 0,1,2 -> for hash func 3 if it fails
	//it will be stored in the list/vector/sqlite
	return ERROR;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x38, %rsp
movl %r9d, %ebx
movq %rcx, %rax
movq %rdx, %rcx
xorl %edx, %edx
divq %rcx
movq %rax, %r14
movl %r14d, %r12d
shrl $0x8, %r12d
movl %r14d, %edi
shrl $0x10, %edi
movl %r14d, %r9d
shrl $0x18, %r9d
movq %rax, %r15
shrq $0x20, %r15
leaq (%rdx,%rdx,4), %rax
leaq (%rsi,%rax), %rbp
movzbl 0x4(%rsi,%rax), %r13d
cmpl $0xf, %r13d
ja 0x38db
movb %r14b, (%rbp)
movb %r12b, 0x1(%rbp)
movb %dil, 0x2(%rbp)
movb %r9b, 0x3(%rbp)
andl $0x1, %r15d
leal (%r15,%rbx,2), %ebx
movb %bl, 0x4(%rbp)
movsbl %r8b, %edi
callq 0x3470
movl %eax, %ecx
movl $0x1, %eax
cmpl $0x46, %ecx
jg 0x3a1a
cmpl $0x41, %ecx
je 0x3a43
cmpl $0x43, %ecx
jne 0x3b10
orb $0x20, %bl
jmp 0x3a4b
movq %rdx, %rcx
movl %r13d, %eax
shrl %eax
andl $0x7, %eax
cmpl %ebx, %eax
jne 0x3946
cmpb %r14b, (%rbp)
jne 0x3946
cmpb %r12b, 0x1(%rbp)
jne 0x3946
cmpb %dil, 0x2(%rbp)
jne 0x3946
cmpb %r9b, 0x3(%rbp)
jne 0x3946
movl %r13d, %eax
andl $0x1, %eax
movl %r15d, %edx
andl $0x1, %edx
cmpl %eax, %edx
jne 0x3946
movsbl %r8b, %edi
callq 0x3470
movl %eax, %ecx
movl $0x2, %eax
cmpl $0x46, %ecx
jg 0x3b2c
cmpl $0x41, %ecx
je 0x3b3c
cmpl $0x43, %ecx
jne 0x3b10
orb $0x20, %r13b
jmp 0x3b46
leaq 0xa967(%rip), %rdx      # 0xe2b4
movl $0x3, %eax
cmpl %ebx, (%rdx)
jne 0x3b10
leaq 0xa97f(%rip), %rsi      # 0xe2e0
movq %rcx, %rax
xorl %edx, %edx
divq (%rsi)
xorl %ebp, %ebp
movq 0xa90e(%rip), %rax      # 0xe280
movslq %edx, %rdx
leaq (%rdx,%rdx,2), %rdx
movq (%rax,%rdx,8), %rsi
movq %rdx, 0x30(%rsp)
movq 0x8(%rax,%rdx,8), %rdx
cmpq %rdx, %rsi
je 0x39a1
cmpq %rcx, (%rsi)
je 0x399f
incl %ebp
addq $0x20, %rsi
cmpq %rdx, %rsi
jne 0x398c
movq %rdx, %rsi
movl %ebp, %ebp
movl %r9d, 0x8(%rsp)
movl %edi, %r13d
cmpq %rdx, %rsi
jne 0x39f4
movl %r8d, 0xc(%rsp)
movq 0x30(%rsp), %rdx
leaq (%rax,%rdx,8), %rdi
xorps %xmm0, %xmm0
leaq 0x10(%rsp), %rsi
movups %xmm0, 0x8(%rsi)
movq $0x0, 0x18(%rsi)
movq %rcx, (%rsi)
callq 0x5e18
movq 0x18(%rsp), %rdi
testq %rdi, %rdi
je 0x39ef
movq 0x28(%rsp), %rsi
subq %rdi, %rsi
callq 0x3260
movl 0xc(%rsp), %r8d
movsbl %r8b, %edi
callq 0x3470
xorl %ecx, %ecx
cmpl $0x46, %eax
jg 0x3a2d
cmpl $0x41, %eax
movl %r13d, %r10d
movl 0x8(%rsp), %r11d
je 0x3a53
cmpl $0x43, %eax
jne 0x3a59
movb $0x20, %cl
jmp 0x3a59
cmpl $0x47, %ecx
je 0x3a48
cmpl $0x54, %ecx
jne 0x3b10
orb $0x40, %bl
jmp 0x3a4b
cmpl $0x47, %eax
movl %r13d, %r10d
movl 0x8(%rsp), %r11d
je 0x3a57
cmpl $0x54, %eax
jne 0x3a59
movb $0x40, %cl
jmp 0x3a59
orb $-0x80, %bl
jmp 0x3a4b
orb $0x10, %bl
movb %bl, 0x4(%rbp)
jmp 0x3b10
movb $-0x80, %cl
jmp 0x3a59
movb $0x10, %cl
movq 0xa820(%rip), %rax      # 0xe280
movq 0x30(%rsp), %rdx
movq (%rax,%rdx,8), %rax
shlq $0x5, %rbp
movq 0x8(%rax,%rbp), %rdx
movq 0x10(%rax,%rbp), %rsi
cmpq %rsi, %rdx
je 0x3ac2
movl %r15d, %edi
andl $0x1, %edi
movzbl 0x4(%rdx), %r8d
movl %r8d, %r9d
shrl %r9d
andl $0x7, %r9d
cmpl %ebx, %r9d
jne 0x3ab9
cmpb %r14b, (%rdx)
jne 0x3ab9
cmpb %r12b, 0x1(%rdx)
jne 0x3ab9
cmpb %r10b, 0x2(%rdx)
jne 0x3ab9
cmpb %r11b, 0x3(%rdx)
jne 0x3ab9
movl %r8d, %r9d
andl $0x1, %r9d
cmpl %r9d, %edi
je 0x3b1f
addq $0x5, %rdx
cmpq %rsi, %rdx
jne 0x3a82
leaq (%rax,%rbp), %rdi
addq $0x8, %rdi
movb %r14b, 0x10(%rsp)
movb %r12b, 0x11(%rsp)
movb %r10b, 0x12(%rsp)
movb %r11b, 0x13(%rsp)
andl $0x1, %r15d
leal (%r15,%rbx,2), %eax
movb %al, 0x14(%rsp)
cmpq 0x10(%rdi), %rsi
je 0x3b04
movb 0x14(%rsp), %al
movb %al, 0x4(%rsi)
movl 0x10(%rsp), %eax
movl %eax, (%rsi)
addq $0x5, 0x8(%rdi)
jmp 0x3b0e
leaq 0x10(%rsp), %rdx
callq 0x61fa
xorl %eax, %eax
addq $0x38, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
orb %r8b, %cl
movb %cl, 0x4(%rdx)
movl $0x6, %eax
jmp 0x3b10
cmpl $0x47, %ecx
je 0x3b42
cmpl $0x54, %ecx
jne 0x3b10
orb $0x40, %r13b
jmp 0x3b46
orb $-0x80, %r13b
jmp 0x3b46
orb $0x10, %r13b
movb %r13b, 0x4(%rbp)
jmp 0x3b10
movq %rax, %rbx
movq 0x18(%rsp), %rdi
testq %rdi, %rdi
je 0x3b66
movq 0x28(%rsp), %rsi
subq %rdi, %rsi
callq 0x3260
movq %rbx, %rdi
callq 0x3430