// File: /workspace/github_c_makefile_star2_O2/cbouilla[P]AES-attacks-finder/SysEqLin.c
// Function: ExtraireEX
int ExtraireEX(unsigned char ** __restrict dst, int * __restrict var, const int N, SysEqLin E) // Calcul E(X) (sous forme de matrice)
{

	const int nombre_ligne_big_matrix = E->a;
	const int nombre_colone_big_matrix = E->b + E->gen*N;
	unsigned char ** __restrict big_matrix=malloc(nombre_ligne_big_matrix*sizeof(unsigned char *));
	unsigned char * __restrict espace_big_matrix=malloc(nombre_colone_big_matrix*nombre_ligne_big_matrix*sizeof(unsigned char));

	int i;
	for (i = 0; i < nombre_ligne_big_matrix; i++) big_matrix[i]=espace_big_matrix + i*nombre_colone_big_matrix;
	for (i = 0; i < nombre_ligne_big_matrix; i++)
	{
		int j;
		for (j = 0; j < E->b; j++) big_matrix[i][j]=E->mat[i][j];
		for (j = E->b; j < nombre_colone_big_matrix; j++) big_matrix[i][j]=0;
	}
	for (i = 0; i < N; i++)
	{
		if (E->lignevar[var[i]]<E->a/E->gen)
		{
			int j;
			for (j = 0; j < E->gen; j++) big_matrix[E->gen*E->lignevar[var[i]]+j][E->b+E->gen*i+j]=1;
		}
	}
	
	int dim = 0;
	const int colonne_max_pour_pivot = E->b;
	int * __restrict place_pivot = malloc(min(colonne_max_pour_pivot,nombre_ligne_big_matrix)*sizeof(int));
	int pivot_c;
	for (pivot_c = 0; pivot_c < colonne_max_pour_pivot; pivot_c++)
	{
		int new_pivot_l;
		for (new_pivot_l = dim; new_pivot_l < nombre_ligne_big_matrix; new_pivot_l++)
		{
			if (big_matrix[new_pivot_l][pivot_c])
			{
				if (new_pivot_l!=dim)
				{
					unsigned char *tmp = big_matrix[dim];
					big_matrix[dim]=big_matrix[new_pivot_l];
					big_matrix[new_pivot_l]=tmp;
				}
				place_pivot[dim]=pivot_c;
				const unsigned char inv = Inverse(big_matrix[dim][pivot_c]);
				int colonne;
				for (colonne = pivot_c; colonne < nombre_colone_big_matrix; colonne++) big_matrix[dim][colonne]=Multiply(inv,big_matrix[dim][colonne]);
				int ligne;
				for (ligne = 0; ligne < dim; ligne++)
				{
					if (big_matrix[ligne][pivot_c])
					{
						for (colonne = pivot_c+1; colonne < nombre_colone_big_matrix; colonne++)
						{
							big_matrix[ligne][colonne]^=Multiply(big_matrix[ligne][pivot_c],big_matrix[dim][colonne]);
						}
						big_matrix[ligne][pivot_c]=0;
					}
				}
				for (ligne = new_pivot_l+1; ligne < nombre_ligne_big_matrix; ligne++)
				{
					if (big_matrix[ligne][pivot_c])
					{
						for (colonne = pivot_c+1; colonne < nombre_colone_big_matrix; colonne++)
						{
							big_matrix[ligne][colonne]^=Multiply(big_matrix[ligne][pivot_c],big_matrix[dim][colonne]);
						}
						big_matrix[ligne][pivot_c]=0;
					}
				}
				dim++;
				break;
			}
		}
	}
	
	const int dim_save = dim;
	for (pivot_c = colonne_max_pour_pivot; pivot_c < nombre_colone_big_matrix; pivot_c++)
	{
		int new_pivot_l;
		for (new_pivot_l = dim; new_pivot_l < nombre_ligne_big_matrix; new_pivot_l++)
		{
			if (big_matrix[new_pivot_l][pivot_c])
			{
				if (new_pivot_l!=dim)
				{
					unsigned char *tmp = big_matrix[dim];
					big_matrix[dim]=big_matrix[new_pivot_l];
					big_matrix[new_pivot_l]=tmp;
				}
				const unsigned char inv = Inverse(big_matrix[dim][pivot_c]);
				int colonne;
				for (colonne = pivot_c; colonne < nombre_colone_big_matrix; colonne++) big_matrix[dim][colonne]=Multiply(inv,big_matrix[dim][colonne]);
				int ligne;
				for (ligne = 0; ligne < dim; ligne++)
				{
					if (big_matrix[ligne][pivot_c])
					{
						for (colonne = pivot_c+1; colonne < nombre_colone_big_matrix; colonne++)
						{
							big_matrix[ligne][colonne]^=Multiply(big_matrix[ligne][pivot_c],big_matrix[dim][colonne]);
						}
						big_matrix[ligne][pivot_c]=0;
					}
				}
				for (ligne = new_pivot_l+1; ligne < nombre_ligne_big_matrix; ligne++)
				{
					if (big_matrix[ligne][pivot_c])
					{
						for (colonne = pivot_c+1; colonne < nombre_colone_big_matrix; colonne++)
						{
							big_matrix[ligne][colonne]^=Multiply(big_matrix[ligne][pivot_c],big_matrix[dim][colonne]);
						}
						big_matrix[ligne][pivot_c]=0;
					}
				}
				dim++;
				break;
			}
		}
	}

	const int nombre_de_lignes_max = VARIABLES*E->gen;
	int pos = 0;
	int ligne;	
	int colonne = colonne_max_pour_pivot;
	for (ligne = dim_save; ligne < dim; ligne++)
	{
		while (colonne<nombre_colone_big_matrix && big_matrix[ligne][colonne]==0)
		{
			unsigned char premier = 0;
			int j;
			for (j = 0; j < dim_save; j++)
			{
				if (big_matrix[j][colonne])
				{
					int k;
					if (premier) for (k = 0; k < nombre_de_lignes_max; k++) dst[k][pos]^=Multiply(big_matrix[j][colonne],E->mat[k][place_pivot[j]]);
					else
					{
						for (k = 0; k < nombre_de_lignes_max; k++) dst[k][pos]=Multiply(big_matrix[j][colonne],E->mat[k][place_pivot[j]]);
						premier=1;
					}			
				}
			}
			if (premier) pos++;
			colonne++;
		}
		colonne++;
	}

	for (i = colonne; i < nombre_colone_big_matrix; i++)
	{
		unsigned char premier = 0;
		int j;
		for (j = 0; j < dim_save; j++)
		{
			if (big_matrix[j][i])
			{
				int k;
				if (premier) for (k = 0; k < nombre_de_lignes_max; k++) dst[k][pos]^=Multiply(big_matrix[j][i],E->mat[k][place_pivot[j]]);
				else
				{
					for (k = 0; k < nombre_de_lignes_max; k++) dst[k][pos]=Multiply(big_matrix[j][i],E->mat[k][place_pivot[j]]);
					premier=1;
				}			
			}
		}
		if (premier) pos++;
	}

	free(place_pivot);
	free(big_matrix);
	free(espace_big_matrix);

	return pos;	

	/* A améliorer */
	#if 0
	int ligne=VARIABLES*E->gen;
	unsigned char **m=malloc(ligne*sizeof(unsigned char *));
	int b1=(N+VARIABLES)*E->gen-E->a, i;
	for (i = 0; i < ligne; i++)
	{
		m[i]=malloc(b1*sizeof(unsigned char));
		int j;
		for (j = 0; j < b1; j++) m[i][j]=0;
	}
	int col=0;
	for (i = 0; i < N; i++)
	{
		int j;
		for (j = 0; j < E->gen; j++) m[E->gen*E->lignevar[var[i]]+j][col++]=1;
	}
	for (i = E->a; i < VARIABLES*E->gen; i++) m[i][col++]=1;
	int b=Intersection(dst,E->mat,E->b,m,ligne,b1);
	for (i = 0; i < ligne; i++) free(m[i]);
	free(m);
	return b;
	#endif
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x58, %rsp
movq %rcx, %rbx
movl %edx, %r13d
movq %rsi, %rbp
movq %rdi, %r14
movslq 0x8(%rcx), %rdx
movq %rdx, 0x18(%rsp)
movslq 0xc(%rcx), %rax
movslq 0x10(%rcx), %rcx
movslq %r13d, %r15
imulq %rcx, %r15
addq %rax, %r15
leaq (,%rdx,8), %rdi
callq 0x21c0
movq %rax, %r12
movl %r15d, %eax
imull 0x18(%rsp), %eax
movslq %eax, %rdi
callq 0x21c0
movq 0x18(%rsp), %r10
movq %r15, %r9
movq %rax, %rdx
xorl %ecx, %ecx
testl %r10d, %r10d
movl $0x0, %eax
cmovgl %r10d, %eax
movq %rdx, 0x50(%rsp)
cmpq %rcx, %rax
je 0xa6c8
movq %rdx, (%r12,%rcx,8)
incq %rcx
addq %r9, %rdx
jmp 0xa6b7
xorl %ecx, %ecx
cmpq %rax, %rcx
je 0xa707
xorl %edx, %edx
movslq 0xc(%rbx), %rsi
cmpq %rsi, %rdx
jge 0xa6fd
movq (%rbx), %rsi
movq (%rsi,%rcx,8), %rsi
movb (%rsi,%rdx), %sil
movq (%r12,%rcx,8), %rdi
movb %sil, (%rdi,%rdx)
incq %rdx
jmp 0xa6d1
movq (%r12,%rcx,8), %rdx
movb $0x0, (%rdx,%rsi)
incq %rsi
cmpq %r9, %rsi
jl 0xa6f2
incq %rcx
jmp 0xa6ca
xorl %ecx, %ecx
testl %r13d, %r13d
cmovlel %ecx, %r13d
cmpq %r13, %rcx
je 0xa768
movq 0x18(%rbx), %rax
movslq (%rbp,%rcx,4), %rsi
movl (%rax,%rsi,4), %r8d
movl 0x8(%rbx), %eax
movl 0x10(%rbx), %edi
cltd
idivl %edi
cmpl %eax, %r8d
jge 0xa763
xorl %eax, %eax
cmpl %edi, %eax
jge 0xa763
movq 0x18(%rbx), %rdx
movslq (%rdx,%rsi,4), %rdx
movslq %edi, %r8
imulq %rdx, %r8
addq %rax, %r8
movq (%r12,%r8,8), %rdx
imull %ecx, %edi
addl 0xc(%rbx), %edi
addl %eax, %edi
movslq %edi, %rdi
movb $0x1, (%rdx,%rdi)
movl 0x10(%rbx), %edi
incq %rax
jmp 0xa732
incq %rcx
jmp 0xa710
movq %r12, 0x10(%rsp)
movl 0xc(%rbx), %eax
movl %eax, 0x24(%rsp)
movslq %eax, %r15
cmpl %r10d, %r15d
movl %r10d, %eax
cmovll %r15d, %eax
movslq %eax, %rdi
shlq $0x2, %rdi
movq %r9, 0x30(%rsp)
callq 0x21c0
movq %r15, %r11
movq 0x30(%rsp), %r9
movq %rax, %r13
xorl %r12d, %r12d
testl %r11d, %r11d
movl $0x0, %edi
cmovgl %r11d, %edi
leaq 0xc85d(%rip), %rbp      # 0x17010
movq $0x0, 0x28(%rsp)
movq %r15, 0x48(%rsp)
movq %rdi, 0x40(%rsp)
cmpl %r9d, %r12d
movl %r9d, %r10d
cmovgl %r12d, %r10d
movslq 0x28(%rsp), %rcx
cmpq %rdi, %r12
je 0xa940
movq 0x10(%rsp), %rax
movq %rcx, %r8
leaq (%rax,%rcx,8), %rax
xorl %ecx, %ecx
movq 0x18(%rsp), %rsi
leaq (%r8,%rcx), %rdx
cmpq %rsi, %rdx
jge 0xa938
movq %rdx, 0x8(%rsp)
movq (%rax,%rcx,8), %rdx
cmpb $0x0, (%rdx,%r12)
jne 0xa813
incq %rcx
jmp 0xa7f1
movq %r10, 0x38(%rsp)
testl %ecx, %ecx
movq 0x10(%rsp), %rdi
je 0xa82d
movq (%rdi,%r8,8), %rsi
movq %rdx, (%rdi,%r8,8)
movq %rsi, (%rax,%rcx,8)
movl %r12d, (%r13,%r8,4)
movq (%rdi,%r8,8), %r15
movzbl (%r15,%r12), %edi
callq 0x2433
movzbl %al, %eax
shll $0x8, %eax
movq %r12, %rcx
movq 0x30(%rsp), %r9
movq 0x38(%rsp), %rdi
cmpq %rcx, %rdi
je 0xa86d
movzbl (%r15,%rcx), %edx
leaq (%rax,%rbp), %rsi
movb (%rdx,%rsi), %dl
movb %dl, (%r15,%rcx)
incq %rcx
jmp 0xa853
movq 0x28(%rsp), %rcx
testl %ecx, %ecx
movl $0x0, %eax
cmovgl %ecx, %eax
xorl %ecx, %ecx
movq 0x18(%rsp), %r10
movq 0x48(%rsp), %r11
cmpq %rax, %rcx
je 0xa8d1
movq 0x10(%rsp), %rdx
movq (%rdx,%rcx,8), %rdx
cmpb $0x0, (%rdx,%r12)
je 0xa8cc
movq %r12, %rsi
leal 0x1(%rsi), %edi
cmpl %edi, %r9d
jle 0xa8c7
movzbl (%rdx,%r12), %edi
movzbl 0x1(%r15,%rsi), %r8d
shll $0x8, %edi
addq %rbp, %rdi
movb (%r8,%rdi), %dil
xorb %dil, 0x1(%rdx,%rsi)
incq %rsi
jmp 0xa8a0
movb $0x0, (%rdx,%r12)
incq %rcx
jmp 0xa888
movq 0x8(%rsp), %rdx
leaq 0x1(%rdx), %rax
cmpq %r10, %rax
jge 0xa927
movq 0x10(%rsp), %rcx
movq 0x8(%rcx,%rdx,8), %rcx
cmpb $0x0, (%rcx,%r12)
movq %rax, %rdx
je 0xa8d6
movq %r12, %rdx
leal 0x1(%rdx), %esi
cmpl %esi, %r9d
jle 0xa91d
movzbl (%rcx,%r12), %esi
movzbl 0x1(%r15,%rdx), %edi
shll $0x8, %esi
addq %rbp, %rsi
movb (%rdi,%rsi), %sil
xorb %sil, 0x1(%rcx,%rdx)
incq %rdx
jmp 0xa8f6
movb $0x0, (%rcx,%r12)
movq %rax, %rdx
jmp 0xa8d6
movq 0x28(%rsp), %rax
incl %eax
movq %rax, 0x28(%rsp)
movq 0x40(%rsp), %rdi
incq %r12
jmp 0xa7c6
movq %rcx, 0x40(%rsp)
leaq 0x1(%r11), %rax
movq %rax, 0x8(%rsp)
movq 0x28(%rsp), %rax
movl %eax, %edi
movq 0x18(%rsp), %r10
movslq %edi, %rcx
cmpq %r9, %r11
jge 0xaaa6
movq 0x10(%rsp), %rax
leaq (%rax,%rcx,8), %rax
xorl %edx, %edx
leaq (%rcx,%rdx), %r12
cmpq %r10, %r12
jge 0xaa99
movq (%rax,%rdx,8), %rsi
cmpb $0x0, (%rsi,%r11)
jne 0xa98e
incq %rdx
jmp 0xa971
movl %edi, 0x38(%rsp)
testl %edx, %edx
movq 0x10(%rsp), %r8
je 0xa9a7
movq (%r8,%rcx,8), %rdi
movq %rsi, (%r8,%rcx,8)
movq %rdi, (%rax,%rdx,8)
movq (%r8,%rcx,8), %r15
movzbl (%r15,%r11), %edi
movq %r11, 0x48(%rsp)
callq 0x2433
movq 0x48(%rsp), %r11
movzbl %al, %eax
shll $0x8, %eax
movq %r11, %rcx
movq 0x30(%rsp), %r9
cmpq %r9, %rcx
jge 0xa9e7
movzbl (%r15,%rcx), %edx
leaq (%rax,%rbp), %rsi
movb (%rdx,%rsi), %dl
movb %dl, (%r15,%rcx)
incq %rcx
jmp 0xa9cd
movl 0x38(%rsp), %ecx
testl %ecx, %ecx
movl $0x0, %eax
cmovgl %ecx, %eax
xorl %ecx, %ecx
movq 0x18(%rsp), %r10
cmpq %rax, %rcx
je 0xaa89
movq 0x10(%rsp), %rdx
movq (%rdx,%rcx,8), %rdx
cmpb $0x0, (%rdx,%r11)
je 0xaa41
movq 0x8(%rsp), %rsi
cmpq %r9, %rsi
jge 0xaa3c
movzbl (%rdx,%r11), %edi
movzbl (%r15,%rsi), %r8d
shll $0x8, %edi
addq %rbp, %rdi
movb (%r8,%rdi), %dil
xorb %dil, (%rdx,%rsi)
incq %rsi
jmp 0xaa1a
movb $0x0, (%rdx,%r11)
incq %rcx
jmp 0xa9fc
movq 0x10(%rsp), %rcx
movq 0x8(%rcx,%r12,8), %rcx
cmpb $0x0, (%rcx,%r11)
movq %rax, %r12
je 0xaa89
movq 0x8(%rsp), %rdx
cmpq %r9, %rdx
jge 0xaa81
movzbl (%rcx,%r11), %esi
movzbl (%r15,%rdx), %edi
shll $0x8, %esi
addq %rbp, %rsi
movb (%rdi,%rsi), %sil
xorb %sil, (%rcx,%rdx)
incq %rdx
jmp 0xaa5f
movb $0x0, (%rcx,%r11)
movq %rax, %r12
leaq 0x1(%r12), %rax
cmpq %r10, %rax
jl 0xaa46
movl 0x38(%rsp), %edi
incl %edi
incq %r11
incq 0x8(%rsp)
jmp 0xa95a
movq %rcx, 0x18(%rsp)
leaq 0x25806(%rip), %rdx     # 0x302b8
movl 0x10(%rbx), %eax
imull (%rdx), %eax
xorl %edx, %edx
testl %eax, %eax
cmovlel %edx, %eax
movq 0x28(%rsp), %r12
testl %r12d, %r12d
movl $0x0, %ecx
movq %rcx, 0x8(%rsp)
cmovlel %edx, %r12d
movl 0x24(%rsp), %edx
movq 0x40(%rsp), %rsi
cmpq 0x18(%rsp), %rsi
jge 0xabe8
movq %rsi, %rcx
movl %edx, %esi
movslq %edx, %rdx
cmpl %r9d, %edx
cmovlel %r9d, %esi
movl %esi, 0x24(%rsp)
cmpq %r9, %rdx
jge 0xabd5
movq 0x10(%rsp), %rsi
movq (%rsi,%rcx,8), %rsi
cmpb $0x0, (%rsi,%rdx)
jne 0xabdb
movslq 0x8(%rsp), %rsi
xorl %edi, %edi
xorl %r9d, %r9d
cmpq %r12, %rdi
je 0xabb7
movq 0x10(%rsp), %r8
movq (%r8,%rdi,8), %r8
cmpb $0x0, (%r8,%rdx)
je 0xabaf
testb %r9b, %r9b
je 0xab76
xorl %r9d, %r9d
cmpq %r9, %rax
je 0xabac
movzbl (%r8,%rdx), %r10d
movq (%rbx), %r11
movq (%r11,%r9,8), %r11
movslq (%r13,%rdi,4), %r15
movzbl (%r11,%r15), %r11d
shll $0x8, %r10d
addq %rbp, %r10
movb (%r11,%r10), %r10b
movq (%r14,%r9,8), %r11
xorb %r10b, (%r11,%rsi)
incq %r9
jmp 0xab43
xorl %r9d, %r9d
cmpq %r9, %rax
je 0xabac
movzbl (%r8,%rdx), %r10d
movq (%rbx), %r11
movq (%r11,%r9,8), %r11
movslq (%r13,%rdi,4), %r15
movzbl (%r11,%r15), %r11d
shll $0x8, %r10d
addq %rbp, %r10
movb (%r11,%r10), %r10b
movq (%r14,%r9,8), %r11
movb %r10b, (%r11,%rsi)
incq %r9
jmp 0xab79
movb $0x1, %r9b
incq %rdi
jmp 0xab22
cmpb $0x1, %r9b
movq 0x8(%rsp), %rsi
sbbl $-0x1, %esi
movq %rsi, 0x8(%rsp)
incq %rdx
movq 0x30(%rsp), %r9
jmp 0xaafc
movl 0x24(%rsp), %edx
jmp 0xabdb
incl %edx
movq %rcx, %rsi
incq %rsi
jmp 0xaade
movslq %edx, %rcx
cmpq %r9, %rcx
jge 0xacb0
movslq 0x8(%rsp), %rdx
xorl %esi, %esi
xorl %r8d, %r8d
cmpq %r12, %rsi
je 0xac97
movq 0x10(%rsp), %rdi
movq (%rdi,%rsi,8), %rdi
cmpb $0x0, (%rdi,%rcx)
je 0xac8f
testb %r8b, %r8b
je 0xac51
xorl %r8d, %r8d
cmpq %r8, %rax
je 0xac87
movzbl (%rdi,%rcx), %r9d
movq (%rbx), %r10
movq (%r10,%r8,8), %r10
movslq (%r13,%rsi,4), %r11
movzbl (%r10,%r11), %r10d
shll $0x8, %r9d
addq %rbp, %r9
movb (%r10,%r9), %r9b
movq (%r14,%r8,8), %r10
xorb %r9b, (%r10,%rdx)
incq %r8
jmp 0xac1e
xorl %r8d, %r8d
cmpq %r8, %rax
je 0xac87
movzbl (%rdi,%rcx), %r9d
movq (%rbx), %r10
movq (%r10,%r8,8), %r10
movslq (%r13,%rsi,4), %r11
movzbl (%r10,%r11), %r10d
shll $0x8, %r9d
addq %rbp, %r9
movb (%r10,%r9), %r9b
movq (%r14,%r8,8), %r10
movb %r9b, (%r10,%rdx)
incq %r8
jmp 0xac54
movb $0x1, %r8b
movq 0x30(%rsp), %r9
incq %rsi
jmp 0xabfe
cmpb $0x1, %r8b
movq 0x8(%rsp), %rdx
sbbl $-0x1, %edx
movq %rdx, 0x8(%rsp)
incq %rcx
jmp 0xabeb
movq %r13, %rdi
callq 0x2030
movq 0x10(%rsp), %rdi
callq 0x2030
movq 0x50(%rsp), %rdi
callq 0x2030
movq 0x8(%rsp), %rax
addq $0x58, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq