// File: /workspace/github_cpp_makefile_star2_O1/gersteinlab[P]MUSIC/src/ms_signal_enrichment_utils.cpp
// Function: get_poisson_thresholds_per_win(double*, int, int, int, double, int, int)
double get_poisson_thresholds_per_win(double* signal_profile,
								int l_profile,
								int l_win,
								int win_start,
								double target_fdr,
								int min_thresh,
								int max_thresh)
{
	// Count the number of reads per window.
	double total_sig_in_cur_window = 0.0;
	for(int i = win_start; i <= win_start + l_win; i++)
	{
        if(i > 0 && i <= l_profile)
        {
			total_sig_in_cur_window += signal_profile[i];
		}
	} // i loop.

	// Get the total amount of signal in the current window.
	if(total_sig_in_cur_window == 0.0)
	{
		return(0.0);
	}

	if(l_win == 0)
	{
		return(0.0);
	}
	else
	{
		// This is the average of poisson distribution for the heights in this window.
		double avg_read_depth = total_sig_in_cur_window / l_win;
		double lambda = avg_read_depth;
		double log_lambda = xlog(lambda);

		double log_target_cdf = xlog(1.0 - target_fdr);

		// Update the log_cdf value for thresholds smaller than min_threshold.
		double current_log_cdf = -1.0 * lambda;
		double current_factor = -1.0 * lambda; // This is the probability value differentially updated in CDF computation.
		for(int thresh = 1; 
			thresh < min_thresh;
			thresh++)
		{
			double new_multiplier = xlog_div(log_lambda, xlog((double)thresh));
			current_factor = xlog_mul(current_factor, new_multiplier);
			current_log_cdf = xlog_sum(current_log_cdf, current_factor);
		}

		// For thresholds between min and max thresholds, compare the value of (log)CDF with the (log)target FDR.
		bool found_thresh = false;
		double cur_threshold = 0;
		for(int thresh = min_thresh; 
			thresh <= max_thresh && !found_thresh; 
			thresh++)
		{
			double new_multiplier = xlog_div(log_lambda, xlog((double)thresh));
			current_factor = xlog_mul(current_factor, new_multiplier);
			current_log_cdf = xlog_sum(current_log_cdf, current_factor);

			if(current_log_cdf > log_target_cdf)
			{
				found_thresh = true;
				cur_threshold = thresh; // Set the threshold in this window.
			}
		} // thresh loop.

		if(cur_threshold > 0)
		{
			return(cur_threshold);
		}
		else
		{
			return(0.0);
		}
	} // Check for positive number of reads in the window.
}

// Assembly:
pushq %rbp
pushq %r14
pushq %rbx
subq $0x40, %rsp
movl %r9d, %ebx
movl %r8d, %r14d
movapd %xmm0, %xmm3
xorpd %xmm2, %xmm2
xorpd %xmm0, %xmm0
testl %edx, %edx
js 0x1e369
leal (%rcx,%rdx), %eax
cmpl %eax, %ecx
cmovgl %ecx, %eax
incl %eax
testl %ecx, %ecx
setle %r8b
cmpl %esi, %ecx
setg %r9b
orb %r8b, %r9b
jne 0x1e363
movl %ecx, %r8d
addsd (%rdi,%r8,8), %xmm0
incl %ecx
cmpl %ecx, %eax
jne 0x1e349
testl %edx, %edx
je 0x1e4e2
xorpd %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jne 0x1e381
jnp 0x1e4e2
xorps %xmm1, %xmm1
cvtsi2sd %edx, %xmm1
divsd %xmm1, %xmm0
movapd %xmm0, 0x10(%rsp)
movsd %xmm3, (%rsp)
callq 0x25878
movsd %xmm0, 0x28(%rsp)
movsd 0xcc5e(%rip), %xmm0     # 0x2b008
subsd (%rsp), %xmm0
callq 0x25878
movapd 0x10(%rsp), %xmm1
movsd %xmm0, 0x30(%rsp)
xorpd 0x10d28(%rip), %xmm1    # 0x2f0f0
cmpl $0x2, %r14d
movapd %xmm1, 0x10(%rsp)
jl 0x1e43e
leal -0x1(%r14), %ebp
movsd 0xcc28(%rip), %xmm2     # 0x2b008
movapd %xmm1, %xmm0
movsd %xmm0, (%rsp)
movsd %xmm2, 0x8(%rsp)
movsd 0x8(%rsp), %xmm0
callq 0x25878
movaps %xmm0, %xmm1
movsd 0x28(%rsp), %xmm0
callq 0x25a1c
movaps %xmm0, %xmm1
movapd 0x10(%rsp), %xmm0
callq 0x259e1
movapd %xmm0, %xmm1
movsd (%rsp), %xmm0
movapd %xmm1, 0x10(%rsp)
callq 0x258cc
movsd 0x8(%rsp), %xmm2
addsd 0xcbd0(%rip), %xmm2     # 0x2b008
decl %ebp
jne 0x1e3e4
jmp 0x1e442
movapd %xmm1, %xmm0
movsd %xmm0, (%rsp)
xorpd %xmm2, %xmm2
cmpl %ebx, %r14d
jg 0x1e4da
xorpd %xmm0, %xmm0
xorl %ebp, %ebp
movsd %xmm0, 0x38(%rsp)
xorps %xmm0, %xmm0
cvtsi2sd %r14d, %xmm0
movsd %xmm0, 0x8(%rsp)
callq 0x25878
movapd %xmm0, %xmm1
movsd 0x28(%rsp), %xmm0
callq 0x25a1c
movaps %xmm0, %xmm1
movapd 0x10(%rsp), %xmm0
callq 0x259e1
movapd %xmm0, %xmm1
movsd (%rsp), %xmm0
movapd %xmm1, 0x10(%rsp)
callq 0x258cc
ucomisd 0x30(%rsp), %xmm0
movl $0x1, %eax
ja 0x1e4b5
movzbl %bpl, %eax
movsd 0x8(%rsp), %xmm2
ja 0x1e4c3
movsd 0x38(%rsp), %xmm2
cmpl %ebx, %r14d
jge 0x1e4da
movsd %xmm0, (%rsp)
incl %r14d
movapd %xmm2, %xmm0
movl %eax, %ebp
testb $0x1, %al
je 0x1e45a
maxsd 0xcbce(%rip), %xmm2     # 0x2b0b0
movapd %xmm2, %xmm0
addq $0x40, %rsp
popq %rbx
popq %r14
popq %rbp
retq