mirror of
https://github.com/adamhathcock/sharpcompress.git
synced 2026-02-09 21:24:08 +00:00
163 lines
4.7 KiB
C#
163 lines
4.7 KiB
C#
using System;
|
|
|
|
namespace SharpCompress.Compressors.LZMA.RangeCoder
|
|
{
|
|
internal struct BitTreeEncoder
|
|
{
|
|
private readonly BitEncoder[] _models;
|
|
private readonly int _numBitLevels;
|
|
|
|
public BitTreeEncoder(int numBitLevels)
|
|
{
|
|
_numBitLevels = numBitLevels;
|
|
_models = new BitEncoder[1 << numBitLevels];
|
|
}
|
|
|
|
public void Init()
|
|
{
|
|
for (uint i = 1; i < (1 << _numBitLevels); i++)
|
|
{
|
|
_models[i].Init();
|
|
}
|
|
}
|
|
|
|
public void Encode(Encoder rangeEncoder, UInt32 symbol)
|
|
{
|
|
UInt32 m = 1;
|
|
for (int bitIndex = _numBitLevels; bitIndex > 0;)
|
|
{
|
|
bitIndex--;
|
|
UInt32 bit = (symbol >> bitIndex) & 1;
|
|
_models[m].Encode(rangeEncoder, bit);
|
|
m = (m << 1) | bit;
|
|
}
|
|
}
|
|
|
|
public void ReverseEncode(Encoder rangeEncoder, UInt32 symbol)
|
|
{
|
|
UInt32 m = 1;
|
|
for (UInt32 i = 0; i < _numBitLevels; i++)
|
|
{
|
|
UInt32 bit = symbol & 1;
|
|
_models[m].Encode(rangeEncoder, bit);
|
|
m = (m << 1) | bit;
|
|
symbol >>= 1;
|
|
}
|
|
}
|
|
|
|
public UInt32 GetPrice(UInt32 symbol)
|
|
{
|
|
UInt32 price = 0;
|
|
UInt32 m = 1;
|
|
for (int bitIndex = _numBitLevels; bitIndex > 0;)
|
|
{
|
|
bitIndex--;
|
|
UInt32 bit = (symbol >> bitIndex) & 1;
|
|
price += _models[m].GetPrice(bit);
|
|
m = (m << 1) + bit;
|
|
}
|
|
return price;
|
|
}
|
|
|
|
public UInt32 ReverseGetPrice(UInt32 symbol)
|
|
{
|
|
UInt32 price = 0;
|
|
UInt32 m = 1;
|
|
for (int i = _numBitLevels; i > 0; i--)
|
|
{
|
|
UInt32 bit = symbol & 1;
|
|
symbol >>= 1;
|
|
price += _models[m].GetPrice(bit);
|
|
m = (m << 1) | bit;
|
|
}
|
|
return price;
|
|
}
|
|
|
|
public static UInt32 ReverseGetPrice(BitEncoder[] models, UInt32 startIndex,
|
|
int numBitLevels, UInt32 symbol)
|
|
{
|
|
UInt32 price = 0;
|
|
UInt32 m = 1;
|
|
for (int i = numBitLevels; i > 0; i--)
|
|
{
|
|
UInt32 bit = symbol & 1;
|
|
symbol >>= 1;
|
|
price += models[startIndex + m].GetPrice(bit);
|
|
m = (m << 1) | bit;
|
|
}
|
|
return price;
|
|
}
|
|
|
|
public static void ReverseEncode(BitEncoder[] models, UInt32 startIndex,
|
|
Encoder rangeEncoder, int numBitLevels, UInt32 symbol)
|
|
{
|
|
UInt32 m = 1;
|
|
for (int i = 0; i < numBitLevels; i++)
|
|
{
|
|
UInt32 bit = symbol & 1;
|
|
models[startIndex + m].Encode(rangeEncoder, bit);
|
|
m = (m << 1) | bit;
|
|
symbol >>= 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
internal struct BitTreeDecoder
|
|
{
|
|
private readonly BitDecoder[] _models;
|
|
private readonly int _numBitLevels;
|
|
|
|
public BitTreeDecoder(int numBitLevels)
|
|
{
|
|
_numBitLevels = numBitLevels;
|
|
_models = new BitDecoder[1 << numBitLevels];
|
|
}
|
|
|
|
public void Init()
|
|
{
|
|
for (uint i = 1; i < (1 << _numBitLevels); i++)
|
|
{
|
|
_models[i].Init();
|
|
}
|
|
}
|
|
|
|
public uint Decode(Decoder rangeDecoder)
|
|
{
|
|
uint m = 1;
|
|
for (int bitIndex = _numBitLevels; bitIndex > 0; bitIndex--)
|
|
{
|
|
m = (m << 1) + _models[m].Decode(rangeDecoder);
|
|
}
|
|
return m - ((uint)1 << _numBitLevels);
|
|
}
|
|
|
|
public uint ReverseDecode(Decoder rangeDecoder)
|
|
{
|
|
uint m = 1;
|
|
uint symbol = 0;
|
|
for (int bitIndex = 0; bitIndex < _numBitLevels; bitIndex++)
|
|
{
|
|
uint bit = _models[m].Decode(rangeDecoder);
|
|
m <<= 1;
|
|
m += bit;
|
|
symbol |= (bit << bitIndex);
|
|
}
|
|
return symbol;
|
|
}
|
|
|
|
public static uint ReverseDecode(BitDecoder[] models, UInt32 startIndex,
|
|
Decoder rangeDecoder, int numBitLevels)
|
|
{
|
|
uint m = 1;
|
|
uint symbol = 0;
|
|
for (int bitIndex = 0; bitIndex < numBitLevels; bitIndex++)
|
|
{
|
|
uint bit = models[startIndex + m].Decode(rangeDecoder);
|
|
m <<= 1;
|
|
m += bit;
|
|
symbol |= (bit << bitIndex);
|
|
}
|
|
return symbol;
|
|
}
|
|
}
|
|
} |