// File: /workspace/github_cpp_makefile_star2_O3/dcarrey[P]hgt-detection/./fonctions.cpp
// Function: findBestHGT(int, InputTree, InputTree, Parameters, HGT*)
int findBestHGT(int initial,struct InputTree SpeciesTree,struct InputTree GeneTree,struct Parameters param,struct HGT *aHGT){

	struct InputTree tmpTree;
	int i,j,k,l,first=1,ret=0;
	int size = SpeciesTree.size;
	int ktSpecies;
	struct CRITERIA aCrit,aCritRef;
	struct DescTree *DTSpecies,*DTGene;

	initInputTree(&tmpTree);

	//printf("\ndebut findBestHgt");
	//== compute criteria
	InitCriteria(&aCrit,size);
	InitCriteria(&aCritRef,size);
	computeCriteria(SpeciesTree.ADD,GeneTree.ADD,size,&aCrit,SpeciesTree.LONGUEUR,SpeciesTree.ARETE,GeneTree.LONGUEUR,GeneTree.ARETE);
	computeCriteria(SpeciesTree.ADD,GeneTree.ADD,size,&aCritRef,SpeciesTree.LONGUEUR,SpeciesTree.ARETE,GeneTree.LONGUEUR,GeneTree.ARETE);
	loadCriteria(aCrit,aHGT);

	DTGene = (struct DescTree*)malloc((2*GeneTree.size-2-GeneTree.kt+1)*sizeof(struct DescTree));
	RechercherBipartition(GeneTree.ARETE,GeneTree.ADD,GeneTree.Root,GeneTree.Adjacence,DTGene,GeneTree.size,GeneTree.kt);	

	DTSpecies = (struct DescTree*)malloc((2*SpeciesTree.size-2-SpeciesTree.kt+1)*sizeof(struct DescTree));
	RechercherBipartition(SpeciesTree.ARETE,SpeciesTree.ADD,SpeciesTree.Root,SpeciesTree.Adjacence,DTSpecies,SpeciesTree.size,SpeciesTree.kt);
	//printf("\nRF = %d , LS = %lf , BD = %lf , QD = %d",aCrit.RF,aCrit.LS,aCrit.BD,aCrit.QD);

	/*for(i=1;i<=2*SpeciesTree.size-3-SpeciesTree.kt;i++)
		printf("\n%d-%d -->%lf",SpeciesTree.ARETE[2*i-1],SpeciesTree.ARETE[2*i-2],SpeciesTree.LONGUEUR[i-1]);
	printf("\n");*/

	//== Test all possible HGT
	for(i=1;i<2*size-3-SpeciesTree.kt;i++)
		for(j=1;j<2*size-3-SpeciesTree.kt;j++){
			//printf("\nicit : %d %d",i,j);
			//== is it a valid hgt ?
			if(isAValidHGT(SpeciesTree,i,j)==1 && i!=j ){

				//printf("\n%d-%d -> %d-%d",SpeciesTree.ARETE[2*i-1],SpeciesTree.ARETE[2*i-2],SpeciesTree.ARETE[2*j-1],SpeciesTree.ARETE[2*j-2]);
				//printf(".");

				copyInputTree(&tmpTree,SpeciesTree,0,0);
				
				//printf("\nTransfert : %d--%d -> %d--%d",tmpTree.ARETE[2*i-1],tmpTree.ARETE[2*i-2],tmpTree.ARETE[2*j-1],tmpTree.ARETE[2*j-2]);
				
				//if(tmpTree.ARETE[2*i-1]==6 && tmpTree.ARETE[2*i-2]==15 && tmpTree.ARETE[2*j-1]==7 && tmpTree.ARETE[2*j-2]==14)
				//	printf("");

				if(strcmp(param.subtree,"yes") == 0)
					if(TestSubTreeConstraint(SpeciesTree,i,j,DTSpecies,DTGene) == 0) {
						continue;
						//FreeMemory_InputTree(&tmpTree);
						tmpTree.ADD = NULL;
						tmpTree.ARETE = NULL;
						
					}
				
				//printf("\n\n");
				//printEdges(0,tmpTree.ARETE,tmpTree.LONGUEUR,SpeciesTree.SpeciesName,tmpTree.size);
				//printf("\navant apply");
				applyHGT(GeneTree.ADD,&tmpTree,i,j);
				//printf("\napres apply");

				//printEdges(0,tmpTree.ARETE,tmpTree.LONGUEUR,SpeciesTree.SpeciesName,tmpTree.size);
				//printEdges(0,GeneTree.ARETE,GeneTree.LONGUEUR,SpeciesTree.SpeciesName,GeneTree.size);
				/*for(k=1;k<=2*tmpTree.size-2-tmpTree.kt;k++){
					printf("\n");
					for(l=1;l<=2*tmpTree.size-2-tmpTree.kt;l++)ListeSommets_taille_0(SpeciesTree.Input,tab_sommet);
						printf("%lf ",tmpTree.ADD[k][l]);
				}
				for(k=1;k<=2*tmpTree.size-3-tmpTree.kt;k++)
					printf("\n%d-%d -->%lf",tmpTree.ARETE[2*k-1],tmpTree.ARETE[2*k-2],tmpTree.LONGUEUR[k-1]);
				printf("\n");*/
				//printMatrix(SpeciesTree.SpeciesName,GeneTree.ADD,GeneTree.size);
				
				AdjustBranchLength(&tmpTree,GeneTree,0,1);
				//printMatrix(SpeciesTree.SpeciesName,tmpTree.ADD,tmpTree.size);
				
				
			//	computeCriteria(tmpTree.ADD,GeneTree.ADD,size,&aCrit);
			//	printf("<br>Transfert : %d--%d (%d)-> %d--%d (%d)",SpeciesTree.ARETE[2*i-1],SpeciesTree.ARETE[2*i-2],i,SpeciesTree.ARETE[2*j-1],SpeciesTree.ARETE[2*j-2],j);
			//	printf("=====>RF = %d, LS = %lf",aCrit.RF,aCrit.LS);
				
			//	if(i==12 && j==7){
			//		aCrit.RF = 100;
			//	}	
				if(initial == 1){
					computeCriteria(tmpTree.ADD,SpeciesTree.ADD,size,&aCrit,tmpTree.LONGUEUR,tmpTree.ARETE,SpeciesTree.LONGUEUR,SpeciesTree.ARETE);
					if(aCrit.RF == 1){
						ret += TestCriterionAndUpdate(&first,param.criterion,aCrit,aHGT,i,j,0,0);
						i=j=(int)INFINI;
						break;
					}
				}
				else{
					computeCriteria(tmpTree.ADD,GeneTree.ADD,size,&aCrit,tmpTree.LONGUEUR,tmpTree.ARETE,GeneTree.LONGUEUR,GeneTree.ARETE);
			//		printf("<br>aCrit : RF = %d, LS = %lf",aCrit.RF,aCrit.LS);
			//		printf("<br>aHGT : RF = %d, LS = %lf",aHGT->crit.RF,aHGT->crit.LS);
		//			if(i==13 && j==3){
						//printf("Le gros changement");
		//				aCrit.RF=7;
		//			}
					ret += TestCriterionAndUpdate(&first,param.criterion,aCrit,aHGT,i,j,0,0);
					if(aHGT->crit.RF == 0 /*|| aHGT->crit.LS < epsilon */|| aHGT->crit.BD == 0 || aHGT->crit.QD == 0) { i=j=(int)INFINI;}
				}

				
				//FreeMemory_InputTree(&tmpTree);
				//tmpTree.ADD = NULL;
				//tmpTree.ARETE = NULL;

			}
			//printf("apres");
		}
	//printf("\n===> %d-%d -> %d-%d , RF = %d , LS = %lf QD = %d",SpeciesTree.ARETE[2*(aHGT->source)-1],SpeciesTree.ARETE[2*(aHGT->source)-2],SpeciesTree.ARETE[2*(aHGT->destination)-1],SpeciesTree.ARETE[2*(aHGT->destination)-2],aHGT->crit.RF,aHGT->crit.LS,aHGT->crit.QD);
	//printf("icit");
	if(ret > 0 )
		findListSpecies(aHGT,DTSpecies,SpeciesTree);
	
	deleteBipartition(DTSpecies,SpeciesTree);
	deleteBipartition(DTGene,GeneTree);
	FreeCriteria(&aCrit,size);
	FreeCriteria(&aCritRef,size);
	FreeMemory_InputTree(&tmpTree,tmpTree.size);

	//printf("\nfin findBestHgt");
	return ret;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x1d8, %rsp            # imm = 0x1D8
movq %rsi, %r13
movl %edi, -0x5c(%rbp)
leaq 0x10(%rbp), %r12
movl $0x1, %r15d
movl %r15d, -0x44(%rbp)
movl (%r12), %ebx
xorl %eax, %eax
movq %rax, -0xd0(%rbp)
xorps %xmm0, %xmm0
movups %xmm0, -0xb0(%rbp)
movq %rax, -0xa0(%rbp)
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
movl %eax, -0xb8(%rbp)
movl %eax, -0xd8(%rbp)
movl $0x0, -0x90(%rbp)
movups %xmm0, -0xc8(%rbp)
leaq -0x138(%rbp), %rdi
movl %ebx, %esi
callq 0xb8ba
leaq -0x198(%rbp), %rdi
movl %ebx, %esi
callq 0xb8ba
movq 0x8(%r12), %r14
movq 0x30(%r12), %rax
movq %rax, -0x40(%rbp)
leaq 0x68(%rbp), %rax
movq 0x8(%rax), %r12
movq 0x30(%rax), %rcx
movq %rcx, -0x30(%rbp)
movq %r14, %rdi
movq %r14, -0x70(%rbp)
movq %r12, %rsi
movl %ebx, %edx
leaq -0x138(%rbp), %rcx
callq 0x8c46
movq %r14, %rdi
movq %r12, %rsi
movq %rbx, %r14
movl %r14d, %edx
leaq -0x198(%rbp), %rcx
callq 0x8c46
leaq -0x138(%rbp), %rax
movsd (%rax), %xmm0
movsd 0x10(%rax), %xmm1
movq 0x30(%rax), %rax
movsd %xmm0, 0x20(%r13)
movq %rax, 0x50(%r13)
movsd %xmm1, 0x30(%r13)
movq %r13, -0x58(%rbp)
movl %r15d, (%r13)
leaq 0x68(%rbp), %rax
movl (%rax), %ebx
movl 0x48(%rax), %r13d
movl %r13d, %eax
movl $0xffffffff, %ecx       # imm = 0xFFFFFFFF
xorl %ecx, %eax
leal (%rax,%rbx,2), %eax
cltq
shlq $0x3, %rax
leaq (%rax,%rax,2), %rdi
callq 0x1140
leaq 0x68(%rbp), %rcx
movl 0x20(%rcx), %edx
movq 0x28(%rcx), %rcx
movl %r13d, (%rsp)
movq -0x30(%rbp), %rdi
movq %r12, -0x80(%rbp)
movq %r12, %rsi
movq %rax, -0x68(%rbp)
movq %rax, %r8
movl %ebx, %r9d
callq 0x4e01
movq %r14, %rcx
movq %r14, -0x50(%rbp)
addl %r14d, %r14d
leaq 0x10(%rbp), %rbx
movl 0x48(%rbx), %r12d
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
xorl %r12d, %eax
leal (%rax,%rcx,2), %eax
cltq
shlq $0x3, %rax
leaq (%rax,%rax,2), %rdi
callq 0x1140
movq %rax, %r13
movl 0x20(%rbx), %edx
movq 0x28(%rbx), %rcx
movl %r12d, (%rsp)
movq -0x40(%rbp), %rdi
movq -0x70(%rbp), %rsi
movq %rax, %r8
movq -0x50(%rbp), %r9
callq 0x4e01
movq %r13, %rax
subl %r12d, %r14d
xorl %r13d, %r13d
addl $-0x3, %r14d
cmpl $0x2, %r14d
jl 0xc20b
leaq 0xc0(%rbp), %rcx
addq $0x3fc, %rcx            # imm = 0x3FC
movq %rcx, -0x78(%rbp)
movq $0x0, -0x40(%rbp)
leaq -0x138(%rbp), %r13
movl $0x1, %ebx
movq %rax, -0x30(%rbp)
movl %r14d, -0x34(%rbp)
movl $0xb, %ecx
movq %rsp, %rdi
leaq 0x10(%rbp), %r12
movq %r12, %rsi
rep  movsq (%rsi), %es:(%rdi)
movl %r15d, %edi
movl %ebx, %esi
callq 0xa42b
testl %eax, %eax
sete %al
cmpl %ebx, %r15d
sete %cl
orb %al, %cl
je 0xc03e
movq -0x58(%rbp), %r12
movq -0x30(%rbp), %rax
jmp 0xc1b3
movl $0xb, %ecx
movq %rsp, %rdi
movq %r12, %rsi
rep  movsq (%rsi), %es:(%rdi)
leaq -0xd8(%rbp), %r12
movq %r12, %rdi
xorl %esi, %esi
xorl %edx, %edx
callq 0xa587
leaq 0xc0(%rbp), %rax
cmpl $0x736579, 0xe9e(%rax)  # imm = 0x736579
jne 0xc097
movl $0xb, %ecx
movq %rsp, %rdi
leaq 0x10(%rbp), %rsi
rep  movsq (%rsi), %es:(%rdi)
movl %r15d, %edi
movl %ebx, %esi
movq -0x30(%rbp), %rdx
movq -0x68(%rbp), %rcx
callq 0x7eee
testl %eax, %eax
je 0xc031
movq %r12, %rsi
movl %r15d, %edx
movl %ebx, %ecx
callq 0x8d4e
movl $0xb, %ecx
movq %rsp, %rdi
leaq 0x68(%rbp), %rsi
rep  movsq (%rsi), %es:(%rdi)
movq %r12, %rdi
xorl %esi, %esi
movl $0x1, %edx
callq 0xb793
movq -0xd0(%rbp), %rdi
cmpl $0x1, -0x5c(%rbp)
movq -0x58(%rbp), %r12
jne 0xc13c
movq -0x70(%rbp), %rsi
movq -0x50(%rbp), %rdx
movq %r13, %rcx
callq 0x8c46
cmpl $0x1, -0x108(%rbp)
jne 0xc1ab
movl $0xc, %ecx
movq %rsp, %rdi
movq %r13, %rsi
rep  movsq (%rsi), %es:(%rdi)
movl $0x0, 0x60(%rsp)
leaq -0x44(%rbp), %rdi
movq -0x78(%rbp), %rsi
movq %r12, %rdx
movl %r15d, %ecx
movl %ebx, %r8d
xorl %r9d, %r9d
callq 0xa27b
movq -0x40(%rbp), %rcx
addl %eax, %ecx
movq %rcx, -0x40(%rbp)
movl $0xf4240, %r15d         # imm = 0xF4240
movq -0x30(%rbp), %rax
movl -0x34(%rbp), %r14d
jmp 0xc1c1
movq -0x80(%rbp), %rsi
movq -0x50(%rbp), %rdx
movq %r13, %rcx
callq 0x8c46
movl $0xc, %ecx
movq %rsp, %rdi
movq %r13, %rsi
rep  movsq (%rsi), %es:(%rdi)
movl $0x0, 0x60(%rsp)
leaq -0x44(%rbp), %rdi
movq -0x78(%rbp), %rsi
movq %r12, %rdx
movl %r15d, %ecx
movl %ebx, %r8d
xorl %r9d, %r9d
callq 0xa27b
movq -0x40(%rbp), %rcx
addl %eax, %ecx
movq %rcx, -0x40(%rbp)
cmpl $0x0, 0x50(%r12)
je 0xc1a0
movsd 0x30(%r12), %xmm0
ucomisd 0x8ed4(%rip), %xmm0     # 0x15070
jne 0xc1d1
jp 0xc1d1
movl $0xf423f, %ebx          # imm = 0xF423F
movl $0xf423f, %r15d         # imm = 0xF423F
movq -0x30(%rbp), %rax
movl -0x34(%rbp), %r14d
incl %ebx
cmpl %r14d, %ebx
jl 0xc006
incl %r15d
movl $0x1, %ebx
cmpl %r14d, %r15d
jl 0xc006
jmp 0xc1db
cmpl $0x0, 0x54(%r12)
jne 0xc1ab
jmp 0xc1a0
movq -0x40(%rbp), %r13
testl %r13d, %r13d
jle 0xc207
movl $0xb, %ecx
movq %rsp, %rdi
leaq 0x10(%rbp), %rbx
movq %rbx, %rsi
rep  movsq (%rsi), %es:(%rdi)
movq %r12, %rdi
movq %rax, %rsi
callq 0xa143
movq -0x30(%rbp), %rax
jmp 0xc20b
leaq 0x10(%rbp), %rbx
movl $0xb, %ecx
movq %rsp, %rdi
movq %rbx, %rsi
rep  movsq (%rsi), %es:(%rdi)
movq %rax, %rdi
callq 0x792f
movl $0xb, %ecx
movq %rsp, %rdi
leaq 0x68(%rbp), %rsi
rep  movsq (%rsi), %es:(%rdi)
movq -0x68(%rbp), %rdi
callq 0x792f
leaq -0x138(%rbp), %rdi
movq -0x50(%rbp), %r14
movl %r14d, %esi
callq 0xb982
leaq -0x198(%rbp), %rdi
movl %r14d, %esi
callq 0xb982
leaq -0xd8(%rbp), %rdi
movl (%rdi), %esi
callq 0xb07d
movl %r13d, %eax
addq $0x1d8, %rsp            # imm = 0x1D8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq