// File: /workspace/github_cpp_makefile_star2_O2/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, %r15
movl %edi, -0x54(%rbp)
leaq 0x68(%rbp), %r12
leaq 0x10(%rbp), %r14
pushq $0x1
popq %rcx
leaq -0x34(%rbp), %rax
movl %ecx, (%rax)
leaq -0x130(%rbp), %rax
andq $0x0, 0x8(%rax)
xorps %xmm0, %xmm0
andq $0x0, 0x38(%rax)
movups %xmm0, 0x28(%rax)
orl $-0x1, 0x20(%rax)
movl (%r14), %ebx
orl $-0x1, (%rax)
andl $0x0, 0x48(%rax)
movups %xmm0, 0x10(%rax)
leaq -0xd8(%rbp), %r13
movq %r13, %rdi
movl %ebx, %esi
callq 0xa979
leaq -0x190(%rbp), %rdi
movl %ebx, %esi
callq 0xa979
movq 0x8(%r14), %rdi
movq 0x30(%r14), %rax
movq %rax, -0x30(%rbp)
movq 0x8(%r12), %r14
movq 0x30(%r12), %rax
movq %rax, -0x40(%rbp)
movq %rdi, %r12
movq %rdi, -0x70(%rbp)
movq %r14, %rsi
movl %ebx, %edx
movq %r13, %rcx
callq 0x7f5c
movq %r12, %rdi
movq %r14, %rsi
movl %ebx, %edx
leaq -0x190(%rbp), %rcx
callq 0x7f5c
movsd (%r13), %xmm0
movsd 0x10(%r13), %xmm1
movq 0x30(%r13), %rax
movsd %xmm0, 0x20(%r15)
movq %rax, 0x50(%r15)
movsd %xmm1, 0x30(%r15)
movq %r15, -0x48(%rbp)
pushq $0x1
popq %rax
movl %eax, (%r15)
leaq 0x68(%rbp), %rax
movl (%rax), %r12d
movl 0x48(%rax), %r15d
pushq $-0x1
popq %r13
movl %r15d, %eax
xorl %r13d, %eax
leal (%rax,%r12,2), %eax
cltq
imulq $0x18, %rax, %rdi
callq 0x1130
leaq 0x68(%rbp), %rcx
movl 0x20(%rcx), %edx
movq 0x28(%rcx), %rcx
movl %r15d, (%rsp)
leaq -0x130(%rbp), %r15
movq -0x40(%rbp), %rdi
movq %r14, -0x78(%rbp)
movq %r14, %rsi
movq %rax, -0x68(%rbp)
movq %rax, %r8
movl %r12d, %r9d
callq 0x4769
leal (%rbx,%rbx), %r12d
leaq 0x10(%rbp), %rax
movl 0x48(%rax), %r14d
xorl %r14d, %r13d
leal (%r13,%rbx,2), %eax
cltq
imulq $0x18, %rax, %rdi
callq 0x1130
leaq 0x10(%rbp), %rcx
movl 0x20(%rcx), %edx
movq 0x28(%rcx), %rcx
movl %r14d, (%rsp)
movq -0x30(%rbp), %rdi
movq -0x70(%rbp), %rsi
movq %rax, -0x60(%rbp)
movq %rax, %r8
movq %rbx, -0x50(%rbp)
movl %ebx, %r9d
callq 0x4769
subl %r14d, %r12d
addl $-0x3, %r12d
movl %r12d, -0x40(%rbp)
xorl %r13d, %r13d
pushq $0xb
popq %rbx
pushq $0x1
popq %r12
cmpl -0x40(%rbp), %r12d
jge 0xb1d3
pushq $0x1
popq %r14
cmpl -0x40(%rbp), %r14d
jge 0xb184
movl %r13d, -0x30(%rbp)
movq %r15, %r13
movq %rbx, %rcx
movq %rsp, %rdi
leaq 0x10(%rbp), %r15
movq %r15, %rsi
rep  movsq (%rsi), %es:(%rdi)
movl %r12d, %edi
movl %r14d, %esi
callq 0x9610
testl %eax, %eax
sete %al
cmpl %r14d, %r12d
sete %cl
orb %al, %cl
je 0xb048
movl -0x30(%rbp), %eax
movq %r13, %r15
jmp 0xb16b
movq %rbx, %rcx
movq %rsp, %rdi
movq %r15, %rsi
rep  movsq (%rsi), %es:(%rdi)
movq %r13, %r15
movq %r13, %rdi
xorl %esi, %esi
xorl %edx, %edx
callq 0x976c
leaq 0xf5e(%rbp), %rax
cmpl $0x736579, (%rax)       # imm = 0x736579
jne 0xb09a
movq %rbx, %rcx
movq %rsp, %rdi
leaq 0x10(%rbp), %rsi
rep  movsq (%rsi), %es:(%rdi)
movl %r12d, %edi
movl %r14d, %esi
movq -0x60(%rbp), %rdx
movq -0x68(%rbp), %rcx
callq 0x735d
testl %eax, %eax
je 0xb176
movq %r15, %rsi
movl %r12d, %edx
movl %r14d, %ecx
callq 0x804e
movq %rbx, %rcx
movq %rsp, %rdi
leaq 0x68(%rbp), %rsi
rep  movsq (%rsi), %es:(%rdi)
movq %r15, %rdi
xorl %esi, %esi
pushq $0x1
popq %rdx
callq 0xa854
movq -0x128(%rbp), %rdi
cmpl $0x1, -0x54(%rbp)
jne 0xb0f5
movq -0x70(%rbp), %rsi
movq -0x50(%rbp), %rdx
leaq -0xd8(%rbp), %rcx
callq 0x7f5c
cmpl $0x1, -0xa8(%rbp)
je 0xb18c
movl -0x30(%rbp), %eax
jmp 0xb168
movq -0x78(%rbp), %rsi
movq -0x50(%rbp), %rdx
leaq -0xd8(%rbp), %r15
movq %r15, %rcx
callq 0x7f5c
pushq $0xc
popq %rcx
movq %rsp, %rdi
movq %r15, %rsi
rep  movsq (%rsi), %es:(%rdi)
andl $0x0, 0x60(%rsp)
leaq -0x34(%rbp), %rdi
leaq 0x4bc(%rbp), %rsi
movq -0x48(%rbp), %r15
movq %r15, %rdx
movl %r12d, %ecx
movl %r14d, %r8d
xorl %r9d, %r9d
callq 0x9471
addl -0x30(%rbp), %eax
cmpl $0x0, 0x50(%r15)
je 0xb159
movsd 0x30(%r15), %xmm0
ucomisd 0x8f1b(%rip), %xmm0     # 0x14070
jne 0xb17b
jp 0xb17b
movl $0xf423f, %r14d         # imm = 0xF423F
movl $0xf423f, %r12d         # imm = 0xF423F
movq %r13, %r15
pushq $0xb
popq %rbx
incl %r14d
movl %eax, %r13d
jmp 0xb002
movl -0x30(%rbp), %eax
jmp 0xb16b
cmpl $0x0, 0x54(%r15)
jne 0xb165
jmp 0xb159
incl %r12d
jmp 0xaff4
pushq $0xc
popq %rcx
movq %rsp, %rdi
leaq -0xd8(%rbp), %rsi
rep  movsq (%rsi), %es:(%rdi)
andl $0x0, 0x60(%rsp)
leaq -0x34(%rbp), %rdi
leaq 0x4bc(%rbp), %rsi
movq -0x48(%rbp), %rdx
movl %r12d, %ecx
movl %r14d, %r8d
xorl %r9d, %r9d
callq 0x9471
movl -0x30(%rbp), %r13d
addl %eax, %r13d
movl $0xf4240, %r12d         # imm = 0xF4240
pushq $0xb
popq %rbx
jmp 0xaff4
testl %r13d, %r13d
leaq 0x10(%rbp), %r15
movq -0x60(%rbp), %r12
jle 0xb1f8
pushq $0xb
popq %rcx
movq %rsp, %rdi
movq %r15, %rsi
rep  movsq (%rsi), %es:(%rdi)
movq -0x48(%rbp), %rdi
movq %r12, %rsi
callq 0x934f
pushq $0xb
popq %r14
movq %r14, %rcx
movq %rsp, %rdi
movq %r15, %rsi
rep  movsq (%rsi), %es:(%rdi)
movq %r12, %rdi
callq 0x6dfa
movq %r14, %rcx
movq %rsp, %rdi
leaq 0x68(%rbp), %rsi
rep  movsq (%rsi), %es:(%rdi)
movq -0x68(%rbp), %rdi
callq 0x6dfa
leaq -0xd8(%rbp), %rdi
movq -0x50(%rbp), %r14
movl %r14d, %esi
callq 0xaa34
leaq -0x190(%rbp), %rdi
movl %r14d, %esi
callq 0xaa34
leaq -0x130(%rbp), %rdi
movl (%rdi), %esi
callq 0xa1b9
movl %r13d, %eax
addq $0x1d8, %rsp            # imm = 0x1D8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq