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

    LightPath* best_existing_lightpath = NULL;
    list<CandidatePath>& c_path_list = p_graph.get_path_list(source, destination);
    Spectrum best_path_spectrum;
    double current_weight;
    Path best_p_path;

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

    if(dst_node.num_available_OFDM_receiver < 1)
    {
        return NULL;
    }

    for(auto &c_path : c_path_list)
    {
        for(auto &lp : exist_OFDM_light_path_list)
        {
            int split_node_i;
            unsigned int num_hops = lp->p_path.size();

            OFDMTransceiver& transmitter = src_node.OFDMtransmitter[lp->transmitter_index[0]];

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

            if(c_path.path.size() < lp->p_path.size())
            {
                num_hops = c_path.path.size() - 1;
            }
            else
            {
                num_hops = lp->p_path.size() - 1;
            }

            split_node_i = num_hops;

            for(unsigned int node_i = 0; node_i <= num_hops; node_i++)
            {
                if(c_path.path[node_i] != lp->p_path[node_i])
                {
                    split_node_i = node_i - 1;
                    break;
                }
            }

            if(split_node_i < 1)
            {
                continue;
            }

            if(split_node_i == (int)lp->p_path.size()-1) // use OFDM WOB instead
            {
                continue;
            }


            Path trunk(lp->p_path.begin(), lp->p_path.begin() + split_node_i);
            Path branch(lp->p_path.begin() + split_node_i, lp->p_path.end());

            int trunk_require_slots = ceil(1.0 * event.bandwidth / lp->modulation_level / slot_capacity);

            Spectrum transmitter_sp = src_node.OFDMtransmitter[lp->transmitter_index.front()].spectrum;

            int num_used_slots = transmitter_sp.slot_ed - transmitter_sp.slot_st + 1;

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

            int t_slot_st;  // start slot for trunk
            int t_slot_ed;  // end slot for trunk

            int b_slot_st;  // start slot for branch
            int b_slot_ed;  // end slot for branch

            // spectrum over the exisiting LightPath
            t_slot_st = transmitter_sp.slot_st - trunk_require_slots;
            t_slot_ed = lp->spectrum.slot_st - 1;

            b_slot_st = t_slot_st;
            b_slot_ed = t_slot_ed + num_guardband_slot;

            if(t_slot_st >= 0)  // check for slot boundary
            {
                if(path_spectrum_available(trunk, t_slot_st, t_slot_ed, p_graph) < 0) // trunk spectrum available
                {
                    if(path_spectrum_available(branch, b_slot_st, b_slot_ed, p_graph) < 0) // branch spectrum available
                    {
                        current_weight = weigh_path_spectrum(lp->p_path, b_slot_st, b_slot_ed, p_graph);
                        if(current_weight < best_path_spectrum.weight)
                        {
                            best_p_path = c_path.path;
                            best_path_spectrum.slot_st = b_slot_st;
                            best_path_spectrum.slot_ed = b_slot_ed;
                            best_path_spectrum.weight = current_weight;
                            best_existing_lightpath = lp;
                        }
                    }
                }
            }

            // spectrum under the exisiting LightPath
            t_slot_st = lp->spectrum.slot_ed + 1;
            t_slot_ed = lp->spectrum.slot_ed + trunk_require_slots;

            b_slot_st = t_slot_st - num_guardband_slot;
            b_slot_ed = t_slot_ed;

            if(b_slot_ed < transceiver_slot_limit)  // check for slot boundary
            {
                if(path_spectrum_available(trunk, t_slot_st, t_slot_ed, p_graph) < 0) // trunk spectrum available
                {
                    if(path_spectrum_available(branch, b_slot_st, b_slot_ed, p_graph) < 0) // branch spectrum available
                    {
                        current_weight = weigh_path_spectrum(lp->p_path, b_slot_st, b_slot_ed, p_graph);
                        if(current_weight < best_path_spectrum.weight)
                        {
                            best_p_path = c_path.path;
                            best_path_spectrum.slot_st = b_slot_st;
                            best_path_spectrum.slot_ed = b_slot_ed;
                            best_path_spectrum.weight = current_weight;
                            best_existing_lightpath = lp;
                        }
                    }
                }
            }
        }
    }

    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_WB;
    path->p_path = best_p_path;
    path->modulation_level = best_existing_lightpath->modulation_level;
    path->available_bitrate = available_bitrate;
    path->weight = best_path_spectrum.weight;
    path->spectrum = best_path_spectrum;
    path->transmitter_index = best_existing_lightpath->transmitter_index;
    path->receiver_index = best_existing_lightpath->receiver_index;
    return path;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x1f0, %rsp            # imm = 0x1F0
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)
movq -0x20(%rbp), %rdi
movl -0x10(%rbp), %esi
callq 0x1b450
movq %rax, -0x30(%rbp)
movq $0x0, -0x38(%rbp)
movq -0x20(%rbp), %rdi
movl -0xc(%rbp), %esi
movl -0x10(%rbp), %edx
callq 0x1b670
movq %rax, -0x40(%rbp)
leaq -0x58(%rbp), %rdi
callq 0x2c120
leaq -0x78(%rbp), %rdi
callq 0xaed0
movl $0xffffffff, -0x50(%rbp) # imm = 0xFFFFFFFF
movl $0xffffffff, -0x4c(%rbp) # imm = 0xFFFFFFFF
movsd 0x25204(%rip), %xmm0    # 0x2d030
movsd %xmm0, -0x48(%rbp)
movq -0x30(%rbp), %rax
cmpl $0x1, 0x34(%rax)
jge 0x7e4f
movq $0x0, -0x8(%rbp)
movl $0x1, -0x7c(%rbp)
jmp 0x87c4
movq -0x40(%rbp), %rax
movq %rax, -0x88(%rbp)
movq -0x88(%rbp), %rdi
callq 0xc050
movq %rax, -0x90(%rbp)
movq -0x88(%rbp), %rdi
callq 0xc080
movq %rax, -0x98(%rbp)
leaq -0x90(%rbp), %rdi
leaq -0x98(%rbp), %rsi
callq 0xc0b0
testb $0x1, %al
jne 0x7e9c
jmp 0x8621
leaq -0x90(%rbp), %rdi
callq 0xc0e0
movq %rax, -0xa0(%rbp)
leaq 0x3b582(%rip), %rax     # 0x43438
movq %rax, -0xa8(%rbp)
leaq 0x3b574(%rip), %rdi     # 0x43438
callq 0xb680
movq %rax, -0xb0(%rbp)
leaq 0x3b561(%rip), %rdi     # 0x43438
callq 0xb6b0
movq %rax, -0xb8(%rbp)
leaq -0xb0(%rbp), %rdi
leaq -0xb8(%rbp), %rsi
callq 0xb6e0
testb $0x1, %al
jne 0x7eff
jmp 0x860e
leaq -0xb0(%rbp), %rdi
callq 0xb710
movq %rax, -0xc0(%rbp)
movq -0xc0(%rbp), %rax
movq (%rax), %rdi
addq $0x68, %rdi
callq 0xb380
movl %eax, -0xc8(%rbp)
movq -0x28(%rbp), %rax
addq $0x68, %rax
movq %rax, -0x1a0(%rbp)
movq -0xc0(%rbp), %rax
movq (%rax), %rdi
addq $0xc8, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0xb210
movq -0x1a0(%rbp), %rdi
movslq (%rax), %rsi
callq 0xb4f0
movq %rax, -0xd0(%rbp)
movq -0xd0(%rbp), %rax
cmpl $0x1, 0xc(%rax)
jge 0x7f7c
jmp 0x85ec
movq -0xa0(%rbp), %rdi
addq $0x8, %rdi
callq 0xb380
movq %rax, -0x1a8(%rbp)
movq -0xc0(%rbp), %rax
movq (%rax), %rdi
addq $0x68, %rdi
callq 0xb380
movq %rax, %rcx
movq -0x1a8(%rbp), %rax
cmpq %rcx, %rax
jae 0x7fd1
movq -0xa0(%rbp), %rdi
addq $0x8, %rdi
callq 0xb380
subq $0x1, %rax
movl %eax, -0xc8(%rbp)
jmp 0x7fee
movq -0xc0(%rbp), %rax
movq (%rax), %rdi
addq $0x68, %rdi
callq 0xb380
subq $0x1, %rax
movl %eax, -0xc8(%rbp)
movl -0xc8(%rbp), %eax
movl %eax, -0xc4(%rbp)
movl $0x0, -0xd4(%rbp)
movl -0xd4(%rbp), %eax
cmpl -0xc8(%rbp), %eax
ja 0x807e
movq -0xa0(%rbp), %rdi
addq $0x8, %rdi
movl -0xd4(%rbp), %eax
movl %eax, %esi
callq 0xb210
movl (%rax), %eax
movl %eax, -0x1ac(%rbp)
movq -0xc0(%rbp), %rax
movq (%rax), %rdi
addq $0x68, %rdi
movl -0xd4(%rbp), %eax
movl %eax, %esi
callq 0xb210
movq %rax, %rcx
movl -0x1ac(%rbp), %eax
cmpl (%rcx), %eax
je 0x806b
movl -0xd4(%rbp), %eax
subl $0x1, %eax
movl %eax, -0xc4(%rbp)
jmp 0x807e
jmp 0x806d
movl -0xd4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xd4(%rbp)
jmp 0x8004
cmpl $0x1, -0xc4(%rbp)
jge 0x808c
jmp 0x85ec
movl -0xc4(%rbp), %eax
movl %eax, -0x1b0(%rbp)
movq -0xc0(%rbp), %rax
movq (%rax), %rdi
addq $0x68, %rdi
callq 0xb380
movq %rax, %rcx
movl -0x1b0(%rbp), %eax
subl $0x1, %ecx
cmpl %ecx, %eax
jne 0x80c0
jmp 0x85ec
movq -0xc0(%rbp), %rax
movq (%rax), %rdi
addq $0x68, %rdi
callq 0xbf70
movq %rax, -0xf8(%rbp)
movq -0xc0(%rbp), %rax
movq (%rax), %rdi
addq $0x68, %rdi
callq 0xbf70
movq %rax, -0x108(%rbp)
movslq -0xc4(%rbp), %rsi
leaq -0x108(%rbp), %rdi
callq 0xc160
movq %rax, -0x100(%rbp)
leaq -0x109(%rbp), %rdi
movq %rdi, -0x1b8(%rbp)
callq 0xc1a0
movq -0x1b8(%rbp), %rcx
movq -0xf8(%rbp), %rsi
movq -0x100(%rbp), %rdx
leaq -0xf0(%rbp), %rdi
callq 0xc1c0
jmp 0x8144
leaq -0x109(%rbp), %rdi
callq 0xc240
movq -0xc0(%rbp), %rax
movq (%rax), %rdi
addq $0x68, %rdi
callq 0xbf70
movq %rax, -0x148(%rbp)
movslq -0xc4(%rbp), %rsi
leaq -0x148(%rbp), %rdi
callq 0xc160
movq %rax, -0x140(%rbp)
movq -0xc0(%rbp), %rax
movq (%rax), %rdi
addq $0x68, %rdi
callq 0xbfa0
movq %rax, -0x150(%rbp)
leaq -0x151(%rbp), %rdi
movq %rdi, -0x1c0(%rbp)
callq 0xc1a0
movq -0x1c0(%rbp), %rcx
movq -0x140(%rbp), %rsi
movq -0x150(%rbp), %rdx
leaq -0x138(%rbp), %rdi
callq 0xc1c0
jmp 0x81d4
leaq -0x151(%rbp), %rdi
callq 0xc240
movq -0x18(%rbp), %rax
cvtsi2sdl 0x4c(%rax), %xmm1
movsd 0x24e1f(%rip), %xmm0    # 0x2d010
mulsd %xmm1, %xmm0
movq -0xc0(%rbp), %rax
movq (%rax), %rax
cvtsi2sdl 0x40(%rax), %xmm1
divsd %xmm1, %xmm0
cvtsi2sdl 0x3afe8(%rip), %xmm1 # 0x431f8
divsd %xmm1, %xmm0
callq 0x3060
cvttsd2si %xmm0, %eax
movl %eax, -0x158(%rbp)
movq -0x28(%rbp), %rax
addq $0x68, %rax
movq %rax, -0x1c8(%rbp)
movq -0xc0(%rbp), %rax
movq (%rax), %rdi
addq $0xc8, %rdi
callq 0xb480
movq -0x1c8(%rbp), %rdi
movslq (%rax), %rsi
callq 0xb4f0
movq %rax, %rsi
addq $0x40, %rsi
leaq -0x170(%rbp), %rdi
callq 0xc260
movl -0x164(%rbp), %eax
subl -0x168(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x174(%rbp)
movl 0x3af77(%rip), %eax     # 0x431fc
subl -0x174(%rbp), %eax
cmpl -0x158(%rbp), %eax
jge 0x82e5
movl $0x5, -0x7c(%rbp)
jmp 0x85bb
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x118(%rbp)
movl %eax, -0x11c(%rbp)
leaq -0x109(%rbp), %rdi
callq 0xc240
jmp 0x87e3
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x118(%rbp)
movl %eax, -0x11c(%rbp)
leaq -0x151(%rbp), %rdi
callq 0xc240
jmp 0x85fd
movl -0x168(%rbp), %eax
subl -0x158(%rbp), %eax
movl %eax, -0x178(%rbp)
movq -0xc0(%rbp), %rax
movq (%rax), %rax
movl 0x58(%rax), %eax
subl $0x1, %eax
movl %eax, -0x17c(%rbp)
movl -0x178(%rbp), %eax
movl %eax, -0x180(%rbp)
movl -0x17c(%rbp), %eax
addl 0x3aedf(%rip), %eax     # 0x43204
movl %eax, -0x184(%rbp)
cmpl $0x0, -0x178(%rbp)
jl 0x845f
movl -0x178(%rbp), %esi
movl -0x17c(%rbp), %edx
movq -0x20(%rbp), %rcx
leaq -0xf0(%rbp), %rdi
callq 0xa5b0
movl %eax, -0x1cc(%rbp)
jmp 0x835c
movl -0x1cc(%rbp), %eax
cmpl $0x0, %eax
jge 0x845d
movl -0x180(%rbp), %esi
movl -0x184(%rbp), %edx
movq -0x20(%rbp), %rcx
leaq -0x138(%rbp), %rdi
callq 0xa5b0
movl %eax, -0x1d0(%rbp)
jmp 0x838f
movl -0x1d0(%rbp), %eax
cmpl $0x0, %eax
jge 0x845b
movq -0xc0(%rbp), %rax
movq (%rax), %rdi
addq $0x68, %rdi
movl -0x180(%rbp), %esi
movl -0x184(%rbp), %edx
movq -0x20(%rbp), %rcx
callq 0xaaf0
movsd %xmm0, -0x1d8(%rbp)
jmp 0x83cb
movsd -0x1d8(%rbp), %xmm0
movsd %xmm0, -0x60(%rbp)
movsd -0x60(%rbp), %xmm1
movsd -0x48(%rbp), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x8459
movq -0xa0(%rbp), %rsi
addq $0x8, %rsi
leaq -0x78(%rbp), %rdi
callq 0xbc80
jmp 0x83fe
movl -0x180(%rbp), %eax
movl %eax, -0x50(%rbp)
movl -0x184(%rbp), %eax
movl %eax, -0x4c(%rbp)
movsd -0x60(%rbp), %xmm0
movsd %xmm0, -0x48(%rbp)
movq -0xc0(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x38(%rbp)
jmp 0x8459
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x118(%rbp)
movl %eax, -0x11c(%rbp)
leaq -0x170(%rbp), %rdi
callq 0x2c140
leaq -0x138(%rbp), %rdi
callq 0xaef0
jmp 0x85fd
jmp 0x845b
jmp 0x845d
jmp 0x845f
movq -0xc0(%rbp), %rax
movq (%rax), %rax
movl 0x5c(%rax), %eax
addl $0x1, %eax
movl %eax, -0x178(%rbp)
movq -0xc0(%rbp), %rax
movq (%rax), %rax
movl 0x5c(%rax), %eax
addl -0x158(%rbp), %eax
movl %eax, -0x17c(%rbp)
movl -0x178(%rbp), %eax
subl 0x3ad6a(%rip), %eax     # 0x43204
movl %eax, -0x180(%rbp)
movl -0x17c(%rbp), %eax
movl %eax, -0x184(%rbp)
movl -0x184(%rbp), %eax
cmpl 0x3ad44(%rip), %eax     # 0x431fc
jge 0x85b4
movl -0x178(%rbp), %esi
movl -0x17c(%rbp), %edx
movq -0x20(%rbp), %rcx
leaq -0xf0(%rbp), %rdi
callq 0xa5b0
movl %eax, -0x1dc(%rbp)
jmp 0x84e2
movl -0x1dc(%rbp), %eax
cmpl $0x0, %eax
jge 0x85b2
movl -0x180(%rbp), %esi
movl -0x184(%rbp), %edx
movq -0x20(%rbp), %rcx
leaq -0x138(%rbp), %rdi
callq 0xa5b0
movl %eax, -0x1e0(%rbp)
jmp 0x8515
movl -0x1e0(%rbp), %eax
cmpl $0x0, %eax
jge 0x85b0
movq -0xc0(%rbp), %rax
movq (%rax), %rdi
addq $0x68, %rdi
movl -0x180(%rbp), %esi
movl -0x184(%rbp), %edx
movq -0x20(%rbp), %rcx
callq 0xaaf0
movsd %xmm0, -0x1e8(%rbp)
jmp 0x8551
movsd -0x1e8(%rbp), %xmm0
movsd %xmm0, -0x60(%rbp)
movsd -0x60(%rbp), %xmm1
movsd -0x48(%rbp), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x85ae
movq -0xa0(%rbp), %rsi
addq $0x8, %rsi
leaq -0x78(%rbp), %rdi
callq 0xbc80
jmp 0x8584
movl -0x180(%rbp), %eax
movl %eax, -0x50(%rbp)
movl -0x184(%rbp), %eax
movl %eax, -0x4c(%rbp)
movsd -0x60(%rbp), %xmm0
movsd %xmm0, -0x48(%rbp)
movq -0xc0(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x38(%rbp)
jmp 0x85b0
jmp 0x85b2
jmp 0x85b4
movl $0x0, -0x7c(%rbp)
leaq -0x170(%rbp), %rdi
callq 0x2c140
leaq -0x138(%rbp), %rdi
callq 0xaef0
leaq -0xf0(%rbp), %rdi
callq 0xaef0
movl -0x7c(%rbp), %eax
testl %eax, %eax
je 0x85ea
jmp 0x85e8
jmp 0x85ec
jmp 0x85ec
leaq -0xb0(%rbp), %rdi
callq 0xb900
jmp 0x7ee3
leaq -0xf0(%rbp), %rdi
callq 0xaef0
jmp 0x87e3
jmp 0x8610
leaq -0x90(%rbp), %rdi
callq 0xc110
jmp 0x7e80
cmpl $0x0, -0x50(%rbp)
jge 0x863b
movq $0x0, -0x8(%rbp)
movl $0x1, -0x7c(%rbp)
jmp 0x87c4
movq -0x18(%rbp), %rax
cvtsi2sdl 0x4c(%rax), %xmm0
movq -0x38(%rbp), %rax
cvtsi2sdl 0x40(%rax), %xmm1
divsd %xmm1, %xmm0
cvtsi2sdl 0x3ab9f(%rip), %xmm1 # 0x431f8
divsd %xmm1, %xmm0
callq 0x3060
cvttsd2si %xmm0, %eax
movl %eax, -0x188(%rbp)
movl -0x188(%rbp), %eax
movl 0x3ab8c(%rip), %ecx     # 0x43204
addl %ecx, %ecx
subl %ecx, %eax
movq -0x38(%rbp), %rcx
movl 0x40(%rcx), %ecx
imull %ecx, %eax
movl 0x3ab6c(%rip), %ecx     # 0x431f8
imull %ecx, %eax
movq -0x18(%rbp), %rcx
movl 0x4c(%rcx), %ecx
subl %ecx, %eax
movl %eax, -0x18c(%rbp)
movl $0xf8, %edi
callq 0x3200
movq %rax, -0x1f0(%rbp)
jmp 0x86b1
movq -0x1f0(%rbp), %rdi
callq 0x2be50
jmp 0x86bf
movq -0x1f0(%rbp), %rax
movq %rax, -0x198(%rbp)
movq -0x198(%rbp), %rax
movl $0x2, 0x8(%rax)
movq -0x198(%rbp), %rdi
addq $0x68, %rdi
leaq -0x78(%rbp), %rsi
callq 0xbc80
jmp 0x86f1
movq -0x38(%rbp), %rax
movl 0x40(%rax), %ecx
movq -0x198(%rbp), %rax
movl %ecx, 0x40(%rax)
movl -0x18c(%rbp), %ecx
movq -0x198(%rbp), %rax
movl %ecx, 0x44(%rax)
movsd -0x48(%rbp), %xmm0
movq -0x198(%rbp), %rax
movsd %xmm0, 0x48(%rax)
movq -0x198(%rbp), %rdi
addq $0x50, %rdi
leaq -0x58(%rbp), %rsi
callq 0xbc50
movq -0x38(%rbp), %rsi
addq $0xc8, %rsi
movq -0x198(%rbp), %rdi
addq $0xc8, %rdi
callq 0xbc80
jmp 0x8757
movq -0x38(%rbp), %rsi
addq $0xe0, %rsi
movq -0x198(%rbp), %rdi
addq $0xe0, %rdi
callq 0xbc80
jmp 0x8777
movq -0x198(%rbp), %rax
movq %rax, -0x8(%rbp)
movl $0x1, -0x7c(%rbp)
jmp 0x87c4
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x118(%rbp)
movl %eax, -0x11c(%rbp)
jmp 0x87e3
movq -0x1f0(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x118(%rbp)
movl %eax, -0x11c(%rbp)
movl $0xf8, %esi
callq 0x3210
jmp 0x87e3
leaq -0x78(%rbp), %rdi
callq 0xaef0
leaq -0x58(%rbp), %rdi
callq 0x2c140
movq -0x8(%rbp), %rax
addq $0x1f0, %rsp            # imm = 0x1F0
popq %rbp
retq
leaq -0x78(%rbp), %rdi
callq 0xaef0
leaq -0x58(%rbp), %rdi
callq 0x2c140
movq -0x118(%rbp), %rdi
callq 0x3340
nopw %cs:(%rax,%rax)