// File: fanyazhi[P]Spline-Fitting/main.cpp
// Function: main
int main() {
    //--------------------------------------------------------------------------------------
    // Step 1: construct the anchor points or read from file
    //--------------------------------------------------------------------------------------
    std::cout << "constructing the anchor points..." << std::endl;
    std::vector<double> x { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0 };
    std::vector<double> y { 0.0, 1.0, 0.0, -1.0, 0.0, 1.0 };
    // std::vector<double> x = constructVariables("../examples/example_input_sine_x.csv");
    // std::vector<double> y = constructVariables("../examples/example_input_sine_y.csv");

    //--------------------------------------------------------------------------------------
    // Step 2: initialize amount of interpolated points you want to be returned
    //         higher number means smoother line
    //         initialize qx, qy for extraction
    //--------------------------------------------------------------------------------------
    int points = 500;
    std::vector<double> qx(points);
    std::vector<double> qy(points);

    //--------------------------------------------------------------------------------------
    // Step 3: perform cubic spline calculation
    //--------------------------------------------------------------------------------------
    std::cout << "calculating spline..." << std::endl;
    cubicSpline(x, y, qx, qy);

    //--------------------------------------------------------------------------------------
    // Optional: save result to output file
    //--------------------------------------------------------------------------------------
    std::ofstream outputFile_x("../examples/example_output_sine_x.csv");
    std::ostream_iterator<double> output_iterator_x(outputFile_x, "\n");
    std::copy(qx.begin(), qx.end(), output_iterator_x);
    outputFile_x.close();
    std::ofstream outputFile_y("../examples/example_output_sine_y.csv");
    std::ostream_iterator<double> output_iterator_y(outputFile_y, "\n");
    std::copy(qy.begin(), qy.end(), output_iterator_y);
    outputFile_y.close();

    //--------------------------------------------------------------------------------------
    // Optional: perform a continuous second derivative test to verify the result
    //--------------------------------------------------------------------------------------
    secondDerivativeTest(qx, qy);

    return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x640, %rsp            # imm = 0x640
movl $0x0, -0x4(%rbp)
movq 0x68c7(%rip), %rdi      # 0x10fd0
leaq 0x1ae6(%rip), %rsi      # 0xc1f6
callq 0x2170
movq %rax, %rdi
movq 0x6899(%rip), %rsi      # 0x10fb8
callq 0x21a0
movups 0x1b75(%rip), %xmm0     # 0xc2a0
movaps %xmm0, -0x40(%rbp)
movups 0x1b5a(%rip), %xmm0     # 0xc290
movaps %xmm0, -0x50(%rbp)
movups 0x1b3f(%rip), %xmm0     # 0xc280
movaps %xmm0, -0x60(%rbp)
leaq -0x60(%rbp), %rax
movq %rax, -0x30(%rbp)
movq $0x6, -0x28(%rbp)
leaq -0x61(%rbp), %rdi
movq %rdi, -0x600(%rbp)
callq 0x4a00
movq -0x600(%rbp), %rcx
movq -0x30(%rbp), %rsi
movq -0x28(%rbp), %rdx
leaq -0x20(%rbp), %rdi
callq 0xac90
jmp 0xa77f
leaq -0x61(%rbp), %rdi
callq 0x4a90
movups 0x1b41(%rip), %xmm0     # 0xc2d0
movaps %xmm0, -0xb0(%rbp)
movups 0x1b23(%rip), %xmm0     # 0xc2c0
movaps %xmm0, -0xc0(%rbp)
movups 0x1b05(%rip), %xmm0     # 0xc2b0
movaps %xmm0, -0xd0(%rbp)
leaq -0xd0(%rbp), %rax
movq %rax, -0xa0(%rbp)
movq $0x6, -0x98(%rbp)
leaq -0xd1(%rbp), %rdi
movq %rdi, -0x608(%rbp)
callq 0x4a00
movq -0x608(%rbp), %rcx
movq -0xa0(%rbp), %rsi
movq -0x98(%rbp), %rdx
leaq -0x90(%rbp), %rdi
callq 0xac90
jmp 0xa801
leaq -0xd1(%rbp), %rdi
callq 0x4a90
movl $0x1f4, -0xd8(%rbp)     # imm = 0x1F4
movslq -0xd8(%rbp), %rax
movq %rax, -0x618(%rbp)
leaq -0xf1(%rbp), %rdi
movq %rdi, -0x610(%rbp)
callq 0x4a00
movq -0x618(%rbp), %rsi
movq -0x610(%rbp), %rdx
leaq -0xf0(%rbp), %rdi
callq 0x4a20
jmp 0xa854
leaq -0xf1(%rbp), %rdi
callq 0x4a90
movslq -0xd8(%rbp), %rax
movq %rax, -0x628(%rbp)
leaq -0x111(%rbp), %rdi
movq %rdi, -0x620(%rbp)
callq 0x4a00
movq -0x628(%rbp), %rsi
movq -0x620(%rbp), %rdx
leaq -0x110(%rbp), %rdi
callq 0x4a20
jmp 0xa89d
leaq -0x111(%rbp), %rdi
callq 0x4a90
movq 0x6720(%rip), %rdi      # 0x10fd0
leaq 0x1961(%rip), %rsi      # 0xc218
callq 0x2170
movq %rax, -0x630(%rbp)
jmp 0xa8c5
movq -0x630(%rbp), %rdi
movq 0x66e5(%rip), %rsi      # 0x10fb8
callq 0x21a0
jmp 0xa8da
leaq -0x130(%rbp), %rdi
leaq -0x20(%rbp), %rsi
callq 0x4da0
jmp 0xa8ec
leaq -0x148(%rbp), %rdi
leaq -0x90(%rbp), %rsi
callq 0x4da0
jmp 0xa901
leaq -0x130(%rbp), %rdi
leaq -0x148(%rbp), %rsi
leaq -0xf0(%rbp), %rdx
leaq -0x110(%rbp), %rcx
callq 0x9420
jmp 0xa924
leaq -0x148(%rbp), %rdi
callq 0x4720
leaq -0x130(%rbp), %rdi
callq 0x4720
leaq 0x18eb(%rip), %rsi      # 0xc22e
leaq -0x348(%rbp), %rdi
movl $0x10, %edx
callq 0x21d0
jmp 0xa956
leaq 0x18f7(%rip), %rdx      # 0xc254
leaq -0x358(%rbp), %rdi
leaq -0x348(%rbp), %rsi
callq 0xad10
jmp 0xa972
leaq -0xf0(%rbp), %rdi
movq %rdi, -0x638(%rbp)
callq 0x4b20
movq -0x638(%rbp), %rdi
movq %rax, -0x360(%rbp)
callq 0x5dd0
movq %rax, -0x368(%rbp)
leaq -0x378(%rbp), %rdi
leaq -0x358(%rbp), %rsi
callq 0xadc0
jmp 0xa9b4
movq -0x360(%rbp), %rsi
movq -0x368(%rbp), %rdx
leaq -0x388(%rbp), %rdi
leaq -0x378(%rbp), %rcx
callq 0xad40
jmp 0xa9d7
leaq -0x348(%rbp), %rdi
callq 0x2270
jmp 0xa9e5
leaq 0x186a(%rip), %rsi      # 0xc256
leaq -0x588(%rbp), %rdi
movl $0x10, %edx
callq 0x21d0
jmp 0xa9ff
leaq 0x184e(%rip), %rdx      # 0xc254
leaq -0x598(%rbp), %rdi
leaq -0x588(%rbp), %rsi
callq 0xad10
jmp 0xaa1b
leaq -0x110(%rbp), %rdi
movq %rdi, -0x640(%rbp)
callq 0x4b20
movq -0x640(%rbp), %rdi
movq %rax, -0x5a0(%rbp)
callq 0x5dd0
movq %rax, -0x5a8(%rbp)
leaq -0x5b8(%rbp), %rdi
leaq -0x598(%rbp), %rsi
callq 0xadc0
jmp 0xaa5d
movq -0x5a0(%rbp), %rsi
movq -0x5a8(%rbp), %rdx
leaq -0x5c8(%rbp), %rdi
leaq -0x5b8(%rbp), %rcx
callq 0xad40
jmp 0xaa80
leaq -0x588(%rbp), %rdi
callq 0x2270
jmp 0xaa8e
leaq -0x5e0(%rbp), %rdi
leaq -0xf0(%rbp), %rsi
callq 0x4da0
jmp 0xaaa3
leaq -0x5f8(%rbp), %rdi
leaq -0x110(%rbp), %rsi
callq 0x4da0
jmp 0xaab8
leaq -0x5e0(%rbp), %rdi
leaq -0x5f8(%rbp), %rsi
callq 0xa300
jmp 0xaacd
leaq -0x5f8(%rbp), %rdi
callq 0x4720
leaq -0x5e0(%rbp), %rdi
callq 0x4720
movl $0x0, -0x4(%rbp)
leaq -0x588(%rbp), %rdi
callq 0x22a0
leaq -0x348(%rbp), %rdi
callq 0x22a0
leaq -0x110(%rbp), %rdi
callq 0x4720
leaq -0xf0(%rbp), %rdi
callq 0x4720
leaq -0x90(%rbp), %rdi
callq 0x4720
leaq -0x20(%rbp), %rdi
callq 0x4720
movl -0x4(%rbp), %eax
addq $0x640, %rsp            # imm = 0x640
popq %rbp
retq
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
leaq -0x61(%rbp), %rdi
callq 0x4a90
jmp 0xac86
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
leaq -0xd1(%rbp), %rdi
callq 0x4a90
jmp 0xac7d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
leaq -0xf1(%rbp), %rdi
callq 0x4a90
jmp 0xac71
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
leaq -0x111(%rbp), %rdi
callq 0x4a90
jmp 0xac65
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
jmp 0xac59
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
jmp 0xabe5
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
leaq -0x148(%rbp), %rdi
callq 0x4720
leaq -0x130(%rbp), %rdi
callq 0x4720
jmp 0xac59
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
jmp 0xac4d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
jmp 0xac41
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
jmp 0xac35
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
leaq -0x5f8(%rbp), %rdi
callq 0x4720
leaq -0x5e0(%rbp), %rdi
callq 0x4720
leaq -0x588(%rbp), %rdi
callq 0x22a0
leaq -0x348(%rbp), %rdi
callq 0x22a0
leaq -0x110(%rbp), %rdi
callq 0x4720
leaq -0xf0(%rbp), %rdi
callq 0x4720
leaq -0x90(%rbp), %rdi
callq 0x4720
leaq -0x20(%rbp), %rdi
callq 0x4720
movq -0x70(%rbp), %rdi
callq 0x2310
nop