// File: /workspace/github_c_makefile_star2_O3/samtools[P]htslib/cram/cram_codecs.c
// Function: cram_xdelta_encode_flush
int cram_xdelta_encode_flush(cram_codec *c) {
    int r = -1;
    cram_block *b = cram_new_block(0, 0);
    if (!b)
        return -1;

    switch (c->u.e_xdelta.word_size) {
    case 2: {
        // Delta + zigzag transform.
        // Subtracting two 8-bit values has a 9-bit result (-255 to 255).
        // However think of it as turning a wheel clockwise or anti-clockwise.
        // If it has 256 gradations then a -ve rotation followed by a +ve
        // rotation of the same amount reverses it regardless.
        //
        // Similarly the zig-zag transformation doesn't invent any extra bits,
        // so the entire thing can be done in-situ.  This may permit faster
        // SIMD loops if we break apart the steps.

        // uint16_t last = 0, d;
        // for (i = 0; i < n; i++) {
        //     d = io[i] - last;
        //     last = io[i];
        //     io[i] = zigzag16(vd);
        // }

        // --- vs ---

        // for (i = n-1; i >= 1; i--)
        //     io[i] -= io[i-1];
        // for (i = 0; i < n; i++)
        //     io[i] = zigzag16(io[i]);

        // varint: need array variant for speed here.
        // With zig-zag
        int i, n = BLOCK_SIZE(c->out)/2;;
        uint16_t *dat = (uint16_t *)BLOCK_DATA(c->out), last = 0;

        if (n*2 < BLOCK_SIZE(c->out)) {
            // half word
            last = *(uint8_t *)dat;
            c->vv->varint_put32_blk(b, zigzag16(last));
            dat = (uint16_t *)(((uint8_t *)dat)+1);
        }

        for (i = 0; i < n; i++) {
            uint16_t d = dat[i] - last; // possibly unaligned
            last = dat[i];
            c->vv->varint_put32_blk(b, zigzag16(d));
        }

        break;
    }

    case 4: {
        int i, n = BLOCK_SIZE(c->out)/4;;
        uint32_t *dat = (uint32_t *)BLOCK_DATA(c->out), last = 0;

        for (i = 0; i < n; i++) {
            uint32_t d = dat[i] - last;
            last = dat[i];
            c->vv->varint_put32_blk(b, zigzag32(d));
        }

        break;
    }

    case 1: {
        int i, n = BLOCK_SIZE(c->out);;
        uint8_t *dat = (uint8_t *)BLOCK_DATA(c->out), last = 0;

        for (i = 0; i < n; i++) {
            uint32_t d = dat[i] - last;
            last = dat[i];
            c->vv->varint_put32_blk(b, zigzag8(d));
        }

        break;
    }

    default:
        goto err;
    }

    if (c->u.e_xdelta.sub_codec->encode(NULL, c->u.e_xdelta.sub_codec,
                                      (char *)b->data, b->byte))
        goto err;

    r = 0;

 err:
    cram_free_block(b);
    return r;

}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
pushq %rax
movq %rdi, %r14
xorl %edi, %edi
xorl %esi, %esi
callq 0x4c675
testq %rax, %rax
je 0x8e9fb
movq %rax, %rbx
movzbl 0x68(%r14), %eax
cmpl $0x1, %eax
je 0x8ea54
cmpl $0x4, %eax
je 0x8ea06
movl $0xffffffff, %r15d      # imm = 0xFFFFFFFF
cmpl $0x2, %eax
jne 0x8eb03
movq 0x8(%r14), %rax
movq 0x20(%rax), %rbp
movq 0x30(%rax), %rax
movq %rax, %r12
shrq %r12
leal (%r12,%r12), %ecx
movslq %ecx, %rcx
cmpq %rcx, %rax
jbe 0x8ea9e
movzbl (%rbp), %r15d
movzwl %r15w, %esi
movq 0x10(%r14), %rax
addl %esi, %esi
movq %rbx, %rdi
callq *0x58(%rax)
incq %rbp
jmp 0x8eaa1
movl $0xffffffff, %r15d      # imm = 0xFFFFFFFF
jmp 0x8eb0b
movq 0x8(%r14), %rax
movq 0x30(%rax), %r15
shrq $0x2, %r15
testl %r15d, %r15d
jle 0x8eaeb
movq 0x20(%rax), %r12
andl $0x7fffffff, %r15d      # imm = 0x7FFFFFFF
xorl %r13d, %r13d
xorl %eax, %eax
movl (%r12,%r13,4), %ebp
movl %ebp, %esi
subl %eax, %esi
movq 0x10(%r14), %rax
leal (%rsi,%rsi), %ecx
sarl $0x1f, %esi
xorl %ecx, %esi
movq %rbx, %rdi
callq *0x58(%rax)
incq %r13
movl %ebp, %eax
cmpq %r13, %r15
jne 0x8ea2b
jmp 0x8eaeb
movq 0x8(%r14), %rax
movq 0x30(%rax), %r15
testl %r15d, %r15d
jle 0x8eaeb
movq 0x20(%rax), %r12
andl $0x7fffffff, %r15d      # imm = 0x7FFFFFFF
xorl %r13d, %r13d
xorl %eax, %eax
movb (%r12,%r13), %bpl
movl %ebp, %ecx
subb %al, %cl
movq 0x10(%r14), %rax
leal (%rcx,%rcx), %edx
sarb $0x7, %cl
xorb %dl, %cl
movzbl %cl, %esi
movq %rbx, %rdi
callq *0x58(%rax)
incq %r13
movl %ebp, %eax
cmpq %r13, %r15
jne 0x8ea75
jmp 0x8eaeb
xorl %r15d, %r15d
testl %r12d, %r12d
jle 0x8eaeb
andl $0x7fffffff, %r12d      # imm = 0x7FFFFFFF
xorl %r13d, %r13d
movq %r12, (%rsp)
movq %rbp, %r12
movzwl (%rbp,%r13,2), %ebp
movl %ebp, %eax
subl %r15d, %eax
movswl %ax, %ecx
movq 0x10(%r14), %rdx
addl %eax, %eax
sarl $0xf, %ecx
xorl %eax, %ecx
movzwl %cx, %esi
movq %rbx, %rdi
callq *0x58(%rdx)
incq %r13
movl %ebp, %r15d
movq %r12, %rbp
movq (%rsp), %r12
cmpq %r13, %r12
jne 0x8eab4
movq 0x78(%r14), %rsi
movq 0x20(%rbx), %rdx
movl 0x30(%rbx), %ecx
xorl %r15d, %r15d
xorl %edi, %edi
callq *0x30(%rsi)
negl %eax
sbbl %r15d, %r15d
movq %rbx, %rdi
callq 0x4ceb6
movl %r15d, %eax
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq