// File: 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
movq %rsp, %rbp
subq $0x100, %rsp            # imm = 0x100
movl %edi, -0xc(%rbp)
movl %esi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq %rcx, -0x20(%rbp)
movq -0x20(%rbp), %rdi
movl -0xc(%rbp), %esi
callq 0x1b450
movq %rax, -0x28(%rbp)
leaq -0x40(%rbp), %rdi
callq 0x2c120
leaq -0x58(%rbp), %rdi
callq 0x2c120
jmp 0x884d
movl $0xffffffff, -0x50(%rbp) # imm = 0xFFFFFFFF
movl $0xffffffff, -0x4c(%rbp) # imm = 0xFFFFFFFF
movsd 0x247cd(%rip), %xmm0    # 0x2d030
movsd %xmm0, -0x48(%rbp)
movq $0x0, -0x78(%rbp)
leaq 0x3abc1(%rip), %rax     # 0x43438
movq %rax, -0x80(%rbp)
leaq 0x3abb6(%rip), %rdi     # 0x43438
callq 0xb680
movq %rax, -0x88(%rbp)
leaq 0x3aba3(%rip), %rdi     # 0x43438
callq 0xb6b0
movq %rax, -0x90(%rbp)
leaq -0x88(%rbp), %rdi
leaq -0x90(%rbp), %rsi
callq 0xb6e0
testb $0x1, %al
jne 0x88bd
jmp 0x8c2a
leaq -0x88(%rbp), %rdi
callq 0xb710
movq %rax, -0x98(%rbp)
movq -0x18(%rbp), %rax
cvtsi2sdl 0x4c(%rax), %xmm1
movsd 0x2472f(%rip), %xmm0    # 0x2d010
mulsd %xmm1, %xmm0
movq -0x98(%rbp), %rax
movq (%rax), %rax
cvtsi2sdl 0x40(%rax), %xmm1
divsd %xmm1, %xmm0
cvtsi2sdl 0x3a8f8(%rip), %xmm1 # 0x431f8
divsd %xmm1, %xmm0
callq 0x3060
cvttsd2si %xmm0, %eax
movl %eax, -0x9c(%rbp)
movq -0x28(%rbp), %rax
addq $0x68, %rax
movq %rax, -0xd8(%rbp)
movq -0x98(%rbp), %rax
movq (%rax), %rdi
addq $0xc8, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0xb210
movq -0xd8(%rbp), %rdi
movslq (%rax), %rsi
callq 0xb4f0
movq %rax, -0xa8(%rbp)
movq -0xa8(%rbp), %rax
movl 0x4c(%rax), %eax
movq -0xa8(%rbp), %rcx
subl 0x48(%rcx), %eax
addl $0x1, %eax
movl %eax, -0xac(%rbp)
movl -0xc(%rbp), %eax
movl %eax, -0xcc(%rbp)
movq -0x98(%rbp), %rax
movq (%rax), %rdi
addq $0x68, %rdi
callq 0xb480
movq %rax, %rcx
movl -0xcc(%rbp), %eax
cmpl (%rcx), %eax
jne 0x89c1
movl -0x10(%rbp), %eax
movl %eax, -0xdc(%rbp)
movq -0x98(%rbp), %rax
movq (%rax), %rdi
addq $0x68, %rdi
callq 0xb4b0
movq %rax, %rcx
movl -0xdc(%rbp), %eax
cmpl (%rcx), %eax
je 0x89d7
jmp 0x8c19
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
jmp 0x8de5
movq -0xa8(%rbp), %rax
cmpl $0x1, 0xc(%rax)
jge 0x89e9
jmp 0x8c19
movl 0x3a80d(%rip), %eax     # 0x431fc
subl -0xac(%rbp), %eax
cmpl -0x9c(%rbp), %eax
jge 0x8a02
jmp 0x8c19
movq -0x98(%rbp), %rax
movq (%rax), %rax
movl 0x58(%rax), %eax
subl -0x9c(%rbp), %eax
movl %eax, -0xb0(%rbp)
movq -0x98(%rbp), %rax
movq (%rax), %rax
movl 0x58(%rax), %eax
subl $0x1, %eax
movl %eax, -0xb4(%rbp)
cmpl $0x0, -0xb0(%rbp)
jl 0x8b13
cmpl $0x0, -0xb4(%rbp)
jl 0x8b13
movq -0x98(%rbp), %rax
movq (%rax), %rdi
addq $0x68, %rdi
movl -0xb0(%rbp), %esi
movl -0xb4(%rbp), %edx
movq -0x20(%rbp), %rcx
callq 0xa5b0
movl %eax, -0xe0(%rbp)
jmp 0x8a76
movl -0xe0(%rbp), %eax
cmpl $0x0, %eax
jge 0x8b11
movq -0x98(%rbp), %rax
movq (%rax), %rdi
addq $0x68, %rdi
movl -0xb0(%rbp), %esi
movl -0xb4(%rbp), %edx
movq -0x20(%rbp), %rcx
callq 0xaaf0
movsd %xmm0, -0xe8(%rbp)
jmp 0x8ab2
movsd -0xe8(%rbp), %xmm0
movsd %xmm0, -0x70(%rbp)
movsd -0x70(%rbp), %xmm1
movsd -0x48(%rbp), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x8b0f
movl -0xb0(%rbp), %eax
movl %eax, -0x50(%rbp)
movl -0xb4(%rbp), %eax
addl $0x2, %eax
movl %eax, -0x4c(%rbp)
movsd -0x70(%rbp), %xmm0
movsd %xmm0, -0x48(%rbp)
movq -0x98(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x78(%rbp)
jmp 0x8b0f
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
jmp 0x8ddc
jmp 0x8b11
jmp 0x8b13
movq -0x98(%rbp), %rax
movq (%rax), %rax
movl 0x5c(%rax), %eax
addl $0x1, %eax
movl %eax, -0xb0(%rbp)
movq -0x98(%rbp), %rax
movq (%rax), %rax
movl 0x5c(%rax), %eax
addl -0x9c(%rbp), %eax
movl %eax, -0xb4(%rbp)
movl -0xb0(%rbp), %eax
cmpl 0x3a6ae(%rip), %eax     # 0x431fc
jge 0x8c17
movl -0xb4(%rbp), %eax
cmpl 0x3a69c(%rip), %eax     # 0x431fc
jge 0x8c17
movq -0x98(%rbp), %rax
movq (%rax), %rdi
addq $0x68, %rdi
movl -0xb0(%rbp), %esi
movl -0xb4(%rbp), %edx
movq -0x20(%rbp), %rcx
callq 0xa5b0
movl %eax, -0xec(%rbp)
jmp 0x8b91
movl -0xec(%rbp), %eax
cmpl $0x0, %eax
jge 0x8c15
movq -0x98(%rbp), %rax
movq (%rax), %rdi
addq $0x68, %rdi
movl -0xb0(%rbp), %esi
movl -0xb4(%rbp), %edx
movq -0x20(%rbp), %rcx
callq 0xaaf0
movsd %xmm0, -0xf8(%rbp)
jmp 0x8bc9
movsd -0xf8(%rbp), %xmm0
movsd %xmm0, -0x70(%rbp)
movsd -0x70(%rbp), %xmm1
movsd -0x48(%rbp), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x8c13
movl -0xb0(%rbp), %eax
subl $0x2, %eax
movl %eax, -0x50(%rbp)
movl -0xb4(%rbp), %eax
movl %eax, -0x4c(%rbp)
movsd -0x70(%rbp), %xmm0
movsd %xmm0, -0x48(%rbp)
movq -0x98(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x78(%rbp)
jmp 0x8c15
jmp 0x8c17
jmp 0x8c19
leaq -0x88(%rbp), %rdi
callq 0xb900
jmp 0x88a1
cmpl $0x0, -0x50(%rbp)
jge 0x8c47
movq $0x0, -0x8(%rbp)
movl $0x1, -0xb8(%rbp)
jmp 0x8dbd
movq -0x18(%rbp), %rax
cvtsi2sdl 0x4c(%rax), %xmm0
movq -0x78(%rbp), %rax
cvtsi2sdl 0x40(%rax), %xmm1
divsd %xmm1, %xmm0
cvtsi2sdl 0x3a593(%rip), %xmm1 # 0x431f8
divsd %xmm1, %xmm0
callq 0x3060
cvttsd2si %xmm0, %eax
movl %eax, -0xbc(%rbp)
movl -0xbc(%rbp), %eax
movl 0x3a580(%rip), %ecx     # 0x43204
addl %ecx, %ecx
subl %ecx, %eax
movq -0x78(%rbp), %rcx
movl 0x40(%rcx), %ecx
imull %ecx, %eax
movl 0x3a560(%rip), %ecx     # 0x431f8
imull %ecx, %eax
movq -0x18(%rbp), %rcx
movl 0x4c(%rcx), %ecx
subl %ecx, %eax
movl %eax, -0xc0(%rbp)
movl $0xf8, %edi
callq 0x3200
movq %rax, -0x100(%rbp)
jmp 0x8cbd
movq -0x100(%rbp), %rdi
callq 0x2be50
jmp 0x8ccb
movq -0x100(%rbp), %rax
movq %rax, -0xc8(%rbp)
movq -0xc8(%rbp), %rax
movl $0x3, 0x8(%rax)
movq -0x78(%rbp), %rax
movl 0x40(%rax), %ecx
movq -0xc8(%rbp), %rax
movl %ecx, 0x40(%rax)
movl -0xc0(%rbp), %ecx
movq -0xc8(%rbp), %rax
movl %ecx, 0x44(%rax)
movq -0x78(%rbp), %rsi
addq $0x68, %rsi
movq -0xc8(%rbp), %rdi
addq $0x68, %rdi
callq 0xbc80
jmp 0x8d22
movq -0x78(%rbp), %rsi
addq $0xc8, %rsi
movq -0xc8(%rbp), %rdi
addq $0xc8, %rdi
callq 0xbc80
jmp 0x8d42
movq -0x78(%rbp), %rsi
addq $0xe0, %rsi
movq -0xc8(%rbp), %rdi
addq $0xe0, %rdi
callq 0xbc80
jmp 0x8d62
movsd -0x48(%rbp), %xmm0
movq -0xc8(%rbp), %rax
movsd %xmm0, 0x48(%rax)
movq -0xc8(%rbp), %rdi
addq $0x50, %rdi
leaq -0x58(%rbp), %rsi
callq 0xbc50
movq -0xc8(%rbp), %rax
movq %rax, -0x8(%rbp)
movl $0x1, -0xb8(%rbp)
jmp 0x8dbd
movq -0x100(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
movl $0xf8, %esi
callq 0x3210
jmp 0x8ddc
leaq -0x58(%rbp), %rdi
callq 0x2c140
leaq -0x40(%rbp), %rdi
callq 0x2c140
movq -0x8(%rbp), %rax
addq $0x100, %rsp            # imm = 0x100
popq %rbp
retq
leaq -0x58(%rbp), %rdi
callq 0x2c140
leaq -0x40(%rbp), %rdi
callq 0x2c140
movq -0x60(%rbp), %rdi
callq 0x3340
nopw (%rax,%rax)