// File: /workspace/github_c_makefile_star2_O2/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
movq %rsi, 0x20(%rsp)
movq %rdi, 0x38(%rsp)
movslq 0x10(%rdx), %rbp
leaq 0x27786(%rip), %rax     # 0x302b8
movslq (%rax), %r12
movq %rbp, %r13
imulq %r12, %r13
movq %r13, %rdi
shlq $0x3, %rdi
callq 0x21c0
movq %rax, %r14
xorl %r15d, %r15d
testl %r13d, %r13d
movl $0x0, %eax
movq %r13, 0x18(%rsp)
cmovgl %r13d, %eax
movq %rax, 0x30(%rsp)
movl 0xc(%rbx), %r13d
cmpq 0x30(%rsp), %r15
je 0x8bc1
addl %r13d, %ebp
movslq %ebp, %rdi
callq 0x21c0
movq %rax, (%r14,%r15,8)
xorl %eax, %eax
movslq %r13d, %rcx
cmpq %rcx, %rax
jge 0x8ba2
movq (%rbx), %rcx
movq (%rcx,%r15,8), %rcx
movb (%rcx,%rax), %cl
movq (%r14,%r15,8), %rdx
movb %cl, (%rdx,%rax)
incq %rax
movl 0xc(%rbx), %r13d
jmp 0x8b80
xorl %eax, %eax
movl 0x10(%rbx), %ebp
cmpl %ebp, %eax
jge 0x8bbc
movslq 0xc(%rbx), %rcx
addq (%r14,%r15,8), %rcx
movb $0x0, (%rax,%rcx)
incq %rax
jmp 0x8ba4
incq %r15
jmp 0x8b64
pushq $0x1
popq %rcx
movq %r14, %rdi
movq 0x18(%rsp), %rsi
movl %r13d, %edx
callq 0x2e41
movl %eax, 0x14(%rsp)
shlq $0x2, %r12
movq %r12, %rdi
callq 0x21c0
xorl %edx, %edx
movq 0x20(%rsp), %rcx
testl %ecx, %ecx
cmovlel %edx, %ecx
movq %rcx, 0x20(%rsp)
movq %rax, %r12
xorl %eax, %eax
movl $0x0, 0xc(%rsp)
cmpq 0x20(%rsp), %rax
je 0x8e57
movq %rax, 0x28(%rsp)
xorl %r15d, %r15d
movl $0x0, 0x8(%rsp)
movq 0x38(%rsp), %rax
movq 0x28(%rsp), %rcx
movq (%rax,%rcx,8), %rax
movslq 0x8(%rax), %rcx
cmpq %rcx, %r15
jge 0x8c72
movq (%rax), %rax
movl (%rax,%r15,4), %edi
movq %rbx, %rsi
callq 0xb528
testl %eax, %eax
jne 0x8c6d
movq 0x38(%rsp), %rax
movq 0x28(%rsp), %rcx
movq (%rax,%rcx,8), %rax
movq (%rax), %rax
movl (%rax,%r15,4), %eax
movl 0x8(%rsp), %edx
movslq %edx, %rcx
incl %edx
movl %edx, 0x8(%rsp)
movl %eax, (%r12,%rcx,4)
incq %r15
jmp 0x8c1d
xorl %r13d, %r13d
movslq 0x8(%rsp), %rax
cmpq %rax, %r13
jge 0x8e4a
leaq 0x1(%r13), %rax
movq %rax, 0x48(%rsp)
movl %eax, %ecx
movq %r13, 0x40(%rsp)
cmpl 0x8(%rsp), %ecx
jge 0x8e40
movl %ecx, 0x10(%rsp)
movslq %ecx, %r15
xorl %r10d, %r10d
movl 0x10(%rbx), %ecx
cmpl %ecx, %r10d
jge 0x8d78
movslq %ecx, %rax
movq 0x18(%rbx), %rcx
movslq (%r12,%r13,4), %rbp
movslq (%rcx,%rbp,4), %rcx
imulq %rax, %rcx
addq %r10, %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 (%r12,%r15,4), %rsi
movq %rsi, 0x50(%rsp)
movslq (%rcx,%rsi,4), %rcx
imulq %rax, %rcx
addq %r10, %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
pushq $0x1
popq %rcx
movq %r10, %r13
callq 0x2e41
movq %r13, %r10
movslq 0x10(%rbx), %rcx
movq 0x18(%rbx), %rdx
movslq (%rdx,%rbp,4), %rdx
imulq %rcx, %rdx
addq %r13, %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
movq 0x50(%rsp), %rdi
movslq (%rdx,%rdi,4), %rdx
imulq %rcx, %rdx
addq %r13, %rdx
movq (%r14,%rdx,8), %rcx
movslq 0xc(%rbx), %rdx
movb %sil, (%rcx,%rdx)
cmpl 0x14(%rsp), %eax
jle 0x8d70
incq %r10
movq 0x40(%rsp), %r13
jmp 0x8ca7
movl 0x10(%rbx), %ecx
movq 0x40(%rsp), %r13
cmpl %ecx, %r10d
jge 0x8df0
xorl %eax, %eax
cmpl %ecx, %eax
jge 0x8df6
cmpl %eax, %r10d
jne 0x8d8c
incl %eax
jmp 0x8d7f
xorl %edx, %edx
movslq 0xc(%rbx), %rsi
movl 0x10(%rbx), %ecx
cmpq %rsi, %rdx
jge 0x8d88
movq 0x18(%rbx), %rdi
movslq (%r12,%r15,4), %rsi
movl (%rdi,%rsi,4), %r8d
imull %ecx, %r8d
addl %eax, %r8d
movslq %r8d, %r8
movq (%r14,%r8,8), %r8
movb (%r8,%rdx), %r8b
testb %r8b, %r8b
je 0x8deb
movslq (%r12,%r13,4), %r9
imull (%rdi,%r9,4), %ecx
addl %eax, %ecx
movslq %ecx, %rcx
movq (%r14,%rcx,8), %rcx
xorb %r8b, (%rcx,%rdx)
movq 0x18(%rbx), %rcx
movl (%rcx,%rsi,4), %ecx
imull 0x10(%rbx), %ecx
addl %eax, %ecx
movslq %ecx, %rcx
movq (%r14,%rcx,8), %rcx
movb $0x0, (%rcx,%rdx)
incq %rdx
jmp 0x8d8e
movl 0x10(%rsp), %ecx
jmp 0x8e39
movl 0xc(%rbx), %edx
movq %r14, %rdi
movq 0x18(%rsp), %rsi
pushq $0x1
popq %rcx
callq 0x2e41
movl %eax, 0x14(%rsp)
movl 0x8(%rsp), %eax
decl %eax
movl %eax, 0x8(%rsp)
cltq
cmpq %rax, %r15
jge 0x8e2c
movl 0x4(%r12,%r15,4), %ecx
movl %ecx, (%r12,%r15,4)
incq %r15
jmp 0x8e19
movl 0x10(%rsp), %ecx
decl %ecx
pushq $0x1
popq %rax
movl %eax, 0xc(%rsp)
incl %ecx
jmp 0x8c93
movq 0x48(%rsp), %r13
jmp 0x8c75
movq 0x28(%rsp), %rax
incq %rax
jmp 0x8c02
movq %r12, %rdi
callq 0x2030
movq (%rbx), %rdi
movl 0xc(%rbx), %ecx
movq %r14, %rsi
movq 0x18(%rsp), %rdx
callq 0x2f18
movl %eax, %r15d
xorl %r12d, %r12d
cmpq %r12, 0x30(%rsp)
je 0x8e8d
movq (%r14,%r12,8), %rdi
callq 0x2030
incq %r12
jmp 0x8e78
movq %r14, %rdi
callq 0x2030
cmpl $0x0, 0xc(%rsp)
jne 0x8ea4
xorl %ebp, %ebp
cmpl 0xc(%rbx), %r15d
je 0x8ee5
movl %r15d, 0xc(%rbx)
pushq $0x1
popq %rbp
cmpb $0x0, 0x28(%rbx)
je 0x8ee5
xorl %r14d, %r14d
movl 0x8(%rbx), %eax
cltd
idivl 0x10(%rbx)
cltq
movq 0x30(%rbx), %rdi
cmpq %rax, %r14
jge 0x8edc
movq 0x20(%rbx), %rax
movslq (%rax,%r14,4), %rax
movq (%rdi,%rax,8), %rdi
callq 0x90c6
incq %r14
jmp 0x8eb4
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