// File: /workspace/github_cpp_makefile_star2_O1/ADAPTLab[P]MuDBSCAN/clustering.cpp
// Function: get_clusters_distributed(dataHdr*)
struct result* get_clusters_distributed(DataHdr dataList)
{
	int rank, nproc, i;
	MPI_Comm_rank(MPI_COMM_WORLD, &rank);
	MPI_Comm_size(MPI_COMM_WORLD, &nproc);

	vector < vector <int > > merge_received;
	vector < vector <int > > merge_send1;
	vector < vector <int > > merge_send2;
	vector <int> init;

	merge_received.resize(nproc, init);
	merge_send1.resize(nproc, init);
	merge_send2.resize(nproc, init);

	int pid;

    for(pid = 0; pid < nproc; pid++)
	{
    	merge_received[pid].reserve(dataList->localCnt);
    	merge_send1[pid].reserve(dataList->localCnt);
		merge_send2[pid].reserve(dataList->localCnt);
	}

	vector < vector <int > >* pswap;
	vector < vector <int > >* p_cur_send;
	vector < vector <int > >* p_cur_insert;

	p_cur_send = &merge_send1;
	p_cur_insert = &merge_send2;


	int root, local_continue_to_run = 0, global_continue_to_run;
	for(i = 0; i < dataList->localCnt; i++)
	{
		// find the point containing i
		root = i;
		Data dataroot = dataList->dataClstElem + root;
		// Find highest ancestor in this node
		while(dataroot->parentProcessId == rank)
		{
			if(dataroot->parentId == root)
				break;
			root = dataroot->parentId;
			dataroot = dataList->dataClstElem + root;
		}
		
		// if the highest ancestor from the previous loop is local point
		if(dataroot->parentId == root && dataroot->parentProcessId == rank) // root is a local root
		{
			Data datai = dataList->dataClstElem + i;
			datai->parentId = root;
			dataroot->childCount = dataroot->childCount + 1;
		}
		else
		{
			(*p_cur_insert)[dataroot->parentProcessId].push_back(0); // flag: 0 means query and 1 means a reply
			(*p_cur_insert)[dataroot->parentProcessId].push_back(dataroot->parentId);
   			(*p_cur_insert)[dataroot->parentProcessId].push_back(i);
			(*p_cur_insert)[dataroot->parentProcessId].push_back(rank);
			local_continue_to_run++;
		}			
	}

	int pos, round = 0, quadraples, scount, tid, tag = 0, rtag, rsource, rcount, isend[nproc], irecv[nproc], flag;

	MPI_Request s_req_recv[nproc], s_req_send[nproc], d_req_send[nproc], d_req_recv[nproc]; // better to malloc the memory
	MPI_Status  s_stat, d_stat_send[nproc], d_stat;
	int target_point, source_point, source_pr;

	while(1)
	{
		global_continue_to_run = 0;

		MPI_Allreduce(&local_continue_to_run, &global_continue_to_run, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
		
		if(global_continue_to_run == 0)
    		break;

		pswap = p_cur_insert;
   		p_cur_insert = p_cur_send;
   		p_cur_send = pswap;

		for(tid = 0; tid < nproc; tid++)
   			(*p_cur_insert)[tid].clear();

		scount = 0;
		for(tid = 0; tid < nproc; tid++)
		{
			if(tid != rank)
			{
				isend[tid] = (*p_cur_send)[tid].size();
				if(isend[tid] > 0)
	    		{
	    			MPI_Isend(&(*p_cur_send)[tid][0], isend[tid], MPI_INT, tid, tag + 1, MPI_COMM_WORLD, &d_req_send[scount]);
	        		scount++;
	    		}	
			}
		}

		MPI_Alltoall(&isend[0], 1, MPI_INT, &irecv[0], 1, MPI_INT, MPI_COMM_WORLD);

		rcount = 0;
		for(tid = 0; tid < nproc; tid++)
		{
			if(tid != rank)
			{
				if(irecv[tid] > 0)
				{
					merge_received[tid].clear();
					merge_received[tid].assign(irecv[tid], -1);
					MPI_Irecv(&merge_received[tid][0], irecv[tid], MPI_INT, tid, tag + 1, MPI_COMM_WORLD, &d_req_recv[rcount]);
					rcount++;
				}
			}
		}

		local_continue_to_run = 0;
		Data dataroot;
		Data datatarget;
		for(tid = 0; tid < rcount; tid++)
		{
			MPI_Waitany(rcount, &d_req_recv[0], &pos, &d_stat);
		
			rtag = d_stat.MPI_TAG;
			rsource = d_stat.MPI_SOURCE;

			if(rtag == tag + 1)
			{
				quadraples = merge_received[rsource].size()/4;

				for(pid = 0; pid < quadraples; pid++)
				{
					source_pr = merge_received[rsource].back();
					merge_received[rsource].pop_back();

        			source_point = merge_received[rsource].back();
        			merge_received[rsource].pop_back();

        			target_point = merge_received[rsource].back();
        			merge_received[rsource].pop_back();
		
					flag = merge_received[rsource].back();
        			merge_received[rsource].pop_back();

					if(flag == 0)
					{					
						root = target_point;
						dataroot = dataList->dataClstElem + root;
						while(dataroot->parentProcessId == rank)
						{
							if(dataroot->parentId == root)
								break;
							root = dataroot->parentId;
							dataroot = dataList->dataClstElem + root;
						}
						if(dataroot->parentId == root && dataroot->parentProcessId == rank) // root is a local root
						{
							dataroot->childCount = dataroot->childCount + 1; // increase the child count by one
							// have to return the child about root
							
            				(*p_cur_insert)[source_pr].push_back(1);
            				(*p_cur_insert)[source_pr].push_back(source_point);
            				(*p_cur_insert)[source_pr].push_back(dataroot->parentId);
            				(*p_cur_insert)[source_pr].push_back(dataroot->parentProcessId);
							local_continue_to_run++;
						}
						else
						{
							(*p_cur_insert)[dataroot->parentProcessId].push_back(0);
							(*p_cur_insert)[dataroot->parentProcessId].push_back(dataroot->parentId);
		         			(*p_cur_insert)[dataroot->parentProcessId].push_back(source_point);
        	    			(*p_cur_insert)[dataroot->parentProcessId].push_back(source_pr);
							local_continue_to_run++;
						}
					}
					else
					{
						datatarget = dataList->dataClstElem + target_point;
						datatarget->parentId = source_point;
						datatarget->parentProcessId = source_pr;
					}
				}
			}
		}
		tag++;
		round++;

		if(scount > 0)
			MPI_Waitall(scount, &d_req_send[0], &d_stat_send[0]); // wait for all the sending operation
	}

	int final_cluster_root = 0, total_final_cluster_root = 0;
	int points_in_cluster_final = 0, total_points_in_cluster_final = 0;
	int noise = 0;

	/*FILE* debug;
	string currFile("");
	currFile = neighbourFileName + patch::to_string(rank);
	debug = fopen(currFile.c_str(), "w");
*/
	Data datai;
	for(i = 0; i < dataList->localCnt; i++)
	{

		datai = dataList->dataClstElem + i;

		if(datai->ClusterID == 0 && datai->haloPoint == FALSE) noise++;

		//fprintf(debug, "%d_%d\t%d_%d\t%d\t%d\n", datai->id, datai->actualProcessId, datai->parentId, datai->parentProcessId, datai->ClusterID, datai->core_tag);
		
		if(datai->parentId == i && datai->parentProcessId == rank && datai->childCount >= 1)
		{
			points_in_cluster_final += datai->childCount;
			final_cluster_root++;
		}

	}

	MPI_Allreduce(&final_cluster_root, &total_final_cluster_root, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);

	struct result* result = (struct result*)calloc(1, sizeof(struct result));

	result->noise = noise;
	result->clusters = total_final_cluster_root;
	result->corepoints = -1;

	merge_received.clear();
	merge_send1.clear();
	merge_send2.clear();
	init.clear();

	return result;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x118, %rsp            # imm = 0x118
movq %rdi, %r12
movq 0x851a(%rip), %rbx      # 0x16fa8
leaq -0x34(%rbp), %rsi
movq %rbx, %rdi
callq 0x33e0
leaq -0x2c(%rbp), %r14
movq %rbx, %rdi
movq %r14, %rsi
callq 0x32e0
xorl %eax, %eax
leaq -0xc0(%rbp), %rdi
movq %rax, 0x10(%rdi)
xorps %xmm0, %xmm0
movaps %xmm0, (%rdi)
movq %rax, -0xd0(%rbp)
movaps %xmm0, -0xe0(%rbp)
movq %rax, -0x70(%rbp)
movaps %xmm0, -0x80(%rbp)
leaq -0x110(%rbp), %rdx
movq %rax, 0x10(%rdx)
movaps %xmm0, (%rdx)
movslq (%r14), %rsi
callq 0xb68a
movslq -0x2c(%rbp), %rsi
leaq -0xe0(%rbp), %rdi
leaq -0x110(%rbp), %rdx
movq %rdi, -0x88(%rbp)
callq 0xb68a
movslq -0x2c(%rbp), %rsi
leaq -0x80(%rbp), %r14
leaq -0x110(%rbp), %rdx
movq %r14, %rdi
callq 0xb68a
cmpl $0x0, -0x2c(%rbp)
jle 0xeb71
xorl %ebx, %ebx
xorl %r15d, %r15d
movq -0xc0(%rbp), %rdi
addq %rbx, %rdi
movslq 0x4(%r12), %rsi
callq 0x1000e
movq -0xe0(%rbp), %rdi
addq %rbx, %rdi
movslq 0x4(%r12), %rsi
callq 0x1000e
movq -0x80(%rbp), %rdi
addq %rbx, %rdi
movslq 0x4(%r12), %rsi
callq 0x1000e
incq %r15
movslq -0x2c(%rbp), %rax
addq $0x18, %rbx
cmpq %rax, %r15
jl 0xeb28
xorl %eax, %eax
movl %eax, -0x40(%rbp)
movl %eax, -0x3c(%rbp)
movq $0x0, -0x58(%rbp)
cmpl %eax, 0x4(%r12)
movq %r12, %rdx
movq %r12, -0x68(%rbp)
jle 0xecdd
xorl %eax, %eax
leaq -0x140(%rbp), %r13
leaq -0x3c(%rbp), %r15
leaq -0x34(%rbp), %r12
movq 0x8(%rdx), %rcx
movslq %eax, %rdx
movl -0x34(%rbp), %r8d
shlq $0x6, %rdx
leaq (%rcx,%rdx), %rbx
movl 0x18(%rcx,%rdx), %esi
cmpl %r8d, %esi
setne %dil
jne 0xebe1
movl 0x14(%rbx), %r9d
cmpl %eax, %r9d
je 0xebe1
movl %r9d, %eax
movslq %r9d, %rsi
shlq $0x6, %rsi
leaq (%rcx,%rsi), %rbx
movl 0x18(%rcx,%rsi), %esi
jmp 0xebbb
testb %dil, %dil
jne 0xebf7
cmpl %eax, 0x14(%rbx)
jne 0xebf7
movl %eax, 0x14(%rcx,%rdx)
incl 0x24(%rbx)
jmp 0xecc8
movslq %esi, %rax
movq -0x80(%rbp), %rcx
leaq (%rax,%rax,2), %rax
leaq (%rcx,%rax,8), %rdi
movl $0x0, -0x140(%rbp)
movq 0x8(%rdi), %rsi
cmpq 0x10(%rdi), %rsi
je 0xec2a
movl $0x0, (%rsi)
addq $0x4, %rsi
movq %rsi, 0x8(%rdi)
jmp 0xec32
movq %r13, %rdx
callq 0x10264
leaq 0x14(%rbx), %rdx
movslq 0x18(%rbx), %rax
movq -0x80(%rbp), %rcx
leaq (%rax,%rax,2), %rax
leaq (%rcx,%rax,8), %rdi
movq 0x8(%rdi), %rsi
cmpq 0x10(%rdi), %rsi
je 0xec5e
movl (%rdx), %eax
movl %eax, (%rsi)
addq $0x4, %rsi
movq %rsi, 0x8(%rdi)
jmp 0xec63
callq 0x50ac
movslq 0x18(%rbx), %rax
movq -0x80(%rbp), %rcx
leaq (%rax,%rax,2), %rax
leaq (%rcx,%rax,8), %rdi
movq 0x8(%rdi), %rsi
cmpq 0x10(%rdi), %rsi
je 0xec8c
movl -0x3c(%rbp), %eax
movl %eax, (%rsi)
addq $0x4, %rsi
movq %rsi, 0x8(%rdi)
jmp 0xec94
movq %r15, %rdx
callq 0x50ac
movslq 0x18(%rbx), %rax
movq -0x80(%rbp), %rcx
leaq (%rax,%rax,2), %rax
leaq (%rcx,%rax,8), %rdi
movq 0x8(%rdi), %rsi
cmpq 0x10(%rdi), %rsi
je 0xecbd
movl -0x34(%rbp), %eax
movl %eax, (%rsi)
addq $0x4, %rsi
movq %rsi, 0x8(%rdi)
jmp 0xecc5
movq %r12, %rdx
callq 0x50ac
incl -0x40(%rbp)
movl -0x3c(%rbp), %eax
incl %eax
movl %eax, -0x3c(%rbp)
movq -0x68(%rbp), %rdx
cmpl 0x4(%rdx), %eax
jl 0xeba4
movq %rsp, -0x118(%rbp)
movl -0x2c(%rbp), %eax
movq %rsp, %rcx
leaq 0xf(,%rax,4), %rax
andq $-0x10, %rax
subq %rax, %rcx
movq %rcx, -0xf0(%rbp)
movq %rcx, %rsp
movl -0x2c(%rbp), %eax
movq %rsp, %rsi
leaq 0xf(,%rax,4), %rcx
andq $-0x10, %rcx
subq %rcx, %rsi
movq %rsi, -0x90(%rbp)
movq %rsi, %rsp
movq %rsp, %rsi
leaq 0xf(,%rax,8), %rcx
andq $-0x10, %rcx
subq %rcx, %rsi
movq %rsi, -0xe8(%rbp)
movq %rsi, %rsp
movq %rsp, %rsi
subq %rcx, %rsi
movq %rsi, -0xf8(%rbp)
movq %rsi, %rsp
movq %rsp, %rcx
leaq (%rax,%rax,2), %rax
leaq 0xf(,%rax,8), %rax
andq $-0x10, %rax
subq %rax, %rcx
movq %rcx, -0x120(%rbp)
movq %rcx, %rsp
movq %rdx, %r13
movq -0x88(%rbp), %rbx
movq %r14, -0x88(%rbp)
movl $0x0, -0x60(%rbp)
leaq -0x40(%rbp), %rdi
leaq -0x60(%rbp), %rsi
movl $0x1, %edx
movq 0x8236(%rip), %rcx      # 0x16fd0
movq 0x81ef(%rip), %r8       # 0x16f90
movq 0x8200(%rip), %r9       # 0x16fa8
callq 0x3350
cmpl $0x0, -0x60(%rbp)
je 0xf2af
movslq -0x2c(%rbp), %rcx
testq %rcx, %rcx
jle 0xede6
movq (%rbx), %rax
shlq $0x3, %rcx
leaq (%rcx,%rcx,2), %rcx
xorl %edx, %edx
movq (%rax,%rdx), %rsi
cmpq %rsi, 0x8(%rax,%rdx)
je 0xeddd
movq %rsi, 0x8(%rax,%rdx)
addq $0x18, %rdx
cmpq %rdx, %rcx
jne 0xedcd
movq %rbx, -0x48(%rbp)
cmpl $0x0, -0x2c(%rbp)
jle 0xee7d
movq -0x58(%rbp), %rax
leal 0x1(%rax), %r15d
xorl %r12d, %r12d
movl $0x2, %ebx
xorl %r14d, %r14d
movl -0x34(%rbp), %eax
cmpq %rax, %r12
je 0xee6b
movq -0x88(%rbp), %rax
movq (%rax), %rax
movq -0x8(%rax,%rbx,4), %rdi
movq (%rax,%rbx,4), %rsi
subq %rdi, %rsi
shrq $0x2, %rsi
movq -0xf0(%rbp), %rax
movl %esi, (%rax,%r12,4)
testl %esi, %esi
jle 0xee6b
movslq %r14d, %rax
movq -0xe8(%rbp), %rcx
leaq (%rcx,%rax,8), %rax
subq $0x8, %rsp
movq 0x817f(%rip), %rdx      # 0x16fd0
movl %r12d, %ecx
movl %r15d, %r8d
movq 0x814a(%rip), %r9       # 0x16fa8
pushq %rax
callq 0x3130
addq $0x10, %rsp
incl %r14d
incq %r12
movslq -0x2c(%rbp), %rax
addq $0x6, %rbx
cmpq %rax, %r12
jl 0xee07
jmp 0xee80
xorl %r14d, %r14d
subq $0x8, %rsp
movq -0xf0(%rbp), %rdi
movl $0x1, %esi
movq 0x8139(%rip), %rdx      # 0x16fd0
movq -0x90(%rbp), %rcx
movl $0x1, %r8d
movq %rdx, %r9
pushq 0x80fb(%rip)            # 0x16fa8
callq 0x3170
addq $0x10, %rsp
cmpl $0x0, -0x2c(%rbp)
jle 0xef7c
movq -0x58(%rbp), %rax
incl %eax
movl %eax, -0x50(%rbp)
xorl %ebx, %ebx
xorl %r12d, %r12d
xorl %edi, %edi
movl -0x34(%rbp), %eax
cmpq %rax, %r12
je 0xef66
movq -0x90(%rbp), %rax
movslq (%rax,%r12,4), %rsi
testq %rsi, %rsi
jle 0xef66
movl %edi, %r15d
movq -0xc0(%rbp), %rcx
leaq (%rcx,%rbx), %rdi
movq (%rcx,%rbx), %rax
cmpq %rax, 0x8(%rcx,%rbx)
je 0xef09
movq %rax, 0x8(%rdi)
movl $0xffffffff, -0x30(%rbp) # imm = 0xFFFFFFFF
leaq -0x30(%rbp), %rdx
callq 0x100e8
movq -0xc0(%rbp), %rax
movq (%rax,%rbx), %rdi
movq -0x90(%rbp), %rax
movl (%rax,%r12,4), %esi
movslq %r15d, %rax
movq -0xf8(%rbp), %rcx
leaq (%rcx,%rax,8), %rax
subq $0x8, %rsp
movq 0x8088(%rip), %rdx      # 0x16fd0
movl %r12d, %ecx
movl -0x50(%rbp), %r8d
movq 0x8052(%rip), %r9       # 0x16fa8
pushq %rax
callq 0x33c0
addq $0x10, %rsp
incl %r15d
movl %r15d, %edi
incq %r12
movslq -0x2c(%rbp), %rax
addq $0x18, %rbx
cmpq %rax, %r12
jl 0xeed0
jmp 0xef7e
xorl %edi, %edi
movl $0x0, -0x40(%rbp)
testl %edi, %edi
jle 0xf278
movq -0x58(%rbp), %rax
incl %eax
movl %eax, -0x9c(%rbp)
xorl %ebx, %ebx
movl %r14d, -0x98(%rbp)
movl %edi, -0x94(%rbp)
movq -0xf8(%rbp), %rsi
leaq -0x124(%rbp), %rdx
leaq -0x140(%rbp), %rcx
callq 0x3390
movl %ebx, -0x50(%rbp)
movl -0x9c(%rbp), %eax
cmpl %eax, -0x13c(%rbp)
jne 0xf25a
movslq -0x140(%rbp), %rax
movq -0xc0(%rbp), %rcx
leaq (%rax,%rax,2), %rbx
movq 0x8(%rcx,%rbx,8), %r14
subq (%rcx,%rbx,8), %r14
shrq $0x4, %r14
testl %r14d, %r14d
jle 0xf25a
xorl %r13d, %r13d
movq -0xc0(%rbp), %rdx
movq 0x8(%rdx,%rbx,8), %rsi
leaq -0x4(%rsi), %rcx
movslq -0x4(%rsi), %rax
movl %eax, -0x38(%rbp)
movq %rcx, 0x8(%rdx,%rbx,8)
leaq -0x8(%rsi), %rdi
movl -0x8(%rsi), %ecx
movl %ecx, -0x4c(%rbp)
movq %rdi, 0x8(%rdx,%rbx,8)
leaq -0xc(%rsi), %rdi
movl -0xc(%rsi), %r9d
movq %rdi, 0x8(%rdx,%rbx,8)
leaq -0x10(%rsi), %rdi
cmpl $0x0, -0x10(%rsi)
movq %rdi, 0x8(%rdx,%rbx,8)
je 0xf068
movslq %r9d, %rax
movq -0x68(%rbp), %rdx
movq 0x8(%rdx), %rdx
shlq $0x6, %rax
movl %ecx, 0x14(%rdx,%rax)
movl -0x38(%rbp), %ecx
movl %ecx, 0x18(%rdx,%rax)
jmp 0xf24e
movq -0x68(%rbp), %rcx
movq 0x8(%rcx), %r8
movl -0x34(%rbp), %edi
movl %r9d, %ecx
movslq %r9d, %rsi
shlq $0x6, %rsi
leaq (%r8,%rsi), %rdx
movslq 0x18(%r8,%rsi), %rsi
cmpl %edi, %esi
jne 0xf093
movl 0x14(%rdx), %r9d
cmpl %ecx, %r9d
jne 0xf073
leaq 0x18(%rdx), %r15
leaq 0x14(%rdx), %r12
cmpl %edi, %esi
jne 0xf0d7
cmpl %ecx, 0x14(%rdx)
jne 0xf0d7
incl 0x24(%rdx)
movq -0x48(%rbp), %rcx
movq (%rcx), %rcx
leaq (%rax,%rax,2), %rax
leaq (%rcx,%rax,8), %rdi
movl $0x1, -0x30(%rbp)
movq 0x8(%rdi), %rsi
cmpq 0x10(%rdi), %rsi
je 0xf13c
movl $0x1, (%rsi)
addq $0x4, %rsi
movq %rsi, 0x8(%rdi)
jmp 0xf145
movq -0x48(%rbp), %rax
movq (%rax), %rax
leaq (%rsi,%rsi,2), %rcx
leaq (%rax,%rcx,8), %rdi
movl $0x0, -0x30(%rbp)
movq 0x8(%rdi), %rsi
cmpq 0x10(%rdi), %rsi
je 0xf107
movl $0x0, (%rsi)
addq $0x4, %rsi
movq %rsi, 0x8(%rdi)
jmp 0xf110
leaq -0x30(%rbp), %rdx
callq 0x10264
movslq (%r15), %rax
movq -0x48(%rbp), %rcx
movq (%rcx), %rcx
leaq (%rax,%rax,2), %rax
leaq (%rcx,%rax,8), %rdi
movq 0x8(%rdi), %rsi
cmpq 0x10(%rdi), %rsi
je 0xf171
movl (%r12), %eax
movl %eax, (%rsi)
addq $0x4, %rsi
movq %rsi, 0x8(%rdi)
jmp 0xf179
leaq -0x30(%rbp), %rdx
callq 0x10264
movslq -0x38(%rbp), %rax
movq -0x48(%rbp), %rcx
movq (%rcx), %rcx
leaq (%rax,%rax,2), %rax
leaq (%rcx,%rax,8), %rdi
movq 0x8(%rdi), %rsi
cmpq 0x10(%rdi), %rsi
je 0xf1a4
movl -0x4c(%rbp), %eax
movl %eax, (%rsi)
addq $0x4, %rsi
movq %rsi, 0x8(%rdi)
jmp 0xf1ad
movq %r12, %rdx
callq 0x50ac
movslq (%r15), %rax
movq -0x48(%rbp), %rcx
movq (%rcx), %rcx
leaq (%rax,%rax,2), %rax
leaq (%rcx,%rax,8), %rdi
movq 0x8(%rdi), %rsi
cmpq 0x10(%rdi), %rsi
je 0xf1da
movl -0x4c(%rbp), %eax
movl %eax, (%rsi)
addq $0x4, %rsi
movq %rsi, 0x8(%rdi)
jmp 0xf1e3
leaq -0x4c(%rbp), %rdx
callq 0x50ac
movslq -0x38(%rbp), %rax
movq -0x48(%rbp), %rcx
movq (%rcx), %rcx
leaq (%rax,%rax,2), %rax
leaq (%rcx,%rax,8), %rdi
movq 0x8(%rdi), %rsi
cmpq 0x10(%rdi), %rsi
je 0xf204
movl (%r12), %eax
movl %eax, (%rsi)
addq $0x4, %rsi
movq %rsi, 0x8(%rdi)
jmp 0xf20c
leaq -0x4c(%rbp), %rdx
callq 0x50ac
movslq (%r15), %rax
movq -0x48(%rbp), %rcx
movq (%rcx), %rcx
leaq (%rax,%rax,2), %rax
leaq (%rcx,%rax,8), %rdi
movq 0x8(%rdi), %rsi
cmpq 0x10(%rdi), %rsi
je 0xf238
movl -0x38(%rbp), %eax
jmp 0xf22c
movq %r12, %rdx
callq 0x50ac
movslq -0x38(%rbp), %rax
movq -0x48(%rbp), %rcx
movq (%rcx), %rcx
leaq (%rax,%rax,2), %rax
leaq (%rcx,%rax,8), %rdi
movq 0x8(%rdi), %rsi
cmpq 0x10(%rdi), %rsi
je 0xf243
movl (%r15), %eax
movl %eax, (%rsi)
addq $0x4, %rsi
movq %rsi, 0x8(%rdi)
jmp 0xf24b
leaq -0x38(%rbp), %rdx
callq 0x50ac
jmp 0xf24b
movq %r15, %rdx
callq 0x50ac
incl -0x40(%rbp)
incl %r13d
cmpl %r14d, %r13d
jne 0xf002
movl -0x50(%rbp), %ebx
incl %ebx
movl -0x94(%rbp), %edi
cmpl %edi, %ebx
movq -0x68(%rbp), %r13
movl -0x98(%rbp), %r14d
jne 0xefa8
movq -0x58(%rbp), %rax
incl %eax
movq %rax, -0x58(%rbp)
movq -0x48(%rbp), %rbx
movl %r14d, %edi
movq %rbx, %r14
testl %edi, %edi
jle 0xed71
movq -0xe8(%rbp), %rsi
movq -0x120(%rbp), %rdx
callq 0x3320
movq %rbx, %r14
jmp 0xed71
xorl %r14d, %r14d
movl %r14d, -0x30(%rbp)
movl %r14d, -0x5c(%rbp)
movslq 0x4(%r13), %rax
movl %r14d, -0x3c(%rbp)
testq %rax, %rax
jle 0xf30e
movq 0x8(%r13), %rcx
movl -0x34(%rbp), %edx
addq $0x8, %rcx
xorl %esi, %esi
xorl %r14d, %r14d
xorl %edi, %edi
cmpl $0x0, 0x28(%rcx)
jne 0xf2e6
cmpl $0x1, (%rcx)
adcl $0x0, %r14d
movl 0xc(%rcx), %r8d
cmpq %r8, %rsi
jne 0xf2ff
cmpl %edx, 0x10(%rcx)
jne 0xf2ff
cmpl $0x0, 0x1c(%rcx)
jle 0xf2ff
incl %edi
movl %edi, -0x30(%rbp)
incq %rsi
movl %esi, -0x3c(%rbp)
addq $0x40, %rcx
cmpq %rsi, %rax
jne 0xf2d9
movq 0x7cbb(%rip), %rcx      # 0x16fd0
movq 0x7c74(%rip), %r8       # 0x16f90
movq 0x7c85(%rip), %r9       # 0x16fa8
leaq -0x30(%rbp), %rdi
leaq -0x5c(%rbp), %rsi
movl $0x1, %edx
callq 0x3350
movl $0x1, %edi
movl $0xc, %esi
callq 0x31b0
movq %rax, %rbx
movl %r14d, (%rax)
movl -0x5c(%rbp), %eax
movl %eax, 0x4(%rbx)
movl $0xffffffff, 0x8(%rbx)  # imm = 0xFFFFFFFF
movq -0xc0(%rbp), %r14
movq -0xb8(%rbp), %r15
cmpq %r14, %r15
je 0xf38b
movq %r14, %r12
movq (%r12), %rdi
testq %rdi, %rdi
je 0xf37b
callq 0x3270
addq $0x18, %r12
cmpq %r15, %r12
jne 0xf36d
movq %r14, -0xb8(%rbp)
movq -0xe0(%rbp), %r14
movq -0xd8(%rbp), %r15
cmpq %r14, %r15
je 0xf3bf
movq %r14, %r12
movq (%r12), %rdi
testq %rdi, %rdi
je 0xf3af
callq 0x3270
addq $0x18, %r12
cmpq %r15, %r12
jne 0xf3a1
movq %r14, -0xd8(%rbp)
movq -0x80(%rbp), %r14
movq -0x78(%rbp), %r15
cmpq %r14, %r15
je 0xf3ea
movq %r14, %r12
movq (%r12), %rdi
testq %rdi, %rdi
je 0xf3dd
callq 0x3270
addq $0x18, %r12
cmpq %r15, %r12
jne 0xf3cf
movq %r14, -0x78(%rbp)
movq -0x110(%rbp), %rax
cmpq %rax, -0x108(%rbp)
je 0xf401
movq %rax, -0x108(%rbp)
movq -0x118(%rbp), %rsp
movq -0x110(%rbp), %rdi
testq %rdi, %rdi
je 0xf419
callq 0x3270
leaq -0x80(%rbp), %rdi
callq 0xb70c
leaq -0xe0(%rbp), %rdi
callq 0xb70c
leaq -0xc0(%rbp), %rdi
callq 0xb70c
movq %rbx, %rax
leaq -0x28(%rbp), %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0xf466
jmp 0xf466
jmp 0xf466
jmp 0xf466
jmp 0xf466
jmp 0xf466
jmp 0xf466
jmp 0xf466
jmp 0xf466
jmp 0xf466
jmp 0xf466
jmp 0xf466
jmp 0xf466
movq %rax, %rbx
movq -0x110(%rbp), %rdi
testq %rdi, %rdi
je 0xf47a
callq 0x3270
leaq -0x80(%rbp), %rdi
callq 0xb70c
leaq -0xe0(%rbp), %rdi
callq 0xb70c
leaq -0xc0(%rbp), %rdi
callq 0xb70c
movq %rbx, %rdi
callq 0x34c0