VirtualBox

source: vbox/trunk/src/libs/liblzma-5.4.1/lzma/lzma_encoder_optimum_normal.c

Last change on this file was 98730, checked in by vboxsync, 15 months ago

libs/liblzma-5.4.1: Export to OSE, bugref:10254

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 22.7 KB
Line 
1///////////////////////////////////////////////////////////////////////////////
2//
3/// \file lzma_encoder_optimum_normal.c
4//
5// Author: Igor Pavlov
6//
7// This file has been put into the public domain.
8// You can do whatever you want with this file.
9//
10///////////////////////////////////////////////////////////////////////////////
11
12#include "lzma_encoder_private.h"
13#include "fastpos.h"
14#include "memcmplen.h"
15
16
17////////////
18// Prices //
19////////////
20
21static uint32_t
22get_literal_price(const lzma_lzma1_encoder *const coder, const uint32_t pos,
23 const uint32_t prev_byte, const bool match_mode,
24 uint32_t match_byte, uint32_t symbol)
25{
26 const probability *const subcoder = literal_subcoder(coder->literal,
27 coder->literal_context_bits, coder->literal_pos_mask,
28 pos, prev_byte);
29
30 uint32_t price = 0;
31
32 if (!match_mode) {
33 price = rc_bittree_price(subcoder, 8, symbol);
34 } else {
35 uint32_t offset = 0x100;
36 symbol += UINT32_C(1) << 8;
37
38 do {
39 match_byte <<= 1;
40
41 const uint32_t match_bit = match_byte & offset;
42 const uint32_t subcoder_index
43 = offset + match_bit + (symbol >> 8);
44 const uint32_t bit = (symbol >> 7) & 1;
45 price += rc_bit_price(subcoder[subcoder_index], bit);
46
47 symbol <<= 1;
48 offset &= ~(match_byte ^ symbol);
49
50 } while (symbol < (UINT32_C(1) << 16));
51 }
52
53 return price;
54}
55
56
57static inline uint32_t
58get_len_price(const lzma_length_encoder *const lencoder,
59 const uint32_t len, const uint32_t pos_state)
60{
61 // NOTE: Unlike the other price tables, length prices are updated
62 // in lzma_encoder.c
63 return lencoder->prices[pos_state][len - MATCH_LEN_MIN];
64}
65
66
67static inline uint32_t
68get_short_rep_price(const lzma_lzma1_encoder *const coder,
69 const lzma_lzma_state state, const uint32_t pos_state)
70{
71 return rc_bit_0_price(coder->is_rep0[state])
72 + rc_bit_0_price(coder->is_rep0_long[state][pos_state]);
73}
74
75
76static inline uint32_t
77get_pure_rep_price(const lzma_lzma1_encoder *const coder, const uint32_t rep_index,
78 const lzma_lzma_state state, uint32_t pos_state)
79{
80 uint32_t price;
81
82 if (rep_index == 0) {
83 price = rc_bit_0_price(coder->is_rep0[state]);
84 price += rc_bit_1_price(coder->is_rep0_long[state][pos_state]);
85 } else {
86 price = rc_bit_1_price(coder->is_rep0[state]);
87
88 if (rep_index == 1) {
89 price += rc_bit_0_price(coder->is_rep1[state]);
90 } else {
91 price += rc_bit_1_price(coder->is_rep1[state]);
92 price += rc_bit_price(coder->is_rep2[state],
93 rep_index - 2);
94 }
95 }
96
97 return price;
98}
99
100
101static inline uint32_t
102get_rep_price(const lzma_lzma1_encoder *const coder, const uint32_t rep_index,
103 const uint32_t len, const lzma_lzma_state state,
104 const uint32_t pos_state)
105{
106 return get_len_price(&coder->rep_len_encoder, len, pos_state)
107 + get_pure_rep_price(coder, rep_index, state, pos_state);
108}
109
110
111static inline uint32_t
112get_dist_len_price(const lzma_lzma1_encoder *const coder, const uint32_t dist,
113 const uint32_t len, const uint32_t pos_state)
114{
115 const uint32_t dist_state = get_dist_state(len);
116 uint32_t price;
117
118 if (dist < FULL_DISTANCES) {
119 price = coder->dist_prices[dist_state][dist];
120 } else {
121 const uint32_t dist_slot = get_dist_slot_2(dist);
122 price = coder->dist_slot_prices[dist_state][dist_slot]
123 + coder->align_prices[dist & ALIGN_MASK];
124 }
125
126 price += get_len_price(&coder->match_len_encoder, len, pos_state);
127
128 return price;
129}
130
131
132static void
133fill_dist_prices(lzma_lzma1_encoder *coder)
134{
135 for (uint32_t dist_state = 0; dist_state < DIST_STATES; ++dist_state) {
136
137 uint32_t *const dist_slot_prices
138 = coder->dist_slot_prices[dist_state];
139
140 // Price to encode the dist_slot.
141 for (uint32_t dist_slot = 0;
142 dist_slot < coder->dist_table_size; ++dist_slot)
143 dist_slot_prices[dist_slot] = rc_bittree_price(
144 coder->dist_slot[dist_state],
145 DIST_SLOT_BITS, dist_slot);
146
147 // For matches with distance >= FULL_DISTANCES, add the price
148 // of the direct bits part of the match distance. (Align bits
149 // are handled by fill_align_prices()).
150 for (uint32_t dist_slot = DIST_MODEL_END;
151 dist_slot < coder->dist_table_size;
152 ++dist_slot)
153 dist_slot_prices[dist_slot] += rc_direct_price(
154 ((dist_slot >> 1) - 1) - ALIGN_BITS);
155
156 // Distances in the range [0, 3] are fully encoded with
157 // dist_slot, so they are used for coder->dist_prices
158 // as is.
159 for (uint32_t i = 0; i < DIST_MODEL_START; ++i)
160 coder->dist_prices[dist_state][i]
161 = dist_slot_prices[i];
162 }
163
164 // Distances in the range [4, 127] depend on dist_slot and
165 // dist_special. We do this in a loop separate from the above
166 // loop to avoid redundant calls to get_dist_slot().
167 for (uint32_t i = DIST_MODEL_START; i < FULL_DISTANCES; ++i) {
168 const uint32_t dist_slot = get_dist_slot(i);
169 const uint32_t footer_bits = ((dist_slot >> 1) - 1);
170 const uint32_t base = (2 | (dist_slot & 1)) << footer_bits;
171 const uint32_t price = rc_bittree_reverse_price(
172 coder->dist_special + base - dist_slot - 1,
173 footer_bits, i - base);
174
175 for (uint32_t dist_state = 0; dist_state < DIST_STATES;
176 ++dist_state)
177 coder->dist_prices[dist_state][i]
178 = price + coder->dist_slot_prices[
179 dist_state][dist_slot];
180 }
181
182 coder->match_price_count = 0;
183 return;
184}
185
186
187static void
188fill_align_prices(lzma_lzma1_encoder *coder)
189{
190 for (uint32_t i = 0; i < ALIGN_SIZE; ++i)
191 coder->align_prices[i] = rc_bittree_reverse_price(
192 coder->dist_align, ALIGN_BITS, i);
193
194 coder->align_price_count = 0;
195 return;
196}
197
198
199/////////////
200// Optimal //
201/////////////
202
203static inline void
204make_literal(lzma_optimal *optimal)
205{
206 optimal->back_prev = UINT32_MAX;
207 optimal->prev_1_is_literal = false;
208}
209
210
211static inline void
212make_short_rep(lzma_optimal *optimal)
213{
214 optimal->back_prev = 0;
215 optimal->prev_1_is_literal = false;
216}
217
218
219#define is_short_rep(optimal) \
220 ((optimal).back_prev == 0)
221
222
223static void
224backward(lzma_lzma1_encoder *restrict coder, uint32_t *restrict len_res,
225 uint32_t *restrict back_res, uint32_t cur)
226{
227 coder->opts_end_index = cur;
228
229 uint32_t pos_mem = coder->opts[cur].pos_prev;
230 uint32_t back_mem = coder->opts[cur].back_prev;
231
232 do {
233 if (coder->opts[cur].prev_1_is_literal) {
234 make_literal(&coder->opts[pos_mem]);
235 coder->opts[pos_mem].pos_prev = pos_mem - 1;
236
237 if (coder->opts[cur].prev_2) {
238 coder->opts[pos_mem - 1].prev_1_is_literal
239 = false;
240 coder->opts[pos_mem - 1].pos_prev
241 = coder->opts[cur].pos_prev_2;
242 coder->opts[pos_mem - 1].back_prev
243 = coder->opts[cur].back_prev_2;
244 }
245 }
246
247 const uint32_t pos_prev = pos_mem;
248 const uint32_t back_cur = back_mem;
249
250 back_mem = coder->opts[pos_prev].back_prev;
251 pos_mem = coder->opts[pos_prev].pos_prev;
252
253 coder->opts[pos_prev].back_prev = back_cur;
254 coder->opts[pos_prev].pos_prev = cur;
255 cur = pos_prev;
256
257 } while (cur != 0);
258
259 coder->opts_current_index = coder->opts[0].pos_prev;
260 *len_res = coder->opts[0].pos_prev;
261 *back_res = coder->opts[0].back_prev;
262
263 return;
264}
265
266
267//////////
268// Main //
269//////////
270
271static inline uint32_t
272helper1(lzma_lzma1_encoder *restrict coder, lzma_mf *restrict mf,
273 uint32_t *restrict back_res, uint32_t *restrict len_res,
274 uint32_t position)
275{
276 const uint32_t nice_len = mf->nice_len;
277
278 uint32_t len_main;
279 uint32_t matches_count;
280
281 if (mf->read_ahead == 0) {
282 len_main = mf_find(mf, &matches_count, coder->matches);
283 } else {
284 assert(mf->read_ahead == 1);
285 len_main = coder->longest_match_length;
286 matches_count = coder->matches_count;
287 }
288
289 const uint32_t buf_avail = my_min(mf_avail(mf) + 1, MATCH_LEN_MAX);
290 if (buf_avail < 2) {
291 *back_res = UINT32_MAX;
292 *len_res = 1;
293 return UINT32_MAX;
294 }
295
296 const uint8_t *const buf = mf_ptr(mf) - 1;
297
298 uint32_t rep_lens[REPS];
299 uint32_t rep_max_index = 0;
300
301 for (uint32_t i = 0; i < REPS; ++i) {
302 const uint8_t *const buf_back = buf - coder->reps[i] - 1;
303
304 if (not_equal_16(buf, buf_back)) {
305 rep_lens[i] = 0;
306 continue;
307 }
308
309 rep_lens[i] = lzma_memcmplen(buf, buf_back, 2, buf_avail);
310
311 if (rep_lens[i] > rep_lens[rep_max_index])
312 rep_max_index = i;
313 }
314
315 if (rep_lens[rep_max_index] >= nice_len) {
316 *back_res = rep_max_index;
317 *len_res = rep_lens[rep_max_index];
318 mf_skip(mf, *len_res - 1);
319 return UINT32_MAX;
320 }
321
322
323 if (len_main >= nice_len) {
324 *back_res = coder->matches[matches_count - 1].dist + REPS;
325 *len_res = len_main;
326 mf_skip(mf, len_main - 1);
327 return UINT32_MAX;
328 }
329
330 const uint8_t current_byte = *buf;
331 const uint8_t match_byte = *(buf - coder->reps[0] - 1);
332
333 if (len_main < 2 && current_byte != match_byte
334 && rep_lens[rep_max_index] < 2) {
335 *back_res = UINT32_MAX;
336 *len_res = 1;
337 return UINT32_MAX;
338 }
339
340 coder->opts[0].state = coder->state;
341
342 const uint32_t pos_state = position & coder->pos_mask;
343
344 coder->opts[1].price = rc_bit_0_price(
345 coder->is_match[coder->state][pos_state])
346 + get_literal_price(coder, position, buf[-1],
347 !is_literal_state(coder->state),
348 match_byte, current_byte);
349
350 make_literal(&coder->opts[1]);
351
352 const uint32_t match_price = rc_bit_1_price(
353 coder->is_match[coder->state][pos_state]);
354 const uint32_t rep_match_price = match_price
355 + rc_bit_1_price(coder->is_rep[coder->state]);
356
357 if (match_byte == current_byte) {
358 const uint32_t short_rep_price = rep_match_price
359 + get_short_rep_price(
360 coder, coder->state, pos_state);
361
362 if (short_rep_price < coder->opts[1].price) {
363 coder->opts[1].price = short_rep_price;
364 make_short_rep(&coder->opts[1]);
365 }
366 }
367
368 const uint32_t len_end = my_max(len_main, rep_lens[rep_max_index]);
369
370 if (len_end < 2) {
371 *back_res = coder->opts[1].back_prev;
372 *len_res = 1;
373 return UINT32_MAX;
374 }
375
376 coder->opts[1].pos_prev = 0;
377
378 for (uint32_t i = 0; i < REPS; ++i)
379 coder->opts[0].backs[i] = coder->reps[i];
380
381 uint32_t len = len_end;
382 do {
383 coder->opts[len].price = RC_INFINITY_PRICE;
384 } while (--len >= 2);
385
386
387 for (uint32_t i = 0; i < REPS; ++i) {
388 uint32_t rep_len = rep_lens[i];
389 if (rep_len < 2)
390 continue;
391
392 const uint32_t price = rep_match_price + get_pure_rep_price(
393 coder, i, coder->state, pos_state);
394
395 do {
396 const uint32_t cur_and_len_price = price
397 + get_len_price(
398 &coder->rep_len_encoder,
399 rep_len, pos_state);
400
401 if (cur_and_len_price < coder->opts[rep_len].price) {
402 coder->opts[rep_len].price = cur_and_len_price;
403 coder->opts[rep_len].pos_prev = 0;
404 coder->opts[rep_len].back_prev = i;
405 coder->opts[rep_len].prev_1_is_literal = false;
406 }
407 } while (--rep_len >= 2);
408 }
409
410
411 const uint32_t normal_match_price = match_price
412 + rc_bit_0_price(coder->is_rep[coder->state]);
413
414 len = rep_lens[0] >= 2 ? rep_lens[0] + 1 : 2;
415 if (len <= len_main) {
416 uint32_t i = 0;
417 while (len > coder->matches[i].len)
418 ++i;
419
420 for(; ; ++len) {
421 const uint32_t dist = coder->matches[i].dist;
422 const uint32_t cur_and_len_price = normal_match_price
423 + get_dist_len_price(coder,
424 dist, len, pos_state);
425
426 if (cur_and_len_price < coder->opts[len].price) {
427 coder->opts[len].price = cur_and_len_price;
428 coder->opts[len].pos_prev = 0;
429 coder->opts[len].back_prev = dist + REPS;
430 coder->opts[len].prev_1_is_literal = false;
431 }
432
433 if (len == coder->matches[i].len)
434 if (++i == matches_count)
435 break;
436 }
437 }
438
439 return len_end;
440}
441
442
443static inline uint32_t
444helper2(lzma_lzma1_encoder *coder, uint32_t *reps, const uint8_t *buf,
445 uint32_t len_end, uint32_t position, const uint32_t cur,
446 const uint32_t nice_len, const uint32_t buf_avail_full)
447{
448 uint32_t matches_count = coder->matches_count;
449 uint32_t new_len = coder->longest_match_length;
450 uint32_t pos_prev = coder->opts[cur].pos_prev;
451 lzma_lzma_state state;
452
453 if (coder->opts[cur].prev_1_is_literal) {
454 --pos_prev;
455
456 if (coder->opts[cur].prev_2) {
457 state = coder->opts[coder->opts[cur].pos_prev_2].state;
458
459 if (coder->opts[cur].back_prev_2 < REPS)
460 update_long_rep(state);
461 else
462 update_match(state);
463
464 } else {
465 state = coder->opts[pos_prev].state;
466 }
467
468 update_literal(state);
469
470 } else {
471 state = coder->opts[pos_prev].state;
472 }
473
474 if (pos_prev == cur - 1) {
475 if (is_short_rep(coder->opts[cur]))
476 update_short_rep(state);
477 else
478 update_literal(state);
479 } else {
480 uint32_t pos;
481 if (coder->opts[cur].prev_1_is_literal
482 && coder->opts[cur].prev_2) {
483 pos_prev = coder->opts[cur].pos_prev_2;
484 pos = coder->opts[cur].back_prev_2;
485 update_long_rep(state);
486 } else {
487 pos = coder->opts[cur].back_prev;
488 if (pos < REPS)
489 update_long_rep(state);
490 else
491 update_match(state);
492 }
493
494 if (pos < REPS) {
495 reps[0] = coder->opts[pos_prev].backs[pos];
496
497 uint32_t i;
498 for (i = 1; i <= pos; ++i)
499 reps[i] = coder->opts[pos_prev].backs[i - 1];
500
501 for (; i < REPS; ++i)
502 reps[i] = coder->opts[pos_prev].backs[i];
503
504 } else {
505 reps[0] = pos - REPS;
506
507 for (uint32_t i = 1; i < REPS; ++i)
508 reps[i] = coder->opts[pos_prev].backs[i - 1];
509 }
510 }
511
512 coder->opts[cur].state = state;
513
514 for (uint32_t i = 0; i < REPS; ++i)
515 coder->opts[cur].backs[i] = reps[i];
516
517 const uint32_t cur_price = coder->opts[cur].price;
518
519 const uint8_t current_byte = *buf;
520 const uint8_t match_byte = *(buf - reps[0] - 1);
521
522 const uint32_t pos_state = position & coder->pos_mask;
523
524 const uint32_t cur_and_1_price = cur_price
525 + rc_bit_0_price(coder->is_match[state][pos_state])
526 + get_literal_price(coder, position, buf[-1],
527 !is_literal_state(state), match_byte, current_byte);
528
529 bool next_is_literal = false;
530
531 if (cur_and_1_price < coder->opts[cur + 1].price) {
532 coder->opts[cur + 1].price = cur_and_1_price;
533 coder->opts[cur + 1].pos_prev = cur;
534 make_literal(&coder->opts[cur + 1]);
535 next_is_literal = true;
536 }
537
538 const uint32_t match_price = cur_price
539 + rc_bit_1_price(coder->is_match[state][pos_state]);
540 const uint32_t rep_match_price = match_price
541 + rc_bit_1_price(coder->is_rep[state]);
542
543 if (match_byte == current_byte
544 && !(coder->opts[cur + 1].pos_prev < cur
545 && coder->opts[cur + 1].back_prev == 0)) {
546
547 const uint32_t short_rep_price = rep_match_price
548 + get_short_rep_price(coder, state, pos_state);
549
550 if (short_rep_price <= coder->opts[cur + 1].price) {
551 coder->opts[cur + 1].price = short_rep_price;
552 coder->opts[cur + 1].pos_prev = cur;
553 make_short_rep(&coder->opts[cur + 1]);
554 next_is_literal = true;
555 }
556 }
557
558 if (buf_avail_full < 2)
559 return len_end;
560
561 const uint32_t buf_avail = my_min(buf_avail_full, nice_len);
562
563 if (!next_is_literal && match_byte != current_byte) { // speed optimization
564 // try literal + rep0
565 const uint8_t *const buf_back = buf - reps[0] - 1;
566 const uint32_t limit = my_min(buf_avail_full, nice_len + 1);
567
568 const uint32_t len_test = lzma_memcmplen(buf, buf_back, 1, limit) - 1;
569
570 if (len_test >= 2) {
571 lzma_lzma_state state_2 = state;
572 update_literal(state_2);
573
574 const uint32_t pos_state_next = (position + 1) & coder->pos_mask;
575 const uint32_t next_rep_match_price = cur_and_1_price
576 + rc_bit_1_price(coder->is_match[state_2][pos_state_next])
577 + rc_bit_1_price(coder->is_rep[state_2]);
578
579 //for (; len_test >= 2; --len_test) {
580 const uint32_t offset = cur + 1 + len_test;
581
582 while (len_end < offset)
583 coder->opts[++len_end].price = RC_INFINITY_PRICE;
584
585 const uint32_t cur_and_len_price = next_rep_match_price
586 + get_rep_price(coder, 0, len_test,
587 state_2, pos_state_next);
588
589 if (cur_and_len_price < coder->opts[offset].price) {
590 coder->opts[offset].price = cur_and_len_price;
591 coder->opts[offset].pos_prev = cur + 1;
592 coder->opts[offset].back_prev = 0;
593 coder->opts[offset].prev_1_is_literal = true;
594 coder->opts[offset].prev_2 = false;
595 }
596 //}
597 }
598 }
599
600
601 uint32_t start_len = 2; // speed optimization
602
603 for (uint32_t rep_index = 0; rep_index < REPS; ++rep_index) {
604 const uint8_t *const buf_back = buf - reps[rep_index] - 1;
605 if (not_equal_16(buf, buf_back))
606 continue;
607
608 uint32_t len_test = lzma_memcmplen(buf, buf_back, 2, buf_avail);
609
610 while (len_end < cur + len_test)
611 coder->opts[++len_end].price = RC_INFINITY_PRICE;
612
613 const uint32_t len_test_temp = len_test;
614 const uint32_t price = rep_match_price + get_pure_rep_price(
615 coder, rep_index, state, pos_state);
616
617 do {
618 const uint32_t cur_and_len_price = price
619 + get_len_price(&coder->rep_len_encoder,
620 len_test, pos_state);
621
622 if (cur_and_len_price < coder->opts[cur + len_test].price) {
623 coder->opts[cur + len_test].price = cur_and_len_price;
624 coder->opts[cur + len_test].pos_prev = cur;
625 coder->opts[cur + len_test].back_prev = rep_index;
626 coder->opts[cur + len_test].prev_1_is_literal = false;
627 }
628 } while (--len_test >= 2);
629
630 len_test = len_test_temp;
631
632 if (rep_index == 0)
633 start_len = len_test + 1;
634
635
636 uint32_t len_test_2 = len_test + 1;
637 const uint32_t limit = my_min(buf_avail_full,
638 len_test_2 + nice_len);
639 // NOTE: len_test_2 may be greater than limit so the call to
640 // lzma_memcmplen() must be done conditionally.
641 if (len_test_2 < limit)
642 len_test_2 = lzma_memcmplen(buf, buf_back, len_test_2, limit);
643
644 len_test_2 -= len_test + 1;
645
646 if (len_test_2 >= 2) {
647 lzma_lzma_state state_2 = state;
648 update_long_rep(state_2);
649
650 uint32_t pos_state_next = (position + len_test) & coder->pos_mask;
651
652 const uint32_t cur_and_len_literal_price = price
653 + get_len_price(&coder->rep_len_encoder,
654 len_test, pos_state)
655 + rc_bit_0_price(coder->is_match[state_2][pos_state_next])
656 + get_literal_price(coder, position + len_test,
657 buf[len_test - 1], true,
658 buf_back[len_test], buf[len_test]);
659
660 update_literal(state_2);
661
662 pos_state_next = (position + len_test + 1) & coder->pos_mask;
663
664 const uint32_t next_rep_match_price = cur_and_len_literal_price
665 + rc_bit_1_price(coder->is_match[state_2][pos_state_next])
666 + rc_bit_1_price(coder->is_rep[state_2]);
667
668 //for(; len_test_2 >= 2; len_test_2--) {
669 const uint32_t offset = cur + len_test + 1 + len_test_2;
670
671 while (len_end < offset)
672 coder->opts[++len_end].price = RC_INFINITY_PRICE;
673
674 const uint32_t cur_and_len_price = next_rep_match_price
675 + get_rep_price(coder, 0, len_test_2,
676 state_2, pos_state_next);
677
678 if (cur_and_len_price < coder->opts[offset].price) {
679 coder->opts[offset].price = cur_and_len_price;
680 coder->opts[offset].pos_prev = cur + len_test + 1;
681 coder->opts[offset].back_prev = 0;
682 coder->opts[offset].prev_1_is_literal = true;
683 coder->opts[offset].prev_2 = true;
684 coder->opts[offset].pos_prev_2 = cur;
685 coder->opts[offset].back_prev_2 = rep_index;
686 }
687 //}
688 }
689 }
690
691
692 //for (uint32_t len_test = 2; len_test <= new_len; ++len_test)
693 if (new_len > buf_avail) {
694 new_len = buf_avail;
695
696 matches_count = 0;
697 while (new_len > coder->matches[matches_count].len)
698 ++matches_count;
699
700 coder->matches[matches_count++].len = new_len;
701 }
702
703
704 if (new_len >= start_len) {
705 const uint32_t normal_match_price = match_price
706 + rc_bit_0_price(coder->is_rep[state]);
707
708 while (len_end < cur + new_len)
709 coder->opts[++len_end].price = RC_INFINITY_PRICE;
710
711 uint32_t i = 0;
712 while (start_len > coder->matches[i].len)
713 ++i;
714
715 for (uint32_t len_test = start_len; ; ++len_test) {
716 const uint32_t cur_back = coder->matches[i].dist;
717 uint32_t cur_and_len_price = normal_match_price
718 + get_dist_len_price(coder,
719 cur_back, len_test, pos_state);
720
721 if (cur_and_len_price < coder->opts[cur + len_test].price) {
722 coder->opts[cur + len_test].price = cur_and_len_price;
723 coder->opts[cur + len_test].pos_prev = cur;
724 coder->opts[cur + len_test].back_prev
725 = cur_back + REPS;
726 coder->opts[cur + len_test].prev_1_is_literal = false;
727 }
728
729 if (len_test == coder->matches[i].len) {
730 // Try Match + Literal + Rep0
731 const uint8_t *const buf_back = buf - cur_back - 1;
732 uint32_t len_test_2 = len_test + 1;
733 const uint32_t limit = my_min(buf_avail_full,
734 len_test_2 + nice_len);
735
736 // NOTE: len_test_2 may be greater than limit
737 // so the call to lzma_memcmplen() must be
738 // done conditionally.
739 if (len_test_2 < limit)
740 len_test_2 = lzma_memcmplen(buf, buf_back,
741 len_test_2, limit);
742
743 len_test_2 -= len_test + 1;
744
745 if (len_test_2 >= 2) {
746 lzma_lzma_state state_2 = state;
747 update_match(state_2);
748 uint32_t pos_state_next
749 = (position + len_test) & coder->pos_mask;
750
751 const uint32_t cur_and_len_literal_price = cur_and_len_price
752 + rc_bit_0_price(
753 coder->is_match[state_2][pos_state_next])
754 + get_literal_price(coder,
755 position + len_test,
756 buf[len_test - 1],
757 true,
758 buf_back[len_test],
759 buf[len_test]);
760
761 update_literal(state_2);
762 pos_state_next = (pos_state_next + 1) & coder->pos_mask;
763
764 const uint32_t next_rep_match_price
765 = cur_and_len_literal_price
766 + rc_bit_1_price(
767 coder->is_match[state_2][pos_state_next])
768 + rc_bit_1_price(coder->is_rep[state_2]);
769
770 // for(; len_test_2 >= 2; --len_test_2) {
771 const uint32_t offset = cur + len_test + 1 + len_test_2;
772
773 while (len_end < offset)
774 coder->opts[++len_end].price = RC_INFINITY_PRICE;
775
776 cur_and_len_price = next_rep_match_price
777 + get_rep_price(coder, 0, len_test_2,
778 state_2, pos_state_next);
779
780 if (cur_and_len_price < coder->opts[offset].price) {
781 coder->opts[offset].price = cur_and_len_price;
782 coder->opts[offset].pos_prev = cur + len_test + 1;
783 coder->opts[offset].back_prev = 0;
784 coder->opts[offset].prev_1_is_literal = true;
785 coder->opts[offset].prev_2 = true;
786 coder->opts[offset].pos_prev_2 = cur;
787 coder->opts[offset].back_prev_2
788 = cur_back + REPS;
789 }
790 //}
791 }
792
793 if (++i == matches_count)
794 break;
795 }
796 }
797 }
798
799 return len_end;
800}
801
802
803extern void
804lzma_lzma_optimum_normal(lzma_lzma1_encoder *restrict coder,
805 lzma_mf *restrict mf,
806 uint32_t *restrict back_res, uint32_t *restrict len_res,
807 uint32_t position)
808{
809 // If we have symbols pending, return the next pending symbol.
810 if (coder->opts_end_index != coder->opts_current_index) {
811 assert(mf->read_ahead > 0);
812 *len_res = coder->opts[coder->opts_current_index].pos_prev
813 - coder->opts_current_index;
814 *back_res = coder->opts[coder->opts_current_index].back_prev;
815 coder->opts_current_index = coder->opts[
816 coder->opts_current_index].pos_prev;
817 return;
818 }
819
820 // Update the price tables. In LZMA SDK <= 4.60 (and possibly later)
821 // this was done in both initialization function and in the main loop.
822 // In liblzma they were moved into this single place.
823 if (mf->read_ahead == 0) {
824 if (coder->match_price_count >= (1 << 7))
825 fill_dist_prices(coder);
826
827 if (coder->align_price_count >= ALIGN_SIZE)
828 fill_align_prices(coder);
829 }
830
831 // TODO: This needs quite a bit of cleaning still. But splitting
832 // the original function into two pieces makes it at least a little
833 // more readable, since those two parts don't share many variables.
834
835 uint32_t len_end = helper1(coder, mf, back_res, len_res, position);
836 if (len_end == UINT32_MAX)
837 return;
838
839 uint32_t reps[REPS];
840 memcpy(reps, coder->reps, sizeof(reps));
841
842 uint32_t cur;
843 for (cur = 1; cur < len_end; ++cur) {
844 assert(cur < OPTS);
845
846 coder->longest_match_length = mf_find(
847 mf, &coder->matches_count, coder->matches);
848
849 if (coder->longest_match_length >= mf->nice_len)
850 break;
851
852 len_end = helper2(coder, reps, mf_ptr(mf) - 1, len_end,
853 position + cur, cur, mf->nice_len,
854 my_min(mf_avail(mf) + 1, OPTS - 1 - cur));
855 }
856
857 backward(coder, len_res, back_res, cur);
858 return;
859}
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use