// File: ADAPTLab[P]MuDBSCAN/partition.cpp
// Function: start_partitioning(std::vector<std::vector<double, std::allocator<double>>, std::allocator<std::vector<double, std::allocator<double>>>>&, int*)
void start_partitioning(vector< vector<double> >& objects, int* num_points)
{
	int r_count, s_count, rank, nproc, i, j, k;
	MPI_Comm_rank(MPI_COMM_WORLD, &rank);
	MPI_Comm_size(MPI_COMM_WORLD, &nproc);

	interval* box = new interval[DIMENSION];

	for(i = 0; i < DIMENSION; i++)
	{	
		box[i].upper = MAXGRIDSIZEglobal[i];
		box[i].lower = MINGRIDSIZEglobal[i];
	}

	interval* gbox = new interval[DIMENSION];
	compute_global_bounding_box(box, gbox, nproc);
	delete [] box;

	int internal_nodes, partner_rank, loops, b, color, sub_rank, d, max, sub_nprocs;
	MPI_Comm new_comm;
	MPI_Status status;

	loops = 0;
	i = nproc;
	internal_nodes = 1;

	while((i = i >> 1) > 0)
	{
		loops++;
		internal_nodes = internal_nodes << 1;
	}

	internal_nodes = internal_nodes << 1;

	interval** nodes_gbox = new interval*[internal_nodes];
	for(i = 0; i < internal_nodes; i++)
		nodes_gbox[i] = new interval[DIMENSION];

	copy_global_box_to_each_node(nodes_gbox, gbox, internal_nodes);
	// now each node in the tree has gbox

	vector <double> send_buf;
	vector <int>   invalid_pos_as;
	vector <double> recv_buf;

	int pow2_i;
	double median;

	for(i = 0; i < loops; i++)
	{
		pow2_i = POW2(i);
		b  = nproc - (int) (nproc / pow2_i);
		color = (int)((rank & b) / POW2(loops - i ));
		partner_rank = rank ^ (int)(nproc/POW2(i + 1));

		MPI_Comm new_comm;
		MPI_Comm_split(MPI_COMM_WORLD, color, rank, &new_comm);
		MPI_Comm_rank(new_comm, &sub_rank);

		if(sub_rank == 0)
		{
			d = 0;
			for(j = 1; j < DIMENSION; j++)
			{
				if(nodes_gbox[pow2_i + color][j].upper - nodes_gbox[pow2_i + color][j].lower > 
						nodes_gbox[pow2_i + color][d].upper - nodes_gbox[pow2_i + color][d].lower)
					d = j;
			}
		}	

		MPI_Bcast(&d, 1, MPI_INT, 0, new_comm);

		double median  = get_median(objects, num_points, d, new_comm);		

		s_count = get_points_to_send(objects, num_points,send_buf, invalid_pos_as, median, d, rank, partner_rank);

		if (rank < partner_rank)
		{
			MPI_Sendrecv(&s_count, 1, MPI_INT, partner_rank, 4, &r_count, 1, MPI_INT, partner_rank, 5, MPI_COMM_WORLD, &status);
			recv_buf.resize(r_count * DIMENSION, 0.0);
			MPI_Sendrecv(&send_buf[0], s_count * DIMENSION, MPI_DOUBLE, partner_rank, 2,
					&recv_buf[0], r_count * DIMENSION, MPI_DOUBLE, partner_rank, 3, MPI_COMM_WORLD, &status);
			send_buf.clear();
		}
		else
		{
			MPI_Sendrecv(&s_count, 1, MPI_INT, partner_rank, 5, &r_count, 1, MPI_INT, partner_rank, 4, MPI_COMM_WORLD, &status);

			recv_buf.resize(r_count * DIMENSION, 0.0);

			MPI_Sendrecv(&send_buf[0], s_count * DIMENSION, MPI_DOUBLE, partner_rank, 3, 
					&recv_buf[0], r_count * DIMENSION, MPI_DOUBLE, partner_rank, 2, MPI_COMM_WORLD, &status);

			send_buf.clear();
		}

		update_points(objects, num_points, s_count, invalid_pos_as, recv_buf);
		recv_buf.clear();

		copy_box(nodes_gbox[LOWER(pow2_i+color)], nodes_gbox[pow2_i+color]);
		nodes_gbox[LOWER(pow2_i+color)][d].upper =  median;
		copy_box(nodes_gbox[UPPER(pow2_i+color)], nodes_gbox[pow2_i+color]);
		nodes_gbox[UPPER(pow2_i+color)][d].lower =  median;	

		MPI_Comm_free(&new_comm);
	}
	for(i = 0; i < internal_nodes; i++)
		delete [] nodes_gbox[i];

	delete nodes_gbox;

	delete [] gbox;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x1d0, %rsp            # imm = 0x1D0
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq 0x1dbbe(%rip), %rdi     # 0x37fa8
leaq -0x1c(%rbp), %rsi
callq 0x99e0
movq 0x1dbae(%rip), %rdi     # 0x37fa8
leaq -0x20(%rbp), %rsi
callq 0x9790
leaq 0x1e3ca(%rip), %rax     # 0x387d4
movslq (%rax), %rax
movl $0x10, %ecx
mulq %rcx
movq %rax, %rdi
seto %cl
movq $-0x1, %rax
testb $0x1, %cl
cmovneq %rax, %rdi
callq 0x9030
movq %rax, -0x38(%rbp)
movl $0x0, -0x24(%rbp)
movl -0x24(%rbp), %eax
leaq 0x1e391(%rip), %rcx     # 0x387d4
cmpl (%rcx), %eax
jge 0x1a49f
leaq 0x1e422(%rip), %rax     # 0x38870
movq (%rax), %rax
movslq -0x24(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm0
movq -0x38(%rbp), %rax
movslq -0x24(%rbp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movsd %xmm0, 0x8(%rax)
leaq 0x1e3f3(%rip), %rax     # 0x38868
movq (%rax), %rax
movslq -0x24(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm0
movq -0x38(%rbp), %rax
movslq -0x24(%rbp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movsd %xmm0, (%rax)
movl -0x24(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x24(%rbp)
jmp 0x1a439
leaq 0x1e32e(%rip), %rax     # 0x387d4
movslq (%rax), %rax
movl $0x10, %ecx
mulq %rcx
movq %rax, %rdi
seto %cl
movq $-0x1, %rax
testb $0x1, %cl
cmovneq %rax, %rdi
callq 0x9030
movq %rax, -0x40(%rbp)
movq -0x38(%rbp), %rdi
movq -0x40(%rbp), %rsi
movl -0x20(%rbp), %edx
callq 0x19810
movq -0x38(%rbp), %rax
movq %rax, -0x120(%rbp)
cmpq $0x0, %rax
je 0x1a4fb
movq -0x120(%rbp), %rdi
callq 0x98a0
movl $0x0, -0x4c(%rbp)
movl -0x20(%rbp), %eax
movl %eax, -0x24(%rbp)
movl $0x1, -0x44(%rbp)
movl -0x24(%rbp), %eax
sarl %eax
movl %eax, -0x24(%rbp)
cmpl $0x0, %eax
jle 0x1a52f
movl -0x4c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x4c(%rbp)
movl -0x44(%rbp), %eax
shll %eax
movl %eax, -0x44(%rbp)
jmp 0x1a50f
movl -0x44(%rbp), %eax
shll %eax
movl %eax, -0x44(%rbp)
movslq -0x44(%rbp), %rax
movl $0x8, %ecx
mulq %rcx
movq %rax, %rdi
seto %cl
movq $-0x1, %rax
testb $0x1, %cl
cmovneq %rax, %rdi
callq 0x9030
movq %rax, -0x90(%rbp)
movl $0x0, -0x24(%rbp)
movl -0x24(%rbp), %eax
cmpl -0x44(%rbp), %eax
jge 0x1a5ba
leaq 0x1e25b(%rip), %rax     # 0x387d4
movslq (%rax), %rax
movl $0x10, %ecx
mulq %rcx
movq %rax, %rdi
seto %cl
movq $-0x1, %rax
testb $0x1, %cl
cmovneq %rax, %rdi
callq 0x9030
movq %rax, %rdx
movq -0x90(%rbp), %rax
movslq -0x24(%rbp), %rcx
movq %rdx, (%rax,%rcx,8)
movl -0x24(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x24(%rbp)
jmp 0x1a56a
movq -0x90(%rbp), %rdi
movq -0x40(%rbp), %rsi
movl -0x44(%rbp), %edx
callq 0x199f0
leaq -0xa8(%rbp), %rdi
callq 0xf890
leaq -0xc0(%rbp), %rdi
callq 0x1c260
leaq -0xd8(%rbp), %rdi
callq 0xf890
movl $0x0, -0x24(%rbp)
movl -0x24(%rbp), %eax
cmpl -0x4c(%rbp), %eax
jge 0x1ac0f
movb -0x24(%rbp), %cl
movl $0x1, %eax
movl %eax, -0x128(%rbp)
shll %cl, %eax
movl %eax, -0xdc(%rbp)
movl -0x20(%rbp), %eax
movl %eax, -0x12c(%rbp)
movl -0xdc(%rbp), %ecx
cltd
idivl %ecx
movl -0x128(%rbp), %edx
movl %eax, %ecx
movl -0x12c(%rbp), %eax
subl %ecx, %eax
movl %eax, -0x50(%rbp)
movl -0x1c(%rbp), %eax
movl -0x50(%rbp), %ecx
andl %ecx, %eax
movl -0x4c(%rbp), %ecx
movl -0x24(%rbp), %esi
subl %esi, %ecx
shll %cl, %edx
movl %edx, %ecx
cltd
idivl %ecx
movl -0x128(%rbp), %edx
movl %eax, -0x54(%rbp)
movl -0x1c(%rbp), %eax
movl %eax, -0x124(%rbp)
movl -0x20(%rbp), %eax
movb -0x24(%rbp), %cl
incb %cl
shll %cl, %edx
movl %edx, %ecx
cltd
idivl %ecx
movl %eax, %ecx
movl -0x124(%rbp), %eax
xorl %ecx, %eax
movl %eax, -0x48(%rbp)
movl -0x54(%rbp), %esi
movl -0x1c(%rbp), %edx
movq 0x1d917(%rip), %rdi     # 0x37fa8
leaq -0xf0(%rbp), %rcx
callq 0x9b30
jmp 0x1a69f
movq -0xf0(%rbp), %rdi
leaq -0x58(%rbp), %rsi
callq 0x99e0
jmp 0x1a6b1
cmpl $0x0, -0x58(%rbp)
jne 0x1a7d0
movl $0x0, -0x5c(%rbp)
movl $0x1, -0x28(%rbp)
movl -0x28(%rbp), %eax
leaq 0x1e101(%rip), %rcx     # 0x387d4
cmpl (%rcx), %eax
jge 0x1a7ce
movq -0x90(%rbp), %rax
movl -0xdc(%rbp), %ecx
addl -0x54(%rbp), %ecx
movslq %ecx, %rcx
movq (%rax,%rcx,8), %rax
movslq -0x28(%rbp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movsd 0x8(%rax), %xmm0
movq -0x90(%rbp), %rax
movl -0xdc(%rbp), %ecx
addl -0x54(%rbp), %ecx
movslq %ecx, %rcx
movq (%rax,%rcx,8), %rax
movslq -0x28(%rbp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
subsd (%rax), %xmm0
movq -0x90(%rbp), %rax
movl -0xdc(%rbp), %ecx
addl -0x54(%rbp), %ecx
movslq %ecx, %rcx
movq (%rax,%rcx,8), %rax
movslq -0x5c(%rbp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movsd 0x8(%rax), %xmm1
movq -0x90(%rbp), %rax
movl -0xdc(%rbp), %ecx
addl -0x54(%rbp), %ecx
movslq %ecx, %rcx
movq (%rax,%rcx,8), %rax
movslq -0x5c(%rbp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
subsd (%rax), %xmm1
ucomisd %xmm1, %xmm0
jbe 0x1a7be
movl -0x28(%rbp), %eax
movl %eax, -0x5c(%rbp)
jmp 0x1a7be
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xf8(%rbp)
movl %eax, -0xfc(%rbp)
leaq -0xd8(%rbp), %rdi
callq 0xf910
leaq -0xc0(%rbp), %rdi
callq 0x1c350
leaq -0xa8(%rbp), %rdi
callq 0xf910
jmp 0x1acbd
jmp 0x1a7c0
movl -0x28(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x28(%rbp)
jmp 0x1a6c9
jmp 0x1a7d0
movq -0xf0(%rbp), %r8
movq 0x1d7f2(%rip), %rdx     # 0x37fd0
leaq -0x5c(%rbp), %rdi
movl $0x1, %esi
xorl %ecx, %ecx
callq 0x90d0
jmp 0x1a7f0
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rsi
movl -0x5c(%rbp), %edx
leaq -0xf0(%rbp), %rcx
callq 0x19be0
movsd %xmm0, -0x138(%rbp)
jmp 0x1a811
movsd -0x138(%rbp), %xmm0
movsd %xmm0, -0x108(%rbp)
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rsi
movsd -0x108(%rbp), %xmm0
movl -0x5c(%rbp), %r8d
movl -0x1c(%rbp), %r9d
movl -0x48(%rbp), %ecx
movq %rsp, %rax
movl %ecx, (%rax)
leaq -0xa8(%rbp), %rdx
leaq -0xc0(%rbp), %rcx
callq 0x19d80
movl %eax, -0x13c(%rbp)
jmp 0x1a85c
movl -0x13c(%rbp), %eax
movl %eax, -0x18(%rbp)
movl -0x1c(%rbp), %eax
cmpl -0x48(%rbp), %eax
jge 0x1a9c3
movl -0x48(%rbp), %ecx
movq %rsp, %rax
leaq -0x88(%rbp), %rdx
movq %rdx, 0x28(%rax)
movq 0x1d71f(%rip), %rdx     # 0x37fa8
movq %rdx, 0x20(%rax)
movl %ecx, 0x10(%rax)
movq 0x1d739(%rip), %rdx     # 0x37fd0
movq %rdx, 0x8(%rax)
movl $0x5, 0x18(%rax)
movl $0x1, (%rax)
leaq -0x18(%rbp), %rdi
movl $0x1, %esi
movl $0x4, %r8d
leaq -0x14(%rbp), %r9
callq 0x94c0
jmp 0x1a8c2
movl -0x14(%rbp), %eax
leaq 0x1df08(%rip), %rcx     # 0x387d4
movl (%rcx), %ecx
imull %ecx, %eax
movslq %eax, %rsi
movq $0x0, -0x110(%rbp)
leaq -0xd8(%rbp), %rdi
leaq -0x110(%rbp), %rdx
callq 0x1c280
jmp 0x1a8f4
xorl %eax, %eax
movl %eax, %esi
movq %rsi, -0x160(%rbp)
leaq -0xa8(%rbp), %rdi
callq 0xf870
movq -0x160(%rbp), %rsi
movq %rax, -0x158(%rbp)
movl -0x18(%rbp), %eax
leaq 0x1deb1(%rip), %rcx     # 0x387d4
movq %rcx, -0x148(%rbp)
movl (%rcx), %ecx
imull %ecx, %eax
movl %eax, -0x150(%rbp)
movl -0x48(%rbp), %eax
movl %eax, -0x14c(%rbp)
leaq -0xd8(%rbp), %rdi
callq 0xf870
movq -0x158(%rbp), %rdi
movl -0x150(%rbp), %esi
movl -0x14c(%rbp), %ecx
movq %rax, %r9
movq -0x148(%rbp), %rax
movl -0x14(%rbp), %r8d
movl (%rax), %eax
imull %eax, %r8d
movl -0x48(%rbp), %edx
movq %rsp, %rax
leaq -0x88(%rbp), %r10
movq %r10, 0x28(%rax)
movq 0x1d61f(%rip), %r10     # 0x37fa8
movq %r10, 0x20(%rax)
movl %edx, 0x10(%rax)
movq 0x1d621(%rip), %rdx     # 0x37fb8
movq %rdx, 0x8(%rax)
movl %r8d, (%rax)
movl $0x3, 0x18(%rax)
movl $0x2, %r8d
callq 0x94c0
jmp 0x1a9b2
leaq -0xa8(%rbp), %rdi
callq 0x1c330
jmp 0x1ab10
movl -0x48(%rbp), %ecx
movq %rsp, %rax
leaq -0x88(%rbp), %rdx
movq %rdx, 0x28(%rax)
movq 0x1d5cd(%rip), %rdx     # 0x37fa8
movq %rdx, 0x20(%rax)
movl %ecx, 0x10(%rax)
movq 0x1d5e7(%rip), %rdx     # 0x37fd0
movq %rdx, 0x8(%rax)
movl $0x4, 0x18(%rax)
movl $0x1, (%rax)
leaq -0x18(%rbp), %rdi
movl $0x1, %esi
movl $0x5, %r8d
leaq -0x14(%rbp), %r9
callq 0x94c0
jmp 0x1aa14
movl -0x14(%rbp), %eax
leaq 0x1ddb6(%rip), %rcx     # 0x387d4
movl (%rcx), %ecx
imull %ecx, %eax
movslq %eax, %rsi
movq $0x0, -0x118(%rbp)
leaq -0xd8(%rbp), %rdi
leaq -0x118(%rbp), %rdx
callq 0x1c280
jmp 0x1aa46
xorl %eax, %eax
movl %eax, %esi
movq %rsi, -0x180(%rbp)
leaq -0xa8(%rbp), %rdi
callq 0xf870
movq -0x180(%rbp), %rsi
movq %rax, -0x178(%rbp)
movl -0x18(%rbp), %eax
leaq 0x1dd5f(%rip), %rcx     # 0x387d4
movq %rcx, -0x168(%rbp)
movl (%rcx), %ecx
imull %ecx, %eax
movl %eax, -0x170(%rbp)
movl -0x48(%rbp), %eax
movl %eax, -0x16c(%rbp)
leaq -0xd8(%rbp), %rdi
callq 0xf870
movq -0x178(%rbp), %rdi
movl -0x170(%rbp), %esi
movl -0x16c(%rbp), %ecx
movq %rax, %r9
movq -0x168(%rbp), %rax
movl -0x14(%rbp), %r8d
movl (%rax), %eax
imull %eax, %r8d
movl -0x48(%rbp), %edx
movq %rsp, %rax
leaq -0x88(%rbp), %r10
movq %r10, 0x28(%rax)
movq 0x1d4cd(%rip), %r10     # 0x37fa8
movq %r10, 0x20(%rax)
movl %edx, 0x10(%rax)
movq 0x1d4cf(%rip), %rdx     # 0x37fb8
movq %rdx, 0x8(%rax)
movl %r8d, (%rax)
movl $0x2, 0x18(%rax)
movl $0x3, %r8d
callq 0x94c0
jmp 0x1ab04
leaq -0xa8(%rbp), %rdi
callq 0x1c330
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rsi
movl -0x18(%rbp), %edx
leaq -0xc0(%rbp), %rcx
leaq -0xd8(%rbp), %r8
callq 0x19fe0
jmp 0x1ab30
leaq -0xd8(%rbp), %rdi
callq 0x1c330
movq -0x90(%rbp), %rax
movl -0xdc(%rbp), %ecx
movl -0x54(%rbp), %edx
addl %edx, %ecx
movl %ecx, %edx
addl %edx, %edx
movslq %edx, %rdx
movq (%rax,%rdx,8), %rdi
movslq %ecx, %rcx
movq (%rax,%rcx,8), %rsi
callq 0x19f60
movsd -0x108(%rbp), %xmm0
movq -0x90(%rbp), %rax
movl -0xdc(%rbp), %ecx
movl -0x54(%rbp), %edx
addl %edx, %ecx
addl %ecx, %ecx
movslq %ecx, %rcx
movq (%rax,%rcx,8), %rax
movslq -0x5c(%rbp), %rcx
shlq $0x4, %rcx
movsd %xmm0, 0x8(%rax,%rcx)
movq -0x90(%rbp), %rax
movl -0xdc(%rbp), %ecx
movl -0x54(%rbp), %edx
addl %edx, %ecx
movl %ecx, %edx
addl %edx, %edx
movslq %edx, %rdx
movq 0x8(%rax,%rdx,8), %rdi
movslq %ecx, %rcx
movq (%rax,%rcx,8), %rsi
callq 0x19f60
movsd -0x108(%rbp), %xmm0
movq -0x90(%rbp), %rax
movl -0xdc(%rbp), %ecx
movl -0x54(%rbp), %edx
addl %edx, %ecx
addl %ecx, %ecx
movslq %ecx, %rcx
movq 0x8(%rax,%rcx,8), %rax
movslq -0x5c(%rbp), %rcx
shlq $0x4, %rcx
movsd %xmm0, (%rax,%rcx)
leaq -0xf0(%rbp), %rdi
callq 0x9b10
jmp 0x1abff
jmp 0x1ac01
movl -0x24(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x24(%rbp)
jmp 0x1a5f8
movl $0x0, -0x24(%rbp)
movl -0x24(%rbp), %eax
cmpl -0x44(%rbp), %eax
jge 0x1ac53
movq -0x90(%rbp), %rax
movslq -0x24(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movq %rax, -0x188(%rbp)
cmpq $0x0, %rax
je 0x1ac46
movq -0x188(%rbp), %rdi
callq 0x98a0
jmp 0x1ac48
movl -0x24(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x24(%rbp)
jmp 0x1ac16
movq -0x90(%rbp), %rax
movq %rax, -0x190(%rbp)
cmpq $0x0, %rax
je 0x1ac73
movq -0x190(%rbp), %rdi
callq 0x9630
movq -0x40(%rbp), %rax
movq %rax, -0x198(%rbp)
cmpq $0x0, %rax
je 0x1ac90
movq -0x198(%rbp), %rdi
callq 0x98a0
leaq -0xd8(%rbp), %rdi
callq 0xf910
leaq -0xc0(%rbp), %rdi
callq 0x1c350
leaq -0xa8(%rbp), %rdi
callq 0xf910
addq $0x1d0, %rsp            # imm = 0x1D0
popq %rbp
retq
movq -0xf8(%rbp), %rdi
callq 0x9c70
nopl (%rax)