// File: 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
subq $0x590, %rsp            # imm = 0x590
leaq 0xc0(%rbp), %rax
movq %rax, -0x4f8(%rbp)
leaq 0x68(%rbp), %rax
movq %rax, -0x4f0(%rbp)
leaq 0x10(%rbp), %rax
movq %rax, -0x4e8(%rbp)
movl %edi, -0x4(%rbp)
movq %rsi, -0x10(%rbp)
movl $0x1, -0x7c(%rbp)
movl $0x0, -0x80(%rbp)
movl (%rax), %eax
movl %eax, -0x84(%rbp)
leaq -0x68(%rbp), %rdi
callq 0xd040
movl -0x84(%rbp), %esi
leaq -0xe8(%rbp), %rdi
callq 0x14520
movl -0x84(%rbp), %esi
leaq -0x148(%rbp), %rdi
callq 0x14520
movq -0x4f0(%rbp), %rax
movq -0x4e8(%rbp), %rcx
movq 0x8(%rcx), %rdi
movq 0x8(%rax), %rsi
movl -0x84(%rbp), %edx
movq 0x38(%rcx), %r8
movq 0x30(%rcx), %r9
movq 0x38(%rax), %r10
movq 0x30(%rax), %rax
leaq -0xe8(%rbp), %rcx
movq %r10, (%rsp)
movq %rax, 0x8(%rsp)
callq 0xea10
movq -0x4f0(%rbp), %rax
movq -0x4e8(%rbp), %rcx
movq 0x8(%rcx), %rdi
movq 0x8(%rax), %rsi
movl -0x84(%rbp), %edx
movq 0x38(%rcx), %r8
movq 0x30(%rcx), %r9
movq 0x38(%rax), %r10
movq 0x30(%rax), %rax
leaq -0x148(%rbp), %rcx
movq %r10, (%rsp)
movq %rax, 0x8(%rsp)
callq 0xea10
leaq -0x1b8(%rbp), %rdi
leaq -0xe8(%rbp), %rsi
movl $0x60, %edx
callq 0x1070
movq -0x10(%rbp), %rdi
movups -0x168(%rbp), %xmm0
movq %rsp, %rax
movups %xmm0, 0x50(%rax)
movups -0x178(%rbp), %xmm0
movups %xmm0, 0x40(%rax)
movups -0x1b8(%rbp), %xmm0
movups -0x1a8(%rbp), %xmm1
movups -0x198(%rbp), %xmm2
movups -0x188(%rbp), %xmm3
movups %xmm3, 0x30(%rax)
movups %xmm2, 0x20(%rax)
movups %xmm1, 0x10(%rax)
movups %xmm0, (%rax)
callq 0xe9c0
movq -0x4f0(%rbp), %rcx
movl (%rcx), %eax
shll %eax
subl $0x2, %eax
subl 0x48(%rcx), %eax
addl $0x1, %eax
cltq
imulq $0x18, %rax, %rdi
callq 0x1110
movq %rax, %rcx
movq -0x4f0(%rbp), %rax
movq %rcx, -0x158(%rbp)
movq 0x30(%rax), %rdi
movq 0x8(%rax), %rsi
movl 0x20(%rax), %edx
movq 0x28(%rax), %rcx
movq -0x158(%rbp), %r8
movl (%rax), %r9d
movl 0x48(%rax), %eax
movl %eax, (%rsp)
callq 0x84e0
movq -0x4e8(%rbp), %rcx
movl (%rcx), %eax
shll %eax
subl $0x2, %eax
subl 0x48(%rcx), %eax
addl $0x1, %eax
cltq
imulq $0x18, %rax, %rdi
callq 0x1110
movq %rax, %rcx
movq -0x4e8(%rbp), %rax
movq %rcx, -0x150(%rbp)
movq 0x30(%rax), %rdi
movq 0x8(%rax), %rsi
movl 0x20(%rax), %edx
movq 0x28(%rax), %rcx
movq -0x150(%rbp), %r8
movl (%rax), %r9d
movl 0x48(%rax), %eax
movl %eax, (%rsp)
callq 0x84e0
movl $0x1, -0x6c(%rbp)
movq -0x4e8(%rbp), %rdx
movl -0x6c(%rbp), %eax
movl -0x84(%rbp), %ecx
shll %ecx
subl $0x3, %ecx
subl 0x48(%rdx), %ecx
cmpl %ecx, %eax
jge 0x15552
movl $0x1, -0x70(%rbp)
movq -0x4e8(%rbp), %rdx
movl -0x70(%rbp), %eax
movl -0x84(%rbp), %ecx
shll %ecx
subl $0x3, %ecx
subl 0x48(%rdx), %ecx
cmpl %ecx, %eax
jge 0x15542
movq -0x4e8(%rbp), %rsi
leaq -0x210(%rbp), %rdi
movl $0x58, %edx
callq 0x1070
movl -0x6c(%rbp), %edi
movl -0x70(%rbp), %esi
movq -0x1c0(%rbp), %rcx
movq %rsp, %rax
movq %rcx, 0x50(%rax)
movups -0x1d0(%rbp), %xmm0
movups %xmm0, 0x40(%rax)
movups -0x210(%rbp), %xmm0
movups -0x200(%rbp), %xmm1
movups -0x1f0(%rbp), %xmm2
movups -0x1e0(%rbp), %xmm3
movups %xmm3, 0x30(%rax)
movups %xmm2, 0x20(%rax)
movups %xmm1, 0x10(%rax)
movups %xmm0, (%rax)
callq 0x12050
cmpl $0x1, %eax
jne 0x15532
movl -0x6c(%rbp), %eax
cmpl -0x70(%rbp), %eax
je 0x15532
movq -0x4e8(%rbp), %rsi
leaq -0x268(%rbp), %rdi
movl $0x58, %edx
callq 0x1070
xorl %eax, %eax
movq -0x218(%rbp), %rcx
movq %rsp, %rax
movq %rcx, 0x50(%rax)
movups -0x228(%rbp), %xmm0
movups %xmm0, 0x40(%rax)
movups -0x268(%rbp), %xmm0
movups -0x258(%rbp), %xmm1
movups -0x248(%rbp), %xmm2
movups -0x238(%rbp), %xmm3
movups %xmm3, 0x30(%rax)
movups %xmm2, 0x20(%rax)
movups %xmm1, 0x10(%rax)
movups %xmm0, (%rax)
leaq -0x68(%rbp), %rdi
xorl %edx, %edx
movl %edx, %esi
callq 0x12530
movq -0x4f8(%rbp), %rdi
addq $0xe9e, %rdi            # imm = 0xE9E
leaq 0x107d9(%rip), %rsi     # 0x259db
callq 0x1130
cmpl $0x0, %eax
jne 0x15291
movq -0x4e8(%rbp), %rsi
leaq -0x2c0(%rbp), %rdi
movl $0x58, %edx
callq 0x1070
movl -0x6c(%rbp), %edi
movl -0x70(%rbp), %esi
movq -0x150(%rbp), %rdx
movq -0x158(%rbp), %rcx
movq -0x270(%rbp), %r8
movq %rsp, %rax
movq %r8, 0x50(%rax)
movups -0x280(%rbp), %xmm0
movups %xmm0, 0x40(%rax)
movups -0x2c0(%rbp), %xmm0
movups -0x2b0(%rbp), %xmm1
movups -0x2a0(%rbp), %xmm2
movups -0x290(%rbp), %xmm3
movups %xmm3, 0x30(%rax)
movups %xmm2, 0x20(%rax)
movups %xmm1, 0x10(%rax)
movups %xmm0, (%rax)
callq 0xd5f0
cmpl $0x0, %eax
jne 0x1528f
jmp 0x15534
jmp 0x15291
movq -0x4f0(%rbp), %rax
movq 0x8(%rax), %rdi
movl -0x6c(%rbp), %edx
movl -0x70(%rbp), %ecx
leaq -0x68(%rbp), %rsi
callq 0xec00
movq -0x4f0(%rbp), %rsi
leaq -0x318(%rbp), %rdi
movl $0x58, %edx
callq 0x1070
xorl %eax, %eax
movq -0x2c8(%rbp), %rcx
movq %rsp, %rax
movq %rcx, 0x50(%rax)
movups -0x2d8(%rbp), %xmm0
movups %xmm0, 0x40(%rax)
movups -0x318(%rbp), %xmm0
movups -0x308(%rbp), %xmm1
movups -0x2f8(%rbp), %xmm2
movups -0x2e8(%rbp), %xmm3
movups %xmm3, 0x30(%rax)
movups %xmm2, 0x20(%rax)
movups %xmm1, 0x10(%rax)
movups %xmm0, (%rax)
leaq -0x68(%rbp), %rdi
xorl %esi, %esi
movl $0x1, %edx
callq 0x14340
cmpl $0x1, -0x4(%rbp)
jne 0x1541f
movq -0x4e8(%rbp), %rax
movq -0x60(%rbp), %rdi
movq 0x8(%rax), %rsi
movl -0x84(%rbp), %edx
movq -0x30(%rbp), %r8
movq -0x38(%rbp), %r9
movq 0x38(%rax), %r10
movq 0x30(%rax), %rax
leaq -0xe8(%rbp), %rcx
movq %r10, (%rsp)
movq %rax, 0x8(%rsp)
callq 0xea10
cmpl $0x1, -0xb8(%rbp)
jne 0x1541a
movq -0x4f8(%rbp), %rax
addq $0x3fc, %rax            # imm = 0x3FC
movq %rax, -0x500(%rbp)
leaq -0x378(%rbp), %rdi
leaq -0xe8(%rbp), %rsi
movl $0x60, %edx
callq 0x1070
movq -0x500(%rbp), %rsi
movq -0x10(%rbp), %rdx
movl -0x6c(%rbp), %ecx
movl -0x70(%rbp), %r8d
xorl %eax, %eax
movups -0x328(%rbp), %xmm0
movq %rsp, %rax
movups %xmm0, 0x50(%rax)
movups -0x338(%rbp), %xmm0
movups %xmm0, 0x40(%rax)
movups -0x378(%rbp), %xmm0
movups -0x368(%rbp), %xmm1
movups -0x358(%rbp), %xmm2
movups -0x348(%rbp), %xmm3
movups %xmm3, 0x30(%rax)
movups %xmm2, 0x20(%rax)
movups %xmm1, 0x10(%rax)
movups %xmm0, (%rax)
movl $0x0, 0x60(%rax)
leaq -0x7c(%rbp), %rdi
xorl %r9d, %r9d
callq 0x11df0
addl -0x80(%rbp), %eax
movl %eax, -0x80(%rbp)
movl $0xf423f, -0x70(%rbp)   # imm = 0xF423F
movl $0xf423f, -0x6c(%rbp)   # imm = 0xF423F
jmp 0x15542
jmp 0x15530
movq -0x4f0(%rbp), %rax
movq -0x60(%rbp), %rdi
movq 0x8(%rax), %rsi
movl -0x84(%rbp), %edx
movq -0x30(%rbp), %r8
movq -0x38(%rbp), %r9
movq 0x38(%rax), %r10
movq 0x30(%rax), %rax
leaq -0xe8(%rbp), %rcx
movq %r10, (%rsp)
movq %rax, 0x8(%rsp)
callq 0xea10
movq -0x4f8(%rbp), %rax
addq $0x3fc, %rax            # imm = 0x3FC
movq %rax, -0x508(%rbp)
leaq -0x3d8(%rbp), %rdi
leaq -0xe8(%rbp), %rsi
movl $0x60, %edx
callq 0x1070
movq -0x508(%rbp), %rsi
movq -0x10(%rbp), %rdx
movl -0x6c(%rbp), %ecx
movl -0x70(%rbp), %r8d
xorl %eax, %eax
movups -0x388(%rbp), %xmm0
movq %rsp, %rax
movups %xmm0, 0x50(%rax)
movups -0x398(%rbp), %xmm0
movups %xmm0, 0x40(%rax)
movups -0x3d8(%rbp), %xmm0
movups -0x3c8(%rbp), %xmm1
movups -0x3b8(%rbp), %xmm2
movups -0x3a8(%rbp), %xmm3
movups %xmm3, 0x30(%rax)
movups %xmm2, 0x20(%rax)
movups %xmm1, 0x10(%rax)
movups %xmm0, (%rax)
movl $0x0, 0x60(%rax)
leaq -0x7c(%rbp), %rdi
xorl %r9d, %r9d
callq 0x11df0
addl -0x80(%rbp), %eax
movl %eax, -0x80(%rbp)
movq -0x10(%rbp), %rax
cmpl $0x0, 0x50(%rax)
je 0x15520
movq -0x10(%rbp), %rax
movsd 0x30(%rax), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jne 0x15516
jp 0x15516
jmp 0x15520
movq -0x10(%rbp), %rax
cmpl $0x0, 0x54(%rax)
jne 0x1552e
movl $0xf423f, -0x70(%rbp)   # imm = 0xF423F
movl $0xf423f, -0x6c(%rbp)   # imm = 0xF423F
jmp 0x15530
jmp 0x15532
jmp 0x15534
movl -0x70(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x70(%rbp)
jmp 0x150e6
jmp 0x15544
movl -0x6c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x6c(%rbp)
jmp 0x150bf
cmpl $0x0, -0x80(%rbp)
jle 0x155e4
movq -0x4e8(%rbp), %rsi
movq -0x10(%rbp), %rax
movq %rax, -0x518(%rbp)
movq -0x150(%rbp), %rax
movq %rax, -0x510(%rbp)
leaq -0x430(%rbp), %rdi
movl $0x58, %edx
callq 0x1070
movq -0x518(%rbp), %rdi
movq -0x510(%rbp), %rsi
movq -0x3e0(%rbp), %rcx
movq %rsp, %rax
movq %rcx, 0x50(%rax)
movups -0x3f0(%rbp), %xmm0
movups %xmm0, 0x40(%rax)
movups -0x430(%rbp), %xmm0
movups -0x420(%rbp), %xmm1
movups -0x410(%rbp), %xmm2
movups -0x400(%rbp), %xmm3
movups %xmm3, 0x30(%rax)
movups %xmm2, 0x20(%rax)
movups %xmm1, 0x10(%rax)
movups %xmm0, (%rax)
callq 0x11b40
movq -0x4e8(%rbp), %rsi
movq -0x150(%rbp), %rax
movq %rax, -0x528(%rbp)
leaq -0x488(%rbp), %rdi
movl $0x58, %edx
callq 0x1070
movq -0x528(%rbp), %rdi
movq -0x438(%rbp), %rcx
movq %rsp, %rax
movq %rcx, 0x50(%rax)
movups -0x448(%rbp), %xmm0
movups %xmm0, 0x40(%rax)
movups -0x488(%rbp), %xmm0
movups -0x478(%rbp), %xmm1
movups -0x468(%rbp), %xmm2
movups -0x458(%rbp), %xmm3
movups %xmm3, 0x30(%rax)
movups %xmm2, 0x20(%rax)
movups %xmm1, 0x10(%rax)
movups %xmm0, (%rax)
callq 0xce00
movq -0x4f0(%rbp), %rsi
movq -0x158(%rbp), %rax
movq %rax, -0x520(%rbp)
leaq -0x4e0(%rbp), %rdi
movl $0x58, %edx
callq 0x1070
movq -0x520(%rbp), %rdi
movq -0x490(%rbp), %rcx
movq %rsp, %rax
movq %rcx, 0x50(%rax)
movups -0x4a0(%rbp), %xmm0
movups %xmm0, 0x40(%rax)
movups -0x4e0(%rbp), %xmm0
movups -0x4d0(%rbp), %xmm1
movups -0x4c0(%rbp), %xmm2
movups -0x4b0(%rbp), %xmm3
movups %xmm3, 0x30(%rax)
movups %xmm2, 0x20(%rax)
movups %xmm1, 0x10(%rax)
movups %xmm0, (%rax)
callq 0xce00
movl -0x84(%rbp), %esi
leaq -0xe8(%rbp), %rdi
callq 0x14650
movl -0x84(%rbp), %esi
leaq -0x148(%rbp), %rdi
callq 0x14650
movl -0x68(%rbp), %esi
leaq -0x68(%rbp), %rdi
callq 0x13810
movl -0x80(%rbp), %eax
addq $0x590, %rsp            # imm = 0x590
popq %rbp
retq
nopl (%rax)