// File: /workspace/github_cpp_makefile_star2_O2/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, %ebp
movapd %xmm0, %xmm3
leal (%rcx,%rdx), %eax
xorpd %xmm0, %xmm0
cmpl %eax, %ecx
jg 0x19882
testl %ecx, %ecx
setle %r8b
cmpl %esi, %ecx
setg %r9b
orb %r8b, %r9b
jne 0x1987e
movl %ecx, %r8d
addsd (%rdi,%r8,8), %xmm0
incl %ecx
jmp 0x19860
xorpd %xmm2, %xmm2
testl %edx, %edx
je 0x199d3
xorpd %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jne 0x1989e
jnp 0x199d3
cvtsi2sd %edx, %xmm1
divsd %xmm1, %xmm0
movapd %xmm0, 0x10(%rsp)
movsd %xmm3, (%rsp)
callq 0x1f860
movsd %xmm0, 0x28(%rsp)
movsd 0xa744(%rip), %xmm0     # 0x24008
subsd (%rsp), %xmm0
callq 0x1f860
movapd 0x10(%rsp), %xmm1
xorpd 0xe814(%rip), %xmm1     # 0x280f0
movsd %xmm0, 0x30(%rsp)
pushq $0x1
popq %r14
movsd %xmm1, (%rsp)
movsd 0xa715(%rip), %xmm0     # 0x24008
cmpl %ebp, %r14d
jge 0x19954
movsd %xmm0, 0x8(%rsp)
movsd 0x8(%rsp), %xmm0
movapd %xmm1, 0x10(%rsp)
callq 0x1f860
movaps %xmm0, %xmm1
movsd 0x28(%rsp), %xmm0
callq 0x1f9cf
movaps %xmm0, %xmm1
movsd (%rsp), %xmm0
callq 0x1f994
movaps %xmm0, %xmm1
movapd 0x10(%rsp), %xmm0
movsd %xmm1, (%rsp)
callq 0x1f8b2
movapd %xmm0, %xmm1
movsd 0x8(%rsp), %xmm0
addsd 0xa6b9(%rip), %xmm0     # 0x24008
incl %r14d
jmp 0x198f3
xorpd %xmm2, %xmm2
xorl %eax, %eax
cmpl %ebx, %ebp
jg 0x199cb
testb $0x1, %al
jne 0x199cb
movsd %xmm2, 0x38(%rsp)
cvtsi2sd %ebp, %xmm0
movsd %xmm0, 0x8(%rsp)
movapd %xmm1, 0x10(%rsp)
callq 0x1f860
movapd %xmm0, %xmm1
movsd 0x28(%rsp), %xmm0
callq 0x1f9cf
movaps %xmm0, %xmm1
movsd (%rsp), %xmm0
callq 0x1f994
movaps %xmm0, %xmm1
movapd 0x10(%rsp), %xmm0
movsd %xmm1, (%rsp)
callq 0x1f8b2
movapd %xmm0, %xmm1
movsd 0x8(%rsp), %xmm2
ucomisd 0x30(%rsp), %xmm0
seta %al
ja 0x199c7
movsd 0x38(%rsp), %xmm2
incl %ebp
jmp 0x1995a
xorpd %xmm0, %xmm0
maxsd %xmm0, %xmm2
movapd %xmm2, %xmm0
addq $0x40, %rsp
popq %rbx
popq %r14
popq %rbp
retq