// File: /workspace/github_cpp_makefile_star2_O3/ADAPTLab[P]MuDBSCAN/MuC_RTree.cpp
// Function: findNeighbours3(dataHdr*, int, double, std::vector<std::vector<int, std::allocator<int>>, std::allocator<std::vector<int, std::allocator<int>>>>*)
Neighbours findNeighbours3(DataHdr dataList, int pointid, double eps, vector < vector <int > >* p_cur_insert)
{

	findNeighbourCount++;
	Data point = dataList->dataClstElem + pointid;

	// if(point->haloPoint == TRUE)
	// {
	// 	fprintf(stderr, "Unexpected condition! FindNeighbours called on Remote Point!");
	// 	exit(-1);
	// }

	Group group = groupList->groupItems[point->group_id];

	Neighbours n = (Neighbours)calloc(1, sizeof(struct neighbours));
	// assert(n != NULL);
	
	n->id = pointid;

	n->neighbours_local_outer = (vectorc*)malloc(sizeof(struct vectorc));
	// assert(n->neighbours_local != NULL);
	VECTOR_INIT(n->neighbours_local_outer, INTEGER);

	n->neighbours_remote_outer = (vectorc*)malloc(sizeof(struct vectorc));
	// assert(n->neighbours_remote != NULL);
	VECTOR_INIT(n->neighbours_remote_outer, INTEGER);

	n->neighbours_local_inner=(vectorc*)malloc(sizeof(struct vectorc));
	// assert(n->neighbours_local_distance != NULL);
	VECTOR_INIT(n->neighbours_local_inner, INTEGER);

	n->neighbours_remote_inner = (vectorc*)malloc(sizeof(struct vectorc));
	// assert(n->neighbours_remote_distance != NULL);
	VECTOR_INIT(n->neighbours_remote_inner, INTEGER);

	Region region = createCellRegOfPoint(point, eps);
	Region potentialRegion;

	int inner_neighbours = 0;
	int total_neighbours = 0;
	double two = 2;
	Data temp;

	int i=0, j=0;

	//FIRST SEARCH FOR NEIGHBOURS IN THE PRESENT GROUP.
	RHdrNd hdrNdTree = group->bcell->auxCellRTree;
	findNeighboursGroup(hdrNdTree, region, point, n, eps);
	int p;
	i=0;

	// if(VECTOR_TOTAL(n->neighbours_local) != VECTOR_TOTAL(n->neighbours_local_distance) || VECTOR_TOTAL(n->neighbours_remote) != VECTOR_TOTAL(n->neighbours_remote_distance))
	// {
	// 	fprintf(stderr, "findNeighbours3 doesn't not conform to the standard!\n");
	// 	exit(-1);
	// }

	//THEN SEARCH FOR NEIGHBOURS IN THE FILTERED REACHABLE GROUPS
	Group reachableGroup,filteredGroup;
	DataPoint d;
	for(i=0; i<VECTOR_TOTAL(group->reachable_groups); i++)
	{
		int id = group->reachable_groups->intItems[i];
		Group reachableGroup = groupList->groupItems[id];
		DataPoint d = (dataList->dataClstElem + reachableGroup->master_id)->iData;
		potentialRegion = createCellRegOfDataPoint(d, eps);

		if(GisOverLap(region, potentialRegion))
		{
			filteredGroup = groupList->groupItems[id];
			j=0;
			hdrNdTree = filteredGroup->bcell->auxCellRTree;
			findNeighboursGroup(hdrNdTree, region, point, n, eps);
		}

		free(potentialRegion->iBottomLeft);
		free(potentialRegion->iTopRight);
		free(potentialRegion);
	}

	inner_neighbours = VECTOR_TOTAL(n->neighbours_remote_inner) + VECTOR_TOTAL(n->neighbours_local_inner);
	total_neighbours = VECTOR_TOTAL(n->neighbours_remote_outer) + VECTOR_TOTAL(n->neighbours_local_outer) + inner_neighbours;

	if(inner_neighbours >= MINPOINTS)
	{
		if(point->haloPoint == FALSE && point->core_tag == FALSE) totalCore++;

		point->core_tag = TRUE;
		point->ClusterID = 1;
		point->isProcessed = TRUE;

		Group g = groupList->groupItems[point->group_id];

		if(visited[point->id] != 1)
        {
            visited[point->id] = 1;
            addHelper[0] = point->id;
            VECTOR_ADD(g->corepoints, addHelper);
            VECTOR_ADD(unprocessedCore, addHelper);
        }

        int root = point->id;
        Data data;
        Data dataroot1;
        Data dataroot2;
        for(i=0;i<VECTOR_TOTAL(n->neighbours_local_inner);i++)
        {
			data = dataList->dataClstElem + n->neighbours_local_inner->intItems[i];
			if(data->haloPoint == FALSE && data->core_tag == FALSE) totalCore++;
			
			data->core_tag = TRUE;
			data->isProcessed = TRUE;
			data->ClusterID = 1;
			
			g = groupList->groupItems[data->group_id];

			if(visited[data->id] != 1)
        	{
                visited[data->id] = 1;
                addHelper[0] = data->id;
                VECTOR_ADD(g->corepoints, addHelper);
              	VECTOR_ADD(unprocessedCore, addHelper);
        	}

        	int root1 = data->id;
			int root2 = root;

			dataroot1 = dataList->dataClstElem + root1;
            dataroot2 = dataList->dataClstElem + root2;

			unionFindMerge(dataList, root1, root2, dataroot1, dataroot2);
        }

        for(i=0;i<VECTOR_TOTAL(n->neighbours_local_outer);i++)
        {
        	data = dataList->dataClstElem + n->neighbours_local_outer->intItems[i];

			if(data->ClusterID == 0 || data->core_tag == TRUE)
			{
				int root1 = data->id;
				int root2 = root;
				data->ClusterID = 1;
				dataroot1 = dataList->dataClstElem + root1;
                dataroot2 = dataList->dataClstElem + root2;

                unionFindMerge(dataList, root1, root2, dataroot1, dataroot2);
                // REMS algorithm to (union) merge the trees
                // UNION OPERATION
			}
        }

        Data dataremote;
        for(i=0;i<VECTOR_TOTAL(n->neighbours_remote_inner);i++)
        {
        	data = dataList->dataClstElem + n->neighbours_remote_inner->intItems[i];

			if(visited[data->id] != 1)
        	{
                visited[data->id] = 1;
                addHelper[0] = data->id;
                VECTOR_ADD(g->corepoints, addHelper);
              	VECTOR_ADD(unprocessedCore, addHelper);
        	}

			data->core_tag = TRUE;
			data->isProcessed = TRUE;
			data->ClusterID = 1;

			Data dataremote = data;
            (*p_cur_insert)[dataremote->actualProcessId].push_back(point->id);
            (*p_cur_insert)[dataremote->actualProcessId].push_back(dataremote->remoteIndex);
        }


        for(i=0;i<VECTOR_TOTAL(n->neighbours_remote_outer);i++)
        {
        	Data data = dataList->dataClstElem + n->neighbours_remote_outer->intItems[i];

			data->ClusterID = 1;
			dataremote = data;
            (*p_cur_insert)[dataremote->actualProcessId].push_back(point->id);
            (*p_cur_insert)[dataremote->actualProcessId].push_back(dataremote->remoteIndex);
		}
	}

	if(total_neighbours >= MINPOINTS)
	{
		Group g = groupList->groupItems[point->group_id];

		if(point->haloPoint == FALSE && point->core_tag == FALSE) totalCore++;
		
		point->core_tag = TRUE;
		point->ClusterID = 1;

		if(visited[point->id] != 1)
        {
	        visited[point->id] = 1;
	        addHelper[0] = point->id;
	        VECTOR_ADD(g->corepoints, addHelper);
            VECTOR_ADD(unprocessedCore, addHelper);
	    }
	}

	free(region->iBottomLeft);
	free(region->iTopRight);
	free(region);

	return n;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x78, %rsp
movq %rdx, -0x98(%rbp)
movsd %xmm0, -0x30(%rbp)
leaq 0xf3f5(%rip), %rax      # 0x173cc
incl (%rax)
movq %rdi, -0x38(%rbp)
movq 0x8(%rdi), %rax
movslq %esi, %rbx
movq %rbx, %rcx
shlq $0x6, %rcx
leaq (%rax,%rcx), %r13
leaq 0xf3aa(%rip), %rdx      # 0x173a0
movq (%rdx), %rdx
movq (%rdx), %rdx
movslq 0x20(%rax,%rcx), %rax
movq (%rdx,%rax,8), %r15
movl $0x1, %edi
movl $0x30, %esi
callq 0x31b0
movq %rax, %r14
movl %ebx, (%rax)
movl $0x30, %edi
callq 0x33a0
movq %rax, 0x20(%r14)
movq %rax, -0x58(%rbp)
movq %rax, %rdi
xorl %esi, %esi
callq 0x39bc
movl $0x30, %edi
callq 0x33a0
movq %rax, 0x18(%r14)
movq %rax, -0x40(%rbp)
movq %rax, %rdi
xorl %esi, %esi
callq 0x39bc
movl $0x30, %edi
callq 0x33a0
movq %rax, 0x10(%r14)
movq %rax, -0x80(%rbp)
movq %rax, %rdi
xorl %esi, %esi
callq 0x39bc
movl $0x30, %edi
callq 0x33a0
movq %rax, 0x8(%r14)
movq %rax, -0x60(%rbp)
movq %rax, %rdi
xorl %esi, %esi
callq 0x39bc
movq %r13, %rdi
movsd -0x30(%rbp), %xmm0
callq 0x8695
movq %rax, %rsi
movq 0x38(%r15), %rax
movq 0x20(%rax), %rdi
movq %rsi, -0x90(%rbp)
movq %r13, -0x68(%rbp)
movq %r13, %rdx
movq %r14, -0x88(%rbp)
movq %r14, %rcx
movsd -0x30(%rbp), %xmm0
callq 0x7e0a
movq 0x50(%r15), %rdi
callq 0x3a4d
testl %eax, %eax
jle 0x818f
xorl %r13d, %r13d
movq %r15, -0x48(%rbp)
movq 0x50(%r15), %rax
movq 0x8(%rax), %rax
movslq (%rax,%r13,4), %r14
leaq 0xf2b2(%rip), %r12      # 0x173a0
movq (%r12), %rax
movq (%rax), %rax
movq (%rax,%r14,8), %rax
movq -0x38(%rbp), %rcx
movq 0x8(%rcx), %rcx
movslq 0x30(%rax), %rax
shlq $0x6, %rax
movq (%rcx,%rax), %rdi
movsd -0x30(%rbp), %xmm0
callq 0x8731
movq %rax, %rbx
movq -0x90(%rbp), %r15
movq %r15, %rdi
movq %rax, %rsi
callq 0x6868
testl %eax, %eax
je 0x815b
movq (%r12), %rax
movq (%rax), %rax
movq (%rax,%r14,8), %rax
movq 0x38(%rax), %rax
movq 0x20(%rax), %rdi
movq %r15, %rsi
movq -0x68(%rbp), %rdx
movq -0x88(%rbp), %rcx
movsd -0x30(%rbp), %xmm0
callq 0x7e0a
movq (%rbx), %rdi
callq 0x3310
movq 0x8(%rbx), %rdi
callq 0x3310
movq %rbx, %rdi
callq 0x3310
incq %r13
movq -0x48(%rbp), %r15
movq 0x50(%r15), %rdi
callq 0x3a4d
cltq
cmpq %rax, %r13
jl 0x80db
movq -0x60(%rbp), %rdi
callq 0x3a4d
movl %eax, %ebx
movq -0x80(%rbp), %rdi
callq 0x3a4d
movl %eax, %r15d
addl %ebx, %r15d
movq -0x40(%rbp), %rdi
callq 0x3a4d
movl %eax, %ebx
movq -0x58(%rbp), %rdi
callq 0x3a4d
addl %ebx, %eax
addl %r15d, %eax
movl %eax, -0x74(%rbp)
leaq 0xf194(%rip), %rax      # 0x17360
cmpl (%rax), %r15d
jl 0x85d4
movq -0x68(%rbp), %rdx
cmpl $0x0, 0x8(%rdx)
jne 0x81ee
cmpl $0x0, 0x28(%rdx)
jne 0x81ee
leaq 0xf1ec(%rip), %rax      # 0x173d8
incl (%rax)
movabsq $0x100000001, %rax      # imm = 0x100000001
movq %rax, 0x28(%rdx)
movl $0x1, 0x30(%rdx)
leaq 0xf196(%rip), %rax      # 0x173a0
movq (%rax), %rax
movq (%rax), %rax
movslq 0x20(%rdx), %rcx
movq (%rax,%rcx,8), %rax
movq %rax, -0x70(%rbp)
leaq 0xf18d(%rip), %rax      # 0x173b0
movq (%rax), %rax
leaq 0x1c(%rdx), %rcx
movq %rcx, -0x30(%rbp)
movl 0x1c(%rdx), %r14d
movslq %r14d, %rcx
cmpl $0x1, (%rax,%rcx,4)
je 0x8277
movl $0x1, (%rax,%rcx,4)
movq -0x30(%rbp), %r14
movl (%r14), %eax
leaq 0xf140(%rip), %rbx      # 0x17390
movq (%rbx), %rsi
movl %eax, (%rsi)
movq -0x70(%rbp), %rax
movq 0x58(%rax), %rdi
callq 0x3c20
leaq 0xf177(%rip), %rax      # 0x173e0
movq (%rax), %rdi
movq (%rbx), %rsi
callq 0x3c20
movl (%r14), %r14d
movq -0x80(%rbp), %rbx
movq %rbx, %rdi
callq 0x3a4d
movl %r14d, -0x48(%rbp)
movslq %r14d, %rcx
movq %rcx, -0x50(%rbp)
testl %eax, %eax
jle 0x8386
xorl %r13d, %r13d
movq -0x50(%rbp), %r15
shlq $0x6, %r15
movq -0x38(%rbp), %rax
movq 0x8(%rax), %r8
movq 0x8(%rbx), %rax
movslq (%rax,%r13,4), %rax
shlq $0x6, %rax
leaq (%r8,%rax), %r14
cmpl $0x0, 0x8(%r8,%rax)
jne 0x82d1
cmpl $0x0, 0x28(%r14)
jne 0x82d1
leaq 0xf109(%rip), %rax      # 0x173d8
incl (%rax)
movabsq $0x100000001, %rax      # imm = 0x100000001
movq %rax, 0x28(%r14)
movl $0x1, 0x30(%r14)
leaq 0xf0b2(%rip), %rax      # 0x173a0
movq (%rax), %rax
movq (%rax), %rax
movslq 0x20(%r14), %rcx
movq (%rax,%rcx,8), %rdx
leaq 0xf0ad(%rip), %rax      # 0x173b0
movq (%rax), %rax
movl 0x1c(%r14), %esi
movslq %esi, %rcx
cmpl $0x1, (%rax,%rcx,4)
movq %rdx, -0x70(%rbp)
je 0x835a
movl $0x1, (%rax,%rcx,4)
movl 0x1c(%r14), %eax
leaq 0xf067(%rip), %r12      # 0x17390
movq (%r12), %rsi
movl %eax, (%rsi)
movq 0x58(%rdx), %rdi
callq 0x3c20
leaq 0xf0a1(%rip), %rax      # 0x173e0
movq (%rax), %rdi
movq (%r12), %rsi
callq 0x3c20
movl 0x1c(%r14), %esi
movq -0x38(%rbp), %rax
movq 0x8(%rax), %r8
movslq %esi, %rcx
shlq $0x6, %rcx
addq %r8, %rcx
addq %r15, %r8
movq -0x38(%rbp), %rdi
movl -0x48(%rbp), %edx
callq 0x3cdc
incq %r13
movq %rbx, %rdi
callq 0x3a4d
cltq
cmpq %rax, %r13
jl 0x82a1
movq -0x58(%rbp), %rbx
movq %rbx, %rdi
callq 0x3a4d
testl %eax, %eax
movq -0x98(%rbp), %r13
movq -0x40(%rbp), %r15
jle 0x840a
xorl %r14d, %r14d
shlq $0x6, -0x50(%rbp)
movq -0x38(%rbp), %rax
movq 0x8(%rax), %r8
movq 0x8(%rbx), %rax
movslq (%rax,%r14,4), %rcx
shlq $0x6, %rcx
leaq (%r8,%rcx), %rax
cmpl $0x0, 0x30(%r8,%rcx)
je 0x83cf
cmpl $0x1, 0x28(%rax)
jne 0x83f8
movslq 0x1c(%rax), %rsi
movl $0x1, 0x30(%rax)
movq %rsi, %rcx
shlq $0x6, %rcx
addq %r8, %rcx
addq -0x50(%rbp), %r8
movq -0x38(%rbp), %rdi
movl -0x48(%rbp), %edx
callq 0x3cdc
movq -0x58(%rbp), %rbx
incq %r14
movq %rbx, %rdi
callq 0x3a4d
cltq
cmpq %rax, %r14
jl 0x83a9
movq -0x60(%rbp), %rbx
movq %rbx, %rdi
callq 0x3a4d
testl %eax, %eax
jle 0x851d
xorl %r14d, %r14d
movq -0x38(%rbp), %rax
movq 0x8(%rax), %rcx
movq 0x8(%rbx), %rax
movslq (%rax,%r14,4), %rdx
shlq $0x6, %rdx
leaq (%rcx,%rdx), %rbx
leaq 0xef70(%rip), %rax      # 0x173b0
movq (%rax), %rax
movslq 0x1c(%rcx,%rdx), %rcx
cmpl $0x1, (%rax,%rcx,4)
je 0x8485
movl $0x1, (%rax,%rcx,4)
movl 0x1c(%rbx), %eax
leaq 0xef31(%rip), %r12      # 0x17390
movq (%r12), %rsi
movl %eax, (%rsi)
movq -0x70(%rbp), %rax
movq 0x58(%rax), %rdi
callq 0x3c20
leaq 0xef67(%rip), %rax      # 0x173e0
movq (%rax), %rdi
movq (%r12), %rsi
callq 0x3c20
movabsq $0x100000001, %rax      # imm = 0x100000001
movq %rax, 0x28(%rbx)
movl $0x1, 0x30(%rbx)
movslq 0xc(%rbx), %rcx
movq (%r13), %rax
leaq (%rcx,%rcx,2), %rcx
leaq (%rax,%rcx,8), %rdi
movq 0x8(%rdi), %rsi
cmpq 0x10(%rdi), %rsi
je 0x84c6
movq -0x30(%rbp), %rcx
movl (%rcx), %ecx
movl %ecx, (%rsi)
addq $0x4, %rsi
movq %rsi, 0x8(%rdi)
jmp 0x84d3
movq -0x30(%rbp), %rdx
callq 0x5002
movq (%r13), %rax
movslq 0xc(%rbx), %rcx
leaq (%rcx,%rcx,2), %rcx
leaq (%rax,%rcx,8), %rdi
addq $0x10, %rbx
movq 0x8(%rdi), %rsi
cmpq 0x10(%rdi), %rsi
je 0x84fb
movl (%rbx), %eax
movl %eax, (%rsi)
addq $0x4, %rsi
movq %rsi, 0x8(%rdi)
jmp 0x8503
movq %rbx, %rdx
callq 0x5002
incq %r14
movq -0x60(%rbp), %rbx
movq %rbx, %rdi
callq 0x3a4d
cltq
cmpq %rax, %r14
jl 0x8421
movq %r15, %rdi
callq 0x3a4d
testl %eax, %eax
jle 0x85d4
xorl %r14d, %r14d
movq -0x38(%rbp), %rax
movq 0x8(%rax), %rbx
movq 0x8(%r15), %rax
movslq (%rax,%r14,4), %r15
shlq $0x6, %r15
movl $0x1, 0x30(%rbx,%r15)
movslq 0xc(%rbx,%r15), %rcx
movq (%r13), %rax
leaq (%rcx,%rcx,2), %rcx
leaq (%rax,%rcx,8), %rdi
movq 0x8(%rdi), %rsi
cmpq 0x10(%rdi), %rsi
je 0x857a
movq -0x30(%rbp), %rcx
movl (%rcx), %ecx
movl %ecx, (%rsi)
addq $0x4, %rsi
movq %rsi, 0x8(%rdi)
jmp 0x8587
movq -0x30(%rbp), %rdx
callq 0x5002
movq (%r13), %rax
addq %r15, %rbx
movslq 0xc(%rbx), %rcx
leaq (%rcx,%rcx,2), %rcx
leaq (%rax,%rcx,8), %rdi
addq $0x10, %rbx
movq 0x8(%rdi), %rsi
cmpq 0x10(%rdi), %rsi
je 0x85b2
movl (%rbx), %eax
movl %eax, (%rsi)
addq $0x4, %rsi
movq %rsi, 0x8(%rdi)
jmp 0x85ba
movq %rbx, %rdx
callq 0x5002
movq -0x40(%rbp), %r15
incq %r14
movq %r15, %rdi
callq 0x3a4d
cltq
cmpq %rax, %r14
jl 0x8530
movl -0x74(%rbp), %eax
leaq 0xed82(%rip), %rcx      # 0x17360
cmpl (%rcx), %eax
movq -0x68(%rbp), %rdi
movq -0x90(%rbp), %r14
jl 0x8666
leaq 0xedac(%rip), %rax      # 0x173a0
movq (%rax), %rax
movq (%rax), %rax
movslq 0x20(%rdi), %rcx
movq (%rax,%rcx,8), %rax
cmpl $0x0, 0x8(%rdi)
jne 0x8617
cmpl $0x0, 0x28(%rdi)
jne 0x8617
leaq 0xedc3(%rip), %rcx      # 0x173d8
incl (%rcx)
movl $0x1, %esi
movl %esi, 0x28(%rdi)
movl %esi, 0x30(%rdi)
leaq 0xed87(%rip), %rcx      # 0x173b0
movq (%rcx), %rcx
movslq 0x1c(%rdi), %rdx
cmpl %esi, (%rcx,%rdx,4)
je 0x8666
movl $0x1, (%rcx,%rdx,4)
movl 0x1c(%rdi), %ecx
leaq 0xed4a(%rip), %rbx      # 0x17390
movq (%rbx), %rsi
movl %ecx, (%rsi)
movq 0x58(%rax), %rdi
callq 0x3c20
leaq 0xed85(%rip), %rax      # 0x173e0
movq (%rax), %rdi
movq (%rbx), %rsi
callq 0x3c20
movq (%r14), %rdi
callq 0x3310
movq 0x8(%r14), %rdi
callq 0x3310
movq %r14, %rdi
callq 0x3310
movq -0x88(%rbp), %rax
addq $0x78, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq