package SevenZip.Compression.RangeCoder; | |
import java.io.IOException; | |
public class Encoder | |
{ | |
static final int kTopMask = ~((1 << 24) - 1); | |
static final int kNumBitModelTotalBits = 11; | |
static final int kBitModelTotal = (1 << kNumBitModelTotalBits); | |
static final int kNumMoveBits = 5; | |
java.io.OutputStream Stream; | |
long Low; | |
int Range; | |
int _cacheSize; | |
int _cache; | |
long _position; | |
public void SetStream(java.io.OutputStream stream) | |
{ | |
Stream = stream; | |
} | |
public void ReleaseStream() | |
{ | |
Stream = null; | |
} | |
public void Init() | |
{ | |
_position = 0; | |
Low = 0; | |
Range = -1; | |
_cacheSize = 1; | |
_cache = 0; | |
} | |
public void FlushData() throws IOException | |
{ | |
for (int i = 0; i < 5; i++) | |
ShiftLow(); | |
} | |
public void FlushStream() throws IOException | |
{ | |
Stream.flush(); | |
} | |
public void ShiftLow() throws IOException | |
{ | |
int LowHi = (int)(Low >>> 32); | |
if (LowHi != 0 || Low < 0xFF000000L) | |
{ | |
_position += _cacheSize; | |
int temp = _cache; | |
do | |
{ | |
Stream.write(temp + LowHi); | |
temp = 0xFF; | |
} | |
while(--_cacheSize != 0); | |
_cache = (((int)Low) >>> 24); | |
} | |
_cacheSize++; | |
Low = (Low & 0xFFFFFF) << 8; | |
} | |
public void EncodeDirectBits(int v, int numTotalBits) throws IOException | |
{ | |
for (int i = numTotalBits - 1; i >= 0; i--) | |
{ | |
Range >>>= 1; | |
if (((v >>> i) & 1) == 1) | |
Low += Range; | |
if ((Range & Encoder.kTopMask) == 0) | |
{ | |
Range <<= 8; | |
ShiftLow(); | |
} | |
} | |
} | |
public long GetProcessedSizeAdd() | |
{ | |
return _cacheSize + _position + 4; | |
} | |
static final int kNumMoveReducingBits = 2; | |
public static final int kNumBitPriceShiftBits = 6; | |
public static void InitBitModels(short []probs) | |
{ | |
for (int i = 0; i < probs.length; i++) | |
probs[i] = (kBitModelTotal >>> 1); | |
} | |
public void Encode(short []probs, int index, int symbol) throws IOException | |
{ | |
int prob = probs[index]; | |
int newBound = (Range >>> kNumBitModelTotalBits) * prob; | |
if (symbol == 0) | |
{ | |
Range = newBound; | |
probs[index] = (short)(prob + ((kBitModelTotal - prob) >>> kNumMoveBits)); | |
} | |
else | |
{ | |
Low += (newBound & 0xFFFFFFFFL); | |
Range -= newBound; | |
probs[index] = (short)(prob - ((prob) >>> kNumMoveBits)); | |
} | |
if ((Range & kTopMask) == 0) | |
{ | |
Range <<= 8; | |
ShiftLow(); | |
} | |
} | |
private static int[] ProbPrices = new int[kBitModelTotal >>> kNumMoveReducingBits]; | |
static | |
{ | |
int kNumBits = (kNumBitModelTotalBits - kNumMoveReducingBits); | |
for (int i = kNumBits - 1; i >= 0; i--) | |
{ | |
int start = 1 << (kNumBits - i - 1); | |
int end = 1 << (kNumBits - i); | |
for (int j = start; j < end; j++) | |
ProbPrices[j] = (i << kNumBitPriceShiftBits) + | |
(((end - j) << kNumBitPriceShiftBits) >>> (kNumBits - i - 1)); | |
} | |
} | |
static public int GetPrice(int Prob, int symbol) | |
{ | |
return ProbPrices[(((Prob - symbol) ^ ((-symbol))) & (kBitModelTotal - 1)) >>> kNumMoveReducingBits]; | |
} | |
static public int GetPrice0(int Prob) | |
{ | |
return ProbPrices[Prob >>> kNumMoveReducingBits]; | |
} | |
static public int GetPrice1(int Prob) | |
{ | |
return ProbPrices[(kBitModelTotal - Prob) >>> kNumMoveReducingBits]; | |
} | |
} |