// File: /workspace/github_c_makefile_star2_O2/asford[P]tmalign/TMalign.cpp
// Function: main
int main(int argc, char *argv[])
{
	strcpy(version, "20120126");

    if (argc < 2) 
    {
        print_help(argv[0]);        
    } 
	
	
	clock_t t1, t2;
	t1 = clock();

    /*********************************************************************************/
	/*                                get argument                                   */ 
    /*********************************************************************************/
    char xname[MAXLEN], yname[MAXLEN],  Lnorm_ave[MAXLEN];
	bool A_opt, B_opt, h_opt=false;
	A_opt = B_opt = o_opt = a_opt = u_opt = d_opt = v_opt = false;

	for(int i = 0; i < argc; i++)
	{
		if ( !strcmp(argv[i],"-B") && i < argc ) { strcpy(xname,    argv[i+1]);      B_opt = true; }
		if ( !strcmp(argv[i],"-A") && i < argc ) { strcpy(yname,    argv[i+1]);      A_opt = true; }
		if ( !strcmp(argv[i],"-o") && i < argc ) { strcpy(out_reg,  argv[i+1]);      o_opt = true; }
		if ( !strcmp(argv[i],"-u") && i < argc ) { Lnorm_ass      = atof(argv[i+1]); u_opt = true; }
		if ( !strcmp(argv[i],"-a") && i < argc ) { strcpy(Lnorm_ave, argv[i+1]);     a_opt = true; }
		if ( !strcmp(argv[i],"-d") && i < argc ) { d0_scale        = atof(argv[i+1]); d_opt = true; }
		if ( !strcmp(argv[i],"-v") ) { v_opt = true; }
		if ( !strcmp(argv[i],"-h") ) { h_opt = true; }
	}


	if(!B_opt || !A_opt)
	{

		if( h_opt )
		{
			print_help(argv[0]);    			
		}
		
		if(v_opt)
		{
			cout <<endl;
			cout << " *****************************************************************************" << endl
				 << " * TM-align (Version "<< version <<"): A protein structural alignment algorithm     *" << endl
				 << " * Reference: Y Zhang and J Skolnick, Nucl Acids Res 33, 2302-9 (2005)       *" << endl
				 << " * Please email your comments and suggestions to Yang Zhang (zhng@umich.edu) *" << endl
				 << " *****************************************************************************" << endl;	
			exit(EXIT_FAILURE);
		}
	}

	if( !B_opt )
	{
		cout << "Please provide structure B" << endl;
		exit(EXIT_FAILURE);
	}		
	if( !A_opt )
	{
		cout << "Please provide structure A" << endl;
		exit(EXIT_FAILURE);
	}


	if( a_opt )
	{
		if(!strcmp(Lnorm_ave, "T"))
		{
		}
		else if(!strcmp(Lnorm_ave, "F"))
		{
			a_opt=false;
		}
		else
		{
			cout << "Wrong value for option -a!  It should be T or F" << endl;
			exit(EXIT_FAILURE);
		}
	}
	if( u_opt )
	{
		if(Lnorm_ass<=0)
		{
			cout << "Wrong value for option -u!  It should be >0" << endl;
			exit(EXIT_FAILURE);
		}
	}
	if( d_opt )
	{
		if(d0_scale<=0)
		{
			cout << "Wrong value for option -d!  It should be >0" << endl;
			exit(EXIT_FAILURE);
		}
	}














    /*********************************************************************************/
	/*                                load data                                      */ 
    /*********************************************************************************/
    load_PDB_allocate_memory(xname, yname);



    

    /*********************************************************************************/
	/*                                parameter set                                  */ 
    /*********************************************************************************/
	parameter_set4search(xlen, ylen);          //please set parameters in the function
    int simplify_step     = 40;               //for similified search engine
    int score_sum_method  = 8;                //for scoring method, whether only sum over pairs with dis<score_d8
        
	int i;
    int *invmap0          = new int[ylen+1]; 
    int *invmap           = new int[ylen+1]; 
    double TM, TMmax=-1;
	for(i=0; i<ylen; i++)
	{
		invmap0[i]=-1;
	}	


	double ddcc=0.4;
	if(Lnorm <= 40) ddcc=0.1;   //Lnorm was setted in parameter_set4search
      

    /*********************************************************************************/
	/*         get initial alignment with gapless threading                          */ 
    /*********************************************************************************/
    get_initial(xa, ya, xlen, ylen, invmap0);
    //find the max TMscore for this initial alignment with the simplified search_engin
    TM=detailed_search(xa, ya, xlen, ylen, invmap0, t, u, simplify_step, score_sum_method);
	if(TM>TMmax)
    {
        TMmax=TM;
    }           
    //run dynamic programing iteratively to find the best alignment
    TM=DP_iter(xa, ya, xlen, ylen, t, u, invmap, 0, 2, 30);
    if(TM>TMmax)
    {        
        TMmax=TM;
        for(int i=0; i<ylen; i++)
        {
            invmap0[i]=invmap[i];
        }
    }
	
    
	


    /*********************************************************************************/
	/*         get initial alignment based on secondary structure                    */ 
    /*********************************************************************************/	
	get_initial_ss(xa, ya, xlen, ylen, invmap);
    TM=detailed_search(xa, ya, xlen, ylen, invmap, t, u, simplify_step, score_sum_method);
    if(TM>TMmax)
    {
        TMmax=TM;
        for(int i=0; i<ylen; i++)
        {
            invmap0[i]=invmap[i];
        }
    } 
    if(TM > TMmax*0.2)
    {
        TM=DP_iter(xa, ya, xlen, ylen, t, u, invmap, 0, 2, 30);
        if(TM>TMmax)
        {
            TMmax=TM;
            for(int i=0; i<ylen; i++)
            {
                invmap0[i]=invmap[i];
            }
        }   
    }
	//output_align(invmap0, ylen);


	
    /*********************************************************************************/
	/*         get initial alignment based on local superposition                    */ 
    /*********************************************************************************/	
	//=initial5 in original TM-align
    if(get_initial_local(xa, ya, xlen, ylen, invmap))
	{		
		TM=detailed_search(xa, ya, xlen, ylen, invmap, t, u, simplify_step, score_sum_method);
		if(TM>TMmax)
		{
			TMmax=TM;
			for(int i=0; i<ylen; i++)
			{
				invmap0[i]=invmap[i];
			}
		} 
		if(TM > TMmax*ddcc)
		{
			TM=DP_iter(xa, ya, xlen, ylen, t, u, invmap, 0, 2, 2);
			if(TM>TMmax)
			{
				TMmax=TM;
				for(int i=0; i<ylen; i++)
				{
					invmap0[i]=invmap[i];
				}
			}   
		}
		//output_align(invmap0, ylen);
	}    
	else
	{
		cout << endl << endl << "Warning: initial alignment from local superposition fail!" << endl << endl <<endl;		
	}
	
	



    /*********************************************************************************/
	/*    get initial alignment based on previous alignment+secondary structure      */ 
    /*********************************************************************************/	
	//=initial3 in original TM-align
    get_initial_ssplus(xa, ya, xlen, ylen, invmap0, invmap);
    TM=detailed_search(xa, ya, xlen, ylen, invmap, t, u, simplify_step, score_sum_method);
    if(TM>TMmax)
    {
        TMmax=TM;
        for(i=0; i<ylen; i++)
        {
            invmap0[i]=invmap[i];
        }
    } 
    if(TM > TMmax*ddcc)
    {
        TM=DP_iter(xa, ya, xlen, ylen, t, u, invmap, 0, 2, 30);
        if(TM>TMmax)
        {
            TMmax=TM;
            for(i=0; i<ylen; i++)
            {
                invmap0[i]=invmap[i];
            }
        }   
    }
	//output_align(invmap0, ylen);   
      
	


	

    /*********************************************************************************/
	/*        get initial alignment based on fragment gapless threading              */ 
    /*********************************************************************************/	    
	//=initial4 in original TM-align
	get_initial_fgt(xa, ya, xlen, ylen, xresno, yresno, invmap);
    TM=detailed_search(xa, ya, xlen, ylen, invmap, t, u, simplify_step, score_sum_method);	
    if(TM>TMmax)
    {
        TMmax=TM;
        for(i=0; i<ylen; i++)
        {
            invmap0[i]=invmap[i];
        }
    } 
    if(TM > TMmax*ddcc)
    {
        TM=DP_iter(xa, ya, xlen, ylen, t, u, invmap, 1, 2, 2);
        if(TM>TMmax)
        {         
            TMmax=TM;
            for(i=0; i<ylen; i++)
            {
                invmap0[i]=invmap[i];
            }
        }   
    } 
	//output_align(invmap0, ylen); 






	
    //*********************************************************************************//
    //     The alignment will not be changed any more in the following                 //
    //*********************************************************************************//
	//check if the initial alignment is generated approately	
	bool flag=false;
	for(i=0; i<ylen; i++)
	{
		if(invmap0[i]>=0)
		{
			flag=true;
			break;			
		}			
	}		
	if(!flag) 
	{
		cout << "There is no alignment between the two proteins!" << endl;
		cout << "Program stop with no result!" << endl;
		return 1;
	}
	//cout << "final alignment" << endl;
	//output_align(invmap0, ylen);










    //*********************************************************************************//
    //       Detailed TMscore search engine  --> prepare for final TMscore             //
    //*********************************************************************************//       
    //run detailed TMscore search engine for the best alignment, and 
	//extract the best rotation matrix (t, u) for the best alginment
    simplify_step=1;
    score_sum_method=8;
    TM=detailed_search(xa, ya, xlen, ylen, invmap0, t, u, simplify_step, score_sum_method);

	//select pairs with dis<d8 for final TMscore computation and output alignment
	int n_ali8, k=0;
	int n_ali=0;
	int *m1, *m2;
	double d;
	m1=new int[xlen]; //alignd index in x
	m2=new int[ylen]; //alignd index in y
	do_rotation(xa, xt, xlen, t, u);
	k=0;
    for(int j=0; j<ylen; j++)
    {
        i=invmap0[j];
        if(i>=0)//aligned
        {
			n_ali++;        
            d=sqrt(dist(&xt[i][0], &ya[j][0]));
			if(d <= score_d8)
			{
				m1[k]=i;
				m2[k]=j;

				xtm[k][0]=xa[i][0];
                xtm[k][1]=xa[i][1];
                xtm[k][2]=xa[i][2];
                    
                ytm[k][0]=ya[j][0];
                ytm[k][1]=ya[j][1];
                ytm[k][2]=ya[j][2];								
				
				k++;
			}
		}
	}
	n_ali8=k;







    //*********************************************************************************//
    //                               Final TMscore                                     //
    //                     Please set parameters for output                            //
    //*********************************************************************************//
    double rmsd, TM1, TM2;
	double d0_out=5.0;  
    simplify_step=1;
    score_sum_method=0;

	double t0[3], u0[3][3];
	double d0_0, TM_0;
	double Lnorm_0=ylen;
	
	
	//normalized by length of structure A
	parameter_set4final(Lnorm_0);
	d0A=d0;
	d0_0=d0A;
	TM1=TMscore8_search(xtm, ytm, n_ali8, t0, u0, simplify_step, score_sum_method, &rmsd);
	TM_0=TM1;

	//normalized by length of structure B
	parameter_set4final(xlen+0.0);
	d0B=d0;
	TM2=TMscore8_search(xtm, ytm, n_ali8, t, u, simplify_step, score_sum_method, &rmsd);




	if(a_opt)
	{
		//normalized by average length of structures A, B
		Lnorm_0=(xlen+ylen)*0.5;
		parameter_set4final(Lnorm_0);
		d0a=d0;
		d0_0=d0a;
		TM3=TMscore8_search(xtm, ytm, n_ali8, t, u, simplify_step, score_sum_method, &rmsd);
		TM_0=TM3;
	}
	if(u_opt)
	{	
		//normalized by user assigned length		
		parameter_set4final(Lnorm_ass);		
		d0u=d0;		
		d0_0=d0u;
		Lnorm_0=Lnorm_ass;
		TM4=TMscore8_search(xtm, ytm, n_ali8, t, u, simplify_step, score_sum_method, &rmsd);	
		TM_0=TM4;
	}
	if(d_opt)
	{	
		//scaled by user assigned d0
		parameter_set4scale(ylen, d0_scale);
		d0_out=d0_scale;
		d0_0=d0_scale;
		//Lnorm_0=ylen;
		Lnorm_d0=Lnorm_0;
		TM5=TMscore8_search(xtm, ytm, n_ali8, t, u, simplify_step, score_sum_method, &rmsd);	
		TM_0=TM5;
	}

   
        
	output_results(xname, yname, xlen, ylen, t0, u0, TM1, TM2, rmsd, d0_out, m1, m2, n_ali8, n_ali, TM_0, Lnorm_0, d0_0);
                    
 









    //*********************************************************************************//
    //                            Done! Free memory                                    //
    //*********************************************************************************//           
    free_memory();
    delete [] invmap0;
    delete [] invmap;
	delete [] m1;
	delete [] m2;


    t2 = clock();    
    float diff = ((float)t2 - (float)t1)/CLOCKS_PER_SEC;
    printf("\nTotal running time is %5.2f seconds\n", diff);        

 	return 0;	
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x7608, %rsp           # imm = 0x7608
movq %rsi, %r14
movabsq $0x3632313032313032, %rax # imm = 0x3632313032313032
movq %rax, 0x1f850f(%rip)    # 0x602550
movb $0x0, 0x1f8510(%rip)    # 0x602558
cmpl $0x1, %edi
jle 0x40adc4
movl %edi, %ebx
callq 0x53fe60
movq %rax, 0x48(%rsp)
xorl %ebp, %ebp
movb %bpl, 0x1fad86(%rip)    # 0x604dec
movb %bpl, 0x1fad7e(%rip)    # 0x604deb
movb %bpl, 0x1fad76(%rip)    # 0x604dea
movb %bpl, 0x1fad6e(%rip)    # 0x604de9
movb %bpl, 0x1fad66(%rip)    # 0x604de8
movl %ebx, %r12d
movq $0x0, 0x18(%rsp)
movq $0x0, 0x28(%rsp)
movq $0x0, 0x20(%rsp)
xorl %r15d, %r15d
xorl %ebx, %ebx
movq $0x0, (%rsp)
movq $0x0, 0x8(%rsp)
cmpq %r15, %r12
je 0x40a241
movq (%r14,%r15,8), %r13
cmpb $0x2d, (%r13)
jne 0x40a239
cmpb $0x42, 0x1(%r13)
jne 0x40a0ff
cmpb $0x0, 0x2(%r13)
jne 0x40a0ff
movq 0x8(%r14,%r15,8), %rsi
leaq 0x27e0(%rsp), %rdi
callq 0x401080
movb $0x1, %al
movq %rax, (%rsp)
cmpb $0x2d, (%r13)
jne 0x40a239
cmpb $0x41, 0x1(%r13)
jne 0x40a131
cmpb $0x0, 0x2(%r13)
jne 0x40a131
movq 0x8(%r14,%r15,8), %rsi
leaq 0xd0(%rsp), %rdi
callq 0x401080
movb $0x1, %al
movq %rax, 0x8(%rsp)
cmpb $0x2d, (%r13)
jne 0x40a239
cmpb $0x6f, 0x1(%r13)
jne 0x40a166
cmpb $0x0, 0x2(%r13)
jne 0x40a166
movq 0x8(%r14,%r15,8), %rsi
leaq 0x1f8555(%rip), %rdi    # 0x6026a0
callq 0x401080
movb $0x1, 0x1fac91(%rip)    # 0x604de8
movq (%r14,%r15,8), %r13
cmpb $0x2d, (%r13)
jne 0x40a239
cmpb $0x75, 0x1(%r13)
jne 0x40a19f
cmpb $0x0, 0x2(%r13)
jne 0x40a19f
movq 0x8(%r14,%r15,8), %rdi
callq 0x4cc820
movsd %xmm0, 0x1fac2a(%rip)   # 0x604db0
movb $0x1, 0x1fac5d(%rip)    # 0x604dea
movb $0x1, %al
movq %rax, 0x18(%rsp)
cmpb $0x2d, (%r13)
jne 0x40a239
cmpb $0x61, 0x1(%r13)
jne 0x40a1d4
cmpb $0x0, 0x2(%r13)
jne 0x40a1d4
movq 0x8(%r14,%r15,8), %rsi
leaq 0x4ef0(%rsp), %rdi
callq 0x401080
movb $0x1, 0x1fac23(%rip)    # 0x604de9
movb $0x1, %al
movq %rax, 0x28(%rsp)
cmpb $0x2d, (%r13)
jne 0x40a239
cmpb $0x64, 0x1(%r13)
jne 0x40a205
cmpb $0x0, 0x2(%r13)
jne 0x40a205
movq 0x8(%r14,%r15,8), %rdi
callq 0x4cc820
movsd %xmm0, 0x1fabcc(%rip)   # 0x604dc0
movb $0x1, 0x1fabf0(%rip)    # 0x604deb
movb $0x1, %bpl
cmpb $0x2d, (%r13)
jne 0x40a239
cmpb $0x76, 0x1(%r13)
jne 0x40a228
cmpb $0x0, 0x2(%r13)
jne 0x40a228
movb $0x1, 0x1fabd2(%rip)    # 0x604dec
movb $0x1, %al
movq %rax, 0x20(%rsp)
cmpb $0x2d, (%r13)
jne 0x40a239
cmpb $0x68, 0x1(%r13)
jne 0x40a239
cmpb $0x0, 0x2(%r13)
sete %al
orb %al, %bl
incq %r15
jmp 0x40a0b6
movq (%rsp), %rcx
testb $0x1, %cl
movq 0x8(%rsp), %rax
je 0x40a253
testb $0x1, %al
jne 0x40a278
testb $0x1, %bl
jne 0x40adc4
testb $0x1, 0x20(%rsp)
jne 0x40adf2
testb $0x1, %cl
je 0x40ae86
testb $0x1, %al
je 0x40ae96
movzwl 0x4ef0(%rsp), %eax
cmpw $0x54, %ax
setne %cl
movq 0x28(%rsp), %rdx
andb %cl, %dl
cmpb $0x1, %dl
jne 0x40a2a4
cmpw $0x46, %ax
jne 0x40aea6
movb $0x0, 0x1fab45(%rip)    # 0x604de9
testb $0x1, 0x18(%rsp)
je 0x40a2c1
movsd 0x1faafd(%rip), %xmm0   # 0x604db0
xorpd %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jbe 0x40adcc
testb $0x1, %bpl
je 0x40a2dd
movsd 0x1faaf1(%rip), %xmm0   # 0x604dc0
xorpd %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jbe 0x40addf
leaq 0x27e0(%rsp), %rdi
leaq 0xd0(%rsp), %rsi
callq 0x406a89
movl 0x1f82b8(%rip), %edi    # 0x6025b0
movl 0x1f82b6(%rip), %esi    # 0x6025b4
callq 0x409ecf
movslq 0x1f82aa(%rip), %r12    # 0x6025b4
cmpq $-0x1, %r12
leaq 0x4(,%r12,4), %rbx
pushq $-0x1
popq %rax
cmovlq %rax, %rbx
movq %rbx, %rdi
callq 0x40be00
movq %rax, %r14
movq %rbx, %rdi
callq 0x40be00
movq %rax, %r15
xorl %eax, %eax
testl %r12d, %r12d
movl $0x0, %ecx
cmovgl %r12d, %ecx
cmpq %rax, %rcx
je 0x40a350
orl $-0x1, (%r14,%rax,4)
incq %rax
jmp 0x40a341
movsd 0x178d98(%rip), %xmm0   # 0x5830f0
xorl %r13d, %r13d
ucomisd 0x1f820d(%rip), %xmm0   # 0x602570
setb %bpl
movq 0x1f8252(%rip), %rdi    # 0x6025c0
movq 0x1f8253(%rip), %rsi    # 0x6025c8
movl 0x1f8235(%rip), %edx    # 0x6025b0
movl %r12d, %ecx
movq %r14, %r8
callq 0x407963
movq 0x1f8233(%rip), %rdi    # 0x6025c0
movq 0x1f8234(%rip), %rsi    # 0x6025c8
movl 0x1f821a(%rip), %ecx    # 0x6025b4
subq $0x8, %rsp
leaq 0x1f82ab(%rip), %r12    # 0x602650
leaq 0x1f8284(%rip), %rbx    # 0x602630
movq %r14, %r8
movq %rbx, %r9
pushq $0x8
pushq $0x28
pushq %r12
callq 0x4073a8
addq $0x20, %rsp
maxsd 0x178c67(%rip), %xmm0   # 0x583030
movsd %xmm0, (%rsp)
movq 0x1f81eb(%rip), %rdi    # 0x6025c0
movq 0x1f81ec(%rip), %rsi    # 0x6025c8
movl 0x1f81ce(%rip), %edx    # 0x6025b0
movl 0x1f81cc(%rip), %ecx    # 0x6025b4
movq %rbx, %r8
movq %r12, %r9
pushq $0x1e
pushq $0x2
pushq $0x0
pushq %r15
callq 0x408a57
movsd 0x20(%rsp), %xmm1
addq $0x20, %rsp
ucomisd %xmm1, %xmm0
movl 0x1f81a5(%rip), %ecx    # 0x6025b4
jbe 0x40a433
xorl %eax, %eax
testl %ecx, %ecx
movl $0x0, %edx
cmovgl %ecx, %edx
cmpq %rax, %rdx
je 0x40a42f
movl (%r15,%rax,4), %esi
movl %esi, (%r14,%rax,4)
incq %rax
jmp 0x40a41d
movapd %xmm0, %xmm1
movsd %xmm1, (%rsp)
movb %bpl, %r13b
movq 0x1f817e(%rip), %rdi    # 0x6025c0
movq 0x1f817f(%rip), %rsi    # 0x6025c8
movl 0x1f8161(%rip), %edx    # 0x6025b0
movq %r15, %r8
callq 0x407e63
movq 0x1f8162(%rip), %rdi    # 0x6025c0
movq 0x1f8163(%rip), %rsi    # 0x6025c8
movl 0x1f8149(%rip), %ecx    # 0x6025b4
subq $0x8, %rsp
leaq 0x1f81ba(%rip), %r9     # 0x602630
movq %r15, %r8
pushq $0x8
pushq $0x28
pushq %r12
callq 0x4073a8
movsd 0x20(%rsp), %xmm2
addq $0x20, %rsp
ucomisd %xmm2, %xmm0
movl 0x1f811c(%rip), %ecx    # 0x6025b4
jbe 0x40a4bc
xorl %eax, %eax
testl %ecx, %ecx
movl $0x0, %edx
cmovgl %ecx, %edx
cmpq %rax, %rdx
je 0x40a4b8
movl (%r15,%rax,4), %esi
movl %esi, (%r14,%rax,4)
incq %rax
jmp 0x40a4a6
movapd %xmm0, %xmm2
leaq 0x178c8d(%rip), %rbx    # 0x583150
movsd 0x178c2d(%rip), %xmm1   # 0x5830f8
mulsd %xmm2, %xmm1
ucomisd %xmm1, %xmm0
movsd %xmm2, (%rsp)
jbe 0x40a53d
movq 0x1f80df(%rip), %rdi    # 0x6025c0
movq 0x1f80e0(%rip), %rsi    # 0x6025c8
movl 0x1f80c2(%rip), %edx    # 0x6025b0
leaq 0x1f813b(%rip), %r8     # 0x602630
leaq 0x1f8154(%rip), %r9     # 0x602650
pushq $0x1e
pushq $0x2
pushq $0x0
pushq %r15
callq 0x408a57
addq $0x20, %rsp
ucomisd (%rsp), %xmm0
movl 0x1f809c(%rip), %ecx    # 0x6025b4
jbe 0x40a53d
xorl %eax, %eax
testl %ecx, %ecx
movl $0x0, %edx
cmovgl %ecx, %edx
cmpq %rax, %rdx
je 0x40a538
movl (%r15,%rax,4), %esi
movl %esi, (%r14,%rax,4)
incq %rax
jmp 0x40a526
movsd %xmm0, (%rsp)
movsd (%rbx,%r13,8), %xmm0
movsd %xmm0, 0x8(%rsp)
movq 0x1f8070(%rip), %rdi    # 0x6025c0
movq 0x1f8071(%rip), %rsi    # 0x6025c8
movl 0x1f8053(%rip), %edx    # 0x6025b0
movq %r15, %r8
callq 0x407ec2
pushq $0x2
popq %rbx
testb %al, %al
je 0x40a5cc
movq 0x1f804d(%rip), %rdi    # 0x6025c0
movq 0x1f804e(%rip), %rsi    # 0x6025c8
movl 0x1f8034(%rip), %ecx    # 0x6025b4
subq $0x8, %rsp
leaq 0x1f80a5(%rip), %r9     # 0x602630
movq %r15, %r8
pushq $0x8
pushq $0x28
pushq %r12
callq 0x4073a8
addq $0x20, %rsp
movsd (%rsp), %xmm2
ucomisd %xmm2, %xmm0
movl 0x1f8008(%rip), %ecx    # 0x6025b4
jbe 0x40a613
xorl %eax, %eax
testl %ecx, %ecx
movl $0x0, %edx
cmovgl %ecx, %edx
cmpq %rax, %rdx
je 0x40a60f
movl (%r15,%rax,4), %esi
movl %esi, (%r14,%rax,4)
incq %rax
jmp 0x40a5ba
movq $0x605d20, %rdi         # imm = 0x605D20
callq 0x473f90
movq %rax, %rdi
callq 0x473f90
leaq 0x179758(%rip), %rsi    # 0x583d3f
movq %rax, %rdi
callq 0x4746b0
movq %rax, %rdi
callq 0x473f90
movq %rax, %rdi
callq 0x473f90
movq %rax, %rdi
callq 0x473f90
movl 0x1f7fa7(%rip), %ecx    # 0x6025b4
jmp 0x40a68d
movapd %xmm0, %xmm2
movapd %xmm2, %xmm1
mulsd 0x8(%rsp), %xmm1
ucomisd %xmm1, %xmm0
movsd %xmm2, (%rsp)
jbe 0x40a68d
movq 0x1f7f91(%rip), %rdi    # 0x6025c0
movq 0x1f7f92(%rip), %rsi    # 0x6025c8
movl 0x1f7f74(%rip), %edx    # 0x6025b0
leaq 0x1f7fed(%rip), %r8     # 0x602630
leaq 0x1f8006(%rip), %r9     # 0x602650
pushq %rbx
pushq %rbx
pushq $0x0
pushq %r15
callq 0x408a57
addq $0x20, %rsp
movsd (%rsp), %xmm1
ucomisd %xmm1, %xmm0
movl 0x1f7f4c(%rip), %ecx    # 0x6025b4
jbe 0x40a68d
xorl %eax, %eax
testl %ecx, %ecx
movl $0x0, %edx
cmovgl %ecx, %edx
cmpq %rax, %rdx
je 0x40a688
movl (%r15,%rax,4), %esi
movl %esi, (%r14,%rax,4)
incq %rax
jmp 0x40a676
movsd %xmm0, (%rsp)
movq 0x1f7f2c(%rip), %rdi    # 0x6025c0
movq 0x1f7f2d(%rip), %rsi    # 0x6025c8
movl 0x1f7f0f(%rip), %edx    # 0x6025b0
movq %r14, %r8
movq %r15, %r9
callq 0x40852d
movq 0x1f7f0d(%rip), %rdi    # 0x6025c0
movq 0x1f7f0e(%rip), %rsi    # 0x6025c8
movl 0x1f7ef4(%rip), %ecx    # 0x6025b4
subq $0x8, %rsp
leaq 0x1f7f65(%rip), %r9     # 0x602630
movq %r15, %r8
pushq $0x8
pushq $0x28
pushq %r12
callq 0x4073a8
addq $0x20, %rsp
movsd (%rsp), %xmm2
ucomisd %xmm2, %xmm0
movl 0x1f7ec8(%rip), %ecx    # 0x6025b4
jbe 0x40a710
xorl %eax, %eax
testl %ecx, %ecx
movl $0x0, %edx
cmovgl %ecx, %edx
cmpq %rax, %rdx
je 0x40a70c
movl (%r15,%rax,4), %esi
movl %esi, (%r14,%rax,4)
incq %rax
jmp 0x40a6fa
movapd %xmm0, %xmm2
movapd %xmm2, %xmm1
mulsd 0x8(%rsp), %xmm1
ucomisd %xmm1, %xmm0
movsd %xmm2, (%rsp)
jbe 0x40a788
movq 0x1f7e94(%rip), %rdi    # 0x6025c0
movq 0x1f7e95(%rip), %rsi    # 0x6025c8
movl 0x1f7e77(%rip), %edx    # 0x6025b0
leaq 0x1f7ef0(%rip), %r8     # 0x602630
leaq 0x1f7f09(%rip), %r9     # 0x602650
pushq $0x1e
pushq $0x2
pushq $0x0
pushq %r15
callq 0x408a57
addq $0x20, %rsp
ucomisd (%rsp), %xmm0
movl 0x1f7e51(%rip), %ecx    # 0x6025b4
jbe 0x40a788
xorl %eax, %eax
testl %ecx, %ecx
movl $0x0, %edx
cmovgl %ecx, %edx
cmpq %rax, %rdx
je 0x40a783
movl (%r15,%rax,4), %esi
movl %esi, (%r14,%rax,4)
incq %rax
jmp 0x40a771
movsd %xmm0, (%rsp)
movq 0x1f7e31(%rip), %rdi    # 0x6025c0
movq 0x1f7e32(%rip), %rsi    # 0x6025c8
movl 0x1f7e14(%rip), %edx    # 0x6025b0
movq 0x1f7e2d(%rip), %r8     # 0x6025d0
movq 0x1f7e2e(%rip), %r9     # 0x6025d8
subq $0x8, %rsp
pushq %r15
callq 0x4086bd
popq %rax
popq %rcx
movq 0x1f7e02(%rip), %rdi    # 0x6025c0
movq 0x1f7e03(%rip), %rsi    # 0x6025c8
movl 0x1f7de9(%rip), %ecx    # 0x6025b4
subq $0x8, %rsp
leaq 0x1f7e5a(%rip), %r9     # 0x602630
movq %r15, %r8
pushq $0x8
pushq $0x28
pushq %r12
callq 0x4073a8
addq $0x20, %rsp
movsd (%rsp), %xmm1
ucomisd %xmm1, %xmm0
movl 0x1f7dbd(%rip), %ecx    # 0x6025b4
jbe 0x40a81b
xorl %eax, %eax
testl %ecx, %ecx
movl $0x0, %edx
cmovgl %ecx, %edx
cmpq %rax, %rdx
je 0x40a817
movl (%r15,%rax,4), %esi
movl %esi, (%r14,%rax,4)
incq %rax
jmp 0x40a805
movapd %xmm0, %xmm1
movsd 0x8(%rsp), %xmm2
mulsd %xmm1, %xmm2
ucomisd %xmm2, %xmm0
jbe 0x40a88d
movq 0x1f7d8e(%rip), %rdi    # 0x6025c0
movq 0x1f7d8f(%rip), %rsi    # 0x6025c8
movl 0x1f7d71(%rip), %edx    # 0x6025b0
leaq 0x1f7dea(%rip), %r8     # 0x602630
leaq 0x1f7e03(%rip), %r9     # 0x602650
pushq %rbx
pushq %rbx
pushq $0x1
pushq %r15
movsd %xmm1, 0x20(%rsp)
callq 0x408a57
addq $0x20, %rsp
ucomisd (%rsp), %xmm0
movl 0x1f7d47(%rip), %ecx    # 0x6025b4
jbe 0x40a88d
xorl %eax, %eax
testl %ecx, %ecx
movl $0x0, %edx
cmovgl %ecx, %edx
cmpq %rax, %rdx
je 0x40a88d
movl (%r15,%rax,4), %esi
movl %esi, (%r14,%rax,4)
incq %rax
jmp 0x40a87b
xorl %eax, %eax
testl %ecx, %ecx
movl $0x0, %edx
cmovgl %ecx, %edx
cmpq %rax, %rdx
je 0x40aa5c
cmpl $0x0, (%r14,%rax,4)
leaq 0x1(%rax), %rax
js 0x40a899
movq %r15, 0x40(%rsp)
movq 0x1f7d07(%rip), %rdi    # 0x6025c0
movq 0x1f7d08(%rip), %rsi    # 0x6025c8
subq $0x8, %rsp
leaq 0x1f7d65(%rip), %rbx    # 0x602630
movq %r14, %r8
movq %rbx, %r9
pushq $0x8
pushq $0x1
pushq %r12
callq 0x4073a8
addq $0x20, %rsp
movq %r12, %r13
movslq 0x1f7cc6(%rip), %r12    # 0x6025b0
leaq (,%r12,4), %rdi
testq %r12, %r12
pushq $-0x1
popq %r15
cmovsq %r15, %rdi
callq 0x40be00
movq %rax, 0x28(%rsp)
movslq 0x1f7ca6(%rip), %rax    # 0x6025b4
leaq (,%rax,4), %rdi
testq %rax, %rax
cmovsq %r15, %rdi
callq 0x40be00
movq %rax, 0x20(%rsp)
movq 0x1f7c92(%rip), %rdi    # 0x6025c0
movq 0x1f7cbb(%rip), %rsi    # 0x6025f0
movl %r12d, %edx
movq %rbx, %rcx
movq %r13, %r8
callq 0x405577
movl 0x1f7c6b(%rip), %eax    # 0x6025b4
movq 0x1f7ca0(%rip), %rcx    # 0x6025f0
movq %rcx, 0x8(%rsp)
movq 0x1f7c6c(%rip), %rcx    # 0x6025c8
movq %rcx, 0x18(%rsp)
movq 0x1f7c58(%rip), %rcx    # 0x6025c0
movq %rcx, 0x10(%rsp)
movq 0x1f7c6c(%rip), %rcx    # 0x6025e0
movq %rcx, 0x30(%rsp)
movq 0x1f7c68(%rip), %rcx    # 0x6025e8
movq %rcx, 0x50(%rsp)
xorl %ebp, %ebp
testl %eax, %eax
movl $0x0, %r13d
movl %eax, 0x3c(%rsp)
cmovgl %eax, %r13d
movq $0x0, (%rsp)
xorl %r15d, %r15d
cmpq %rbp, %r13
je 0x40aa99
movslq (%r14,%rbp,4), %r12
testq %r12, %r12
js 0x40aa54
incl %r15d
movq 0x8(%rsp), %rax
movq (%rax,%r12,8), %rdi
movq 0x18(%rsp), %rax
movq (%rax,%rbp,8), %rbx
movq %rbx, %rsi
callq 0x4054a5
sqrtsd %xmm0, %xmm0
ucomisd 0x1f7b97(%rip), %xmm0   # 0x602578
ja 0x40aa54
movq (%rsp), %rdx
movslq %edx, %rdx
movq 0x28(%rsp), %rax
movl %r12d, (%rax,%rdx,4)
movq 0x20(%rsp), %rax
movl %ebp, (%rax,%rdx,4)
movq 0x10(%rsp), %rax
movq (%rax,%r12,8), %rax
movsd (%rax), %xmm0
movq 0x30(%rsp), %rcx
movq (%rcx,%rdx,8), %rcx
movsd %xmm0, (%rcx)
movsd 0x8(%rax), %xmm0
movsd %xmm0, 0x8(%rcx)
movsd 0x10(%rax), %xmm0
movsd %xmm0, 0x10(%rcx)
movsd (%rbx), %xmm0
movq 0x50(%rsp), %rax
movq (%rax,%rdx,8), %rax
movsd %xmm0, (%rax)
movsd 0x8(%rbx), %xmm0
movsd %xmm0, 0x8(%rax)
movsd 0x10(%rbx), %xmm0
movsd %xmm0, 0x10(%rax)
incl %edx
movq %rdx, (%rsp)
incq %rbp
jmp 0x40a9a2
movq $0x605d20, %rbx         # imm = 0x605D20
leaq 0x17930f(%rip), %rsi    # 0x583d79
movq %rbx, %rdi
callq 0x4746b0
movq %rax, %rdi
callq 0x473f90
leaq 0x179328(%rip), %rsi    # 0x583da9
movq %rbx, %rdi
callq 0x4746b0
movq %rax, %rdi
callq 0x473f90
pushq $0x1
popq %rax
jmp 0x40adb2
cvtsi2sdl 0x3c(%rsp), %xmm0
movsd %xmm0, 0x8(%rsp)
callq 0x409f7a
movsd 0x1f7ace(%rip), %xmm0   # 0x602580
movsd %xmm0, 0x10(%rsp)
movsd %xmm0, 0x1fa308(%rip)   # 0x604dc8
movq 0x1f7b19(%rip), %rdi    # 0x6025e0
movq 0x1f7b1a(%rip), %rsi    # 0x6025e8
leaq 0x58(%rsp), %r12
leaq 0x60(%rsp), %rcx
leaq 0x80(%rsp), %r8
pushq $0x1
popq %rbx
movq (%rsp), %r15
movl %r15d, %edx
movl %ebx, %r9d
pushq %r12
pushq $0x0
callq 0x406ed7
popq %rax
popq %rcx
movsd %xmm0, 0x18(%rsp)
cvtsi2sdl 0x1f7aaa(%rip), %xmm0 # 0x6025b0
callq 0x409f7a
movsd 0x1f7a6d(%rip), %xmm0   # 0x602580
movsd %xmm0, 0x1fa2b5(%rip)   # 0x604dd0
movq 0x1f7abe(%rip), %rdi    # 0x6025e0
movq 0x1f7abf(%rip), %rsi    # 0x6025e8
leaq 0x1f7b00(%rip), %rcx    # 0x602630
leaq 0x1f7b19(%rip), %r8     # 0x602650
movl %r15d, %edx
movl %ebx, %r9d
pushq %r12
pushq $0x0
callq 0x406ed7
popq %rax
popq %rcx
movsd %xmm0, 0x30(%rsp)
cmpb $0x0, 0x1fa294(%rip)    # 0x604de9
movsd 0x18(%rsp), %xmm4
je 0x40abcf
movl 0x1f7a51(%rip), %eax    # 0x6025b4
addl 0x1f7a47(%rip), %eax    # 0x6025b0
cvtsi2sd %eax, %xmm0
mulsd 0x1784a3(%rip), %xmm0   # 0x583018
movsd %xmm0, 0x8(%rsp)
callq 0x409f7a
movsd 0x1f79f8(%rip), %xmm0   # 0x602580
movsd %xmm0, 0x10(%rsp)
movsd %xmm0, 0x1fa24a(%rip)   # 0x604de0
movq 0x1f7a43(%rip), %rdi    # 0x6025e0
movq 0x1f7a44(%rip), %rsi    # 0x6025e8
leaq 0x1f7a85(%rip), %rcx    # 0x602630
leaq 0x1f7a9e(%rip), %r8     # 0x602650
pushq $0x1
popq %r9
movl %r15d, %edx
pushq %r12
pushq $0x0
callq 0x406ed7
popq %rax
popq %rcx
movaps %xmm0, %xmm4
movsd %xmm0, 0x1fa221(%rip)   # 0x604df0
cmpb $0x1, 0x1fa214(%rip)    # 0x604dea
movq 0x40(%rsp), %rbx
jne 0x40ac47
movsd 0x1fa1cb(%rip), %xmm0   # 0x604db0
callq 0x409f7a
movsd 0x1f798e(%rip), %xmm0   # 0x602580
movsd %xmm0, 0x10(%rsp)
movsd %xmm0, 0x1fa1d8(%rip)   # 0x604dd8
movsd 0x1fa1a8(%rip), %xmm0   # 0x604db0
movsd %xmm0, 0x8(%rsp)
movq 0x1f79cb(%rip), %rdi    # 0x6025e0
movq 0x1f79cc(%rip), %rsi    # 0x6025e8
leaq 0x1f7a0d(%rip), %rcx    # 0x602630
leaq 0x1f7a26(%rip), %r8     # 0x602650
pushq $0x1
popq %r9
movl %r15d, %edx
pushq %r12
pushq $0x0
callq 0x406ed7
popq %rax
popq %rcx
movaps %xmm0, %xmm4
movsd %xmm0, 0x1fa1b1(%rip)   # 0x604df8
cmpb $0x1, 0x1fa19d(%rip)    # 0x604deb
jne 0x40acf0
movsd 0x1fa164(%rip), %xmm1   # 0x604dc0
movsd %xmm1, 0x10(%rsp)
movsd %xmm1, 0x1f7916(%rip)   # 0x602580
cvtsi2sdl 0x1f7942(%rip), %xmm0 # 0x6025b4
movsd %xmm0, 0x1f78f6(%rip)   # 0x602570
movsd 0x1783f6(%rip), %xmm0   # 0x583078
minsd %xmm1, %xmm0
maxsd 0x178432(%rip), %xmm0   # 0x5830c0
movsd %xmm0, 0x1f78f2(%rip)   # 0x602588
movsd 0x8(%rsp), %xmm0
movsd %xmm0, 0x1fa114(%rip)   # 0x604db8
movq 0x1f7935(%rip), %rdi    # 0x6025e0
movq 0x1f7936(%rip), %rsi    # 0x6025e8
leaq 0x1f7977(%rip), %rcx    # 0x602630
leaq 0x1f7990(%rip), %r8     # 0x602650
pushq $0x1
popq %r9
movl %r15d, %edx
pushq %r12
pushq $0x0
callq 0x406ed7
movsd 0x20(%rsp), %xmm3
movsd 0x18(%rsp), %xmm5
addq $0x10, %rsp
movaps %xmm0, %xmm4
movsd %xmm0, 0x1fa115(%rip)   # 0x604e00
movaps %xmm3, %xmm6
jmp 0x40ad04
movsd 0x178408(%rip), %xmm3   # 0x583100
movsd 0x8(%rsp), %xmm5
movsd 0x10(%rsp), %xmm6
movl 0x1f78a6(%rip), %edx    # 0x6025b0
movl 0x1f78a4(%rip), %ecx    # 0x6025b4
movsd 0x58(%rsp), %xmm2
subq $0x8, %rsp
leaq 0x27e8(%rsp), %rdi
leaq 0xd8(%rsp), %rsi
leaq 0x68(%rsp), %r8
leaq 0x88(%rsp), %r9
movsd 0x20(%rsp), %xmm0
movsd 0x38(%rsp), %xmm1
pushq %r15
movq 0x30(%rsp), %r12
pushq %r12
movq 0x40(%rsp), %r15
pushq %r15
callq 0x409488
addq $0x20, %rsp
callq 0x406c75
movq %r14, %rdi
callq 0x40b100
movq %rbx, %rdi
callq 0x40b100
movq %r15, %rdi
callq 0x40b100
movq %r12, %rdi
callq 0x40b100
callq 0x53fe60
cvtsi2ss %rax, %xmm0
cvtsi2ssq 0x48(%rsp), %xmm1
subss %xmm1, %xmm0
mulss 0x1783e2(%rip), %xmm0   # 0x583180
cvtss2sd %xmm0, %xmm0
leaq 0x17901d(%rip), %rdi    # 0x583dc6
movb $0x1, %al
callq 0x4d8720
xorl %eax, %eax
addq $0x7608, %rsp           # imm = 0x7608
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq (%r14), %rdi
callq 0x409b4d
movq $0x605d20, %rdi         # imm = 0x605D20
leaq 0x178f0d(%rip), %rsi    # 0x583ce7
jmp 0x40aeb4
movq $0x605d20, %rdi         # imm = 0x605D20
leaq 0x178f26(%rip), %rsi    # 0x583d13
jmp 0x40aeb4
movq $0x605d20, %r14         # imm = 0x605D20
movq %r14, %rdi
callq 0x473f90
leaq 0x1785e0(%rip), %rbx    # 0x5833e8
movq %r14, %rdi
movq %rbx, %rsi
callq 0x4746b0
movq %rax, %rdi
callq 0x473f90
leaq 0x178615(%rip), %rsi    # 0x583437
movq %rax, %rdi
callq 0x4746b0
leaq 0x1f771f(%rip), %rsi    # 0x602550
movq %rax, %rdi
callq 0x4746b0
leaq 0x17860d(%rip), %rsi    # 0x58344d
movq %rax, %rdi
callq 0x4746b0
movq %rax, %rdi
callq 0x473f90
leaq 0x178628(%rip), %rsi    # 0x58347f
movq %rax, %rdi
callq 0x4746b0
movq %rax, %rdi
callq 0x473f90
leaq 0x178660(%rip), %rsi    # 0x5834ce
movq %rax, %rdi
callq 0x4746b0
movq %rax, %rdi
callq 0x473f90
movq %rax, %rdi
movq %rbx, %rsi
jmp 0x40aeb4
movq $0x605d20, %rdi         # imm = 0x605D20
leaq 0x178ded(%rip), %rsi    # 0x583c81
jmp 0x40aeb4
movq $0x605d20, %rdi         # imm = 0x605D20
leaq 0x178df8(%rip), %rsi    # 0x583c9c
jmp 0x40aeb4
movq $0x605d20, %rdi         # imm = 0x605D20
leaq 0x178e03(%rip), %rsi    # 0x583cb7
callq 0x4746b0
movq %rax, %rdi
callq 0x473f90
pushq $0x1
popq %rdi
callq 0x4cd390
nop