// File: cristian-bicheru[P]arith/./arith.h
// Function: arith::UncompressBuffer(std::vector<unsigned char, std::allocator<unsigned char>>&, arith::CodecProbabilityTable&, buffer::CodecByteStream&, unsigned long)
void UncompressBuffer(std::vector<unsigned char>& InputBuffer,
                          CodecProbabilityTable& ProbabilityTable,
                          buffer::CodecByteStream& OutputBuffer,
                          uint64_t UncompressedSize) {
        uint8_t shift = InputBuffer[256*4+8];
        uint8_t residual_byte = InputBuffer[256*4+9];
        buffer::CodecBitIterator Buffer(InputBuffer, 256*4+10);
        uint64_t high = MAXVAL;
        uint64_t low = 0ull;
        uint64_t value = 0ull;
        uint64_t range, denom, count, pLow, pUp;
        denom = ProbabilityTable.GetDenom();
        uint8_t byte;

        // Rate Stuff
        auto StartTime = std::chrono::high_resolution_clock::now();
        uint64_t StartSize = UncompressedSize;
        uint64_t BufSizePct = UncompressedSize/100ull;

        if (shift != 0) {
            for (uint8_t i = 0; i < shift; i++) {
                OutputBuffer.WriteBit((residual_byte>>(shift-i-1u))&1u);
            }
        }

        for (uint8_t i = 0; i < 32; i++) {
            value <<= 1ull;
            value += Buffer.ReadBit();
        }

        while (UncompressedSize > 1) {

            if ((UncompressedSize<<44ll>>44ull) == 0ull) {
                std::cout << "\33[2K\r";
                std::cout << "Uncompressing... " << 101ull-UncompressedSize/BufSizePct << "%  @" << (StartSize-UncompressedSize)/std::chrono::duration_cast<std::chrono::duration<double>>(std::chrono::high_resolution_clock::now() - StartTime).count() << " Bytes/Second." << std::flush;
            }

            range = high-low+1ull;
            count = ((value - low + 1ull) * denom - 1ull) / range;
            std::tie(pLow, pUp, byte) = ProbabilityTable.DecodeFromCount(count);
            OutputBuffer.WriteByte(byte);
            high = low + (range*pUp)/denom - 1ull;
            low = low + (range*pLow)/denom;

            while (true) {
                if (high < HALF) {
                    //pass;
                } else if (low >= HALF) {
                    value -= HALF;
                    low -= HALF;
                    high -= HALF;
                } else if (high < THREE_QUARTERS && low >= QUARTER) {
                    value -= QUARTER;
                    low -= QUARTER;
                    high -= QUARTER;
                } else {
                    break;
                }
                low <<= 1ull;
                high <<= 1ull;
                high++;
                value <<= 1ull;
                value += Buffer.ReadBit();
            }


            UncompressedSize--;
        }

        for (uint8_t i = 0; i < 8u-shift; i++) {
            OutputBuffer.WriteBit((residual_byte>>(7u-i))&1u);
        }

        std::cout << std::endl;
    }

// Assembly:
subq $0x1a8, %rsp            # imm = 0x1A8
movq %rdi, 0x1a0(%rsp)
movq %rsi, 0x198(%rsp)
movq %rdx, 0x190(%rsp)
movq %rcx, 0x188(%rsp)
movq 0x1a0(%rsp), %rdi
movl $0x408, %esi            # imm = 0x408
callq 0x4ae0
movb (%rax), %al
movb %al, 0x187(%rsp)
movq 0x1a0(%rsp), %rdi
movl $0x409, %esi            # imm = 0x409
callq 0x4ae0
movb (%rax), %al
movb %al, 0x186(%rsp)
movq 0x1a0(%rsp), %rsi
leaq 0x140(%rsp), %rdi
movq %rdi, 0x78(%rsp)
callq 0x4f00
movq 0x78(%rsp), %rsi
leaq 0x158(%rsp), %rdi
movl $0x40a, %edx            # imm = 0x40A
callq 0x5000
jmp 0x3230
leaq 0x140(%rsp), %rdi
callq 0x5050
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
movq %rax, 0x128(%rsp)
movq $0x0, 0x120(%rsp)
movq $0x0, 0x118(%rsp)
movq 0x198(%rsp), %rdi
callq 0x50b0
movl %eax, 0x74(%rsp)
jmp 0x3275
movl 0x74(%rsp), %eax
movl %eax, %eax
movq %rax, 0x108(%rsp)
callq 0x2030
movq %rax, 0xe0(%rsp)
movq 0x188(%rsp), %rax
movq %rax, 0xd8(%rsp)
movq 0x188(%rsp), %rax
movl $0x64, %ecx
xorl %edx, %edx
divq %rcx
movq %rax, 0xd0(%rsp)
movzbl 0x187(%rsp), %eax
cmpl $0x0, %eax
je 0x3384
movb $0x0, 0xcf(%rsp)
movzbl 0xcf(%rsp), %eax
movzbl 0x187(%rsp), %ecx
cmpl %ecx, %eax
jge 0x3382
movq 0x190(%rsp), %rdi
movzbl 0x186(%rsp), %eax
movzbl 0x187(%rsp), %ecx
movzbl 0xcf(%rsp), %edx
subl %edx, %ecx
decb %cl
movzbl %cl, %ecx
btl %ecx, %eax
setb %al
movzbl %al, %esi
callq 0x50d0
jmp 0x3322
jmp 0x3324
movb 0xcf(%rsp), %al
addb $0x1, %al
movb %al, 0xcf(%rsp)
jmp 0x32d3
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x138(%rsp)
movl %eax, 0x134(%rsp)
leaq 0x140(%rsp), %rdi
callq 0x5050
jmp 0x38d5
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x138(%rsp)
movl %eax, 0x134(%rsp)
leaq 0x158(%rsp), %rdi
callq 0x5370
jmp 0x38d5
jmp 0x3384
movb $0x0, 0xce(%rsp)
movzbl 0xce(%rsp), %eax
cmpl $0x20, %eax
jge 0x33e8
movq 0x118(%rsp), %rax
addq %rax, %rax
movq %rax, 0x118(%rsp)
leaq 0x158(%rsp), %rdi
callq 0x5160
movb %al, 0x73(%rsp)
jmp 0x33bf
movb 0x73(%rsp), %al
movzbl %al, %eax
addq 0x118(%rsp), %rax
movq %rax, 0x118(%rsp)
movb 0xce(%rsp), %al
addb $0x1, %al
movb %al, 0xce(%rsp)
jmp 0x338c
jmp 0x33ea
cmpq $0x1, 0x188(%rsp)
jbe 0x3846
movq 0x188(%rsp), %rax
shlq $0x2c, %rax
shrq $0x2c, %rax
cmpq $0x0, %rax
jne 0x3585
movq 0x1eba6(%rip), %rdi     # 0x21fc0
leaq 0x14c37(%rip), %rsi     # 0x18058
callq 0x21a0
jmp 0x3428
movq 0x1eb91(%rip), %rdi     # 0x21fc0
leaq 0x14c4c(%rip), %rsi     # 0x18082
callq 0x21a0
movq %rax, 0x68(%rsp)
jmp 0x3442
movq 0x68(%rsp), %rdi
movq 0x188(%rsp), %rax
movq 0xd0(%rsp), %rcx
xorl %edx, %edx
divq %rcx
movl $0x65, %esi
subq %rax, %rsi
callq 0x2180
movq %rax, 0x60(%rsp)
jmp 0x3470
movq 0x60(%rsp), %rdi
leaq 0x14bf2(%rip), %rsi     # 0x1806e
callq 0x21a0
movq %rax, 0x58(%rsp)
jmp 0x3488
movq 0xd8(%rsp), %rax
movq 0x188(%rsp), %rcx
subq %rcx, %rax
movq %rax, %xmm0
movaps 0x14b69(%rip), %xmm1    # 0x18010
punpckldq %xmm1, %xmm0    # xmm0 = xmm0[0],xmm1[0],xmm0[1],xmm1[1]
movapd 0x14b6d(%rip), %xmm1    # 0x18020
subpd %xmm1, %xmm0
movaps %xmm0, %xmm1
unpckhpd %xmm0, %xmm0            # xmm0 = xmm0[1,1]
addsd %xmm1, %xmm0
movsd %xmm0, 0x48(%rsp)
callq 0x2030
movq %rax, 0xb0(%rsp)
leaq 0xb0(%rsp), %rdi
leaq 0xe0(%rsp), %rsi
callq 0x4cd0
movq %rax, 0x50(%rsp)
jmp 0x34f1
movq 0x50(%rsp), %rax
movq %rax, 0xb8(%rsp)
leaq 0xb8(%rsp), %rdi
callq 0x4ca0
movsd %xmm0, 0x40(%rsp)
jmp 0x3513
movsd 0x40(%rsp), %xmm0
movsd %xmm0, 0xc0(%rsp)
leaq 0xc0(%rsp), %rdi
callq 0x4d20
movsd %xmm0, 0x38(%rsp)
jmp 0x3537
movq 0x58(%rsp), %rdi
movsd 0x38(%rsp), %xmm1
movsd 0x48(%rsp), %xmm0
divsd %xmm1, %xmm0
callq 0x2340
movq %rax, 0x30(%rsp)
jmp 0x3558
movq 0x30(%rsp), %rdi
leaq 0x14b0f(%rip), %rsi     # 0x18073
callq 0x21a0
movq %rax, 0x28(%rsp)
jmp 0x3570
movq 0x28(%rsp), %rdi
movq 0x1ea4c(%rip), %rsi     # 0x21fc8
callq 0x21d0
jmp 0x3583
jmp 0x3585
movq 0x128(%rsp), %rax
movq 0x120(%rsp), %rcx
subq %rcx, %rax
incq %rax
movq %rax, 0x110(%rsp)
movq 0x118(%rsp), %rax
movq 0x120(%rsp), %rcx
subq %rcx, %rax
incq %rax
movq 0x108(%rsp), %rcx
imulq %rcx, %rax
decq %rax
movq 0x110(%rsp), %rcx
xorl %edx, %edx
divq %rcx
movq %rax, 0x100(%rsp)
movq 0x198(%rsp), %rsi
movq 0x100(%rsp), %rdx
leaq 0xa4(%rsp), %rdi
callq 0x51d0
jmp 0x35fc
leaq 0x88(%rsp), %rdi
movq %rdi, 0x20(%rsp)
leaq 0xf8(%rsp), %rsi
leaq 0xf0(%rsp), %rdx
leaq 0xef(%rsp), %rcx
callq 0x52f0
movq 0x20(%rsp), %rdi
leaq 0xa4(%rsp), %rsi
callq 0x5330
movq 0x190(%rsp), %rdi
movzbl 0xef(%rsp), %esi
callq 0x4c10
jmp 0x364f
movq 0x120(%rsp), %rax
movq %rax, 0x10(%rsp)
movq 0x110(%rsp), %rax
imulq 0xf0(%rsp), %rax
xorl %ecx, %ecx
movl %ecx, %edx
divq 0x108(%rsp)
movq %rax, %rcx
movq 0x10(%rsp), %rax
addq %rcx, %rax
subq $0x1, %rax
movq %rax, 0x128(%rsp)
movq 0x120(%rsp), %rax
movq %rax, 0x18(%rsp)
movq 0x110(%rsp), %rax
imulq 0xf8(%rsp), %rax
xorl %ecx, %ecx
movl %ecx, %edx
divq 0x108(%rsp)
movq %rax, %rcx
movq 0x18(%rsp), %rax
addq %rcx, %rax
movq %rax, 0x120(%rsp)
jmp 0x36cf
movl $0x80000000, %eax       # imm = 0x80000000
cmpq %rax, 0x128(%rsp)
jae 0x36e3
jmp 0x37b2
movl $0x80000000, %eax       # imm = 0x80000000
cmpq %rax, 0x120(%rsp)
jb 0x374b
movq 0x118(%rsp), %rax
movabsq $0x80000000, %rcx       # imm = 0x80000000
subq %rcx, %rax
movq %rax, 0x118(%rsp)
movq 0x120(%rsp), %rax
movabsq $0x80000000, %rcx       # imm = 0x80000000
subq %rcx, %rax
movq %rax, 0x120(%rsp)
movq 0x128(%rsp), %rax
movabsq $0x80000000, %rcx       # imm = 0x80000000
subq %rcx, %rax
movq %rax, 0x128(%rsp)
jmp 0x37b0
movl $0xc0000000, %eax       # imm = 0xC0000000
cmpq %rax, 0x128(%rsp)
jae 0x37ac
cmpq $0x40000000, 0x120(%rsp) # imm = 0x40000000
jb 0x37ac
movq 0x118(%rsp), %rax
subq $0x40000000, %rax       # imm = 0x40000000
movq %rax, 0x118(%rsp)
movq 0x120(%rsp), %rax
subq $0x40000000, %rax       # imm = 0x40000000
movq %rax, 0x120(%rsp)
movq 0x128(%rsp), %rax
subq $0x40000000, %rax       # imm = 0x40000000
movq %rax, 0x128(%rsp)
jmp 0x37ae
jmp 0x382d
jmp 0x37b0
jmp 0x37b2
movq 0x120(%rsp), %rax
addq %rax, %rax
movq %rax, 0x120(%rsp)
movq 0x128(%rsp), %rax
addq %rax, %rax
movq %rax, 0x128(%rsp)
movq 0x128(%rsp), %rax
incq %rax
movq %rax, 0x128(%rsp)
movq 0x118(%rsp), %rax
addq %rax, %rax
movq %rax, 0x118(%rsp)
leaq 0x158(%rsp), %rdi
callq 0x5160
movb %al, 0xf(%rsp)
jmp 0x3811
movb 0xf(%rsp), %al
movzbl %al, %eax
addq 0x118(%rsp), %rax
movq %rax, 0x118(%rsp)
jmp 0x36cd
movq 0x188(%rsp), %rax
addq $-0x1, %rax
movq %rax, 0x188(%rsp)
jmp 0x33ea
movb $0x0, 0x87(%rsp)
movzbl 0x87(%rsp), %eax
movzbl 0x187(%rsp), %edx
movl $0x8, %ecx
subl %edx, %ecx
cmpl %ecx, %eax
jae 0x38ab
movq 0x190(%rsp), %rdi
movzbl 0x186(%rsp), %eax
movb 0x87(%rsp), %dl
movb $0x7, %cl
subb %dl, %cl
movzbl %cl, %ecx
btl %ecx, %eax
setb %al
movzbl %al, %esi
callq 0x50d0
jmp 0x3897
jmp 0x3899
movb 0x87(%rsp), %al
addb $0x1, %al
movb %al, 0x87(%rsp)
jmp 0x384e
movq 0x1e70e(%rip), %rdi     # 0x21fc0
movq 0x1e6e7(%rip), %rsi     # 0x21fa0
callq 0x21d0
jmp 0x38c0
leaq 0x158(%rsp), %rdi
callq 0x5370
addq $0x1a8, %rsp            # imm = 0x1A8
retq
movq 0x138(%rsp), %rdi
callq 0x2310
nopw %cs:(%rax,%rax)