// File: /workspace/github_cpp_makefile_star2_O2/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
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xd8, %rsp
movq %rsi, -0x58(%rbp)
movq %rdi, -0x50(%rbp)
movq 0xbcad(%rip), %rbx      # 0x13fb0
leaq -0x3c(%rbp), %rsi
movq %rbx, %rdi
callq 0x2370
leaq -0x38(%rbp), %rsi
movq %rbx, %rdi
callq 0x2250
leaq 0xc012(%rip), %rax      # 0x14334
movslq (%rax), %r12
movq %r12, %r14
shlq $0x4, %r14
testq %r12, %r12
pushq $-0x1
popq %r15
cmovsq %r15, %r14
movq %r14, %rdi
callq 0x2030
movq %rax, %rbx
leaq 0xc087(%rip), %rax      # 0x143d0
movq (%rax), %rax
leaq 0xc075(%rip), %rcx      # 0x143c8
movq (%rcx), %rcx
xorl %edx, %edx
testl %r12d, %r12d
movl $0x0, %esi
cmovgl %r12d, %esi
shlq $0x3, %rsi
cmpq %rdx, %rsi
je 0x8388
movsd (%rax,%rdx), %xmm0
movsd %xmm0, 0x8(%rbx,%rdx,2)
movsd (%rcx,%rdx), %xmm0
movsd %xmm0, (%rbx,%rdx,2)
addq $0x8, %rdx
jmp 0x8368
movq %r14, %rdi
callq 0x2030
movl -0x38(%rbp), %edx
movq %rbx, %rdi
movq %rax, -0xb8(%rbp)
movq %rax, %rsi
callq 0x7b68
movq %rbx, %rdi
callq 0x22e0
pushq $0x1
popq %rbx
xorl %ecx, %ecx
movl -0x38(%rbp), %eax
leaq 0xbf78(%rip), %r14      # 0x14334
sarl %eax
testl %eax, %eax
jle 0x83c8
incl %ecx
addl %ebx, %ebx
jmp 0x83bc
movl %ecx, -0x6c(%rbp)
addl %ebx, %ebx
movslq %ebx, %rax
leaq (,%rax,8), %rdi
xorl %r12d, %r12d
testl %eax, %eax
cmovsq %r15, %rdi
movl $0x0, %eax
cmovgl %ebx, %eax
movq %rax, -0xc0(%rbp)
callq 0x2030
movq %rax, %r13
movslq (%r14), %rax
movq %rax, %r14
shlq $0x4, %r14
testq %rax, %rax
cmovsq %r15, %r14
cmpq %r12, -0xc0(%rbp)
je 0x8424
movq %r14, %rdi
callq 0x2030
movq %rax, (%r13,%r12,8)
incq %r12
jmp 0x8409
movq %r13, %rdi
movq -0xb8(%rbp), %rsi
movl %ebx, %edx
callq 0x7c67
xorpd %xmm0, %xmm0
leaq -0xb0(%rbp), %rax
andq $0x0, 0x10(%rax)
leaq -0xe0(%rbp), %rcx
andq $0x0, 0x10(%rcx)
movapd %xmm0, (%rax)
movapd %xmm0, (%rcx)
leaq -0x90(%rbp), %rax
movapd %xmm0, (%rax)
andq $0x0, 0x10(%rax)
xorl %r9d, %r9d
movl -0x6c(%rbp), %esi
subl %r9d, %esi
je 0x87bf
pushq $0x1
popq %r8
movl %r8d, %r12d
movl %r9d, %ecx
shll %cl, %r12d
movl -0x38(%rbp), %edi
movl %edi, %eax
cltd
idivl %r12d
movl %edi, %edx
subl %eax, %edx
movl -0x3c(%rbp), %r14d
andl %r14d, %edx
movl %esi, %ecx
shll %cl, %r8d
movl %edx, %eax
cltd
idivl %r8d
movl %eax, %r15d
pushq $0x2
popq %rsi
movl %r9d, -0x70(%rbp)
movl %r9d, %ecx
shll %cl, %esi
movl %edi, %eax
cltd
idivl %esi
movl %eax, %ebx
movq 0xbaef(%rip), %rdi      # 0x13fb0
movl %r15d, %esi
movl %r14d, %edx
leaq -0x48(%rbp), %rcx
callq 0x2410
movq -0x48(%rbp), %rdi
leaq -0x74(%rbp), %rsi
callq 0x2370
cmpl $0x0, -0x74(%rbp)
je 0x875f
movq -0x48(%rbp), %r8
leaq -0x2c(%rbp), %rdi
pushq $0x1
popq %rsi
movq 0xbad7(%rip), %rdx      # 0x13fd0
xorl %ecx, %ecx
callq 0x2060
movl -0x2c(%rbp), %edx
movq -0x50(%rbp), %rdi
movq -0x58(%rbp), %rsi
leaq -0x48(%rbp), %rcx
callq 0x7d4e
movsd %xmm0, -0x60(%rbp)
xorl %r14d, %ebx
movl -0x2c(%rbp), %r8d
movl -0x3c(%rbp), %r9d
subq $0x8, %rsp
movq -0x50(%rbp), %rdi
movq -0x58(%rbp), %rsi
leaq -0xb0(%rbp), %rdx
leaq -0xe0(%rbp), %rcx
movsd -0x60(%rbp), %xmm0
pushq %rbx
callq 0x7e95
popq %rcx
popq %rdx
movl %eax, -0x30(%rbp)
cmpl %ebx, -0x3c(%rbp)
jge 0x85fd
leaq -0x30(%rbp), %rdi
pushq $0x1
popq %rsi
movq 0xba6b(%rip), %rdx      # 0x13fd0
movl %ebx, %ecx
pushq $0x4
popq %r8
leaq -0x34(%rbp), %r9
leaq -0xf8(%rbp), %rax
pushq %rax
pushq 0xba33(%rip)            # 0x13fb0
pushq $0x5
pushq %rbx
pushq %rdx
pushq $0x1
callq 0x21b0
addq $0x30, %rsp
movslq -0x34(%rbp), %rax
leaq 0xbd9d(%rip), %r14      # 0x14334
movslq (%r14), %rsi
imulq %rax, %rsi
andq $0x0, -0x68(%rbp)
leaq -0x90(%rbp), %rdi
leaq -0x68(%rbp), %rdx
callq 0x9520
movq -0xb0(%rbp), %rdi
movl (%r14), %eax
movl -0x30(%rbp), %esi
imull %eax, %esi
movq -0x90(%rbp), %r9
imull -0x34(%rbp), %eax
movq 0xb9eb(%rip), %rdx      # 0x13fc0
movl %ebx, %ecx
pushq $0x2
popq %r8
leaq -0xf8(%rbp), %r10
pushq %r10
pushq 0xb9c6(%rip)            # 0x13fb0
pushq $0x3
pushq %rbx
pushq %rdx
pushq %rax
callq 0x21b0
addq $0x30, %rsp
jmp 0x869e
leaq -0x30(%rbp), %rdi
pushq $0x1
popq %rsi
movq 0xb9c5(%rip), %rdx      # 0x13fd0
movl %ebx, %ecx
pushq $0x5
popq %r8
leaq -0x34(%rbp), %r9
leaq -0xf8(%rbp), %rax
pushq %rax
pushq 0xb98d(%rip)            # 0x13fb0
pushq $0x4
pushq %rbx
pushq %rdx
pushq $0x1
callq 0x21b0
addq $0x30, %rsp
movslq -0x34(%rbp), %rax
leaq 0xbcf7(%rip), %r14      # 0x14334
movslq (%r14), %rsi
imulq %rax, %rsi
andq $0x0, -0x68(%rbp)
leaq -0x90(%rbp), %rdi
leaq -0x68(%rbp), %rdx
callq 0x9520
movq -0xb0(%rbp), %rdi
movl (%r14), %eax
movl -0x30(%rbp), %esi
imull %eax, %esi
movq -0x90(%rbp), %r9
imull -0x34(%rbp), %eax
movq 0xb945(%rip), %rdx      # 0x13fc0
movl %ebx, %ecx
pushq $0x3
popq %r8
leaq -0xf8(%rbp), %r10
pushq %r10
pushq 0xb920(%rip)            # 0x13fb0
pushq $0x2
pushq %rbx
pushq %rdx
pushq %rax
callq 0x21b0
addq $0x30, %rsp
movq -0xb0(%rbp), %rax
cmpq %rax, -0xa8(%rbp)
je 0x86b5
movq %rax, -0xa8(%rbp)
movl -0x30(%rbp), %edx
movq -0x50(%rbp), %rdi
movq -0x58(%rbp), %rsi
leaq -0xe0(%rbp), %rcx
leaq -0x90(%rbp), %r8
callq 0x803e
movq -0x90(%rbp), %rax
cmpq %rax, -0x88(%rbp)
je 0x86ea
movq %rax, -0x88(%rbp)
addl %r12d, %r15d
leal (%r15,%r15), %eax
cltq
movq (%r13,%rax,8), %rbx
movslq %r15d, %r15
movq (%r13,%r15,8), %r14
movq %rbx, %rdi
movq %r14, %rsi
callq 0x7ffe
movslq -0x2c(%rbp), %rax
shlq $0x4, %rax
movsd -0x60(%rbp), %xmm0
movsd %xmm0, 0x8(%rbx,%rax)
leal 0x1(,%r15,2), %eax
cltq
movq (%r13,%rax,8), %rbx
movq %rbx, %rdi
movq %r14, %rsi
callq 0x7ffe
movslq -0x2c(%rbp), %rax
shlq $0x4, %rax
movsd -0x60(%rbp), %xmm0
movsd %xmm0, (%rbx,%rax)
leaq -0x48(%rbp), %rdi
callq 0x2400
movl -0x70(%rbp), %r9d
incl %r9d
jmp 0x846c
andl $0x0, -0x2c(%rbp)
leaq 0xbbca(%rip), %rax      # 0x14334
movslq (%rax), %rax
leal (%r15,%r12), %ecx
movslq %ecx, %rcx
xorl %edi, %edi
pushq $0x18
popq %rdx
pushq $0x1
popq %rsi
cmpq %rax, %rsi
jge 0x84e7
movq (%r13,%rcx,8), %r8
movsd (%r8,%rdx), %xmm0
subsd -0x8(%r8,%rdx), %xmm0
movslq %edi, %r9
shlq $0x4, %r9
movsd 0x8(%r8,%r9), %xmm1
subsd (%r8,%r9), %xmm1
ucomisd %xmm1, %xmm0
jbe 0x87b6
movl %esi, -0x2c(%rbp)
movl %esi, %edi
incq %rsi
addq $0x10, %rdx
jmp 0x877c
xorl %ebx, %ebx
cmpq %rbx, -0xc0(%rbp)
je 0x87de
movq (%r13,%rbx,8), %rdi
testq %rdi, %rdi
je 0x87d9
callq 0x22e0
incq %rbx
jmp 0x87c1
movq %r13, %rdi
callq 0x2210
movq -0xb8(%rbp), %rdi
callq 0x22e0
leaq -0x90(%rbp), %rdi
callq 0x2ede
leaq -0xe0(%rbp), %rdi
callq 0x9d22
leaq -0xb0(%rbp), %rdi
callq 0x2ede
addq $0xd8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x882e
jmp 0x882e
jmp 0x882e
movq %rax, %rbx
leaq -0x90(%rbp), %rdi
callq 0x2ede
leaq -0xe0(%rbp), %rdi
callq 0x9d22
leaq -0xb0(%rbp), %rdi
callq 0x2ede
movq %rbx, %rdi
callq 0x2460