// File: /workspace/github_c_makefile_star2_O3/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 $0x48, %rsp
movq %rdx, %rbx
movl %esi, (%rsp)
movq %rdi, 0x38(%rsp)
movslq 0x10(%rdx), %r12
leaq 0x28a91(%rip), %rax     # 0x322b8
movslq (%rax), %r13
movq %r13, %r15
imulq %r12, %r15
movq %r15, %rdi
shlq $0x3, %rdi
callq 0x21d0
movq %rax, %r14
movl %r15d, %eax
movq %rax, 0x18(%rsp)
movq %r15, 0x10(%rsp)
testl %r15d, %r15d
jle 0x98bb
xorl %r15d, %r15d
movl 0xc(%rbx), %ebp
leal (%r12,%rbp), %eax
movslq %eax, %rdi
callq 0x21d0
movq %rax, (%r14,%r15,8)
testl %ebp, %ebp
jle 0x988f
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 0x986e
movl 0x10(%rbx), %r12d
testl %r12d, %r12d
movq 0x18(%rsp), %rdx
jle 0x98b3
xorl %eax, %eax
movslq 0xc(%rbx), %rcx
addq (%r14,%r15,8), %rcx
movb $0x0, (%rax,%rcx)
movl 0x10(%rbx), %r12d
incq %rax
cmpl %r12d, %eax
jl 0x989b
incq %r15
cmpq %rdx, %r15
jne 0x9855
movl 0xc(%rbx), %edx
movq %r14, %rdi
movq 0x10(%rsp), %rsi
movl $0x1, %ecx
callq 0x34b3
movl %eax, 0xc(%rsp)
shlq $0x2, %r13
movq %r13, %rdi
callq 0x21d0
movq %rax, %r13
movl (%rsp), %eax
testl %eax, %eax
jle 0x9b78
movl %eax, %eax
movq %rax, 0x30(%rsp)
xorl %eax, %eax
movl $0x0, 0x4(%rsp)
movq %r13, 0x28(%rsp)
movq 0x38(%rsp), %r12
movq %rax, 0x20(%rsp)
movq (%r12,%rax,8), %rcx
cmpl $0x0, 0x8(%rcx)
jle 0x9b5a
xorl %r15d, %r15d
xorl %ebp, %ebp
movq (%rcx), %rax
movl (%rax,%r15,4), %edi
movq %rbx, %rsi
callq 0xc7ef
movq 0x20(%rsp), %rcx
movq (%r12,%rcx,8), %rcx
testl %eax, %eax
jne 0x994e
movq (%rcx), %rax
movl (%rax,%r15,4), %eax
movslq %ebp, %rdx
incl %ebp
movl %eax, (%r13,%rdx,4)
incq %r15
movslq 0x8(%rcx), %rax
cmpq %rax, %r15
jl 0x9921
testl %ebp, %ebp
jle 0x9b5a
movl %ebp, %r15d
xorl %ecx, %ecx
movq %rcx, %r12
incq %rcx
movslq %r15d, %rax
cmpq %rax, %rcx
jge 0x9b51
movq %rcx, 0x40(%rsp)
movl %ecx, %r11d
movl 0x10(%rbx), %edx
testl %edx, %edx
jle 0x9a5c
movl %r15d, (%rsp)
movslq (%r13,%r12,4), %r15
movl %r11d, 0x8(%rsp)
movslq %r11d, %rax
movslq (%r13,%rax,4), %r13
xorl %ebp, %ebp
movq 0x18(%rbx), %rax
movslq (%rax,%r15,4), %rax
movslq %edx, %rcx
imulq %rax, %rcx
addq %rbp, %rcx
movq (%r14,%rcx,8), %rax
movslq 0xc(%rbx), %rcx
movb $0x1, %dl
movb %dl, (%rax,%rcx)
movslq 0x10(%rbx), %rax
movq 0x18(%rbx), %rcx
movslq (%rcx,%r13,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 0x10(%rsp), %rsi
movl $0x1, %ecx
callq 0x34b3
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
xorl %esi, %esi
movb %sil, (%rcx,%rdx)
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
movb %sil, (%rcx,%rdx)
movl 0x10(%rbx), %edx
cmpl 0xc(%rsp), %eax
jle 0x9a4c
incq %rbp
cmpl %edx, %ebp
jl 0x99a4
movq 0x28(%rsp), %r13
movl (%rsp), %r15d
movl 0x8(%rsp), %r11d
jmp 0x9a5e
xorl %ebp, %ebp
cmpl %edx, %ebp
jge 0x9b3d
testl %edx, %edx
jle 0x9aef
movslq %r11d, %rax
xorl %ecx, %ecx
cmpl %ebp, %ecx
je 0x9ae9
movl 0xc(%rbx), %edi
testl %edi, %edi
jle 0x9ae9
movslq (%r13,%rax,4), %rdx
xorl %esi, %esi
movl 0x10(%rbx), %r8d
movq 0x18(%rbx), %r9
movl (%r9,%rdx,4), %r10d
imull %r8d, %r10d
addl %ecx, %r10d
movslq %r10d, %r10
movq (%r14,%r10,8), %r10
movb (%r10,%rsi), %r10b
testb %r10b, %r10b
je 0x9adb
movslq (%r13,%r12,4), %rdi
imull (%r9,%rdi,4), %r8d
addl %ecx, %r8d
movslq %r8d, %rdi
movq (%r14,%rdi,8), %rdi
xorb %r10b, (%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)
movl 0xc(%rbx), %edi
incq %rsi
movslq %edi, %r8
cmpq %r8, %rsi
jl 0x9a85
movl 0x10(%rbx), %edx
incl %ecx
cmpl %edx, %ecx
jl 0x9a73
movl 0xc(%rbx), %edx
movq %r14, %rdi
movq 0x10(%rsp), %rsi
movl $0x1, %ecx
movl %r11d, %ebp
callq 0x34b3
movl %ebp, %r11d
movl %eax, 0xc(%rsp)
decl %r15d
cmpl %r15d, %ebp
jge 0x9b32
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 0x9b1c
decl %r11d
movl $0x1, 0x4(%rsp)
incl %r11d
cmpl %r15d, %r11d
jl 0x9981
movslq %r15d, %rax
movq 0x40(%rsp), %rcx
cmpq %rax, %rcx
jl 0x9967
movq 0x20(%rsp), %rax
incq %rax
cmpq 0x30(%rsp), %rax
jne 0x9904
cmpl $0x0, 0x4(%rsp)
sete %bpl
jmp 0x9b7b
movb $0x1, %bpl
movq %r13, %rdi
callq 0x2030
movq (%rbx), %rdi
movl 0xc(%rbx), %ecx
movq %r14, %rsi
movq 0x10(%rsp), %r15
movl %r15d, %edx
callq 0x357e
movl %eax, %r12d
testl %r15d, %r15d
movq 0x18(%rsp), %r13
jle 0x9bba
xorl %r15d, %r15d
movq (%r14,%r15,8), %rdi
callq 0x2030
incq %r15
cmpq %r15, %r13
jne 0x9ba9
movq %r14, %rdi
callq 0x2030
testb %bpl, %bpl
je 0x9bcf
xorl %ebp, %ebp
cmpl 0xc(%rbx), %r12d
je 0x9c1f
movl %r12d, 0xc(%rbx)
movl $0x1, %ebp
cmpb $0x0, 0x28(%rbx)
je 0x9c1f
movl 0x8(%rbx), %eax
cltd
idivl 0x10(%rbx)
testl %eax, %eax
jle 0x9c12
xorl %r14d, %r14d
movq 0x20(%rbx), %rax
movq 0x30(%rbx), %rcx
movslq (%rax,%r14,4), %rax
movq (%rcx,%rax,8), %rdi
callq 0x9e08
movl 0x8(%rbx), %eax
cltd
idivl 0x10(%rbx)
incq %r14
cltq
cmpq %rax, %r14
jl 0x9bec
movq 0x30(%rbx), %rdi
callq 0x2030
movb $0x0, 0x28(%rbx)
movl %ebp, %eax
addq $0x48, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq