#include "config.h"
#include "ssc_macro.h"
#include "rc_decode.h"
#include "rc_symbol.h"



static void dec_norm(ec_dec *curr_ec){


  while(curr_ec->rng<=DEC_BOT){
    int tt = curr_ec->rem;
    curr_ec->nbits_total+=DEC_BITS;
    curr_ec->rng<<=DEC_BITS;

	curr_ec->rem=curr_ec->offs<curr_ec->storage?curr_ec->buf[curr_ec->offs++]:0;
    tt=(tt<<(8)|curr_ec->rem)>>(1);

    curr_ec->val=((curr_ec->val<<(8))+((0xFF)&~tt))&(8388607);

  }
}

void rc_dec_init(ec_dec *curr_ec,unsigned char *buffer,unsigned int size){
  
	curr_ec->end_offs=0;
	curr_ec->end_window=0;
	curr_ec->nend_bits=0;
	curr_ec->buf=buffer;
    curr_ec->storage=size;

	curr_ec->offs=0;
	curr_ec->rng=128;
	curr_ec->nbits_total=9;


  curr_ec->rem = curr_ec->offs<curr_ec->storage?curr_ec->buf[curr_ec->offs++]:0;


  curr_ec->val=curr_ec->rng-1-(curr_ec->rem>>1);

  curr_ec->error=0;

  dec_norm(curr_ec);
}

unsigned rc_dec(ec_dec *curr_dec,unsigned _ft){
  unsigned int ww;
  curr_dec->ext=curr_dec->rng/_ft;
  ww=(unsigned int)(curr_dec->val/curr_dec->ext);
  return _ft-RC_MIN(ww+1,_ft);
}

unsigned rc_dec_bin(ec_dec *curr_dec,unsigned _bits){
   unsigned int ww;
   curr_dec->ext=curr_dec->rng>>_bits;
   ww=(unsigned)(curr_dec->val/curr_dec->ext);
   return (1U<<_bits)-RC_MIN(ww+1U,1U<<_bits);
}

void rc_decode_upd(ec_dec *curr_dec,unsigned il,unsigned ih,unsigned it){
  unsigned int w;
  w=IntMUL32(curr_dec->ext,it-ih);   // IMUL check 1 2

  curr_dec->val-=w;

  curr_dec->rng=il>0?IntMUL32(curr_dec->ext,ih-il):curr_dec->rng-w;
  dec_norm(curr_dec);
}


int rc_decode_logp_bit(ec_dec *curr_dec,unsigned p_log){
  unsigned int r;
  unsigned int d;
  unsigned int s;
  int         ret;

  r=curr_dec->rng;
  d=curr_dec->val;
  s=r>>p_log;
  ret=d<s;
  if(!ret)
	  curr_dec->val=d-s;

  curr_dec->rng=ret?s:r-s;
  dec_norm(curr_dec);
  return ret;
}

int rc_decode_cdf(ec_dec *curr_dec,const unsigned char *cdf,unsigned fb){
  
  unsigned int s;
  unsigned int t;	
  unsigned int r;
  unsigned int d;

  int         ret;
  s=curr_dec->rng;
  d=curr_dec->val;
  r=s>>fb;
  ret=-1;
  do{
    t=s;
    s=IntMUL32(r,cdf[++ret]);        // IMULÀÌ ³Ñ´Â °æ¿ì°¡ ÀÖ´Â Áö È®ÀÎ. check 1

  }
  while(d<s);
  curr_dec->val=d-s;
  curr_dec->rng=t-s;
  dec_norm(curr_dec);
  return ret;
}

unsigned int rc_decode_uint(ec_dec *curr_ec,unsigned int _ft){
  unsigned ft;
  unsigned s;
  int      ftb;

  _ft--;

  if (_ft > 2147483647)
  {
	  ftb = 32;
  }
  else
  {
	  ftb = EC_ILOG(_ft);
  }

  if(ftb>EC_UINT_BITS){
    unsigned int t;
    ftb-=EC_UINT_BITS;
    ft=(unsigned)(_ft>>ftb)+1;
    s=rc_dec(curr_ec,ft);
    rc_decode_upd(curr_ec,s,s+1,ft);
    t=(unsigned int)s<<ftb|ec_dec_bits(curr_ec,ftb);
    if(t<=_ft)return t;
    curr_ec->error=1;
    return _ft;
  }
  else{
    _ft++;
    s=rc_dec(curr_ec,(unsigned)_ft);
    rc_decode_upd(curr_ec,s,s+1,(unsigned)_ft);
    return s;
  }
}

unsigned int ec_dec_bits(ec_dec *curr_ec,unsigned _bits){
  ec_window   window;
  int         available;
  unsigned int ret;
 
  window=curr_ec->end_window;
  available=curr_ec->nend_bits;

  if((unsigned)available<_bits){

    do{
	   window|=(ec_window)(curr_ec->end_offs<curr_ec->storage?curr_ec->buf[curr_ec->storage-++(curr_ec->end_offs)]<<available:0);


      available+=DEC_BITS;
    }while(available<=24);





  }


  ret=(unsigned int)window&(((unsigned int)1<<_bits)-1U);
  window>>=_bits;
  available-=_bits;
  curr_ec->end_window=window;
  curr_ec->nend_bits=available;
  curr_ec->nbits_total+=_bits;
  return ret;
}
