// File: /workspace/github_cpp_makefile_star2_O2/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 0x3c273(%rip), %rdi     # 0x41a53
xorl %eax, %eax
callq 0xa59c
callq 0x11215
movq %rbx, %r8
movq %rax, %rdx
movq %rax, 0x10(%rbx)
leaq 0x3b807(%rip), %r12     # 0x41004
movq $0x0, 0x8(%rsp)
movq $0x0, 0x18(%rsp)
movq %rbx, (%rsp)
movq 0x18(%r8), %rsi
movq 0x28(%r8), %rax
movq 0x198(%rax), %rdi
movq %r8, %r14
callq 0x132b0
testl %eax, %eax
js 0x5a7e
movq 0x10(%r14), %rax
movq 0x28(%rax), %r15
movq 0x8(%rax), %rbp
movl 0x10(%rax), %ebx
movl (%rax), %esi
movl 0x4(%rax), %r13d
movl %ebp, %eax
shrl $0x10, %eax
movzbl %al, %ecx
movq %rbp, %rax
shrq $0x20, %rax
movzwl %ax, %edx
movq %r14, %rdi
movl %esi, %r14d
callq 0x7928
testb %al, %al
je 0x5a0d
movq %rbp, %rdx
shrq $0x30, %rdx
leal (,%rdx,4), %eax
shrl $0x18, %ebp
movq %r15, 0x20(%rsp)
addq %r15, %rbp
movl %r14d, %ecx
leaq (%rax,%rbp), %r14
incl %ebx
sarl %ebx
movslq %ebx, %rdi
movq %rdx, %rsi
movl %ecx, 0x14(%rsp)
movslq %ecx, %rcx
movq %rcx, 0x48(%rsp)
addq %rax, %rdi
addq %rbp, %rdi
movq %rdi, 0x28(%rsp)
xorl %edi, %edi
xorl %r15d, %r15d
movq (%rsp), %r8
movq %rbp, 0x38(%rsp)
movq %rdx, 0x30(%rsp)
cmpq %rsi, %rdi
je 0x5a13
movl (%rbp,%rdi,4), %eax
movl %eax, %ecx
andl $0xf, %ecx
cmpl $0x9, %ecx
ja 0x5a05
shrl $0x4, %eax
leal (%rax,%r15), %edx
movslq (%r12,%rcx,4), %rcx
addq %r12, %rcx
jmpq *%rcx
movq %rdi, 0x40(%rsp)
movslq %r15d, %r15
movslq %edx, %r12
movslq %r13d, %r13
leal (,%r15,4), %ebp
movq 0x28(%rsp), %rax
leaq (%rax,%r15), %rbx
movq %r12, 0x50(%rsp)
cmpq %r12, %r15
jge 0x59dd
movl %r15d, %eax
sarl %eax
cltq
movzbl (%r14,%rax), %eax
movl %ebp, %ecx
notb %cl
andb $0x4, %cl
shrl %cl, %eax
andl $0xf, %eax
leaq 0x3b759(%rip), %rcx     # 0x41090
movb (%rax,%rcx), %cl
movzbl (%rbx), %edx
cmpl $0xff, %edx
je 0x5955
movq 0x20(%r8), %rsi
movq 0x30(%rsi), %rsi
cmpl %edx, 0x1b4(%rsi)
jg 0x59cc
movl $0xfee9, %edx           # imm = 0xFEE9
btl %eax, %edx
jb 0x59cc
movq 0x20(%r8), %rax
movq 0x28(%rax), %rax
movq %r14, %r12
movq 0x48(%rsp), %r14
movq (%rax,%r14,8), %rax
movzwl (%rax,%r13,2), %edi
movzbl %cl, %esi
callq 0x7950
movq (%rsp), %r8
movq 0x20(%r8), %rdi
movq 0x28(%rdi), %rcx
movq (%rcx,%r14,8), %rcx
movq %r12, %r14
movq 0x50(%rsp), %r12
movw %ax, (%rcx,%r13,2)
movq 0x30(%rdi), %rax
cmpl $0x1, 0x1a8(%rax)
jne 0x59cc
movq 0x28(%r8), %rax
movq 0x180(%rax), %rsi
movq 0x188(%rax), %rdx
movl 0x14(%rsp), %ecx
movq %r13, %r8
callq 0x79c0
movq (%rsp), %r8
incq %r15
incq %r13
addl $0x4, %ebp
incq %rbx
jmp 0x590f
leaq 0x3b620(%rip), %r12     # 0x41004
movq 0x38(%rsp), %rbp
movq 0x30(%rsp), %rsi
movq 0x40(%rsp), %rdi
jmp 0x5a05
addl %r13d, %eax
movl %eax, %r13d
jmp 0x5a05
movl %edx, %r15d
jmp 0x5a05
subl %eax, %r13d
incq %rdi
jmp 0x58c0
movq (%rsp), %r8
jmp 0x5a75
movq 0x20(%r8), %rax
movq 0x30(%rax), %rax
movq 0x1a0(%rax), %rdi
testq %rdi, %rdi
movq 0x20(%rsp), %rcx
je 0x5a68
movq 0x208(%rax), %r8
subq 0x18(%rsp), %r8
leaq 0x3c02d(%rip), %rsi     # 0x41a6c
movq 0x8(%rsp), %rbx
movq %rbx, %rdx
xorl %eax, %eax
callq 0x4770
movq (%rsp), %r8
movq 0x20(%r8), %rax
movq 0x30(%rax), %rax
movq 0x208(%rax), %rax
movq %rax, 0x18(%rsp)
jmp 0x5a6d
movq 0x8(%rsp), %rbx
incq %rbx
movq %rbx, 0x8(%rsp)
movq 0x10(%r8), %rdx
jmp 0x5813
movq 0x20(%r14), %rdi
movq 0x28(%r14), %rsi
movq 0x30(%rdi), %rax
cmpl $0x0, 0x1a8(%rax)
je 0x5b06
cmpq $0x0, 0x128(%rsi)
je 0x5af7
movq 0x120(%rsi), %rsi
leaq 0x3bfed(%rip), %rdi     # 0x41a98
xorl %eax, %eax
callq 0xa59c
movq (%rsp), %rax
movq 0x20(%rax), %rdi
movl $0x120, %esi            # imm = 0x120
movq (%rsp), %rax
addq 0x28(%rax), %rsi
callq 0x7cbc
movq (%rsp), %rcx
testl %eax, %eax
je 0x5af7
movq 0x28(%rcx), %rax
movq 0x120(%rax), %rsi
leaq 0x3bfcd(%rip), %rdi     # 0x41ab3
xorl %eax, %eax
movq %rcx, %rbx
callq 0xa428
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 0x7b0c
movq (%rsp), %rax
movq 0x28(%rax), %rsi
cmpq $0x0, 0x108(%rsi)
je 0x5a93
addq $0x100, %rsi            # imm = 0x100
movq 0x20(%rax), %rdi
callq 0x7b88
movq (%rsp), %rcx
movq 0x28(%rcx), %rsi
testl %eax, %eax
je 0x5a93
movq 0x100(%rsi), %rsi
leaq 0x3bf18(%rip), %rdi     # 0x41a78
xorl %eax, %eax
callq 0xa428
movq (%rsp), %rax
movl $0x1, 0x4(%rax)
movq 0x28(%rax), %rsi
jmp 0x5a93
nop