// File: tomfunkhouser[P]gaps/pkgs/RNMath/RNPolynomial.cpp
// Function: gaps::RNPolynomial::Multiply(gaps::RNPolynomial const&)
void RNPolynomial::
Multiply(const RNPolynomial& polynomial)
{
  // Check special cases for speed
  if (IsZero()) {
    // Do nothing
  }
  else if (polynomial.IsZero()) {
    Multiply(0.0);
  }
  else if (polynomial.IsConstant()) {
    // Polynomial is constant (multiply by factor)
    assert(polynomial.NTerms() == 1);
    RNPolynomialTerm *term = polynomial.Term(0);
    assert(term->IsConstant());
    Multiply(term->Coefficient());
  }
  else {
    // Convenient variables
    RNPolynomial polynomial1(*this);
    RNPolynomial polynomial2(polynomial);
    const int max_factors = 1024;
    int v [ max_factors ];
    RNScalar e [ max_factors ];
    int n = 0;
    
    // Start from scratch
    Empty();
    
    // For each term of this polynomial
    for (int i = 0; i < polynomial1.NTerms(); i++) {
      RNPolynomialTerm *term1 = polynomial1.Term(i);
      
      // Start with factors from this term
      n = 0;
      for (int k = 0; k < term1->NVariables(); k++) {
        if (n >= max_factors) break;
        v[n] = term1->Variable(k);
        e[n] = term1->Exponent(k);
        n++;
      }
      
      // For each term of other polynomial
      for (int j = 0; j < polynomial2.NTerms(); j++) {
        RNPolynomialTerm *term2 = polynomial2.Term(j);
        
        // Include factors from other term
        n = term1->NVariables();
        for (int k = 0; k < term2->NVariables(); k++) {
          if (n >= max_factors) break;
          v[n] = term2->Variable(k);
          e[n] = term2->Exponent(k);
          n++;
        }
        
        // Add term to this polynomial
        AddTerm(term1->Coefficient() * term2->Coefficient(), n, v, e);
      }
    }
  }
}

// Assembly:
subq $0x30d8, %rsp           # imm = 0x30D8
movq %rdi, 0x30d0(%rsp)
movq %rsi, 0x30c8(%rsp)
movq 0x30d0(%rsp), %rdi
movq %rdi, 0x60(%rsp)
callq 0x3cf90
cmpl $0x0, %eax
je 0x3d7b3
jmp 0x3dbb0
movq 0x30c8(%rsp), %rdi
callq 0x3cf90
cmpl $0x0, %eax
je 0x3d7d7
movq 0x60(%rsp), %rdi
xorps %xmm0, %xmm0
callq 0x3d4e0
jmp 0x3dbae
movq 0x30c8(%rsp), %rdi
callq 0x3d070
cmpl $0x0, %eax
je 0x3d81c
movq 0x30c8(%rsp), %rdi
xorl %esi, %esi
callq 0x3f5d0
movq %rax, 0x30c0(%rsp)
movq 0x30c0(%rsp), %rdi
callq 0x3f6a0
movq 0x60(%rsp), %rdi
callq 0x3d4e0
jmp 0x3dbac
movq 0x60(%rsp), %rsi
leaq 0x30b0(%rsp), %rdi
callq 0x3c530
movq 0x30c8(%rsp), %rsi
leaq 0x30a0(%rsp), %rdi
callq 0x3c530
jmp 0x3d845
movq 0x60(%rsp), %rdi
movl $0x400, 0x3090(%rsp) # imm = 0x400
movl $0x0, 0x8c(%rsp)
callq 0x3cb00
jmp 0x3d867
movl $0x0, 0x88(%rsp)
movl 0x88(%rsp), %eax
movl %eax, 0x58(%rsp)
leaq 0x30b0(%rsp), %rdi
callq 0x3f5c0
movl %eax, 0x5c(%rsp)
jmp 0x3d890
movl 0x58(%rsp), %eax
movl 0x5c(%rsp), %ecx
cmpl %ecx, %eax
jge 0x3db81
movl 0x88(%rsp), %esi
leaq 0x30b0(%rsp), %rdi
callq 0x3f5d0
movq %rax, 0x50(%rsp)
jmp 0x3d8bb
movq 0x50(%rsp), %rax
movq %rax, 0x80(%rsp)
movl $0x0, 0x8c(%rsp)
movl $0x0, 0x7c(%rsp)
movl 0x7c(%rsp), %eax
movl %eax, 0x48(%rsp)
movq 0x80(%rsp), %rdi
callq 0x3f6b0
movl %eax, 0x4c(%rsp)
jmp 0x3d8f6
movl 0x48(%rsp), %eax
movl 0x4c(%rsp), %ecx
cmpl %ecx, %eax
jge 0x3d9d2
cmpl $0x400, 0x8c(%rsp) # imm = 0x400
jl 0x3d957
jmp 0x3d9d2
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x3098(%rsp)
movl %eax, 0x3094(%rsp)
jmp 0x3db9d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x3098(%rsp)
movl %eax, 0x3094(%rsp)
leaq 0x30a0(%rsp), %rdi
callq 0x3cac0
jmp 0x3db9d
movq 0x80(%rsp), %rdi
movl 0x7c(%rsp), %esi
callq 0x3f6e0
movl %eax, 0x44(%rsp)
jmp 0x3d96e
movl 0x44(%rsp), %ecx
movslq 0x8c(%rsp), %rax
movl %ecx, 0x2090(%rsp,%rax,4)
movq 0x80(%rsp), %rdi
movl 0x7c(%rsp), %esi
callq 0x3f700
movsd %xmm0, 0x38(%rsp)
jmp 0x3d99a
movsd 0x38(%rsp), %xmm0
movslq 0x8c(%rsp), %rax
movsd %xmm0, 0x90(%rsp,%rax,8)
movl 0x8c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x8c(%rsp)
movl 0x7c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x7c(%rsp)
jmp 0x3d8db
movl $0x0, 0x78(%rsp)
movl 0x78(%rsp), %eax
movl %eax, 0x30(%rsp)
leaq 0x30a0(%rsp), %rdi
callq 0x3f5c0
movl %eax, 0x34(%rsp)
jmp 0x3d9f5
movl 0x30(%rsp), %eax
movl 0x34(%rsp), %ecx
cmpl %ecx, %eax
jge 0x3db69
movl 0x78(%rsp), %esi
leaq 0x30a0(%rsp), %rdi
callq 0x3f5d0
movq %rax, 0x28(%rsp)
jmp 0x3da1d
movq 0x28(%rsp), %rax
movq %rax, 0x70(%rsp)
movq 0x80(%rsp), %rdi
callq 0x3f6b0
movl %eax, 0x24(%rsp)
jmp 0x3da3a
movl 0x24(%rsp), %eax
movl %eax, 0x8c(%rsp)
movl $0x0, 0x6c(%rsp)
movl 0x6c(%rsp), %eax
movl %eax, 0x1c(%rsp)
movq 0x70(%rsp), %rdi
callq 0x3f6b0
movl %eax, 0x20(%rsp)
jmp 0x3da65
movl 0x1c(%rsp), %eax
movl 0x20(%rsp), %ecx
cmpl %ecx, %eax
jge 0x3daf9
cmpl $0x400, 0x8c(%rsp) # imm = 0x400
jl 0x3da84
jmp 0x3daf9
movq 0x70(%rsp), %rdi
movl 0x6c(%rsp), %esi
callq 0x3f6e0
movl %eax, 0x18(%rsp)
jmp 0x3da98
movl 0x18(%rsp), %ecx
movslq 0x8c(%rsp), %rax
movl %ecx, 0x2090(%rsp,%rax,4)
movq 0x70(%rsp), %rdi
movl 0x6c(%rsp), %esi
callq 0x3f700
movsd %xmm0, 0x10(%rsp)
jmp 0x3dac1
movsd 0x10(%rsp), %xmm0
movslq 0x8c(%rsp), %rax
movsd %xmm0, 0x90(%rsp,%rax,8)
movl 0x8c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x8c(%rsp)
movl 0x6c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x6c(%rsp)
jmp 0x3da4d
movq 0x80(%rsp), %rdi
callq 0x3f6a0
movsd %xmm0, 0x8(%rsp)
jmp 0x3db0e
movq 0x70(%rsp), %rdi
callq 0x3f6a0
movsd %xmm0, (%rsp)
jmp 0x3db1f
movq 0x60(%rsp), %rdi
movsd (%rsp), %xmm1
movsd 0x8(%rsp), %xmm0
mulsd %xmm1, %xmm0
movl 0x8c(%rsp), %esi
leaq 0x2090(%rsp), %rdx
leaq 0x90(%rsp), %rcx
xorl %r9d, %r9d
movl %r9d, %r8d
callq 0x3c760
jmp 0x3db57
jmp 0x3db59
movl 0x78(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x78(%rsp)
jmp 0x3d9da
jmp 0x3db6b
movl 0x88(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x88(%rsp)
jmp 0x3d872
leaq 0x30a0(%rsp), %rdi
callq 0x3cac0
leaq 0x30b0(%rsp), %rdi
callq 0x3cac0
jmp 0x3dbac
leaq 0x30b0(%rsp), %rdi
callq 0x3cac0
jmp 0x3dbb8
jmp 0x3dbae
jmp 0x3dbb0
addq $0x30d8, %rsp           # imm = 0x30D8
retq
movq 0x3098(%rsp), %rdi
callq 0x44b0
nopw %cs:(%rax,%rax)