// File: /workspace/github_cpp_makefile_star2_O2/RasmusFonseca[P]PDBCluster/main.cpp
// Function: main
int main(int argc, char** argv)
{
	//Print usage
	if( argc==1 ){
		cout<<"Usage: "<<endl<<argv[0]<<" -name <atomtype1> [-name <atomtype2> ..] -clusteringType <distSum|maxDistSum|maxDist> -firstRes <int> -lastRes <int> -clusters <integer> [list of pdb-files]"<<endl;
		cout<<"or: "<<endl<<argv[0]<<" -name <atomtype1> [-name <atomtype2> ..] -dumpDistances <filename>"<<endl;
		cout<<"Example of running k-centers for k=10:"<<endl;
		cout<<argv[0]<<" -name CA -name CB -clusteringType maxDist -clusters 10 sample1.pdb sample2.pdb sample3.pdb ..."<<endl;
		cout<<endl;
		cout<<"Standard value for -name is C4' and CA"<<endl;
		cout<<"Standard value for -clusteringType is distSum"<<endl;
		cout<<"Standard value for -clusters is 10"<<endl;
		cout<<"Standard value for -firstRes is -10000000"<<endl;
		cout<<"Standard value for -lastRes is 10000000"<<endl;
		cout<<endl;
		cout<<"\"-clusteringType distSum\" will perform standard k-medoids clustering where the cost associated with a set of medoids is the average distance from each member to its nearest medoid."<<endl;
		cout<<"\"-clusteringType maxDistSum\" will perform a variant of k-centers clustering where the cost associated with a set of medoids is the average distance from each medoid to its furthest associated member."<<endl;
		cout<<"\"-clusteringType maxDist\" will perform k-centers clustering where the cost associated with a set of medoids is the largest distance from any site to the nearest medoid."<<endl;
		cout<<"For all clustering types, the dRMSD metric is used to indicate the distance between two structures. If -dumpDistances is specified no clustering is performed, the structure dRMSD distance matrix is just written to the specified file."<<endl;
		exit(0);
	}

	//Parse arguments
	vector<string> atomTypes;
	vector<string> files;
	string distFileName;
	int clusters = 10;
	int clusteringType = 0;
	int firstRes = -10000000;
	int lastRes = 10000000;
	for(int i=1;i<argc;i++){
		string arg(argv[i]);
		if( arg=="-name" ){
			string nextArg(argv[++i]);
			atomTypes.push_back(nextArg);
		}else if( arg=="-clusteringType" ){
			string nextArg(argv[++i]);
			if(nextArg=="distSum") clusteringType = 0;
			if(nextArg=="maxDistSum") clusteringType = 1;
			if(nextArg=="maxDist") clusteringType = 2;
		}else if( arg=="-dumpDistances" ){
			string nextArg(argv[++i]);
			distFileName = nextArg;
		}else if( arg=="-clusters" ){
			clusters = atoi(argv[++i]);
		}else if( arg=="-firstRes" ){
			firstRes = atoi(argv[++i]);
		}else if( arg=="-lastRes" ){
			lastRes = atoi(argv[++i]);
		}else if( arg[0]=='-' ){
			cerr<<"Unknown argument: "<<arg<<endl;
			exit(-1);
		}else{
			files.push_back(arg);
		}
	}
	if(atomTypes.empty()){
		atomTypes.push_back("C4'");
		atomTypes.push_back("CA");
	}


	double start_cpu = get_cpu_time();
	double start_wall = get_wall_time();

	vector<Matrix*> strucMatrices;
	cout<<"Reading pdb-files"<<endl;
	fillMatrices(files, atomTypes, firstRes, lastRes, strucMatrices);

	cout<<"Filling matrix"<<endl;
	int s = strucMatrices.size();
	Matrix allDists(s,s);
	for(int i=0; i<s; i++){
		for(int j=i+1; j<s; j++){
			double d = strucMatrices[i]->getDifferenceSum(strucMatrices[j]);
			allDists.set(i,j,d);
			allDists.set(j,i,d);
		}
	}

	//If -dumpDistances was specified distFileName will be nonempty and we only print the distances and exit
	if(!distFileName.empty()){
		cout<<"Writing distances to "<<distFileName<<endl;
		//Check if all files are of the format "newpdb_.*.pdb"
		bool newpdbFiles = true;
		for(unsigned int i=0;i<files.size();i++){
			size_t pos1 = files[i].find("newpdb_");
			size_t pos2 = files[i].find(".pdb", pos1);
			if(pos1==string::npos || pos2==string::npos || pos2<pos1){
				newpdbFiles = false;
				break;
			}
		}

		
		ofstream distFile;
		distFile.open(distFileName);
		if(newpdbFiles){
			for(int i=0; i<s; i++){
				size_t pos1 = files[i].find("newpdb_");
				size_t pos2 = files[i].find(".pdb",pos1);
				string id_i = files[i].substr(pos1+7, pos2-pos1-7); 
				for(int j=i+1; j<s; j++){
					pos1 = files[j].find("newpdb_");
					pos2 = files[j].find(".pdb",pos1);
					string id_j = files[j].substr(pos1+7, pos2-pos1-7); 
					distFile<<id_i<<" "<<id_j<<" "<<allDists.get(i,j)<<endl;
				}
			}
		}else{
			for(int i=0; i<s; i++){
				for(int j=i+1; j<s; j++){
					distFile<<files[i]<<" "<<files[j]<<" "<<allDists.get(i,j)<<endl;
				}
			}
		}
		distFile.close();

		//ofstream distFile;
		//distFile.open(distFileName);
		//for(int i=0; i<s; i++){
		//	for(int j=i+1; j<s; j++){
		//		distFile<<i<<" "<<j<<" "<<allDists.get(i,j)<<endl;
		//	}
		//}
		//distFile.close();
		exit(0);
	}

	if(clusters>s){
		cerr<<"Cannot find "<<clusters<<" clusters in "<<s<<" structures"<<endl;
		exit(-1);
	}

	cout<<"Clustering"<<endl;
	vector<int> medoids;
	for(int i=0;i<clusters;i++){
		int val = rand()%s;
		while(contains(medoids, val)) val=rand()%s;
		medoids.push_back(val);
		//medoids.push_back(rand()%s);
		//medoids.push_back(i);
	}

	//Partitioning around medoids: http://en.wikipedia.org/wiki/K-medoids
	double oldCost = -1, cost = medoidCosts(medoids, allDists, clusteringType);
	while(cost!=oldCost){
		oldCost = cost;
		for(int i=0;i<clusters;i++){
			int medoid = medoids[i];
			for(int j=0;j<s;j++){
				if( contains(medoids,j) ) continue;
				medoids[i] = j;
				double newCost = medoidCosts(medoids, allDists, clusteringType );
				if(newCost<cost){
					cost=newCost;
					medoid = j;
					cout<<"Improved cost: "<<newCost<<endl;
				}
			}
			medoids[i] = medoid;
		}
	}
	sort(medoids.begin(), medoids.end());
	double end_cpu = get_cpu_time();
	double end_wall = get_wall_time();
	cout<<"CPU-time : "<<(end_cpu-start_cpu)<<" seconds"<<endl;
	cout<<"Wall-time: "<<(end_wall-start_wall)<<" seconds"<<endl;

	cout<<"Clusters:"<<endl;
	for(unsigned int i=0;i<files.size();i++){
		double min = 1000000000.0;
		int minMed = -1;

		for(unsigned int j=0;j<medoids.size();j++){
			int m = medoids[j];
			double d = allDists.get(m,i);
			if( d<min ) { min = d; minMed = j; }
		}
		cout<<files[i]<<" "<<minMed<<endl;

	}
	cout<<"Medoids:"<<endl;
	for( int m=0;m<clusters;m++)
		cout<<files[medoids[m]]<<endl;

	return 0;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x308, %rsp            # imm = 0x308
movq %rsi, %r12
cmpl $0x1, %edi
je 0x39f6
movl %edi, %r13d
xorpd %xmm0, %xmm0
leaq 0x50(%rsp), %rcx
andq $0x0, 0x10(%rcx)
leaq 0x20(%rsp), %rdx
andq $0x0, 0x10(%rdx)
leaq 0xd0(%rsp), %rax
movq %rax, -0x10(%rax)
andq $0x0, -0x8(%rax)
movapd %xmm0, (%rcx)
movapd %xmm0, (%rdx)
movb $0x0, (%rax)
pushq $0xa
popq %rax
movl %eax, 0x18(%rsp)
movl $0xff676980, 0x8(%rsp)  # imm = 0xFF676980
movl $0x989680, 0x10(%rsp)   # imm = 0x989680
pushq $0x1
popq %rbx
leaq 0x100(%rsp), %r15
leaq 0x70(%rsp), %r14
movl $0x0, 0x4(%rsp)
cmpl %r13d, %ebx
jge 0x347f
movslq %ebx, %rbp
movq (%r12,%rbp,8), %rsi
movq %r15, %rdi
movq %r14, %rdx
callq 0x20c0
movq %r15, %rdi
leaq 0x234c(%rip), %rsi      # 0x5637
callq 0x3ff1
testb %al, %al
je 0x331a
movq 0x8(%r12,%rbp,8), %rsi
movq %r14, %rdi
leaq 0xe0(%rsp), %rdx
callq 0x20c0
leaq 0x50(%rsp), %rdi
movq %r14, %rsi
callq 0x401c
incl %ebx
jmp 0x3393
movq %r15, %rdi
leaq 0x2319(%rip), %rsi      # 0x563d
callq 0x3ff1
testb %al, %al
je 0x33aa
movq 0x8(%r12,%rbp,8), %rsi
movq %r14, %rdi
leaq 0xe0(%rsp), %rdx
callq 0x20c0
incl %ebx
movq %r14, %rdi
leaq 0x1f5c(%rip), %rsi      # 0x52aa
callq 0x3ff1
testb %al, %al
movl 0x4(%rsp), %ebp
movl $0x0, %eax
cmovnel %eax, %ebp
movq %r14, %rdi
leaq 0x22e2(%rip), %rsi      # 0x564d
callq 0x3ff1
testb %al, %al
pushq $0x1
popq %rax
cmovnel %eax, %ebp
movq %r14, %rdi
leaq 0x22d6(%rip), %rsi      # 0x5658
callq 0x3ff1
testb %al, %al
pushq $0x2
popq %rax
cmovnel %eax, %ebp
movl %ebp, 0x4(%rsp)
movq %r14, %rdi
callq 0x20f0
movq %r15, %rdi
callq 0x20f0
incl %ebx
jmp 0x32c6
movq %r15, %rdi
leaq 0x22ac(%rip), %rsi      # 0x5660
callq 0x3ff1
testb %al, %al
je 0x33e7
movq 0x8(%r12,%rbp,8), %rsi
movq %r14, %rdi
leaq 0xe0(%rsp), %rdx
callq 0x20c0
leaq 0xc0(%rsp), %rdi
movq %r14, %rsi
callq 0x2130
jmp 0x3316
movq %r15, %rdi
leaq 0x227e(%rip), %rsi      # 0x566f
callq 0x3ff1
testb %al, %al
je 0x340c
incl %ebx
movq 0x8(%r12,%rbp,8), %rdi
callq 0x22b0
movl %eax, 0x18(%rsp)
jmp 0x339b
movq %r15, %rdi
leaq 0x2263(%rip), %rsi      # 0x5679
callq 0x3ff1
testb %al, %al
je 0x3434
incl %ebx
movq 0x8(%r12,%rbp,8), %rdi
callq 0x22b0
movl %eax, 0x8(%rsp)
jmp 0x339b
movq %r15, %rdi
leaq 0x2245(%rip), %rsi      # 0x5683
callq 0x3ff1
testb %al, %al
je 0x345c
incl %ebx
movq 0x8(%r12,%rbp,8), %rdi
callq 0x22b0
movl %eax, 0x10(%rsp)
jmp 0x339b
movq 0x100(%rsp), %rax
cmpb $0x2d, (%rax)
je 0x3d5a
leaq 0x20(%rsp), %rdi
movq %r15, %rsi
callq 0x401c
jmp 0x339b
movq 0x50(%rsp), %rax
cmpq 0x58(%rsp), %rax
jne 0x34fb
leaq 0x220d(%rip), %rsi      # 0x569f
leaq 0x100(%rsp), %rdi
leaq 0x70(%rsp), %rdx
callq 0x20c0
leaq 0x50(%rsp), %rdi
leaq 0x100(%rsp), %rsi
callq 0x46fe
leaq 0x100(%rsp), %rdi
callq 0x20f0
leaq 0x1db7(%rip), %rsi      # 0x5281
leaq 0x100(%rsp), %rdi
leaq 0x70(%rsp), %rdx
callq 0x20c0
leaq 0x50(%rsp), %rdi
leaq 0x100(%rsp), %rsi
callq 0x46fe
leaq 0x100(%rsp), %rdi
callq 0x20f0
callq 0x322e
movsd %xmm0, 0xb0(%rsp)
callq 0x31f3
movsd %xmm0, 0xa8(%rsp)
xorpd %xmm0, %xmm0
movapd %xmm0, 0x90(%rsp)
andq $0x0, 0xa0(%rsp)
movq 0x4a9c(%rip), %rdi      # 0x7fd0
leaq 0x2168(%rip), %rsi      # 0x56a3
callq 0x21d0
movq %rax, %rdi
callq 0x2110
leaq 0x20(%rsp), %rdi
leaq 0x50(%rsp), %rsi
leaq 0x90(%rsp), %r8
movl 0x8(%rsp), %edx
movl 0x10(%rsp), %ecx
callq 0x2780
movq 0x4a62(%rip), %rdi      # 0x7fd0
leaq 0x2140(%rip), %rsi      # 0x56b5
callq 0x21d0
movq %rax, %rdi
callq 0x2110
movq 0x98(%rsp), %r14
subq 0x90(%rsp), %r14
shrq $0x3, %r14
leaq 0x40(%rsp), %rdi
movl %r14d, %esi
movl %r14d, %edx
callq 0x249c
xorl %r15d, %r15d
testl %r14d, %r14d
movl $0x0, %ebx
cmovgl %r14d, %ebx
pushq $0x1
popq %rbp
leaq 0x40(%rsp), %r12
cmpq %rbx, %r15
je 0x3625
leaq 0x1(%r15), %rax
movq %rax, 0x10(%rsp)
movq %rbp, %r13
cmpl %r14d, %r13d
jge 0x361b
movq 0x90(%rsp), %rax
movq (%rax,%r15,8), %rdi
movq (%rax,%r13,8), %rsi
callq 0x2676
movq %r12, %rdi
movl %r15d, %esi
movl %r13d, %edx
movsd %xmm0, 0x8(%rsp)
movsd 0x8(%rsp), %xmm0
callq 0x25ea
movsd 0x8(%rsp), %xmm0
movq %r12, %rdi
movl %r13d, %esi
movl %r15d, %edx
callq 0x25ea
incq %r13
jmp 0x35ce
incq %rbp
movq 0x10(%rsp), %r15
jmp 0x35bd
cmpq $0x0, 0xc8(%rsp)
jne 0x3b91
cmpl %r14d, 0x18(%rsp)
jg 0x3d08
movq 0x498a(%rip), %rdi      # 0x7fd0
leaq 0x20c1(%rip), %rsi      # 0x570e
callq 0x21d0
movq %rax, %rdi
callq 0x2110
xorpd %xmm0, %xmm0
leaq 0x100(%rsp), %r15
movapd %xmm0, (%r15)
andq $0x0, 0x10(%r15)
xorl %ebp, %ebp
movl 0x18(%rsp), %r13d
testl %r13d, %r13d
cmovlel %ebp, %r13d
leaq 0x70(%rsp), %r12
cmpl %r13d, %ebp
je 0x36b2
callq 0x2080
cltd
idivl %r14d
movl %edx, 0x70(%rsp)
movq %r15, %rdi
movl %edx, %esi
callq 0x2ed8
testb %al, %al
jne 0x3688
movq %r15, %rdi
movq %r12, %rsi
callq 0x4048
incl %ebp
jmp 0x3683
leaq 0x100(%rsp), %rdi
leaq 0x40(%rsp), %rsi
movl 0x4(%rsp), %edx
callq 0x31a3
movl %r13d, %eax
movq %rax, 0x18(%rsp)
movsd 0x19e8(%rip), %xmm1     # 0x50c0
leaq 0x100(%rsp), %r14
leaq 0x40(%rsp), %r15
ucomisd %xmm1, %xmm0
jne 0x36f1
jnp 0x37c1
xorl %r12d, %r12d
movsd %xmm0, 0xb8(%rsp)
movsd %xmm0, 0x10(%rsp)
cmpq 0x18(%rsp), %r12
je 0x37ad
movq 0x100(%rsp), %rax
movl (%rax,%r12,4), %r13d
xorl %ebp, %ebp
cmpl %ebp, %ebx
je 0x3799
movq %r14, %rdi
movl %ebp, %esi
callq 0x2ed8
testb %al, %al
jne 0x3795
movq 0x100(%rsp), %rax
movl %ebp, (%rax,%r12,4)
movq %r14, %rdi
movq %r15, %rsi
movl 0x4(%rsp), %edx
callq 0x31a3
movsd %xmm0, 0x8(%rsp)
movsd 0x10(%rsp), %xmm0
ucomisd 0x8(%rsp), %xmm0
jbe 0x3795
movq 0x486c(%rip), %rdi      # 0x7fd0
leaq 0x1fae(%rip), %rsi      # 0x5719
callq 0x21d0
movq %rax, %rdi
movsd 0x8(%rsp), %xmm0
callq 0x22c0
movq %rax, %rdi
callq 0x2110
movsd 0x8(%rsp), %xmm0
movsd %xmm0, 0x10(%rsp)
movl %ebp, %r13d
incl %ebp
jmp 0x371c
movq 0x100(%rsp), %rax
movl %r13d, (%rax,%r12,4)
incq %r12
jmp 0x3703
movsd 0xb8(%rsp), %xmm1
movsd 0x10(%rsp), %xmm0
jmp 0x36e5
movq 0x100(%rsp), %rdi
movq 0x108(%rsp), %rsi
callq 0x4939
callq 0x322e
movsd %xmm0, 0x8(%rsp)
callq 0x31f3
movsd %xmm0, 0x10(%rsp)
movq 0x47dd(%rip), %rdi      # 0x7fd0
leaq 0x1f2f(%rip), %rsi      # 0x5729
callq 0x21d0
movsd 0x8(%rsp), %xmm0
subsd 0xb0(%rsp), %xmm0
movq %rax, %rdi
callq 0x22c0
leaq 0x1f18(%rip), %rsi      # 0x5735
movq %rax, %rdi
callq 0x21d0
movq %rax, %rdi
callq 0x2110
movq 0x479c(%rip), %rdi      # 0x7fd0
leaq 0x1f03(%rip), %rsi      # 0x573e
callq 0x21d0
movsd 0x10(%rsp), %xmm0
subsd 0xa8(%rsp), %xmm0
movq %rax, %rdi
callq 0x22c0
leaq 0x1ed7(%rip), %rsi      # 0x5735
movq %rax, %rdi
callq 0x21d0
movq %rax, %rdi
callq 0x2110
movq 0x475b(%rip), %rdi      # 0x7fd0
leaq 0x1ece(%rip), %rsi      # 0x574a
callq 0x21d0
movq %rax, %rdi
callq 0x2110
xorl %ebx, %ebx
leaq 0x40(%rsp), %r14
movq 0x4739(%rip), %r15      # 0x7fd0
leaq 0x1e95(%rip), %r12      # 0x5733
movl %ebx, %ebx
movq 0x28(%rsp), %rax
subq 0x20(%rsp), %rax
sarq $0x5, %rax
cmpq %rbx, %rax
jbe 0x3947
xorl %r13d, %r13d
movsd 0x17e6(%rip), %xmm0     # 0x50a8
pushq $-0x1
popq %rbp
movl %r13d, %r13d
movq 0x100(%rsp), %rax
movq 0x108(%rsp), %rcx
subq %rax, %rcx
sarq $0x2, %rcx
cmpq %r13, %rcx
jbe 0x390f
movsd %xmm0, 0x8(%rsp)
movl (%rax,%r13,4), %esi
movq %r14, %rdi
movl %ebx, %edx
callq 0x255e
movsd 0x8(%rsp), %xmm1
ucomisd %xmm0, %xmm1
cmoval %r13d, %ebp
minsd %xmm1, %xmm0
incl %r13d
jmp 0x38c5
movq %rbx, %rsi
shlq $0x5, %rsi
addq 0x20(%rsp), %rsi
movq %r15, %rdi
callq 0x21b0
movq %rax, %rdi
movq %r12, %rsi
callq 0x21d0
movq %rax, %rdi
movl %ebp, %esi
callq 0x2310
movq %rax, %rdi
callq 0x2110
incl %ebx
jmp 0x389e
movq 0x4682(%rip), %rdi      # 0x7fd0
leaq 0x1dff(%rip), %rsi      # 0x5754
callq 0x21d0
movq %rax, %rdi
callq 0x2110
xorl %r14d, %r14d
movq 0x4664(%rip), %rbx      # 0x7fd0
cmpq %r14, 0x18(%rsp)
je 0x399d
movq 0x100(%rsp), %rax
movslq (%rax,%r14,4), %rsi
shlq $0x5, %rsi
addq 0x20(%rsp), %rsi
movq %rbx, %rdi
callq 0x21b0
movq %rax, %rdi
callq 0x2110
incq %r14
jmp 0x396c
leaq 0x100(%rsp), %rdi
callq 0x47ea
leaq 0x40(%rsp), %rdi
callq 0x2548
leaq 0x90(%rsp), %rdi
callq 0x47dc
leaq 0xc0(%rsp), %rdi
callq 0x20f0
leaq 0x20(%rsp), %rdi
callq 0x4066
leaq 0x50(%rsp), %rdi
callq 0x4066
xorl %eax, %eax
addq $0x308, %rsp            # imm = 0x308
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x45d3(%rip), %rbx      # 0x7fd0
leaq 0x16e3(%rip), %rsi      # 0x50e7
movq %rbx, %rdi
callq 0x21d0
movq %rax, %rdi
callq 0x2110
movq (%r12), %rsi
movq %rax, %rdi
callq 0x21d0
leaq 0x16c8(%rip), %rsi      # 0x50ef
movq %rax, %rdi
callq 0x21d0
movq %rax, %rdi
callq 0x2110
leaq 0x174f(%rip), %rsi      # 0x518d
movq %rbx, %rdi
callq 0x21d0
movq %rax, %rdi
callq 0x2110
movq (%r12), %rsi
movq %rax, %rdi
callq 0x21d0
leaq 0x1731(%rip), %rsi      # 0x5192
movq %rax, %rdi
callq 0x21d0
movq %rax, %rdi
callq 0x2110
leaq 0x175e(%rip), %rsi      # 0x51d6
movq %rbx, %rdi
callq 0x21d0
movq %rax, %rdi
callq 0x2110
movq (%r12), %rsi
movq %rbx, %rdi
callq 0x21d0
leaq 0x1762(%rip), %rsi      # 0x51fd
movq %rax, %rdi
callq 0x21d0
movq %rax, %rdi
callq 0x2110
movq %rbx, %rdi
callq 0x2110
leaq 0x17a3(%rip), %rsi      # 0x525d
movq %rbx, %rdi
callq 0x21d0
movq %rax, %rdi
callq 0x2110
leaq 0x17b3(%rip), %rsi      # 0x5284
movq %rbx, %rdi
callq 0x21d0
movq %rax, %rdi
callq 0x2110
leaq 0x17ca(%rip), %rsi      # 0x52b2
movq %rbx, %rdi
callq 0x21d0
movq %rax, %rdi
callq 0x2110
leaq 0x17d6(%rip), %rsi      # 0x52d5
movq %rbx, %rdi
callq 0x21d0
movq %rax, %rdi
callq 0x2110
leaq 0x17e9(%rip), %rsi      # 0x52ff
movq %rbx, %rdi
callq 0x21d0
movq %rax, %rdi
callq 0x2110
movq %rbx, %rdi
callq 0x2110
leaq 0x17f2(%rip), %rsi      # 0x5327
movq %rbx, %rdi
callq 0x21d0
movq %rax, %rdi
callq 0x2110
leaq 0x1890(%rip), %rsi      # 0x53dc
movq %rbx, %rdi
callq 0x21d0
movq %rax, %rdi
callq 0x2110
leaq 0x1941(%rip), %rsi      # 0x54a4
movq %rbx, %rdi
callq 0x21d0
movq %rax, %rdi
callq 0x2110
leaq 0x19d3(%rip), %rsi      # 0x554d
movq %rbx, %rdi
callq 0x21d0
movq %rax, %rdi
callq 0x2110
xorl %edi, %edi
callq 0x2210
movq 0x4438(%rip), %rdi      # 0x7fd0
leaq 0x1b25(%rip), %rsi      # 0x56c4
callq 0x21d0
leaq 0xc0(%rsp), %rsi
movq %rax, %rdi
callq 0x21b0
movq %rax, %rdi
callq 0x2110
xorl %ecx, %ecx
movl %ecx, %ebp
movq 0x20(%rsp), %rdi
movq 0x28(%rsp), %r15
subq %rdi, %r15
sarq $0x5, %r15
cmpq %rbp, %r15
jbe 0x3c1c
movq %rbp, %r13
shlq $0x5, %r13
addq %r13, %rdi
leaq 0x1af3(%rip), %rsi      # 0x56da
xorl %edx, %edx
callq 0x2340
movq %rax, %r12
addq 0x20(%rsp), %r13
movq %r13, %rdi
leaq 0x1ae2(%rip), %rsi      # 0x56e2
movq %rax, %rdx
callq 0x2340
cmpq %r12, %rax
jb 0x3c1c
cmpq $-0x1, %r12
je 0x3c1c
leal 0x1(%rbp), %ecx
cmpq $-0x1, %rax
jne 0x3bbe
leaq 0x100(%rsp), %rdi
callq 0x2300
leaq 0x100(%rsp), %rdi
leaq 0xc0(%rsp), %rsi
pushq $0x10
popq %rdx
callq 0x2100
pushq $0x20
popq %rax
cmpq %rbp, %r15
jbe 0x3d8d
movq %rax, 0x10(%rsp)
pushq $0x1
popq %rax
movl %eax, 0x4(%rsp)
xorl %r13d, %r13d
cmpq %rbx, %r13
je 0x3f04
leaq 0x1(%r13), %rax
movq %rax, 0x18(%rsp)
movq %r13, 0x8(%rsp)
shlq $0x5, %r13
movl 0x4(%rsp), %ebp
movq 0x10(%rsp), %r15
cmpl %r14d, %ebp
jge 0x3cf4
movq 0x20(%rsp), %rsi
addq %r13, %rsi
leaq 0x100(%rsp), %rdi
callq 0x21b0
movq %rax, %rdi
leaq 0x1a8f(%rip), %rsi      # 0x5733
callq 0x21d0
movq 0x20(%rsp), %rsi
addq %r15, %rsi
movq %rax, %rdi
callq 0x21b0
movq %rax, %rdi
leaq 0x1a70(%rip), %rsi      # 0x5733
callq 0x21d0
movq %rax, %r12
leaq 0x40(%rsp), %rdi
movq 0x8(%rsp), %rsi
movl %ebp, %edx
callq 0x255e
movq %r12, %rdi
callq 0x22c0
movq %rax, %rdi
callq 0x2110
addq $0x20, %r15
incl %ebp
jmp 0x3c80
addq $0x20, 0x10(%rsp)
incl 0x4(%rsp)
movq 0x18(%rsp), %r13
jmp 0x3c5c
movq 0x42e1(%rip), %rdi      # 0x7ff0
leaq 0x19d1(%rip), %rsi      # 0x56e7
callq 0x21d0
movq %rax, %rdi
movl 0x18(%rsp), %esi
callq 0x2310
leaq 0x19c6(%rip), %rsi      # 0x56f4
movq %rax, %rdi
callq 0x21d0
movq %rax, %rdi
movl %r14d, %esi
callq 0x2310
leaq 0x19ba(%rip), %rsi      # 0x5702
movq %rax, %rdi
callq 0x21d0
movq %rax, %rdi
callq 0x2110
jmp 0x3d85
movq 0x428f(%rip), %rdi      # 0x7ff0
leaq 0x1924(%rip), %rsi      # 0x568c
callq 0x21d0
leaq 0x100(%rsp), %rsi
movq %rax, %rdi
callq 0x21b0
movq %rax, %rdi
callq 0x2110
pushq $-0x1
popq %rdi
callq 0x2210
movq %rax, 0x10(%rsp)
pushq $0x1
popq %rax
movl %eax, 0x4(%rsp)
xorl %ebp, %ebp
leaq 0xe0(%rsp), %r13
cmpq %rbx, %rbp
je 0x3f04
movq %rbp, %r15
shlq $0x5, %r15
movq 0x20(%rsp), %rdi
addq %r15, %rdi
leaq 0x1918(%rip), %rsi      # 0x56da
xorl %edx, %edx
callq 0x2340
movq %rax, %r12
movq 0x20(%rsp), %rdi
addq %r15, %rdi
leaq 0x1907(%rip), %rsi      # 0x56e2
movq %rax, %rdx
callq 0x2340
addq 0x20(%rsp), %r15
subq %r12, %rax
addq $0x7, %r12
leaq -0x7(%rax), %rcx
leaq 0x70(%rsp), %rdi
movq %r15, %rsi
movq %r12, %rdx
callq 0x21f0
movq %rbp, 0x8(%rsp)
leaq 0x1(%rbp), %rax
movq %rax, 0x18(%rsp)
movl 0x4(%rsp), %r15d
movq 0x10(%rsp), %rbp
cmpl %r14d, %r15d
jge 0x3ee6
movq 0x20(%rsp), %rdi
addq %rbp, %rdi
leaq 0x18a7(%rip), %rsi      # 0x56da
xorl %edx, %edx
callq 0x2340
movq %rax, %r12
movq 0x20(%rsp), %rdi
addq %rbp, %rdi
leaq 0x1896(%rip), %rsi      # 0x56e2
movq %rax, %rdx
callq 0x2340
movq 0x20(%rsp), %rsi
addq %rbp, %rsi
subq %r12, %rax
addq $0x7, %r12
leaq -0x7(%rax), %rcx
movq %r13, %rdi
movq %r12, %rdx
callq 0x21f0
leaq 0x100(%rsp), %rdi
leaq 0x70(%rsp), %rsi
callq 0x21b0
movq %rax, %rdi
leaq 0x18a5(%rip), %rsi      # 0x5733
callq 0x21d0
movq %rax, %rdi
movq %r13, %rsi
callq 0x21b0
movq %rax, %rdi
leaq 0x188b(%rip), %rsi      # 0x5733
callq 0x21d0
movq %rax, %r12
leaq 0x40(%rsp), %rdi
movq 0x8(%rsp), %rsi
movl %r15d, %edx
callq 0x255e
movq %r12, %rdi
callq 0x22c0
movq %rax, %rdi
callq 0x2110
movq %r13, %rdi
callq 0x20f0
addq $0x20, %rbp
incl %r15d
jmp 0x3e1b
leaq 0x70(%rsp), %rdi
callq 0x20f0
addq $0x20, 0x10(%rsp)
incl 0x4(%rsp)
movq 0x18(%rsp), %rbp
jmp 0x3da3
leaq 0x100(%rsp), %rdi
callq 0x2270
jmp 0x3b8a
jmp 0x3f3b
movq %rax, %rbx
jmp 0x3f2d
movq %rax, %rbx
leaq 0xe0(%rsp), %rdi
callq 0x20f0
leaq 0x70(%rsp), %rdi
callq 0x20f0
jmp 0x3f3e
jmp 0x3f3b
movq %rax, %rbx
leaq 0x100(%rsp), %rdi
callq 0x2290
jmp 0x3fb1
jmp 0x3f9c
jmp 0x3f7d
jmp 0x3f91
jmp 0x3f7d
jmp 0x3f91
jmp 0x3f7d
jmp 0x3f7d
jmp 0x3f65
jmp 0x3fa1
jmp 0x3f9c
jmp 0x3f6e
jmp 0x3f7d
movq %rax, %rbx
jmp 0x3fbb
jmp 0x3f7d
jmp 0x3fa1
movq %rax, %rbx
leaq 0x70(%rsp), %rdi
callq 0x20f0
jmp 0x3f80
movq %rax, %rbx
leaq 0x100(%rsp), %rdi
callq 0x20f0
jmp 0x3fc8
jmp 0x3fa1
movq %rax, %rbx
jmp 0x3fc8
jmp 0x3fa1
jmp 0x3fa1
jmp 0x3fa1
movq %rax, %rbx
jmp 0x3fb1
movq %rax, %rbx
leaq 0x100(%rsp), %rdi
callq 0x47ea
leaq 0x40(%rsp), %rdi
callq 0x2548
leaq 0x90(%rsp), %rdi
callq 0x47dc
leaq 0xc0(%rsp), %rdi
callq 0x20f0
leaq 0x20(%rsp), %rdi
callq 0x4066
leaq 0x50(%rsp), %rdi
callq 0x4066
movq %rbx, %rdi
callq 0x2320