// File: /workspace/github_cpp_makefile_star2_O2/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 $0x68, %rsp
movq %rdx, %rbp
movl %esi, 0x44(%rsp)
movl %edi, %r12d
movq %rcx, 0x8(%rsp)
movq %rcx, %rdi
movl %r12d, %esi
callq 0x98a8
movq %rax, 0x48(%rsp)
leaq 0x50(%rsp), %rdi
callq 0xe148
leaq 0x10(%rsp), %rdi
callq 0xe148
leaq 0x18(%rsp), %rcx
orq $-0x1, (%rcx)
movabsq $0x7fefffffffffffff, %rax # imm = 0x7FEFFFFFFFFFFFFF
movq %rax, 0x8(%rcx)
leaq 0x13179(%rip), %r14     # 0x18420
movq $0x0, 0x28(%rsp)
movq %rbp, 0x30(%rsp)
cvtsi2sdl 0x4c(%rbp), %xmm0
movsd %xmm0, (%rsp)
cvtsi2sdl 0x12f19(%rip), %xmm0 # 0x181e0
movsd %xmm0, 0x38(%rsp)
movq 0x48(%rsp), %rax
movq 0x68(%rax), %rbp
movl 0x12f07(%rip), %r15d    # 0x181e4
movq (%r14), %r14
leaq 0x13139(%rip), %rax     # 0x18420
cmpq %rax, %r14
je 0x545d
movq 0x10(%r14), %rbx
cvtsi2sdl 0x40(%rbx), %xmm1
movsd (%rsp), %xmm0
divsd %xmm1, %xmm0
divsd 0x38(%rsp), %xmm0
callq 0x2060
movq 0x68(%rbx), %rax
cmpl %r12d, (%rax)
jne 0x52dd
movq 0x70(%rbx), %rax
movl 0x44(%rsp), %ecx
cmpl %ecx, -0x4(%rax)
jne 0x52dd
movq 0xc8(%rbx), %rax
movslq (%rax), %rax
imulq $0x58, %rax, %rax
leaq (%rax,%rbp), %rcx
cmpl $0x0, 0xc(%rcx)
jle 0x52dd
cvttsd2si %xmm0, %r13d
movl 0x4c(%rbp,%rax), %ecx
notl %ecx
addl 0x48(%rbp,%rax), %ecx
addl %r15d, %ecx
cmpl %r13d, %ecx
jl 0x52dd
movl 0x58(%rbx), %r15d
testl %r15d, %r15d
jle 0x53d0
movl %r15d, %esi
subl %r13d, %esi
movq 0x30(%rsp), %rbp
js 0x53d5
addq $0x68, %rbx
leal -0x1(%r15), %edx
movq %rbx, %rdi
movl %esi, (%rsp)
movl %edx, 0x38(%rsp)
movq 0x8(%rsp), %rcx
callq 0x5fb5
movq 0x10(%r14), %rbx
testl %eax, %eax
jns 0x53d5
addq $0x68, %rbx
movq %rbx, %rdi
movl (%rsp), %esi
movl 0x38(%rsp), %edx
movq 0x8(%rsp), %rcx
callq 0x62ef
movsd 0x20(%rsp), %xmm1
ucomisd %xmm0, %xmm1
movq 0x10(%r14), %rbx
jbe 0x53d5
movl (%rsp), %eax
movl %eax, 0x18(%rsp)
incl %r15d
movl %r15d, 0x1c(%rsp)
movsd %xmm0, 0x20(%rsp)
movq %rbx, 0x28(%rsp)
jmp 0x53d5
movq 0x30(%rsp), %rbp
movl 0x5c(%rbx), %r15d
leal 0x1(%r15), %esi
movl 0x12e01(%rip), %eax     # 0x181e4
cmpl %eax, %esi
jge 0x52b5
addl %r15d, %r13d
cmpl %eax, %r13d
jge 0x52b5
addq $0x68, %rbx
movq %rbx, %rdi
movl %esi, %ebx
movl %r13d, %edx
movq 0x8(%rsp), %rcx
callq 0x5fb5
testl %eax, %eax
jns 0x52b5
movl %ebx, %esi
movq 0x10(%r14), %rdi
addq $0x68, %rdi
movl %r13d, %edx
movq 0x8(%rsp), %rcx
callq 0x62ef
movsd 0x20(%rsp), %xmm1
ucomisd %xmm0, %xmm1
jbe 0x52b5
decl %r15d
movl %r15d, 0x18(%rsp)
movl %r13d, 0x1c(%rsp)
movsd %xmm0, 0x20(%rsp)
movq 0x10(%r14), %rax
movq %rax, 0x28(%rsp)
jmp 0x52b5
cmpl $0x0, 0x18(%rsp)
js 0x5533
movq 0x30(%rsp), %rax
movl 0x4c(%rax), %ebp
cvtsi2sd %ebp, %xmm0
movq 0x28(%rsp), %r13
movl 0x40(%r13), %r15d
cvtsi2sd %r15d, %xmm1
divsd %xmm1, %xmm0
movl 0x12d53(%rip), %r14d    # 0x181e0
cvtsi2sd %r14d, %xmm1
divsd %xmm1, %xmm0
callq 0x2060
movsd %xmm0, (%rsp)
movl 0x12d45(%rip), %r12d    # 0x181ec
movl $0xf8, %edi
callq 0x21f0
movq %rax, %rbx
movq %rax, %rdi
callq 0xe020
cvttsd2si (%rsp), %eax
addl %r12d, %r12d
subl %r12d, %eax
imull %r15d, %r14d
imull %eax, %r14d
subl %ebp, %r14d
movl $0x3, 0x8(%rbx)
movl 0x40(%r13), %eax
movl %eax, 0x40(%rbx)
movl %r14d, 0x44(%rbx)
leaq 0x68(%r13), %rsi
leaq 0x68(%rbx), %rdi
callq 0x6876
movl $0xc8, %edi
leaq (%rdi,%r13), %rsi
addq %rbx, %rdi
callq 0x6876
movl $0xe0, %eax
addq %rax, %r13
movq %rbx, %rdi
addq %rax, %rdi
movq %r13, %rsi
callq 0x6876
movsd 0x20(%rsp), %xmm0
movsd %xmm0, 0x48(%rbx)
leaq 0x18(%rsp), %rax
movupd (%rax), %xmm0
movupd %xmm0, 0x58(%rbx)
jmp 0x5535
xorl %ebx, %ebx
leaq 0x10(%rsp), %rdi
callq 0xe154
leaq 0x50(%rsp), %rdi
callq 0xe154
movq %rbx, %rax
addq $0x68, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %rax, %r14
movl $0xf8, %esi
movq %rbx, %rdi
callq 0x2200
jmp 0x5577
jmp 0x5574
movq %rax, %r14
jmp 0x5581
movq %rax, %r14
leaq 0x10(%rsp), %rdi
callq 0xe154
leaq 0x50(%rsp), %rdi
callq 0xe154
movq %r14, %rdi
callq 0x2320