// File: medvedevgroup[P]varmatch/src/wholegenome.cpp
// Function: WholeGenome::ParallelClustering()
bool WholeGenome::ParallelClustering(){
    // parallel by chr
    variant_cluster_by_chrid = new vector<vector<VariantIndicator>> *[chrom_num];
    for (int j = 0; j < chrom_num; j++) {
        variant_cluster_by_chrid[j] = new vector<vector<VariantIndicator>>;
    }

    int parallel_steps = chrom_num / thread_num;
    if(parallel_steps*thread_num < chrom_num) parallel_steps += 1;
    int chr_id = 0;
    for(int i = 0; i < parallel_steps; i++){
        vector<thread> threads;
        for(int j = 0; j < thread_num-1 && chr_id < chrom_num-1; j++){
            if(chrname_by_chrid.find(chr_id) != chrname_by_chrid.end()){
                if(ref_variant_by_chrid[chr_id]->size() > 0 && que_variant_by_chrid[chr_id]->size() > 0){
                    threads.push_back(thread(&WholeGenome::SingleThreadClustering, this, chr_id));
                }
            }
            chr_id ++;
        }
        if(chr_id < chrom_num){
            if(chrname_by_chrid.find(chr_id) != chrname_by_chrid.end()){
                SingleThreadClustering(chr_id);
            }
            chr_id ++;
        }
        std::for_each(threads.begin(), threads.end(), std::mem_fn(&std::thread::join));
        threads.clear();
    }


    for(int i = 0; i < chrom_num; i++){
        if(variant_cluster_by_chrid[i]->size() > 0){
            variants_by_cluster.insert(variants_by_cluster.end(), variant_cluster_by_chrid[i]->begin(), variant_cluster_by_chrid[i]->end());
        }
    }

    // test output
    //dout << endl;
    map<int, int> size_num;
    map<int, int> size_chrid;
    for(int i = 0; i < chrom_num; i++){
        //dout << i << ": " << variant_cluster_by_chrid[i]->size() << endl;
        for(int j = 0; j < variant_cluster_by_chrid[i]->size(); j++){
            int temp_size = variant_cluster_by_chrid[i]->at(j).size();
            if(size_num.find(temp_size) != size_num.end()){
                size_num[temp_size] ++;
            }else{
                size_num[temp_size] = 1;
            }
            if(size_chrid.find(temp_size) == size_chrid.end()){
                size_chrid[temp_size] = i;
            }
        }
    }

    //cout << endl;
    //for(auto it = size_num.begin(); it != size_num.end(); ++it){
    //    dout << it->first << ": " << it->second << endl;
    //}

//    cout << endl;
//    cout << "size and location:" << endl;
//    for(auto it = size_chrid.begin(); it != size_chrid.end(); ++it){
//        dout << it->first << ": " << it->second << endl;
//    }
        // clean at the end of function

    for(int j = 0; j < chrom_num; j++){
        variant_cluster_by_chrid[j]->clear();
        delete variant_cluster_by_chrid[j];
    }
    delete[] variant_cluster_by_chrid;

    return true;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x230, %rsp            # imm = 0x230
movq %rdi, -0x8(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x198(%rbp)
movslq (%rax), %rax
movl $0x8, %ecx
mulq %rcx
movq %rax, %rdi
seto %cl
movq $-0x1, %rax
testb $0x1, %cl
cmovneq %rax, %rdi
callq 0x6040
movq %rax, %rcx
movq -0x198(%rbp), %rax
movq %rcx, 0x158(%rax)
movl $0x0, -0xc(%rbp)
movq -0x198(%rbp), %rcx
movl -0xc(%rbp), %eax
cmpl (%rcx), %eax
jge 0x1e235
movl $0x18, %edi
callq 0x6430
movq %rax, %rdi
movq %rdi, -0x1a0(%rbp)
callq 0x32250
movq -0x198(%rbp), %rax
movq -0x1a0(%rbp), %rdx
movq 0x158(%rax), %rax
movslq -0xc(%rbp), %rcx
movq %rdx, (%rax,%rcx,8)
movl -0xc(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xc(%rbp)
jmp 0x1e1e6
movq -0x198(%rbp), %rcx
movl (%rcx), %eax
cltd
idivl 0x4(%rcx)
movl %eax, -0x10(%rbp)
movl -0x10(%rbp), %eax
imull 0x4(%rcx), %eax
cmpl (%rcx), %eax
jge 0x1e259
movl -0x10(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x10(%rbp)
movl $0x0, -0x14(%rbp)
movl $0x0, -0x18(%rbp)
movl -0x18(%rbp), %eax
cmpl -0x10(%rbp), %eax
jge 0x1e55d
leaq -0x30(%rbp), %rdi
callq 0x33500
movl $0x0, -0x34(%rbp)
movq -0x198(%rbp), %rax
movl -0x34(%rbp), %ecx
movl 0x4(%rax), %edx
subl $0x1, %edx
xorl %eax, %eax
cmpl %edx, %ecx
movb %al, -0x1a1(%rbp)
jge 0x1e2b9
movq -0x198(%rbp), %rcx
movl -0x14(%rbp), %eax
movl (%rcx), %ecx
subl $0x1, %ecx
cmpl %ecx, %eax
setl %al
movb %al, -0x1a1(%rbp)
movb -0x1a1(%rbp), %al
testb $0x1, %al
jne 0x1e2c8
jmp 0x1e3f9
movq -0x198(%rbp), %rdi
addq $0xb8, %rdi
leaq -0x14(%rbp), %rsi
callq 0x33550
movq %rax, -0x1b0(%rbp)
jmp 0x1e2e8
movq -0x198(%rbp), %rdi
movq -0x1b0(%rbp), %rax
movq %rax, -0x40(%rbp)
addq $0xb8, %rdi
callq 0x33580
movq %rax, -0x58(%rbp)
leaq -0x40(%rbp), %rdi
leaq -0x58(%rbp), %rsi
callq 0x33520
testb $0x1, %al
jne 0x1e320
jmp 0x1e3e2
movq -0x198(%rbp), %rax
movq 0x148(%rax), %rax
movslq -0x14(%rbp), %rcx
movq (%rax,%rcx,8), %rdi
callq 0x335b0
cmpq $0x0, %rax
jbe 0x1e3e0
movq -0x198(%rbp), %rax
movq 0x150(%rax), %rax
movslq -0x14(%rbp), %rcx
movq (%rax,%rcx,8), %rdi
callq 0x335b0
cmpq $0x0, %rax
jbe 0x1e3e0
movq -0x198(%rbp), %rax
leaq 0x62c(%rip), %rcx       # 0x1e9a0
movq %rcx, -0x70(%rbp)
movq $0x0, -0x68(%rbp)
movq %rax, -0x78(%rbp)
leaq -0x60(%rbp), %rdi
leaq -0x70(%rbp), %rsi
leaq -0x78(%rbp), %rdx
leaq -0x14(%rbp), %rcx
callq 0x33610
jmp 0x1e39b
leaq -0x30(%rbp), %rdi
leaq -0x60(%rbp), %rsi
callq 0x335e0
jmp 0x1e3aa
leaq -0x60(%rbp), %rdi
callq 0x336e0
jmp 0x1e3e0
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
jmp 0x1e54f
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
leaq -0x60(%rbp), %rdi
callq 0x336e0
jmp 0x1e54f
jmp 0x1e3e2
movl -0x14(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x14(%rbp)
movl -0x34(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x34(%rbp)
jmp 0x1e283
movq -0x198(%rbp), %rcx
movl -0x14(%rbp), %eax
cmpl (%rcx), %eax
jge 0x1e47e
movq -0x198(%rbp), %rdi
addq $0xb8, %rdi
leaq -0x14(%rbp), %rsi
callq 0x33550
movq %rax, -0x1b8(%rbp)
jmp 0x1e427
movq -0x198(%rbp), %rdi
movq -0x1b8(%rbp), %rax
movq %rax, -0x80(%rbp)
addq $0xb8, %rdi
callq 0x33580
movq %rax, -0x88(%rbp)
leaq -0x80(%rbp), %rdi
leaq -0x88(%rbp), %rsi
callq 0x33520
testb $0x1, %al
jne 0x1e462
jmp 0x1e475
movq -0x198(%rbp), %rdi
movl -0x14(%rbp), %esi
callq 0x1e9a0
jmp 0x1e473
jmp 0x1e475
movl -0x14(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x14(%rbp)
leaq -0x30(%rbp), %rdi
movq %rdi, -0x1d0(%rbp)
callq 0x33780
movq -0x1d0(%rbp), %rdi
movq %rax, -0x90(%rbp)
callq 0x337b0
movq %rax, -0x98(%rbp)
movq 0x55b19(%rip), %rax     # 0x73fc8
movq %rax, -0xb8(%rbp)
movq $0x0, -0xb0(%rbp)
movq -0xb8(%rbp), %rdi
movq -0xb0(%rbp), %rsi
callq 0x337e0
movq %rax, -0xa8(%rbp)
movq %rdx, -0xa0(%rbp)
movq -0x90(%rbp), %rdi
movq -0x98(%rbp), %rsi
movq -0xa8(%rbp), %rdx
movq -0xa0(%rbp), %rcx
callq 0x33710
movq %rdx, -0x1c8(%rbp)
movq %rax, -0x1c0(%rbp)
jmp 0x1e513
movq -0x1c8(%rbp), %rax
movq -0x1c0(%rbp), %rcx
movq %rcx, -0xc8(%rbp)
movq %rax, -0xc0(%rbp)
leaq -0x30(%rbp), %rdi
callq 0x33830
leaq -0x30(%rbp), %rdi
callq 0x33850
movl -0x18(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x18(%rbp)
jmp 0x1e267
leaq -0x30(%rbp), %rdi
callq 0x33850
jmp 0x1e997
movl $0x0, -0xcc(%rbp)
movq -0x198(%rbp), %rcx
movl -0xcc(%rbp), %eax
cmpl (%rcx), %eax
jge 0x1e66c
movq -0x198(%rbp), %rax
movq 0x158(%rax), %rax
movslq -0xcc(%rbp), %rcx
movq (%rax,%rcx,8), %rdi
callq 0x338b0
cmpq $0x0, %rax
jbe 0x1e656
movq -0x198(%rbp), %rdi
movq %rdi, %rax
addq $0x160, %rax            # imm = 0x160
movq %rax, -0x1d8(%rbp)
addq $0x160, %rdi            # imm = 0x160
callq 0x33990
movq %rax, -0xe0(%rbp)
leaq -0xd8(%rbp), %rdi
leaq -0xe0(%rbp), %rsi
callq 0x339c0
movq -0x198(%rbp), %rax
movq 0x158(%rax), %rax
movslq -0xcc(%rbp), %rcx
movq (%rax,%rcx,8), %rdi
callq 0x33a00
movq %rax, %rcx
movq -0x198(%rbp), %rax
movq %rcx, -0xe8(%rbp)
movq 0x158(%rax), %rax
movslq -0xcc(%rbp), %rcx
movq (%rax,%rcx,8), %rdi
callq 0x33990
movq -0x1d8(%rbp), %rdi
movq %rax, -0xf0(%rbp)
movq -0xd8(%rbp), %rsi
movq -0xe8(%rbp), %rdx
movq -0xf0(%rbp), %rcx
callq 0x338e0
movq %rax, -0xf8(%rbp)
jmp 0x1e658
movl -0xcc(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xcc(%rbp)
jmp 0x1e567
leaq -0x128(%rbp), %rdi
callq 0x33a30
leaq -0x158(%rbp), %rdi
callq 0x33a30
movl $0x0, -0x15c(%rbp)
movq -0x198(%rbp), %rcx
movl -0x15c(%rbp), %eax
cmpl (%rcx), %eax
jge 0x1e8b9
movl $0x0, -0x160(%rbp)
movq -0x198(%rbp), %rax
movslq -0x160(%rbp), %rcx
movq %rcx, -0x1e0(%rbp)
movq 0x158(%rax), %rax
movslq -0x15c(%rbp), %rcx
movq (%rax,%rcx,8), %rdi
callq 0x338b0
movq %rax, %rcx
movq -0x1e0(%rbp), %rax
cmpq %rcx, %rax
jae 0x1e8a3
movq -0x198(%rbp), %rax
movq 0x158(%rax), %rax
movslq -0x15c(%rbp), %rcx
movq (%rax,%rcx,8), %rdi
movslq -0x160(%rbp), %rsi
callq 0x33a50
movq %rax, -0x1e8(%rbp)
jmp 0x1e71a
movq -0x1e8(%rbp), %rdi
callq 0x33a90
movl %eax, -0x164(%rbp)
leaq -0x128(%rbp), %rdi
leaq -0x164(%rbp), %rsi
callq 0x33af0
movq %rax, -0x1f0(%rbp)
jmp 0x1e748
movq -0x1f0(%rbp), %rax
movq %rax, -0x170(%rbp)
leaq -0x128(%rbp), %rdi
callq 0x33b20
movq %rax, -0x178(%rbp)
leaq -0x170(%rbp), %rdi
leaq -0x178(%rbp), %rsi
callq 0x33ac0
testb $0x1, %al
jne 0x1e782
jmp 0x1e7d7
leaq -0x128(%rbp), %rdi
leaq -0x164(%rbp), %rsi
callq 0x33b50
movq %rax, -0x1f8(%rbp)
jmp 0x1e79e
movq -0x1f8(%rbp), %rax
movl (%rax), %ecx
addl $0x1, %ecx
movl %ecx, (%rax)
jmp 0x1e800
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
leaq -0x158(%rbp), %rdi
callq 0x33c80
leaq -0x128(%rbp), %rdi
callq 0x33c80
jmp 0x1e997
leaq -0x128(%rbp), %rdi
leaq -0x164(%rbp), %rsi
callq 0x33b50
movq %rax, -0x200(%rbp)
jmp 0x1e7f3
movq -0x200(%rbp), %rax
movl $0x1, (%rax)
leaq -0x158(%rbp), %rdi
leaq -0x164(%rbp), %rsi
callq 0x33af0
movq %rax, -0x208(%rbp)
jmp 0x1e81c
movq -0x208(%rbp), %rax
movq %rax, -0x180(%rbp)
leaq -0x158(%rbp), %rdi
callq 0x33b20
movq %rax, -0x188(%rbp)
leaq -0x180(%rbp), %rdi
leaq -0x188(%rbp), %rsi
callq 0x33c30
testb $0x1, %al
jne 0x1e856
jmp 0x1e88d
movl -0x15c(%rbp), %eax
movl %eax, -0x214(%rbp)
leaq -0x158(%rbp), %rdi
leaq -0x164(%rbp), %rsi
callq 0x33b50
movq %rax, -0x210(%rbp)
jmp 0x1e87e
movq -0x210(%rbp), %rax
movl -0x214(%rbp), %ecx
movl %ecx, (%rax)
jmp 0x1e88f
movl -0x160(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x160(%rbp)
jmp 0x1e6ad
jmp 0x1e8a5
movl -0x15c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x15c(%rbp)
jmp 0x1e68e
movl $0x0, -0x18c(%rbp)
movq -0x198(%rbp), %rcx
movl -0x18c(%rbp), %eax
cmpl (%rcx), %eax
jge 0x1e94b
movq -0x198(%rbp), %rax
movq 0x158(%rax), %rax
movslq -0x18c(%rbp), %rcx
movq (%rax,%rcx,8), %rdi
callq 0x33c60
movq -0x198(%rbp), %rax
movq 0x158(%rax), %rax
movslq -0x18c(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movq %rax, -0x220(%rbp)
cmpq $0x0, %rax
je 0x1e935
movq -0x220(%rbp), %rdi
callq 0x325c0
movq -0x220(%rbp), %rdi
movl $0x18, %esi
callq 0x6440
jmp 0x1e937
movl -0x18c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x18c(%rbp)
jmp 0x1e8c3
movq -0x198(%rbp), %rax
movq 0x158(%rax), %rax
movq %rax, -0x228(%rbp)
cmpq $0x0, %rax
je 0x1e972
movq -0x228(%rbp), %rdi
callq 0x6570
leaq -0x158(%rbp), %rdi
callq 0x33c80
leaq -0x128(%rbp), %rdi
callq 0x33c80
movb $0x1, %al
andb $0x1, %al
addq $0x230, %rsp            # imm = 0x230
popq %rbp
retq
movq -0x48(%rbp), %rdi
callq 0x6750