o
    Si2                     @   s   d Z ddlZddlZddlZddlZddlZddlmZm	Z	 		ddej
ded	ed
ededej
fddZG dd dZG dd dZdd ZedkrOe  dS dS )zArithmetic coder.    N   )	BitPackerBitUnpacker:0yE>Tpdftotal_range_bitsroundoff	min_rangecheckreturnc           
      C   s   |   } |r| |  | } d| }t| }|| | }|dks$J dd| | |    }||7 }tj|dd}	|dk rCtd|rm|	d d| ksSJ |	d |	dd |	dd  |k  si|	d |k rmtd	|	S )
a}  Turn the given PDF into a quantized CDF that splits
    [0, 2 ** self.total_range_bits - 1] into chunks of size roughly proportional
    to the PDF.

    Args:
        pdf (torch.Tensor): probability distribution, shape should be `[N]`.
        total_range_bits (int): see `ArithmeticCoder`, the typical range we expect
            during the coding process is `[0, 2 ** total_range_bits - 1]`.
        roundoff (float): will round the pdf up to that level to remove difference coming
        from e.g. evaluating the Language Model on different architectures.
        min_range (int): minimum range width. Should always be at least 2 for numerical
            stability. Use this to avoid pathological behavior is a value
            that is expected to be rare actually happens in real life.
        check (bool): if True, checks that nothing bad happened, can be deactivated for speed.
    r      zyou must reduce min_rangedimzmin_range must be at least 2.Nr   z(You must increase your total_range_bits.)detachfloorlenlongtorchcumsum
ValueErrorany)
r   r   r   r	   r
   total_rangecardinalityalpharangesquantized_cdf r   K/home/ubuntu/.local/lib/python3.10/site-packages/encodec/quantization/ac.pybuild_stable_quantized_cdf   s"   ,r   c                   @   s`   e Zd ZdZddeje defddZe	defdd	Z
d
d ZdedejfddZdd ZdS )ArithmeticCodera	  ArithmeticCoder,
    Let us take a distribution `p` over `N` symbols, and assume we have a stream
    of random variables `s_t` sampled from `p`. Let us assume that we have a budget
    of `B` bits that we can afford to write on device. There are `2**B` possible numbers,
    corresponding to the range `[0, 2 ** B - 1]`. We can map each of those number to a single
    sequence `(s_t)` by doing the following:

    1) Initialize the current range to` [0 ** 2 B - 1]`.
    2) For each time step t, split the current range into contiguous chunks,
        one for each possible outcome, with size roughly proportional to `p`.
        For instance, if `p = [0.75, 0.25]`, and the range is `[0, 3]`, the chunks
        would be `{[0, 2], [3, 3]}`.
    3) Select the chunk corresponding to `s_t`, and replace the current range with this.
    4) When done encoding all the values, just select any value remaining in the range.

    You will notice that this procedure can fail: for instance if at any point in time
    the range is smaller than `N`, then we can no longer assign a non-empty chunk to each
    possible outcome. Intuitively, the more likely a value is, the less the range width
    will reduce, and the longer we can go on encoding values. This makes sense: for any efficient
    coding scheme, likely outcomes would take less bits, and more of them can be coded
    with a fixed budget.

    In practice, we do not know `B` ahead of time, but we have a way to inject new bits
    when the current range decreases below a given limit (given by `total_range_bits`), without
    having to redo all the computations. If we encode mostly likely values, we will seldom
    need to inject new bits, but a single rare value can deplete our stock of entropy!

    In this explanation, we assumed that the distribution `p` was constant. In fact, the present
    code works for any sequence `(p_t)` possibly different for each timestep.
    We also assume that `s_t ~ p_t`, but that doesn't need to be true, although the smaller
    the KL between the true distribution and `p_t`, the most efficient the coding will be.

    Args:
        fo (IO[bytes]): file-like object to which the bytes will be written to.
        total_range_bits (int): the range `M` described above is `2 ** total_range_bits.
            Any time the current range width fall under this limit, new bits will
            be injected to rescale the initial range.
       for   c                 C   sB   |dksJ || _ td|d| _d| _d| _d| _g | _g | _d S )N   r   bitsr"   r   r   )r   r   packerlowhighmax_bit_dbg_dbg2selfr"   r   r   r   r   __init__`   s   
zArithmeticCoder.__init__r   c                 C      | j | j d S )zReturn the current range width.r   r(   r'   r-   r   r   r   deltaj   s   zArithmeticCoder.deltac                 C   s   | j | jksJ | j| j f| j d| jd  k sJ | jdkrq| j| j? }| j | j? }||krh|  j|| j> 8  _|  j || j> 8  _ | j | jksSJ | j | j| jf| jdksZJ |  jd8  _| j| nd S | jdksd S d S )Nr   r   r   )r(   r'   r)   r&   pushr-   b1b2r   r   r   _flush_common_prefixo   s   
 z$ArithmeticCoder._flush_common_prefixsymbolr   c                 C   s^  | j d| j k r&|  jd9  _| jd d | _|  jd7  _| j d| j k s|dkr,dn||d   }||  d }tt|| j d| j   }tt	|| j d| j   }| j| jksbJ | j| | _| j| | _| j| jks|J ||||f| j
| j| jf | j| j| jf |  }| j| jksJ | jdksJ | jdksJ | j|S )a  Push the given symbol on the stream, flushing out bits
        if possible.

        Args:
            symbol (int): symbol to encode with the AC.
            quantized_cdf (torch.Tensor): use `build_stable_quantized_cdf`
                to build this from your pdf estimate.
        r   r   r   r   =   )r2   r   r'   r(   r)   itemintmathceilr   r*   appendr+   r7   )r-   r8   r   	range_low
range_higheffective_loweffective_highoutsr   r   r   r3      s(   	zArithmeticCoder.pushc                 C   sL   | j dkr| j| j ? d@ }| j| |  j d8  _ | j dks| j  dS )z7Flush the remaining information to the stream.
        r   r   N)r)   r'   r&   r3   flush)r-   r5   r   r   r   rD      s   

zArithmeticCoder.flushNr!   )__name__
__module____qualname____doc__tpIObytesr;   r.   propertyr2   r7   r   Tensorr3   rD   r   r   r   r   r    8   s    '
r    c                   @   s^   e Zd ZdZddeje defddZe	defdd	Z
d
d Zdejdeje fddZdS )ArithmeticDecoderan  ArithmeticDecoder, see `ArithmeticCoder` for a detailed explanation.

    Note that this must be called with **exactly** the same parameters and sequence
    of quantized cdf as the arithmetic encoder or the wrong values will be decoded.

    If the AC encoder current range is [L, H], with `L` and `H` having the some common
    prefix (i.e. the same most significant bits), then this prefix will be flushed to the stream.
    For instances, having read 3 bits `b1 b2 b3`, we know that `[L, H]` is contained inside
    `[b1 b2 b3 0 ... 0 b1 b3 b3 1 ... 1]`. Now this specific sub-range can only be obtained
    for a specific sequence of symbols and a binary-search allows us to decode those symbols.
    At some point, the prefix `b1 b2 b3` will no longer be sufficient to decode new symbols,
    and we will need to read new bits from the stream and repeat the process.

    r!   r"   r   c                 C   sB   || _ d| _d| _d| _d| _td|d| _g | _g | _d | _	d S )Nr   r   r   r$   )
r   r'   r(   currentr)   r   unpackerr*   r+   _lastr,   r   r   r   r.      s   
zArithmeticDecoder.__init__r   c                 C   r/   )Nr   r0   r1   r   r   r   r2      s   zArithmeticDecoder.deltac                 C   s   | j dkrS| j| j ? }| j| j ? }||krJ|  j|| j > 8  _|  j|| j > 8  _|  j|| j > 8  _| j| jks;J | jdksBJ |  j d8  _ nd S | j dksd S d S )Nr   r   )r)   r'   r(   rP   r4   r   r   r   r7      s   
z&ArithmeticDecoder._flush_common_prefixr   c                    s   j dj k r9j }|du rdS  jd9  _jd d _jd | _ jd7  _j dj k sdtdtf fdd jjjjf_	 dt
d \}___jjjjf   jjjjf |S )	ap  Pull a symbol, reading as many bits from the stream as required.
        This returns `None` when the stream has been exhausted.

        Args:
            quantized_cdf (torch.Tensor): use `build_stable_quantized_cdf`
                to build this from your pdf estimate. This must be **exatly**
                the same cdf as the one used at encoding time.
        r   Nr   low_idxhigh_idxc           	         s   || k rt d| | d }|dkr|d   nd}|  d }tt|jdj   }tt|jdj   }|j }|j }j	|krdj	|kr]|||j	fS  |d |S  | |d S )NzBinary search failedr   r   r   )
RuntimeErrorr:   r;   r<   r=   r2   r   r   r'   rP   )	rS   rT   midr?   r@   rA   rB   r'   r(   
bin_searchr   r-   r   r   rX      s   



z*ArithmeticDecoder.pull.<locals>.bin_searchr   )r2   r   rQ   pullr'   r(   rP   r)   r;   rR   r   r*   r>   r7   r+   )r-   r   bitsymr   rW   r   rY      s    	
	 zArithmeticDecoder.pullNrE   )rF   rG   rH   rI   rJ   rK   rL   r;   r.   rM   r2   r7   r   rN   OptionalrY   r   r   r   r   rO      s    rO   c                  C   s&  t d td tdD ]} g }td}tdd}t }t|}g }t|D ]*}t j	t 
|dd}|| t||j}	t |d }
||
 ||
|	 q+|  |d t|}tt||D ]\}\}}
t||j}	||	}||
ksJ |qj|t dd u sJ qd S )	Ni     i  d   i  r   r   r   )r   manual_seedrandomseedrange	randrangeioBytesIOr    softmaxrandnr>   r   r   multinomialr:   r3   rD   seekrO   	enumerateziprY   zeros)_pdfsr   stepsr"   encodersymbolsstepr   q_cdfr8   decoderidxdecoded_symbolr   r   r   test  s2   






rw   __main__)r   r   T)rI   rd   r<   r`   typingrJ   r   binaryr   r   rN   r;   floatboolr   r    rO   rw   rF   r   r   r   r   <module>   s0   
&r]
