// File: manschga[P]M5GB/main.cpp
// Function: main
int main(int argc, char *argv[])
{
  int n = 20;
  int d = 10;
  binom_table = Create_binom_table(n+d,n+d);
  cout << "binom table created!" << endl;
  table = Create_table(n,d); //check, maybe neednot d = n!
  cout << "size: " << table.size() << endl;
  int p = 2;
  //const string input_file("Examples/medium_ideal.txt");
  //const string input_file("Examples/test_ideal.txt");
  //const string input_file("Examples/small_test.txt");
  //const string input_file("Examples/test_ideal_orig.txt");
  //const string input_file("Examples/example_2.txt");
  //const string input_file("Examples/big_example.txt");
  const string input_file("Examples/n_20.txt");
  //const string input_file("Examples/ToyExample-type4-n10-seed3");
  //const string input_file("Examples/ToyExample-type4-n15-seed0");
  //const string input_file("katsura_4.txt");
  //const string input_file("Examples/example_31.txt");

  vector<polynomial> system_ = Create_poly_system(input_file,n,p);
  //#define PRINT
  
  #ifdef PRINT
  cout << "Polynomials before reduce:" << endl;
  for (int i = 0; i < system_.size(); ++i)
    {
      vector<vector<int>> poly_i = vec_from_poly(system_[i],n);
	for (int j = 0; j < poly_i.size(); ++j)
	  {
	    bool is_zero = true;
	    for (int k = 0; k < poly_i[j].size(); ++k)
	      {
		if ((poly_i[j])[k]>0 )
		{
		  is_zero = false;
		  cout << char(97+k) << (poly_i[j])[k];
		//		    cout << "x_" << k+1 << "^" << ((poly_i[j])[k] );
		}
	      }
	    if (is_zero)
	      cout << "1";
	    if (j < poly_i.size()-1)
	    cout << "+";
	  }
      //      cout << basis[i] << endl;
	cout << "," << endl;
    }
  #endif

  cout << "M5GB start!!!!!" << endl << endl;

  
  //  Basis solution = M5GB(system_,n);
    
  vector<polynomial> basis = M5GB(system_,n);//Poly(solution,n,p); //remove signatures

  
  /*
  //cout << "not reduced basis:" << endl;
  for (int i = 0; i < basis.size(); ++i)
    {
      basis[i].update();
      //cout << basis[i] << endl;
    }

  int size = 0;
  int size_before = 1;
  size = 0;
  size_before = 1;
  while(size != size_before)
    {
      size_before = basis.size();
      reduce(basis); //get the (unique) reduced gröbner basis
      //cout << "in here! " << endl;
      size = basis.size();//maybe the size drops
    }
  sort(basis);
  */

  sort(basis);
  ///*
  cout << "Gröbner Basis polynomials:" << endl;
  for (int i = 0; i < basis.size(); ++i)
    {
      vector<vector<int>> poly_i = vec_from_poly(basis[i],n);
      for (int j = 0; j < poly_i.size(); ++j)
	  {
	    bool is_zero = true;
	    cout << basis[i].Get_monomials()[j].Get_coeff();
	    for (int k = 0; k < poly_i[j].size(); ++k)
	      {
		if ((poly_i[j])[k]>0 )
		{
		  is_zero = false;
		  cout << char(97+k) << (poly_i[j])[k];
		//		    cout << "x_" << k+1 << "^" << ((poly_i[j])[k] );
		}
	      }
	    if (is_zero)
	      cout << "1";
	    if (j < poly_i.size()-1)
	    cout << "+";
	  }
	cout << "," << endl;
    }
  //*/
 

  //cout << "basis size:" << basis.size() << endl;

     return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x180, %rsp            # imm = 0x180
movl $0x0, -0x4(%rbp)
movl %edi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movl $0x14, -0x14(%rbp)
movl $0xa, -0x18(%rbp)
movl -0x14(%rbp), %edx
movl -0x18(%rbp), %eax
addl %eax, %edx
leaq -0x30(%rbp), %rdi
movq %rdi, -0x120(%rbp)
movl %edx, %esi
callq 0x5140
movq -0x120(%rbp), %rsi
leaq 0x3d7b9(%rip), %rdi     # 0x401f8
callq 0x2f80
movq -0x120(%rbp), %rdi
callq 0x2fb0
movq 0x3d581(%rip), %rdi     # 0x3ffd8
movq %rdi, -0x110(%rbp)
leaq 0x2859f(%rip), %rsi     # 0x2b004
callq 0x2190
movq %rax, %rdi
movq 0x3d554(%rip), %rsi     # 0x3ffc8
movq %rsi, -0xf8(%rbp)
callq 0x21d0
movl -0x14(%rbp), %esi
movl -0x18(%rbp), %edx
leaq -0x48(%rbp), %rdi
movq %rdi, -0x118(%rbp)
callq 0x5900
movq -0x118(%rbp), %rsi
leaq 0x3d73c(%rip), %rdi     # 0x401e0
movq %rdi, -0x108(%rbp)
callq 0x3010
movq -0x118(%rbp), %rdi
callq 0x3040
movq -0x110(%rbp), %rdi
leaq 0x28644(%rip), %rsi     # 0x2b10e
callq 0x2190
movq -0x108(%rbp), %rdi
movq %rax, -0x100(%rbp)
callq 0x30a0
movq -0x100(%rbp), %rdi
movq %rax, %rsi
callq 0x2070
movq -0xf8(%rbp), %rsi
movq %rax, %rdi
callq 0x21d0
movl $0x2, -0x4c(%rbp)
leaq -0x71(%rbp), %rdi
movq %rdi, -0xf0(%rbp)
callq 0x2310
movq -0xf0(%rbp), %rdx
leaq 0x284f4(%rip), %rsi     # 0x2b019
leaq -0x70(%rbp), %rdi
callq 0x30d0
jmp 0x2b30
leaq -0x71(%rbp), %rdi
callq 0x21f0
movl -0x14(%rbp), %edx
movl -0x4c(%rbp), %ecx
leaq -0xa0(%rbp), %rdi
leaq -0x70(%rbp), %rsi
callq 0x26440
jmp 0x2b51
movq 0x3d480(%rip), %rdi     # 0x3ffd8
leaq 0x284cc(%rip), %rsi     # 0x2b02b
callq 0x2190
movq %rax, -0x128(%rbp)
jmp 0x2b6d
movq -0x128(%rbp), %rdi
movq 0x3d44d(%rip), %rsi     # 0x3ffc8
callq 0x21d0
movq %rax, -0x130(%rbp)
jmp 0x2b89
movq -0x130(%rbp), %rdi
movq 0x3d431(%rip), %rsi     # 0x3ffc8
callq 0x21d0
jmp 0x2b9e
movl -0x14(%rbp), %edx
leaq -0xb8(%rbp), %rdi
leaq -0xa0(%rbp), %rsi
callq 0x10870
jmp 0x2bb6
leaq -0xb8(%rbp), %rdi
callq 0x27190
jmp 0x2bc4
movq 0x3d40d(%rip), %rdi     # 0x3ffd8
leaq 0x28469(%rip), %rsi     # 0x2b03b
callq 0x2190
movq %rax, -0x138(%rbp)
jmp 0x2be0
movq -0x138(%rbp), %rdi
movq 0x3d3da(%rip), %rsi     # 0x3ffc8
callq 0x21d0
jmp 0x2bf5
movl $0x0, -0xbc(%rbp)
movslq -0xbc(%rbp), %rax
movq %rax, -0x140(%rbp)
leaq -0xb8(%rbp), %rdi
callq 0x3180
movq %rax, %rcx
movq -0x140(%rbp), %rax
cmpq %rcx, %rax
jae 0x2f13
movslq -0xbc(%rbp), %rsi
leaq -0xb8(%rbp), %rdi
callq 0x31a0
movq %rax, %rsi
movl -0x14(%rbp), %edx
leaq -0xd8(%rbp), %rdi
callq 0x26820
jmp 0x2c53
movl $0x0, -0xdc(%rbp)
movslq -0xdc(%rbp), %rax
movq %rax, -0x148(%rbp)
leaq -0xd8(%rbp), %rdi
callq 0x31c0
movq %rax, %rcx
movq -0x148(%rbp), %rax
cmpq %rcx, %rax
jae 0x2ec2
movb $0x1, -0xdd(%rbp)
movslq -0xbc(%rbp), %rsi
leaq -0xb8(%rbp), %rdi
callq 0x31a0
movq %rax, %rdi
callq 0x31f0
movq %rax, -0x150(%rbp)
jmp 0x2cb5
movq -0x150(%rbp), %rdi
movslq -0xdc(%rbp), %rsi
callq 0x3200
movq %rax, %rdi
callq 0x3220
movl %eax, -0x154(%rbp)
jmp 0x2cd8
movl -0x154(%rbp), %esi
movq 0x3d2f3(%rip), %rdi     # 0x3ffd8
callq 0x22f0
jmp 0x2cec
movl $0x0, -0xe4(%rbp)
movslq -0xe4(%rbp), %rax
movq %rax, -0x160(%rbp)
movslq -0xdc(%rbp), %rsi
leaq -0xd8(%rbp), %rdi
callq 0x3240
movq %rax, %rdi
callq 0x3260
movq %rax, %rcx
movq -0x160(%rbp), %rax
cmpq %rcx, %rax
jae 0x2e48
movslq -0xdc(%rbp), %rsi
leaq -0xd8(%rbp), %rdi
callq 0x3240
movq %rax, %rdi
movslq -0xe4(%rbp), %rsi
callq 0x3280
cmpl $0x0, (%rax)
jle 0x2e32
movb $0x0, -0xdd(%rbp)
movl -0xe4(%rbp), %eax
addl $0x61, %eax
movsbl %al, %esi
movq 0x3d261(%rip), %rdi     # 0x3ffd8
callq 0x2230
movq %rax, -0x168(%rbp)
jmp 0x2d85
movslq -0xdc(%rbp), %rsi
leaq -0xd8(%rbp), %rdi
callq 0x3240
movq %rax, %rdi
movslq -0xe4(%rbp), %rsi
callq 0x3280
movq -0x168(%rbp), %rdi
movl (%rax), %esi
callq 0x22f0
jmp 0x2db7
jmp 0x2e32
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x80(%rbp)
movl %eax, -0x84(%rbp)
leaq -0x71(%rbp), %rdi
callq 0x21f0
jmp 0x2f68
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x80(%rbp)
movl %eax, -0x84(%rbp)
jmp 0x2f5f
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x80(%rbp)
movl %eax, -0x84(%rbp)
jmp 0x2f53
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x80(%rbp)
movl %eax, -0x84(%rbp)
jmp 0x2f47
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x80(%rbp)
movl %eax, -0x84(%rbp)
leaq -0xd8(%rbp), %rdi
callq 0x32a0
jmp 0x2f47
jmp 0x2e34
movl -0xe4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xe4(%rbp)
jmp 0x2cf6
testb $0x1, -0xdd(%rbp)
je 0x2e68
movq 0x3d180(%rip), %rdi     # 0x3ffd8
leaq 0x281f8(%rip), %rsi     # 0x2b057
callq 0x2190
jmp 0x2e66
jmp 0x2e68
movslq -0xdc(%rbp), %rax
movq %rax, -0x170(%rbp)
leaq -0xd8(%rbp), %rdi
callq 0x31c0
movq %rax, %rcx
movq -0x170(%rbp), %rax
subq $0x1, %rcx
cmpq %rcx, %rax
jae 0x2eac
movq 0x3d13c(%rip), %rdi     # 0x3ffd8
leaq 0x281b6(%rip), %rsi     # 0x2b059
callq 0x2190
jmp 0x2eaa
jmp 0x2eac
jmp 0x2eae
movl -0xdc(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xdc(%rbp)
jmp 0x2c5d
movq 0x3d10f(%rip), %rdi     # 0x3ffd8
leaq 0x2818b(%rip), %rsi     # 0x2b05b
callq 0x2190
movq %rax, -0x178(%rbp)
jmp 0x2ede
movq -0x178(%rbp), %rdi
movq 0x3d0dc(%rip), %rsi     # 0x3ffc8
callq 0x21d0
jmp 0x2ef3
leaq -0xd8(%rbp), %rdi
callq 0x32a0
movl -0xbc(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xbc(%rbp)
jmp 0x2bff
movl $0x0, -0x4(%rbp)
leaq -0xb8(%rbp), %rdi
callq 0x3300
leaq -0xa0(%rbp), %rdi
callq 0x3300
leaq -0x70(%rbp), %rdi
callq 0x2100
movl -0x4(%rbp), %eax
addq $0x180, %rsp            # imm = 0x180
popq %rbp
retq
leaq -0xb8(%rbp), %rdi
callq 0x3300
leaq -0xa0(%rbp), %rdi
callq 0x3300
leaq -0x70(%rbp), %rdi
callq 0x2100
movq -0x80(%rbp), %rdi
callq 0x2300
nopw %cs:(%rax,%rax)
nopl (%rax,%rax)