// File: /workspace/github_cpp_makefile_star2_O3/cristian-bicheru[P]arith/./arith.h
// Function: arith::CompressBuffer(std::vector<unsigned char, std::allocator<unsigned char>>&, arith::CodecProbabilityTable&, buffer::CodecByteStream&)
void CompressBuffer(std::vector<unsigned char>& InputBuffer,
                        CodecProbabilityTable& ProbabilityTable,
                        buffer::CodecByteStream& OutputBuffer) {
        uint64_t high = MAXVAL;
        uint64_t low = 0ull;
        uint8_t shift = ProbabilityTable.GetShift();
        buffer::CodecBufferWrapper Buffer(InputBuffer, shift);
        OutputBuffer.WriteByte(shift);
        OutputBuffer.WriteByte((InputBuffer[InputBuffer.size()-1]<<shift)+(InputBuffer[0]>>(8u-shift))); // residual due to shift
        uint64_t pLow, pUp, pDenom, range;

        // Rate Stuff
        auto StartTime = std::chrono::high_resolution_clock::now();
        uint64_t BufSizePct = Buffer.Size()/100ull;


        for (uint64_t i = 0; i < Buffer.Size(); i++) {

            if ((i<<44ll>>44ull) == 0ull) {
                std::cout << "\33[2K\r";
                std::cout << "Compressing... " << i/BufSizePct+1 << "%  @" << double(i)/std::chrono::duration_cast<std::chrono::duration<double>>(std::chrono::high_resolution_clock::now() - StartTime).count() << " Bytes/Second." << std::flush;
            }

            range = high - low + 1ull;
            std::tie(pLow, pUp, pDenom) = ProbabilityTable.GetProbability(Buffer[i]);
            high = low + (range * pUp / pDenom) - 1ull;
            low = low + (range * pLow / pDenom);

            while (true) {
                if (high < HALF) {
                    OutputBuffer.WriteBitBuffered(0u);
                } else if (low >= HALF) {
                    OutputBuffer.WriteBitBuffered(1u);
                } else if (high < THREE_QUARTERS && low >= QUARTER) {
                    OutputBuffer.IncPendingBits();
                    low -= QUARTER;
                    high -= QUARTER;
                } else {
                    break;
                }
                high <<= 1ull;
                high++;
                low <<= 1ull;
                high &= MAXVAL;
                low &= MAXVAL;
            }
        }

        OutputBuffer.IncPendingBits();
        if (low < QUARTER) {
            OutputBuffer.WriteBitBuffered(0);
        } else {
            OutputBuffer.WriteBitBuffered(1);
        }

        std::cout << std::endl;
    }

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x68, %rsp
movq %rdx, %rbx
movq %rdi, %r15
movq %rsi, 0x20(%rsp)
movzbl 0x404(%rsi), %ebp
leaq 0x28(%rsp), %rdi
movq %r15, %rsi
movl %ebp, %edx
callq 0x3b52
movq %rbx, %rdi
movl %ebp, %esi
callq 0x3baa
movq 0x8(%r15), %rax
movzbl -0x1(%rax), %eax
movl %ebp, %ecx
shll %cl, %eax
movq (%r15), %rcx
movzbl (%rcx), %edx
movb $0x8, %cl
subb %bpl, %cl
shrl %cl, %edx
addl %eax, %edx
movzbl %dl, %esi
movq %rbx, %rdi
callq 0x3baa
callq 0x2040
movq %rax, 0x18(%rsp)
movq 0x48(%rsp), %rcx
movq %rcx, %rax
shrq $0x2, %rax
movabsq $0x28f5c28f5c28f5c3, %rdx # imm = 0x28F5C28F5C28F5C3
mulq %rdx
testq %rcx, %rcx
je 0x2c2b
shrq $0x2, %rdx
movq %rdx, 0x10(%rsp)
movl $0x80000000, %ebp       # imm = 0x80000000
leaq 0x7fffffff(%rbp), %r15
xorl %eax, %eax
leaq 0x40000000(%rbp), %r14
movq $-0x40000000, %r13      # imm = 0xC0000000
xorl %r12d, %r12d
movq %rax, 0x8(%rsp)
shlq $0x2c, %rax
jne 0x2b68
movl $0x5, %edx
movq 0xa52e(%rip), %rdi      # 0xcfc8
leaq 0x65c7(%rip), %rsi      # 0x9068
callq 0x2220
movl $0xf, %edx
movq 0xa516(%rip), %rdi      # 0xcfc8
leaq 0x65b5(%rip), %rsi      # 0x906e
callq 0x2220
movq 0x8(%rsp), %rax
xorl %edx, %edx
divq 0x10(%rsp)
leaq 0x1(%rax), %rsi
movq 0xa4f3(%rip), %rdi      # 0xcfc8
callq 0x2130
movq %rax, (%rsp)
movl $0x4, %edx
movq (%rsp), %rdi
leaq 0x6590(%rip), %rsi      # 0x907e
callq 0x2220
movsd 0x8(%rsp), %xmm0
unpcklps 0x6510(%rip), %xmm0     # xmm0 = xmm0[0],mem[0],xmm0[1],mem[1]
subpd 0x6518(%rip), %xmm0     # 0x9020
movapd %xmm0, %xmm1
unpckhpd %xmm0, %xmm1            # xmm1 = xmm1[1],xmm0[1]
addsd %xmm0, %xmm1
movapd %xmm1, 0x50(%rsp)
callq 0x2040
subq 0x18(%rsp), %rax
xorps %xmm1, %xmm1
cvtsi2sd %rax, %xmm1
divsd 0x6514(%rip), %xmm1     # 0x9048
movapd 0x50(%rsp), %xmm0
divsd %xmm1, %xmm0
movq (%rsp), %rdi
callq 0x22d0
movl $0xe, %edx
movq %rax, %rdi
leaq 0x652d(%rip), %rsi      # 0x9083
movq %rax, (%rsp)
callq 0x2220
movq (%rsp), %rdi
callq 0x2140
movq 0x28(%rsp), %rax
movq 0x8(%rsp), %rsi
movzbl (%rax,%rsi), %edx
movb 0x40(%rsp), %cl
shll %cl, %edx
movzbl 0x1(%rax,%rsi), %eax
movb 0x41(%rsp), %cl
shrl %cl, %eax
addl %edx, %eax
movzbl %al, %eax
movq 0x20(%rsp), %rdx
movl 0x400(%rdx), %ecx
movl (%rdx,%rax,4), %esi
movl 0x4(%rdx,%rax,4), %eax
subq %r12, %r15
incq %r15
imulq %r15, %rax
xorl %edx, %edx
divq %rcx
leaq (%r12,%rax), %rdi
decq %rdi
imulq %rsi, %r15
movq %r15, %rax
xorl %edx, %edx
divq %rcx
addq %rax, %r12
movq %rdi, %r15
cmpq %rbp, %r15
jae 0x2bcf
xorl %eax, %eax
jmp 0x2bda
movb $0x1, %al
cmpq $0x7fffffff, %r12       # imm = 0x7FFFFFFF
jbe 0x2be7
movzbl %al, %esi
movq %rbx, %rdi
callq 0x3bfe
jmp 0x2bfe
cmpq %r14, %r15
jae 0x2c09
cmpq $0x40000000, %r12       # imm = 0x40000000
jb 0x2c09
incl 0x28(%rbx)
addq %r13, %r12
addq %r13, %r15
addl %r15d, %r15d
addl %r12d, %r12d
incq %r15
jmp 0x2bc6
movq 0x8(%rsp), %rax
incq %rax
cmpq 0x48(%rsp), %rax
jb 0x2a7f
cmpq $0x40000000, %r12       # imm = 0x40000000
setae %al
incl 0x28(%rbx)
jmp 0x2c30
incl 0x28(%rbx)
xorl %eax, %eax
movzbl %al, %esi
movq %rbx, %rdi
callq 0x3bfe
movq 0xa386(%rip), %rdi      # 0xcfc8
movq (%rdi), %rax
addq -0x18(%rax), %rdi
movl $0xa, %esi
callq 0x21d0
movsbl %al, %esi
movq 0xa36b(%rip), %rdi      # 0xcfc8
callq 0x2030
movq %rax, %rdi
callq 0x2140
movq 0x28(%rsp), %rdi
testq %rdi, %rdi
je 0x2c79
callq 0x21c0
addq $0x68, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x2c90
jmp 0x2c90
jmp 0x2c90
jmp 0x2c90
movq %rax, %rbx
movq 0x28(%rsp), %rdi
testq %rdi, %rdi
je 0x2ca2
callq 0x21c0
movq %rbx, %rdi
callq 0x2320