// File: /workspace/github_c_makefile_star2_O2/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, %r13
xorl %edi, %edi
xorl %esi, %esi
callq 0x3f426
testq %rax, %rax
je 0x7134d
movq %rax, %r12
movzbl 0x68(%r13), %eax
cmpl $0x1, %eax
je 0x713a2
cmpl $0x4, %eax
je 0x71356
cmpl $0x2, %eax
jne 0x713e9
movq 0x8(%r13), %rax
movq 0x20(%rax), %r15
movq 0x30(%rax), %rax
movq %rax, %rcx
shrq %rcx
movq %r13, %rdx
movq %rcx, (%rsp)
addl %ecx, %ecx
movslq %ecx, %rcx
xorl %r13d, %r13d
cmpq %rcx, %rax
jbe 0x713ef
movzbl (%r15), %ebp
movzwl %bp, %esi
movq %rdx, %rbx
movq 0x10(%rdx), %rax
addl %esi, %esi
movq %r12, %r14
movq %r12, %rdi
callq *0x58(%rax)
incq %r15
jmp 0x713f7
pushq $-0x1
popq %r14
jmp 0x7145e
movq %r12, %r14
movq %r13, %rbx
movq 0x8(%r13), %rax
movq 0x20(%rax), %r15
movq 0x30(%rax), %r12
shrq $0x2, %r12
xorl %r13d, %r13d
testl %r12d, %r12d
cmovlel %r13d, %r12d
xorl %eax, %eax
cmpq %r13, %r12
je 0x7143a
movl (%r15,%r13,4), %ebp
movl %ebp, %esi
subl %eax, %esi
movq 0x10(%rbx), %rax
leal (%rsi,%rsi), %ecx
sarl $0x1f, %esi
xorl %ecx, %esi
movq %r14, %rdi
callq *0x58(%rax)
incq %r13
movl %ebp, %eax
jmp 0x71378
movq %r12, %r14
movq %r13, %rbx
movq 0x8(%r13), %rax
movl 0x30(%rax), %r15d
movq 0x20(%rax), %r12
xorl %r13d, %r13d
testl %r15d, %r15d
cmovlel %r13d, %r15d
xorl %eax, %eax
cmpq %r13, %r15
je 0x7143a
movb (%r12,%r13), %bpl
movl %ebp, %ecx
subb %al, %cl
movq 0x10(%rbx), %rax
leal (%rcx,%rcx), %edx
sarb $0x7, %cl
xorb %dl, %cl
movzbl %cl, %esi
movq %r14, %rdi
callq *0x58(%rax)
incq %r13
movl %ebp, %eax
jmp 0x713c0
pushq $-0x1
popq %r14
jmp 0x71456
movq %rdx, %rbx
movq %r12, %r14
xorl %ebp, %ebp
movq (%rsp), %rax
testl %eax, %eax
cmovlel %r13d, %eax
movq %rax, (%rsp)
cmpq %r13, (%rsp)
je 0x7143a
movq %r15, %r12
movzwl (%r15,%r13,2), %r15d
movl %r15d, %eax
subl %ebp, %eax
movswl %ax, %ecx
movq 0x10(%rbx), %rdx
addl %eax, %eax
sarl $0xf, %ecx
xorl %eax, %ecx
movzwl %cx, %esi
movq %r14, %rdi
callq *0x58(%rdx)
incq %r13
movl %r15d, %ebp
movq %r12, %r15
jmp 0x71405
movq 0x78(%rbx), %rsi
movq %r14, %r12
movq 0x20(%r14), %rdx
movl 0x30(%r14), %ecx
xorl %r14d, %r14d
xorl %edi, %edi
callq *0x30(%rsi)
negl %eax
sbbl %r14d, %r14d
movq %r12, %rdi
callq 0x3f8fc
movl %r14d, %eax
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq