// File: Czxck001[P]algorithms/src/fft.cc
// Function: auto fft<double>(std::vector<std::complex<double>, std::allocator<std::complex<double>>> const&)
auto fft(const CVec<T> &x) {
  // X[k] = E[k] + g^k * O[k]

  auto N = x.size();
  auto M = N / 2;

  if (N == 1) {
    return x;
  }

  // subdivide the signal into even part and odd part
  auto e = CVec<T>();
  auto o = CVec<T>();
  for (auto i = 0; i < N; i++) {
    if (i % 2 == 0) {
      e.push_back(x[i]);
    } else {
      o.push_back(x[i]);
    }
  }

  // recursively calculate sub-spectrums
  auto E = fft(e);
  auto O = fft(o);

  // calculate the spectrum from the sub-spectrums
  auto X = CVec<T>();
  for (auto k = 0; k < N; k++) {
    X.push_back(E[k % M] + cru<T>(k, N) * O[k % M]);
  }

  return X;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x130, %rsp            # imm = 0x130
movq %rdi, -0xf8(%rbp)
movq %rdi, %rax
movq %rax, -0xf0(%rbp)
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq -0x10(%rbp), %rdi
callq 0x1d10
movq %rax, -0x18(%rbp)
movq -0x18(%rbp), %rax
shrq %rax
movq %rax, -0x20(%rbp)
cmpq $0x1, -0x18(%rbp)
jne 0x1838
movq -0xf8(%rbp), %rdi
movq -0x10(%rbp), %rsi
callq 0x1d30
jmp 0x1b0a
leaq -0x38(%rbp), %rdi
xorl %esi, %esi
movl $0x18, %edx
callq 0x1080
leaq -0x38(%rbp), %rdi
callq 0x1e20
leaq -0x50(%rbp), %rdi
xorl %esi, %esi
movl $0x18, %edx
callq 0x1080
leaq -0x50(%rbp), %rdi
callq 0x1e20
movl $0x0, -0x54(%rbp)
movslq -0x54(%rbp), %rax
cmpq -0x18(%rbp), %rax
jae 0x18e3
movl -0x54(%rbp), %eax
movl $0x2, %ecx
cltd
idivl %ecx
cmpl $0x0, %edx
jne 0x18b9
movq -0x10(%rbp), %rdi
movslq -0x54(%rbp), %rsi
callq 0x1eb0
movq %rax, %rsi
leaq -0x38(%rbp), %rdi
callq 0x1e40
jmp 0x18a6
jmp 0x18d6
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
jmp 0x1af6
movq -0x10(%rbp), %rdi
movslq -0x54(%rbp), %rsi
callq 0x1eb0
movq %rax, %rsi
leaq -0x50(%rbp), %rdi
callq 0x1e40
jmp 0x18d4
jmp 0x18d6
jmp 0x18d8
movl -0x54(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x54(%rbp)
jmp 0x1871
leaq -0x80(%rbp), %rdi
leaq -0x38(%rbp), %rsi
callq 0x17e0
jmp 0x18f2
leaq -0x98(%rbp), %rdi
leaq -0x50(%rbp), %rsi
callq 0x17e0
jmp 0x1904
leaq -0xb0(%rbp), %rdi
xorl %esi, %esi
movl $0x18, %edx
callq 0x1080
leaq -0xb0(%rbp), %rdi
callq 0x1e20
movl $0x0, -0xb4(%rbp)
movslq -0xb4(%rbp), %rax
cmpq -0x18(%rbp), %rax
jae 0x1aa5
movslq -0xb4(%rbp), %rax
movq -0x20(%rbp), %rcx
xorl %edx, %edx
divq %rcx
movq %rdx, %rsi
leaq -0x80(%rbp), %rdi
callq 0x1f40
movq %rax, -0x110(%rbp)
movl -0xb4(%rbp), %edi
movl -0x18(%rbp), %esi
callq 0x1fa0
movsd %xmm1, -0x108(%rbp)
movsd %xmm0, -0x100(%rbp)
jmp 0x1981
movsd -0x108(%rbp), %xmm0
movsd -0x100(%rbp), %xmm1
movsd %xmm1, -0xe8(%rbp)
movsd %xmm0, -0xe0(%rbp)
movslq -0xb4(%rbp), %rax
movq -0x20(%rbp), %rcx
xorl %edx, %edx
divq %rcx
movq %rdx, %rsi
leaq -0x98(%rbp), %rdi
callq 0x1f40
movq %rax, %rsi
leaq -0xe8(%rbp), %rdi
callq 0x1f60
movsd %xmm1, -0x120(%rbp)
movsd %xmm0, -0x118(%rbp)
jmp 0x19e1
movq -0x110(%rbp), %rdi
movsd -0x120(%rbp), %xmm0
movsd -0x118(%rbp), %xmm1
movsd %xmm1, -0xd8(%rbp)
movsd %xmm0, -0xd0(%rbp)
leaq -0xd8(%rbp), %rsi
callq 0x1f00
movsd %xmm1, -0x130(%rbp)
movsd %xmm0, -0x128(%rbp)
jmp 0x1a26
movsd -0x130(%rbp), %xmm0
movsd -0x128(%rbp), %xmm1
movsd %xmm1, -0xc8(%rbp)
movsd %xmm0, -0xc0(%rbp)
leaq -0xb0(%rbp), %rdi
leaq -0xc8(%rbp), %rsi
callq 0x1ed0
jmp 0x1a5b
jmp 0x1a5d
movl -0xb4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xb4(%rbp)
jmp 0x192d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
jmp 0x1aed
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
leaq -0xb0(%rbp), %rdi
callq 0x1cb0
leaq -0x98(%rbp), %rdi
callq 0x1cb0
jmp 0x1aed
movq -0xf8(%rbp), %rdi
leaq -0xb0(%rbp), %rsi
callq 0x2050
leaq -0xb0(%rbp), %rdi
callq 0x1cb0
leaq -0x98(%rbp), %rdi
callq 0x1cb0
leaq -0x80(%rbp), %rdi
callq 0x1cb0
leaq -0x50(%rbp), %rdi
callq 0x1cb0
leaq -0x38(%rbp), %rdi
callq 0x1cb0
jmp 0x1b0a
leaq -0x80(%rbp), %rdi
callq 0x1cb0
leaq -0x50(%rbp), %rdi
callq 0x1cb0
leaq -0x38(%rbp), %rdi
callq 0x1cb0
jmp 0x1b1a
movq -0xf0(%rbp), %rax
addq $0x130, %rsp            # imm = 0x130
popq %rbp
retq
movq -0x60(%rbp), %rdi
callq 0x1130
nopw %cs:(%rax,%rax)
nopl (%rax)