// File: Mengjintao[P]SWAPCounter/src/kmerGraph.cpp
// Function: kmerGraph::constructKmerGraph(parameter*, MPIEnviroment*, bloomFilter*)
int kmerGraph::constructKmerGraph(parameter *parameters, MPIEnviroment *MPIcontrol, bloomFilter *bFilter)
{
	clock_t IOTime=0, IOTimeRead=0, commTime=0, compTime=0, totTime=0, checkTime=0, t0, t1, t2;
	char message[1024];
	long long int readBases = min((long long int) MPIcontrol->nprocs/MPIcontrol->groupProc*1024*16, (long long int) BUF_SIZE);
	char          *readBuf = NULL; //new char [readBases*2+2];
	if(MPIcontrol->rank%MPIcontrol->groupProc==0)	readBuf = new char [readBases*2+2];	
	long long int readEnd=0, readStart=0, readLen=0, readRound=0;
	
	t0 = clock();
	MPIcontrol->File_open(parameters->fastaPath);
	
//	printf("Proc %d: %llu End\n", MPIcontrol->rank, readRound);
//	fflush(stdout);
	MPIcontrol->File_locate();
	t1 = clock();
	IOTime += t1-t0;
	totTime += t1-t0;
	int endTag = 1, totalTag = 0;
	
	do
	{
		t0 = clock();
		readLen = MPIcontrol->File_read(readBuf+readEnd, readBases);
		if(readBuf)	readBuf[readEnd+readLen] = 0;
		readEnd += readLen;		

		//losed the last sequence
//		if(MPIcontrol->datasize==0&&MPIcontrol->rank==MPIcontrol->nprocs-1)	{readBuf[readEnd]='>'; readBuf[++readEnd]=0;}	
		t1 = clock();
		IOTimeRead += t1-t0;
		if(DEBUG)
		{
			printf("Proc %d: %llu File_readLen=%llu, read_offset=%llu(%llu)\n", MPIcontrol->rank, readRound, readLen, MPIcontrol->read_offset-MPIcontrol->start_pos, MPIcontrol->datasize);
			fflush(stdout);
		}
		long long int localEnd = readEnd;
		
		if(readBuf)
		{
			while(localEnd>0 && readBuf[localEnd]!='>')	localEnd--;
			assert(readBuf[localEnd]=='>'||localEnd==0);
			readStart=localEnd;
		}
		//redistributed to groupProcs 	
		dataShuttleBetweenGroupProcs(parameters, MPIcontrol, readBuf, localEnd, readRound);

		extractKmerGraph(parameters, MPIcontrol, bFilter, readBuf, localEnd, readRound, commTime, checkTime);

		endTag=1, totalTag=0;
		if(MPIcontrol->datasize)	endTag=0;
		MPI_Allreduce(&endTag, &totalTag, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);

		if(readBuf)	
		{
			for(long long int i=0; i<readEnd-readStart; i++)	readBuf[i] = readBuf[readStart+i];
			readBuf[readEnd-readStart] = 0;
			readEnd   = readEnd-readStart;			
			readStart = 0;
		}

		t2 = clock();
		compTime += t2-t1;
		totTime  += t2-t0;
		readRound++;
		
		if(MPIcontrol->rank==0)
		{
			sprintf(message, "Proc %d: round %llu\n", MPIcontrol->rank, readRound);
			MPIcontrol->print(message);
		}
	}while(totalTag<MPIcontrol->nprocs);

	if(readBuf)
	{	
		for(long long int i=0; i<readEnd-readStart; i++)	readBuf[i] = readBuf[readStart+i];
		readBuf[readEnd-readStart] = 0;
	}
	readEnd = readEnd-readStart;			
	readStart = 0;
	long long int localEnd = readEnd;
	extractKmerGraph(parameters, MPIcontrol, bFilter, readBuf, localEnd, readRound, commTime, checkTime);
/*
	long long int tot_kmol=0, cur_kmol=0;
	
	for(unordered_map<unsigned long long, unsigned long long>::iterator I=kmolecules.begin(); I!=kmolecules.end(); I++)
//	for(auto I: kmolecules)
	{
		unsigned char *p = (unsigned char *) &(I->second);
		int t=0;
		for(int j=0;j<8;j++)	t += p[j];
		if(t>parameters->cutoffThreshold)	cur_kmol++;	
	}

	MPI_Allreduce(&cur_kmol, &tot_kmol, 1, MPI_LONG_LONG_INT, MPI_SUM, MPI_COMM_WORLD);
	printf("Proc %d: %llu Num of filtered kmolecules is %llu(totNum is %llu)\n", MPIcontrol->rank, readRound, cur_kmol, tot_kmol);
*/
	clock_t avgIOTime, avgIOTimeRead, avgCompTime, avgCommTime, avgTotTime, avgCheckTime;
	MPI_Allreduce(&IOTime,   &avgIOTime,   1, MPI_LONG, MPI_SUM, MPI_COMM_WORLD);
	MPI_Allreduce(&IOTimeRead, &avgIOTimeRead, 1, MPI_LONG, MPI_SUM, MPI_COMM_WORLD);
	MPI_Allreduce(&compTime, &avgCompTime, 1, MPI_LONG, MPI_SUM, MPI_COMM_WORLD);
	MPI_Allreduce(&commTime, &avgCommTime, 1, MPI_LONG, MPI_SUM, MPI_COMM_WORLD);
	MPI_Allreduce(&totTime,  &avgTotTime,  1, MPI_LONG, MPI_SUM, MPI_COMM_WORLD);
	MPI_Allreduce(&checkTime,  &avgCheckTime,  1, MPI_LONG, MPI_SUM, MPI_COMM_WORLD);
	avgIOTime   = avgIOTime/MPIcontrol->nprocs;
	avgIOTimeRead = avgIOTimeRead/MPIcontrol->nprocs;
	avgCommTime = avgCommTime/MPIcontrol->nprocs;
	avgCompTime = avgCompTime/MPIcontrol->nprocs;
	avgTotTime  = avgTotTime/MPIcontrol->nprocs;
	avgCheckTime = avgCheckTime/MPIcontrol->nprocs;
	
	long long int tot_kmol=0, cur_kmol=kmolecules.size();
	MPI_Allreduce(&cur_kmol, &tot_kmol, 1, MPI_LONG_LONG_INT, MPI_SUM, MPI_COMM_WORLD);

	if(DEBUG)
	{	
		sprintf(message, "Proc %d: %llu Num of kmolecules is %llu(totNum is %llu)", MPIcontrol->rank, readRound, cur_kmol, tot_kmol);
		MPIcontrol->print(message);
	}

	if(MPIcontrol->rank==0)	
	{
		printf("IOTime=%.5fs IOTimeRead=%.5fs compTime=%.5fs commTime=%.5fs totTime=%.5fs checkTime=%.5fs\n", avgIOTime/(float)CLOCKS_PER_SEC, avgIOTimeRead/(float)CLOCKS_PER_SEC, avgCompTime/(float)CLOCKS_PER_SEC, avgCommTime/(float)CLOCKS_PER_SEC, avgTotTime/(float)CLOCKS_PER_SEC, avgCheckTime/(float)CLOCKS_PER_SEC);
	}

	MPIcontrol->File_close();
	if(readBuf)	delete [] readBuf;
	readBuf = NULL;
	return 1;
}

// Assembly:
subq $0x548, %rsp            # imm = 0x548
movq %rdi, 0x540(%rsp)
movq %rsi, 0x538(%rsp)
movq %rdx, 0x530(%rsp)
movq %rcx, 0x528(%rsp)
movq 0x540(%rsp), %rax
movq %rax, 0x30(%rsp)
movq $0x0, 0x520(%rsp)
movq $0x0, 0x518(%rsp)
movq $0x0, 0x510(%rsp)
movq $0x0, 0x508(%rsp)
movq $0x0, 0x500(%rsp)
movq $0x0, 0x4f8(%rsp)
movq 0x530(%rsp), %rax
movslq 0x4(%rax), %rax
movq 0x530(%rsp), %rcx
movslq 0x278(%rcx), %rcx
cqto
idivq %rcx
shlq $0xa, %rax
shlq $0x4, %rax
movq %rax, 0xd0(%rsp)
movq $0x2000000, 0xc8(%rsp) # imm = 0x2000000
leaq 0xd0(%rsp), %rdi
leaq 0xc8(%rsp), %rsi
callq 0xd510
movq (%rax), %rax
movq %rax, 0xd8(%rsp)
movq $0x0, 0xc0(%rsp)
movq 0x530(%rsp), %rax
movl (%rax), %eax
movq 0x530(%rsp), %rcx
cltd
idivl 0x278(%rcx)
cmpl $0x0, %edx
jne 0xb47d
movq 0xd8(%rsp), %rdi
shlq %rdi
addq $0x2, %rdi
movq $-0x1, %rax
cmpq $0x0, %rdi
cmovlq %rax, %rdi
callq 0x8030
movq %rax, 0xc0(%rsp)
movq $0x0, 0xb8(%rsp)
movq $0x0, 0xb0(%rsp)
movq $0x0, 0xa8(%rsp)
movq $0x0, 0xa0(%rsp)
callq 0x83e0
movq %rax, 0x4f0(%rsp)
movq 0x530(%rsp), %rdi
movq 0x538(%rsp), %rsi
callq 0x15430
movq 0x530(%rsp), %rdi
callq 0x15520
callq 0x83e0
movq %rax, 0x4e8(%rsp)
movq 0x4e8(%rsp), %rax
subq 0x4f0(%rsp), %rax
addq 0x520(%rsp), %rax
movq %rax, 0x520(%rsp)
movq 0x4e8(%rsp), %rax
subq 0x4f0(%rsp), %rax
addq 0x500(%rsp), %rax
movq %rax, 0x500(%rsp)
movl $0x1, 0x9c(%rsp)
movl $0x0, 0x98(%rsp)
callq 0x83e0
movq %rax, 0x4f0(%rsp)
movq 0x530(%rsp), %rdi
movq 0xc0(%rsp), %rsi
addq 0xb8(%rsp), %rsi
movq 0xd8(%rsp), %rdx
callq 0x159c0
movq %rax, 0xa8(%rsp)
cmpq $0x0, 0xc0(%rsp)
je 0xb5a0
movq 0xc0(%rsp), %rax
movq 0xb8(%rsp), %rcx
addq 0xa8(%rsp), %rcx
movb $0x0, (%rax,%rcx)
movq 0xa8(%rsp), %rax
addq 0xb8(%rsp), %rax
movq %rax, 0xb8(%rsp)
callq 0x83e0
movq %rax, 0x4e8(%rsp)
movq 0x4e8(%rsp), %rax
subq 0x4f0(%rsp), %rax
addq 0x518(%rsp), %rax
movq %rax, 0x518(%rsp)
movq 0xb8(%rsp), %rax
movq %rax, 0x90(%rsp)
cmpq $0x0, 0xc0(%rsp)
je 0xb6bf
jmp 0xb606
xorl %eax, %eax
cmpq $0x0, 0x90(%rsp)
movb %al, 0x2f(%rsp)
jle 0xb635
movq 0xc0(%rsp), %rax
movq 0x90(%rsp), %rcx
movsbl (%rax,%rcx), %eax
cmpl $0x3e, %eax
setne %al
movb %al, 0x2f(%rsp)
movb 0x2f(%rsp), %al
testb $0x1, %al
jne 0xb63f
jmp 0xb655
movq 0x90(%rsp), %rax
addq $-0x1, %rax
movq %rax, 0x90(%rsp)
jmp 0xb606
movq 0xc0(%rsp), %rax
movq 0x90(%rsp), %rcx
movsbl (%rax,%rcx), %ecx
movb $0x1, %al
cmpl $0x3e, %ecx
movb %al, 0x2e(%rsp)
je 0xb684
cmpq $0x0, 0x90(%rsp)
sete %al
movb %al, 0x2e(%rsp)
movb 0x2e(%rsp), %al
testb $0x1, %al
jne 0xb68e
jmp 0xb690
jmp 0xb6af
leaq 0xada7(%rip), %rdi      # 0x1643e
leaq 0xa9b5(%rip), %rsi      # 0x16053
movl $0x1e6, %edx            # imm = 0x1E6
leaq 0xadb8(%rip), %rcx      # 0x16462
callq 0x83d0
movq 0x90(%rsp), %rax
movq %rax, 0xb0(%rsp)
movq 0x30(%rsp), %rdi
movq 0x538(%rsp), %rsi
movq 0x530(%rsp), %rdx
movq 0xa0(%rsp), %r9
leaq 0xc0(%rsp), %rcx
leaq 0x90(%rsp), %r8
callq 0xaff0
movq 0x30(%rsp), %rdi
movq 0x538(%rsp), %rsi
movq 0x530(%rsp), %rdx
movq 0x528(%rsp), %rcx
movq 0xc0(%rsp), %r8
movq 0x90(%rsp), %r9
movq 0xa0(%rsp), %r11
leaq 0x510(%rsp), %r10
leaq 0x4f8(%rsp), %rax
movq %r11, (%rsp)
movq %r10, 0x8(%rsp)
movq %rax, 0x10(%rsp)
callq 0x9a50
movl $0x1, 0x9c(%rsp)
movl $0x0, 0x98(%rsp)
movq 0x530(%rsp), %rax
cmpq $0x0, 0x238(%rax)
je 0xb77c
movl $0x0, 0x9c(%rsp)
leaq 0x9c(%rsp), %rdi
leaq 0x98(%rsp), %rsi
movl $0x1, %edx
movq 0x11828(%rip), %rcx     # 0x1cfc0
movq 0x117c9(%rip), %r8      # 0x1cf68
movq 0x117ea(%rip), %r9      # 0x1cf90
callq 0x8820
cmpq $0x0, 0xc0(%rsp)
je 0xb867
movq $0x0, 0x88(%rsp)
movq 0x88(%rsp), %rax
movq 0xb8(%rsp), %rcx
subq 0xb0(%rsp), %rcx
cmpq %rcx, %rax
jge 0xb827
movq 0xc0(%rsp), %rax
movq 0xb0(%rsp), %rcx
addq 0x88(%rsp), %rcx
movb (%rax,%rcx), %dl
movq 0xc0(%rsp), %rax
movq 0x88(%rsp), %rcx
movb %dl, (%rax,%rcx)
movq 0x88(%rsp), %rax
addq $0x1, %rax
movq %rax, 0x88(%rsp)
jmp 0xb7c6
movq 0xc0(%rsp), %rax
movq 0xb8(%rsp), %rcx
subq 0xb0(%rsp), %rcx
movb $0x0, (%rax,%rcx)
movq 0xb8(%rsp), %rax
subq 0xb0(%rsp), %rax
movq %rax, 0xb8(%rsp)
movq $0x0, 0xb0(%rsp)
callq 0x83e0
movq %rax, 0x4e0(%rsp)
movq 0x4e0(%rsp), %rax
subq 0x4e8(%rsp), %rax
addq 0x508(%rsp), %rax
movq %rax, 0x508(%rsp)
movq 0x4e0(%rsp), %rax
subq 0x4f0(%rsp), %rax
addq 0x500(%rsp), %rax
movq %rax, 0x500(%rsp)
movq 0xa0(%rsp), %rax
addq $0x1, %rax
movq %rax, 0xa0(%rsp)
movq 0x530(%rsp), %rax
cmpl $0x0, (%rax)
jne 0xb912
leaq 0xe0(%rsp), %rdi
movq 0x530(%rsp), %rax
movl (%rax), %edx
movq 0xa0(%rsp), %rcx
leaq 0xabbb(%rip), %rsi      # 0x164b1
movb $0x0, %al
callq 0x80e0
movq 0x530(%rsp), %rdi
leaq 0xe0(%rsp), %rsi
callq 0x152a0
jmp 0xb914
movl 0x98(%rsp), %eax
movq 0x530(%rsp), %rcx
cmpl 0x4(%rcx), %eax
jl 0xb53f
cmpq $0x0, 0xc0(%rsp)
je 0xb9c4
movq $0x0, 0x80(%rsp)
movq 0x80(%rsp), %rax
movq 0xb8(%rsp), %rcx
subq 0xb0(%rsp), %rcx
cmpq %rcx, %rax
jge 0xb9a8
movq 0xc0(%rsp), %rax
movq 0xb0(%rsp), %rcx
addq 0x80(%rsp), %rcx
movb (%rax,%rcx), %dl
movq 0xc0(%rsp), %rax
movq 0x80(%rsp), %rcx
movb %dl, (%rax,%rcx)
movq 0x80(%rsp), %rax
addq $0x1, %rax
movq %rax, 0x80(%rsp)
jmp 0xb947
movq 0xc0(%rsp), %rax
movq 0xb8(%rsp), %rcx
subq 0xb0(%rsp), %rcx
movb $0x0, (%rax,%rcx)
movq 0x30(%rsp), %rdi
movq 0xb8(%rsp), %rax
subq 0xb0(%rsp), %rax
movq %rax, 0xb8(%rsp)
movq $0x0, 0xb0(%rsp)
movq 0xb8(%rsp), %rax
movq %rax, 0x78(%rsp)
movq 0x538(%rsp), %rsi
movq 0x530(%rsp), %rdx
movq 0x528(%rsp), %rcx
movq 0xc0(%rsp), %r8
movq 0x78(%rsp), %r9
movq 0xa0(%rsp), %r11
leaq 0x510(%rsp), %r10
leaq 0x4f8(%rsp), %rax
movq %r11, (%rsp)
movq %r10, 0x8(%rsp)
movq %rax, 0x10(%rsp)
callq 0x9a50
leaq 0x520(%rsp), %rdi
leaq 0x70(%rsp), %rsi
movl $0x1, %edx
movq 0x11545(%rip), %rcx     # 0x1cfa8
movq 0x114fe(%rip), %r8      # 0x1cf68
movq 0x1151f(%rip), %r9      # 0x1cf90
callq 0x8820
leaq 0x518(%rsp), %rdi
leaq 0x68(%rsp), %rsi
movl $0x1, %edx
movq 0x11519(%rip), %rcx     # 0x1cfa8
movq 0x114d2(%rip), %r8      # 0x1cf68
movq 0x114f3(%rip), %r9      # 0x1cf90
callq 0x8820
leaq 0x508(%rsp), %rdi
leaq 0x60(%rsp), %rsi
movl $0x1, %edx
movq 0x114ed(%rip), %rcx     # 0x1cfa8
movq 0x114a6(%rip), %r8      # 0x1cf68
movq 0x114c7(%rip), %r9      # 0x1cf90
callq 0x8820
leaq 0x510(%rsp), %rdi
leaq 0x58(%rsp), %rsi
movl $0x1, %edx
movq 0x114c1(%rip), %rcx     # 0x1cfa8
movq 0x1147a(%rip), %r8      # 0x1cf68
movq 0x1149b(%rip), %r9      # 0x1cf90
callq 0x8820
leaq 0x500(%rsp), %rdi
leaq 0x50(%rsp), %rsi
movl $0x1, %edx
movq 0x11495(%rip), %rcx     # 0x1cfa8
movq 0x1144e(%rip), %r8      # 0x1cf68
movq 0x1146f(%rip), %r9      # 0x1cf90
callq 0x8820
leaq 0x4f8(%rsp), %rdi
leaq 0x48(%rsp), %rsi
movl $0x1, %edx
movq 0x11469(%rip), %rcx     # 0x1cfa8
movq 0x11422(%rip), %r8      # 0x1cf68
movq 0x11443(%rip), %r9      # 0x1cf90
callq 0x8820
movq 0x30(%rsp), %rdi
movq 0x70(%rsp), %rax
movq 0x530(%rsp), %rcx
movslq 0x4(%rcx), %rcx
cqto
idivq %rcx
movq %rax, 0x70(%rsp)
movq 0x68(%rsp), %rax
movq 0x530(%rsp), %rcx
movslq 0x4(%rcx), %rcx
cqto
idivq %rcx
movq %rax, 0x68(%rsp)
movq 0x58(%rsp), %rax
movq 0x530(%rsp), %rcx
movslq 0x4(%rcx), %rcx
cqto
idivq %rcx
movq %rax, 0x58(%rsp)
movq 0x60(%rsp), %rax
movq 0x530(%rsp), %rcx
movslq 0x4(%rcx), %rcx
cqto
idivq %rcx
movq %rax, 0x60(%rsp)
movq 0x50(%rsp), %rax
movq 0x530(%rsp), %rcx
movslq 0x4(%rcx), %rcx
cqto
idivq %rcx
movq %rax, 0x50(%rsp)
movq 0x48(%rsp), %rax
movq 0x530(%rsp), %rcx
movslq 0x4(%rcx), %rcx
cqto
idivq %rcx
movq %rax, 0x48(%rsp)
movq $0x0, 0x40(%rsp)
callq 0xd500
movq %rax, 0x38(%rsp)
leaq 0x38(%rsp), %rdi
leaq 0x40(%rsp), %rsi
movl $0x1, %edx
movq 0x1137e(%rip), %rcx     # 0x1cfa0
movq 0x1133f(%rip), %r8      # 0x1cf68
movq 0x11360(%rip), %r9      # 0x1cf90
callq 0x8820
movq 0x530(%rsp), %rax
cmpl $0x0, (%rax)
jne 0xbcde
cvtsi2ssq 0x70(%rsp), %xmm0
movss 0xa3af(%rip), %xmm1     # 0x16004
divss %xmm1, %xmm0
cvtss2sd %xmm0, %xmm0
cvtsi2ssq 0x68(%rsp), %xmm1
movss 0xa398(%rip), %xmm2     # 0x16004
divss %xmm2, %xmm1
cvtss2sd %xmm1, %xmm1
cvtsi2ssq 0x60(%rsp), %xmm2
movss 0xa381(%rip), %xmm3     # 0x16004
divss %xmm3, %xmm2
cvtss2sd %xmm2, %xmm2
cvtsi2ssq 0x58(%rsp), %xmm3
movss 0xa36a(%rip), %xmm4     # 0x16004
divss %xmm4, %xmm3
cvtss2sd %xmm3, %xmm3
cvtsi2ssq 0x50(%rsp), %xmm4
movss 0xa353(%rip), %xmm5     # 0x16004
divss %xmm5, %xmm4
cvtss2sd %xmm4, %xmm4
cvtsi2ssq 0x48(%rsp), %xmm5
movss 0xa33c(%rip), %xmm6     # 0x16004
divss %xmm6, %xmm5
cvtss2sd %xmm5, %xmm5
leaq 0xa7ef(%rip), %rdi      # 0x164c6
movb $0x6, %al
callq 0x8040
movq 0x530(%rsp), %rdi
callq 0x15c40
cmpq $0x0, 0xc0(%rsp)
je 0xbd15
movq 0xc0(%rsp), %rax
movq %rax, 0x20(%rsp)
cmpq $0x0, %rax
je 0xbd13
movq 0x20(%rsp), %rdi
callq 0x8870
jmp 0xbd15
movq $0x0, 0xc0(%rsp)
movl $0x1, %eax
addq $0x548, %rsp            # imm = 0x548
retq
nop