1 /* Ppmd7Dec.c -- PPMdH Decoder
2 2018-07-04 : Igor Pavlov : Public domain
3 This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */
9 #define kTopValue (1 << 24)
11 BoolInt
Ppmd7z_RangeDec_Init(CPpmd7z_RangeDec
*p
)
15 p
->Range
= 0xFFFFFFFF;
16 if (IByteIn_Read(p
->Stream
) != 0)
18 for (i
= 0; i
< 4; i
++)
19 p
->Code
= (p
->Code
<< 8) | IByteIn_Read(p
->Stream
);
20 return (p
->Code
< 0xFFFFFFFF);
23 #define GET_Ppmd7z_RangeDec CPpmd7z_RangeDec *p = CONTAINER_FROM_VTBL(pp, CPpmd7z_RangeDec, vt);
25 static UInt32
Range_GetThreshold(const IPpmd7_RangeDec
*pp
, UInt32 total
)
28 return p
->Code
/ (p
->Range
/= total
);
31 static void Range_Normalize(CPpmd7z_RangeDec
*p
)
33 if (p
->Range
< kTopValue
)
35 p
->Code
= (p
->Code
<< 8) | IByteIn_Read(p
->Stream
);
37 if (p
->Range
< kTopValue
)
39 p
->Code
= (p
->Code
<< 8) | IByteIn_Read(p
->Stream
);
45 static void Range_Decode(const IPpmd7_RangeDec
*pp
, UInt32 start
, UInt32 size
)
48 p
->Code
-= start
* p
->Range
;
53 static UInt32
Range_DecodeBit(const IPpmd7_RangeDec
*pp
, UInt32 size0
)
56 UInt32 newBound
= (p
->Range
>> 14) * size0
;
58 if (p
->Code
< newBound
)
73 void Ppmd7z_RangeDec_CreateVTable(CPpmd7z_RangeDec
*p
)
75 p
->vt
.GetThreshold
= Range_GetThreshold
;
76 p
->vt
.Decode
= Range_Decode
;
77 p
->vt
.DecodeBit
= Range_DecodeBit
;
81 #define MASK(sym) ((signed char *)charMask)[sym]
83 int Ppmd7_DecodeSymbol(CPpmd7
*p
, const IPpmd7_RangeDec
*rc
)
85 size_t charMask
[256 / sizeof(size_t)];
86 if (p
->MinContext
->NumStats
!= 1)
88 CPpmd_State
*s
= Ppmd7_GetStats(p
, p
->MinContext
);
91 if ((count
= rc
->GetThreshold(rc
, p
->MinContext
->SummFreq
)) < (hiCnt
= s
->Freq
))
94 rc
->Decode(rc
, 0, s
->Freq
);
101 i
= p
->MinContext
->NumStats
- 1;
104 if ((hiCnt
+= (++s
)->Freq
) > count
)
107 rc
->Decode(rc
, hiCnt
- s
->Freq
, s
->Freq
);
115 if (count
>= p
->MinContext
->SummFreq
)
117 p
->HiBitsFlag
= p
->HB2Flag
[p
->FoundState
->Symbol
];
118 rc
->Decode(rc
, hiCnt
, p
->MinContext
->SummFreq
- hiCnt
);
119 PPMD_SetAllBitsIn256Bytes(charMask
);
121 i
= p
->MinContext
->NumStats
- 1;
122 do { MASK((--s
)->Symbol
) = 0; } while (--i
);
126 UInt16
*prob
= Ppmd7_GetBinSumm(p
);
127 if (rc
->DecodeBit(rc
, *prob
) == 0)
130 *prob
= (UInt16
)PPMD_UPDATE_PROB_0(*prob
);
131 symbol
= (p
->FoundState
= Ppmd7Context_OneState(p
->MinContext
))->Symbol
;
135 *prob
= (UInt16
)PPMD_UPDATE_PROB_1(*prob
);
136 p
->InitEsc
= PPMD7_kExpEscape
[*prob
>> 10];
137 PPMD_SetAllBitsIn256Bytes(charMask
);
138 MASK(Ppmd7Context_OneState(p
->MinContext
)->Symbol
) = 0;
143 CPpmd_State
*ps
[256], *s
;
144 UInt32 freqSum
, count
, hiCnt
;
146 unsigned i
, num
, numMasked
= p
->MinContext
->NumStats
;
150 if (!p
->MinContext
->Suffix
)
152 p
->MinContext
= Ppmd7_GetContext(p
, p
->MinContext
->Suffix
);
154 while (p
->MinContext
->NumStats
== numMasked
);
156 s
= Ppmd7_GetStats(p
, p
->MinContext
);
158 num
= p
->MinContext
->NumStats
- numMasked
;
161 int k
= (int)(MASK(s
->Symbol
));
162 hiCnt
+= (s
->Freq
& k
);
168 see
= Ppmd7_MakeEscFreq(p
, numMasked
, &freqSum
);
170 count
= rc
->GetThreshold(rc
, freqSum
);
175 CPpmd_State
**pps
= ps
;
176 for (hiCnt
= 0; (hiCnt
+= (*pps
)->Freq
) <= count
; pps
++);
178 rc
->Decode(rc
, hiCnt
- s
->Freq
, s
->Freq
);
179 Ppmd_See_Update(see
);
185 if (count
>= freqSum
)
187 rc
->Decode(rc
, hiCnt
, freqSum
- hiCnt
);
188 see
->Summ
= (UInt16
)(see
->Summ
+ freqSum
);
189 do { MASK(ps
[--i
]->Symbol
) = 0; } while (i
!= 0);