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