1 /* Ppmd7Enc.c -- PPMdH Encoder
2 2017-04-03 : Igor Pavlov : Public domain
3 This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */
9 #define kTopValue (1 << 24)
11 void Ppmd7z_RangeEnc_Init(CPpmd7z_RangeEnc
*p
)
14 p
->Range
= 0xFFFFFFFF;
19 static void RangeEnc_ShiftLow(CPpmd7z_RangeEnc
*p
)
21 if ((UInt32
)p
->Low
< (UInt32
)0xFF000000 || (unsigned)(p
->Low
>> 32) != 0)
26 IByteOut_Write(p
->Stream
, (Byte
)(temp
+ (Byte
)(p
->Low
>> 32)));
29 while (--p
->CacheSize
!= 0);
30 p
->Cache
= (Byte
)((UInt32
)p
->Low
>> 24);
33 p
->Low
= (UInt32
)p
->Low
<< 8;
36 static void RangeEnc_Encode(CPpmd7z_RangeEnc
*p
, UInt32 start
, UInt32 size
, UInt32 total
)
38 p
->Low
+= start
* (p
->Range
/= total
);
40 while (p
->Range
< kTopValue
)
47 static void RangeEnc_EncodeBit_0(CPpmd7z_RangeEnc
*p
, UInt32 size0
)
49 p
->Range
= (p
->Range
>> 14) * size0
;
50 while (p
->Range
< kTopValue
)
57 static void RangeEnc_EncodeBit_1(CPpmd7z_RangeEnc
*p
, UInt32 size0
)
59 UInt32 newBound
= (p
->Range
>> 14) * size0
;
62 while (p
->Range
< kTopValue
)
69 void Ppmd7z_RangeEnc_FlushData(CPpmd7z_RangeEnc
*p
)
72 for (i
= 0; i
< 5; i
++)
77 #define MASK(sym) ((signed char *)charMask)[sym]
79 void Ppmd7_EncodeSymbol(CPpmd7
*p
, CPpmd7z_RangeEnc
*rc
, int symbol
)
81 size_t charMask
[256 / sizeof(size_t)];
82 if (p
->MinContext
->NumStats
!= 1)
84 CPpmd_State
*s
= Ppmd7_GetStats(p
, p
->MinContext
);
87 if (s
->Symbol
== symbol
)
89 RangeEnc_Encode(rc
, 0, s
->Freq
, p
->MinContext
->SummFreq
);
96 i
= p
->MinContext
->NumStats
- 1;
99 if ((++s
)->Symbol
== symbol
)
101 RangeEnc_Encode(rc
, sum
, s
->Freq
, p
->MinContext
->SummFreq
);
110 p
->HiBitsFlag
= p
->HB2Flag
[p
->FoundState
->Symbol
];
111 PPMD_SetAllBitsIn256Bytes(charMask
);
113 i
= p
->MinContext
->NumStats
- 1;
114 do { MASK((--s
)->Symbol
) = 0; } while (--i
);
115 RangeEnc_Encode(rc
, sum
, p
->MinContext
->SummFreq
- sum
, p
->MinContext
->SummFreq
);
119 UInt16
*prob
= Ppmd7_GetBinSumm(p
);
120 CPpmd_State
*s
= Ppmd7Context_OneState(p
->MinContext
);
121 if (s
->Symbol
== symbol
)
123 RangeEnc_EncodeBit_0(rc
, *prob
);
124 *prob
= (UInt16
)PPMD_UPDATE_PROB_0(*prob
);
131 RangeEnc_EncodeBit_1(rc
, *prob
);
132 *prob
= (UInt16
)PPMD_UPDATE_PROB_1(*prob
);
133 p
->InitEsc
= PPMD7_kExpEscape
[*prob
>> 10];
134 PPMD_SetAllBitsIn256Bytes(charMask
);
145 unsigned i
, numMasked
= p
->MinContext
->NumStats
;
149 if (!p
->MinContext
->Suffix
)
150 return; /* EndMarker (symbol = -1) */
151 p
->MinContext
= Ppmd7_GetContext(p
, p
->MinContext
->Suffix
);
153 while (p
->MinContext
->NumStats
== numMasked
);
155 see
= Ppmd7_MakeEscFreq(p
, numMasked
, &escFreq
);
156 s
= Ppmd7_GetStats(p
, p
->MinContext
);
158 i
= p
->MinContext
->NumStats
;
168 sum
+= (s
->Freq
& (int)(MASK(s
->Symbol
)));
172 RangeEnc_Encode(rc
, low
, s1
->Freq
, sum
+ escFreq
);
173 Ppmd_See_Update(see
);
178 sum
+= (s
->Freq
& (int)(MASK(cur
)));
184 RangeEnc_Encode(rc
, sum
, escFreq
, sum
+ escFreq
);
185 see
->Summ
= (UInt16
)(see
->Summ
+ sum
+ escFreq
);