Files
sharpcompress/src/SharpCompress/Compressors/LZMA/RangeCoder/RangeCoderBit.cs

140 lines
4.4 KiB
C#
Raw Normal View History

2015-12-30 11:19:42 +00:00
using System;
2016-09-26 11:49:49 +01:00
namespace SharpCompress.Compressors.LZMA.RangeCoder
2015-12-30 11:19:42 +00:00
{
internal struct BitEncoder
{
2018-05-06 08:49:32 +01:00
public const int K_NUM_BIT_MODEL_TOTAL_BITS = 11;
public const uint K_BIT_MODEL_TOTAL = (1 << K_NUM_BIT_MODEL_TOTAL_BITS);
private const int K_NUM_MOVE_BITS = 5;
private const int K_NUM_MOVE_REDUCING_BITS = 2;
public const int K_NUM_BIT_PRICE_SHIFT_BITS = 6;
2015-12-30 11:19:42 +00:00
2018-05-06 08:49:32 +01:00
private uint _prob;
2015-12-30 11:19:42 +00:00
public void Init()
{
2018-05-06 08:49:32 +01:00
_prob = K_BIT_MODEL_TOTAL >> 1;
2015-12-30 11:19:42 +00:00
}
public void UpdateModel(uint symbol)
{
if (symbol == 0)
{
2018-05-06 08:49:32 +01:00
_prob += (K_BIT_MODEL_TOTAL - _prob) >> K_NUM_MOVE_BITS;
}
2015-12-30 11:19:42 +00:00
else
{
2018-05-06 08:49:32 +01:00
_prob -= (_prob) >> K_NUM_MOVE_BITS;
}
2015-12-30 11:19:42 +00:00
}
public void Encode(Encoder encoder, uint symbol)
{
// encoder.EncodeBit(Prob, kNumBitModelTotalBits, symbol);
// UpdateModel(symbol);
2018-05-06 08:49:32 +01:00
uint newBound = (encoder._range >> K_NUM_BIT_MODEL_TOTAL_BITS) * _prob;
2015-12-30 11:19:42 +00:00
if (symbol == 0)
{
2018-05-06 08:49:32 +01:00
encoder._range = newBound;
_prob += (K_BIT_MODEL_TOTAL - _prob) >> K_NUM_MOVE_BITS;
2015-12-30 11:19:42 +00:00
}
else
{
2018-05-06 08:49:32 +01:00
encoder._low += newBound;
encoder._range -= newBound;
_prob -= (_prob) >> K_NUM_MOVE_BITS;
2015-12-30 11:19:42 +00:00
}
2018-05-06 08:49:32 +01:00
if (encoder._range < Encoder.K_TOP_VALUE)
2015-12-30 11:19:42 +00:00
{
2018-05-06 08:49:32 +01:00
encoder._range <<= 8;
2015-12-30 11:19:42 +00:00
encoder.ShiftLow();
}
}
2018-05-06 08:49:32 +01:00
private static readonly UInt32[] PROB_PRICES = new UInt32[K_BIT_MODEL_TOTAL >> K_NUM_MOVE_REDUCING_BITS];
2015-12-30 11:19:42 +00:00
static BitEncoder()
{
2018-05-06 08:49:32 +01:00
const int kNumBits = (K_NUM_BIT_MODEL_TOTAL_BITS - K_NUM_MOVE_REDUCING_BITS);
2015-12-30 11:19:42 +00:00
for (int i = kNumBits - 1; i >= 0; i--)
{
UInt32 start = (UInt32)1 << (kNumBits - i - 1);
UInt32 end = (UInt32)1 << (kNumBits - i);
2015-12-30 11:19:42 +00:00
for (UInt32 j = start; j < end; j++)
{
2018-05-06 08:49:32 +01:00
PROB_PRICES[j] = ((UInt32)i << K_NUM_BIT_PRICE_SHIFT_BITS) +
(((end - j) << K_NUM_BIT_PRICE_SHIFT_BITS) >> (kNumBits - i - 1));
}
2015-12-30 11:19:42 +00:00
}
}
public uint GetPrice(uint symbol)
{
2018-05-06 08:49:32 +01:00
return PROB_PRICES[(((_prob - symbol) ^ ((-(int)symbol))) & (K_BIT_MODEL_TOTAL - 1)) >> K_NUM_MOVE_REDUCING_BITS];
2015-12-30 11:19:42 +00:00
}
public uint GetPrice0()
{
2018-05-06 08:49:32 +01:00
return PROB_PRICES[_prob >> K_NUM_MOVE_REDUCING_BITS];
2015-12-30 11:19:42 +00:00
}
public uint GetPrice1()
{
2018-05-06 08:49:32 +01:00
return PROB_PRICES[(K_BIT_MODEL_TOTAL - _prob) >> K_NUM_MOVE_REDUCING_BITS];
2015-12-30 11:19:42 +00:00
}
}
internal struct BitDecoder
{
2018-05-06 08:49:32 +01:00
public const int K_NUM_BIT_MODEL_TOTAL_BITS = 11;
public const uint K_BIT_MODEL_TOTAL = (1 << K_NUM_BIT_MODEL_TOTAL_BITS);
private const int K_NUM_MOVE_BITS = 5;
2015-12-30 11:19:42 +00:00
2018-05-06 08:49:32 +01:00
private uint _prob;
2015-12-30 11:19:42 +00:00
public void UpdateModel(int numMoveBits, uint symbol)
{
if (symbol == 0)
{
2018-05-06 08:49:32 +01:00
_prob += (K_BIT_MODEL_TOTAL - _prob) >> numMoveBits;
}
2015-12-30 11:19:42 +00:00
else
{
2018-05-06 08:49:32 +01:00
_prob -= (_prob) >> numMoveBits;
}
2015-12-30 11:19:42 +00:00
}
public void Init()
{
2018-05-06 08:49:32 +01:00
_prob = K_BIT_MODEL_TOTAL >> 1;
2015-12-30 11:19:42 +00:00
}
public uint Decode(Decoder rangeDecoder)
2015-12-30 11:19:42 +00:00
{
2018-05-06 08:49:32 +01:00
uint newBound = (rangeDecoder._range >> K_NUM_BIT_MODEL_TOTAL_BITS) * _prob;
if (rangeDecoder._code < newBound)
2015-12-30 11:19:42 +00:00
{
2018-05-06 08:49:32 +01:00
rangeDecoder._range = newBound;
_prob += (K_BIT_MODEL_TOTAL - _prob) >> K_NUM_MOVE_BITS;
if (rangeDecoder._range < Decoder.K_TOP_VALUE)
2015-12-30 11:19:42 +00:00
{
2018-05-06 08:49:32 +01:00
rangeDecoder._code = (rangeDecoder._code << 8) | (byte)rangeDecoder._stream.ReadByte();
rangeDecoder._range <<= 8;
rangeDecoder._total++;
2015-12-30 11:19:42 +00:00
}
return 0;
}
2018-05-06 08:49:32 +01:00
rangeDecoder._range -= newBound;
rangeDecoder._code -= newBound;
_prob -= (_prob) >> K_NUM_MOVE_BITS;
if (rangeDecoder._range < Decoder.K_TOP_VALUE)
2015-12-30 11:19:42 +00:00
{
2018-05-06 08:49:32 +01:00
rangeDecoder._code = (rangeDecoder._code << 8) | (byte)rangeDecoder._stream.ReadByte();
rangeDecoder._range <<= 8;
rangeDecoder._total++;
2015-12-30 11:19:42 +00:00
}
return 1;
2015-12-30 11:19:42 +00:00
}
}
2013-04-28 12:32:55 +01:00
}