// File: gersteinlab[P]MUSIC/src/ms_filter_utils.cpp
// Function: mean_filter_data(double*, int, int, int)
double* mean_filter_data(double* track_data,
						int l_track_data, 
						int l_averaging_win,
						int skip_value) // This is the value to be skipped from the window values.
{
	// Do copying from start to end.
    double* cur_filtered_track = new double[l_track_data + 2];

	int half_l_averaging = l_averaging_win / 2;
		
	// Initialize the current pdf.
	double cur_total_win_val = 0;
	bool val_inited = false;

	int prev_avg_start = -1;
	int prev_avg_end = -1;

	// Go over all the positions as the middle of the filtering window.
	for(int cur_win_mid = 1; cur_win_mid <= l_track_data; cur_win_mid++)
	{
		cur_filtered_track[cur_win_mid] = 0;

		int cur_avg_start = (cur_win_mid > half_l_averaging)?(cur_win_mid - half_l_averaging):(1);
		int cur_avg_end = (cur_win_mid + half_l_averaging <= l_track_data)?(cur_win_mid + half_l_averaging):(l_track_data);
		if(!val_inited)
		{
			for(int i = cur_avg_start; i <= cur_avg_end; i++)
			{
				cur_total_win_val += track_data[i];
			} // i loop.

			val_inited = true;
		}
		else
		{
			// Exclude the signal values that got out of the current window.
			for(int i = prev_avg_start; i < cur_avg_start; i++)
			{
				cur_total_win_val -= track_data[i];
			} // i loop.

			// Add the signal values that entered the current window.
			for(int i = prev_avg_end+1; i <= cur_avg_end; i++)
			{
				cur_total_win_val += track_data[i];
			} // i loop.
		}

		// Following does a sanity check for the computed values.
if(__DUMP_FILTER_MSGS__)
{
		double check_val = 0;
		for(int i = cur_avg_start; i <= cur_avg_end; i++)
		{
			check_val += track_data[i];
		} // i loop.

		if(fabs(check_val - cur_total_win_val) > 2)
		{
			fprintf(stderr, "Check failed: %d: %lf, %lf\n", cur_win_mid, check_val, cur_total_win_val);
			exit(0);
		}
}

		cur_filtered_track[cur_win_mid] = cur_total_win_val / (cur_avg_end - cur_avg_start + 1);

		prev_avg_start = cur_avg_start;
		prev_avg_end = cur_avg_end;
	} // main signal filtering loop.

	return(cur_filtered_track);
}

// Assembly:
subq $0x78, %rsp
movq %rdi, 0x70(%rsp)
movl %esi, 0x6c(%rsp)
movl %edx, 0x68(%rsp)
movl %ecx, 0x64(%rsp)
movl 0x6c(%rsp), %eax
addl $0x2, %eax
cltq
movl $0x8, %ecx
mulq %rcx
movq %rax, %rdi
seto %cl
movq $-0x1, %rax
testb $0x1, %cl
cmovneq %rax, %rdi
callq 0x2040
movq %rax, 0x58(%rsp)
movl 0x68(%rsp), %eax
movl $0x2, %ecx
cltd
idivl %ecx
movl %eax, 0x54(%rsp)
xorps %xmm0, %xmm0
movsd %xmm0, 0x48(%rsp)
movb $0x0, 0x47(%rsp)
movl $0xffffffff, 0x40(%rsp) # imm = 0xFFFFFFFF
movl $0xffffffff, 0x3c(%rsp) # imm = 0xFFFFFFFF
movl $0x1, 0x38(%rsp)
movl 0x38(%rsp), %eax
cmpl 0x6c(%rsp), %eax
jg 0x22924
movq 0x58(%rsp), %rax
movslq 0x38(%rsp), %rcx
xorps %xmm0, %xmm0
movsd %xmm0, (%rax,%rcx,8)
movl 0x38(%rsp), %eax
cmpl 0x54(%rsp), %eax
jle 0x22732
movl 0x38(%rsp), %eax
subl 0x54(%rsp), %eax
movl %eax, 0x10(%rsp)
jmp 0x2273d
movl $0x1, %eax
movl %eax, 0x10(%rsp)
jmp 0x2273d
movl 0x10(%rsp), %eax
movl %eax, 0x34(%rsp)
movl 0x38(%rsp), %eax
addl 0x54(%rsp), %eax
cmpl 0x6c(%rsp), %eax
jg 0x22761
movl 0x38(%rsp), %eax
addl 0x54(%rsp), %eax
movl %eax, 0xc(%rsp)
jmp 0x22769
movl 0x6c(%rsp), %eax
movl %eax, 0xc(%rsp)
movl 0xc(%rsp), %eax
movl %eax, 0x30(%rsp)
testb $0x1, 0x47(%rsp)
jne 0x227b9
movl 0x34(%rsp), %eax
movl %eax, 0x2c(%rsp)
movl 0x2c(%rsp), %eax
cmpl 0x30(%rsp), %eax
jg 0x227b2
movq 0x70(%rsp), %rax
movslq 0x2c(%rsp), %rcx
movsd (%rax,%rcx,8), %xmm0
addsd 0x48(%rsp), %xmm0
movsd %xmm0, 0x48(%rsp)
movl 0x2c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x2c(%rsp)
jmp 0x22780
movb $0x1, 0x47(%rsp)
jmp 0x22836
movl 0x40(%rsp), %eax
movl %eax, 0x28(%rsp)
movl 0x28(%rsp), %eax
cmpl 0x34(%rsp), %eax
jge 0x227f7
movq 0x70(%rsp), %rax
movslq 0x28(%rsp), %rcx
movsd (%rax,%rcx,8), %xmm1
movsd 0x48(%rsp), %xmm0
subsd %xmm1, %xmm0
movsd %xmm0, 0x48(%rsp)
movl 0x28(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x28(%rsp)
jmp 0x227c1
movl 0x3c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x24(%rsp)
movl 0x24(%rsp), %eax
cmpl 0x30(%rsp), %eax
jg 0x22834
movq 0x70(%rsp), %rax
movslq 0x24(%rsp), %rcx
movsd (%rax,%rcx,8), %xmm0
addsd 0x48(%rsp), %xmm0
movsd %xmm0, 0x48(%rsp)
movl 0x24(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x24(%rsp)
jmp 0x22802
jmp 0x22836
testb $0x1, 0x429a0(%rip)     # 0x651dd
je 0x228dc
xorps %xmm0, %xmm0
movsd %xmm0, 0x18(%rsp)
movl 0x34(%rsp), %eax
movl %eax, 0x14(%rsp)
movl 0x14(%rsp), %eax
cmpl 0x30(%rsp), %eax
jg 0x22886
movq 0x70(%rsp), %rax
movslq 0x14(%rsp), %rcx
movsd (%rax,%rcx,8), %xmm0
addsd 0x18(%rsp), %xmm0
movsd %xmm0, 0x18(%rsp)
movl 0x14(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x14(%rsp)
jmp 0x22854
movsd 0x18(%rsp), %xmm0
subsd 0x48(%rsp), %xmm0
movaps 0x324f7(%rip), %xmm1    # 0x54d90
pand %xmm1, %xmm0
movsd 0x2f7ab(%rip), %xmm1    # 0x52050
ucomisd %xmm1, %xmm0
jbe 0x228da
movq 0x4272e(%rip), %rax     # 0x64fe0
movq (%rax), %rdi
movl 0x38(%rsp), %edx
movsd 0x18(%rsp), %xmm0
movsd 0x48(%rsp), %xmm1
leaq 0x3312b(%rip), %rsi     # 0x559f7
movb $0x2, %al
callq 0x2250
xorl %edi, %edi
callq 0x21f0
jmp 0x228dc
movsd 0x48(%rsp), %xmm0
movl 0x30(%rsp), %eax
subl 0x34(%rsp), %eax
addl $0x1, %eax
cvtsi2sd %eax, %xmm1
divsd %xmm1, %xmm0
movq 0x58(%rsp), %rax
movslq 0x38(%rsp), %rcx
movsd %xmm0, (%rax,%rcx,8)
movl 0x34(%rsp), %eax
movl %eax, 0x40(%rsp)
movl 0x30(%rsp), %eax
movl %eax, 0x3c(%rsp)
movl 0x38(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x38(%rsp)
jmp 0x226fa
movq 0x58(%rsp), %rax
addq $0x78, %rsp
retq
nop