// File: 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
subq $0xe0, %rsp
movq %rdi, -0x8(%rbp)
movl %esi, -0xc(%rbp)
movq %rdx, -0x18(%rbp)
movq 0x2707b(%rip), %rdi     # 0x37fa8
leaq -0x1c(%rbp), %rsi
callq 0x99e0
leaq 0x278d3(%rip), %rax     # 0x38810
movq (%rax), %rax
movq (%rax), %rax
movslq -0xc(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movq %rax, -0x28(%rbp)
movq -0x28(%rbp), %rax
movq 0x8(%rax), %rdi
callq 0xa2b0
leaq 0x2786d(%rip), %rcx     # 0x387d0
movl (%rcx), %ecx
addl $0x1, %ecx
cmpl %ecx, %eax
jl 0x112c5
movq -0x8(%rbp), %rax
movq 0x8(%rax), %rax
movq -0x28(%rbp), %rcx
movslq 0x30(%rcx), %rcx
shlq $0x6, %rcx
addq %rcx, %rax
movq %rax, -0x38(%rbp)
movq -0x28(%rbp), %rax
movl 0x30(%rax), %eax
movl %eax, -0x3c(%rbp)
movl $0x0, -0x2c(%rbp)
movl -0x2c(%rbp), %eax
movl %eax, -0xd0(%rbp)
movq -0x28(%rbp), %rax
movq 0x8(%rax), %rdi
callq 0xa2b0
movl %eax, %ecx
movl -0xd0(%rbp), %eax
cmpl %ecx, %eax
jge 0x110b7
movq -0x8(%rbp), %rax
movq 0x8(%rax), %rax
movq -0x28(%rbp), %rcx
movq 0x8(%rcx), %rcx
movq 0x8(%rcx), %rcx
movslq -0x2c(%rbp), %rdx
movslq (%rcx,%rdx,4), %rcx
shlq $0x6, %rcx
addq %rcx, %rax
movq %rax, -0x48(%rbp)
movq -0x48(%rbp), %rax
cmpl $0x0, 0x8(%rax)
jne 0x11012
movq -0x48(%rbp), %rax
cmpl $0x0, 0x28(%rax)
jne 0x11012
leaq 0x27844(%rip), %rax     # 0x38848
movl (%rax), %ecx
addl $0x1, %ecx
leaq 0x27838(%rip), %rax     # 0x38848
movl %ecx, (%rax)
movq -0x48(%rbp), %rax
movl $0x1, 0x28(%rax)
movq -0x48(%rbp), %rax
movl $0x1, 0x2c(%rax)
movq -0x48(%rbp), %rax
movl $0x1, 0x30(%rax)
leaq 0x277e6(%rip), %rax     # 0x38820
movq (%rax), %rax
movq -0x48(%rbp), %rcx
movslq 0x1c(%rcx), %rcx
cmpl $0x1, (%rax,%rcx,4)
je 0x110a7
leaq 0x277ce(%rip), %rax     # 0x38820
movq (%rax), %rax
movq -0x48(%rbp), %rcx
movslq 0x1c(%rcx), %rcx
movl $0x1, (%rax,%rcx,4)
movq -0x48(%rbp), %rax
movl 0x1c(%rax), %ecx
leaq 0x2778e(%rip), %rax     # 0x38800
movq (%rax), %rax
movl %ecx, (%rax)
leaq 0x277d2(%rip), %rax     # 0x38850
movq (%rax), %rdi
leaq 0x27778(%rip), %rax     # 0x38800
movq (%rax), %rsi
callq 0xa6e0
movq -0x28(%rbp), %rax
movq 0x58(%rax), %rdi
leaq 0x27761(%rip), %rax     # 0x38800
movq (%rax), %rsi
callq 0xa6e0
jmp 0x110a9
movl -0x2c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x2c(%rbp)
jmp 0x10f9c
movl $0x0, -0x2c(%rbp)
movq -0x38(%rbp), %rax
cmpl $0x0, 0x8(%rax)
jne 0x112c0
movl $0x0, -0x2c(%rbp)
movl -0x2c(%rbp), %eax
movl %eax, -0xd4(%rbp)
movq -0x28(%rbp), %rax
movq 0x10(%rax), %rdi
callq 0xa2b0
movl %eax, %ecx
movl -0xd4(%rbp), %eax
cmpl %ecx, %eax
jge 0x112be
movq -0x8(%rbp), %rax
movq 0x8(%rax), %rax
movq -0x28(%rbp), %rcx
movq 0x10(%rcx), %rcx
movq 0x8(%rcx), %rcx
movslq -0x2c(%rbp), %rdx
movslq (%rcx,%rdx,4), %rcx
shlq $0x6, %rcx
addq %rcx, %rax
movq %rax, -0x50(%rbp)
movq -0x50(%rbp), %rax
movl $0x1, 0x30(%rax)
movq -0x50(%rbp), %rax
cmpl $0x1, 0x8(%rax)
jne 0x11184
movq -0x50(%rbp), %rax
movq %rax, -0x68(%rbp)
movq -0x18(%rbp), %rdi
movq -0x68(%rbp), %rax
movslq 0xc(%rax), %rsi
callq 0x11a90
movq %rax, %rdi
movq -0x38(%rbp), %rsi
addq $0x1c, %rsi
callq 0x11ab0
movq -0x18(%rbp), %rdi
movq -0x68(%rbp), %rax
movslq 0xc(%rax), %rsi
callq 0x11a90
movq %rax, %rdi
movq -0x68(%rbp), %rsi
addq $0x10, %rsi
callq 0x11ab0
jmp 0x112ae
movq -0x50(%rbp), %rax
movl 0x1c(%rax), %eax
movl %eax, -0x6c(%rbp)
movl -0x6c(%rbp), %eax
movl %eax, -0x70(%rbp)
movl -0x3c(%rbp), %eax
movl %eax, -0x74(%rbp)
movq -0x8(%rbp), %rax
movq 0x8(%rax), %rax
movslq -0x70(%rbp), %rcx
shlq $0x6, %rcx
addq %rcx, %rax
movq %rax, -0x58(%rbp)
movq -0x8(%rbp), %rax
movq 0x8(%rax), %rax
movslq -0x74(%rbp), %rcx
shlq $0x6, %rcx
addq %rcx, %rax
movq %rax, -0x60(%rbp)
movq -0x58(%rbp), %rax
movl 0x14(%rax), %eax
movq -0x60(%rbp), %rcx
cmpl 0x14(%rcx), %eax
je 0x112ac
movq -0x58(%rbp), %rax
movl 0x14(%rax), %eax
movq -0x60(%rbp), %rcx
cmpl 0x14(%rcx), %eax
jge 0x1124c
movq -0x58(%rbp), %rax
movl 0x14(%rax), %eax
cmpl -0x70(%rbp), %eax
jne 0x11215
movq -0x60(%rbp), %rax
movl 0x14(%rax), %ecx
movq -0x58(%rbp), %rax
movl %ecx, 0x14(%rax)
movq -0x60(%rbp), %rax
movl 0x14(%rax), %eax
movl %eax, -0x3c(%rbp)
jmp 0x112ac
movq -0x58(%rbp), %rax
movl 0x14(%rax), %eax
movl %eax, -0x78(%rbp)
movq -0x60(%rbp), %rax
movl 0x14(%rax), %ecx
movq -0x58(%rbp), %rax
movl %ecx, 0x14(%rax)
movl -0x78(%rbp), %eax
movl %eax, -0x70(%rbp)
movq -0x8(%rbp), %rax
movq 0x8(%rax), %rax
movslq -0x70(%rbp), %rcx
shlq $0x6, %rcx
addq %rcx, %rax
movq %rax, -0x58(%rbp)
jmp 0x112a7
movq -0x60(%rbp), %rax
movl 0x14(%rax), %eax
cmpl -0x74(%rbp), %eax
jne 0x11272
movq -0x58(%rbp), %rax
movl 0x14(%rax), %ecx
movq -0x60(%rbp), %rax
movl %ecx, 0x14(%rax)
movq -0x58(%rbp), %rax
movl 0x14(%rax), %eax
movl %eax, -0x3c(%rbp)
jmp 0x112ac
movq -0x60(%rbp), %rax
movl 0x14(%rax), %eax
movl %eax, -0x7c(%rbp)
movq -0x58(%rbp), %rax
movl 0x14(%rax), %ecx
movq -0x60(%rbp), %rax
movl %ecx, 0x14(%rax)
movl -0x7c(%rbp), %eax
movl %eax, -0x74(%rbp)
movq -0x8(%rbp), %rax
movq 0x8(%rax), %rax
movslq -0x74(%rbp), %rcx
shlq $0x6, %rcx
addq %rcx, %rax
movq %rax, -0x60(%rbp)
jmp 0x111c8
jmp 0x112ae
jmp 0x112b0
movl -0x2c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x2c(%rbp)
jmp 0x110d3
jmp 0x112c0
jmp 0x116b1
movq -0x28(%rbp), %rax
movq 0x10(%rax), %rdi
callq 0xa2b0
leaq 0x274f7(%rip), %rcx     # 0x387d0
movl (%rcx), %ecx
addl $0x1, %ecx
cmpl %ecx, %eax
jl 0x116af
movq -0x8(%rbp), %rax
movq 0x8(%rax), %rax
movq -0x28(%rbp), %rcx
movslq 0x30(%rcx), %rcx
shlq $0x6, %rcx
addq %rcx, %rax
movq %rax, -0x88(%rbp)
movq -0x88(%rbp), %rax
cmpl $0x0, 0x8(%rax)
jne 0x11333
movq -0x88(%rbp), %rax
cmpl $0x0, 0x28(%rax)
jne 0x11333
leaq 0x27523(%rip), %rax     # 0x38848
movl (%rax), %ecx
addl $0x1, %ecx
leaq 0x27517(%rip), %rax     # 0x38848
movl %ecx, (%rax)
movq -0x88(%rbp), %rax
movl $0x1, 0x28(%rax)
movq -0x88(%rbp), %rax
movl $0x1, 0x2c(%rax)
movq -0x88(%rbp), %rax
movl $0x1, 0x30(%rax)
leaq 0x274bc(%rip), %rax     # 0x38820
movq (%rax), %rax
movq -0x88(%rbp), %rcx
movslq 0x1c(%rcx), %rcx
cmpl $0x1, (%rax,%rcx,4)
je 0x113da
leaq 0x274a1(%rip), %rax     # 0x38820
movq (%rax), %rax
movq -0x88(%rbp), %rcx
movslq 0x1c(%rcx), %rcx
movl $0x1, (%rax,%rcx,4)
movq -0x88(%rbp), %rax
movl 0x1c(%rax), %ecx
leaq 0x2745b(%rip), %rax     # 0x38800
movq (%rax), %rax
movl %ecx, (%rax)
leaq 0x2749f(%rip), %rax     # 0x38850
movq (%rax), %rdi
leaq 0x27445(%rip), %rax     # 0x38800
movq (%rax), %rsi
callq 0xa6e0
movq -0x28(%rbp), %rax
movq 0x58(%rax), %rdi
leaq 0x2742e(%rip), %rax     # 0x38800
movq (%rax), %rsi
callq 0xa6e0
movq -0x8(%rbp), %rax
movq 0x8(%rax), %rax
movq -0x28(%rbp), %rcx
movslq 0x30(%rcx), %rcx
shlq $0x6, %rcx
addq %rcx, %rax
movq %rax, -0x90(%rbp)
movq -0x90(%rbp), %rax
movl 0x1c(%rax), %eax
movl %eax, -0x94(%rbp)
movq -0x90(%rbp), %rax
cmpl $0x0, 0x8(%rax)
jne 0x116ad
movl $0x0, -0x80(%rbp)
movl -0x80(%rbp), %eax
movl %eax, -0xd8(%rbp)
movq -0x28(%rbp), %rax
movq 0x10(%rax), %rdi
callq 0xa2b0
movl %eax, %ecx
movl -0xd8(%rbp), %eax
cmpl %ecx, %eax
jge 0x116ab
movq -0x8(%rbp), %rax
movq 0x8(%rax), %rax
movq -0x28(%rbp), %rcx
movq 0x10(%rcx), %rcx
movq 0x8(%rcx), %rcx
movslq -0x80(%rbp), %rdx
movslq (%rcx,%rdx,4), %rcx
shlq $0x6, %rcx
addq %rcx, %rax
movq %rax, -0xa0(%rbp)
movq -0xa0(%rbp), %rax
movl $0x1, 0x30(%rax)
movq -0xa0(%rbp), %rax
cmpl $0x1, 0x8(%rax)
jne 0x114ec
movq -0xa0(%rbp), %rax
movq %rax, -0xb8(%rbp)
movq -0x18(%rbp), %rdi
movq -0xb8(%rbp), %rax
movslq 0xc(%rax), %rsi
callq 0x11a90
movq %rax, %rdi
movq -0x90(%rbp), %rsi
addq $0x1c, %rsi
callq 0x11ab0
movq -0x18(%rbp), %rdi
movq -0xb8(%rbp), %rax
movslq 0xc(%rax), %rsi
callq 0x11a90
movq %rax, %rdi
movq -0xb8(%rbp), %rsi
addq $0x10, %rsi
callq 0x11ab0
jmp 0x1169b
movq -0xa0(%rbp), %rax
movl 0x1c(%rax), %eax
movl %eax, -0xbc(%rbp)
movl -0xbc(%rbp), %eax
movl %eax, -0xc0(%rbp)
movl -0x94(%rbp), %eax
movl %eax, -0xc4(%rbp)
movq -0x8(%rbp), %rax
movq 0x8(%rax), %rax
movslq -0xc0(%rbp), %rcx
shlq $0x6, %rcx
addq %rcx, %rax
movq %rax, -0xa8(%rbp)
movq -0x8(%rbp), %rax
movq 0x8(%rax), %rax
movslq -0xc4(%rbp), %rcx
shlq $0x6, %rcx
addq %rcx, %rax
movq %rax, -0xb0(%rbp)
movq -0xa8(%rbp), %rax
movl 0x14(%rax), %eax
movq -0xb0(%rbp), %rcx
cmpl 0x14(%rcx), %eax
je 0x11699
movq -0xa8(%rbp), %rax
movl 0x14(%rax), %eax
movq -0xb0(%rbp), %rcx
cmpl 0x14(%rcx), %eax
jge 0x1160f
movq -0xa8(%rbp), %rax
movl 0x14(%rax), %eax
cmpl -0xc0(%rbp), %eax
jne 0x115bd
movq -0xb0(%rbp), %rax
movl 0x14(%rax), %ecx
movq -0xa8(%rbp), %rax
movl %ecx, 0x14(%rax)
movq -0xb0(%rbp), %rax
movl 0x14(%rax), %eax
movl %eax, -0x94(%rbp)
jmp 0x11699
movq -0xa8(%rbp), %rax
movl 0x14(%rax), %eax
movl %eax, -0xc8(%rbp)
movq -0xb0(%rbp), %rax
movl 0x14(%rax), %ecx
movq -0xa8(%rbp), %rax
movl %ecx, 0x14(%rax)
movl -0xc8(%rbp), %eax
movl %eax, -0xc0(%rbp)
movq -0x8(%rbp), %rax
movq 0x8(%rax), %rax
movslq -0xc0(%rbp), %rcx
shlq $0x6, %rcx
addq %rcx, %rax
movq %rax, -0xa8(%rbp)
jmp 0x11694
movq -0xb0(%rbp), %rax
movl 0x14(%rax), %eax
cmpl -0xc4(%rbp), %eax
jne 0x11647
movq -0xa8(%rbp), %rax
movl 0x14(%rax), %ecx
movq -0xb0(%rbp), %rax
movl %ecx, 0x14(%rax)
movq -0xa8(%rbp), %rax
movl 0x14(%rax), %eax
movl %eax, -0x94(%rbp)
jmp 0x11699
movq -0xb0(%rbp), %rax
movl 0x14(%rax), %eax
movl %eax, -0xcc(%rbp)
movq -0xa8(%rbp), %rax
movl 0x14(%rax), %ecx
movq -0xb0(%rbp), %rax
movl %ecx, 0x14(%rax)
movl -0xcc(%rbp), %eax
movl %eax, -0xc4(%rbp)
movq -0x8(%rbp), %rax
movq 0x8(%rax), %rax
movslq -0xc4(%rbp), %rcx
shlq $0x6, %rcx
addq %rcx, %rax
movq %rax, -0xb0(%rbp)
jmp 0x1154e
jmp 0x1169b
jmp 0x1169d
movl -0x80(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x80(%rbp)
jmp 0x11420
jmp 0x116ad
jmp 0x116af
jmp 0x116b1
addq $0xe0, %rsp
popq %rbp
retq
nopw (%rax,%rax)