// File: /workspace/github_cpp_makefile_star2_O1/gersteinlab[P]MUSIC/src/ms_min_max_utils.cpp
// Function: prune_extrema_derivative_map(std::vector<t_extrema_node*, std::allocator<t_extrema_node*>>*, std::vector<t_extrema_node*, std::allocator<t_extrema_node*>>*, int*, int, int, std::vector<t_extrema_node*, std::allocator<t_extrema_node*>>*, std::vector<t_extrema_node*, std::allocator<t_extrema_node*>>*, int*)
void prune_extrema_derivative_map(vector<t_extrema_node*>* mins,
	vector<t_extrema_node*>* maxes,
	signed int* derivative_map, 
	int l_smallest_side,
	int l_signal, 
	vector<t_extrema_node*>* pruned_mins,
	vector<t_extrema_node*>* pruned_maxes,
	signed int* pruned_derivative_map)
{
	vector<t_extrema_node*>* extrema = new vector<t_extrema_node*>();
	extrema->insert(extrema->end(), mins->begin(), mins->end());
	extrema->insert(extrema->end(), maxes->begin(), maxes->end());

	sort(extrema->begin(), extrema->end(), sort_extremas_per_posn);

	// Copy pruned derivative map.
	for(int i = 0; i < l_signal; i++)
	{
		pruned_derivative_map[i] = derivative_map[i];
	}	
	
	int i_ext = 0;
	while(i_ext < (int)extrema->size()-1)
	{
		int l_cur_side = extrema->at(i_ext+1)->extrema_posn - extrema->at(i_ext)->extrema_posn;

		if(l_cur_side < l_smallest_side)
		{
			if(extrema->at(i_ext)->extrema_type == EXTREMA_MAX)
			{
				// This is from MAX to MIN: Fix the derivative map, do not add these extrema to the pruned list.
if(__DUMP_MIN_MAX_UTILS_MSGS__)
				fprintf(stderr, "Pruning MAX-MIN transition at %d, %d\n",extrema->at(i_ext)->extrema_posn, extrema->at(i_ext+1)->extrema_posn);
				for(int i = extrema->at(i_ext)->extrema_posn; i <= extrema->at(i_ext+1)->extrema_posn; i++)
				{
					if(derivative_map[i] > 0)
					{
						fprintf(stderr, "The derivative is set to negative from max to min transition.\n");
						exit(0);
					}
					else
					{
						pruned_derivative_map[i] = 1;
					}
				} // i loop.
			}
			else if(extrema->at(i_ext)->extrema_type == EXTREMA_MIN)
			{
if(__DUMP_MIN_MAX_UTILS_MSGS__)
				fprintf(stderr, "Pruning MIN-MAX transition at %d, %d\n",extrema->at(i_ext)->extrema_posn, extrema->at(i_ext+1)->extrema_posn);
				// This is from MIN to MAX: Fix the derivative map, do not add these extrema to the pruned list.
				for(int i = extrema->at(i_ext)->extrema_posn; i <= extrema->at(i_ext+1)->extrema_posn; i++)
				{
					if(derivative_map[i] < 0)
					{
						fprintf(stderr, "The derivative is set to negative from max to min transition.\n");
						exit(0);
					}
					else
					{
						pruned_derivative_map[i] = -1;
					}
				} // i loop.
			}

			// Remove the extrema at i_ext and i_ext+1.
			extrema->erase(extrema->begin()+i_ext);
			extrema->erase(extrema->begin()+i_ext);

			// At this point, we are basically at the next element.
		}
		else
		{
			// This side's length is ok. Move to the next side.
			i_ext++;
		}
	} // i_ext loop.

	// Must check whether the last extrema nodes are removed, then make sure those are added for correct tracing.
	if(pruned_derivative_map[0] != 0)
	{
		fprintf(stderr, "The first extrema is removed, adding it back.\n");
		//getc(stdin);

		t_extrema_node* begin_ext_node = new t_extrema_node();
		begin_ext_node->extrema_posn = 0;
		begin_ext_node->extrema_type = EXTREMA_MIN;
		begin_ext_node->higher_node = NULL;
		begin_ext_node->lower_node = NULL;
		begin_ext_node->scale = extrema->at(0)->scale;

		if(pruned_derivative_map[0] > 0)
		{
			// Add a minima to the beginning.
			begin_ext_node->extrema_type = EXTREMA_MIN;
		}
		else if(pruned_derivative_map[0] < 0)
		{
			// Add a maxima to the beginning.
			begin_ext_node->extrema_type = EXTREMA_MAX;
		}

		pruned_derivative_map[0] = 0;
		extrema->push_back(begin_ext_node);
	}

	if(pruned_derivative_map[l_signal-1] != 0)
	{
		fprintf(stderr, "The last extrema is removed, adding it back.\n");
		//getc(stdin);

		t_extrema_node* end_ext_node = new t_extrema_node();
		end_ext_node->extrema_posn = l_signal-1;
		end_ext_node->extrema_type = EXTREMA_MIN;
		end_ext_node->higher_node = NULL;
		end_ext_node->lower_node = NULL;
		end_ext_node->scale = extrema->back()->scale;

		if(pruned_derivative_map[l_signal-1] > 0)
		{
			end_ext_node->extrema_type = EXTREMA_MAX;
		}
		else if(pruned_derivative_map[l_signal-1] < 0)
		{
			end_ext_node->extrema_type = EXTREMA_MIN;
		}

		pruned_derivative_map[l_signal-1] = 0;
		extrema->push_back(end_ext_node);
	}

	// Sort the extrema.
	sort(extrema->begin(), extrema->end(), sort_extremas_per_posn);

	// Separate the total list into two lists.
	for(i_ext = 0; i_ext < (int)extrema->size(); i_ext++)
	{
		if(extrema->at(i_ext)->extrema_type == EXTREMA_MIN)
		{
			pruned_mins->push_back(extrema->at(i_ext));
		}
		else if(extrema->at(i_ext)->extrema_type == EXTREMA_MAX)
		{
			pruned_maxes->push_back(extrema->at(i_ext));
		}
	} // i_ext loop.

	//vector<t_extrema_node*>* all_pruned_nodes = new vector<t_extrema_node*>();
	//all_pruned_nodes->insert(all_pruned_nodes->begin(), pruned_mins->begin(), pruned_mins->end());
	//all_pruned_nodes->insert(all_pruned_nodes->begin(), pruned_maxes->begin(), pruned_maxes->end());

	//sort(all_pruned_nodes->begin(), all_pruned_nodes->end(), sort_extremas);

	// Set the derivative map.
	//int i_cur_nuc = 0;
	for(int i_ext = 0; i_ext < (int)extrema->size(); i_ext++)
	{
		if(i_ext > 0 &&
			extrema->at(i_ext-1)->extrema_type == extrema->at(i_ext)->extrema_type)
		{
			fprintf(stderr, "Consecutive same extrema: %d, %d: %d\n", 
				extrema->at(i_ext-1)->extrema_posn, 
				extrema->at(i_ext)->extrema_posn, 
				extrema->at(i_ext)->extrema_type);
			exit(0);
		}
	} // i_ext loop.
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x38, %rsp
movq %r9, 0x20(%rsp)
movl %r8d, 0x14(%rsp)
movl %ecx, 0x18(%rsp)
movq %rdx, %r12
movq %rsi, %r14
movq %rdi, %r15
movl $0x18, %edi
callq 0x2180
movq %rax, %rbx
xorps %xmm0, %xmm0
movups %xmm0, (%rax)
movq $0x0, 0x10(%rax)
movq 0x8(%rax), %rsi
movq (%r15), %rdx
movq 0x8(%r15), %rcx
movq %rax, %rdi
callq 0x2540a
movq 0x8(%rbx), %rsi
movq (%r14), %rdx
movq 0x8(%r14), %rcx
movq %rbx, %rdi
callq 0x2540a
movq (%rbx), %r13
movq 0x8(%rbx), %r15
cmpq %r15, %r13
movq %rbx, 0x8(%rsp)
je 0x241ec
movq %r15, %rbx
subq %r13, %rbx
movq %rbx, %rax
sarq $0x3, %rax
bsrq %rax, %rdx
xorl $0x3f, %edx
addl %edx, %edx
xorq $0x7e, %rdx
leaq 0x6e8(%rip), %rcx       # 0x2477c
movq %r13, %rdi
movq %r15, %rsi
callq 0x10dc5
leaq 0x8(%r13), %r9
cmpq $0x81, %rbx
jl 0x2417e
movq %r15, (%rsp)
movl $0x8, %r15d
movq %r9, %r14
movq %r13, %rbp
movq %r12, 0x28(%rsp)
movq %rbp, %rcx
leaq (%r15,%r13), %rbp
movq (%r13,%r15), %rbx
movq (%r13), %rdx
movl (%rbx), %eax
cmpl (%rdx), %eax
jge 0x240f9
movq %r9, %rdi
movq %r13, %rsi
movq %r15, %rdx
movq %r9, %r12
callq 0x22b0
movq %r12, %r9
movq 0x28(%rsp), %r12
movq %r13, %rcx
jmp 0x2411c
movq (%rcx), %rdx
movq %rbp, %rcx
cmpl (%rdx), %eax
jge 0x2411c
movq %r14, %rdx
leaq -0x8(%rdx), %rcx
movq -0x10(%rdx), %rsi
movq -0x8(%rdx), %rdi
movq %rdi, (%rdx)
movq %rcx, %rdx
cmpl (%rsi), %eax
jl 0x24106
movq %rbx, (%rcx)
addq $0x8, %r15
addq $0x8, %r14
cmpq $0x80, %r15
jne 0x240c5
subq $-0x80, %r13
movq (%rsp), %r9
cmpq %r9, %r13
movq 0x8(%rsp), %rbx
je 0x241ec
movq -0x8(%r13), %rsi
movq (%r13), %rax
movl (%rax), %ecx
movq %r13, %rdx
cmpl (%rsi), %ecx
jge 0x24170
movq %r13, %rsi
leaq -0x8(%rsi), %rdx
movq -0x10(%rsi), %rdi
movq -0x8(%rsi), %r8
movq %r8, (%rsi)
movq %rdx, %rsi
cmpl (%rdi), %ecx
jl 0x2415a
movq %rax, (%rdx)
addq $0x8, %r13
cmpq %r9, %r13
jne 0x24146
jmp 0x241ec
cmpq %r15, %r9
movq 0x8(%rsp), %rbx
je 0x241ec
movq %r13, %r14
movq %r14, %rdi
movq %r9, %r14
movq (%r9), %rbx
movq (%r13), %rcx
movl (%rbx), %eax
cmpl (%rcx), %eax
jge 0x241b8
movq %r14, %rdx
subq %r13, %rdx
subq %rdx, %rdi
addq $0x10, %rdi
movq %r13, %rsi
callq 0x22b0
movq %r13, %rcx
jmp 0x241db
movq (%rdi), %rdx
movq %r14, %rcx
cmpl (%rdx), %eax
jge 0x241db
movq %r14, %rdx
leaq -0x8(%rdx), %rcx
movq -0x10(%rdx), %rsi
movq -0x8(%rdx), %rdi
movq %rdi, (%rdx)
movq %rcx, %rdx
cmpl (%rsi), %eax
jl 0x241c5
movq %rbx, (%rcx)
leaq 0x8(%r14), %r9
cmpq %r15, %r9
movq 0x8(%rsp), %rbx
jne 0x2418b
movq 0x78(%rsp), %r13
movl 0x14(%rsp), %eax
testl %eax, %eax
jle 0x2420e
movl %eax, %eax
xorl %ecx, %ecx
movl (%r12,%rcx,4), %edx
movl %edx, (%r13,%rcx,4)
incq %rcx
cmpq %rcx, %rax
jne 0x241fd
movq %rbx, %rax
addq $0x8, %rax
movq %rax, (%rsp)
movq (%rbx), %rax
movq 0x8(%rbx), %rdx
subq %rax, %rdx
sarq $0x3, %rdx
cmpl $0x2, %edx
jl 0x243e6
xorl %ebp, %ebp
leal 0x1(%rbp), %esi
movslq %esi, %r15
cmpq %r15, %rdx
jbe 0x24726
movslq %ebp, %r14
cmpq %r14, %rdx
jbe 0x24741
movq (%rax,%r15,8), %rcx
movl (%rcx), %ecx
movq (%rax,%r14,8), %rax
movl (%rax), %edx
movl %ecx, %edi
subl %edx, %edi
cmpl 0x18(%rsp), %edi
jge 0x2438f
movl 0x4(%rax), %eax
cmpl $0x1, %eax
je 0x242dc
testl %eax, %eax
jne 0x2433d
cmpb $0x1, 0x15f55(%rip)     # 0x3a1d3
je 0x243ac
movq (%rbx), %rax
movq 0x8(%rbx), %rdx
subq %rax, %rdx
sarq $0x3, %rdx
cmpq %r14, %rdx
jbe 0x24741
cmpq %r15, %rdx
jbe 0x24726
movq (%rax,%r14,8), %rcx
movslq (%rcx), %rcx
movq (%rax,%r15,8), %rax
movslq (%rax), %rsi
cmpq %rsi, %rcx
jg 0x2433d
cmpl $0x0, (%r12,%rcx,4)
jg 0x24737
movl $0x1, (%r13,%rcx,4)
incq %rcx
cmpq %r15, %rdx
ja 0x242af
jmp 0x24726
cmpb $0x1, 0x15ef0(%rip)     # 0x3a1d3
je 0x243c9
movq (%rbx), %rax
movq 0x8(%rbx), %rdx
subq %rax, %rdx
sarq $0x3, %rdx
cmpq %r14, %rdx
jbe 0x24741
cmpq %r15, %rdx
jbe 0x24726
movq (%rax,%r14,8), %rcx
movslq (%rcx), %rcx
movq (%rax,%r15,8), %rax
movslq (%rax), %rsi
cmpq %rsi, %rcx
jg 0x2433d
cmpl $0x0, (%r12,%rcx,4)
js 0x2473c
movl $0xffffffff, (%r13,%rcx,4) # imm = 0xFFFFFFFF
incq %rcx
cmpq %r15, %rdx
ja 0x24314
jmp 0x24726
movq (%rbx), %rax
movq 0x8(%rbx), %rdx
leaq (%rax,%r14,8), %rsi
addq $0x8, %rsi
cmpq %rdx, %rsi
je 0x2435d
leaq (%rax,%r14,8), %rdi
subq %rsi, %rdx
callq 0x22b0
movq (%rbx), %rax
movq 0x8(%rbx), %rdx
addq $-0x8, %rdx
movq %rdx, 0x8(%rbx)
leaq (%rax,%r14,8), %rsi
addq $0x8, %rsi
cmpq %rdx, %rsi
je 0x24385
leaq (%rax,%r14,8), %rdi
subq %rsi, %rdx
callq 0x22b0
movq (%rsp), %rax
addq $-0x8, (%rax)
movl %ebp, %esi
movq (%rbx), %rax
movq 0x8(%rbx), %rdx
subq %rax, %rdx
sarq $0x3, %rdx
leal -0x1(%rdx), %ecx
movl %esi, %ebp
cmpl %ecx, %esi
jl 0x24232
jmp 0x243e6
movq 0x15c2d(%rip), %rax     # 0x39fe0
movq (%rax), %rdi
leaq 0xb143(%rip), %rsi      # 0x2f500
xorl %eax, %eax
callq 0x2250
jmp 0x24284
movq 0x15c10(%rip), %rax     # 0x39fe0
movq (%rax), %rdi
leaq 0xb18b(%rip), %rsi      # 0x2f565
xorl %eax, %eax
callq 0x2250
jmp 0x242e9
cmpl $0x0, (%r13)
jne 0x24669
movl 0x14(%rsp), %ebp
movslq %ebp, %r14
cmpl $0x0, -0x4(%r13,%r14,4)
jne 0x2467d
movq (%rbx), %r15
movq 0x8(%rbx), %r12
cmpq %r12, %r15
je 0x2457d
movq %r12, %rbx
subq %r15, %rbx
movq %rbx, %rax
sarq $0x3, %rax
bsrq %rax, %rdx
xorl $0x3f, %edx
addl %edx, %edx
xorq $0x7e, %rdx
leaq 0x347(%rip), %rcx       # 0x2477c
movq %r15, %rdi
movq %r12, %rsi
callq 0x10dc5
leaq 0x8(%r15), %r14
cmpq $0x81, %rbx
jl 0x24510
movq %r12, 0x18(%rsp)
movl $0x8, %r13d
movq %r14, %rbp
movq %r15, %rbx
movq %rbx, %rcx
leaq (%r15,%r13), %rbx
movq (%r15,%r13), %r12
movq (%r15), %rdx
movl (%r12), %eax
cmpl (%rdx), %eax
jge 0x2448b
movq %r14, %rdi
movq %r15, %rsi
movq %r13, %rdx
callq 0x22b0
movq %r15, %rcx
jmp 0x244ae
movq (%rcx), %rdx
movq %rbx, %rcx
cmpl (%rdx), %eax
jge 0x244ae
movq %rbp, %rdx
leaq -0x8(%rdx), %rcx
movq -0x10(%rdx), %rsi
movq -0x8(%rdx), %rdi
movq %rdi, (%rdx)
movq %rcx, %rdx
cmpl (%rsi), %eax
jl 0x24498
movq %r12, (%rcx)
addq $0x8, %r13
addq $0x8, %rbp
cmpq $0x80, %r13
jne 0x24462
subq $-0x80, %r15
movq 0x18(%rsp), %r9
cmpq %r9, %r15
movq 0x8(%rsp), %rbx
je 0x2457d
movq -0x8(%r15), %rsi
movq (%r15), %rax
movl (%rax), %ecx
movq %r15, %rdx
cmpl (%rsi), %ecx
jge 0x24502
movq %r15, %rsi
leaq -0x8(%rsi), %rdx
movq -0x10(%rsi), %rdi
movq -0x8(%rsi), %r8
movq %r8, (%rsi)
movq %rdx, %rsi
cmpl (%rdi), %ecx
jl 0x244ec
movq %rax, (%rdx)
addq $0x8, %r15
cmpq %r9, %r15
jne 0x244d9
jmp 0x2457d
cmpq %r12, %r14
movq 0x8(%rsp), %rbx
je 0x2457d
movq %r15, %r13
movq %r13, %rdi
movq %r14, %r13
movq (%r14), %rbx
movq (%r15), %rcx
movl (%rbx), %eax
cmpl (%rcx), %eax
jge 0x24549
movq %r13, %rdx
subq %r15, %rdx
subq %rdx, %rdi
addq $0x10, %rdi
movq %r15, %rsi
callq 0x22b0
movq %r15, %rcx
jmp 0x2456c
movq (%rdi), %rdx
movq %r13, %rcx
cmpl (%rdx), %eax
jge 0x2456c
movq %r13, %rdx
leaq -0x8(%rdx), %rcx
movq -0x10(%rdx), %rsi
movq -0x8(%rdx), %rdi
movq %rdi, (%rdx)
movq %rcx, %rdx
cmpl (%rsi), %eax
jl 0x24556
movq %rbx, (%rcx)
leaq 0x8(%r13), %r14
cmpq %r12, %r14
movq 0x8(%rsp), %rbx
jne 0x2451d
movq (%rbx), %rdx
movq 0x8(%rbx), %rax
subq %rdx, %rax
sarq $0x3, %rax
testl %eax, %eax
jle 0x24618
movq 0x70(%rsp), %r15
xorl %r12d, %r12d
xorl %r14d, %r14d
movq 0x20(%rsp), %r13
cmpq %r14, %rax
jbe 0x2474d
movq (%rdx,%r12), %rax
addq %r12, %rdx
movl 0x4(%rax), %ecx
testl %ecx, %ecx
je 0x245d3
cmpl $0x1, %ecx
jne 0x245f4
movq 0x8(%r13), %rsi
cmpq 0x10(%r13), %rsi
je 0x245e7
movq %rax, (%rsi)
addq $0x8, 0x8(%r13)
jmp 0x245f4
movq 0x8(%r15), %rsi
cmpq 0x10(%r15), %rsi
je 0x245ec
movq %rax, (%rsi)
addq $0x8, 0x8(%r15)
jmp 0x245f4
movq %r13, %rdi
jmp 0x245ef
movq %r15, %rdi
callq 0x2565e
incq %r14
movq (%rbx), %rdx
movq 0x8(%rbx), %rcx
subq %rdx, %rcx
movq %rcx, %rax
sarq $0x3, %rax
shrq $0x3, %rcx
movslq %ecx, %rcx
addq $0x8, %r12
cmpq %rcx, %r14
jl 0x245a3
testl %eax, %eax
jle 0x2465a
movl %eax, %edi
xorl %ecx, %ecx
testq %rcx, %rcx
je 0x24652
leaq -0x1(%rcx), %rsi
cmpq %rsi, %rax
jbe 0x24765
cmpq %rcx, %rax
jbe 0x24759
movq -0x8(%rdx,%rcx,8), %r8
movq (%rdx,%rcx,8), %r9
movl 0x4(%r8), %r8d
cmpl 0x4(%r9), %r8d
je 0x24771
incq %rcx
cmpq %rcx, %rdi
jne 0x24620
addq $0x38, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq (%rsp), %rdi
movq %rbx, %rsi
movq %r13, %rdx
callq 0x55c1
jmp 0x243f1
decl %ebp
decq %r14
movq 0x15957(%rip), %rax     # 0x39fe0
movq (%rax), %rcx
leaq 0xaf27(%rip), %rdi      # 0x2f5ba
movl $0x2d, %esi
movl $0x1, %edx
callq 0x2340
movl $0x30, %edi
callq 0x2180
xorps %xmm0, %xmm0
movaps %xmm0, (%rax)
movaps %xmm0, 0x10(%rax)
movaps %xmm0, 0x20(%rax)
movq %rax, 0x30(%rsp)
movl %ebp, (%rax)
movl $0x1, 0x4(%rax)
movups %xmm0, 0x10(%rax)
movq (%rsp), %rcx
movq (%rcx), %rsi
movq -0x8(%rsi), %rcx
movl 0x8(%rcx), %ecx
movl %ecx, 0x8(%rax)
xorl %ecx, %ecx
cmpl $0x0, (%r13,%r14,4)
jle 0x246ec
movl %ecx, 0x4(%rax)
jmp 0x246ee
js 0x2471f
movl $0x0, (%r13,%r14,4)
cmpq 0x10(%rbx), %rsi
je 0x2470d
movq %rax, (%rsi)
movq (%rsp), %rax
addq $0x8, (%rax)
jmp 0x24404
leaq 0x30(%rsp), %rdx
movq %rbx, %rdi
callq 0x2565e
jmp 0x24404
movl $0x1, %ecx
jmp 0x246e7
leaq 0x91a9(%rip), %rdi      # 0x2d8d6
movq %r15, %rsi
xorl %eax, %eax
callq 0x2270
callq 0x559d
callq 0x5579
leaq 0x918e(%rip), %rdi      # 0x2d8d6
movq %r14, %rsi
jmp 0x24730
leaq 0x9182(%rip), %rdi      # 0x2d8d6
movq %r14, %rsi
jmp 0x2476c
leaq 0x9176(%rip), %rdi      # 0x2d8d6
movq %rcx, %rsi
jmp 0x2476c
leaq 0x916a(%rip), %rdi      # 0x2d8d6
movq %rax, %rdx
jmp 0x24730
movq %rbx, %rdi
movq %rcx, %rdx
callq 0x5680