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