1// Compress/RangeCoder/RangeCoderBit.h 2 3#ifndef __COMPRESS_RANGECODER_BIT_H 4#define __COMPRESS_RANGECODER_BIT_H 5 6#include "RangeCoder.h" 7 8namespace NCompress { 9namespace NRangeCoder { 10 11const int kNumBitModelTotalBits = 11; 12const UInt32 kBitModelTotal = (1 << kNumBitModelTotalBits); 13 14const int kNumMoveReducingBits = 2; 15 16const int kNumBitPriceShiftBits = 6; 17const UInt32 kBitPrice = 1 << kNumBitPriceShiftBits; 18 19class CPriceTables 20{ 21public: 22 static UInt32 ProbPrices[kBitModelTotal >> kNumMoveReducingBits]; 23 static void Init(); 24 CPriceTables(); 25}; 26 27template <int numMoveBits> 28class CBitModel 29{ 30public: 31 UInt32 Prob; 32 void UpdateModel(UInt32 symbol) 33 { 34 /* 35 Prob -= (Prob + ((symbol - 1) & ((1 << numMoveBits) - 1))) >> numMoveBits; 36 Prob += (1 - symbol) << (kNumBitModelTotalBits - numMoveBits); 37 */ 38 if (symbol == 0) 39 Prob += (kBitModelTotal - Prob) >> numMoveBits; 40 else 41 Prob -= (Prob) >> numMoveBits; 42 } 43public: 44 void Init() { Prob = kBitModelTotal / 2; } 45}; 46 47template <int numMoveBits> 48class CBitEncoder: public CBitModel<numMoveBits> 49{ 50public: 51 void Encode(CEncoder *encoder, UInt32 symbol) 52 { 53 /* 54 encoder->EncodeBit(this->Prob, kNumBitModelTotalBits, symbol); 55 this->UpdateModel(symbol); 56 */ 57 UInt32 newBound = (encoder->Range >> kNumBitModelTotalBits) * this->Prob; 58 if (symbol == 0) 59 { 60 encoder->Range = newBound; 61 this->Prob += (kBitModelTotal - this->Prob) >> numMoveBits; 62 } 63 else 64 { 65 encoder->Low += newBound; 66 encoder->Range -= newBound; 67 this->Prob -= (this->Prob) >> numMoveBits; 68 } 69 if (encoder->Range < kTopValue) 70 { 71 encoder->Range <<= 8; 72 encoder->ShiftLow(); 73 } 74 } 75 UInt32 GetPrice(UInt32 symbol) const 76 { 77 return CPriceTables::ProbPrices[ 78 (((this->Prob - symbol) ^ ((-(int)symbol))) & (kBitModelTotal - 1)) >> kNumMoveReducingBits]; 79 } 80 UInt32 GetPrice0() const { return CPriceTables::ProbPrices[this->Prob >> kNumMoveReducingBits]; } 81 UInt32 GetPrice1() const { return CPriceTables::ProbPrices[(kBitModelTotal - this->Prob) >> kNumMoveReducingBits]; } 82}; 83 84 85template <int numMoveBits> 86class CBitDecoder: public CBitModel<numMoveBits> 87{ 88public: 89 UInt32 Decode(CDecoder *decoder) 90 { 91 UInt32 newBound = (decoder->Range >> kNumBitModelTotalBits) * this->Prob; 92 if (decoder->Code < newBound) 93 { 94 decoder->Range = newBound; 95 this->Prob += (kBitModelTotal - this->Prob) >> numMoveBits; 96 if (decoder->Range < kTopValue) 97 { 98 decoder->Code = (decoder->Code << 8) | decoder->Stream.ReadByte(); 99 decoder->Range <<= 8; 100 } 101 return 0; 102 } 103 else 104 { 105 decoder->Range -= newBound; 106 decoder->Code -= newBound; 107 this->Prob -= (this->Prob) >> numMoveBits; 108 if (decoder->Range < kTopValue) 109 { 110 decoder->Code = (decoder->Code << 8) | decoder->Stream.ReadByte(); 111 decoder->Range <<= 8; 112 } 113 return 1; 114 } 115 } 116}; 117 118}} 119 120#endif 121