// File: /workspace/github_c_makefile_star2_O3/samtools[P]htslib/cram/cram_decode.c
// Function: cram_decode_slice_xref
static int cram_decode_slice_xref(cram_slice *s, int required_fields) {
    int rec;

    if (!(required_fields & (SAM_RNEXT | SAM_PNEXT | SAM_TLEN))) {
        for (rec = 0; rec < s->hdr->num_records; rec++) {
            cram_record *cr = &s->crecs[rec];

            cr->tlen = 0;
            cr->mate_pos = 0;
            cr->mate_ref_id = -1;
        }

        return 0;
    }

    for (rec = 0; rec < s->hdr->num_records; rec++) {
        cram_record *cr = &s->crecs[rec];

        if (cr->mate_line >= 0) {
            if (cr->mate_line < s->hdr->num_records) {
                /*
                 * On the first read, loop through computing lengths.
                 * It's not perfect as we have one slice per reference so we
                 * cannot detect when TLEN should be zero due to seqs that
                 * map to multiple references.
                 *
                 * We also cannot set tlen correct when it spans a slice for
                 * other reasons. This may make tlen too small. Should we
                 * fix this by forcing TLEN to be stored verbatim in such cases?
                 *
                 * Or do we just admit defeat and output 0 for tlen? It's the
                 * safe option...
                 */
                if (cr->tlen == INT64_MIN) {
                    int id1 = rec, id2 = rec;
                    int64_t aleft = cr->apos, aright = cr->aend;
                    int64_t tlen;
                    int ref = cr->ref_id;

                    // number of segments starting at the same point.
                    int left_cnt = 0;

                    do {
                        if (aleft > s->crecs[id2].apos)
                            aleft = s->crecs[id2].apos, left_cnt = 1;
                        else if (aleft == s->crecs[id2].apos)
                            left_cnt++;
                        if (aright < s->crecs[id2].aend)
                            aright = s->crecs[id2].aend;
                        if (s->crecs[id2].mate_line == -1) {
                            s->crecs[id2].mate_line = rec;
                            break;
                        }
                        if (s->crecs[id2].mate_line <= id2 ||
                            s->crecs[id2].mate_line >= s->hdr->num_records)
                            return -1;
                        id2 = s->crecs[id2].mate_line;

                        if (s->crecs[id2].ref_id != ref)
                            ref = -1;
                    } while (id2 != id1);

                    if (ref != -1) {
                        tlen = aright - aleft + 1;
                        id1 = id2 = rec;

                        /*
                         * When we have two seqs with identical start and
                         * end coordinates, set +/- tlen based on 1st/last
                         * bit flags instead, as a tie breaker.
                         */
                        if (s->crecs[id2].apos == aleft) {
                            if (left_cnt == 1 ||
                                (s->crecs[id2].flags & BAM_FREAD1))
                                s->crecs[id2].tlen = tlen;
                            else
                                s->crecs[id2].tlen = -tlen;
                        } else {
                            s->crecs[id2].tlen = -tlen;
                        }

                        id2 = s->crecs[id2].mate_line;
                        while (id2 != id1) {
                            if (s->crecs[id2].apos == aleft) {
                                if (left_cnt == 1 ||
                                    (s->crecs[id2].flags & BAM_FREAD1))
                                    s->crecs[id2].tlen = tlen;
                                else
                                    s->crecs[id2].tlen = -tlen;
                            } else {
                                s->crecs[id2].tlen = -tlen;
                            }
                            id2 = s->crecs[id2].mate_line;
                        }
                    } else {
                        id1 = id2 = rec;

                        s->crecs[id2].tlen = 0;
                        id2 = s->crecs[id2].mate_line;
                        while (id2 != id1) {
                            s->crecs[id2].tlen = 0;
                            id2 = s->crecs[id2].mate_line;
                        }
                    }
                }

                cr->mate_pos = s->crecs[cr->mate_line].apos;
                cr->mate_ref_id = s->crecs[cr->mate_line].ref_id;

                // paired
                cr->flags |= BAM_FPAIRED;

                // set mate unmapped if needed
                if (s->crecs[cr->mate_line].flags & BAM_FUNMAP) {
                    cr->flags |= BAM_FMUNMAP;
                    cr->tlen = 0;
                }
                if (cr->flags & BAM_FUNMAP) {
                    cr->tlen = 0;
                }

                // set mate reversed if needed
                if (s->crecs[cr->mate_line].flags & BAM_FREVERSE)
                    cr->flags |= BAM_FMREVERSE;
            } else {
                hts_log_error("Mate line out of bounds: %d vs [0, %d]",
                              cr->mate_line, s->hdr->num_records-1);
            }

            /* FIXME: construct read names here too if needed */
        } else {
            if (cr->mate_flags & CRAM_M_REVERSE) {
                cr->flags |= BAM_FPAIRED | BAM_FMREVERSE;
            }
            if (cr->mate_flags & CRAM_M_UNMAP) {
                cr->flags |= BAM_FMUNMAP;
                //cr->mate_ref_id = -1;
            }
            if (!(cr->flags & BAM_FPAIRED))
                cr->mate_ref_id = -1;
        }

        if (cr->tlen == INT64_MIN)
            cr->tlen = 0; // Just incase
    }

    for (rec = 0; rec < s->hdr->num_records; rec++) {
        cram_record *cr = &s->crecs[rec];
        if (cr->explicit_tlen != INT64_MIN)
            cr->tlen = cr->explicit_tlen;
    }

    return 0;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
pushq %rax
movq %rdi, %rbx
movq (%rdi), %rax
movl 0x18(%rax), %r8d
testl $0x1c0, %esi            # imm = 0x1C0
je 0x3d37c
testl %r8d, %r8d
jle 0x3d3b2
movabsq $-0x8000000000000000, %r12 # imm = 0x8000000000000000
leaq 0x5c582(%rip), %r13     # 0x99609
leaq 0x5c592(%rip), %rbp     # 0x99620
xorl %r14d, %r14d
movq 0x30(%rbx), %rdx
leaq (%r14,%r14,8), %r9
shlq $0x4, %r9
leaq (%rdx,%r9), %r15
movl 0x2c(%rdx,%r9), %ecx
testl %ecx, %ecx
js 0x3d15e
cmpl %r8d, %ecx
jge 0x3d194
cmpq %r12, 0x40(%r15)
jne 0x3d2ca
movq 0x18(%r15), %rcx
movq 0x78(%r15), %r10
movl 0x8(%r15), %r11d
xorl %esi, %esi
movl %r14d, %r13d
movq %rcx, %rdi
movq %r10, %r12
movq %rdi, %r10
movslq %r13d, %rax
leaq (%rax,%rax,8), %rax
shlq $0x4, %rax
movq 0x18(%rdx,%rax), %rdi
xorl %ebp, %ebp
cmpq %rdi, %r10
sete %bpl
addl %ebp, %esi
cmpq %rdi, %r10
cmovlq %r10, %rdi
movq 0x78(%rdx,%rax), %r10
movl $0x1, %ebp
cmovgl %ebp, %esi
cmpq %r10, %r12
cmovgq %r12, %r10
movslq 0x2c(%rdx,%rax), %r12
cmpq $-0x1, %r12
je 0x3d1ae
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
cmpl %r13d, %r12d
jle 0x3d3b4
cmpl %r8d, %r12d
jge 0x3d3b4
leaq (%r12,%r12,8), %rax
shlq $0x4, %rax
cmpl %r11d, 0x8(%rdx,%rax)
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
cmovnel %eax, %r11d
movl %r12d, %eax
movl %r12d, %r13d
cmpq %rax, %r14
jne 0x3d0d5
jmp 0x3d1b8
movl 0x8c(%r15), %ecx
testb $0x1, %cl
je 0x3d16f
orb $0x21, 0xc(%r15)
movl 0xc(%r15), %eax
testb $0x2, %cl
je 0x3d17f
orl $0x8, %eax
movl %eax, 0xc(%r15)
testb $0x1, %al
jne 0x3d32b
movl $0xffffffff, 0x30(%r15) # imm = 0xFFFFFFFF
jmp 0x3d32b
decl %r8d
movl $0x1, %edi
movq %r13, %rsi
movq %rbp, %rdx
xorl %eax, %eax
callq 0x13de5
jmp 0x3d32b
addq %rdx, %rax
addq $0x2c, %rax
movl %r14d, (%rax)
cmpl $-0x1, %r11d
je 0x3d1f0
subq %rdi, %r10
leaq 0x1(%r10), %rax
notq %r10
cmpq %rdi, %rcx
jne 0x3d224
cmpl $0x1, %esi
movabsq $-0x8000000000000000, %r12 # imm = 0x8000000000000000
leaq 0x5c43f(%rip), %rbp     # 0x99620
je 0x3d242
testb $0x40, 0xc(%r15)
jne 0x3d242
movq %r10, 0x40(%r15)
jmp 0x3d247
movq $0x0, 0x40(%rdx,%r9)
movl 0x2c(%rdx,%r9), %ecx
cmpq %rcx, %r14
jne 0x3d294
movabsq $-0x8000000000000000, %r12 # imm = 0x8000000000000000
leaq 0x5c3f1(%rip), %r13     # 0x99609
leaq 0x5c401(%rip), %rbp     # 0x99620
jmp 0x3d2ca
movq %r10, 0x40(%r15)
movabsq $-0x8000000000000000, %r12 # imm = 0x8000000000000000
leaq 0x5c3d0(%rip), %r13     # 0x99609
leaq 0x5c3e0(%rip), %rbp     # 0x99620
jmp 0x3d24e
movq %rax, 0x40(%rdx,%r9)
leaq 0x5c3bb(%rip), %r13     # 0x99609
movl 0x2c(%rdx,%r9), %ecx
cmpq %rcx, %r14
je 0x3d2ca
movl %ecx, %r8d
movslq %r8d, %r8
leaq (%r8,%r8,8), %r8
shlq $0x4, %r8
leaq (%rdx,%r8), %r9
cmpq %rdi, 0x18(%rdx,%r8)
jne 0x3d27d
cmpl $0x1, %esi
je 0x3d283
testb $0x40, 0xc(%r9)
jne 0x3d283
movq %r10, 0x40(%r9)
jmp 0x3d288
movq %rax, 0x40(%rdx,%r8)
movl 0x2c(%rdx,%r8), %r8d
cmpq %r8, %r14
jne 0x3d25b
jmp 0x3d2ca
movl %ecx, %eax
movabsq $-0x8000000000000000, %r12 # imm = 0x8000000000000000
leaq 0x5c362(%rip), %r13     # 0x99609
leaq 0x5c372(%rip), %rbp     # 0x99620
cltq
leaq (%rax,%rax,8), %rax
shlq $0x4, %rax
movq $0x0, 0x40(%rdx,%rax)
movl 0x2c(%rdx,%rax), %eax
cmpq %rax, %r14
jne 0x3d2ae
movslq %ecx, %rax
leaq (%rax,%rax,8), %rax
shlq $0x4, %rax
movq 0x18(%rdx,%rax), %rcx
movq %rcx, 0x38(%r15)
movl 0x8(%rdx,%rax), %ecx
movl %ecx, 0x30(%r15)
movl 0xc(%r15), %esi
movl %esi, %ecx
orl $0x1, %ecx
movl %ecx, 0xc(%r15)
testb $0x4, 0xc(%rdx,%rax)
je 0x3d30b
orl $0x9, %esi
movl %esi, 0xc(%r15)
movq $0x0, 0x40(%r15)
movl %esi, %ecx
testb $0x4, %cl
je 0x3d318
movq $0x0, 0x40(%r15)
addq %rdx, %rax
addq $0xc, %rax
testb $0x10, (%rax)
je 0x3d32b
orl $0x20, %ecx
movl %ecx, 0xc(%r15)
cmpq %r12, 0x40(%r15)
jne 0x3d339
movq $0x0, 0x40(%r15)
incq %r14
movq (%rbx), %rax
movslq 0x18(%rax), %r8
cmpq %r8, %r14
jl 0x3d091
testl %r8d, %r8d
jle 0x3d3b2
movq 0x30(%rbx), %rax
shlq $0x4, %r8
leaq (%r8,%r8,8), %rcx
xorl %edx, %edx
movq 0x48(%rax,%rdx), %rsi
cmpq %r12, %rsi
je 0x3d36e
movq %rsi, 0x40(%rax,%rdx)
addq $0x90, %rdx
cmpq %rdx, %rcx
jne 0x3d35f
jmp 0x3d3b2
testl %r8d, %r8d
jle 0x3d3b2
movq 0x30(%rbx), %rcx
addq $0x38, %rcx
shlq $0x4, %r8
leaq (%r8,%r8,8), %rdx
xorl %eax, %eax
xorps %xmm0, %xmm0
xorl %esi, %esi
movups %xmm0, (%rcx,%rsi)
movl $0xffffffff, -0x8(%rcx,%rsi) # imm = 0xFFFFFFFF
addq $0x90, %rsi
cmpq %rsi, %rdx
jne 0x3d398
jmp 0x3d3b4
xorl %eax, %eax
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq