// File: /workspace/github_cpp_makefile_star2_O2/sus304[P]ForRocket/src/interpolate.cpp
// Function: forrocket::interpolate::Linear1D::polate(double const&, std::vector<double, std::allocator<double>> const&, std::vector<double, std::allocator<double>> const&, int const&)
double forrocket::interpolate::Linear1D::polate(const double& x, const std::vector<double>& x_src, const std::vector<double>& y_src, const int& fill_value) {
    if (x >= x_src[0] && x <= x_src.back()) {  // 内挿
        // TODO: binary search
        for (int i=0; i < x_src.size(); ++i) {
            if (x == x_src[i]) {
                return y_src[i];
            }
            if (x < x_src[i]) {
                double slope = (y_src[i] - y_src[i-1]) / (x_src[i] - x_src[i-1]);
                return y_src[i-1] + slope * (x - x_src[i-1]);
            }
        }
    } else if (x < x_src[0]) {  // 左外挿
        switch (fill_value) {
        case 0:  // zero
            return 0;
            break;
        
        case 1:  // same
            return y_src[0];
            break;

        case 2:  // extrapolate
            double slope = (y_src[1] - y_src[0]) / (x_src[1] - x_src[0]);
            return y_src[0] + slope * (x - x_src[0]);
            break;
        }
    } else if (x > x_src[x_src.size()-1]) {  // 右外挿
        switch (fill_value) {
        case 0:  // zero
            return 0;
            break;
        
        case 1:  // same
            return y_src[y_src.size()-1];
            break;

        case 2:  // extrapolate
            int index_end = y_src.size()-1;
            double slope = (y_src[index_end] - y_src[index_end-1]) / (x_src[index_end] - x_src[index_end-1]);
            return y_src[index_end] + slope * (x - x_src[index_end]);
            break;
        }
    }
}

// Assembly:
movsd (%rsi), %xmm0
movq (%rdx), %rax
movsd (%rax), %xmm1
ucomisd %xmm1, %xmm0
jb 0xf636
movq 0x8(%rdx), %rdx
movsd -0x8(%rdx), %xmm2
ucomisd %xmm0, %xmm2
jae 0xf6e8
ucomisd %xmm0, %xmm1
jbe 0xf67a
movl (%r8), %edx
testl %edx, %edx
je 0xf6e3
cmpl $0x2, %edx
jne 0xf723
movq (%rcx), %rcx
movsd (%rcx), %xmm2
movsd 0x8(%rcx), %xmm3
subsd %xmm2, %xmm3
movsd 0x8(%rax), %xmm4
subsd %xmm1, %xmm4
divsd %xmm4, %xmm3
subsd %xmm1, %xmm0
mulsd %xmm3, %xmm0
addsd %xmm2, %xmm0
retq
movl (%r8), %edx
testl %edx, %edx
je 0xf6e3
cmpl $0x2, %edx
jne 0xf72b
movq (%rcx), %rdx
movq 0x8(%rcx), %rcx
subq %rdx, %rcx
shlq $0x1d, %rcx
movabsq $-0x100000000, %rsi     # imm = 0xFFFFFFFF00000000
addq %rcx, %rsi
sarq $0x1d, %rsi
movsd (%rdx,%rsi), %xmm1
movabsq $-0x200000000, %rdi     # imm = 0xFFFFFFFE00000000
addq %rcx, %rdi
sarq $0x1d, %rdi
movapd %xmm1, %xmm2
subsd (%rdx,%rdi), %xmm2
movsd (%rax,%rsi), %xmm3
subsd %xmm3, %xmm0
subsd (%rax,%rdi), %xmm3
divsd %xmm3, %xmm2
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
retq
xorpd %xmm0, %xmm0
retq
movabsq $-0x100000000, %rdx     # imm = 0xFFFFFFFF00000000
xorl %esi, %esi
movabsq $0x100000000, %rdi      # imm = 0x100000000
ucomisd %xmm1, %xmm0
jne 0xf706
jnp 0xf71a
ucomisd %xmm0, %xmm1
ja 0xf735
movsd 0x8(%rax,%rsi,8), %xmm1
incq %rsi
addq %rdi, %rdx
jmp 0xf6fe
movq (%rcx), %rax
movsd (%rax,%rsi,8), %xmm0
retq
movq (%rcx), %rax
movsd (%rax), %xmm0
retq
movq 0x8(%rcx), %rax
movsd -0x8(%rax), %xmm0
retq
movq (%rcx), %rcx
movsd (%rcx,%rsi,8), %xmm2
sarq $0x1d, %rdx
movsd (%rcx,%rdx), %xmm3
subsd %xmm3, %xmm2
movsd (%rax,%rdx), %xmm4
subsd %xmm4, %xmm1
divsd %xmm1, %xmm2
subsd %xmm4, %xmm0
mulsd %xmm2, %xmm0
addsd %xmm3, %xmm0
retq