// File: adamiaonr[P]rid-analytics/src/prob.cpp
// Function: Prob::calc_out_fptree_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>>>>>*, std::vector<long double, std::allocator<long double>>*, std::vector<std::vector<long double, std::allocator<long double>>, std::allocator<std::vector<long double, std::allocator<long double>>>>&)
int Prob::calc_out_fptree_prob(
    uint8_t i,
    Prob::fp_data * iface_fp_data,
    std::map<int, std::vector<uint8_t> > * tree_bitmasks,
    std::vector<__float080> * in_fptree_prob,
    std::vector<std::vector<__float080> > & out_fptree_probs) {

    // 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);

    // init all probs to 0.0
    for (uint8_t t = 0; t <= this->n; t++)
        out_fptree_probs[i][t] = 0.0;

    // we add the influence of events 2.1 and 2.2
    //  - k = 0 : event 2.1
    //  - k = 1 : event 2.2
    std::vector<__float080> lt_ratios;

    for (int k = 0; k < 2; k++) {

        __float080 subevent_prob = 0.0;

        if (k == 0) {
        
            // 2.1) req. got into router w/ no assoc. w/ fp tree
            subevent_prob = (*in_fptree_prob)[0];
            // all entries count for fp prob calculation
            lt_ratios = std::vector<__float080>(n, 1.0);

        } else {

            // 2.2) req. assoc. fp tree, but not iface i
            subevent_prob = (1.0 - (*in_fptree_prob)[0]) * (this->fptree_prob[0][i][0]);
            // only account w/ % of entries coming from local trees
            lt_ratios = std::vector<__float080>(n, 1.0);
            // local_tree_ratios(iface_fp_data, tree_bitmasks, lt_ratios);
        }

        calc_log_prob_fp_neq(iface_fp_data, log_prob_fp_neq, lt_ratios);
        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];

        // P(T_{out,i} = 0)
        if (iface_fp_data->tp_size > 0) {

            // the req. can advance to the next router w/ t = 0 w/ prob P(|FP| = 0)
            // this can happen if:
            //  - iface i is not assoc. to fp tree
            //      - cases 2.1 or 2.2 above
            //  - P(FP = 0)
            out_fptree_probs[i][0] += 
                subevent_prob                   // i not associated w/ fp tree
                * exp(log_prob_fp_smeq[0]);     // not have a FP > 0 (i.e. having only FP = 0)

            // std::cout << "Prob::calc_out_fptree_prob() : P[" 
            //     << (int) i << "](T_out = 0) = " << exp(log_prob_fp_smeq[0]) << std::endl;

        } else {

            // there's no way of having a req. advance to the next router
            // without at least 1 fp match
            out_fptree_probs[i][0] = 0.0;
        }

        // P(T_{out,i} > 0)
        for (uint8_t t = 1; t <= this->n; t++) {

            out_fptree_probs[i][t] +=
                subevent_prob
                * exp(log_prob_fp_smeq[t])              // not have a FP > t
                * (1.0 - exp(log_prob_fp_neq[t - 1]));  // have a FP of size t
        }
    }

    // contribution of event 1
    for (uint8_t t = 1; t <= this->n; t++)
        out_fptree_probs[i][t] += (1.0 - (*in_fptree_prob)[0]) * this->fptree_prob[0][i][t];

    return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x2d0, %rsp            # imm = 0x2D0
movb %sil, %al
movq %rdi, -0x8(%rbp)
movb %al, -0x9(%rbp)
movq %rdx, -0x18(%rbp)
movq %rcx, -0x20(%rbp)
movq %r8, -0x28(%rbp)
movq %r9, -0x30(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x1c8(%rbp)
fldt 0x90(%rax)
flds 0x8700(%rip)            # 0x635fc
fucomi %st(1), %st
setbe %al
fldz
fld %st(0)
fcmovbe %st(2), %st
fstp %st(2)
fxch %st(2)
fsubp %st, %st(1)
fnstcw -0x19a(%rbp)
movzwl -0x19a(%rbp), %ecx
orl $0xc00, %ecx            # imm = 0xC00
movw %cx, -0x19c(%rbp)
fldcw -0x19c(%rbp)
fistpll -0x170(%rbp)
fldcw -0x19a(%rbp)
movzbl %al, %eax
movl %eax, %ecx
shlq $0x3f, %rcx
movq -0x170(%rbp), %rax
xorq %rcx, %rax
movq %rax, -0x1c0(%rbp)
fstpt -0x60(%rbp)
leaq -0x61(%rbp), %rdi
movq %rdi, -0x1b8(%rbp)
callq 0x34a40
movq -0x1c0(%rbp), %rsi
movq -0x1b8(%rbp), %rcx
leaq -0x48(%rbp), %rdi
leaq -0x60(%rbp), %rdx
callq 0x34a60
jmp 0x5af83
leaq -0x61(%rbp), %rdi
callq 0x34b70
movq -0x1c8(%rbp), %rax
fldt 0x90(%rax)
fld1
faddp %st, %st(1)
flds 0x8659(%rip)            # 0x635fc
fxch %st(1)
fucomi %st(1), %st
fldz
fld %st(0)
fcmovnb %st(3), %st
fstp %st(3)
fxch %st(1)
fsubp %st, %st(2)
setae %al
fnstcw -0x19e(%rbp)
movzwl -0x19e(%rbp), %ecx
orl $0xc00, %ecx            # imm = 0xC00
movw %cx, -0x1a0(%rbp)
fldcw -0x1a0(%rbp)
fxch %st(1)
fistpll -0x178(%rbp)
fldcw -0x19e(%rbp)
movzbl %al, %eax
movl %eax, %ecx
shlq $0x3f, %rcx
movq -0x178(%rbp), %rax
xorq %rcx, %rax
movq %rax, -0x1d8(%rbp)
fstpt -0xa0(%rbp)
leaq -0xa1(%rbp), %rdi
movq %rdi, -0x1d0(%rbp)
callq 0x34a40
movq -0x1d8(%rbp), %rsi
movq -0x1d0(%rbp), %rcx
leaq -0x90(%rbp), %rdi
leaq -0xa0(%rbp), %rdx
callq 0x34a60
jmp 0x5b03a
leaq -0xa1(%rbp), %rdi
callq 0x34b70
movb $0x0, -0xa2(%rbp)
movq -0x1c8(%rbp), %rax
movzbl -0xa2(%rbp), %ecx
movl %ecx, -0x17c(%rbp)
fildl -0x17c(%rbp)
fldt 0x90(%rax)
fucompi %st(1), %st
fstp %st(0)
jb 0x5b0e0
jmp 0x5b075
movq -0x30(%rbp), %rdi
movzbl -0x9(%rbp), %eax
movl %eax, %esi
callq 0x358a0
movq %rax, %rdi
movzbl -0xa2(%rbp), %eax
movl %eax, %esi
callq 0x34c70
fldz
fstpt (%rax)
movb -0xa2(%rbp), %al
addb $0x1, %al
movb %al, -0xa2(%rbp)
jmp 0x5b04d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
leaq -0x61(%rbp), %rdi
callq 0x34b70
jmp 0x5b790
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
leaq -0xa1(%rbp), %rdi
callq 0x34b70
jmp 0x5b787
leaq -0xc0(%rbp), %rdi
callq 0x38e40
movl $0x0, -0xc4(%rbp)
cmpl $0x2, -0xc4(%rbp)
jge 0x5b669
fldz
fstpt -0xe0(%rbp)
cmpl $0x0, -0xc4(%rbp)
jne 0x5b221
movq -0x28(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x34c70
movq %rax, %rcx
movq -0x1c8(%rbp), %rax
fldt (%rcx)
fstpt -0xe0(%rbp)
fldt 0x90(%rax)
flds 0x84b9(%rip)            # 0x635fc
fucomi %st(1), %st
setbe %al
fldz
fcmovbe %st(1), %st
fstp %st(1)
fsubrp %st, %st(1)
fnstcw -0x1a2(%rbp)
movzwl -0x1a2(%rbp), %ecx
orl $0xc00, %ecx            # imm = 0xC00
movw %cx, -0x1a4(%rbp)
fldcw -0x1a4(%rbp)
fistpll -0x190(%rbp)
fldcw -0x1a2(%rbp)
movzbl %al, %eax
movl %eax, %ecx
shlq $0x3f, %rcx
movq -0x190(%rbp), %rax
xorq %rcx, %rax
movq %rax, -0x1e8(%rbp)
fld1
fstpt -0x110(%rbp)
leaq -0x111(%rbp), %rdi
movq %rdi, -0x1e0(%rbp)
callq 0x34a40
movq -0x1e8(%rbp), %rsi
movq -0x1e0(%rbp), %rcx
leaq -0xf8(%rbp), %rdi
leaq -0x110(%rbp), %rdx
callq 0x34a60
jmp 0x5b1d4
leaq -0xc0(%rbp), %rdi
leaq -0xf8(%rbp), %rsi
callq 0x34ae0
leaq -0xf8(%rbp), %rdi
callq 0x34b10
leaq -0x111(%rbp), %rdi
callq 0x34b70
jmp 0x5b384
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
leaq -0x111(%rbp), %rdi
callq 0x34b70
jmp 0x5b76f
movq -0x28(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
movq %rsi, -0x218(%rbp)
callq 0x34c70
movq -0x218(%rbp), %rsi
movq -0x1c8(%rbp), %rdi
fldt (%rax)
fld1
fld %st(0)
fstpt -0x204(%rbp)
fsubp %st, %st(1)
fstpt -0x210(%rbp)
addq $0x60, %rdi
callq 0x5d910
movq %rax, %rdi
movzbl -0x9(%rbp), %eax
movl %eax, %esi
callq 0x358a0
movq -0x218(%rbp), %rsi
movq %rax, %rdi
callq 0x34c70
fldt -0x210(%rbp)
fldt -0x204(%rbp)
movq %rax, %rcx
movq -0x1c8(%rbp), %rax
fldt (%rcx)
fmulp %st, %st(2)
fxch %st(1)
fstpt -0xe0(%rbp)
fldt 0x90(%rax)
flds 0x8351(%rip)            # 0x635fc
fucomi %st(1), %st
setbe %al
fldz
fcmovbe %st(1), %st
fstp %st(1)
fsubrp %st, %st(1)
fnstcw -0x1a6(%rbp)
movzwl -0x1a6(%rbp), %ecx
orl $0xc00, %ecx            # imm = 0xC00
movw %cx, -0x1a8(%rbp)
fldcw -0x1a8(%rbp)
fistpll -0x188(%rbp)
fldcw -0x1a6(%rbp)
movzbl %al, %eax
movl %eax, %ecx
shlq $0x3f, %rcx
movq -0x188(%rbp), %rax
xorq %rcx, %rax
movq %rax, -0x1f8(%rbp)
fstpt -0x140(%rbp)
leaq -0x141(%rbp), %rdi
movq %rdi, -0x1f0(%rbp)
callq 0x34a40
movq -0x1f8(%rbp), %rsi
movq -0x1f0(%rbp), %rcx
leaq -0x130(%rbp), %rdi
leaq -0x140(%rbp), %rdx
callq 0x34a60
jmp 0x5b33a
leaq -0xc0(%rbp), %rdi
leaq -0x130(%rbp), %rsi
callq 0x34ae0
leaq -0x130(%rbp), %rdi
callq 0x34b10
leaq -0x141(%rbp), %rdi
callq 0x34b70
jmp 0x5b384
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
leaq -0x141(%rbp), %rdi
callq 0x34b70
jmp 0x5b76f
movq -0x18(%rbp), %rax
movq %rax, -0x220(%rbp)
leaq -0x160(%rbp), %rdi
leaq -0xc0(%rbp), %rsi
callq 0x36d30
jmp 0x5b3a4
movq -0x220(%rbp), %rsi
movq -0x1c8(%rbp), %rdi
leaq -0x48(%rbp), %rdx
leaq -0x160(%rbp), %rcx
callq 0x59b60
jmp 0x5b3c4
leaq -0x160(%rbp), %rdi
callq 0x34b10
movq -0x1c8(%rbp), %rax
fldt 0x90(%rax)
fld1
fchs
faddp %st, %st(1)
fnstcw -0x1aa(%rbp)
movzwl -0x1aa(%rbp), %eax
orl $0xc00, %eax            # imm = 0xC00
movw %ax, -0x1ac(%rbp)
fldcw -0x1ac(%rbp)
fistpl -0x194(%rbp)
fldcw -0x1aa(%rbp)
movl -0x194(%rbp), %eax
movl %eax, -0x164(%rbp)
cmpl $0x0, -0x164(%rbp)
jl 0x5b4c7
movl -0x164(%rbp), %eax
incl %eax
movslq %eax, %rsi
leaq -0x90(%rbp), %rdi
movq %rdi, -0x238(%rbp)
callq 0x34c70
fldt (%rax)
fstpt -0x244(%rbp)
movslq -0x164(%rbp), %rsi
leaq -0x48(%rbp), %rdi
callq 0x34c70
fldt -0x244(%rbp)
movq -0x238(%rbp), %rdi
fldt (%rax)
faddp %st, %st(1)
fstpt -0x22c(%rbp)
movslq -0x164(%rbp), %rsi
callq 0x34c70
fldt -0x22c(%rbp)
fstpt (%rax)
movl -0x164(%rbp), %eax
addl $-0x1, %eax
movl %eax, -0x164(%rbp)
jmp 0x5b41a
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
jmp 0x5b76f
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
leaq -0x160(%rbp), %rdi
callq 0x34b10
jmp 0x5b76f
movq -0x18(%rbp), %rax
movzbl (%rax), %eax
cmpl $0x0, %eax
jle 0x5b536
fldt -0xe0(%rbp)
fstpt -0x25c(%rbp)
xorl %eax, %eax
movl %eax, %esi
leaq -0x90(%rbp), %rdi
callq 0x34c70
fldt (%rax)
movq %rsp, %rax
fstpt (%rax)
callq 0x5d870
fstpt -0x250(%rbp)
jmp 0x5b503
movq -0x30(%rbp), %rdi
movzbl -0x9(%rbp), %eax
movl %eax, %esi
callq 0x358a0
movq %rax, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x34c70
fldt -0x250(%rbp)
fldt -0x25c(%rbp)
fldt (%rax)
fxch %st(1)
fmulp %st, %st(2)
faddp %st, %st(1)
fstpt (%rax)
jmp 0x5b555
movq -0x30(%rbp), %rdi
movzbl -0x9(%rbp), %eax
movl %eax, %esi
callq 0x358a0
movq %rax, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x34c70
fldz
fstpt (%rax)
movb $0x1, -0x165(%rbp)
movq -0x1c8(%rbp), %rax
movzbl -0x165(%rbp), %ecx
movl %ecx, -0x198(%rbp)
fildl -0x198(%rbp)
fldt 0x90(%rax)
fucompi %st(1), %st
fstp %st(0)
jb 0x5b653
jmp 0x5b588
fldt -0xe0(%rbp)
fstpt -0x274(%rbp)
movzbl -0x165(%rbp), %eax
movl %eax, %esi
leaq -0x90(%rbp), %rdi
callq 0x34c70
fldt (%rax)
movq %rsp, %rax
fstpt (%rax)
callq 0x5d870
fstpt -0x268(%rbp)
jmp 0x5b5bd
fldt -0x274(%rbp)
fldt -0x268(%rbp)
fmulp %st, %st(1)
fstpt -0x28c(%rbp)
movzbl -0x165(%rbp), %eax
movl %eax, %esi
decq %rsi
leaq -0x48(%rbp), %rdi
callq 0x34c70
fldt (%rax)
movq %rsp, %rax
fstpt (%rax)
callq 0x5d870
fstpt -0x280(%rbp)
jmp 0x5b5fa
fldt -0x280(%rbp)
fld1
fsubp %st, %st(1)
fstpt -0x298(%rbp)
movq -0x30(%rbp), %rdi
movzbl -0x9(%rbp), %eax
movl %eax, %esi
callq 0x358a0
movq %rax, %rdi
movzbl -0x165(%rbp), %eax
movl %eax, %esi
callq 0x34c70
fldt -0x298(%rbp)
fldt -0x28c(%rbp)
fldt (%rax)
fxch %st(1)
fmulp %st, %st(2)
faddp %st, %st(1)
fstpt (%rax)
movb -0x165(%rbp), %al
addb $0x1, %al
movb %al, -0x165(%rbp)
jmp 0x5b55c
jmp 0x5b655
movl -0xc4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xc4(%rbp)
jmp 0x5b0f6
movb $0x1, -0x166(%rbp)
movq -0x1c8(%rbp), %rax
movzbl -0x166(%rbp), %ecx
movl %ecx, -0x180(%rbp)
fildl -0x180(%rbp)
fldt 0x90(%rax)
fucompi %st(1), %st
fstp %st(0)
jb 0x5b743
jmp 0x5b69c
movq -0x28(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
movq %rsi, -0x2b8(%rbp)
callq 0x34c70
movq -0x1c8(%rbp), %rdi
movq -0x2b8(%rbp), %rsi
fldt (%rax)
fld1
fsubp %st, %st(1)
fstpt -0x2a4(%rbp)
addq $0x60, %rdi
callq 0x5d910
movq %rax, %rdi
movzbl -0x9(%rbp), %eax
movl %eax, %esi
callq 0x358a0
movq %rax, %rdi
movzbl -0x166(%rbp), %eax
movl %eax, %esi
callq 0x34c70
fldt (%rax)
fstpt -0x2b0(%rbp)
movq -0x30(%rbp), %rdi
movzbl -0x9(%rbp), %eax
movl %eax, %esi
callq 0x358a0
movq %rax, %rdi
movzbl -0x166(%rbp), %eax
movl %eax, %esi
callq 0x34c70
fldt -0x2b0(%rbp)
fldt -0x2a4(%rbp)
fldt (%rax)
fxch %st(1)
fmulp %st, %st(2)
faddp %st, %st(1)
fstpt (%rax)
movb -0x166(%rbp), %al
addb $0x1, %al
movb %al, -0x166(%rbp)
jmp 0x5b670
leaq -0xc0(%rbp), %rdi
callq 0x34b10
leaq -0x90(%rbp), %rdi
callq 0x34b10
leaq -0x48(%rbp), %rdi
callq 0x34b10
xorl %eax, %eax
addq $0x2d0, %rsp            # imm = 0x2D0
popq %rbp
retq
leaq -0xc0(%rbp), %rdi
callq 0x34b10
leaq -0x90(%rbp), %rdi
callq 0x34b10
leaq -0x48(%rbp), %rdi
callq 0x34b10
movq -0x70(%rbp), %rdi
callq 0x5920
nopl (%rax)