summaryrefslogtreecommitdiffstats
path: root/src/libs/7zip/win/CPP/7zip/Compress/RangeCoderBit.h
blob: 0eddd558630949e3a5bd6389931d0d05b2b9c5ca (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
// Compress/RangeCoderBit.h
// 2013-01-10 : Igor Pavlov : Public domain

#ifndef __COMPRESS_RANGE_CODER_BIT_H
#define __COMPRESS_RANGE_CODER_BIT_H

#include "RangeCoder.h"

namespace NCompress {
namespace NRangeCoder {

const unsigned kNumBitModelTotalBits = 11;
const UInt32 kBitModelTotal = (1 << kNumBitModelTotalBits);

const unsigned kNumMoveReducingBits = 4;

const unsigned kNumBitPriceShiftBits = 4;
const UInt32 kBitPrice = 1 << kNumBitPriceShiftBits;

extern UInt32 ProbPrices[kBitModelTotal >> kNumMoveReducingBits];

template <unsigned numMoveBits>
class CBitModel
{
public:
  UInt32 Prob;
  void UpdateModel(UInt32 symbol)
  {
    /*
    Prob -= (Prob + ((symbol - 1) & ((1 << numMoveBits) - 1))) >> numMoveBits;
    Prob += (1 - symbol) << (kNumBitModelTotalBits - numMoveBits);
    */
    if (symbol == 0)
      Prob += (kBitModelTotal - Prob) >> numMoveBits;
    else
      Prob -= (Prob) >> numMoveBits;
  }
public:
  void Init() { Prob = kBitModelTotal / 2; }
};

template <unsigned numMoveBits>
class CBitEncoder: public CBitModel<numMoveBits>
{
public:
  void Encode(CEncoder *encoder, UInt32 symbol)
  {
    /*
    encoder->EncodeBit(this->Prob, kNumBitModelTotalBits, symbol);
    this->UpdateModel(symbol);
    */
    UInt32 newBound = (encoder->Range >> kNumBitModelTotalBits) * this->Prob;
    if (symbol == 0)
    {
      encoder->Range = newBound;
      this->Prob += (kBitModelTotal - this->Prob) >> numMoveBits;
    }
    else
    {
      encoder->Low += newBound;
      encoder->Range -= newBound;
      this->Prob -= (this->Prob) >> numMoveBits;
    }
    if (encoder->Range < kTopValue)
    {
      encoder->Range <<= 8;
      encoder->ShiftLow();
    }
  }
  UInt32 GetPrice(UInt32 symbol) const
  {
    return ProbPrices[(this->Prob ^ ((-(int)(Int32)symbol)) & (kBitModelTotal - 1)) >> kNumMoveReducingBits];
  }
  UInt32 GetPrice0() const { return ProbPrices[this->Prob >> kNumMoveReducingBits]; }
  UInt32 GetPrice1() const { return ProbPrices[(this->Prob ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits]; }
};


template <unsigned numMoveBits>
class CBitDecoder: public CBitModel<numMoveBits>
{
public:
  UInt32 Decode(CDecoder *decoder)
  {
    UInt32 newBound = (decoder->Range >> kNumBitModelTotalBits) * this->Prob;
    if (decoder->Code < newBound)
    {
      decoder->Range = newBound;
      this->Prob += (kBitModelTotal - this->Prob) >> numMoveBits;
      if (decoder->Range < kTopValue)
      {
        decoder->Code = (decoder->Code << 8) | decoder->Stream.ReadByte();
        decoder->Range <<= 8;
      }
      return 0;
    }
    else
    {
      decoder->Range -= newBound;
      decoder->Code -= newBound;
      this->Prob -= (this->Prob) >> numMoveBits;
      if (decoder->Range < kTopValue)
      {
        decoder->Code = (decoder->Code << 8) | decoder->Stream.ReadByte();
        decoder->Range <<= 8;
      }
      return 1;
    }
  }
};

}}

#endif