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
18*13d37d77SDavid du Colombier #include "lzip.h"
19*13d37d77SDavid du Colombier
20*13d37d77SDavid du Colombier static void
Dis_slots_init(void)21*13d37d77SDavid du Colombier Dis_slots_init(void)
22*13d37d77SDavid du Colombier {
23*13d37d77SDavid du Colombier int i, size, slot;
24*13d37d77SDavid du Colombier for (slot = 0; slot < 4; ++slot)
25*13d37d77SDavid du Colombier dis_slots[slot] = slot;
26*13d37d77SDavid du Colombier for (i = 4, size = 2, slot = 4; slot < 20; slot += 2) {
27*13d37d77SDavid du Colombier memset(&dis_slots[i], slot, size);
28*13d37d77SDavid du Colombier memset(&dis_slots[i+size], slot + 1, size);
29*13d37d77SDavid du Colombier size <<= 1;
30*13d37d77SDavid du Colombier i += size;
31*13d37d77SDavid du Colombier }
32*13d37d77SDavid du Colombier }
33*13d37d77SDavid du Colombier
34*13d37d77SDavid du Colombier static uchar
get_slot(unsigned dis)35*13d37d77SDavid du Colombier get_slot(unsigned dis)
36*13d37d77SDavid du Colombier {
37*13d37d77SDavid du Colombier if (dis < (1 << 10))
38*13d37d77SDavid du Colombier return dis_slots[dis];
39*13d37d77SDavid du Colombier if (dis < (1 << 19))
40*13d37d77SDavid du Colombier return dis_slots[dis>> 9] + 18;
41*13d37d77SDavid du Colombier if (dis < (1 << 28))
42*13d37d77SDavid du Colombier return dis_slots[dis>>18] + 36;
43*13d37d77SDavid du Colombier return dis_slots[dis>>27] + 54;
44*13d37d77SDavid du Colombier }
45*13d37d77SDavid du Colombier
46*13d37d77SDavid du Colombier static void
Prob_prices_init(void)47*13d37d77SDavid du Colombier Prob_prices_init(void)
48*13d37d77SDavid du Colombier {
49*13d37d77SDavid du Colombier int i, j;
50*13d37d77SDavid du Colombier for (i = 0; i < bit_model_total >> price_step_bits; ++i) {
51*13d37d77SDavid du Colombier unsigned val = (i * price_step) + (price_step / 2);
52*13d37d77SDavid du Colombier int bits = 0; /* base 2 logarithm of val */
53*13d37d77SDavid du Colombier
54*13d37d77SDavid du Colombier for (j = 0; j < price_shift_bits; ++j) {
55*13d37d77SDavid du Colombier val = val * val;
56*13d37d77SDavid du Colombier bits <<= 1;
57*13d37d77SDavid du Colombier while (val >= (1 << 16)) {
58*13d37d77SDavid du Colombier val >>= 1;
59*13d37d77SDavid du Colombier ++bits;
60*13d37d77SDavid du Colombier }
61*13d37d77SDavid du Colombier }
62*13d37d77SDavid du Colombier bits += 15; /* remaining bits in val */
63*13d37d77SDavid du Colombier prob_prices[i] = (bit_model_total_bits << price_shift_bits) - bits;
64*13d37d77SDavid du Colombier }
65*13d37d77SDavid du Colombier }
66*13d37d77SDavid du Colombier
67*13d37d77SDavid du Colombier static int
price_symbol3(Bit_model bm[],int symbol)68*13d37d77SDavid du Colombier price_symbol3(Bit_model bm[], int symbol)
69*13d37d77SDavid du Colombier {
70*13d37d77SDavid du Colombier int price;
71*13d37d77SDavid du Colombier bool bit = symbol & 1;
72*13d37d77SDavid du Colombier
73*13d37d77SDavid du Colombier symbol |= 8;
74*13d37d77SDavid du Colombier symbol >>= 1;
75*13d37d77SDavid du Colombier price = price_bit(bm[symbol], bit);
76*13d37d77SDavid du Colombier bit = symbol & 1;
77*13d37d77SDavid du Colombier symbol >>= 1;
78*13d37d77SDavid du Colombier price += price_bit(bm[symbol], bit);
79*13d37d77SDavid du Colombier return price + price_bit(bm[1], symbol & 1);
80*13d37d77SDavid du Colombier }
81*13d37d77SDavid du Colombier
82*13d37d77SDavid du Colombier static int
price_symbol6(Bit_model bm[],unsigned symbol)83*13d37d77SDavid du Colombier price_symbol6(Bit_model bm[], unsigned symbol)
84*13d37d77SDavid du Colombier {
85*13d37d77SDavid du Colombier int price;
86*13d37d77SDavid du Colombier bool bit = symbol & 1;
87*13d37d77SDavid du Colombier
88*13d37d77SDavid du Colombier symbol |= 64;
89*13d37d77SDavid du Colombier symbol >>= 1;
90*13d37d77SDavid du Colombier price = price_bit(bm[symbol], bit);
91*13d37d77SDavid du Colombier bit = symbol & 1;
92*13d37d77SDavid du Colombier symbol >>= 1;
93*13d37d77SDavid du Colombier price += price_bit(bm[symbol], bit);
94*13d37d77SDavid du Colombier bit = symbol & 1;
95*13d37d77SDavid du Colombier symbol >>= 1;
96*13d37d77SDavid du Colombier price += price_bit(bm[symbol], bit);
97*13d37d77SDavid du Colombier bit = symbol & 1;
98*13d37d77SDavid du Colombier symbol >>= 1;
99*13d37d77SDavid du Colombier price += price_bit(bm[symbol], bit);
100*13d37d77SDavid du Colombier bit = symbol & 1;
101*13d37d77SDavid du Colombier symbol >>= 1;
102*13d37d77SDavid du Colombier price += price_bit(bm[symbol], bit);
103*13d37d77SDavid du Colombier return price + price_bit(bm[1], symbol & 1);
104*13d37d77SDavid du Colombier }
105*13d37d77SDavid du Colombier
106*13d37d77SDavid du Colombier static int
price_symbol8(Bit_model bm[],int symbol)107*13d37d77SDavid du Colombier price_symbol8(Bit_model bm[], int symbol)
108*13d37d77SDavid du Colombier {
109*13d37d77SDavid du Colombier int price;
110*13d37d77SDavid du Colombier bool bit = symbol & 1;
111*13d37d77SDavid du Colombier symbol |= 0x100;
112*13d37d77SDavid du Colombier symbol >>= 1;
113*13d37d77SDavid du Colombier price = price_bit(bm[symbol], bit);
114*13d37d77SDavid du Colombier bit = symbol & 1;
115*13d37d77SDavid du Colombier symbol >>= 1;
116*13d37d77SDavid du Colombier price += price_bit(bm[symbol], bit);
117*13d37d77SDavid du Colombier bit = symbol & 1;
118*13d37d77SDavid du Colombier symbol >>= 1;
119*13d37d77SDavid du Colombier price += price_bit(bm[symbol], bit);
120*13d37d77SDavid du Colombier bit = symbol & 1;
121*13d37d77SDavid du Colombier symbol >>= 1;
122*13d37d77SDavid du Colombier price += price_bit(bm[symbol], bit);
123*13d37d77SDavid du Colombier bit = symbol & 1;
124*13d37d77SDavid du Colombier symbol >>= 1;
125*13d37d77SDavid du Colombier price += price_bit(bm[symbol], bit);
126*13d37d77SDavid du Colombier bit = symbol & 1;
127*13d37d77SDavid du Colombier symbol >>= 1;
128*13d37d77SDavid du Colombier price += price_bit(bm[symbol], bit);
129*13d37d77SDavid du Colombier bit = symbol & 1;
130*13d37d77SDavid du Colombier symbol >>= 1;
131*13d37d77SDavid du Colombier price += price_bit(bm[symbol], bit);
132*13d37d77SDavid du Colombier return price + price_bit(bm[1], symbol & 1);
133*13d37d77SDavid du Colombier }
134*13d37d77SDavid du Colombier
135*13d37d77SDavid du Colombier static int
price_symbol_reversed(Bit_model bm[],int symbol,int num_bits)136*13d37d77SDavid du Colombier price_symbol_reversed(Bit_model bm[], int symbol, int num_bits)
137*13d37d77SDavid du Colombier {
138*13d37d77SDavid du Colombier int price = 0;
139*13d37d77SDavid du Colombier int model = 1;
140*13d37d77SDavid du Colombier int i;
141*13d37d77SDavid du Colombier
142*13d37d77SDavid du Colombier for (i = num_bits; i > 0; --i) {
143*13d37d77SDavid du Colombier bool bit = symbol & 1;
144*13d37d77SDavid du Colombier symbol >>= 1;
145*13d37d77SDavid du Colombier price += price_bit(bm[model], bit);
146*13d37d77SDavid du Colombier model = (model << 1) | bit;
147*13d37d77SDavid du Colombier }
148*13d37d77SDavid du Colombier return price;
149*13d37d77SDavid du Colombier }
150*13d37d77SDavid du Colombier
151*13d37d77SDavid du Colombier static int
price_matched(Bit_model bm[],unsigned symbol,unsigned match_byte)152*13d37d77SDavid du Colombier price_matched(Bit_model bm[], unsigned symbol, unsigned match_byte)
153*13d37d77SDavid du Colombier {
154*13d37d77SDavid du Colombier int price = 0;
155*13d37d77SDavid du Colombier unsigned mask = 0x100;
156*13d37d77SDavid du Colombier
157*13d37d77SDavid du Colombier symbol |= mask;
158*13d37d77SDavid du Colombier for (;;) {
159*13d37d77SDavid du Colombier unsigned match_bit = (match_byte <<= 1) & mask;
160*13d37d77SDavid du Colombier bool bit = (symbol <<= 1) & 0x100;
161*13d37d77SDavid du Colombier
162*13d37d77SDavid du Colombier price += price_bit(bm[(symbol>>9) + match_bit + mask], bit);
163*13d37d77SDavid du Colombier if (symbol >= 0x10000)
164*13d37d77SDavid du Colombier return price;
165*13d37d77SDavid du Colombier mask &= ~(match_bit ^ symbol);
166*13d37d77SDavid du Colombier /* if(match_bit != bit) mask = 0; */
167*13d37d77SDavid du Colombier }
168*13d37d77SDavid du Colombier }
169*13d37d77SDavid du Colombier
170*13d37d77SDavid du Colombier struct Matchfinder_base {
171*13d37d77SDavid du Colombier uvlong partial_data_pos;
172*13d37d77SDavid du Colombier uchar * buffer; /* input buffer */
173*13d37d77SDavid du Colombier int32_t * prev_positions; /* 1 + last seen position of key. else 0 */
174*13d37d77SDavid du Colombier int32_t * pos_array; /* may be tree or chain */
175*13d37d77SDavid du Colombier int before_size; /* bytes to keep in buffer before dictionary */
176*13d37d77SDavid du Colombier int buffer_size;
177*13d37d77SDavid du Colombier int dict_size; /* bytes to keep in buffer before pos */
178*13d37d77SDavid du Colombier int pos; /* current pos in buffer */
179*13d37d77SDavid du Colombier int cyclic_pos; /* cycles through [0, dict_size] */
180*13d37d77SDavid du Colombier int stream_pos; /* first byte not yet read from file */
181*13d37d77SDavid du Colombier int pos_limit; /* when reached, a new block must be read */
182*13d37d77SDavid du Colombier int key4_mask;
183*13d37d77SDavid du Colombier int num_prev_positions; /* size of prev_positions */
184*13d37d77SDavid du Colombier int pos_array_size;
185*13d37d77SDavid du Colombier int infd; /* input file descriptor */
186*13d37d77SDavid du Colombier bool at_stream_end; /* stream_pos shows real end of file */
187*13d37d77SDavid du Colombier };
188*13d37d77SDavid du Colombier
189*13d37d77SDavid du Colombier bool Mb_read_block(Matchfinder_base *mb);
190*13d37d77SDavid du Colombier void Mb_normalize_pos(Matchfinder_base *mb);
191*13d37d77SDavid du Colombier bool Mb_init(Matchfinder_base *mb, int before, int dict_size, int after_size, int dict_factor, int num_prev_positions23, int pos_array_factor, int ifd);
192*13d37d77SDavid du Colombier
193*13d37d77SDavid du Colombier static void
Mb_free(Matchfinder_base * mb)194*13d37d77SDavid du Colombier Mb_free(Matchfinder_base *mb)
195*13d37d77SDavid du Colombier {
196*13d37d77SDavid du Colombier free(mb->prev_positions);
197*13d37d77SDavid du Colombier free(mb->buffer);
198*13d37d77SDavid du Colombier }
199*13d37d77SDavid du Colombier
200*13d37d77SDavid du Colombier static int
Mb_avail_bytes(Matchfinder_base * mb)201*13d37d77SDavid du Colombier Mb_avail_bytes(Matchfinder_base *mb)
202*13d37d77SDavid du Colombier {
203*13d37d77SDavid du Colombier return mb->stream_pos - mb->pos;
204*13d37d77SDavid du Colombier }
205*13d37d77SDavid du Colombier
206*13d37d77SDavid du Colombier static uvlong
Mb_data_position(Matchfinder_base * mb)207*13d37d77SDavid du Colombier Mb_data_position(Matchfinder_base *mb)
208*13d37d77SDavid du Colombier {
209*13d37d77SDavid du Colombier return mb->partial_data_pos + mb->pos;
210*13d37d77SDavid du Colombier }
211*13d37d77SDavid du Colombier
212*13d37d77SDavid du Colombier static bool
Mb_data_finished(Matchfinder_base * mb)213*13d37d77SDavid du Colombier Mb_data_finished(Matchfinder_base *mb)
214*13d37d77SDavid du Colombier {
215*13d37d77SDavid du Colombier return mb->at_stream_end && mb->pos >= mb->stream_pos;
216*13d37d77SDavid du Colombier }
217*13d37d77SDavid du Colombier
218*13d37d77SDavid du Colombier static int
Mb_true_match_len(Matchfinder_base * mb,int index,int distance)219*13d37d77SDavid du Colombier Mb_true_match_len(Matchfinder_base *mb, int index, int distance)
220*13d37d77SDavid du Colombier {
221*13d37d77SDavid du Colombier uchar * data = mb->buffer + mb->pos;
222*13d37d77SDavid du Colombier int i = index;
223*13d37d77SDavid du Colombier int len_limit = min(Mb_avail_bytes(mb), max_match_len);
224*13d37d77SDavid du Colombier while (i < len_limit && data[i-distance] == data[i])
225*13d37d77SDavid du Colombier ++i;
226*13d37d77SDavid du Colombier return i;
227*13d37d77SDavid du Colombier }
228*13d37d77SDavid du Colombier
229*13d37d77SDavid du Colombier static void
Mb_move_pos(Matchfinder_base * mb)230*13d37d77SDavid du Colombier Mb_move_pos(Matchfinder_base *mb)
231*13d37d77SDavid du Colombier {
232*13d37d77SDavid du Colombier if (++mb->cyclic_pos > mb->dict_size)
233*13d37d77SDavid du Colombier mb->cyclic_pos = 0;
234*13d37d77SDavid du Colombier if (++mb->pos >= mb->pos_limit)
235*13d37d77SDavid du Colombier Mb_normalize_pos(mb);
236*13d37d77SDavid du Colombier }
237*13d37d77SDavid du Colombier
238*13d37d77SDavid du Colombier void Mb_reset(Matchfinder_base *mb);
239*13d37d77SDavid du Colombier
240*13d37d77SDavid du Colombier enum { re_buffer_size = 65536 };
241*13d37d77SDavid du Colombier
242*13d37d77SDavid du Colombier typedef struct LZ_encoder_base LZ_encoder_base;
243*13d37d77SDavid du Colombier typedef struct Matchfinder_base Matchfinder_base;
244*13d37d77SDavid du Colombier typedef struct Range_encoder Range_encoder;
245*13d37d77SDavid du Colombier
246*13d37d77SDavid du Colombier struct Range_encoder {
247*13d37d77SDavid du Colombier uvlong low;
248*13d37d77SDavid du Colombier uvlong partial_member_pos;
249*13d37d77SDavid du Colombier uchar * buffer; /* output buffer */
250*13d37d77SDavid du Colombier int pos; /* current pos in buffer */
251*13d37d77SDavid du Colombier uint32_t range;
252*13d37d77SDavid du Colombier unsigned ff_count;
253*13d37d77SDavid du Colombier int outfd; /* output file descriptor */
254*13d37d77SDavid du Colombier uchar cache;
255*13d37d77SDavid du Colombier File_header header;
256*13d37d77SDavid du Colombier };
257*13d37d77SDavid du Colombier
258*13d37d77SDavid du Colombier void Re_flush_data(Range_encoder *renc);
259*13d37d77SDavid du Colombier
260*13d37d77SDavid du Colombier static void
Re_put_byte(Range_encoder * renc,uchar b)261*13d37d77SDavid du Colombier Re_put_byte(Range_encoder *renc, uchar b)
262*13d37d77SDavid du Colombier {
263*13d37d77SDavid du Colombier renc->buffer[renc->pos] = b;
264*13d37d77SDavid du Colombier if (++renc->pos >= re_buffer_size)
265*13d37d77SDavid du Colombier Re_flush_data(renc);
266*13d37d77SDavid du Colombier }
267*13d37d77SDavid du Colombier
268*13d37d77SDavid du Colombier static void
Re_shift_low(Range_encoder * renc)269*13d37d77SDavid du Colombier Re_shift_low(Range_encoder *renc)
270*13d37d77SDavid du Colombier {
271*13d37d77SDavid du Colombier if (renc->low >> 24 != 0xFF) {
272*13d37d77SDavid du Colombier bool carry = (renc->low > 0xFFFFFFFFU);
273*13d37d77SDavid du Colombier Re_put_byte(renc, renc->cache + carry);
274*13d37d77SDavid du Colombier for (; renc->ff_count > 0; --renc->ff_count)
275*13d37d77SDavid du Colombier Re_put_byte(renc, 0xFF + carry);
276*13d37d77SDavid du Colombier renc->cache = renc->low >> 24;
277*13d37d77SDavid du Colombier } else
278*13d37d77SDavid du Colombier ++renc->ff_count;
279*13d37d77SDavid du Colombier renc->low = (renc->low & 0x00FFFFFFU) << 8;
280*13d37d77SDavid du Colombier }
281*13d37d77SDavid du Colombier
282*13d37d77SDavid du Colombier static void
Re_reset(Range_encoder * renc)283*13d37d77SDavid du Colombier Re_reset(Range_encoder *renc)
284*13d37d77SDavid du Colombier {
285*13d37d77SDavid du Colombier int i;
286*13d37d77SDavid du Colombier renc->low = 0;
287*13d37d77SDavid du Colombier renc->partial_member_pos = 0;
288*13d37d77SDavid du Colombier renc->pos = 0;
289*13d37d77SDavid du Colombier renc->range = 0xFFFFFFFFU;
290*13d37d77SDavid du Colombier renc->ff_count = 0;
291*13d37d77SDavid du Colombier renc->cache = 0;
292*13d37d77SDavid du Colombier for (i = 0; i < Fh_size; ++i)
293*13d37d77SDavid du Colombier Re_put_byte(renc, renc->header[i]);
294*13d37d77SDavid du Colombier }
295*13d37d77SDavid du Colombier
296*13d37d77SDavid du Colombier static bool
Re_init(Range_encoder * renc,unsigned dict_size,int ofd)297*13d37d77SDavid du Colombier Re_init(Range_encoder *renc, unsigned dict_size, int ofd)
298*13d37d77SDavid du Colombier {
299*13d37d77SDavid du Colombier renc->buffer = (uchar *)malloc(re_buffer_size);
300*13d37d77SDavid du Colombier if (!renc->buffer)
301*13d37d77SDavid du Colombier return false;
302*13d37d77SDavid du Colombier renc->outfd = ofd;
303*13d37d77SDavid du Colombier Fh_set_magic(renc->header);
304*13d37d77SDavid du Colombier Fh_set_dict_size(renc->header, dict_size);
305*13d37d77SDavid du Colombier Re_reset(renc);
306*13d37d77SDavid du Colombier return true;
307*13d37d77SDavid du Colombier }
308*13d37d77SDavid du Colombier
309*13d37d77SDavid du Colombier static void
Re_free(Range_encoder * renc)310*13d37d77SDavid du Colombier Re_free(Range_encoder *renc)
311*13d37d77SDavid du Colombier {
312*13d37d77SDavid du Colombier free(renc->buffer);
313*13d37d77SDavid du Colombier }
314*13d37d77SDavid du Colombier
315*13d37d77SDavid du Colombier static uvlong
Re_member_position(Range_encoder * renc)316*13d37d77SDavid du Colombier Re_member_position(Range_encoder *renc)
317*13d37d77SDavid du Colombier {
318*13d37d77SDavid du Colombier return renc->partial_member_pos + renc->pos + renc->ff_count;
319*13d37d77SDavid du Colombier }
320*13d37d77SDavid du Colombier
321*13d37d77SDavid du Colombier static void
Re_flush(Range_encoder * renc)322*13d37d77SDavid du Colombier Re_flush(Range_encoder *renc)
323*13d37d77SDavid du Colombier {
324*13d37d77SDavid du Colombier int i;
325*13d37d77SDavid du Colombier for (i = 0; i < 5; ++i)
326*13d37d77SDavid du Colombier Re_shift_low(renc);
327*13d37d77SDavid du Colombier }
328*13d37d77SDavid du Colombier
329*13d37d77SDavid du Colombier static void
Re_encode(Range_encoder * renc,int symbol,int num_bits)330*13d37d77SDavid du Colombier Re_encode(Range_encoder *renc, int symbol, int num_bits)
331*13d37d77SDavid du Colombier {
332*13d37d77SDavid du Colombier unsigned mask;
333*13d37d77SDavid du Colombier for (mask = 1 << (num_bits - 1); mask > 0; mask >>= 1) {
334*13d37d77SDavid du Colombier renc->range >>= 1;
335*13d37d77SDavid du Colombier if (symbol & mask)
336*13d37d77SDavid du Colombier renc->low += renc->range;
337*13d37d77SDavid du Colombier if (renc->range <= 0x00FFFFFFU) {
338*13d37d77SDavid du Colombier renc->range <<= 8;
339*13d37d77SDavid du Colombier Re_shift_low(renc);
340*13d37d77SDavid du Colombier }
341*13d37d77SDavid du Colombier }
342*13d37d77SDavid du Colombier }
343*13d37d77SDavid du Colombier
344*13d37d77SDavid du Colombier static void
Re_encode_bit(Range_encoder * renc,Bit_model * probability,bool bit)345*13d37d77SDavid du Colombier Re_encode_bit(Range_encoder *renc, Bit_model *probability, bool bit)
346*13d37d77SDavid du Colombier {
347*13d37d77SDavid du Colombier Bit_model prob = *probability;
348*13d37d77SDavid du Colombier uint32_t bound = (renc->range >> bit_model_total_bits) * prob;
349*13d37d77SDavid du Colombier
350*13d37d77SDavid du Colombier if (!bit) {
351*13d37d77SDavid du Colombier renc->range = bound;
352*13d37d77SDavid du Colombier *probability += (bit_model_total - prob) >> bit_model_move_bits;
353*13d37d77SDavid du Colombier } else {
354*13d37d77SDavid du Colombier renc->low += bound;
355*13d37d77SDavid du Colombier renc->range -= bound;
356*13d37d77SDavid du Colombier *probability -= prob >> bit_model_move_bits;
357*13d37d77SDavid du Colombier }
358*13d37d77SDavid du Colombier if (renc->range <= 0x00FFFFFFU) {
359*13d37d77SDavid du Colombier renc->range <<= 8;
360*13d37d77SDavid du Colombier Re_shift_low(renc);
361*13d37d77SDavid du Colombier }
362*13d37d77SDavid du Colombier }
363*13d37d77SDavid du Colombier
364*13d37d77SDavid du Colombier static void
Re_encode_tree3(Range_encoder * renc,Bit_model bm[],int symbol)365*13d37d77SDavid du Colombier Re_encode_tree3(Range_encoder *renc, Bit_model bm[], int symbol)
366*13d37d77SDavid du Colombier {
367*13d37d77SDavid du Colombier int model = 1;
368*13d37d77SDavid du Colombier bool bit = (symbol >> 2) & 1;
369*13d37d77SDavid du Colombier
370*13d37d77SDavid du Colombier Re_encode_bit(renc, &bm[model], bit);
371*13d37d77SDavid du Colombier model = (model << 1) | bit;
372*13d37d77SDavid du Colombier bit = (symbol >> 1) & 1;
373*13d37d77SDavid du Colombier Re_encode_bit(renc, &bm[model], bit);
374*13d37d77SDavid du Colombier model = (model << 1) | bit;
375*13d37d77SDavid du Colombier Re_encode_bit(renc, &bm[model], symbol & 1);
376*13d37d77SDavid du Colombier }
377*13d37d77SDavid du Colombier
378*13d37d77SDavid du Colombier static void
Re_encode_tree6(Range_encoder * renc,Bit_model bm[],unsigned symbol)379*13d37d77SDavid du Colombier Re_encode_tree6(Range_encoder *renc, Bit_model bm[], unsigned symbol)
380*13d37d77SDavid du Colombier {
381*13d37d77SDavid du Colombier int model = 1;
382*13d37d77SDavid du Colombier bool bit = (symbol >> 5) & 1;
383*13d37d77SDavid du Colombier Re_encode_bit(renc, &bm[model], bit);
384*13d37d77SDavid du Colombier model = (model << 1) | bit;
385*13d37d77SDavid du Colombier bit = (symbol >> 4) & 1;
386*13d37d77SDavid du Colombier Re_encode_bit(renc, &bm[model], bit);
387*13d37d77SDavid du Colombier model = (model << 1) | bit;
388*13d37d77SDavid du Colombier bit = (symbol >> 3) & 1;
389*13d37d77SDavid du Colombier Re_encode_bit(renc, &bm[model], bit);
390*13d37d77SDavid du Colombier model = (model << 1) | bit;
391*13d37d77SDavid du Colombier bit = (symbol >> 2) & 1;
392*13d37d77SDavid du Colombier Re_encode_bit(renc, &bm[model], bit);
393*13d37d77SDavid du Colombier model = (model << 1) | bit;
394*13d37d77SDavid du Colombier bit = (symbol >> 1) & 1;
395*13d37d77SDavid du Colombier Re_encode_bit(renc, &bm[model], bit);
396*13d37d77SDavid du Colombier model = (model << 1) | bit;
397*13d37d77SDavid du Colombier Re_encode_bit(renc, &bm[model], symbol & 1);
398*13d37d77SDavid du Colombier }
399*13d37d77SDavid du Colombier
400*13d37d77SDavid du Colombier static void
Re_encode_tree8(Range_encoder * renc,Bit_model bm[],int symbol)401*13d37d77SDavid du Colombier Re_encode_tree8(Range_encoder *renc, Bit_model bm[], int symbol)
402*13d37d77SDavid du Colombier {
403*13d37d77SDavid du Colombier int model = 1;
404*13d37d77SDavid du Colombier int i;
405*13d37d77SDavid du Colombier for (i = 7; i >= 0; --i) {
406*13d37d77SDavid du Colombier bool bit = (symbol >> i) & 1;
407*13d37d77SDavid du Colombier Re_encode_bit(renc, &bm[model], bit);
408*13d37d77SDavid du Colombier model = (model << 1) | bit;
409*13d37d77SDavid du Colombier }
410*13d37d77SDavid du Colombier }
411*13d37d77SDavid du Colombier
412*13d37d77SDavid du Colombier static void
Re_encode_tree_reversed(Range_encoder * renc,Bit_model bm[],int symbol,int num_bits)413*13d37d77SDavid du Colombier Re_encode_tree_reversed(Range_encoder *renc, Bit_model bm[], int symbol, int num_bits)
414*13d37d77SDavid du Colombier {
415*13d37d77SDavid du Colombier int model = 1;
416*13d37d77SDavid du Colombier int i;
417*13d37d77SDavid du Colombier for (i = num_bits; i > 0; --i) {
418*13d37d77SDavid du Colombier bool bit = symbol & 1;
419*13d37d77SDavid du Colombier symbol >>= 1;
420*13d37d77SDavid du Colombier Re_encode_bit(renc, &bm[model], bit);
421*13d37d77SDavid du Colombier model = (model << 1) | bit;
422*13d37d77SDavid du Colombier }
423*13d37d77SDavid du Colombier }
424*13d37d77SDavid du Colombier
425*13d37d77SDavid du Colombier static void
Re_encode_matched(Range_encoder * renc,Bit_model bm[],unsigned symbol,unsigned match_byte)426*13d37d77SDavid du Colombier Re_encode_matched(Range_encoder *renc, Bit_model bm[], unsigned symbol, unsigned match_byte)
427*13d37d77SDavid du Colombier {
428*13d37d77SDavid du Colombier unsigned mask = 0x100;
429*13d37d77SDavid du Colombier symbol |= mask;
430*13d37d77SDavid du Colombier while (true) {
431*13d37d77SDavid du Colombier unsigned match_bit = (match_byte <<= 1) & mask;
432*13d37d77SDavid du Colombier bool bit = (symbol <<= 1) & 0x100;
433*13d37d77SDavid du Colombier Re_encode_bit(renc, &bm[(symbol>>9)+match_bit+mask], bit);
434*13d37d77SDavid du Colombier if (symbol >= 0x10000)
435*13d37d77SDavid du Colombier break;
436*13d37d77SDavid du Colombier mask &= ~(match_bit ^ symbol);
437*13d37d77SDavid du Colombier /* if(match_bit != bit) mask = 0; */
438*13d37d77SDavid du Colombier }
439*13d37d77SDavid du Colombier }
440*13d37d77SDavid du Colombier
441*13d37d77SDavid du Colombier static void
Re_encode_len(struct Range_encoder * renc,Len_model * lm,int symbol,int pos_state)442*13d37d77SDavid du Colombier Re_encode_len(struct Range_encoder *renc, Len_model *lm, int symbol, int pos_state)
443*13d37d77SDavid du Colombier {
444*13d37d77SDavid du Colombier bool bit = ((symbol -= min_match_len) >= len_low_syms);
445*13d37d77SDavid du Colombier Re_encode_bit(renc, &lm->choice1, bit);
446*13d37d77SDavid du Colombier if (!bit)
447*13d37d77SDavid du Colombier Re_encode_tree3(renc, lm->bm_low[pos_state], symbol);
448*13d37d77SDavid du Colombier else {
449*13d37d77SDavid du Colombier bit = ((symbol -= len_low_syms) >= len_mid_syms);
450*13d37d77SDavid du Colombier Re_encode_bit(renc, &lm->choice2, bit);
451*13d37d77SDavid du Colombier if (!bit)
452*13d37d77SDavid du Colombier Re_encode_tree3(renc, lm->bm_mid[pos_state], symbol);
453*13d37d77SDavid du Colombier else
454*13d37d77SDavid du Colombier Re_encode_tree8(renc, lm->bm_high, symbol - len_mid_syms);
455*13d37d77SDavid du Colombier }
456*13d37d77SDavid du Colombier }
457*13d37d77SDavid du Colombier
458*13d37d77SDavid du Colombier enum {
459*13d37d77SDavid du Colombier max_marker_size = 16,
460*13d37d77SDavid du Colombier num_rep_distances = 4 /* must be 4 */
461*13d37d77SDavid du Colombier };
462*13d37d77SDavid du Colombier
463*13d37d77SDavid du Colombier struct LZ_encoder_base {
464*13d37d77SDavid du Colombier struct Matchfinder_base mb;
465*13d37d77SDavid du Colombier uint32_t crc;
466*13d37d77SDavid du Colombier
467*13d37d77SDavid du Colombier Bit_model bm_literal[1<<literal_context_bits][0x300];
468*13d37d77SDavid du Colombier Bit_model bm_match[states][pos_states];
469*13d37d77SDavid du Colombier Bit_model bm_rep[states];
470*13d37d77SDavid du Colombier Bit_model bm_rep0[states];
471*13d37d77SDavid du Colombier Bit_model bm_rep1[states];
472*13d37d77SDavid du Colombier Bit_model bm_rep2[states];
473*13d37d77SDavid du Colombier Bit_model bm_len[states][pos_states];
474*13d37d77SDavid du Colombier Bit_model bm_dis_slot[len_states][1<<dis_slot_bits];
475*13d37d77SDavid du Colombier Bit_model bm_dis[modeled_distances-end_dis_model+1];
476*13d37d77SDavid du Colombier Bit_model bm_align[dis_align_size];
477*13d37d77SDavid du Colombier struct Len_model match_len_model;
478*13d37d77SDavid du Colombier struct Len_model rep_len_model;
479*13d37d77SDavid du Colombier struct Range_encoder renc;
480*13d37d77SDavid du Colombier };
481*13d37d77SDavid du Colombier
482*13d37d77SDavid du Colombier void LZeb_reset(LZ_encoder_base *eb);
483*13d37d77SDavid du Colombier
484*13d37d77SDavid du Colombier static bool
LZeb_init(LZ_encoder_base * eb,int before,int dict_size,int after_size,int dict_factor,int num_prev_positions23,int pos_array_factor,int ifd,int outfd)485*13d37d77SDavid du Colombier LZeb_init(LZ_encoder_base *eb, int before, int dict_size, int after_size, int dict_factor, int num_prev_positions23, int pos_array_factor, int ifd, int outfd)
486*13d37d77SDavid du Colombier {
487*13d37d77SDavid du Colombier if (!Mb_init(&eb->mb, before, dict_size, after_size, dict_factor,
488*13d37d77SDavid du Colombier num_prev_positions23, pos_array_factor, ifd))
489*13d37d77SDavid du Colombier return false;
490*13d37d77SDavid du Colombier if (!Re_init(&eb->renc, eb->mb.dict_size, outfd))
491*13d37d77SDavid du Colombier return false;
492*13d37d77SDavid du Colombier LZeb_reset(eb);
493*13d37d77SDavid du Colombier return true;
494*13d37d77SDavid du Colombier }
495*13d37d77SDavid du Colombier
496*13d37d77SDavid du Colombier static void
LZeb_free(LZ_encoder_base * eb)497*13d37d77SDavid du Colombier LZeb_free(LZ_encoder_base *eb)
498*13d37d77SDavid du Colombier {
499*13d37d77SDavid du Colombier Re_free(&eb->renc);
500*13d37d77SDavid du Colombier Mb_free(&eb->mb);
501*13d37d77SDavid du Colombier }
502*13d37d77SDavid du Colombier
503*13d37d77SDavid du Colombier static unsigned
LZeb_crc(LZ_encoder_base * eb)504*13d37d77SDavid du Colombier LZeb_crc(LZ_encoder_base *eb)
505*13d37d77SDavid du Colombier {
506*13d37d77SDavid du Colombier return eb->crc ^ 0xFFFFFFFFU;
507*13d37d77SDavid du Colombier }
508*13d37d77SDavid du Colombier
509*13d37d77SDavid du Colombier static int
LZeb_price_literal(LZ_encoder_base * eb,uchar prev_byte,uchar symbol)510*13d37d77SDavid du Colombier LZeb_price_literal(LZ_encoder_base *eb, uchar prev_byte, uchar symbol)
511*13d37d77SDavid du Colombier {
512*13d37d77SDavid du Colombier return price_symbol8(eb->bm_literal[get_lit_state(prev_byte)], symbol);
513*13d37d77SDavid du Colombier }
514*13d37d77SDavid du Colombier
515*13d37d77SDavid du Colombier static int
LZeb_price_matched(LZ_encoder_base * eb,uchar prev_byte,uchar symbol,uchar match_byte)516*13d37d77SDavid du Colombier LZeb_price_matched(LZ_encoder_base *eb, uchar prev_byte, uchar symbol, uchar match_byte)
517*13d37d77SDavid du Colombier {
518*13d37d77SDavid du Colombier return price_matched(eb->bm_literal[get_lit_state(prev_byte)], symbol,
519*13d37d77SDavid du Colombier match_byte);
520*13d37d77SDavid du Colombier }
521*13d37d77SDavid du Colombier
522*13d37d77SDavid du Colombier static void
LZeb_encode_literal(LZ_encoder_base * eb,uchar prev_byte,uchar symbol)523*13d37d77SDavid du Colombier LZeb_encode_literal(LZ_encoder_base *eb, uchar prev_byte, uchar symbol)
524*13d37d77SDavid du Colombier {
525*13d37d77SDavid du Colombier Re_encode_tree8(&eb->renc, eb->bm_literal[get_lit_state(prev_byte)],
526*13d37d77SDavid du Colombier symbol);
527*13d37d77SDavid du Colombier }
528*13d37d77SDavid du Colombier
529*13d37d77SDavid du Colombier static void
LZeb_encode_matched(LZ_encoder_base * eb,uchar prev_byte,uchar symbol,uchar match_byte)530*13d37d77SDavid du Colombier LZeb_encode_matched(LZ_encoder_base *eb, uchar prev_byte, uchar symbol, uchar match_byte)
531*13d37d77SDavid du Colombier {
532*13d37d77SDavid du Colombier Re_encode_matched(&eb->renc, eb->bm_literal[get_lit_state(prev_byte)],
533*13d37d77SDavid du Colombier symbol, match_byte);
534*13d37d77SDavid du Colombier }
535*13d37d77SDavid du Colombier
536*13d37d77SDavid du Colombier static void
LZeb_encode_pair(LZ_encoder_base * eb,unsigned dis,int len,int pos_state)537*13d37d77SDavid du Colombier LZeb_encode_pair(LZ_encoder_base *eb, unsigned dis, int len, int pos_state)
538*13d37d77SDavid du Colombier {
539*13d37d77SDavid du Colombier unsigned dis_slot = get_slot(dis);
540*13d37d77SDavid du Colombier Re_encode_len(&eb->renc, &eb->match_len_model, len, pos_state);
541*13d37d77SDavid du Colombier Re_encode_tree6(&eb->renc, eb->bm_dis_slot[get_len_state(len)], dis_slot);
542*13d37d77SDavid du Colombier
543*13d37d77SDavid du Colombier if (dis_slot >= start_dis_model) {
544*13d37d77SDavid du Colombier int direct_bits = (dis_slot >> 1) - 1;
545*13d37d77SDavid du Colombier unsigned base = (2 | (dis_slot & 1)) << direct_bits;
546*13d37d77SDavid du Colombier unsigned direct_dis = dis - base;
547*13d37d77SDavid du Colombier
548*13d37d77SDavid du Colombier if (dis_slot < end_dis_model)
549*13d37d77SDavid du Colombier Re_encode_tree_reversed(&eb->renc, eb->bm_dis + (base - dis_slot),
550*13d37d77SDavid du Colombier direct_dis, direct_bits);
551*13d37d77SDavid du Colombier else {
552*13d37d77SDavid du Colombier Re_encode(&eb->renc, direct_dis >> dis_align_bits,
553*13d37d77SDavid du Colombier direct_bits - dis_align_bits);
554*13d37d77SDavid du Colombier Re_encode_tree_reversed(&eb->renc, eb->bm_align, direct_dis, dis_align_bits);
555*13d37d77SDavid du Colombier }
556*13d37d77SDavid du Colombier }
557*13d37d77SDavid du Colombier }
558*13d37d77SDavid du Colombier
559*13d37d77SDavid du Colombier void LZeb_full_flush(LZ_encoder_base *eb, State state);
560