// File: princelab[P]emass/emass.cpp
// Function: convolute_basic(std::vector<peak, std::allocator<peak>>&, std::vector<peak, std::allocator<peak>> const&, std::vector<peak, std::allocator<peak>> const&)
void convolute_basic(Pattern & h, const Pattern & g, const Pattern & f)
{
  h.clear();
  size_t g_n = g.size();
  size_t f_n = f.size();
  if(g_n == 0 || f_n == 0)
     return;
  for(size_t k = 0; k < g_n + f_n - 1; k++) {
    double sumweight = 0, summass = 0;
    size_t start = k < (f_n - 1) ? 0 : k - f_n + 1; // max(0, k-f_n+1)
    size_t end = k < (g_n - 1) ? k : g_n - 1;       // min(g_n - 1, k)
    for(size_t i = start; i <= end; i++) {
      double weight = g[i].rel_area * f[k - i].rel_area;
      double mass = g[i].mass + f[k - i].mass;
      sumweight += weight;
      summass += weight * mass;
    }
    peak p;
    if(sumweight == 0)
      p.mass = DUMMY_MASS;
    else
      p.mass = summass / sumweight;
    p.rel_area = sumweight;
    h.push_back(p);
  }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xa0, %rsp
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq -0x8(%rbp), %rdi
callq 0x6450
movq -0x10(%rbp), %rdi
callq 0x6380
movq %rax, -0x20(%rbp)
movq -0x18(%rbp), %rdi
callq 0x6380
movq %rax, -0x28(%rbp)
cmpq $0x0, -0x20(%rbp)
je 0x4e98
cmpq $0x0, -0x28(%rbp)
jne 0x4e9d
jmp 0x5057
movq $0x0, -0x30(%rbp)
movq -0x30(%rbp), %rax
movq -0x20(%rbp), %rcx
addq -0x28(%rbp), %rcx
subq $0x1, %rcx
cmpq %rcx, %rax
jae 0x5057
xorps %xmm0, %xmm0
movsd %xmm0, -0x38(%rbp)
xorps %xmm0, %xmm0
movsd %xmm0, -0x40(%rbp)
movq -0x30(%rbp), %rax
movq -0x28(%rbp), %rcx
subq $0x1, %rcx
cmpq %rcx, %rax
jae 0x4ee7
xorl %eax, %eax
movq %rax, -0x80(%rbp)
jmp 0x4ef7
movq -0x30(%rbp), %rax
subq -0x28(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x80(%rbp)
movq -0x80(%rbp), %rax
movq %rax, -0x48(%rbp)
movq -0x30(%rbp), %rax
movq -0x20(%rbp), %rcx
subq $0x1, %rcx
cmpq %rcx, %rax
jae 0x4f1d
movq -0x30(%rbp), %rax
movq %rax, -0x88(%rbp)
jmp 0x4f2c
movq -0x20(%rbp), %rax
subq $0x1, %rax
movq %rax, -0x88(%rbp)
movq -0x88(%rbp), %rax
movq %rax, -0x50(%rbp)
movq -0x48(%rbp), %rax
movq %rax, -0x58(%rbp)
movq -0x58(%rbp), %rax
cmpq -0x50(%rbp), %rax
ja 0x5001
movq -0x10(%rbp), %rdi
movq -0x58(%rbp), %rsi
callq 0x6470
movsd 0x8(%rax), %xmm0
movsd %xmm0, -0x98(%rbp)
movq -0x18(%rbp), %rdi
movq -0x30(%rbp), %rsi
subq -0x58(%rbp), %rsi
callq 0x6470
movsd -0x98(%rbp), %xmm0
mulsd 0x8(%rax), %xmm0
movsd %xmm0, -0x60(%rbp)
movq -0x10(%rbp), %rdi
movq -0x58(%rbp), %rsi
callq 0x6470
movsd (%rax), %xmm0
movsd %xmm0, -0x90(%rbp)
movq -0x18(%rbp), %rdi
movq -0x30(%rbp), %rsi
subq -0x58(%rbp), %rsi
callq 0x6470
movsd -0x90(%rbp), %xmm0
addsd (%rax), %xmm0
movsd %xmm0, -0x68(%rbp)
movsd -0x60(%rbp), %xmm0
addsd -0x38(%rbp), %xmm0
movsd %xmm0, -0x38(%rbp)
movsd -0x60(%rbp), %xmm0
movsd -0x68(%rbp), %xmm2
movsd -0x40(%rbp), %xmm1
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, -0x40(%rbp)
movq -0x58(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x58(%rbp)
jmp 0x4f3f
movsd -0x38(%rbp), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jne 0x5020
jp 0x5020
movsd 0xcff7(%rip), %xmm0     # 0x12010
movsd %xmm0, -0x78(%rbp)
jmp 0x502f
movsd -0x40(%rbp), %xmm0
divsd -0x38(%rbp), %xmm0
movsd %xmm0, -0x78(%rbp)
movsd -0x38(%rbp), %xmm0
movsd %xmm0, -0x70(%rbp)
movq -0x8(%rbp), %rdi
leaq -0x78(%rbp), %rsi
callq 0x63e0
movq -0x30(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x30(%rbp)
jmp 0x4ea5
addq $0xa0, %rsp
popq %rbp
retq