// File: 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
movq %rsp, %rbp
subq $0x500, %rsp            # imm = 0x500
movq %rdi, -0x3d8(%rbp)
movq %rdi, %rax
movq %rax, -0x3d0(%rbp)
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movl %ecx, -0x1c(%rbp)
movq -0x10(%rbp), %rsi
leaq -0x58(%rbp), %rdi
movq %rdi, -0x3c8(%rbp)
callq 0x16be0
movq -0x3c8(%rbp), %rdi
callq 0xb8d0
movq %rax, -0x3c0(%rbp)
jmp 0x145f4
movq -0x3c0(%rbp), %rax
movq (%rax), %rcx
movq %rcx, -0x68(%rbp)
movq 0x8(%rax), %rax
movq %rax, -0x60(%rbp)
movl $0x1, -0x78(%rbp)
cmpl $0x2710, -0x78(%rbp)    # imm = 0x2710
jge 0x150e1
movl -0x78(%rbp), %eax
incl %eax
movl %eax, -0x78(%rbp)
movq -0x10(%rbp), %rdi
callq 0xb8c0
movq %rax, -0x3e0(%rbp)
jmp 0x14638
movq -0x3e0(%rbp), %rsi
leaq -0x98(%rbp), %rdi
callq 0xd980
jmp 0x1464d
leaq -0xb8(%rbp), %rdi
leaq -0x98(%rbp), %rsi
callq 0xd980
jmp 0x14662
leaq -0x98(%rbp), %rdi
callq 0x31f0
movq %rax, -0x3e8(%rbp)
jmp 0x14677
movq -0x3e8(%rbp), %rdi
callq 0xc5c0
movq %rax, -0xc8(%rbp)
leaq -0xc8(%rbp), %rdi
callq 0xca80
movq (%rax), %rax
movq %rax, -0xc0(%rbp)
leaq -0x98(%rbp), %rdi
callq 0x31f0
movq %rax, -0x3f0(%rbp)
jmp 0x146b5
movq -0x3f0(%rbp), %rdi
callq 0xc5f0
movq %rax, -0xd0(%rbp)
leaq -0xc0(%rbp), %rdi
leaq -0xd0(%rbp), %rsi
callq 0xc9f0
testb $0x1, %al
jne 0x146e4
jmp 0x14ff5
leaq -0xc0(%rbp), %rdi
callq 0x173d0
movq %rax, %rdi
callq 0xda60
movq %rax, -0x3f8(%rbp)
jmp 0x14701
movq -0x3f8(%rbp), %rax
movl %eax, -0xd4(%rbp)
leaq -0xc0(%rbp), %rdi
callq 0x173d0
movq %rax, %rdi
callq 0x3220
movl %eax, -0x3fc(%rbp)
jmp 0x1472a
movl -0x3fc(%rbp), %eax
movl %eax, -0xd8(%rbp)
movslq -0xd4(%rbp), %rax
movq %rax, -0xe8(%rbp)
leaq 0x2bc55(%rip), %rdi     # 0x403a0
leaq -0xe8(%rbp), %rsi
callq 0x17170
movq %rax, -0x408(%rbp)
jmp 0x14760
movq -0x408(%rbp), %rax
movq %rax, -0xe0(%rbp)
leaq 0x2bc2b(%rip), %rdi     # 0x403a0
callq 0x17020
movq %rax, -0xf0(%rbp)
leaq -0xe0(%rbp), %rdi
leaq -0xf0(%rbp), %rsi
callq 0x17050
movb %al, %cl
xorl %eax, %eax
testb $0x1, %cl
movb %al, -0x409(%rbp)
jne 0x147a8
jmp 0x1488f
movslq -0xd4(%rbp), %rax
movq %rax, -0x100(%rbp)
leaq 0x2bbe3(%rip), %rdi     # 0x403a0
leaq -0x100(%rbp), %rsi
callq 0x17170
movq %rax, -0x418(%rbp)
jmp 0x147d2
movq -0x418(%rbp), %rax
movq %rax, -0xf8(%rbp)
leaq -0xf8(%rbp), %rdi
callq 0x171a0
movq %rax, %rdi
addq $0x8, %rdi
movq -0x18(%rbp), %rsi
callq 0x171d0
movb %al, -0x419(%rbp)
jmp 0x14804
movb -0x419(%rbp), %cl
movb $0x1, %al
testb $0x1, %cl
movb %al, -0x41a(%rbp)
jne 0x14883
jmp 0x14819
movslq -0xd4(%rbp), %rax
movq %rax, -0x110(%rbp)
leaq 0x2bb72(%rip), %rdi     # 0x403a0
leaq -0x110(%rbp), %rsi
callq 0x17170
movq %rax, -0x428(%rbp)
jmp 0x14843
movq -0x428(%rbp), %rax
movq %rax, -0x108(%rbp)
leaq -0x108(%rbp), %rdi
callq 0x171a0
movq %rax, %rdi
addq $0x8, %rdi
movq -0x18(%rbp), %rsi
callq 0xbe50
movb %al, -0x429(%rbp)
jmp 0x14875
movb -0x429(%rbp), %al
movb %al, -0x41a(%rbp)
jmp 0x14883
movb -0x41a(%rbp), %al
movb %al, -0x409(%rbp)
movb -0x409(%rbp), %al
testb $0x1, %al
jne 0x1489e
jmp 0x14a7d
movslq -0xd4(%rbp), %rax
movq %rax, -0x120(%rbp)
leaq 0x2bbcd(%rip), %rdi     # 0x40480
leaq -0x120(%rbp), %rsi
callq 0x17220
movq %rax, -0x438(%rbp)
jmp 0x148c8
movq -0x438(%rbp), %rax
movq %rax, -0x118(%rbp)
leaq -0x118(%rbp), %rdi
callq 0x17250
movslq 0x8(%rax), %rax
movq %rax, -0x440(%rbp)
leaq 0x2ba3c(%rip), %rdi     # 0x40330
callq 0x16cc0
movq %rax, %rcx
movq -0x440(%rbp), %rax
cmpq %rcx, %rax
jne 0x14940
jmp 0x14fe4
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
jmp 0x15143
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
jmp 0x150d3
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
jmp 0x150c7
movslq -0xd4(%rbp), %rdi
movq -0x18(%rbp), %rsi
callq 0x13760
movb %al, -0x441(%rbp)
jmp 0x14958
movb -0x441(%rbp), %al
testb $0x1, %al
jne 0x14a79
jmp 0x14968
movslq -0xd4(%rbp), %rax
movq %rax, -0x128(%rbp)
leaq 0x2bb03(%rip), %rdi     # 0x40480
leaq -0x128(%rbp), %rsi
callq 0x16f30
jmp 0x1498b
leaq 0x2b99e(%rip), %rdi     # 0x40330
callq 0x16cc0
movl %eax, -0x454(%rbp)
movslq -0xd4(%rbp), %rax
movq %rax, -0x130(%rbp)
leaq 0x2bace(%rip), %rdi     # 0x40480
leaq -0x130(%rbp), %rsi
callq 0x17280
movq %rax, -0x450(%rbp)
jmp 0x149c7
movq -0x450(%rbp), %rax
movl -0x454(%rbp), %ecx
movl %ecx, (%rax)
movslq -0xd4(%rbp), %rax
movq %rax, -0x138(%rbp)
leaq 0x2b9b5(%rip), %rdi     # 0x403a0
leaq -0x138(%rbp), %rsi
callq 0x16f90
jmp 0x149f9
movslq -0xd4(%rbp), %rdi
callq 0x13a00
movq %rdx, -0x460(%rbp)
movl %eax, -0x458(%rbp)
jmp 0x14a14
movq -0x460(%rbp), %rax
movl -0x458(%rbp), %ecx
movl %ecx, -0x148(%rbp)
movq %rax, -0x140(%rbp)
movslq -0xd4(%rbp), %rax
movq %rax, -0x150(%rbp)
leaq 0x2b95d(%rip), %rdi     # 0x403a0
leaq -0x150(%rbp), %rsi
callq 0x172b0
movq %rax, -0x468(%rbp)
jmp 0x14a58
movq -0x468(%rbp), %rax
movq -0x148(%rbp), %rcx
movq %rcx, (%rax)
movq -0x140(%rbp), %rcx
movq %rcx, 0x8(%rax)
jmp 0x14fe4
jmp 0x14a7b
jmp 0x14a7d
movslq -0xd4(%rbp), %rax
movq %rax, -0x160(%rbp)
leaq 0x2b866(%rip), %rdi     # 0x402f8
leaq -0x160(%rbp), %rsi
callq 0x17170
movq %rax, -0x470(%rbp)
jmp 0x14aa7
movq -0x470(%rbp), %rax
movq %rax, -0x158(%rbp)
leaq 0x2b83c(%rip), %rdi     # 0x402f8
callq 0x17020
movq %rax, -0x168(%rbp)
leaq -0x158(%rbp), %rdi
leaq -0x168(%rbp), %rsi
callq 0x17050
testb $0x1, %al
jne 0x14ae4
jmp 0x14cf9
leaq -0x158(%rbp), %rdi
callq 0x171a0
movq %rax, %rsi
leaq 0x2b86e(%rip), %rdi     # 0x40368
callq 0x170c0
movq %rax, -0x478(%rbp)
jmp 0x14b08
movq -0x478(%rbp), %rax
movq %rax, -0x200(%rbp)
leaq -0x200(%rbp), %rdi
callq 0x170f0
movq %rax, %rsi
addq $0x8, %rsi
leaq -0x1f8(%rbp), %rdi
callq 0xd980
jmp 0x14b37
leaq -0x158(%rbp), %rdi
callq 0x171a0
movups 0x8(%rax), %xmm0
movaps %xmm0, -0x210(%rbp)
movl -0x210(%rbp), %edx
movq -0x208(%rbp), %rcx
leaq -0x1d8(%rbp), %rdi
leaq -0x1f8(%rbp), %rsi
callq 0x9d90
jmp 0x14b70
movq -0x18(%rbp), %rdx
movl -0x1c(%rbp), %ecx
leaq -0x1a0(%rbp), %rdi
leaq -0x1d8(%rbp), %rsi
callq 0x13c40
jmp 0x14b8c
leaq -0x1d8(%rbp), %rdi
callq 0xbc80
leaq -0x1f8(%rbp), %rdi
callq 0x44a0
leaq -0x1a0(%rbp), %rdi
callq 0xb8c0
movq %rax, -0x480(%rbp)
jmp 0x14bb9
movq -0x480(%rbp), %rsi
movl -0xd8(%rbp), %edx
leaq -0x250(%rbp), %rdi
movl $0x1, %ecx
callq 0xd4a0
jmp 0x14bd9
leaq -0x230(%rbp), %rdi
leaq -0xb8(%rbp), %rsi
leaq -0x250(%rbp), %rdx
callq 0xd790
jmp 0x14bf5
leaq -0xb8(%rbp), %rdi
leaq -0x230(%rbp), %rsi
movq %rsi, -0x490(%rbp)
callq 0xb810
movq -0x490(%rbp), %rdi
callq 0x44a0
leaq -0x250(%rbp), %rdi
callq 0x44a0
leaq -0x1a0(%rbp), %rdi
callq 0xb8d0
movq %rax, -0x488(%rbp)
jmp 0x14c3c
movq -0x488(%rbp), %rsi
leaq -0x68(%rbp), %rdi
callq 0x2a400
movq %rax, -0x498(%rbp)
jmp 0x14c55
movq -0x498(%rbp), %rax
movq (%rax), %rcx
movq %rcx, -0x68(%rbp)
movq 0x8(%rax), %rax
movq %rax, -0x60(%rbp)
movl 0x2b5b7(%rip), %eax     # 0x40228
addl $0x1, %eax
movl %eax, 0x2b5ae(%rip)     # 0x40228
leaq -0x1a0(%rbp), %rdi
callq 0xbc80
jmp 0x14fe2
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
jmp 0x14cb1
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
leaq -0x1d8(%rbp), %rdi
callq 0xbc80
leaq -0x1f8(%rbp), %rdi
callq 0x44a0
jmp 0x150c7
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
jmp 0x14ce8
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
leaq -0x250(%rbp), %rdi
callq 0x44a0
leaq -0x1a0(%rbp), %rdi
callq 0xbc80
jmp 0x150c7
movslq -0xd4(%rbp), %rdi
movq -0x18(%rbp), %rsi
callq 0x13760
movb %al, -0x499(%rbp)
jmp 0x14d11
movb -0x499(%rbp), %al
testb $0x1, %al
jne 0x14d20
jmp 0x14edf
movslq -0xd4(%rbp), %rax
movq %rax, -0x258(%rbp)
leaq 0x2b66b(%rip), %rdi     # 0x403a0
leaq -0x258(%rbp), %rsi
callq 0x16f90
jmp 0x14d43
movslq -0xd4(%rbp), %rax
movq %rax, -0x260(%rbp)
leaq 0x2b728(%rip), %rdi     # 0x40480
leaq -0x260(%rbp), %rsi
callq 0x16f30
jmp 0x14d66
movslq -0xd4(%rbp), %rsi
movq -0x18(%rbp), %rdx
leaq -0x298(%rbp), %rdi
callq 0x13dd0
jmp 0x14d7f
movq -0x18(%rbp), %rdx
movl -0x1c(%rbp), %ecx
leaq -0x2d0(%rbp), %rdi
leaq -0x298(%rbp), %rsi
callq 0x145a0
jmp 0x14d9b
leaq -0x2d0(%rbp), %rdi
callq 0xb8c0
movq %rax, -0x4a8(%rbp)
jmp 0x14db0
movq -0x4a8(%rbp), %rsi
movl -0xd8(%rbp), %edx
leaq -0x310(%rbp), %rdi
movl $0x1, %ecx
callq 0xd4a0
jmp 0x14dd0
leaq -0x2f0(%rbp), %rdi
leaq -0xb8(%rbp), %rsi
leaq -0x310(%rbp), %rdx
callq 0xd790
jmp 0x14dec
leaq -0xb8(%rbp), %rdi
leaq -0x2f0(%rbp), %rsi
movq %rsi, -0x4b8(%rbp)
callq 0xb810
movq -0x4b8(%rbp), %rdi
callq 0x44a0
leaq -0x310(%rbp), %rdi
callq 0x44a0
leaq -0x2d0(%rbp), %rdi
callq 0xb8d0
movq %rax, -0x4b0(%rbp)
jmp 0x14e33
movq -0x4b0(%rbp), %rsi
leaq -0x68(%rbp), %rdi
callq 0x2a400
movq %rax, -0x4c0(%rbp)
jmp 0x14e4c
movq -0x4c0(%rbp), %rax
movq (%rax), %rcx
movq %rcx, -0x68(%rbp)
movq 0x8(%rax), %rax
movq %rax, -0x60(%rbp)
movl 0x2b3c0(%rip), %eax     # 0x40228
addl $0x1, %eax
movl %eax, 0x2b3b7(%rip)     # 0x40228
leaq -0x2d0(%rbp), %rdi
callq 0xbc80
leaq -0x298(%rbp), %rdi
callq 0xbc80
jmp 0x14fe0
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
jmp 0x14ece
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
jmp 0x14ec2
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
leaq -0x310(%rbp), %rdi
callq 0x44a0
leaq -0x2d0(%rbp), %rdi
callq 0xbc80
leaq -0x298(%rbp), %rdi
callq 0xbc80
jmp 0x150c7
movslq -0xd4(%rbp), %rax
movq %rax, -0x318(%rbp)
leaq 0x2b4ac(%rip), %rdi     # 0x403a0
leaq -0x318(%rbp), %rsi
callq 0x16f90
jmp 0x14f02
movslq -0xd4(%rbp), %rdi
callq 0x13a00
movq %rdx, -0x4d0(%rbp)
movl %eax, -0x4c4(%rbp)
jmp 0x14f1d
movq -0x4d0(%rbp), %rax
movl -0x4c4(%rbp), %ecx
movl %ecx, -0x328(%rbp)
movq %rax, -0x320(%rbp)
movslq -0xd4(%rbp), %rax
movq %rax, -0x330(%rbp)
leaq 0x2b454(%rip), %rdi     # 0x403a0
leaq -0x330(%rbp), %rsi
callq 0x172b0
movq %rax, -0x4d8(%rbp)
jmp 0x14f61
movq -0x4d8(%rbp), %rax
movups -0x328(%rbp), %xmm0
movups %xmm0, (%rax)
movslq -0xd4(%rbp), %rax
movq %rax, -0x338(%rbp)
leaq 0x2b4f9(%rip), %rdi     # 0x40480
leaq -0x338(%rbp), %rsi
callq 0x16f30
jmp 0x14f95
leaq 0x2b394(%rip), %rdi     # 0x40330
callq 0x16cc0
movl %eax, -0x4e4(%rbp)
movslq -0xd4(%rbp), %rax
movq %rax, -0x340(%rbp)
leaq 0x2b4c4(%rip), %rdi     # 0x40480
leaq -0x340(%rbp), %rsi
callq 0x17280
movq %rax, -0x4e0(%rbp)
jmp 0x14fd1
movq -0x4e0(%rbp), %rax
movl -0x4e4(%rbp), %ecx
movl %ecx, (%rax)
jmp 0x14fe2
jmp 0x14fe4
leaq -0xc0(%rbp), %rdi
callq 0xca80
jmp 0x146a0
leaq -0x398(%rbp), %rdi
leaq -0xb8(%rbp), %rsi
callq 0xd980
jmp 0x1500a
movups -0x68(%rbp), %xmm0
movaps %xmm0, -0x3b0(%rbp)
movl -0x3b0(%rbp), %edx
movq -0x3a8(%rbp), %rcx
leaq -0x378(%rbp), %rdi
leaq -0x398(%rbp), %rsi
callq 0x9d90
jmp 0x15037
leaq -0x58(%rbp), %rdi
movq %rdi, -0x4f0(%rbp)
leaq -0x378(%rbp), %rsi
movq %rsi, -0x4f8(%rbp)
callq 0xbf00
movq -0x4f8(%rbp), %rdi
callq 0xbc80
leaq -0x398(%rbp), %rdi
callq 0x44a0
movq -0x4f0(%rbp), %rdi
callq 0x130e0
jmp 0x1507b
movq -0x3d8(%rbp), %rdi
leaq -0x58(%rbp), %rsi
callq 0xf6d0
movl $0x1, -0x3b4(%rbp)
leaq -0xb8(%rbp), %rdi
callq 0x44a0
leaq -0x98(%rbp), %rdi
callq 0x44a0
jmp 0x1512a
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
leaq -0x398(%rbp), %rdi
callq 0x44a0
leaq -0xb8(%rbp), %rdi
callq 0x44a0
leaq -0x98(%rbp), %rdi
callq 0x44a0
jmp 0x15143
movq 0x2aef0(%rip), %rdi     # 0x3ffd8
leaq 0x16291(%rip), %rsi     # 0x2b380
callq 0x2190
movq %rax, -0x500(%rbp)
jmp 0x150fd
movq -0x500(%rbp), %rdi
movq 0x2aebd(%rip), %rsi     # 0x3ffc8
callq 0x21d0
jmp 0x15112
movq -0x3d8(%rbp), %rdi
callq 0x9cf0
jmp 0x15120
movl $0x1, -0x3b4(%rbp)
leaq -0x58(%rbp), %rdi
callq 0xbc80
movq -0x3d0(%rbp), %rax
addq $0x500, %rsp            # imm = 0x500
popq %rbp
retq
leaq -0x58(%rbp), %rdi
callq 0xbc80
movq -0x70(%rbp), %rdi
callq 0x2300
nopw %cs:(%rax,%rax)