lzham_lzcomp_state.cpp 49 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413
  1. // File: lzham_lzcomp_state.cpp
  2. // See Copyright Notice and license at the end of include/lzham.h
  3. #include "lzham_core.h"
  4. #include "lzham_lzcomp_internal.h"
  5. namespace lzham
  6. {
  7. static uint get_huge_match_code_len(uint len)
  8. {
  9. LZHAM_ASSERT((len > CLZBase::cMaxMatchLen) && (len <= CLZBase::cMaxHugeMatchLen));
  10. len -= (CLZBase::cMaxMatchLen + 1);
  11. if (len < 256)
  12. return 1 + 8;
  13. else if (len < (256 + 1024))
  14. return 2 + 10;
  15. else if (len < (256 + 1024 + 4096))
  16. return 3 + 12;
  17. else
  18. return 3 + 16;
  19. }
  20. static uint get_huge_match_code_bits(uint len)
  21. {
  22. LZHAM_ASSERT((len > CLZBase::cMaxMatchLen) && (len <= CLZBase::cMaxHugeMatchLen));
  23. len -= (CLZBase::cMaxMatchLen + 1);
  24. uint c;
  25. if (len < 256)
  26. c = len;
  27. else if (len < (256 + 1024))
  28. {
  29. uint r = (len - 256);
  30. LZHAM_ASSERT(r <= 1023);
  31. c = r | (2 << 10);
  32. }
  33. else if (len < (256 + 1024 + 4096))
  34. {
  35. uint r = (len - (256 + 1024));
  36. LZHAM_ASSERT(r <= 4095);
  37. c = r | (6 << 12);
  38. }
  39. else
  40. {
  41. uint r = (len - (256 + 1024 + 4096));
  42. LZHAM_ASSERT(r <= 65535);
  43. c = r | (7 << 16);
  44. }
  45. return c;
  46. }
  47. uint lzcompressor::lzdecision::get_match_dist(const state& cur_state) const
  48. {
  49. if (!is_match())
  50. return 0;
  51. else if (is_rep())
  52. {
  53. int index = -m_dist - 1;
  54. LZHAM_ASSERT(index < CLZBase::cMatchHistSize);
  55. return cur_state.m_match_hist[index];
  56. }
  57. else
  58. return m_dist;
  59. }
  60. lzcompressor::state::state()
  61. {
  62. m_cur_ofs = 0;
  63. m_cur_state = 0;
  64. m_block_start_dict_ofs = 0;
  65. m_match_hist[0] = 1;
  66. m_match_hist[1] = 1;
  67. m_match_hist[2] = 1;
  68. m_match_hist[3] = 1;
  69. }
  70. void lzcompressor::state::clear()
  71. {
  72. m_cur_ofs = 0;
  73. m_cur_state = 0;
  74. m_block_start_dict_ofs = 0;
  75. for (uint i = 0; i < 2; i++)
  76. {
  77. m_rep_len_table[i].clear();
  78. m_large_len_table[i].clear();
  79. }
  80. m_main_table.clear();
  81. m_dist_lsb_table.clear();
  82. m_lit_table.clear();
  83. m_delta_lit_table.clear();
  84. m_match_hist[0] = 1;
  85. m_match_hist[1] = 1;
  86. m_match_hist[2] = 1;
  87. m_match_hist[3] = 1;
  88. }
  89. void lzcompressor::state::reset()
  90. {
  91. m_cur_ofs = 0;
  92. m_cur_state = 0;
  93. m_block_start_dict_ofs = 0;
  94. for (uint i = 0; i < LZHAM_ARRAY_SIZE(m_is_match_model); i++)
  95. m_is_match_model[i].clear();
  96. for (uint i = 0; i < LZHAM_ARRAY_SIZE(m_is_rep_model); i++)
  97. m_is_rep_model[i].clear();
  98. for (uint i = 0; i < LZHAM_ARRAY_SIZE(m_is_rep0_model); i++)
  99. m_is_rep0_model[i].clear();
  100. for (uint i = 0; i < LZHAM_ARRAY_SIZE(m_is_rep0_single_byte_model); i++)
  101. m_is_rep0_single_byte_model[i].clear();
  102. for (uint i = 0; i < LZHAM_ARRAY_SIZE(m_is_rep1_model); i++)
  103. m_is_rep1_model[i].clear();
  104. for (uint i = 0; i < LZHAM_ARRAY_SIZE(m_is_rep2_model); i++)
  105. m_is_rep2_model[i].clear();
  106. for (uint i = 0; i < 2; i++)
  107. {
  108. m_rep_len_table[i].reset();
  109. m_large_len_table[i].reset();
  110. }
  111. m_main_table.reset();
  112. m_dist_lsb_table.reset();
  113. m_lit_table.reset();
  114. m_delta_lit_table.reset();
  115. m_match_hist[0] = 1;
  116. m_match_hist[1] = 1;
  117. m_match_hist[2] = 1;
  118. m_match_hist[3] = 1;
  119. }
  120. bool lzcompressor::state::init(CLZBase& lzbase, uint table_max_update_interval, uint table_update_interval_slow_rate)
  121. {
  122. m_cur_ofs = 0;
  123. m_cur_state = 0;
  124. if (!m_rep_len_table[0].init2(true, CLZBase::cNumHugeMatchCodes + (CLZBase::cMaxMatchLen - CLZBase::cMinMatchLen + 1), table_max_update_interval, table_update_interval_slow_rate, NULL))
  125. return false;
  126. if (!m_rep_len_table[1].assign(m_rep_len_table[0]))
  127. return false;
  128. if (!m_large_len_table[0].init2(true, CLZBase::cNumHugeMatchCodes + CLZBase::cLZXNumSecondaryLengths, table_max_update_interval, table_update_interval_slow_rate, NULL))
  129. return false;
  130. if (!m_large_len_table[1].assign(m_large_len_table[0]))
  131. return false;
  132. if (!m_main_table.init2(true, CLZBase::cLZXNumSpecialLengths + (lzbase.m_num_lzx_slots - CLZBase::cLZXLowestUsableMatchSlot) * 8, table_max_update_interval, table_update_interval_slow_rate, NULL))
  133. return false;
  134. if (!m_dist_lsb_table.init2(true, 16, table_max_update_interval, table_update_interval_slow_rate, NULL))
  135. return false;
  136. if (!m_lit_table.init2(true, 256, table_max_update_interval, table_update_interval_slow_rate, NULL))
  137. return false;
  138. if (!m_delta_lit_table.init2(true, 256, table_max_update_interval, table_update_interval_slow_rate, NULL))
  139. return false;
  140. m_match_hist[0] = 1;
  141. m_match_hist[1] = 1;
  142. m_match_hist[2] = 1;
  143. m_match_hist[3] = 1;
  144. return true;
  145. }
  146. void lzcompressor::state_base::partial_advance(const lzdecision& lzdec)
  147. {
  148. if (lzdec.m_len == 0)
  149. {
  150. if (m_cur_state < 4) m_cur_state = 0; else if (m_cur_state < 10) m_cur_state -= 3; else m_cur_state -= 6;
  151. }
  152. else
  153. {
  154. if (lzdec.m_dist < 0)
  155. {
  156. int match_hist_index = -lzdec.m_dist - 1;
  157. if (!match_hist_index)
  158. {
  159. if (lzdec.m_len == 1)
  160. {
  161. m_cur_state = (m_cur_state < CLZBase::cNumLitStates) ? 9 : 11;
  162. }
  163. else
  164. {
  165. m_cur_state = (m_cur_state < CLZBase::cNumLitStates) ? 8 : 11;
  166. }
  167. }
  168. else
  169. {
  170. if (match_hist_index == 1)
  171. {
  172. std::swap(m_match_hist[0], m_match_hist[1]);
  173. }
  174. else if (match_hist_index == 2)
  175. {
  176. int dist = m_match_hist[2];
  177. m_match_hist[2] = m_match_hist[1];
  178. m_match_hist[1] = m_match_hist[0];
  179. m_match_hist[0] = dist;
  180. }
  181. else
  182. {
  183. LZHAM_ASSERT(match_hist_index == 3);
  184. int dist = m_match_hist[3];
  185. m_match_hist[3] = m_match_hist[2];
  186. m_match_hist[2] = m_match_hist[1];
  187. m_match_hist[1] = m_match_hist[0];
  188. m_match_hist[0] = dist;
  189. }
  190. m_cur_state = (m_cur_state < CLZBase::cNumLitStates) ? 8 : 11;
  191. }
  192. }
  193. else
  194. {
  195. // full
  196. LZHAM_ASSUME(CLZBase::cMatchHistSize == 4);
  197. m_match_hist[3] = m_match_hist[2];
  198. m_match_hist[2] = m_match_hist[1];
  199. m_match_hist[1] = m_match_hist[0];
  200. m_match_hist[0] = lzdec.m_dist;
  201. m_cur_state = (m_cur_state < CLZBase::cNumLitStates) ? CLZBase::cNumLitStates : CLZBase::cNumLitStates + 3;
  202. }
  203. }
  204. m_cur_ofs = lzdec.m_pos + lzdec.get_len();
  205. }
  206. uint lzcompressor::state::get_pred_char(const search_accelerator& dict, int pos, int backward_ofs) const
  207. {
  208. LZHAM_ASSERT(pos >= (int)m_block_start_dict_ofs);
  209. int limit = pos - m_block_start_dict_ofs;
  210. if (backward_ofs > limit)
  211. return 0;
  212. return dict[pos - backward_ofs];
  213. }
  214. bit_cost_t lzcompressor::state::get_cost(CLZBase& lzbase, const search_accelerator& dict, const lzdecision& lzdec) const
  215. {
  216. //const uint lit_pred0 = get_pred_char(dict, lzdec.m_pos, 1);
  217. uint is_match_model_index = LZHAM_IS_MATCH_MODEL_INDEX(m_cur_state);
  218. LZHAM_ASSERT(is_match_model_index < LZHAM_ARRAY_SIZE(m_is_match_model));
  219. bit_cost_t cost = m_is_match_model[is_match_model_index].get_cost(lzdec.is_match());
  220. if (!lzdec.is_match())
  221. {
  222. const uint lit = dict[lzdec.m_pos];
  223. if (m_cur_state < CLZBase::cNumLitStates)
  224. {
  225. // literal
  226. cost += m_lit_table.get_cost(lit);
  227. }
  228. else
  229. {
  230. // delta literal
  231. const uint rep_lit0 = dict[(lzdec.m_pos - m_match_hist[0]) & dict.m_max_dict_size_mask];
  232. uint delta_lit = rep_lit0 ^ lit;
  233. cost += m_delta_lit_table.get_cost(delta_lit);
  234. }
  235. }
  236. else
  237. {
  238. // match
  239. if (lzdec.m_dist < 0)
  240. {
  241. // rep match
  242. cost += m_is_rep_model[m_cur_state].get_cost(1);
  243. int match_hist_index = -lzdec.m_dist - 1;
  244. if (!match_hist_index)
  245. {
  246. // rep0 match
  247. cost += m_is_rep0_model[m_cur_state].get_cost(1);
  248. if (lzdec.m_len == 1)
  249. {
  250. // single byte rep0
  251. cost += m_is_rep0_single_byte_model[m_cur_state].get_cost(1);
  252. }
  253. else
  254. {
  255. // normal rep0
  256. cost += m_is_rep0_single_byte_model[m_cur_state].get_cost(0);
  257. if (lzdec.m_len > CLZBase::cMaxMatchLen)
  258. {
  259. cost += get_huge_match_code_len(lzdec.m_len) + m_rep_len_table[m_cur_state >= CLZBase::cNumLitStates].get_cost((CLZBase::cMaxMatchLen + 1) - CLZBase::cMinMatchLen);
  260. }
  261. else
  262. {
  263. cost += m_rep_len_table[m_cur_state >= CLZBase::cNumLitStates].get_cost(lzdec.m_len - CLZBase::cMinMatchLen);
  264. }
  265. }
  266. }
  267. else
  268. {
  269. if (lzdec.m_len > CLZBase::cMaxMatchLen)
  270. {
  271. cost += get_huge_match_code_len(lzdec.m_len) + m_rep_len_table[m_cur_state >= CLZBase::cNumLitStates].get_cost((CLZBase::cMaxMatchLen + 1) - CLZBase::cMinMatchLen);
  272. }
  273. else
  274. {
  275. cost += m_rep_len_table[m_cur_state >= CLZBase::cNumLitStates].get_cost(lzdec.m_len - CLZBase::cMinMatchLen);
  276. }
  277. // rep1-rep3 match
  278. cost += m_is_rep0_model[m_cur_state].get_cost(0);
  279. if (match_hist_index == 1)
  280. {
  281. // rep1
  282. cost += m_is_rep1_model[m_cur_state].get_cost(1);
  283. }
  284. else
  285. {
  286. cost += m_is_rep1_model[m_cur_state].get_cost(0);
  287. if (match_hist_index == 2)
  288. {
  289. // rep2
  290. cost += m_is_rep2_model[m_cur_state].get_cost(1);
  291. }
  292. else
  293. {
  294. LZHAM_ASSERT(match_hist_index == 3);
  295. // rep3
  296. cost += m_is_rep2_model[m_cur_state].get_cost(0);
  297. }
  298. }
  299. }
  300. }
  301. else
  302. {
  303. cost += m_is_rep_model[m_cur_state].get_cost(0);
  304. LZHAM_ASSERT(lzdec.m_len >= CLZBase::cMinMatchLen);
  305. // full match
  306. uint match_slot, match_extra;
  307. lzbase.compute_lzx_position_slot(lzdec.m_dist, match_slot, match_extra);
  308. uint match_low_sym = 0;
  309. if (lzdec.m_len >= 9)
  310. {
  311. match_low_sym = 7;
  312. if (lzdec.m_len > CLZBase::cMaxMatchLen)
  313. {
  314. cost += get_huge_match_code_len(lzdec.m_len) + m_large_len_table[m_cur_state >= CLZBase::cNumLitStates].get_cost((CLZBase::cMaxMatchLen + 1) - 9);
  315. }
  316. else
  317. {
  318. cost += m_large_len_table[m_cur_state >= CLZBase::cNumLitStates].get_cost(lzdec.m_len - 9);
  319. }
  320. }
  321. else
  322. match_low_sym = lzdec.m_len - 2;
  323. uint match_high_sym = 0;
  324. LZHAM_ASSERT(match_slot >= CLZBase::cLZXLowestUsableMatchSlot && (match_slot < lzbase.m_num_lzx_slots));
  325. match_high_sym = match_slot - CLZBase::cLZXLowestUsableMatchSlot;
  326. uint main_sym = match_low_sym | (match_high_sym << 3);
  327. cost += m_main_table.get_cost(CLZBase::cLZXNumSpecialLengths + main_sym);
  328. uint num_extra_bits = lzbase.m_lzx_position_extra_bits[match_slot];
  329. if (num_extra_bits < 3)
  330. cost += convert_to_scaled_bitcost(num_extra_bits);
  331. else
  332. {
  333. if (num_extra_bits > 4)
  334. cost += convert_to_scaled_bitcost(num_extra_bits - 4);
  335. cost += m_dist_lsb_table.get_cost(match_extra & 15);
  336. }
  337. }
  338. }
  339. return cost;
  340. }
  341. bit_cost_t lzcompressor::state::get_len2_match_cost(CLZBase& lzbase, uint dict_pos, uint len2_match_dist, uint is_match_model_index)
  342. {
  343. LZHAM_NOTE_UNUSED(dict_pos);
  344. bit_cost_t cost = m_is_match_model[is_match_model_index].get_cost(1);
  345. cost += m_is_rep_model[m_cur_state].get_cost(0);
  346. // full match
  347. uint match_slot, match_extra;
  348. lzbase.compute_lzx_position_slot(len2_match_dist, match_slot, match_extra);
  349. const uint match_len = 2;
  350. uint match_low_sym = match_len - 2;
  351. uint match_high_sym = 0;
  352. LZHAM_ASSERT(match_slot >= CLZBase::cLZXLowestUsableMatchSlot && (match_slot < lzbase.m_num_lzx_slots));
  353. match_high_sym = match_slot - CLZBase::cLZXLowestUsableMatchSlot;
  354. uint main_sym = match_low_sym | (match_high_sym << 3);
  355. cost += m_main_table.get_cost(CLZBase::cLZXNumSpecialLengths + main_sym);
  356. uint num_extra_bits = lzbase.m_lzx_position_extra_bits[match_slot];
  357. if (num_extra_bits < 3)
  358. cost += convert_to_scaled_bitcost(num_extra_bits);
  359. else
  360. {
  361. if (num_extra_bits > 4)
  362. cost += convert_to_scaled_bitcost(num_extra_bits - 4);
  363. cost += m_dist_lsb_table.get_cost(match_extra & 15);
  364. }
  365. return cost;
  366. }
  367. bit_cost_t lzcompressor::state::get_lit_cost(CLZBase& lzbase, const search_accelerator& dict, uint dict_pos, uint lit_pred0, uint is_match_model_index) const
  368. {
  369. LZHAM_NOTE_UNUSED(lzbase);
  370. LZHAM_NOTE_UNUSED(lit_pred0);
  371. bit_cost_t cost = m_is_match_model[is_match_model_index].get_cost(0);
  372. const uint lit = dict[dict_pos];
  373. if (m_cur_state < CLZBase::cNumLitStates)
  374. {
  375. // literal
  376. cost += m_lit_table.get_cost(lit);
  377. }
  378. else
  379. {
  380. // delta literal
  381. const uint rep_lit0 = dict[(dict_pos - m_match_hist[0]) & dict.m_max_dict_size_mask];
  382. uint delta_lit = rep_lit0 ^ lit;
  383. cost += m_delta_lit_table.get_cost(delta_lit);
  384. }
  385. return cost;
  386. }
  387. void lzcompressor::state::get_rep_match_costs(uint dict_pos, bit_cost_t *pBitcosts, uint match_hist_index, int min_len, int max_len, uint is_match_model_index) const
  388. {
  389. LZHAM_NOTE_UNUSED(dict_pos);
  390. // match
  391. const quasi_adaptive_huffman_data_model &rep_len_table = m_rep_len_table[m_cur_state >= CLZBase::cNumLitStates];
  392. bit_cost_t base_cost = m_is_match_model[is_match_model_index].get_cost(1);
  393. base_cost += m_is_rep_model[m_cur_state].get_cost(1);
  394. if (!match_hist_index)
  395. {
  396. // rep0 match
  397. base_cost += m_is_rep0_model[m_cur_state].get_cost(1);
  398. }
  399. else
  400. {
  401. // rep1-rep3 matches
  402. base_cost += m_is_rep0_model[m_cur_state].get_cost(0);
  403. if (match_hist_index == 1)
  404. {
  405. // rep1
  406. base_cost += m_is_rep1_model[m_cur_state].get_cost(1);
  407. }
  408. else
  409. {
  410. base_cost += m_is_rep1_model[m_cur_state].get_cost(0);
  411. if (match_hist_index == 2)
  412. {
  413. // rep2
  414. base_cost += m_is_rep2_model[m_cur_state].get_cost(1);
  415. }
  416. else
  417. {
  418. // rep3
  419. base_cost += m_is_rep2_model[m_cur_state].get_cost(0);
  420. }
  421. }
  422. }
  423. // rep match
  424. if (!match_hist_index)
  425. {
  426. if (min_len == 1)
  427. {
  428. // single byte rep0
  429. pBitcosts[1] = base_cost + m_is_rep0_single_byte_model[m_cur_state].get_cost(1);
  430. min_len++;
  431. }
  432. bit_cost_t rep0_match_base_cost = base_cost + m_is_rep0_single_byte_model[m_cur_state].get_cost(0);
  433. for (int match_len = min_len; match_len <= max_len; match_len++)
  434. {
  435. // normal rep0
  436. if (match_len > CLZBase::cMaxMatchLen)
  437. {
  438. pBitcosts[match_len] = get_huge_match_code_len(match_len) + rep0_match_base_cost + rep_len_table.get_cost((CLZBase::cMaxMatchLen + 1) - CLZBase::cMinMatchLen);
  439. }
  440. else
  441. {
  442. pBitcosts[match_len] = rep0_match_base_cost + rep_len_table.get_cost(match_len - CLZBase::cMinMatchLen);
  443. }
  444. }
  445. }
  446. else
  447. {
  448. for (int match_len = min_len; match_len <= max_len; match_len++)
  449. {
  450. if (match_len > CLZBase::cMaxMatchLen)
  451. {
  452. pBitcosts[match_len] = get_huge_match_code_len(match_len) + base_cost + rep_len_table.get_cost((CLZBase::cMaxMatchLen + 1) - CLZBase::cMinMatchLen);
  453. }
  454. else
  455. {
  456. pBitcosts[match_len] = base_cost + rep_len_table.get_cost(match_len - CLZBase::cMinMatchLen);
  457. }
  458. }
  459. }
  460. }
  461. void lzcompressor::state::get_full_match_costs(CLZBase& lzbase, uint dict_pos, bit_cost_t *pBitcosts, uint match_dist, int min_len, int max_len, uint is_match_model_index) const
  462. {
  463. LZHAM_NOTE_UNUSED(dict_pos);
  464. LZHAM_ASSERT(min_len >= CLZBase::cMinMatchLen);
  465. bit_cost_t cost = m_is_match_model[is_match_model_index].get_cost(1);
  466. cost += m_is_rep_model[m_cur_state].get_cost(0);
  467. uint match_slot, match_extra;
  468. lzbase.compute_lzx_position_slot(match_dist, match_slot, match_extra);
  469. LZHAM_ASSERT(match_slot >= CLZBase::cLZXLowestUsableMatchSlot && (match_slot < lzbase.m_num_lzx_slots));
  470. uint num_extra_bits = lzbase.m_lzx_position_extra_bits[match_slot];
  471. if (num_extra_bits < 3)
  472. cost += convert_to_scaled_bitcost(num_extra_bits);
  473. else
  474. {
  475. if (num_extra_bits > 4)
  476. cost += convert_to_scaled_bitcost(num_extra_bits - 4);
  477. cost += m_dist_lsb_table.get_cost(match_extra & 15);
  478. }
  479. uint match_high_sym = match_slot - CLZBase::cLZXLowestUsableMatchSlot;
  480. const quasi_adaptive_huffman_data_model &large_len_table = m_large_len_table[m_cur_state >= CLZBase::cNumLitStates];
  481. for (int match_len = min_len; match_len <= max_len; match_len++)
  482. {
  483. bit_cost_t len_cost = cost;
  484. uint match_low_sym = 0;
  485. if (match_len >= 9)
  486. {
  487. match_low_sym = 7;
  488. if (match_len > CLZBase::cMaxMatchLen)
  489. {
  490. len_cost += get_huge_match_code_len(match_len) + large_len_table.get_cost((CLZBase::cMaxMatchLen + 1) - 9);
  491. }
  492. else
  493. {
  494. len_cost += large_len_table.get_cost(match_len - 9);
  495. }
  496. }
  497. else
  498. match_low_sym = match_len - 2;
  499. uint main_sym = match_low_sym | (match_high_sym << 3);
  500. pBitcosts[match_len] = len_cost + m_main_table.get_cost(CLZBase::cLZXNumSpecialLengths + main_sym);
  501. }
  502. }
  503. bool lzcompressor::state::advance(CLZBase& lzbase, const search_accelerator& dict, const lzdecision& lzdec)
  504. {
  505. //const uint lit_pred0 = get_pred_char(dict, lzdec.m_pos, 1);
  506. uint is_match_model_index = LZHAM_IS_MATCH_MODEL_INDEX(m_cur_state);
  507. m_is_match_model[is_match_model_index].update(lzdec.is_match());
  508. if (!lzdec.is_match())
  509. {
  510. const uint lit = dict[lzdec.m_pos];
  511. if (m_cur_state < CLZBase::cNumLitStates)
  512. {
  513. // literal
  514. if (!m_lit_table.update_sym(lit)) return false;
  515. }
  516. else
  517. {
  518. // delta literal
  519. const uint rep_lit0 = dict[(lzdec.m_pos - m_match_hist[0]) & dict.m_max_dict_size_mask];
  520. uint delta_lit = rep_lit0 ^ lit;
  521. if (!m_delta_lit_table.update_sym(delta_lit)) return false;
  522. }
  523. if (m_cur_state < 4) m_cur_state = 0; else if (m_cur_state < 10) m_cur_state -= 3; else m_cur_state -= 6;
  524. }
  525. else
  526. {
  527. // match
  528. if (lzdec.m_dist < 0)
  529. {
  530. // rep match
  531. m_is_rep_model[m_cur_state].update(1);
  532. int match_hist_index = -lzdec.m_dist - 1;
  533. if (!match_hist_index)
  534. {
  535. // rep0 match
  536. m_is_rep0_model[m_cur_state].update(1);
  537. if (lzdec.m_len == 1)
  538. {
  539. // single byte rep0
  540. m_is_rep0_single_byte_model[m_cur_state].update(1);
  541. m_cur_state = (m_cur_state < CLZBase::cNumLitStates) ? 9 : 11;
  542. }
  543. else
  544. {
  545. // normal rep0
  546. m_is_rep0_single_byte_model[m_cur_state].update(0);
  547. if (lzdec.m_len > CLZBase::cMaxMatchLen)
  548. {
  549. if (!m_rep_len_table[m_cur_state >= CLZBase::cNumLitStates].update_sym((CLZBase::cMaxMatchLen + 1) - CLZBase::cMinMatchLen)) return false;
  550. }
  551. else
  552. {
  553. if (!m_rep_len_table[m_cur_state >= CLZBase::cNumLitStates].update_sym(lzdec.m_len - CLZBase::cMinMatchLen)) return false;
  554. }
  555. m_cur_state = (m_cur_state < CLZBase::cNumLitStates) ? 8 : 11;
  556. }
  557. }
  558. else
  559. {
  560. // rep1-rep3 match
  561. m_is_rep0_model[m_cur_state].update(0);
  562. if (lzdec.m_len > CLZBase::cMaxMatchLen)
  563. {
  564. if (!m_rep_len_table[m_cur_state >= CLZBase::cNumLitStates].update_sym((CLZBase::cMaxMatchLen + 1) - CLZBase::cMinMatchLen)) return false;
  565. }
  566. else
  567. {
  568. if (!m_rep_len_table[m_cur_state >= CLZBase::cNumLitStates].update_sym(lzdec.m_len - CLZBase::cMinMatchLen)) return false;
  569. }
  570. if (match_hist_index == 1)
  571. {
  572. // rep1
  573. m_is_rep1_model[m_cur_state].update(1);
  574. std::swap(m_match_hist[0], m_match_hist[1]);
  575. }
  576. else
  577. {
  578. m_is_rep1_model[m_cur_state].update(0);
  579. if (match_hist_index == 2)
  580. {
  581. // rep2
  582. m_is_rep2_model[m_cur_state].update(1);
  583. int dist = m_match_hist[2];
  584. m_match_hist[2] = m_match_hist[1];
  585. m_match_hist[1] = m_match_hist[0];
  586. m_match_hist[0] = dist;
  587. }
  588. else
  589. {
  590. // rep3
  591. m_is_rep2_model[m_cur_state].update(0);
  592. int dist = m_match_hist[3];
  593. m_match_hist[3] = m_match_hist[2];
  594. m_match_hist[2] = m_match_hist[1];
  595. m_match_hist[1] = m_match_hist[0];
  596. m_match_hist[0] = dist;
  597. }
  598. }
  599. m_cur_state = (m_cur_state < CLZBase::cNumLitStates) ? 8 : 11;
  600. }
  601. }
  602. else
  603. {
  604. m_is_rep_model[m_cur_state].update(0);
  605. LZHAM_ASSERT(lzdec.m_len >= CLZBase::cMinMatchLen);
  606. // full match
  607. uint match_slot, match_extra;
  608. lzbase.compute_lzx_position_slot(lzdec.m_dist, match_slot, match_extra);
  609. uint match_low_sym = 0;
  610. int large_len_sym = -1;
  611. if (lzdec.m_len >= 9)
  612. {
  613. match_low_sym = 7;
  614. large_len_sym = lzdec.m_len - 9;
  615. }
  616. else
  617. match_low_sym = lzdec.m_len - 2;
  618. uint match_high_sym = 0;
  619. LZHAM_ASSERT(match_slot >= CLZBase::cLZXLowestUsableMatchSlot && (match_slot < lzbase.m_num_lzx_slots));
  620. match_high_sym = match_slot - CLZBase::cLZXLowestUsableMatchSlot;
  621. uint main_sym = match_low_sym | (match_high_sym << 3);
  622. if (!m_main_table.update_sym(CLZBase::cLZXNumSpecialLengths + main_sym)) return false;
  623. if (large_len_sym >= 0)
  624. {
  625. if (lzdec.m_len > CLZBase::cMaxMatchLen)
  626. {
  627. if (!m_large_len_table[m_cur_state >= CLZBase::cNumLitStates].update_sym((CLZBase::cMaxMatchLen + 1) - 9)) return false;
  628. }
  629. else
  630. {
  631. if (!m_large_len_table[m_cur_state >= CLZBase::cNumLitStates].update_sym(large_len_sym)) return false;
  632. }
  633. }
  634. uint num_extra_bits = lzbase.m_lzx_position_extra_bits[match_slot];
  635. if (num_extra_bits >= 3)
  636. {
  637. if (!m_dist_lsb_table.update_sym(match_extra & 15)) return false;
  638. }
  639. update_match_hist(lzdec.m_dist);
  640. m_cur_state = (m_cur_state < CLZBase::cNumLitStates) ? CLZBase::cNumLitStates : CLZBase::cNumLitStates + 3;
  641. }
  642. }
  643. m_cur_ofs = lzdec.m_pos + lzdec.get_len();
  644. return true;
  645. }
  646. bool lzcompressor::state::encode(symbol_codec& codec, CLZBase& lzbase, const search_accelerator& dict, const lzdecision& lzdec)
  647. {
  648. //const uint lit_pred0 = get_pred_char(dict, lzdec.m_pos, 1);
  649. uint is_match_model_index = LZHAM_IS_MATCH_MODEL_INDEX(m_cur_state);
  650. if (!codec.encode(lzdec.is_match(), m_is_match_model[is_match_model_index])) return false;
  651. if (!lzdec.is_match())
  652. {
  653. const uint lit = dict[lzdec.m_pos];
  654. #ifdef LZHAM_LZDEBUG
  655. if (!codec.encode_bits(lit, 8)) return false;
  656. #endif
  657. if (m_cur_state < CLZBase::cNumLitStates)
  658. {
  659. // literal
  660. if (!codec.encode(lit, m_lit_table)) return false;
  661. }
  662. else
  663. {
  664. // delta literal
  665. const uint rep_lit0 = dict[(lzdec.m_pos - m_match_hist[0]) & dict.m_max_dict_size_mask];
  666. uint delta_lit = rep_lit0 ^ lit;
  667. #ifdef LZHAM_LZDEBUG
  668. if (!codec.encode_bits(rep_lit0, 8)) return false;
  669. #endif
  670. if (!codec.encode(delta_lit, m_delta_lit_table)) return false;
  671. }
  672. if (m_cur_state < 4) m_cur_state = 0; else if (m_cur_state < 10) m_cur_state -= 3; else m_cur_state -= 6;
  673. }
  674. else
  675. {
  676. // match
  677. if (lzdec.m_dist < 0)
  678. {
  679. // rep match
  680. if (!codec.encode(1, m_is_rep_model[m_cur_state])) return false;
  681. int match_hist_index = -lzdec.m_dist - 1;
  682. if (!match_hist_index)
  683. {
  684. // rep0 match
  685. if (!codec.encode(1, m_is_rep0_model[m_cur_state])) return false;
  686. if (lzdec.m_len == 1)
  687. {
  688. // single byte rep0
  689. if (!codec.encode(1, m_is_rep0_single_byte_model[m_cur_state])) return false;
  690. m_cur_state = (m_cur_state < CLZBase::cNumLitStates) ? 9 : 11;
  691. }
  692. else
  693. {
  694. // normal rep0
  695. if (!codec.encode(0, m_is_rep0_single_byte_model[m_cur_state])) return false;
  696. if (lzdec.m_len > CLZBase::cMaxMatchLen)
  697. {
  698. if (!codec.encode((CLZBase::cMaxMatchLen + 1) - CLZBase::cMinMatchLen, m_rep_len_table[m_cur_state >= CLZBase::cNumLitStates])) return false;
  699. if (!codec.encode_bits(get_huge_match_code_bits(lzdec.m_len), get_huge_match_code_len(lzdec.m_len))) return false;
  700. }
  701. else
  702. {
  703. if (!codec.encode(lzdec.m_len - CLZBase::cMinMatchLen, m_rep_len_table[m_cur_state >= CLZBase::cNumLitStates])) return false;
  704. }
  705. m_cur_state = (m_cur_state < CLZBase::cNumLitStates) ? 8 : 11;
  706. }
  707. }
  708. else
  709. {
  710. // rep1-rep3 match
  711. if (!codec.encode(0, m_is_rep0_model[m_cur_state])) return false;
  712. if (lzdec.m_len > CLZBase::cMaxMatchLen)
  713. {
  714. if (!codec.encode((CLZBase::cMaxMatchLen + 1) - CLZBase::cMinMatchLen, m_rep_len_table[m_cur_state >= CLZBase::cNumLitStates])) return false;
  715. if (!codec.encode_bits(get_huge_match_code_bits(lzdec.m_len), get_huge_match_code_len(lzdec.m_len))) return false;
  716. }
  717. else
  718. {
  719. if (!codec.encode(lzdec.m_len - CLZBase::cMinMatchLen, m_rep_len_table[m_cur_state >= CLZBase::cNumLitStates])) return false;
  720. }
  721. if (match_hist_index == 1)
  722. {
  723. // rep1
  724. if (!codec.encode(1, m_is_rep1_model[m_cur_state])) return false;
  725. std::swap(m_match_hist[0], m_match_hist[1]);
  726. }
  727. else
  728. {
  729. if (!codec.encode(0, m_is_rep1_model[m_cur_state])) return false;
  730. if (match_hist_index == 2)
  731. {
  732. // rep2
  733. if (!codec.encode(1, m_is_rep2_model[m_cur_state])) return false;
  734. int dist = m_match_hist[2];
  735. m_match_hist[2] = m_match_hist[1];
  736. m_match_hist[1] = m_match_hist[0];
  737. m_match_hist[0] = dist;
  738. }
  739. else
  740. {
  741. // rep3
  742. if (!codec.encode(0, m_is_rep2_model[m_cur_state])) return false;
  743. int dist = m_match_hist[3];
  744. m_match_hist[3] = m_match_hist[2];
  745. m_match_hist[2] = m_match_hist[1];
  746. m_match_hist[1] = m_match_hist[0];
  747. m_match_hist[0] = dist;
  748. }
  749. }
  750. m_cur_state = (m_cur_state < CLZBase::cNumLitStates) ? 8 : 11;
  751. }
  752. }
  753. else
  754. {
  755. if (!codec.encode(0, m_is_rep_model[m_cur_state])) return false;
  756. LZHAM_ASSERT(lzdec.m_len >= CLZBase::cMinMatchLen);
  757. // full match
  758. uint match_slot, match_extra;
  759. lzbase.compute_lzx_position_slot(lzdec.m_dist, match_slot, match_extra);
  760. uint match_low_sym = 0;
  761. int large_len_sym = -1;
  762. if (lzdec.m_len >= 9)
  763. {
  764. match_low_sym = 7;
  765. large_len_sym = lzdec.m_len - 9;
  766. }
  767. else
  768. match_low_sym = lzdec.m_len - 2;
  769. uint match_high_sym = 0;
  770. LZHAM_ASSERT(match_slot >= CLZBase::cLZXLowestUsableMatchSlot && (match_slot < lzbase.m_num_lzx_slots));
  771. match_high_sym = match_slot - CLZBase::cLZXLowestUsableMatchSlot;
  772. uint main_sym = match_low_sym | (match_high_sym << 3);
  773. if (!codec.encode(CLZBase::cLZXNumSpecialLengths + main_sym, m_main_table)) return false;
  774. if (large_len_sym >= 0)
  775. {
  776. if (lzdec.m_len > CLZBase::cMaxMatchLen)
  777. {
  778. if (!codec.encode((CLZBase::cMaxMatchLen + 1) - 9, m_large_len_table[m_cur_state >= CLZBase::cNumLitStates])) return false;
  779. if (!codec.encode_bits(get_huge_match_code_bits(lzdec.m_len), get_huge_match_code_len(lzdec.m_len))) return false;
  780. }
  781. else
  782. {
  783. if (!codec.encode(large_len_sym, m_large_len_table[m_cur_state >= CLZBase::cNumLitStates])) return false;
  784. }
  785. }
  786. uint num_extra_bits = lzbase.m_lzx_position_extra_bits[match_slot];
  787. if (num_extra_bits < 3)
  788. {
  789. if (!codec.encode_bits(match_extra, num_extra_bits)) return false;
  790. }
  791. else
  792. {
  793. if (num_extra_bits > 4)
  794. {
  795. if (!codec.encode_bits((match_extra >> 4), num_extra_bits - 4)) return false;
  796. }
  797. if (!codec.encode(match_extra & 15, m_dist_lsb_table)) return false;
  798. }
  799. update_match_hist(lzdec.m_dist);
  800. m_cur_state = (m_cur_state < CLZBase::cNumLitStates) ? CLZBase::cNumLitStates : CLZBase::cNumLitStates + 3;
  801. }
  802. #ifdef LZHAM_LZDEBUG
  803. if (!codec.encode_bits(m_match_hist[0], 29)) return false;
  804. #endif
  805. }
  806. m_cur_ofs = lzdec.m_pos + lzdec.get_len();
  807. return true;
  808. }
  809. /*void lzcompressor::state::print(symbol_codec& codec, CLZBase& lzbase, const search_accelerator& dict, const lzdecision& lzdec) ESENTHEL CHANGED
  810. {
  811. LZHAM_NOTE_UNUSED(codec), LZHAM_NOTE_UNUSED(lzbase), LZHAM_NOTE_UNUSED(dict);
  812. const uint lit_pred0 = get_pred_char(dict, lzdec.m_pos, 1);
  813. uint is_match_model_index = LZHAM_IS_MATCH_MODEL_INDEX(m_cur_state);
  814. printf(" pos: %u, state: %u, match_pred: %u, is_match_model_index: %u, is_match: %u, cost: %f\n",
  815. lzdec.m_pos,
  816. m_cur_state,
  817. lit_pred0, is_match_model_index, lzdec.is_match(), get_cost(lzbase, dict, lzdec) / (float)cBitCostScale);
  818. if (!lzdec.is_match())
  819. {
  820. const uint lit = dict[lzdec.m_pos];
  821. if (m_cur_state < CLZBase::cNumLitStates)
  822. {
  823. printf("---Regular lit: %u '%c'\n",
  824. lit, ((lit >= 32) && (lit <= 127)) ? lit : '.');
  825. }
  826. else
  827. {
  828. // delta literal
  829. const uint rep_lit0 = dict[(lzdec.m_pos - m_match_hist[0]) & dict.m_max_dict_size_mask];
  830. uint delta_lit = rep_lit0 ^ lit;
  831. printf("***Delta lit: %u '%c', Mismatch: %u '%c', Delta: 0x%02X\n",
  832. lit, ((lit >= 32) && (lit <= 127)) ? lit : '.',
  833. rep_lit0, ((rep_lit0 >= 32) && (rep_lit0 <= 127)) ? rep_lit0 : '.',
  834. delta_lit);
  835. }
  836. }
  837. else
  838. {
  839. uint actual_match_len = dict.get_match_len(0, lzdec.get_match_dist(*this), CLZBase::cMaxMatchLen);
  840. LZHAM_ASSERT(actual_match_len >= lzdec.get_len());
  841. // match
  842. if (lzdec.m_dist < 0)
  843. {
  844. int match_hist_index = -lzdec.m_dist - 1;
  845. if (!match_hist_index)
  846. {
  847. if (lzdec.m_len == 1)
  848. {
  849. printf("!!!Rep 0 len1\n");
  850. }
  851. else
  852. {
  853. printf("!!!Rep 0 full len %u\n", lzdec.m_len);
  854. }
  855. }
  856. else
  857. {
  858. printf("!!!Rep %u full len %u\n", match_hist_index, lzdec.m_len);
  859. }
  860. }
  861. else
  862. {
  863. LZHAM_ASSERT(lzdec.m_len >= CLZBase::cMinMatchLen);
  864. // full match
  865. uint match_slot, match_extra;
  866. lzbase.compute_lzx_position_slot(lzdec.m_dist, match_slot, match_extra);
  867. uint match_low_sym = 0; LZHAM_NOTE_UNUSED(match_low_sym);
  868. int large_len_sym = -1; LZHAM_NOTE_UNUSED(large_len_sym);
  869. if (lzdec.m_len >= 9)
  870. {
  871. match_low_sym = 7;
  872. large_len_sym = lzdec.m_len - 9;
  873. }
  874. else
  875. match_low_sym = lzdec.m_len - 2;
  876. uint match_high_sym = 0; LZHAM_NOTE_UNUSED(match_high_sym);
  877. LZHAM_ASSERT(match_slot >= CLZBase::cLZXLowestUsableMatchSlot && (match_slot < lzbase.m_num_lzx_slots));
  878. match_high_sym = match_slot - CLZBase::cLZXLowestUsableMatchSlot;
  879. //uint main_sym = match_low_sym | (match_high_sym << 3);
  880. uint num_extra_bits = lzbase.m_lzx_position_extra_bits[match_slot];
  881. printf("^^^Full match Len %u Dist %u, Slot %u, ExtraBits: %u", lzdec.m_len, lzdec.m_dist, match_slot, num_extra_bits);
  882. if (num_extra_bits < 3)
  883. {
  884. }
  885. else
  886. {
  887. printf(" (Low 4 bits: %u vs. %u)", lzdec.m_dist & 15, match_extra & 15);
  888. }
  889. printf("\n");
  890. }
  891. if (actual_match_len > lzdec.get_len())
  892. {
  893. printf(" TRUNCATED match, actual len is %u, shortened by %u\n", actual_match_len, actual_match_len - lzdec.get_len());
  894. }
  895. }
  896. }*/
  897. bool lzcompressor::state::encode_eob(symbol_codec& codec, const search_accelerator& dict, uint dict_pos)
  898. {
  899. LZHAM_NOTE_UNUSED(dict);
  900. LZHAM_NOTE_UNUSED(dict_pos);
  901. #ifdef LZHAM_LZDEBUG
  902. if (!codec.encode_bits(CLZBase::cLZHAMDebugSyncMarkerValue, CLZBase::cLZHAMDebugSyncMarkerBits)) return false;
  903. if (!codec.encode_bits(1, 1)) return false;
  904. if (!codec.encode_bits(0, 17)) return false;
  905. if (!codec.encode_bits(m_cur_state, 4)) return false;
  906. #endif
  907. //const uint match_pred = get_pred_char(dict, dict_pos, 1);
  908. uint is_match_model_index = LZHAM_IS_MATCH_MODEL_INDEX(m_cur_state);
  909. if (!codec.encode(1, m_is_match_model[is_match_model_index])) return false;
  910. // full match
  911. if (!codec.encode(0, m_is_rep_model[m_cur_state])) return false;
  912. return codec.encode(CLZBase::cLZXSpecialCodeEndOfBlockCode, m_main_table);
  913. }
  914. bool lzcompressor::state::encode_reset_state_partial(symbol_codec& codec, const search_accelerator& dict, uint dict_pos)
  915. {
  916. LZHAM_NOTE_UNUSED(dict);
  917. LZHAM_NOTE_UNUSED(dict_pos);
  918. #ifdef LZHAM_LZDEBUG
  919. if (!codec.encode_bits(CLZBase::cLZHAMDebugSyncMarkerValue, CLZBase::cLZHAMDebugSyncMarkerBits)) return false;
  920. if (!codec.encode_bits(1, 1)) return false;
  921. if (!codec.encode_bits(0, 17)) return false;
  922. if (!codec.encode_bits(m_cur_state, 4)) return false;
  923. #endif
  924. //const uint match_pred = get_pred_char(dict, dict_pos, 1);
  925. uint is_match_model_index = LZHAM_IS_MATCH_MODEL_INDEX(m_cur_state);
  926. if (!codec.encode(1, m_is_match_model[is_match_model_index])) return false;
  927. // full match
  928. if (!codec.encode(0, m_is_rep_model[m_cur_state])) return false;
  929. if (!codec.encode(CLZBase::cLZXSpecialCodePartialStateReset, m_main_table))
  930. return false;
  931. reset_state_partial();
  932. return true;
  933. }
  934. void lzcompressor::state::update_match_hist(uint match_dist)
  935. {
  936. LZHAM_ASSUME(CLZBase::cMatchHistSize == 4);
  937. m_match_hist[3] = m_match_hist[2];
  938. m_match_hist[2] = m_match_hist[1];
  939. m_match_hist[1] = m_match_hist[0];
  940. m_match_hist[0] = match_dist;
  941. }
  942. int lzcompressor::state::find_match_dist(uint match_dist) const
  943. {
  944. for (uint match_hist_index = 0; match_hist_index < CLZBase::cMatchHistSize; match_hist_index++)
  945. if (match_dist == m_match_hist[match_hist_index])
  946. return match_hist_index;
  947. return -1;
  948. }
  949. void lzcompressor::state::reset_state_partial()
  950. {
  951. LZHAM_ASSUME(CLZBase::cMatchHistSize == 4);
  952. m_match_hist[0] = 1;
  953. m_match_hist[1] = 1;
  954. m_match_hist[2] = 1;
  955. m_match_hist[3] = 1;
  956. m_cur_state = 0;
  957. }
  958. void lzcompressor::state::start_of_block(const search_accelerator& dict, uint cur_ofs, uint block_index)
  959. {
  960. LZHAM_NOTE_UNUSED(dict), LZHAM_NOTE_UNUSED(block_index);
  961. reset_state_partial();
  962. m_cur_ofs = cur_ofs;
  963. m_block_start_dict_ofs = cur_ofs;
  964. }
  965. void lzcompressor::state::reset_update_rate()
  966. {
  967. m_lit_table.reset_update_rate();
  968. m_delta_lit_table.reset_update_rate();
  969. m_main_table.reset_update_rate();
  970. for (uint i = 0; i < LZHAM_ARRAY_SIZE(m_rep_len_table); i++)
  971. m_rep_len_table[i].reset_update_rate();
  972. for (uint i = 0; i < LZHAM_ARRAY_SIZE(m_large_len_table); i++)
  973. m_large_len_table[i].reset_update_rate();
  974. m_dist_lsb_table.reset_update_rate();
  975. }
  976. void lzcompressor::coding_stats::clear()
  977. {
  978. m_total_bytes = 0;
  979. m_total_contexts = 0;
  980. m_total_match_bits_cost = 0;
  981. m_worst_match_bits_cost = 0;
  982. m_total_is_match0_bits_cost = 0;
  983. m_total_is_match1_bits_cost = 0;
  984. m_context_stats.clear();
  985. m_total_nonmatches = 0;
  986. m_total_matches = 0;
  987. m_total_cost = 0.0f;
  988. m_lit_stats.clear();
  989. m_delta_lit_stats.clear();
  990. m_rep0_len1_stats.clear();
  991. for (uint i = 0; i < CLZBase::cMatchHistSize; i++)
  992. m_rep_stats[i].clear();
  993. m_rep0_len1_stats.clear();
  994. m_rep0_len2_plus_stats.clear();
  995. for (uint i = 0; i <= CLZBase::cMaxMatchLen; i++)
  996. m_full_match_stats[i].clear();
  997. m_total_far_len2_matches = 0;
  998. m_total_near_len2_matches = 0;
  999. m_total_truncated_matches = 0;
  1000. utils::zero_object(m_match_truncation_len_hist);
  1001. utils::zero_object(m_match_truncation_hist);
  1002. utils::zero_object(m_match_type_truncation_hist);
  1003. utils::zero_object(m_match_type_was_not_truncated_hist);
  1004. m_total_update_rate_resets = 0;
  1005. m_max_len2_dist = 0;
  1006. }
  1007. /*void lzcompressor::coding_stats::print() ESENTHEL CHANGED
  1008. {
  1009. if (!m_total_contexts)
  1010. return;
  1011. printf("-----------\n");
  1012. printf("Coding statistics:\n");
  1013. printf("Total update rate resets: %u\n", m_total_update_rate_resets);
  1014. printf("Total Bytes: %u, Total Contexts: %u, Total Cost: %f bits (%f bytes)\nContext ave cost: %f StdDev: %f Min: %f Max: %f\n", m_total_bytes, m_total_contexts, m_total_cost, m_total_cost / 8.0f, m_context_stats.get_average(), m_context_stats.get_std_dev(), m_context_stats.get_min_val(), m_context_stats.get_max_val());
  1015. printf("Ave bytes per context: %f\n", m_total_bytes / (float)m_total_contexts);
  1016. printf("IsMatch:\n");
  1017. printf(" Total: %u, Cost: %f (%f bytes), Ave. Cost: %f, Worst Cost: %f\n",
  1018. m_total_contexts, m_total_match_bits_cost, m_total_match_bits_cost / 8.0f, m_total_match_bits_cost / math::maximum<uint>(1, m_total_contexts), m_worst_match_bits_cost);
  1019. printf(" IsMatch(0): %u, Cost: %f (%f bytes), Ave. Cost: %f\n",
  1020. m_total_nonmatches, m_total_is_match0_bits_cost, m_total_is_match0_bits_cost / 8.0f, m_total_is_match0_bits_cost / math::maximum<uint>(1, m_total_nonmatches));
  1021. printf(" IsMatch(1): %u, Cost: %f (%f bytes), Ave. Cost: %f\n",
  1022. m_total_matches, m_total_is_match1_bits_cost, m_total_is_match1_bits_cost / 8.0f, m_total_is_match1_bits_cost / math::maximum<uint>(1, m_total_matches));
  1023. printf("Literal stats:\n");
  1024. printf(" Count: %u, Cost: %f (%f bytes), Ave: %f StdDev: %f Min: %f Max: %f\n", m_lit_stats.get_number_of_values32(), m_lit_stats.get_total(), m_lit_stats.get_total() / 8.0f, m_lit_stats.get_average(), m_lit_stats.get_std_dev(), m_lit_stats.get_min_val(), m_lit_stats.get_max_val());
  1025. printf("Delta literal stats:\n");
  1026. printf(" Count: %u, Cost: %f (%f bytes), Ave: %f StdDev: %f Min: %f Max: %f\n", m_delta_lit_stats.get_number_of_values32(), m_delta_lit_stats.get_total(), m_delta_lit_stats.get_total() / 8.0f, m_delta_lit_stats.get_average(), m_delta_lit_stats.get_std_dev(), m_delta_lit_stats.get_min_val(), m_delta_lit_stats.get_max_val());
  1027. printf("Rep0 Len1 stats:\n");
  1028. printf(" Count: %u, Cost: %f (%f bytes), Ave. Cost: %f StdDev: %f Min: %f Max: %f\n", m_rep0_len1_stats.get_number_of_values32(), m_rep0_len1_stats.get_total(), m_rep0_len1_stats.get_total() / 8.0f, m_rep0_len1_stats.get_average(), m_rep0_len1_stats.get_std_dev(), m_rep0_len1_stats.get_min_val(), m_rep0_len1_stats.get_max_val());
  1029. printf("Rep0 Len2+ stats:\n");
  1030. printf(" Count: %u, Cost: %f (%f bytes), Ave. Cost: %f StdDev: %f Min: %f Max: %f\n", m_rep0_len2_plus_stats.get_number_of_values32(), m_rep0_len2_plus_stats.get_total(), m_rep0_len2_plus_stats.get_total() / 8.0f, m_rep0_len2_plus_stats.get_average(), m_rep0_len2_plus_stats.get_std_dev(), m_rep0_len2_plus_stats.get_min_val(), m_rep0_len2_plus_stats.get_max_val());
  1031. for (uint i = 0; i < CLZBase::cMatchHistSize; i++)
  1032. {
  1033. printf("Rep %u stats:\n", i);
  1034. printf(" Count: %u, Cost: %f (%f bytes), Ave. Cost: %f StdDev: %f Min: %f Max: %f\n", m_rep_stats[i].get_number_of_values32(), m_rep_stats[i].get_total(), m_rep_stats[i].get_total() / 8.0f, m_rep_stats[i].get_average(), m_rep_stats[i].get_std_dev(), m_rep_stats[i].get_min_val(), m_rep_stats[i].get_max_val());
  1035. }
  1036. for (uint i = CLZBase::cMinMatchLen; i <= CLZBase::cMaxMatchLen; i++)
  1037. {
  1038. printf("Match %u: Total: %u, Cost: %f (%f bytes), Ave: %f StdDev: %f Min: %f Max: %f\n", i,
  1039. m_full_match_stats[i].get_number_of_values32(), m_full_match_stats[i].get_total(), m_full_match_stats[i].get_total() / 8.0f,
  1040. m_full_match_stats[i].get_average(), m_full_match_stats[i].get_std_dev(), m_full_match_stats[i].get_min_val(), m_full_match_stats[i].get_max_val());
  1041. }
  1042. printf("Total near len2 matches: %u, total far len2 matches: %u\n", m_total_near_len2_matches, m_total_far_len2_matches);
  1043. printf("Total matches: %u, truncated matches: %u\n", m_total_matches, m_total_truncated_matches);
  1044. printf("Max full match len2 distance: %u\n", m_max_len2_dist);
  1045. #if 0
  1046. printf("Size of truncation histogram:\n");
  1047. for (uint i = 0; i <= CLZBase::cMaxMatchLen; i++)
  1048. {
  1049. printf("%05u ", m_match_truncation_len_hist[i]);
  1050. if ((i & 15) == 15) printf("\n");
  1051. }
  1052. printf("\n");
  1053. printf("Number of truncations per encoded match length histogram:\n");
  1054. for (uint i = 0; i <= CLZBase::cMaxMatchLen; i++)
  1055. {
  1056. printf("%05u ", m_match_truncation_hist[i]);
  1057. if ((i & 15) == 15) printf("\n");
  1058. }
  1059. printf("\n");
  1060. for (uint s = 0; s < CLZBase::cNumStates; s++)
  1061. {
  1062. printf("-- Match type truncation hist for state %u:\n", s);
  1063. for (uint i = 0; i < LZHAM_ARRAY_SIZE(m_match_type_truncation_hist[s]); i++)
  1064. {
  1065. printf("%u truncated (%3.1f%%), %u not truncated\n", m_match_type_truncation_hist[s][i], 100.0f * (float)m_match_type_truncation_hist[s][i] / (m_match_type_truncation_hist[s][i] + m_match_type_was_not_truncated_hist[s][i]), m_match_type_was_not_truncated_hist[s][i]);
  1066. }
  1067. }
  1068. #endif
  1069. }*/
  1070. void lzcompressor::coding_stats::update(const lzdecision& lzdec, const state& cur_state, const search_accelerator& dict, bit_cost_t cost)
  1071. {
  1072. m_total_bytes += lzdec.get_len();
  1073. m_total_contexts++;
  1074. float cost_in_bits = cost / (float)cBitCostScale;
  1075. LZHAM_ASSERT(cost_in_bits > 0.0f);
  1076. m_total_cost += cost_in_bits;
  1077. m_context_stats.update(cost_in_bits);
  1078. //uint match_pred = cur_state.get_pred_char(dict, lzdec.m_pos, 1);
  1079. uint is_match_model_index = LZHAM_IS_MATCH_MODEL_INDEX(cur_state.m_cur_state);
  1080. if (lzdec.m_len == 0)
  1081. {
  1082. float match_bit_cost = cur_state.m_is_match_model[is_match_model_index].get_cost(0) / (float)cBitCostScale;
  1083. m_total_is_match0_bits_cost += match_bit_cost;
  1084. m_total_match_bits_cost += match_bit_cost;
  1085. m_worst_match_bits_cost = math::maximum<double>(m_worst_match_bits_cost, static_cast<double>(match_bit_cost));
  1086. m_total_nonmatches++;
  1087. if (cur_state.m_cur_state < CLZBase::cNumLitStates)
  1088. {
  1089. m_lit_stats.update(cost_in_bits);
  1090. }
  1091. else
  1092. {
  1093. m_delta_lit_stats.update(cost_in_bits);
  1094. }
  1095. }
  1096. else if (lzdec.m_len <= CLZBase::cMaxMatchLen)
  1097. {
  1098. const uint match_len = lzdec.get_len();
  1099. {
  1100. uint match_dist = lzdec.get_match_dist(cur_state);
  1101. uint cur_lookahead_size = dict.get_lookahead_size();
  1102. uint actual_match_len = dict.get_match_len(0, match_dist, LZHAM_MIN(cur_lookahead_size, static_cast<uint>(CLZBase::cMaxMatchLen)));
  1103. LZHAM_VERIFY(match_len <= actual_match_len);
  1104. m_total_truncated_matches += match_len < actual_match_len;
  1105. m_match_truncation_len_hist[math::maximum<int>(0, actual_match_len - match_len)]++;
  1106. uint type_index = 4;
  1107. if (!lzdec.is_full_match())
  1108. {
  1109. LZHAM_ASSUME(CLZBase::cMatchHistSize == 4);
  1110. type_index = -lzdec.m_dist - 1;
  1111. }
  1112. if (actual_match_len > match_len)
  1113. {
  1114. m_match_truncation_hist[match_len]++;
  1115. m_match_type_truncation_hist[cur_state.m_cur_state][type_index]++;
  1116. }
  1117. else
  1118. {
  1119. m_match_type_was_not_truncated_hist[cur_state.m_cur_state][type_index]++;
  1120. }
  1121. }
  1122. float match_bit_cost = cur_state.m_is_match_model[is_match_model_index].get_cost(1) / (float)cBitCostScale;
  1123. m_total_is_match1_bits_cost += match_bit_cost;
  1124. m_total_match_bits_cost += match_bit_cost;
  1125. m_worst_match_bits_cost = math::maximum<double>(m_worst_match_bits_cost, static_cast<double>(match_bit_cost));
  1126. m_total_matches++;
  1127. if (lzdec.m_dist < 0)
  1128. {
  1129. // rep match
  1130. int match_hist_index = -lzdec.m_dist - 1;
  1131. LZHAM_ASSERT(match_hist_index < CLZBase::cMatchHistSize);
  1132. m_rep_stats[match_hist_index].update(cost_in_bits);
  1133. if (!match_hist_index)
  1134. {
  1135. // rep0 match
  1136. if (lzdec.m_len == 1)
  1137. {
  1138. m_rep0_len1_stats.update(cost_in_bits);
  1139. }
  1140. else
  1141. {
  1142. m_rep0_len2_plus_stats.update(cost_in_bits);
  1143. }
  1144. }
  1145. }
  1146. else
  1147. {
  1148. m_full_match_stats[math::minimum<int>(cMaxMatchLen, match_len)].update(cost_in_bits);
  1149. if (match_len == 2)
  1150. {
  1151. if (lzdec.m_dist <= 512)
  1152. m_total_near_len2_matches++;
  1153. else
  1154. m_total_far_len2_matches++;
  1155. m_max_len2_dist = LZHAM_MAX((int)m_max_len2_dist, lzdec.m_dist);
  1156. }
  1157. }
  1158. }
  1159. else
  1160. {
  1161. // TODO: Handle huge matches.
  1162. }
  1163. }
  1164. } // namespace lzham