// File: /workspace/github_c_makefile_star2_O1/cbouilla[P]AES-attacks-finder/Solver.c
// Function: EnleveFaussesEq
int EnleveFaussesEq(Solver *B1, int N1, SysEqLin E) // Prend en compte le fait que x = y soit equivalent à S(x) = S(y)
{
	/*
	 * Doit être lancé avec les solvers 1 issues de MakeSolver1.
     * Cela permet de savoir si oui ou non il y a une equation entre 2 variables.
     * Il ne reste donc plus qu'à déterminer si cette équation est x = y ou équivalent.
     * Si c'est le cas, on remplace toutes les occurences de y par x, sauf pour cette équation.
     */
	int trouve = 0; // indique si l'on trouve une équation d'égalité entre 2 variables
	
	int a=E->gen*VARIABLES; // nombre de lignes de E->mat
	
	unsigned char **m=malloc(a*sizeof(unsigned char *));

	int i;
	for (i = 0; i < a; i++)
	{
		m[i]=malloc((E->b+E->gen)*sizeof(unsigned char));
		int j;
		for (j = 0; j < E->b; j++) m[i][j]=E->mat[i][j];
		for (j = 0; j < E->gen; j++) m[i][j+E->b]=0;
	}
	
	int c=Dimension(m,a,E->b,1);
	
	int *X=malloc(VARIABLES*sizeof(int));
	
	for (i = 0; i < N1; i++)
	{
		int pos=0,j;
		/* Si une variable apparait "linéairement" c'est inutile */
		for (j = 0; j < B1[i]->Nvar; j++) if (!ApparaitLineairement(B1[i]->var[j],E)) X[pos++]=B1[i]->var[j];
		for (j = 0; j < pos; j++)
		{
			int k;
			for (k = j+1; k < pos; k++)
			{
				#if 1
				int l;
				for (l = 0; l < E->gen; l++)
				{
					m[E->gen*E->lignevar[X[j]]+l][E->b]=1;
					m[E->gen*E->lignevar[X[k]]+l][E->b]=1;
					int d=Dimension(m,a,E->b+1,1);
					m[E->gen*E->lignevar[X[j]]+l][E->b]=0;
					m[E->gen*E->lignevar[X[k]]+l][E->b]=0;
					if (d<c+1) break;				
				}
				if (l<E->gen)
				{
					int b=l;
					for (l = 0; l < E->gen; l++)
					{
						if (l!=b) // Permet de garder l'équation x = y ou S(x) = S(y)
						{
							int p;
							for (p = 0; p < E->b; p++)
							{
								if (m[E->gen*E->lignevar[X[k]]+l][p])
								{
									m[E->gen*E->lignevar[X[j]]+l][p]^=m[E->gen*E->lignevar[X[k]]+l][p];
									m[E->gen*E->lignevar[X[k]]+l][p]=0;
								}
							}
						}
					}
					trouve=1;
					c=Dimension(m,a,E->b,1);
					pos--;
					for (l = k; l < pos; l++) X[l]=X[l+1];
					k--;
				}
				#else // Ce serait mieux : on regarde si il exite une fonction f tel que f(x) = f(y), il faudrait vérifier si f est bijective.
				int l;
				for (l = 0; l < E->gen; l++)
				{
					m[E->gen*E->lignevar[X[j]]+l][E->b+l]=1;
					m[E->gen*E->lignevar[X[k]]+l][E->b+l]=1;			
				}
				int d=Dimension(m,a,E->b+E->gen,1);
				for (l = 0; l < E->gen; l++)
				{
					m[E->gen*E->lignevar[X[j]]+l][E->b+l]=0;
					m[E->gen*E->lignevar[X[k]]+l][E->b+l]=0;			
				}
				if (d<c+E->gen)
				{
					for (l = 0; l < E->gen; l++)
					{
						int p;
						for (p = 0; p < E->b; p++)
						{
							if (m[E->gen*E->lignevar[X[k]]+l][p])
							{
								m[E->gen*E->lignevar[X[j]]+l][p]^=m[E->gen*E->lignevar[X[k]]+l][p];
								m[E->gen*E->lignevar[X[k]]+l][p]=0;
							}
						}
					}
					trouve=1;
					c=Dimension(m,a,E->b,1);
					pos--;
					for (l = k; l < pos; l++) X[l]=X[l+1];
					k--;
				}
				#endif
				
			}
		}
	}
	free(X);
	
	int j=Base(E->mat,m,a,E->b);
	
	for (i = 0; i < a; i++) free(m[i]);
	free(m);

	if (!trouve && j==E->b) return 0; // Il n'y avait pas d'équations du type x = y ou S(x) = S(y)
	
	E->b=j;
	
	if (E->initialise)
	{
		for (i = 0; i < E->a/E->gen; i++)
		{
			freeMatriceCreuse(E->sousmat[E->varligne[i]]);
		}
		free(E->sousmat);
		E->initialise=0;
	}

	#if 0 // Activer si l'on supprime des variables
	int *dedans=malloc(VARIABLES*sizeof(int));
	for (i = 0; i < VARIABLES; i++)
	{
		for (j = 0; j < E->gen; j++)
		{
			int k=0;
			while (k<E->b && E->mat[E->lignevar[i]*E->gen+j][k]==0) k++;
			if (k<E->b) break;
		}
		if (j<E->gen) dedans[i]=1;
		else dedans[i]=0;
	}
	for (i = 0; i < VARIABLES; i++)
	{
		if (dedans[i]==0 && E->gen*E->lignevar[i]<E->a)
		{
			E->a=E->a-E->gen;
			int l;
			for (l = 0; l < E->gen; l++) echangeligne(E->gen*E->lignevar[i]+l,E->a+l,E->mat,E->gen*VARIABLES,E->b);
			j=E->varligne[E->a/E->gen];
			int k=E->lignevar[i];
			E->lignevar[i]=E->lignevar[j];
			E->lignevar[j]=k;
			E->varligne[E->a/E->gen]=i;
			E->varligne[k]=j;
		}
	}
	free(dedans);
	#endif
	return 1;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x58, %rsp
movq %rdx, %rbx
movl %esi, %ebp
movq %rdi, %r12
movslq 0x10(%rdx), %r15
leaq 0x28d67(%rip), %rax     # 0x322b8
movslq (%rax), %r13
imulq %r13, %r15
movq %r15, %rdi
shlq $0x3, %rdi
callq 0x21d0
movq %rax, %r14
movl %r15d, %eax
movq %rax, 0x28(%rsp)
movq %r15, 0x18(%rsp)
testl %r15d, %r15d
jle 0x95db
xorl %r15d, %r15d
movslq 0xc(%rbx), %rax
movslq 0x10(%rbx), %rdi
addq %rax, %rdi
callq 0x21d0
movq %rax, (%r14,%r15,8)
cmpl $0x0, 0xc(%rbx)
jle 0x95b5
xorl %eax, %eax
movq (%rbx), %rcx
movq (%rcx,%r15,8), %rcx
movb (%rcx,%rax), %cl
movq (%r14,%r15,8), %rdx
movb %cl, (%rdx,%rax)
incq %rax
movslq 0xc(%rbx), %rcx
cmpq %rcx, %rax
jl 0x9598
cmpl $0x0, 0x10(%rbx)
jle 0x95d1
xorl %eax, %eax
movslq 0xc(%rbx), %rcx
addq (%r14,%r15,8), %rcx
movb $0x0, (%rax,%rcx)
incq %rax
cmpl 0x10(%rbx), %eax
jl 0x95bd
incq %r15
cmpq 0x28(%rsp), %r15
jne 0x957c
movl 0xc(%rbx), %edx
movq %r14, %rdi
movq 0x18(%rsp), %rsi
movl $0x1, %ecx
callq 0x319f
movl %eax, 0x14(%rsp)
shlq $0x2, %r13
movq %r13, %rdi
callq 0x21d0
movq %rax, %r13
testl %ebp, %ebp
jle 0x98b3
movl %ebp, %eax
movq %rax, 0x38(%rsp)
xorl %eax, %eax
movl $0x0, 0x8(%rsp)
movq %r13, 0x30(%rsp)
movq %r12, 0x40(%rsp)
movq %rax, 0x20(%rsp)
movq (%r12,%rax,8), %rax
cmpl $0x0, 0x8(%rax)
movl $0x0, %ebp
jle 0x9686
xorl %r15d, %r15d
xorl %ebp, %ebp
movq (%rax), %rax
movl (%rax,%r15,4), %edi
movq %rbx, %rsi
callq 0xc415
testl %eax, %eax
je 0x9659
movq 0x20(%rsp), %rax
jmp 0x9676
movq 0x20(%rsp), %rdx
movq (%r12,%rdx,8), %rax
movq (%rax), %rax
movl (%rax,%r15,4), %eax
movslq %ebp, %rcx
incl %ebp
movl %eax, (%r13,%rcx,4)
movq %rdx, %rax
incq %r15
movq (%r12,%rax,8), %rax
movslq 0x8(%rax), %rcx
cmpq %rcx, %r15
jl 0x963f
testl %ebp, %ebp
jle 0x9890
movl %ebp, %r15d
xorl %r12d, %r12d
leaq 0x1(%r12), %rcx
movslq %r15d, %rax
cmpq %rax, %rcx
movq %rcx, 0x48(%rsp)
jge 0x987f
movl %ecx, %r11d
movl 0x10(%rbx), %eax
testl %eax, %eax
jle 0x978e
movl %r15d, 0x10(%rsp)
movslq (%r13,%r12,4), %rcx
movq %rcx, 0x50(%rsp)
movl %r11d, 0xc(%rsp)
movslq %r11d, %rcx
movslq (%r13,%rcx,4), %r15
xorl %ebp, %ebp
movq 0x18(%rbx), %rcx
movq 0x50(%rsp), %r13
movslq (%rcx,%r13,4), %rcx
cltq
imulq %rcx, %rax
addq %rbp, %rax
movq (%r14,%rax,8), %rax
movslq 0xc(%rbx), %rcx
movb $0x1, %dl
movb %dl, (%rax,%rcx)
movslq 0x10(%rbx), %rax
movq 0x18(%rbx), %rcx
movslq (%rcx,%r15,4), %rcx
imulq %rax, %rcx
addq %rbp, %rcx
movq (%r14,%rcx,8), %rax
movslq 0xc(%rbx), %rcx
movb %dl, (%rax,%rcx)
movl 0xc(%rbx), %edx
incl %edx
movq %r14, %rdi
movq 0x18(%rsp), %rsi
movl $0x1, %ecx
callq 0x319f
movslq 0x10(%rbx), %rcx
movq 0x18(%rbx), %rdx
movslq (%rdx,%r13,4), %rdx
imulq %rcx, %rdx
addq %rbp, %rdx
movq (%r14,%rdx,8), %rcx
movslq 0xc(%rbx), %rdx
xorl %esi, %esi
movb %sil, (%rcx,%rdx)
movslq 0x10(%rbx), %rcx
movq 0x18(%rbx), %rdx
movslq (%rdx,%r15,4), %rdx
imulq %rcx, %rdx
addq %rbp, %rdx
movq (%r14,%rdx,8), %rcx
movslq 0xc(%rbx), %rdx
movb %sil, (%rcx,%rdx)
cmpl 0x14(%rsp), %eax
jle 0x9782
movl 0x10(%rbx), %eax
incq %rbp
cmpl %eax, %ebp
jl 0x96d6
movl 0x10(%rsp), %r15d
movl 0xc(%rsp), %r11d
jmp 0x9790
xorl %ebp, %ebp
cmpl 0x10(%rbx), %ebp
jge 0x986e
cmpl $0x0, 0x10(%rbx)
movq 0x30(%rsp), %r13
jle 0x981e
movslq %r11d, %rax
xorl %ecx, %ecx
cmpl %ebp, %ecx
je 0x9817
cmpl $0x0, 0xc(%rbx)
jle 0x9817
movslq (%r13,%rax,4), %rdx
xorl %esi, %esi
movl 0x10(%rbx), %edi
movq 0x18(%rbx), %r8
movl (%r8,%rdx,4), %r9d
imull %edi, %r9d
addl %ecx, %r9d
movslq %r9d, %r9
movq (%r14,%r9,8), %r9
movb (%r9,%rsi), %r9b
testb %r9b, %r9b
je 0x980b
movslq (%r13,%r12,4), %r10
imull (%r8,%r10,4), %edi
addl %ecx, %edi
movslq %edi, %rdi
movq (%r14,%rdi,8), %rdi
xorb %r9b, (%rdi,%rsi)
movq 0x18(%rbx), %rdi
movl (%rdi,%rdx,4), %edi
imull 0x10(%rbx), %edi
addl %ecx, %edi
movslq %edi, %rdi
movq (%r14,%rdi,8), %rdi
movb $0x0, (%rdi,%rsi)
incq %rsi
movslq 0xc(%rbx), %rdi
cmpq %rdi, %rsi
jl 0x97ba
incl %ecx
cmpl 0x10(%rbx), %ecx
jl 0x97a9
movl 0xc(%rbx), %edx
movq %r14, %rdi
movq 0x18(%rsp), %rsi
movl $0x1, %ecx
movl %r11d, %ebp
callq 0x319f
movl %ebp, %r11d
movl %eax, 0x14(%rsp)
decl %r15d
cmpl %r15d, %ebp
jge 0x9861
movslq %r11d, %rcx
movslq %r15d, %rax
movl 0x4(%r13,%rcx,4), %edx
movl %edx, (%r13,%rcx,4)
leaq 0x1(%rcx), %rdx
movq %rdx, %rcx
cmpq %rdx, %rax
jne 0x984b
decl %r11d
movl $0x1, 0x8(%rsp)
jmp 0x9873
movq 0x30(%rsp), %r13
incl %r11d
cmpl %r15d, %r11d
jl 0x96ad
movslq %r15d, %rax
movq 0x48(%rsp), %r12
cmpq %rax, %r12
jl 0x9694
movq 0x20(%rsp), %rax
incq %rax
cmpq 0x38(%rsp), %rax
movq 0x40(%rsp), %r12
jne 0x9626
cmpl $0x0, 0x8(%rsp)
sete %bpl
jmp 0x98b6
movb $0x1, %bpl
movq %r13, %rdi
callq 0x2030
movq (%rbx), %rdi
movl 0xc(%rbx), %ecx
movq %r14, %rsi
movq 0x18(%rsp), %r15
movl %r15d, %edx
callq 0x326a
movl %eax, %r12d
testl %r15d, %r15d
movq 0x28(%rsp), %r13
jle 0x98f5
xorl %r15d, %r15d
movq (%r14,%r15,8), %rdi
callq 0x2030
incq %r15
cmpq %r15, %r13
jne 0x98e4
movq %r14, %rdi
callq 0x2030
testb %bpl, %bpl
je 0x990a
xorl %ebp, %ebp
cmpl 0xc(%rbx), %r12d
je 0x995a
movl %r12d, 0xc(%rbx)
movl $0x1, %ebp
cmpb $0x0, 0x28(%rbx)
je 0x995a
movl 0x8(%rbx), %eax
cltd
idivl 0x10(%rbx)
testl %eax, %eax
jle 0x994d
xorl %r14d, %r14d
movq 0x20(%rbx), %rax
movq 0x30(%rbx), %rcx
movslq (%rax,%r14,4), %rax
movq (%rcx,%rax,8), %rdi
callq 0x9b36
movl 0x8(%rbx), %eax
cltd
idivl 0x10(%rbx)
incq %r14
cltq
cmpq %rax, %r14
jl 0x9927
movq 0x30(%rbx), %rdi
callq 0x2030
movb $0x0, 0x28(%rbx)
movl %ebp, %eax
addq $0x58, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
nop