// File: /workspace/github_c_makefile_star2_O0/c-zhou[P]oatk/syncmer.c
// Function: process_kmer_cluster
static void process_kmer_cluster(uint128_t *scm, uint32_t n, syncmer_db_t *scm_db, sr_db_t *sr_db)
{
    int n_clus, *clus;
    MYMALLOC(clus, n);

    if (n == 1) {
        // no hash collision for sure
        n_clus = 1;
        clus[0] = 0;
    } else {
        int i, j, k, b, c, B, C, p0, p1, rev, res;
        uint8_t *kmer, *kmer_list;
        uint32_t n_s;
        uint64_t sid;
        size_t s;

        k = sr_db->k;
        B = (((k - 1) >> 3) + 1) << 3; // maxmum number bytes to hold syncmer 64bit aligned
        C = B >> 3; // number of comparsions of 64bit interger
        n_clus = 0;
        kmer_list = 0;
        MYMALLOC(kmer, B);

        for (s = 0; s < n; ++s) {
            sid = (uint64_t) scm[s] >> 32;
            n_s = (uint32_t) ((uint64_t) scm[s]) >> 1;
            rev = scm[s] & 1;
            p0 = sr_db->a[sid].m_pos[n_s] >> 1;
            p1 = p0 + k - 1;
            res = rev? ((p1&3)^3)<<1 : (p0&3)<<1;
            b = p1 / 4 - p0 / 4 + 1; // actual number bytes holding syncmer
            memcpy(kmer, sr_db->a[sid].hoco_s + p0 / 4, b);
            // do reverse complementary
            if (rev) {
                for (i = 0, j = b - 1; i < j; ++i, --j) {
                    c = kmer[i];
                    kmer[i] = comp_seq8_table[kmer[j]];
                    kmer[j] = comp_seq8_table[c];
                }
                if (i == j) kmer[i] = comp_seq8_table[kmer[i]];
            }
            // do bit shift to align syncmer bytes
            for (i = 0; i < b - 1; ++i) {
                kmer[i] <<= res;
                kmer[i] |= kmer[i+1] >> (8-res);
            }
            kmer[b-1] <<= res;
            // real bytes
            b = (k - 1) / 4 + 1;
            // mask the lower bits
            kmer[b-1] &= lmask[k&3];
            // mask the remaining bytes
            MYBZERO(&kmer[b], B - b);
            // compare to the existing kmers to find hash collision
            for (i = 0; i < n_clus; ++i)
                if (equal_array(kmer, &kmer_list[i * B], C))
                    break;
            clus[s] = i;
            if (i >= n_clus) {
                // new kmer
                // add to kmer list
                ++n_clus;
                MYREALLOC(kmer_list, n_clus * B);
                memcpy(&kmer_list[(n_clus - 1) * B], kmer, B);
            }
        }
#ifdef DEBUG_CHECK_HASH_COLLISION
        uint64_t h64 = (uint64_t) (scm[0] >> 64);
        for (i = 0; i < n_clus; ++i)
            assert(h64 == MurmurHash64A(&kmer_list[i * B], (k - 1) / 4 + 1, murmur3_seed));
#endif
        free(kmer);
        free(kmer_list);
    }

    // add each cluster to syncmer database
    uint32_t s, *cnts;
    MYCALLOC(cnts, n_clus);
    for (s = 0; s < n; ++s)
        ++cnts[clus[s]];

    syncmer_t *syncmer;
    int i;
    for (i = 0; i < n_clus; ++i) {
        kv_pushp(syncmer_t, *scm_db, &syncmer);
        syncmer->h = (uint64_t) (scm[0] >> 64);
        syncmer->s = UINT64_MAX; // UINT64_MAX cannot be a smer as the first bit of smer is always zero
        syncmer->cov = 0;
        syncmer->del = 0;
        MYMALLOC(syncmer->m_pos, cnts[i]);
    }

    uint64_t smer;
    for (s = 0; s < n; ++s) {
        // update syncmer database
        syncmer = &scm_db->a[scm_db->n - n_clus + clus[s]];
        syncmer->m_pos[syncmer->cov++] = (uint64_t) scm[s];
        smer = sr_db->a[(uint64_t) scm[s] >> 32].s_mer[(uint32_t) ((uint64_t) scm[s]) >> 1];
        if (syncmer->s == UINT64_MAX) {
            syncmer->s = smer;
        } else if (syncmer->s != smer) {
            fprintf(stderr, "[E::%s] identical kmers have different smers\n", __func__);
            fprintf(stderr, "[E::%s] kmer hash  : %lu\n", __func__, syncmer->h);
            fprintf(stderr, "[E::%s] smer code 0: %lu; read id: %lu\n", __func__, syncmer->s, syncmer->m_pos[0] >> 32);
            fprintf(stderr, "[E::%s] smer code 1: %lu; read id: %lu\n", __func__, smer, (uint64_t) scm[s] >> 32);
            exit(EXIT_FAILURE);
        }
        // update read database
        sr_db->a[(uint64_t) scm[s] >> 32].k_mer[(uint32_t) ((uint64_t) scm[s]) >> 1] = (scm_db->n - n_clus + clus[s]) << 1;
    }

#ifdef DEBUG_CHECK_HASH_COLLISION
    if (n_clus > 1) {
        fprintf(stderr, "[DEBUG_CHECK_HASH_COLLISION::%s] hash collision: hash = %lu; clus = %d\n", 
                __func__, (uint64_t) (scm[0] >> 64), n_clus);
        for (i = 0; i < n_clus; ++i)
            fprintf(stderr, "[DEBUG_CHECK_HASH_COLLISION::%s] clus %d: read id %lu\n", 
                    __func__, i, scm_db->a[scm_db->n - n_clus + i].m_pos[0] >> 32);
    }
#endif    

    free(cnts);
    free(clus);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xf0, %rsp
movq %rdi, -0x8(%rbp)
movl %esi, -0xc(%rbp)
movq %rdx, -0x18(%rbp)
movq %rcx, -0x20(%rbp)
movl -0xc(%rbp), %eax
movl %eax, %edi
shlq $0x2, %rdi
callq 0x2320
movq %rax, -0x30(%rbp)
cmpl $0x1, -0xc(%rbp)
jne 0x14cb8
movl $0x1, -0x24(%rbp)
movq -0x30(%rbp), %rax
movl $0x0, (%rax)
jmp 0x1507f
movq -0x20(%rbp), %rax
movl 0x18(%rax), %eax
movl %eax, -0x3c(%rbp)
movl -0x3c(%rbp), %eax
subl $0x1, %eax
sarl $0x3, %eax
addl $0x1, %eax
shll $0x3, %eax
movl %eax, -0x48(%rbp)
movl -0x48(%rbp), %eax
sarl $0x3, %eax
movl %eax, -0x4c(%rbp)
movl $0x0, -0x24(%rbp)
movq $0x0, -0x70(%rbp)
movslq -0x48(%rbp), %rdi
shlq $0x0, %rdi
callq 0x2320
movq %rax, -0x68(%rbp)
movq $0x0, -0x88(%rbp)
movq -0x88(%rbp), %rax
movl -0xc(%rbp), %ecx
cmpq %rcx, %rax
jae 0x1506d
movq -0x8(%rbp), %rax
movq -0x88(%rbp), %rcx
shlq $0x4, %rcx
movl 0x4(%rax,%rcx), %eax
movq %rax, -0x80(%rbp)
movq -0x8(%rbp), %rax
movq -0x88(%rbp), %rcx
shlq $0x4, %rcx
movl (%rax,%rcx), %eax
shrl %eax
movl %eax, -0x74(%rbp)
movq -0x8(%rbp), %rax
movq -0x88(%rbp), %rcx
shlq $0x4, %rcx
movl (%rax,%rcx), %eax
andl $0x1, %eax
movl %eax, -0x58(%rbp)
movq -0x20(%rbp), %rax
movq 0x10(%rax), %rax
imulq $0x58, -0x80(%rbp), %rcx
addq %rcx, %rax
movq 0x40(%rax), %rax
movl -0x74(%rbp), %ecx
movl (%rax,%rcx,4), %eax
shrl %eax
movl %eax, -0x50(%rbp)
movl -0x50(%rbp), %eax
addl -0x3c(%rbp), %eax
subl $0x1, %eax
movl %eax, -0x54(%rbp)
cmpl $0x0, -0x58(%rbp)
je 0x14da5
movl -0x54(%rbp), %eax
andl $0x3, %eax
xorl $0x3, %eax
shll %eax
movl %eax, -0xb4(%rbp)
jmp 0x14db3
movl -0x50(%rbp), %eax
andl $0x3, %eax
shll %eax
movl %eax, -0xb4(%rbp)
movl -0xb4(%rbp), %eax
movl %eax, -0x5c(%rbp)
movl -0x54(%rbp), %eax
movl $0x4, %ecx
cltd
idivl %ecx
movl %eax, -0xb8(%rbp)
movl -0x50(%rbp), %eax
movl $0x4, %ecx
cltd
idivl %ecx
movl %eax, %ecx
movl -0xb8(%rbp), %eax
subl %ecx, %eax
addl $0x1, %eax
movl %eax, -0x40(%rbp)
movq -0x68(%rbp), %rdi
movq -0x20(%rbp), %rax
movq 0x10(%rax), %rax
imulq $0x58, -0x80(%rbp), %rcx
addq %rcx, %rax
movq 0x18(%rax), %rsi
movl -0x50(%rbp), %eax
movl $0x4, %ecx
cltd
idivl %ecx
cltq
addq %rax, %rsi
movslq -0x40(%rbp), %rdx
callq 0x22c0
cmpl $0x0, -0x58(%rbp)
je 0x14ec7
movl $0x0, -0x34(%rbp)
movl -0x40(%rbp), %eax
subl $0x1, %eax
movl %eax, -0x38(%rbp)
movl -0x34(%rbp), %eax
cmpl -0x38(%rbp), %eax
jge 0x14e9a
movq -0x68(%rbp), %rax
movslq -0x34(%rbp), %rcx
movzbl (%rax,%rcx), %eax
movl %eax, -0x44(%rbp)
movq -0x68(%rbp), %rax
movslq -0x38(%rbp), %rcx
movzbl (%rax,%rcx), %eax
movl %eax, %ecx
leaq 0x1f521(%rip), %rax     # 0x34380
movb (%rax,%rcx), %dl
movq -0x68(%rbp), %rax
movslq -0x34(%rbp), %rcx
movb %dl, (%rax,%rcx)
movslq -0x44(%rbp), %rcx
leaq 0x1f508(%rip), %rax     # 0x34380
movb (%rax,%rcx), %dl
movq -0x68(%rbp), %rax
movslq -0x38(%rbp), %rcx
movb %dl, (%rax,%rcx)
movl -0x34(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x34(%rbp)
movl -0x38(%rbp), %eax
addl $-0x1, %eax
movl %eax, -0x38(%rbp)
jmp 0x14e33
movl -0x34(%rbp), %eax
cmpl -0x38(%rbp), %eax
jne 0x14ec5
movq -0x68(%rbp), %rax
movslq -0x34(%rbp), %rcx
movzbl (%rax,%rcx), %eax
movl %eax, %ecx
leaq 0x1f4c9(%rip), %rax     # 0x34380
movb (%rax,%rcx), %dl
movq -0x68(%rbp), %rax
movslq -0x34(%rbp), %rcx
movb %dl, (%rax,%rcx)
jmp 0x14ec7
movl $0x0, -0x34(%rbp)
movl -0x34(%rbp), %eax
movl -0x40(%rbp), %ecx
subl $0x1, %ecx
cmpl %ecx, %eax
jge 0x14f34
movl -0x5c(%rbp), %ecx
movq -0x68(%rbp), %rax
movslq -0x34(%rbp), %rdx
movq %rdx, -0xc0(%rbp)
movzbl (%rax,%rdx), %edx
shll %cl, %edx
movq -0xc0(%rbp), %rcx
movb %dl, (%rax,%rcx)
movq -0x68(%rbp), %rax
movl -0x34(%rbp), %ecx
addl $0x1, %ecx
movslq %ecx, %rcx
movzbl (%rax,%rcx), %esi
movl $0x8, %ecx
subl -0x5c(%rbp), %ecx
sarl %cl, %esi
movq -0x68(%rbp), %rax
movslq -0x34(%rbp), %rcx
movzbl (%rax,%rcx), %edx
orl %esi, %edx
movb %dl, (%rax,%rcx)
movl -0x34(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x34(%rbp)
jmp 0x14ece
movl -0x5c(%rbp), %ecx
movq -0x68(%rbp), %rax
movl -0x40(%rbp), %edx
subl $0x1, %edx
movslq %edx, %rdx
movq %rdx, -0xc8(%rbp)
movzbl (%rax,%rdx), %edx
shll %cl, %edx
movq -0xc8(%rbp), %rcx
movb %dl, (%rax,%rcx)
movl -0x3c(%rbp), %eax
subl $0x1, %eax
movl $0x4, %ecx
cltd
idivl %ecx
addl $0x1, %eax
movl %eax, -0x40(%rbp)
movl -0x3c(%rbp), %eax
andl $0x3, %eax
movslq %eax, %rcx
leaq 0x1f501(%rip), %rax     # 0x34480
movzbl (%rax,%rcx), %esi
movq -0x68(%rbp), %rax
movl -0x40(%rbp), %ecx
subl $0x1, %ecx
movslq %ecx, %rcx
movzbl (%rax,%rcx), %edx
andl %esi, %edx
movb %dl, (%rax,%rcx)
movq -0x68(%rbp), %rdi
movslq -0x40(%rbp), %rax
addq %rax, %rdi
movl -0x48(%rbp), %eax
subl -0x40(%rbp), %eax
movslq %eax, %rdx
shlq $0x0, %rdx
xorl %esi, %esi
callq 0x21f0
movl $0x0, -0x34(%rbp)
movl -0x34(%rbp), %eax
cmpl -0x24(%rbp), %eax
jge 0x14ff7
movq -0x68(%rbp), %rdi
movq -0x70(%rbp), %rsi
movl -0x34(%rbp), %eax
imull -0x48(%rbp), %eax
cltq
addq %rax, %rsi
movl -0x4c(%rbp), %edx
callq 0x190d0
cmpl $0x0, %eax
je 0x14fea
jmp 0x14ff7
jmp 0x14fec
movl -0x34(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x34(%rbp)
jmp 0x14fbf
movl -0x34(%rbp), %edx
movq -0x30(%rbp), %rax
movq -0x88(%rbp), %rcx
movl %edx, (%rax,%rcx,4)
movl -0x34(%rbp), %eax
cmpl -0x24(%rbp), %eax
jl 0x15054
movl -0x24(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x24(%rbp)
movq -0x70(%rbp), %rdi
movl -0x24(%rbp), %eax
imull -0x48(%rbp), %eax
movslq %eax, %rsi
shlq $0x0, %rsi
callq 0x2360
movq %rax, -0x70(%rbp)
movq -0x70(%rbp), %rdi
movl -0x24(%rbp), %eax
subl $0x1, %eax
imull -0x48(%rbp), %eax
cltq
addq %rax, %rdi
movq -0x68(%rbp), %rsi
movslq -0x48(%rbp), %rdx
callq 0x22c0
jmp 0x15056
movq -0x88(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x88(%rbp)
jmp 0x14d08
movq -0x68(%rbp), %rdi
callq 0x2060
movq -0x70(%rbp), %rdi
callq 0x2060
movslq -0x24(%rbp), %rdi
movl $0x4, %esi
callq 0x2250
movq %rax, -0x98(%rbp)
movl $0x0, -0x8c(%rbp)
movl -0x8c(%rbp), %eax
cmpl -0xc(%rbp), %eax
jae 0x150d8
movq -0x98(%rbp), %rax
movq -0x30(%rbp), %rcx
movl -0x8c(%rbp), %edx
movslq (%rcx,%rdx,4), %rcx
movl (%rax,%rcx,4), %edx
addl $0x1, %edx
movl %edx, (%rax,%rcx,4)
movl -0x8c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x8c(%rbp)
jmp 0x1509e
movl $0x0, -0xa4(%rbp)
movl -0xa4(%rbp), %eax
cmpl -0x24(%rbp), %eax
jge 0x15216
jmp 0x150f3
movq -0x18(%rbp), %rax
movq (%rax), %rax
movq -0x18(%rbp), %rcx
cmpq 0x8(%rcx), %rax
jne 0x15164
movq -0x18(%rbp), %rax
cmpq $0x0, 0x8(%rax)
je 0x15123
movq -0x18(%rbp), %rax
movq 0x8(%rax), %rax
shlq %rax
movq %rax, -0xd0(%rbp)
jmp 0x15131
movl $0x2, %eax
movq %rax, -0xd0(%rbp)
jmp 0x15131
movq -0xd0(%rbp), %rcx
movq -0x18(%rbp), %rax
movq %rcx, 0x8(%rax)
movq -0x18(%rbp), %rax
movq 0x10(%rax), %rdi
movq -0x18(%rbp), %rax
movq 0x8(%rax), %rsi
shlq $0x5, %rsi
callq 0x2360
movq %rax, %rcx
movq -0x18(%rbp), %rax
movq %rcx, 0x10(%rax)
movq -0x18(%rbp), %rax
movq 0x10(%rax), %rax
movq -0x18(%rbp), %rdx
movq (%rdx), %rcx
movq %rcx, %rsi
addq $0x1, %rsi
movq %rsi, (%rdx)
shlq $0x5, %rcx
addq %rcx, %rax
movq %rax, -0xa0(%rbp)
movq -0x8(%rbp), %rax
movq 0x8(%rax), %rcx
movq -0xa0(%rbp), %rax
movq %rcx, (%rax)
movq -0xa0(%rbp), %rax
movq $-0x1, 0x8(%rax)
movq -0xa0(%rbp), %rax
movl 0x10(%rax), %ecx
andl $0x80000000, %ecx       # imm = 0x80000000
orl $0x0, %ecx
movl %ecx, 0x10(%rax)
movq -0xa0(%rbp), %rax
movl 0x10(%rax), %ecx
andl $0x7fffffff, %ecx       # imm = 0x7FFFFFFF
orl $0x0, %ecx
movl %ecx, 0x10(%rax)
movq -0x98(%rbp), %rax
movslq -0xa4(%rbp), %rcx
movl (%rax,%rcx,4), %eax
movl %eax, %edi
shlq $0x3, %rdi
callq 0x2320
movq %rax, %rcx
movq -0xa0(%rbp), %rax
movq %rcx, 0x18(%rax)
movl -0xa4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xa4(%rbp)
jmp 0x150e2
movl $0x0, -0x8c(%rbp)
movl -0x8c(%rbp), %eax
cmpl -0xc(%rbp), %eax
jae 0x1545f
movq -0x18(%rbp), %rax
movq (%rax), %rcx
movq 0x10(%rax), %rax
movslq -0x24(%rbp), %rdx
subq %rdx, %rcx
movq -0x30(%rbp), %rdx
movl -0x8c(%rbp), %esi
movslq (%rdx,%rsi,4), %rdx
addq %rdx, %rcx
shlq $0x5, %rcx
addq %rcx, %rax
movq %rax, -0xa0(%rbp)
movq -0x8(%rbp), %rax
movl -0x8c(%rbp), %ecx
shlq $0x4, %rcx
movq (%rax,%rcx), %rdx
movq -0xa0(%rbp), %rsi
movq 0x18(%rsi), %rax
movl 0x10(%rsi), %edi
movl %edi, %ecx
andl $0x7fffffff, %ecx       # imm = 0x7FFFFFFF
movl %edi, %r8d
incl %r8d
andl $0x7fffffff, %r8d       # imm = 0x7FFFFFFF
andl $0x80000000, %edi       # imm = 0x80000000
orl %r8d, %edi
movl %edi, 0x10(%rsi)
movq %rdx, (%rax,%rcx,8)
movq -0x20(%rbp), %rax
movq 0x10(%rax), %rax
movq -0x8(%rbp), %rcx
movl -0x8c(%rbp), %edx
shlq $0x4, %rdx
movq (%rcx,%rdx), %rcx
movq %rcx, %rdx
shrq $0x20, %rdx
imulq $0x58, %rdx, %rdx
movq 0x48(%rax,%rdx), %rax
shrl %ecx
movl %ecx, %ecx
movq (%rax,%rcx,8), %rax
movq %rax, -0xb0(%rbp)
movq -0xa0(%rbp), %rax
cmpq $-0x1, 0x8(%rax)
jne 0x15303
movq -0xb0(%rbp), %rcx
movq -0xa0(%rbp), %rax
movq %rcx, 0x8(%rax)
jmp 0x153fb
movq -0xa0(%rbp), %rax
movq 0x8(%rax), %rax
cmpq -0xb0(%rbp), %rax
je 0x153f9
movq 0x1ecd6(%rip), %rax     # 0x33ff8
movq %rax, -0xd8(%rbp)
movq (%rax), %rdi
leaq 0x191c8(%rip), %rsi     # 0x2e4fb
leaq 0x191ef(%rip), %rdx     # 0x2e529
movq %rdx, -0xe8(%rbp)
xorl %eax, %eax
movb %al, -0xd9(%rbp)
callq 0x2290
movq -0xe8(%rbp), %rdx
movq -0xd8(%rbp), %rcx
movb -0xd9(%rbp), %al
movq (%rcx), %rdi
movq -0xa0(%rbp), %rcx
movq (%rcx), %rcx
leaq 0x191c8(%rip), %rsi     # 0x2e53e
callq 0x2290
movq -0xe8(%rbp), %rdx
movq -0xd8(%rbp), %rcx
movb -0xd9(%rbp), %al
movq (%rcx), %rdi
movq -0xa0(%rbp), %rsi
movq 0x8(%rsi), %rcx
movq 0x18(%rsi), %rsi
movl 0x4(%rsi), %esi
movl %esi, %r8d
leaq 0x191aa(%rip), %rsi     # 0x2e558
callq 0x2290
movq -0xd8(%rbp), %rax
movq (%rax), %rdi
movq -0xb0(%rbp), %rcx
movq -0x8(%rbp), %rax
movl -0x8c(%rbp), %edx
shlq $0x4, %rdx
movq (%rax,%rdx), %r8
shrq $0x20, %r8
leaq 0x1919f(%rip), %rsi     # 0x2e580
leaq 0x19141(%rip), %rdx     # 0x2e529
movb $0x0, %al
callq 0x2290
movl $0x1, %edi
callq 0x2450
jmp 0x153fb
movq -0x18(%rbp), %rax
movq (%rax), %rdx
movslq -0x24(%rbp), %rax
subq %rax, %rdx
movq -0x30(%rbp), %rax
movl -0x8c(%rbp), %ecx
movl %ecx, %esi
movslq (%rax,%rsi,4), %rax
addq %rax, %rdx
addq %rdx, %rdx
movq -0x20(%rbp), %rax
movq 0x10(%rax), %rax
movq -0x8(%rbp), %rcx
shlq $0x4, %rsi
movq (%rcx,%rsi), %rcx
movq %rcx, %rsi
shrq $0x20, %rsi
imulq $0x58, %rsi, %rsi
movq 0x50(%rax,%rsi), %rax
shrl %ecx
movl %ecx, %ecx
movq %rdx, (%rax,%rcx,8)
movl -0x8c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x8c(%rbp)
jmp 0x15220
movq -0x98(%rbp), %rdi
callq 0x2060
movq -0x30(%rbp), %rdi
callq 0x2060
addq $0xf0, %rsp
popq %rbp
retq
nopl (%rax)