// File: UCBASiCS[P]SPRIGHT/src/binprocessor.cpp
// Function: BinProcessor::computeThresholds()
void BinProcessor::computeThresholds()
{
    // for computing the histogram for zeroton-singleton-multiton test
    std::vector<double> energyBins;
    double noiseEstimation = 0;
    double tempEnergy = 0;
    int    energyHistogramBinsCounted = 0;

    if ( config->isNoisy() )
    {
        // go over the stages

        for (int stage = 0; stage < config->getBinsNb(); ++stage)
        {
            // go over the bins in the stage
            for (int i = 0; i < config->getBinNumItems(stage); ++i)
            {
                // this is the energy of a bin measurement
                tempEnergy = 0;
                // go over the delays (go over bin measurements)
                for (int j = 0; j < config->getDelaysNb(); j++)
                {
                    // std::norm calculates norm-squared
                    tempEnergy += std::norm(observationMatrix[config->getBinOffset(stage)+i][j]);
                }
                energyBins.push_back(tempEnergy);
            }
        }

        // make histogram below
        // sort the energy bins
        std::sort (energyBins.begin(), energyBins.end());

        bool noiseLevelCrossed = false;
        while (!noiseLevelCrossed)
        {
            noiseEstimation += energyBins[energyHistogramBinsCounted];
            energyHistogramBinsCounted++;

            // if the bin energy is 10 times the previous one, declare it has signal in it
            if ( energyBins[energyHistogramBinsCounted] / energyBins[energyHistogramBinsCounted-1] >= 10 )
            {
                noiseLevelCrossed = true;
            }
        }



        // CHOICE 1: this corresponds to the average energy of the zero-ton bins
        noiseEstimation /= energyHistogramBinsCounted;

        // CHOICE 2: this corresponds to the maximum energy of the zero-ton bins
        // noiseEstimation = energyBins[energyHistogramBinsCounted-1];

    }

    // Minimum energy for the signal to be accepted as non-zero
    // 10 percent of the minimum SNR

    if( !config->isNoisy() ) // noiseless ongrid
    {
        minimumEnergy = pow(10,-8);
    }
    else if ( config->isNoisy() ) // noisy ongrid
    {
        /*
            We want a threshold on the minimum signal energy to eliminate false
            detections. A simple one would be of the sort:
            minimumEnergy = 0.1 * noiseEstimation * pow(10,config->getSNRdB()/10);
            However, for large signal to noise ratio, this is not working since there
            is always a noise floor around 1e-18 due to numerical issues, hence when
            multiplied with high SNR it blows up. Hence, for small SNR we do that, but
            for large SNR we clip it.
            We chose it to clip to 1000 times the noise floor.
        */
        minimumEnergy = std::min( 0.1 * noiseEstimation * pow(10,config->getSNRdB()/10) , 1000 * noiseEstimation );

    }

    /*
        Base threshold for the remaining bin signal to be considered as
        zero-ton after the signal is peeled from it. This value, in theory, is zero
        for noiseless simulations. However, due to machine precision, it needs to be positive
        value. For noiseless simulations we chose it to be 1e-13. If this value is high,
        we start to get false detections. One can decrease the thrsholds or increase the
        number of delays to reduce the false detections.
    */
    ffast_real baseThreshold = pow(10, -13);

    ffast_real factor;

    // Thresholds are obtained using tailbounds of Gaussian random variable
    if (delaysNb < 10)
    {
        factor = 4;
    }
    else if (delaysNb < 20)
    {
        factor = 3;
    }
    else if (delaysNb < 50)
    {
        factor = 2;
    }
    else
    {
        factor = 1.5;
    }

    for (int stage=0; stage<config->getBinsNb(); stage++)
    {
        thresholds[stage] = baseThreshold;

        if (config->isNoisy() )
            thresholds[stage] = pow(10,-10) + (ffast_real) factor * noiseEstimation;
    }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x130, %rsp            # imm = 0x130
movq %rdi, -0x8(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x98(%rbp)
leaq -0x20(%rbp), %rdi
callq 0x5940
movq -0x98(%rbp), %rax
movq $0x0, -0x28(%rbp)
movq $0x0, -0x30(%rbp)
movl $0x0, -0x34(%rbp)
movq 0x10(%rax), %rdi
callq 0xeb90
movb %al, -0x8d(%rbp)
jmp 0x9322
movb -0x8d(%rbp), %al
testb $0x1, %al
jne 0x9331
jmp 0x9576
movl $0x0, -0x48(%rbp)
movq -0x98(%rbp), %rax
movl -0x48(%rbp), %ecx
movl %ecx, -0xa0(%rbp)
movq 0x10(%rax), %rdi
callq 0xeb10
movl %eax, -0x9c(%rbp)
jmp 0x9359
movl -0xa0(%rbp), %eax
movl -0x9c(%rbp), %ecx
cmpl %ecx, %eax
jge 0x94b2
movl $0x0, -0x4c(%rbp)
movq -0x98(%rbp), %rax
movl -0x4c(%rbp), %ecx
movl %ecx, -0xa8(%rbp)
movq 0x10(%rax), %rdi
movl -0x48(%rbp), %esi
callq 0xea50
movl %eax, -0xa4(%rbp)
jmp 0x9398
movl -0xa8(%rbp), %eax
movl -0xa4(%rbp), %ecx
cmpl %ecx, %eax
jge 0x94a2
xorps %xmm0, %xmm0
movsd %xmm0, -0x30(%rbp)
movl $0x0, -0x50(%rbp)
movq -0x98(%rbp), %rax
movl -0x50(%rbp), %ecx
movl %ecx, -0xb0(%rbp)
movq 0x10(%rax), %rdi
callq 0xeb30
movl %eax, -0xac(%rbp)
jmp 0x93dc
movl -0xb0(%rbp), %eax
movl -0xac(%rbp), %ecx
cmpl %ecx, %eax
jge 0x9483
movq -0x98(%rbp), %rax
movq 0x10(%rax), %rdi
movq 0x18(%rax), %rax
movq %rax, -0xc0(%rbp)
movl -0x48(%rbp), %esi
callq 0xeac0
movl %eax, -0xb4(%rbp)
jmp 0x9416
movq -0xc0(%rbp), %rax
movl -0xb4(%rbp), %ecx
movl -0x4c(%rbp), %edx
addl %edx, %ecx
movslq %ecx, %rcx
movq (%rax,%rcx,8), %rdi
movslq -0x50(%rbp), %rax
shlq $0x4, %rax
addq %rax, %rdi
callq 0xa180
movsd %xmm0, -0xc8(%rbp)
jmp 0x9449
movsd -0xc8(%rbp), %xmm0
addsd -0x30(%rbp), %xmm0
movsd %xmm0, -0x30(%rbp)
movl -0x50(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x50(%rbp)
jmp 0x93bb
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
leaq -0x20(%rbp), %rdi
callq 0x59a0
jmp 0x9833
leaq -0x20(%rbp), %rdi
leaq -0x30(%rbp), %rsi
callq 0xa480
jmp 0x9492
jmp 0x9494
movl -0x4c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x4c(%rbp)
jmp 0x9374
jmp 0x94a4
movl -0x48(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x48(%rbp)
jmp 0x9338
leaq -0x20(%rbp), %rdi
movq %rdi, -0xd0(%rbp)
callq 0x87d0
movq -0xd0(%rbp), %rdi
movq %rax, -0x58(%rbp)
callq 0x8610
movq %rax, -0x60(%rbp)
movq -0x58(%rbp), %rdi
movq -0x60(%rbp), %rsi
callq 0xa4f0
jmp 0x94e5
movb $0x0, -0x61(%rbp)
movb -0x61(%rbp), %al
xorb $-0x1, %al
testb $0x1, %al
jne 0x94f4
jmp 0x9563
movslq -0x34(%rbp), %rsi
leaq -0x20(%rbp), %rdi
callq 0xa530
movsd (%rax), %xmm0
addsd -0x28(%rbp), %xmm0
movsd %xmm0, -0x28(%rbp)
movl -0x34(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x34(%rbp)
movslq -0x34(%rbp), %rsi
leaq -0x20(%rbp), %rdi
callq 0xa530
movsd (%rax), %xmm0
movsd %xmm0, -0xd8(%rbp)
movl -0x34(%rbp), %eax
subl $0x1, %eax
movslq %eax, %rsi
leaq -0x20(%rbp), %rdi
callq 0xa530
movsd -0xd8(%rbp), %xmm0
divsd (%rax), %xmm0
movsd 0x16b71(%rip), %xmm1    # 0x200c8
ucomisd %xmm1, %xmm0
jb 0x9561
movb $0x1, -0x61(%rbp)
jmp 0x94e9
cvtsi2sdl -0x34(%rbp), %xmm1
movsd -0x28(%rbp), %xmm0
divsd %xmm1, %xmm0
movsd %xmm0, -0x28(%rbp)
movq -0x98(%rbp), %rax
movq 0x10(%rax), %rdi
callq 0xeb90
movb %al, -0xd9(%rbp)
jmp 0x958e
movb -0xd9(%rbp), %al
testb $0x1, %al
jne 0x95cc
jmp 0x959a
movl $0xa, %edi
movl $0xfffffff8, %esi       # imm = 0xFFFFFFF8
callq 0xa240
movsd %xmm0, -0xe8(%rbp)
jmp 0x95b3
movq -0x98(%rbp), %rax
movsd -0xe8(%rbp), %xmm0
movsd %xmm0, 0x30(%rax)
jmp 0x96ac
movq -0x98(%rbp), %rax
movq 0x10(%rax), %rdi
callq 0xeb90
movb %al, -0xe9(%rbp)
jmp 0x95e4
movb -0xe9(%rbp), %al
testb $0x1, %al
jne 0x95f3
jmp 0x96aa
movq -0x98(%rbp), %rax
movsd -0x28(%rbp), %xmm0
movsd 0x16a91(%rip), %xmm1    # 0x20098
mulsd %xmm1, %xmm0
movsd %xmm0, -0xf8(%rbp)
movq 0x10(%rax), %rdi
callq 0xebb0
movss %xmm0, -0xf0(%rbp)
jmp 0x9626
movss -0xf0(%rbp), %xmm0
movss 0x16aaa(%rip), %xmm1    # 0x200e0
divss %xmm1, %xmm0
movl $0xa, %edi
callq 0xa590
movsd %xmm0, -0x100(%rbp)
jmp 0x964e
movsd -0x100(%rbp), %xmm1
movsd -0xf8(%rbp), %xmm0
mulsd %xmm1, %xmm0
movsd %xmm0, -0x70(%rbp)
movsd -0x28(%rbp), %xmm0
movsd 0x16a2c(%rip), %xmm1    # 0x200a0
mulsd %xmm1, %xmm0
movsd %xmm0, -0x78(%rbp)
leaq -0x70(%rbp), %rdi
leaq -0x78(%rbp), %rsi
callq 0xa550
movq %rax, -0x108(%rbp)
jmp 0x9693
movq -0x98(%rbp), %rax
movq -0x108(%rbp), %rcx
movsd (%rcx), %xmm0
movsd %xmm0, 0x30(%rax)
jmp 0x96ac
movl $0xa, %edi
movl $0xfffffff3, %esi       # imm = 0xFFFFFFF3
callq 0xa240
movsd %xmm0, -0x110(%rbp)
jmp 0x96c5
movq -0x98(%rbp), %rax
movsd -0x110(%rbp), %xmm0
movsd %xmm0, -0x80(%rbp)
cmpl $0xa, 0x24(%rax)
jge 0x96f1
movsd 0x169d9(%rip), %xmm0    # 0x200c0
movsd %xmm0, -0x88(%rbp)
jmp 0x9743
movq -0x98(%rbp), %rax
cmpl $0x14, 0x24(%rax)
jge 0x9710
movsd 0x169b2(%rip), %xmm0    # 0x200b8
movsd %xmm0, -0x88(%rbp)
jmp 0x9741
movq -0x98(%rbp), %rax
cmpl $0x32, 0x24(%rax)
jge 0x972f
movsd 0x1698b(%rip), %xmm0    # 0x200b0
movsd %xmm0, -0x88(%rbp)
jmp 0x973f
movsd 0x16971(%rip), %xmm0    # 0x200a8
movsd %xmm0, -0x88(%rbp)
jmp 0x9741
jmp 0x9743
movl $0x0, -0x8c(%rbp)
movq -0x98(%rbp), %rax
movl -0x8c(%rbp), %ecx
movl %ecx, -0x118(%rbp)
movq 0x10(%rax), %rdi
callq 0xeb10
movl %eax, -0x114(%rbp)
jmp 0x9771
movl -0x118(%rbp), %eax
movl -0x114(%rbp), %ecx
cmpl %ecx, %eax
jge 0x9821
movq -0x98(%rbp), %rax
movsd -0x80(%rbp), %xmm0
movq 0x78(%rax), %rcx
movslq -0x8c(%rbp), %rdx
movsd %xmm0, (%rcx,%rdx,8)
movq 0x10(%rax), %rdi
callq 0xeb90
movb %al, -0x119(%rbp)
jmp 0x97b2
movb -0x119(%rbp), %al
testb $0x1, %al
jne 0x97be
jmp 0x980b
movl $0xa, %edi
movl $0xfffffff6, %esi       # imm = 0xFFFFFFF6
callq 0xa240
movsd %xmm0, -0x128(%rbp)
jmp 0x97d7
movq -0x98(%rbp), %rax
movsd -0x128(%rbp), %xmm1
movsd -0x88(%rbp), %xmm0
movsd -0x28(%rbp), %xmm2
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movq 0x78(%rax), %rax
movslq -0x8c(%rbp), %rcx
movsd %xmm0, (%rax,%rcx,8)
jmp 0x980d
movl -0x8c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x8c(%rbp)
jmp 0x974d
leaq -0x20(%rbp), %rdi
callq 0x59a0
addq $0x130, %rsp            # imm = 0x130
popq %rbp
retq
movq -0x40(%rbp), %rdi
callq 0x4540
nopl (%rax)