// File: /workspace/github_cpp_makefile_star2_O1/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 $0x318, %rsp            # imm = 0x318
movq %rsi, %r12
cmpl $0x1, %edi
je 0x4280
movl %edi, %r13d
xorpd %xmm0, %xmm0
movapd %xmm0, 0x80(%rsp)
xorl %ecx, %ecx
movq %rcx, 0x90(%rsp)
movq %rcx, 0x40(%rsp)
movapd %xmm0, 0x30(%rsp)
leaq 0xf0(%rsp), %rax
movq %rax, -0x10(%rax)
movq $0x0, 0x20(%rsp)
movq %rcx, -0x8(%rax)
movb $0x0, (%rax)
cmpl $0x2, %edi
jl 0x39ae
movl $0x989680, 0x8(%rsp)    # imm = 0x989680
movl $0xff676980, 0x18(%rsp) # imm = 0xFF676980
movq $0x0, 0x20(%rsp)
movl $0xa, 0x14(%rsp)
leaq 0x110(%rsp), %rbp
leaq 0x50(%rsp), %r14
movl $0x1, %ebx
movslq %ebx, %r15
movq (%r12,%r15,8), %rsi
movq %rbp, %rdi
movq %r14, %rdx
callq 0x20c0
movq %rbp, %rdi
leaq 0x2e86(%rip), %rsi      # 0x665f
callq 0x20a0
testl %eax, %eax
je 0x387c
movq %rbp, %rdi
leaq 0x2e75(%rip), %rsi      # 0x6665
callq 0x20a0
testl %eax, %eax
je 0x38a6
movq %rbp, %rdi
leaq 0x2e81(%rip), %rsi      # 0x6688
callq 0x20a0
testl %eax, %eax
je 0x3910
movq %rbp, %rdi
leaq 0x2e79(%rip), %rsi      # 0x6697
callq 0x20a0
testl %eax, %eax
je 0x3972
movq %rbp, %rdi
leaq 0x2e6c(%rip), %rsi      # 0x66a1
callq 0x20a0
testl %eax, %eax
je 0x3986
movq %rbp, %rdi
leaq 0x2e5f(%rip), %rsi      # 0x66ab
callq 0x20a0
testl %eax, %eax
je 0x399a
movq 0x110(%rsp), %rax
cmpb $0x2d, (%rax)
je 0x477e
leaq 0x30(%rsp), %rdi
movq %rbp, %rsi
callq 0x4a0e
jmp 0x394b
movq 0x8(%r12,%r15,8), %rsi
movq %r14, %rdi
leaq 0xc0(%rsp), %rdx
callq 0x20c0
leaq 0x80(%rsp), %rdi
movq %r14, %rsi
callq 0x4a0e
jmp 0x3935
movq 0x8(%r12,%r15,8), %rsi
movq %r14, %rdi
leaq 0xc0(%rsp), %rdx
callq 0x20c0
movq %r14, %rdi
leaq 0x2a0d(%rip), %rsi      # 0x62d2
callq 0x20a0
testl %eax, %eax
movq 0x20(%rsp), %r15
cmovel %eax, %r15d
movq %r14, %rdi
leaq 0x2d96(%rip), %rsi      # 0x6675
callq 0x20a0
testl %eax, %eax
movl $0x1, %eax
cmovel %eax, %r15d
movq %r14, %rdi
leaq 0x2d87(%rip), %rsi      # 0x6680
callq 0x20a0
testl %eax, %eax
movl $0x2, %eax
cmovel %eax, %r15d
movq %r15, 0x20(%rsp)
jmp 0x3935
movq 0x8(%r12,%r15,8), %rsi
movq %r14, %rdi
leaq 0xc0(%rsp), %rdx
callq 0x20c0
leaq 0xe0(%rsp), %rdi
movq %r14, %rsi
callq 0x2110
movq 0x50(%rsp), %rdi
leaq 0x60(%rsp), %rax
cmpq %rax, %rdi
je 0x3949
callq 0x21b0
incl %ebx
movq 0x110(%rsp), %rdi
leaq 0x120(%rsp), %rax
cmpq %rax, %rdi
je 0x3965
callq 0x21b0
incl %ebx
cmpl %r13d, %ebx
jl 0x37bd
jmp 0x39c6
leal 0x1(%r15), %ebx
movq 0x8(%r12,%r15,8), %rdi
callq 0x22b0
movl %eax, 0x14(%rsp)
jmp 0x394b
leal 0x1(%r15), %ebx
movq 0x8(%r12,%r15,8), %rdi
callq 0x22b0
movl %eax, 0x18(%rsp)
jmp 0x394b
leal 0x1(%r15), %ebx
movq 0x8(%r12,%r15,8), %rdi
callq 0x22b0
movl %eax, 0x8(%rsp)
jmp 0x394b
movl $0xa, 0x14(%rsp)
movl $0xff676980, 0x18(%rsp) # imm = 0xFF676980
movl $0x989680, 0x8(%rsp)    # imm = 0x989680
movq 0x80(%rsp), %rax
cmpq 0x88(%rsp), %rax
jne 0x3a6f
leaq 0x120(%rsp), %rbx
movq %rbx, -0x10(%rbx)
leaq 0x2cd8(%rip), %rsi      # 0x66c7
leaq 0x2cd4(%rip), %rdx      # 0x66ca
leaq 0x110(%rsp), %rdi
callq 0x4c5e
leaq 0x80(%rsp), %rdi
leaq 0x110(%rsp), %rsi
callq 0x5062
movq 0x110(%rsp), %rdi
cmpq %rbx, %rdi
je 0x3a2a
callq 0x21b0
leaq 0x110(%rsp), %rdi
movq %rbx, (%rdi)
leaq 0x286d(%rip), %rsi      # 0x62a9
leaq 0x2868(%rip), %rdx      # 0x62ab
callq 0x4c5e
leaq 0x80(%rsp), %rdi
leaq 0x110(%rsp), %rsi
callq 0x5062
movq 0x110(%rsp), %rdi
cmpq %rbx, %rdi
je 0x3a6f
callq 0x21b0
callq 0x2140
movq %rax, %r14
callq 0x36d3
movsd %xmm0, 0x108(%rsp)
xorpd %xmm0, %xmm0
movapd %xmm0, 0xa0(%rsp)
movq $0x0, 0xb0(%rsp)
movq 0x552b(%rip), %rbx      # 0x8fd0
leaq 0x2c1f(%rip), %rsi      # 0x66cb
movl $0x11, %edx
movq %rbx, %rdi
callq 0x2210
movq (%rbx), %rax
addq -0x18(%rax), %rbx
movq %rbx, %rdi
movl $0xa, %esi
callq 0x21c0
movsbl %al, %esi
movq 0x54f9(%rip), %rdi      # 0x8fd0
callq 0x2040
movq %rax, %rdi
callq 0x2150
leaq 0x30(%rsp), %rdi
leaq 0x80(%rsp), %rsi
leaq 0xa0(%rsp), %r8
movl 0x18(%rsp), %edx
movl 0x8(%rsp), %ecx
callq 0x2858
movq 0x54c3(%rip), %rbx      # 0x8fd0
leaq 0x2bc9(%rip), %rsi      # 0x66dd
movl $0xe, %edx
movq %rbx, %rdi
callq 0x2210
movq (%rbx), %rax
addq -0x18(%rax), %rbx
movq %rbx, %rdi
movl $0xa, %esi
callq 0x21c0
movsbl %al, %esi
movq 0x5491(%rip), %rdi      # 0x8fd0
callq 0x2040
movq %rax, %rdi
callq 0x2150
movq %r14, 0x100(%rsp)
movq 0xa8(%rsp), %rbx
subq 0xa0(%rsp), %rbx
shrq $0x3, %rbx
leaq 0x70(%rsp), %rdi
movl %ebx, %esi
movl %ebx, %edx
callq 0x24fc
movq %rbx, 0x8(%rsp)
testl %ebx, %ebx
jle 0x3bf9
movq 0x8(%rsp), %r14
andl $0x7fffffff, %r14d      # imm = 0x7FFFFFFF
movl $0x1, %r15d
xorl %ebp, %ebp
leaq 0x70(%rsp), %rbx
movq %rbp, %r12
incq %rbp
cmpq %r14, %rbp
jae 0x3bf1
movq %r15, %r13
movq 0xa0(%rsp), %rax
movq (%rax,%r12,8), %rdi
movq (%rax,%r13,8), %rsi
callq 0x2706
movq %rbx, %rdi
movl %r12d, %esi
movl %r13d, %edx
movsd %xmm0, 0x18(%rsp)
movsd 0x18(%rsp), %xmm0
callq 0x2666
movsd 0x18(%rsp), %xmm0
movq %rbx, %rdi
movl %r13d, %esi
movl %r12d, %edx
callq 0x2666
incq %r13
cmpq %r13, %r14
jne 0x3ba6
incq %r15
cmpq %r14, %rbp
jne 0x3b98
cmpq $0x0, 0xe8(%rsp)
jne 0x441b
movq 0x8(%rsp), %r14
cmpl %r14d, 0x14(%rsp)
jg 0x4713
movq 0x53b1(%rip), %rbx      # 0x8fd0
leaq 0x2b10(%rip), %rsi      # 0x6736
movl $0xa, %edx
movq %rbx, %rdi
callq 0x2210
movq (%rbx), %rax
addq -0x18(%rax), %rbx
movq %rbx, %rdi
movl $0xa, %esi
callq 0x21c0
movsbl %al, %esi
movq 0x537f(%rip), %rdi      # 0x8fd0
callq 0x2040
movq %rax, %rdi
callq 0x2150
xorpd %xmm0, %xmm0
movapd %xmm0, 0x110(%rsp)
movq $0x0, 0x120(%rsp)
cmpl $0x0, 0x14(%rsp)
jle 0x3d10
xorl %ebp, %ebp
leaq 0x110(%rsp), %rbx
leaq 0x50(%rsp), %r12
callq 0x2080
cltd
idivl %r14d
movq 0x110(%rsp), %rax
movq 0x118(%rsp), %rsi
movq %rsi, %rcx
movl %edx, 0x50(%rsp)
subq %rax, %rcx
setne %dil
je 0x3cde
cmpl %edx, (%rax)
je 0x3cde
sarq $0x2, %rcx
movl $0x1, %r8d
movl %r8d, %r9d
cmpq %r9, %rcx
seta %dil
jbe 0x3cde
leal 0x1(%r9), %r8d
cmpl %edx, (%rax,%r9,4)
jne 0x3cc8
testb %dil, %dil
jne 0x3c91
cmpq 0x120(%rsp), %rsi
je 0x3cfd
movl %edx, (%rsi)
addq $0x4, %rsi
movq %rsi, 0x118(%rsp)
jmp 0x3d08
movq %rbx, %rdi
movq %r12, %rdx
callq 0x5264
incl %ebp
cmpl 0x14(%rsp), %ebp
jne 0x3c91
leaq 0x110(%rsp), %rdi
leaq 0x70(%rsp), %rsi
movq 0x20(%rsp), %rdx
callq 0x3681
movsd %xmm0, 0x48(%rsp)
ucomisd 0x2393(%rip), %xmm0     # 0x60c8
movl 0x14(%rsp), %eax
movq %rax, 0x98(%rsp)
jne 0x3d49
jnp 0x3eac
leaq 0x110(%rsp), %r13
leaq 0x70(%rsp), %rbp
movq 0x5273(%rip), %r12      # 0x8fd0
movsd 0x48(%rsp), %xmm0
movsd %xmm0, 0x28(%rsp)
cmpl $0x0, 0x14(%rsp)
jle 0x3e8e
xorl %ebx, %ebx
movsd 0x48(%rsp), %xmm0
movsd %xmm0, 0x28(%rsp)
movq 0x110(%rsp), %rax
movl (%rax,%rbx,4), %r15d
testl %r14d, %r14d
jle 0x3e6c
xorl %r14d, %r14d
movq 0x110(%rsp), %rax
movq 0x118(%rsp), %rcx
subq %rax, %rcx
setne %dl
je 0x3dd3
cmpl %r14d, (%rax)
je 0x3dd3
sarq $0x2, %rcx
movl $0x1, %esi
movl %esi, %edi
cmpq %rdi, %rcx
seta %dl
jbe 0x3dd3
leal 0x1(%rdi), %esi
cmpl %r14d, (%rax,%rdi,4)
jne 0x3dc0
testb %dl, %dl
jne 0x3e5e
movl %r14d, (%rax,%rbx,4)
movq %r13, %rdi
movq %rbp, %rsi
movq 0x20(%rsp), %rdx
callq 0x3681
movsd %xmm0, 0x18(%rsp)
movsd 0x28(%rsp), %xmm0
ucomisd 0x18(%rsp), %xmm0
jbe 0x3e5e
movl $0xf, %edx
movq %r12, %rdi
leaq 0x292f(%rip), %rsi      # 0x6741
callq 0x2210
movq %r12, %rdi
movsd 0x18(%rsp), %xmm0
callq 0x22c0
movq %rax, %r15
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %r15, %rdi
movl $0xa, %esi
callq 0x21c0
movsbl %al, %esi
movq %r15, %rdi
callq 0x2040
movq %rax, %rdi
callq 0x2150
movsd 0x18(%rsp), %xmm0
movsd %xmm0, 0x28(%rsp)
movl %r14d, %r15d
incl %r14d
cmpl 0x8(%rsp), %r14d
jne 0x3d9a
movq 0x110(%rsp), %rax
movl %r15d, (%rax,%rbx,4)
incq %rbx
cmpq 0x98(%rsp), %rbx
movq 0x8(%rsp), %r14
jne 0x3d82
movsd 0x28(%rsp), %xmm0
ucomisd 0x48(%rsp), %xmm0
movsd %xmm0, 0x48(%rsp)
jne 0x3d69
jp 0x3d69
movq 0x110(%rsp), %rbx
movq 0x118(%rsp), %r14
cmpq %r14, %rbx
je 0x3eee
movq %r14, %rax
subq %rbx, %rax
sarq $0x2, %rax
bsrq %rax, %rdx
xorl $0x3f, %edx
addl %edx, %edx
xorq $0x7e, %rdx
movq %rbx, %rdi
movq %r14, %rsi
callq 0x5397
movq %rbx, %rdi
movq %r14, %rsi
callq 0x547a
callq 0x2140
movq %rax, %rbx
callq 0x36d3
movsd %xmm0, 0x18(%rsp)
movq 0x50c8(%rip), %rdi      # 0x8fd0
leaq 0x2842(%rip), %rsi      # 0x6751
movl $0xb, %edx
callq 0x2210
cvtsi2sdq 0x100(%rsp), %xmm1
divsd 0x2195(%rip), %xmm1     # 0x60c0
xorps %xmm0, %xmm0
cvtsi2sd %rbx, %xmm0
divsd 0x2185(%rip), %xmm0     # 0x60c0
subsd %xmm1, %xmm0
movq 0x508a(%rip), %rdi      # 0x8fd0
callq 0x22c0
movq %rax, %rbx
leaq 0x2808(%rip), %rsi      # 0x675d
movl $0x8, %edx
movq %rax, %rdi
callq 0x2210
movq (%rbx), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
movl $0xa, %esi
callq 0x21c0
movsbl %al, %esi
movq %rbx, %rdi
callq 0x2040
movq %rax, %rdi
callq 0x2150
movq 0x5040(%rip), %rdi      # 0x8fd0
leaq 0x27cf(%rip), %rsi      # 0x6766
movl $0xb, %edx
callq 0x2210
movsd 0x18(%rsp), %xmm0
subsd 0x108(%rsp), %xmm0
movq 0x5019(%rip), %rdi      # 0x8fd0
callq 0x22c0
movq %rax, %rbx
leaq 0x2797(%rip), %rsi      # 0x675d
movl $0x8, %edx
movq %rax, %rdi
callq 0x2210
movq (%rbx), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
movl $0xa, %esi
callq 0x21c0
movsbl %al, %esi
movq %rbx, %rdi
callq 0x2040
movq %rax, %rdi
callq 0x2150
movq 0x4fcf(%rip), %rbx      # 0x8fd0
leaq 0x276a(%rip), %rsi      # 0x6772
movl $0x9, %edx
movq %rbx, %rdi
callq 0x2210
movq (%rbx), %rax
addq -0x18(%rax), %rbx
movq %rbx, %rdi
movl $0xa, %esi
callq 0x21c0
movsbl %al, %esi
movq 0x4f9d(%rip), %rdi      # 0x8fd0
callq 0x2040
movq %rax, %rdi
callq 0x2150
movq 0x38(%rsp), %rax
cmpq 0x30(%rsp), %rax
je 0x4159
xorl %r13d, %r13d
leaq 0x2701(%rip), %r14      # 0x675b
leaq 0x70(%rsp), %r15
xorl %r12d, %r12d
movq 0x110(%rsp), %rax
cmpq %rax, 0x118(%rsp)
je 0x40d2
movl $0xffffffff, %ebp       # imm = 0xFFFFFFFF
movl $0x1, %ebx
xorl %ecx, %ecx
movsd 0x2028(%rip), %xmm0     # 0x60b0
movsd %xmm0, 0x18(%rsp)
movl (%rax,%rcx,4), %esi
movq %r15, %rdi
movl %r12d, %edx
callq 0x25c6
leal -0x1(%rbx), %eax
movsd 0x18(%rsp), %xmm1
ucomisd %xmm0, %xmm1
minsd %xmm1, %xmm0
cmoval %eax, %ebp
movl %ebx, %ecx
movq 0x110(%rsp), %rax
movq 0x118(%rsp), %rdx
subq %rax, %rdx
sarq $0x2, %rdx
incl %ebx
cmpq %rcx, %rdx
ja 0x4088
jmp 0x40d7
movl $0xffffffff, %ebp       # imm = 0xFFFFFFFF
movq 0x30(%rsp), %rax
shlq $0x5, %r13
movq (%rax,%r13), %rsi
movq 0x8(%rax,%r13), %rdx
movq 0x4ee0(%rip), %rdi      # 0x8fd0
callq 0x2210
movq %rax, %r13
movl $0x1, %edx
movq %rax, %rdi
movq %r14, %rsi
callq 0x2210
movq %r13, %rdi
movl %ebp, %esi
callq 0x2310
movq %rax, %r13
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %r13, %rdi
movl $0xa, %esi
callq 0x21c0
movsbl %al, %esi
movq %r13, %rdi
callq 0x2040
movq %rax, %rdi
callq 0x2150
movq 0x38(%rsp), %rax
subq 0x30(%rsp), %rax
incl %r12d
sarq $0x5, %rax
movq %r12, %r13
cmpq %r12, %rax
ja 0x4062
movq 0x4e70(%rip), %rbx      # 0x8fd0
leaq 0x2615(%rip), %rsi      # 0x677c
movl $0x8, %edx
movq %rbx, %rdi
callq 0x2210
movq (%rbx), %rax
addq -0x18(%rax), %rbx
movq %rbx, %rdi
movl $0xa, %esi
callq 0x21c0
movsbl %al, %esi
movq 0x4e3e(%rip), %rdi      # 0x8fd0
callq 0x2040
movq %rax, %rdi
callq 0x2150
cmpl $0x0, 0x14(%rsp)
jle 0x420d
xorl %r15d, %r15d
movq 0x4e20(%rip), %rbx      # 0x8fd0
movq 0x110(%rsp), %rax
movslq (%rax,%r15,4), %rax
movq 0x30(%rsp), %rcx
shlq $0x5, %rax
movq (%rcx,%rax), %rsi
movq 0x8(%rcx,%rax), %rdx
movq %rbx, %rdi
callq 0x2210
movq %rax, %r14
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %r14, %rdi
movl $0xa, %esi
callq 0x21c0
movsbl %al, %esi
movq %r14, %rdi
callq 0x2040
movq %rax, %rdi
callq 0x2150
incq %r15
cmpq %r15, 0x98(%rsp)
jne 0x41b0
movq 0x110(%rsp), %rdi
testq %rdi, %rdi
je 0x421f
callq 0x21b0
leaq 0x70(%rsp), %rdi
callq 0x25b0
movq 0xa0(%rsp), %rdi
testq %rdi, %rdi
je 0x423b
callq 0x21b0
movq 0xe0(%rsp), %rdi
leaq 0xf0(%rsp), %rax
cmpq %rax, %rdi
je 0x4255
callq 0x21b0
leaq 0x30(%rsp), %rdi
callq 0x4a4c
leaq 0x80(%rsp), %rdi
callq 0x4a4c
xorl %eax, %eax
addq $0x318, %rsp            # imm = 0x318
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x4d49(%rip), %rbx      # 0x8fd0
leaq 0x1e81(%rip), %rsi      # 0x610f
movq %rbx, %rdi
callq 0x21d0
movq %rax, %rdi
callq 0x20f0
movq (%r12), %rsi
movq %rax, %rdi
callq 0x21d0
leaq 0x1e66(%rip), %rsi      # 0x6117
movq %rax, %rdi
callq 0x21d0
movq %rax, %rdi
callq 0x20f0
leaq 0x1eed(%rip), %rsi      # 0x61b5
movq %rbx, %rdi
callq 0x21d0
movq %rax, %rdi
callq 0x20f0
movq (%r12), %rsi
movq %rax, %rdi
callq 0x21d0
leaq 0x1ecf(%rip), %rsi      # 0x61ba
movq %rax, %rdi
callq 0x21d0
movq %rax, %rdi
callq 0x20f0
leaq 0x1efc(%rip), %rsi      # 0x61fe
movq %rbx, %rdi
callq 0x21d0
movq %rax, %rdi
callq 0x20f0
movq (%r12), %rsi
movq %rbx, %rdi
callq 0x21d0
leaq 0x1f00(%rip), %rsi      # 0x6225
movq %rax, %rdi
callq 0x21d0
movq %rax, %rdi
callq 0x20f0
movq %rbx, %rdi
callq 0x20f0
leaq 0x1f41(%rip), %rsi      # 0x6285
movq %rbx, %rdi
callq 0x21d0
movq %rax, %rdi
callq 0x20f0
leaq 0x1f51(%rip), %rsi      # 0x62ac
movq %rbx, %rdi
callq 0x21d0
movq %rax, %rdi
callq 0x20f0
leaq 0x1f68(%rip), %rsi      # 0x62da
movq %rbx, %rdi
callq 0x21d0
movq %rax, %rdi
callq 0x20f0
leaq 0x1f74(%rip), %rsi      # 0x62fd
movq %rbx, %rdi
callq 0x21d0
movq %rax, %rdi
callq 0x20f0
leaq 0x1f87(%rip), %rsi      # 0x6327
movq %rbx, %rdi
callq 0x21d0
movq %rax, %rdi
callq 0x20f0
movq %rbx, %rdi
callq 0x20f0
leaq 0x1f90(%rip), %rsi      # 0x634f
movq %rbx, %rdi
callq 0x21d0
movq %rax, %rdi
callq 0x20f0
leaq 0x202e(%rip), %rsi      # 0x6404
movq %rbx, %rdi
callq 0x21d0
movq %rax, %rdi
callq 0x20f0
leaq 0x20df(%rip), %rsi      # 0x64cc
movq %rbx, %rdi
callq 0x21d0
movq %rax, %rdi
callq 0x20f0
leaq 0x2171(%rip), %rsi      # 0x6575
movq %rbx, %rdi
callq 0x21d0
movq %rax, %rdi
callq 0x20f0
xorl %edi, %edi
callq 0x2230
movq 0x4bae(%rip), %rdi      # 0x8fd0
leaq 0x22c3(%rip), %rsi      # 0x66ec
movl $0x15, %edx
callq 0x2210
movq 0xe0(%rsp), %rsi
movq 0xe8(%rsp), %rdx
movq 0x4b86(%rip), %rdi      # 0x8fd0
callq 0x2210
movq %rax, %rdi
callq 0x20f0
movq 0x30(%rsp), %rdi
movb $0x1, %bpl
cmpq %rdi, 0x38(%rsp)
je 0x44f7
movb $0x1, %bpl
movl $0x1, %r14d
leaq 0x2288(%rip), %rbx      # 0x6702
leaq 0x2289(%rip), %r15      # 0x670a
xorl %r12d, %r12d
shlq $0x5, %r12
addq %r12, %rdi
movl $0x7, %ecx
movq %rbx, %rsi
xorl %edx, %edx
callq 0x2320
movq %rax, %r13
addq 0x30(%rsp), %r12
movl $0x4, %ecx
movq %r12, %rdi
movq %r15, %rsi
movq %rax, %rdx
callq 0x2320
cmpq $-0x1, %r13
setne %cl
cmpq $-0x1, %rax
setne %dl
andb %cl, %dl
cmpq %r13, %rax
setae %al
movzbl %bpl, %ebp
testb %dl, %al
movl $0x0, %eax
cmovel %eax, %ebp
je 0x44f7
movl %r14d, %r12d
movq 0x30(%rsp), %rdi
movq 0x38(%rsp), %rax
subq %rdi, %rax
sarq $0x5, %rax
incl %r14d
cmpq %r12, %rax
ja 0x4484
leaq 0x110(%rsp), %rdi
callq 0x2300
leaq 0x110(%rsp), %rdi
leaq 0xe0(%rsp), %rsi
movl $0x10, %edx
callq 0x20e0
testb $0x1, %bpl
je 0x47c4
cmpl $0x0, 0x8(%rsp)
jle 0x48c4
movq 0x8(%rsp), %rax
andl $0x7fffffff, %eax       # imm = 0x7FFFFFFF
movq %rax, 0x8(%rsp)
movl $0x1, %eax
movq %rax, 0x28(%rsp)
movl $0x20, %eax
movq %rax, 0x20(%rsp)
xorl %ebp, %ebp
leaq 0x21fc(%rip), %r12      # 0x675b
movq 0x8(%rsp), %r14
movq %rbp, %r13
shlq $0x5, %r13
movq 0x30(%rsp), %rdi
addq %r13, %rdi
movl $0x7, %ecx
leaq 0x2183(%rip), %rsi      # 0x6702
xorl %edx, %edx
callq 0x2320
movq %rax, %rbx
movq 0x30(%rsp), %rdi
addq %r13, %rdi
movl $0x4, %ecx
leaq 0x216d(%rip), %rsi      # 0x670a
movq %rax, %rdx
callq 0x2320
addq 0x30(%rsp), %r13
subq %rbx, %rax
addq $0x7, %rbx
leaq -0x7(%rax), %rcx
leaq 0x50(%rsp), %rdi
movq %r13, %rsi
movq %rbx, %rdx
callq 0x2200
leaq 0x1(%rbp), %rax
movq %rax, 0x18(%rsp)
cmpq %r14, %rax
jae 0x46dc
movq 0x20(%rsp), %r15
movq 0x28(%rsp), %r13
movq 0x30(%rsp), %rdi
addq %r15, %rdi
movl $0x7, %ecx
leaq 0x210d(%rip), %rsi      # 0x6702
xorl %edx, %edx
callq 0x2320
movq %rax, %rbx
movq 0x30(%rsp), %rdi
addq %r15, %rdi
movl $0x4, %ecx
leaq 0x20f7(%rip), %rsi      # 0x670a
movq %rax, %rdx
callq 0x2320
movq 0x30(%rsp), %rsi
addq %r15, %rsi
subq %rbx, %rax
addq $0x7, %rbx
leaq -0x7(%rax), %rcx
leaq 0xc0(%rsp), %rdi
movq %rbx, %rdx
callq 0x2200
movq 0x50(%rsp), %rsi
movq 0x58(%rsp), %rdx
leaq 0x110(%rsp), %rdi
callq 0x2210
movq %rax, %rbx
movl $0x1, %edx
movq %rax, %rdi
movq %r12, %rsi
callq 0x2210
movq 0xc0(%rsp), %rsi
movq 0xc8(%rsp), %rdx
movq %rbx, %rdi
callq 0x2210
movq %rax, %rbx
movl $0x1, %edx
movq %rax, %rdi
movq %r12, %rsi
callq 0x2210
leaq 0x70(%rsp), %rdi
movl %ebp, %esi
movl %r13d, %edx
callq 0x25c6
movq %rbx, %rdi
callq 0x22c0
movq %rax, %rdi
callq 0x20f0
movq 0xc0(%rsp), %rdi
leaq 0xd0(%rsp), %rax
cmpq %rax, %rdi
je 0x46cc
callq 0x21b0
incq %r13
addq $0x20, %r15
cmpq %r13, %r14
jne 0x45e1
movq 0x50(%rsp), %rdi
leaq 0x60(%rsp), %rax
cmpq %rax, %rdi
je 0x46f0
callq 0x21b0
incq 0x28(%rsp)
addq $0x20, 0x20(%rsp)
movq 0x18(%rsp), %rax
movq %rax, %rbp
cmpq 0x8(%rsp), %rax
jne 0x4564
jmp 0x48c4
movq 0x48d6(%rip), %rdi      # 0x8ff0
leaq 0x1fee(%rip), %rsi      # 0x670f
movl $0xc, %edx
callq 0x2210
movq 0x48be(%rip), %rdi      # 0x8ff0
movl 0x14(%rsp), %esi
callq 0x2310
movq %rax, %rbx
leaq 0x1fd7(%rip), %rsi      # 0x671c
movl $0xd, %edx
movq %rax, %rdi
callq 0x2210
movq %rbx, %rdi
movl %r14d, %esi
callq 0x2310
movq %rax, %rbx
leaq 0x1fc3(%rip), %rsi      # 0x672a
movl $0xb, %edx
movq %rax, %rdi
callq 0x2210
movq %rbx, %rdi
callq 0x20f0
jmp 0x47ba
movq 0x486b(%rip), %rdi      # 0x8ff0
leaq 0x1f28(%rip), %rsi      # 0x66b4
movl $0x12, %edx
callq 0x2210
movq 0x110(%rsp), %rsi
movq 0x118(%rsp), %rdx
movq 0x4843(%rip), %rdi      # 0x8ff0
callq 0x2210
movq %rax, %rdi
callq 0x20f0
movl $0xffffffff, %edi       # imm = 0xFFFFFFFF
callq 0x2230
cmpl $0x0, 0x8(%rsp)
jle 0x48c4
movq 0x8(%rsp), %rax
andl $0x7fffffff, %eax       # imm = 0x7FFFFFFF
movq %rax, 0x8(%rsp)
movl $0x1, %eax
movq %rax, 0x28(%rsp)
movl $0x28, %eax
movq %rax, 0x20(%rsp)
xorl %r14d, %r14d
leaq 0x1f5f(%rip), %r15      # 0x675b
leaq 0x1(%r14), %rax
movq %rax, 0x18(%rsp)
cmpq 0x8(%rsp), %rax
jae 0x48a9
movq %r14, %r13
shlq $0x5, %r13
movq 0x20(%rsp), %r12
movq 0x28(%rsp), %rbp
movq 0x30(%rsp), %rax
movq (%rax,%r13), %rsi
movq 0x8(%rax,%r13), %rdx
leaq 0x110(%rsp), %rdi
callq 0x2210
movq %rax, %rbx
movl $0x1, %edx
movq %rax, %rdi
movq %r15, %rsi
callq 0x2210
movq 0x30(%rsp), %rax
movq -0x8(%rax,%r12), %rsi
movq (%rax,%r12), %rdx
movq %rbx, %rdi
callq 0x2210
movq %rax, %rbx
movl $0x1, %edx
movq %rax, %rdi
movq %r15, %rsi
callq 0x2210
leaq 0x70(%rsp), %rdi
movl %r14d, %esi
movl %ebp, %edx
callq 0x25c6
movq %rbx, %rdi
callq 0x22c0
movq %rax, %rdi
callq 0x20f0
incq %rbp
addq $0x20, %r12
cmpq %rbp, 0x8(%rsp)
jne 0x4821
incq 0x28(%rsp)
addq $0x20, 0x20(%rsp)
movq 0x18(%rsp), %r14
cmpq 0x8(%rsp), %r14
jne 0x47fc
leaq 0x110(%rsp), %rdi
callq 0x2270
jmp 0x4414
jmp 0x4912
movq %rax, %r14
jmp 0x48fa
movq %rax, %r14
movq 0xc0(%rsp), %rdi
leaq 0xd0(%rsp), %rax
cmpq %rax, %rdi
je 0x48fa
callq 0x21b0
movq 0x50(%rsp), %rdi
leaq 0x60(%rsp), %rax
cmpq %rax, %rdi
je 0x4915
callq 0x21b0
jmp 0x4915
jmp 0x4912
movq %rax, %r14
leaq 0x110(%rsp), %rdi
callq 0x2290
jmp 0x49b9
jmp 0x499f
jmp 0x492d
jmp 0x4992
movq %rax, %r14
movq 0x110(%rsp), %rdi
cmpq %rbx, %rdi
jne 0x49d0
jmp 0x49d5
jmp 0x4992
jmp 0x4958
jmp 0x4958
jmp 0x498d
jmp 0x49a4
jmp 0x495d
jmp 0x4958
jmp 0x4958
jmp 0x499f
movq %rax, %r14
jmp 0x4974
movq %rax, %r14
movq 0x50(%rsp), %rdi
leaq 0x60(%rsp), %rax
cmpq %rax, %rdi
je 0x4974
callq 0x21b0
movq 0x110(%rsp), %rdi
leaq 0x120(%rsp), %rax
cmpq %rax, %rdi
jne 0x49d0
jmp 0x49d5
jmp 0x49a4
movq %rax, %r14
jmp 0x49c3
movq %rax, %r14
jmp 0x49d5
jmp 0x49a4
jmp 0x49a4
jmp 0x49a4
jmp 0x49a4
movq %rax, %r14
jmp 0x49b9
movq %rax, %r14
movq 0x110(%rsp), %rdi
testq %rdi, %rdi
je 0x49b9
callq 0x21b0
leaq 0x70(%rsp), %rdi
callq 0x25b0
movq 0xa0(%rsp), %rdi
testq %rdi, %rdi
je 0x49d5
callq 0x21b0
movq 0xe0(%rsp), %rdi
leaq 0xf0(%rsp), %rax
cmpq %rax, %rdi
je 0x49ef
callq 0x21b0
leaq 0x30(%rsp), %rdi
callq 0x4a4c
leaq 0x80(%rsp), %rdi
callq 0x4a4c
movq %r14, %rdi
callq 0x2330