xref: /plan9-contrib/sys/src/cmd/lzip/encoder.c (revision 13d37d7716a3e781f408392d7869dff5927c6669)
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