// File: /workspace/github_cpp_makefile_star2_O3/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 $0x1a8, %rsp            # imm = 0x1A8
movl %ecx, 0x8(%rsp)
movq %rdx, %r14
movq %rsi, %rbx
movq %rdi, %r12
leaq 0x100(%rsp), %r15
movq %r15, %rdi
callq 0x68a4
movl 0x18(%rbx), %eax
movl %eax, 0x18(%r15)
movups 0x20(%rbx), %xmm0
movaps %xmm0, 0x20(%r15)
movl 0x30(%rbx), %eax
movl %eax, 0x30(%r15)
movups 0x20(%rbx), %xmm0
movaps %xmm0, 0x90(%rsp)
leaq 0xe0(%rsp), %rdi
movq %rbx, %rsi
callq 0x68a4
movq %r12, 0x140(%rsp)
movl 0x18(%rbx), %eax
leaq 0xe0(%rsp), %rsi
movl %eax, 0x18(%rsi)
leaq 0x10(%rsp), %rdi
callq 0x68a4
movl 0xf8(%rsp), %eax
movl %eax, 0x28(%rsp)
movq 0xe0(%rsp), %r13
addq $0x10, %r13
cmpq 0xe8(%rsp), %r13
je 0xb540
leaq 0x30(%rsp), %r12
leaq 0x70(%rsp), %r15
movslq (%r13), %rbx
movl 0x8(%r13), %eax
movl %eax, 0xc(%rsp)
movq %rbx, 0x30(%rsp)
leaq 0xf308(%rip), %rdi      # 0x1a338
movq %r12, %rsi
callq 0xed76
testq %rax, %rax
je 0xb164
movq %rbx, 0xa0(%rsp)
leaq 0xf2e8(%rip), %rdi      # 0x1a338
leaq 0xa0(%rsp), %rsi
callq 0xed76
movq 0x8(%r14), %rcx
movl (%r14), %edx
movl 0x10(%rax), %esi
xorl %edi, %edi
cmpl %esi, %edx
setl %dil
xorl %r8d, %r8d
cmpq 0x18(%rax), %rcx
setne %al
setl %r8b
cmovnel %r8d, %edi
cmpl %edx, %esi
setne %cl
orb %al, %cl
testb %cl, %dil
je 0xb13a
movq %rbx, 0x30(%rsp)
leaq 0xf37b(%rip), %rdi      # 0x1a418
movq %r12, %rsi
callq 0xedd2
movslq 0x10(%rax), %rax
cmpq %rax, 0xf230(%rip)      # 0x1a2e0
je 0xb4b3
movq %rbx, %rdi
movq %r14, %rsi
callq 0xa330
testb %al, %al
jne 0xb164
movq %rbx, 0x30(%rsp)
leaq 0xf343(%rip), %rbp      # 0x1a418
movq %rbp, %rdi
movq %r12, %rsi
callq 0xe59e
movq 0xf1f9(%rip), %r15      # 0x1a2e0
movq %rbx, 0x30(%rsp)
movq %rbp, %rdi
movq %r12, %rsi
callq 0xee2e
movl %r15d, (%rax)
movq %rbx, 0x30(%rsp)
leaq 0xf232(%rip), %rdi      # 0x1a338
movq %r12, %rsi
callq 0xe926
movq %rbx, %rdi
callq 0xa4f6
movl %eax, %ebp
movq %rdx, %r15
movq %rbx, 0x30(%rsp)
leaq 0xf211(%rip), %rdi      # 0x1a338
movq %r12, %rsi
callq 0xeeec
movl %ebp, (%rax)
movq %r15, 0x8(%rax)
jmp 0xb4ae
movq %rbx, 0x70(%rsp)
leaq 0xf1f2(%rip), %rdi      # 0x1a338
movq %r15, %rsi
callq 0xed76
movl 0x10(%rax), %ecx
cmpl (%r14), %ecx
jne 0xb164
movq 0x18(%rax), %rax
cmpq 0x8(%r14), %rax
je 0xb091
movq %rbx, 0x30(%rsp)
leaq 0xf120(%rip), %rdi      # 0x1a290
movq %r12, %rsi
callq 0xed76
movq %rax, %r15
testq %rax, %rax
je 0xb2d3
movq %r14, %rbp
movq %r12, %r14
leaq 0x8(%r15), %rsi
leaq 0xf16b(%rip), %rdi      # 0x1a300
callq 0xed1a
leaq 0x168(%rsp), %r12
movq %rax, %rbx
leaq 0x10(%rax), %rsi
movq %r12, %rdi
callq 0x68a4
movl 0x28(%rbx), %eax
movl %eax, 0x180(%rsp)
movl 0x10(%r15), %edx
movq 0x18(%r15), %rcx
leaq 0xa0(%rsp), %rbx
movq %rbx, %rdi
movq %r12, %rsi
callq 0x50f8
movq %r14, %r12
movq %r14, %rdi
movq %rbx, %rsi
movq %rbp, %r14
movq %rbp, %rdx
movl 0x8(%rsp), %ecx
callq 0xa6cc
leaq 0x70(%rsp), %r15
movq 0xa0(%rsp), %rdi
testq %rdi, %rdi
je 0xb210
movq 0xb0(%rsp), %rsi
subq %rdi, %rsi
callq 0x2180
movq 0x168(%rsp), %rdi
testq %rdi, %rdi
je 0xb22d
movq 0x178(%rsp), %rsi
subq %rdi, %rsi
callq 0x2180
movq %r15, %rdi
movq %r12, %rsi
movl 0xc(%rsp), %edx
movl $0x1, %ecx
callq 0x6992
leaq 0xa0(%rsp), %rdi
leaq 0x10(%rsp), %rsi
movq %r15, %rdx
callq 0x6bd0
movq 0x10(%rsp), %rdi
movq 0x20(%rsp), %rsi
movaps 0xa0(%rsp), %xmm0
movaps %xmm0, 0x10(%rsp)
movq 0xb0(%rsp), %rax
movq %rax, 0x20(%rsp)
xorps %xmm0, %xmm0
movaps %xmm0, 0xa0(%rsp)
movq $0x0, 0xb0(%rsp)
testq %rdi, %rdi
je 0xb3dd
subq %rdi, %rsi
callq 0x2180
movq 0xa0(%rsp), %rdi
movl 0xb8(%rsp), %eax
movl %eax, 0x28(%rsp)
testq %rdi, %rdi
je 0xb3e8
movq 0xb0(%rsp), %rsi
subq %rdi, %rsi
callq 0x2180
jmp 0xb3e8
movq %rbx, %rdi
movq %r14, %rsi
callq 0xa330
testb %al, %al
je 0xb442
movq %rbx, 0x30(%rsp)
leaq 0xf046(%rip), %rdi      # 0x1a338
movq %r12, %rsi
callq 0xe926
movq %rbx, 0x30(%rsp)
leaq 0xf112(%rip), %rdi      # 0x1a418
movq %r12, %rsi
callq 0xe59e
movq %r12, %rdi
movq %rbx, %rsi
movq %r14, %rdx
callq 0xa822
leaq 0xa0(%rsp), %rbx
movq %rbx, %rdi
movq %r12, %rsi
movq %r14, %rdx
movl 0x8(%rsp), %ecx
callq 0xaf68
leaq 0x188(%rsp), %r15
movq %r15, %rdi
movq %rbx, %rsi
movl 0xc(%rsp), %edx
movl $0x1, %ecx
callq 0x6992
leaq 0x70(%rsp), %rdi
leaq 0x10(%rsp), %rsi
movq %r15, %rdx
callq 0x6bd0
movq 0x10(%rsp), %rdi
movq 0x20(%rsp), %rsi
movaps 0x70(%rsp), %xmm0
movaps %xmm0, 0x10(%rsp)
movq 0x80(%rsp), %rax
movq %rax, 0x20(%rsp)
xorps %xmm0, %xmm0
movaps %xmm0, 0x70(%rsp)
movq $0x0, 0x80(%rsp)
testq %rdi, %rdi
je 0xb4c7
subq %rdi, %rsi
callq 0x2180
movq 0x70(%rsp), %rdi
movl 0x88(%rsp), %eax
movl %eax, 0x28(%rsp)
testq %rdi, %rdi
leaq 0x70(%rsp), %r15
je 0xb4d7
movq 0x80(%rsp), %rsi
subq %rdi, %rsi
callq 0x2180
jmp 0xb4d7
movl 0xb8(%rsp), %eax
movl %eax, 0x28(%rsp)
movq 0x70(%rsp), %rdi
testq %rdi, %rdi
je 0xb402
movq 0x80(%rsp), %rsi
subq %rdi, %rsi
callq 0x2180
leaq 0x90(%rsp), %rdi
leaq 0x50(%rsp), %rsi
callq 0x12773
movups (%rax), %xmm0
incl 0xeda3(%rip)            # 0x1a1c0
movaps %xmm0, 0x90(%rsp)
movq 0x30(%rsp), %rdi
testq %rdi, %rdi
je 0xb4b3
movq 0x40(%rsp), %rsi
subq %rdi, %rsi
callq 0x2180
jmp 0xb4b3
movq %rbx, 0x30(%rsp)
leaq 0xeeea(%rip), %rdi      # 0x1a338
movq %r12, %rsi
callq 0xe926
movq %rbx, %rdi
callq 0xa4f6
movl %eax, %ebp
movq %rdx, %r15
movq %rbx, 0x30(%rsp)
leaq 0xeec9(%rip), %rdi      # 0x1a338
movq %r12, %rsi
callq 0xeeec
movl %ebp, (%rax)
movq %r15, 0x8(%rax)
movq %rbx, 0x30(%rsp)
leaq 0xef8f(%rip), %rbp      # 0x1a418
movq %rbp, %rdi
movq %r12, %rsi
callq 0xe59e
movq 0xee45(%rip), %r15      # 0x1a2e0
movq %rbx, 0x30(%rsp)
movq %rbp, %rdi
movq %r12, %rsi
callq 0xee2e
movl %r15d, (%rax)
leaq 0x70(%rsp), %r15
addq $0x10, %r13
cmpq 0xe8(%rsp), %r13
jne 0xb018
jmp 0xb540
movl 0x88(%rsp), %eax
movl %eax, 0x28(%rsp)
leaq 0x70(%rsp), %r15
movq 0x188(%rsp), %rdi
testq %rdi, %rdi
je 0xb4f4
movq 0x198(%rsp), %rsi
subq %rdi, %rsi
callq 0x2180
leaq 0x90(%rsp), %rdi
leaq 0xc0(%rsp), %rsi
callq 0x12773
movups (%rax), %xmm0
incl 0xecae(%rip)            # 0x1a1c0
movaps %xmm0, 0x90(%rsp)
movq 0xa0(%rsp), %rdi
testq %rdi, %rdi
je 0xb425
movq 0xb0(%rsp), %rsi
subq %rdi, %rsi
callq 0x2180
jmp 0xb425
leaq 0x148(%rsp), %rdi
leaq 0x10(%rsp), %rsi
callq 0x68a4
movl 0x28(%rsp), %eax
leaq 0x148(%rsp), %rsi
movl %eax, 0x18(%rsi)
movl 0x90(%rsp), %edx
movq 0x98(%rsp), %rcx
leaq 0x30(%rsp), %rdi
callq 0x50f8
leaq 0x120(%rsp), %rbx
movq -0x20(%rbx), %rdi
movq -0x10(%rbx), %rsi
movaps 0x30(%rsp), %xmm0
movaps %xmm0, -0x20(%rbx)
movq 0x40(%rsp), %rax
movq %rax, -0x10(%rbx)
xorps %xmm0, %xmm0
movaps %xmm0, 0x30(%rsp)
movq $0x0, 0x40(%rsp)
testq %rdi, %rdi
movq 0x140(%rsp), %r14
je 0xb5f5
subq %rdi, %rsi
callq 0x2180
movq 0x30(%rsp), %rdi
movl 0x48(%rsp), %eax
movl %eax, 0x118(%rsp)
movl 0x60(%rsp), %eax
movl %eax, 0x10(%rbx)
movaps 0x50(%rsp), %xmm0
movaps %xmm0, (%rbx)
testq %rdi, %rdi
je 0xb60f
movq 0x40(%rsp), %rsi
subq %rdi, %rsi
callq 0x2180
jmp 0xb60f
movl 0x48(%rsp), %eax
movl %eax, 0x118(%rsp)
movl 0x60(%rsp), %eax
movl %eax, 0x10(%rbx)
movaps 0x50(%rsp), %xmm0
movaps %xmm0, (%rbx)
movq 0x148(%rsp), %rdi
testq %rdi, %rdi
je 0xb62c
movq 0x158(%rsp), %rsi
subq %rdi, %rsi
callq 0x2180
leaq 0x100(%rsp), %rdi
callq 0x9d77
movaps 0x100(%rsp), %xmm0
movups %xmm0, (%r14)
movq 0x110(%rsp), %rax
movq %rax, 0x10(%r14)
xorps %xmm0, %xmm0
movaps %xmm0, 0x100(%rsp)
movq $0x0, 0x110(%rsp)
movl 0x118(%rsp), %eax
movl %eax, 0x18(%r14)
movl 0x10(%rbx), %eax
movl %eax, 0x30(%r14)
movups (%rbx), %xmm0
movups %xmm0, 0x20(%r14)
movq 0x10(%rsp), %rdi
testq %rdi, %rdi
je 0xb699
movq 0x20(%rsp), %rsi
subq %rdi, %rsi
callq 0x2180
movq 0xe0(%rsp), %rdi
testq %rdi, %rdi
je 0xb6b6
movq 0xf0(%rsp), %rsi
subq %rdi, %rsi
callq 0x2180
movq 0x100(%rsp), %rdi
testq %rdi, %rdi
je 0xb6d3
movq 0x110(%rsp), %rsi
subq %rdi, %rsi
callq 0x2180
movq %r14, %rax
addq $0x1a8, %rsp            # imm = 0x1A8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0xb838
movq %rax, %rbx
movq 0x148(%rsp), %rdi
testq %rdi, %rdi
je 0xb83b
movq 0x158(%rsp), %rsi
jmp 0xb828
jmp 0xb838
movq %rax, %rbx
jmp 0xb852
movq %rax, %rbx
jmp 0xb86f
jmp 0xb838
jmp 0xb838
jmp 0xb838
jmp 0xb838
jmp 0xb838
jmp 0xb760
movq %rax, %rbx
movq 0x188(%rsp), %rdi
testq %rdi, %rdi
je 0xb763
movq 0x198(%rsp), %rsi
subq %rdi, %rsi
callq 0x2180
jmp 0xb763
movq %rax, %rbx
movq 0xa0(%rsp), %rdi
testq %rdi, %rdi
je 0xb7ff
movq 0xb0(%rsp), %rsi
jmp 0xb7f7
jmp 0xb7bb
jmp 0xb838
jmp 0xb838
jmp 0xb838
jmp 0xb838
jmp 0xb838
jmp 0xb838
jmp 0xb838
jmp 0xb838
jmp 0xb838
jmp 0xb838
jmp 0xb838
jmp 0xb838
jmp 0xb7bb
movq %rax, %rbx
jmp 0xb7ff
movq %rax, %rbx
movq 0xa0(%rsp), %rdi
testq %rdi, %rdi
je 0xb813
movq 0xb0(%rsp), %rsi
subq %rdi, %rsi
callq 0x2180
jmp 0xb813
movq %rax, %rbx
movq 0x70(%rsp), %rdi
testq %rdi, %rdi
je 0xb7ff
movq 0x80(%rsp), %rsi
subq %rdi, %rsi
callq 0x2180
movq 0x30(%rsp), %rdi
testq %rdi, %rdi
je 0xb83b
movq 0x40(%rsp), %rsi
jmp 0xb828
movq %rax, %rbx
movq 0x168(%rsp), %rdi
testq %rdi, %rdi
je 0xb83b
movq 0x178(%rsp), %rsi
subq %rdi, %rsi
callq 0x2180
jmp 0xb83b
jmp 0xb838
jmp 0xb838
jmp 0xb838
movq %rax, %rbx
movq 0x10(%rsp), %rdi
testq %rdi, %rdi
je 0xb852
movq 0x20(%rsp), %rsi
subq %rdi, %rsi
callq 0x2180
movq 0xe0(%rsp), %rdi
testq %rdi, %rdi
je 0xb86f
movq 0xf0(%rsp), %rsi
subq %rdi, %rsi
callq 0x2180
movq 0x100(%rsp), %rdi
testq %rdi, %rdi
je 0xb88c
movq 0x110(%rsp), %rsi
subq %rdi, %rsi
callq 0x2180
movq %rbx, %rdi
callq 0x2240