1cf204528SSimon Glass
2cf204528SSimon Glass /*-------------------------------------------------------------*/
3cf204528SSimon Glass /*--- Compression machinery (not incl block sorting) ---*/
4cf204528SSimon Glass /*--- compress.c ---*/
5cf204528SSimon Glass /*-------------------------------------------------------------*/
6cf204528SSimon Glass
7cf204528SSimon Glass /*--
8cf204528SSimon Glass This file is a part of bzip2 and/or libbzip2, a program and
9cf204528SSimon Glass library for lossless, block-sorting data compression.
10cf204528SSimon Glass
11cf204528SSimon Glass Copyright (C) 1996-2002 Julian R Seward. All rights reserved.
12cf204528SSimon Glass
13cf204528SSimon Glass Redistribution and use in source and binary forms, with or without
14cf204528SSimon Glass modification, are permitted provided that the following conditions
15cf204528SSimon Glass are met:
16cf204528SSimon Glass
17cf204528SSimon Glass 1. Redistributions of source code must retain the above copyright
18cf204528SSimon Glass notice, this list of conditions and the following disclaimer.
19cf204528SSimon Glass
20cf204528SSimon Glass 2. The origin of this software must not be misrepresented; you must
21cf204528SSimon Glass not claim that you wrote the original software. If you use this
22cf204528SSimon Glass software in a product, an acknowledgment in the product
23cf204528SSimon Glass documentation would be appreciated but is not required.
24cf204528SSimon Glass
25cf204528SSimon Glass 3. Altered source versions must be plainly marked as such, and must
26cf204528SSimon Glass not be misrepresented as being the original software.
27cf204528SSimon Glass
28cf204528SSimon Glass 4. The name of the author may not be used to endorse or promote
29cf204528SSimon Glass products derived from this software without specific prior written
30cf204528SSimon Glass permission.
31cf204528SSimon Glass
32cf204528SSimon Glass THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
33cf204528SSimon Glass OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
34cf204528SSimon Glass WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
35cf204528SSimon Glass ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
36cf204528SSimon Glass DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37cf204528SSimon Glass DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
38cf204528SSimon Glass GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
39cf204528SSimon Glass INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
40cf204528SSimon Glass WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
41cf204528SSimon Glass NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
42cf204528SSimon Glass SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
43cf204528SSimon Glass
44cf204528SSimon Glass Julian Seward, Cambridge, UK.
45cf204528SSimon Glass jseward@acm.org
46cf204528SSimon Glass bzip2/libbzip2 version 1.0.6 of 6 September 2010
47cf204528SSimon Glass Copyright (C) 1996-2010 Julian Seward <jseward@bzip.org>
48cf204528SSimon Glass
49cf204528SSimon Glass This program is based on (at least) the work of:
50cf204528SSimon Glass Mike Burrows
51cf204528SSimon Glass David Wheeler
52cf204528SSimon Glass Peter Fenwick
53cf204528SSimon Glass Alistair Moffat
54cf204528SSimon Glass Radford Neal
55cf204528SSimon Glass Ian H. Witten
56cf204528SSimon Glass Robert Sedgewick
57cf204528SSimon Glass Jon L. Bentley
58cf204528SSimon Glass
59cf204528SSimon Glass For more information on these sources, see the manual.
60cf204528SSimon Glass --*/
61cf204528SSimon Glass
62cf204528SSimon Glass /* CHANGES
63cf204528SSimon Glass 0.9.0 -- original version.
64cf204528SSimon Glass 0.9.0a/b -- no changes in this file.
65cf204528SSimon Glass 0.9.0c -- changed setting of nGroups in sendMTFValues()
66cf204528SSimon Glass so as to do a bit better on small files
67cf204528SSimon Glass */
68cf204528SSimon Glass
69cf204528SSimon Glass #include "bzlib_private.h"
70*512cab7eSSimon Glass #include <compiler.h>
71cf204528SSimon Glass
72cf204528SSimon Glass /*---------------------------------------------------*/
73cf204528SSimon Glass /*--- Bit stream I/O ---*/
74cf204528SSimon Glass /*---------------------------------------------------*/
75cf204528SSimon Glass
76cf204528SSimon Glass /*---------------------------------------------------*/
BZ2_bsInitWrite(EState * s)77cf204528SSimon Glass void BZ2_bsInitWrite ( EState* s )
78cf204528SSimon Glass {
79cf204528SSimon Glass s->bsLive = 0;
80cf204528SSimon Glass s->bsBuff = 0;
81cf204528SSimon Glass }
82cf204528SSimon Glass
83cf204528SSimon Glass
84cf204528SSimon Glass /*---------------------------------------------------*/
85cf204528SSimon Glass static
bsFinishWrite(EState * s)86cf204528SSimon Glass void bsFinishWrite ( EState* s )
87cf204528SSimon Glass {
88cf204528SSimon Glass while (s->bsLive > 0) {
89cf204528SSimon Glass s->zbits[s->numZ] = (UChar)(s->bsBuff >> 24);
90cf204528SSimon Glass s->numZ++;
91cf204528SSimon Glass s->bsBuff <<= 8;
92cf204528SSimon Glass s->bsLive -= 8;
93cf204528SSimon Glass }
94cf204528SSimon Glass }
95cf204528SSimon Glass
96cf204528SSimon Glass
97cf204528SSimon Glass /*---------------------------------------------------*/
98cf204528SSimon Glass #define bsNEEDW(nz) \
99cf204528SSimon Glass { \
100cf204528SSimon Glass while (s->bsLive >= 8) { \
101cf204528SSimon Glass s->zbits[s->numZ] \
102cf204528SSimon Glass = (UChar)(s->bsBuff >> 24); \
103cf204528SSimon Glass s->numZ++; \
104cf204528SSimon Glass s->bsBuff <<= 8; \
105cf204528SSimon Glass s->bsLive -= 8; \
106cf204528SSimon Glass } \
107cf204528SSimon Glass }
108cf204528SSimon Glass
109cf204528SSimon Glass
110cf204528SSimon Glass /*---------------------------------------------------*/
111cf204528SSimon Glass static
112cf204528SSimon Glass __inline__
bsW(EState * s,Int32 n,UInt32 v)113cf204528SSimon Glass void bsW ( EState* s, Int32 n, UInt32 v )
114cf204528SSimon Glass {
115cf204528SSimon Glass bsNEEDW ( n );
116cf204528SSimon Glass s->bsBuff |= (v << (32 - s->bsLive - n));
117cf204528SSimon Glass s->bsLive += n;
118cf204528SSimon Glass }
119cf204528SSimon Glass
120cf204528SSimon Glass
121cf204528SSimon Glass /*---------------------------------------------------*/
122cf204528SSimon Glass static
bsPutUInt32(EState * s,UInt32 u)123cf204528SSimon Glass void bsPutUInt32 ( EState* s, UInt32 u )
124cf204528SSimon Glass {
125cf204528SSimon Glass bsW ( s, 8, (u >> 24) & 0xffL );
126cf204528SSimon Glass bsW ( s, 8, (u >> 16) & 0xffL );
127cf204528SSimon Glass bsW ( s, 8, (u >> 8) & 0xffL );
128cf204528SSimon Glass bsW ( s, 8, u & 0xffL );
129cf204528SSimon Glass }
130cf204528SSimon Glass
131cf204528SSimon Glass
132cf204528SSimon Glass /*---------------------------------------------------*/
133cf204528SSimon Glass static
bsPutUChar(EState * s,UChar c)134cf204528SSimon Glass void bsPutUChar ( EState* s, UChar c )
135cf204528SSimon Glass {
136cf204528SSimon Glass bsW( s, 8, (UInt32)c );
137cf204528SSimon Glass }
138cf204528SSimon Glass
139cf204528SSimon Glass
140cf204528SSimon Glass /*---------------------------------------------------*/
141cf204528SSimon Glass /*--- The back end proper ---*/
142cf204528SSimon Glass /*---------------------------------------------------*/
143cf204528SSimon Glass
144cf204528SSimon Glass /*---------------------------------------------------*/
145cf204528SSimon Glass static
makeMaps_e(EState * s)146cf204528SSimon Glass void makeMaps_e ( EState* s )
147cf204528SSimon Glass {
148cf204528SSimon Glass Int32 i;
149cf204528SSimon Glass s->nInUse = 0;
150cf204528SSimon Glass for (i = 0; i < 256; i++)
151cf204528SSimon Glass if (s->inUse[i]) {
152cf204528SSimon Glass s->unseqToSeq[i] = s->nInUse;
153cf204528SSimon Glass s->nInUse++;
154cf204528SSimon Glass }
155cf204528SSimon Glass }
156cf204528SSimon Glass
157cf204528SSimon Glass
158cf204528SSimon Glass /*---------------------------------------------------*/
159cf204528SSimon Glass static
generateMTFValues(EState * s)160cf204528SSimon Glass void generateMTFValues ( EState* s )
161cf204528SSimon Glass {
162cf204528SSimon Glass UChar yy[256];
163cf204528SSimon Glass Int32 i, j;
164cf204528SSimon Glass Int32 zPend;
165cf204528SSimon Glass Int32 wr;
166cf204528SSimon Glass Int32 EOB;
167cf204528SSimon Glass
168cf204528SSimon Glass /*
169cf204528SSimon Glass After sorting (eg, here),
170cf204528SSimon Glass s->arr1 [ 0 .. s->nblock-1 ] holds sorted order,
171cf204528SSimon Glass and
172cf204528SSimon Glass ((UChar*)s->arr2) [ 0 .. s->nblock-1 ]
173cf204528SSimon Glass holds the original block data.
174cf204528SSimon Glass
175cf204528SSimon Glass The first thing to do is generate the MTF values,
176cf204528SSimon Glass and put them in
177cf204528SSimon Glass ((UInt16*)s->arr1) [ 0 .. s->nblock-1 ].
178cf204528SSimon Glass Because there are strictly fewer or equal MTF values
179cf204528SSimon Glass than block values, ptr values in this area are overwritten
180cf204528SSimon Glass with MTF values only when they are no longer needed.
181cf204528SSimon Glass
182cf204528SSimon Glass The final compressed bitstream is generated into the
183cf204528SSimon Glass area starting at
184cf204528SSimon Glass (UChar*) (&((UChar*)s->arr2)[s->nblock])
185cf204528SSimon Glass
186cf204528SSimon Glass These storage aliases are set up in bzCompressInit(),
187cf204528SSimon Glass except for the last one, which is arranged in
188cf204528SSimon Glass compressBlock().
189cf204528SSimon Glass */
190cf204528SSimon Glass UInt32* ptr = s->ptr;
191cf204528SSimon Glass UChar* block = s->block;
192cf204528SSimon Glass UInt16* mtfv = s->mtfv;
193cf204528SSimon Glass
194cf204528SSimon Glass makeMaps_e ( s );
195cf204528SSimon Glass EOB = s->nInUse+1;
196cf204528SSimon Glass
197cf204528SSimon Glass for (i = 0; i <= EOB; i++) s->mtfFreq[i] = 0;
198cf204528SSimon Glass
199cf204528SSimon Glass wr = 0;
200cf204528SSimon Glass zPend = 0;
201cf204528SSimon Glass for (i = 0; i < s->nInUse; i++) yy[i] = (UChar) i;
202cf204528SSimon Glass
203cf204528SSimon Glass for (i = 0; i < s->nblock; i++) {
204cf204528SSimon Glass UChar ll_i;
205cf204528SSimon Glass AssertD ( wr <= i, "generateMTFValues(1)" );
206cf204528SSimon Glass j = ptr[i]-1; if (j < 0) j += s->nblock;
207cf204528SSimon Glass ll_i = s->unseqToSeq[block[j]];
208cf204528SSimon Glass AssertD ( ll_i < s->nInUse, "generateMTFValues(2a)" );
209cf204528SSimon Glass
210cf204528SSimon Glass if (yy[0] == ll_i) {
211cf204528SSimon Glass zPend++;
212cf204528SSimon Glass } else {
213cf204528SSimon Glass
214cf204528SSimon Glass if (zPend > 0) {
215cf204528SSimon Glass zPend--;
216cf204528SSimon Glass while (True) {
217cf204528SSimon Glass if (zPend & 1) {
218cf204528SSimon Glass mtfv[wr] = BZ_RUNB; wr++;
219cf204528SSimon Glass s->mtfFreq[BZ_RUNB]++;
220cf204528SSimon Glass } else {
221cf204528SSimon Glass mtfv[wr] = BZ_RUNA; wr++;
222cf204528SSimon Glass s->mtfFreq[BZ_RUNA]++;
223cf204528SSimon Glass }
224cf204528SSimon Glass if (zPend < 2) break;
225cf204528SSimon Glass zPend = (zPend - 2) / 2;
226cf204528SSimon Glass };
227cf204528SSimon Glass zPend = 0;
228cf204528SSimon Glass }
229cf204528SSimon Glass {
230cf204528SSimon Glass register UChar rtmp;
231cf204528SSimon Glass register UChar* ryy_j;
232cf204528SSimon Glass register UChar rll_i;
233cf204528SSimon Glass rtmp = yy[1];
234cf204528SSimon Glass yy[1] = yy[0];
235cf204528SSimon Glass ryy_j = &(yy[1]);
236cf204528SSimon Glass rll_i = ll_i;
237cf204528SSimon Glass while ( rll_i != rtmp ) {
238cf204528SSimon Glass register UChar rtmp2;
239cf204528SSimon Glass ryy_j++;
240cf204528SSimon Glass rtmp2 = rtmp;
241cf204528SSimon Glass rtmp = *ryy_j;
242cf204528SSimon Glass *ryy_j = rtmp2;
243cf204528SSimon Glass };
244cf204528SSimon Glass yy[0] = rtmp;
245cf204528SSimon Glass j = ryy_j - &(yy[0]);
246cf204528SSimon Glass mtfv[wr] = j+1; wr++; s->mtfFreq[j+1]++;
247cf204528SSimon Glass }
248cf204528SSimon Glass
249cf204528SSimon Glass }
250cf204528SSimon Glass }
251cf204528SSimon Glass
252cf204528SSimon Glass if (zPend > 0) {
253cf204528SSimon Glass zPend--;
254cf204528SSimon Glass while (True) {
255cf204528SSimon Glass if (zPend & 1) {
256cf204528SSimon Glass mtfv[wr] = BZ_RUNB; wr++;
257cf204528SSimon Glass s->mtfFreq[BZ_RUNB]++;
258cf204528SSimon Glass } else {
259cf204528SSimon Glass mtfv[wr] = BZ_RUNA; wr++;
260cf204528SSimon Glass s->mtfFreq[BZ_RUNA]++;
261cf204528SSimon Glass }
262cf204528SSimon Glass if (zPend < 2) break;
263cf204528SSimon Glass zPend = (zPend - 2) / 2;
264cf204528SSimon Glass };
265cf204528SSimon Glass zPend = 0;
266cf204528SSimon Glass }
267cf204528SSimon Glass
268cf204528SSimon Glass mtfv[wr] = EOB; wr++; s->mtfFreq[EOB]++;
269cf204528SSimon Glass
270cf204528SSimon Glass s->nMTF = wr;
271cf204528SSimon Glass }
272cf204528SSimon Glass
273cf204528SSimon Glass
274cf204528SSimon Glass /*---------------------------------------------------*/
275cf204528SSimon Glass #define BZ_LESSER_ICOST 0
276cf204528SSimon Glass #define BZ_GREATER_ICOST 15
277cf204528SSimon Glass
278cf204528SSimon Glass static
sendMTFValues(EState * s)279cf204528SSimon Glass void sendMTFValues ( EState* s )
280cf204528SSimon Glass {
281cf204528SSimon Glass Int32 v, t, i, j, gs, ge, totc, bt, bc, iter;
282cf204528SSimon Glass Int32 nSelectors, alphaSize, minLen, maxLen, selCtr;
283*512cab7eSSimon Glass Int32 nGroups;
284*512cab7eSSimon Glass Int32 nBytes __maybe_unused;
285cf204528SSimon Glass
286cf204528SSimon Glass /*--
287cf204528SSimon Glass UChar len [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
288cf204528SSimon Glass is a global since the decoder also needs it.
289cf204528SSimon Glass
290cf204528SSimon Glass Int32 code[BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
291cf204528SSimon Glass Int32 rfreq[BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
292cf204528SSimon Glass are also globals only used in this proc.
293cf204528SSimon Glass Made global to keep stack frame size small.
294cf204528SSimon Glass --*/
295cf204528SSimon Glass
296cf204528SSimon Glass
297cf204528SSimon Glass UInt16 cost[BZ_N_GROUPS];
298cf204528SSimon Glass Int32 fave[BZ_N_GROUPS];
299cf204528SSimon Glass
300cf204528SSimon Glass UInt16* mtfv = s->mtfv;
301cf204528SSimon Glass
302cf204528SSimon Glass if (s->verbosity >= 3)
303cf204528SSimon Glass VPrintf3( " %d in block, %d after MTF & 1-2 coding, "
304cf204528SSimon Glass "%d+2 syms in use\n",
305cf204528SSimon Glass s->nblock, s->nMTF, s->nInUse );
306cf204528SSimon Glass
307cf204528SSimon Glass alphaSize = s->nInUse+2;
308cf204528SSimon Glass for (t = 0; t < BZ_N_GROUPS; t++)
309cf204528SSimon Glass for (v = 0; v < alphaSize; v++)
310cf204528SSimon Glass s->len[t][v] = BZ_GREATER_ICOST;
311cf204528SSimon Glass
312cf204528SSimon Glass /*--- Decide how many coding tables to use ---*/
313cf204528SSimon Glass AssertH ( s->nMTF > 0, 3001 );
314cf204528SSimon Glass if (s->nMTF < 200) nGroups = 2; else
315cf204528SSimon Glass if (s->nMTF < 600) nGroups = 3; else
316cf204528SSimon Glass if (s->nMTF < 1200) nGroups = 4; else
317cf204528SSimon Glass if (s->nMTF < 2400) nGroups = 5; else
318cf204528SSimon Glass nGroups = 6;
319cf204528SSimon Glass
320cf204528SSimon Glass /*--- Generate an initial set of coding tables ---*/
321cf204528SSimon Glass {
322cf204528SSimon Glass Int32 nPart, remF, tFreq, aFreq;
323cf204528SSimon Glass
324cf204528SSimon Glass nPart = nGroups;
325cf204528SSimon Glass remF = s->nMTF;
326cf204528SSimon Glass gs = 0;
327cf204528SSimon Glass while (nPart > 0) {
328cf204528SSimon Glass tFreq = remF / nPart;
329cf204528SSimon Glass ge = gs-1;
330cf204528SSimon Glass aFreq = 0;
331cf204528SSimon Glass while (aFreq < tFreq && ge < alphaSize-1) {
332cf204528SSimon Glass ge++;
333cf204528SSimon Glass aFreq += s->mtfFreq[ge];
334cf204528SSimon Glass }
335cf204528SSimon Glass
336cf204528SSimon Glass if (ge > gs
337cf204528SSimon Glass && nPart != nGroups && nPart != 1
338cf204528SSimon Glass && ((nGroups-nPart) % 2 == 1)) {
339cf204528SSimon Glass aFreq -= s->mtfFreq[ge];
340cf204528SSimon Glass ge--;
341cf204528SSimon Glass }
342cf204528SSimon Glass
343cf204528SSimon Glass if (s->verbosity >= 3)
344cf204528SSimon Glass VPrintf5( " initial group %d, [%d .. %d], "
345cf204528SSimon Glass "has %d syms (%4.1f%%)\n",
346cf204528SSimon Glass nPart, gs, ge, aFreq,
347cf204528SSimon Glass (100.0 * (float)aFreq) / (float)(s->nMTF) );
348cf204528SSimon Glass
349cf204528SSimon Glass for (v = 0; v < alphaSize; v++)
350cf204528SSimon Glass if (v >= gs && v <= ge)
351cf204528SSimon Glass s->len[nPart-1][v] = BZ_LESSER_ICOST; else
352cf204528SSimon Glass s->len[nPart-1][v] = BZ_GREATER_ICOST;
353cf204528SSimon Glass
354cf204528SSimon Glass nPart--;
355cf204528SSimon Glass gs = ge+1;
356cf204528SSimon Glass remF -= aFreq;
357cf204528SSimon Glass }
358cf204528SSimon Glass }
359cf204528SSimon Glass
360cf204528SSimon Glass /*---
361cf204528SSimon Glass Iterate up to BZ_N_ITERS times to improve the tables.
362cf204528SSimon Glass ---*/
363cf204528SSimon Glass for (iter = 0; iter < BZ_N_ITERS; iter++) {
364cf204528SSimon Glass
365cf204528SSimon Glass for (t = 0; t < nGroups; t++) fave[t] = 0;
366cf204528SSimon Glass
367cf204528SSimon Glass for (t = 0; t < nGroups; t++)
368cf204528SSimon Glass for (v = 0; v < alphaSize; v++)
369cf204528SSimon Glass s->rfreq[t][v] = 0;
370cf204528SSimon Glass
371cf204528SSimon Glass /*---
372cf204528SSimon Glass Set up an auxiliary length table which is used to fast-track
373cf204528SSimon Glass the common case (nGroups == 6).
374cf204528SSimon Glass ---*/
375cf204528SSimon Glass if (nGroups == 6) {
376cf204528SSimon Glass for (v = 0; v < alphaSize; v++) {
377cf204528SSimon Glass s->len_pack[v][0] = (s->len[1][v] << 16) | s->len[0][v];
378cf204528SSimon Glass s->len_pack[v][1] = (s->len[3][v] << 16) | s->len[2][v];
379cf204528SSimon Glass s->len_pack[v][2] = (s->len[5][v] << 16) | s->len[4][v];
380cf204528SSimon Glass }
381cf204528SSimon Glass }
382cf204528SSimon Glass
383cf204528SSimon Glass nSelectors = 0;
384cf204528SSimon Glass totc = 0;
385cf204528SSimon Glass gs = 0;
386cf204528SSimon Glass while (True) {
387cf204528SSimon Glass
388cf204528SSimon Glass /*--- Set group start & end marks. --*/
389cf204528SSimon Glass if (gs >= s->nMTF) break;
390cf204528SSimon Glass ge = gs + BZ_G_SIZE - 1;
391cf204528SSimon Glass if (ge >= s->nMTF) ge = s->nMTF-1;
392cf204528SSimon Glass
393cf204528SSimon Glass /*--
394cf204528SSimon Glass Calculate the cost of this group as coded
395cf204528SSimon Glass by each of the coding tables.
396cf204528SSimon Glass --*/
397cf204528SSimon Glass for (t = 0; t < nGroups; t++) cost[t] = 0;
398cf204528SSimon Glass
399cf204528SSimon Glass if (nGroups == 6 && 50 == ge-gs+1) {
400cf204528SSimon Glass /*--- fast track the common case ---*/
401cf204528SSimon Glass register UInt32 cost01, cost23, cost45;
402cf204528SSimon Glass register UInt16 icv;
403cf204528SSimon Glass cost01 = cost23 = cost45 = 0;
404cf204528SSimon Glass
405cf204528SSimon Glass # define BZ_ITER(nn) \
406cf204528SSimon Glass icv = mtfv[gs+(nn)]; \
407cf204528SSimon Glass cost01 += s->len_pack[icv][0]; \
408cf204528SSimon Glass cost23 += s->len_pack[icv][1]; \
409cf204528SSimon Glass cost45 += s->len_pack[icv][2]; \
410cf204528SSimon Glass
411cf204528SSimon Glass BZ_ITER(0); BZ_ITER(1); BZ_ITER(2); BZ_ITER(3); BZ_ITER(4);
412cf204528SSimon Glass BZ_ITER(5); BZ_ITER(6); BZ_ITER(7); BZ_ITER(8); BZ_ITER(9);
413cf204528SSimon Glass BZ_ITER(10); BZ_ITER(11); BZ_ITER(12); BZ_ITER(13); BZ_ITER(14);
414cf204528SSimon Glass BZ_ITER(15); BZ_ITER(16); BZ_ITER(17); BZ_ITER(18); BZ_ITER(19);
415cf204528SSimon Glass BZ_ITER(20); BZ_ITER(21); BZ_ITER(22); BZ_ITER(23); BZ_ITER(24);
416cf204528SSimon Glass BZ_ITER(25); BZ_ITER(26); BZ_ITER(27); BZ_ITER(28); BZ_ITER(29);
417cf204528SSimon Glass BZ_ITER(30); BZ_ITER(31); BZ_ITER(32); BZ_ITER(33); BZ_ITER(34);
418cf204528SSimon Glass BZ_ITER(35); BZ_ITER(36); BZ_ITER(37); BZ_ITER(38); BZ_ITER(39);
419cf204528SSimon Glass BZ_ITER(40); BZ_ITER(41); BZ_ITER(42); BZ_ITER(43); BZ_ITER(44);
420cf204528SSimon Glass BZ_ITER(45); BZ_ITER(46); BZ_ITER(47); BZ_ITER(48); BZ_ITER(49);
421cf204528SSimon Glass
422cf204528SSimon Glass # undef BZ_ITER
423cf204528SSimon Glass
424cf204528SSimon Glass cost[0] = cost01 & 0xffff; cost[1] = cost01 >> 16;
425cf204528SSimon Glass cost[2] = cost23 & 0xffff; cost[3] = cost23 >> 16;
426cf204528SSimon Glass cost[4] = cost45 & 0xffff; cost[5] = cost45 >> 16;
427cf204528SSimon Glass
428cf204528SSimon Glass } else {
429cf204528SSimon Glass /*--- slow version which correctly handles all situations ---*/
430cf204528SSimon Glass for (i = gs; i <= ge; i++) {
431cf204528SSimon Glass UInt16 icv = mtfv[i];
432cf204528SSimon Glass for (t = 0; t < nGroups; t++) cost[t] += s->len[t][icv];
433cf204528SSimon Glass }
434cf204528SSimon Glass }
435cf204528SSimon Glass
436cf204528SSimon Glass /*--
437cf204528SSimon Glass Find the coding table which is best for this group,
438cf204528SSimon Glass and record its identity in the selector table.
439cf204528SSimon Glass --*/
440cf204528SSimon Glass bc = 999999999; bt = -1;
441cf204528SSimon Glass for (t = 0; t < nGroups; t++)
442cf204528SSimon Glass if (cost[t] < bc) { bc = cost[t]; bt = t; };
443cf204528SSimon Glass totc += bc;
444cf204528SSimon Glass fave[bt]++;
445cf204528SSimon Glass s->selector[nSelectors] = bt;
446cf204528SSimon Glass nSelectors++;
447cf204528SSimon Glass
448cf204528SSimon Glass /*--
449cf204528SSimon Glass Increment the symbol frequencies for the selected table.
450cf204528SSimon Glass --*/
451cf204528SSimon Glass if (nGroups == 6 && 50 == ge-gs+1) {
452cf204528SSimon Glass /*--- fast track the common case ---*/
453cf204528SSimon Glass
454cf204528SSimon Glass # define BZ_ITUR(nn) s->rfreq[bt][ mtfv[gs+(nn)] ]++
455cf204528SSimon Glass
456cf204528SSimon Glass BZ_ITUR(0); BZ_ITUR(1); BZ_ITUR(2); BZ_ITUR(3); BZ_ITUR(4);
457cf204528SSimon Glass BZ_ITUR(5); BZ_ITUR(6); BZ_ITUR(7); BZ_ITUR(8); BZ_ITUR(9);
458cf204528SSimon Glass BZ_ITUR(10); BZ_ITUR(11); BZ_ITUR(12); BZ_ITUR(13); BZ_ITUR(14);
459cf204528SSimon Glass BZ_ITUR(15); BZ_ITUR(16); BZ_ITUR(17); BZ_ITUR(18); BZ_ITUR(19);
460cf204528SSimon Glass BZ_ITUR(20); BZ_ITUR(21); BZ_ITUR(22); BZ_ITUR(23); BZ_ITUR(24);
461cf204528SSimon Glass BZ_ITUR(25); BZ_ITUR(26); BZ_ITUR(27); BZ_ITUR(28); BZ_ITUR(29);
462cf204528SSimon Glass BZ_ITUR(30); BZ_ITUR(31); BZ_ITUR(32); BZ_ITUR(33); BZ_ITUR(34);
463cf204528SSimon Glass BZ_ITUR(35); BZ_ITUR(36); BZ_ITUR(37); BZ_ITUR(38); BZ_ITUR(39);
464cf204528SSimon Glass BZ_ITUR(40); BZ_ITUR(41); BZ_ITUR(42); BZ_ITUR(43); BZ_ITUR(44);
465cf204528SSimon Glass BZ_ITUR(45); BZ_ITUR(46); BZ_ITUR(47); BZ_ITUR(48); BZ_ITUR(49);
466cf204528SSimon Glass
467cf204528SSimon Glass # undef BZ_ITUR
468cf204528SSimon Glass
469cf204528SSimon Glass } else {
470cf204528SSimon Glass /*--- slow version which correctly handles all situations ---*/
471cf204528SSimon Glass for (i = gs; i <= ge; i++)
472cf204528SSimon Glass s->rfreq[bt][ mtfv[i] ]++;
473cf204528SSimon Glass }
474cf204528SSimon Glass
475cf204528SSimon Glass gs = ge+1;
476cf204528SSimon Glass }
477cf204528SSimon Glass if (s->verbosity >= 3) {
478cf204528SSimon Glass VPrintf2 ( " pass %d: size is %d, grp uses are ",
479cf204528SSimon Glass iter+1, totc/8 );
480cf204528SSimon Glass for (t = 0; t < nGroups; t++)
481cf204528SSimon Glass VPrintf1 ( "%d ", fave[t] );
482cf204528SSimon Glass VPrintf0 ( "\n" );
483cf204528SSimon Glass }
484cf204528SSimon Glass
485cf204528SSimon Glass /*--
486cf204528SSimon Glass Recompute the tables based on the accumulated frequencies.
487cf204528SSimon Glass --*/
488cf204528SSimon Glass /* maxLen was changed from 20 to 17 in bzip2-1.0.3. See
489cf204528SSimon Glass comment in huffman.c for details. */
490cf204528SSimon Glass for (t = 0; t < nGroups; t++)
491cf204528SSimon Glass BZ2_hbMakeCodeLengths ( &(s->len[t][0]), &(s->rfreq[t][0]),
492cf204528SSimon Glass alphaSize, 17 /*20*/ );
493cf204528SSimon Glass }
494cf204528SSimon Glass
495cf204528SSimon Glass
496cf204528SSimon Glass AssertH( nGroups < 8, 3002 );
497cf204528SSimon Glass AssertH( nSelectors < 32768 &&
498cf204528SSimon Glass nSelectors <= (2 + (900000 / BZ_G_SIZE)),
499cf204528SSimon Glass 3003 );
500cf204528SSimon Glass
501cf204528SSimon Glass
502cf204528SSimon Glass /*--- Compute MTF values for the selectors. ---*/
503cf204528SSimon Glass {
504cf204528SSimon Glass UChar pos[BZ_N_GROUPS], ll_i, tmp2, tmp;
505cf204528SSimon Glass for (i = 0; i < nGroups; i++) pos[i] = i;
506cf204528SSimon Glass for (i = 0; i < nSelectors; i++) {
507cf204528SSimon Glass ll_i = s->selector[i];
508cf204528SSimon Glass j = 0;
509cf204528SSimon Glass tmp = pos[j];
510cf204528SSimon Glass while ( ll_i != tmp ) {
511cf204528SSimon Glass j++;
512cf204528SSimon Glass tmp2 = tmp;
513cf204528SSimon Glass tmp = pos[j];
514cf204528SSimon Glass pos[j] = tmp2;
515cf204528SSimon Glass };
516cf204528SSimon Glass pos[0] = tmp;
517cf204528SSimon Glass s->selectorMtf[i] = j;
518cf204528SSimon Glass }
519cf204528SSimon Glass };
520cf204528SSimon Glass
521cf204528SSimon Glass /*--- Assign actual codes for the tables. --*/
522cf204528SSimon Glass for (t = 0; t < nGroups; t++) {
523cf204528SSimon Glass minLen = 32;
524cf204528SSimon Glass maxLen = 0;
525cf204528SSimon Glass for (i = 0; i < alphaSize; i++) {
526cf204528SSimon Glass if (s->len[t][i] > maxLen) maxLen = s->len[t][i];
527cf204528SSimon Glass if (s->len[t][i] < minLen) minLen = s->len[t][i];
528cf204528SSimon Glass }
529cf204528SSimon Glass AssertH ( !(maxLen > 17 /*20*/ ), 3004 );
530cf204528SSimon Glass AssertH ( !(minLen < 1), 3005 );
531cf204528SSimon Glass BZ2_hbAssignCodes ( &(s->code[t][0]), &(s->len[t][0]),
532cf204528SSimon Glass minLen, maxLen, alphaSize );
533cf204528SSimon Glass }
534cf204528SSimon Glass
535cf204528SSimon Glass /*--- Transmit the mapping table. ---*/
536cf204528SSimon Glass {
537cf204528SSimon Glass Bool inUse16[16];
538cf204528SSimon Glass for (i = 0; i < 16; i++) {
539cf204528SSimon Glass inUse16[i] = False;
540cf204528SSimon Glass for (j = 0; j < 16; j++)
541cf204528SSimon Glass if (s->inUse[i * 16 + j]) inUse16[i] = True;
542cf204528SSimon Glass }
543cf204528SSimon Glass
544cf204528SSimon Glass nBytes = s->numZ;
545cf204528SSimon Glass for (i = 0; i < 16; i++)
546cf204528SSimon Glass if (inUse16[i]) bsW(s,1,1); else bsW(s,1,0);
547cf204528SSimon Glass
548cf204528SSimon Glass for (i = 0; i < 16; i++)
549cf204528SSimon Glass if (inUse16[i])
550cf204528SSimon Glass for (j = 0; j < 16; j++) {
551cf204528SSimon Glass if (s->inUse[i * 16 + j]) bsW(s,1,1); else bsW(s,1,0);
552cf204528SSimon Glass }
553cf204528SSimon Glass
554cf204528SSimon Glass if (s->verbosity >= 3)
555cf204528SSimon Glass VPrintf1( " bytes: mapping %d, ", s->numZ-nBytes );
556cf204528SSimon Glass }
557cf204528SSimon Glass
558cf204528SSimon Glass /*--- Now the selectors. ---*/
559cf204528SSimon Glass nBytes = s->numZ;
560cf204528SSimon Glass bsW ( s, 3, nGroups );
561cf204528SSimon Glass bsW ( s, 15, nSelectors );
562cf204528SSimon Glass for (i = 0; i < nSelectors; i++) {
563cf204528SSimon Glass for (j = 0; j < s->selectorMtf[i]; j++) bsW(s,1,1);
564cf204528SSimon Glass bsW(s,1,0);
565cf204528SSimon Glass }
566cf204528SSimon Glass if (s->verbosity >= 3)
567cf204528SSimon Glass VPrintf1( "selectors %d, ", s->numZ-nBytes );
568cf204528SSimon Glass
569cf204528SSimon Glass /*--- Now the coding tables. ---*/
570cf204528SSimon Glass nBytes = s->numZ;
571cf204528SSimon Glass
572cf204528SSimon Glass for (t = 0; t < nGroups; t++) {
573cf204528SSimon Glass Int32 curr = s->len[t][0];
574cf204528SSimon Glass bsW ( s, 5, curr );
575cf204528SSimon Glass for (i = 0; i < alphaSize; i++) {
576cf204528SSimon Glass while (curr < s->len[t][i]) { bsW(s,2,2); curr++; /* 10 */ };
577cf204528SSimon Glass while (curr > s->len[t][i]) { bsW(s,2,3); curr--; /* 11 */ };
578cf204528SSimon Glass bsW ( s, 1, 0 );
579cf204528SSimon Glass }
580cf204528SSimon Glass }
581cf204528SSimon Glass
582cf204528SSimon Glass if (s->verbosity >= 3)
583cf204528SSimon Glass VPrintf1 ( "code lengths %d, ", s->numZ-nBytes );
584cf204528SSimon Glass
585cf204528SSimon Glass /*--- And finally, the block data proper ---*/
586cf204528SSimon Glass nBytes = s->numZ;
587cf204528SSimon Glass selCtr = 0;
588cf204528SSimon Glass gs = 0;
589cf204528SSimon Glass while (True) {
590cf204528SSimon Glass if (gs >= s->nMTF) break;
591cf204528SSimon Glass ge = gs + BZ_G_SIZE - 1;
592cf204528SSimon Glass if (ge >= s->nMTF) ge = s->nMTF-1;
593cf204528SSimon Glass AssertH ( s->selector[selCtr] < nGroups, 3006 );
594cf204528SSimon Glass
595cf204528SSimon Glass if (nGroups == 6 && 50 == ge-gs+1) {
596cf204528SSimon Glass /*--- fast track the common case ---*/
597cf204528SSimon Glass UInt16 mtfv_i;
598cf204528SSimon Glass UChar* s_len_sel_selCtr
599cf204528SSimon Glass = &(s->len[s->selector[selCtr]][0]);
600cf204528SSimon Glass Int32* s_code_sel_selCtr
601cf204528SSimon Glass = &(s->code[s->selector[selCtr]][0]);
602cf204528SSimon Glass
603cf204528SSimon Glass # define BZ_ITAH(nn) \
604cf204528SSimon Glass mtfv_i = mtfv[gs+(nn)]; \
605cf204528SSimon Glass bsW ( s, \
606cf204528SSimon Glass s_len_sel_selCtr[mtfv_i], \
607cf204528SSimon Glass s_code_sel_selCtr[mtfv_i] )
608cf204528SSimon Glass
609cf204528SSimon Glass BZ_ITAH(0); BZ_ITAH(1); BZ_ITAH(2); BZ_ITAH(3); BZ_ITAH(4);
610cf204528SSimon Glass BZ_ITAH(5); BZ_ITAH(6); BZ_ITAH(7); BZ_ITAH(8); BZ_ITAH(9);
611cf204528SSimon Glass BZ_ITAH(10); BZ_ITAH(11); BZ_ITAH(12); BZ_ITAH(13); BZ_ITAH(14);
612cf204528SSimon Glass BZ_ITAH(15); BZ_ITAH(16); BZ_ITAH(17); BZ_ITAH(18); BZ_ITAH(19);
613cf204528SSimon Glass BZ_ITAH(20); BZ_ITAH(21); BZ_ITAH(22); BZ_ITAH(23); BZ_ITAH(24);
614cf204528SSimon Glass BZ_ITAH(25); BZ_ITAH(26); BZ_ITAH(27); BZ_ITAH(28); BZ_ITAH(29);
615cf204528SSimon Glass BZ_ITAH(30); BZ_ITAH(31); BZ_ITAH(32); BZ_ITAH(33); BZ_ITAH(34);
616cf204528SSimon Glass BZ_ITAH(35); BZ_ITAH(36); BZ_ITAH(37); BZ_ITAH(38); BZ_ITAH(39);
617cf204528SSimon Glass BZ_ITAH(40); BZ_ITAH(41); BZ_ITAH(42); BZ_ITAH(43); BZ_ITAH(44);
618cf204528SSimon Glass BZ_ITAH(45); BZ_ITAH(46); BZ_ITAH(47); BZ_ITAH(48); BZ_ITAH(49);
619cf204528SSimon Glass
620cf204528SSimon Glass # undef BZ_ITAH
621cf204528SSimon Glass
622cf204528SSimon Glass } else {
623cf204528SSimon Glass /*--- slow version which correctly handles all situations ---*/
624cf204528SSimon Glass for (i = gs; i <= ge; i++) {
625cf204528SSimon Glass bsW ( s,
626cf204528SSimon Glass s->len [s->selector[selCtr]] [mtfv[i]],
627cf204528SSimon Glass s->code [s->selector[selCtr]] [mtfv[i]] );
628cf204528SSimon Glass }
629cf204528SSimon Glass }
630cf204528SSimon Glass
631cf204528SSimon Glass
632cf204528SSimon Glass gs = ge+1;
633cf204528SSimon Glass selCtr++;
634cf204528SSimon Glass }
635cf204528SSimon Glass AssertH( selCtr == nSelectors, 3007 );
636cf204528SSimon Glass
637cf204528SSimon Glass if (s->verbosity >= 3)
638cf204528SSimon Glass VPrintf1( "codes %d\n", s->numZ-nBytes );
639cf204528SSimon Glass }
640cf204528SSimon Glass
641cf204528SSimon Glass
642cf204528SSimon Glass /*---------------------------------------------------*/
BZ2_compressBlock(EState * s,Bool is_last_block)643cf204528SSimon Glass void BZ2_compressBlock ( EState* s, Bool is_last_block )
644cf204528SSimon Glass {
645cf204528SSimon Glass if (s->nblock > 0) {
646cf204528SSimon Glass
647cf204528SSimon Glass BZ_FINALISE_CRC ( s->blockCRC );
648cf204528SSimon Glass s->combinedCRC = (s->combinedCRC << 1) | (s->combinedCRC >> 31);
649cf204528SSimon Glass s->combinedCRC ^= s->blockCRC;
650cf204528SSimon Glass if (s->blockNo > 1) s->numZ = 0;
651cf204528SSimon Glass
652cf204528SSimon Glass if (s->verbosity >= 2)
653cf204528SSimon Glass VPrintf4( " block %d: crc = 0x%08x, "
654cf204528SSimon Glass "combined CRC = 0x%08x, size = %d\n",
655cf204528SSimon Glass s->blockNo, s->blockCRC, s->combinedCRC, s->nblock );
656cf204528SSimon Glass
657cf204528SSimon Glass BZ2_blockSort ( s );
658cf204528SSimon Glass }
659cf204528SSimon Glass
660cf204528SSimon Glass s->zbits = (UChar*) (&((UChar*)s->arr2)[s->nblock]);
661cf204528SSimon Glass
662cf204528SSimon Glass /*-- If this is the first block, create the stream header. --*/
663cf204528SSimon Glass if (s->blockNo == 1) {
664cf204528SSimon Glass BZ2_bsInitWrite ( s );
665cf204528SSimon Glass bsPutUChar ( s, BZ_HDR_B );
666cf204528SSimon Glass bsPutUChar ( s, BZ_HDR_Z );
667cf204528SSimon Glass bsPutUChar ( s, BZ_HDR_h );
668cf204528SSimon Glass bsPutUChar ( s, (UChar)(BZ_HDR_0 + s->blockSize100k) );
669cf204528SSimon Glass }
670cf204528SSimon Glass
671cf204528SSimon Glass if (s->nblock > 0) {
672cf204528SSimon Glass
673cf204528SSimon Glass bsPutUChar ( s, 0x31 ); bsPutUChar ( s, 0x41 );
674cf204528SSimon Glass bsPutUChar ( s, 0x59 ); bsPutUChar ( s, 0x26 );
675cf204528SSimon Glass bsPutUChar ( s, 0x53 ); bsPutUChar ( s, 0x59 );
676cf204528SSimon Glass
677cf204528SSimon Glass /*-- Now the block's CRC, so it is in a known place. --*/
678cf204528SSimon Glass bsPutUInt32 ( s, s->blockCRC );
679cf204528SSimon Glass
680cf204528SSimon Glass /*--
681cf204528SSimon Glass Now a single bit indicating (non-)randomisation.
682cf204528SSimon Glass As of version 0.9.5, we use a better sorting algorithm
683cf204528SSimon Glass which makes randomisation unnecessary. So always set
684cf204528SSimon Glass the randomised bit to 'no'. Of course, the decoder
685cf204528SSimon Glass still needs to be able to handle randomised blocks
686cf204528SSimon Glass so as to maintain backwards compatibility with
687cf204528SSimon Glass older versions of bzip2.
688cf204528SSimon Glass --*/
689cf204528SSimon Glass bsW(s,1,0);
690cf204528SSimon Glass
691cf204528SSimon Glass bsW ( s, 24, s->origPtr );
692cf204528SSimon Glass generateMTFValues ( s );
693cf204528SSimon Glass sendMTFValues ( s );
694cf204528SSimon Glass }
695cf204528SSimon Glass
696cf204528SSimon Glass
697cf204528SSimon Glass /*-- If this is the last block, add the stream trailer. --*/
698cf204528SSimon Glass if (is_last_block) {
699cf204528SSimon Glass
700cf204528SSimon Glass bsPutUChar ( s, 0x17 ); bsPutUChar ( s, 0x72 );
701cf204528SSimon Glass bsPutUChar ( s, 0x45 ); bsPutUChar ( s, 0x38 );
702cf204528SSimon Glass bsPutUChar ( s, 0x50 ); bsPutUChar ( s, 0x90 );
703cf204528SSimon Glass bsPutUInt32 ( s, s->combinedCRC );
704cf204528SSimon Glass if (s->verbosity >= 2)
705cf204528SSimon Glass VPrintf1( " final combined CRC = 0x%08x\n ", s->combinedCRC );
706cf204528SSimon Glass bsFinishWrite ( s );
707cf204528SSimon Glass }
708cf204528SSimon Glass }
709cf204528SSimon Glass
710cf204528SSimon Glass
711cf204528SSimon Glass /*-------------------------------------------------------------*/
712cf204528SSimon Glass /*--- end compress.c ---*/
713cf204528SSimon Glass /*-------------------------------------------------------------*/
714