// File: /workspace/github_cpp_makefile_star2_O2/gersteinlab[P]MUSIC/src/ms_annot_region_tools.cpp
// Function: get_inter_region_distance_distribution(std::vector<t_annot_region*, std::allocator<t_annot_region*>>*, std::vector<t_annot_region*, std::allocator<t_annot_region*>>*)
vector<int>* get_inter_region_distance_distribution(vector<t_annot_region*>* annot_regions1, 
	vector<t_annot_region*>* annot_regions2)
{
	int max_dist = 10*1000*1000;

	vector<int>* distances = new vector<int>();

	t_sorted_annot_region_lists* restr_regs1 = restructure_annot_regions(annot_regions1);
	t_sorted_annot_region_lists* restr_regs2 = restructure_annot_regions(annot_regions2);

	for(int i_chr1 = 0; i_chr1 < (int)restr_regs1->chr_ids->size(); i_chr1++)
	{
		fprintf(stderr, "Processing regions in %s\n", restr_regs1->chr_ids->at(i_chr1));

		int i_chr2 = t_string::get_i_str(restr_regs2->chr_ids, restr_regs1->chr_ids->at(i_chr1));
		vector<t_annot_region*>* cur_chr_regs1 = restr_regs1->regions_per_chrom[i_chr1];

		if(i_chr2 < (int)restr_regs2->chr_ids->size())
		{			
			vector<t_annot_region*>* cur_chr_regs2 = restr_regs2->regions_per_chrom[i_chr2];			

			for(int i_reg1 = 0; i_reg1 < (int)cur_chr_regs1->size(); i_reg1++)
			{
				fprintf(stderr, "Searching for %s:%d-%d\n", cur_chr_regs1->at(i_reg1)->chrom, cur_chr_regs1->at(i_reg1)->start, cur_chr_regs1->at(i_reg1)->end);

				int cur_reg_min_distance = max_dist;

				int i_loc_reg2 = locate_posn_region_per_region_starts(cur_chr_regs1->at(i_reg1)->start, cur_chr_regs2, 0, (int)cur_chr_regs2->size()-1);

				while(i_loc_reg2 > 0 &&
					cur_chr_regs2->at(i_loc_reg2)->end > cur_chr_regs1->at(i_reg1)->start)
				{
					i_loc_reg2--;
				}

				while(i_loc_reg2 < (int)cur_chr_regs2->size() &&
					cur_chr_regs2->at(i_loc_reg2)->start < cur_chr_regs1->at(i_reg1)->end)
				{
					// Get the distance of the current region2 to region1.
					int cur_dist = get_reg2reg_distance(cur_chr_regs1->at(i_reg1), cur_chr_regs2->at(i_loc_reg2));

					if(cur_reg_min_distance > cur_dist)
					{
						cur_reg_min_distance = cur_dist;
						//fprintf(stderr, "5' close exon: %s:%d-%d\n", cur_chr_regs2->at(i_loc_reg2)->chrom, cur_chr_regs2->at(i_loc_reg2)->start, cur_chr_regs2->at(i_loc_reg2)->end);
						//getc(stdin);
					}

					i_loc_reg2++;
				} // i_loc_reg2 loop.

				// The above loop is out when the reg2 passes over reg1. Must check it again. On the right.
				if(i_loc_reg2 < (int)cur_chr_regs2->size())
				{
					int cur_dist = get_reg2reg_distance(cur_chr_regs1->at(i_reg1), cur_chr_regs2->at(i_loc_reg2));

					if(cur_reg_min_distance > cur_dist)
					{
						cur_reg_min_distance = cur_dist;
						//fprintf(stderr, "3' close exon: %s:%d-%d\n", cur_chr_regs2->at(i_loc_reg2)->chrom, cur_chr_regs2->at(i_loc_reg2)->start, cur_chr_regs2->at(i_loc_reg2)->end);
						//getc(stdin);
					}
				}

				fprintf(stderr, "%s:%d-%d: %d\n", cur_chr_regs1->at(i_reg1)->chrom, cur_chr_regs1->at(i_reg1)->start, cur_chr_regs1->at(i_reg1)->end, cur_reg_min_distance);

				distances->push_back(cur_reg_min_distance);
			} // i_reg1 loop.
		} // i_chr2 check.
		else
		{

			fprintf(stderr, "Could not find %s in chr2 list.\n", restr_regs1->chr_ids->at(i_chr1));
			getc(stdin);

			// Add 10000000 to the distances.
			for(int i_reg1 = 0; i_reg1 < (int)cur_chr_regs1->size(); i_reg1++)
			{
				distances->push_back(max_dist);
			} // i_reg1 loop.
		}
	} // i_chr1 loop.

	return(distances);
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x38, %rsp
movq %rsi, %rbx
movq %rdi, %r14
leaq 0x8(%rsp), %rax
movl $0x989680, (%rax)       # imm = 0x989680
pushq $0x18
popq %rdi
callq 0x2170
movq %rax, %r13
xorps %xmm0, %xmm0
movups %xmm0, (%rax)
andq $0x0, 0x10(%rax)
movq %r14, %rdi
callq 0x12b99
movq %rax, %r14
movq %rbx, %rdi
callq 0x12b99
movq %rax, %r15
movq %r14, 0x20(%rsp)
movq 0x18(%r14), %r12
xorl %ebp, %ebp
movq %r12, 0x10(%rsp)
movq %r13, 0x30(%rsp)
movq %rax, 0x18(%rsp)
movq 0x8(%r12), %rax
subq (%r12), %rax
shrq $0x3, %rax
cltq
cmpq %rax, %rbp
jge 0x1598f
movq 0x1f94a(%rip), %rax     # 0x34fe0
movq (%rax), %rbx
movq %r12, %rdi
movq %rbp, %rsi
callq 0x7342
movq (%rax), %rdx
movq %rbx, %rdi
leaq 0x1266c(%rip), %rsi     # 0x27d1d
xorl %eax, %eax
callq 0x2240
movq 0x18(%r15), %r14
movq %r12, %rdi
movq %rbp, %rsi
callq 0x7342
movq (%rax), %rsi
movq %r14, %rdi
callq 0x21152
movq 0x20(%rsp), %rcx
movq (%rcx), %rcx
movq (%rcx,%rbp,8), %rbx
movq 0x8(%r14), %rcx
subq (%r14), %rcx
shrq $0x3, %rcx
cmpl %ecx, %eax
movq %rbp, 0x28(%rsp)
jge 0x1591e
movq (%r15), %rcx
cltq
movq (%rcx,%rax,8), %r15
xorl %r12d, %r12d
movq 0x8(%rbx), %rax
subq (%rbx), %rax
shrq $0x3, %rax
cltq
cmpq %rax, %r12
jge 0x15978
movq 0x1f8c1(%rip), %rax     # 0x34fe0
movq (%rax), %r14
movq %rbx, %rdi
movq %r12, %rsi
callq 0x7404
movq (%rax), %rax
movq (%rax), %r13
movq %rbx, %rdi
movq %r12, %rsi
callq 0x7404
movq (%rax), %rax
movl 0xc(%rax), %ebp
movq %rbx, %rdi
movq %r12, %rsi
callq 0x7404
movq (%rax), %rax
movl 0x20(%rax), %r8d
movq %r14, %rdi
leaq 0x125d7(%rip), %rsi     # 0x27d37
movq %r13, %rdx
movl %ebp, %ecx
xorl %eax, %eax
callq 0x2240
movl 0x8(%rsp), %eax
movl %eax, 0x4(%rsp)
movq %rbx, %rdi
movq %r12, %rsi
callq 0x7404
movq (%rax), %rax
movl 0xc(%rax), %edi
movq 0x8(%r15), %rcx
subq (%r15), %rcx
shrq $0x3, %rcx
decl %ecx
movq %r15, %rsi
xorl %edx, %edx
callq 0x12dee
movl %eax, %r14d
movl %eax, %r13d
sarl $0x1f, %eax
andl %r14d, %eax
movl %eax, 0xc(%rsp)
incl %r14d
testl %r13d, %r13d
jle 0x157e0
movq %r15, %rdi
movq %r13, %rsi
callq 0x7404
movq (%rax), %rax
movl 0x20(%rax), %ebp
movq %rbx, %rdi
movq %r12, %rsi
callq 0x7404
movq (%rax), %rax
decq %r13
decl %r14d
cmpl 0xc(%rax), %ebp
jg 0x157af
jmp 0x157e5
movl 0xc(%rsp), %r14d
movslq %r14d, %r14
movq %r14, %r13
shlq $0x20, %r13
movq 0x8(%r15), %rax
subq (%r15), %rax
movq %rax, %rcx
shrq $0x3, %rcx
movslq %ecx, %rcx
cmpq %rcx, %r14
jge 0x15870
movq %r15, %rdi
movq %r14, %rsi
callq 0x7404
movq (%rax), %rax
movl 0xc(%rax), %ebp
movq %rbx, %rdi
movq %r12, %rsi
callq 0x7404
movq (%rax), %rax
cmpl 0x20(%rax), %ebp
jge 0x15869
movq %rbx, %rdi
movq %r12, %rsi
callq 0x7404
movq (%rax), %rbp
movq %r15, %rdi
movq %r14, %rsi
callq 0x7404
movq (%rax), %rsi
movq %rbp, %rdi
callq 0x159a1
cmpl %eax, 0x4(%rsp)
jle 0x15857
movl %eax, 0x4(%rsp)
incq %r14
movabsq $0x100000000, %rax      # imm = 0x100000000
addq %rax, %r13
jmp 0x157ef
movq 0x8(%r15), %rax
subq (%r15), %rax
shrq $0x3, %rax
cmpl %eax, %r14d
jge 0x158ab
movq %rbx, %rdi
movq %r12, %rsi
callq 0x7404
movq (%rax), %r14
sarq $0x20, %r13
movq %r15, %rdi
movq %r13, %rsi
callq 0x7404
movq (%rax), %rsi
movq %r14, %rdi
callq 0x159a1
cmpl %eax, 0x4(%rsp)
jle 0x158ab
movl %eax, 0x4(%rsp)
movq 0x1f72e(%rip), %rax     # 0x34fe0
movq (%rax), %r14
movq %rbx, %rdi
movq %r12, %rsi
callq 0x7404
movq (%rax), %rax
movq (%rax), %r13
movq %rbx, %rdi
movq %r12, %rsi
callq 0x7404
movq (%rax), %rax
movl 0xc(%rax), %ebp
movq %rbx, %rdi
movq %r12, %rsi
callq 0x7404
movq (%rax), %rax
movl 0x20(%rax), %r8d
movl 0x4(%rsp), %r9d
movq %r14, %rdi
leaq 0x11841(%rip), %rsi     # 0x27139
movq %r13, %rdx
movl %ebp, %ecx
xorl %eax, %eax
callq 0x2240
movq 0x30(%rsp), %r13
movq %r13, %rdi
leaq 0x4(%rsp), %rsi
callq 0x73a8
incq %r12
jmp 0x15702
movq 0x1f6bb(%rip), %rax     # 0x34fe0
movq (%rax), %r14
movq %r12, %rdi
movq %rbp, %rsi
callq 0x7342
movq (%rax), %rdx
xorl %ebp, %ebp
movq %r14, %rdi
leaq 0x1240d(%rip), %rsi     # 0x27d4f
xorl %eax, %eax
callq 0x2240
movq 0x1f688(%rip), %rax     # 0x34fd8
movq (%rax), %rdi
callq 0x20a0
movq 0x8(%rbx), %rax
subq (%rbx), %rax
shrq $0x3, %rax
cmpl %eax, %ebp
jge 0x15978
movq %r13, %rdi
leaq 0x8(%rsp), %rsi
callq 0x73a8
incl %ebp
jmp 0x15958
movq 0x28(%rsp), %rbp
incq %rbp
movq 0x18(%rsp), %r15
movq 0x10(%rsp), %r12
jmp 0x15677
movq %r13, %rax
addq $0x38, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq