1// Compress/RangeCoderBit.h 2// 2009-05-30 : 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 9namespace NCompress { 10namespace NRangeCoder { 11 12const int kNumBitModelTotalBits = 11; 13const UInt32 kBitModelTotal = (1 << kNumBitModelTotalBits); 14 15const int kNumMoveReducingBits = 4; 16 17const int kNumBitPriceShiftBits = 4; 18const UInt32 kBitPrice = 1 << kNumBitPriceShiftBits; 19 20extern UInt32 ProbPrices[kBitModelTotal >> kNumMoveReducingBits]; 21 22template <int numMoveBits> 23class CBitModel 24{ 25public: 26 UInt32 Prob; 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 } 38public: 39 void Init() { Prob = kBitModelTotal / 2; } 40}; 41 42template <int numMoveBits> 43class CBitEncoder: public CBitModel<numMoveBits> 44{ 45public: 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 } 70 UInt32 GetPrice(UInt32 symbol) const 71 { 72 return ProbPrices[(this->Prob ^ ((-(int)symbol)) & (kBitModelTotal - 1)) >> kNumMoveReducingBits]; 73 } 74 UInt32 GetPrice0() const { return ProbPrices[this->Prob >> kNumMoveReducingBits]; } 75 UInt32 GetPrice1() const { return ProbPrices[(this->Prob ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits]; } 76}; 77 78 79template <int numMoveBits> 80class CBitDecoder: public CBitModel<numMoveBits> 81{ 82public: 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