kolibrios-gitea/programs/other/kpack/kerpack_linux/lzma_c/RangeCoder.c
CleverMouse cd74d1af33 switch build system to Tup
git-svn-id: svn://kolibrios.org@5098 a494cfbc-eb01-0410-851d-a64ba20cac60
2014-09-12 15:15:23 +00:00

192 lines
4.2 KiB
C

#include "RangeCoderBitTree.h"
#include "lzma.h"
static unsigned _cacheSize;
static byte _cache;
static uint64 low;
static unsigned range;
static unsigned PriceTable[kBitModelTotal >> kNumMoveReducingBits];
void RangeEncoder_Init(void)
{
int i;
unsigned start,end,j;
low = 0;
range = 0xFFFFFFFF;
_cacheSize = 1;
_cache = 0;
/* init price table */
#define kNumBits (kNumBitModelTotalBits - kNumMoveReducingBits)
for (i=kNumBits;i--;)
{
start = 1 << (kNumBits - i - 1);
end = 1 << (kNumBits - i);
for (j=start;j<end;j++)
PriceTable[j] = (i<<kNumBitPriceShiftBits) +
(((end-j)<<kNumBitPriceShiftBits) >> (kNumBits - i - 1));
}
#undef kNumBits
}
void RangeEncoder_ShiftLow(void)
{
if ((unsigned)low < 0xFF000000U || (int)(low>>32))
{
byte temp = _cache;
do
{
*curout++ = (byte)(temp + (byte)(low>>32));
temp = 0xFF;
} while (--_cacheSize);
_cache = (byte)((unsigned)low>>24);
}
_cacheSize++;
low = (unsigned)low << 8;
}
void RangeEncoder_FlushData(void)
{
int i;
for (i=0;i<5;i++)
RangeEncoder_ShiftLow();
}
void RangeEncoder_EncodeDirectBits(unsigned value,int numTotalBits)
{
int i;
for (i=numTotalBits;i--;)
{
range >>= 1;
if (((value >> i) & 1) == 1)
low += range;
if (range < kTopValue)
{
range <<= 8;
RangeEncoder_ShiftLow();
}
}
}
void CMyBitEncoder_Encode(CMyBitEncoder* e,unsigned symbol)
{
unsigned newBound;
newBound = (range >> kNumBitModelTotalBits) * *e;
if (symbol == 0)
{
range = newBound;
*e += (kBitModelTotal - *e) >> kNumMoveBits;
}
else
{
low += newBound;
range -= newBound;
*e -= *e >> kNumMoveBits;
}
if (range < kTopValue)
{
range <<= 8;
RangeEncoder_ShiftLow();
}
}
unsigned CMyBitEncoder_GetPrice(CMyBitEncoder* e, unsigned symbol)
{
return PriceTable[(((*e-symbol)^((-(int)symbol))) & (kBitModelTotal-1)) >> kNumMoveReducingBits];
}
unsigned CMyBitEncoder_GetPrice0(CMyBitEncoder* e)
{
return PriceTable[*e >> kNumMoveReducingBits];
}
unsigned CMyBitEncoder_GetPrice1(CMyBitEncoder* e)
{
return PriceTable[(kBitModelTotal - *e) >> kNumMoveReducingBits];
}
void CBitTreeEncoder_Init(NRangeCoder_CBitTreeEncoder*e,int numBitLevels)
{
unsigned i;
e->numBitLevels = numBitLevels;
for (i=1;i<((unsigned)1<<numBitLevels);i++)
CMyBitEncoder_Init(e->Models[i]);
}
void CBitTreeEncoder_Encode(NRangeCoder_CBitTreeEncoder*e,unsigned symbol)
{
unsigned modelIndex = 1;
int bitIndex;
unsigned bit;
for (bitIndex = e->numBitLevels; bitIndex--;)
{
bit = (symbol >> bitIndex) & 1;
CMyBitEncoder_Encode(&e->Models[modelIndex],bit);
modelIndex = (modelIndex << 1) | bit;
}
}
void CBitTreeEncoder_ReverseEncode(NRangeCoder_CBitTreeEncoder*e,unsigned symbol)
{
unsigned modelIndex = 1;
int i;
unsigned bit;
for (i=0;i<e->numBitLevels;i++)
{
bit = symbol & 1;
CMyBitEncoder_Encode(&e->Models[modelIndex],bit);
modelIndex = (modelIndex << 1) | bit;
symbol >>= 1;
}
}
unsigned CBitTreeEncoder_GetPrice(NRangeCoder_CBitTreeEncoder*e,unsigned symbol)
{
unsigned price = 0;
symbol |= (1 << e->numBitLevels);
while (symbol != 1)
{
price += CMyBitEncoder_GetPrice(&e->Models[symbol>>1],symbol&1);
symbol >>= 1;
}
return price;
}
unsigned CBitTreeEncoder_ReverseGetPrice(NRangeCoder_CBitTreeEncoder*e,unsigned symbol)
{
unsigned price=0;
unsigned modelIndex=1;
int i;
unsigned bit;
for (i=e->numBitLevels;i;i--)
{
bit = symbol&1;
symbol >>= 1;
price += CMyBitEncoder_GetPrice(&e->Models[modelIndex],bit);
modelIndex = (modelIndex<<1)|bit;
}
return price;
}
unsigned ReverseBitTreeGetPrice(CMyBitEncoder*Models,unsigned NumBitLevels,unsigned symbol)
{
unsigned price=0;
unsigned modelIndex=1;
unsigned bit;
int i;
for (i=NumBitLevels;i;i--)
{
bit = symbol & 1;
symbol >>= 1;
price += CMyBitEncoder_GetPrice(Models+modelIndex,bit);
modelIndex = (modelIndex<<1)|bit;
}
return price;
}
void ReverseBitTreeEncode(CMyBitEncoder*Models,int NumBitLevels,unsigned symbol)
{
unsigned modelIndex = 1;
int i;
unsigned bit;
for (i=0;i<NumBitLevels;i++)
{
bit = symbol & 1;
CMyBitEncoder_Encode(Models+modelIndex,bit);
modelIndex = (modelIndex<<1)|bit;
symbol >>= 1;
}
}