// File: /workspace/github_c_makefile_star2_O3/samtools[P]htslib/cram/cram_encode.c
// Function: cram_put_bam_seq
int cram_put_bam_seq(cram_fd *fd, bam_seq_t *b) {
    cram_container *c;

    if (!fd->ctr) {
        fd->ctr = cram_new_container(fd->seqs_per_slice,
                                     fd->slices_per_container);
        if (!fd->ctr)
            return -1;
        fd->ctr->record_counter = fd->record_counter;

        pthread_mutex_lock(&fd->ref_lock);
        fd->ctr->no_ref = fd->no_ref;
        fd->ctr->embed_ref = fd->embed_ref;
        pthread_mutex_unlock(&fd->ref_lock);
    }
    c = fd->ctr;

    int embed_ref = c->embed_ref;

    if (!c->slice || c->curr_rec == c->max_rec ||
        (bam_ref(b) != c->curr_ref && c->curr_ref >= -1) ||
        (c->s_num_bases + c->s_aux_bytes >= fd->bases_per_slice)) {
        int slice_rec, curr_rec, multi_seq = fd->multi_seq == 1;
        int curr_ref = c->slice ? c->curr_ref : bam_ref(b);

        /*
         * Start packing slices when we routinely have under 1/4tr full.
         *
         * This option isn't available if we choose to embed references
         * since we can only have one per slice.
         *
         * The multi_seq var here refers to our intention for the next slice.
         * This slice has already been encoded so we output as-is.
         */
        if (fd->multi_seq == -1 && c->curr_rec < c->max_rec/4+10 &&
            fd->last_slice && fd->last_slice < c->max_rec/4+10 &&
            embed_ref<=0) {
            if (!c->multi_seq)
                hts_log_info("Multi-ref enabled for next container");
            multi_seq = 1;
        } else if (fd->multi_seq == 1) {
            pthread_mutex_lock(&fd->metrics_lock);
            if (fd->last_RI_count <= c->max_slice && fd->multi_seq_user != 1) {
                multi_seq = 0;
                hts_log_info("Multi-ref disabled for next container");
            }
            pthread_mutex_unlock(&fd->metrics_lock);
        }

        slice_rec = c->slice_rec;
        curr_rec  = c->curr_rec;

        if (CRAM_MAJOR_VERS(fd->version) == 1 ||
            c->curr_rec == c->max_rec || fd->multi_seq != 1 || !c->slice ||
            c->s_num_bases + c->s_aux_bytes >= fd->bases_per_slice) {
            if (NULL == (c = cram_next_container(fd, b))) {
                if (fd->ctr) {
                    // prevent cram_close attempting to flush
                    fd->ctr_mt = fd->ctr; // delay free when threading
                    fd->ctr = NULL;
                }
                return -1;
            }
        }

        /*
         * Due to our processing order, some things we've already done we
         * cannot easily undo. So when we first notice we should be packing
         * multiple sequences per container we emit the small partial
         * container as-is and then start a fresh one in a different mode.
         */
        if (multi_seq == 0 && fd->multi_seq == 1 && fd->multi_seq_user == -1) {
            // User selected auto-mode, we're currently using multi-seq, but
            // have detected we don't need to.  Switch back to auto.
            fd->multi_seq = -1;
        } else if (multi_seq) {
            // We detected we need multi-seq
            fd->multi_seq = 1;
            c->multi_seq = 1;
            c->pos_sorted = 0;

            // Cram_next_container may end up flushing an existing one and
            // triggering fd->embed_ref=2 if no reference is found.
            // Embedded refs are incompatible with multi-seq, so we bail
            // out and switch to no_ref in this scenario.  We do this
            // within the container only, as multi_seq may be temporary
            // and we switch back away from it again.
            pthread_mutex_lock(&fd->ref_lock);
            if (fd->embed_ref > 0 && c->curr_rec == 0 && c->curr_slice == 0) {
                hts_log_warning("Changing from embed_ref to no_ref mode");
                // Should we update fd->embed_ref and no_ref here too?
                // Doing so means if we go into multi-seq and back out
                // again, eg due a cluster of tiny refs in the middle of
                // much larger ones, then we bake in no-ref mode.
                //
                // However for unsorted data we're realistically not
                // going to switch back.
                c->embed_ref = fd->embed_ref = 0; // or -1 for auto?
                c->no_ref = fd->no_ref = 1;
            }
            pthread_mutex_unlock(&fd->ref_lock);

            if (!c->refs_used) {
                pthread_mutex_lock(&fd->ref_lock);
                c->refs_used = calloc(fd->refs->nref, sizeof(int));
                pthread_mutex_unlock(&fd->ref_lock);
                if (!c->refs_used)
                    return -1;
            }
        }

        fd->last_slice = curr_rec - slice_rec;
        c->slice_rec = c->curr_rec;

        // Have we seen this reference before?
        if (bam_ref(b) >= 0 && curr_ref >= 0 && bam_ref(b) != curr_ref &&
            embed_ref<=0 && !fd->unsorted && multi_seq) {

            if (!c->refs_used) {
                pthread_mutex_lock(&fd->ref_lock);
                c->refs_used = calloc(fd->refs->nref, sizeof(int));
                pthread_mutex_unlock(&fd->ref_lock);
                if (!c->refs_used)
                    return -1;
            } else if (c->refs_used && c->refs_used[bam_ref(b)]) {
                pthread_mutex_lock(&fd->ref_lock);
                fd->unsorted = 1;
                fd->multi_seq = 1;
                pthread_mutex_unlock(&fd->ref_lock);
            }
        }

        c->curr_ref = bam_ref(b);
        if (c->refs_used && c->curr_ref >= 0) c->refs_used[c->curr_ref]++;
    }

    if (!c->bams) {
        /* First time through, allocate a set of bam pointers */
        pthread_mutex_lock(&fd->bam_list_lock);
        if (fd->bl) {
            spare_bams *spare = fd->bl;
            c->bams = spare->bams;
            fd->bl = spare->next;
            free(spare);
        } else {
            c->bams = calloc(c->max_c_rec, sizeof(bam_seq_t *));
            if (!c->bams) {
                pthread_mutex_unlock(&fd->bam_list_lock);
                return -1;
            }
        }
        pthread_mutex_unlock(&fd->bam_list_lock);
    }

    /* Copy or alloc+copy the bam record, for later encoding */
    if (c->bams[c->curr_c_rec]) {
        if (bam_copy1(c->bams[c->curr_c_rec], b) == NULL)
            return -1;
    } else {
        c->bams[c->curr_c_rec] = bam_dup1(b);
        if (c->bams[c->curr_c_rec] == NULL)
            return -1;
    }
    if (bam_seq_len(b)) {
        c->s_num_bases += bam_seq_len(b);
    } else {
        // No sequence in BAM record.  CRAM doesn't directly support this
        // case, it ends up being stored as a string of N's for each query
        // consuming CIGAR operation.  As this can become very inefficient
        // in time and memory, data where the query length is excessively
        // long are rejected.
        hts_pos_t qlen = bam_cigar2qlen(b->core.n_cigar, bam_get_cigar(b));
        if (qlen > 100000000) {
            hts_log_error("CIGAR query length %"PRIhts_pos
                          " for read \"%s\" is too long",
                          qlen, bam_get_qname(b));
            return -1;
        }
        c->s_num_bases += qlen;
    }
    c->curr_rec++;
    c->curr_c_rec++;
    c->s_aux_bytes += bam_get_l_aux(b);
    c->n_mapped += (bam_flag(b) & BAM_FUNMAP) ? 0 : 1;
    fd->record_counter++;

    return 0;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x18, %rsp
movq %rsi, %r14
movq %rdi, %rbx
movq 0x38(%rdi), %r15
testq %r15, %r15
jne 0x4779f
movl 0x214(%rbx), %edi
movl 0x21c(%rbx), %esi
callq 0x4fc97
movq %rax, 0x38(%rbx)
testq %rax, %rax
je 0x47eb9
movq 0x28(%rbx), %rcx
movq %rcx, 0x18(%rax)
leaq 0x88f0(%rbx), %r15
movq %r15, %rdi
callq 0x4750
movq 0x38(%rbx), %rax
movq 0x220(%rbx), %rcx
movq %rcx, 0xe8(%rax)
movq %r15, %rdi
callq 0x4340
movq 0x38(%rbx), %r15
movl 0xe8(%r15), %ebp
movq 0x90(%r15), %rax
testq %rax, %rax
je 0x477ef
movl 0x68(%r15), %ecx
cmpl 0x64(%r15), %ecx
je 0x477ef
movl 0x78(%r15), %ecx
cmpl %ecx, 0x8(%r14)
setne %dl
cmpl $-0x1, %ecx
setge %cl
testb %cl, %dl
jne 0x477ef
movq 0x290(%r15), %rcx
addq 0x288(%r15), %rcx
movslq 0x218(%rbx), %rdx
cmpq %rdx, %rcx
jb 0x47d59
movl 0x889c(%rbx), %ecx
xorl %r12d, %r12d
cmpl $0x1, %ecx
sete %dl
leaq 0x78(%r15), %rsi
leaq 0x8(%r14), %r13
testq %rax, %rax
cmoveq %r13, %rsi
movl (%rsi), %eax
movl %eax, 0x14(%rsp)
cmpl $-0x1, %ecx
je 0x47888
xorl %r12d, %r12d
cmpl $0x1, %ecx
jne 0x478e8
movq %r13, 0x8(%rsp)
movq %r14, %r13
leaq 0x88c8(%rbx), %r12
movq %r12, %rdi
callq 0x4750
movl 0x8898(%rbx), %eax
movl $0x1, %r14d
cmpl 0x58(%r15), %eax
jg 0x47873
cmpl $0x1, 0x88a0(%rbx)
je 0x47873
leaq 0x52422(%rip), %rsi     # 0x99c7f
leaq 0x52451(%rip), %rdx     # 0x99cb5
xorl %r14d, %r14d
movl $0x4, %edi
xorl %eax, %eax
callq 0x13de5
movq %r12, %rdi
callq 0x4340
movl %r14d, %r12d
movq %r13, %r14
movq 0x8(%rsp), %r13
jmp 0x478e8
movb %dl, %r12b
movl 0x64(%r15), %ecx
leal 0x3(%rcx), %eax
testl %ecx, %ecx
cmovnsl %ecx, %eax
sarl $0x2, %eax
addl $0xa, %eax
cmpl %eax, 0x68(%r15)
jge 0x478e8
movl 0x8894(%rbx), %ecx
testl %ecx, %ecx
je 0x478e8
cmpl %eax, %ecx
setl %al
testl %ebp, %ebp
setle %cl
andb %al, %cl
cmpb $0x1, %cl
jne 0x478e8
movl $0x1, %r12d
cmpl $0x0, 0xac(%r15)
jne 0x478e8
leaq 0x523aa(%rip), %rsi     # 0x99c7f
leaq 0x523b4(%rip), %rdx     # 0x99c90
movl $0x4, %edi
xorl %eax, %eax
callq 0x13de5
movl %ebp, 0x10(%rsp)
movl 0x68(%r15), %ebp
movl 0x74(%r15), %eax
movl %eax, 0x8(%rsp)
movl 0xc(%rbx), %esi
movl %esi, %eax
andl $0xffffff00, %eax       # imm = 0xFFFFFF00
cmpl $0x100, %eax            # imm = 0x100
je 0x47940
cmpl 0x64(%r15), %ebp
je 0x47940
cmpl $0x1, 0x889c(%rbx)
jne 0x47940
cmpq $0x0, 0x90(%r15)
je 0x47940
movq 0x290(%r15), %rax
addq 0x288(%r15), %rax
movslq 0x218(%rbx), %rcx
cmpq %rcx, %rax
jb 0x47b72
movq 0x38(%rbx), %r15
cmpl $-0x2, 0x78(%r15)
jne 0x47953
movl (%r13), %eax
movl %eax, 0x78(%r15)
cmpq $0x0, 0x90(%r15)
je 0x47965
movq %r15, %rdi
callq 0x47686
movl 0x5c(%r15), %eax
cmpl 0x58(%r15), %eax
jne 0x47a90
movslq 0x4c(%rbx), %r9
movq 0x8(%r15), %r8
movq %r9, %rax
subq %r8, %rax
incq %rax
movq %rax, 0x10(%r15)
movl 0x4(%r15), %ecx
leaq 0x52678(%rip), %rsi     # 0x9a00b
leaq 0x52685(%rip), %rdx     # 0x9a01f
movl $0x4, %edi
xorl %eax, %eax
callq 0x13de5
movq %rbx, %rdi
movq %r15, %rsi
callq 0x51009
cmpl $-0x1, %eax
je 0x47b09
cmpq $0x0, 0x88b8(%rbx)
jne 0x47a1e
movl %r12d, 0x4(%rsp)
cmpl $0x0, 0x58(%r15)
jle 0x479fe
xorl %r12d, %r12d
movq 0x88(%r15), %rax
movq (%rax,%r12,8), %rdi
callq 0x50127
movq 0x88(%r15), %rax
movq $0x0, (%rax,%r12,8)
incq %r12
movslq 0x58(%r15), %rax
cmpq %rax, %r12
jl 0x479d3
movq $0x0, 0x90(%r15)
movl $0x0, 0x5c(%r15)
movq %r15, %rdi
callq 0x4fe2e
movl 0x4(%rsp), %r12d
movl 0x214(%rbx), %edi
movl 0x21c(%rbx), %esi
callq 0x4fc97
movq %rax, 0x38(%rbx)
testq %rax, %rax
je 0x47eb9
movq %rax, %r15
movl %ebp, 0x4(%rsp)
movq %r13, %rbp
movq %r14, %r13
movl %r12d, %r14d
leaq 0x88f0(%rbx), %r12
movq %r12, %rdi
callq 0x4750
movq 0x220(%rbx), %rax
movq %rax, 0xe8(%r15)
movq 0x28(%rbx), %rax
movq %rax, 0x18(%r15)
movq %r12, %rdi
movl %r14d, %r12d
movq %r13, %r14
movq %rbp, %r13
movl 0x4(%rsp), %ebp
callq 0x4340
movl (%r13), %eax
movl %eax, 0x78(%r15)
jmp 0x47aa8
movl (%r13), %eax
cmpl 0x78(%r15), %eax
je 0x47aa8
cmpl $0x0, 0xac(%r15)
je 0x47973
movq (%r14), %rax
incq %rax
movq %rax, 0xd0(%r15)
movq %rax, 0xc8(%r15)
movq %rax, 0x80(%r15)
movl 0x64(%r15), %esi
movl $0x2, %edi
callq 0x51358
movq 0x88(%r15), %rcx
movslq 0x5c(%r15), %rdx
movq %rax, (%rcx,%rdx,8)
movq %rax, 0x90(%r15)
testq %rax, %rax
je 0x47b09
cmpl $0x0, 0xac(%r15)
je 0x47b2c
movq (%rax), %rcx
movl $0xfffffffe, 0x4(%rcx)  # imm = 0xFFFFFFFE
movl $0x1, %esi
xorl %edx, %edx
jmp 0x47b3f
movq 0x38(%rbx), %rcx
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
testq %rcx, %rcx
je 0x47ebe
movq %rcx, 0x40(%rbx)
movq $0x0, 0x38(%rbx)
jmp 0x47ebe
movl 0x8(%r14), %edx
movq (%rax), %rcx
movl %edx, 0x4(%rcx)
movq (%r14), %rdx
incq %rdx
movq %rdx, %rsi
movq %rdx, 0x8(%rcx)
movq %rsi, 0x20(%rax)
xorl %eax, %eax
movl %eax, 0x68(%r15)
movq $0x0, 0x288(%r15)
movl %eax, 0x298(%r15)
xorl %eax, %eax
cmpl $0x400, 0xc(%rbx)       # imm = 0x400
setl %al
movl %eax, 0xb4(%r15)
movl %r12d, 0x4(%rsp)
testl %r12d, %r12d
je 0x47c48
movl $0x1, %eax
movl %eax, 0x889c(%rbx)
movl %eax, 0xac(%r15)
movl $0x0, 0x98(%r15)
leaq 0x88f0(%rbx), %r12
movq %r12, %rdi
callq 0x4750
cmpl $0x0, 0x220(%rbx)
jle 0x47bfe
cmpl $0x0, 0x68(%r15)
jne 0x47bfe
cmpl $0x0, 0x5c(%r15)
jne 0x47bfe
leaq 0x520b5(%rip), %rsi     # 0x99c7f
leaq 0x5210a(%rip), %rdx     # 0x99cdb
movl $0x3, %edi
xorl %eax, %eax
callq 0x13de5
xorl %eax, %eax
movl %eax, 0x220(%rbx)
movl %eax, 0xe8(%r15)
movl $0x1, %eax
movl %eax, 0x224(%rbx)
movl %eax, 0xec(%r15)
movq %r12, %rdi
callq 0x4340
cmpq $0x0, 0x278(%r15)
jne 0x47c64
movq %r12, %rdi
callq 0x4750
movq 0x50(%rbx), %rax
movslq 0x18(%rax), %rdi
movl $0x4, %esi
callq 0x4300
movq %rax, 0x278(%r15)
movq %r12, %rdi
callq 0x4340
cmpq $0x0, 0x278(%r15)
jne 0x47c64
jmp 0x47eb9
cmpl $0x1, 0x889c(%rbx)
jne 0x47c64
cmpl $-0x1, 0x88a0(%rbx)
jne 0x47c64
movl $0xffffffff, 0x889c(%rbx) # imm = 0xFFFFFFFF
subl 0x8(%rsp), %ebp
movl %ebp, 0x8894(%rbx)
movl 0x68(%r15), %eax
movl %eax, 0x74(%r15)
movslq (%r13), %rax
testq %rax, %rax
movl 0x14(%rsp), %ecx
js 0x47d30
testl %ecx, %ecx
js 0x47d30
cmpl %ecx, %eax
je 0x47d30
cmpl $0x0, 0x10(%rsp)
jg 0x47d30
cmpl $0x0, 0x4(%rsp)
je 0x47d30
cmpl $0x0, 0x88a4(%rbx)
jne 0x47d30
movq 0x278(%r15), %rcx
testq %rcx, %rcx
je 0x47cf2
cmpl $0x0, (%rcx,%rax,4)
je 0x47d30
leaq 0x88f0(%rbx), %r12
movq %r12, %rdi
callq 0x4750
movl $0x1, %eax
movl %eax, 0x88a4(%rbx)
movl %eax, 0x889c(%rbx)
movq %r12, %rdi
callq 0x4340
jmp 0x47d30
leaq 0x88f0(%rbx), %r12
movq %r12, %rdi
callq 0x4750
movq 0x50(%rbx), %rax
movslq 0x18(%rax), %rdi
movl $0x4, %esi
callq 0x4300
movq %rax, 0x278(%r15)
movq %r12, %rdi
callq 0x4340
cmpq $0x0, 0x278(%r15)
je 0x47eb9
movl (%r13), %eax
movl %eax, 0x78(%r15)
movq 0x278(%r15), %rcx
testq %rcx, %rcx
setne %dl
testl %eax, %eax
setns %sil
andb %dl, %sil
cmpb $0x1, %sil
jne 0x47d59
movl %eax, %eax
incl (%rcx,%rax,4)
movq 0xf0(%r15), %rax
testq %rax, %rax
jne 0x47dc9
leaq 0x8948(%rbx), %r12
movq %r12, %rdi
callq 0x4750
movq 0x8940(%rbx), %rdi
testq %rdi, %rdi
je 0x47d9c
movq (%rdi), %rax
movq %rax, 0xf0(%r15)
movq 0x8(%rdi), %rax
movq %rax, 0x8940(%rbx)
callq 0x45c0
jmp 0x47dba
movslq 0x6c(%r15), %rdi
movl $0x8, %esi
callq 0x4300
movq %rax, 0xf0(%r15)
testq %rax, %rax
je 0x47eb1
movq %r12, %rdi
callq 0x4340
movq 0xf0(%r15), %rax
movslq 0x70(%r15), %rcx
movq (%rax,%rcx,8), %rdi
testq %rdi, %rdi
je 0x47de8
movq %r14, %rsi
callq 0x22b64
testq %rax, %rax
jne 0x47e11
jmp 0x47eb9
movq %r14, %rdi
callq 0x22bd1
movq 0xf0(%r15), %rcx
movslq 0x70(%r15), %rdx
movq %rax, (%rcx,%rdx,8)
movq 0xf0(%r15), %rax
cmpq $0x0, (%rax,%rdx,8)
je 0x47eb9
movslq 0x18(%r14), %rax
testq %rax, %rax
je 0x47e23
addq %rax, 0x288(%r15)
jmp 0x47e48
movl 0x14(%r14), %edi
movzwl 0x12(%r14), %esi
addq 0x38(%r14), %rsi
callq 0x23094
cmpq $0x5f5e100, %rax        # imm = 0x5F5E100
jg 0x47e8e
addq %rax, 0x288(%r15)
movl 0x18(%r14), %eax
incl 0x68(%r15)
incl 0x70(%r15)
movl 0x14(%r14), %ecx
movl 0x40(%r14), %edx
movzwl 0x12(%r14), %esi
leal 0x1(%rax), %edi
sarl %edi
leal (%rsi,%rcx,4), %ecx
addl %eax, %ecx
addl %edi, %ecx
subl %ecx, %edx
addq %rdx, 0x290(%r15)
movzwl 0x10(%r14), %eax
andl $0x4, %eax
cmpw $0x1, %ax
adcl $0x0, 0x298(%r15)
incq 0x28(%rbx)
xorl %eax, %eax
jmp 0x47ebe
movq 0x38(%r14), %r8
leaq 0x51de6(%rip), %rsi     # 0x99c7f
leaq 0x51e62(%rip), %rdx     # 0x99d02
movl $0x1, %edi
movq %rax, %rcx
xorl %eax, %eax
callq 0x13de5
jmp 0x47eb9
movq %r12, %rdi
callq 0x4340
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq