// File: /workspace/github_cpp_makefile_star2_O1/Mengjintao[P]SWAPCounter/src/kmerGraph.cpp
// Function: kmerGraph::addKmers(char const*, char const*, unsigned long long*, unsigned char*, parameter*)
long long kmerGraph::addKmers(const char *s, const char *end, unsigned long long *kmers, unsigned char *arcs, parameter *parameters)
{
//	if(s>end || end-s <= parameters->hashLength)	return 0;
	unsigned long long curNodeID=0,     primeNodeID=0,   	twinNodeID=0;
	unsigned long long preNodeID=0,     prePrimeNodeID=0; 
	unsigned long long kmer_index=0;
//	for(int i=0; i<end-s; i++)	printf("%c", *(s+i));
//	printf("\n");
	
	curNodeID = this->stringToLongLong(s, 0, parameters->hashLength-1, parameters);
        for(int j=parameters->hashLength-1; s+j<end; j++) 
	{
		if(!(s[j]=='A'||s[j]=='T'||s[j]=='C'||s[j]=='G'))	continue;	
		assert(s[j]=='A'||s[j]=='T'||s[j]=='C'||s[j]=='G');
	       	curNodeID <<= 2;
               	curNodeID |= (parameters->nucleotideValue[(int) s[j]]&(3ull));
               	curNodeID &= parameters->MASK;
		
               	twinNodeID  = this->reverseComplement(curNodeID, parameters);
               	primeNodeID = max(curNodeID, twinNodeID);
//		cout<<longLongToString(curNodeID, parameters)<<" "<<longLongToString(primeNodeID, parameters)<<endl;
	
		if(j-parameters->hashLength+1==0)	{
			preNodeID = curNodeID;
			prePrimeNodeID = primeNodeID; 
			kmers[kmer_index] = primeNodeID;	arcs[kmer_index] = 0;
			kmer_index ++;
			continue;
		}
		kmers[kmer_index]  = primeNodeID;	arcs[kmer_index]  = 0;

		int pos_ret;
		//preNode -> curNode  add(A, B, +, +, last(B+))
		if( preNodeID == prePrimeNodeID && curNodeID == primeNodeID)
		{
			pos_ret = arcPos(prePrimeNodeID, primeNodeID, '+', '+', parameters->hashLength);	
			assert(kmer_index-1>=0);
			arcs[kmer_index-1] |= ((unsigned char) 1<<pos_ret);
				
			pos_ret = arcPos(primeNodeID, prePrimeNodeID, '-', '-', parameters->hashLength); 
			arcs[kmer_index] |=  ((unsigned char) 1<<pos_ret);
		}
		//preNode -> ~curNode
		else if(preNodeID == prePrimeNodeID && curNodeID != primeNodeID)
		{
			pos_ret = arcPos(prePrimeNodeID, primeNodeID, '+', '-', parameters->hashLength);	
			assert(kmer_index-1>=0);
			arcs[kmer_index-1] |= ((unsigned char) 1<<pos_ret);
				
			pos_ret = arcPos(primeNodeID, prePrimeNodeID, '+', '-', parameters->hashLength); 
			arcs[kmer_index] |= ((unsigned char) 1<<pos_ret);
		}
		//~preNode -> curNode
		else if(preNodeID != prePrimeNodeID && curNodeID == primeNodeID)
		{
			pos_ret = arcPos(prePrimeNodeID, primeNodeID, '-', '+', parameters->hashLength);	
			assert(kmer_index-1>=0);
			arcs[kmer_index-1] |= ((unsigned char) 1<<pos_ret);
				
			pos_ret = arcPos(primeNodeID, prePrimeNodeID, '-', '+', parameters->hashLength); 
			arcs[kmer_index] |= ((unsigned char) 1<<pos_ret);
		}			
		//~preNode -> ~curNode
		else if(preNodeID != prePrimeNodeID && curNodeID != primeNodeID)
		{
			pos_ret = arcPos(prePrimeNodeID, primeNodeID, '-', '-', parameters->hashLength);	
			assert(kmer_index-1>=0);
			arcs[kmer_index-1] |= ((unsigned char) 1<<pos_ret);
				
			pos_ret = arcPos(primeNodeID, prePrimeNodeID, '+', '+', parameters->hashLength); 
			arcs[kmer_index] |=  ((unsigned char) 1<<pos_ret);
		}
		preNodeID = curNodeID;
		prePrimeNodeID = primeNodeID;
		kmer_index++;
	}
	return (long long int) kmer_index;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
pushq %rax
movq %r9, %rbx
movq %r8, %r14
movq %rcx, %r15
movq %rdx, %r12
movq %rsi, %r13
movl 0xaf8(%r9), %edx
decl %edx
xorl %ebp, %ebp
movq %rsi, %rdi
xorl %esi, %esi
movq %r9, %rcx
callq 0x262e
movslq 0xaf8(%rbx), %rsi
leaq (%rsi,%r13), %r9
decq %r9
cmpq %r12, %r9
jae 0x2a09
movq %rax, %rdi
decq %rsi
xorl %ebp, %ebp
xorl %ecx, %ecx
xorl %edx, %edx
movzbl (%r9), %r8d
leal -0x41(%r8), %r9d
cmpl $0x13, %r9d
ja 0x2985
movl $0x80045, %eax          # imm = 0x80045
btl %r9d, %eax
jae 0x2985
movsbq %r8b, %r8
movzbl 0xb38(%rbx,%r8), %r8d
andl $0x3, %r8d
leaq (%r8,%rdi,4), %rdi
andq 0xb00(%rbx), %rdi
movl 0xaf8(%rbx), %r10d
testl %r10d, %r10d
jle 0x28d3
movl %r10d, %r8d
xorl %r9d, %r9d
movq %rdi, %rax
movl %eax, %r11d
andl $0x3, %r11d
leaq (%r11,%r9,4), %r9
xorq $0x3, %r9
shrq $0x2, %rax
decl %r8d
jne 0x28b9
jmp 0x28d6
xorl %r9d, %r9d
cmpq %r9, %rdi
movq %r9, %r8
cmovaq %rdi, %r8
movl %esi, %eax
subl %r10d, %eax
movq %r8, (%r15,%rbp,8)
movb $0x0, (%r14,%rbp)
cmpl $-0x1, %eax
je 0x29ed
cmpq %rdx, %rcx
jne 0x2925
cmpq %r9, %rdi
jb 0x2925
movl %r8d, %ecx
andb $0x3, %cl
movb $0x1, %al
shlb %cl, %al
orb %al, -0x1(%r14,%rbp)
movb 0xaf8(%rbx), %cl
addb %cl, %cl
addb $-0x2, %cl
shrq %cl, %rdx
movl $0x7, %ecx
jmp 0x296f
cmpq %rdx, %rcx
jne 0x298a
cmpq %r9, %rdi
jae 0x298a
movb 0xaf8(%rbx), %cl
addb %cl, %cl
addb $-0x2, %cl
movq %r8, %rax
shrq %cl, %rax
movl $0x3, %ecx
subl %eax, %ecx
cmpl $0x8, %ecx
jae 0x2a1b
movl $0x1, %eax
shll %cl, %eax
orb %al, -0x1(%r14,%rbp)
movb 0xaf8(%rbx), %cl
addb %cl, %cl
addb $-0x2, %cl
shrq %cl, %rdx
movl $0x3, %ecx
subl %edx, %ecx
cmpl $0x8, %ecx
jae 0x2a1b
movl $0x1, %r9d
shll %cl, %r9d
jmp 0x29e9
movq %rdx, %r8
jmp 0x29f3
cmpq %rdx, %rcx
je 0x29ab
cmpq %r9, %rdi
jb 0x29ab
movl %r8d, %ecx
andb $0x3, %cl
movb $0x10, %al
shlb %cl, %al
orb %al, -0x1(%r14,%rbp)
andb $0x3, %dl
movb $0x10, %r9b
jmp 0x29e4
cmpq %rdx, %rcx
je 0x29ed
cmpq %r9, %rdi
jae 0x29ed
movb 0xaf8(%rbx), %cl
addb %cl, %cl
addb $-0x2, %cl
movq %r8, %rax
shrq %cl, %rax
movl $0x7, %ecx
subl %eax, %ecx
cmpl $0x8, %ecx
jae 0x2a1b
movl $0x1, %eax
shll %cl, %eax
orb %al, -0x1(%r14,%rbp)
andb $0x3, %dl
movb $0x1, %r9b
movl %edx, %ecx
shlb %cl, %r9b
movb %r9b, (%r14,%rbp)
incq %rbp
movq %rdi, %rcx
leaq (%rsi,%r13), %r9
incq %r9
incq %rsi
movq %r8, %rdx
cmpq %r12, %r9
jb 0x2867
movq %rbp, %rax
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x368e(%rip), %rdi      # 0x60b0
leaq 0x361a(%rip), %rsi      # 0x6043
leaq 0x3692(%rip), %rcx      # 0x60c2
movl $0x30, %edx
callq 0x2170