// File: /workspace/github_cpp_makefile_star2_O2/gersteinlab[P]MUSIC/src/ms_peak_calling_utils.cpp
// Function: get_trough_posn_per_ER(double*, int, double*, int, double, int, int, int)
int get_trough_posn_per_ER(double* signal_profile, int l_profile, 
							double* multi_mapp_signal, int l_multi_map_signal, double max_multi_mapp_val,
							int ER_start, int ER_end,
							int l_trough_win)
{
	//vector<int>* maxima_posns = new vector<int>();
	//double min_max_val = 0.0;

	vector<t_extrema_node*>* maxima_nodes = new vector<t_extrema_node*>();
	vector<t_extrema_node*>* minima_nodes = new vector<t_extrema_node*>();
	int* derivative_map = new int[ER_end - ER_start + 2];
	memset(derivative_map, 0, sizeof(int) * (ER_end - ER_start + 2));
	get_extrema_per_plateaus(&signal_profile[ER_start], ER_end-ER_start+1, maxima_nodes, minima_nodes, derivative_map, 0);

	if((int)maxima_nodes->size() == 0 ||
		(int)minima_nodes->size() == 0)
	{
		return(0);
	}

	sort(maxima_nodes->begin(), maxima_nodes->end(), sort_extremas_per_decreasing_height);

	// Sort the minima with increasing height then take the top minima.
	sort(minima_nodes->begin(), minima_nodes->end(), sort_extremas_per_height);

	// Start from the top minimum and check if it is around one of the top maxima.
	vector<int>* rank_sum_per_minimum = new vector<int>();
	for(int i_min = 0; i_min < (int)minima_nodes->size(); i_min++)
	{
		t_extrema_node* prev_max = NULL;
		t_extrema_node* next_max = NULL;
		int prev_max_rank = 0;
		int next_max_rank = 0;

		for(int i_max = 0; i_max < (int)maxima_nodes->size(); i_max++)
		{
			if(prev_max == NULL &&
				maxima_nodes->at(i_max)->extrema_posn < minima_nodes->at(i_min)->extrema_posn)
			{
				prev_max_rank = i_max;
				prev_max = maxima_nodes->at(i_max);
			}

			if(next_max == NULL &&
				maxima_nodes->at(i_max)->extrema_posn > minima_nodes->at(i_min)->extrema_posn)
			{
				next_max_rank = i_max;
				next_max = maxima_nodes->at(i_max);
			}
		} // i_max loop.

		if(prev_max == NULL ||
			next_max == NULL)
		{
			rank_sum_per_minimum->push_back((int)maxima_nodes->size() + (int)maxima_nodes->size() + (int)minima_nodes->size());
			continue;
		}

		double total_multi_mapp_signal = 0;
		if(multi_mapp_signal != NULL)
		{
            for(int i = MAX(0, minima_nodes->at(i_min)->extrema_posn-l_trough_win/2); 
				i < MIN(l_multi_map_signal-1, minima_nodes->at(i_min)->extrema_posn+l_trough_win/2); i++)
            {
                total_multi_mapp_signal += multi_mapp_signal[ER_start+i];
            } // i loop.

			//for(int i = prev_max->extrema_posn; i <= next_max->extrema_posn; i++)
			//{
			//	total_multi_mapp_signal += multi_mapp_signal[ER_start+i];
			//} // i loop.
		}

		// Make sure that the region in this trough is mappable.
		// total_multi_mapp_signal / (next_max->extrema_posn - prev_max->extrema_posn+1) < max_multi_mapp_val)
		if(multi_mapp_signal == NULL ||
			total_multi_mapp_signal / l_trough_win < max_multi_mapp_val)
		{
			rank_sum_per_minimum->push_back(i_min + prev_max_rank + next_max_rank);
		}
		else
		{
			rank_sum_per_minimum->push_back((int)maxima_nodes->size() + (int)maxima_nodes->size() + (int)minima_nodes->size());
		}
	} // i_min loop.

	// Check on the number of rank sums that are generated.
	if(rank_sum_per_minimum->size() != minima_nodes->size())
	{
		fprintf(stderr, "The sanity check failed, per minimum rank sum count does not match the minima positions.\n");
		exit(0);
	}

	// Find the minimum with smallest rank-sum statistic.
	int smallest_rank_sum_stat = (int)maxima_nodes->size() + (int)maxima_nodes->size() + (int)minima_nodes->size();
	int smallest_rank_sum_min_i = 0;
	for(int i_min = 0; i_min < (int)rank_sum_per_minimum->size(); i_min++)
	{
		if(smallest_rank_sum_stat > rank_sum_per_minimum->at(i_min))
		{
			smallest_rank_sum_stat = rank_sum_per_minimum->at(i_min);
			smallest_rank_sum_min_i = i_min;
		}
	} // i_min loop.

	// This position is with respect to the beginning of the ER. Since extrema are with respect to begining of the ER, translate this coordinate.
	int trough_posn = minima_nodes->at(smallest_rank_sum_min_i)->extrema_posn + ER_start;

	delete_extrema_nodes(minima_nodes);
	delete_extrema_nodes(maxima_nodes);

	// Free the current decomposition.
	delete [] derivative_map;

	return(trough_posn);
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x68, %rsp
movl %r9d, %ebx
movl %r8d, %ebp
movsd %xmm0, 0x58(%rsp)
movl %ecx, 0xc(%rsp)
movq %rdx, 0x40(%rsp)
movq %rdi, 0x10(%rsp)
pushq $0x18
popq %r15
movq %r15, %rdi
callq 0x2170
movq %rax, %r14
xorpd %xmm0, %xmm0
movupd %xmm0, (%rax)
andq $0x0, 0x10(%rax)
movq %r15, %rdi
callq 0x2170
movq %rax, %r15
subl %ebp, %ebx
movslq %ebx, %r13
leaq 0x8(,%r13,4), %r12
cmpl $-0x2, %r13d
pushq $-0x1
popq %rdi
cmovgeq %r12, %rdi
xorpd %xmm0, %xmm0
movupd %xmm0, (%rax)
andq $0x0, 0x10(%rax)
callq 0x2040
movq %rax, %rbx
movq %rax, %rdi
xorl %esi, %esi
movq %r12, %rdx
callq 0x20f0
movl %ebp, 0x2c(%rsp)
movslq %ebp, %rbp
movq 0x10(%rsp), %rax
leaq (%rax,%rbp,8), %rdi
incl %r13d
movl %r13d, %esi
movq %r14, %rdx
movq %r15, %rcx
movq %rbx, 0x48(%rsp)
movq %rbx, %r8
xorl %r9d, %r9d
callq 0x1ea88
movabsq $0x7fffffff8, %rcx      # imm = 0x7FFFFFFF8
movq (%r14), %rdi
movq 0x8(%r14), %rsi
movq %rsi, %rax
subq %rdi, %rax
testq %rcx, %rax
je 0xc841
movq 0x8(%r15), %rax
subq (%r15), %rax
testq %rcx, %rax
movl $0x0, %eax
je 0xc843
movl 0xa0(%rsp), %r12d
leaq 0x12d6c(%rip), %rdx     # 0x1f297
callq 0xd2d0
movq (%r15), %rdi
movq 0x8(%r15), %rsi
leaq 0x12d67(%rip), %rdx     # 0x1f2a5
callq 0xd2d0
pushq $0x18
popq %rdi
callq 0x2170
movq %rax, %rsi
pushq $0x2
popq %rcx
movl %r12d, %eax
cltd
idivl %ecx
movl %eax, %ecx
cvtsi2sd %r12d, %xmm0
movsd %xmm0, 0x50(%rsp)
movl 0xc(%rsp), %r12d
decl %r12d
andq $0x0, 0x10(%rsi)
xorpd %xmm0, %xmm0
movq %rsi, 0x20(%rsp)
movupd %xmm0, (%rsi)
movq 0x40(%rsp), %rax
leaq (%rax,%rbp,8), %rax
movq %rax, 0x60(%rsp)
xorl %r13d, %r13d
movl %r12d, 0xc(%rsp)
movl %ecx, 0x30(%rsp)
movq 0x8(%r15), %rdx
subq (%r15), %rdx
movq %rdx, %rax
shrq $0x3, %rax
cltq
cmpq %rax, %r13
jge 0xc79a
xorl %r12d, %r12d
xorl %ebp, %ebp
xorl %ebx, %ebx
movl $0x0, 0x1c(%rsp)
movl $0x0, 0x18(%rsp)
movq 0x8(%r14), %rax
subq (%r14), %rax
movq %rax, %rcx
shrq $0x3, %rcx
movslq %ecx, %rcx
cmpq %rcx, %r12
jge 0xc666
testq %rbp, %rbp
jne 0xc620
movq %r14, %rdi
movq %r12, %rsi
callq 0xcfc8
movq (%rax), %rax
movl (%rax), %ebp
movq %r15, %rdi
movq %r13, %rsi
callq 0xcfc8
movq (%rax), %rax
cmpl (%rax), %ebp
jge 0xc61e
movq %r14, %rdi
movq %r12, %rsi
callq 0xcfc8
movq (%rax), %rbp
movl %r12d, 0x1c(%rsp)
jmp 0xc620
xorl %ebp, %ebp
testq %rbx, %rbx
jne 0xc65e
movq %r14, %rdi
movq %r12, %rsi
callq 0xcfc8
movq (%rax), %rax
movl (%rax), %ebx
movq %r15, %rdi
movq %r13, %rsi
callq 0xcfc8
movq (%rax), %rax
cmpl (%rax), %ebx
jle 0xc65c
movq %r14, %rdi
movq %r12, %rsi
callq 0xcfc8
movq (%rax), %rbx
movl %r12d, 0x18(%rsp)
jmp 0xc65e
xorl %ebx, %ebx
incq %r12
jmp 0xc5c8
testq %rbp, %rbp
je 0xc69b
testq %rbx, %rbx
je 0xc69b
cmpq $0x0, 0x40(%rsp)
movl 0xc(%rsp), %r12d
movl 0x30(%rsp), %ebp
je 0xc749
movq %r15, %rdi
movq %r13, %rsi
callq 0xcfc8
movq (%rax), %rax
cmpl %ebp, (%rax)
jge 0xc6c2
xorl %ebx, %ebx
jmp 0xc6d9
shrq $0x2, %rax
movq 0x8(%r15), %rcx
subq (%r15), %rcx
andl $-0x2, %eax
shrq $0x3, %rcx
addl %eax, %ecx
movl %ecx, 0x3c(%rsp)
movq 0x20(%rsp), %rdi
leaq 0x3c(%rsp), %rsi
jmp 0xc78d
movq %r15, %rdi
movq %r13, %rsi
callq 0xcfc8
movq (%rax), %rax
movslq (%rax), %rbx
movslq %ebp, %rax
subq %rax, %rbx
xorpd %xmm0, %xmm0
movsd %xmm0, 0x10(%rsp)
movq %r15, %rdi
movq %r13, %rsi
callq 0xcfc8
movq (%rax), %rax
movl (%rax), %ecx
addl %ebp, %ecx
movl %r12d, %eax
cmpl %ecx, %r12d
jle 0xc70f
movq %r15, %rdi
movq %r13, %rsi
callq 0xcfc8
movq (%rax), %rax
movl (%rax), %eax
addl %ebp, %eax
cltq
cmpq %rax, %rbx
jge 0xc731
movq 0x60(%rsp), %rax
movsd 0x10(%rsp), %xmm0
addsd (%rax,%rbx,8), %xmm0
movsd %xmm0, 0x10(%rsp)
incq %rbx
jmp 0xc6e3
movsd 0x10(%rsp), %xmm1
divsd 0x50(%rsp), %xmm1
movsd 0x58(%rsp), %xmm0
ucomisd %xmm1, %xmm0
jbe 0xc764
movl 0x1c(%rsp), %eax
addl %r13d, %eax
addl 0x18(%rsp), %eax
movl %eax, 0x38(%rsp)
movq 0x20(%rsp), %rdi
leaq 0x38(%rsp), %rsi
jmp 0xc78d
movq 0x8(%r14), %rax
subq (%r14), %rax
shrq $0x2, %rax
movq 0x8(%r15), %rcx
subq (%r15), %rcx
andl $-0x2, %eax
shrq $0x3, %rcx
addl %eax, %ecx
movl %ecx, 0x34(%rsp)
movq 0x20(%rsp), %rdi
leaq 0x34(%rsp), %rsi
callq 0x77a4
incq %r13
jmp 0xc598
sarq $0x3, %rdx
movq 0x20(%rsp), %r13
movq (%r13), %rcx
movq 0x8(%r13), %rax
movq %rax, %rsi
subq %rcx, %rsi
sarq $0x2, %rsi
cmpq %rdx, %rsi
jne 0xc852
movq 0x8(%r14), %r12
subq (%r14), %r12
shrq $0x2, %r12
andl $-0x2, %r12d
addl %edx, %r12d
xorl %ebx, %ebx
xorl %ebp, %ebp
subq %rcx, %rax
shrq $0x2, %rax
cltq
cmpq %rax, %rbx
jge 0xc80f
movq %r13, %rdi
movq %rbx, %rsi
callq 0x7364
cmpl (%rax), %r12d
jle 0xc802
movq %r13, %rdi
movq %rbx, %rsi
callq 0x7364
movl (%rax), %r12d
movl %ebx, %ebp
incq %rbx
movq (%r13), %rcx
movq 0x8(%r13), %rax
jmp 0xc7d4
movslq %ebp, %rsi
movq %r15, %rdi
callq 0xcfc8
movq (%rax), %rax
movl 0x2c(%rsp), %ebx
addl (%rax), %ebx
movq %r15, %rdi
callq 0x1f2b3
movq %r14, %rdi
callq 0x1f2b3
movq 0x48(%rsp), %rdi
callq 0x2210
movl %ebx, %eax
jmp 0xc843
xorl %eax, %eax
addq $0x68, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x28787(%rip), %rax     # 0x34fe0
movq (%rax), %rcx
leaq 0x1a996(%rip), %rdi     # 0x271f9
pushq $0x59
popq %rsi
pushq $0x1
popq %rdx
callq 0x2330
xorl %edi, %edi
callq 0x21d0