// File: /workspace/github_cpp_makefile_star2_O2/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 $0x38, %rsp
movq %rdx, %r14
movl %esi, %r15d
movq %rdi, %r12
movq 0x10aab(%rip), %rdi     # 0x13fb0
leaq -0x54(%rbp), %rsi
callq 0x2370
leaq 0x10e5b(%rip), %rax     # 0x14370
movq (%rax), %rax
movq (%rax), %rax
movslq %r15d, %rcx
movq (%rax,%rcx,8), %r13
movq 0x8(%r13), %rdi
callq 0x2831
leaq 0x10dfe(%rip), %rbx     # 0x14330
cmpl (%rbx), %eax
movq %r12, -0x30(%rbp)
jle 0x3603
movq %r14, -0x50(%rbp)
movq 0x8(%r12), %rax
movq %rax, -0x40(%rbp)
movl 0x30(%r13), %eax
movl %eax, -0x38(%rbp)
cltq
movq %rax, -0x48(%rbp)
xorl %r12d, %r12d
movabsq $0x100000001, %rbx      # imm = 0x100000001
leaq 0x10e14(%rip), %r15     # 0x14380
leaq 0x10ded(%rip), %r14     # 0x14360
movq 0x8(%r13), %rdi
callq 0x2831
cltq
cmpq %rax, %r12
jge 0x379d
movq -0x30(%rbp), %rax
movq 0x8(%rax), %rcx
movq 0x8(%r13), %rax
movq 0x8(%rax), %rax
movslq (%rax,%r12,4), %rdx
shlq $0x6, %rdx
leaq (%rcx,%rdx), %rax
cmpl $0x0, 0x8(%rcx,%rdx)
jne 0x35b9
cmpl $0x0, 0x28(%rax)
jne 0x35b9
leaq 0x10df1(%rip), %rcx     # 0x143a8
incl (%rcx)
movq %rbx, 0x28(%rax)
movl $0x1, 0x30(%rax)
movq (%r15), %rcx
movslq 0x1c(%rax), %rdx
cmpl $0x1, (%rcx,%rdx,4)
je 0x35fb
movl $0x1, (%rcx,%rdx,4)
movl 0x1c(%rax), %eax
movq (%r14), %rsi
movl %eax, (%rsi)
leaq 0x10dc9(%rip), %rax     # 0x143b0
movq (%rax), %rdi
callq 0x29f0
movq 0x58(%r13), %rdi
movq (%r14), %rsi
callq 0x29f0
incq %r12
jmp 0x3573
movq 0x10(%r13), %rdi
callq 0x2831
cmpl (%rbx), %eax
jle 0x37b8
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 0x363f
cmpl $0x0, 0x28(%rsi)
jne 0x363f
leaq 0x10d6b(%rip), %rdi     # 0x143a8
incl (%rdi)
movabsq $0x100000001, %rdi      # imm = 0x100000001
movq %rdi, 0x28(%rsi)
movl $0x1, 0x30(%rsi)
leaq 0x10d25(%rip), %rdi     # 0x14380
movq (%rdi), %rdi
movslq 0x1c(%rsi), %r8
cmpl $0x1, (%rdi,%r8,4)
je 0x36af
movl $0x1, (%rdi,%r8,4)
movl 0x1c(%rsi), %eax
leaq 0x10ce5(%rip), %rbx     # 0x14360
movq (%rbx), %rsi
movl %eax, (%rsi)
leaq 0x10d29(%rip), %rax     # 0x143b0
movq (%rax), %rdi
callq 0x29f0
movq 0x58(%r13), %rdi
movq (%rbx), %rsi
callq 0x29f0
movq 0x8(%r12), %rax
movslq 0x30(%r13), %rcx
movq %rcx, %rdx
shlq $0x6, %rdx
movl 0x8(%rax,%rdx), %edx
testl %edx, %edx
jne 0x37b8
shlq $0x6, %rcx
addq %rcx, %rax
addq $0x1c, %rax
movq %rax, -0x38(%rbp)
movl (%rax), %ebx
xorl %r15d, %r15d
movq 0x10(%r13), %rdi
callq 0x2831
cltq
cmpq %rax, %r15
jge 0x37b8
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 0x373a
movslq 0xc(%r12), %rax
imulq $0x18, %rax, %rdi
addq (%r14), %rdi
movq -0x38(%rbp), %rsi
callq 0x3b0a
movslq 0xc(%r12), %rax
imulq $0x18, %rax, %rdi
addq (%r14), %rdi
addq $0x10, %r12
movq %r12, %rsi
callq 0x3b0a
movq -0x30(%rbp), %r12
jmp 0x3795
movl 0x1c(%r12), %ecx
movslq %ebx, %rdx
shlq $0x6, %rdx
addq %rax, %rdx
movl %ebx, %esi
movq -0x30(%rbp), %r12
movslq %ecx, %rdi
shlq $0x6, %rdi
addq %rax, %rdi
addq $0x14, %rdi
movl (%rdi), %r9d
movl 0x14(%rdx), %r8d
cmpl %r8d, %r9d
je 0x3795
jl 0x3783
movl %r9d, 0x14(%rdx)
cmpl %esi, %r8d
je 0x3793
movslq %r8d, %rdx
shlq $0x6, %rdx
addq %rax, %rdx
movl %r8d, %esi
jmp 0x375d
movl %r8d, (%rdi)
cmpl %ecx, %r9d
movl %r9d, %ecx
jne 0x374f
movl 0x14(%rdx), %ebx
jmp 0x3795
movl (%rdi), %ebx
incq %r15
jmp 0x36cb
movq -0x48(%rbp), %rcx
shlq $0x6, %rcx
movq -0x40(%rbp), %rax
cmpl $0x0, 0x8(%rax,%rcx)
movq -0x50(%rbp), %r14
movq -0x30(%rbp), %r15
je 0x37c7
addq $0x38, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq -0x40(%rbp), %rax
addq %rcx, %rax
addq $0x1c, %rax
movq %rax, -0x40(%rbp)
xorl %ebx, %ebx
movq 0x10(%r13), %rdi
callq 0x2831
cltq
cmpq %rax, %rbx
jge 0x37b8
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 0x3842
movslq 0xc(%r12), %rax
imulq $0x18, %rax, %rdi
addq (%r14), %rdi
movq -0x40(%rbp), %rsi
callq 0x3b0a
movslq 0xc(%r12), %rax
imulq $0x18, %rax, %rdi
addq (%r14), %rdi
addq $0x10, %r12
movq %r12, %rsi
callq 0x3b0a
movq -0x30(%rbp), %r15
jmp 0x38a1
movslq 0x1c(%r12), %rsi
movq %rsi, %rcx
shlq $0x6, %rcx
addq %rax, %rcx
movl -0x38(%rbp), %edx
movq -0x30(%rbp), %r15
movslq %edx, %rdi
shlq $0x6, %rdi
addq %rax, %rdi
addq $0x14, %rdi
movl 0x14(%rcx), %r8d
movl (%rdi), %r9d
cmpl %r9d, %r8d
je 0x38a1
jge 0x388c
movl %r9d, 0x14(%rcx)
cmpl %esi, %r8d
je 0x389c
movslq %r8d, %rcx
shlq $0x6, %rcx
addq %rax, %rcx
movl %r8d, %esi
jmp 0x3866
movl %r8d, (%rdi)
cmpl %edx, %r9d
movl %r9d, %edx
jne 0x3858
movl 0x14(%rcx), %eax
jmp 0x389e
movl (%rdi), %eax
movl %eax, -0x38(%rbp)
incq %rbx
jmp 0x37d8