Blame libcelt/rangeenc.c

Packit 664db3
#ifdef HAVE_CONFIG_H
Packit 664db3
#include "config.h"
Packit 664db3
#endif
Packit 664db3
Packit 664db3
#include "arch.h"
Packit 664db3
#include "entenc.h"
Packit 664db3
#include "mfrngcod.h"
Packit 664db3
Packit 664db3
Packit 664db3
Packit 664db3
/*A range encoder.
Packit 664db3
  See rangedec.c and the references for implementation details
Packit 664db3
   \cite{Mar79,MNW98}.
Packit 664db3
Packit 664db3
  @INPROCEEDINGS{Mar79,
Packit 664db3
   author="Martin, G.N.N.",
Packit 664db3
   title="Range encoding: an algorithm for removing redundancy from a digitised
Packit 664db3
    message",
Packit 664db3
   booktitle="Video \& Data Recording Conference",
Packit 664db3
   year=1979,
Packit 664db3
   address="Southampton",
Packit 664db3
   month=Jul
Packit 664db3
  }
Packit 664db3
  @ARTICLE{MNW98,
Packit 664db3
   author="Alistair Moffat and Radford Neal and Ian H. Witten",
Packit 664db3
   title="Arithmetic Coding Revisited",
Packit 664db3
   journal="{ACM} Transactions on Information Systems",
Packit 664db3
   year=1998,
Packit 664db3
   volume=16,
Packit 664db3
   number=3,
Packit 664db3
   pages="256--294",
Packit 664db3
   month=Jul,
Packit 664db3
   URL="http://www.stanford.edu/class/ee398/handouts/papers/Moffat98ArithmCoding.pdf"
Packit 664db3
  }*/
Packit 664db3
Packit 664db3
Packit 664db3
Packit 664db3
/*Outputs a symbol, with a carry bit.
Packit 664db3
  If there is a potential to propagate a carry over several symbols, they are
Packit 664db3
   buffered until it can be determined whether or not an actual carry will
Packit 664db3
   occur.
Packit 664db3
  If the counter for the buffered symbols overflows, then the stream becomes
Packit 664db3
   undecodable.
Packit 664db3
  This gives a theoretical limit of a few billion symbols in a single packet on
Packit 664db3
   32-bit systems.
Packit 664db3
  The alternative is to truncate the range in order to force a carry, but
Packit 664db3
   requires similar carry tracking in the decoder, needlessly slowing it down.*/
Packit 664db3
static void ec_enc_carry_out(ec_enc *_this,int _c){
Packit 664db3
  if(_c!=EC_SYM_MAX){
Packit 664db3
    /*No further carry propagation possible, flush buffer.*/
Packit 664db3
    int carry;
Packit 664db3
    carry=_c>>EC_SYM_BITS;
Packit 664db3
    /*Don't output a byte on the first write.
Packit 664db3
      This compare should be taken care of by branch-prediction thereafter.*/
Packit 664db3
    if(_this->rem>=0)ec_byte_write1(_this->buf,_this->rem+carry);
Packit 664db3
    if(_this->ext>0){
Packit 664db3
      unsigned sym;
Packit 664db3
      sym=EC_SYM_MAX+carry&EC_SYM_MAX;
Packit 664db3
      do ec_byte_write1(_this->buf,sym);
Packit 664db3
      while(--(_this->ext)>0);
Packit 664db3
    }
Packit 664db3
    _this->rem=_c&EC_SYM_MAX;
Packit 664db3
  }
Packit 664db3
  else _this->ext++;
Packit 664db3
}
Packit 664db3
Packit 664db3
static inline void ec_enc_normalize(ec_enc *_this){
Packit 664db3
  /*If the range is too small, output some bits and rescale it.*/
Packit 664db3
  while(_this->rng<=EC_CODE_BOT){
Packit 664db3
    ec_enc_carry_out(_this,(int)(_this->low>>EC_CODE_SHIFT));
Packit 664db3
    /*Move the next-to-high-order symbol into the high-order position.*/
Packit 664db3
    _this->low=_this->low<
Packit 664db3
    _this->rng<<=EC_SYM_BITS;
Packit 664db3
  }
Packit 664db3
}
Packit 664db3
Packit 664db3
void ec_enc_init(ec_enc *_this,ec_byte_buffer *_buf){
Packit 664db3
  _this->buf=_buf;
Packit 664db3
  _this->rem=-1;
Packit 664db3
  _this->ext=0;
Packit 664db3
  _this->low=0;
Packit 664db3
  _this->rng=EC_CODE_TOP;
Packit 664db3
}
Packit 664db3
Packit 664db3
void ec_encode(ec_enc *_this,unsigned _fl,unsigned _fh,unsigned _ft){
Packit 664db3
  ec_uint32 r;
Packit 664db3
  r=_this->rng/_ft;
Packit 664db3
  if(_fl>0){
Packit 664db3
    _this->low+=_this->rng-IMUL32(r,(_ft-_fl));
Packit 664db3
    _this->rng=IMUL32(r,(_fh-_fl));
Packit 664db3
  }
Packit 664db3
  else _this->rng-=IMUL32(r,(_ft-_fh));
Packit 664db3
  ec_enc_normalize(_this);
Packit 664db3
}
Packit 664db3
Packit 664db3
void ec_encode_bin(ec_enc *_this,unsigned _fl,unsigned _fh,unsigned bits){
Packit 664db3
   ec_uint32 r, ft;
Packit 664db3
   r=_this->rng>>bits;
Packit 664db3
   ft = (ec_uint32)1<
Packit 664db3
   if(_fl>0){
Packit 664db3
     _this->low+=_this->rng-IMUL32(r,(ft-_fl));
Packit 664db3
     _this->rng=IMUL32(r,(_fh-_fl));
Packit 664db3
   }
Packit 664db3
   else _this->rng-=IMUL32(r,(ft-_fh));
Packit 664db3
   ec_enc_normalize(_this);
Packit 664db3
}
Packit 664db3
Packit 664db3
long ec_enc_tell(ec_enc *_this,int _b){
Packit 664db3
  ec_uint32 r;
Packit 664db3
  int       l;
Packit 664db3
  long      nbits;
Packit 664db3
  nbits=(ec_byte_bytes(_this->buf)+(_this->rem>=0)+_this->ext)*EC_SYM_BITS;
Packit 664db3
  /*To handle the non-integral number of bits still left in the encoder state,
Packit 664db3
     we compute the number of bits of low that must be encoded to ensure that
Packit 664db3
     the value is inside the range for any possible subsequent bits.
Packit 664db3
    Note that this is subtly different than the actual value we would end the
Packit 664db3
     stream with, which tries to make as many of the trailing bits zeros as
Packit 664db3
     possible.*/
Packit 664db3
  nbits+=EC_CODE_BITS;
Packit 664db3
  nbits<<=_b;
Packit 664db3
  l=EC_ILOG(_this->rng);
Packit 664db3
  r=_this->rng>>l-16;
Packit 664db3
  while(_b-->0){
Packit 664db3
    int b;
Packit 664db3
    r=r*r>>15;
Packit 664db3
    b=(int)(r>>16);
Packit 664db3
    l=l<<1|b;
Packit 664db3
    r>>=b;
Packit 664db3
  }
Packit 664db3
  return nbits-l;
Packit 664db3
}
Packit 664db3
Packit 664db3
void ec_enc_done(ec_enc *_this){
Packit 664db3
  /*We compute the integer in the current interval that has the largest number
Packit 664db3
     of trailing zeros, and write that to the stream.
Packit 664db3
    This is guaranteed to yield the smallest possible encoding.*/
Packit 664db3
  if(_this->low){
Packit 664db3
    ec_uint32 end;
Packit 664db3
    end=EC_CODE_TOP;
Packit 664db3
    /*Ensure that the end value is in the range.*/
Packit 664db3
    if(end-_this->low>=_this->rng){
Packit 664db3
      ec_uint32 msk;
Packit 664db3
      msk=EC_CODE_TOP-1;
Packit 664db3
      do{
Packit 664db3
        msk>>=1;
Packit 664db3
        end=_this->low+msk&~msk|msk+1;
Packit 664db3
      }
Packit 664db3
      while(end-_this->low>=_this->rng);
Packit 664db3
    }
Packit 664db3
    /*The remaining output is the next free end.*/
Packit 664db3
    while(end){
Packit 664db3
      ec_enc_carry_out(_this,end>>EC_CODE_SHIFT);
Packit 664db3
      end=end<
Packit 664db3
    }
Packit 664db3
  }
Packit 664db3
  /*If we have a buffered byte flush it into the output buffer.*/
Packit 664db3
  if(_this->rem>0||_this->ext>0){
Packit 664db3
    ec_enc_carry_out(_this,0);
Packit 664db3
    _this->rem=-1;
Packit 664db3
  }
Packit 664db3
}