| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925 |
- ///////////////////////////////////////////////////////////////////////////////
- //
- /// \file lzma_encoder_optimum_normal.c
- //
- // Author: Igor Pavlov
- //
- // This file has been put into the public domain.
- // You can do whatever you want with this file.
- //
- ///////////////////////////////////////////////////////////////////////////////
- #include "lzma_encoder_private.h"
- #include "fastpos.h"
- ////////////
- // Prices //
- ////////////
- static uint32_t
- get_literal_price(const lzma_coder *const coder, const uint32_t pos,
- const uint32_t prev_byte, const bool match_mode,
- uint32_t match_byte, uint32_t symbol)
- {
- const probability *const subcoder = literal_subcoder(coder->literal,
- coder->literal_context_bits, coder->literal_pos_mask,
- pos, prev_byte);
- uint32_t price = 0;
- if (!match_mode) {
- price = rc_bittree_price(subcoder, 8, symbol);
- } else {
- uint32_t offset = 0x100;
- symbol += UINT32_C(1) << 8;
- do {
- uint32_t match_bit;
- uint32_t subcoder_index;
- uint32_t bit;
- match_byte <<= 1;
- match_bit = match_byte & offset;
- subcoder_index = offset + match_bit + (symbol >> 8);
- bit = (symbol >> 7) & 1;
- price += rc_bit_price(subcoder[subcoder_index], bit);
- symbol <<= 1;
- offset &= ~(match_byte ^ symbol);
- } while (symbol < (UINT32_C(1) << 16));
- }
- return price;
- }
- static inline uint32_t
- get_len_price(const lzma_length_encoder *const lencoder,
- const uint32_t len, const uint32_t pos_state)
- {
- // NOTE: Unlike the other price tables, length prices are updated
- // in lzma_encoder.c
- return lencoder->prices[pos_state][len - MATCH_LEN_MIN];
- }
- static inline uint32_t
- get_short_rep_price(const lzma_coder *const coder,
- const lzma_lzma_state state, const uint32_t pos_state)
- {
- return rc_bit_0_price(coder->is_rep0[state])
- + rc_bit_0_price(coder->is_rep0_long[state][pos_state]);
- }
- static inline uint32_t
- get_pure_rep_price(const lzma_coder *const coder, const uint32_t rep_index,
- const lzma_lzma_state state, uint32_t pos_state)
- {
- uint32_t price;
- if (rep_index == 0) {
- price = rc_bit_0_price(coder->is_rep0[state]);
- price += rc_bit_1_price(coder->is_rep0_long[state][pos_state]);
- } else {
- price = rc_bit_1_price(coder->is_rep0[state]);
- if (rep_index == 1) {
- price += rc_bit_0_price(coder->is_rep1[state]);
- } else {
- price += rc_bit_1_price(coder->is_rep1[state]);
- price += rc_bit_price(coder->is_rep2[state],
- rep_index - 2);
- }
- }
- return price;
- }
- static inline uint32_t
- get_rep_price(const lzma_coder *const coder, const uint32_t rep_index,
- const uint32_t len, const lzma_lzma_state state,
- const uint32_t pos_state)
- {
- return get_len_price(&coder->rep_len_encoder, len, pos_state)
- + get_pure_rep_price(coder, rep_index, state, pos_state);
- }
- static inline uint32_t
- get_pos_len_price(const lzma_coder *const coder, const uint32_t pos,
- const uint32_t len, const uint32_t pos_state)
- {
- const uint32_t len_to_pos_state = get_len_to_pos_state(len);
- uint32_t price;
- if (pos < FULL_DISTANCES) {
- price = coder->distances_prices[len_to_pos_state][pos];
- } else {
- const uint32_t pos_slot = get_pos_slot_2(pos);
- price = coder->pos_slot_prices[len_to_pos_state][pos_slot]
- + coder->align_prices[pos & ALIGN_MASK];
- }
- price += get_len_price(&coder->match_len_encoder, len, pos_state);
- return price;
- }
- static void
- fill_distances_prices(lzma_coder *coder)
- {
- uint32_t len_to_pos_state;
- uint32_t pos_slot;
- uint32_t i;
- for (len_to_pos_state = 0;
- len_to_pos_state < LEN_TO_POS_STATES;
- ++len_to_pos_state) {
- uint32_t *const pos_slot_prices
- = coder->pos_slot_prices[len_to_pos_state];
- // Price to encode the pos_slot.
- for (pos_slot = 0;
- pos_slot < coder->dist_table_size; ++pos_slot)
- pos_slot_prices[pos_slot] = rc_bittree_price(
- coder->pos_slot[len_to_pos_state],
- POS_SLOT_BITS, pos_slot);
- // For matches with distance >= FULL_DISTANCES, add the price
- // of the direct bits part of the match distance. (Align bits
- // are handled by fill_align_prices()).
- for (pos_slot = END_POS_MODEL_INDEX;
- pos_slot < coder->dist_table_size; ++pos_slot)
- pos_slot_prices[pos_slot] += rc_direct_price(
- ((pos_slot >> 1) - 1) - ALIGN_BITS);
- // Distances in the range [0, 3] are fully encoded with
- // pos_slot, so they are used for coder->distances_prices
- // as is.
- for (i = 0; i < START_POS_MODEL_INDEX; ++i)
- coder->distances_prices[len_to_pos_state][i]
- = pos_slot_prices[i];
- }
- // Distances in the range [4, 127] depend on pos_slot and pos_special.
- // We do this in a loop separate from the above loop to avoid
- // redundant calls to get_pos_slot().
- for (i = START_POS_MODEL_INDEX; i < FULL_DISTANCES; ++i) {
- const uint32_t pos_slot = get_pos_slot(i);
- const uint32_t footer_bits = ((pos_slot >> 1) - 1);
- const uint32_t base = (2 | (pos_slot & 1)) << footer_bits;
- const uint32_t price = rc_bittree_reverse_price(
- coder->pos_special + base - pos_slot - 1,
- footer_bits, i - base);
- for (len_to_pos_state = 0;
- len_to_pos_state < LEN_TO_POS_STATES;
- ++len_to_pos_state)
- coder->distances_prices[len_to_pos_state][i]
- = price + coder->pos_slot_prices[
- len_to_pos_state][pos_slot];
- }
- coder->match_price_count = 0;
- return;
- }
- static void
- fill_align_prices(lzma_coder *coder)
- {
- uint32_t i;
- for (i = 0; i < ALIGN_TABLE_SIZE; ++i)
- coder->align_prices[i] = rc_bittree_reverse_price(
- coder->pos_align, ALIGN_BITS, i);
- coder->align_price_count = 0;
- return;
- }
- /////////////
- // Optimal //
- /////////////
- static inline void
- make_literal(lzma_optimal *optimal)
- {
- optimal->back_prev = UINT32_MAX;
- optimal->prev_1_is_literal = false;
- }
- static inline void
- make_short_rep(lzma_optimal *optimal)
- {
- optimal->back_prev = 0;
- optimal->prev_1_is_literal = false;
- }
- #define is_short_rep(optimal) \
- ((optimal).back_prev == 0)
- static void
- backward(lzma_coder *LZMA_RESTRICT coder, uint32_t *LZMA_RESTRICT len_res,
- uint32_t *LZMA_RESTRICT back_res, uint32_t cur)
- {
- uint32_t pos_mem = coder->opts[cur].pos_prev;
- uint32_t back_mem = coder->opts[cur].back_prev;
- coder->opts_end_index = cur;
- do {
- const uint32_t pos_prev = pos_mem;
- const uint32_t back_cur = back_mem;
- if (coder->opts[cur].prev_1_is_literal) {
- make_literal(&coder->opts[pos_mem]);
- coder->opts[pos_mem].pos_prev = pos_mem - 1;
- if (coder->opts[cur].prev_2) {
- coder->opts[pos_mem - 1].prev_1_is_literal
- = false;
- coder->opts[pos_mem - 1].pos_prev
- = coder->opts[cur].pos_prev_2;
- coder->opts[pos_mem - 1].back_prev
- = coder->opts[cur].back_prev_2;
- }
- }
- back_mem = coder->opts[pos_prev].back_prev;
- pos_mem = coder->opts[pos_prev].pos_prev;
- coder->opts[pos_prev].back_prev = back_cur;
- coder->opts[pos_prev].pos_prev = cur;
- cur = pos_prev;
- } while (cur != 0);
- coder->opts_current_index = coder->opts[0].pos_prev;
- *len_res = coder->opts[0].pos_prev;
- *back_res = coder->opts[0].back_prev;
- return;
- }
- //////////
- // Main //
- //////////
- static inline uint32_t
- helper1(lzma_coder *LZMA_RESTRICT coder, lzma_mf *LZMA_RESTRICT mf,
- uint32_t *LZMA_RESTRICT back_res, uint32_t *LZMA_RESTRICT len_res,
- uint32_t position)
- {
- uint32_t buf_avail;
- const uint8_t *buf;
- uint32_t rep_lens[REP_DISTANCES];
- uint32_t rep_max_index = 0;
- uint32_t i;
- uint8_t current_byte;
- uint8_t match_byte;
- uint32_t pos_state;
- uint32_t match_price;
- uint32_t rep_match_price;
- uint32_t len_end;
- uint32_t len;
- uint32_t normal_match_price;
- const uint32_t nice_len = mf->nice_len;
- uint32_t len_main;
- uint32_t matches_count;
- if (mf->read_ahead == 0) {
- len_main = mf_find(mf, &matches_count, coder->matches);
- } else {
- assert(mf->read_ahead == 1);
- len_main = coder->longest_match_length;
- matches_count = coder->matches_count;
- }
- buf_avail = my_min(mf_avail(mf) + 1, MATCH_LEN_MAX);
- if (buf_avail < 2) {
- *back_res = UINT32_MAX;
- *len_res = 1;
- return UINT32_MAX;
- }
- buf = mf_ptr(mf) - 1;
- for (i = 0; i < REP_DISTANCES; ++i) {
- uint32_t len_test;
- const uint8_t *const buf_back = buf - coder->reps[i] - 1;
- if (not_equal_16(buf, buf_back)) {
- rep_lens[i] = 0;
- continue;
- }
- for (len_test = 2; len_test < buf_avail
- && buf[len_test] == buf_back[len_test];
- ++len_test) ;
- rep_lens[i] = len_test;
- if (len_test > rep_lens[rep_max_index])
- rep_max_index = i;
- }
- if (rep_lens[rep_max_index] >= nice_len) {
- *back_res = rep_max_index;
- *len_res = rep_lens[rep_max_index];
- mf_skip(mf, *len_res - 1);
- return UINT32_MAX;
- }
- if (len_main >= nice_len) {
- *back_res = coder->matches[matches_count - 1].dist
- + REP_DISTANCES;
- *len_res = len_main;
- mf_skip(mf, len_main - 1);
- return UINT32_MAX;
- }
- current_byte = *buf;
- match_byte = *(buf - coder->reps[0] - 1);
- if (len_main < 2 && current_byte != match_byte
- && rep_lens[rep_max_index] < 2) {
- *back_res = UINT32_MAX;
- *len_res = 1;
- return UINT32_MAX;
- }
- coder->opts[0].state = coder->state;
- pos_state = position & coder->pos_mask;
- coder->opts[1].price = rc_bit_0_price(
- coder->is_match[coder->state][pos_state])
- + get_literal_price(coder, position, buf[-1],
- !is_literal_state(coder->state),
- match_byte, current_byte);
- make_literal(&coder->opts[1]);
- match_price = rc_bit_1_price(
- coder->is_match[coder->state][pos_state]);
- rep_match_price = match_price
- + rc_bit_1_price(coder->is_rep[coder->state]);
- if (match_byte == current_byte) {
- const uint32_t short_rep_price = rep_match_price
- + get_short_rep_price(
- coder, coder->state, pos_state);
- if (short_rep_price < coder->opts[1].price) {
- coder->opts[1].price = short_rep_price;
- make_short_rep(&coder->opts[1]);
- }
- }
- len_end = my_max(len_main, rep_lens[rep_max_index]);
- if (len_end < 2) {
- *back_res = coder->opts[1].back_prev;
- *len_res = 1;
- return UINT32_MAX;
- }
- coder->opts[1].pos_prev = 0;
- for (i = 0; i < REP_DISTANCES; ++i)
- coder->opts[0].backs[i] = coder->reps[i];
- len = len_end;
- do {
- coder->opts[len].price = RC_INFINITY_PRICE;
- } while (--len >= 2);
- for (i = 0; i < REP_DISTANCES; ++i) {
- uint32_t price;
- uint32_t rep_len = rep_lens[i];
- if (rep_len < 2)
- continue;
- price = rep_match_price + get_pure_rep_price(
- coder, i, coder->state, pos_state);
- do {
- const uint32_t cur_and_len_price = price
- + get_len_price(
- &coder->rep_len_encoder,
- rep_len, pos_state);
- if (cur_and_len_price < coder->opts[rep_len].price) {
- coder->opts[rep_len].price = cur_and_len_price;
- coder->opts[rep_len].pos_prev = 0;
- coder->opts[rep_len].back_prev = i;
- coder->opts[rep_len].prev_1_is_literal = false;
- }
- } while (--rep_len >= 2);
- }
- normal_match_price = match_price
- + rc_bit_0_price(coder->is_rep[coder->state]);
- len = rep_lens[0] >= 2 ? rep_lens[0] + 1 : 2;
- if (len <= len_main) {
- uint32_t i = 0;
- while (len > coder->matches[i].len)
- ++i;
- for(; ; ++len) {
- const uint32_t dist = coder->matches[i].dist;
- const uint32_t cur_and_len_price = normal_match_price
- + get_pos_len_price(coder,
- dist, len, pos_state);
- if (cur_and_len_price < coder->opts[len].price) {
- coder->opts[len].price = cur_and_len_price;
- coder->opts[len].pos_prev = 0;
- coder->opts[len].back_prev
- = dist + REP_DISTANCES;
- coder->opts[len].prev_1_is_literal = false;
- }
- if (len == coder->matches[i].len)
- if (++i == matches_count)
- break;
- }
- }
- return len_end;
- }
- static inline uint32_t
- helper2(lzma_coder *coder, uint32_t *reps, const uint8_t *buf,
- uint32_t len_end, uint32_t position, const uint32_t cur,
- const uint32_t nice_len, const uint32_t buf_avail_full)
- {
- uint32_t matches_count = coder->matches_count;
- uint32_t new_len = coder->longest_match_length;
- uint32_t pos_prev = coder->opts[cur].pos_prev;
- lzma_lzma_state state;
- uint32_t buf_avail;
- uint32_t rep_index;
- uint32_t i;
- uint32_t cur_price;
- uint8_t current_byte;
- uint8_t match_byte;
- uint32_t pos_state;
- uint32_t cur_and_1_price;
- bool next_is_literal = false;
- uint32_t match_price;
- uint32_t rep_match_price;
- uint32_t start_len = 2;
- if (coder->opts[cur].prev_1_is_literal) {
- --pos_prev;
- if (coder->opts[cur].prev_2) {
- state = coder->opts[coder->opts[cur].pos_prev_2].state;
- if (coder->opts[cur].back_prev_2 < REP_DISTANCES)
- update_long_rep(state);
- else
- update_match(state);
- } else {
- state = coder->opts[pos_prev].state;
- }
- update_literal(state);
- } else {
- state = coder->opts[pos_prev].state;
- }
- if (pos_prev == cur - 1) {
- if (is_short_rep(coder->opts[cur]))
- update_short_rep(state);
- else
- update_literal(state);
- } else {
- uint32_t pos;
- if (coder->opts[cur].prev_1_is_literal
- && coder->opts[cur].prev_2) {
- pos_prev = coder->opts[cur].pos_prev_2;
- pos = coder->opts[cur].back_prev_2;
- update_long_rep(state);
- } else {
- pos = coder->opts[cur].back_prev;
- if (pos < REP_DISTANCES)
- update_long_rep(state);
- else
- update_match(state);
- }
- if (pos < REP_DISTANCES) {
- uint32_t i;
- reps[0] = coder->opts[pos_prev].backs[pos];
- for (i = 1; i <= pos; ++i)
- reps[i] = coder->opts[pos_prev].backs[i - 1];
- for (; i < REP_DISTANCES; ++i)
- reps[i] = coder->opts[pos_prev].backs[i];
- } else {
- reps[0] = pos - REP_DISTANCES;
- for (i = 1; i < REP_DISTANCES; ++i)
- reps[i] = coder->opts[pos_prev].backs[i - 1];
- }
- }
- coder->opts[cur].state = state;
- for (i = 0; i < REP_DISTANCES; ++i)
- coder->opts[cur].backs[i] = reps[i];
- cur_price = coder->opts[cur].price;
- current_byte = *buf;
- match_byte = *(buf - reps[0] - 1);
- pos_state = position & coder->pos_mask;
- cur_and_1_price = cur_price
- + rc_bit_0_price(coder->is_match[state][pos_state])
- + get_literal_price(coder, position, buf[-1],
- !is_literal_state(state), match_byte, current_byte);
- if (cur_and_1_price < coder->opts[cur + 1].price) {
- coder->opts[cur + 1].price = cur_and_1_price;
- coder->opts[cur + 1].pos_prev = cur;
- make_literal(&coder->opts[cur + 1]);
- next_is_literal = true;
- }
- match_price = cur_price
- + rc_bit_1_price(coder->is_match[state][pos_state]);
- rep_match_price = match_price
- + rc_bit_1_price(coder->is_rep[state]);
- if (match_byte == current_byte
- && !(coder->opts[cur + 1].pos_prev < cur
- && coder->opts[cur + 1].back_prev == 0)) {
- const uint32_t short_rep_price = rep_match_price
- + get_short_rep_price(coder, state, pos_state);
- if (short_rep_price <= coder->opts[cur + 1].price) {
- coder->opts[cur + 1].price = short_rep_price;
- coder->opts[cur + 1].pos_prev = cur;
- make_short_rep(&coder->opts[cur + 1]);
- next_is_literal = true;
- }
- }
- if (buf_avail_full < 2)
- return len_end;
- buf_avail = my_min(buf_avail_full, nice_len);
- if (!next_is_literal && match_byte != current_byte) { // speed optimization
- // try literal + rep0
- const uint8_t *const buf_back = buf - reps[0] - 1;
- const uint32_t limit = my_min(buf_avail_full, nice_len + 1);
- uint32_t len_test = 1;
- while (len_test < limit && buf[len_test] == buf_back[len_test])
- ++len_test;
- --len_test;
- if (len_test >= 2) {
- uint32_t pos_state_next;
- uint32_t next_rep_match_price;
- uint32_t offset;
- uint32_t cur_and_len_price;
- lzma_lzma_state state_2 = state;
- update_literal(state_2);
- pos_state_next = (position + 1) & coder->pos_mask;
- next_rep_match_price = cur_and_1_price
- + rc_bit_1_price(coder->is_match[state_2][pos_state_next])
- + rc_bit_1_price(coder->is_rep[state_2]);
- //for (; len_test >= 2; --len_test) {
- offset = cur + 1 + len_test;
- while (len_end < offset)
- coder->opts[++len_end].price = RC_INFINITY_PRICE;
- cur_and_len_price = next_rep_match_price
- + get_rep_price(coder, 0, len_test,
- state_2, pos_state_next);
- if (cur_and_len_price < coder->opts[offset].price) {
- coder->opts[offset].price = cur_and_len_price;
- coder->opts[offset].pos_prev = cur + 1;
- coder->opts[offset].back_prev = 0;
- coder->opts[offset].prev_1_is_literal = true;
- coder->opts[offset].prev_2 = false;
- }
- //}
- }
- }
- for (rep_index = 0; rep_index < REP_DISTANCES; ++rep_index) {
- uint32_t len_test, len_test_2, len_test_temp;
- uint32_t price, limit;
- const uint8_t *const buf_back = buf - reps[rep_index] - 1;
- if (not_equal_16(buf, buf_back))
- continue;
- for (len_test = 2; len_test < buf_avail
- && buf[len_test] == buf_back[len_test];
- ++len_test) ;
- while (len_end < cur + len_test)
- coder->opts[++len_end].price = RC_INFINITY_PRICE;
- len_test_temp = len_test;
- price = rep_match_price + get_pure_rep_price(
- coder, rep_index, state, pos_state);
- do {
- const uint32_t cur_and_len_price = price
- + get_len_price(&coder->rep_len_encoder,
- len_test, pos_state);
- if (cur_and_len_price < coder->opts[cur + len_test].price) {
- coder->opts[cur + len_test].price = cur_and_len_price;
- coder->opts[cur + len_test].pos_prev = cur;
- coder->opts[cur + len_test].back_prev = rep_index;
- coder->opts[cur + len_test].prev_1_is_literal = false;
- }
- } while (--len_test >= 2);
- len_test = len_test_temp;
- if (rep_index == 0)
- start_len = len_test + 1;
- len_test_2 = len_test + 1;
- limit = my_min(buf_avail_full,
- len_test_2 + nice_len);
- for (; len_test_2 < limit
- && buf[len_test_2] == buf_back[len_test_2];
- ++len_test_2) ;
- len_test_2 -= len_test + 1;
- if (len_test_2 >= 2) {
- uint32_t pos_state_next;
- uint32_t cur_and_len_literal_price;
- uint32_t next_rep_match_price;
- uint32_t offset;
- uint32_t cur_and_len_price;
- lzma_lzma_state state_2 = state;
- update_long_rep(state_2);
- pos_state_next = (position + len_test) & coder->pos_mask;
- cur_and_len_literal_price = price
- + get_len_price(&coder->rep_len_encoder,
- len_test, pos_state)
- + rc_bit_0_price(coder->is_match[state_2][pos_state_next])
- + get_literal_price(coder, position + len_test,
- buf[len_test - 1], true,
- buf_back[len_test], buf[len_test]);
- update_literal(state_2);
- pos_state_next = (position + len_test + 1) & coder->pos_mask;
- next_rep_match_price = cur_and_len_literal_price
- + rc_bit_1_price(coder->is_match[state_2][pos_state_next])
- + rc_bit_1_price(coder->is_rep[state_2]);
- //for(; len_test_2 >= 2; len_test_2--) {
- offset = cur + len_test + 1 + len_test_2;
- while (len_end < offset)
- coder->opts[++len_end].price = RC_INFINITY_PRICE;
- cur_and_len_price = next_rep_match_price
- + get_rep_price(coder, 0, len_test_2,
- state_2, pos_state_next);
- if (cur_and_len_price < coder->opts[offset].price) {
- coder->opts[offset].price = cur_and_len_price;
- coder->opts[offset].pos_prev = cur + len_test + 1;
- coder->opts[offset].back_prev = 0;
- coder->opts[offset].prev_1_is_literal = true;
- coder->opts[offset].prev_2 = true;
- coder->opts[offset].pos_prev_2 = cur;
- coder->opts[offset].back_prev_2 = rep_index;
- }
- //}
- }
- }
- //for (uint32_t len_test = 2; len_test <= new_len; ++len_test)
- if (new_len > buf_avail) {
- new_len = buf_avail;
- matches_count = 0;
- while (new_len > coder->matches[matches_count].len)
- ++matches_count;
- coder->matches[matches_count++].len = new_len;
- }
- if (new_len >= start_len) {
- uint32_t len_test;
- uint32_t i = 0;
- const uint32_t normal_match_price = match_price
- + rc_bit_0_price(coder->is_rep[state]);
- while (len_end < cur + new_len)
- coder->opts[++len_end].price = RC_INFINITY_PRICE;
- while (start_len > coder->matches[i].len)
- ++i;
- for (len_test = start_len; ; ++len_test) {
- const uint32_t cur_back = coder->matches[i].dist;
- uint32_t cur_and_len_price = normal_match_price
- + get_pos_len_price(coder,
- cur_back, len_test, pos_state);
- if (cur_and_len_price < coder->opts[cur + len_test].price) {
- coder->opts[cur + len_test].price = cur_and_len_price;
- coder->opts[cur + len_test].pos_prev = cur;
- coder->opts[cur + len_test].back_prev
- = cur_back + REP_DISTANCES;
- coder->opts[cur + len_test].prev_1_is_literal = false;
- }
- if (len_test == coder->matches[i].len) {
- // Try Match + Literal + Rep0
- const uint8_t *const buf_back = buf - cur_back - 1;
- uint32_t len_test_2 = len_test + 1;
- const uint32_t limit = my_min(buf_avail_full,
- len_test_2 + nice_len);
- for (; len_test_2 < limit &&
- buf[len_test_2] == buf_back[len_test_2];
- ++len_test_2) ;
- len_test_2 -= len_test + 1;
- if (len_test_2 >= 2) {
- uint32_t pos_state_next;
- uint32_t cur_and_len_literal_price;
- uint32_t next_rep_match_price;
- uint32_t offset;
- lzma_lzma_state state_2 = state;
- update_match(state_2);
- pos_state_next = (position + len_test) & coder->pos_mask;
- cur_and_len_literal_price = cur_and_len_price
- + rc_bit_0_price(
- coder->is_match[state_2][pos_state_next])
- + get_literal_price(coder,
- position + len_test,
- buf[len_test - 1],
- true,
- buf_back[len_test],
- buf[len_test]);
- update_literal(state_2);
- pos_state_next = (pos_state_next + 1) & coder->pos_mask;
- next_rep_match_price
- = cur_and_len_literal_price
- + rc_bit_1_price(
- coder->is_match[state_2][pos_state_next])
- + rc_bit_1_price(coder->is_rep[state_2]);
- // for(; len_test_2 >= 2; --len_test_2) {
- offset = cur + len_test + 1 + len_test_2;
- while (len_end < offset)
- coder->opts[++len_end].price = RC_INFINITY_PRICE;
- cur_and_len_price = next_rep_match_price
- + get_rep_price(coder, 0, len_test_2,
- state_2, pos_state_next);
- if (cur_and_len_price < coder->opts[offset].price) {
- coder->opts[offset].price = cur_and_len_price;
- coder->opts[offset].pos_prev = cur + len_test + 1;
- coder->opts[offset].back_prev = 0;
- coder->opts[offset].prev_1_is_literal = true;
- coder->opts[offset].prev_2 = true;
- coder->opts[offset].pos_prev_2 = cur;
- coder->opts[offset].back_prev_2
- = cur_back + REP_DISTANCES;
- }
- //}
- }
- if (++i == matches_count)
- break;
- }
- }
- }
- return len_end;
- }
- extern void
- lzma_lzma_optimum_normal(lzma_coder *LZMA_RESTRICT coder, lzma_mf *LZMA_RESTRICT mf,
- uint32_t *LZMA_RESTRICT back_res, uint32_t *LZMA_RESTRICT len_res,
- uint32_t position)
- {
- uint32_t reps[REP_DISTANCES];
- uint32_t len_end;
- uint32_t cur;
- // If we have symbols pending, return the next pending symbol.
- if (coder->opts_end_index != coder->opts_current_index) {
- assert(mf->read_ahead > 0);
- *len_res = coder->opts[coder->opts_current_index].pos_prev
- - coder->opts_current_index;
- *back_res = coder->opts[coder->opts_current_index].back_prev;
- coder->opts_current_index = coder->opts[
- coder->opts_current_index].pos_prev;
- return;
- }
- // Update the price tables. In LZMA SDK <= 4.60 (and possibly later)
- // this was done in both initialization function and in the main loop.
- // In liblzma they were moved into this single place.
- if (mf->read_ahead == 0) {
- if (coder->match_price_count >= (1 << 7))
- fill_distances_prices(coder);
- if (coder->align_price_count >= ALIGN_TABLE_SIZE)
- fill_align_prices(coder);
- }
- // TODO: This needs quite a bit of cleaning still. But splitting
- // the original function into two pieces makes it at least a little
- // more readable, since those two parts don't share many variables.
- len_end = helper1(coder, mf, back_res, len_res, position);
- if (len_end == UINT32_MAX)
- return;
- memcpy(reps, coder->reps, sizeof(reps));
- for (cur = 1; cur < len_end; ++cur) {
- assert(cur < OPTS);
- coder->longest_match_length = mf_find(
- mf, &coder->matches_count, coder->matches);
- if (coder->longest_match_length >= mf->nice_len)
- break;
- len_end = helper2(coder, reps, mf_ptr(mf) - 1, len_end,
- position + cur, cur, mf->nice_len,
- my_min(mf_avail(mf) + 1, OPTS - 1 - cur));
- }
- backward(coder, len_res, back_res, cur);
- return;
- }
|