archive_ppmd8.c 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287
  1. /* Ppmd8.c -- PPMdI codec
  2. 2016-05-21 : Igor Pavlov : Public domain
  3. This code is based on PPMd var.I (2002): Dmitry Shkarin : Public domain */
  4. #include "archive_platform.h"
  5. #include <string.h>
  6. #include "archive_ppmd8_private.h"
  7. const Byte PPMD8_kExpEscape[16] = { 25, 14, 9, 7, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2 };
  8. static const UInt16 kInitBinEsc[] = { 0x3CDD, 0x1F3F, 0x59BF, 0x48F3, 0x64A1, 0x5ABC, 0x6632, 0x6051};
  9. #define MAX_FREQ 124
  10. #define UNIT_SIZE 12
  11. #define U2B(nu) ((UInt32)(nu) * UNIT_SIZE)
  12. #define U2I(nu) (p->Units2Indx[(nu) - 1])
  13. #define I2U(indx) (p->Indx2Units[indx])
  14. #ifdef PPMD_32BIT
  15. #define REF(ptr) (ptr)
  16. #else
  17. #define REF(ptr) ((UInt32)((Byte *)(ptr) - (p)->Base))
  18. #endif
  19. #define STATS_REF(ptr) ((CPpmd_State_Ref)REF(ptr))
  20. #define CTX(ref) ((CPpmd8_Context *)Ppmd8_GetContext(p, ref))
  21. #define STATS(ctx) Ppmd8_GetStats(p, ctx)
  22. #define ONE_STATE(ctx) Ppmd8Context_OneState(ctx)
  23. #define SUFFIX(ctx) CTX((ctx)->Suffix)
  24. #define kTop (1 << 24)
  25. #define kBot (1 << 15)
  26. typedef CPpmd8_Context * CTX_PTR;
  27. struct CPpmd8_Node_;
  28. typedef
  29. #ifdef PPMD_32BIT
  30. struct CPpmd8_Node_ *
  31. #else
  32. UInt32
  33. #endif
  34. CPpmd8_Node_Ref;
  35. typedef struct CPpmd8_Node_
  36. {
  37. UInt32 Stamp;
  38. CPpmd8_Node_Ref Next;
  39. UInt32 NU;
  40. } CPpmd8_Node;
  41. #ifdef PPMD_32BIT
  42. #define NODE(ptr) (ptr)
  43. #else
  44. #define NODE(offs) ((CPpmd8_Node *)(p->Base + (offs)))
  45. #endif
  46. #define EMPTY_NODE 0xFFFFFFFF
  47. void Ppmd8_Construct(CPpmd8 *p)
  48. {
  49. unsigned i, k, m;
  50. p->Base = 0;
  51. for (i = 0, k = 0; i < PPMD_NUM_INDEXES; i++)
  52. {
  53. unsigned step = (i >= 12 ? 4 : (i >> 2) + 1);
  54. do { p->Units2Indx[k++] = (Byte)i; } while (--step);
  55. p->Indx2Units[i] = (Byte)k;
  56. }
  57. p->NS2BSIndx[0] = (0 << 1);
  58. p->NS2BSIndx[1] = (1 << 1);
  59. memset(p->NS2BSIndx + 2, (2 << 1), 9);
  60. memset(p->NS2BSIndx + 11, (3 << 1), 256 - 11);
  61. for (i = 0; i < 5; i++)
  62. p->NS2Indx[i] = (Byte)i;
  63. for (m = i, k = 1; i < 260; i++)
  64. {
  65. p->NS2Indx[i] = (Byte)m;
  66. if (--k == 0)
  67. k = (++m) - 4;
  68. }
  69. }
  70. void Ppmd8_Free(CPpmd8 *p)
  71. {
  72. free(p->Base);
  73. p->Size = 0;
  74. p->Base = 0;
  75. }
  76. Bool Ppmd8_Alloc(CPpmd8 *p, UInt32 size)
  77. {
  78. if (p->Base == 0 || p->Size != size)
  79. {
  80. Ppmd8_Free(p);
  81. p->AlignOffset =
  82. #ifdef PPMD_32BIT
  83. (4 - size) & 3;
  84. #else
  85. 4 - (size & 3);
  86. #endif
  87. if ((p->Base = (Byte *)malloc(p->AlignOffset + size)) == 0)
  88. return False;
  89. p->Size = size;
  90. }
  91. return True;
  92. }
  93. static void InsertNode(CPpmd8 *p, void *node, unsigned indx)
  94. {
  95. ((CPpmd8_Node *)node)->Stamp = EMPTY_NODE;
  96. ((CPpmd8_Node *)node)->Next = (CPpmd8_Node_Ref)p->FreeList[indx];
  97. ((CPpmd8_Node *)node)->NU = I2U(indx);
  98. p->FreeList[indx] = REF(node);
  99. p->Stamps[indx]++;
  100. }
  101. static void *RemoveNode(CPpmd8 *p, unsigned indx)
  102. {
  103. CPpmd8_Node *node = NODE((CPpmd8_Node_Ref)p->FreeList[indx]);
  104. p->FreeList[indx] = node->Next;
  105. p->Stamps[indx]--;
  106. return node;
  107. }
  108. static void SplitBlock(CPpmd8 *p, void *ptr, unsigned oldIndx, unsigned newIndx)
  109. {
  110. unsigned i, nu = I2U(oldIndx) - I2U(newIndx);
  111. ptr = (Byte *)ptr + U2B(I2U(newIndx));
  112. if (I2U(i = U2I(nu)) != nu)
  113. {
  114. unsigned k = I2U(--i);
  115. InsertNode(p, ((Byte *)ptr) + U2B(k), nu - k - 1);
  116. }
  117. InsertNode(p, ptr, i);
  118. }
  119. static void GlueFreeBlocks(CPpmd8 *p)
  120. {
  121. CPpmd8_Node_Ref head = 0;
  122. CPpmd8_Node_Ref *prev = &head;
  123. unsigned i;
  124. p->GlueCount = 1 << 13;
  125. memset(p->Stamps, 0, sizeof(p->Stamps));
  126. /* Order-0 context is always at top UNIT, so we don't need guard NODE at the end.
  127. All blocks up to p->LoUnit can be free, so we need guard NODE at LoUnit. */
  128. if (p->LoUnit != p->HiUnit)
  129. ((CPpmd8_Node *)p->LoUnit)->Stamp = 0;
  130. /* Glue free blocks */
  131. for (i = 0; i < PPMD_NUM_INDEXES; i++)
  132. {
  133. CPpmd8_Node_Ref next = (CPpmd8_Node_Ref)p->FreeList[i];
  134. p->FreeList[i] = 0;
  135. while (next != 0)
  136. {
  137. CPpmd8_Node *node = NODE(next);
  138. if (node->NU != 0)
  139. {
  140. CPpmd8_Node *node2;
  141. *prev = next;
  142. prev = &(node->Next);
  143. while ((node2 = node + node->NU)->Stamp == EMPTY_NODE)
  144. {
  145. node->NU += node2->NU;
  146. node2->NU = 0;
  147. }
  148. }
  149. next = node->Next;
  150. }
  151. }
  152. *prev = 0;
  153. /* Fill lists of free blocks */
  154. while (head != 0)
  155. {
  156. CPpmd8_Node *node = NODE(head);
  157. unsigned nu;
  158. head = node->Next;
  159. nu = node->NU;
  160. if (nu == 0)
  161. continue;
  162. for (; nu > 128; nu -= 128, node += 128)
  163. InsertNode(p, node, PPMD_NUM_INDEXES - 1);
  164. if (I2U(i = U2I(nu)) != nu)
  165. {
  166. unsigned k = I2U(--i);
  167. InsertNode(p, node + k, nu - k - 1);
  168. }
  169. InsertNode(p, node, i);
  170. }
  171. }
  172. static void *AllocUnitsRare(CPpmd8 *p, unsigned indx)
  173. {
  174. unsigned i;
  175. void *retVal;
  176. if (p->GlueCount == 0)
  177. {
  178. GlueFreeBlocks(p);
  179. if (p->FreeList[indx] != 0)
  180. return RemoveNode(p, indx);
  181. }
  182. i = indx;
  183. do
  184. {
  185. if (++i == PPMD_NUM_INDEXES)
  186. {
  187. UInt32 numBytes = U2B(I2U(indx));
  188. p->GlueCount--;
  189. return ((UInt32)(p->UnitsStart - p->Text) > numBytes) ? (p->UnitsStart -= numBytes) : (NULL);
  190. }
  191. }
  192. while (p->FreeList[i] == 0);
  193. retVal = RemoveNode(p, i);
  194. SplitBlock(p, retVal, i, indx);
  195. return retVal;
  196. }
  197. static void *AllocUnits(CPpmd8 *p, unsigned indx)
  198. {
  199. UInt32 numBytes;
  200. if (p->FreeList[indx] != 0)
  201. return RemoveNode(p, indx);
  202. numBytes = U2B(I2U(indx));
  203. if (numBytes <= (UInt32)(p->HiUnit - p->LoUnit))
  204. {
  205. void *retVal = p->LoUnit;
  206. p->LoUnit += numBytes;
  207. return retVal;
  208. }
  209. return AllocUnitsRare(p, indx);
  210. }
  211. #define MyMem12Cpy(dest, src, num) \
  212. { UInt32 *d = (UInt32 *)dest; const UInt32 *z = (const UInt32 *)src; UInt32 n = num; \
  213. do { d[0] = z[0]; d[1] = z[1]; d[2] = z[2]; z += 3; d += 3; } while (--n); }
  214. static void *ShrinkUnits(CPpmd8 *p, void *oldPtr, unsigned oldNU, unsigned newNU)
  215. {
  216. unsigned i0 = U2I(oldNU);
  217. unsigned i1 = U2I(newNU);
  218. if (i0 == i1)
  219. return oldPtr;
  220. if (p->FreeList[i1] != 0)
  221. {
  222. void *ptr = RemoveNode(p, i1);
  223. MyMem12Cpy(ptr, oldPtr, newNU);
  224. InsertNode(p, oldPtr, i0);
  225. return ptr;
  226. }
  227. SplitBlock(p, oldPtr, i0, i1);
  228. return oldPtr;
  229. }
  230. static void FreeUnits(CPpmd8 *p, void *ptr, unsigned nu)
  231. {
  232. InsertNode(p, ptr, U2I(nu));
  233. }
  234. static void SpecialFreeUnit(CPpmd8 *p, void *ptr)
  235. {
  236. if ((Byte *)ptr != p->UnitsStart)
  237. InsertNode(p, ptr, 0);
  238. else
  239. {
  240. #ifdef PPMD8_FREEZE_SUPPORT
  241. *(UInt32 *)ptr = EMPTY_NODE; /* it's used for (Flags == 0xFF) check in RemoveBinContexts */
  242. #endif
  243. p->UnitsStart += UNIT_SIZE;
  244. }
  245. }
  246. static void *MoveUnitsUp(CPpmd8 *p, void *oldPtr, unsigned nu)
  247. {
  248. unsigned indx = U2I(nu);
  249. void *ptr;
  250. if ((Byte *)oldPtr > p->UnitsStart + 16 * 1024 || REF(oldPtr) > p->FreeList[indx])
  251. return oldPtr;
  252. ptr = RemoveNode(p, indx);
  253. MyMem12Cpy(ptr, oldPtr, nu);
  254. if ((Byte*)oldPtr != p->UnitsStart)
  255. InsertNode(p, oldPtr, indx);
  256. else
  257. p->UnitsStart += U2B(I2U(indx));
  258. return ptr;
  259. }
  260. static void ExpandTextArea(CPpmd8 *p)
  261. {
  262. UInt32 count[PPMD_NUM_INDEXES];
  263. unsigned i;
  264. memset(count, 0, sizeof(count));
  265. if (p->LoUnit != p->HiUnit)
  266. ((CPpmd8_Node *)p->LoUnit)->Stamp = 0;
  267. {
  268. CPpmd8_Node *node = (CPpmd8_Node *)p->UnitsStart;
  269. for (; node->Stamp == EMPTY_NODE; node += node->NU)
  270. {
  271. node->Stamp = 0;
  272. count[U2I(node->NU)]++;
  273. }
  274. p->UnitsStart = (Byte *)node;
  275. }
  276. for (i = 0; i < PPMD_NUM_INDEXES; i++)
  277. {
  278. CPpmd8_Node_Ref *next = (CPpmd8_Node_Ref *)&p->FreeList[i];
  279. while (count[i] != 0)
  280. {
  281. CPpmd8_Node *node = NODE(*next);
  282. while (node->Stamp == 0)
  283. {
  284. *next = node->Next;
  285. node = NODE(*next);
  286. p->Stamps[i]--;
  287. if (--count[i] == 0)
  288. break;
  289. }
  290. next = &node->Next;
  291. }
  292. }
  293. }
  294. #define SUCCESSOR(p) ((CPpmd_Void_Ref)((p)->SuccessorLow | ((UInt32)(p)->SuccessorHigh << 16)))
  295. static void SetSuccessor(CPpmd_State *p, CPpmd_Void_Ref v)
  296. {
  297. (p)->SuccessorLow = (UInt16)((UInt32)(v) & 0xFFFF);
  298. (p)->SuccessorHigh = (UInt16)(((UInt32)(v) >> 16) & 0xFFFF);
  299. }
  300. #define RESET_TEXT(offs) { p->Text = p->Base + p->AlignOffset + (offs); }
  301. static void RestartModel(CPpmd8 *p)
  302. {
  303. unsigned i, k, m, r;
  304. memset(p->FreeList, 0, sizeof(p->FreeList));
  305. memset(p->Stamps, 0, sizeof(p->Stamps));
  306. RESET_TEXT(0);
  307. p->HiUnit = p->Text + p->Size;
  308. p->LoUnit = p->UnitsStart = p->HiUnit - p->Size / 8 / UNIT_SIZE * 7 * UNIT_SIZE;
  309. p->GlueCount = 0;
  310. p->OrderFall = p->MaxOrder;
  311. p->RunLength = p->InitRL = -(Int32)((p->MaxOrder < 12) ? p->MaxOrder : 12) - 1;
  312. p->PrevSuccess = 0;
  313. p->MinContext = p->MaxContext = (CTX_PTR)(p->HiUnit -= UNIT_SIZE); /* AllocContext(p); */
  314. p->MinContext->Suffix = 0;
  315. p->MinContext->NumStats = 255;
  316. p->MinContext->Flags = 0;
  317. p->MinContext->SummFreq = 256 + 1;
  318. p->FoundState = (CPpmd_State *)p->LoUnit; /* AllocUnits(p, PPMD_NUM_INDEXES - 1); */
  319. p->LoUnit += U2B(256 / 2);
  320. p->MinContext->Stats = REF(p->FoundState);
  321. for (i = 0; i < 256; i++)
  322. {
  323. CPpmd_State *s = &p->FoundState[i];
  324. s->Symbol = (Byte)i;
  325. s->Freq = 1;
  326. SetSuccessor(s, 0);
  327. }
  328. for (i = m = 0; m < 25; m++)
  329. {
  330. while (p->NS2Indx[i] == m)
  331. i++;
  332. for (k = 0; k < 8; k++)
  333. {
  334. UInt16 val = (UInt16)(PPMD_BIN_SCALE - kInitBinEsc[k] / (i + 1));
  335. UInt16 *dest = p->BinSumm[m] + k;
  336. for (r = 0; r < 64; r += 8)
  337. dest[r] = val;
  338. }
  339. }
  340. for (i = m = 0; m < 24; m++)
  341. {
  342. while (p->NS2Indx[i + 3] == m + 3)
  343. i++;
  344. for (k = 0; k < 32; k++)
  345. {
  346. CPpmd_See *s = &p->See[m][k];
  347. s->Summ = (UInt16)((2 * i + 5) << (s->Shift = PPMD_PERIOD_BITS - 4));
  348. s->Count = 7;
  349. }
  350. }
  351. }
  352. void Ppmd8_Init(CPpmd8 *p, unsigned maxOrder, unsigned restoreMethod)
  353. {
  354. p->MaxOrder = maxOrder;
  355. p->RestoreMethod = restoreMethod;
  356. RestartModel(p);
  357. p->DummySee.Shift = PPMD_PERIOD_BITS;
  358. p->DummySee.Summ = 0; /* unused */
  359. p->DummySee.Count = 64; /* unused */
  360. }
  361. static void Refresh(CPpmd8 *p, CTX_PTR ctx, unsigned oldNU, unsigned scale)
  362. {
  363. unsigned i = ctx->NumStats, escFreq, sumFreq, flags;
  364. CPpmd_State *s = (CPpmd_State *)ShrinkUnits(p, STATS(ctx), oldNU, (i + 2) >> 1);
  365. ctx->Stats = REF(s);
  366. #ifdef PPMD8_FREEZE_SUPPORT
  367. /* fixed over Shkarin's code. Fixed code is not compatible with original code for some files in FREEZE mode. */
  368. scale |= (ctx->SummFreq >= ((UInt32)1 << 15));
  369. #endif
  370. flags = (ctx->Flags & (0x10 + 0x04 * scale)) + 0x08 * (s->Symbol >= 0x40);
  371. escFreq = ctx->SummFreq - s->Freq;
  372. sumFreq = (s->Freq = (Byte)((s->Freq + scale) >> scale));
  373. do
  374. {
  375. escFreq -= (++s)->Freq;
  376. sumFreq += (s->Freq = (Byte)((s->Freq + scale) >> scale));
  377. flags |= 0x08 * (s->Symbol >= 0x40);
  378. }
  379. while (--i);
  380. ctx->SummFreq = (UInt16)(sumFreq + ((escFreq + scale) >> scale));
  381. ctx->Flags = (Byte)flags;
  382. }
  383. static void SwapStates(CPpmd_State *t1, CPpmd_State *t2)
  384. {
  385. CPpmd_State tmp = *t1;
  386. *t1 = *t2;
  387. *t2 = tmp;
  388. }
  389. static CPpmd_Void_Ref CutOff(CPpmd8 *p, CTX_PTR ctx, unsigned order)
  390. {
  391. int i;
  392. unsigned tmp;
  393. CPpmd_State *s;
  394. if (!ctx->NumStats)
  395. {
  396. s = ONE_STATE(ctx);
  397. if ((Byte *)Ppmd8_GetPtr(p, SUCCESSOR(s)) >= p->UnitsStart)
  398. {
  399. if (order < p->MaxOrder)
  400. SetSuccessor(s, CutOff(p, CTX(SUCCESSOR(s)), order + 1));
  401. else
  402. SetSuccessor(s, 0);
  403. if (SUCCESSOR(s) || order <= 9) /* O_BOUND */
  404. return REF(ctx);
  405. }
  406. SpecialFreeUnit(p, ctx);
  407. return 0;
  408. }
  409. ctx->Stats = STATS_REF(MoveUnitsUp(p, STATS(ctx), tmp = ((unsigned)ctx->NumStats + 2) >> 1));
  410. for (s = STATS(ctx) + (i = ctx->NumStats); s >= STATS(ctx); s--)
  411. if ((Byte *)Ppmd8_GetPtr(p, SUCCESSOR(s)) < p->UnitsStart)
  412. {
  413. CPpmd_State *s2 = STATS(ctx) + (i--);
  414. SetSuccessor(s, 0);
  415. SwapStates(s, s2);
  416. }
  417. else if (order < p->MaxOrder)
  418. SetSuccessor(s, CutOff(p, CTX(SUCCESSOR(s)), order + 1));
  419. else
  420. SetSuccessor(s, 0);
  421. if (i != ctx->NumStats && order)
  422. {
  423. ctx->NumStats = (Byte)i;
  424. s = STATS(ctx);
  425. if (i < 0)
  426. {
  427. FreeUnits(p, s, tmp);
  428. SpecialFreeUnit(p, ctx);
  429. return 0;
  430. }
  431. if (i == 0)
  432. {
  433. ctx->Flags = (Byte)((ctx->Flags & 0x10) + 0x08 * (s->Symbol >= 0x40));
  434. *ONE_STATE(ctx) = *s;
  435. FreeUnits(p, s, tmp);
  436. /* 9.31: the code was fixed. It's was not BUG, if Freq <= MAX_FREQ = 124 */
  437. ONE_STATE(ctx)->Freq = (Byte)(((unsigned)ONE_STATE(ctx)->Freq + 11) >> 3);
  438. }
  439. else
  440. Refresh(p, ctx, tmp, ctx->SummFreq > 16 * i);
  441. }
  442. return REF(ctx);
  443. }
  444. #ifdef PPMD8_FREEZE_SUPPORT
  445. static CPpmd_Void_Ref RemoveBinContexts(CPpmd8 *p, CTX_PTR ctx, unsigned order)
  446. {
  447. CPpmd_State *s;
  448. if (!ctx->NumStats)
  449. {
  450. s = ONE_STATE(ctx);
  451. if ((Byte *)Ppmd8_GetPtr(p, SUCCESSOR(s)) >= p->UnitsStart && order < p->MaxOrder)
  452. SetSuccessor(s, RemoveBinContexts(p, CTX(SUCCESSOR(s)), order + 1));
  453. else
  454. SetSuccessor(s, 0);
  455. /* Suffix context can be removed already, since different (high-order)
  456. Successors may refer to same context. So we check Flags == 0xFF (Stamp == EMPTY_NODE) */
  457. if (!SUCCESSOR(s) && (!SUFFIX(ctx)->NumStats || SUFFIX(ctx)->Flags == 0xFF))
  458. {
  459. FreeUnits(p, ctx, 1);
  460. return 0;
  461. }
  462. else
  463. return REF(ctx);
  464. }
  465. for (s = STATS(ctx) + ctx->NumStats; s >= STATS(ctx); s--)
  466. if ((Byte *)Ppmd8_GetPtr(p, SUCCESSOR(s)) >= p->UnitsStart && order < p->MaxOrder)
  467. SetSuccessor(s, RemoveBinContexts(p, CTX(SUCCESSOR(s)), order + 1));
  468. else
  469. SetSuccessor(s, 0);
  470. return REF(ctx);
  471. }
  472. #endif
  473. static UInt32 GetUsedMemory(const CPpmd8 *p)
  474. {
  475. UInt32 v = 0;
  476. unsigned i;
  477. for (i = 0; i < PPMD_NUM_INDEXES; i++)
  478. v += p->Stamps[i] * I2U(i);
  479. return p->Size - (UInt32)(p->HiUnit - p->LoUnit) - (UInt32)(p->UnitsStart - p->Text) - U2B(v);
  480. }
  481. #ifdef PPMD8_FREEZE_SUPPORT
  482. #define RESTORE_MODEL(c1, fSuccessor) RestoreModel(p, c1, fSuccessor)
  483. #else
  484. #define RESTORE_MODEL(c1, fSuccessor) RestoreModel(p, c1)
  485. #endif
  486. static void RestoreModel(CPpmd8 *p, CTX_PTR c1
  487. #ifdef PPMD8_FREEZE_SUPPORT
  488. , CTX_PTR fSuccessor
  489. #endif
  490. )
  491. {
  492. CTX_PTR c;
  493. CPpmd_State *s;
  494. RESET_TEXT(0);
  495. for (c = p->MaxContext; c != c1; c = SUFFIX(c))
  496. if (--(c->NumStats) == 0)
  497. {
  498. s = STATS(c);
  499. c->Flags = (Byte)((c->Flags & 0x10) + 0x08 * (s->Symbol >= 0x40));
  500. *ONE_STATE(c) = *s;
  501. SpecialFreeUnit(p, s);
  502. ONE_STATE(c)->Freq = (Byte)(((unsigned)ONE_STATE(c)->Freq + 11) >> 3);
  503. }
  504. else
  505. Refresh(p, c, (c->NumStats+3) >> 1, 0);
  506. for (; c != p->MinContext; c = SUFFIX(c))
  507. if (!c->NumStats)
  508. ONE_STATE(c)->Freq = (Byte)(ONE_STATE(c)->Freq - (ONE_STATE(c)->Freq >> 1));
  509. else if ((c->SummFreq += 4) > 128 + 4 * c->NumStats)
  510. Refresh(p, c, (c->NumStats + 2) >> 1, 1);
  511. #ifdef PPMD8_FREEZE_SUPPORT
  512. if (p->RestoreMethod > PPMD8_RESTORE_METHOD_FREEZE)
  513. {
  514. p->MaxContext = fSuccessor;
  515. p->GlueCount += !(p->Stamps[1] & 1);
  516. }
  517. else if (p->RestoreMethod == PPMD8_RESTORE_METHOD_FREEZE)
  518. {
  519. while (p->MaxContext->Suffix)
  520. p->MaxContext = SUFFIX(p->MaxContext);
  521. RemoveBinContexts(p, p->MaxContext, 0);
  522. p->RestoreMethod++;
  523. p->GlueCount = 0;
  524. p->OrderFall = p->MaxOrder;
  525. }
  526. else
  527. #endif
  528. if (p->RestoreMethod == PPMD8_RESTORE_METHOD_RESTART || GetUsedMemory(p) < (p->Size >> 1))
  529. RestartModel(p);
  530. else
  531. {
  532. while (p->MaxContext->Suffix)
  533. p->MaxContext = SUFFIX(p->MaxContext);
  534. do
  535. {
  536. CutOff(p, p->MaxContext, 0);
  537. ExpandTextArea(p);
  538. }
  539. while (GetUsedMemory(p) > 3 * (p->Size >> 2));
  540. p->GlueCount = 0;
  541. p->OrderFall = p->MaxOrder;
  542. }
  543. }
  544. static CTX_PTR CreateSuccessors(CPpmd8 *p, Bool skip, CPpmd_State *s1, CTX_PTR c)
  545. {
  546. CPpmd_State upState;
  547. Byte flags;
  548. CPpmd_Byte_Ref upBranch = (CPpmd_Byte_Ref)SUCCESSOR(p->FoundState);
  549. /* fixed over Shkarin's code. Maybe it could work without + 1 too. */
  550. CPpmd_State *ps[PPMD8_MAX_ORDER + 1];
  551. unsigned numPs = 0;
  552. if (!skip)
  553. ps[numPs++] = p->FoundState;
  554. while (c->Suffix)
  555. {
  556. CPpmd_Void_Ref successor;
  557. CPpmd_State *s;
  558. c = SUFFIX(c);
  559. if (s1)
  560. {
  561. s = s1;
  562. s1 = NULL;
  563. }
  564. else if (c->NumStats != 0)
  565. {
  566. for (s = STATS(c); s->Symbol != p->FoundState->Symbol; s++);
  567. if (s->Freq < MAX_FREQ - 9)
  568. {
  569. s->Freq++;
  570. c->SummFreq++;
  571. }
  572. }
  573. else
  574. {
  575. s = ONE_STATE(c);
  576. s->Freq = (Byte)(s->Freq + (!SUFFIX(c)->NumStats & (s->Freq < 24)));
  577. }
  578. successor = SUCCESSOR(s);
  579. if (successor != upBranch)
  580. {
  581. c = CTX(successor);
  582. if (numPs == 0)
  583. return c;
  584. break;
  585. }
  586. ps[numPs++] = s;
  587. }
  588. upState.Symbol = *(const Byte *)Ppmd8_GetPtr(p, upBranch);
  589. SetSuccessor(&upState, upBranch + 1);
  590. flags = (Byte)(0x10 * (p->FoundState->Symbol >= 0x40) + 0x08 * (upState.Symbol >= 0x40));
  591. if (c->NumStats == 0)
  592. upState.Freq = ONE_STATE(c)->Freq;
  593. else
  594. {
  595. UInt32 cf, s0;
  596. CPpmd_State *s;
  597. for (s = STATS(c); s->Symbol != upState.Symbol; s++);
  598. cf = s->Freq - 1;
  599. s0 = c->SummFreq - c->NumStats - cf;
  600. upState.Freq = (Byte)(1 + ((2 * cf <= s0) ? (5 * cf > s0) : ((cf + 2 * s0 - 3) / s0)));
  601. }
  602. do
  603. {
  604. /* Create Child */
  605. CTX_PTR c1; /* = AllocContext(p); */
  606. if (p->HiUnit != p->LoUnit)
  607. c1 = (CTX_PTR)(p->HiUnit -= UNIT_SIZE);
  608. else if (p->FreeList[0] != 0)
  609. c1 = (CTX_PTR)RemoveNode(p, 0);
  610. else
  611. {
  612. c1 = (CTX_PTR)AllocUnitsRare(p, 0);
  613. if (!c1)
  614. return NULL;
  615. }
  616. c1->NumStats = 0;
  617. c1->Flags = flags;
  618. *ONE_STATE(c1) = upState;
  619. c1->Suffix = REF(c);
  620. SetSuccessor(ps[--numPs], REF(c1));
  621. c = c1;
  622. }
  623. while (numPs != 0);
  624. return c;
  625. }
  626. static CTX_PTR ReduceOrder(CPpmd8 *p, CPpmd_State *s1, CTX_PTR c)
  627. {
  628. CPpmd_State *s = NULL;
  629. CTX_PTR c1 = c;
  630. CPpmd_Void_Ref upBranch = REF(p->Text);
  631. #ifdef PPMD8_FREEZE_SUPPORT
  632. /* The BUG in Shkarin's code was fixed: ps could overflow in CUT_OFF mode. */
  633. CPpmd_State *ps[PPMD8_MAX_ORDER + 1];
  634. unsigned numPs = 0;
  635. ps[numPs++] = p->FoundState;
  636. #endif
  637. SetSuccessor(p->FoundState, upBranch);
  638. p->OrderFall++;
  639. for (;;)
  640. {
  641. if (s1)
  642. {
  643. c = SUFFIX(c);
  644. s = s1;
  645. s1 = NULL;
  646. }
  647. else
  648. {
  649. if (!c->Suffix)
  650. {
  651. #ifdef PPMD8_FREEZE_SUPPORT
  652. if (p->RestoreMethod > PPMD8_RESTORE_METHOD_FREEZE)
  653. {
  654. do { SetSuccessor(ps[--numPs], REF(c)); } while (numPs);
  655. RESET_TEXT(1);
  656. p->OrderFall = 1;
  657. }
  658. #endif
  659. return c;
  660. }
  661. c = SUFFIX(c);
  662. if (c->NumStats)
  663. {
  664. if ((s = STATS(c))->Symbol != p->FoundState->Symbol)
  665. do { s++; } while (s->Symbol != p->FoundState->Symbol);
  666. if (s->Freq < MAX_FREQ - 9)
  667. {
  668. s->Freq += 2;
  669. c->SummFreq += 2;
  670. }
  671. }
  672. else
  673. {
  674. s = ONE_STATE(c);
  675. s->Freq = (Byte)(s->Freq + (s->Freq < 32));
  676. }
  677. }
  678. if (SUCCESSOR(s))
  679. break;
  680. #ifdef PPMD8_FREEZE_SUPPORT
  681. ps[numPs++] = s;
  682. #endif
  683. SetSuccessor(s, upBranch);
  684. p->OrderFall++;
  685. }
  686. #ifdef PPMD8_FREEZE_SUPPORT
  687. if (p->RestoreMethod > PPMD8_RESTORE_METHOD_FREEZE)
  688. {
  689. c = CTX(SUCCESSOR(s));
  690. do { SetSuccessor(ps[--numPs], REF(c)); } while (numPs);
  691. RESET_TEXT(1);
  692. p->OrderFall = 1;
  693. return c;
  694. }
  695. else
  696. #endif
  697. if (SUCCESSOR(s) <= upBranch)
  698. {
  699. CTX_PTR successor;
  700. CPpmd_State *s2 = p->FoundState;
  701. p->FoundState = s;
  702. successor = CreateSuccessors(p, False, NULL, c);
  703. if (successor == NULL)
  704. SetSuccessor(s, 0);
  705. else
  706. SetSuccessor(s, REF(successor));
  707. p->FoundState = s2;
  708. }
  709. if (p->OrderFall == 1 && c1 == p->MaxContext)
  710. {
  711. SetSuccessor(p->FoundState, SUCCESSOR(s));
  712. p->Text--;
  713. }
  714. if (SUCCESSOR(s) == 0)
  715. return NULL;
  716. return CTX(SUCCESSOR(s));
  717. }
  718. static void UpdateModel(CPpmd8 *p)
  719. {
  720. CPpmd_Void_Ref successor, fSuccessor = SUCCESSOR(p->FoundState);
  721. CTX_PTR c;
  722. unsigned s0, ns, fFreq = p->FoundState->Freq;
  723. Byte flag, fSymbol = p->FoundState->Symbol;
  724. CPpmd_State *s = NULL;
  725. if (p->FoundState->Freq < MAX_FREQ / 4 && p->MinContext->Suffix != 0)
  726. {
  727. c = SUFFIX(p->MinContext);
  728. if (c->NumStats == 0)
  729. {
  730. s = ONE_STATE(c);
  731. if (s->Freq < 32)
  732. s->Freq++;
  733. }
  734. else
  735. {
  736. s = STATS(c);
  737. if (s->Symbol != p->FoundState->Symbol)
  738. {
  739. do { s++; } while (s->Symbol != p->FoundState->Symbol);
  740. if (s[0].Freq >= s[-1].Freq)
  741. {
  742. SwapStates(&s[0], &s[-1]);
  743. s--;
  744. }
  745. }
  746. if (s->Freq < MAX_FREQ - 9)
  747. {
  748. s->Freq += 2;
  749. c->SummFreq += 2;
  750. }
  751. }
  752. }
  753. c = p->MaxContext;
  754. if (p->OrderFall == 0 && fSuccessor)
  755. {
  756. CTX_PTR cs = CreateSuccessors(p, True, s, p->MinContext);
  757. if (cs == 0)
  758. {
  759. SetSuccessor(p->FoundState, 0);
  760. RESTORE_MODEL(c, CTX(fSuccessor));
  761. }
  762. else
  763. {
  764. SetSuccessor(p->FoundState, REF(cs));
  765. p->MaxContext = cs;
  766. }
  767. return;
  768. }
  769. *p->Text++ = p->FoundState->Symbol;
  770. successor = REF(p->Text);
  771. if (p->Text >= p->UnitsStart)
  772. {
  773. RESTORE_MODEL(c, CTX(fSuccessor)); /* check it */
  774. return;
  775. }
  776. if (!fSuccessor)
  777. {
  778. CTX_PTR cs = ReduceOrder(p, s, p->MinContext);
  779. if (cs == NULL)
  780. {
  781. RESTORE_MODEL(c, 0);
  782. return;
  783. }
  784. fSuccessor = REF(cs);
  785. }
  786. else if ((Byte *)Ppmd8_GetPtr(p, fSuccessor) < p->UnitsStart)
  787. {
  788. CTX_PTR cs = CreateSuccessors(p, False, s, p->MinContext);
  789. if (cs == NULL)
  790. {
  791. RESTORE_MODEL(c, 0);
  792. return;
  793. }
  794. fSuccessor = REF(cs);
  795. }
  796. if (--p->OrderFall == 0)
  797. {
  798. successor = fSuccessor;
  799. p->Text -= (p->MaxContext != p->MinContext);
  800. }
  801. #ifdef PPMD8_FREEZE_SUPPORT
  802. else if (p->RestoreMethod > PPMD8_RESTORE_METHOD_FREEZE)
  803. {
  804. successor = fSuccessor;
  805. RESET_TEXT(0);
  806. p->OrderFall = 0;
  807. }
  808. #endif
  809. s0 = p->MinContext->SummFreq - (ns = p->MinContext->NumStats) - fFreq;
  810. flag = (Byte)(0x08 * (fSymbol >= 0x40));
  811. for (; c != p->MinContext; c = SUFFIX(c))
  812. {
  813. unsigned ns1;
  814. UInt32 cf, sf;
  815. if ((ns1 = c->NumStats) != 0)
  816. {
  817. if ((ns1 & 1) != 0)
  818. {
  819. /* Expand for one UNIT */
  820. unsigned oldNU = (ns1 + 1) >> 1;
  821. unsigned i = U2I(oldNU);
  822. if (i != U2I(oldNU + 1))
  823. {
  824. void *ptr = AllocUnits(p, i + 1);
  825. void *oldPtr;
  826. if (!ptr)
  827. {
  828. RESTORE_MODEL(c, CTX(fSuccessor));
  829. return;
  830. }
  831. oldPtr = STATS(c);
  832. MyMem12Cpy(ptr, oldPtr, oldNU);
  833. InsertNode(p, oldPtr, i);
  834. c->Stats = STATS_REF(ptr);
  835. }
  836. }
  837. c->SummFreq = (UInt16)(c->SummFreq + (3 * ns1 + 1 < ns));
  838. }
  839. else
  840. {
  841. CPpmd_State *s2 = (CPpmd_State*)AllocUnits(p, 0);
  842. if (!s2)
  843. {
  844. RESTORE_MODEL(c, CTX(fSuccessor));
  845. return;
  846. }
  847. *s2 = *ONE_STATE(c);
  848. c->Stats = REF(s2);
  849. if (s2->Freq < MAX_FREQ / 4 - 1)
  850. s2->Freq <<= 1;
  851. else
  852. s2->Freq = MAX_FREQ - 4;
  853. c->SummFreq = (UInt16)(s2->Freq + p->InitEsc + (ns > 2));
  854. }
  855. cf = 2 * fFreq * (c->SummFreq + 6);
  856. sf = (UInt32)s0 + c->SummFreq;
  857. if (cf < 6 * sf)
  858. {
  859. cf = 1 + (cf > sf) + (cf >= 4 * sf);
  860. c->SummFreq += 4;
  861. }
  862. else
  863. {
  864. cf = 4 + (cf > 9 * sf) + (cf > 12 * sf) + (cf > 15 * sf);
  865. c->SummFreq = (UInt16)(c->SummFreq + cf);
  866. }
  867. {
  868. CPpmd_State *s2 = STATS(c) + ns1 + 1;
  869. SetSuccessor(s2, successor);
  870. s2->Symbol = fSymbol;
  871. s2->Freq = (Byte)cf;
  872. c->Flags |= flag;
  873. c->NumStats = (Byte)(ns1 + 1);
  874. }
  875. }
  876. p->MaxContext = p->MinContext = CTX(fSuccessor);
  877. }
  878. static void Rescale(CPpmd8 *p)
  879. {
  880. unsigned i, adder, sumFreq, escFreq;
  881. CPpmd_State *stats = STATS(p->MinContext);
  882. CPpmd_State *s = p->FoundState;
  883. {
  884. CPpmd_State tmp = *s;
  885. for (; s != stats; s--)
  886. s[0] = s[-1];
  887. *s = tmp;
  888. }
  889. escFreq = p->MinContext->SummFreq - s->Freq;
  890. s->Freq += 4;
  891. adder = (p->OrderFall != 0
  892. #ifdef PPMD8_FREEZE_SUPPORT
  893. || p->RestoreMethod > PPMD8_RESTORE_METHOD_FREEZE
  894. #endif
  895. );
  896. s->Freq = (Byte)((s->Freq + adder) >> 1);
  897. sumFreq = s->Freq;
  898. i = p->MinContext->NumStats;
  899. do
  900. {
  901. escFreq -= (++s)->Freq;
  902. s->Freq = (Byte)((s->Freq + adder) >> 1);
  903. sumFreq += s->Freq;
  904. if (s[0].Freq > s[-1].Freq)
  905. {
  906. CPpmd_State *s1 = s;
  907. CPpmd_State tmp = *s1;
  908. do
  909. s1[0] = s1[-1];
  910. while (--s1 != stats && tmp.Freq > s1[-1].Freq);
  911. *s1 = tmp;
  912. }
  913. }
  914. while (--i);
  915. if (s->Freq == 0)
  916. {
  917. unsigned numStats = p->MinContext->NumStats;
  918. unsigned n0, n1;
  919. do { i++; } while ((--s)->Freq == 0);
  920. escFreq += i;
  921. p->MinContext->NumStats = (Byte)(p->MinContext->NumStats - i);
  922. if (p->MinContext->NumStats == 0)
  923. {
  924. CPpmd_State tmp = *stats;
  925. tmp.Freq = (Byte)((2 * tmp.Freq + escFreq - 1) / escFreq);
  926. if (tmp.Freq > MAX_FREQ / 3)
  927. tmp.Freq = MAX_FREQ / 3;
  928. InsertNode(p, stats, U2I((numStats + 2) >> 1));
  929. p->MinContext->Flags = (Byte)((p->MinContext->Flags & 0x10) + 0x08 * (tmp.Symbol >= 0x40));
  930. *(p->FoundState = ONE_STATE(p->MinContext)) = tmp;
  931. return;
  932. }
  933. n0 = (numStats + 2) >> 1;
  934. n1 = (p->MinContext->NumStats + 2) >> 1;
  935. if (n0 != n1)
  936. p->MinContext->Stats = STATS_REF(ShrinkUnits(p, stats, n0, n1));
  937. p->MinContext->Flags &= ~0x08;
  938. p->MinContext->Flags |= 0x08 * ((s = STATS(p->MinContext))->Symbol >= 0x40);
  939. i = p->MinContext->NumStats;
  940. do { p->MinContext->Flags |= 0x08*((++s)->Symbol >= 0x40); } while (--i);
  941. }
  942. p->MinContext->SummFreq = (UInt16)(sumFreq + escFreq - (escFreq >> 1));
  943. p->MinContext->Flags |= 0x4;
  944. p->FoundState = STATS(p->MinContext);
  945. }
  946. CPpmd_See *Ppmd8_MakeEscFreq(CPpmd8 *p, unsigned numMasked1, UInt32 *escFreq)
  947. {
  948. CPpmd_See *see;
  949. if (p->MinContext->NumStats != 0xFF)
  950. {
  951. see = p->See[(unsigned)p->NS2Indx[(unsigned)p->MinContext->NumStats + 2] - 3] +
  952. (p->MinContext->SummFreq > 11 * ((unsigned)p->MinContext->NumStats + 1)) +
  953. 2 * (unsigned)(2 * (unsigned)p->MinContext->NumStats <
  954. ((unsigned)SUFFIX(p->MinContext)->NumStats + numMasked1)) +
  955. p->MinContext->Flags;
  956. {
  957. unsigned r = (see->Summ >> see->Shift);
  958. see->Summ = (UInt16)(see->Summ - r);
  959. *escFreq = r + (r == 0);
  960. }
  961. }
  962. else
  963. {
  964. see = &p->DummySee;
  965. *escFreq = 1;
  966. }
  967. return see;
  968. }
  969. static void NextContext(CPpmd8 *p)
  970. {
  971. CTX_PTR c = CTX(SUCCESSOR(p->FoundState));
  972. if (p->OrderFall == 0 && (Byte *)c >= p->UnitsStart)
  973. p->MinContext = p->MaxContext = c;
  974. else
  975. {
  976. UpdateModel(p);
  977. p->MinContext = p->MaxContext;
  978. }
  979. }
  980. void Ppmd8_Update1(CPpmd8 *p)
  981. {
  982. CPpmd_State *s = p->FoundState;
  983. s->Freq += 4;
  984. p->MinContext->SummFreq += 4;
  985. if (s[0].Freq > s[-1].Freq)
  986. {
  987. SwapStates(&s[0], &s[-1]);
  988. p->FoundState = --s;
  989. if (s->Freq > MAX_FREQ)
  990. Rescale(p);
  991. }
  992. NextContext(p);
  993. }
  994. void Ppmd8_Update1_0(CPpmd8 *p)
  995. {
  996. p->PrevSuccess = (2 * p->FoundState->Freq >= p->MinContext->SummFreq);
  997. p->RunLength += p->PrevSuccess;
  998. p->MinContext->SummFreq += 4;
  999. if ((p->FoundState->Freq += 4) > MAX_FREQ)
  1000. Rescale(p);
  1001. NextContext(p);
  1002. }
  1003. void Ppmd8_UpdateBin(CPpmd8 *p)
  1004. {
  1005. p->FoundState->Freq = (Byte)(p->FoundState->Freq + (p->FoundState->Freq < 196));
  1006. p->PrevSuccess = 1;
  1007. p->RunLength++;
  1008. NextContext(p);
  1009. }
  1010. void Ppmd8_Update2(CPpmd8 *p)
  1011. {
  1012. p->MinContext->SummFreq += 4;
  1013. if ((p->FoundState->Freq += 4) > MAX_FREQ)
  1014. Rescale(p);
  1015. p->RunLength = p->InitRL;
  1016. UpdateModel(p);
  1017. p->MinContext = p->MaxContext;
  1018. }
  1019. /* Ppmd8Dec.c -- PPMdI Decoder
  1020. 2010-04-16 : Igor Pavlov : Public domain
  1021. This code is based on:
  1022. PPMd var.I (2002): Dmitry Shkarin : Public domain
  1023. Carryless rangecoder (1999): Dmitry Subbotin : Public domain */
  1024. Bool Ppmd8_RangeDec_Init(CPpmd8 *p)
  1025. {
  1026. unsigned i;
  1027. p->Low = 0;
  1028. p->Range = 0xFFFFFFFF;
  1029. p->Code = 0;
  1030. for (i = 0; i < 4; i++)
  1031. p->Code = (p->Code << 8) | p->Stream.In->Read(p->Stream.In);
  1032. return (p->Code < 0xFFFFFFFF);
  1033. }
  1034. static UInt32 RangeDec_GetThreshold(CPpmd8 *p, UInt32 total)
  1035. {
  1036. return p->Code / (p->Range /= total);
  1037. }
  1038. static void RangeDec_Decode(CPpmd8 *p, UInt32 start, UInt32 size)
  1039. {
  1040. start *= p->Range;
  1041. p->Low += start;
  1042. p->Code -= start;
  1043. p->Range *= size;
  1044. while ((p->Low ^ (p->Low + p->Range)) < kTop ||
  1045. (p->Range < kBot && ((p->Range = (0 - p->Low) & (kBot - 1)), 1)))
  1046. {
  1047. p->Code = (p->Code << 8) | p->Stream.In->Read(p->Stream.In);
  1048. p->Range <<= 8;
  1049. p->Low <<= 8;
  1050. }
  1051. }
  1052. #define MASK(sym) ((signed char *)charMask)[sym]
  1053. int Ppmd8_DecodeSymbol(CPpmd8 *p)
  1054. {
  1055. size_t charMask[256 / sizeof(size_t)];
  1056. if (p->MinContext->NumStats != 0)
  1057. {
  1058. CPpmd_State *s = Ppmd8_GetStats(p, p->MinContext);
  1059. unsigned i;
  1060. UInt32 count, hiCnt;
  1061. if ((count = RangeDec_GetThreshold(p, p->MinContext->SummFreq)) < (hiCnt = s->Freq))
  1062. {
  1063. Byte symbol;
  1064. RangeDec_Decode(p, 0, s->Freq);
  1065. p->FoundState = s;
  1066. symbol = s->Symbol;
  1067. Ppmd8_Update1_0(p);
  1068. return symbol;
  1069. }
  1070. p->PrevSuccess = 0;
  1071. i = p->MinContext->NumStats;
  1072. do
  1073. {
  1074. if ((hiCnt += (++s)->Freq) > count)
  1075. {
  1076. Byte symbol;
  1077. RangeDec_Decode(p, hiCnt - s->Freq, s->Freq);
  1078. p->FoundState = s;
  1079. symbol = s->Symbol;
  1080. Ppmd8_Update1(p);
  1081. return symbol;
  1082. }
  1083. }
  1084. while (--i);
  1085. if (count >= p->MinContext->SummFreq)
  1086. return -2;
  1087. RangeDec_Decode(p, hiCnt, p->MinContext->SummFreq - hiCnt);
  1088. PPMD_SetAllBitsIn256Bytes(charMask);
  1089. MASK(s->Symbol) = 0;
  1090. i = p->MinContext->NumStats;
  1091. do { MASK((--s)->Symbol) = 0; } while (--i);
  1092. }
  1093. else
  1094. {
  1095. UInt16 *prob = Ppmd8_GetBinSumm(p);
  1096. if (((p->Code / (p->Range >>= 14)) < *prob))
  1097. {
  1098. Byte symbol;
  1099. RangeDec_Decode(p, 0, *prob);
  1100. *prob = (UInt16)PPMD_UPDATE_PROB_0(*prob);
  1101. symbol = (p->FoundState = Ppmd8Context_OneState(p->MinContext))->Symbol;
  1102. Ppmd8_UpdateBin(p);
  1103. return symbol;
  1104. }
  1105. RangeDec_Decode(p, *prob, (1 << 14) - *prob);
  1106. *prob = (UInt16)PPMD_UPDATE_PROB_1(*prob);
  1107. p->InitEsc = PPMD8_kExpEscape[*prob >> 10];
  1108. PPMD_SetAllBitsIn256Bytes(charMask);
  1109. MASK(Ppmd8Context_OneState(p->MinContext)->Symbol) = 0;
  1110. p->PrevSuccess = 0;
  1111. }
  1112. for (;;)
  1113. {
  1114. CPpmd_State *ps[256], *s;
  1115. UInt32 freqSum, count, hiCnt;
  1116. CPpmd_See *see;
  1117. unsigned i, num, numMasked = p->MinContext->NumStats;
  1118. do
  1119. {
  1120. p->OrderFall++;
  1121. if (!p->MinContext->Suffix)
  1122. return -1;
  1123. p->MinContext = Ppmd8_GetContext(p, p->MinContext->Suffix);
  1124. }
  1125. while (p->MinContext->NumStats == numMasked);
  1126. hiCnt = 0;
  1127. s = Ppmd8_GetStats(p, p->MinContext);
  1128. i = 0;
  1129. num = p->MinContext->NumStats - numMasked;
  1130. do
  1131. {
  1132. int k = (int)(MASK(s->Symbol));
  1133. hiCnt += (s->Freq & k);
  1134. ps[i] = s++;
  1135. i -= k;
  1136. }
  1137. while (i != num);
  1138. see = Ppmd8_MakeEscFreq(p, numMasked, &freqSum);
  1139. freqSum += hiCnt;
  1140. count = RangeDec_GetThreshold(p, freqSum);
  1141. if (count < hiCnt)
  1142. {
  1143. Byte symbol;
  1144. CPpmd_State **pps = ps;
  1145. for (hiCnt = 0; (hiCnt += (*pps)->Freq) <= count; pps++);
  1146. s = *pps;
  1147. RangeDec_Decode(p, hiCnt - s->Freq, s->Freq);
  1148. Ppmd_See_Update(see);
  1149. p->FoundState = s;
  1150. symbol = s->Symbol;
  1151. Ppmd8_Update2(p);
  1152. return symbol;
  1153. }
  1154. if (count >= freqSum)
  1155. return -2;
  1156. RangeDec_Decode(p, hiCnt, freqSum - hiCnt);
  1157. see->Summ = (UInt16)(see->Summ + freqSum);
  1158. do { MASK(ps[--i]->Symbol) = 0; } while (i != 0);
  1159. }
  1160. }
  1161. /* H->I changes:
  1162. NS2Indx
  1163. GlewCount, and Glue method
  1164. BinSum
  1165. See / EscFreq
  1166. CreateSuccessors updates more suffix contexts
  1167. UpdateModel consts.
  1168. PrevSuccess Update
  1169. */
  1170. const IPpmd8 __archive_ppmd8_functions =
  1171. {
  1172. &Ppmd8_Construct,
  1173. &Ppmd8_Alloc,
  1174. &Ppmd8_Free,
  1175. &Ppmd8_Init,
  1176. &Ppmd8_RangeDec_Init,
  1177. &Ppmd8_DecodeSymbol,
  1178. };