// File: /workspace/github_cpp_makefile_star2_O3/ADAPTLab[P]MuDBSCAN/MuC.cpp
// Function: processGroup(dataHdr*, int, std::vector<std::vector<int, std::allocator<int>>, std::allocator<std::vector<int, std::allocator<int>>>>*)
void processGroup(DataHdr dataList, int i, vector < vector <int > >* p_cur_insert)
{
    int myrank;
    MPI_Comm_rank(MPI_COMM_WORLD, &myrank);
    Group g = groupList->groupItems[i];

    if(VECTOR_TOTAL(g->inner_points) >= MINPOINTS + 1)
    {
        int i;
        Data master = dataList->dataClstElem + g->master_id; // CORE POINT
        int root = g->master_id;

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

            if(data->haloPoint == FALSE && data->core_tag == FALSE) totalCore++;

            data->core_tag = TRUE; // ALL INNER POINTS ARE CORE POINTS
            data->isProcessed = TRUE;
            data->ClusterID = 1;
            
            if(visited[data->id] != 1)
            {
                visited[data->id] = 1;
                addHelper[0] = data->id;
                VECTOR_ADD(unprocessedCore, addHelper);
                VECTOR_ADD(g->corepoints, addHelper);
            } 
        }

        i = 0;

        //If master if non halo do merging right now itself
        //If master is halo then don't do merging now, because you don't know how to do merging. Do merging when you are doing postProcessing of core points. For every non halo core point check if
        //its master point is halo and core, if yes then do merging there

        if(master->haloPoint == FALSE) //master is local point
        {
            Data datalocal;
            Data dataroot1;
            Data dataroot2;
            for(i=0; i<VECTOR_TOTAL(g->total_points); i++)
            {
                datalocal = dataList->dataClstElem + g->total_points->intItems[i];
                datalocal->ClusterID = 1;

                if(datalocal->haloPoint == TRUE)
                {
                    Data dataremote = datalocal;
                    (*p_cur_insert)[dataremote->actualProcessId].push_back(master->id);
                    (*p_cur_insert)[dataremote->actualProcessId].push_back(dataremote->remoteIndex);
                }
                else
                {
                    int npid = datalocal->id;

                    int root1 = npid;
                    int root2 = root;

                     dataroot1 = dataList->dataClstElem + root1;
                     dataroot2 = dataList->dataClstElem + root2; //MASTER - CORE POINT

                    while(dataroot1->parentId != dataroot2->parentId)
                    {
                        if(dataroot1->parentId < dataroot2->parentId)
                        {
                            if(dataroot1->parentId == root1)
                            {
                                dataroot1->parentId = dataroot2->parentId;
                                root = dataroot2->parentId;
                                break;
                            }

                            // splicing comression technique
                            int z = dataroot1->parentId;
                            dataroot1->parentId = dataroot2->parentId;
                            root1 = z;
                            dataroot1 = dataList->dataClstElem + root1;
                        }
                        else
                        {
                            if(dataroot2->parentId == root2)
                            {
                                dataroot2->parentId = dataroot1->parentId;
                                root = dataroot1->parentId;
                                break;
                            }

                            int z = dataroot2->parentId;
                            dataroot2->parentId = dataroot1->parentId;                
                            root2 = z;
                            dataroot2 = dataList->dataClstElem + root2;
                        }
                    }
                }
            }
        }
    }
    else if(VECTOR_TOTAL(g->total_points) >= MINPOINTS + 1)
    {
        int i;

        Data data = dataList->dataClstElem + g->master_id;
        if(data->haloPoint == FALSE && data->core_tag == FALSE) totalCore++;

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

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

        Data master = dataList->dataClstElem + g->master_id;
        int root = master->id;
        //If master if non halo do merging right now itself
        //If master is halo then don't do merging now, because you don't know how to do merging. Do merging when you are doing postProcessing of core points. For every non halo core point check if
        //its master point is halo and core, if yes then do merging there
        if(master->haloPoint == FALSE)
        {
            Data datalocal;
            Data dataroot1;
            Data dataroot2;
            for(i=0; i<VECTOR_TOTAL(g->total_points); i++)
            {
                datalocal = dataList->dataClstElem + g->total_points->intItems[i];
                datalocal->ClusterID = 1;

                if(datalocal->haloPoint == TRUE)
                {
                        Data dataremote = datalocal;
                        (*p_cur_insert)[dataremote->actualProcessId].push_back(master->id);
                        (*p_cur_insert)[dataremote->actualProcessId].push_back(dataremote->remoteIndex);
                }
                else
                {
                    int npid = datalocal->id;

                    int root1 = npid;
                    int root2 = root;


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

                    // REMS algorithm to (union) merge the trees
                    // UNION OPERATION
                    while(dataroot1->parentId != dataroot2->parentId)
                    {
                        if(dataroot1->parentId < dataroot2->parentId)
                        {
                            if(dataroot1->parentId == root1)
                            {
                                dataroot1->parentId = dataroot2->parentId;
                                root = dataroot2->parentId;
                                break;
                            }

                            // splicing comression technique
                            int z = dataroot1->parentId;
                            dataroot1->parentId = dataroot2->parentId;
                            root1 = z;
                            dataroot1 = dataList->dataClstElem + root1;
                        }
                        else
                        {
                            if(dataroot2->parentId == root2)
                            {
                                dataroot2->parentId = dataroot1->parentId;
                                root = dataroot1->parentId;
                                break;
                            }

                            int z = dataroot2->parentId;
                            dataroot2->parentId = dataroot1->parentId;                
                            root2 = z;
                            dataroot2 = dataList->dataClstElem + root2;
                        }
                    }
                }
            }
        }   
    }

}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x28, %rsp
movq %rdx, %r14
movl %esi, %r15d
movq %rdi, %r12
movq 0x126da(%rip), %rdi     # 0x16fa8
leaq -0x4c(%rbp), %rsi
callq 0x33e0
leaq 0x12ac2(%rip), %rax     # 0x173a0
movq (%rax), %rax
movq (%rax), %rax
movslq %r15d, %rcx
movq (%rax,%rcx,8), %r13
movq 0x8(%r13), %rdi
callq 0x3a4d
leaq 0x12a65(%rip), %rbx     # 0x17360
cmpl (%rbx), %eax
movq %r12, -0x30(%rbp)
jle 0x4b62
movq %r14, -0x48(%rbp)
movslq 0x30(%r13), %rax
movq %rax, -0x40(%rbp)
shlq $0x6, %rax
addq 0x8(%r12), %rax
movq %rax, -0x38(%rbp)
movq 0x8(%r13), %rdi
callq 0x3a4d
testl %eax, %eax
jle 0x49d6
xorl %ebx, %ebx
movabsq $0x100000001, %r12      # imm = 0x100000001
leaq 0x12a6c(%rip), %r15     # 0x173b0
leaq 0x12a45(%rip), %r14     # 0x17390
movq -0x30(%rbp), %rax
movq 0x8(%rax), %rcx
movq 0x8(%r13), %rdi
movq 0x8(%rdi), %rax
movslq (%rax,%rbx,4), %rdx
shlq $0x6, %rdx
leaq (%rcx,%rdx), %rax
cmpl $0x0, 0x8(%rcx,%rdx)
jne 0x497d
cmpl $0x0, 0x28(%rax)
jne 0x497d
leaq 0x12a5d(%rip), %rcx     # 0x173d8
incl (%rcx)
movq %r12, 0x28(%rax)
movl $0x1, 0x30(%rax)
movq (%r15), %rcx
movslq 0x1c(%rax), %rdx
cmpl $0x1, (%rcx,%rdx,4)
je 0x49c3
movl $0x1, (%rcx,%rdx,4)
movl 0x1c(%rax), %eax
movq (%r14), %rsi
movl %eax, (%rsi)
leaq 0x12a35(%rip), %rax     # 0x173e0
movq (%rax), %rdi
callq 0x3c20
movq 0x58(%r13), %rdi
movq (%r14), %rsi
callq 0x3c20
movq 0x8(%r13), %rdi
incq %rbx
callq 0x3a4d
cltq
cmpq %rax, %rbx
jl 0x494b
movq -0x38(%rbp), %rax
cmpl $0x0, 0x8(%rax)
movq -0x48(%rbp), %r14
movq -0x30(%rbp), %r15
jne 0x4c12
movq 0x10(%r13), %rdi
callq 0x3a4d
testl %eax, %eax
jle 0x4c12
addq $0x1c, -0x38(%rbp)
xorl %ebx, %ebx
movq 0x8(%r15), %rax
movq 0x10(%r13), %rcx
movq 0x8(%rcx), %rcx
movslq (%rcx,%rbx,4), %rcx
shlq $0x6, %rcx
leaq (%rax,%rcx), %r12
movl $0x1, 0x30(%rax,%rcx)
cmpl $0x1, 0x8(%rax,%rcx)
jne 0x4a5e
movslq 0xc(%r12), %rcx
movq (%r14), %rax
leaq (%rcx,%rcx,2), %rcx
leaq (%rax,%rcx,8), %rdi
movq 0x8(%rdi), %rsi
cmpq 0x10(%rdi), %rsi
je 0x4af5
movq -0x38(%rbp), %rcx
movl (%rcx), %ecx
movl %ecx, (%rsi)
addq $0x4, %rsi
movq %rsi, 0x8(%rdi)
jmp 0x4b01
movslq 0x1c(%r12), %rdx
movq %rdx, %r8
shlq $0x6, %r8
movq -0x40(%rbp), %r15
movslq %r15d, %r11
shlq $0x6, %r11
movl 0x14(%rax,%r8), %esi
movl 0x14(%rax,%r11), %r9d
cmpl %r9d, %esi
je 0x4b34
leaq (%rax,%r8), %rcx
leaq (%rax,%r11), %rdi
leaq (%rax,%r8), %r10
addq $0x14, %r10
addq %rax, %r11
addq $0x14, %r11
movl %r15d, %r8d
movq -0x30(%rbp), %r15
cmpl %r9d, %esi
jge 0x4ac2
movl %r9d, (%r10)
cmpl %edx, %esi
je 0x4b59
movslq %esi, %rcx
shlq $0x6, %rcx
addq %rax, %rcx
jmp 0x4add
movl %esi, (%r11)
cmpl %r8d, %r9d
je 0x4b54
movslq %r9d, %rdi
shlq $0x6, %rdi
addq %rax, %rdi
movl %r9d, %r8d
movl %edx, %esi
movl %esi, %edx
leaq 0x14(%rcx), %r10
movl 0x14(%rcx), %esi
leaq 0x14(%rdi), %r11
movl 0x14(%rdi), %r9d
cmpl %r9d, %esi
jne 0x4aa6
jmp 0x4b38
movq -0x38(%rbp), %rdx
callq 0x5002
movq (%r14), %rax
movslq 0xc(%r12), %rcx
leaq (%rcx,%rcx,2), %rcx
leaq (%rax,%rcx,8), %rdi
addq $0x10, %r12
movq 0x8(%rdi), %rsi
cmpq 0x10(%rdi), %rsi
je 0x4b2c
movl (%r12), %eax
movl %eax, (%rsi)
addq $0x4, %rsi
movq %rsi, 0x8(%rdi)
jmp 0x4b34
movq %r12, %rdx
callq 0x5002
movq -0x30(%rbp), %r15
incq %rbx
movq 0x10(%r13), %rdi
callq 0x3a4d
cltq
cmpq %rax, %rbx
jl 0x4a04
jmp 0x4c12
movl (%r10), %eax
jmp 0x4b5c
movl (%r11), %eax
movq %rax, -0x40(%rbp)
jmp 0x4b38
movq 0x10(%r13), %rdi
callq 0x3a4d
cmpl (%rbx), %eax
jle 0x4c12
movq 0x8(%r12), %rax
movslq 0x30(%r13), %rcx
movq %rcx, %rdx
shlq $0x6, %rdx
leaq (%rax,%rdx), %rsi
movl 0x8(%rax,%rdx), %edx
testl %edx, %edx
jne 0x4b9e
cmpl $0x0, 0x28(%rsi)
jne 0x4b9e
leaq 0x1283c(%rip), %rdi     # 0x173d8
incl (%rdi)
movabsq $0x100000001, %rdi      # imm = 0x100000001
movq %rdi, 0x28(%rsi)
movl $0x1, 0x30(%rsi)
leaq 0x127f6(%rip), %rdi     # 0x173b0
movq (%rdi), %rdi
movslq 0x1c(%rsi), %r8
cmpl $0x1, (%rdi,%r8,4)
je 0x4c0e
movl $0x1, (%rdi,%r8,4)
movl 0x1c(%rsi), %eax
leaq 0x127b6(%rip), %rbx     # 0x17390
movq (%rbx), %rsi
movl %eax, (%rsi)
leaq 0x127fa(%rip), %rax     # 0x173e0
movq (%rax), %rdi
callq 0x3c20
movq 0x58(%r13), %rdi
movq (%rbx), %rsi
callq 0x3c20
movq 0x8(%r12), %rax
movslq 0x30(%r13), %rcx
movq %rcx, %rdx
shlq $0x6, %rdx
movl 0x8(%rax,%rdx), %edx
testl %edx, %edx
je 0x4c21
addq $0x28, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
shlq $0x6, %rcx
addq %rcx, %rax
addq $0x1c, %rax
movq %rax, -0x38(%rbp)
movl (%rax), %ebx
movq 0x10(%r13), %rdi
callq 0x3a4d
testl %eax, %eax
jle 0x4c12
xorl %r15d, %r15d
movq 0x8(%r12), %rax
movq 0x10(%r13), %rcx
movq 0x8(%rcx), %rcx
movslq (%rcx,%r15,4), %rcx
shlq $0x6, %rcx
leaq (%rax,%rcx), %r12
movl $0x1, 0x30(%rax,%rcx)
cmpl $0x1, 0x8(%rax,%rcx)
jne 0x4c9d
movslq 0xc(%r12), %rcx
movq (%r14), %rax
leaq (%rcx,%rcx,2), %rcx
leaq (%rax,%rcx,8), %rdi
movq 0x8(%rdi), %rsi
cmpq 0x10(%rdi), %rsi
je 0x4d30
movq -0x38(%rbp), %rcx
movl (%rcx), %ecx
movl %ecx, (%rsi)
addq $0x4, %rsi
movq %rsi, 0x8(%rdi)
jmp 0x4d3c
movslq 0x1c(%r12), %rcx
movq %rcx, %r9
shlq $0x6, %r9
movslq %ebx, %r11
shlq $0x6, %r11
movl 0x14(%rax,%r9), %edi
movl 0x14(%rax,%r11), %r8d
cmpl %r8d, %edi
je 0x4d6f
leaq (%rax,%r9), %rdx
leaq (%rax,%r11), %rsi
leaq (%rax,%r9), %r10
addq $0x14, %r10
addq %rax, %r11
addq $0x14, %r11
movl %ebx, %r9d
movq -0x30(%rbp), %r12
cmpl %r8d, %edi
jge 0x4cfd
movl %r8d, (%r10)
cmpl %ecx, %edi
je 0x4d94
movslq %edi, %rdx
shlq $0x6, %rdx
addq %rax, %rdx
jmp 0x4d18
movl %edi, (%r11)
cmpl %r9d, %r8d
je 0x4d8f
movslq %r8d, %rsi
shlq $0x6, %rsi
addq %rax, %rsi
movl %ecx, %edi
movl %r8d, %r9d
movl %edi, %ecx
leaq 0x14(%rdx), %r10
movl 0x14(%rdx), %edi
leaq 0x14(%rsi), %r11
movl 0x14(%rsi), %r8d
cmpl %r8d, %edi
jne 0x4ce1
jmp 0x4d73
movq -0x38(%rbp), %rdx
callq 0x5002
movq (%r14), %rax
movslq 0xc(%r12), %rcx
leaq (%rcx,%rcx,2), %rcx
leaq (%rax,%rcx,8), %rdi
addq $0x10, %r12
movq 0x8(%rdi), %rsi
cmpq 0x10(%rdi), %rsi
je 0x4d67
movl (%r12), %eax
movl %eax, (%rsi)
addq $0x4, %rsi
movq %rsi, 0x8(%rdi)
jmp 0x4d6f
movq %r12, %rdx
callq 0x5002
movq -0x30(%rbp), %r12
incq %r15
movq 0x10(%r13), %rdi
callq 0x3a4d
cltq
cmpq %rax, %r15
jl 0x4c42
jmp 0x4c12
movl (%r10), %ebx
jmp 0x4d73
movl (%r11), %ebx
jmp 0x4d73