1*13d37d77SDavid du Colombier /* Clzip - LZMA lossless data compressor
2*13d37d77SDavid du Colombier Copyright (C) 2010-2017 Antonio Diaz Diaz.
3*13d37d77SDavid du Colombier
4*13d37d77SDavid du Colombier This program is free software: you can redistribute it and/or modify
5*13d37d77SDavid du Colombier it under the terms of the GNU General Public License as published by
6*13d37d77SDavid du Colombier the Free Software Foundation, either version 2 of the License, or
7*13d37d77SDavid du Colombier (at your option) any later version.
8*13d37d77SDavid du Colombier
9*13d37d77SDavid du Colombier This program is distributed in the hope that it will be useful,
10*13d37d77SDavid du Colombier but WITHOUT ANY WARRANTY; without even the implied warranty of
11*13d37d77SDavid du Colombier MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12*13d37d77SDavid du Colombier GNU General Public License for more details.
13*13d37d77SDavid du Colombier
14*13d37d77SDavid du Colombier You should have received a copy of the GNU General Public License
15*13d37d77SDavid du Colombier along with this program. If not, see <http://www.gnu.org/licenses/>. */
16*13d37d77SDavid du Colombier
17*13d37d77SDavid du Colombier #include "lzip.h"
18*13d37d77SDavid du Colombier #include "encoder_base.h"
19*13d37d77SDavid du Colombier #include "encoder.h"
20*13d37d77SDavid du Colombier
21*13d37d77SDavid du Colombier CRC32 crc32;
22*13d37d77SDavid du Colombier
23*13d37d77SDavid du Colombier /*
24*13d37d77SDavid du Colombier * starting at data[len] and data[len-delta], what's the longest match
25*13d37d77SDavid du Colombier * up to len_limit?
26*13d37d77SDavid du Colombier */
27*13d37d77SDavid du Colombier int
maxmatch(uchar * data,int delta,int len,int len_limit)28*13d37d77SDavid du Colombier maxmatch(uchar *data, int delta, int len, int len_limit)
29*13d37d77SDavid du Colombier {
30*13d37d77SDavid du Colombier uchar *pdel, *p;
31*13d37d77SDavid du Colombier
32*13d37d77SDavid du Colombier p = &data[len];
33*13d37d77SDavid du Colombier pdel = p - delta;
34*13d37d77SDavid du Colombier while (*pdel++ == *p++ && len < len_limit)
35*13d37d77SDavid du Colombier ++len;
36*13d37d77SDavid du Colombier return len;
37*13d37d77SDavid du Colombier }
38*13d37d77SDavid du Colombier
39*13d37d77SDavid du Colombier static int
findpairmaxlen(LZ_encoder * e,Pair ** pairsp,int * npairsp,int maxlen,int pos1,int len_limit,int min_pos,uchar * data,int np2,int np3)40*13d37d77SDavid du Colombier findpairmaxlen(LZ_encoder *e, Pair **pairsp, int *npairsp, int maxlen, int pos1,
41*13d37d77SDavid du Colombier int len_limit, int min_pos, uchar *data, int np2, int np3)
42*13d37d77SDavid du Colombier {
43*13d37d77SDavid du Colombier int num_pairs;
44*13d37d77SDavid du Colombier Pair *pairs;
45*13d37d77SDavid du Colombier
46*13d37d77SDavid du Colombier pairs = *pairsp;
47*13d37d77SDavid du Colombier num_pairs = *npairsp;
48*13d37d77SDavid du Colombier if (np2 > min_pos && e->eb.mb.buffer[np2-1] == data[0]) {
49*13d37d77SDavid du Colombier pairs[0].dis = e->eb.mb.pos - np2;
50*13d37d77SDavid du Colombier pairs[0].len = maxlen = 2;
51*13d37d77SDavid du Colombier num_pairs = 1;
52*13d37d77SDavid du Colombier }
53*13d37d77SDavid du Colombier if (np2 != np3 && np3 > min_pos && e->eb.mb.buffer[np3-1] == data[0]) {
54*13d37d77SDavid du Colombier maxlen = 3;
55*13d37d77SDavid du Colombier np2 = np3;
56*13d37d77SDavid du Colombier pairs[num_pairs].dis = e->eb.mb.pos - np2;
57*13d37d77SDavid du Colombier ++num_pairs;
58*13d37d77SDavid du Colombier }
59*13d37d77SDavid du Colombier if (num_pairs > 0) {
60*13d37d77SDavid du Colombier maxlen = maxmatch(data, pos1 - np2, maxlen, len_limit);
61*13d37d77SDavid du Colombier pairs[num_pairs-1].len = maxlen;
62*13d37d77SDavid du Colombier if (maxlen >= len_limit)
63*13d37d77SDavid du Colombier *pairsp = nil; /* done. now just skip */
64*13d37d77SDavid du Colombier }
65*13d37d77SDavid du Colombier if (maxlen < 3)
66*13d37d77SDavid du Colombier maxlen = 3;
67*13d37d77SDavid du Colombier *npairsp = num_pairs;
68*13d37d77SDavid du Colombier return maxlen;
69*13d37d77SDavid du Colombier }
70*13d37d77SDavid du Colombier
71*13d37d77SDavid du Colombier int
LZe_get_match_pairs(LZ_encoder * e,Pair * pairs)72*13d37d77SDavid du Colombier LZe_get_match_pairs(LZ_encoder *e, Pair *pairs)
73*13d37d77SDavid du Colombier {
74*13d37d77SDavid du Colombier int len = 0, len0, len1, maxlen, num_pairs, len_limit, avail;
75*13d37d77SDavid du Colombier int pos1, min_pos, cyclic_pos, delta, count, key2, key3, key4, newpos1;
76*13d37d77SDavid du Colombier int32_t *ptr0, *ptr1, *newptr, *prevpos;
77*13d37d77SDavid du Colombier uchar *data;
78*13d37d77SDavid du Colombier uchar *p;
79*13d37d77SDavid du Colombier unsigned tmp;
80*13d37d77SDavid du Colombier
81*13d37d77SDavid du Colombier len_limit = e->match_len_limit;
82*13d37d77SDavid du Colombier avail = Mb_avail_bytes(&e->eb.mb);
83*13d37d77SDavid du Colombier if (len_limit > avail) {
84*13d37d77SDavid du Colombier len_limit = avail;
85*13d37d77SDavid du Colombier if (len_limit < 4)
86*13d37d77SDavid du Colombier return 0;
87*13d37d77SDavid du Colombier }
88*13d37d77SDavid du Colombier
89*13d37d77SDavid du Colombier data = Mb_ptr_to_current_pos(&e->eb.mb);
90*13d37d77SDavid du Colombier tmp = crc32[data[0]] ^ data[1];
91*13d37d77SDavid du Colombier key2 = tmp & (Nprevpos2 - 1);
92*13d37d77SDavid du Colombier tmp ^= (unsigned)data[2] << 8;
93*13d37d77SDavid du Colombier key3 = Nprevpos2 + (tmp & (Nprevpos3 - 1));
94*13d37d77SDavid du Colombier key4 = Nprevpos2 + Nprevpos3 +
95*13d37d77SDavid du Colombier ((tmp ^ (crc32[data[3]] << 5)) & e->eb.mb.key4_mask);
96*13d37d77SDavid du Colombier
97*13d37d77SDavid du Colombier min_pos = (e->eb.mb.pos > e->eb.mb.dict_size) ?
98*13d37d77SDavid du Colombier e->eb.mb.pos - e->eb.mb.dict_size : 0;
99*13d37d77SDavid du Colombier pos1 = e->eb.mb.pos + 1;
100*13d37d77SDavid du Colombier prevpos = e->eb.mb.prev_positions;
101*13d37d77SDavid du Colombier maxlen = 0;
102*13d37d77SDavid du Colombier num_pairs = 0;
103*13d37d77SDavid du Colombier if (pairs)
104*13d37d77SDavid du Colombier maxlen = findpairmaxlen(e, &pairs, &num_pairs, maxlen, pos1,
105*13d37d77SDavid du Colombier len_limit, min_pos, data, prevpos[key2], prevpos[key3]);
106*13d37d77SDavid du Colombier newpos1 = prevpos[key4];
107*13d37d77SDavid du Colombier prevpos[key2] = prevpos[key3] = prevpos[key4] = pos1;
108*13d37d77SDavid du Colombier
109*13d37d77SDavid du Colombier cyclic_pos = e->eb.mb.cyclic_pos;
110*13d37d77SDavid du Colombier ptr0 = e->eb.mb.pos_array + (cyclic_pos << 1);
111*13d37d77SDavid du Colombier ptr1 = ptr0 + 1;
112*13d37d77SDavid du Colombier len0 = len1 = 0;
113*13d37d77SDavid du Colombier for (count = e->cycles; ;) {
114*13d37d77SDavid du Colombier if (newpos1 <= min_pos || --count < 0) {
115*13d37d77SDavid du Colombier *ptr0 = *ptr1 = 0;
116*13d37d77SDavid du Colombier break;
117*13d37d77SDavid du Colombier }
118*13d37d77SDavid du Colombier
119*13d37d77SDavid du Colombier delta = pos1 - newpos1;
120*13d37d77SDavid du Colombier newptr = e->eb.mb.pos_array + ((cyclic_pos - delta +
121*13d37d77SDavid du Colombier (cyclic_pos >= delta? 0: e->eb.mb.dict_size + 1)) << 1);
122*13d37d77SDavid du Colombier p = &data[len];
123*13d37d77SDavid du Colombier if (p[-delta] == *p) {
124*13d37d77SDavid du Colombier len = maxmatch(data, delta, len + 1, len_limit);
125*13d37d77SDavid du Colombier if (pairs && maxlen < len) {
126*13d37d77SDavid du Colombier pairs[num_pairs].dis = delta - 1;
127*13d37d77SDavid du Colombier pairs[num_pairs].len = maxlen = len;
128*13d37d77SDavid du Colombier ++num_pairs;
129*13d37d77SDavid du Colombier }
130*13d37d77SDavid du Colombier if (len >= len_limit) {
131*13d37d77SDavid du Colombier *ptr0 = newptr[0];
132*13d37d77SDavid du Colombier *ptr1 = newptr[1];
133*13d37d77SDavid du Colombier break;
134*13d37d77SDavid du Colombier }
135*13d37d77SDavid du Colombier p = &data[len];
136*13d37d77SDavid du Colombier }
137*13d37d77SDavid du Colombier if (p[-delta] < *p) {
138*13d37d77SDavid du Colombier *ptr0 = newpos1;
139*13d37d77SDavid du Colombier ptr0 = newptr + 1;
140*13d37d77SDavid du Colombier newpos1 = *ptr0;
141*13d37d77SDavid du Colombier len0 = len;
142*13d37d77SDavid du Colombier if (len1 < len)
143*13d37d77SDavid du Colombier len = len1;
144*13d37d77SDavid du Colombier } else {
145*13d37d77SDavid du Colombier *ptr1 = newpos1;
146*13d37d77SDavid du Colombier ptr1 = newptr;
147*13d37d77SDavid du Colombier newpos1 = *ptr1;
148*13d37d77SDavid du Colombier len1 = len;
149*13d37d77SDavid du Colombier if (len0 < len)
150*13d37d77SDavid du Colombier len = len0;
151*13d37d77SDavid du Colombier }
152*13d37d77SDavid du Colombier }
153*13d37d77SDavid du Colombier return num_pairs;
154*13d37d77SDavid du Colombier }
155*13d37d77SDavid du Colombier
156*13d37d77SDavid du Colombier static void
LZe_update_distance_prices(LZ_encoder * e)157*13d37d77SDavid du Colombier LZe_update_distance_prices(LZ_encoder *e)
158*13d37d77SDavid du Colombier {
159*13d37d77SDavid du Colombier int dis, len_state;
160*13d37d77SDavid du Colombier
161*13d37d77SDavid du Colombier for (dis = start_dis_model; dis < modeled_distances; ++dis) {
162*13d37d77SDavid du Colombier int dis_slot = dis_slots[dis];
163*13d37d77SDavid du Colombier int direct_bits = (dis_slot >> 1) - 1;
164*13d37d77SDavid du Colombier int base = (2 | (dis_slot & 1)) << direct_bits;
165*13d37d77SDavid du Colombier int price = price_symbol_reversed(e->eb.bm_dis + (base - dis_slot),
166*13d37d77SDavid du Colombier dis - base, direct_bits);
167*13d37d77SDavid du Colombier
168*13d37d77SDavid du Colombier for (len_state = 0; len_state < len_states; ++len_state)
169*13d37d77SDavid du Colombier e->dis_prices[len_state][dis] = price;
170*13d37d77SDavid du Colombier }
171*13d37d77SDavid du Colombier
172*13d37d77SDavid du Colombier for (len_state = 0; len_state < len_states; ++len_state) {
173*13d37d77SDavid du Colombier int *dsp = e->dis_slot_prices[len_state];
174*13d37d77SDavid du Colombier int *dp = e->dis_prices[len_state];
175*13d37d77SDavid du Colombier Bit_model * bmds = e->eb.bm_dis_slot[len_state];
176*13d37d77SDavid du Colombier int slot = 0;
177*13d37d77SDavid du Colombier
178*13d37d77SDavid du Colombier for (; slot < end_dis_model; ++slot)
179*13d37d77SDavid du Colombier dsp[slot] = price_symbol6(bmds, slot);
180*13d37d77SDavid du Colombier for (; slot < e->num_dis_slots; ++slot)
181*13d37d77SDavid du Colombier dsp[slot] = price_symbol6(bmds, slot) +
182*13d37d77SDavid du Colombier ((((slot >> 1) - 1) - dis_align_bits) << price_shift_bits);
183*13d37d77SDavid du Colombier
184*13d37d77SDavid du Colombier for (dis = 0; dis < start_dis_model; ++dis)
185*13d37d77SDavid du Colombier dp[dis] = dsp[dis];
186*13d37d77SDavid du Colombier for (; dis < modeled_distances; ++dis)
187*13d37d77SDavid du Colombier dp[dis] += dsp[dis_slots[dis]];
188*13d37d77SDavid du Colombier }
189*13d37d77SDavid du Colombier }
190*13d37d77SDavid du Colombier
191*13d37d77SDavid du Colombier static int
pricestate2(LZ_encoder * e,int price,int * ps2p,State * st2p,int len2)192*13d37d77SDavid du Colombier pricestate2(LZ_encoder *e, int price, int *ps2p, State *st2p, int len2)
193*13d37d77SDavid du Colombier {
194*13d37d77SDavid du Colombier int pos_state2;
195*13d37d77SDavid du Colombier State state2;
196*13d37d77SDavid du Colombier
197*13d37d77SDavid du Colombier state2 = *st2p;
198*13d37d77SDavid du Colombier pos_state2 = *ps2p;
199*13d37d77SDavid du Colombier
200*13d37d77SDavid du Colombier pos_state2 = (pos_state2 + 1) & pos_state_mask;
201*13d37d77SDavid du Colombier state2 = St_set_char(state2);
202*13d37d77SDavid du Colombier price += price1(e->eb.bm_match[state2][pos_state2]) +
203*13d37d77SDavid du Colombier price1(e->eb.bm_rep[state2]) +
204*13d37d77SDavid du Colombier LZe_price_rep0_len(e, len2, state2, pos_state2);
205*13d37d77SDavid du Colombier
206*13d37d77SDavid du Colombier *ps2p = pos_state2;
207*13d37d77SDavid du Colombier *st2p = state2;
208*13d37d77SDavid du Colombier return price;
209*13d37d77SDavid du Colombier }
210*13d37d77SDavid du Colombier
211*13d37d77SDavid du Colombier static int
encinit(LZ_encoder * e,int reps[num_rep_distances],int replens[num_rep_distances],State state,int main_len,int num_pairs,int rep_index,int * ntrialsp)212*13d37d77SDavid du Colombier encinit(LZ_encoder *e, int reps[num_rep_distances],
213*13d37d77SDavid du Colombier int replens[num_rep_distances], State state, int main_len,
214*13d37d77SDavid du Colombier int num_pairs, int rep_index, int *ntrialsp)
215*13d37d77SDavid du Colombier {
216*13d37d77SDavid du Colombier int i, rep, num_trials, len;
217*13d37d77SDavid du Colombier int pos_state = Mb_data_position(&e->eb.mb) & pos_state_mask;
218*13d37d77SDavid du Colombier int match_price = price1(e->eb.bm_match[state][pos_state]);
219*13d37d77SDavid du Colombier int rep_match_price = match_price + price1(e->eb.bm_rep[state]);
220*13d37d77SDavid du Colombier uchar prev_byte = Mb_peek(&e->eb.mb, 1);
221*13d37d77SDavid du Colombier uchar cur_byte = Mb_peek(&e->eb.mb, 0);
222*13d37d77SDavid du Colombier uchar match_byte = Mb_peek(&e->eb.mb, reps[0] + 1);
223*13d37d77SDavid du Colombier
224*13d37d77SDavid du Colombier e->trials[1].price = price0(e->eb.bm_match[state][pos_state]);
225*13d37d77SDavid du Colombier if (St_is_char(state))
226*13d37d77SDavid du Colombier e->trials[1].price += LZeb_price_literal(&e->eb,
227*13d37d77SDavid du Colombier prev_byte, cur_byte);
228*13d37d77SDavid du Colombier else
229*13d37d77SDavid du Colombier e->trials[1].price += LZeb_price_matched(&e->eb,
230*13d37d77SDavid du Colombier prev_byte, cur_byte, match_byte);
231*13d37d77SDavid du Colombier e->trials[1].dis4 = -1; /* literal */
232*13d37d77SDavid du Colombier
233*13d37d77SDavid du Colombier if (match_byte == cur_byte)
234*13d37d77SDavid du Colombier Tr_update(&e->trials[1], rep_match_price +
235*13d37d77SDavid du Colombier LZeb_price_shortrep(&e->eb, state, pos_state), 0, 0);
236*13d37d77SDavid du Colombier num_trials = replens[rep_index];
237*13d37d77SDavid du Colombier if (num_trials < main_len)
238*13d37d77SDavid du Colombier num_trials = main_len;
239*13d37d77SDavid du Colombier *ntrialsp = num_trials;
240*13d37d77SDavid du Colombier if (num_trials < min_match_len) {
241*13d37d77SDavid du Colombier e->trials[0].price = 1;
242*13d37d77SDavid du Colombier e->trials[0].dis4 = e->trials[1].dis4;
243*13d37d77SDavid du Colombier Mb_move_pos(&e->eb.mb);
244*13d37d77SDavid du Colombier return 1;
245*13d37d77SDavid du Colombier }
246*13d37d77SDavid du Colombier
247*13d37d77SDavid du Colombier e->trials[0].state = state;
248*13d37d77SDavid du Colombier for (i = 0; i < num_rep_distances; ++i)
249*13d37d77SDavid du Colombier e->trials[0].reps[i] = reps[i];
250*13d37d77SDavid du Colombier
251*13d37d77SDavid du Colombier for (len = min_match_len; len <= num_trials; ++len)
252*13d37d77SDavid du Colombier e->trials[len].price = infinite_price;
253*13d37d77SDavid du Colombier
254*13d37d77SDavid du Colombier for (rep = 0; rep < num_rep_distances; ++rep) {
255*13d37d77SDavid du Colombier int price, replen;
256*13d37d77SDavid du Colombier
257*13d37d77SDavid du Colombier if (replens[rep] < min_match_len)
258*13d37d77SDavid du Colombier continue;
259*13d37d77SDavid du Colombier price = rep_match_price + LZeb_price_rep(&e->eb, rep,
260*13d37d77SDavid du Colombier state, pos_state);
261*13d37d77SDavid du Colombier replen = replens[rep];
262*13d37d77SDavid du Colombier for (len = min_match_len; len <= replen; ++len)
263*13d37d77SDavid du Colombier Tr_update(&e->trials[len], price +
264*13d37d77SDavid du Colombier Lp_price(&e->rep_len_prices, len, pos_state), rep, 0);
265*13d37d77SDavid du Colombier }
266*13d37d77SDavid du Colombier
267*13d37d77SDavid du Colombier if (main_len > replens[0]) {
268*13d37d77SDavid du Colombier int dis, normal_match_price = match_price +
269*13d37d77SDavid du Colombier price0(e->eb.bm_rep[state]);
270*13d37d77SDavid du Colombier int replp1 = replens[0] + 1;
271*13d37d77SDavid du Colombier int i = 0, len = max(replp1, min_match_len);
272*13d37d77SDavid du Colombier
273*13d37d77SDavid du Colombier while (len > e->pairs[i].len)
274*13d37d77SDavid du Colombier ++i;
275*13d37d77SDavid du Colombier for (;;) {
276*13d37d77SDavid du Colombier dis = e->pairs[i].dis;
277*13d37d77SDavid du Colombier Tr_update(&e->trials[len], normal_match_price +
278*13d37d77SDavid du Colombier LZe_price_pair(e, dis, len, pos_state),
279*13d37d77SDavid du Colombier dis + num_rep_distances, 0);
280*13d37d77SDavid du Colombier if (++len > e->pairs[i].len && ++i >= num_pairs)
281*13d37d77SDavid du Colombier break;
282*13d37d77SDavid du Colombier }
283*13d37d77SDavid du Colombier }
284*13d37d77SDavid du Colombier return 0;
285*13d37d77SDavid du Colombier }
286*13d37d77SDavid du Colombier
287*13d37d77SDavid du Colombier static void
finalvalues(LZ_encoder * e,int cur,Trial * cur_trial,State * cstatep)288*13d37d77SDavid du Colombier finalvalues(LZ_encoder *e, int cur, Trial *cur_trial, State *cstatep)
289*13d37d77SDavid du Colombier {
290*13d37d77SDavid du Colombier int i;
291*13d37d77SDavid du Colombier int dis4 = cur_trial->dis4;
292*13d37d77SDavid du Colombier int prev_index = cur_trial->prev_index;
293*13d37d77SDavid du Colombier int prev_index2 = cur_trial->prev_index2;
294*13d37d77SDavid du Colombier State cur_state;
295*13d37d77SDavid du Colombier
296*13d37d77SDavid du Colombier if (prev_index2 == single_step_trial) {
297*13d37d77SDavid du Colombier cur_state = e->trials[prev_index].state;
298*13d37d77SDavid du Colombier if (prev_index + 1 == cur) { /* len == 1 */
299*13d37d77SDavid du Colombier if (dis4 == 0)
300*13d37d77SDavid du Colombier cur_state = St_set_short_rep(cur_state);
301*13d37d77SDavid du Colombier else
302*13d37d77SDavid du Colombier cur_state = St_set_char(cur_state); /* literal */
303*13d37d77SDavid du Colombier } else if (dis4 < num_rep_distances)
304*13d37d77SDavid du Colombier cur_state = St_set_rep(cur_state);
305*13d37d77SDavid du Colombier else
306*13d37d77SDavid du Colombier cur_state = St_set_match(cur_state);
307*13d37d77SDavid du Colombier } else {
308*13d37d77SDavid du Colombier if (prev_index2 == dual_step_trial) /* dis4 == 0 (rep0) */
309*13d37d77SDavid du Colombier --prev_index;
310*13d37d77SDavid du Colombier else /* prev_index2 >= 0 */
311*13d37d77SDavid du Colombier prev_index = prev_index2;
312*13d37d77SDavid du Colombier cur_state = 8; /* St_set_char_rep(); */
313*13d37d77SDavid du Colombier }
314*13d37d77SDavid du Colombier cur_trial->state = cur_state;
315*13d37d77SDavid du Colombier for (i = 0; i < num_rep_distances; ++i)
316*13d37d77SDavid du Colombier cur_trial->reps[i] = e->trials[prev_index].reps[i];
317*13d37d77SDavid du Colombier mtf_reps(dis4, cur_trial->reps); /* literal is ignored */
318*13d37d77SDavid du Colombier *cstatep = cur_state;
319*13d37d77SDavid du Colombier }
320*13d37d77SDavid du Colombier
321*13d37d77SDavid du Colombier static int
litrep0(LZ_encoder * e,State cur_state,int cur,Trial * cur_trial,int num_trials,int triable_bytes,int pos_state,int next_price)322*13d37d77SDavid du Colombier litrep0(LZ_encoder *e, State cur_state, int cur, Trial *cur_trial,
323*13d37d77SDavid du Colombier int num_trials, int triable_bytes, int pos_state, int next_price)
324*13d37d77SDavid du Colombier {
325*13d37d77SDavid du Colombier int len = 1, endtrials, limit, mlpl1, dis;
326*13d37d77SDavid du Colombier uchar *data = Mb_ptr_to_current_pos(&e->eb.mb);
327*13d37d77SDavid du Colombier
328*13d37d77SDavid du Colombier dis = cur_trial->reps[0] + 1;
329*13d37d77SDavid du Colombier mlpl1 = e->match_len_limit + 1;
330*13d37d77SDavid du Colombier limit = min(mlpl1, triable_bytes);
331*13d37d77SDavid du Colombier len = maxmatch(data, dis, len, limit);
332*13d37d77SDavid du Colombier if (--len >= min_match_len) {
333*13d37d77SDavid du Colombier int pos_state2, price;
334*13d37d77SDavid du Colombier State state2;
335*13d37d77SDavid du Colombier
336*13d37d77SDavid du Colombier pos_state2 = (pos_state + 1) & pos_state_mask;
337*13d37d77SDavid du Colombier state2 = St_set_char(cur_state);
338*13d37d77SDavid du Colombier price = next_price + price1(e->eb.bm_match[state2][pos_state2])+
339*13d37d77SDavid du Colombier price1(e->eb.bm_rep[state2]) +
340*13d37d77SDavid du Colombier LZe_price_rep0_len(e, len, state2, pos_state2);
341*13d37d77SDavid du Colombier endtrials = cur + 1 + len;
342*13d37d77SDavid du Colombier while (num_trials < endtrials)
343*13d37d77SDavid du Colombier e->trials[++num_trials].price = infinite_price;
344*13d37d77SDavid du Colombier Tr_update2(&e->trials[endtrials], price, cur + 1);
345*13d37d77SDavid du Colombier }
346*13d37d77SDavid du Colombier return num_trials;
347*13d37d77SDavid du Colombier }
348*13d37d77SDavid du Colombier
349*13d37d77SDavid du Colombier static int
repdists(LZ_encoder * e,State cur_state,int cur,Trial * cur_trial,int num_trials,int triable_bytes,int pos_state,int rep_match_price,int len_limit,int * stlenp)350*13d37d77SDavid du Colombier repdists(LZ_encoder *e, State cur_state, int cur, Trial *cur_trial,
351*13d37d77SDavid du Colombier int num_trials, int triable_bytes, int pos_state,
352*13d37d77SDavid du Colombier int rep_match_price, int len_limit, int *stlenp)
353*13d37d77SDavid du Colombier {
354*13d37d77SDavid du Colombier int i, rep, len, price, dis, start_len;
355*13d37d77SDavid du Colombier
356*13d37d77SDavid du Colombier start_len = *stlenp;
357*13d37d77SDavid du Colombier for (rep = 0; rep < num_rep_distances; ++rep) {
358*13d37d77SDavid du Colombier uchar *data = Mb_ptr_to_current_pos(&e->eb.mb);
359*13d37d77SDavid du Colombier
360*13d37d77SDavid du Colombier dis = cur_trial->reps[rep] + 1;
361*13d37d77SDavid du Colombier if (data[0-dis] != data[0] || data[1-dis] != data[1])
362*13d37d77SDavid du Colombier continue;
363*13d37d77SDavid du Colombier len = maxmatch(data, dis, min_match_len, len_limit);
364*13d37d77SDavid du Colombier while (num_trials < cur + len)
365*13d37d77SDavid du Colombier e->trials[++num_trials].price = infinite_price;
366*13d37d77SDavid du Colombier price = rep_match_price + LZeb_price_rep(&e->eb, rep,
367*13d37d77SDavid du Colombier cur_state, pos_state);
368*13d37d77SDavid du Colombier for (i = min_match_len; i <= len; ++i)
369*13d37d77SDavid du Colombier Tr_update(&e->trials[cur+i], price +
370*13d37d77SDavid du Colombier Lp_price(&e->rep_len_prices, i, pos_state), rep, cur);
371*13d37d77SDavid du Colombier
372*13d37d77SDavid du Colombier if (rep == 0)
373*13d37d77SDavid du Colombier start_len = len + 1; /* discard shorter matches */
374*13d37d77SDavid du Colombier
375*13d37d77SDavid du Colombier /* try rep + literal + rep0 */
376*13d37d77SDavid du Colombier {
377*13d37d77SDavid du Colombier int pos_state2, endtrials, limit, mlpl2, len2;
378*13d37d77SDavid du Colombier State state2;
379*13d37d77SDavid du Colombier
380*13d37d77SDavid du Colombier len2 = len + 1;
381*13d37d77SDavid du Colombier mlpl2 = e->match_len_limit + len2;
382*13d37d77SDavid du Colombier limit = min(mlpl2, triable_bytes);
383*13d37d77SDavid du Colombier len2 = maxmatch(data, dis, len2, limit);
384*13d37d77SDavid du Colombier len2 -= len + 1;
385*13d37d77SDavid du Colombier if (len2 < min_match_len)
386*13d37d77SDavid du Colombier continue;
387*13d37d77SDavid du Colombier
388*13d37d77SDavid du Colombier pos_state2 = (pos_state + len) & pos_state_mask;
389*13d37d77SDavid du Colombier state2 = St_set_rep(cur_state);
390*13d37d77SDavid du Colombier price += Lp_price(&e->rep_len_prices, len, pos_state) +
391*13d37d77SDavid du Colombier price0(e->eb.bm_match[state2][pos_state2]) +
392*13d37d77SDavid du Colombier LZeb_price_matched(&e->eb, data[len-1],
393*13d37d77SDavid du Colombier data[len], data[len-dis]);
394*13d37d77SDavid du Colombier price = pricestate2(e, price, &pos_state2,
395*13d37d77SDavid du Colombier &state2, len2);
396*13d37d77SDavid du Colombier endtrials = cur + len + 1 + len2;
397*13d37d77SDavid du Colombier while (num_trials < endtrials)
398*13d37d77SDavid du Colombier e->trials[++num_trials].price = infinite_price;
399*13d37d77SDavid du Colombier Tr_update3(&e->trials[endtrials], price, rep,
400*13d37d77SDavid du Colombier endtrials - len2, cur);
401*13d37d77SDavid du Colombier }
402*13d37d77SDavid du Colombier }
403*13d37d77SDavid du Colombier *stlenp = start_len;
404*13d37d77SDavid du Colombier return num_trials;
405*13d37d77SDavid du Colombier }
406*13d37d77SDavid du Colombier
407*13d37d77SDavid du Colombier static int
trymatches(LZ_encoder * e,State cur_state,int cur,int num_trials,int triable_bytes,int pos_state,int num_pairs,int normal_match_price,int start_len)408*13d37d77SDavid du Colombier trymatches(LZ_encoder *e, State cur_state, int cur, int num_trials,
409*13d37d77SDavid du Colombier int triable_bytes, int pos_state, int num_pairs,
410*13d37d77SDavid du Colombier int normal_match_price, int start_len)
411*13d37d77SDavid du Colombier {
412*13d37d77SDavid du Colombier int i, dis, len, price;
413*13d37d77SDavid du Colombier
414*13d37d77SDavid du Colombier i = 0;
415*13d37d77SDavid du Colombier while (e->pairs[i].len < start_len)
416*13d37d77SDavid du Colombier ++i;
417*13d37d77SDavid du Colombier dis = e->pairs[i].dis;
418*13d37d77SDavid du Colombier for (len = start_len; ; ++len) {
419*13d37d77SDavid du Colombier price = normal_match_price + LZe_price_pair(e, dis, len, pos_state);
420*13d37d77SDavid du Colombier Tr_update(&e->trials[cur+len], price, dis + num_rep_distances, cur);
421*13d37d77SDavid du Colombier
422*13d37d77SDavid du Colombier /* try match + literal + rep0 */
423*13d37d77SDavid du Colombier if (len == e->pairs[i].len) {
424*13d37d77SDavid du Colombier uchar *data = Mb_ptr_to_current_pos(&e->eb.mb);
425*13d37d77SDavid du Colombier int endtrials, mlpl2, limit;
426*13d37d77SDavid du Colombier int dis2 = dis + 1, len2 = len + 1;
427*13d37d77SDavid du Colombier
428*13d37d77SDavid du Colombier mlpl2 = e->match_len_limit + len2;
429*13d37d77SDavid du Colombier limit = min(mlpl2, triable_bytes);
430*13d37d77SDavid du Colombier len2 = maxmatch(data, dis2, len2, limit);
431*13d37d77SDavid du Colombier len2 -= len + 1;
432*13d37d77SDavid du Colombier if (len2 >= min_match_len) {
433*13d37d77SDavid du Colombier int pos_state2 = (pos_state + len) &pos_state_mask;
434*13d37d77SDavid du Colombier State state2 = St_set_match(cur_state);
435*13d37d77SDavid du Colombier
436*13d37d77SDavid du Colombier price += price0(e->eb.bm_match[state2][pos_state2]) +
437*13d37d77SDavid du Colombier LZeb_price_matched(&e->eb, data[len-1], data[len], data[len-dis2]);
438*13d37d77SDavid du Colombier price = pricestate2(e, price,
439*13d37d77SDavid du Colombier &pos_state2, &state2, len2);
440*13d37d77SDavid du Colombier endtrials = cur + len + 1 + len2;
441*13d37d77SDavid du Colombier while (num_trials < endtrials)
442*13d37d77SDavid du Colombier e->trials[++num_trials].price = infinite_price;
443*13d37d77SDavid du Colombier Tr_update3(&e->trials[endtrials],
444*13d37d77SDavid du Colombier price, dis +
445*13d37d77SDavid du Colombier num_rep_distances,
446*13d37d77SDavid du Colombier endtrials - len2, cur);
447*13d37d77SDavid du Colombier }
448*13d37d77SDavid du Colombier if (++i >= num_pairs)
449*13d37d77SDavid du Colombier break;
450*13d37d77SDavid du Colombier dis = e->pairs[i].dis;
451*13d37d77SDavid du Colombier }
452*13d37d77SDavid du Colombier }
453*13d37d77SDavid du Colombier return num_trials;
454*13d37d77SDavid du Colombier }
455*13d37d77SDavid du Colombier
456*13d37d77SDavid du Colombier /*
457*13d37d77SDavid du Colombier * Returns the number of bytes advanced (ahead).
458*13d37d77SDavid du Colombier trials[0]..trials[ahead-1] contain the steps to encode.
459*13d37d77SDavid du Colombier (trials[0].dis4 == -1) means literal.
460*13d37d77SDavid du Colombier A match/rep longer or equal than match_len_limit finishes the sequence.
461*13d37d77SDavid du Colombier */
462*13d37d77SDavid du Colombier static int
LZe_sequence_optimizer(LZ_encoder * e,int reps[num_rep_distances],State state)463*13d37d77SDavid du Colombier LZe_sequence_optimizer(LZ_encoder *e, int reps[num_rep_distances], State state)
464*13d37d77SDavid du Colombier {
465*13d37d77SDavid du Colombier int main_len, num_pairs, i, num_trials;
466*13d37d77SDavid du Colombier int rep_index = 0, cur = 0;
467*13d37d77SDavid du Colombier int replens[num_rep_distances];
468*13d37d77SDavid du Colombier
469*13d37d77SDavid du Colombier if (e->pending_num_pairs > 0) { /* from previous call */
470*13d37d77SDavid du Colombier num_pairs = e->pending_num_pairs;
471*13d37d77SDavid du Colombier e->pending_num_pairs = 0;
472*13d37d77SDavid du Colombier } else
473*13d37d77SDavid du Colombier num_pairs = LZe_read_match_distances(e);
474*13d37d77SDavid du Colombier main_len = (num_pairs > 0) ? e->pairs[num_pairs-1].len : 0;
475*13d37d77SDavid du Colombier
476*13d37d77SDavid du Colombier for (i = 0; i < num_rep_distances; ++i) {
477*13d37d77SDavid du Colombier replens[i] = Mb_true_match_len(&e->eb.mb, 0, reps[i] + 1);
478*13d37d77SDavid du Colombier if (replens[i] > replens[rep_index])
479*13d37d77SDavid du Colombier rep_index = i;
480*13d37d77SDavid du Colombier }
481*13d37d77SDavid du Colombier if (replens[rep_index] >= e->match_len_limit) {
482*13d37d77SDavid du Colombier e->trials[0].price = replens[rep_index];
483*13d37d77SDavid du Colombier e->trials[0].dis4 = rep_index;
484*13d37d77SDavid du Colombier LZe_move_and_update(e, replens[rep_index]);
485*13d37d77SDavid du Colombier return replens[rep_index];
486*13d37d77SDavid du Colombier }
487*13d37d77SDavid du Colombier
488*13d37d77SDavid du Colombier if (main_len >= e->match_len_limit) {
489*13d37d77SDavid du Colombier e->trials[0].price = main_len;
490*13d37d77SDavid du Colombier e->trials[0].dis4 = e->pairs[num_pairs-1].dis + num_rep_distances;
491*13d37d77SDavid du Colombier LZe_move_and_update(e, main_len);
492*13d37d77SDavid du Colombier return main_len;
493*13d37d77SDavid du Colombier }
494*13d37d77SDavid du Colombier
495*13d37d77SDavid du Colombier if (encinit(e, reps, replens, state, main_len, num_pairs, rep_index,
496*13d37d77SDavid du Colombier &num_trials) > 0)
497*13d37d77SDavid du Colombier return 1;
498*13d37d77SDavid du Colombier
499*13d37d77SDavid du Colombier /*
500*13d37d77SDavid du Colombier * Optimize price.
501*13d37d77SDavid du Colombier */
502*13d37d77SDavid du Colombier for (;;) {
503*13d37d77SDavid du Colombier Trial *cur_trial, *next_trial;
504*13d37d77SDavid du Colombier int newlen, pos_state, triable_bytes, len_limit;
505*13d37d77SDavid du Colombier int next_price, match_price, rep_match_price;
506*13d37d77SDavid du Colombier int start_len = min_match_len;
507*13d37d77SDavid du Colombier State cur_state;
508*13d37d77SDavid du Colombier uchar prev_byte, cur_byte, match_byte;
509*13d37d77SDavid du Colombier
510*13d37d77SDavid du Colombier Mb_move_pos(&e->eb.mb);
511*13d37d77SDavid du Colombier if (++cur >= num_trials) { /* no more initialized trials */
512*13d37d77SDavid du Colombier LZe_backward(e, cur);
513*13d37d77SDavid du Colombier return cur;
514*13d37d77SDavid du Colombier }
515*13d37d77SDavid du Colombier
516*13d37d77SDavid du Colombier num_pairs = LZe_read_match_distances(e);
517*13d37d77SDavid du Colombier newlen = num_pairs > 0? e->pairs[num_pairs-1].len: 0;
518*13d37d77SDavid du Colombier if (newlen >= e->match_len_limit) {
519*13d37d77SDavid du Colombier e->pending_num_pairs = num_pairs;
520*13d37d77SDavid du Colombier LZe_backward(e, cur);
521*13d37d77SDavid du Colombier return cur;
522*13d37d77SDavid du Colombier }
523*13d37d77SDavid du Colombier
524*13d37d77SDavid du Colombier /* give final values to current trial */
525*13d37d77SDavid du Colombier cur_trial = &e->trials[cur];
526*13d37d77SDavid du Colombier finalvalues(e, cur, cur_trial, &cur_state);
527*13d37d77SDavid du Colombier
528*13d37d77SDavid du Colombier pos_state = Mb_data_position(&e->eb.mb) & pos_state_mask;
529*13d37d77SDavid du Colombier prev_byte = Mb_peek(&e->eb.mb, 1);
530*13d37d77SDavid du Colombier cur_byte = Mb_peek(&e->eb.mb, 0);
531*13d37d77SDavid du Colombier match_byte = Mb_peek(&e->eb.mb, cur_trial->reps[0] + 1);
532*13d37d77SDavid du Colombier
533*13d37d77SDavid du Colombier next_price = cur_trial->price +
534*13d37d77SDavid du Colombier price0(e->eb.bm_match[cur_state][pos_state]);
535*13d37d77SDavid du Colombier if (St_is_char(cur_state))
536*13d37d77SDavid du Colombier next_price += LZeb_price_literal(&e->eb, prev_byte, cur_byte);
537*13d37d77SDavid du Colombier else
538*13d37d77SDavid du Colombier next_price += LZeb_price_matched(&e->eb, prev_byte,
539*13d37d77SDavid du Colombier cur_byte, match_byte);
540*13d37d77SDavid du Colombier
541*13d37d77SDavid du Colombier /* try last updates to next trial */
542*13d37d77SDavid du Colombier next_trial = &e->trials[cur+1];
543*13d37d77SDavid du Colombier
544*13d37d77SDavid du Colombier Tr_update(next_trial, next_price, -1, cur); /* literal */
545*13d37d77SDavid du Colombier
546*13d37d77SDavid du Colombier match_price = cur_trial->price +
547*13d37d77SDavid du Colombier price1(e->eb.bm_match[cur_state][pos_state]);
548*13d37d77SDavid du Colombier rep_match_price = match_price + price1(e->eb.bm_rep[cur_state]);
549*13d37d77SDavid du Colombier
550*13d37d77SDavid du Colombier if (match_byte == cur_byte && next_trial->dis4 != 0 &&
551*13d37d77SDavid du Colombier next_trial->prev_index2 == single_step_trial) {
552*13d37d77SDavid du Colombier int price = rep_match_price +
553*13d37d77SDavid du Colombier LZeb_price_shortrep(&e->eb, cur_state, pos_state);
554*13d37d77SDavid du Colombier if (price <= next_trial->price) {
555*13d37d77SDavid du Colombier next_trial->price = price;
556*13d37d77SDavid du Colombier next_trial->dis4 = 0; /* rep0 */
557*13d37d77SDavid du Colombier next_trial->prev_index = cur;
558*13d37d77SDavid du Colombier }
559*13d37d77SDavid du Colombier }
560*13d37d77SDavid du Colombier
561*13d37d77SDavid du Colombier int trm1mcur = max_num_trials - 1 - cur;
562*13d37d77SDavid du Colombier
563*13d37d77SDavid du Colombier triable_bytes = Mb_avail_bytes(&e->eb.mb);
564*13d37d77SDavid du Colombier if (triable_bytes > trm1mcur)
565*13d37d77SDavid du Colombier triable_bytes = trm1mcur;
566*13d37d77SDavid du Colombier if (triable_bytes < min_match_len)
567*13d37d77SDavid du Colombier continue;
568*13d37d77SDavid du Colombier
569*13d37d77SDavid du Colombier len_limit = min(e->match_len_limit, triable_bytes);
570*13d37d77SDavid du Colombier
571*13d37d77SDavid du Colombier /* try literal + rep0 */
572*13d37d77SDavid du Colombier if (match_byte != cur_byte && next_trial->prev_index != cur)
573*13d37d77SDavid du Colombier num_trials = litrep0(e, cur_state, cur, cur_trial,
574*13d37d77SDavid du Colombier num_trials, triable_bytes, pos_state, next_price);
575*13d37d77SDavid du Colombier
576*13d37d77SDavid du Colombier /* try rep distances */
577*13d37d77SDavid du Colombier num_trials = repdists(e, cur_state, cur, cur_trial,
578*13d37d77SDavid du Colombier num_trials, triable_bytes, pos_state,
579*13d37d77SDavid du Colombier rep_match_price, len_limit, &start_len);
580*13d37d77SDavid du Colombier
581*13d37d77SDavid du Colombier /* try matches */
582*13d37d77SDavid du Colombier if (newlen >= start_len && newlen <= len_limit) {
583*13d37d77SDavid du Colombier int normal_match_price = match_price +
584*13d37d77SDavid du Colombier price0(e->eb.bm_rep[cur_state]);
585*13d37d77SDavid du Colombier
586*13d37d77SDavid du Colombier while (num_trials < cur + newlen)
587*13d37d77SDavid du Colombier e->trials[++num_trials].price = infinite_price;
588*13d37d77SDavid du Colombier
589*13d37d77SDavid du Colombier num_trials = trymatches(e, cur_state, cur, num_trials,
590*13d37d77SDavid du Colombier triable_bytes, pos_state, num_pairs,
591*13d37d77SDavid du Colombier normal_match_price, start_len);
592*13d37d77SDavid du Colombier }
593*13d37d77SDavid du Colombier }
594*13d37d77SDavid du Colombier }
595*13d37d77SDavid du Colombier
596*13d37d77SDavid du Colombier static int
encrepmatch(LZ_encoder * e,State state,int len,int dis,int pos_state)597*13d37d77SDavid du Colombier encrepmatch(LZ_encoder *e, State state, int len, int dis, int pos_state)
598*13d37d77SDavid du Colombier {
599*13d37d77SDavid du Colombier int bit = (dis == 0);
600*13d37d77SDavid du Colombier
601*13d37d77SDavid du Colombier Re_encode_bit(&e->eb.renc, &e->eb.bm_rep0[state], !bit);
602*13d37d77SDavid du Colombier if (bit)
603*13d37d77SDavid du Colombier Re_encode_bit(&e->eb.renc, &e->eb.bm_len[state][pos_state],
604*13d37d77SDavid du Colombier len > 1);
605*13d37d77SDavid du Colombier else {
606*13d37d77SDavid du Colombier Re_encode_bit(&e->eb.renc, &e->eb.bm_rep1[state], dis > 1);
607*13d37d77SDavid du Colombier if (dis > 1)
608*13d37d77SDavid du Colombier Re_encode_bit(&e->eb.renc, &e->eb.bm_rep2[state],
609*13d37d77SDavid du Colombier dis > 2);
610*13d37d77SDavid du Colombier }
611*13d37d77SDavid du Colombier if (len == 1)
612*13d37d77SDavid du Colombier state = St_set_short_rep(state);
613*13d37d77SDavid du Colombier else {
614*13d37d77SDavid du Colombier Re_encode_len(&e->eb.renc, &e->eb.rep_len_model, len, pos_state);
615*13d37d77SDavid du Colombier Lp_decr_counter(&e->rep_len_prices, pos_state);
616*13d37d77SDavid du Colombier state = St_set_rep(state);
617*13d37d77SDavid du Colombier }
618*13d37d77SDavid du Colombier return state;
619*13d37d77SDavid du Colombier }
620*13d37d77SDavid du Colombier
621*13d37d77SDavid du Colombier bool
LZe_encode_member(LZ_encoder * e,uvlong member_size)622*13d37d77SDavid du Colombier LZe_encode_member(LZ_encoder *e, uvlong member_size)
623*13d37d77SDavid du Colombier {
624*13d37d77SDavid du Colombier uvlong member_size_limit = member_size - Ft_size - max_marker_size;
625*13d37d77SDavid du Colombier bool best = (e->match_len_limit > 12);
626*13d37d77SDavid du Colombier int dis_price_count = best? 1: 512;
627*13d37d77SDavid du Colombier int align_price_count = best? 1: dis_align_size;
628*13d37d77SDavid du Colombier int price_count = (e->match_len_limit > 36? 1013 : 4093);
629*13d37d77SDavid du Colombier int price_counter = 0; /* counters may decrement below 0 */
630*13d37d77SDavid du Colombier int dis_price_counter = 0;
631*13d37d77SDavid du Colombier int align_price_counter = 0;
632*13d37d77SDavid du Colombier int ahead, i;
633*13d37d77SDavid du Colombier int reps[num_rep_distances];
634*13d37d77SDavid du Colombier State state = 0;
635*13d37d77SDavid du Colombier
636*13d37d77SDavid du Colombier for (i = 0; i < num_rep_distances; ++i)
637*13d37d77SDavid du Colombier reps[i] = 0;
638*13d37d77SDavid du Colombier
639*13d37d77SDavid du Colombier if (Mb_data_position(&e->eb.mb) != 0 ||
640*13d37d77SDavid du Colombier Re_member_position(&e->eb.renc) != Fh_size)
641*13d37d77SDavid du Colombier return false; /* can be called only once */
642*13d37d77SDavid du Colombier
643*13d37d77SDavid du Colombier if (!Mb_data_finished(&e->eb.mb)) { /* encode first byte */
644*13d37d77SDavid du Colombier uchar prev_byte = 0;
645*13d37d77SDavid du Colombier uchar cur_byte = Mb_peek(&e->eb.mb, 0);
646*13d37d77SDavid du Colombier
647*13d37d77SDavid du Colombier Re_encode_bit(&e->eb.renc, &e->eb.bm_match[state][0], 0);
648*13d37d77SDavid du Colombier LZeb_encode_literal(&e->eb, prev_byte, cur_byte);
649*13d37d77SDavid du Colombier CRC32_update_byte(&e->eb.crc, cur_byte);
650*13d37d77SDavid du Colombier LZe_get_match_pairs(e, 0);
651*13d37d77SDavid du Colombier Mb_move_pos(&e->eb.mb);
652*13d37d77SDavid du Colombier }
653*13d37d77SDavid du Colombier
654*13d37d77SDavid du Colombier while (!Mb_data_finished(&e->eb.mb)) {
655*13d37d77SDavid du Colombier if (price_counter <= 0 && e->pending_num_pairs == 0) {
656*13d37d77SDavid du Colombier /* recalculate prices every these many bytes */
657*13d37d77SDavid du Colombier price_counter = price_count;
658*13d37d77SDavid du Colombier if (dis_price_counter <= 0) {
659*13d37d77SDavid du Colombier dis_price_counter = dis_price_count;
660*13d37d77SDavid du Colombier LZe_update_distance_prices(e);
661*13d37d77SDavid du Colombier }
662*13d37d77SDavid du Colombier if (align_price_counter <= 0) {
663*13d37d77SDavid du Colombier align_price_counter = align_price_count;
664*13d37d77SDavid du Colombier for (i = 0; i < dis_align_size; ++i)
665*13d37d77SDavid du Colombier e->align_prices[i] = price_symbol_reversed(
666*13d37d77SDavid du Colombier e->eb.bm_align, i, dis_align_bits);
667*13d37d77SDavid du Colombier }
668*13d37d77SDavid du Colombier Lp_update_prices(&e->match_len_prices);
669*13d37d77SDavid du Colombier Lp_update_prices(&e->rep_len_prices);
670*13d37d77SDavid du Colombier }
671*13d37d77SDavid du Colombier
672*13d37d77SDavid du Colombier ahead = LZe_sequence_optimizer(e, reps, state);
673*13d37d77SDavid du Colombier price_counter -= ahead;
674*13d37d77SDavid du Colombier
675*13d37d77SDavid du Colombier for (i = 0; ahead > 0;) {
676*13d37d77SDavid du Colombier int pos_state = (Mb_data_position(&e->eb.mb) - ahead) &
677*13d37d77SDavid du Colombier pos_state_mask;
678*13d37d77SDavid du Colombier int len = e->trials[i].price;
679*13d37d77SDavid du Colombier int dis = e->trials[i].dis4;
680*13d37d77SDavid du Colombier bool bit = (dis < 0);
681*13d37d77SDavid du Colombier
682*13d37d77SDavid du Colombier Re_encode_bit(&e->eb.renc, &e->eb.bm_match[state][pos_state],
683*13d37d77SDavid du Colombier !bit);
684*13d37d77SDavid du Colombier if (bit) { /* literal byte */
685*13d37d77SDavid du Colombier uchar prev_byte = Mb_peek(&e->eb.mb, ahead+1);
686*13d37d77SDavid du Colombier uchar cur_byte = Mb_peek(&e->eb.mb, ahead);
687*13d37d77SDavid du Colombier
688*13d37d77SDavid du Colombier CRC32_update_byte(&e->eb.crc, cur_byte);
689*13d37d77SDavid du Colombier if (St_is_char(state))
690*13d37d77SDavid du Colombier LZeb_encode_literal(&e->eb, prev_byte,
691*13d37d77SDavid du Colombier cur_byte);
692*13d37d77SDavid du Colombier else {
693*13d37d77SDavid du Colombier uchar match_byte = Mb_peek(&e->eb.mb,
694*13d37d77SDavid du Colombier ahead + reps[0] + 1);
695*13d37d77SDavid du Colombier
696*13d37d77SDavid du Colombier LZeb_encode_matched(&e->eb, prev_byte,
697*13d37d77SDavid du Colombier cur_byte, match_byte);
698*13d37d77SDavid du Colombier }
699*13d37d77SDavid du Colombier state = St_set_char(state);
700*13d37d77SDavid du Colombier } else { /* match or repeated match */
701*13d37d77SDavid du Colombier CRC32_update_buf(&e->eb.crc,
702*13d37d77SDavid du Colombier Mb_ptr_to_current_pos(&e->eb.mb) - ahead,
703*13d37d77SDavid du Colombier len);
704*13d37d77SDavid du Colombier mtf_reps(dis, reps);
705*13d37d77SDavid du Colombier bit = (dis < num_rep_distances);
706*13d37d77SDavid du Colombier Re_encode_bit(&e->eb.renc, &e->eb.bm_rep[state],
707*13d37d77SDavid du Colombier bit);
708*13d37d77SDavid du Colombier if (bit) /* repeated match */
709*13d37d77SDavid du Colombier state = encrepmatch(e, state, len, dis,
710*13d37d77SDavid du Colombier pos_state);
711*13d37d77SDavid du Colombier else { /* match */
712*13d37d77SDavid du Colombier dis -= num_rep_distances;
713*13d37d77SDavid du Colombier LZeb_encode_pair(&e->eb, dis, len,
714*13d37d77SDavid du Colombier pos_state);
715*13d37d77SDavid du Colombier if (dis >= modeled_distances)
716*13d37d77SDavid du Colombier --align_price_counter;
717*13d37d77SDavid du Colombier --dis_price_counter;
718*13d37d77SDavid du Colombier Lp_decr_counter(
719*13d37d77SDavid du Colombier &e->match_len_prices, pos_state);
720*13d37d77SDavid du Colombier state = St_set_match(state);
721*13d37d77SDavid du Colombier }
722*13d37d77SDavid du Colombier }
723*13d37d77SDavid du Colombier ahead -= len;
724*13d37d77SDavid du Colombier i += len;
725*13d37d77SDavid du Colombier if (Re_member_position(&e->eb.renc) >= member_size_limit) {
726*13d37d77SDavid du Colombier if (!Mb_dec_pos(&e->eb.mb, ahead))
727*13d37d77SDavid du Colombier return false;
728*13d37d77SDavid du Colombier LZeb_full_flush(&e->eb, state);
729*13d37d77SDavid du Colombier return true;
730*13d37d77SDavid du Colombier }
731*13d37d77SDavid du Colombier }
732*13d37d77SDavid du Colombier }
733*13d37d77SDavid du Colombier LZeb_full_flush(&e->eb, state);
734*13d37d77SDavid du Colombier return true;
735*13d37d77SDavid du Colombier }
736