// File: hdlguy[P]fft_demo/demo.cpp
// Function: main
int main(int argc, char **argv) {
    const int N  = 4096;
    const int P = 16;
    const double Fs = 327.68e6;
    const double Fc = (+500.1/N)*Fs;
    const double Wc = 2*M_PI*Fc/Fs;
    const int B = 10;
    const double A = pow(2.0,(B-1))-1.0;
    cout << "A = " << A << "\n";

    vector<double> real_vec(N);
    vector<double> imag_vec(N);

    // synthesize quantized sinusoids
    for(int i=0; i<N; i++) {
        real_vec[i] = round(A*cos(Wc*i));
        imag_vec[i] = round(A*sin(Wc*i));
    }

    // window the data for spectral analysis
    window(&real_vec);
    window(&imag_vec);

    // zero pad the vectors.
    vector<double> real_vec_pad(N*P, 0.0);
    vector<double> imag_vec_pad(N*P, 0.0);
    for (int i=0; i<N; i++) real_vec_pad[i] = real_vec[i];
    for (int i=0; i<N; i++) imag_vec_pad[i] = imag_vec[i];

    // plot time domain data
    FILE* gnuplotPipe = popen ("gnuplot -persistent", "w");
    fprintf(gnuplotPipe, "plot '-' ps 0.1 lt 6\n");
    for (int i=0; i<N*P; i++) fprintf(gnuplotPipe, "%lf\n", real_vec_pad[i]);
    fprintf(gnuplotPipe, "e");
    pclose(gnuplotPipe);

    // commpute and convert to power
    Fft::transform(real_vec_pad, imag_vec_pad);
    vector<double> powvec(N*P);
    for(int i=0; i<N*P; i++) powvec[i] = pow(real_vec_pad[i]/A,2.0) + pow(imag_vec_pad[i]/A,2.0);

    // Plot frequency domain data in dB
    gnuplotPipe = popen ("gnuplot -persistent", "w");
    fprintf(gnuplotPipe, "plot '-' ps 0.1 lt 6\n");
    for (int i=0; i<N*P; i++) fprintf(gnuplotPipe, "%lf\n", 10*log10(powvec[i]));
    fprintf(gnuplotPipe, "e");
    pclose(gnuplotPipe);

    return EXIT_SUCCESS;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x1b0, %rsp            # imm = 0x1B0
movl $0x0, -0x4(%rbp)
movl %edi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movl $0x1000, -0x14(%rbp)    # imm = 0x1000
movl $0x10, -0x18(%rbp)
movabsq $0x41b3880000000000, %rax # imm = 0x41B3880000000000
movq %rax, -0x20(%rbp)
movabsq $0x418313ca00000000, %rax # imm = 0x418313CA00000000
movq %rax, -0x28(%rbp)
movabsq $0x3fe88c712341fdd9, %rax # imm = 0x3FE88C712341FDD9
movq %rax, -0x30(%rbp)
movl $0xa, -0x34(%rbp)
movsd 0x1400(%rip), %xmm0     # 0x50c0
movsd 0x1400(%rip), %xmm1     # 0x50c8
callq 0x1160
movsd 0x13fb(%rip), %xmm1     # 0x50d0
addsd %xmm1, %xmm0
movsd %xmm0, -0x40(%rbp)
movq 0x42f3(%rip), %rdi      # 0x7fd8
leaq 0x13fc(%rip), %rsi      # 0x50e8
callq 0x10f0
movq %rax, %rdi
movsd -0x40(%rbp), %xmm0
callq 0x1190
movq %rax, %rdi
leaq 0x140f(%rip), %rsi      # 0x5117
callq 0x10f0
leaq -0x59(%rbp), %rdi
movq %rdi, -0x128(%rbp)
callq 0x2df0
movq -0x128(%rbp), %rdx
leaq -0x58(%rbp), %rdi
movl $0x1000, %esi           # imm = 0x1000
callq 0x2e10
jmp 0x3d34
leaq -0x59(%rbp), %rdi
callq 0x2e80
leaq -0x89(%rbp), %rdi
movq %rdi, -0x130(%rbp)
callq 0x2df0
movq -0x130(%rbp), %rdx
leaq -0x88(%rbp), %rdi
movl $0x1000, %esi           # imm = 0x1000
callq 0x2e10
jmp 0x3d6a
leaq -0x89(%rbp), %rdi
callq 0x2e80
movl $0x0, -0x90(%rbp)
cmpl $0x1000, -0x90(%rbp)    # imm = 0x1000
jge 0x3e9a
movsd -0x40(%rbp), %xmm0
movsd %xmm0, -0x150(%rbp)
cvtsi2sdl -0x90(%rbp), %xmm1
movsd 0x1333(%rip), %xmm0     # 0x50e0
mulsd %xmm1, %xmm0
callq 0x1180
movaps %xmm0, %xmm1
movsd -0x150(%rbp), %xmm0
mulsd %xmm1, %xmm0
callq 0x1080
movsd %xmm0, -0x148(%rbp)
movslq -0x90(%rbp), %rsi
leaq -0x58(%rbp), %rdi
callq 0x2ea0
movsd -0x148(%rbp), %xmm0
movsd %xmm0, (%rax)
movsd -0x40(%rbp), %xmm0
movsd %xmm0, -0x140(%rbp)
cvtsi2sdl -0x90(%rbp), %xmm1
movsd 0x12d5(%rip), %xmm0     # 0x50e0
mulsd %xmm1, %xmm0
callq 0x1030
movaps %xmm0, %xmm1
movsd -0x140(%rbp), %xmm0
mulsd %xmm1, %xmm0
callq 0x1080
movsd %xmm0, -0x138(%rbp)
movslq -0x90(%rbp), %rsi
leaq -0x88(%rbp), %rdi
callq 0x2ea0
movsd -0x138(%rbp), %xmm0
movsd %xmm0, (%rax)
movl -0x90(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x90(%rbp)
jmp 0x3d80
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x68(%rbp)
movl %eax, -0x6c(%rbp)
leaq -0x59(%rbp), %rdi
callq 0x2e80
jmp 0x43b1
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x68(%rbp)
movl %eax, -0x6c(%rbp)
leaq -0x89(%rbp), %rdi
callq 0x2e80
jmp 0x43a8
leaq -0x58(%rbp), %rdi
callq 0x3b90
leaq -0x88(%rbp), %rdi
callq 0x3b90
movq $0x0, -0xb0(%rbp)
leaq -0xb1(%rbp), %rdi
movq %rdi, -0x158(%rbp)
callq 0x2df0
movq -0x158(%rbp), %rcx
leaq -0xa8(%rbp), %rdi
movl $0x10000, %esi          # imm = 0x10000
leaq -0xb0(%rbp), %rdx
callq 0x43c0
jmp 0x3eee
leaq -0xb1(%rbp), %rdi
callq 0x2e80
movq $0x0, -0xd8(%rbp)
leaq -0xd9(%rbp), %rdi
movq %rdi, -0x160(%rbp)
callq 0x2df0
movq -0x160(%rbp), %rcx
leaq -0xd0(%rbp), %rdi
movl $0x10000, %esi          # imm = 0x10000
leaq -0xd8(%rbp), %rdx
callq 0x43c0
jmp 0x3f39
leaq -0xd9(%rbp), %rdi
callq 0x2e80
movl $0x0, -0xe0(%rbp)
cmpl $0x1000, -0xe0(%rbp)    # imm = 0x1000
jge 0x3fe5
movslq -0xe0(%rbp), %rsi
leaq -0x58(%rbp), %rdi
callq 0x2ea0
movsd (%rax), %xmm0
movsd %xmm0, -0x168(%rbp)
movslq -0xe0(%rbp), %rsi
leaq -0xa8(%rbp), %rdi
callq 0x2ea0
movsd -0x168(%rbp), %xmm0
movsd %xmm0, (%rax)
movl -0xe0(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xe0(%rbp)
jmp 0x3f4f
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x68(%rbp)
movl %eax, -0x6c(%rbp)
leaq -0xb1(%rbp), %rdi
callq 0x2e80
jmp 0x439c
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x68(%rbp)
movl %eax, -0x6c(%rbp)
leaq -0xd9(%rbp), %rdi
callq 0x2e80
jmp 0x4390
movl $0x0, -0xe4(%rbp)
cmpl $0x1000, -0xe4(%rbp)    # imm = 0x1000
jge 0x404a
movslq -0xe4(%rbp), %rsi
leaq -0x88(%rbp), %rdi
callq 0x2ea0
movsd (%rax), %xmm0
movsd %xmm0, -0x170(%rbp)
movslq -0xe4(%rbp), %rsi
leaq -0xd0(%rbp), %rdi
callq 0x2ea0
movsd -0x170(%rbp), %xmm0
movsd %xmm0, (%rax)
movl -0xe4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xe4(%rbp)
jmp 0x3fef
leaq 0x109c(%rip), %rdi      # 0x50ed
leaq 0x10a9(%rip), %rsi      # 0x5101
callq 0x1050
movq %rax, -0x178(%rbp)
jmp 0x4066
movq -0x178(%rbp), %rax
movq %rax, -0xf0(%rbp)
movq -0xf0(%rbp), %rdi
leaq 0x1081(%rip), %rsi      # 0x5103
movb $0x0, %al
callq 0x1120
movl $0x0, -0xf4(%rbp)
cmpl $0x10000, -0xf4(%rbp)   # imm = 0x10000
jge 0x40fb
movq -0xf0(%rbp), %rax
movq %rax, -0x180(%rbp)
movslq -0xf4(%rbp), %rsi
leaq -0xa8(%rbp), %rdi
callq 0x2ea0
movq -0x180(%rbp), %rdi
movsd (%rax), %xmm0
leaq 0x1047(%rip), %rsi      # 0x5119
movb $0x1, %al
callq 0x1120
movl -0xf4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xf4(%rbp)
jmp 0x4093
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x68(%rbp)
movl %eax, -0x6c(%rbp)
jmp 0x4384
movq -0xf0(%rbp), %rdi
leaq 0xf74(%rip), %rsi       # 0x507d
xorl %eax, %eax
callq 0x1120
movq -0xf0(%rbp), %rdi
callq 0x1110
jmp 0x411e
leaq -0xa8(%rbp), %rdi
leaq -0xd0(%rbp), %rsi
callq 0x12e0
jmp 0x4133
leaq -0x111(%rbp), %rdi
movq %rdi, -0x188(%rbp)
callq 0x2df0
movq -0x188(%rbp), %rdx
leaq -0x110(%rbp), %rdi
movl $0x10000, %esi          # imm = 0x10000
callq 0x2e10
jmp 0x4160
leaq -0x111(%rbp), %rdi
callq 0x2e80
movl $0x0, -0x118(%rbp)
cmpl $0x10000, -0x118(%rbp)  # imm = 0x10000
jge 0x4247
movslq -0x118(%rbp), %rsi
leaq -0xa8(%rbp), %rdi
callq 0x2ea0
movsd (%rax), %xmm0
divsd -0x40(%rbp), %xmm0
movsd 0xf16(%rip), %xmm1      # 0x50c0
callq 0x1160
movsd %xmm0, -0x198(%rbp)
movslq -0x118(%rbp), %rsi
leaq -0xd0(%rbp), %rdi
callq 0x2ea0
movsd (%rax), %xmm0
divsd -0x40(%rbp), %xmm0
movsd 0xee5(%rip), %xmm1      # 0x50c0
callq 0x1160
movaps %xmm0, %xmm1
movsd -0x198(%rbp), %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, -0x190(%rbp)
movslq -0x118(%rbp), %rsi
leaq -0x110(%rbp), %rdi
callq 0x2ea0
movsd -0x190(%rbp), %xmm0
movsd %xmm0, (%rax)
movl -0x118(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x118(%rbp)
jmp 0x4176
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x68(%rbp)
movl %eax, -0x6c(%rbp)
leaq -0x111(%rbp), %rdi
callq 0x2e80
jmp 0x4384
leaq 0xe9f(%rip), %rdi       # 0x50ed
leaq 0xeac(%rip), %rsi       # 0x5101
callq 0x1050
movq %rax, -0x1a0(%rbp)
jmp 0x4263
movq -0x1a0(%rbp), %rax
movq %rax, -0xf0(%rbp)
movq -0xf0(%rbp), %rdi
leaq 0xe84(%rip), %rsi       # 0x5103
movb $0x0, %al
callq 0x1120
movl $0x0, -0x11c(%rbp)
cmpl $0x10000, -0x11c(%rbp)  # imm = 0x10000
jge 0x4315
movq -0xf0(%rbp), %rax
movq %rax, -0x1a8(%rbp)
movslq -0x11c(%rbp), %rsi
leaq -0x110(%rbp), %rdi
callq 0x2ea0
movsd (%rax), %xmm0
callq 0x10a0
movq -0x1a8(%rbp), %rdi
movaps %xmm0, %xmm1
movsd 0xe00(%rip), %xmm0      # 0x50d8
mulsd %xmm1, %xmm0
leaq 0xe36(%rip), %rsi       # 0x5119
movb $0x1, %al
callq 0x1120
movl -0x11c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x11c(%rbp)
jmp 0x4290
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x68(%rbp)
movl %eax, -0x6c(%rbp)
leaq -0x110(%rbp), %rdi
callq 0x2ec0
jmp 0x4384
movq -0xf0(%rbp), %rdi
leaq 0xd5a(%rip), %rsi       # 0x507d
xorl %eax, %eax
callq 0x1120
movq -0xf0(%rbp), %rdi
callq 0x1110
jmp 0x4338
movl $0x0, -0x4(%rbp)
leaq -0x110(%rbp), %rdi
callq 0x2ec0
leaq -0xd0(%rbp), %rdi
callq 0x2ec0
leaq -0xa8(%rbp), %rdi
callq 0x2ec0
leaq -0x88(%rbp), %rdi
callq 0x2ec0
leaq -0x58(%rbp), %rdi
callq 0x2ec0
movl -0x4(%rbp), %eax
addq $0x1b0, %rsp            # imm = 0x1B0
popq %rbp
retq
leaq -0xd0(%rbp), %rdi
callq 0x2ec0
leaq -0xa8(%rbp), %rdi
callq 0x2ec0
leaq -0x88(%rbp), %rdi
callq 0x2ec0
leaq -0x58(%rbp), %rdi
callq 0x2ec0
movq -0x68(%rbp), %rdi
callq 0x1170
nopw (%rax,%rax)