// File: /workspace/github_cpp_makefile_star2_O2/manschga[P]M5GB/M5GB.cpp
// Function: Tail_S_Reduce(Lab_poly const&, signature const&, int)
Lab_poly Tail_S_Reduce(const Lab_poly& F_,const signature& T, const int n)
{
#ifdef PRECISE_DEBUG
  cout << "doing Tail-reduce with polynomial " << F_ << endl;
#endif
  Lab_poly F = F_;
  signature S_F = F.Get_sign();
  //signature flag(table.size(),m);
  int rec_depth = 1; //cheap workaround until now
  if (rec_depth < 10000)
    {
      rec_depth++;
      polynomial f = F_.Get_poly();
      polynomial f_ = f;
      for (auto monom = ++f.Get_monomials().begin(); monom != f.Get_monomials().end(); ++monom) //leave out LT, need to stay at that datastructure, otherwise for-loop! (poss error source)
     {
       int t = monom->Get_term();
       int c = monom->Get_coeff();
#ifdef PRECISE_DEBUG
       cout << "t = " << monom->Get_term() << endl;
#endif
       if (Flags_T.find(t) != Flags_T.end() &&  (Flags_T.find(t)->second > T || Flags_T.find(t)->second == T )) 
	 {
	   if (Generations_T.find(t)->second == G_.size())//t is known to be irreducible -> nothing needs to be done!
	     {
	       continue;
	     }
	   else if (!Check_TGFT(t,T))//if not reducible by G, possible improvement: check only for newer elements, nothing for counting argument!
	     {
	       Generations_T.erase(t);
	       Generations_T[t] = G_.size();
	       Flags_T.erase(t);//update signature flag since new generation, improvement: take only newer ons and do min with old flag
	       Flags_T[t] = Create_term_flag(t);
	       continue;
	     }
	 }
       auto itr = LT_M.find(t);
      if (itr != LT_M.end()) //element found, check on order if checking by div by G is faster?
	{
	  Lab_poly m_ = Update_m(Lab_poly(M.find(itr->first)->second,itr->second),T,n); //bring m in right form such that it is tail-irreducible again
	  f_ = f_ - m_.Get_poly().Multiply(c,true); //f - c_t(f)*m_t
	  S_F = max(S_F,m_.Get_sign());
	  number_of_reductions++;
	}
      else if (Check_TGFT(t,T))//if reducible by G
	{
	  Flags_T.erase(t);//t is no longer irreducible (only first one needed, rest for less storage) 
	  Generations_T.erase(t);
	  
	  Lab_poly vM = Div_by_M(t,T);//find best divisor in M, improvment: map G -> M, only need to check that m's on divisibility
	  Lab_poly m_ = Tail_S_Reduce(vM,T,n); //create new element in M such that it is tail-irreducible
	  f_ = f_ - m_.Get_poly().Multiply(c,true); //f - c_t(f)*m_t
	  S_F = max(S_F,m_.Get_sign());
	  number_of_reductions++;	
	}
       else
	 {
	   //not yet reducible -> keep t as irreducible term!
	   Flags_T.erase(t);//update signature flag since new generation, improvement: take only newer ons and do min with old flag
	   Flags_T[t] = Create_term_flag(t);
	   Generations_T.erase(t);
	   Generations_T[t] = G_.size();//set current generation when t was updated the last time
	 }
     }
      F = Lab_poly(f_,S_F);
      Add_to_M(F);
      return F;
    }
  
  cout << "Too small recursion depth" << endl;
   
  return Lab_poly();
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x198, %rsp            # imm = 0x198
movl %ecx, 0xc(%rsp)
movq %rdx, %r14
movq %rsi, %rbx
movq %rdi, 0x60(%rsp)
leaq 0x140(%rsp), %r15
movq %r15, %rdi
callq 0x97ca
movups 0x20(%r15), %xmm0
movaps %xmm0, 0x10(%rsp)
leaq 0x88(%rsp), %rdi
movq %rbx, %rsi
callq 0x57a2
leaq 0x68(%rsp), %rdi
leaq 0x88(%rsp), %rsi
callq 0x57a2
movq 0x88(%rsp), %r12
addq $0x10, %r12
leaq 0x28(%rsp), %rbx
cmpq 0x90(%rsp), %r12
je 0x88ec
movslq (%r12), %rbp
movl 0x8(%r12), %r15d
movq %rbp, 0x28(%rsp)
leaq 0xfdb7(%rip), %rdi      # 0x18330
movq %rbx, %rsi
callq 0xbc02
testq %rax, %rax
je 0x869a
movq %rbp, 0xc8(%rsp)
leaq 0xfd97(%rip), %rdi      # 0x18330
leaq 0xc8(%rsp), %rsi
callq 0xbc02
addq $0x10, %rax
movq %rax, %rdi
movq %r14, %rsi
callq 0x984e
testb %al, %al
je 0x8668
movq %rbp, 0x28(%rsp)
leaq 0xfe47(%rip), %rdi      # 0x18410
movq %rbx, %rsi
callq 0xbc20
movslq 0x10(%rax), %rax
cmpq %rax, 0xfcfc(%rip)      # 0x182d8
je 0x8873
movq %rbp, %rdi
movq %r14, %rsi
callq 0x7c7f
testb %al, %al
jne 0x869a
movq %rbp, 0x28(%rsp)
leaq 0xfe0f(%rip), %r13      # 0x18410
movq %r13, %rdi
movq %rbx, %rsi
callq 0xb374
movq 0xfcc5(%rip), %r15      # 0x182d8
movq %rbp, 0x28(%rsp)
movq %r13, %rdi
movq %rbx, %rsi
callq 0xbc3e
movl %r15d, (%rax)
movq %rbp, 0x28(%rsp)
leaq 0xfcfe(%rip), %rdi      # 0x18330
movq %rbx, %rsi
callq 0xb7bc
movq %rbp, %rdi
callq 0x7df9
movl %eax, %r15d
movq %rdx, %r13
movq %rbp, 0x28(%rsp)
leaq 0xfcdc(%rip), %rdi      # 0x18330
movq %rbx, %rsi
callq 0xbd0e
movl %r15d, (%rax)
movq %r13, 0x8(%rax)
jmp 0x8873
movq %rbp, 0xa8(%rsp)
leaq 0xfcb9(%rip), %rdi      # 0x18330
leaq 0xa8(%rsp), %rsi
callq 0xbc02
movl 0x10(%rax), %ecx
cmpl (%r14), %ecx
jne 0x869a
movq 0x18(%rax), %rax
cmpq 0x8(%r14), %rax
je 0x85bd
movq %rbp, 0x28(%rsp)
leaq 0xfbe2(%rip), %rdi      # 0x18288
movq %rbx, %rsi
callq 0xbc02
movq %rax, %r13
testq %rax, %rax
je 0x878c
leaq 0x8(%r13), %rsi
leaq 0xfc33(%rip), %rdi      # 0x182f8
callq 0xbbe4
leaq 0x120(%rsp), %rbp
addq $0x10, %rax
movq %rbp, %rdi
movq %rax, %rsi
callq 0x57a2
movl 0x10(%r13), %edx
movq 0x18(%r13), %rcx
leaq 0xc8(%rsp), %r13
movq %r13, %rdi
movq %rbp, %rsi
callq 0x4524
movq %rbx, %rdi
movq %r13, %rsi
movq %r14, %rdx
movl 0xc(%rsp), %ecx
callq 0x7f4e
movq %r13, %rdi
callq 0x2f74
leaq 0x120(%rsp), %rdi
callq 0x2f74
leaq 0xa8(%rsp), %rbp
movq %rbp, %rdi
movq %rbx, %rsi
movl %r15d, %edx
pushq $0x1
popq %rcx
callq 0x54e6
movq %r13, %rdi
leaq 0x68(%rsp), %r15
movq %r15, %rsi
movq %rbp, %rdx
callq 0x56ba
movq %r15, %rdi
movq %r13, %rsi
callq 0x4ef0
movq %r13, %rdi
callq 0x2f74
movq %rbp, %rdi
callq 0x2f74
leaq 0x10(%rsp), %rdi
leaq 0x48(%rsp), %rsi
callq 0xebd5
movups (%rax), %xmm0
movaps %xmm0, 0x10(%rsp)
incl 0xfa31(%rip)            # 0x181b8
jmp 0x886b
movq %rbp, %rdi
movq %r14, %rsi
callq 0x7c7f
testb %al, %al
je 0x887c
movq %rbp, 0x28(%rsp)
leaq 0xfb85(%rip), %rdi      # 0x18330
movq %rbx, %rsi
callq 0xb7bc
movq %rbp, 0x28(%rsp)
leaq 0xfc51(%rip), %rdi      # 0x18410
movq %rbx, %rsi
callq 0xb374
movq %rbx, %rdi
movq %rbp, %rsi
movq %r14, %rdx
callq 0x805b
leaq 0xc8(%rsp), %r13
movq %r13, %rdi
movq %rbx, %rsi
movq %r14, %rdx
movl 0xc(%rsp), %ecx
callq 0x84e9
leaq 0x178(%rsp), %rbp
movq %rbp, %rdi
movq %r13, %rsi
movl %r15d, %edx
pushq $0x1
popq %rcx
callq 0x54e6
leaq 0xa8(%rsp), %r15
movq %r15, %rdi
leaq 0x68(%rsp), %r13
movq %r13, %rsi
movq %rbp, %rdx
callq 0x56ba
movq %r13, %rdi
movq %r15, %rsi
callq 0x4ef0
movq %r15, %rdi
callq 0x2f74
movq %rbp, %rdi
callq 0x2f74
leaq 0x10(%rsp), %rdi
leaq 0xe8(%rsp), %rsi
callq 0xebd5
movups (%rax), %xmm0
movaps %xmm0, 0x10(%rsp)
incl 0xf95a(%rip)            # 0x181b8
leaq 0xc8(%rsp), %rdi
callq 0x2f74
movq %rbx, %rdi
callq 0x2f74
addq $0x10, %r12
jmp 0x8556
movq %rbp, 0x28(%rsp)
leaq 0xfaa8(%rip), %rdi      # 0x18330
movq %rbx, %rsi
callq 0xb7bc
movq %rbp, %rdi
callq 0x7df9
movl %eax, %r15d
movq %rdx, %r13
movq %rbp, 0x28(%rsp)
leaq 0xfa86(%rip), %rdi      # 0x18330
movq %rbx, %rsi
callq 0xbd0e
movl %r15d, (%rax)
movq %r13, 0x8(%rax)
movq %rbp, 0x28(%rsp)
leaq 0xfb4b(%rip), %r13      # 0x18410
movq %r13, %rdi
movq %rbx, %rsi
callq 0xb374
movq 0xfa01(%rip), %r15      # 0x182d8
movq %rbp, 0x28(%rsp)
movq %r13, %rdi
movq %rbx, %rsi
callq 0xbc3e
movl %r15d, (%rax)
jmp 0x8873
leaq 0x100(%rsp), %rdi
leaq 0x68(%rsp), %rsi
callq 0x57a2
movl 0x10(%rsp), %edx
movq 0x18(%rsp), %rcx
leaq 0x28(%rsp), %rdi
leaq 0x100(%rsp), %rsi
callq 0x4524
leaq 0x140(%rsp), %rbx
leaq 0x28(%rsp), %r14
movq %rbx, %rdi
movq %r14, %rsi
callq 0x511e
movq %r14, %rdi
callq 0x2f74
leaq 0x100(%rsp), %rdi
callq 0x2f74
movq %rbx, %rdi
callq 0x7836
leaq 0x140(%rsp), %rbx
movq 0x60(%rsp), %r14
movq %r14, %rdi
movq %rbx, %rsi
callq 0x5f8e
leaq 0x68(%rsp), %rdi
callq 0x2f74
leaq 0x88(%rsp), %rdi
callq 0x2f74
movq %rbx, %rdi
callq 0x2f74
movq %r14, %rax
addq $0x198, %rsp            # imm = 0x198
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x8a60
movq %rax, %rbx
leaq 0x100(%rsp), %rdi
jmp 0x8a53
jmp 0x8a60
movq %rax, %rbx
jmp 0x8a6d
movq %rax, %rbx
jmp 0x8a7a
jmp 0x8a60
jmp 0x8a60
jmp 0x8a60
jmp 0x8a60
jmp 0x8a60
jmp 0x89f1
movq %rax, %rbx
leaq 0x178(%rsp), %rdi
callq 0x2f74
jmp 0x89f4
movq %rax, %rbx
leaq 0xc8(%rsp), %rdi
jmp 0x8a3c
jmp 0x8a1a
jmp 0x8a60
jmp 0x8a60
jmp 0x8a60
jmp 0x8a60
jmp 0x8a60
jmp 0x8a60
jmp 0x8a60
jmp 0x8a60
jmp 0x8a60
jmp 0x8a60
jmp 0x8a60
jmp 0x8a60
jmp 0x8a1a
movq %rax, %rbx
jmp 0x8a41
movq %rax, %rbx
leaq 0xc8(%rsp), %rdi
callq 0x2f74
jmp 0x8a4b
movq %rax, %rbx
leaq 0xa8(%rsp), %rdi
callq 0x2f74
leaq 0x28(%rsp), %rdi
jmp 0x8a53
movq %rax, %rbx
leaq 0x120(%rsp), %rdi
callq 0x2f74
jmp 0x8a63
jmp 0x8a60
jmp 0x8a60
jmp 0x8a60
movq %rax, %rbx
leaq 0x68(%rsp), %rdi
callq 0x2f74
leaq 0x88(%rsp), %rdi
callq 0x2f74
leaq 0x140(%rsp), %rdi
callq 0x2f74
movq %rbx, %rdi
callq 0x2260