// File: /workspace/github_cpp_makefile_star2_O2/manschga[P]M5GB/M5GB.cpp
// Function: M5GB(std::vector<polynomial, std::allocator<polynomial>>&, int)
vector<polynomial> M5GB(vector<polynomial>& system, int n) //table might overflow -> need to redefine inside
{
  auto start = std::chrono::steady_clock::now();
  degrees = create_degrees(n,10); //upper found for degree, have to change for larger examples
  Initialize(system,n);  

#ifdef DEBUG
  cout << "Size of P: " << P.size() << endl;
#endif
  int polys_left = m-2;
  int debug = 1000000;
  int maxiter = debug;
  int last_non_zero = maxiter-debug;
  //signature last_syz(table.size(),m);

  while (Spol_sign.size() > 0 && debug > 0)
    {
#ifdef DEBUG
      //cout << "iteration " << maxiter-debug << endl;
#endif
      if (Spol_sign.size() > 0)
	{
	  signature smallest_sign  = *Spol_sign.begin();
	  /*
	  */
	  Spol_sign.erase(Spol_sign.begin());//remove first item
	  if (Syzygy(smallest_sign,H))
	     {
	       syz_counter ++; //to be precise, take away all spairs of that syzygy
	       debug --;
	       continue;
	     }
	  if (smallest_sign.Get_term() != 0)
	    {
	      auto same_sign_pairs = Spairs_map.equal_range(smallest_sign);
	      for (auto pair = same_sign_pairs.first; pair!= same_sign_pairs.second; ++pair)
		{
		  Lab_poly uF = pair->second.first;
		  //Lab_poly vG = pair->second.second.first;
		  /*
		   if(Syzygy(vG.Get_sign(),H))//meets syzygy criterion
		    {
#ifdef DEBUG
		      cout << "syzygy criterion works for " << vG.Get_sign() << endl;
#endif
		      syz_counter ++;
		      debug --;
		      continue;
		    }
		  */
		   if (isRewritable(uF,pair->second.second)) //changed order, check!, could change first taking maximum w.r.t. rewrite order!
		    {
		      rewrite_counter++;
#ifdef DEBUG
		      cout << "Rewritable criterion works for " << uF << endl;
#endif
		      debug --;
		      continue;
		    }
		   /*
		    if (isRewritable(vG,pair->second.second.second))//Generations_G.find(G.Get_LT())->second)) //changed order, check!, could change first taking maximum w.r.t. rewrite order!)) //changed order, check!
		    {
		      rewrite_counter++;
#ifdef DEBUG
		      cout << "Rewritable criterion works for " << vG << endl;
#endif
		      debug --;
		      continue;
		    }
		   */
		    //Lab_poly Spol = uF - vG;
		   term_vec out = table[smallest_sign.Get_term()].first;
		   for (auto &it : out)
		     {
		       //cout << it;
		     }
		   //cout << endl;
#ifdef LOWER_POL
		   Lab_poly Spol = Low_pol(smallest_sign,uF,pair->second.second,n);
#else
		   Lab_poly Spol = uF;//variant
#endif
		   
		  /*
		  if (Spol.Get_LC() == 0)//is 0-polynomial
		    {
		      H[Spol.Get_sign().Get_index()].emplace_back(Spol.Get_sign().Get_term());//add syzygy signature
		      spol_is_zero ++;
		      debug --;
		      break;
		    }
		  */
#ifdef PRECISE_DEBUG
		  cout << "uF:" << uF<< endl;
		  //cout << "vG:" << vG << endl;
		  cout << "Next signature: " << Spol.Get_sign() << endl;
	  if (((maxiter - debug) % 1000) == 1)
	    {
	      cout << "size of G:" << G_.size() << endl;
	      cout << "iteration " << maxiter - debug << endl;
	      cout << "First Buchberger criterion works: " << BB_counter << endl;
	      cout << "spol is zero: " << spol_is_zero << endl;
	      cout << "rewritten: " << rewrite_counter << endl;
	      cout << "syzygy crit: " << syz_counter << endl;
	      cout << "actually reduced: " << actual_red << endl;
	      cout << "signature: " << Spol.Get_sign() << endl;
	    }
#endif
	  if (((maxiter - debug) % 100) == 33)
	    cout << "signature: " << Spol.Get_sign() << endl;
	  //if not rewriteable
	    
	  actual_red ++;
	  //cout << "signature: " << Spol.Get_sign() << endl;
	  //cout << Spol << endl << endl << endl;
	  if (actual_red == 1500)
	    {
	      debug = 0;
	      continue;
	    }
	  Full_S_Reduce(Spol,n);
	  //cout << " --> " << Spol << endl << endl << endl;
#ifdef DEBUG
	  cout << " --> " << Spol << endl << endl << endl;
#endif
	  if((Spol.Get_poly()).Get_LC() == 0)// 0-polynomial
	    {
	      //cout << maxiter-debug << endl;
	      debug = 0;
	      continue;
	      zero_reductions ++;
	      debug --;
	      H[Spol.Get_sign().Get_index()].emplace_back(Spol.Get_sign().Get_term());//add syzygy signature
	      break; //this signature already reduces to 0
	    }
	  else
	    {
	      last_non_zero = maxiter-debug;
	      Update_syz(Spol);//add new koszul syzygies
	      Update_pairs(Spol,system,n,BB_counter);//system needed? check!
#ifdef PRECISE_DEBUG
	      if (G_.find(Spol.Get_LT()) != G_.end())
		cout << "Same leading term! Error!" << endl;
#endif
	      Add_to_M(Spol);
	      Add_to_G(Spol);
	      /*
	      G_[Spol.Get_LT()] = Spol;
	      M[Spol.Get_LT()] = Spol;
	      Generations_M[Spol.Get_LT()] = G_.size(); //generation for M
	      Generations_G[Spol.Get_LT()] = G_.size(); //generation for G
	      Flags_M[Spol.Get_LT()] = Create_Flag(Spol.Get_poly()); //create flag for M
	      */
	      //Update_step(Spol); -> not needed since done in lazy manner!
	    }
	  debug --;
	  break; //one element of this signature already examined
		}
	    }
	}
    }
  vector<polynomial> basis = Poly(G_,n,p); //remove signatures

  sort(basis);
  Interreduce(basis);
  
#ifdef statistics
  cout << "Number of examined S-polynomials: " << maxiter - debug << endl;
  cout << "discarded since zero:" << spol_is_zero << endl;
  cout << "Discarded by Rewriteable criterion: " << rewrite_counter << endl;
  cout << "discarded by syzygy criterion: " << syz_counter << endl;
  cout << "actually reduced: " << actual_red << endl;
  cout << "Number of full reduction steps:" << full_red_steps << endl;
  cout << "Number of total reductions:" << number_of_reductions << endl;
  cout<< "Number of fast reductions: " <<  straight_m_reduces << endl;
  cout<< "Number of re-reductions: " <<  m_re_reduced << endl;
  cout<< "Number of g-reductions: " <<  g_reduced << endl;
  cout<< "Size of M: " << M.size() << endl;
  cout<< "Size of G: " << G_.size() << endl;
  cout << "Number of Zero reductions:" << zero_reductions << endl;
  cout << "First Buchberger criterion works: " << BB_counter << endl;
  cout << "Last non-zero: " << last_non_zero << endl;
#endif
  if (debug == 0)
    cout << "maximal number of iterations reached!!!"<< endl << endl;
  auto end = chrono::steady_clock::now();
  cout << "Elapsed time in Seconds : "
	 << chrono::duration_cast<chrono::milliseconds>(end - start).count()
	 << " milliseconds " << endl;
  return basis;
  //return G_;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xc8, %rsp
movl %edx, %ebp
movq %rsi, %rbx
movq %rdi, %r14
callq 0x21f0
movq %rax, %r15
leaq 0x90(%rsp), %r12
pushq $0xa
popq %rdx
movq %r12, %rdi
movl %ebp, %esi
callq 0x3429
leaq 0x121df(%rip), %rdi     # 0x184f0
movq %r12, %rsi
callq 0xa97e
movq %r12, %rdi
callq 0x2dfe
movq %rbx, %rdi
movl %ebp, 0xc(%rsp)
movl %ebp, %esi
callq 0x6880
movl $0xf4240, %r12d         # imm = 0xF4240
xorl %ebp, %ebp
leaq 0x12122(%rip), %r13     # 0x18460
leaq 0x20(%rsp), %rbx
cmpq $0x0, 0x1213d(%rip)     # 0x18488
je 0x652e
testl %r12d, %r12d
jle 0x652e
movq 0x12117(%rip), %rsi     # 0x18478
movups 0x20(%rsi), %xmm0
movaps %xmm0, 0x20(%rsp)
movq %r13, %rdi
callq 0xa9d0
movq %rbx, %rdi
leaq 0x120cc(%rip), %rsi     # 0x18448
callq 0x6a6b
testb %al, %al
je 0x6390
incl 0x11e45(%rip)           # 0x181d0
decl %r12d
jmp 0x6343
cmpq $0x0, 0x28(%rsp)
je 0x6343
movl %ebp, 0x8(%rsp)
movq %r15, 0x10(%rsp)
movq %r14, 0x18(%rsp)
leaq 0x120e3(%rip), %rdi     # 0x18490
movq %rbx, %rsi
callq 0xaa1e
movq %rax, %r13
movq %rdx, 0x38(%rsp)
cmpq 0x38(%rsp), %r13
je 0x6514
leaq 0x30(%r13), %rsi
leaq 0x90(%rsp), %r14
movq %r14, %rdi
callq 0x97ca
movq %r14, %rdi
callq 0x6afe
testb %al, %al
je 0x63f9
incl 0x11dda(%rip)           # 0x181c8
decl %r12d
movb $0x1, %bpl
jmp 0x64f2
imulq $0x30, 0x28(%rsp), %rsi
leaq 0x11d6a(%rip), %rax     # 0x18170
addq (%rax), %rsi
leaq 0x78(%rsp), %rdi
callq 0x3a1a
leaq 0x40(%rsp), %rdi
movq %rbx, %rsi
leaq 0x90(%rsp), %rdx
callq 0x6c71
movl $0xf4240, %r15d         # imm = 0xF4240
subl %r12d, %r15d
movl %r15d, %eax
cltd
pushq $0x64
popq %rcx
idivl %ecx
cmpl $0x21, %edx
jne 0x6467
movq 0x11b92(%rip), %rdi     # 0x17fd8
leaq 0x8d77(%rip), %rsi      # 0xf1c4
callq 0x2180
movq %rax, %rdi
leaq 0x60(%rsp), %rsi
callq 0xec5b
movq %rax, %rdi
callq 0x20d0
movl 0x11d67(%rip), %eax     # 0x181d4
incl %eax
movl %eax, 0x11d5f(%rip)     # 0x181d4
xorl %r14d, %r14d
movb $0x1, %bpl
cmpl $0x5dc, %eax            # imm = 0x5DC
je 0x64db
leaq 0x40(%rsp), %rdi
movl 0xc(%rsp), %esi
callq 0x6f30
movq 0x40(%rsp), %rax
cmpl $0x0, 0x8(%rax)
je 0x64db
leaq 0x40(%rsp), %rdi
callq 0x746f
leaq 0x40(%rsp), %rdi
movl 0xc(%rsp), %edx
leaq 0x11d27(%rip), %rcx     # 0x181dc
callq 0x750e
leaq 0x40(%rsp), %rdi
callq 0x7836
leaq 0x40(%rsp), %rdi
callq 0x7970
decl %r12d
xorl %ebp, %ebp
movl %r15d, 0x8(%rsp)
movl %r12d, %r14d
leaq 0x40(%rsp), %rdi
callq 0x2f74
leaq 0x78(%rsp), %rdi
callq 0x2dfe
movl %r14d, %r12d
leaq 0x90(%rsp), %rdi
callq 0x2f74
testb %bpl, %bpl
je 0x6514
movq %r13, %rdi
callq 0x2120
movq %rax, %r13
jmp 0x63bd
movq 0x18(%rsp), %r14
movq 0x10(%rsp), %r15
movl 0x8(%rsp), %ebp
leaq 0x11f37(%rip), %r13     # 0x18460
jmp 0x6343
movq %r14, %rdi
callq 0x7a41
movq %r14, %rdi
callq 0xe05d
movq %r14, %rdi
callq 0x7ad1
movq 0x11a8b(%rip), %rdi     # 0x17fd8
leaq 0x8c7c(%rip), %rsi      # 0xf1d0
callq 0x2180
movl $0xf4240, %esi          # imm = 0xF4240
subl %r12d, %esi
movq %rax, %rdi
callq 0x2250
movq %rax, %rdi
callq 0x20d0
movq 0x11a60(%rip), %rdi     # 0x17fd8
leaq 0x8c74(%rip), %rsi      # 0xf1f3
callq 0x2180
movl 0x11c42(%rip), %esi     # 0x181cc
movq %rax, %rdi
callq 0x2250
movq %rax, %rdi
callq 0x20d0
movq 0x11a37(%rip), %rdi     # 0x17fd8
leaq 0x8c61(%rip), %rsi      # 0xf209
callq 0x2180
movl 0x11c15(%rip), %esi     # 0x181c8
movq %rax, %rdi
callq 0x2250
movq %rax, %rdi
callq 0x20d0
movq 0x11a0e(%rip), %rdi     # 0x17fd8
leaq 0x8c5d(%rip), %rsi      # 0xf22e
callq 0x2180
movl 0x11bf4(%rip), %esi     # 0x181d0
movq %rax, %rdi
callq 0x2250
movq %rax, %rdi
callq 0x20d0
movq 0x119e5(%rip), %rdi     # 0x17fd8
leaq 0x8c54(%rip), %rsi      # 0xf24e
callq 0x2180
movl 0x11bcf(%rip), %esi     # 0x181d4
movq %rax, %rdi
callq 0x2250
movq %rax, %rdi
callq 0x20d0
movq 0x119bc(%rip), %rdi     # 0x17fd8
leaq 0x8c3e(%rip), %rsi      # 0xf261
callq 0x2180
movl 0x11b86(%rip), %esi     # 0x181b4
movq %rax, %rdi
callq 0x2250
movq %rax, %rdi
callq 0x20d0
movq 0x11993(%rip), %rdi     # 0x17fd8
leaq 0x8c35(%rip), %rsi      # 0xf281
callq 0x2180
movl 0x11b61(%rip), %esi     # 0x181b8
movq %rax, %rdi
callq 0x2250
movq %rax, %rdi
callq 0x20d0
movq 0x1196a(%rip), %rdi     # 0x17fd8
leaq 0x8c28(%rip), %rsi      # 0xf29d
callq 0x2180
movl 0x11b3c(%rip), %esi     # 0x181bc
movq %rax, %rdi
callq 0x2250
movq %rax, %rdi
callq 0x20d0
movq 0x11941(%rip), %rdi     # 0x17fd8
leaq 0x8c1b(%rip), %rsi      # 0xf2b9
callq 0x2180
movl 0x11b17(%rip), %esi     # 0x181c0
movq %rax, %rdi
callq 0x2250
movq %rax, %rdi
callq 0x20d0
movq 0x11918(%rip), %rdi     # 0x17fd8
leaq 0x8c0c(%rip), %rsi      # 0xf2d3
callq 0x2180
movl 0x11af2(%rip), %esi     # 0x181c4
movq %rax, %rdi
callq 0x2250
movq %rax, %rdi
callq 0x20d0
movq 0x118ef(%rip), %rdi     # 0x17fd8
leaq 0x8bfc(%rip), %rsi      # 0xf2ec
callq 0x2180
movq 0x11c14(%rip), %rsi     # 0x18310
movq %rax, %rdi
callq 0x2110
movq %rax, %rdi
callq 0x20d0
movq 0x118c5(%rip), %rdi     # 0x17fd8
leaq 0x8bde(%rip), %rsi      # 0xf2f8
callq 0x2180
movq 0x11bb2(%rip), %rsi     # 0x182d8
movq %rax, %rdi
callq 0x2110
movq %rax, %rdi
callq 0x20d0
movq 0x1189b(%rip), %rdi     # 0x17fd8
leaq 0x8bc0(%rip), %rsi      # 0xf304
callq 0x2180
movl 0x11a89(%rip), %esi     # 0x181d8
movq %rax, %rdi
callq 0x2250
movq %rax, %rdi
callq 0x20d0
movq 0x11872(%rip), %rdi     # 0x17fd8
leaq 0x8bb2(%rip), %rsi      # 0xf31f
callq 0x2180
movl 0x11a64(%rip), %esi     # 0x181dc
movq %rax, %rdi
callq 0x2250
movq %rax, %rdi
callq 0x20d0
movq 0x11849(%rip), %rdi     # 0x17fd8
leaq 0x8bac(%rip), %rsi      # 0xf342
callq 0x2180
movq %rax, %rdi
movl %ebp, %esi
callq 0x2250
movq %rax, %rdi
callq 0x20d0
testl %r12d, %r12d
jne 0x67d5
movq 0x1181f(%rip), %rdi     # 0x17fd8
leaq 0x8b92(%rip), %rsi      # 0xf352
callq 0x2180
movq %rax, %rdi
callq 0x20d0
movq %rax, %rdi
callq 0x20d0
callq 0x21f0
movq %rax, %rbx
movq 0x117f4(%rip), %rdi     # 0x17fd8
leaq 0x8b8f(%rip), %rsi      # 0xf37a
callq 0x2180
movq %rax, %rdi
subq %r15, %rbx
movl $0xf4240, %ecx          # imm = 0xF4240
movq %rbx, %rax
cqto
idivq %rcx
movq %rax, %rsi
callq 0x2170
leaq 0x8b83(%rip), %rsi      # 0xf395
movq %rax, %rdi
callq 0x2180
movq %rax, %rdi
callq 0x20d0
movq %r14, %rax
addq $0xc8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x686d
jmp 0x686d
jmp 0x6842
movq %rax, %rbx
jmp 0x6854
movq %rax, %rbx
jmp 0x685e
movq %rax, %rbx
leaq 0x40(%rsp), %rdi
callq 0x2f74
leaq 0x78(%rsp), %rdi
callq 0x2dfe
leaq 0x90(%rsp), %rdi
callq 0x2f74
jmp 0x6878
movq %r14, %rdi
movq %rax, %rbx
callq 0x2c88
movq %rbx, %rdi
callq 0x2260