// File: /workspace/github_cpp_makefile_star2_O2/giovannarosone[P]BCR_LCP_GSA/BCRexternalBWT.cpp
// Function: BCRexternalBWT::storeEntireBWTFilePartial(char const*)
void BCRexternalBWT::storeEntireBWTFilePartial( const char* fn ) {

	static FILE *OutFileBWT, *InFileBWT;                  // output and input file BWT;
	char *filenameIn = new char[strlen(fn)+100];
	char *filename = new char[strlen(fn)+100];
	
	#if USE_QS == 1
		static FILE *OutFileBWTQS, *InFileBWTQS;                  // output and input file BWT;
		char *filenameInQS = new char[120];
		char *filenameQS = new char[120];
		char *fnQS = new char[strlen(fn)+100];
		sprintf (fnQS,"%s%s",fn,".ebwt.qs");
	#endif
	
	dataTypeNChar numchar=0;
	dataTypeNChar numcharWrite=0;

	uchar *buffer = new uchar[SIZEBUFFER];
	std::cerr << "storeEntireBWTFilePartial:SIZEBUFFER is " << SIZEBUFFER << std::endl;

	dataTypeNChar *freqOut = new dataTypeNChar [SIZE_ALPHA];
	for (dataTypedimAlpha i = 0; i < SIZE_ALPHA-1; ++i)
        freqOut[i] = 0;
	freqOut[SIZE_ALPHA-1] = 0;

	char *fnBWT = new char[strlen(fn)+100];
	numchar=sprintf (fnBWT,"%s%s",fn,".ebwt");		
	OutFileBWT = fopen(fnBWT, "wb");
	if (OutFileBWT==NULL) {
		std::cerr << "storeEntireBWTFilePartial: Entire BWT file: Error opening " << std::endl;
		exit (EXIT_FAILURE);
	}
	
	#if USE_QS == 1
		OutFileBWTQS = fopen(fnQS, "wb");
		if (OutFileBWTQS==NULL) {
			std::cerr << "storeEntireBWTFilePartial: Entire BWT QS file: Error opening " << std::endl;
			exit (EXIT_FAILURE);
		}
	#endif

	std::cerr << "storeEntireBWTFilePartial: Build the entire BWT file and compute the distribution of chars.\n";

	for (dataTypedimAlpha g = 0 ; g < sizeAlpha; g++) {
		numchar=sprintf (filename, "bwt_%d", g);
		numchar=sprintf (filenameIn,"%s%s",filename,ext);
		InFileBWT = fopen(filenameIn, "rb");
		if (InFileBWT==NULL) {
			std::cerr << "storeEntireBWTFilePartial: BWT file " << (unsigned int)g <<": Error opening " << std::endl;
			exit (EXIT_FAILURE);
		}

		#if USE_QS == 1
			numchar=sprintf (filenameQS, "bwt.qs_%d", g);
			numchar=sprintf (filenameInQS,"%s%s",filenameQS,ext);
			InFileBWTQS = fopen(filenameInQS, "rb");
			if (InFileBWTQS==NULL) {
				std::cerr << "storeEntireBWTFilePartial: BWT QS file " << (unsigned int)g <<": Error opening " << std::endl;
				exit (EXIT_FAILURE);
			}
		#endif

		//std::cerr << "BWT file " << (unsigned int)g << "= ";
		numchar = fread(buffer,sizeof(uchar),SIZEBUFFER,InFileBWT);
		numcharWrite = fwrite (buffer, sizeof(uchar), numchar , OutFileBWT);
		//std::cerr << "numchar= " << numchar << std::endl;
		//std::cerr << "numcharWrite= " << numcharWrite << std::endl;
		assert(numchar == numcharWrite); // we should always read/write the same number of characters

		for (dataTypeNChar j = 0 ; j < numchar; j++)
	        freqOut[(unsigned int)(buffer[j])]++;

		#if USE_QS == 1
			numchar = fread(buffer,sizeof(uchar),SIZEBUFFER,InFileBWTQS);
			numcharWrite = fwrite (buffer, sizeof(uchar), numchar , OutFileBWTQS);
			assert(numchar == numcharWrite);
		#endif

		while (numchar!=0) {
			numchar = fread(buffer,sizeof(uchar),SIZEBUFFER,InFileBWT);
			numcharWrite = fwrite (buffer, sizeof(uchar), numchar , OutFileBWT);
			assert(numchar == numcharWrite); // we should always read/write the same number of characters

			for (dataTypeNChar j = 0 ; j < numchar; j++)
				freqOut[(unsigned int)(buffer[j])]++;
			
			#if USE_QS == 1
				numchar = fread(buffer,sizeof(uchar),SIZEBUFFER,InFileBWTQS);
				numcharWrite = fwrite (buffer, sizeof(uchar), numchar , OutFileBWTQS);
				assert(numchar == numcharWrite);
			#endif

		}

		fclose(InFileBWT);		
		#if USE_QS==1
			fclose(InFileBWTQS);
		#endif
			
	}
	fclose(OutFileBWT);

	#if verboseEncode==1
		std::cerr << "\nThe Entire BWT:"<< std::endl;
		fnBWT = new char[strlen(fn) + 7];
		sprintf (fnBWT,"%s%s",fn,".ebwt");
		OutFileBWT = fopen(fnBWT, "rb");
		if (OutFileBWT==NULL) {
			std::cerr << "storeEntireBWTFilePartial: Entire BWT file: Error opening " << std::endl;
			exit (EXIT_FAILURE);
		}

		numchar = 1;
		for (dataTypeNSeq g = 0 ; g < SIZEBUFFER; g++)
			buffer[g] = '\0';
		numchar = fread(buffer,sizeof(uchar),SIZEBUFFER,OutFileBWT);
   		if (numchar==0)
			   std::cerr  << "empty\n";
		else
			    std::cerr  << buffer;
       	while (numchar!=0) {
	     		for (dataTypeNChar g = 0 ; g < SIZEBUFFER; g++)
		     		buffer[g] = '\0';
			   numchar = fread(buffer,sizeof(uchar),SIZEBUFFER,OutFileBWT);
			   if (numchar!=0)
			      std::cerr  << buffer;
        }
		std::cerr << std::endl;
		fclose(OutFileBWT);
	#endif

	delete [] buffer;

	
	
	int check=0;
	std::cerr << "Distribution in BWT\n";
	for (dataTypedimAlpha g = 0 ; g < SIZE_ALPHA-1; g++) {
		if (freqOut[g] > 0){
			InFileBWT = openFilePartialIn(alpha[(unsigned int)g]);
			fseek(InFileBWT,0,SEEK_END);
			dataTypeNChar lengthBWTPartial=ftell(InFileBWT);
			if (freqOut[g] == lengthBWTPartial)
				std::cerr << (unsigned int)g << " freq: " << freqOut[g] << "\n";
			else {
				std::cerr << (unsigned int)g << " freq: " << freqOut[g] << " freq in BWT: " << lengthBWTPartial << "***********************\n";
				check = 1;
			}
			closeFilePartial(InFileBWT);
			
			#if deletePartialBWT == 1
				sprintf (filename, "bwt_%d", alpha[(unsigned int)g]);
				sprintf (filenameIn,"%s%s",filename,ext);
				if (remove(filenameIn)!=0)
					std::cerr << "storeEntireBWTFilePartial: Error deleting (bwt aux): " << filenameIn << std::endl;
			#endif
			
			#if ((deletePartialQS == 1) && (USE_QS==1))
				sprintf (filename, "bwt.qs_%d", alpha[(unsigned int)g]);
				sprintf (filenameInQS,"%s%s",filename,ext);
				if (remove(filenameInQS)!=0)
					std::cerr << "storeEntireBWTFilePartial: Error deleting (qs aux): " << filenameInQS << std::endl;
			#endif
			
		}
	}
	if (freqOut[(SIZE_ALPHA-1)] > 0){
		InFileBWT = openFilePartialIn(alpha[(unsigned int)(SIZE_ALPHA-1)]);
		fseek(InFileBWT,0,SEEK_END);
		dataTypeNChar lengthBWTPartial=ftell(InFileBWT);
		if (freqOut[(SIZE_ALPHA-1)] == lengthBWTPartial)
			std::cerr << (unsigned int)(SIZE_ALPHA-1) << " freq: " << freqOut[(SIZE_ALPHA-1)] << "\n";
		else {
			std::cerr << (unsigned int)(SIZE_ALPHA-1) << " freq: " << freqOut[(SIZE_ALPHA-1)] << " freq in BWT: " << lengthBWTPartial << "***********************\n";
			check = 1;
		}
		closeFilePartial(InFileBWT);
		#if deletePartialBWT == 1
			sprintf (filename, "bwt_%d", alpha[(unsigned int)(SIZE_ALPHA-1)] );
			sprintf (filenameIn,"%s%s",filename,ext);
			if (remove(filenameIn)!=0)
				std::cerr << "storeEntireBWTFilePartial: Error deleting (bwt aux): " << filenameIn << std::endl;
		#endif
		
		#if ((deletePartialQS == 1) && (USE_QS==1))
			sprintf (filename, "bwt.qs_%d", alpha[(unsigned int)SIZE_ALPHA-1]);
			sprintf (filenameInQS,"%s%s",filename,ext);
			if (remove(filenameInQS)!=0)
				std::cerr << "storeEntireBWTFilePartial: Error deleting (qs aux): " << filenameInQS << std::endl;
		#endif
		
	}

	if (check == 1) {
		std::cerr << "storeEntireBWTFilePartial: WARNING! Some length partial BWT != the number of occorrences! " << std::endl;
		exit (EXIT_FAILURE);
	}
	else
		std::cerr << "storeEntireBWTFilePartial: test ok! " << std::endl;

	delete [] freqOut;
	delete [] filenameIn;
	delete [] filename;

	#if USE_QS == 1
		delete [] filenameInQS;
		delete [] filenameQS;
		delete [] fnQS;
	#endif
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x18, %rsp
movq %rsi, %r14
movq %rdi, %r12
movq %rsi, %rdi
callq 0x3110
leaq 0x64(%rax), %rbx
movq %rbx, %rdi
callq 0x3040
movq %rax, 0x10(%rsp)
movq %rbx, %rdi
callq 0x3040
movq %rax, 0x8(%rsp)
movl $0x400, %edi            # imm = 0x400
callq 0x3040
movq %rax, %r13
movq 0xa96c(%rip), %rdi      # 0xfff0
leaq 0x55a4(%rip), %rsi      # 0xac2f
callq 0x3270
movq %rax, %rdi
movl $0x400, %esi            # imm = 0x400
callq 0x3430
movq %rax, %rdi
callq 0x3130
movl $0x800, %edi            # imm = 0x800
callq 0x3040
movq %rax, %r15
xorl %eax, %eax
cmpq $0xff, %rax
je 0x56c6
andq $0x0, (%r15,%rax,8)
incq %rax
jmp 0x56b4
andq $0x0, 0x7f8(%r15)
movq %r14, %rdi
callq 0x3110
leaq 0x64(%rax), %rdi
callq 0x3040
movq %rax, %rbx
leaq 0x53f3(%rip), %rsi      # 0xaadc
leaq 0x54dd(%rip), %rcx      # 0xabcd
movq %rax, %rdi
movq %r14, %rdx
xorl %eax, %eax
callq 0x3060
leaq 0x53dd(%rip), %rsi      # 0xaae1
movq %rbx, %rdi
callq 0x32c0
movq %rax, 0xab9d(%rip)      # 0x102b0
movq 0xa8d6(%rip), %rdi      # 0xfff0
testq %rax, %rax
je 0x5bd2
leaq 0x5569(%rip), %rsi      # 0xac93
callq 0x3270
pushq $0x1
popq %r14
xorl %edx, %edx
movzbl 0x148(%r12), %eax
cmpl %eax, %edx
jae 0x5855
movq %r12, %rbp
movq 0x8(%rsp), %r12
movq %r12, %rdi
leaq 0x5848(%rip), %rsi      # 0xafa0
movl %edx, 0x4(%rsp)
xorl %eax, %eax
callq 0x3060
movq 0x10(%rsp), %rbx
movq %rbx, %rdi
leaq 0x536a(%rip), %rsi      # 0xaadc
movq %r12, %rdx
leaq 0x52b3(%rip), %rcx      # 0xaa2f
xorl %eax, %eax
callq 0x3060
movq %rbx, %rdi
leaq 0x519e(%rip), %rsi      # 0xa92b
callq 0x32c0
movq %rax, 0xab1f(%rip)      # 0x102b8
testq %rax, %rax
je 0x5b75
movl $0x400, %edx            # imm = 0x400
movq %r13, %rdi
movq %r14, %rsi
movq %rax, %rcx
callq 0x3390
movq %rax, %rbx
movq 0xaaf1(%rip), %rcx      # 0x102b0
movq %r13, %rdi
movq %r14, %rsi
movq %rax, %rdx
callq 0x3490
cmpq %rax, %rbx
jne 0x5bb3
xorl %eax, %eax
movq %rbp, %r12
cmpq %rax, %rbx
je 0x5836
movzbl (%r13,%rax), %ecx
incq (%r15,%rcx,8)
incq %rax
jmp 0x57db
movl $0x400, %edx            # imm = 0x400
movq %r13, %rdi
movq %r14, %rsi
callq 0x3390
movq %rax, %rbx
movq 0xaaa7(%rip), %rcx      # 0x102b0
movq %r13, %rdi
movq %r14, %rsi
movq %rax, %rdx
callq 0x3490
cmpq %rax, %rbx
jne 0x5b56
xorl %eax, %eax
cmpq %rax, %rbx
je 0x5836
movzbl (%r13,%rax), %ecx
incq (%r15,%rcx,8)
incq %rax
jmp 0x5822
movq 0xaa7b(%rip), %rcx      # 0x102b8
testq %rbx, %rbx
jne 0x57ef
movq %rcx, %rdi
callq 0x3280
movl 0x4(%rsp), %edx
incl %edx
jmp 0x5735
movq 0xaa54(%rip), %rdi      # 0x102b0
callq 0x3280
movq %r13, %rdi
callq 0x3310
movq 0xa780(%rip), %r13      # 0xfff0
leaq 0x54e3(%rip), %rsi      # 0xad5a
movq %r13, %rdi
callq 0x3270
xorl %ebp, %ebp
movl $0x0, 0x4(%rsp)
movq 0x10(%rsp), %r14
cmpq $0xff, %rbp
je 0x59c9
movq (%r15,%rbp,8), %rbx
testq %rbx, %rbx
je 0x59c1
movzbl 0x48(%r12,%rbp), %esi
movq (%r12), %rax
movq %r12, %rdi
callq *0x70(%rax)
movq %rax, 0xa9f9(%rip)      # 0x102b8
movq %rax, %rdi
xorl %esi, %esi
pushq $0x2
popq %rdx
callq 0x32a0
movq 0xa9e5(%rip), %rdi      # 0x102b8
callq 0x3030
movq %rax, %r14
movq %r13, %rdi
movq %rbp, %rsi
callq 0x31c0
movq %rax, %rdi
leaq 0x547f(%rip), %rsi      # 0xad6f
callq 0x3270
movq %rax, %rdi
movq %rbx, %rsi
callq 0x31c0
movq %rax, %rdi
cmpq %r14, %rbx
jne 0x5916
leaq 0x50ff(%rip), %rsi      # 0xaa0e
callq 0x3270
jmp 0x5943
leaq 0x545a(%rip), %rsi      # 0xad77
callq 0x3270
movq %rax, %rdi
movq %r14, %rsi
callq 0x31c0
movq %rax, %rdi
leaq 0x544f(%rip), %rsi      # 0xad86
callq 0x3270
pushq $0x1
popq %rax
movl %eax, 0x4(%rsp)
movq 0xa96e(%rip), %rsi      # 0x102b8
movq (%r12), %rax
movq %r12, %rdi
callq *0x80(%rax)
movzbl 0x48(%r12,%rbp), %edx
movq 0x8(%rsp), %rbx
movq %rbx, %rdi
leaq 0x5634(%rip), %rsi      # 0xafa0
xorl %eax, %eax
callq 0x3060
movq 0x10(%rsp), %r14
movq %r14, %rdi
leaq 0x515a(%rip), %rsi      # 0xaadc
movq %rbx, %rdx
leaq 0x50a3(%rip), %rcx      # 0xaa2f
xorl %eax, %eax
callq 0x3060
movq %r14, %rdi
callq 0x3460
testl %eax, %eax
je 0x59c1
movq %r13, %rdi
leaq 0x53f6(%rip), %rsi      # 0xad9f
callq 0x3270
movq %rax, %rdi
movq %r14, %rsi
callq 0x3270
movq %rax, %rdi
callq 0x3130
incq %rbp
jmp 0x588e
movq 0x7f8(%r15), %rbx
testq %rbx, %rbx
je 0x5a50
movzbl 0x147(%r12), %esi
movq (%r12), %rax
movq %r12, %rdi
callq *0x70(%rax)
movq %rax, 0xa8c9(%rip)      # 0x102b8
pushq $0x2
popq %rdx
movq %rax, %rdi
xorl %esi, %esi
callq 0x32a0
movq 0xa8b5(%rip), %rdi      # 0x102b8
callq 0x3030
movq %rax, %r14
movq 0xa5de(%rip), %rdi      # 0xfff0
movl $0xff, %esi
callq 0x31c0
leaq 0x534c(%rip), %rsi      # 0xad6f
movq %rax, %rdi
callq 0x3270
movq %rax, %rdi
movq %rbx, %rsi
callq 0x31c0
cmpq %r14, %rbx
movl 0x4(%rsp), %ebp
jne 0x5a59
leaq 0x4fc8(%rip), %rsi      # 0xaa0e
movq %rax, %rdi
callq 0x3270
jmp 0x5a85
movl 0x4(%rsp), %ebp
jmp 0x5b0a
leaq 0x5317(%rip), %rsi      # 0xad77
movq %rax, %rdi
callq 0x3270
movq %rax, %rdi
movq %r14, %rsi
callq 0x31c0
leaq 0x530c(%rip), %rsi      # 0xad86
movq %rax, %rdi
callq 0x3270
pushq $0x1
popq %rbp
movq 0xa82c(%rip), %rsi      # 0x102b8
movq (%r12), %rax
movq %r12, %rdi
callq *0x80(%rax)
movzbl 0x147(%r12), %edx
leaq 0x54f7(%rip), %rsi      # 0xafa0
movq 0x8(%rsp), %rbx
movq %rbx, %rdi
xorl %eax, %eax
callq 0x3060
leaq 0x501d(%rip), %rsi      # 0xaadc
leaq 0x4f69(%rip), %rcx      # 0xaa2f
movq 0x10(%rsp), %r14
movq %r14, %rdi
movq %rbx, %rdx
xorl %eax, %eax
callq 0x3060
movq %r14, %rdi
callq 0x3460
testl %eax, %eax
je 0x5b0a
movq 0xa505(%rip), %rdi      # 0xfff0
leaq 0x52ad(%rip), %rsi      # 0xad9f
callq 0x3270
movq %rax, %rdi
movq %r14, %rsi
callq 0x3270
movq %rax, %rdi
callq 0x3130
movq 0xa4df(%rip), %rdi      # 0xfff0
cmpl $0x1, %ebp
je 0x5bdb
leaq 0x530f(%rip), %rsi      # 0xae30
callq 0x3270
movq %rax, %rdi
callq 0x3130
movq %r15, %rdi
callq 0x3310
movq %r14, %rdi
callq 0x3310
movq 0x8(%rsp), %rdi
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x3310
leaq 0x4ff5(%rip), %rdi      # 0xab52
leaq 0x4851(%rip), %rsi      # 0xa3b5
leaq 0x51aa(%rip), %rcx      # 0xad15
movl $0x1392, %edx           # imm = 0x1392
callq 0x3190
movq 0xa474(%rip), %rdi      # 0xfff0
leaq 0x516d(%rip), %rsi      # 0xacf0
callq 0x3270
movq %rax, %rdi
movl 0x4(%rsp), %esi
callq 0x3330
leaq 0x4d9c(%rip), %rsi      # 0xa937
movq %rax, %rdi
callq 0x3270
movq %rax, %rdi
callq 0x3130
pushq $0x1
popq %rdi
callq 0x32e0
leaq 0x4f98(%rip), %rdi      # 0xab52
leaq 0x47f4(%rip), %rsi      # 0xa3b5
leaq 0x514d(%rip), %rcx      # 0xad15
movl $0x1384, %edx           # imm = 0x1384
callq 0x3190
leaq 0x507f(%rip), %rsi      # 0xac58
jmp 0x5b9e
leaq 0x51f3(%rip), %rsi      # 0xadd5
jmp 0x5b9e