// File: manschga[P]M5GB/./poly.h
// Function: polynomial::operator+(polynomial const&) const
polynomial operator+(const polynomial& rhs) const
  {
    //polynomial test_1 = *this;
    //polynomial test_2 = rhs;
    //cout << "Add " << test_1 << "and" << test_2 << endl;

    //compute *this+rhs = f+g (sum of polynomials)
    vector<monomial> f_mon = this->_monomials;

    if (this->Get_LC() == 0)
      {
	return rhs;
      }
    if (rhs.Get_LC() == 0)
      {
	return *this;
      }
    
    vector<monomial> g_mon = rhs._monomials;
    reverse(f_mon.begin(),f_mon.end());
    reverse(g_mon.begin(),g_mon.end());
    vector<monomial> h_mon = {};

    int f_i = f_mon.size()-1;
    int g_i = g_mon.size()-1;
    h_mon.reserve(f_i+g_i+2);
    vector<monomial> merged(f_i+g_i+2);
    std::merge(f_mon.begin(),f_mon.end(),g_mon.begin(),g_mon.end(),merged.begin());

    if (merged.size() > 1)
      {
	for (int i = 0; i < merged.size()-1; ++i)
	  {
	    //if (count(merged[i], merged[i+1], merged[i+1].Get_term()) == 1) 
	    if (merged[i].Get_term() != merged[i+1].Get_term())
	      {
		h_mon.push_back(merged[i]);
	      }
	    else
	      {
		++i;// do sum of both in one step
		//push_back sum of coeffs, case p != 2
	      }
	  }
	{
	  if (merged[merged.size()-2].Get_term() < merged[merged.size()-1].Get_term())
	    {
	      h_mon.push_back(merged[merged.size()-1]);
	    }
	}
      }
    else
      {
	h_mon = merged;
      }
    reverse(h_mon.begin(),h_mon.end());
    /*
    
   
    while (f_i >= 0 || g_i >= 0)//go through all terms of f and g
      {
	if (f_i < 0) //all terms of f done, avoid index crash!
	{
	  h_mon.emplace_back(g_mon[g_i]);
	  g_i--;
	}
      else if (g_i < 0)
	{
	  h_mon.emplace_back(f_mon[f_i]);
	  f_i--;
	}
	else
	{
	  if (f_mon[f_i].Get_term() == g_mon[g_i].Get_term())
	    {//same term appears in both, add up coefficients
	      h_mon.emplace_back(monomial(f_mon[f_i].Get_term(), (f_mon[f_i].Get_coeff() + g_mon[g_i].Get_coeff())%rhs._p, f_mon[f_i].Get_p()));
	      f_i--;
	      g_i--;
	    }
	  else
	    {
	      if (f_mon[f_i].Get_term()< g_mon[g_i].Get_term())
		{
		  h_mon.emplace_back(f_mon[f_i]);
		  f_i--;
		}
	      else
		{
		  h_mon.emplace_back(g_mon[g_i]);
		  g_i--;
		}
	    }
      }
      }
    */
    if (h_mon.size() == 0)
      {
	int p = this->Get_p();
	polynomial h({monomial(0,0,p)});
	//cout << "equals" << h << endl;
	return h;
      }
    polynomial h(h_mon);
    //cout << "in addtion, p:" << h.Get_p() << endl;
    //h = h.update();
    //reorder, remove zeros, do a function!
    return h;
  }

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x1e0, %rsp            # imm = 0x1E0
movq %rdi, -0x160(%rbp)
movq %rdi, %rax
movq %rax, -0x158(%rbp)
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq -0x10(%rbp), %rsi
movq %rsi, -0x150(%rbp)
leaq -0x30(%rbp), %rdi
callq 0xd190
movq -0x150(%rbp), %rdi
callq 0xe7c0
movl %eax, -0x148(%rbp)
jmp 0xdad0
movl -0x148(%rbp), %eax
cmpl $0x0, %eax
jne 0xdb0a
movq -0x160(%rbp), %rdi
movq -0x18(%rbp), %rsi
callq 0xd980
jmp 0xdaed
movl $0x1, -0x40(%rbp)
jmp 0xe10d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
jmp 0xe126
movq -0x18(%rbp), %rdi
callq 0xe7c0
movl %eax, -0x164(%rbp)
jmp 0xdb1b
movl -0x164(%rbp), %eax
cmpl $0x0, %eax
jne 0xdb47
movq -0x150(%rbp), %rsi
movq -0x160(%rbp), %rdi
callq 0xd980
jmp 0xdb3b
movl $0x1, -0x40(%rbp)
jmp 0xe10d
movq -0x18(%rbp), %rsi
leaq -0x58(%rbp), %rdi
callq 0xd190
jmp 0xdb56
leaq -0x30(%rbp), %rdi
movq %rdi, -0x170(%rbp)
callq 0xc6d0
movq -0x170(%rbp), %rdi
movq %rax, -0x60(%rbp)
callq 0xc700
movq %rax, -0x68(%rbp)
movq -0x60(%rbp), %rdi
movq -0x68(%rbp), %rsi
callq 0xe7f0
jmp 0xdb89
leaq -0x58(%rbp), %rdi
movq %rdi, -0x178(%rbp)
callq 0xc6d0
movq -0x178(%rbp), %rdi
movq %rax, -0x70(%rbp)
callq 0xc700
movq %rax, -0x78(%rbp)
movq -0x70(%rbp), %rdi
movq -0x78(%rbp), %rsi
callq 0xe7f0
jmp 0xdbbc
xorps %xmm0, %xmm0
movaps %xmm0, -0x90(%rbp)
movq $0x0, -0x80(%rbp)
leaq -0x90(%rbp), %rdi
movq %rdi, -0x180(%rbp)
callq 0xd9c0
leaq -0x30(%rbp), %rdi
callq 0xc4b0
decl %eax
movl %eax, -0x94(%rbp)
leaq -0x58(%rbp), %rdi
callq 0xc4b0
movq -0x180(%rbp), %rdi
decl %eax
movl %eax, -0x98(%rbp)
movl -0x94(%rbp), %edx
movl -0x98(%rbp), %eax
movl %eax, %ecx
movl %edx, %eax
leal 0x2(%rax,%rcx), %eax
movslq %eax, %rsi
callq 0xe830
jmp 0xdc28
movl -0x94(%rbp), %edx
movl -0x98(%rbp), %eax
movl %eax, %ecx
movl %edx, %eax
leal 0x2(%rax,%rcx), %eax
cltq
movq %rax, -0x190(%rbp)
leaq -0xb1(%rbp), %rdi
movq %rdi, -0x188(%rbp)
callq 0xe930
movq -0x190(%rbp), %rsi
movq -0x188(%rbp), %rdx
leaq -0xb0(%rbp), %rdi
callq 0xe950
jmp 0xdc74
leaq -0xb1(%rbp), %rdi
callq 0x46a0
leaq -0x30(%rbp), %rdi
movq %rdi, -0x1a8(%rbp)
callq 0xc6d0
movq -0x1a8(%rbp), %rdi
movq %rax, -0xc0(%rbp)
callq 0xc700
movq %rax, -0xc8(%rbp)
leaq -0x58(%rbp), %rdi
movq %rdi, -0x1a0(%rbp)
callq 0xc6d0
movq -0x1a0(%rbp), %rdi
movq %rax, -0xd0(%rbp)
callq 0xc700
movq %rax, -0xd8(%rbp)
leaq -0xb0(%rbp), %rdi
callq 0xc6d0
movq %rax, -0xe0(%rbp)
movq -0xc0(%rbp), %rdi
movq -0xc8(%rbp), %rsi
movq -0xd0(%rbp), %rdx
movq -0xd8(%rbp), %rcx
movq -0xe0(%rbp), %r8
callq 0xe9c0
movq %rax, -0x198(%rbp)
jmp 0xdd18
movq -0x198(%rbp), %rax
movq %rax, -0xe8(%rbp)
leaq -0xb0(%rbp), %rdi
callq 0xc4b0
cmpq $0x1, %rax
jbe 0xdf01
movl $0x0, -0xec(%rbp)
movslq -0xec(%rbp), %rax
movq %rax, -0x1b0(%rbp)
leaq -0xb0(%rbp), %rdi
callq 0xc4b0
movq %rax, %rcx
movq -0x1b0(%rbp), %rax
subq $0x1, %rcx
cmpq %rcx, %rax
jae 0xde63
movslq -0xec(%rbp), %rsi
leaq -0xb0(%rbp), %rdi
callq 0xd280
movq %rax, %rdi
callq 0xda60
movq %rax, -0x1b8(%rbp)
movl -0xec(%rbp), %eax
addl $0x1, %eax
movslq %eax, %rsi
leaq -0xb0(%rbp), %rdi
callq 0xd280
movq %rax, %rdi
callq 0xda60
movq %rax, %rcx
movq -0x1b8(%rbp), %rax
cmpq %rcx, %rax
je 0xde3e
movslq -0xec(%rbp), %rsi
leaq -0xb0(%rbp), %rdi
callq 0xd280
movq %rax, %rsi
leaq -0x90(%rbp), %rdi
callq 0xea30
jmp 0xddec
jmp 0xde4d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
jmp 0xe102
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
jmp 0xe0f6
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
leaq -0xb1(%rbp), %rdi
callq 0x46a0
jmp 0xe0f6
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
jmp 0xe0ea
movl -0xec(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xec(%rbp)
jmp 0xde4f
movl -0xec(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xec(%rbp)
jmp 0xdd46
leaq -0xb0(%rbp), %rdi
callq 0xc4b0
movq %rax, %rsi
subq $0x2, %rsi
leaq -0xb0(%rbp), %rdi
callq 0xd280
movq %rax, %rdi
callq 0xda60
movq %rax, -0x1c0(%rbp)
leaq -0xb0(%rbp), %rdi
callq 0xc4b0
movq %rax, %rsi
subq $0x1, %rsi
leaq -0xb0(%rbp), %rdi
callq 0xd280
movq %rax, %rdi
callq 0xda60
movq %rax, %rcx
movq -0x1c0(%rbp), %rax
cmpq %rcx, %rax
jge 0xdeff
leaq -0xb0(%rbp), %rdi
movq %rdi, -0x1c8(%rbp)
callq 0xc4b0
movq -0x1c8(%rbp), %rdi
movq %rax, %rsi
decq %rsi
callq 0xd280
movq %rax, %rsi
leaq -0x90(%rbp), %rdi
callq 0xea30
jmp 0xdefd
jmp 0xdeff
jmp 0xdf18
leaq -0x90(%rbp), %rdi
leaq -0xb0(%rbp), %rsi
callq 0xc260
jmp 0xdf16
jmp 0xdf18
leaq -0x90(%rbp), %rdi
movq %rdi, -0x1d0(%rbp)
callq 0xc6d0
movq -0x1d0(%rbp), %rdi
movq %rax, -0xf8(%rbp)
callq 0xc700
movq %rax, -0x100(%rbp)
movq -0xf8(%rbp), %rdi
movq -0x100(%rbp), %rsi
callq 0xe7f0
jmp 0xdf5a
leaq -0x90(%rbp), %rdi
callq 0xc4b0
cmpq $0x0, %rax
jne 0xe086
movq -0x150(%rbp), %rdi
callq 0xb890
movl %eax, -0x1d4(%rbp)
jmp 0xdf84
movl -0x1d4(%rbp), %eax
movl %eax, -0x104(%rbp)
movb $0x0, -0x105(%rbp)
movl -0x104(%rbp), %ecx
xorl %edx, %edx
movl %edx, %esi
leaq -0x140(%rbp), %rdi
callq 0x25de0
jmp 0xdfaf
leaq -0x140(%rbp), %rax
movq %rax, -0x130(%rbp)
movq $0x1, -0x128(%rbp)
leaq -0x141(%rbp), %rdi
movq %rdi, -0x1e0(%rbp)
callq 0xe930
movq -0x1e0(%rbp), %rcx
movq -0x130(%rbp), %rsi
movq -0x128(%rbp), %rdx
leaq -0x120(%rbp), %rdi
callq 0xeaa0
jmp 0xdffe
movq -0x160(%rbp), %rdi
leaq -0x120(%rbp), %rsi
callq 0x25f60
jmp 0xe013
leaq -0x120(%rbp), %rdi
callq 0x44c0
leaq -0x141(%rbp), %rdi
callq 0x46a0
movb $0x1, -0x105(%rbp)
movl $0x1, -0x40(%rbp)
testb $0x1, -0x105(%rbp)
jne 0xe084
jmp 0xe078
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
jmp 0xe06a
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
leaq -0x120(%rbp), %rdi
callq 0x44c0
leaq -0x141(%rbp), %rdi
callq 0x46a0
jmp 0xe0ea
movq -0x160(%rbp), %rdi
callq 0x44a0
jmp 0xe0c7
movq -0x160(%rbp), %rdi
movb $0x0, -0x142(%rbp)
leaq -0x90(%rbp), %rsi
callq 0x25f60
jmp 0xe0a2
movb $0x1, -0x142(%rbp)
movl $0x1, -0x40(%rbp)
testb $0x1, -0x142(%rbp)
jne 0xe0c5
movq -0x160(%rbp), %rdi
callq 0x44a0
jmp 0xe0c7
leaq -0xb0(%rbp), %rdi
callq 0x44c0
leaq -0x90(%rbp), %rdi
callq 0x44c0
leaq -0x58(%rbp), %rdi
callq 0x44c0
jmp 0xe10d
leaq -0xb0(%rbp), %rdi
callq 0x44c0
leaq -0x90(%rbp), %rdi
callq 0x44c0
leaq -0x58(%rbp), %rdi
callq 0x44c0
jmp 0xe126
leaq -0x30(%rbp), %rdi
callq 0x44c0
movq -0x158(%rbp), %rax
addq $0x1e0, %rsp            # imm = 0x1E0
popq %rbp
retq
leaq -0x30(%rbp), %rdi
callq 0x44c0
movq -0x38(%rbp), %rdi
callq 0x2300
nopl (%rax,%rax)