Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

187 lines
4.3 KiB

  1. /* Ppmd7Enc.c -- PPMdH Encoder
  2. 2010-03-12 : Igor Pavlov : Public domain
  3. This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */
  4. #include "Precomp.h"
  5. #include "Ppmd7.h"
  6. #define kTopValue (1 << 24)
  7. void Ppmd7z_RangeEnc_Init(CPpmd7z_RangeEnc *p)
  8. {
  9. p->Low = 0;
  10. p->Range = 0xFFFFFFFF;
  11. p->Cache = 0;
  12. p->CacheSize = 1;
  13. }
  14. static void RangeEnc_ShiftLow(CPpmd7z_RangeEnc *p)
  15. {
  16. if ((UInt32)p->Low < (UInt32)0xFF000000 || (unsigned)(p->Low >> 32) != 0)
  17. {
  18. Byte temp = p->Cache;
  19. do
  20. {
  21. p->Stream->Write(p->Stream, (Byte)(temp + (Byte)(p->Low >> 32)));
  22. temp = 0xFF;
  23. }
  24. while(--p->CacheSize != 0);
  25. p->Cache = (Byte)((UInt32)p->Low >> 24);
  26. }
  27. p->CacheSize++;
  28. p->Low = (UInt32)p->Low << 8;
  29. }
  30. static void RangeEnc_Encode(CPpmd7z_RangeEnc *p, UInt32 start, UInt32 size, UInt32 total)
  31. {
  32. p->Low += start * (p->Range /= total);
  33. p->Range *= size;
  34. while (p->Range < kTopValue)
  35. {
  36. p->Range <<= 8;
  37. RangeEnc_ShiftLow(p);
  38. }
  39. }
  40. static void RangeEnc_EncodeBit_0(CPpmd7z_RangeEnc *p, UInt32 size0)
  41. {
  42. p->Range = (p->Range >> 14) * size0;
  43. while (p->Range < kTopValue)
  44. {
  45. p->Range <<= 8;
  46. RangeEnc_ShiftLow(p);
  47. }
  48. }
  49. static void RangeEnc_EncodeBit_1(CPpmd7z_RangeEnc *p, UInt32 size0)
  50. {
  51. UInt32 newBound = (p->Range >> 14) * size0;
  52. p->Low += newBound;
  53. p->Range -= newBound;
  54. while (p->Range < kTopValue)
  55. {
  56. p->Range <<= 8;
  57. RangeEnc_ShiftLow(p);
  58. }
  59. }
  60. void Ppmd7z_RangeEnc_FlushData(CPpmd7z_RangeEnc *p)
  61. {
  62. unsigned i;
  63. for (i = 0; i < 5; i++)
  64. RangeEnc_ShiftLow(p);
  65. }
  66. #define MASK(sym) ((signed char *)charMask)[sym]
  67. void Ppmd7_EncodeSymbol(CPpmd7 *p, CPpmd7z_RangeEnc *rc, int symbol)
  68. {
  69. size_t charMask[256 / sizeof(size_t)];
  70. if (p->MinContext->NumStats != 1)
  71. {
  72. CPpmd_State *s = Ppmd7_GetStats(p, p->MinContext);
  73. UInt32 sum;
  74. unsigned i;
  75. if (s->Symbol == symbol)
  76. {
  77. RangeEnc_Encode(rc, 0, s->Freq, p->MinContext->SummFreq);
  78. p->FoundState = s;
  79. Ppmd7_Update1_0(p);
  80. return;
  81. }
  82. p->PrevSuccess = 0;
  83. sum = s->Freq;
  84. i = p->MinContext->NumStats - 1;
  85. do
  86. {
  87. if ((++s)->Symbol == symbol)
  88. {
  89. RangeEnc_Encode(rc, sum, s->Freq, p->MinContext->SummFreq);
  90. p->FoundState = s;
  91. Ppmd7_Update1(p);
  92. return;
  93. }
  94. sum += s->Freq;
  95. }
  96. while (--i);
  97. p->HiBitsFlag = p->HB2Flag[p->FoundState->Symbol];
  98. PPMD_SetAllBitsIn256Bytes(charMask);
  99. MASK(s->Symbol) = 0;
  100. i = p->MinContext->NumStats - 1;
  101. do { MASK((--s)->Symbol) = 0; } while (--i);
  102. RangeEnc_Encode(rc, sum, p->MinContext->SummFreq - sum, p->MinContext->SummFreq);
  103. }
  104. else
  105. {
  106. UInt16 *prob = Ppmd7_GetBinSumm(p);
  107. CPpmd_State *s = Ppmd7Context_OneState(p->MinContext);
  108. if (s->Symbol == symbol)
  109. {
  110. RangeEnc_EncodeBit_0(rc, *prob);
  111. *prob = (UInt16)PPMD_UPDATE_PROB_0(*prob);
  112. p->FoundState = s;
  113. Ppmd7_UpdateBin(p);
  114. return;
  115. }
  116. else
  117. {
  118. RangeEnc_EncodeBit_1(rc, *prob);
  119. *prob = (UInt16)PPMD_UPDATE_PROB_1(*prob);
  120. p->InitEsc = PPMD7_kExpEscape[*prob >> 10];
  121. PPMD_SetAllBitsIn256Bytes(charMask);
  122. MASK(s->Symbol) = 0;
  123. p->PrevSuccess = 0;
  124. }
  125. }
  126. for (;;)
  127. {
  128. UInt32 escFreq;
  129. CPpmd_See *see;
  130. CPpmd_State *s;
  131. UInt32 sum;
  132. unsigned i, numMasked = p->MinContext->NumStats;
  133. do
  134. {
  135. p->OrderFall++;
  136. if (!p->MinContext->Suffix)
  137. return; /* EndMarker (symbol = -1) */
  138. p->MinContext = Ppmd7_GetContext(p, p->MinContext->Suffix);
  139. }
  140. while (p->MinContext->NumStats == numMasked);
  141. see = Ppmd7_MakeEscFreq(p, numMasked, &escFreq);
  142. s = Ppmd7_GetStats(p, p->MinContext);
  143. sum = 0;
  144. i = p->MinContext->NumStats;
  145. do
  146. {
  147. int cur = s->Symbol;
  148. if (cur == symbol)
  149. {
  150. UInt32 low = sum;
  151. CPpmd_State *s1 = s;
  152. do
  153. {
  154. sum += (s->Freq & (int)(MASK(s->Symbol)));
  155. s++;
  156. }
  157. while (--i);
  158. RangeEnc_Encode(rc, low, s1->Freq, sum + escFreq);
  159. Ppmd_See_Update(see);
  160. p->FoundState = s1;
  161. Ppmd7_Update2(p);
  162. return;
  163. }
  164. sum += (s->Freq & (int)(MASK(cur)));
  165. MASK(cur) = 0;
  166. s++;
  167. }
  168. while (--i);
  169. RangeEnc_Encode(rc, sum, escFreq, sum + escFreq);
  170. see->Summ = (UInt16)(see->Summ + sum + escFreq);
  171. }
  172. }