// File: /workspace/github_cpp_makefile_star2_O1/ynilu[P]elastic/simulator.cpp
// Function: get_best_OFDM_WOB_light_path(int, int, Event&, Phy_graph&)
LightPath* get_best_OFDM_WOB_light_path(int source, int destination, Event& event, Phy_graph& p_graph)
{
    Phy_node& src_node = p_graph.get_node(source);

    Spectrum path_spectrum, best_path_spectrum;
    double current_weight;
    LightPath* best_existing_lightpath;

    best_path_spectrum.slot_st = -1;
    best_path_spectrum.slot_ed = -1;
    best_path_spectrum.weight = DBL_MAX;
    best_existing_lightpath = NULL;

    for(auto &lp : exist_OFDM_light_path_list)
    {
        int require_slots = ceil(1.0 * event.bandwidth / lp->modulation_level / slot_capacity);
        OFDMTransceiver& transmitter = src_node.OFDMtransmitter[lp->transmitter_index[0]];
        int num_used_slots = transmitter.spectrum.slot_ed - transmitter.spectrum.slot_st + 1;

        if(source != lp->p_path.front() || destination != lp->p_path.back())
        {
            continue;
        }

        if(transmitter.num_available_sub_transceiver < 1)
        {
            continue;
        }

        if(transceiver_slot_limit - num_used_slots < require_slots)
        {
            continue;
        }

        int slot_st;
        int slot_ed;

        // find the spectrum over the exisiting LightPath
        slot_st = lp->spectrum.slot_st - require_slots;
        slot_ed = lp->spectrum.slot_st - 1;
        if(slot_st >= 0 && slot_ed >= 0)
        {
            if(path_spectrum_available(lp->p_path, slot_st, slot_ed, p_graph) < 0) // spectrum available
            {
                current_weight = weigh_path_spectrum(lp->p_path, slot_st, slot_ed, p_graph);
                if(current_weight < best_path_spectrum.weight)
                {
                    best_path_spectrum.slot_st = slot_st;
                    // pre allocate the guardband slot for leaving adjacent traffic
                    best_path_spectrum.slot_ed = slot_ed + 2;
                    best_path_spectrum.weight = current_weight;
                    best_existing_lightpath = lp;
                }
            }
        }

        // find the spectrum under the exisiting LightPath
        slot_st = lp->spectrum.slot_ed + 1;
        slot_ed = lp->spectrum.slot_ed + require_slots;
        if(slot_st < transceiver_slot_limit && slot_ed < transceiver_slot_limit)
        {
            if(path_spectrum_available(lp->p_path, slot_st, slot_ed, p_graph) < 0) // spectrum available
            {
                current_weight = weigh_path_spectrum(lp->p_path, slot_st, slot_ed, p_graph);
                if(current_weight < best_path_spectrum.weight)
                {
                    best_path_spectrum.slot_st = slot_st - 2;
                    best_path_spectrum.slot_ed = slot_ed;
                    best_path_spectrum.weight = current_weight;
                    best_existing_lightpath = lp;
                }
            }
        }
    } // end of for(auto &lp : exist_OFDM_light_path_list)

    if(best_path_spectrum.slot_st < 0)
    {
        return NULL;
    }

    int require_slots = ceil(1.0 * event.bandwidth / best_existing_lightpath->modulation_level / slot_capacity);
    int available_bitrate = (require_slots - num_guardband_slot * 2) * best_existing_lightpath->modulation_level * slot_capacity - event.bandwidth;

    LightPath* path = new LightPath();

    path->type = LightPath::OFDM_WOB;
    path->modulation_level = best_existing_lightpath->modulation_level;
    path->available_bitrate = available_bitrate;
    path->p_path = best_existing_lightpath->p_path;
    path->transmitter_index = best_existing_lightpath->transmitter_index;
    path->receiver_index = best_existing_lightpath->receiver_index;
    path->weight = best_path_spectrum.weight;
    path->spectrum = best_path_spectrum;

    return path;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x58, %rsp
movq %rdx, 0x10(%rsp)
movl %esi, 0x30(%rsp)
movl %edi, %esi
movq %rcx, 0x8(%rsp)
movq %rcx, %rdi
movl %esi, 0x34(%rsp)
callq 0xb390
movq %rax, 0x38(%rsp)
leaq 0x40(%rsp), %rdi
callq 0x10504
leaq 0x18(%rsp), %rdi
callq 0x10504
movq $-0x1, 0x20(%rsp)
movabsq $0x7fefffffffffffff, %rax # imm = 0x7FEFFFFFFFFFFFFF
movq %rax, 0x28(%rsp)
movq 0x11412(%rip), %r14     # 0x18448
leaq 0x1140b(%rip), %rax     # 0x18448
cmpq %rax, %r14
je 0x71d7
movq $0x0, (%rsp)
movq 0x10(%rsp), %rax
xorps %xmm0, %xmm0
cvtsi2sdl 0x4c(%rax), %xmm0
movq 0x10(%r14), %r15
xorps %xmm1, %xmm1
cvtsi2sdl 0x40(%r15), %xmm1
divsd %xmm1, %xmm0
xorps %xmm1, %xmm1
cvtsi2sdl 0x11191(%rip), %xmm1 # 0x18208
divsd %xmm1, %xmm0
callq 0x3070
movq 0x68(%r15), %rax
movl 0x34(%rsp), %ecx
cmpl %ecx, (%rax)
jne 0x71c2
movq 0x70(%r15), %rax
movl 0x30(%rsp), %ecx
cmpl %ecx, -0x4(%rax)
jne 0x71c2
movq 0xc8(%r15), %rax
movslq (%rax), %rcx
movq 0x38(%rsp), %rax
movq 0x68(%rax), %rax
imulq $0x58, %rcx, %rcx
leaq (%rax,%rcx), %rdx
cmpl $0x0, 0xc(%rdx)
jle 0x71c2
cvttsd2si %xmm0, %ebx
movl 0x4c(%rax,%rcx), %edx
notl %edx
addl 0x48(%rax,%rcx), %edx
addl 0x11132(%rip), %edx     # 0x1820c
cmpl %ebx, %edx
jl 0x71c2
movl 0x58(%r15), %r12d
testl %r12d, %r12d
jle 0x7150
movl %r12d, %r13d
subl %ebx, %r13d
js 0x7150
addq $0x68, %r15
leal -0x1(%r12), %ebp
movq %r15, %rdi
movl %r13d, %esi
movl %ebp, %edx
movq 0x8(%rsp), %rcx
callq 0x7e4f
testl %eax, %eax
jns 0x7150
movq 0x10(%r14), %rdi
addq $0x68, %rdi
movl %r13d, %esi
movl %ebp, %edx
movq 0x8(%rsp), %rcx
callq 0x8242
movsd 0x28(%rsp), %xmm1
ucomisd %xmm0, %xmm1
jbe 0x7150
movl %r13d, 0x20(%rsp)
incl %r12d
movl %r12d, 0x24(%rsp)
movsd %xmm0, 0x28(%rsp)
movq 0x10(%r14), %rax
movq %rax, (%rsp)
movq 0x10(%r14), %rdi
movl 0x5c(%rdi), %r13d
leal 0x1(%r13), %r15d
movl 0x110aa(%rip), %eax     # 0x1820c
cmpl %eax, %r15d
jge 0x71c2
addl %r13d, %ebx
cmpl %eax, %ebx
jge 0x71c2
addq $0x68, %rdi
movl %r15d, %esi
movl %ebx, %edx
movq 0x8(%rsp), %rcx
callq 0x7e4f
testl %eax, %eax
jns 0x71c2
movq 0x10(%r14), %rdi
addq $0x68, %rdi
movl %r15d, %esi
movl %ebx, %edx
movq 0x8(%rsp), %rcx
callq 0x8242
movsd 0x28(%rsp), %xmm1
ucomisd %xmm0, %xmm1
jbe 0x71c2
decl %r13d
movl %r13d, 0x20(%rsp)
movl %ebx, 0x24(%rsp)
movsd %xmm0, 0x28(%rsp)
movq 0x10(%r14), %rax
movq %rax, (%rsp)
movq (%r14), %r14
leaq 0x1127c(%rip), %rax     # 0x18448
cmpq %rax, %r14
jne 0x704e
jmp 0x71df
movq $0x0, (%rsp)
cmpl $0x0, 0x20(%rsp)
js 0x72c2
movq 0x10(%rsp), %rax
movl 0x4c(%rax), %ebp
xorps %xmm0, %xmm0
cvtsi2sd %ebp, %xmm0
movq (%rsp), %rax
movl 0x40(%rax), %r15d
xorps %xmm1, %xmm1
cvtsi2sd %r15d, %xmm1
divsd %xmm1, %xmm0
movl 0x10ff4(%rip), %r14d    # 0x18208
xorps %xmm1, %xmm1
cvtsi2sd %r14d, %xmm1
divsd %xmm1, %xmm0
callq 0x3070
movsd %xmm0, 0x10(%rsp)
movl 0x10fe2(%rip), %r12d    # 0x18214
movl $0xf8, %edi
callq 0x3220
movq %rax, %rbx
movq %rax, %rdi
callq 0x1036c
cvttsd2si 0x10(%rsp), %eax
addl %r12d, %r12d
subl %r12d, %eax
imull %r15d, %r14d
imull %eax, %r14d
subl %ebp, %r14d
movl $0x3, 0x8(%rbx)
movq (%rsp), %r15
movl 0x40(%r15), %eax
movl %eax, 0x40(%rbx)
movl %r14d, 0x44(%rbx)
leaq 0x68(%r15), %rsi
leaq 0x68(%rbx), %rdi
callq 0x88f4
movl $0xc8, %edi
leaq (%r15,%rdi), %rsi
addq %rbx, %rdi
callq 0x88f4
movl $0xe0, %eax
addq %rax, %r15
movq %rbx, %rdi
addq %rax, %rdi
movq %r15, %rsi
callq 0x88f4
leaq 0x20(%rsp), %rax
movsd 0x8(%rax), %xmm0
movsd %xmm0, 0x48(%rbx)
movupd (%rax), %xmm0
movupd %xmm0, 0x58(%rbx)
jmp 0x72c4
xorl %ebx, %ebx
leaq 0x18(%rsp), %rdi
callq 0x10510
leaq 0x40(%rsp), %rdi
callq 0x10510
movq %rbx, %rax
addq $0x58, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %rax, %r14
movl $0xf8, %esi
movq %rbx, %rdi
callq 0x3230
jmp 0x7306
movq %rax, %r14
jmp 0x7310
jmp 0x7303
movq %rax, %r14
leaq 0x18(%rsp), %rdi
callq 0x10510
leaq 0x40(%rsp), %rdi
callq 0x10510
movq %r14, %rdi
callq 0x3370