// File: /workspace/github_cpp_makefile_star2_O1/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 0x12644(%rip), %rdi     # 0x16fa8
leaq -0x4c(%rbp), %rsi
callq 0x33e0
leaq 0x12a2c(%rip), %rax     # 0x173a0
movq (%rax), %rax
movq (%rax), %rax
movslq %r15d, %rcx
movq (%rax,%rcx,8), %r13
movq 0x8(%r13), %rdi
callq 0x3a4d
leaq 0x129cf(%rip), %rbx     # 0x17360
cmpl (%rbx), %eax
movq %r12, -0x30(%rbp)
jle 0x4bf8
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 0x4a6c
xorl %ebx, %ebx
movabsq $0x100000001, %r12      # imm = 0x100000001
leaq 0x129d6(%rip), %r15     # 0x173b0
leaq 0x129af(%rip), %r14     # 0x17390
movq -0x30(%rbp), %rax
movq 0x8(%rax), %rcx
movq 0x8(%r13), %rax
movq 0x8(%rax), %rax
movslq (%rax,%rbx,4), %rdx
shlq $0x6, %rdx
leaq (%rcx,%rdx), %rax
cmpl $0x0, 0x8(%rcx,%rdx)
jne 0x4a13
cmpl $0x0, 0x28(%rax)
jne 0x4a13
leaq 0x129c7(%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 0x4a55
movl $0x1, (%rcx,%rdx,4)
movl 0x1c(%rax), %eax
movq (%r14), %rsi
movl %eax, (%rsi)
leaq 0x1299f(%rip), %rax     # 0x173e0
movq (%rax), %rdi
callq 0x3c19
movq 0x58(%r13), %rdi
movq (%r14), %rsi
callq 0x3c19
incq %rbx
movq 0x8(%r13), %rdi
callq 0x3a4d
cltq
cmpq %rax, %rbx
jl 0x49e1
movq -0x38(%rbp), %rax
cmpl $0x0, 0x8(%rax)
movq -0x48(%rbp), %r14
movq -0x30(%rbp), %r15
jne 0x4c9e
movq 0x10(%r13), %rdi
callq 0x3a4d
testl %eax, %eax
jle 0x4c9e
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 0x4af4
movslq 0xc(%r12), %rax
movq (%r14), %rcx
leaq (%rax,%rax,2), %rax
leaq (%rcx,%rax,8), %rdi
movq 0x8(%rdi), %rsi
cmpq 0x10(%rdi), %rsi
je 0x4b8b
movq -0x38(%rbp), %rax
movl (%rax), %eax
movl %eax, (%rsi)
addq $0x4, %rsi
movq %rsi, 0x8(%rdi)
jmp 0x4b94
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 0x4bca
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 0x4b58
movl %r9d, (%r10)
cmpl %edx, %esi
je 0x4bef
movslq %esi, %rcx
shlq $0x6, %rcx
addq %rax, %rcx
jmp 0x4b73
movl %esi, (%r11)
cmpl %r8d, %r9d
je 0x4bea
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 0x4b3c
jmp 0x4bce
movq -0x38(%rbp), %rdx
callq 0x50ac
movslq 0xc(%r12), %rax
movq (%r14), %rcx
leaq (%rax,%rax,2), %rax
leaq (%rcx,%rax,8), %rdi
addq $0x10, %r12
movq 0x8(%rdi), %rsi
cmpq 0x10(%rdi), %rsi
je 0x4bc2
movl (%r12), %eax
movl %eax, (%rsi)
addq $0x4, %rsi
movq %rsi, 0x8(%rdi)
jmp 0x4bca
movq %r12, %rdx
callq 0x50ac
movq -0x30(%rbp), %r15
incq %rbx
movq 0x10(%r13), %rdi
callq 0x3a4d
cltq
cmpq %rax, %rbx
jl 0x4a9a
jmp 0x4c9e
movl (%r10), %eax
jmp 0x4bf2
movl (%r11), %eax
movq %rax, -0x40(%rbp)
jmp 0x4bce
movq 0x10(%r13), %rdi
callq 0x3a4d
cmpl (%rbx), %eax
jle 0x4c9e
movq 0x8(%r12), %rcx
movslq 0x30(%r13), %rdx
shlq $0x6, %rdx
leaq (%rcx,%rdx), %rax
cmpl $0x0, 0x8(%rcx,%rdx)
jne 0x4c30
cmpl $0x0, 0x28(%rax)
jne 0x4c30
leaq 0x127aa(%rip), %rcx     # 0x173d8
incl (%rcx)
movabsq $0x100000001, %rcx      # imm = 0x100000001
movq %rcx, 0x28(%rax)
movl $0x1, 0x30(%rax)
leaq 0x12764(%rip), %rcx     # 0x173b0
movq (%rcx), %rcx
movslq 0x1c(%rax), %rdx
cmpl $0x1, (%rcx,%rdx,4)
je 0x4c8a
movl $0x1, (%rcx,%rdx,4)
movl 0x1c(%rax), %eax
leaq 0x12726(%rip), %rbx     # 0x17390
movq (%rbx), %rsi
movl %eax, (%rsi)
leaq 0x1276a(%rip), %rax     # 0x173e0
movq (%rax), %rdi
callq 0x3c19
movq 0x58(%r13), %rdi
movq (%rbx), %rsi
callq 0x3c19
movq 0x8(%r12), %rax
movslq 0x30(%r13), %rcx
shlq $0x6, %rcx
cmpl $0x0, 0x8(%rax,%rcx)
je 0x4cad
addq $0x28, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
addq %rcx, %rax
addq $0x1c, %rax
movq %rax, -0x38(%rbp)
movl (%rax), %ebx
movq 0x10(%r13), %rdi
callq 0x3a4d
testl %eax, %eax
jle 0x4c9e
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 0x4d25
movslq 0xc(%r12), %rax
movq (%r14), %rcx
leaq (%rax,%rax,2), %rax
leaq (%rcx,%rax,8), %rdi
movq 0x8(%rdi), %rsi
cmpq 0x10(%rdi), %rsi
je 0x4db8
movq -0x38(%rbp), %rax
movl (%rax), %eax
movl %eax, (%rsi)
addq $0x4, %rsi
movq %rsi, 0x8(%rdi)
jmp 0x4dc1
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 0x4df7
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 0x4d85
movl %r8d, (%r10)
cmpl %ecx, %edi
je 0x4e1c
movslq %edi, %rdx
shlq $0x6, %rdx
addq %rax, %rdx
jmp 0x4da0
movl %edi, (%r11)
cmpl %r9d, %r8d
je 0x4e17
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 0x4d69
jmp 0x4dfb
movq -0x38(%rbp), %rdx
callq 0x50ac
movslq 0xc(%r12), %rax
movq (%r14), %rcx
leaq (%rax,%rax,2), %rax
leaq (%rcx,%rax,8), %rdi
addq $0x10, %r12
movq 0x8(%rdi), %rsi
cmpq 0x10(%rdi), %rsi
je 0x4def
movl (%r12), %eax
movl %eax, (%rsi)
addq $0x4, %rsi
movq %rsi, 0x8(%rdi)
jmp 0x4df7
movq %r12, %rdx
callq 0x50ac
movq -0x30(%rbp), %r12
incq %r15
movq 0x10(%r13), %rdi
callq 0x3a4d
cltq
cmpq %rax, %r15
jl 0x4cca
jmp 0x4c9e
movl (%r10), %ebx
jmp 0x4dfb
movl (%r11), %ebx
jmp 0x4dfb