// File: 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
subq $0x200, %rsp            # imm = 0x200
movq %rdi, -0x8(%rbp)
movq 0x113d2(%rip), %rdi     # 0x37fa8
movq %rdi, -0x1c8(%rbp)
leaq -0xc(%rbp), %rsi
callq 0x99e0
movq -0x1c8(%rbp), %rdi
leaq -0x10(%rbp), %rsi
callq 0x9790
leaq -0x30(%rbp), %rdi
movq %rdi, -0x1c0(%rbp)
callq 0x1c460
leaq -0x48(%rbp), %rdi
callq 0x1c460
leaq -0x60(%rbp), %rdi
callq 0x1c460
leaq -0x78(%rbp), %rdi
movq %rdi, -0x1b8(%rbp)
callq 0x1c260
movq -0x1c0(%rbp), %rdi
movq -0x1b8(%rbp), %rdx
movslq -0x10(%rbp), %rsi
callq 0x1c480
jmp 0x26c41
movslq -0x10(%rbp), %rsi
leaq -0x48(%rbp), %rdi
leaq -0x78(%rbp), %rdx
callq 0x1c480
jmp 0x26c54
movslq -0x10(%rbp), %rsi
leaq -0x60(%rbp), %rdi
leaq -0x78(%rbp), %rdx
callq 0x1c480
jmp 0x26c67
movl $0x0, -0x88(%rbp)
movl -0x88(%rbp), %eax
cmpl -0x10(%rbp), %eax
jge 0x26d34
movslq -0x88(%rbp), %rsi
leaq -0x30(%rbp), %rdi
callq 0x11a90
movq %rax, %rdi
movq -0x8(%rbp), %rax
movslq 0x4(%rax), %rsi
callq 0x28c90
jmp 0x26ca2
movslq -0x88(%rbp), %rsi
leaq -0x48(%rbp), %rdi
callq 0x11a90
movq %rax, %rdi
movq -0x8(%rbp), %rax
movslq 0x4(%rax), %rsi
callq 0x28c90
jmp 0x26cc4
movslq -0x88(%rbp), %rsi
leaq -0x60(%rbp), %rdi
callq 0x11a90
movq %rax, %rdi
movq -0x8(%rbp), %rax
movslq 0x4(%rax), %rsi
callq 0x28c90
jmp 0x26ce6
jmp 0x26ce8
movl -0x88(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x88(%rbp)
jmp 0x26c71
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x80(%rbp)
movl %eax, -0x84(%rbp)
leaq -0x78(%rbp), %rdi
callq 0x1c350
leaq -0x60(%rbp), %rdi
callq 0x1c570
leaq -0x48(%rbp), %rdi
callq 0x1c570
leaq -0x30(%rbp), %rdi
callq 0x1c570
jmp 0x279b8
leaq -0x48(%rbp), %rax
movq %rax, -0x98(%rbp)
leaq -0x60(%rbp), %rax
movq %rax, -0xa0(%rbp)
movl $0x0, -0xa8(%rbp)
movl $0x0, -0x14(%rbp)
movl -0x14(%rbp), %eax
movq -0x8(%rbp), %rcx
cmpl 0x4(%rcx), %eax
jge 0x26f11
movl -0x14(%rbp), %eax
movl %eax, -0xa4(%rbp)
movq -0x8(%rbp), %rax
movq 0x8(%rax), %rax
movslq -0xa4(%rbp), %rcx
shlq $0x6, %rcx
addq %rcx, %rax
movq %rax, -0xb8(%rbp)
movq -0xb8(%rbp), %rax
movl 0x18(%rax), %eax
cmpl -0xc(%rbp), %eax
jne 0x26de3
movq -0xb8(%rbp), %rax
movl 0x14(%rax), %eax
cmpl -0xa4(%rbp), %eax
jne 0x26db4
jmp 0x26de3
movq -0xb8(%rbp), %rax
movl 0x14(%rax), %eax
movl %eax, -0xa4(%rbp)
movq -0x8(%rbp), %rax
movq 0x8(%rax), %rax
movslq -0xa4(%rbp), %rcx
shlq $0x6, %rcx
addq %rcx, %rax
movq %rax, -0xb8(%rbp)
jmp 0x26d91
movq -0xb8(%rbp), %rax
movl 0x14(%rax), %eax
cmpl -0xa4(%rbp), %eax
jne 0x26e4a
movq -0xb8(%rbp), %rax
movl 0x18(%rax), %eax
cmpl -0xc(%rbp), %eax
jne 0x26e4a
movq -0x8(%rbp), %rax
movq 0x8(%rax), %rax
movslq -0x14(%rbp), %rcx
shlq $0x6, %rcx
addq %rcx, %rax
movq %rax, -0xc0(%rbp)
movl -0xa4(%rbp), %ecx
movq -0xc0(%rbp), %rax
movl %ecx, 0x14(%rax)
movq -0xb8(%rbp), %rax
movl 0x24(%rax), %ecx
addl $0x1, %ecx
movq -0xb8(%rbp), %rax
movl %ecx, 0x24(%rax)
jmp 0x26f01
movq -0xa0(%rbp), %rdi
movq -0xb8(%rbp), %rax
movslq 0x18(%rax), %rsi
callq 0x11a90
movq %rax, %rdi
movl $0x0, -0xc4(%rbp)
leaq -0xc4(%rbp), %rsi
callq 0x28e30
jmp 0x26e7c
movq -0xa0(%rbp), %rdi
movq -0xb8(%rbp), %rax
movslq 0x18(%rax), %rsi
callq 0x11a90
movq %rax, %rdi
movq -0xb8(%rbp), %rsi
addq $0x14, %rsi
callq 0x11ab0
jmp 0x26ea8
movq -0xa0(%rbp), %rdi
movq -0xb8(%rbp), %rax
movslq 0x18(%rax), %rsi
callq 0x11a90
movq %rax, %rdi
leaq -0x14(%rbp), %rsi
callq 0x11ab0
jmp 0x26ecd
movq -0xa0(%rbp), %rdi
movq -0xb8(%rbp), %rax
movslq 0x18(%rax), %rsi
callq 0x11a90
movq %rax, %rdi
leaq -0xc(%rbp), %rsi
callq 0x11ab0
jmp 0x26ef2
movl -0xa8(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xa8(%rbp)
jmp 0x26f03
movl -0x14(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x14(%rbp)
jmp 0x26d5b
movl $0x0, -0xcc(%rbp)
movl $0x0, -0xdc(%rbp)
movl -0x10(%rbp), %eax
movq %rsp, %rcx
movq %rcx, -0xf0(%rbp)
leaq 0xf(,%rax,4), %rdx
andq $-0x10, %rdx
movq %rsp, %rcx
subq %rdx, %rcx
movq %rcx, -0x1f0(%rbp)
movq %rcx, %rsp
movq %rax, -0xf8(%rbp)
movl -0x10(%rbp), %eax
leaq 0xf(,%rax,4), %rdx
andq $-0x10, %rdx
movq %rsp, %rcx
subq %rdx, %rcx
movq %rcx, -0x1e8(%rbp)
movq %rcx, %rsp
movq %rax, -0x100(%rbp)
movl -0x10(%rbp), %eax
leaq 0xf(,%rax,8), %rdx
andq $-0x10, %rdx
movq %rsp, %rcx
subq %rdx, %rcx
movq %rcx, %rsp
movq %rax, -0x110(%rbp)
movl -0x10(%rbp), %eax
leaq 0xf(,%rax,8), %rdx
andq $-0x10, %rdx
movq %rsp, %rcx
subq %rdx, %rcx
movq %rcx, %rsp
movq %rax, -0x118(%rbp)
movl -0x10(%rbp), %eax
leaq 0xf(,%rax,8), %rdx
andq $-0x10, %rdx
movq %rsp, %rcx
subq %rdx, %rcx
movq %rcx, -0x1e0(%rbp)
movq %rcx, %rsp
movq %rax, -0x120(%rbp)
movl -0x10(%rbp), %eax
leaq 0xf(,%rax,8), %rdx
andq $-0x10, %rdx
movq %rsp, %rcx
subq %rdx, %rcx
movq %rcx, -0x1d8(%rbp)
movq %rcx, %rsp
movq %rax, -0x128(%rbp)
movl -0x10(%rbp), %eax
leaq (%rax,%rax,2), %rcx
leaq 0xf(,%rcx,8), %rdx
andq $-0x10, %rdx
movq %rsp, %rcx
subq %rdx, %rcx
movq %rcx, -0x1d0(%rbp)
movq %rcx, %rsp
movq %rax, -0x148(%rbp)
jmp 0x27031
movl $0x0, -0xac(%rbp)
movq 0x10f8e(%rip), %rcx     # 0x37fd0
movq 0x10f3f(%rip), %r8      # 0x37f88
movq 0x10f58(%rip), %r9      # 0x37fa8
leaq -0xa8(%rbp), %rdi
leaq -0xac(%rbp), %rsi
movl $0x1, %edx
callq 0x9840
jmp 0x2706a
cmpl $0x0, -0xac(%rbp)
jne 0x27078
jmp 0x277ee
movq -0xa0(%rbp), %rax
movq %rax, -0x90(%rbp)
movq -0x98(%rbp), %rax
movq %rax, -0xa0(%rbp)
movq -0x90(%rbp), %rax
movq %rax, -0x98(%rbp)
movl $0x0, -0xd8(%rbp)
movl -0xd8(%rbp), %eax
cmpl -0x10(%rbp), %eax
jge 0x270e3
movq -0xa0(%rbp), %rdi
movslq -0xd8(%rbp), %rsi
callq 0x11a90
movq %rax, %rdi
callq 0x1c0e0
movl -0xd8(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xd8(%rbp)
jmp 0x270ac
movl $0x0, -0xd4(%rbp)
movl $0x0, -0xd8(%rbp)
movl -0xd8(%rbp), %eax
cmpl -0x10(%rbp), %eax
jge 0x271f2
movl -0xd8(%rbp), %eax
cmpl -0xc(%rbp), %eax
je 0x271dc
movq -0x98(%rbp), %rdi
movslq -0xd8(%rbp), %rsi
callq 0x11a90
movq %rax, %rdi
callq 0x11f90
movq %rax, %rcx
movq -0x1f0(%rbp), %rax
movl %ecx, %edx
movslq -0xd8(%rbp), %rcx
movl %edx, (%rax,%rcx,4)
movslq -0xd8(%rbp), %rcx
cmpl $0x0, (%rax,%rcx,4)
jle 0x271da
movq -0x98(%rbp), %rdi
movslq -0xd8(%rbp), %rsi
callq 0x11a90
movq %rax, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x1c1b0
movq -0x1f0(%rbp), %rdx
movq %rax, %rdi
movq -0x1e0(%rbp), %rax
movslq -0xd8(%rbp), %rsi
movl %esi, %ecx
movl (%rdx,%rsi,4), %esi
movl -0xdc(%rbp), %r8d
incl %r8d
movslq -0xd4(%rbp), %rdx
leaq (%rax,%rdx,8), %rdx
subq $0x10, %rsp
movq %rsp, %rax
movq %rdx, (%rax)
movq 0x10e17(%rip), %rdx     # 0x37fd0
movq 0x10de8(%rip), %r9      # 0x37fa8
callq 0x9290
addq $0x10, %rsp
jmp 0x271cb
movl -0xd4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xd4(%rbp)
jmp 0x271dc
jmp 0x271de
movl -0xd8(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xd8(%rbp)
jmp 0x270f7
movq -0x1e8(%rbp), %rcx
movq -0x1f0(%rbp), %rdi
subq $0x10, %rsp
movq 0x10d9d(%rip), %rdx     # 0x37fa8
movq %rsp, %rax
movq %rdx, (%rax)
movq 0x10db8(%rip), %r9      # 0x37fd0
movl $0x1, %r8d
movl %r8d, %esi
movq %r9, %rdx
callq 0x92f0
addq $0x10, %rsp
jmp 0x2722f
movl $0x0, -0xe8(%rbp)
movl $0x0, -0xd8(%rbp)
movl -0xd8(%rbp), %eax
cmpl -0x10(%rbp), %eax
jge 0x27370
movl -0xd8(%rbp), %eax
cmpl -0xc(%rbp), %eax
je 0x2735a
movq -0x1e8(%rbp), %rax
movslq -0xd8(%rbp), %rcx
cmpl $0x0, (%rax,%rcx,4)
jle 0x27358
movslq -0xd8(%rbp), %rsi
leaq -0x30(%rbp), %rdi
movq %rdi, -0x1f8(%rbp)
callq 0x11a90
movq %rax, %rdi
callq 0x1c0e0
movq -0x1f8(%rbp), %rdi
movslq -0xd8(%rbp), %rsi
callq 0x11a90
movq %rax, %rdi
movq -0x1e8(%rbp), %rax
movslq -0xd8(%rbp), %rcx
movslq (%rax,%rcx,4), %rsi
movl $0xffffffff, -0x170(%rbp) # imm = 0xFFFFFFFF
leaq -0x170(%rbp), %rdx
callq 0x28d90
jmp 0x272d8
movslq -0xd8(%rbp), %rsi
leaq -0x30(%rbp), %rdi
callq 0x11a90
movq %rax, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x1c1b0
movq -0x1e8(%rbp), %rdx
movq %rax, %rdi
movq -0x1d8(%rbp), %rax
movslq -0xd8(%rbp), %rsi
movl %esi, %ecx
movl (%rdx,%rsi,4), %esi
movl -0xdc(%rbp), %r8d
incl %r8d
movslq -0xe8(%rbp), %rdx
leaq (%rax,%rdx,8), %rdx
subq $0x10, %rsp
movq %rsp, %rax
movq %rdx, (%rax)
movq 0x10c99(%rip), %rdx     # 0x37fd0
movq 0x10c6a(%rip), %r9      # 0x37fa8
callq 0x9970
addq $0x10, %rsp
jmp 0x27349
movl -0xe8(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xe8(%rbp)
jmp 0x2735a
jmp 0x2735c
movl -0xd8(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xd8(%rbp)
jmp 0x27243
movl $0x0, -0xa8(%rbp)
movl $0x0, -0xd8(%rbp)
movl -0xd8(%rbp), %eax
cmpl -0xe8(%rbp), %eax
jge 0x277a5
movq -0x1d8(%rbp), %rsi
movl -0xe8(%rbp), %edi
leaq -0xc8(%rbp), %rdx
leaq -0x160(%rbp), %rcx
callq 0x9900
jmp 0x273b8
movl -0x15c(%rbp), %eax
movl %eax, -0xe0(%rbp)
movl -0x160(%rbp), %eax
movl %eax, -0xe4(%rbp)
movl -0xe0(%rbp), %eax
movl -0xdc(%rbp), %ecx
addl $0x1, %ecx
cmpl %ecx, %eax
jne 0x2778f
movslq -0xe4(%rbp), %rsi
leaq -0x30(%rbp), %rdi
callq 0x11a90
movq %rax, %rdi
callq 0x11f90
shrq $0x2, %rax
movl %eax, -0xd0(%rbp)
movl $0x0, -0x88(%rbp)
movl -0x88(%rbp), %eax
cmpl -0xd0(%rbp), %eax
jge 0x2778d
movslq -0xe4(%rbp), %rsi
leaq -0x30(%rbp), %rdi
callq 0x11a90
movq %rax, %rdi
callq 0x28dc0
movl (%rax), %eax
movl %eax, -0x16c(%rbp)
movslq -0xe4(%rbp), %rsi
leaq -0x30(%rbp), %rdi
callq 0x11a90
movq %rax, %rdi
callq 0x28e00
movslq -0xe4(%rbp), %rsi
leaq -0x30(%rbp), %rdi
callq 0x11a90
movq %rax, %rdi
callq 0x28dc0
movl (%rax), %eax
movl %eax, -0x168(%rbp)
movslq -0xe4(%rbp), %rsi
leaq -0x30(%rbp), %rdi
callq 0x11a90
movq %rax, %rdi
callq 0x28e00
movslq -0xe4(%rbp), %rsi
leaq -0x30(%rbp), %rdi
callq 0x11a90
movq %rax, %rdi
callq 0x28dc0
movl (%rax), %eax
movl %eax, -0x164(%rbp)
movslq -0xe4(%rbp), %rsi
leaq -0x30(%rbp), %rdi
callq 0x11a90
movq %rax, %rdi
callq 0x28e00
movslq -0xe4(%rbp), %rsi
leaq -0x30(%rbp), %rdi
callq 0x11a90
movq %rax, %rdi
callq 0x28dc0
movl (%rax), %eax
movl %eax, -0x104(%rbp)
movslq -0xe4(%rbp), %rsi
leaq -0x30(%rbp), %rdi
callq 0x11a90
movq %rax, %rdi
callq 0x28e00
cmpl $0x0, -0x104(%rbp)
jne 0x2773a
movl -0x164(%rbp), %eax
movl %eax, -0xa4(%rbp)
movq -0x8(%rbp), %rax
movq 0x8(%rax), %rax
movslq -0xa4(%rbp), %rcx
shlq $0x6, %rcx
addq %rcx, %rax
movq %rax, -0x178(%rbp)
movq -0x178(%rbp), %rax
movl 0x18(%rax), %eax
cmpl -0xc(%rbp), %eax
jne 0x2758d
movq -0x178(%rbp), %rax
movl 0x14(%rax), %eax
cmpl -0xa4(%rbp), %eax
jne 0x2755e
jmp 0x2758d
movq -0x178(%rbp), %rax
movl 0x14(%rax), %eax
movl %eax, -0xa4(%rbp)
movq -0x8(%rbp), %rax
movq 0x8(%rax), %rax
movslq -0xa4(%rbp), %rcx
shlq $0x6, %rcx
addq %rcx, %rax
movq %rax, -0x178(%rbp)
jmp 0x2753b
movq -0x178(%rbp), %rax
movl 0x14(%rax), %eax
cmpl -0xa4(%rbp), %eax
jne 0x2767b
movq -0x178(%rbp), %rax
movl 0x18(%rax), %eax
cmpl -0xc(%rbp), %eax
jne 0x2767b
movq -0x178(%rbp), %rax
movl 0x24(%rax), %ecx
incl %ecx
movl %ecx, 0x24(%rax)
movq -0xa0(%rbp), %rdi
movslq -0x16c(%rbp), %rsi
callq 0x11a90
movq %rax, %rdi
movl $0x1, -0x184(%rbp)
leaq -0x184(%rbp), %rsi
callq 0x28e30
jmp 0x275f3
movq -0xa0(%rbp), %rdi
movslq -0x16c(%rbp), %rsi
callq 0x11a90
movq %rax, %rdi
leaq -0x168(%rbp), %rsi
callq 0x11ab0
jmp 0x27617
movq -0xa0(%rbp), %rdi
movslq -0x16c(%rbp), %rsi
callq 0x11a90
movq %rax, %rdi
movq -0x178(%rbp), %rsi
addq $0x14, %rsi
callq 0x11ab0
jmp 0x2763f
movq -0xa0(%rbp), %rdi
movslq -0x16c(%rbp), %rsi
callq 0x11a90
movq %rax, %rdi
movq -0x178(%rbp), %rsi
addq $0x18, %rsi
callq 0x11ab0
jmp 0x27667
movl -0xa8(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xa8(%rbp)
jmp 0x27738
movq -0xa0(%rbp), %rdi
movq -0x178(%rbp), %rax
movslq 0x18(%rax), %rsi
callq 0x11a90
movq %rax, %rdi
movl $0x0, -0x188(%rbp)
leaq -0x188(%rbp), %rsi
callq 0x28e30
jmp 0x276ad
movq -0xa0(%rbp), %rdi
movq -0x178(%rbp), %rax
movslq 0x18(%rax), %rsi
callq 0x11a90
movq %rax, %rdi
movq -0x178(%rbp), %rsi
addq $0x14, %rsi
callq 0x11ab0
jmp 0x276d9
movq -0xa0(%rbp), %rdi
movq -0x178(%rbp), %rax
movslq 0x18(%rax), %rsi
callq 0x11a90
movq %rax, %rdi
leaq -0x168(%rbp), %rsi
callq 0x11ab0
jmp 0x27701
movq -0xa0(%rbp), %rdi
movq -0x178(%rbp), %rax
movslq 0x18(%rax), %rsi
callq 0x11a90
movq %rax, %rdi
leaq -0x16c(%rbp), %rsi
callq 0x11ab0
jmp 0x27729
movl -0xa8(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xa8(%rbp)
jmp 0x27777
movq -0x8(%rbp), %rax
movq 0x8(%rax), %rax
movslq -0x164(%rbp), %rcx
shlq $0x6, %rcx
addq %rcx, %rax
movq %rax, -0x180(%rbp)
movl -0x168(%rbp), %ecx
movq -0x180(%rbp), %rax
movl %ecx, 0x14(%rax)
movl -0x16c(%rbp), %ecx
movq -0x180(%rbp), %rax
movl %ecx, 0x18(%rax)
jmp 0x27779
movl -0x88(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x88(%rbp)
jmp 0x27413
jmp 0x2778f
jmp 0x27791
movl -0xd8(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xd8(%rbp)
jmp 0x27384
movl -0xdc(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xdc(%rbp)
movl -0xcc(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xcc(%rbp)
cmpl $0x0, -0xd4(%rbp)
jle 0x277e9
movq -0x1d0(%rbp), %rdx
movq -0x1e0(%rbp), %rsi
movl -0xd4(%rbp), %edi
callq 0x97e0
jmp 0x277e7
jmp 0x277e9
jmp 0x2702f
movl $0x0, -0x18c(%rbp)
movl $0x0, -0x190(%rbp)
movl $0x0, -0x194(%rbp)
movl $0x0, -0x198(%rbp)
movl $0x0, -0x19c(%rbp)
movl $0x0, -0x14(%rbp)
movl -0x14(%rbp), %eax
movq -0x8(%rbp), %rcx
cmpl 0x4(%rcx), %eax
jge 0x278da
movq -0x8(%rbp), %rax
movq 0x8(%rax), %rax
movslq -0x14(%rbp), %rcx
shlq $0x6, %rcx
addq %rcx, %rax
movq %rax, -0x1a8(%rbp)
movq -0x1a8(%rbp), %rax
cmpl $0x0, 0x30(%rax)
jne 0x2787a
movq -0x1a8(%rbp), %rax
cmpl $0x0, 0x8(%rax)
jne 0x2787a
movl -0x19c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x19c(%rbp)
movq -0x1a8(%rbp), %rax
movl 0x14(%rax), %eax
cmpl -0x14(%rbp), %eax
jne 0x278ca
movq -0x1a8(%rbp), %rax
movl 0x18(%rax), %eax
cmpl -0xc(%rbp), %eax
jne 0x278ca
movq -0x1a8(%rbp), %rax
cmpl $0x1, 0x24(%rax)
jl 0x278ca
movq -0x1a8(%rbp), %rax
movl 0x24(%rax), %eax
addl -0x194(%rbp), %eax
movl %eax, -0x194(%rbp)
movl -0x18c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x18c(%rbp)
jmp 0x278cc
movl -0x14(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x14(%rbp)
jmp 0x27827
movq 0x106ef(%rip), %rcx     # 0x37fd0
movq 0x106a0(%rip), %r8      # 0x37f88
movq 0x106b9(%rip), %r9      # 0x37fa8
leaq -0x18c(%rbp), %rdi
leaq -0x190(%rbp), %rsi
movl $0x1, %edx
callq 0x9840
jmp 0x27909
movl $0x1, %edi
movl $0xc, %esi
callq 0x9400
movq %rax, -0x1b0(%rbp)
movl -0x19c(%rbp), %ecx
movq -0x1b0(%rbp), %rax
movl %ecx, (%rax)
movl -0x190(%rbp), %ecx
movq -0x1b0(%rbp), %rax
movl %ecx, 0x4(%rax)
movq -0x1b0(%rbp), %rax
movl $0xffffffff, 0x8(%rax)  # imm = 0xFFFFFFFF
leaq -0x30(%rbp), %rdi
callq 0x1c550
leaq -0x48(%rbp), %rdi
callq 0x1c550
leaq -0x60(%rbp), %rdi
callq 0x1c550
leaq -0x78(%rbp), %rdi
callq 0x1c0e0
movq -0x1b0(%rbp), %rax
movq %rax, -0x200(%rbp)
movq -0xf0(%rbp), %rax
movq %rax, %rsp
leaq -0x78(%rbp), %rdi
callq 0x1c350
leaq -0x60(%rbp), %rdi
callq 0x1c570
leaq -0x48(%rbp), %rdi
callq 0x1c570
leaq -0x30(%rbp), %rdi
callq 0x1c570
movq -0x200(%rbp), %rax
movq %rbp, %rsp
popq %rbp
retq
movq -0x80(%rbp), %rdi
callq 0x9c70
nopw %cs:(%rax,%rax)