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