// File: gersteinlab[P]MUSIC/src/ms_signal_enrichment_utils.cpp
// Function: filter_regions_per_window_average(std::vector<t_annot_region*, std::allocator<t_annot_region*>>*, double*, int, double*, int, double, int)
vector<t_annot_region*>* filter_regions_per_window_average(vector<t_annot_region*>* regions, 
	double* signal_profile, int l_profile, double* control_profile, int l_control,
	double fdr, int l_win)
{
	// Go over all the windows.
	int cur_win_start = 0;
	int cur_l_win = l_win;

	// Sort the regions.
	sort(regions->begin(), regions->end(), sort_regions);

	// List of pruned regions.
	vector<t_annot_region*>* pruned_regions = new vector<t_annot_region*>();

	// The windowing schedule matches up with the ms_decomposition.
	while(cur_win_start < l_profile)
	{
		// Set the length of the window 
		if(cur_win_start+l_win > l_profile)
		{
			cur_l_win = l_profile - cur_win_start;
		}
		else
		{
			cur_l_win = l_win;
		}

		//fprintf(stderr, "Processing %d-%d\n", cur_win_start, cur_win_start+cur_l_win);

		// Get the minimum and maximum in the window.
		int max_thresh = 0;
		for(int i = cur_win_start; i < cur_win_start+cur_l_win && i < l_profile; i++)
		{
			if(max_thresh < signal_profile[i])
			{
				max_thresh = (int)(signal_profile[i]);
			}
		} // i loop.


//#define __POISSON_BCKGRND__
//#undef __GEOMETRIC_BCKGRND__
#ifdef __POISSON_BCKGRND__
		double cur_win_thresh = get_poisson_thresholds_per_win(signal_profile,
										l_profile,
										cur_l_win,
										cur_win_start,
										fdr,
										1,
										max_thresh);
#elif defined __GEOMETRIC_BCKGRND__
		double cur_win_thresh = get_geometric_thresholds_per_win(signal_profile,
										l_profile,
										cur_l_win,
										cur_win_start,
										fdr,
										1,
										max_thresh);
#else
		#error "Did not select a background model."
#endif // Bckgrnd selection

		//fprintf(stderr, "Window: %d-%d: Threshold: %lf\n", cur_win_start, cur_win_start + cur_l_win, cur_win_thresh);

		// Go over all the regions in the current window and prune the ends with respect to the threshold.
		vector<double>* cur_region_sigs = new vector<double>();

		// Go over all the regions in the current window and prune the ends with respect to the threshold.
		for(int i_reg = 0; cur_win_thresh > 0 && i_reg < (int)regions->size(); i_reg++)
		{
			// Process the current region if its start is in the current window.
			if((regions->at(i_reg)->start >= cur_win_start &&
				regions->at(i_reg)->start < cur_win_start + cur_l_win))
			{
				// Get the median signal value in the current region.
				for(int i = regions->at(i_reg)->start; i <= regions->at(i_reg)->end; i++)
				{
					cur_region_sigs->push_back(signal_profile[i]);
				} // i loop.

				sort(cur_region_sigs->begin(), cur_region_sigs->end());

				if(cur_region_sigs->at(cur_region_sigs->size() / 2) > cur_win_thresh)
				{
					pruned_regions->push_back(duplicate_region(regions->at(i_reg)));
				}

				cur_region_sigs->clear();
			} // check if the current region is in the current window.
		} // i_reg loop.

		delete cur_region_sigs;

		// Update window.
		cur_win_start += l_win;
	} // window start check.

if(__DUMP_SIGNAL_ENRICHMENT_MSGS__)
	fprintf(stderr, "Pruned to %d (%d) regions.\n", (int)regions->size(), (int)pruned_regions->size());

	return(pruned_regions);
}

// Assembly:
subq $0xe8, %rsp
movq %rdi, 0xe0(%rsp)
movq %rsi, 0xd8(%rsp)
movl %edx, 0xd4(%rsp)
movq %rcx, 0xc8(%rsp)
movl %r8d, 0xc4(%rsp)
movsd %xmm0, 0xb8(%rsp)
movl %r9d, 0xb4(%rsp)
movl $0x0, 0xb0(%rsp)
movl 0xb4(%rsp), %eax
movl %eax, 0xac(%rsp)
movq 0xe0(%rsp), %rdi
callq 0xc7d0
movq %rax, 0xa0(%rsp)
movq 0xe0(%rsp), %rdi
callq 0xc760
movq %rax, 0x98(%rsp)
movq 0xa0(%rsp), %rdi
movq 0x98(%rsp), %rsi
leaq -0xdda9(%rip), %rdx     # 0x2a3a0
callq 0x31d00
movl $0x18, %edi
callq 0x2190
movq %rax, %rdi
movq %rdi, 0x50(%rsp)
xorl %esi, %esi
movl $0x18, %edx
callq 0x2110
movq 0x50(%rsp), %rdi
callq 0xc670
movq 0x50(%rsp), %rax
movq %rax, 0x90(%rsp)
movl 0xb0(%rsp), %eax
cmpl 0xd4(%rsp), %eax
jge 0x38505
movl 0xb0(%rsp), %eax
addl 0xb4(%rsp), %eax
cmpl 0xd4(%rsp), %eax
jle 0x381c5
movl 0xd4(%rsp), %eax
subl 0xb0(%rsp), %eax
movl %eax, 0xac(%rsp)
jmp 0x381d3
movl 0xb4(%rsp), %eax
movl %eax, 0xac(%rsp)
movl $0x0, 0x8c(%rsp)
movl 0xb0(%rsp), %eax
movl %eax, 0x88(%rsp)
movl 0x88(%rsp), %ecx
movl 0xb0(%rsp), %edx
addl 0xac(%rsp), %edx
xorl %eax, %eax
cmpl %edx, %ecx
movb %al, 0x4f(%rsp)
jge 0x38220
movl 0x88(%rsp), %eax
cmpl 0xd4(%rsp), %eax
setl %al
movb %al, 0x4f(%rsp)
movb 0x4f(%rsp), %al
testb $0x1, %al
jne 0x3822a
jmp 0x38282
cvtsi2sdl 0x8c(%rsp), %xmm1
movq 0xd8(%rsp), %rax
movslq 0x88(%rsp), %rcx
movsd (%rax,%rcx,8), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x3826a
movq 0xd8(%rsp), %rax
movslq 0x88(%rsp), %rcx
cvttsd2si (%rax,%rcx,8), %eax
movl %eax, 0x8c(%rsp)
jmp 0x3826c
movl 0x88(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x88(%rsp)
jmp 0x381ec
movq 0xd8(%rsp), %rdi
movl 0xd4(%rsp), %esi
movl 0xac(%rsp), %edx
movl 0xb0(%rsp), %ecx
movsd 0xb8(%rsp), %xmm0
movl 0x8c(%rsp), %r9d
movl $0x1, %r8d
callq 0x36100
movsd %xmm0, 0x80(%rsp)
movl $0x18, %edi
callq 0x2190
movq %rax, %rdi
movq %rdi, 0x40(%rsp)
xorl %esi, %esi
movl $0x18, %edx
callq 0x2110
movq 0x40(%rsp), %rdi
callq 0xc840
movq 0x40(%rsp), %rax
movq %rax, 0x78(%rsp)
movl $0x0, 0x74(%rsp)
movsd 0x80(%rsp), %xmm0
xorl %eax, %eax
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
movb %al, 0x3f(%rsp)
jbe 0x3833b
movl 0x74(%rsp), %eax
movl %eax, 0x38(%rsp)
movq 0xe0(%rsp), %rdi
callq 0xc680
movq %rax, %rcx
movl 0x38(%rsp), %eax
cmpl %ecx, %eax
setl %al
movb %al, 0x3f(%rsp)
movb 0x3f(%rsp), %al
testb $0x1, %al
jne 0x38348
jmp 0x384c2
movq 0xe0(%rsp), %rdi
movslq 0x74(%rsp), %rsi
callq 0xc800
movq (%rax), %rax
movl 0xc(%rax), %eax
cmpl 0xb0(%rsp), %eax
jl 0x384b0
movq 0xe0(%rsp), %rdi
movslq 0x74(%rsp), %rsi
callq 0xc800
movq (%rax), %rax
movl 0xc(%rax), %eax
movl 0xb0(%rsp), %ecx
addl 0xac(%rsp), %ecx
cmpl %ecx, %eax
jge 0x384b0
movq 0xe0(%rsp), %rdi
movslq 0x74(%rsp), %rsi
callq 0xc800
movq (%rax), %rax
movl 0xc(%rax), %eax
movl %eax, 0x70(%rsp)
movl 0x70(%rsp), %eax
movl %eax, 0x34(%rsp)
movq 0xe0(%rsp), %rdi
movslq 0x74(%rsp), %rsi
callq 0xc800
movq %rax, %rcx
movl 0x34(%rsp), %eax
movq (%rcx), %rcx
cmpl 0x20(%rcx), %eax
jg 0x3840b
movq 0x78(%rsp), %rdi
movq 0xd8(%rsp), %rsi
movslq 0x70(%rsp), %rax
shlq $0x3, %rax
addq %rax, %rsi
callq 0xc850
movl 0x70(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x70(%rsp)
jmp 0x383b7
movq 0x78(%rsp), %rdi
callq 0x11b00
movq %rax, 0x68(%rsp)
movq 0x78(%rsp), %rdi
callq 0x11970
movq %rax, 0x60(%rsp)
movq 0x68(%rsp), %rdi
movq 0x60(%rsp), %rsi
callq 0x3adc0
movq 0x78(%rsp), %rax
movq %rax, 0x28(%rsp)
movq 0x78(%rsp), %rdi
callq 0x11c40
movq 0x28(%rsp), %rdi
movq %rax, %rsi
shrq %rsi
callq 0xc930
movsd (%rax), %xmm0
ucomisd 0x80(%rsp), %xmm0
jbe 0x384a6
movq 0x90(%rsp), %rax
movq %rax, 0x20(%rsp)
movq 0xe0(%rsp), %rdi
movslq 0x74(%rsp), %rsi
callq 0xc800
movq (%rax), %rdi
callq 0x2a410
movq 0x20(%rsp), %rdi
movq %rax, 0x58(%rsp)
leaq 0x58(%rsp), %rsi
callq 0x1acc0
movq 0x78(%rsp), %rdi
callq 0x3ae00
jmp 0x384b2
movl 0x74(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x74(%rsp)
jmp 0x382fe
movq 0x78(%rsp), %rax
movq %rax, 0x18(%rsp)
cmpq $0x0, %rax
je 0x384eb
movq 0x18(%rsp), %rdi
callq 0x1ad50
movq 0x18(%rsp), %rdi
movl $0x18, %esi
callq 0x21a0
movl 0xb4(%rsp), %eax
addl 0xb0(%rsp), %eax
movl %eax, 0xb0(%rsp)
jmp 0x38183
testb $0x1, 0x2ccd4(%rip)     # 0x651e0
je 0x38554
movq 0x2cacb(%rip), %rax     # 0x64fe0
movq (%rax), %rax
movq %rax, 0x8(%rsp)
movq 0xe0(%rsp), %rdi
callq 0xc680
movl %eax, 0x14(%rsp)
movq 0x90(%rsp), %rdi
callq 0xc680
movq 0x8(%rsp), %rdi
movl 0x14(%rsp), %edx
movl %eax, %ecx
leaq 0x1e051(%rip), %rsi     # 0x5659e
movb $0x0, %al
callq 0x2250
movq 0x90(%rsp), %rax
addq $0xe8, %rsp
retq
nopw %cs:(%rax,%rax)