forked from adamhathcock/sharpcompress
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathRangeCoderBit.cs
More file actions
124 lines (107 loc) · 3.58 KB
/
RangeCoderBit.cs
File metadata and controls
124 lines (107 loc) · 3.58 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#nullable disable
using System.Runtime.CompilerServices;
namespace SharpCompress.Compressors.LZMA.RangeCoder;
internal struct BitEncoder
{
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;
private uint _prob;
public void Init() => _prob = K_BIT_MODEL_TOTAL >> 1;
public void UpdateModel(uint symbol)
{
if (symbol == 0)
{
_prob += (K_BIT_MODEL_TOTAL - _prob) >> K_NUM_MOVE_BITS;
}
else
{
_prob -= (_prob) >> K_NUM_MOVE_BITS;
}
}
public void Encode(Encoder encoder, uint symbol)
{
// encoder.EncodeBit(Prob, kNumBitModelTotalBits, symbol);
// UpdateModel(symbol);
var newBound = (encoder._range >> K_NUM_BIT_MODEL_TOTAL_BITS) * _prob;
if (symbol == 0)
{
encoder._range = newBound;
_prob += (K_BIT_MODEL_TOTAL - _prob) >> K_NUM_MOVE_BITS;
}
else
{
encoder._low += newBound;
encoder._range -= newBound;
_prob -= (_prob) >> K_NUM_MOVE_BITS;
}
if (encoder._range < Encoder.K_TOP_VALUE)
{
encoder._range <<= 8;
encoder.ShiftLow();
}
}
private static readonly uint[] PROB_PRICES = new uint[
K_BIT_MODEL_TOTAL >> K_NUM_MOVE_REDUCING_BITS
];
static BitEncoder()
{
const int kNumBits = (K_NUM_BIT_MODEL_TOTAL_BITS - K_NUM_MOVE_REDUCING_BITS);
for (var i = kNumBits - 1; i >= 0; i--)
{
var start = (uint)1 << (kNumBits - i - 1);
var end = (uint)1 << (kNumBits - i);
for (var j = start; j < end; j++)
{
PROB_PRICES[j] =
((uint)i << K_NUM_BIT_PRICE_SHIFT_BITS)
+ (((end - j) << K_NUM_BIT_PRICE_SHIFT_BITS) >> (kNumBits - i - 1));
}
}
}
public uint GetPrice(uint symbol) =>
PROB_PRICES[
(((_prob - symbol) ^ ((-(int)symbol))) & (K_BIT_MODEL_TOTAL - 1))
>> K_NUM_MOVE_REDUCING_BITS
];
public uint GetPrice0() => PROB_PRICES[_prob >> K_NUM_MOVE_REDUCING_BITS];
public uint GetPrice1() => PROB_PRICES[(K_BIT_MODEL_TOTAL - _prob) >> K_NUM_MOVE_REDUCING_BITS];
}
internal struct BitDecoder
{
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 uint _prob;
public void UpdateModel(int numMoveBits, uint symbol)
{
if (symbol == 0)
{
_prob += (K_BIT_MODEL_TOTAL - _prob) >> numMoveBits;
}
else
{
_prob -= (_prob) >> numMoveBits;
}
}
public void Init() => _prob = K_BIT_MODEL_TOTAL >> 1;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public uint Decode(Decoder rangeDecoder)
{
var newBound = (rangeDecoder._range >> K_NUM_BIT_MODEL_TOTAL_BITS) * _prob;
if (rangeDecoder._code < newBound)
{
rangeDecoder._range = newBound;
_prob += (K_BIT_MODEL_TOTAL - _prob) >> K_NUM_MOVE_BITS;
rangeDecoder.Normalize2();
return 0;
}
rangeDecoder._range -= newBound;
rangeDecoder._code -= newBound;
_prob -= (_prob) >> K_NUM_MOVE_BITS;
rangeDecoder.Normalize2();
return 1;
}
}