// File: /workspace/github_c_makefile_star2_O1/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
cmpq $0x0, 0x38(%rdi)
jne 0x49ede
movl 0x214(%rbx), %edi
movl 0x21c(%rbx), %esi
callq 0x5278c
movq %rax, 0x38(%rbx)
testq %rax, %rax
je 0x4a600
movq 0x28(%rbx), %rcx
movq %rcx, 0x18(%rax)
leaq 0x88f0(%rbx), %r15
movq %r15, %rdi
callq 0x4750
movl 0x224(%rbx), %eax
movq 0x38(%rbx), %rcx
movl %eax, 0xec(%rcx)
movl 0x220(%rbx), %eax
movl %eax, 0xe8(%rcx)
movq %r15, %rdi
callq 0x4340
movq 0x38(%rbx), %r15
movl 0xe8(%r15), %eax
movl %eax, 0xc(%rsp)
movq 0x90(%r15), %rdx
testq %rdx, %rdx
je 0x49f36
movl 0x68(%r15), %eax
cmpl 0x64(%r15), %eax
je 0x49f36
movl 0x78(%r15), %eax
cmpl %eax, 0x8(%r14)
setne %cl
cmpl $-0x1, %eax
setge %al
testb %al, %cl
jne 0x49f36
movq 0x290(%r15), %rax
addq 0x288(%r15), %rax
movslq 0x218(%rbx), %rcx
cmpq %rcx, %rax
jb 0x4a491
movl 0x889c(%rbx), %eax
xorl %ebp, %ebp
cmpl $0x1, %eax
sete %cl
leaq 0x78(%r15), %rsi
movq %r14, (%rsp)
leaq 0x8(%r14), %r13
testq %rdx, %rdx
cmoveq %r13, %rsi
movl (%rsi), %r14d
cmpl $-0x1, %eax
movl %r14d, 0x14(%rsp)
jne 0x49fc8
movl 0x64(%r15), %esi
leal 0x3(%rsi), %edx
testl %esi, %esi
cmovnsl %esi, %edx
sarl $0x2, %edx
addl $0xa, %edx
cmpl %edx, 0x68(%r15)
jge 0x49fc8
movl 0x8894(%rbx), %esi
testl %esi, %esi
je 0x49fc8
cmpl %edx, %esi
setl %dl
cmpl $0x0, 0xc(%rsp)
setle %sil
andb %dl, %sil
cmpb $0x1, %sil
jne 0x49fc8
movl $0x1, %ebp
cmpl $0x0, 0xac(%r15)
jne 0x4a018
leaq 0x52c6c(%rip), %rsi     # 0x9cc1f
leaq 0x52c76(%rip), %rdx     # 0x9cc30
movl $0x4, %edi
xorl %eax, %eax
callq 0x14378
jmp 0x4a018
movb %cl, %bpl
cmpl $0x1, %eax
jne 0x4a018
leaq 0x88c8(%rbx), %r12
movq %r12, %rdi
callq 0x4750
movl 0x8898(%rbx), %eax
cmpl 0x58(%r15), %eax
jg 0x4a010
cmpl $0x1, 0x88a0(%rbx)
je 0x4a010
leaq 0x52c24(%rip), %rsi     # 0x9cc1f
leaq 0x52c53(%rip), %rdx     # 0x9cc55
xorl %ebp, %ebp
movl $0x4, %edi
xorl %eax, %eax
callq 0x14378
movq %r12, %rdi
callq 0x4340
movl 0x68(%r15), %r14d
movl 0x74(%r15), %eax
movl %eax, 0x10(%rsp)
movl 0xc(%rbx), %esi
movl %esi, %eax
andl $0xffffff00, %eax       # imm = 0xFFFFFF00
cmpl $0x100, %eax            # imm = 0x100
je 0x4a06c
cmpl 0x64(%r15), %r14d
je 0x4a06c
cmpl $0x1, 0x889c(%rbx)
jne 0x4a06c
cmpq $0x0, 0x90(%r15)
je 0x4a06c
movq 0x290(%r15), %rax
addq 0x288(%r15), %rax
movslq 0x218(%rbx), %rcx
cmpq %rcx, %rax
jb 0x4a278
movq 0x38(%rbx), %r15
cmpl $-0x2, 0x78(%r15)
jne 0x4a07f
movl (%r13), %eax
movl %eax, 0x78(%r15)
cmpq $0x0, 0x90(%r15)
je 0x4a091
movq %r15, %rdi
callq 0x49dcb
movl 0x5c(%r15), %eax
cmpl 0x58(%r15), %eax
jne 0x4a1a4
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 0x52eec(%rip), %rsi     # 0x9cfab
leaq 0x52ef9(%rip), %rdx     # 0x9cfbf
movl $0x4, %edi
xorl %eax, %eax
callq 0x14378
movq %rbx, %rdi
movq %r15, %rsi
callq 0x53b58
cmpl $-0x1, %eax
je 0x4a221
cmpq $0x0, 0x88b8(%rbx)
jne 0x4a140
cmpl $0x0, 0x58(%r15)
jle 0x4a125
xorl %r12d, %r12d
movq 0x88(%r15), %rax
movq (%rax,%r12,8), %rdi
callq 0x52c5d
movq 0x88(%r15), %rax
movq $0x0, (%rax,%r12,8)
incq %r12
movslq 0x58(%r15), %rax
cmpq %rax, %r12
jl 0x4a0fa
movq $0x0, 0x90(%r15)
movl $0x0, 0x5c(%r15)
movq %r15, %rdi
callq 0x5295e
movl 0x214(%rbx), %edi
movl 0x21c(%rbx), %esi
callq 0x5278c
movq %rax, 0x38(%rbx)
testq %rax, %rax
je 0x4a221
movq %rax, %r15
leaq 0x88f0(%rbx), %r12
movq %r12, %rdi
callq 0x4750
movl 0x224(%rbx), %eax
movl %eax, 0xec(%r15)
movl 0x220(%rbx), %eax
movl %eax, 0xe8(%r15)
movq 0x28(%rbx), %rax
movq %rax, 0x18(%r15)
movq %r12, %rdi
callq 0x4340
movl (%r13), %eax
movl %eax, 0x78(%r15)
jmp 0x4a1bc
movl (%r13), %eax
cmpl 0x78(%r15), %eax
je 0x4a1bc
cmpl $0x0, 0xac(%r15)
je 0x4a09f
movq (%rsp), %rax
movq (%rax), %rax
incq %rax
movq %rax, 0xd0(%r15)
movq %rax, 0xc8(%r15)
movq %rax, 0x80(%r15)
movl 0x64(%r15), %esi
movl $0x2, %edi
callq 0x53e6c
movq 0x88(%r15), %rcx
movslq 0x5c(%r15), %rdx
movq %rax, (%rcx,%rdx,8)
movq %rax, 0x90(%r15)
testq %rax, %rax
je 0x4a221
cmpl $0x0, 0xac(%r15)
je 0x4a226
movq (%rax), %rcx
movl $0xfffffffe, 0x4(%rcx)  # imm = 0xFFFFFFFE
movl $0x1, %esi
xorl %edx, %edx
jmp 0x4a23c
xorl %r15d, %r15d
jmp 0x4a26f
movq (%rsp), %rsi
movl 0x8(%rsi), %edx
movq (%rax), %rcx
movl %edx, 0x4(%rcx)
movq (%rsi), %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)
testq %r15, %r15
je 0x4a34a
testl %ebp, %ebp
je 0x4a369
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 0x4a2fe
cmpl $0x0, 0x68(%r15)
jne 0x4a2fe
cmpl $0x0, 0x5c(%r15)
jne 0x4a2fe
leaq 0x52955(%rip), %rsi     # 0x9cc1f
leaq 0x529aa(%rip), %rdx     # 0x9cc7b
movl $0x3, %edi
xorl %eax, %eax
callq 0x14378
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 0x4a385
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 0x4a385
xorl %ecx, %ecx
jmp 0x4a480
movq 0x38(%rbx), %rax
testq %rax, %rax
je 0x4a35f
movq %rax, 0x40(%rbx)
movq $0x0, 0x38(%rbx)
xorl %ecx, %ecx
xorl %r15d, %r15d
jmp 0x4a480
cmpl $0x1, 0x889c(%rbx)
jne 0x4a385
cmpl $-0x1, 0x88a0(%rbx)
jne 0x4a385
movl $0xffffffff, 0x889c(%rbx) # imm = 0xFFFFFFFF
subl 0x10(%rsp), %r14d
movl %r14d, 0x8894(%rbx)
movl 0x68(%r15), %eax
movl %eax, 0x74(%r15)
movslq (%r13), %rax
testq %rax, %rax
movl 0x14(%rsp), %ecx
js 0x4a455
testl %ecx, %ecx
js 0x4a455
cmpl %ecx, %eax
setne %cl
cmpl $0x0, 0xc(%rsp)
setle %dl
andb %cl, %dl
cmpb $0x1, %dl
jne 0x4a455
testl %ebp, %ebp
je 0x4a455
cmpl $0x0, 0x88a4(%rbx)
jne 0x4a455
movq 0x278(%r15), %rcx
testq %rcx, %rcx
je 0x4a417
cmpl $0x0, (%rcx,%rax,4)
je 0x4a455
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 0x4a455
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 0x4a343
movl (%r13), %eax
movl %eax, 0x78(%r15)
movq 0x278(%r15), %rdx
testq %rdx, %rdx
setne %cl
testl %eax, %eax
setns %sil
andb %cl, %sil
movb $0x1, %cl
cmpb $0x1, %sil
jne 0x4a480
movl %eax, %eax
incl (%rdx,%rax,4)
movq (%rsp), %r14
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
testb %cl, %cl
je 0x4a605
cmpq $0x0, 0xf0(%r15)
jne 0x4a4f8
leaq 0x8948(%rbx), %r12
movq %r12, %rdi
callq 0x4750
movq 0x8940(%rbx), %rdi
testq %rdi, %rdi
je 0x4a4d2
movq (%rdi), %rax
movq %rax, 0xf0(%r15)
movq 0x8(%rdi), %rax
movq %rax, 0x8940(%rbx)
callq 0x45c0
jmp 0x4a4f0
movslq 0x6c(%r15), %rdi
movl $0x8, %esi
callq 0x4300
movq %rax, 0xf0(%r15)
testq %rax, %rax
je 0x4a5f8
movq %r12, %rdi
callq 0x4340
movq 0xf0(%r15), %rax
movslq 0x70(%r15), %rcx
movq (%rax,%rcx,8), %rdi
testq %rdi, %rdi
je 0x4a51e
movq %r14, %rsi
callq 0x2357d
testq %rax, %rax
jne 0x4a547
jmp 0x4a600
movq %r14, %rdi
callq 0x235e7
movq 0xf0(%r15), %rcx
movslq 0x70(%r15), %rdx
movq %rax, (%rcx,%rdx,8)
movq 0xf0(%r15), %rax
cmpq $0x0, (%rax,%rdx,8)
je 0x4a600
movslq 0x18(%r14), %rax
testq %rax, %rax
je 0x4a559
addq %rax, 0x288(%r15)
jmp 0x4a5ae
movl 0x14(%r14), %edi
movzwl 0x12(%r14), %esi
addq 0x38(%r14), %rsi
callq 0x23a9a
movq %rax, %r12
cmpq $0x5f5e101, %rax        # imm = 0x5F5E101
jge 0x4a57f
addq %r12, 0x288(%r15)
jmp 0x4a5a0
movq 0x38(%r14), %r8
leaq 0x52695(%rip), %rsi     # 0x9cc1f
leaq 0x52711(%rip), %rdx     # 0x9cca2
movl $0x1, %edi
movq %r12, %rcx
xorl %eax, %eax
callq 0x14378
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
cmpq $0x5f5e100, %r12        # imm = 0x5F5E100
jg 0x4a605
incl 0x68(%r15)
incl 0x70(%r15)
movl 0x40(%r14), %eax
movzwl 0x12(%r14), %ecx
movl 0x14(%r14), %edx
movl 0x18(%r14), %esi
leal 0x1(%rsi), %edi
sarl %edi
leal (%rcx,%rdx,4), %ecx
addl %esi, %ecx
addl %edi, %ecx
subl %ecx, %eax
addq %rax, 0x290(%r15)
movzwl 0x10(%r14), %eax
andl $0x4, %eax
cmpw $0x1, %ax
adcl $0x0, 0x298(%r15)
incq 0x28(%rbx)
xorl %eax, %eax
jmp 0x4a605
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