// File: /workspace/github_cpp_makefile_star2_O1/adamiaonr[P]rid-analytics/src/prob.cpp
// Function: Prob::calc_lm_prob(unsigned char, Prob::fp_data*, std::map<int, std::vector<unsigned char, std::allocator<unsigned char>>, std::less<int>, std::allocator<std::pair<int const, std::vector<unsigned char, std::allocator<unsigned char>>>>>*, bool)
int Prob::calc_lm_prob(
    uint8_t i, 
    Prob::fp_data * iface_fp_data,
    std::map<int, std::vector<uint8_t> > * tree_bitmasks,
    bool iface_complement) {

    // either 'i' or '~i (complement)' largest match probs
    std::vector<std::vector<std::vector<__float080> > > * lmp;
    if (!iface_complement) lmp = &(this->lm_cond_prob);
    else lmp = &(this->lm_complement_cond_prob);

    // aux. arrays used in fp rate calculation:
    //  - P(|FP| =/= f) = (1.0 - P(|FP| = f)) : prob of not having an fp match of size f
    std::vector<__float080> log_prob_fp_neq(n, 0.0);
    //  - P(|FP| <= f) : prob of fp match smaller than or equal to f
    std::vector<__float080> log_prob_fp_smeq(n + 1, 0.0);

    // if there are no entries for this iface, a match is impossible
    // as such, match size f = 0 has prob 1.0 of happening
    if (iface_fp_data->is_blocked) { 
        for (int t = (int) this->n; t >= 0; t--) (*lmp)[i][t][0] = 1.0;
        return 0; 
    }

    if (iface_fp_data->num_entries < 1.0) {
        for (int t = (int) this->n; t >= 0; t--) (*lmp)[i][t][0] = 1.0;
        return 0;
    }

    // calc the ratio of trees which can origin FP trees locally at the router
    // std::cout << "Prob::calc_lm_prob(iface) : [INFO] lt ratio iface  " << (iface_complement ? "~" : "") << (int) i << " :" << std::endl;
    // std::vector<__float080> lt_ratios(n, 0.0);
    // local_tree_ratios(iface_fp_data, tree_bitmasks, lt_ratios);
    std::vector<__float080> lt_ratios = std::vector<__float080>(n, 1.0);

    // std::cout << "Prob::calc_lm_prob(iface) : [INFO] iface " << (iface_complement ? "~" : "") << ((int) i) << " stats :"
    //     << "\n\t [n, m, k] : " << this->n << ", " << this->m << ", " << this->k << ")";
        // << "\n\t [# entries] : " << iface_fp_data->num_entries << " (" << (iface_fp_data->num_entries * lt_ratio) << ")";
    //     << "\t\n [lmp size] : " << (*lmp).size()
    //     << "\t\n [f_distr] : ";
    // for(uint8_t f = 0; f < this->n; f++) 
    //     std::cout << "[" << (int) f << "] = " << iface_fp_data->f_distr[f] << ", ";
    // std::cout << std::endl;

    // fill P(|FP| =/= f) = (1.0 - P(|FP| = f)), for all f
    calc_log_prob_fp_neq(iface_fp_data, log_prob_fp_neq, lt_ratios);
    // calc P(|FP| <= f), for all f
    for (int f = (int) (this->n - 1); f >= 0; f--)
        log_prob_fp_smeq[f] = log_prob_fp_smeq[f + 1] + log_prob_fp_neq[f];

    for (int t = (int) this->n; t >= 0; t--) {
        for (int f = (int) this->n; f >= 0; f--) {
            _calc_lm_prob(
                f, t, 
                iface_fp_data, 
                &log_prob_fp_neq, &log_prob_fp_smeq,
                &((*lmp)[i][t]));
        }
    }

    return 0;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x118, %rsp            # imm = 0x118
movq %rdi, %rbx
xorl %eax, %eax
testl %r8d, %r8d
movl $0x18, %r14d
cmoveq %rax, %r14
fldt 0x90(%rdi)
flds 0x715b(%rip)            # 0x31800
fld %st(0)
fstpt 0x60(%rsp)
xorl %eax, %eax
fucomi %st(1), %st
setbe %al
fldz
fld %st(0)
fld %st(1)
fstpt 0x50(%rsp)
fcmovbe %st(2), %st
fstp %st(2)
fxch %st(2)
fsubp %st, %st(1)
fnstcw 0x1c(%rsp)
movzwl 0x1c(%rsp), %ecx
orl $0xc00, %ecx            # imm = 0xC00
movw %cx, 0x2c(%rsp)
fldcw 0x2c(%rsp)
movq %rdx, %r12
movl %esi, %ebp
fistpll 0xe0(%rsp)
fldcw 0x1c(%rsp)
shlq $0x3f, %rax
xorq 0xe0(%rsp), %rax
fstpt 0x90(%rsp)
leaq 0xb0(%rsp), %rdi
leaq 0x90(%rsp), %rdx
leaq 0x70(%rsp), %rcx
movq %rax, %rsi
callq 0x1ddb8
movq %rbx, 0x30(%rsp)
fldt 0x90(%rbx)
fld1
faddp %st, %st(1)
xorl %esi, %esi
fldt 0x60(%rsp)
fxch %st(1)
fucomi %st(1), %st
fldt 0x50(%rsp)
fld %st(0)
fcmovnb %st(3), %st
fstp %st(3)
fxch %st(1)
fsubp %st, %st(2)
setae %sil
fnstcw 0x1a(%rsp)
movzwl 0x1a(%rsp), %eax
orl $0xc00, %eax            # imm = 0xC00
movw %ax, 0x2a(%rsp)
fldcw 0x2a(%rsp)
fxch %st(1)
fistpll 0xe8(%rsp)
fldcw 0x1a(%rsp)
shlq $0x3f, %rsi
xorq 0xe8(%rsp), %rsi
fstpt 0x70(%rsp)
leaq 0x90(%rsp), %rdi
leaq 0x70(%rsp), %rdx
leaq 0xf0(%rsp), %rcx
callq 0x1ddb8
cmpb $0x1, 0xb8(%r12)
jne 0x2a80e
movq 0x30(%rsp), %rdx
fldt 0x90(%rdx)
fnstcw 0x18(%rsp)
movzwl 0x18(%rsp), %eax
orl $0xc00, %eax            # imm = 0xC00
movw %ax, 0x28(%rsp)
fldcw 0x28(%rsp)
fistpl 0x3c(%rsp)
fldcw 0x18(%rsp)
movl 0x3c(%rsp), %eax
testl %eax, %eax
fldz
js 0x2aaba
fstp %st(0)
movzbl %bpl, %ecx
movq (%rdx,%r14), %rdx
leaq (%rcx,%rcx,2), %rsi
movl %eax, %eax
leaq (%rax,%rax,2), %rcx
incq %rax
shlq $0x3, %rcx
addq (%rdx,%rsi,8), %rcx
fld1
movq (%rcx), %rdx
fld %st(0)
fstpt (%rdx)
addq $-0x18, %rcx
decq %rax
jg 0x2a7f9
jmp 0x2aaba
fldt 0x10(%r12)
fld1
fucompi %st(1), %st
fstp %st(0)
movq 0x30(%rsp), %rdx
jbe 0x2a889
fldt 0x90(%rdx)
fnstcw 0x16(%rsp)
movzwl 0x16(%rsp), %eax
orl $0xc00, %eax            # imm = 0xC00
movw %ax, 0x26(%rsp)
fldcw 0x26(%rsp)
fistpl 0x40(%rsp)
fldcw 0x16(%rsp)
movl 0x40(%rsp), %eax
testl %eax, %eax
fldz
js 0x2aaba
fstp %st(0)
movzbl %bpl, %ecx
movq (%rdx,%r14), %rdx
leaq (%rcx,%rcx,2), %rsi
movl %eax, %eax
leaq (%rax,%rax,2), %rcx
incq %rax
shlq $0x3, %rcx
addq (%rdx,%rsi,8), %rcx
fld1
movq (%rcx), %rdx
fld %st(0)
fstpt (%rdx)
addq $-0x18, %rcx
decq %rax
jg 0x2a874
jmp 0x2aaba
fldt 0x90(%rdx)
flds 0x6f6b(%rip)            # 0x31800
xorl %esi, %esi
fucomi %st(1), %st
setbe %sil
fldz
fcmovbe %st(1), %st
fstp %st(1)
fsubrp %st, %st(1)
fnstcw 0x14(%rsp)
movzwl 0x14(%rsp), %eax
orl $0xc00, %eax            # imm = 0xC00
movw %ax, 0x24(%rsp)
fldcw 0x24(%rsp)
fistpll 0xd8(%rsp)
fldcw 0x14(%rsp)
shlq $0x3f, %rsi
xorq 0xd8(%rsp), %rsi
fld1
fstpt 0xf0(%rsp)
leaq 0x70(%rsp), %rdi
leaq 0xf0(%rsp), %rdx
leaq 0x2f(%rsp), %rcx
callq 0x1ddb8
leaq 0x100(%rsp), %rdi
leaq 0x70(%rsp), %rsi
callq 0x1e548
leaq 0xb0(%rsp), %rdx
leaq 0x100(%rsp), %r15
movq 0x30(%rsp), %rdi
movq %r12, %rsi
movq %r15, %rcx
callq 0x29e64
movq (%r15), %rdi
testq %rdi, %rdi
je 0x2a93d
movq 0x110(%rsp), %rsi
subq %rdi, %rsi
callq 0x43a0
movq %r12, 0xc8(%rsp)
movq %r14, 0xd0(%rsp)
movq 0x30(%rsp), %rax
fldt 0x90(%rax)
fld1
fchs
faddp %st, %st(1)
fnstcw 0x12(%rsp)
movzwl 0x12(%rsp), %eax
orl $0xc00, %eax            # imm = 0xC00
movw %ax, 0x22(%rsp)
fldcw 0x22(%rsp)
fistpl 0x4c(%rsp)
fldcw 0x12(%rsp)
movl 0x4c(%rsp), %edx
testl %edx, %edx
fldz
js 0x2a9bc
fstp %st(0)
movq 0x90(%rsp), %rax
movq 0xb0(%rsp), %rcx
movl %edx, %edx
movq %rdx, %rsi
shlq $0x4, %rsi
fldt 0x10(%rax,%rsi)
incq %rdx
fldt (%rcx,%rsi)
faddp %st, %st(1)
fld %st(0)
fstpt (%rax,%rsi)
addq $-0x10, %rsi
decq %rdx
jg 0x2a9a9
fstp %st(0)
movq 0x30(%rsp), %rsi
fldt 0x90(%rsi)
fnstcw 0x10(%rsp)
movzwl 0x10(%rsp), %eax
orl $0xc00, %eax            # imm = 0xC00
movw %ax, 0x20(%rsp)
fldcw 0x20(%rsp)
fistpl 0x48(%rsp)
fldcw 0x10(%rsp)
movl 0x48(%rsp), %eax
testl %eax, %eax
js 0x2aa9e
movzbl %bpl, %ecx
movl %eax, %r12d
leaq (%rcx,%rcx,2), %rcx
leaq 0xb0(%rsp), %rbx
leaq 0x90(%rsp), %r13
movq %rcx, 0x50(%rsp)
movq 0xd0(%rsp), %r14
movq 0xc8(%rsp), %r15
fldt 0x90(%rsi)
fnstcw 0xe(%rsp)
movzwl 0xe(%rsp), %eax
orl $0xc00, %eax            # imm = 0xC00
movw %ax, 0x1e(%rsp)
fldcw 0x1e(%rsp)
fistpl 0x44(%rsp)
fldcw 0xe(%rsp)
movl 0x44(%rsp), %ebp
testl %ebp, %ebp
js 0x2aa91
leaq (%r12,%r12,2), %rax
shlq $0x3, %rax
movq %rax, 0x60(%rsp)
movq (%rsi,%r14), %rax
movq (%rax,%rcx,8), %r9
addq 0x60(%rsp), %r9
movl %ebp, %edi
movl %r12d, %esi
movq %r15, %rdx
movq %rbx, %rcx
movq %r13, %r8
callq 0x2a261
movq 0x50(%rsp), %rcx
movq 0x30(%rsp), %rsi
leal -0x1(%rbp), %eax
testl %ebp, %ebp
movl %eax, %ebp
jg 0x2aa5e
leaq -0x1(%r12), %rax
testq %r12, %r12
movq %rax, %r12
jg 0x2aa24
movq 0x70(%rsp), %rdi
testq %rdi, %rdi
je 0x2aab8
movq 0x80(%rsp), %rsi
subq %rdi, %rsi
callq 0x43a0
fldz
fstp %st(0)
movq 0x90(%rsp), %rdi
testq %rdi, %rdi
je 0x2aad9
movq 0xa0(%rsp), %rsi
subq %rdi, %rsi
callq 0x43a0
movq 0xb0(%rsp), %rdi
testq %rdi, %rdi
je 0x2aaf6
movq 0xc0(%rsp), %rsi
subq %rdi, %rsi
callq 0x43a0
xorl %eax, %eax
addq $0x118, %rsp            # imm = 0x118
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %rax, %rbx
movq 0x70(%rsp), %rdi
testq %rdi, %rdi
je 0x2ab2c
movq 0x80(%rsp), %rsi
subq %rdi, %rsi
callq 0x43a0
jmp 0x2ab2c
movq %rax, %rbx
movq 0x90(%rsp), %rdi
testq %rdi, %rdi
je 0x2ab4e
movq 0xa0(%rsp), %rsi
subq %rdi, %rsi
callq 0x43a0
jmp 0x2ab4e
movq %rax, %rbx
movq 0xb0(%rsp), %rdi
testq %rdi, %rdi
je 0x2ab6b
movq 0xc0(%rsp), %rsi
subq %rdi, %rsi
callq 0x43a0
movq %rbx, %rdi
callq 0x4700
nop