// File: simonrharris[P]SKA/src/sk_unique.cpp
// Function: uniqueKmers(std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>> const&, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>> const&, float const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&, bool)
int uniqueKmers(const std::vector < std::string > & ingroupsamples, const std::vector < std::string > & kmerfiles, const float & minproportion, const std::string & outputfile, const bool incNs)
{

	const std::chrono::high_resolution_clock::time_point start = std::chrono::high_resolution_clock::now();
	// Create the kmer map
	std::unordered_map < std::string , std::vector < bool > > kmerMap;
	int oldkmersize=0;
	int totalingroupkmers=0;

	std::vector < std::string > sampleNames;

	if (collectSampleNames(kmerfiles, sampleNames)!=0){return 1;}
	int numSamples=sampleNames.size();

	float maxmissing=(1.0-minproportion)*ingroupsamples.size();

	float minrequired=ingroupsamples.size()-maxmissing;

	std::set < std::string > ingroupSet(ingroupsamples.begin(), ingroupsamples.end());

	if (ingroupSet.size()!=ingroupsamples.size()){
		std::cout << "Warning: Duplicate samples in your ingroup sample file have been removed" << std::endl;
	}

	std::vector < int > ingroupSamplePositions;

	for (int i=0; i<sampleNames.size(); ++i){
		std::set < std::string >::iterator it = ingroupSet.find(sampleNames[i]);//check if the kmer is in the map
			if ( it != ingroupSet.end() ){//if the kmer is in the map
				ingroupSamplePositions.push_back(i);
			}
	}
	
	if (ingroupsamples.size()!=ingroupSamplePositions.size()){
		std::cout << ingroupsamples.size() << " " << ingroupSamplePositions.size() << std::endl;
		std::cout << "Error: Some of your ingroup samples are not in your input files" << std::endl << std::endl;
		return 1;
	}

	std::vector < std::string > fileSampleNames;	
	int sampleNum=0;
	int numfiles=kmerfiles.size();
	std::ifstream fileStream;
	int kmersize;
	char * kmerbuffer;


	for (int s = 0; s < kmerfiles.size(); ++s){

		if (openFileStream(kmerfiles[s], fileStream)){return 1;};

		int newkmersize;
		
		readKmerHeader(fileStream, newkmersize, fileSampleNames);
		
		if (s==0){
			kmersize=newkmersize;
		}

		if (newkmersize!=kmersize){
			std::cout << "kmer files have different kmer sizes" << std::endl << std::endl;
			return 0;
		}


		int numFileSamples=fileSampleNames.size();

		char basebuffer[1];
		char kmerbuffer[(kmersize*2/3)+1];
		char asciibuffer[int(std::ceil(float(fileSampleNames.size())/6))];

		while (fileStream.read(asciibuffer, sizeof(asciibuffer))){//read the ascii representation of the taxa
			std::string asciibits (asciibuffer, sizeof(asciibuffer));
			std::vector < bool > mybits;
			vectorbool_from_ascii(asciibits, mybits);//read the ascii representation of the taxa to a vector of bools

			while (fileStream.peek()!='\n' && fileStream.read(kmerbuffer, sizeof(kmerbuffer))){
				std::string kmer (kmerbuffer, (kmersize*2/3)+1);
				
				std::unordered_map < std::string , std::vector < bool > >::iterator it = kmerMap.find(kmer);//check if the kmer is in the map
				if ( it != kmerMap.end() ){//if the kmer is in the map
					for (int i=0; i<mybits.size(); ++i){
						it->second[i+sampleNum]=mybits[i];
					}
				}
				else {//if the kmer is not in the hash
					std::vector < bool > taxonBitset(numSamples, false);//create a new vector of bools for all samples
					for (int i=0; i<mybits.size(); ++i){ //change the bools to true based for taxa in the file containing the kmer
						taxonBitset[i+sampleNum]=mybits[i];
					}
					kmerMap.insert(std::make_pair(kmer, taxonBitset));//add the new vector to the map
				}
	    	}
	    	fileStream.ignore(256,'\n');//skip the end ofline character
    	}
    	sampleNum+=numFileSamples; //add the number of samples in the file to the count of total samples
    	fileSampleNames.clear();
		fileStream.close();
	}

	std::cout << kmerMap.size() << " kmers identified from " << sampleNum << " samples in " << numfiles << " files" << std::endl;

	int uniquecount=0;
	std::unordered_map < std::string , std::vector < bool > >::iterator it = kmerMap.begin();
	std::unordered_map < std::string , std::vector < bool > >::iterator endIter = kmerMap.end();
	std::unordered_map < std::vector < bool >,  std::vector < std::string > > revKmerMap;

	for (; it!=endIter; ){

		if (not incNs && it->first[0]=='N'){
			kmerMap.erase(it++);
			continue;
		}

		int allcount=std::count(it->second.begin(), it->second.end(), true);
		int ingroupcount=0;

		for (std::vector < int >::iterator it2=ingroupSamplePositions.begin(); it2!=ingroupSamplePositions.end(); ++it2){
			if (it->second[*it2]){
				ingroupcount++;
			}
		}
		if (ingroupcount>=minrequired && (allcount-ingroupcount)==0){
			uniquecount++;

			std::vector < bool > ingroupBitString (ingroupSamplePositions.size(), false);
			int i=0;
			for (std::vector < int >::iterator it2=ingroupSamplePositions.begin(); it2!=ingroupSamplePositions.end(); ++it2, ++i){
				ingroupBitString[i]=it->second[*it2];
			}

			std::unordered_map < std::vector < bool >,  std::vector < std::string > >::iterator it2 = revKmerMap.find(ingroupBitString);//check if the bitset is in the map
			if ( it2 != revKmerMap.end() ){//if the bitset is in the map
				it2->second.push_back(it->first); //add the kmer
			}
			else {//if the bitset isn't in the map
				//std::vector < std::string > myvector; //create a new vector of strings
				//myvector.push_back(it->first); //add the bitset to the vector
				revKmerMap.insert(std::make_pair(ingroupBitString, std::vector < std::string > {it->first})); //insert the vector into the map
			}
		}
		kmerMap.erase(it++); //remove kmer from kmerMap to save space
	}

	std::cout << uniquecount << " unique shared kmers will be written to " << outputfile << std::endl;

	std::vector < std::string > orderedingroupsamples;
	for ( std::vector < int >::iterator it=ingroupSamplePositions.begin(); it!=ingroupSamplePositions.end(); ++it){ //print each sample name to output file stream
		orderedingroupsamples.push_back(sampleNames[*it]); 
	}

	if(printMergedKmerFile(revKmerMap, outputfile, orderedingroupsamples, kmersize)){return 1;}

	printDuration(start);
	
	return 0;
	
	
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x9e0, %rsp            # imm = 0x9E0
movb %r8b, %al
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq %rdx, -0x20(%rbp)
movq %rcx, -0x28(%rbp)
andb $0x1, %al
movb %al, -0x29(%rbp)
callq 0x6080
movq %rax, -0x38(%rbp)
leaq -0x70(%rbp), %rdi
callq 0x35160
movl $0x0, -0x74(%rbp)
movl $0x0, -0x78(%rbp)
leaq -0x90(%rbp), %rdi
movq %rdi, -0x730(%rbp)
callq 0x1ab40
movq -0x730(%rbp), %rsi
movq -0x18(%rbp), %rdi
movl $0x1, %edx
callq 0xced0
movl %eax, -0x724(%rbp)
jmp 0x46a43
movl -0x724(%rbp), %eax
cmpl $0x0, %eax
je 0x46a7b
movl $0x1, -0x4(%rbp)
movl $0x1, -0xa0(%rbp)
jmp 0x4818b
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x98(%rbp)
movl %eax, -0x9c(%rbp)
jmp 0x481a8
leaq -0x90(%rbp), %rdi
callq 0xb670
movl %eax, -0xa4(%rbp)
movq -0x20(%rbp), %rax
movss (%rax), %xmm0
cvtss2sd %xmm0, %xmm1
movsd 0x127c7(%rip), %xmm0    # 0x59268
subsd %xmm1, %xmm0
movsd %xmm0, -0x740(%rbp)
movq -0x10(%rbp), %rdi
callq 0xb670
movsd -0x740(%rbp), %xmm0
movq %rax, %xmm1
movaps 0x128e6(%rip), %xmm2    # 0x593b0
punpckldq %xmm2, %xmm1    # xmm1 = xmm1[0],xmm2[0],xmm1[1],xmm2[1]
movapd 0x128ea(%rip), %xmm2    # 0x593c0
subpd %xmm2, %xmm1
movaps %xmm1, %xmm2
unpckhpd %xmm1, %xmm1            # xmm1 = xmm1[1,1]
addsd %xmm2, %xmm1
mulsd %xmm1, %xmm0
cvtsd2ss %xmm0, %xmm0
movss %xmm0, -0xa8(%rbp)
movq -0x10(%rbp), %rdi
callq 0xb670
movq %rax, %rdx
shrq %rdx
movl %eax, %ecx
andl $0x1, %ecx
orq %rdx, %rcx
cvtsi2ss %rcx, %xmm0
addss %xmm0, %xmm0
cvtsi2ss %rax, %xmm1
movss %xmm1, -0x738(%rbp)
testq %rax, %rax
movss %xmm0, -0x734(%rbp)
js 0x46b3f
movss -0x738(%rbp), %xmm0
movss %xmm0, -0x734(%rbp)
movss -0x734(%rbp), %xmm0
movss -0xa8(%rbp), %xmm1
subss %xmm1, %xmm0
movss %xmm0, -0xac(%rbp)
movq -0x10(%rbp), %rdi
callq 0xefe0
movq %rax, -0xe8(%rbp)
movq -0x10(%rbp), %rdi
callq 0xf050
movq %rax, -0xf0(%rbp)
movq -0xe8(%rbp), %rsi
movq -0xf0(%rbp), %rdx
leaq -0xe0(%rbp), %rdi
callq 0x481d0
jmp 0x46b97
leaq -0xe0(%rbp), %rdi
callq 0xf360
movq %rax, -0x748(%rbp)
movq -0x10(%rbp), %rdi
callq 0xb670
movq %rax, %rcx
movq -0x748(%rbp), %rax
cmpq %rcx, %rax
je 0x46c0c
movq 0x323df(%rip), %rdi     # 0x78fa8
leaq 0x13a5e(%rip), %rsi     # 0x5a62e
callq 0x6520
movq %rax, -0x750(%rbp)
jmp 0x46bde
movq -0x750(%rbp), %rdi
movq 0x323a4(%rip), %rsi     # 0x78f90
callq 0x6570
jmp 0x46bf3
jmp 0x46c0c
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x98(%rbp)
movl %eax, -0x9c(%rbp)
jmp 0x4817d
leaq -0x108(%rbp), %rdi
callq 0x1ac10
movl $0x0, -0x10c(%rbp)
movslq -0x10c(%rbp), %rax
movq %rax, -0x758(%rbp)
leaq -0x90(%rbp), %rdi
callq 0xb670
movq %rax, %rcx
movq -0x758(%rbp), %rax
cmpq %rcx, %rax
jae 0x46cf8
movslq -0x10c(%rbp), %rsi
leaq -0x90(%rbp), %rdi
callq 0x1ab60
movq %rax, %rsi
leaq -0xe0(%rbp), %rdi
callq 0xf400
movq %rax, -0x760(%rbp)
jmp 0x46c7a
movq -0x760(%rbp), %rax
movq %rax, -0x118(%rbp)
leaq -0xe0(%rbp), %rdi
callq 0xf470
movq %rax, -0x120(%rbp)
leaq -0x118(%rbp), %rdi
leaq -0x120(%rbp), %rsi
callq 0xf440
testb $0x1, %al
jne 0x46cb4
jmp 0x46ce2
leaq -0x108(%rbp), %rdi
leaq -0x10c(%rbp), %rsi
callq 0x1ac30
jmp 0x46cc9
jmp 0x46ce2
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x98(%rbp)
movl %eax, -0x9c(%rbp)
jmp 0x48171
jmp 0x46ce4
movl -0x10c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x10c(%rbp)
jmp 0x46c22
movq -0x10(%rbp), %rdi
callq 0xb670
movq %rax, -0x768(%rbp)
leaq -0x108(%rbp), %rdi
callq 0xf7f0
movq %rax, %rcx
movq -0x768(%rbp), %rax
cmpq %rcx, %rax
je 0x46e00
movq -0x10(%rbp), %rdi
callq 0xb670
movq %rax, %rsi
movq 0x3226e(%rip), %rdi     # 0x78fa8
callq 0x6120
movq %rax, -0x770(%rbp)
jmp 0x46d48
movq -0x770(%rbp), %rdi
leaq 0x135f7(%rip), %rsi     # 0x5a34d
callq 0x6520
movq %rax, -0x778(%rbp)
jmp 0x46d64
leaq -0x108(%rbp), %rdi
callq 0xf7f0
movq -0x778(%rbp), %rdi
movq %rax, %rsi
callq 0x6120
movq %rax, -0x780(%rbp)
jmp 0x46d88
movq -0x780(%rbp), %rdi
movq 0x321fa(%rip), %rsi     # 0x78f90
callq 0x6570
jmp 0x46d9d
movq 0x32204(%rip), %rdi     # 0x78fa8
leaq 0x138cc(%rip), %rsi     # 0x5a677
callq 0x6520
movq %rax, -0x788(%rbp)
jmp 0x46db9
movq -0x788(%rbp), %rdi
movq 0x321c9(%rip), %rsi     # 0x78f90
callq 0x6570
movq %rax, -0x790(%rbp)
jmp 0x46dd5
movq -0x790(%rbp), %rdi
movq 0x321ad(%rip), %rsi     # 0x78f90
callq 0x6570
jmp 0x46dea
movl $0x1, -0x4(%rbp)
movl $0x1, -0xa0(%rbp)
jmp 0x48157
leaq -0x138(%rbp), %rdi
callq 0x1ab40
movl $0x0, -0x13c(%rbp)
movq -0x18(%rbp), %rdi
callq 0xb670
movl %eax, -0x140(%rbp)
leaq -0x348(%rbp), %rdi
callq 0x65f0
jmp 0x46e33
movl $0x0, -0x35c(%rbp)
movslq -0x35c(%rbp), %rax
movq %rax, -0x798(%rbp)
movq -0x18(%rbp), %rdi
callq 0xb670
movq %rax, %rcx
movq -0x798(%rbp), %rax
cmpq %rcx, %rax
jae 0x476da
movq -0x18(%rbp), %rdi
movslq -0x35c(%rbp), %rsi
callq 0xf2d0
movq %rax, %rdi
leaq -0x348(%rbp), %rsi
movl $0x1, %edx
callq 0xa4f0
movl %eax, -0x79c(%rbp)
jmp 0x46e93
movl -0x79c(%rbp), %eax
cmpl $0x0, %eax
je 0x46ee2
movl $0x1, -0x4(%rbp)
movl $0x1, -0xa0(%rbp)
jmp 0x48123
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x98(%rbp)
movl %eax, -0x9c(%rbp)
jmp 0x48149
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x98(%rbp)
movl %eax, -0x9c(%rbp)
jmp 0x4813d
leaq -0x348(%rbp), %rdi
leaq -0x360(%rbp), %rsi
leaq -0x138(%rbp), %rdx
callq 0xcd40
jmp 0x46efe
cmpl $0x0, -0x35c(%rbp)
jne 0x46f13
movl -0x360(%rbp), %eax
movl %eax, -0x34c(%rbp)
movl -0x360(%rbp), %eax
cmpl -0x34c(%rbp), %eax
je 0x46f84
movq 0x32080(%rip), %rdi     # 0x78fa8
leaq 0x1255c(%rip), %rsi     # 0x5948b
callq 0x6520
movq %rax, -0x7a8(%rbp)
jmp 0x46f3d
movq -0x7a8(%rbp), %rdi
movq 0x32045(%rip), %rsi     # 0x78f90
callq 0x6570
movq %rax, -0x7b0(%rbp)
jmp 0x46f59
movq -0x7b0(%rbp), %rdi
movq 0x32029(%rip), %rsi     # 0x78f90
callq 0x6570
jmp 0x46f6e
movl $0x0, -0x4(%rbp)
movl $0x1, -0xa0(%rbp)
jmp 0x48123
leaq -0x138(%rbp), %rdi
movq %rdi, -0x7d0(%rbp)
callq 0xb670
movq -0x7d0(%rbp), %rdi
movl %eax, -0x364(%rbp)
movl -0x34c(%rbp), %eax
addl %eax, %eax
cltq
imulq $0x55555556, %rax, %rax # imm = 0x55555556
movq %rax, %rcx
shrq $0x20, %rcx
movl %ecx, %edx
shrq $0x3f, %rax
movl %eax, %ecx
movl %edx, %eax
leal 0x1(%rax,%rcx), %eax
movq %rax, -0x7c8(%rbp)
movq %rsp, %rcx
movq %rcx, -0x370(%rbp)
movq %rax, %rdx
addq $0xf, %rdx
andq $-0x10, %rdx
movq %rsp, %rcx
subq %rdx, %rcx
movq %rcx, -0x7c0(%rbp)
movq %rcx, %rsp
movq %rax, -0x378(%rbp)
callq 0xb670
movq %rax, %rdx
shrq %rdx
movl %eax, %ecx
andl $0x1, %ecx
orq %rdx, %rcx
cvtsi2ss %rcx, %xmm0
addss %xmm0, %xmm0
cvtsi2ss %rax, %xmm1
movss %xmm1, -0x7b8(%rbp)
testq %rax, %rax
movss %xmm0, -0x7b4(%rbp)
js 0x47043
movss -0x7b8(%rbp), %xmm0
movss %xmm0, -0x7b4(%rbp)
movss -0x7b4(%rbp), %xmm0
movss 0x12629(%rip), %xmm1    # 0x5967c
divss %xmm1, %xmm0
callq 0x33ed0
movss %xmm0, -0x7d4(%rbp)
jmp 0x47066
movss -0x7d4(%rbp), %xmm0
cvttss2si %xmm0, %eax
movq %rax, -0x7e8(%rbp)
movq %rax, %rdx
addq $0xf, %rdx
andq $-0x10, %rdx
movq %rsp, %rcx
subq %rdx, %rcx
movq %rcx, -0x7e0(%rbp)
movq %rcx, %rsp
movq %rax, -0x380(%rbp)
movq -0x7e8(%rbp), %rdx
movq -0x7e0(%rbp), %rsi
leaq -0x348(%rbp), %rdi
callq 0x6680
movq %rax, -0x7f0(%rbp)
jmp 0x470be
movq -0x7f0(%rbp), %rdi
movq (%rdi), %rax
movq -0x18(%rax), %rax
addq %rax, %rdi
callq 0x6670
movb %al, -0x7f1(%rbp)
jmp 0x470dc
movb -0x7f1(%rbp), %al
testb $0x1, %al
jne 0x470eb
jmp 0x4768e
leaq -0x3a1(%rbp), %rdi
movq %rdi, -0x800(%rbp)
callq 0x6910
movq -0x7e0(%rbp), %rsi
movq -0x7e8(%rbp), %rdx
movq -0x800(%rbp), %rcx
leaq -0x3a0(%rbp), %rdi
callq 0x65e0
jmp 0x47121
leaq -0x3a1(%rbp), %rdi
callq 0x65a0
leaq -0x3d0(%rbp), %rdi
movq %rdi, -0x808(%rbp)
callq 0x1acc0
movq -0x808(%rbp), %rsi
leaq -0x3a0(%rbp), %rdi
callq 0xbd50
jmp 0x47155
jmp 0x47157
leaq -0x348(%rbp), %rdi
callq 0x61c0
movl %eax, -0x80c(%rbp)
jmp 0x4716b
movl -0x80c(%rbp), %ecx
xorl %eax, %eax
cmpl $0xa, %ecx
movb %al, -0x80d(%rbp)
je 0x471cd
movq -0x7c8(%rbp), %rdx
movq -0x7c0(%rbp), %rsi
leaq -0x348(%rbp), %rdi
callq 0x6680
movq %rax, -0x818(%rbp)
jmp 0x471a1
movq -0x818(%rbp), %rdi
movq (%rdi), %rax
movq -0x18(%rax), %rax
addq %rax, %rdi
callq 0x6670
movb %al, -0x819(%rbp)
jmp 0x471bf
movb -0x819(%rbp), %al
movb %al, -0x80d(%rbp)
jmp 0x471cd
movb -0x80d(%rbp), %al
testb $0x1, %al
jne 0x471dc
jmp 0x4763c
movl -0x34c(%rbp), %eax
addl %eax, %eax
cltq
imulq $0x55555556, %rax, %rax # imm = 0x55555556
movq %rax, %rcx
shrq $0x20, %rcx
movl %ecx, %edx
shrq $0x3f, %rax
movl %eax, %ecx
movl %edx, %eax
leal 0x1(%rax,%rcx), %eax
cltq
movq %rax, -0x830(%rbp)
leaq -0x3f1(%rbp), %rdi
movq %rdi, -0x828(%rbp)
callq 0x6910
movq -0x7c0(%rbp), %rsi
movq -0x830(%rbp), %rdx
movq -0x828(%rbp), %rcx
leaq -0x3f0(%rbp), %rdi
callq 0x65e0
jmp 0x47241
leaq -0x3f1(%rbp), %rdi
callq 0x65a0
leaq -0x70(%rbp), %rdi
leaq -0x3f0(%rbp), %rsi
callq 0x35180
movq %rax, -0x838(%rbp)
jmp 0x47266
movq -0x838(%rbp), %rax
movq %rax, -0x400(%rbp)
leaq -0x70(%rbp), %rdi
callq 0xfc20
movq %rax, -0x408(%rbp)
leaq -0x400(%rbp), %rdi
leaq -0x408(%rbp), %rsi
callq 0xfc50
testb $0x1, %al
jne 0x472a0
jmp 0x4740b
movl $0x0, -0x40c(%rbp)
movslq -0x40c(%rbp), %rax
movq %rax, -0x840(%rbp)
leaq -0x3d0(%rbp), %rdi
callq 0x10c80
movq %rax, %rcx
movq -0x840(%rbp), %rax
cmpq %rcx, %rax
jae 0x47406
movslq -0x40c(%rbp), %rsi
leaq -0x3d0(%rbp), %rdi
callq 0xedc0
movq %rdx, -0x850(%rbp)
movq %rax, -0x848(%rbp)
jmp 0x472fa
movq -0x850(%rbp), %rax
movq -0x848(%rbp), %rcx
movq %rcx, -0x420(%rbp)
movq %rax, -0x418(%rbp)
leaq -0x400(%rbp), %rdi
callq 0xfcb0
movq %rax, %rdi
addq $0x20, %rdi
movl -0x40c(%rbp), %eax
movl -0x13c(%rbp), %ecx
addl %ecx, %eax
movslq %eax, %rsi
callq 0xedc0
movq %rdx, -0x860(%rbp)
movq %rax, -0x858(%rbp)
jmp 0x4734f
movq -0x860(%rbp), %rax
movq -0x858(%rbp), %rcx
movq %rcx, -0x430(%rbp)
movq %rax, -0x428(%rbp)
leaq -0x430(%rbp), %rdi
leaq -0x420(%rbp), %rsi
callq 0x12720
movl -0x40c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x40c(%rbp)
jmp 0x472aa
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x98(%rbp)
movl %eax, -0x9c(%rbp)
leaq -0x3a1(%rbp), %rdi
callq 0x65a0
jmp 0x4813d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x98(%rbp)
movl %eax, -0x9c(%rbp)
jmp 0x47671
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x98(%rbp)
movl %eax, -0x9c(%rbp)
leaq -0x3f1(%rbp), %rdi
callq 0x65a0
jmp 0x47671
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x98(%rbp)
movl %eax, -0x9c(%rbp)
jmp 0x4762e
jmp 0x4761d
movslq -0xa4(%rbp), %rax
movq %rax, -0x870(%rbp)
movb $0x0, -0x459(%rbp)
leaq -0x45a(%rbp), %rdi
movq %rdi, -0x868(%rbp)
callq 0xf380
movq -0x870(%rbp), %rsi
movq -0x868(%rbp), %rcx
leaq -0x458(%rbp), %rdi
leaq -0x459(%rbp), %rdx
callq 0xffb0
jmp 0x47456
leaq -0x45a(%rbp), %rdi
callq 0xf3e0
movl $0x0, -0x460(%rbp)
movslq -0x460(%rbp), %rax
movq %rax, -0x878(%rbp)
leaq -0x3d0(%rbp), %rdi
callq 0x10c80
movq %rax, %rcx
movq -0x878(%rbp), %rax
cmpq %rcx, %rax
jae 0x47582
movslq -0x460(%rbp), %rsi
leaq -0x3d0(%rbp), %rdi
callq 0xedc0
movq %rdx, -0x888(%rbp)
movq %rax, -0x880(%rbp)
jmp 0x474bc
movq -0x888(%rbp), %rax
movq -0x880(%rbp), %rcx
movq %rcx, -0x470(%rbp)
movq %rax, -0x468(%rbp)
movl -0x460(%rbp), %eax
movl -0x13c(%rbp), %ecx
addl %ecx, %eax
movslq %eax, %rsi
leaq -0x458(%rbp), %rdi
callq 0xedc0
movq %rdx, -0x898(%rbp)
movq %rax, -0x890(%rbp)
jmp 0x47505
movq -0x898(%rbp), %rax
movq -0x890(%rbp), %rcx
movq %rcx, -0x480(%rbp)
movq %rax, -0x478(%rbp)
leaq -0x480(%rbp), %rdi
leaq -0x470(%rbp), %rsi
callq 0x12720
movl -0x460(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x460(%rbp)
jmp 0x4746c
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x98(%rbp)
movl %eax, -0x9c(%rbp)
leaq -0x45a(%rbp), %rdi
callq 0xf3e0
jmp 0x4762e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x98(%rbp)
movl %eax, -0x9c(%rbp)
jmp 0x4760f
leaq -0x4c8(%rbp), %rdi
leaq -0x3f0(%rbp), %rsi
leaq -0x458(%rbp), %rdx
callq 0x351f0
jmp 0x4759e
leaq -0x70(%rbp), %rdi
leaq -0x4c8(%rbp), %rsi
callq 0x351b0
movb %dl, -0x8a1(%rbp)
movq %rax, -0x8a0(%rbp)
jmp 0x475bd
movb -0x8a1(%rbp), %al
movq -0x8a0(%rbp), %rcx
movq %rcx, -0x4d8(%rbp)
movb %al, -0x4d0(%rbp)
leaq -0x4c8(%rbp), %rdi
callq 0x35230
leaq -0x458(%rbp), %rdi
callq 0xf720
jmp 0x4761d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x98(%rbp)
movl %eax, -0x9c(%rbp)
leaq -0x4c8(%rbp), %rdi
callq 0x35230
leaq -0x458(%rbp), %rdi
callq 0xf720
jmp 0x4762e
leaq -0x3f0(%rbp), %rdi
callq 0x6a08
jmp 0x47157
leaq -0x3f0(%rbp), %rdi
callq 0x6a08
jmp 0x47671
leaq -0x348(%rbp), %rdi
movl $0x100, %esi            # imm = 0x100
movl $0xa, %edx
callq 0x6340
jmp 0x47654
leaq -0x3d0(%rbp), %rdi
callq 0xf720
leaq -0x3a0(%rbp), %rdi
callq 0x6a08
jmp 0x4709b
leaq -0x3d0(%rbp), %rdi
callq 0xf720
leaq -0x3a0(%rbp), %rdi
callq 0x6a08
jmp 0x4813d
movl -0x364(%rbp), %ecx
movl -0x13c(%rbp), %eax
addl %ecx, %eax
movl %eax, -0x13c(%rbp)
leaq -0x138(%rbp), %rdi
callq 0x1aca0
leaq -0x348(%rbp), %rdi
callq 0x60f0
jmp 0x476bc
movq -0x370(%rbp), %rax
movq %rax, %rsp
movl -0x35c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x35c(%rbp)
jmp 0x46e3d
leaq -0x70(%rbp), %rdi
callq 0x35260
movq %rax, %rsi
movq 0x318bb(%rip), %rdi     # 0x78fa8
callq 0x6120
movq %rax, -0x8b0(%rbp)
jmp 0x476fb
movq -0x8b0(%rbp), %rdi
leaq 0x12064(%rip), %rsi     # 0x5976d
callq 0x6520
movq %rax, -0x8b8(%rbp)
jmp 0x47717
movq -0x8b8(%rbp), %rdi
movl -0x13c(%rbp), %esi
callq 0x68d0
movq %rax, -0x8c0(%rbp)
jmp 0x47732
movq -0x8c0(%rbp), %rdi
leaq 0x11d70(%rip), %rsi     # 0x594b0
callq 0x6520
movq %rax, -0x8c8(%rbp)
jmp 0x4774e
movq -0x8c8(%rbp), %rdi
movl -0x140(%rbp), %esi
callq 0x68d0
movq %rax, -0x8d0(%rbp)
jmp 0x47769
movq -0x8d0(%rbp), %rdi
leaq 0x13342(%rip), %rsi     # 0x5aab9
callq 0x6520
movq %rax, -0x8d8(%rbp)
jmp 0x47785
movq -0x8d8(%rbp), %rdi
movq 0x317fd(%rip), %rsi     # 0x78f90
callq 0x6570
jmp 0x4779a
movl $0x0, -0x4dc(%rbp)
leaq -0x70(%rbp), %rdi
callq 0xfbf0
movq %rax, -0x4e8(%rbp)
leaq -0x70(%rbp), %rdi
callq 0xfc20
movq %rax, -0x4f0(%rbp)
leaq -0x528(%rbp), %rdi
callq 0x1ae50
leaq -0x4e8(%rbp), %rdi
leaq -0x4f0(%rbp), %rsi
callq 0xfc50
testb $0x1, %al
jne 0x477ec
jmp 0x47f3e
testb $0x1, -0x29(%rbp)
jne 0x47867
leaq -0x4e8(%rbp), %rdi
callq 0xfcb0
movq %rax, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x65c0
movsbl (%rax), %eax
cmpl $0x4e, %eax
jne 0x47867
leaq -0x4e8(%rbp), %rdi
xorl %esi, %esi
callq 0xff50
movq %rax, -0x530(%rbp)
movq -0x530(%rbp), %rsi
leaq -0x70(%rbp), %rdi
callq 0xff10
movq %rax, -0x8e0(%rbp)
jmp 0x47840
movq -0x8e0(%rbp), %rax
movq %rax, -0x538(%rbp)
jmp 0x477d0
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x98(%rbp)
movl %eax, -0x9c(%rbp)
jmp 0x48115
leaq -0x4e8(%rbp), %rdi
movq %rdi, -0x8f0(%rbp)
callq 0xfcb0
movq %rax, %rdi
addq $0x20, %rdi
callq 0xf580
movq -0x8f0(%rbp), %rdi
movl %edx, -0x558(%rbp)
movq %rax, -0x560(%rbp)
movl -0x558(%rbp), %eax
movl %eax, -0x548(%rbp)
movq -0x560(%rbp), %rax
movq %rax, -0x550(%rbp)
callq 0xfcb0
movq %rax, %rdi
addq $0x20, %rdi
callq 0xf5c0
movl %edx, -0x578(%rbp)
movq %rax, -0x580(%rbp)
movl -0x578(%rbp), %eax
movl %eax, -0x568(%rbp)
movq -0x580(%rbp), %rax
movq %rax, -0x570(%rbp)
movb $0x1, -0x581(%rbp)
movq -0x550(%rbp), %rdi
movl -0x548(%rbp), %esi
movq -0x570(%rbp), %rdx
movl -0x568(%rbp), %ecx
leaq -0x581(%rbp), %r8
callq 0x1ab80
movq %rax, -0x8e8(%rbp)
jmp 0x47922
movq -0x8e8(%rbp), %rax
movl %eax, -0x53c(%rbp)
movl $0x0, -0x588(%rbp)
leaq -0x108(%rbp), %rdi
callq 0x1c1b0
movq %rax, -0x590(%rbp)
leaq -0x108(%rbp), %rdi
callq 0x1c040
movq %rax, -0x598(%rbp)
leaq -0x590(%rbp), %rdi
leaq -0x598(%rbp), %rsi
callq 0x245c0
testb $0x1, %al
jne 0x4797b
jmp 0x47a0d
leaq -0x4e8(%rbp), %rdi
callq 0xfcb0
addq $0x20, %rax
movq %rax, -0x908(%rbp)
leaq -0x590(%rbp), %rdi
callq 0x24600
movq -0x908(%rbp), %rdi
movslq (%rax), %rsi
callq 0xedc0
movq %rdx, -0x900(%rbp)
movq %rax, -0x8f8(%rbp)
jmp 0x479bd
movq -0x900(%rbp), %rax
movq -0x8f8(%rbp), %rcx
movq %rcx, -0x5a8(%rbp)
movq %rax, -0x5a0(%rbp)
leaq -0x5a8(%rbp), %rdi
callq 0xf510
testb $0x1, %al
jne 0x479eb
jmp 0x479fa
movl -0x588(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x588(%rbp)
jmp 0x479fc
leaq -0x590(%rbp), %rdi
callq 0x24620
jmp 0x4794c
cvtsi2ssl -0x588(%rbp), %xmm0
ucomiss -0xac(%rbp), %xmm0
jb 0x47efd
movl -0x53c(%rbp), %eax
subl -0x588(%rbp), %eax
cmpl $0x0, %eax
jne 0x47efd
movl -0x4dc(%rbp), %eax
incl %eax
movl %eax, -0x4dc(%rbp)
leaq -0x108(%rbp), %rdi
callq 0xf7f0
movq %rax, -0x918(%rbp)
movb $0x0, -0x5d1(%rbp)
leaq -0x5d2(%rbp), %rdi
movq %rdi, -0x910(%rbp)
callq 0xf380
movq -0x918(%rbp), %rsi
movq -0x910(%rbp), %rcx
leaq -0x5d0(%rbp), %rdi
leaq -0x5d1(%rbp), %rdx
callq 0xffb0
jmp 0x47a95
leaq -0x5d2(%rbp), %rdi
callq 0xf3e0
movl $0x0, -0x5d8(%rbp)
leaq -0x108(%rbp), %rdi
callq 0x1c1b0
movq %rax, -0x5e0(%rbp)
leaq -0x108(%rbp), %rdi
callq 0x1c040
movq %rax, -0x5e8(%rbp)
leaq -0x5e0(%rbp), %rdi
leaq -0x5e8(%rbp), %rsi
callq 0x245c0
testb $0x1, %al
jne 0x47aed
jmp 0x47bf7
leaq -0x4e8(%rbp), %rdi
callq 0xfcb0
addq $0x20, %rax
movq %rax, -0x930(%rbp)
leaq -0x5e0(%rbp), %rdi
callq 0x24600
movq -0x930(%rbp), %rdi
movslq (%rax), %rsi
callq 0xedc0
movq %rdx, -0x928(%rbp)
movq %rax, -0x920(%rbp)
jmp 0x47b2f
movq -0x928(%rbp), %rax
movq -0x920(%rbp), %rcx
movq %rcx, -0x5f8(%rbp)
movq %rax, -0x5f0(%rbp)
movslq -0x5d8(%rbp), %rsi
leaq -0x5d0(%rbp), %rdi
callq 0xedc0
movq %rdx, -0x940(%rbp)
movq %rax, -0x938(%rbp)
jmp 0x47b6e
movq -0x940(%rbp), %rax
movq -0x938(%rbp), %rcx
movq %rcx, -0x608(%rbp)
movq %rax, -0x600(%rbp)
leaq -0x608(%rbp), %rdi
leaq -0x5f8(%rbp), %rsi
callq 0x12720
leaq -0x5e0(%rbp), %rdi
callq 0x24620
movl -0x5d8(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x5d8(%rbp)
jmp 0x47abe
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x98(%rbp)
movl %eax, -0x9c(%rbp)
leaq -0x5d2(%rbp), %rdi
callq 0xf3e0
jmp 0x48115
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x98(%rbp)
movl %eax, -0x9c(%rbp)
jmp 0x47eec
leaq -0x528(%rbp), %rdi
leaq -0x5d0(%rbp), %rsi
callq 0xfc80
movq %rax, -0x948(%rbp)
jmp 0x47c13
movq -0x948(%rbp), %rax
movq %rax, -0x610(%rbp)
leaq -0x528(%rbp), %rdi
callq 0xfce0
movq %rax, -0x618(%rbp)
leaq -0x610(%rbp), %rdi
leaq -0x618(%rbp), %rsi
callq 0xf0f0
testb $0x1, %al
jne 0x47c4d
jmp 0x47c86
leaq -0x610(%rbp), %rdi
callq 0xfd10
addq $0x28, %rax
movq %rax, -0x950(%rbp)
leaq -0x4e8(%rbp), %rdi
callq 0xfcb0
movq -0x950(%rbp), %rdi
movq %rax, %rsi
callq 0xabd0
jmp 0x47c81
jmp 0x47ede
leaq -0x6a0(%rbp), %rax
movq %rax, -0x958(%rbp)
movq %rax, -0x6a8(%rbp)
leaq -0x4e8(%rbp), %rdi
callq 0xfcb0
movq -0x958(%rbp), %rdi
movq %rax, %rsi
callq 0x6230
jmp 0x47cb8
leaq -0x6a0(%rbp), %rax
movq %rax, -0x680(%rbp)
movq $0x1, -0x678(%rbp)
leaq -0x6a9(%rbp), %rdi
movq %rdi, -0x960(%rbp)
callq 0xfdc0
movq -0x960(%rbp), %rcx
movq -0x680(%rbp), %rsi
movq -0x678(%rbp), %rdx
leaq -0x670(%rbp), %rdi
callq 0xfde0
jmp 0x47d07
leaq -0x658(%rbp), %rdi
leaq -0x5d0(%rbp), %rsi
leaq -0x670(%rbp), %rdx
callq 0xfd80
jmp 0x47d23
leaq -0x528(%rbp), %rdi
leaq -0x658(%rbp), %rsi
callq 0xfd40
movb %dl, -0x969(%rbp)
movq %rax, -0x968(%rbp)
jmp 0x47d45
movb -0x969(%rbp), %al
movq -0x968(%rbp), %rcx
movq %rcx, -0x6c0(%rbp)
movb %al, -0x6b8(%rbp)
leaq -0x658(%rbp), %rdi
callq 0xfe60
leaq -0x670(%rbp), %rdi
callq 0xfe90
leaq -0x6a9(%rbp), %rdi
callq 0xfef0
leaq -0x6a0(%rbp), %rax
movq %rax, -0x980(%rbp)
addq $0x20, %rax
movq %rax, -0x978(%rbp)
movq -0x978(%rbp), %rdi
addq $-0x20, %rdi
movq %rdi, -0x988(%rbp)
callq 0x6a08
movq -0x980(%rbp), %rcx
movq -0x988(%rbp), %rax
cmpq %rcx, %rax
movq %rax, -0x978(%rbp)
jne 0x47d9c
jmp 0x47ede
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x98(%rbp)
movl %eax, -0x9c(%rbp)
movq -0x6a8(%rbp), %rax
leaq -0x6a0(%rbp), %rcx
cmpq %rax, %rcx
movq %rax, -0x990(%rbp)
je 0x47e2f
movq -0x990(%rbp), %rdi
addq $-0x20, %rdi
movq %rdi, -0x998(%rbp)
callq 0x6a08
movq -0x998(%rbp), %rax
leaq -0x6a0(%rbp), %rcx
cmpq %rcx, %rax
movq %rax, -0x990(%rbp)
jne 0x47dfe
jmp 0x47eec
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x98(%rbp)
movl %eax, -0x9c(%rbp)
jmp 0x47e86
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x98(%rbp)
movl %eax, -0x9c(%rbp)
jmp 0x47e7a
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x98(%rbp)
movl %eax, -0x9c(%rbp)
leaq -0x658(%rbp), %rdi
callq 0xfe60
leaq -0x670(%rbp), %rdi
callq 0xfe90
leaq -0x6a9(%rbp), %rdi
callq 0xfef0
leaq -0x6a0(%rbp), %rax
movq %rax, -0x9a8(%rbp)
addq $0x20, %rax
movq %rax, -0x9a0(%rbp)
movq -0x9a0(%rbp), %rdi
addq $-0x20, %rdi
movq %rdi, -0x9b0(%rbp)
callq 0x6a08
movq -0x9a8(%rbp), %rcx
movq -0x9b0(%rbp), %rax
cmpq %rcx, %rax
movq %rax, -0x9a0(%rbp)
jne 0x47eab
jmp 0x47eec
leaq -0x5d0(%rbp), %rdi
callq 0xf720
jmp 0x47efd
leaq -0x5d0(%rbp), %rdi
callq 0xf720
jmp 0x48115
leaq -0x4e8(%rbp), %rdi
xorl %esi, %esi
callq 0xff50
movq %rax, -0x6c8(%rbp)
movq -0x6c8(%rbp), %rsi
leaq -0x70(%rbp), %rdi
callq 0xff10
movq %rax, -0x9b8(%rbp)
jmp 0x47f2b
movq -0x9b8(%rbp), %rax
movq %rax, -0x6d0(%rbp)
jmp 0x477d0
movl -0x4dc(%rbp), %esi
movq 0x3105d(%rip), %rdi     # 0x78fa8
callq 0x68d0
movq %rax, -0x9c0(%rbp)
jmp 0x47f59
movq -0x9c0(%rbp), %rdi
leaq 0x12750(%rip), %rsi     # 0x5a6b7
callq 0x6520
movq %rax, -0x9c8(%rbp)
jmp 0x47f75
movq -0x9c8(%rbp), %rdi
movq -0x28(%rbp), %rsi
callq 0x64d0
movq %rax, -0x9d0(%rbp)
jmp 0x47f8e
movq -0x9d0(%rbp), %rdi
movq 0x30ff4(%rip), %rsi     # 0x78f90
callq 0x6570
jmp 0x47fa3
leaq -0x6e8(%rbp), %rdi
callq 0x1ab40
leaq -0x108(%rbp), %rdi
callq 0x1c1b0
movq %rax, -0x6f0(%rbp)
leaq -0x108(%rbp), %rdi
callq 0x1c040
movq %rax, -0x6f8(%rbp)
leaq -0x6f0(%rbp), %rdi
leaq -0x6f8(%rbp), %rsi
callq 0x245c0
testb $0x1, %al
jne 0x47fee
jmp 0x48041
leaq -0x6f0(%rbp), %rdi
callq 0x24600
movslq (%rax), %rsi
leaq -0x90(%rbp), %rdi
callq 0x1ab60
movq %rax, %rsi
leaq -0x6e8(%rbp), %rdi
callq 0xabd0
jmp 0x4801a
jmp 0x4801c
leaq -0x6f0(%rbp), %rdi
callq 0x24620
jmp 0x47fc2
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x98(%rbp)
movl %eax, -0x9c(%rbp)
jmp 0x48109
movq -0x28(%rbp), %rsi
leaq -0x718(%rbp), %rdi
callq 0x6230
jmp 0x48053
movl -0x34c(%rbp), %ecx
leaq -0x528(%rbp), %rdi
leaq -0x718(%rbp), %rsi
leaq -0x6e8(%rbp), %rdx
callq 0xc810
movl %eax, -0x9d4(%rbp)
jmp 0x4807b
leaq -0x718(%rbp), %rdi
callq 0x6a08
movl -0x9d4(%rbp), %eax
cmpl $0x0, %eax
je 0x480c5
movl $0x1, -0x4(%rbp)
movl $0x1, -0xa0(%rbp)
jmp 0x480ef
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x98(%rbp)
movl %eax, -0x9c(%rbp)
leaq -0x718(%rbp), %rdi
callq 0x6a08
jmp 0x48109
movq -0x38(%rbp), %rax
movq %rax, -0x720(%rbp)
movq -0x720(%rbp), %rdi
callq 0xa8f0
jmp 0x480de
movl $0x0, -0x4(%rbp)
movl $0x1, -0xa0(%rbp)
leaq -0x6e8(%rbp), %rdi
callq 0xfe90
leaq -0x528(%rbp), %rdi
callq 0x1ae90
jmp 0x48123
leaq -0x6e8(%rbp), %rdi
callq 0xfe90
leaq -0x528(%rbp), %rdi
callq 0x1ae90
jmp 0x4813d
leaq -0x348(%rbp), %rdi
callq 0x6140
leaq -0x138(%rbp), %rdi
callq 0xfe90
jmp 0x48157
leaq -0x348(%rbp), %rdi
callq 0x6140
leaq -0x138(%rbp), %rdi
callq 0xfe90
jmp 0x48171
leaq -0x108(%rbp), %rdi
callq 0x1aa00
leaq -0xe0(%rbp), %rdi
callq 0xf740
jmp 0x4818b
leaq -0x108(%rbp), %rdi
callq 0x1aa00
leaq -0xe0(%rbp), %rdi
callq 0xf740
jmp 0x481a8
leaq -0x90(%rbp), %rdi
callq 0xfe90
leaq -0x70(%rbp), %rdi
callq 0x35280
movl -0x4(%rbp), %eax
movq %rbp, %rsp
popq %rbp
retq
leaq -0x90(%rbp), %rdi
callq 0xfe90
leaq -0x70(%rbp), %rdi
callq 0x35280
movq -0x98(%rbp), %rdi
callq 0x6900
nopl (%rax)