// File: karel-brinda[P]ococo/ext/htslib/./cram/rANS_byte.h
// Function: RansEncSymbolInit
static inline void RansEncSymbolInit(RansEncSymbol* s, uint32_t start, uint32_t freq, uint32_t scale_bits)
{
    RansAssert(scale_bits <= 16);
    RansAssert(start <= (1u << scale_bits));
    RansAssert(freq <= (1u << scale_bits) - start);

    // Say M := 1 << scale_bits.
    //
    // The original encoder does:
    //   x_new = (x/freq)*M + start + (x%freq)
    //
    // The fast encoder does (schematically):
    //   q     = mul_hi(x, rcp_freq) >> rcp_shift   (division)
    //   r     = x - q*freq                         (remainder)
    //   x_new = q*M + bias + r                     (new x)
    // plugging in r into x_new yields:
    //   x_new = bias + x + q*(M - freq)
    //        =: bias + x + q*cmpl_freq             (*)
    //
    // and we can just precompute cmpl_freq. Now we just need to
    // set up our parameters such that the original encoder and
    // the fast encoder agree.

    s->x_max = ((RANS_BYTE_L >> scale_bits) << 8) * freq;
    s->cmpl_freq = (uint16_t) ((1 << scale_bits) - freq);
    if (freq < 2) {
        // freq=0 symbols are never valid to encode, so it doesn't matter what
        // we set our values to.
        //
        // freq=1 is tricky, since the reciprocal of 1 is 1; unfortunately,
        // our fixed-point reciprocal approximation can only multiply by values
        // smaller than 1.
        //
        // So we use the "next best thing": rcp_freq=0xffffffff, rcp_shift=0.
        // This gives:
        //   q = mul_hi(x, rcp_freq) >> rcp_shift
        //     = mul_hi(x, (1<<32) - 1)) >> 0
        //     = floor(x - x/(2^32))
        //     = x - 1 if 1 <= x < 2^32
        // and we know that x>0 (x=0 is never in a valid normalization interval).
        //
        // So we now need to choose the other parameters such that
        //   x_new = x*M + start
        // plug it in:
        //     x*M + start                   (desired result)
        //   = bias + x + q*cmpl_freq        (*)
        //   = bias + x + (x - 1)*(M - 1)    (plug in q=x-1, cmpl_freq)
        //   = bias + 1 + (x - 1)*M
        //   = x*M + (bias + 1 - M)
        //
        // so we have start = bias + 1 - M, or equivalently
        //   bias = start + M - 1.
        s->rcp_freq = ~0u;
        s->rcp_shift = 0;
        s->bias = start + (1 << scale_bits) - 1;
    } else {
        // Alverson, "Integer Division using reciprocals"
        // shift=ceil(log2(freq))
        uint32_t shift = 0;
        while (freq > (1u << shift))
            shift++;

        s->rcp_freq = (uint32_t) (((1ull << (shift + 31)) + freq-1) / freq);
        s->rcp_shift = shift - 1;

        // With these values, 'q' is the correct quotient, so we
        // have bias=start.
        s->bias = start;
    }

    s->rcp_shift += 32; // Avoid the extra >>32 in RansEncPutSymbol
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x20, %rsp
movq %rdi, -0x8(%rbp)
movl %esi, -0xc(%rbp)
movl %edx, -0x10(%rbp)
movl %ecx, -0x14(%rbp)
cmpl $0x10, -0x14(%rbp)
ja 0x5898d
jmp 0x589ac
leaq 0x24f24(%rip), %rdi     # 0x7d8b8
leaq 0x24f2e(%rip), %rsi     # 0x7d8c9
movl $0xb9, %edx
leaq 0x24f35(%rip), %rcx     # 0x7d8dc
callq 0x4360
movl -0xc(%rbp), %eax
movl -0x14(%rbp), %ecx
movl $0x1, %edx
shll %cl, %edx
movl %edx, %ecx
cmpl %ecx, %eax
ja 0x589c1
jmp 0x589e0
leaq 0x24f5a(%rip), %rdi     # 0x7d922
leaq 0x24efa(%rip), %rsi     # 0x7d8c9
movl $0xba, %edx
leaq 0x24f01(%rip), %rcx     # 0x7d8dc
callq 0x4360
movl -0x10(%rbp), %eax
movl -0x14(%rbp), %ecx
movl $0x1, %edx
shll %cl, %edx
movl %edx, %ecx
subl -0xc(%rbp), %ecx
cmpl %ecx, %eax
ja 0x589f8
jmp 0x58a17
leaq 0x24f3f(%rip), %rdi     # 0x7d93e
leaq 0x24ec3(%rip), %rsi     # 0x7d8c9
movl $0xbb, %edx
leaq 0x24eca(%rip), %rcx     # 0x7d8dc
callq 0x4360
movl -0x14(%rbp), %ecx
movl $0x800000, %eax         # imm = 0x800000
shrl %cl, %eax
movl %eax, %ecx
shll $0x8, %ecx
imull -0x10(%rbp), %ecx
movq -0x8(%rbp), %rax
movl %ecx, (%rax)
movl -0x14(%rbp), %ecx
movl $0x1, %eax
shll %cl, %eax
subl -0x10(%rbp), %eax
movw %ax, %cx
movq -0x8(%rbp), %rax
movw %cx, 0xc(%rax)
cmpl $0x2, -0x10(%rbp)
jae 0x58a84
movq -0x8(%rbp), %rax
movl $0xffffffff, 0x4(%rax)  # imm = 0xFFFFFFFF
movq -0x8(%rbp), %rax
movw $0x0, 0xe(%rax)
movl -0xc(%rbp), %eax
movl %eax, -0x1c(%rbp)
movl -0x14(%rbp), %ecx
movl $0x1, %eax
shll %cl, %eax
movl -0x1c(%rbp), %ecx
addl %eax, %ecx
subl $0x1, %ecx
movq -0x8(%rbp), %rax
movl %ecx, 0x8(%rax)
jmp 0x58af1
movl $0x0, -0x18(%rbp)
movl -0x10(%rbp), %eax
movl -0x18(%rbp), %ecx
movl $0x1, %edx
shll %cl, %edx
movl %edx, %ecx
cmpl %ecx, %eax
jbe 0x58aa9
movl -0x18(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x18(%rbp)
jmp 0x58a8b
movl -0x18(%rbp), %eax
addl $0x1f, %eax
movl %eax, %eax
movl %eax, %ecx
movl $0x1, %eax
shlq %cl, %rax
movl -0x10(%rbp), %ecx
addq %rcx, %rax
subq $0x1, %rax
movl -0x10(%rbp), %ecx
xorl %edx, %edx
divq %rcx
movl %eax, %ecx
movq -0x8(%rbp), %rax
movl %ecx, 0x4(%rax)
movl -0x18(%rbp), %eax
subl $0x1, %eax
movw %ax, %cx
movq -0x8(%rbp), %rax
movw %cx, 0xe(%rax)
movl -0xc(%rbp), %ecx
movq -0x8(%rbp), %rax
movl %ecx, 0x8(%rax)
movq -0x8(%rbp), %rax
movzwl 0xe(%rax), %ecx
addl $0x20, %ecx
movw %cx, 0xe(%rax)
addq $0x20, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)