1 package SevenZip.Compression.RangeCoder; 2 import java.io.IOException; 3 4 public class Encoder 5 { 6 static final int kTopMask = ~((1 << 24) - 1); 7 8 static final int kNumBitModelTotalBits = 11; 9 static final int kBitModelTotal = (1 << kNumBitModelTotalBits); 10 static final int kNumMoveBits = 5; 11 12 java.io.OutputStream Stream; 13 14 long Low; 15 int Range; 16 int _cacheSize; 17 int _cache; 18 19 long _position; 20 21 public void SetStream(java.io.OutputStream stream) 22 { 23 Stream = stream; 24 } 25 26 public void ReleaseStream() 27 { 28 Stream = null; 29 } 30 31 public void Init() 32 { 33 _position = 0; 34 Low = 0; 35 Range = -1; 36 _cacheSize = 1; 37 _cache = 0; 38 } 39 40 public void FlushData() throws IOException 41 { 42 for (int i = 0; i < 5; i++) 43 ShiftLow(); 44 } 45 46 public void FlushStream() throws IOException 47 { 48 Stream.flush(); 49 } 50 51 public void ShiftLow() throws IOException 52 { 53 int LowHi = (int)(Low >>> 32); 54 if (LowHi != 0 || Low < 0xFF000000L) 55 { 56 _position += _cacheSize; 57 int temp = _cache; 58 do 59 { 60 Stream.write(temp + LowHi); 61 temp = 0xFF; 62 } 63 while(--_cacheSize != 0); 64 _cache = (((int)Low) >>> 24); 65 } 66 _cacheSize++; 67 Low = (Low & 0xFFFFFF) << 8; 68 } 69 70 public void EncodeDirectBits(int v, int numTotalBits) throws IOException 71 { 72 for (int i = numTotalBits - 1; i >= 0; i--) 73 { 74 Range >>>= 1; 75 if (((v >>> i) & 1) == 1) 76 Low += Range; 77 if ((Range & Encoder.kTopMask) == 0) 78 { 79 Range <<= 8; 80 ShiftLow(); 81 } 82 } 83 } 84 85 86 public long GetProcessedSizeAdd() 87 { 88 return _cacheSize + _position + 4; 89 } 90 91 92 93 static final int kNumMoveReducingBits = 2; 94 public static final int kNumBitPriceShiftBits = 6; 95 96 public static void InitBitModels(short []probs) 97 { 98 for (int i = 0; i < probs.length; i++) 99 probs[i] = (kBitModelTotal >>> 1); 100 } 101 102 public void Encode(short []probs, int index, int symbol) throws IOException 103 { 104 int prob = probs[index]; 105 int newBound = (Range >>> kNumBitModelTotalBits) * prob; 106 if (symbol == 0) 107 { 108 Range = newBound; 109 probs[index] = (short)(prob + ((kBitModelTotal - prob) >>> kNumMoveBits)); 110 } 111 else 112 { 113 Low += (newBound & 0xFFFFFFFFL); 114 Range -= newBound; 115 probs[index] = (short)(prob - ((prob) >>> kNumMoveBits)); 116 } 117 if ((Range & kTopMask) == 0) 118 { 119 Range <<= 8; 120 ShiftLow(); 121 } 122 } 123 124 private static int[] ProbPrices = new int[kBitModelTotal >>> kNumMoveReducingBits]; 125 126 static 127 { 128 int kNumBits = (kNumBitModelTotalBits - kNumMoveReducingBits); 129 for (int i = kNumBits - 1; i >= 0; i--) 130 { 131 int start = 1 << (kNumBits - i - 1); 132 int end = 1 << (kNumBits - i); 133 for (int j = start; j < end; j++) 134 ProbPrices[j] = (i << kNumBitPriceShiftBits) + 135 (((end - j) << kNumBitPriceShiftBits) >>> (kNumBits - i - 1)); 136 } 137 } 138 139 static public int GetPrice(int Prob, int symbol) 140 { 141 return ProbPrices[(((Prob - symbol) ^ ((-symbol))) & (kBitModelTotal - 1)) >>> kNumMoveReducingBits]; 142 } 143 static public int GetPrice0(int Prob) 144 { 145 return ProbPrices[Prob >>> kNumMoveReducingBits]; 146 } 147 static public int GetPrice1(int Prob) 148 { 149 return ProbPrices[(kBitModelTotal - Prob) >>> kNumMoveReducingBits]; 150 } 151 } 152