// File: /workspace/github_cpp_makefile_star2_O1/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 $0x68, %rsp
movq %rdx, -0x90(%rbp)
movsd %xmm0, -0x30(%rbp)
leaq 0xf3b5(%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), %r15
leaq 0xf36a(%rip), %rdx      # 0x173a0
movq (%rdx), %rdx
movq (%rdx), %rdx
movslq 0x20(%rax,%rcx), %rax
movq (%rdx,%rax,8), %r12
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, -0x48(%rbp)
movq %rax, %rdi
xorl %esi, %esi
callq 0x39bc
movl $0x30, %edi
callq 0x33a0
movq %rax, 0x10(%r14)
movq %rax, -0x78(%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 %r15, %rdi
movsd -0x30(%rbp), %xmm0
callq 0x86c1
movq %rax, %rsi
movq 0x38(%r12), %rax
movq 0x20(%rax), %rdi
movq %rsi, -0x88(%rbp)
movq %r15, -0x68(%rbp)
movq %r15, %rdx
movq %r14, -0x80(%rbp)
movq %r14, %rcx
movsd -0x30(%rbp), %xmm0
callq 0x7e4a
movq 0x50(%r12), %rdi
callq 0x3a4d
testl %eax, %eax
jle 0x81cd
xorl %r15d, %r15d
movq %r12, -0x40(%rbp)
movq -0x88(%rbp), %r13
movq 0x50(%r12), %rax
movq 0x8(%rax), %rax
movslq (%rax,%r15,4), %r14
leaq 0xf26b(%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 0x875d
movq %rax, %rbx
movq %r13, %rdi
movq %rax, %rsi
callq 0x68ac
testl %eax, %eax
je 0x8198
movq (%r12), %rax
movq (%rax), %rax
movq (%rax,%r14,8), %rax
movq 0x38(%rax), %rax
movq 0x20(%rax), %rdi
movq %r13, %rsi
movq -0x68(%rbp), %rdx
movq -0x80(%rbp), %rcx
movsd -0x30(%rbp), %xmm0
callq 0x7e4a
movq (%rbx), %rdi
callq 0x3310
movq 0x8(%rbx), %rdi
callq 0x3310
movq %rbx, %rdi
callq 0x3310
incq %r15
movq -0x40(%rbp), %r12
movq 0x50(%r12), %rdi
callq 0x3a4d
cltq
cmpq %rax, %r15
jl 0x8121
movq -0x60(%rbp), %rdi
callq 0x3a4d
movl %eax, %ebx
movq -0x78(%rbp), %rdi
callq 0x3a4d
movl %eax, %r13d
addl %ebx, %r13d
movq -0x48(%rbp), %rdi
callq 0x3a4d
movl %eax, %ebx
movq -0x58(%rbp), %rdi
callq 0x3a4d
addl %ebx, %eax
addl %r13d, %eax
movl %eax, -0x6c(%rbp)
leaq 0xf156(%rip), %rax      # 0x17360
cmpl (%rax), %r13d
jl 0x8603
movq -0x68(%rbp), %rdx
cmpl $0x0, 0x8(%rdx)
jne 0x822c
cmpl $0x0, 0x28(%rdx)
jne 0x822c
leaq 0xf1ae(%rip), %rax      # 0x173d8
incl (%rax)
movabsq $0x100000001, %rax      # imm = 0x100000001
movq %rax, 0x28(%rdx)
movl $0x1, 0x30(%rdx)
leaq 0xf158(%rip), %rax      # 0x173a0
movq (%rax), %rax
movq (%rax), %rax
movslq 0x20(%rdx), %rcx
movq (%rax,%rcx,8), %rax
movq %rax, -0x30(%rbp)
leaq 0xf14f(%rip), %rax      # 0x173b0
movq (%rax), %rax
leaq 0x1c(%rdx), %r14
movslq 0x1c(%rdx), %rcx
cmpl $0x1, (%rax,%rcx,4)
movq -0x78(%rbp), %r13
je 0x82ab
movl $0x1, (%rax,%rcx,4)
movl (%r14), %eax
leaq 0xf109(%rip), %rbx      # 0x17390
movq (%rbx), %rsi
movl %eax, (%rsi)
movq -0x30(%rbp), %rax
movq 0x58(%rax), %rdi
callq 0x3c19
leaq 0xf140(%rip), %rax      # 0x173e0
movq (%rax), %rdi
movq (%rbx), %rsi
callq 0x3c19
movq %r14, -0x40(%rbp)
movslq (%r14), %rax
movq %rax, -0x50(%rbp)
movq %r13, %rdi
callq 0x3a4d
testl %eax, %eax
jle 0x83b3
xorl %r15d, %r15d
movq -0x50(%rbp), %rbx
shlq $0x6, %rbx
movq -0x38(%rbp), %rax
movq 0x8(%rax), %rax
movq 0x8(%r13), %rcx
movslq (%rcx,%r15,4), %rcx
shlq $0x6, %rcx
leaq (%rax,%rcx), %r14
cmpl $0x0, 0x8(%rax,%rcx)
leaq 0xf0ab(%rip), %rax      # 0x173a0
jne 0x8307
cmpl $0x0, 0x28(%r14)
jne 0x8307
leaq 0xf0d3(%rip), %rcx      # 0x173d8
incl (%rcx)
movabsq $0x100000001, %rcx      # imm = 0x100000001
movq %rcx, 0x28(%r14)
movl $0x1, 0x30(%r14)
movq (%rax), %rax
movq (%rax), %rax
movslq 0x20(%r14), %rcx
movq (%rax,%rcx,8), %rax
movq %rax, -0x30(%rbp)
leaq 0xf07a(%rip), %rax      # 0x173b0
movq (%rax), %rax
movslq 0x1c(%r14), %rcx
cmpl $0x1, (%rax,%rcx,4)
je 0x837b
movl $0x1, (%rax,%rcx,4)
movl 0x1c(%r14), %eax
leaq 0xf03b(%rip), %r12      # 0x17390
movq (%r12), %rsi
movl %eax, (%rsi)
movq -0x30(%rbp), %rax
movq 0x58(%rax), %rdi
callq 0x3c19
leaq 0xf071(%rip), %rax      # 0x173e0
movq (%rax), %rdi
movq (%r12), %rsi
callq 0x3c19
movslq 0x1c(%r14), %rsi
movq -0x38(%rbp), %rdi
movq 0x8(%rdi), %r8
movq %rsi, %rcx
shlq $0x6, %rcx
addq %r8, %rcx
addq %rbx, %r8
movq -0x50(%rbp), %rdx
callq 0x3d04
incq %r15
movq %r13, %rdi
callq 0x3a4d
cltq
cmpq %rax, %r15
jl 0x82d1
movq -0x58(%rbp), %r13
movq %r13, %rdi
callq 0x3a4d
testl %eax, %eax
movq -0x48(%rbp), %r15
jle 0x8432
xorl %ebx, %ebx
movq -0x50(%rbp), %r14
shlq $0x6, %r14
movq -0x38(%rbp), %rax
movq 0x8(%rax), %r8
movq 0x8(%r13), %rax
movslq (%rax,%rbx,4), %rcx
shlq $0x6, %rcx
leaq (%r8,%rcx), %rax
cmpl $0x0, 0x30(%r8,%rcx)
je 0x83f7
cmpl $0x1, 0x28(%rax)
jne 0x8420
movslq 0x1c(%rax), %rsi
movl $0x1, 0x30(%rax)
movq %rsi, %rcx
shlq $0x6, %rcx
addq %r8, %rcx
addq %r14, %r8
movq -0x38(%rbp), %rdi
movq -0x50(%rbp), %rdx
callq 0x3d04
movq -0x58(%rbp), %r13
incq %rbx
movq %r13, %rdi
callq 0x3a4d
cltq
cmpq %rax, %rbx
jl 0x83d1
movq -0x60(%rbp), %rbx
movq %rbx, %rdi
callq 0x3a4d
testl %eax, %eax
movq -0x90(%rbp), %r13
jle 0x854c
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 0xef41(%rip), %rax      # 0x173b0
movq (%rax), %rax
movslq 0x1c(%rcx,%rdx), %rcx
cmpl $0x1, (%rax,%rcx,4)
je 0x84b4
movl $0x1, (%rax,%rcx,4)
movl 0x1c(%rbx), %eax
leaq 0xef02(%rip), %r12      # 0x17390
movq (%r12), %rsi
movl %eax, (%rsi)
movq -0x30(%rbp), %rax
movq 0x58(%rax), %rdi
callq 0x3c19
leaq 0xef38(%rip), %rax      # 0x173e0
movq (%rax), %rdi
movq (%r12), %rsi
callq 0x3c19
movabsq $0x100000001, %rax      # imm = 0x100000001
movq %rax, 0x28(%rbx)
movl $0x1, 0x30(%rbx)
movslq 0xc(%rbx), %rax
movq (%r13), %rcx
leaq (%rax,%rax,2), %rax
leaq (%rcx,%rax,8), %rdi
movq 0x8(%rdi), %rsi
cmpq 0x10(%rdi), %rsi
je 0x84f5
movq -0x40(%rbp), %rax
movl (%rax), %eax
movl %eax, (%rsi)
addq $0x4, %rsi
movq %rsi, 0x8(%rdi)
jmp 0x84fe
movq -0x40(%rbp), %rdx
callq 0x50ac
movslq 0xc(%rbx), %rax
movq (%r13), %rcx
leaq (%rax,%rax,2), %rax
leaq (%rcx,%rax,8), %rdi
addq $0x10, %rbx
movq 0x8(%rdi), %rsi
cmpq 0x10(%rdi), %rsi
je 0x852a
movl (%rbx), %eax
movl %eax, (%rsi)
addq $0x4, %rsi
movq %rsi, 0x8(%rdi)
jmp 0x8532
movq %rbx, %rdx
callq 0x50ac
incq %r14
movq -0x60(%rbp), %rbx
movq %rbx, %rdi
callq 0x3a4d
cltq
cmpq %rax, %r14
jl 0x8450
movq %r15, %rdi
callq 0x3a4d
testl %eax, %eax
jle 0x8603
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), %rax
movq (%r13), %rcx
leaq (%rax,%rax,2), %rax
leaq (%rcx,%rax,8), %rdi
movq 0x8(%rdi), %rsi
cmpq 0x10(%rdi), %rsi
je 0x85a9
movq -0x40(%rbp), %rax
movl (%rax), %eax
movl %eax, (%rsi)
addq $0x4, %rsi
movq %rsi, 0x8(%rdi)
jmp 0x85b2
movq -0x40(%rbp), %rdx
callq 0x50ac
addq %r15, %rbx
movslq 0xc(%rbx), %rax
movq (%r13), %rcx
leaq (%rax,%rax,2), %rax
leaq (%rcx,%rax,8), %rdi
addq $0x10, %rbx
movq 0x8(%rdi), %rsi
cmpq 0x10(%rdi), %rsi
je 0x85e1
movl (%rbx), %eax
movl %eax, (%rsi)
addq $0x4, %rsi
movq %rsi, 0x8(%rdi)
jmp 0x85e9
movq %rbx, %rdx
callq 0x50ac
movq -0x48(%rbp), %r15
incq %r14
movq %r15, %rdi
callq 0x3a4d
cltq
cmpq %rax, %r14
jl 0x855f
movl -0x6c(%rbp), %eax
leaq 0xed53(%rip), %rcx      # 0x17360
cmpl (%rcx), %eax
movq -0x68(%rbp), %rdi
leaq 0xed86(%rip), %rax      # 0x173a0
movq -0x88(%rbp), %r14
jl 0x8695
movq (%rax), %rax
movq (%rax), %rax
movslq 0x20(%rdi), %rcx
movq (%rax,%rcx,8), %rax
cmpl $0x0, 0x8(%rdi)
jne 0x8646
cmpl $0x0, 0x28(%rdi)
jne 0x8646
leaq 0xed94(%rip), %rcx      # 0x173d8
incl (%rcx)
movl $0x1, %esi
movl %esi, 0x28(%rdi)
movl %esi, 0x30(%rdi)
leaq 0xed58(%rip), %rcx      # 0x173b0
movq (%rcx), %rcx
movslq 0x1c(%rdi), %rdx
cmpl %esi, (%rcx,%rdx,4)
je 0x8695
movl $0x1, (%rcx,%rdx,4)
movl 0x1c(%rdi), %ecx
leaq 0xed1b(%rip), %rbx      # 0x17390
movq (%rbx), %rsi
movl %ecx, (%rsi)
movq 0x58(%rax), %rdi
callq 0x3c19
leaq 0xed56(%rip), %rax      # 0x173e0
movq (%rax), %rdi
movq (%rbx), %rsi
callq 0x3c19
movq (%r14), %rdi
callq 0x3310
movq 0x8(%r14), %rdi
callq 0x3310
movq %r14, %rdi
callq 0x3310
movq -0x80(%rbp), %rax
addq $0x68, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq