// File: /workspace/github_c_makefile_star2_O2/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 $0x28, %rsp
movq %rsi, 0x8(%rsp)
movq %rdi, %r14
movq 0x38(%rdi), %r12
pushq $-0x1
popq %rbx
testq %r12, %r12
jne 0x3b0ed
movl 0x214(%r14), %edi
movl 0x21c(%r14), %esi
callq 0x42222
movq %rax, 0x38(%r14)
testq %rax, %rax
je 0x3b825
movq 0x28(%r14), %rcx
movq %rcx, 0x18(%rax)
leaq 0x88f0(%r14), %r12
movq %r12, %rdi
callq 0x4750
movq 0x38(%r14), %rax
movq 0x220(%r14), %rcx
movq %rcx, 0xe8(%rax)
movq %r12, %rdi
callq 0x4340
movq 0x38(%r14), %r12
movl 0xe8(%r12), %eax
movl %eax, 0x24(%rsp)
movq 0x90(%r12), %rax
testq %rax, %rax
je 0x3b14c
movl 0x68(%r12), %ecx
cmpl 0x64(%r12), %ecx
je 0x3b14c
movl 0x78(%r12), %ecx
movq 0x8(%rsp), %rdx
cmpl %ecx, 0x8(%rdx)
setne %dl
cmpl $-0x1, %ecx
setge %cl
testb %cl, %dl
jne 0x3b14c
movq 0x290(%r12), %rcx
addq 0x288(%r12), %rcx
movslq 0x218(%r14), %rdx
cmpq %rdx, %rcx
jb 0x3b6d0
movl 0x889c(%r14), %ecx
xorl %r13d, %r13d
cmpl $0x1, %ecx
sete %dl
leaq 0x78(%r12), %rsi
movq 0x8(%rsp), %rdi
addq $0x8, %rdi
testq %rax, %rax
movq %rdi, 0x18(%rsp)
cmoveq %rdi, %rsi
movl (%rsi), %r15d
cmpl $-0x1, %ecx
je 0x3b1db
xorl %r13d, %r13d
cmpl $0x1, %ecx
jne 0x3b23b
pushq $0x1
popq %rbx
leaq 0x88c8(%r14), %r13
movq %r13, %rdi
callq 0x4750
movl 0x8898(%r14), %eax
cmpl 0x58(%r12), %eax
jg 0x3b1ce
cmpl $0x1, 0x88a0(%r14)
je 0x3b1ce
leaq 0x40a3c(%rip), %rsi     # 0x7bbf7
leaq 0x40a6b(%rip), %rdx     # 0x7bc2d
xorl %ebx, %ebx
pushq $0x4
popq %rdi
xorl %eax, %eax
callq 0x110c6
movq %r13, %rdi
callq 0x4340
movl %ebx, %r13d
jmp 0x3b23b
movb %dl, %r13b
pushq $0x4
popq %rcx
movl 0x64(%r12), %eax
movl 0x68(%r12), %esi
cltd
idivl %ecx
addl $0xa, %eax
cmpl %eax, %esi
jge 0x3b23b
movl 0x8894(%r14), %ecx
testl %ecx, %ecx
je 0x3b23b
cmpl %eax, %ecx
setl %al
cmpl $0x0, 0x24(%rsp)
setle %cl
andb %al, %cl
cmpb $0x1, %cl
jne 0x3b23b
pushq $0x1
popq %r13
cmpl $0x0, 0xac(%r12)
jne 0x3b23b
leaq 0x409cd(%rip), %rsi     # 0x7bbf7
leaq 0x409d7(%rip), %rdx     # 0x7bc08
pushq $0x4
popq %rdi
xorl %eax, %eax
callq 0x110c6
movl 0x68(%r12), %ebx
movl 0x74(%r12), %ebp
movl 0xc(%r14), %esi
movl %esi, %eax
andl $0xffffff00, %eax       # imm = 0xFFFFFF00
cmpl $0x100, %eax            # imm = 0x100
je 0x3b293
cmpl 0x64(%r12), %ebx
je 0x3b293
cmpl $0x1, 0x889c(%r14)
jne 0x3b293
cmpq $0x0, 0x90(%r12)
je 0x3b293
movq 0x290(%r12), %rax
addq 0x288(%r12), %rax
movslq 0x218(%r14), %rcx
cmpq %rcx, %rax
jb 0x3b4da
movq 0x38(%r14), %r12
cmpl $-0x2, 0x78(%r12)
jne 0x3b2ab
movq 0x18(%rsp), %rax
movl (%rax), %eax
movl %eax, 0x78(%r12)
cmpq $0x0, 0x90(%r12)
je 0x3b2be
movq %r12, %rdi
callq 0x3afd5
movl 0x5c(%r12), %eax
cmpl 0x58(%r12), %eax
jne 0x3b355
movslq 0x4c(%r14), %r9
movq 0x8(%r12), %r8
movq %r9, %rax
subq %r8, %rax
incq %rax
movq %rax, 0x10(%r12)
movl 0x4(%r12), %ecx
leaq 0x40c92(%rip), %rsi     # 0x7bf83
leaq 0x40c9f(%rip), %rdx     # 0x7bf97
pushq $0x4
popq %rdi
xorl %eax, %eax
callq 0x110c6
movq %r14, %rdi
movq %r12, %rsi
callq 0x432eb
cmpl $-0x1, %eax
je 0x3b474
cmpq $0x0, 0x88b8(%r14)
jne 0x3b397
movl %r13d, 0x14(%rsp)
xorl %r13d, %r13d
movslq 0x58(%r12), %rax
cmpq %rax, %r13
jge 0x3b37b
movq 0x88(%r12), %rax
movq (%rax,%r13,8), %rdi
callq 0x42611
movq 0x88(%r12), %rax
andq $0x0, (%rax,%r13,8)
incq %r13
jmp 0x3b328
movq 0x18(%rsp), %rax
movl (%rax), %eax
cmpl 0x78(%r12), %eax
je 0x3b40a
cmpl $0x0, 0xac(%r12)
jne 0x3b40a
jmp 0x3b2ce
andq $0x0, 0x90(%r12)
andl $0x0, 0x5c(%r12)
movq %r12, %rdi
callq 0x4237d
movl 0x14(%rsp), %r13d
movl 0x214(%r14), %edi
movl 0x21c(%r14), %esi
callq 0x42222
movq %rax, 0x38(%r14)
testq %rax, %rax
je 0x3b486
movq %rax, %r12
movl %ebp, 0x14(%rsp)
movl %r15d, %ebp
movl %r13d, %r15d
leaq 0x88f0(%r14), %r13
movq %r13, %rdi
callq 0x4750
movq 0x220(%r14), %rax
movq %rax, 0xe8(%r12)
movq 0x28(%r14), %rax
movq %rax, 0x18(%r12)
movq %r13, %rdi
movl %r15d, %r13d
movq 0x18(%rsp), %r15
callq 0x4340
movl (%r15), %eax
movl %ebp, %r15d
movl 0x14(%rsp), %ebp
movl %eax, 0x78(%r12)
movq 0x8(%rsp), %rax
movq (%rax), %rax
incq %rax
movq %rax, 0xd0(%r12)
movq %rax, 0xc8(%r12)
movq %rax, 0x80(%r12)
movl 0x64(%r12), %esi
pushq $0x2
popq %rdi
callq 0x43611
movq 0x88(%r12), %rcx
movslq 0x5c(%r12), %rdx
movq %rax, (%rcx,%rdx,8)
movq %rax, 0x90(%r12)
testq %rax, %rax
je 0x3b474
cmpl $0x0, 0xac(%r12)
je 0x3b48e
movq (%rax), %rcx
movl $0xfffffffe, 0x4(%rcx)  # imm = 0xFFFFFFFE
pushq $0x1
popq %rsi
xorl %edx, %edx
jmp 0x3b4a5
movq 0x38(%r14), %rax
testq %rax, %rax
je 0x3b486
movq %rax, 0x40(%r14)
andq $0x0, 0x38(%r14)
pushq $-0x1
popq %rbx
jmp 0x3b825
movq 0x8(%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)
andl $0x0, 0x68(%r12)
andq $0x0, 0x288(%r12)
andl $0x0, 0x298(%r12)
xorl %eax, %eax
cmpl $0x400, 0xc(%r14)       # imm = 0x400
setl %al
movl %eax, 0xb4(%r12)
movl %r13d, 0x14(%rsp)
testl %r13d, %r13d
je 0x3b5b2
pushq $0x1
popq %rax
movl %eax, 0x889c(%r14)
movl %eax, 0xac(%r12)
andl $0x0, 0x98(%r12)
leaq 0x88f0(%r14), %r13
movq %r13, %rdi
callq 0x4750
cmpl $0x0, 0x220(%r14)
jle 0x3b567
cmpl $0x0, 0x68(%r12)
jne 0x3b567
cmpl $0x0, 0x5c(%r12)
jne 0x3b567
leaq 0x406c4(%rip), %rsi     # 0x7bbf7
leaq 0x40719(%rip), %rdx     # 0x7bc53
pushq $0x3
popq %rdi
xorl %eax, %eax
callq 0x110c6
andl $0x0, 0x220(%r14)
andl $0x0, 0xe8(%r12)
pushq $0x1
popq %rax
movl %eax, 0x224(%r14)
movl %eax, 0xec(%r12)
movq %r13, %rdi
callq 0x4340
cmpq $0x0, 0x278(%r12)
jne 0x3b5ce
movq %r13, %rdi
callq 0x4750
movq 0x50(%r14), %rax
movslq 0x18(%rax), %rdi
pushq $0x4
popq %rsi
callq 0x4300
movq %rax, 0x278(%r12)
movq %r13, %rdi
callq 0x4340
cmpq $0x0, 0x278(%r12)
jne 0x3b5ce
jmp 0x3b486
cmpl $0x1, 0x889c(%r14)
jne 0x3b5ce
cmpl $-0x1, 0x88a0(%r14)
jne 0x3b5ce
orl $-0x1, 0x889c(%r14)
subl %ebp, %ebx
movl %ebx, 0x8894(%r14)
movl 0x68(%r12), %eax
movl %eax, 0x74(%r12)
movq 0x18(%rsp), %rax
movslq (%rax), %rax
testq %rax, %rax
js 0x3b69f
testl %r15d, %r15d
js 0x3b69f
cmpl %r15d, %eax
je 0x3b69f
cmpl $0x0, 0x24(%rsp)
jg 0x3b69f
cmpl $0x0, 0x14(%rsp)
je 0x3b69f
cmpl $0x0, 0x88a4(%r14)
jne 0x3b69f
movq 0x278(%r12), %rcx
testq %rcx, %rcx
je 0x3b661
cmpl $0x0, (%rcx,%rax,4)
je 0x3b69f
leaq 0x88f0(%r14), %r13
movq %r13, %rdi
callq 0x4750
pushq $0x1
popq %rax
movl %eax, 0x88a4(%r14)
movl %eax, 0x889c(%r14)
movq %r13, %rdi
callq 0x4340
jmp 0x3b69f
leaq 0x88f0(%r14), %r13
movq %r13, %rdi
callq 0x4750
movq 0x50(%r14), %rax
movslq 0x18(%rax), %rdi
pushq $0x4
popq %rsi
callq 0x4300
movq %rax, 0x278(%r12)
movq %r13, %rdi
callq 0x4340
cmpq $0x0, 0x278(%r12)
je 0x3b486
movq 0x18(%rsp), %rax
movl (%rax), %eax
movl %eax, 0x78(%r12)
movq 0x278(%r12), %rcx
testq %rcx, %rcx
setne %dl
testl %eax, %eax
setns %sil
andb %dl, %sil
cmpb $0x1, %sil
jne 0x3b6cd
movl %eax, %eax
incl (%rcx,%rax,4)
pushq $-0x1
popq %rbx
movq 0xf0(%r12), %rax
testq %rax, %rax
jne 0x3b743
leaq 0x8948(%r14), %r13
movq %r13, %rdi
callq 0x4750
movq 0x8940(%r14), %rdi
testq %rdi, %rdi
je 0x3b715
movq (%rdi), %rax
movq %rax, 0xf0(%r12)
movq 0x8(%rdi), %rax
movq %rax, 0x8940(%r14)
callq 0x45c0
jmp 0x3b733
movslq 0x6c(%r12), %rdi
pushq $0x8
popq %rsi
callq 0x4300
movq %rax, 0xf0(%r12)
testq %rax, %rax
je 0x3b85c
movq %r13, %rdi
callq 0x4340
movq 0xf0(%r12), %rax
movslq 0x70(%r12), %rcx
movq (%rax,%rcx,8), %rdi
testq %rdi, %rdi
je 0x3b765
movq 0x8(%rsp), %rsi
callq 0x1dfcb
testq %rax, %rax
jne 0x3b793
jmp 0x3b825
movq 0x8(%rsp), %rdi
callq 0x1e039
movq 0xf0(%r12), %rcx
movslq 0x70(%r12), %rdx
movq %rax, (%rcx,%rdx,8)
movq 0xf0(%r12), %rax
cmpq $0x0, (%rax,%rdx,8)
je 0x3b825
movq 0x8(%rsp), %rax
movslq 0x18(%rax), %rax
testq %rax, %rax
je 0x3b7ab
addq %rax, 0x288(%r12)
jmp 0x3b7d8
movq 0x8(%rsp), %rax
movl 0x14(%rax), %edi
movzwl 0x12(%rax), %esi
addq 0x38(%rax), %rsi
callq 0x1e4a9
cmpq $0x5f5e100, %rax        # imm = 0x5F5E100
jg 0x3b836
addq %rax, 0x288(%r12)
movq 0x8(%rsp), %rax
movl 0x18(%rax), %eax
incl 0x68(%r12)
incl 0x70(%r12)
movq 0x8(%rsp), %r8
movl 0x14(%r8), %ecx
movl 0x40(%r8), %edx
movzwl 0x12(%r8), %esi
leal 0x1(%rax), %edi
sarl %edi
leal (%rsi,%rcx,4), %ecx
addl %eax, %ecx
addl %edi, %ecx
subl %ecx, %edx
addq %rdx, 0x290(%r12)
movzwl 0x10(%r8), %eax
andl $0x4, %eax
cmpw $0x1, %ax
adcl $0x0, 0x298(%r12)
incq 0x28(%r14)
xorl %ebx, %ebx
movl %ebx, %eax
addq $0x28, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x8(%rsp), %rcx
movq 0x38(%rcx), %r8
leaq 0x403b1(%rip), %rsi     # 0x7bbf7
leaq 0x4042d(%rip), %rdx     # 0x7bc7a
pushq $0x1
popq %rdi
movq %rax, %rcx
xorl %eax, %eax
callq 0x110c6
jmp 0x3b825
movq %r13, %rdi
callq 0x4340
jmp 0x3b825