// File: /workspace/github_c_makefile_star2_O2/perdisci[P]LSH/lsh_example.cpp
// Function: main
int main(int argc, char* argv[]) {
    
    unsigned mh_sig_len;
    unsigned lsh_bands;
    unsigned ngram_len;
    std::string corpus_dir;
    
    namespace po = boost::program_options;
    po::options_description desc("Options");
    desc.add_options()
    ("help,h", "Help message")
    ("mh_sig_len,l", po::value<unsigned>(&mh_sig_len)->default_value(240), "Length of minhash signature")
    ("lsh_bands,b", po::value<unsigned>(&lsh_bands)->default_value(80), "Number of bands used for LSH")
    ("ngram_len,n", po::value<unsigned>(&ngram_len)->default_value(1), "ngram length (number of grams)")
    ("corpus_dir,d", po::value<std::string>(), "Directory containing the documents")
    ;
    
    po::variables_map vm;
    po::store(po::parse_command_line(argc, argv, desc), vm);
    po::notify(vm);
    
    if (vm.count("help")) {
        std::cout << desc << std::endl;
        return 1;
    }
    

    if (!vm.count("corpus_dir")) {
        std::cout << "Error: corpus_dir must be provided!" << std::endl;
        std::cout << desc << std::endl;
        return 1;
    }

    corpus_dir = vm["corpus_dir"].as<std::string>();
    
    rp::LSH lsh(mh_sig_len,lsh_bands,ngram_len);
    std::cerr << "parameters:" << mh_sig_len << " | " << lsh_bands << " | " << ngram_len << std::endl;
    
    
    std::cerr << "Computing minhash for files in : " << corpus_dir << std::endl;
    lsh.minhash_corpus(corpus_dir,true,true);
    std::ofstream of;
    of.open("minhash_sigs.csv");
    rp::MinHashMap mh_map = lsh.get_minhash_signatures();
    for (rp::MinHashMap::value_type itm : mh_map) {
        of << itm.first;
        for(uint32_t v : itm.second)
            of << ", " << v;
        of << std::endl;
    }
    of.close();
    
    std::cerr << "Computing bands  " << lsh_bands << std::endl;
    lsh.compute_bands();
    std::cerr << "Computing candidates " << std::endl;
    lsh.compute_candidate_pairs();
    std::vector<rp::CandidatePair> cpv = lsh.get_candidate_pairs();
    
    std::cerr << "Computing minhash similarity: " << cpv.size() << std::endl;
    lsh.compute_minhash_similarities();
    of.open("minhash_sim.csv");
    std::vector<float> jsvmh = lsh.get_minhash_similarities();
    for(int i=0; i<cpv.size(); i++)
        of << cpv[i].first << "," << cpv[i].second << "," << jsvmh[i] << std::endl;
    of.close();
    
    // we can also compute the similarity based on the 
    // original document ngrams
    // this is available if lsh.minhash_corpus() was called with keep_ngrams set to true
    of.open("ngram_sim.csv");
    std::cerr << "Computing ngram similarity: " << cpv.size() << std::endl;
    lsh.compute_ngram_similarities();
    std::vector<float> jsvng = lsh.get_ngram_similarities();
    for(int i=0; i<cpv.size(); i++)
        of << "ngram: " << cpv[i].first << "," << cpv[i].second << "," << jsvng[i] << std::endl;
    of.close();

}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x578, %rsp            # imm = 0x578
movq %rsi, %rbx
movl %edi, %ebp
leaq 0x60(%rsp), %rax
movq %rax, -0x10(%rax)
andq $0x0, -0x8(%rax)
movb $0x0, (%rax)
leaq 0xa80a(%rip), %rsi      # 0x11004
leaq 0x118(%rsp), %rdi
leaq 0x318(%rsp), %rdx
callq 0x6110
movq 0x13782(%rip), %rax     # 0x19f98
movl (%rax), %edx
movl %edx, %ecx
shrl %ecx
leaq 0x4f8(%rsp), %rdi
leaq 0x118(%rsp), %rsi
callq 0x6440
leaq 0x118(%rsp), %rdi
callq 0x6658
leaq 0x4f8(%rsp), %rdi
callq 0x6390
leaq 0x118(%rsp), %rdi
movq %rax, (%rdi)
leaq 0xa7af(%rip), %rsi      # 0x1100c
leaq 0xa7af(%rip), %rdx      # 0x11013
callq 0x65e0
movq %rax, %r14
leaq 0xc(%rsp), %rdi
callq 0x710a
leaq 0x318(%rsp), %rsi
movl $0xf0, (%rsi)
movq %rax, %rdi
callq 0x7148
leaq 0xa78d(%rip), %rsi      # 0x11020
leaq 0xa793(%rip), %rcx      # 0x1102d
movq %r14, %rdi
movq %rax, %rdx
callq 0x6610
movq %rax, %r14
leaq 0x4(%rsp), %rdi
callq 0x710a
leaq 0x458(%rsp), %rsi
movl $0x50, (%rsi)
movq %rax, %rdi
callq 0x7148
leaq 0xa77a(%rip), %rsi      # 0x11049
leaq 0xa77f(%rip), %rcx      # 0x11055
movq %r14, %rdi
movq %rax, %rdx
callq 0x6610
movq %rax, %r14
leaq 0x8(%rsp), %rdi
callq 0x710a
leaq 0x10(%rsp), %rsi
movl $0x1, (%rsi)
movq %rax, %rdi
callq 0x7148
leaq 0xa76a(%rip), %rsi      # 0x11072
leaq 0xa76f(%rip), %rcx      # 0x1107e
movq %r14, %rdi
movq %rax, %rdx
callq 0x6610
movq %rax, %r14
callq 0x71ba
leaq 0xa774(%rip), %rsi      # 0x1109d
leaq 0xa77a(%rip), %rcx      # 0x110aa
movq %r14, %rdi
movq %rax, %rdx
callq 0x6610
leaq 0x458(%rsp), %rdi
callq 0x6140
xorps %xmm0, %xmm0
leaq 0xf0(%rsp), %r9
movaps %xmm0, (%r9)
movaps %xmm0, 0x10(%r9)
leaq 0x118(%rsp), %rdi
leaq 0x4f8(%rsp), %rcx
movl %ebp, %esi
movq %rbx, %rdx
xorl %r8d, %r8d
callq 0x71c1
leaq 0x118(%rsp), %rdi
leaq 0x458(%rsp), %rsi
xorl %edx, %edx
callq 0x6590
leaq 0x118(%rsp), %rdi
callq 0x7460
leaq 0xf0(%rsp), %rdi
callq 0x7272
leaq 0x458(%rsp), %rdi
callq 0x61b0
leaq 0xa70f(%rip), %rsi      # 0x110cd
leaq 0x118(%rsp), %rdi
leaq 0x318(%rsp), %rdx
callq 0x6110
leaq 0x468(%rsp), %rbx
leaq 0x118(%rsp), %rsi
movq %rbx, %rdi
callq 0x7282
movq %rax, %r14
leaq 0x118(%rsp), %rdi
callq 0x6658
testq %r14, %r14
je 0x6a24
movq 0x135b1(%rip), %rdi     # 0x19fb8
leaq 0x4f8(%rsp), %rsi
callq 0x60a0
movq %rax, %rdi
callq 0x6170
pushq $0x1
popq %rbx
jmp 0x6f5d
leaq 0xa6a7(%rip), %rsi      # 0x110d2
leaq 0x118(%rsp), %rdi
leaq 0x318(%rsp), %rdx
callq 0x6110
leaq 0x118(%rsp), %rsi
movq %rbx, %rdi
callq 0x7282
movq %rax, %rbx
leaq 0x118(%rsp), %rdi
callq 0x6658
testq %rbx, %rbx
je 0x6f95
leaq 0xa662(%rip), %rsi      # 0x110d2
leaq 0x118(%rsp), %rdi
leaq 0x318(%rsp), %rdx
callq 0x6110
leaq 0x458(%rsp), %rdi
leaq 0x118(%rsp), %rsi
callq 0x6350
movq %rax, %rdi
callq 0xad9a
leaq 0x50(%rsp), %rdi
movq %rax, %rsi
callq 0x61a0
leaq 0x118(%rsp), %rdi
callq 0x6658
movl 0xc(%rsp), %esi
movl 0x4(%rsp), %edx
movl 0x8(%rsp), %ecx
leaq 0x318(%rsp), %rdi
xorl %r8d, %r8d
callq 0xc65c
movq 0x13511(%rip), %rdi     # 0x19ff0
leaq 0xa61b(%rip), %rsi      # 0x11101
callq 0x6310
movl 0xc(%rsp), %esi
movq %rax, %rdi
callq 0x6230
leaq 0xa60f(%rip), %rsi      # 0x1110d
movq %rax, %rdi
callq 0x6310
movl 0x4(%rsp), %esi
movq %rax, %rdi
callq 0x6230
leaq 0xa5f4(%rip), %rsi      # 0x1110d
movq %rax, %rdi
callq 0x6310
movl 0x8(%rsp), %esi
movq %rax, %rdi
callq 0x6230
movq %rax, %rdi
callq 0x6170
movq 0x134b4(%rip), %rdi     # 0x19ff0
leaq 0xa5ce(%rip), %rsi      # 0x11111
callq 0x6310
leaq 0x50(%rsp), %rsi
movq %rax, %rdi
callq 0x62e0
movq %rax, %rdi
callq 0x6170
leaq 0xa0(%rsp), %rdi
leaq 0x50(%rsp), %rsi
callq 0x6430
leaq 0x318(%rsp), %rdi
leaq 0xa0(%rsp), %rsi
pushq $0x1
popq %rcx
movl %ecx, %edx
callq 0xc80a
leaq 0xa0(%rsp), %rdi
callq 0x6658
leaq 0x118(%rsp), %rdi
callq 0x6550
leaq 0xa589(%rip), %rsi      # 0x11133
leaq 0x118(%rsp), %rdi
pushq $0x10
popq %rdx
callq 0x6040
leaq 0x318(%rsp), %rdi
callq 0xc7e4
leaq 0xc0(%rsp), %rdi
movq %rax, %rsi
callq 0x7536
leaq 0xc8(%rsp), %rax
movq 0x10(%rax), %r15
leaq 0x10(%rsp), %rbx
leaq 0x118(%rsp), %r14
leaq 0xa54d(%rip), %r12      # 0x11144
leaq 0xc8(%rsp), %rax
cmpq %rax, %r15
je 0x6c74
leaq 0x20(%r15), %rsi
movq %rbx, %rdi
callq 0x729c
movq %r15, 0x48(%rsp)
movq %r14, %rdi
movq %rbx, %r15
movq %rbx, %rsi
callq 0x62e0
movq 0x30(%rsp), %rbp
movq 0x38(%rsp), %rbx
cmpq %rbx, %rbp
je 0x6c52
movl (%rbp), %r13d
movq %r14, %rdi
movq %r12, %rsi
callq 0x6310
movq %rax, %rdi
movq %r13, %rsi
callq 0x6230
addq $0x4, %rbp
jmp 0x6c2d
movq %r14, %rdi
callq 0x6170
movq %r15, %rbx
movq %r15, %rdi
callq 0x72d6
movq 0x48(%rsp), %rdi
callq 0x6250
movq %rax, %r15
jmp 0x6bf7
leaq 0x118(%rsp), %rdi
callq 0x6470
movq 0x13368(%rip), %rdi     # 0x19ff0
leaq 0xa4b8(%rip), %rsi      # 0x11147
callq 0x6310
movl 0x4(%rsp), %esi
movq %rax, %rdi
callq 0x6230
movq %rax, %rdi
callq 0x6170
leaq 0x318(%rsp), %rdi
callq 0xd0fe
movq 0x13334(%rip), %rdi     # 0x19ff0
leaq 0xa496(%rip), %rsi      # 0x11159
callq 0x6310
movq %rax, %rdi
callq 0x6170
leaq 0x318(%rsp), %rdi
callq 0xd396
leaq 0x318(%rsp), %rdi
callq 0xc7f2
leaq 0x10(%rsp), %rdi
movq %rax, %rsi
callq 0x72ec
movq 0x132f2(%rip), %rdi     # 0x19ff0
leaq 0xa46a(%rip), %rsi      # 0x1116f
callq 0x6310
movq 0x18(%rsp), %rsi
subq 0x10(%rsp), %rsi
sarq $0x6, %rsi
movq %rax, %rdi
callq 0x6230
movq %rax, %rdi
callq 0x6170
leaq 0x318(%rsp), %rdi
callq 0xd5ca
leaq 0xa452(%rip), %rsi      # 0x1118e
leaq 0x118(%rsp), %rdi
pushq $0x10
popq %rdx
callq 0x6040
leaq 0x318(%rsp), %rdi
callq 0xc7fa
leaq 0x88(%rsp), %rdi
movq %rax, %rsi
callq 0x7340
xorl %r15d, %r15d
leaq 0x118(%rsp), %rbx
leaq 0xa423(%rip), %r14      # 0x1119e
xorl %r12d, %r12d
movq 0x10(%rsp), %rsi
movq 0x18(%rsp), %rax
subq %rsi, %rax
sarq $0x6, %rax
cmpq %r12, %rax
jbe 0x6df1
addq %r15, %rsi
movq %rbx, %rdi
callq 0x62e0
movq %rax, %rdi
movq %r14, %rsi
callq 0x6310
movq 0x10(%rsp), %rcx
leaq (%rcx,%r15), %rsi
addq $0x20, %rsi
movq %rax, %rdi
callq 0x62e0
movq %rax, %rdi
movq %r14, %rsi
callq 0x6310
movq 0x88(%rsp), %rcx
movss (%rcx,%r12,4), %xmm0
movq %rax, %rdi
callq 0x6270
movq %rax, %rdi
callq 0x6170
incq %r12
addq $0x40, %r15
jmp 0x6d7e
leaq 0x118(%rsp), %rdi
callq 0x6470
leaq 0xa39b(%rip), %rsi      # 0x111a0
leaq 0x118(%rsp), %rdi
pushq $0x10
popq %rdx
callq 0x6040
movq 0x131d4(%rip), %rdi     # 0x19ff0
leaq 0xa38b(%rip), %rsi      # 0x111ae
callq 0x6310
movq 0x18(%rsp), %rsi
subq 0x10(%rsp), %rsi
sarq $0x6, %rsi
movq %rax, %rdi
callq 0x6230
movq %rax, %rdi
callq 0x6170
leaq 0x318(%rsp), %rdi
callq 0xd818
leaq 0x318(%rsp), %rdi
callq 0xc802
leaq 0x70(%rsp), %rdi
movq %rax, %rsi
callq 0x7340
xorl %r12d, %r12d
leaq 0xa354(%rip), %rbx      # 0x111cb
leaq 0x118(%rsp), %r14
leaq 0xa318(%rip), %r15      # 0x1119e
xorl %r13d, %r13d
movq 0x18(%rsp), %rax
subq 0x10(%rsp), %rax
sarq $0x6, %rax
cmpq %r13, %rax
jbe 0x6f06
movq %r14, %rdi
movq %rbx, %rsi
callq 0x6310
movq 0x10(%rsp), %rsi
addq %r12, %rsi
movq %rax, %rdi
callq 0x62e0
movq %rax, %rdi
movq %r15, %rsi
callq 0x6310
movq 0x10(%rsp), %rcx
leaq (%rcx,%r12), %rsi
addq $0x20, %rsi
movq %rax, %rdi
callq 0x62e0
movq %rax, %rdi
movq %r15, %rsi
callq 0x6310
movq 0x70(%rsp), %rcx
movss (%rcx,%r13,4), %xmm0
movq %rax, %rdi
callq 0x6270
movq %rax, %rdi
callq 0x6170
incq %r13
addq $0x40, %r12
jmp 0x6e89
leaq 0x118(%rsp), %rdi
callq 0x6470
leaq 0x70(%rsp), %rdi
callq 0xb026
leaq 0x88(%rsp), %rdi
callq 0xb026
leaq 0x10(%rsp), %rdi
callq 0x738e
leaq 0xc0(%rsp), %rdi
callq 0x788e
leaq 0x118(%rsp), %rdi
callq 0x64a0
leaq 0x318(%rsp), %rdi
callq 0x73b0
xorl %ebx, %ebx
leaq 0x458(%rsp), %rdi
callq 0x7406
leaq 0x4f8(%rsp), %rdi
callq 0x7438
leaq 0x50(%rsp), %rdi
callq 0x6658
movl %ebx, %eax
addq $0x578, %rsp            # imm = 0x578
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x1301c(%rip), %rdi     # 0x19fb8
leaq 0xa13a(%rip), %rsi      # 0x110dd
callq 0x6310
movq %rax, %rdi
callq 0x6170
jmp 0x6a00
jmp 0x7084
jmp 0x6ff3
jmp 0x7063
movq %rax, %rbx
leaq 0xa0(%rsp), %rdi
callq 0x6658
jmp 0x70d1
jmp 0x7068
jmp 0x7068
jmp 0x6ffd
jmp 0x7068
jmp 0x707f
jmp 0x705a
jmp 0x7078
movq %rax, %rbx
jmp 0x70c4
jmp 0x6ffd
movq %rax, %rbx
leaq 0x118(%rsp), %rdi
callq 0x6658
jmp 0x70de
jmp 0x7068
movq %rax, %rbx
leaq 0x118(%rsp), %rdi
callq 0x7460
jmp 0x7029
movq %rax, %rbx
leaq 0xf0(%rsp), %rdi
callq 0x7272
jmp 0x70de
jmp 0x7073
movq %rax, %rbx
leaq 0x118(%rsp), %rdi
callq 0x6658
jmp 0x70f8
movq %rax, %rbx
jmp 0x70f8
movq %rax, %rbx
jmp 0x709e
jmp 0x707f
jmp 0x7078
movq %rax, %rbx
jmp 0x70d1
movq %rax, %rbx
jmp 0x70de
jmp 0x7073
jmp 0x7073
jmp 0x7073
movq %rax, %rbx
jmp 0x70eb
movq %rax, %rbx
jmp 0x70b7
jmp 0x70aa
movq %rax, %rbx
jmp 0x7091
movq %rax, %rbx
leaq 0x70(%rsp), %rdi
callq 0xb026
leaq 0x88(%rsp), %rdi
callq 0xb026
leaq 0x10(%rsp), %rdi
callq 0x738e
jmp 0x70b7
movq %rax, %rbx
leaq 0x10(%rsp), %rdi
callq 0x72d6
leaq 0xc0(%rsp), %rdi
callq 0x788e
leaq 0x118(%rsp), %rdi
callq 0x64a0
leaq 0x318(%rsp), %rdi
callq 0x73b0
leaq 0x458(%rsp), %rdi
callq 0x7406
leaq 0x4f8(%rsp), %rdi
callq 0x7438
leaq 0x50(%rsp), %rdi
callq 0x6658
movq %rbx, %rdi
callq 0x65a0