
#include "rc_encode.h"
#include "basic_op.h"
#include "copy.h"



#ifndef HW_CODESIZE
void rc_enc_init_1(ec_enc *_this,unsigned char *_buf,unsigned short _size)
{
	_this->buf=_buf;
	_this->end_offs=0;         /////////////////////////////////
	_this->end_window=0;       /////////////////////////////
	_this->nend_bits=0;           ////////////////////////////
	/*This is the offset from which ec_tell() will subtract partial bits.*/
	_this->nbits_total=EC_CODE_BITS+1;
	_this->offs=0;

//	_this->rng=0x80000000;      // 
	 _this->rng=EC_CODE_TOP+1;  // 24bit coding

	_this->rem=-1;     ///////////////////////////////////////////
	_this->val=0;                 ////////////////////////////
	_this->ext=0;                  ////////////////////////
	_this->storage=_size;         ////////////////////////
	_this->error=0;              /////////////////
}
#endif
void rc_encode_1(ec_enc *curr_enc,unsigned short _fl,unsigned short _fh,unsigned short _ft)
{
	unsigned int r;
	r=curr_enc->rng/_ft;
	if(_fl>0)
	{
		curr_enc->val+=curr_enc->rng-SSC_MUL(r,(_ft-_fl));
		curr_enc->rng=SSC_MUL(r,(_fh-_fl));
	}
	else curr_enc->rng-=SSC_MUL(r,(_ft-_fh));
	rc_enc_normalize_1(curr_enc);
}

void rc_encode_bin_1(ec_enc *curr_enc,unsigned short _fl,unsigned short _fh,unsigned short _bits)
{
	unsigned int r;
	r=curr_enc->rng>>_bits;
	if(_fl>0)
	{
		curr_enc->val+=curr_enc->rng-SSC_MUL(r,((1U<<_bits)-_fl));
		curr_enc->rng=SSC_MUL(r,(_fh-_fl));
	}
	else 
		curr_enc->rng-=SSC_MUL(r,((1U<<_bits)-_fh));
	rc_enc_normalize_1(curr_enc);
}

/*The probability of having a "one" is 1/(1<<_logp).*/
void rc_enc_bit_logp_1(ec_enc *curr_enc,short _val,unsigned short _logp)
{
	unsigned int r, s, l;
	r=curr_enc->rng;
	l=curr_enc->val;
	s=r>>_logp;
	r-=s;
	if(_val) curr_enc->val=l+r;
	curr_enc->rng=_val?s:r;
	rc_enc_normalize_1(curr_enc);
}



void rc_enc_icdf_1(ec_enc *curr_enc,short _s,const unsigned char *_icdf,unsigned short _ftb)
{
	unsigned int r;
	r=curr_enc->rng>>_ftb;
	if(_s>0)
	{
		curr_enc->val+=curr_enc->rng-SSC_MUL(r,_icdf[_s-1]);
		curr_enc->rng=SSC_MUL(r,_icdf[_s-1]-_icdf[_s]);
	}
	else 
		curr_enc->rng-=SSC_MUL(r,_icdf[_s]);
	rc_enc_normalize_1(curr_enc);
}



void rc_enc_uint_1(ec_enc *curr_enc,unsigned int _fl,unsigned int _ft)
{
	unsigned short  ft, fl;
	short ftb;
	_ft--;
#ifndef HW_FOR_GCC
	ftb=EC_ILOG(_ft);
#else
	asm volatile
		(
		"clz      %0,%1 \n\t"
		"RSB		%0,%0,#0x20 \n\t"
		:"=r"(ftb)
		:"r"(_ft) 
		);
#endif
	if(ftb>EC_UINT_BITS)
	{
		ftb-=EC_UINT_BITS;
		ft=(_ft>>ftb)+1;
		fl=(_fl>>ftb);
		rc_encode_1(curr_enc,fl,fl+1,ft);
		rc_enc_bits_1(curr_enc,_fl&(((unsigned int)1<<ftb)-1U),ftb);
	}
	else 
		rc_encode_1(curr_enc,_fl,_fl+1,_ft+1);
}

void rc_enc_bits_1(ec_enc *curr_enc,unsigned int _fl,unsigned _bits)
{
	ec_window window;
	int used;
	window=curr_enc->end_window;
	used=curr_enc->nend_bits;
	if(used+_bits>EC_WINDOW_SIZE)
	{
		do{
			curr_enc->error|=rc_write_byte_at_end_1(curr_enc,(unsigned)window&EC_SYM_MAX);
			window>>=EC_SYM_BITS;
			used-=EC_SYM_BITS;
		}while(used>=EC_SYM_BITS);
	}
/*
	_fl = 0xabcde;
	used = 8;
*/
	window|=(ec_window)_fl<<used;
		
	used+=_bits;
	curr_enc->end_window=window;
	curr_enc->nend_bits=used;
	curr_enc->nbits_total+=_bits;
}

void rc_enc_done_1(ec_enc *curr_enc)
{
	ec_window   window;
	int used, l;
	unsigned int msk;
	unsigned int end;
#ifndef HW_FOR_GCC
	l=EC_CODE_BITS-EC_ILOG(curr_enc->rng);
#else
	asm volatile
		(
		"clz      %0,%1 \n\t"
		:"=r"(l)
		:"r"(curr_enc->rng) 
		);
	l = l-8;
#endif
	msk=(EC_CODE_TOP)>>l;
	end=(curr_enc->val+msk)&~msk;
	if((end|msk)>=curr_enc->val+curr_enc->rng)
	{
		l++;
		msk>>=1;
		end=(curr_enc->val+msk)&~msk;
	}
	while(l>0)
	{
		rc_enc_carry_out_1(curr_enc,(int)(end>>EC_CODE_SHIFT));
		end=(end<<EC_SYM_BITS)&(EC_CODE_TOP);
		l-=EC_SYM_BITS;
	}

	if(curr_enc->rem>=0||curr_enc->ext>0)rc_enc_carry_out_1(curr_enc,0);
	window=curr_enc->end_window;
	used=curr_enc->nend_bits;
	while(used>=EC_SYM_BITS)
	{
		curr_enc->error|=rc_write_byte_at_end_1(curr_enc,(unsigned)window&EC_SYM_MAX);
		window>>=EC_SYM_BITS;
		used-=EC_SYM_BITS;
	}
	if(!curr_enc->error)
	{
		SUN_CLEAR_uchar(curr_enc->buf+curr_enc->offs, curr_enc->storage-curr_enc->offs-curr_enc->end_offs);
		if(used>0)
		{
			if(curr_enc->end_offs>=curr_enc->storage) 
				curr_enc->error=-1;
			else
			{
				l=-l;
				if(curr_enc->offs+curr_enc->end_offs>=curr_enc->storage&&l<used)
				{
					window&=(1<<l)-1;
					curr_enc->error=-1;
				}
				curr_enc->buf[curr_enc->storage-curr_enc->end_offs-1]|=(unsigned char)window;
			}
		}
	}
}



