17e2399c80b851754358adffc821699045534cd0egspencer@chromium.orgpackage SevenZip.Compression.RangeCoder; 27e2399c80b851754358adffc821699045534cd0egspencer@chromium.orgimport java.io.IOException; 37e2399c80b851754358adffc821699045534cd0egspencer@chromium.org 47e2399c80b851754358adffc821699045534cd0egspencer@chromium.orgpublic class Encoder 57e2399c80b851754358adffc821699045534cd0egspencer@chromium.org{ 67e2399c80b851754358adffc821699045534cd0egspencer@chromium.org static final int kTopMask = ~((1 << 24) - 1); 77e2399c80b851754358adffc821699045534cd0egspencer@chromium.org 87e2399c80b851754358adffc821699045534cd0egspencer@chromium.org static final int kNumBitModelTotalBits = 11; 97e2399c80b851754358adffc821699045534cd0egspencer@chromium.org static final int kBitModelTotal = (1 << kNumBitModelTotalBits); 107e2399c80b851754358adffc821699045534cd0egspencer@chromium.org static final int kNumMoveBits = 5; 117e2399c80b851754358adffc821699045534cd0egspencer@chromium.org 127e2399c80b851754358adffc821699045534cd0egspencer@chromium.org java.io.OutputStream Stream; 137e2399c80b851754358adffc821699045534cd0egspencer@chromium.org 147e2399c80b851754358adffc821699045534cd0egspencer@chromium.org long Low; 157e2399c80b851754358adffc821699045534cd0egspencer@chromium.org int Range; 167e2399c80b851754358adffc821699045534cd0egspencer@chromium.org int _cacheSize; 177e2399c80b851754358adffc821699045534cd0egspencer@chromium.org int _cache; 187e2399c80b851754358adffc821699045534cd0egspencer@chromium.org 197e2399c80b851754358adffc821699045534cd0egspencer@chromium.org long _position; 207e2399c80b851754358adffc821699045534cd0egspencer@chromium.org 217e2399c80b851754358adffc821699045534cd0egspencer@chromium.org public void SetStream(java.io.OutputStream stream) 227e2399c80b851754358adffc821699045534cd0egspencer@chromium.org { 237e2399c80b851754358adffc821699045534cd0egspencer@chromium.org Stream = stream; 247e2399c80b851754358adffc821699045534cd0egspencer@chromium.org } 257e2399c80b851754358adffc821699045534cd0egspencer@chromium.org 267e2399c80b851754358adffc821699045534cd0egspencer@chromium.org public void ReleaseStream() 277e2399c80b851754358adffc821699045534cd0egspencer@chromium.org { 287e2399c80b851754358adffc821699045534cd0egspencer@chromium.org Stream = null; 297e2399c80b851754358adffc821699045534cd0egspencer@chromium.org } 307e2399c80b851754358adffc821699045534cd0egspencer@chromium.org 317e2399c80b851754358adffc821699045534cd0egspencer@chromium.org public void Init() 327e2399c80b851754358adffc821699045534cd0egspencer@chromium.org { 337e2399c80b851754358adffc821699045534cd0egspencer@chromium.org _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