Path: blob/master/Utilities/cmliblzma/liblzma/lzma/lzma_encoder_optimum_normal.c
3156 views
// SPDX-License-Identifier: 0BSD12///////////////////////////////////////////////////////////////////////////////3//4/// \file lzma_encoder_optimum_normal.c5//6// Author: Igor Pavlov7//8///////////////////////////////////////////////////////////////////////////////910#include "lzma_encoder_private.h"11#include "fastpos.h"12#include "memcmplen.h"131415////////////16// Prices //17////////////1819static uint32_t20get_literal_price(const lzma_lzma1_encoder *const coder, const uint32_t pos,21const uint32_t prev_byte, const bool match_mode,22uint32_t match_byte, uint32_t symbol)23{24const probability *const subcoder = literal_subcoder(coder->literal,25coder->literal_context_bits, coder->literal_mask,26pos, prev_byte);2728uint32_t price = 0;2930if (!match_mode) {31price = rc_bittree_price(subcoder, 8, symbol);32} else {33uint32_t offset = 0x100;34symbol += UINT32_C(1) << 8;3536do {37match_byte <<= 1;3839const uint32_t match_bit = match_byte & offset;40const uint32_t subcoder_index41= offset + match_bit + (symbol >> 8);42const uint32_t bit = (symbol >> 7) & 1;43price += rc_bit_price(subcoder[subcoder_index], bit);4445symbol <<= 1;46offset &= ~(match_byte ^ symbol);4748} while (symbol < (UINT32_C(1) << 16));49}5051return price;52}535455static inline uint32_t56get_len_price(const lzma_length_encoder *const lencoder,57const uint32_t len, const uint32_t pos_state)58{59// NOTE: Unlike the other price tables, length prices are updated60// in lzma_encoder.c61return lencoder->prices[pos_state][len - MATCH_LEN_MIN];62}636465static inline uint32_t66get_short_rep_price(const lzma_lzma1_encoder *const coder,67const lzma_lzma_state state, const uint32_t pos_state)68{69return rc_bit_0_price(coder->is_rep0[state])70+ rc_bit_0_price(coder->is_rep0_long[state][pos_state]);71}727374static inline uint32_t75get_pure_rep_price(const lzma_lzma1_encoder *const coder, const uint32_t rep_index,76const lzma_lzma_state state, uint32_t pos_state)77{78uint32_t price;7980if (rep_index == 0) {81price = rc_bit_0_price(coder->is_rep0[state]);82price += rc_bit_1_price(coder->is_rep0_long[state][pos_state]);83} else {84price = rc_bit_1_price(coder->is_rep0[state]);8586if (rep_index == 1) {87price += rc_bit_0_price(coder->is_rep1[state]);88} else {89price += rc_bit_1_price(coder->is_rep1[state]);90price += rc_bit_price(coder->is_rep2[state],91rep_index - 2);92}93}9495return price;96}979899static inline uint32_t100get_rep_price(const lzma_lzma1_encoder *const coder, const uint32_t rep_index,101const uint32_t len, const lzma_lzma_state state,102const uint32_t pos_state)103{104return get_len_price(&coder->rep_len_encoder, len, pos_state)105+ get_pure_rep_price(coder, rep_index, state, pos_state);106}107108109static inline uint32_t110get_dist_len_price(const lzma_lzma1_encoder *const coder, const uint32_t dist,111const uint32_t len, const uint32_t pos_state)112{113const uint32_t dist_state = get_dist_state(len);114uint32_t price;115116if (dist < FULL_DISTANCES) {117price = coder->dist_prices[dist_state][dist];118} else {119const uint32_t dist_slot = get_dist_slot_2(dist);120price = coder->dist_slot_prices[dist_state][dist_slot]121+ coder->align_prices[dist & ALIGN_MASK];122}123124price += get_len_price(&coder->match_len_encoder, len, pos_state);125126return price;127}128129130static void131fill_dist_prices(lzma_lzma1_encoder *coder)132{133for (uint32_t dist_state = 0; dist_state < DIST_STATES; ++dist_state) {134135uint32_t *const dist_slot_prices136= coder->dist_slot_prices[dist_state];137138// Price to encode the dist_slot.139for (uint32_t dist_slot = 0;140dist_slot < coder->dist_table_size; ++dist_slot)141dist_slot_prices[dist_slot] = rc_bittree_price(142coder->dist_slot[dist_state],143DIST_SLOT_BITS, dist_slot);144145// For matches with distance >= FULL_DISTANCES, add the price146// of the direct bits part of the match distance. (Align bits147// are handled by fill_align_prices()).148for (uint32_t dist_slot = DIST_MODEL_END;149dist_slot < coder->dist_table_size;150++dist_slot)151dist_slot_prices[dist_slot] += rc_direct_price(152((dist_slot >> 1) - 1) - ALIGN_BITS);153154// Distances in the range [0, 3] are fully encoded with155// dist_slot, so they are used for coder->dist_prices156// as is.157for (uint32_t i = 0; i < DIST_MODEL_START; ++i)158coder->dist_prices[dist_state][i]159= dist_slot_prices[i];160}161162// Distances in the range [4, 127] depend on dist_slot and163// dist_special. We do this in a loop separate from the above164// loop to avoid redundant calls to get_dist_slot().165for (uint32_t i = DIST_MODEL_START; i < FULL_DISTANCES; ++i) {166const uint32_t dist_slot = get_dist_slot(i);167const uint32_t footer_bits = ((dist_slot >> 1) - 1);168const uint32_t base = (2 | (dist_slot & 1)) << footer_bits;169const uint32_t price = rc_bittree_reverse_price(170coder->dist_special + base - dist_slot - 1,171footer_bits, i - base);172173for (uint32_t dist_state = 0; dist_state < DIST_STATES;174++dist_state)175coder->dist_prices[dist_state][i]176= price + coder->dist_slot_prices[177dist_state][dist_slot];178}179180coder->match_price_count = 0;181return;182}183184185static void186fill_align_prices(lzma_lzma1_encoder *coder)187{188for (uint32_t i = 0; i < ALIGN_SIZE; ++i)189coder->align_prices[i] = rc_bittree_reverse_price(190coder->dist_align, ALIGN_BITS, i);191192coder->align_price_count = 0;193return;194}195196197/////////////198// Optimal //199/////////////200201static inline void202make_literal(lzma_optimal *optimal)203{204optimal->back_prev = UINT32_MAX;205optimal->prev_1_is_literal = false;206}207208209static inline void210make_short_rep(lzma_optimal *optimal)211{212optimal->back_prev = 0;213optimal->prev_1_is_literal = false;214}215216217#define is_short_rep(optimal) \218((optimal).back_prev == 0)219220221static void222backward(lzma_lzma1_encoder *restrict coder, uint32_t *restrict len_res,223uint32_t *restrict back_res, uint32_t cur)224{225coder->opts_end_index = cur;226227uint32_t pos_mem = coder->opts[cur].pos_prev;228uint32_t back_mem = coder->opts[cur].back_prev;229230do {231if (coder->opts[cur].prev_1_is_literal) {232make_literal(&coder->opts[pos_mem]);233coder->opts[pos_mem].pos_prev = pos_mem - 1;234235if (coder->opts[cur].prev_2) {236coder->opts[pos_mem - 1].prev_1_is_literal237= false;238coder->opts[pos_mem - 1].pos_prev239= coder->opts[cur].pos_prev_2;240coder->opts[pos_mem - 1].back_prev241= coder->opts[cur].back_prev_2;242}243}244245const uint32_t pos_prev = pos_mem;246const uint32_t back_cur = back_mem;247248back_mem = coder->opts[pos_prev].back_prev;249pos_mem = coder->opts[pos_prev].pos_prev;250251coder->opts[pos_prev].back_prev = back_cur;252coder->opts[pos_prev].pos_prev = cur;253cur = pos_prev;254255} while (cur != 0);256257coder->opts_current_index = coder->opts[0].pos_prev;258*len_res = coder->opts[0].pos_prev;259*back_res = coder->opts[0].back_prev;260261return;262}263264265//////////266// Main //267//////////268269static inline uint32_t270helper1(lzma_lzma1_encoder *restrict coder, lzma_mf *restrict mf,271uint32_t *restrict back_res, uint32_t *restrict len_res,272uint32_t position)273{274const uint32_t nice_len = mf->nice_len;275276uint32_t len_main;277uint32_t matches_count;278279if (mf->read_ahead == 0) {280len_main = mf_find(mf, &matches_count, coder->matches);281} else {282assert(mf->read_ahead == 1);283len_main = coder->longest_match_length;284matches_count = coder->matches_count;285}286287const uint32_t buf_avail = my_min(mf_avail(mf) + 1, MATCH_LEN_MAX);288if (buf_avail < 2) {289*back_res = UINT32_MAX;290*len_res = 1;291return UINT32_MAX;292}293294const uint8_t *const buf = mf_ptr(mf) - 1;295296uint32_t rep_lens[REPS];297uint32_t rep_max_index = 0;298299for (uint32_t i = 0; i < REPS; ++i) {300const uint8_t *const buf_back = buf - coder->reps[i] - 1;301302if (not_equal_16(buf, buf_back)) {303rep_lens[i] = 0;304continue;305}306307rep_lens[i] = lzma_memcmplen(buf, buf_back, 2, buf_avail);308309if (rep_lens[i] > rep_lens[rep_max_index])310rep_max_index = i;311}312313if (rep_lens[rep_max_index] >= nice_len) {314*back_res = rep_max_index;315*len_res = rep_lens[rep_max_index];316mf_skip(mf, *len_res - 1);317return UINT32_MAX;318}319320321if (len_main >= nice_len) {322*back_res = coder->matches[matches_count - 1].dist + REPS;323*len_res = len_main;324mf_skip(mf, len_main - 1);325return UINT32_MAX;326}327328const uint8_t current_byte = *buf;329const uint8_t match_byte = *(buf - coder->reps[0] - 1);330331if (len_main < 2 && current_byte != match_byte332&& rep_lens[rep_max_index] < 2) {333*back_res = UINT32_MAX;334*len_res = 1;335return UINT32_MAX;336}337338coder->opts[0].state = coder->state;339340const uint32_t pos_state = position & coder->pos_mask;341342coder->opts[1].price = rc_bit_0_price(343coder->is_match[coder->state][pos_state])344+ get_literal_price(coder, position, buf[-1],345!is_literal_state(coder->state),346match_byte, current_byte);347348make_literal(&coder->opts[1]);349350const uint32_t match_price = rc_bit_1_price(351coder->is_match[coder->state][pos_state]);352const uint32_t rep_match_price = match_price353+ rc_bit_1_price(coder->is_rep[coder->state]);354355if (match_byte == current_byte) {356const uint32_t short_rep_price = rep_match_price357+ get_short_rep_price(358coder, coder->state, pos_state);359360if (short_rep_price < coder->opts[1].price) {361coder->opts[1].price = short_rep_price;362make_short_rep(&coder->opts[1]);363}364}365366const uint32_t len_end = my_max(len_main, rep_lens[rep_max_index]);367368if (len_end < 2) {369*back_res = coder->opts[1].back_prev;370*len_res = 1;371return UINT32_MAX;372}373374coder->opts[1].pos_prev = 0;375376for (uint32_t i = 0; i < REPS; ++i)377coder->opts[0].backs[i] = coder->reps[i];378379uint32_t len = len_end;380do {381coder->opts[len].price = RC_INFINITY_PRICE;382} while (--len >= 2);383384385for (uint32_t i = 0; i < REPS; ++i) {386uint32_t rep_len = rep_lens[i];387if (rep_len < 2)388continue;389390const uint32_t price = rep_match_price + get_pure_rep_price(391coder, i, coder->state, pos_state);392393do {394const uint32_t cur_and_len_price = price395+ get_len_price(396&coder->rep_len_encoder,397rep_len, pos_state);398399if (cur_and_len_price < coder->opts[rep_len].price) {400coder->opts[rep_len].price = cur_and_len_price;401coder->opts[rep_len].pos_prev = 0;402coder->opts[rep_len].back_prev = i;403coder->opts[rep_len].prev_1_is_literal = false;404}405} while (--rep_len >= 2);406}407408409const uint32_t normal_match_price = match_price410+ rc_bit_0_price(coder->is_rep[coder->state]);411412len = rep_lens[0] >= 2 ? rep_lens[0] + 1 : 2;413if (len <= len_main) {414uint32_t i = 0;415while (len > coder->matches[i].len)416++i;417418for(; ; ++len) {419const uint32_t dist = coder->matches[i].dist;420const uint32_t cur_and_len_price = normal_match_price421+ get_dist_len_price(coder,422dist, len, pos_state);423424if (cur_and_len_price < coder->opts[len].price) {425coder->opts[len].price = cur_and_len_price;426coder->opts[len].pos_prev = 0;427coder->opts[len].back_prev = dist + REPS;428coder->opts[len].prev_1_is_literal = false;429}430431if (len == coder->matches[i].len)432if (++i == matches_count)433break;434}435}436437return len_end;438}439440441static inline uint32_t442helper2(lzma_lzma1_encoder *coder, uint32_t *reps, const uint8_t *buf,443uint32_t len_end, uint32_t position, const uint32_t cur,444const uint32_t nice_len, const uint32_t buf_avail_full)445{446uint32_t matches_count = coder->matches_count;447uint32_t new_len = coder->longest_match_length;448uint32_t pos_prev = coder->opts[cur].pos_prev;449lzma_lzma_state state;450451if (coder->opts[cur].prev_1_is_literal) {452--pos_prev;453454if (coder->opts[cur].prev_2) {455state = coder->opts[coder->opts[cur].pos_prev_2].state;456457if (coder->opts[cur].back_prev_2 < REPS)458update_long_rep(state);459else460update_match(state);461462} else {463state = coder->opts[pos_prev].state;464}465466update_literal(state);467468} else {469state = coder->opts[pos_prev].state;470}471472if (pos_prev == cur - 1) {473if (is_short_rep(coder->opts[cur]))474update_short_rep(state);475else476update_literal(state);477} else {478uint32_t pos;479if (coder->opts[cur].prev_1_is_literal480&& coder->opts[cur].prev_2) {481pos_prev = coder->opts[cur].pos_prev_2;482pos = coder->opts[cur].back_prev_2;483update_long_rep(state);484} else {485pos = coder->opts[cur].back_prev;486if (pos < REPS)487update_long_rep(state);488else489update_match(state);490}491492if (pos < REPS) {493reps[0] = coder->opts[pos_prev].backs[pos];494495uint32_t i;496for (i = 1; i <= pos; ++i)497reps[i] = coder->opts[pos_prev].backs[i - 1];498499for (; i < REPS; ++i)500reps[i] = coder->opts[pos_prev].backs[i];501502} else {503reps[0] = pos - REPS;504505for (uint32_t i = 1; i < REPS; ++i)506reps[i] = coder->opts[pos_prev].backs[i - 1];507}508}509510coder->opts[cur].state = state;511512for (uint32_t i = 0; i < REPS; ++i)513coder->opts[cur].backs[i] = reps[i];514515const uint32_t cur_price = coder->opts[cur].price;516517const uint8_t current_byte = *buf;518const uint8_t match_byte = *(buf - reps[0] - 1);519520const uint32_t pos_state = position & coder->pos_mask;521522const uint32_t cur_and_1_price = cur_price523+ rc_bit_0_price(coder->is_match[state][pos_state])524+ get_literal_price(coder, position, buf[-1],525!is_literal_state(state), match_byte, current_byte);526527bool next_is_literal = false;528529if (cur_and_1_price < coder->opts[cur + 1].price) {530coder->opts[cur + 1].price = cur_and_1_price;531coder->opts[cur + 1].pos_prev = cur;532make_literal(&coder->opts[cur + 1]);533next_is_literal = true;534}535536const uint32_t match_price = cur_price537+ rc_bit_1_price(coder->is_match[state][pos_state]);538const uint32_t rep_match_price = match_price539+ rc_bit_1_price(coder->is_rep[state]);540541if (match_byte == current_byte542&& !(coder->opts[cur + 1].pos_prev < cur543&& coder->opts[cur + 1].back_prev == 0)) {544545const uint32_t short_rep_price = rep_match_price546+ get_short_rep_price(coder, state, pos_state);547548if (short_rep_price <= coder->opts[cur + 1].price) {549coder->opts[cur + 1].price = short_rep_price;550coder->opts[cur + 1].pos_prev = cur;551make_short_rep(&coder->opts[cur + 1]);552next_is_literal = true;553}554}555556if (buf_avail_full < 2)557return len_end;558559const uint32_t buf_avail = my_min(buf_avail_full, nice_len);560561if (!next_is_literal && match_byte != current_byte) { // speed optimization562// try literal + rep0563const uint8_t *const buf_back = buf - reps[0] - 1;564const uint32_t limit = my_min(buf_avail_full, nice_len + 1);565566const uint32_t len_test = lzma_memcmplen(buf, buf_back, 1, limit) - 1;567568if (len_test >= 2) {569lzma_lzma_state state_2 = state;570update_literal(state_2);571572const uint32_t pos_state_next = (position + 1) & coder->pos_mask;573const uint32_t next_rep_match_price = cur_and_1_price574+ rc_bit_1_price(coder->is_match[state_2][pos_state_next])575+ rc_bit_1_price(coder->is_rep[state_2]);576577//for (; len_test >= 2; --len_test) {578const uint32_t offset = cur + 1 + len_test;579580while (len_end < offset)581coder->opts[++len_end].price = RC_INFINITY_PRICE;582583const uint32_t cur_and_len_price = next_rep_match_price584+ get_rep_price(coder, 0, len_test,585state_2, pos_state_next);586587if (cur_and_len_price < coder->opts[offset].price) {588coder->opts[offset].price = cur_and_len_price;589coder->opts[offset].pos_prev = cur + 1;590coder->opts[offset].back_prev = 0;591coder->opts[offset].prev_1_is_literal = true;592coder->opts[offset].prev_2 = false;593}594//}595}596}597598599uint32_t start_len = 2; // speed optimization600601for (uint32_t rep_index = 0; rep_index < REPS; ++rep_index) {602const uint8_t *const buf_back = buf - reps[rep_index] - 1;603if (not_equal_16(buf, buf_back))604continue;605606uint32_t len_test = lzma_memcmplen(buf, buf_back, 2, buf_avail);607608while (len_end < cur + len_test)609coder->opts[++len_end].price = RC_INFINITY_PRICE;610611const uint32_t len_test_temp = len_test;612const uint32_t price = rep_match_price + get_pure_rep_price(613coder, rep_index, state, pos_state);614615do {616const uint32_t cur_and_len_price = price617+ get_len_price(&coder->rep_len_encoder,618len_test, pos_state);619620if (cur_and_len_price < coder->opts[cur + len_test].price) {621coder->opts[cur + len_test].price = cur_and_len_price;622coder->opts[cur + len_test].pos_prev = cur;623coder->opts[cur + len_test].back_prev = rep_index;624coder->opts[cur + len_test].prev_1_is_literal = false;625}626} while (--len_test >= 2);627628len_test = len_test_temp;629630if (rep_index == 0)631start_len = len_test + 1;632633634uint32_t len_test_2 = len_test + 1;635const uint32_t limit = my_min(buf_avail_full,636len_test_2 + nice_len);637// NOTE: len_test_2 may be greater than limit so the call to638// lzma_memcmplen() must be done conditionally.639if (len_test_2 < limit)640len_test_2 = lzma_memcmplen(buf, buf_back, len_test_2, limit);641642len_test_2 -= len_test + 1;643644if (len_test_2 >= 2) {645lzma_lzma_state state_2 = state;646update_long_rep(state_2);647648uint32_t pos_state_next = (position + len_test) & coder->pos_mask;649650const uint32_t cur_and_len_literal_price = price651+ get_len_price(&coder->rep_len_encoder,652len_test, pos_state)653+ rc_bit_0_price(coder->is_match[state_2][pos_state_next])654+ get_literal_price(coder, position + len_test,655buf[len_test - 1], true,656buf_back[len_test], buf[len_test]);657658update_literal(state_2);659660pos_state_next = (position + len_test + 1) & coder->pos_mask;661662const uint32_t next_rep_match_price = cur_and_len_literal_price663+ rc_bit_1_price(coder->is_match[state_2][pos_state_next])664+ rc_bit_1_price(coder->is_rep[state_2]);665666//for(; len_test_2 >= 2; len_test_2--) {667const uint32_t offset = cur + len_test + 1 + len_test_2;668669while (len_end < offset)670coder->opts[++len_end].price = RC_INFINITY_PRICE;671672const uint32_t cur_and_len_price = next_rep_match_price673+ get_rep_price(coder, 0, len_test_2,674state_2, pos_state_next);675676if (cur_and_len_price < coder->opts[offset].price) {677coder->opts[offset].price = cur_and_len_price;678coder->opts[offset].pos_prev = cur + len_test + 1;679coder->opts[offset].back_prev = 0;680coder->opts[offset].prev_1_is_literal = true;681coder->opts[offset].prev_2 = true;682coder->opts[offset].pos_prev_2 = cur;683coder->opts[offset].back_prev_2 = rep_index;684}685//}686}687}688689690//for (uint32_t len_test = 2; len_test <= new_len; ++len_test)691if (new_len > buf_avail) {692new_len = buf_avail;693694matches_count = 0;695while (new_len > coder->matches[matches_count].len)696++matches_count;697698coder->matches[matches_count++].len = new_len;699}700701702if (new_len >= start_len) {703const uint32_t normal_match_price = match_price704+ rc_bit_0_price(coder->is_rep[state]);705706while (len_end < cur + new_len)707coder->opts[++len_end].price = RC_INFINITY_PRICE;708709uint32_t i = 0;710while (start_len > coder->matches[i].len)711++i;712713for (uint32_t len_test = start_len; ; ++len_test) {714const uint32_t cur_back = coder->matches[i].dist;715uint32_t cur_and_len_price = normal_match_price716+ get_dist_len_price(coder,717cur_back, len_test, pos_state);718719if (cur_and_len_price < coder->opts[cur + len_test].price) {720coder->opts[cur + len_test].price = cur_and_len_price;721coder->opts[cur + len_test].pos_prev = cur;722coder->opts[cur + len_test].back_prev723= cur_back + REPS;724coder->opts[cur + len_test].prev_1_is_literal = false;725}726727if (len_test == coder->matches[i].len) {728// Try Match + Literal + Rep0729const uint8_t *const buf_back = buf - cur_back - 1;730uint32_t len_test_2 = len_test + 1;731const uint32_t limit = my_min(buf_avail_full,732len_test_2 + nice_len);733734// NOTE: len_test_2 may be greater than limit735// so the call to lzma_memcmplen() must be736// done conditionally.737if (len_test_2 < limit)738len_test_2 = lzma_memcmplen(buf, buf_back,739len_test_2, limit);740741len_test_2 -= len_test + 1;742743if (len_test_2 >= 2) {744lzma_lzma_state state_2 = state;745update_match(state_2);746uint32_t pos_state_next747= (position + len_test) & coder->pos_mask;748749const uint32_t cur_and_len_literal_price = cur_and_len_price750+ rc_bit_0_price(751coder->is_match[state_2][pos_state_next])752+ get_literal_price(coder,753position + len_test,754buf[len_test - 1],755true,756buf_back[len_test],757buf[len_test]);758759update_literal(state_2);760pos_state_next = (pos_state_next + 1) & coder->pos_mask;761762const uint32_t next_rep_match_price763= cur_and_len_literal_price764+ rc_bit_1_price(765coder->is_match[state_2][pos_state_next])766+ rc_bit_1_price(coder->is_rep[state_2]);767768// for(; len_test_2 >= 2; --len_test_2) {769const uint32_t offset = cur + len_test + 1 + len_test_2;770771while (len_end < offset)772coder->opts[++len_end].price = RC_INFINITY_PRICE;773774cur_and_len_price = next_rep_match_price775+ get_rep_price(coder, 0, len_test_2,776state_2, pos_state_next);777778if (cur_and_len_price < coder->opts[offset].price) {779coder->opts[offset].price = cur_and_len_price;780coder->opts[offset].pos_prev = cur + len_test + 1;781coder->opts[offset].back_prev = 0;782coder->opts[offset].prev_1_is_literal = true;783coder->opts[offset].prev_2 = true;784coder->opts[offset].pos_prev_2 = cur;785coder->opts[offset].back_prev_2786= cur_back + REPS;787}788//}789}790791if (++i == matches_count)792break;793}794}795}796797return len_end;798}799800801extern void802lzma_lzma_optimum_normal(lzma_lzma1_encoder *restrict coder,803lzma_mf *restrict mf,804uint32_t *restrict back_res, uint32_t *restrict len_res,805uint32_t position)806{807// If we have symbols pending, return the next pending symbol.808if (coder->opts_end_index != coder->opts_current_index) {809assert(mf->read_ahead > 0);810*len_res = coder->opts[coder->opts_current_index].pos_prev811- coder->opts_current_index;812*back_res = coder->opts[coder->opts_current_index].back_prev;813coder->opts_current_index = coder->opts[814coder->opts_current_index].pos_prev;815return;816}817818// Update the price tables. In LZMA SDK <= 4.60 (and possibly later)819// this was done in both initialization function and in the main loop.820// In liblzma they were moved into this single place.821if (mf->read_ahead == 0) {822if (coder->match_price_count >= (1 << 7))823fill_dist_prices(coder);824825if (coder->align_price_count >= ALIGN_SIZE)826fill_align_prices(coder);827}828829// TODO: This needs quite a bit of cleaning still. But splitting830// the original function into two pieces makes it at least a little831// more readable, since those two parts don't share many variables.832833uint32_t len_end = helper1(coder, mf, back_res, len_res, position);834if (len_end == UINT32_MAX)835return;836837uint32_t reps[REPS];838memcpy(reps, coder->reps, sizeof(reps));839840uint32_t cur;841for (cur = 1; cur < len_end; ++cur) {842assert(cur < OPTS);843844coder->longest_match_length = mf_find(845mf, &coder->matches_count, coder->matches);846847if (coder->longest_match_length >= mf->nice_len)848break;849850len_end = helper2(coder, reps, mf_ptr(mf) - 1, len_end,851position + cur, cur, mf->nice_len,852my_min(mf_avail(mf) + 1, OPTS - 1 - cur));853}854855backward(coder, len_res, back_res, cur);856return;857}858859860