view src/win32/7zip/7z/CPP/7zip/Compress/RangeCoder.h @ 1:f9f4f1b99eed

importing src directory
author Robert McIntyre <rlm@mit.edu>
date Sat, 03 Mar 2012 10:31:27 -0600
parents
children
line wrap: on
line source
1 // Compress/RangeCoder.h
3 #ifndef __COMPRESS_RANGE_CODER_H
4 #define __COMPRESS_RANGE_CODER_H
6 #include "../Common/InBuffer.h"
7 #include "../Common/OutBuffer.h"
9 namespace NCompress {
10 namespace NRangeCoder {
12 const int kNumTopBits = 24;
13 const UInt32 kTopValue = (1 << kNumTopBits);
15 class CEncoder
16 {
17 UInt32 _cacheSize;
18 Byte _cache;
19 public:
20 UInt64 Low;
21 UInt32 Range;
22 COutBuffer Stream;
23 bool Create(UInt32 bufferSize) { return Stream.Create(bufferSize); }
25 void SetStream(ISequentialOutStream *stream) { Stream.SetStream(stream); }
26 void Init()
27 {
28 Stream.Init();
29 Low = 0;
30 Range = 0xFFFFFFFF;
31 _cacheSize = 1;
32 _cache = 0;
33 }
35 void FlushData()
36 {
37 // Low += 1;
38 for(int i = 0; i < 5; i++)
39 ShiftLow();
40 }
42 HRESULT FlushStream() { return Stream.Flush(); }
44 void ReleaseStream() { Stream.ReleaseStream(); }
46 void Encode(UInt32 start, UInt32 size, UInt32 total)
47 {
48 Low += start * (Range /= total);
49 Range *= size;
50 while (Range < kTopValue)
51 {
52 Range <<= 8;
53 ShiftLow();
54 }
55 }
57 void ShiftLow()
58 {
59 if ((UInt32)Low < (UInt32)0xFF000000 || (int)(Low >> 32) != 0)
60 {
61 Byte temp = _cache;
62 do
63 {
64 Stream.WriteByte((Byte)(temp + (Byte)(Low >> 32)));
65 temp = 0xFF;
66 }
67 while(--_cacheSize != 0);
68 _cache = (Byte)((UInt32)Low >> 24);
69 }
70 _cacheSize++;
71 Low = (UInt32)Low << 8;
72 }
74 void EncodeDirectBits(UInt32 value, int numBits)
75 {
76 for (numBits--; numBits >= 0; numBits--)
77 {
78 Range >>= 1;
79 Low += Range & (0 - ((value >> numBits) & 1));
80 if (Range < kTopValue)
81 {
82 Range <<= 8;
83 ShiftLow();
84 }
85 }
86 }
88 void EncodeBit(UInt32 size0, UInt32 numTotalBits, UInt32 symbol)
89 {
90 UInt32 newBound = (Range >> numTotalBits) * size0;
91 if (symbol == 0)
92 Range = newBound;
93 else
94 {
95 Low += newBound;
96 Range -= newBound;
97 }
98 while (Range < kTopValue)
99 {
100 Range <<= 8;
101 ShiftLow();
102 }
103 }
105 UInt64 GetProcessedSize() { return Stream.GetProcessedSize() + _cacheSize + 4; }
106 };
108 class CDecoder
109 {
110 public:
111 CInBuffer Stream;
112 UInt32 Range;
113 UInt32 Code;
114 bool Create(UInt32 bufferSize) { return Stream.Create(bufferSize); }
116 void Normalize()
117 {
118 while (Range < kTopValue)
119 {
120 Code = (Code << 8) | Stream.ReadByte();
121 Range <<= 8;
122 }
123 }
125 void SetStream(ISequentialInStream *stream) { Stream.SetStream(stream); }
126 void Init()
127 {
128 Stream.Init();
129 Code = 0;
130 Range = 0xFFFFFFFF;
131 for(int i = 0; i < 5; i++)
132 Code = (Code << 8) | Stream.ReadByte();
133 }
135 void ReleaseStream() { Stream.ReleaseStream(); }
137 UInt32 GetThreshold(UInt32 total)
138 {
139 return (Code) / ( Range /= total);
140 }
142 void Decode(UInt32 start, UInt32 size)
143 {
144 Code -= start * Range;
145 Range *= size;
146 Normalize();
147 }
149 UInt32 DecodeDirectBits(int numTotalBits)
150 {
151 UInt32 range = Range;
152 UInt32 code = Code;
153 UInt32 result = 0;
154 for (int i = numTotalBits; i != 0; i--)
155 {
156 range >>= 1;
157 /*
158 result <<= 1;
159 if (code >= range)
160 {
161 code -= range;
162 result |= 1;
163 }
164 */
165 UInt32 t = (code - range) >> 31;
166 code -= range & (t - 1);
167 result = (result << 1) | (1 - t);
169 if (range < kTopValue)
170 {
171 code = (code << 8) | Stream.ReadByte();
172 range <<= 8;
173 }
174 }
175 Range = range;
176 Code = code;
177 return result;
178 }
180 UInt32 DecodeBit(UInt32 size0, UInt32 numTotalBits)
181 {
182 UInt32 newBound = (Range >> numTotalBits) * size0;
183 UInt32 symbol;
184 if (Code < newBound)
185 {
186 symbol = 0;
187 Range = newBound;
188 }
189 else
190 {
191 symbol = 1;
192 Code -= newBound;
193 Range -= newBound;
194 }
195 Normalize();
196 return symbol;
197 }
199 UInt64 GetProcessedSize() {return Stream.GetProcessedSize(); }
200 };
202 }}
204 #endif