// File: /workspace/github_cpp_makefile_star2_O3/karel-brinda[P]ococo/src/caller.h
// Function: ococo::caller_t<unsigned short, 3, 4>::run()
void caller_t<T, counter_size, refbase_size>::run() {
    /*
     * Process alignments.
     */
    ococo::info("Starting the main loop.\n");

    int32_t r;
    b              = bam_init1();
    int64_t n_upd0 = 0;
    int64_t i_read = 0;
    while ((r = sam_read1(params->sam_file, header, b)) >= 0) {
        const char *rname          = bam_get_qname(b);
        const uint8_t *seq         = bam_get_seq(b);
        const uint8_t *qual        = bam_get_qual(b);
        const uint32_t *cigar      = bam_get_cigar(b);
        const int32_t n_cigar      = b->core.n_cigar;
        const int32_t seqid        = b->core.tid;
        const int64_t mappping_pos = b->core.pos;
        const int32_t mapq         = b->core.qual;
        const int32_t flags        = b->core.flag;

        bool read_ok = check_read(seqid, flags, mapq);
        if (!read_ok) {
            continue;
        }

        int32_t ref_pos = mappping_pos;
        for (int32_t cigar_grp = 0, read_pos = 0; cigar_grp < n_cigar;
             cigar_grp++) {
            const int32_t op = bam_cigar_op(cigar[cigar_grp]);
            const int32_t ol = bam_cigar_oplen(cigar[cigar_grp]);

            const int32_t next_read_pos = read_pos + ol;
            switch (op) {
                case BAM_CMATCH:
                case BAM_CDIFF:
                case BAM_CEQUAL:

                    for (; read_pos < next_read_pos; read_pos++, ref_pos++) {
                        const uint8_t nt16 = bam_seqi(seq, read_pos);
                        const uint8_t nt4  = ococo::nt16_nt4[nt16];
                        // const char nt256 =
                        // ococo::nt16_nt256[nt16];
                        const int32_t bq = qual[read_pos];

                        if (bq != 0xff && bq < (stats->params->min_baseq)) {
                            continue;
                        }

                        if (nt4 == 0x4) {
                            continue;
                        }

                        stats->seq_stats[seqid][ref_pos] = stats->increment(
                            stats->seq_stats[seqid][ref_pos], nt4);

                        if (stats->params->mode == ococo::mode_t::REALTIME) {
                            stats->call_consensus_position(params->vcf_file,
                                                           params->pileup_file,
                                                           seqid, ref_pos);
                        }
                    }

                    break;

                case BAM_CDEL:
                case BAM_CREF_SKIP:
                    ref_pos += ol;
                    break;

                case BAM_CSOFT_CLIP:
                    read_pos += ol;
                    break;

                case BAM_CBACK:
                    ref_pos -= ol;
                    break;

                case BAM_CINS:
                    read_pos += ol;
                    break;

                case BAM_CPAD:
                case BAM_CHARD_CLIP:
                    break;
            }

        }

        if (stats->params->log_file != nullptr) {
            fprintf(stats->params->log_file,
                    "%" PRIu64 "\t%s\t%" PRIu64 "\n", i_read, rname,
                    stats->params->n_upd - n_upd0);
            n_upd0 = stats->params->n_upd;
        }

        i_read += 1;
    }

    /*
     * Call final consensus and export stats.
     */

    if (stats->params->mode == ococo::mode_t::BATCH) {
        stats->call_consensus(params->vcf_file, params->pileup_file);

        if (params->fasta_out_fn.size() > 0) {
            int error_code = stats->save_fasta(params->fasta_out_fn);
            if (error_code != 0) {
                ococo::error("FASTA '%s' could not be saved.\n",
                             params->fasta_out_fn.c_str());
                return_code = EXIT_FAILURE;
            }
        }
    }

    if (params->stats_out_fn.size() > 0) {
        ococo::info("Saving statistics ('%s').\n",
                    params->stats_out_fn.c_str());

        int error_code = stats->export_stats(params->stats_out_fn);
        if (error_code != 0) {
            ococo::error("Statistics could not be saved ('%s').\n",
                         params->stats_out_fn.c_str());
            return_code = EXIT_FAILURE;
        }
    }
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x58, %rsp
movq %rdi, %rbx
leaq 0x47709(%rip), %rdi     # 0x4ea33
xorl %eax, %eax
callq 0x4cae
callq 0x1475a
movq %rax, 0x10(%rbx)
movq 0x18(%rbx), %rsi
movq 0x28(%rbx), %rcx
movq 0x198(%rcx), %rdi
movq %rax, %rdx
callq 0x16e4f
testl %eax, %eax
movq %rbx, 0x8(%rsp)
js 0x75d3
leaq 0x46c9f(%rip), %r15     # 0x4e004
xorl %r12d, %r12d
xorl %r14d, %r14d
movq 0x10(%rbx), %rdx
movq 0x8(%rdx), %rdi
btq $0x22, %rdi
movq %rbx, %r8
jb 0x75b4
movslq (%rdx), %rsi
movq 0x20(%r8), %rax
movq 0x8(%rax), %rcx
movq %rsi, 0x10(%rsp)
cmpb $0x1, (%rcx,%rsi)
jne 0x75b4
movl %edi, %ecx
shrl $0x10, %ecx
movzbl %cl, %ecx
movq 0x30(%rax), %rax
cmpl %ecx, 0x1b0(%rax)
jg 0x75b4
movq 0x28(%rdx), %rcx
movq %rdi, %r9
shrq $0x30, %r9
je 0x7572
movq %r12, 0x20(%rsp)
movq %r14, 0x28(%rsp)
leal (,%r9,4), %eax
shrl $0x18, %edi
movq %rcx, 0x18(%rsp)
addq %rcx, %rdi
leaq (%rdi,%rax), %r12
movl 0x10(%rdx), %ecx
incl %ecx
sarl %ecx
movslq %ecx, %rcx
movl 0x4(%rdx), %ebp
addq %rax, %rcx
addq %rdi, %rcx
movq %rcx, 0x30(%rsp)
xorl %r10d, %r10d
xorl %r14d, %r14d
movq %rdi, 0x40(%rsp)
movq %r9, 0x38(%rsp)
movl (%rdi,%r10,4), %eax
movl %eax, %esi
andl $0xf, %esi
cmpl $0x9, %esi
ja 0x754f
movl %eax, %ecx
shrl $0x4, %ecx
leal (%rcx,%r14), %edx
movslq (%r15,%rsi,4), %rsi
addq %r15, %rsi
jmpq *%rsi
cmpl $0x10, %eax
jb 0x754f
movq %r10, 0x48(%rsp)
movslq %ebp, %rbp
movslq %r14d, %r14
movslq %edx, %r13
movq 0x30(%rsp), %rax
leaq (%rax,%r14), %rbx
leal (,%r14,4), %r15d
movq %r13, 0x50(%rsp)
movl %r14d, %eax
sarl %eax
cltq
movzbl (%r12,%rax), %eax
movl %r15d, %ecx
notb %cl
andb $0x4, %cl
shrl %cl, %eax
andl $0xf, %eax
leaq 0x486e2(%rip), %rcx     # 0x4fb60
movb (%rax,%rcx), %cl
movzbl (%rbx), %edx
cmpl $0xff, %edx
je 0x749c
movq 0x20(%r8), %rsi
movq 0x30(%rsi), %rsi
cmpl %edx, 0x1b4(%rsi)
jg 0x7514
movl $0xfee9, %edx           # imm = 0xFEE9
btl %eax, %edx
jb 0x7514
movq 0x20(%r8), %rax
movq 0x28(%rax), %rax
movq %r12, %r13
movq 0x10(%rsp), %r12
movq (%rax,%r12,8), %rax
movzwl (%rax,%rbp,2), %edi
movzbl %cl, %esi
callq 0x9806
movq 0x8(%rsp), %r8
movq 0x20(%r8), %rdi
movq 0x28(%rdi), %rcx
movq (%rcx,%r12,8), %rcx
movq %r13, %r12
movq 0x50(%rsp), %r13
movw %ax, (%rcx,%rbp,2)
movq 0x30(%rdi), %rax
cmpl $0x1, 0x1a8(%rax)
jne 0x7514
movq 0x28(%r8), %rax
movq 0x180(%rax), %rsi
movq 0x188(%rax), %rdx
movq 0x10(%rsp), %rcx
movq %rbp, %r8
callq 0x98ac
movq 0x8(%rsp), %r8
incq %r14
incq %rbp
incq %rbx
addl $0x4, %r15d
cmpq %r13, %r14
jl 0x745e
leaq 0x46ad3(%rip), %r15     # 0x4e004
movq 0x40(%rsp), %rdi
movq 0x38(%rsp), %r9
movq 0x48(%rsp), %r10
jmp 0x754f
addl %ebp, %ecx
movl %ecx, %ebp
jmp 0x754f
movl %edx, %r14d
jmp 0x754f
subl %ecx, %ebp
incq %r10
cmpq %r9, %r10
jne 0x740d
movq 0x20(%r8), %rax
movq 0x30(%rax), %rax
movq 0x28(%rsp), %r14
movq 0x20(%rsp), %r12
movq 0x18(%rsp), %rcx
movq 0x1a0(%rax), %rdi
testq %rdi, %rdi
je 0x75ad
movq 0x208(%rax), %r8
subq %r12, %r8
leaq 0x474bd(%rip), %rsi     # 0x4ea4c
movq %r14, %rdx
xorl %eax, %eax
callq 0x4770
movq 0x8(%rsp), %r8
movq 0x20(%r8), %rax
movq 0x30(%rax), %rax
movq 0x208(%rax), %r12
incq %r14
movq 0x10(%r8), %rdx
movq 0x18(%r8), %rsi
movq 0x28(%r8), %rax
movq 0x198(%rax), %rdi
movq %r8, %rbx
callq 0x16e4f
testl %eax, %eax
jns 0x736b
movq 0x20(%rbx), %rdi
movq 0x28(%rbx), %rsi
movq 0x30(%rdi), %rax
cmpl $0x0, 0x1a8(%rax)
je 0x765e
cmpq $0x0, 0x128(%rsi)
je 0x764f
movq 0x120(%rsi), %rsi
leaq 0x47478(%rip), %rdi     # 0x4ea78
xorl %eax, %eax
callq 0x4cae
movq 0x8(%rsp), %rax
movq 0x20(%rax), %rdi
movl $0x120, %esi            # imm = 0x120
movq 0x8(%rsp), %rax
addq 0x28(%rax), %rsi
callq 0x9bea
movq 0x8(%rsp), %rcx
testl %eax, %eax
je 0x764f
movq 0x28(%rcx), %rax
movq 0x120(%rax), %rsi
leaq 0x47455(%rip), %rdi     # 0x4ea93
xorl %eax, %eax
movq %rcx, %rbx
callq 0x4b3a
movl $0x1, 0x4(%rbx)
addq $0x58, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x180(%rsi), %rax
movq 0x188(%rsi), %rdx
movq %rax, %rsi
callq 0x9a0e
movq 0x8(%rsp), %rax
movq 0x28(%rax), %rsi
cmpq $0x0, 0x108(%rsi)
je 0x75e8
addq $0x100, %rsi            # imm = 0x100
movq 0x20(%rax), %rdi
callq 0x9a9c
movq 0x8(%rsp), %rcx
movq 0x28(%rcx), %rsi
testl %eax, %eax
je 0x75e8
movq 0x100(%rsi), %rsi
leaq 0x4739e(%rip), %rdi     # 0x4ea58
xorl %eax, %eax
callq 0x4b3a
movq 0x8(%rsp), %rax
movl $0x1, 0x4(%rax)
movq 0x28(%rax), %rsi
jmp 0x75e8