171e7ee59SPeter Avalos
271e7ee59SPeter Avalos /*-------------------------------------------------------------*/
371e7ee59SPeter Avalos /*--- Compression machinery (not incl block sorting) ---*/
471e7ee59SPeter Avalos /*--- compress.c ---*/
571e7ee59SPeter Avalos /*-------------------------------------------------------------*/
671e7ee59SPeter Avalos
771e7ee59SPeter Avalos /* ------------------------------------------------------------------
871e7ee59SPeter Avalos This file is part of bzip2/libbzip2, a program and library for
971e7ee59SPeter Avalos lossless, block-sorting data compression.
1071e7ee59SPeter Avalos
11*86954436SDaniel Fojt bzip2/libbzip2 version 1.0.8 of 13 July 2019
12*86954436SDaniel Fojt Copyright (C) 1996-2019 Julian Seward <jseward@acm.org>
1371e7ee59SPeter Avalos
1471e7ee59SPeter Avalos Please read the WARNING, DISCLAIMER and PATENTS sections in the
1571e7ee59SPeter Avalos README file.
1671e7ee59SPeter Avalos
1771e7ee59SPeter Avalos This program is released under the terms of the license contained
1871e7ee59SPeter Avalos in the file LICENSE.
1971e7ee59SPeter Avalos ------------------------------------------------------------------ */
2071e7ee59SPeter Avalos
2171e7ee59SPeter Avalos
2271e7ee59SPeter Avalos /* CHANGES
2371e7ee59SPeter Avalos 0.9.0 -- original version.
2471e7ee59SPeter Avalos 0.9.0a/b -- no changes in this file.
2571e7ee59SPeter Avalos 0.9.0c -- changed setting of nGroups in sendMTFValues()
2671e7ee59SPeter Avalos so as to do a bit better on small files
2771e7ee59SPeter Avalos */
2871e7ee59SPeter Avalos
2971e7ee59SPeter Avalos #include "bzlib_private.h"
3071e7ee59SPeter Avalos
3171e7ee59SPeter Avalos
3271e7ee59SPeter Avalos /*---------------------------------------------------*/
3371e7ee59SPeter Avalos /*--- Bit stream I/O ---*/
3471e7ee59SPeter Avalos /*---------------------------------------------------*/
3571e7ee59SPeter Avalos
3671e7ee59SPeter Avalos /*---------------------------------------------------*/
BZ2_bsInitWrite(EState * s)3771e7ee59SPeter Avalos void BZ2_bsInitWrite ( EState* s )
3871e7ee59SPeter Avalos {
3971e7ee59SPeter Avalos s->bsLive = 0;
4071e7ee59SPeter Avalos s->bsBuff = 0;
4171e7ee59SPeter Avalos }
4271e7ee59SPeter Avalos
4371e7ee59SPeter Avalos
4471e7ee59SPeter Avalos /*---------------------------------------------------*/
4571e7ee59SPeter Avalos static
bsFinishWrite(EState * s)4671e7ee59SPeter Avalos void bsFinishWrite ( EState* s )
4771e7ee59SPeter Avalos {
4871e7ee59SPeter Avalos while (s->bsLive > 0) {
4971e7ee59SPeter Avalos s->zbits[s->numZ] = (UChar)(s->bsBuff >> 24);
5071e7ee59SPeter Avalos s->numZ++;
5171e7ee59SPeter Avalos s->bsBuff <<= 8;
5271e7ee59SPeter Avalos s->bsLive -= 8;
5371e7ee59SPeter Avalos }
5471e7ee59SPeter Avalos }
5571e7ee59SPeter Avalos
5671e7ee59SPeter Avalos
5771e7ee59SPeter Avalos /*---------------------------------------------------*/
5871e7ee59SPeter Avalos #define bsNEEDW(nz) \
5971e7ee59SPeter Avalos { \
6071e7ee59SPeter Avalos while (s->bsLive >= 8) { \
6171e7ee59SPeter Avalos s->zbits[s->numZ] \
6271e7ee59SPeter Avalos = (UChar)(s->bsBuff >> 24); \
6371e7ee59SPeter Avalos s->numZ++; \
6471e7ee59SPeter Avalos s->bsBuff <<= 8; \
6571e7ee59SPeter Avalos s->bsLive -= 8; \
6671e7ee59SPeter Avalos } \
6771e7ee59SPeter Avalos }
6871e7ee59SPeter Avalos
6971e7ee59SPeter Avalos
7071e7ee59SPeter Avalos /*---------------------------------------------------*/
7171e7ee59SPeter Avalos static
7271e7ee59SPeter Avalos __inline__
bsW(EState * s,Int32 n,UInt32 v)7371e7ee59SPeter Avalos void bsW ( EState* s, Int32 n, UInt32 v )
7471e7ee59SPeter Avalos {
7571e7ee59SPeter Avalos bsNEEDW ( n );
7671e7ee59SPeter Avalos s->bsBuff |= (v << (32 - s->bsLive - n));
7771e7ee59SPeter Avalos s->bsLive += n;
7871e7ee59SPeter Avalos }
7971e7ee59SPeter Avalos
8071e7ee59SPeter Avalos
8171e7ee59SPeter Avalos /*---------------------------------------------------*/
8271e7ee59SPeter Avalos static
bsPutUInt32(EState * s,UInt32 u)8371e7ee59SPeter Avalos void bsPutUInt32 ( EState* s, UInt32 u )
8471e7ee59SPeter Avalos {
8571e7ee59SPeter Avalos bsW ( s, 8, (u >> 24) & 0xffL );
8671e7ee59SPeter Avalos bsW ( s, 8, (u >> 16) & 0xffL );
8771e7ee59SPeter Avalos bsW ( s, 8, (u >> 8) & 0xffL );
8871e7ee59SPeter Avalos bsW ( s, 8, u & 0xffL );
8971e7ee59SPeter Avalos }
9071e7ee59SPeter Avalos
9171e7ee59SPeter Avalos
9271e7ee59SPeter Avalos /*---------------------------------------------------*/
9371e7ee59SPeter Avalos static
bsPutUChar(EState * s,UChar c)9471e7ee59SPeter Avalos void bsPutUChar ( EState* s, UChar c )
9571e7ee59SPeter Avalos {
9671e7ee59SPeter Avalos bsW( s, 8, (UInt32)c );
9771e7ee59SPeter Avalos }
9871e7ee59SPeter Avalos
9971e7ee59SPeter Avalos
10071e7ee59SPeter Avalos /*---------------------------------------------------*/
10171e7ee59SPeter Avalos /*--- The back end proper ---*/
10271e7ee59SPeter Avalos /*---------------------------------------------------*/
10371e7ee59SPeter Avalos
10471e7ee59SPeter Avalos /*---------------------------------------------------*/
10571e7ee59SPeter Avalos static
makeMaps_e(EState * s)10671e7ee59SPeter Avalos void makeMaps_e ( EState* s )
10771e7ee59SPeter Avalos {
10871e7ee59SPeter Avalos Int32 i;
10971e7ee59SPeter Avalos s->nInUse = 0;
11071e7ee59SPeter Avalos for (i = 0; i < 256; i++)
11171e7ee59SPeter Avalos if (s->inUse[i]) {
11271e7ee59SPeter Avalos s->unseqToSeq[i] = s->nInUse;
11371e7ee59SPeter Avalos s->nInUse++;
11471e7ee59SPeter Avalos }
11571e7ee59SPeter Avalos }
11671e7ee59SPeter Avalos
11771e7ee59SPeter Avalos
11871e7ee59SPeter Avalos /*---------------------------------------------------*/
11971e7ee59SPeter Avalos static
generateMTFValues(EState * s)12071e7ee59SPeter Avalos void generateMTFValues ( EState* s )
12171e7ee59SPeter Avalos {
12271e7ee59SPeter Avalos UChar yy[256];
12371e7ee59SPeter Avalos Int32 i, j;
12471e7ee59SPeter Avalos Int32 zPend;
12571e7ee59SPeter Avalos Int32 wr;
12671e7ee59SPeter Avalos Int32 EOB;
12771e7ee59SPeter Avalos
12871e7ee59SPeter Avalos /*
12971e7ee59SPeter Avalos After sorting (eg, here),
13071e7ee59SPeter Avalos s->arr1 [ 0 .. s->nblock-1 ] holds sorted order,
13171e7ee59SPeter Avalos and
13271e7ee59SPeter Avalos ((UChar*)s->arr2) [ 0 .. s->nblock-1 ]
13371e7ee59SPeter Avalos holds the original block data.
13471e7ee59SPeter Avalos
13571e7ee59SPeter Avalos The first thing to do is generate the MTF values,
13671e7ee59SPeter Avalos and put them in
13771e7ee59SPeter Avalos ((UInt16*)s->arr1) [ 0 .. s->nblock-1 ].
13871e7ee59SPeter Avalos Because there are strictly fewer or equal MTF values
13971e7ee59SPeter Avalos than block values, ptr values in this area are overwritten
14071e7ee59SPeter Avalos with MTF values only when they are no longer needed.
14171e7ee59SPeter Avalos
14271e7ee59SPeter Avalos The final compressed bitstream is generated into the
14371e7ee59SPeter Avalos area starting at
14471e7ee59SPeter Avalos (UChar*) (&((UChar*)s->arr2)[s->nblock])
14571e7ee59SPeter Avalos
14671e7ee59SPeter Avalos These storage aliases are set up in bzCompressInit(),
14771e7ee59SPeter Avalos except for the last one, which is arranged in
14871e7ee59SPeter Avalos compressBlock().
14971e7ee59SPeter Avalos */
15071e7ee59SPeter Avalos UInt32* ptr = s->ptr;
15171e7ee59SPeter Avalos UChar* block = s->block;
15271e7ee59SPeter Avalos UInt16* mtfv = s->mtfv;
15371e7ee59SPeter Avalos
15471e7ee59SPeter Avalos makeMaps_e ( s );
15571e7ee59SPeter Avalos EOB = s->nInUse+1;
15671e7ee59SPeter Avalos
15771e7ee59SPeter Avalos for (i = 0; i <= EOB; i++) s->mtfFreq[i] = 0;
15871e7ee59SPeter Avalos
15971e7ee59SPeter Avalos wr = 0;
16071e7ee59SPeter Avalos zPend = 0;
16171e7ee59SPeter Avalos for (i = 0; i < s->nInUse; i++) yy[i] = (UChar) i;
16271e7ee59SPeter Avalos
16371e7ee59SPeter Avalos for (i = 0; i < s->nblock; i++) {
16471e7ee59SPeter Avalos UChar ll_i;
16571e7ee59SPeter Avalos AssertD ( wr <= i, "generateMTFValues(1)" );
16671e7ee59SPeter Avalos j = ptr[i]-1; if (j < 0) j += s->nblock;
16771e7ee59SPeter Avalos ll_i = s->unseqToSeq[block[j]];
16871e7ee59SPeter Avalos AssertD ( ll_i < s->nInUse, "generateMTFValues(2a)" );
16971e7ee59SPeter Avalos
17071e7ee59SPeter Avalos if (yy[0] == ll_i) {
17171e7ee59SPeter Avalos zPend++;
17271e7ee59SPeter Avalos } else {
17371e7ee59SPeter Avalos
17471e7ee59SPeter Avalos if (zPend > 0) {
17571e7ee59SPeter Avalos zPend--;
17671e7ee59SPeter Avalos while (True) {
17771e7ee59SPeter Avalos if (zPend & 1) {
17871e7ee59SPeter Avalos mtfv[wr] = BZ_RUNB; wr++;
17971e7ee59SPeter Avalos s->mtfFreq[BZ_RUNB]++;
18071e7ee59SPeter Avalos } else {
18171e7ee59SPeter Avalos mtfv[wr] = BZ_RUNA; wr++;
18271e7ee59SPeter Avalos s->mtfFreq[BZ_RUNA]++;
18371e7ee59SPeter Avalos }
18471e7ee59SPeter Avalos if (zPend < 2) break;
18571e7ee59SPeter Avalos zPend = (zPend - 2) / 2;
18671e7ee59SPeter Avalos };
18771e7ee59SPeter Avalos zPend = 0;
18871e7ee59SPeter Avalos }
18971e7ee59SPeter Avalos {
19071e7ee59SPeter Avalos register UChar rtmp;
19171e7ee59SPeter Avalos register UChar* ryy_j;
19271e7ee59SPeter Avalos register UChar rll_i;
19371e7ee59SPeter Avalos rtmp = yy[1];
19471e7ee59SPeter Avalos yy[1] = yy[0];
19571e7ee59SPeter Avalos ryy_j = &(yy[1]);
19671e7ee59SPeter Avalos rll_i = ll_i;
19771e7ee59SPeter Avalos while ( rll_i != rtmp ) {
19871e7ee59SPeter Avalos register UChar rtmp2;
19971e7ee59SPeter Avalos ryy_j++;
20071e7ee59SPeter Avalos rtmp2 = rtmp;
20171e7ee59SPeter Avalos rtmp = *ryy_j;
20271e7ee59SPeter Avalos *ryy_j = rtmp2;
20371e7ee59SPeter Avalos };
20471e7ee59SPeter Avalos yy[0] = rtmp;
20571e7ee59SPeter Avalos j = ryy_j - &(yy[0]);
20671e7ee59SPeter Avalos mtfv[wr] = j+1; wr++; s->mtfFreq[j+1]++;
20771e7ee59SPeter Avalos }
20871e7ee59SPeter Avalos
20971e7ee59SPeter Avalos }
21071e7ee59SPeter Avalos }
21171e7ee59SPeter Avalos
21271e7ee59SPeter Avalos if (zPend > 0) {
21371e7ee59SPeter Avalos zPend--;
21471e7ee59SPeter Avalos while (True) {
21571e7ee59SPeter Avalos if (zPend & 1) {
21671e7ee59SPeter Avalos mtfv[wr] = BZ_RUNB; wr++;
21771e7ee59SPeter Avalos s->mtfFreq[BZ_RUNB]++;
21871e7ee59SPeter Avalos } else {
21971e7ee59SPeter Avalos mtfv[wr] = BZ_RUNA; wr++;
22071e7ee59SPeter Avalos s->mtfFreq[BZ_RUNA]++;
22171e7ee59SPeter Avalos }
22271e7ee59SPeter Avalos if (zPend < 2) break;
22371e7ee59SPeter Avalos zPend = (zPend - 2) / 2;
22471e7ee59SPeter Avalos };
22571e7ee59SPeter Avalos zPend = 0;
22671e7ee59SPeter Avalos }
22771e7ee59SPeter Avalos
22871e7ee59SPeter Avalos mtfv[wr] = EOB; wr++; s->mtfFreq[EOB]++;
22971e7ee59SPeter Avalos
23071e7ee59SPeter Avalos s->nMTF = wr;
23171e7ee59SPeter Avalos }
23271e7ee59SPeter Avalos
23371e7ee59SPeter Avalos
23471e7ee59SPeter Avalos /*---------------------------------------------------*/
23571e7ee59SPeter Avalos #define BZ_LESSER_ICOST 0
23671e7ee59SPeter Avalos #define BZ_GREATER_ICOST 15
23771e7ee59SPeter Avalos
23871e7ee59SPeter Avalos static
sendMTFValues(EState * s)23971e7ee59SPeter Avalos void sendMTFValues ( EState* s )
24071e7ee59SPeter Avalos {
24171e7ee59SPeter Avalos Int32 v, t, i, j, gs, ge, totc, bt, bc, iter;
24271e7ee59SPeter Avalos Int32 nSelectors, alphaSize, minLen, maxLen, selCtr;
24371e7ee59SPeter Avalos Int32 nGroups, nBytes;
24471e7ee59SPeter Avalos
24571e7ee59SPeter Avalos /*--
24671e7ee59SPeter Avalos UChar len [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
24771e7ee59SPeter Avalos is a global since the decoder also needs it.
24871e7ee59SPeter Avalos
24971e7ee59SPeter Avalos Int32 code[BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
25071e7ee59SPeter Avalos Int32 rfreq[BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
25171e7ee59SPeter Avalos are also globals only used in this proc.
25271e7ee59SPeter Avalos Made global to keep stack frame size small.
25371e7ee59SPeter Avalos --*/
25471e7ee59SPeter Avalos
25571e7ee59SPeter Avalos
25671e7ee59SPeter Avalos UInt16 cost[BZ_N_GROUPS];
25771e7ee59SPeter Avalos Int32 fave[BZ_N_GROUPS];
25871e7ee59SPeter Avalos
25971e7ee59SPeter Avalos UInt16* mtfv = s->mtfv;
26071e7ee59SPeter Avalos
26171e7ee59SPeter Avalos if (s->verbosity >= 3)
26271e7ee59SPeter Avalos VPrintf3( " %d in block, %d after MTF & 1-2 coding, "
26371e7ee59SPeter Avalos "%d+2 syms in use\n",
26471e7ee59SPeter Avalos s->nblock, s->nMTF, s->nInUse );
26571e7ee59SPeter Avalos
26671e7ee59SPeter Avalos alphaSize = s->nInUse+2;
26771e7ee59SPeter Avalos for (t = 0; t < BZ_N_GROUPS; t++)
26871e7ee59SPeter Avalos for (v = 0; v < alphaSize; v++)
26971e7ee59SPeter Avalos s->len[t][v] = BZ_GREATER_ICOST;
27071e7ee59SPeter Avalos
27171e7ee59SPeter Avalos /*--- Decide how many coding tables to use ---*/
27271e7ee59SPeter Avalos AssertH ( s->nMTF > 0, 3001 );
27371e7ee59SPeter Avalos if (s->nMTF < 200) nGroups = 2; else
27471e7ee59SPeter Avalos if (s->nMTF < 600) nGroups = 3; else
27571e7ee59SPeter Avalos if (s->nMTF < 1200) nGroups = 4; else
27671e7ee59SPeter Avalos if (s->nMTF < 2400) nGroups = 5; else
27771e7ee59SPeter Avalos nGroups = 6;
27871e7ee59SPeter Avalos
27971e7ee59SPeter Avalos /*--- Generate an initial set of coding tables ---*/
28071e7ee59SPeter Avalos {
28171e7ee59SPeter Avalos Int32 nPart, remF, tFreq, aFreq;
28271e7ee59SPeter Avalos
28371e7ee59SPeter Avalos nPart = nGroups;
28471e7ee59SPeter Avalos remF = s->nMTF;
28571e7ee59SPeter Avalos gs = 0;
28671e7ee59SPeter Avalos while (nPart > 0) {
28771e7ee59SPeter Avalos tFreq = remF / nPart;
28871e7ee59SPeter Avalos ge = gs-1;
28971e7ee59SPeter Avalos aFreq = 0;
29071e7ee59SPeter Avalos while (aFreq < tFreq && ge < alphaSize-1) {
29171e7ee59SPeter Avalos ge++;
29271e7ee59SPeter Avalos aFreq += s->mtfFreq[ge];
29371e7ee59SPeter Avalos }
29471e7ee59SPeter Avalos
29571e7ee59SPeter Avalos if (ge > gs
29671e7ee59SPeter Avalos && nPart != nGroups && nPart != 1
29771e7ee59SPeter Avalos && ((nGroups-nPart) % 2 == 1)) {
29871e7ee59SPeter Avalos aFreq -= s->mtfFreq[ge];
29971e7ee59SPeter Avalos ge--;
30071e7ee59SPeter Avalos }
30171e7ee59SPeter Avalos
30271e7ee59SPeter Avalos if (s->verbosity >= 3)
30371e7ee59SPeter Avalos VPrintf5( " initial group %d, [%d .. %d], "
30471e7ee59SPeter Avalos "has %d syms (%4.1f%%)\n",
30571e7ee59SPeter Avalos nPart, gs, ge, aFreq,
30671e7ee59SPeter Avalos (100.0 * (float)aFreq) / (float)(s->nMTF) );
30771e7ee59SPeter Avalos
30871e7ee59SPeter Avalos for (v = 0; v < alphaSize; v++)
30971e7ee59SPeter Avalos if (v >= gs && v <= ge)
31071e7ee59SPeter Avalos s->len[nPart-1][v] = BZ_LESSER_ICOST; else
31171e7ee59SPeter Avalos s->len[nPart-1][v] = BZ_GREATER_ICOST;
31271e7ee59SPeter Avalos
31371e7ee59SPeter Avalos nPart--;
31471e7ee59SPeter Avalos gs = ge+1;
31571e7ee59SPeter Avalos remF -= aFreq;
31671e7ee59SPeter Avalos }
31771e7ee59SPeter Avalos }
31871e7ee59SPeter Avalos
31971e7ee59SPeter Avalos /*---
32071e7ee59SPeter Avalos Iterate up to BZ_N_ITERS times to improve the tables.
32171e7ee59SPeter Avalos ---*/
32271e7ee59SPeter Avalos for (iter = 0; iter < BZ_N_ITERS; iter++) {
32371e7ee59SPeter Avalos
32471e7ee59SPeter Avalos for (t = 0; t < nGroups; t++) fave[t] = 0;
32571e7ee59SPeter Avalos
32671e7ee59SPeter Avalos for (t = 0; t < nGroups; t++)
32771e7ee59SPeter Avalos for (v = 0; v < alphaSize; v++)
32871e7ee59SPeter Avalos s->rfreq[t][v] = 0;
32971e7ee59SPeter Avalos
33071e7ee59SPeter Avalos /*---
33171e7ee59SPeter Avalos Set up an auxiliary length table which is used to fast-track
33271e7ee59SPeter Avalos the common case (nGroups == 6).
33371e7ee59SPeter Avalos ---*/
33471e7ee59SPeter Avalos if (nGroups == 6) {
33571e7ee59SPeter Avalos for (v = 0; v < alphaSize; v++) {
33671e7ee59SPeter Avalos s->len_pack[v][0] = (s->len[1][v] << 16) | s->len[0][v];
33771e7ee59SPeter Avalos s->len_pack[v][1] = (s->len[3][v] << 16) | s->len[2][v];
33871e7ee59SPeter Avalos s->len_pack[v][2] = (s->len[5][v] << 16) | s->len[4][v];
33971e7ee59SPeter Avalos }
34071e7ee59SPeter Avalos }
34171e7ee59SPeter Avalos
34271e7ee59SPeter Avalos nSelectors = 0;
34371e7ee59SPeter Avalos totc = 0;
34471e7ee59SPeter Avalos gs = 0;
34571e7ee59SPeter Avalos while (True) {
34671e7ee59SPeter Avalos
34771e7ee59SPeter Avalos /*--- Set group start & end marks. --*/
34871e7ee59SPeter Avalos if (gs >= s->nMTF) break;
34971e7ee59SPeter Avalos ge = gs + BZ_G_SIZE - 1;
35071e7ee59SPeter Avalos if (ge >= s->nMTF) ge = s->nMTF-1;
35171e7ee59SPeter Avalos
35271e7ee59SPeter Avalos /*--
35371e7ee59SPeter Avalos Calculate the cost of this group as coded
35471e7ee59SPeter Avalos by each of the coding tables.
35571e7ee59SPeter Avalos --*/
35671e7ee59SPeter Avalos for (t = 0; t < nGroups; t++) cost[t] = 0;
35771e7ee59SPeter Avalos
35871e7ee59SPeter Avalos if (nGroups == 6 && 50 == ge-gs+1) {
35971e7ee59SPeter Avalos /*--- fast track the common case ---*/
36071e7ee59SPeter Avalos register UInt32 cost01, cost23, cost45;
36171e7ee59SPeter Avalos register UInt16 icv;
36271e7ee59SPeter Avalos cost01 = cost23 = cost45 = 0;
36371e7ee59SPeter Avalos
36471e7ee59SPeter Avalos # define BZ_ITER(nn) \
36571e7ee59SPeter Avalos icv = mtfv[gs+(nn)]; \
36671e7ee59SPeter Avalos cost01 += s->len_pack[icv][0]; \
36771e7ee59SPeter Avalos cost23 += s->len_pack[icv][1]; \
36871e7ee59SPeter Avalos cost45 += s->len_pack[icv][2]; \
36971e7ee59SPeter Avalos
37071e7ee59SPeter Avalos BZ_ITER(0); BZ_ITER(1); BZ_ITER(2); BZ_ITER(3); BZ_ITER(4);
37171e7ee59SPeter Avalos BZ_ITER(5); BZ_ITER(6); BZ_ITER(7); BZ_ITER(8); BZ_ITER(9);
37271e7ee59SPeter Avalos BZ_ITER(10); BZ_ITER(11); BZ_ITER(12); BZ_ITER(13); BZ_ITER(14);
37371e7ee59SPeter Avalos BZ_ITER(15); BZ_ITER(16); BZ_ITER(17); BZ_ITER(18); BZ_ITER(19);
37471e7ee59SPeter Avalos BZ_ITER(20); BZ_ITER(21); BZ_ITER(22); BZ_ITER(23); BZ_ITER(24);
37571e7ee59SPeter Avalos BZ_ITER(25); BZ_ITER(26); BZ_ITER(27); BZ_ITER(28); BZ_ITER(29);
37671e7ee59SPeter Avalos BZ_ITER(30); BZ_ITER(31); BZ_ITER(32); BZ_ITER(33); BZ_ITER(34);
37771e7ee59SPeter Avalos BZ_ITER(35); BZ_ITER(36); BZ_ITER(37); BZ_ITER(38); BZ_ITER(39);
37871e7ee59SPeter Avalos BZ_ITER(40); BZ_ITER(41); BZ_ITER(42); BZ_ITER(43); BZ_ITER(44);
37971e7ee59SPeter Avalos BZ_ITER(45); BZ_ITER(46); BZ_ITER(47); BZ_ITER(48); BZ_ITER(49);
38071e7ee59SPeter Avalos
38171e7ee59SPeter Avalos # undef BZ_ITER
38271e7ee59SPeter Avalos
38371e7ee59SPeter Avalos cost[0] = cost01 & 0xffff; cost[1] = cost01 >> 16;
38471e7ee59SPeter Avalos cost[2] = cost23 & 0xffff; cost[3] = cost23 >> 16;
38571e7ee59SPeter Avalos cost[4] = cost45 & 0xffff; cost[5] = cost45 >> 16;
38671e7ee59SPeter Avalos
38771e7ee59SPeter Avalos } else {
38871e7ee59SPeter Avalos /*--- slow version which correctly handles all situations ---*/
38971e7ee59SPeter Avalos for (i = gs; i <= ge; i++) {
39071e7ee59SPeter Avalos UInt16 icv = mtfv[i];
39171e7ee59SPeter Avalos for (t = 0; t < nGroups; t++) cost[t] += s->len[t][icv];
39271e7ee59SPeter Avalos }
39371e7ee59SPeter Avalos }
39471e7ee59SPeter Avalos
39571e7ee59SPeter Avalos /*--
39671e7ee59SPeter Avalos Find the coding table which is best for this group,
39771e7ee59SPeter Avalos and record its identity in the selector table.
39871e7ee59SPeter Avalos --*/
39971e7ee59SPeter Avalos bc = 999999999; bt = -1;
40071e7ee59SPeter Avalos for (t = 0; t < nGroups; t++)
40171e7ee59SPeter Avalos if (cost[t] < bc) { bc = cost[t]; bt = t; };
40271e7ee59SPeter Avalos totc += bc;
40371e7ee59SPeter Avalos fave[bt]++;
40471e7ee59SPeter Avalos s->selector[nSelectors] = bt;
40571e7ee59SPeter Avalos nSelectors++;
40671e7ee59SPeter Avalos
40771e7ee59SPeter Avalos /*--
40871e7ee59SPeter Avalos Increment the symbol frequencies for the selected table.
40971e7ee59SPeter Avalos --*/
41071e7ee59SPeter Avalos if (nGroups == 6 && 50 == ge-gs+1) {
41171e7ee59SPeter Avalos /*--- fast track the common case ---*/
41271e7ee59SPeter Avalos
41371e7ee59SPeter Avalos # define BZ_ITUR(nn) s->rfreq[bt][ mtfv[gs+(nn)] ]++
41471e7ee59SPeter Avalos
41571e7ee59SPeter Avalos BZ_ITUR(0); BZ_ITUR(1); BZ_ITUR(2); BZ_ITUR(3); BZ_ITUR(4);
41671e7ee59SPeter Avalos BZ_ITUR(5); BZ_ITUR(6); BZ_ITUR(7); BZ_ITUR(8); BZ_ITUR(9);
41771e7ee59SPeter Avalos BZ_ITUR(10); BZ_ITUR(11); BZ_ITUR(12); BZ_ITUR(13); BZ_ITUR(14);
41871e7ee59SPeter Avalos BZ_ITUR(15); BZ_ITUR(16); BZ_ITUR(17); BZ_ITUR(18); BZ_ITUR(19);
41971e7ee59SPeter Avalos BZ_ITUR(20); BZ_ITUR(21); BZ_ITUR(22); BZ_ITUR(23); BZ_ITUR(24);
42071e7ee59SPeter Avalos BZ_ITUR(25); BZ_ITUR(26); BZ_ITUR(27); BZ_ITUR(28); BZ_ITUR(29);
42171e7ee59SPeter Avalos BZ_ITUR(30); BZ_ITUR(31); BZ_ITUR(32); BZ_ITUR(33); BZ_ITUR(34);
42271e7ee59SPeter Avalos BZ_ITUR(35); BZ_ITUR(36); BZ_ITUR(37); BZ_ITUR(38); BZ_ITUR(39);
42371e7ee59SPeter Avalos BZ_ITUR(40); BZ_ITUR(41); BZ_ITUR(42); BZ_ITUR(43); BZ_ITUR(44);
42471e7ee59SPeter Avalos BZ_ITUR(45); BZ_ITUR(46); BZ_ITUR(47); BZ_ITUR(48); BZ_ITUR(49);
42571e7ee59SPeter Avalos
42671e7ee59SPeter Avalos # undef BZ_ITUR
42771e7ee59SPeter Avalos
42871e7ee59SPeter Avalos } else {
42971e7ee59SPeter Avalos /*--- slow version which correctly handles all situations ---*/
43071e7ee59SPeter Avalos for (i = gs; i <= ge; i++)
43171e7ee59SPeter Avalos s->rfreq[bt][ mtfv[i] ]++;
43271e7ee59SPeter Avalos }
43371e7ee59SPeter Avalos
43471e7ee59SPeter Avalos gs = ge+1;
43571e7ee59SPeter Avalos }
43671e7ee59SPeter Avalos if (s->verbosity >= 3) {
43771e7ee59SPeter Avalos VPrintf2 ( " pass %d: size is %d, grp uses are ",
43871e7ee59SPeter Avalos iter+1, totc/8 );
43971e7ee59SPeter Avalos for (t = 0; t < nGroups; t++)
44071e7ee59SPeter Avalos VPrintf1 ( "%d ", fave[t] );
44171e7ee59SPeter Avalos VPrintf0 ( "\n" );
44271e7ee59SPeter Avalos }
44371e7ee59SPeter Avalos
44471e7ee59SPeter Avalos /*--
44571e7ee59SPeter Avalos Recompute the tables based on the accumulated frequencies.
44671e7ee59SPeter Avalos --*/
44771e7ee59SPeter Avalos /* maxLen was changed from 20 to 17 in bzip2-1.0.3. See
44871e7ee59SPeter Avalos comment in huffman.c for details. */
44971e7ee59SPeter Avalos for (t = 0; t < nGroups; t++)
45071e7ee59SPeter Avalos BZ2_hbMakeCodeLengths ( &(s->len[t][0]), &(s->rfreq[t][0]),
45171e7ee59SPeter Avalos alphaSize, 17 /*20*/ );
45271e7ee59SPeter Avalos }
45371e7ee59SPeter Avalos
45471e7ee59SPeter Avalos
45571e7ee59SPeter Avalos AssertH( nGroups < 8, 3002 );
45671e7ee59SPeter Avalos AssertH( nSelectors < 32768 &&
457*86954436SDaniel Fojt nSelectors <= BZ_MAX_SELECTORS,
45871e7ee59SPeter Avalos 3003 );
45971e7ee59SPeter Avalos
46071e7ee59SPeter Avalos
46171e7ee59SPeter Avalos /*--- Compute MTF values for the selectors. ---*/
46271e7ee59SPeter Avalos {
46371e7ee59SPeter Avalos UChar pos[BZ_N_GROUPS], ll_i, tmp2, tmp;
46471e7ee59SPeter Avalos for (i = 0; i < nGroups; i++) pos[i] = i;
46571e7ee59SPeter Avalos for (i = 0; i < nSelectors; i++) {
46671e7ee59SPeter Avalos ll_i = s->selector[i];
46771e7ee59SPeter Avalos j = 0;
46871e7ee59SPeter Avalos tmp = pos[j];
46971e7ee59SPeter Avalos while ( ll_i != tmp ) {
47071e7ee59SPeter Avalos j++;
47171e7ee59SPeter Avalos tmp2 = tmp;
47271e7ee59SPeter Avalos tmp = pos[j];
47371e7ee59SPeter Avalos pos[j] = tmp2;
47471e7ee59SPeter Avalos };
47571e7ee59SPeter Avalos pos[0] = tmp;
47671e7ee59SPeter Avalos s->selectorMtf[i] = j;
47771e7ee59SPeter Avalos }
47871e7ee59SPeter Avalos };
47971e7ee59SPeter Avalos
48071e7ee59SPeter Avalos /*--- Assign actual codes for the tables. --*/
48171e7ee59SPeter Avalos for (t = 0; t < nGroups; t++) {
48271e7ee59SPeter Avalos minLen = 32;
48371e7ee59SPeter Avalos maxLen = 0;
48471e7ee59SPeter Avalos for (i = 0; i < alphaSize; i++) {
48571e7ee59SPeter Avalos if (s->len[t][i] > maxLen) maxLen = s->len[t][i];
48671e7ee59SPeter Avalos if (s->len[t][i] < minLen) minLen = s->len[t][i];
48771e7ee59SPeter Avalos }
48871e7ee59SPeter Avalos AssertH ( !(maxLen > 17 /*20*/ ), 3004 );
48971e7ee59SPeter Avalos AssertH ( !(minLen < 1), 3005 );
49071e7ee59SPeter Avalos BZ2_hbAssignCodes ( &(s->code[t][0]), &(s->len[t][0]),
49171e7ee59SPeter Avalos minLen, maxLen, alphaSize );
49271e7ee59SPeter Avalos }
49371e7ee59SPeter Avalos
49471e7ee59SPeter Avalos /*--- Transmit the mapping table. ---*/
49571e7ee59SPeter Avalos {
49671e7ee59SPeter Avalos Bool inUse16[16];
49771e7ee59SPeter Avalos for (i = 0; i < 16; i++) {
49871e7ee59SPeter Avalos inUse16[i] = False;
49971e7ee59SPeter Avalos for (j = 0; j < 16; j++)
50071e7ee59SPeter Avalos if (s->inUse[i * 16 + j]) inUse16[i] = True;
50171e7ee59SPeter Avalos }
50271e7ee59SPeter Avalos
50371e7ee59SPeter Avalos nBytes = s->numZ;
50471e7ee59SPeter Avalos for (i = 0; i < 16; i++)
50571e7ee59SPeter Avalos if (inUse16[i]) bsW(s,1,1); else bsW(s,1,0);
50671e7ee59SPeter Avalos
50771e7ee59SPeter Avalos for (i = 0; i < 16; i++)
50871e7ee59SPeter Avalos if (inUse16[i])
50971e7ee59SPeter Avalos for (j = 0; j < 16; j++) {
51071e7ee59SPeter Avalos if (s->inUse[i * 16 + j]) bsW(s,1,1); else bsW(s,1,0);
51171e7ee59SPeter Avalos }
51271e7ee59SPeter Avalos
51371e7ee59SPeter Avalos if (s->verbosity >= 3)
51471e7ee59SPeter Avalos VPrintf1( " bytes: mapping %d, ", s->numZ-nBytes );
51571e7ee59SPeter Avalos }
51671e7ee59SPeter Avalos
51771e7ee59SPeter Avalos /*--- Now the selectors. ---*/
51871e7ee59SPeter Avalos nBytes = s->numZ;
51971e7ee59SPeter Avalos bsW ( s, 3, nGroups );
52071e7ee59SPeter Avalos bsW ( s, 15, nSelectors );
52171e7ee59SPeter Avalos for (i = 0; i < nSelectors; i++) {
52271e7ee59SPeter Avalos for (j = 0; j < s->selectorMtf[i]; j++) bsW(s,1,1);
52371e7ee59SPeter Avalos bsW(s,1,0);
52471e7ee59SPeter Avalos }
52571e7ee59SPeter Avalos if (s->verbosity >= 3)
52671e7ee59SPeter Avalos VPrintf1( "selectors %d, ", s->numZ-nBytes );
52771e7ee59SPeter Avalos
52871e7ee59SPeter Avalos /*--- Now the coding tables. ---*/
52971e7ee59SPeter Avalos nBytes = s->numZ;
53071e7ee59SPeter Avalos
53171e7ee59SPeter Avalos for (t = 0; t < nGroups; t++) {
53271e7ee59SPeter Avalos Int32 curr = s->len[t][0];
53371e7ee59SPeter Avalos bsW ( s, 5, curr );
53471e7ee59SPeter Avalos for (i = 0; i < alphaSize; i++) {
53571e7ee59SPeter Avalos while (curr < s->len[t][i]) { bsW(s,2,2); curr++; /* 10 */ };
53671e7ee59SPeter Avalos while (curr > s->len[t][i]) { bsW(s,2,3); curr--; /* 11 */ };
53771e7ee59SPeter Avalos bsW ( s, 1, 0 );
53871e7ee59SPeter Avalos }
53971e7ee59SPeter Avalos }
54071e7ee59SPeter Avalos
54171e7ee59SPeter Avalos if (s->verbosity >= 3)
54271e7ee59SPeter Avalos VPrintf1 ( "code lengths %d, ", s->numZ-nBytes );
54371e7ee59SPeter Avalos
54471e7ee59SPeter Avalos /*--- And finally, the block data proper ---*/
54571e7ee59SPeter Avalos nBytes = s->numZ;
54671e7ee59SPeter Avalos selCtr = 0;
54771e7ee59SPeter Avalos gs = 0;
54871e7ee59SPeter Avalos while (True) {
54971e7ee59SPeter Avalos if (gs >= s->nMTF) break;
55071e7ee59SPeter Avalos ge = gs + BZ_G_SIZE - 1;
55171e7ee59SPeter Avalos if (ge >= s->nMTF) ge = s->nMTF-1;
55271e7ee59SPeter Avalos AssertH ( s->selector[selCtr] < nGroups, 3006 );
55371e7ee59SPeter Avalos
55471e7ee59SPeter Avalos if (nGroups == 6 && 50 == ge-gs+1) {
55571e7ee59SPeter Avalos /*--- fast track the common case ---*/
55671e7ee59SPeter Avalos UInt16 mtfv_i;
55771e7ee59SPeter Avalos UChar* s_len_sel_selCtr
55871e7ee59SPeter Avalos = &(s->len[s->selector[selCtr]][0]);
55971e7ee59SPeter Avalos Int32* s_code_sel_selCtr
56071e7ee59SPeter Avalos = &(s->code[s->selector[selCtr]][0]);
56171e7ee59SPeter Avalos
56271e7ee59SPeter Avalos # define BZ_ITAH(nn) \
56371e7ee59SPeter Avalos mtfv_i = mtfv[gs+(nn)]; \
56471e7ee59SPeter Avalos bsW ( s, \
56571e7ee59SPeter Avalos s_len_sel_selCtr[mtfv_i], \
56671e7ee59SPeter Avalos s_code_sel_selCtr[mtfv_i] )
56771e7ee59SPeter Avalos
56871e7ee59SPeter Avalos BZ_ITAH(0); BZ_ITAH(1); BZ_ITAH(2); BZ_ITAH(3); BZ_ITAH(4);
56971e7ee59SPeter Avalos BZ_ITAH(5); BZ_ITAH(6); BZ_ITAH(7); BZ_ITAH(8); BZ_ITAH(9);
57071e7ee59SPeter Avalos BZ_ITAH(10); BZ_ITAH(11); BZ_ITAH(12); BZ_ITAH(13); BZ_ITAH(14);
57171e7ee59SPeter Avalos BZ_ITAH(15); BZ_ITAH(16); BZ_ITAH(17); BZ_ITAH(18); BZ_ITAH(19);
57271e7ee59SPeter Avalos BZ_ITAH(20); BZ_ITAH(21); BZ_ITAH(22); BZ_ITAH(23); BZ_ITAH(24);
57371e7ee59SPeter Avalos BZ_ITAH(25); BZ_ITAH(26); BZ_ITAH(27); BZ_ITAH(28); BZ_ITAH(29);
57471e7ee59SPeter Avalos BZ_ITAH(30); BZ_ITAH(31); BZ_ITAH(32); BZ_ITAH(33); BZ_ITAH(34);
57571e7ee59SPeter Avalos BZ_ITAH(35); BZ_ITAH(36); BZ_ITAH(37); BZ_ITAH(38); BZ_ITAH(39);
57671e7ee59SPeter Avalos BZ_ITAH(40); BZ_ITAH(41); BZ_ITAH(42); BZ_ITAH(43); BZ_ITAH(44);
57771e7ee59SPeter Avalos BZ_ITAH(45); BZ_ITAH(46); BZ_ITAH(47); BZ_ITAH(48); BZ_ITAH(49);
57871e7ee59SPeter Avalos
57971e7ee59SPeter Avalos # undef BZ_ITAH
58071e7ee59SPeter Avalos
58171e7ee59SPeter Avalos } else {
58271e7ee59SPeter Avalos /*--- slow version which correctly handles all situations ---*/
58371e7ee59SPeter Avalos for (i = gs; i <= ge; i++) {
58471e7ee59SPeter Avalos bsW ( s,
58571e7ee59SPeter Avalos s->len [s->selector[selCtr]] [mtfv[i]],
58671e7ee59SPeter Avalos s->code [s->selector[selCtr]] [mtfv[i]] );
58771e7ee59SPeter Avalos }
58871e7ee59SPeter Avalos }
58971e7ee59SPeter Avalos
59071e7ee59SPeter Avalos
59171e7ee59SPeter Avalos gs = ge+1;
59271e7ee59SPeter Avalos selCtr++;
59371e7ee59SPeter Avalos }
59471e7ee59SPeter Avalos AssertH( selCtr == nSelectors, 3007 );
59571e7ee59SPeter Avalos
59671e7ee59SPeter Avalos if (s->verbosity >= 3)
59771e7ee59SPeter Avalos VPrintf1( "codes %d\n", s->numZ-nBytes );
59871e7ee59SPeter Avalos }
59971e7ee59SPeter Avalos
60071e7ee59SPeter Avalos
60171e7ee59SPeter Avalos /*---------------------------------------------------*/
BZ2_compressBlock(EState * s,Bool is_last_block)60271e7ee59SPeter Avalos void BZ2_compressBlock ( EState* s, Bool is_last_block )
60371e7ee59SPeter Avalos {
60471e7ee59SPeter Avalos if (s->nblock > 0) {
60571e7ee59SPeter Avalos
60671e7ee59SPeter Avalos BZ_FINALISE_CRC ( s->blockCRC );
60771e7ee59SPeter Avalos s->combinedCRC = (s->combinedCRC << 1) | (s->combinedCRC >> 31);
60871e7ee59SPeter Avalos s->combinedCRC ^= s->blockCRC;
60971e7ee59SPeter Avalos if (s->blockNo > 1) s->numZ = 0;
61071e7ee59SPeter Avalos
61171e7ee59SPeter Avalos if (s->verbosity >= 2)
61271e7ee59SPeter Avalos VPrintf4( " block %d: crc = 0x%08x, "
61371e7ee59SPeter Avalos "combined CRC = 0x%08x, size = %d\n",
61471e7ee59SPeter Avalos s->blockNo, s->blockCRC, s->combinedCRC, s->nblock );
61571e7ee59SPeter Avalos
61671e7ee59SPeter Avalos BZ2_blockSort ( s );
61771e7ee59SPeter Avalos }
61871e7ee59SPeter Avalos
61971e7ee59SPeter Avalos s->zbits = (UChar*) (&((UChar*)s->arr2)[s->nblock]);
62071e7ee59SPeter Avalos
62171e7ee59SPeter Avalos /*-- If this is the first block, create the stream header. --*/
62271e7ee59SPeter Avalos if (s->blockNo == 1) {
62371e7ee59SPeter Avalos BZ2_bsInitWrite ( s );
62471e7ee59SPeter Avalos bsPutUChar ( s, BZ_HDR_B );
62571e7ee59SPeter Avalos bsPutUChar ( s, BZ_HDR_Z );
62671e7ee59SPeter Avalos bsPutUChar ( s, BZ_HDR_h );
62771e7ee59SPeter Avalos bsPutUChar ( s, (UChar)(BZ_HDR_0 + s->blockSize100k) );
62871e7ee59SPeter Avalos }
62971e7ee59SPeter Avalos
63071e7ee59SPeter Avalos if (s->nblock > 0) {
63171e7ee59SPeter Avalos
63271e7ee59SPeter Avalos bsPutUChar ( s, 0x31 ); bsPutUChar ( s, 0x41 );
63371e7ee59SPeter Avalos bsPutUChar ( s, 0x59 ); bsPutUChar ( s, 0x26 );
63471e7ee59SPeter Avalos bsPutUChar ( s, 0x53 ); bsPutUChar ( s, 0x59 );
63571e7ee59SPeter Avalos
63671e7ee59SPeter Avalos /*-- Now the block's CRC, so it is in a known place. --*/
63771e7ee59SPeter Avalos bsPutUInt32 ( s, s->blockCRC );
63871e7ee59SPeter Avalos
63971e7ee59SPeter Avalos /*--
64071e7ee59SPeter Avalos Now a single bit indicating (non-)randomisation.
64171e7ee59SPeter Avalos As of version 0.9.5, we use a better sorting algorithm
64271e7ee59SPeter Avalos which makes randomisation unnecessary. So always set
64371e7ee59SPeter Avalos the randomised bit to 'no'. Of course, the decoder
64471e7ee59SPeter Avalos still needs to be able to handle randomised blocks
64571e7ee59SPeter Avalos so as to maintain backwards compatibility with
64671e7ee59SPeter Avalos older versions of bzip2.
64771e7ee59SPeter Avalos --*/
64871e7ee59SPeter Avalos bsW(s,1,0);
64971e7ee59SPeter Avalos
65071e7ee59SPeter Avalos bsW ( s, 24, s->origPtr );
65171e7ee59SPeter Avalos generateMTFValues ( s );
65271e7ee59SPeter Avalos sendMTFValues ( s );
65371e7ee59SPeter Avalos }
65471e7ee59SPeter Avalos
65571e7ee59SPeter Avalos
65671e7ee59SPeter Avalos /*-- If this is the last block, add the stream trailer. --*/
65771e7ee59SPeter Avalos if (is_last_block) {
65871e7ee59SPeter Avalos
65971e7ee59SPeter Avalos bsPutUChar ( s, 0x17 ); bsPutUChar ( s, 0x72 );
66071e7ee59SPeter Avalos bsPutUChar ( s, 0x45 ); bsPutUChar ( s, 0x38 );
66171e7ee59SPeter Avalos bsPutUChar ( s, 0x50 ); bsPutUChar ( s, 0x90 );
66271e7ee59SPeter Avalos bsPutUInt32 ( s, s->combinedCRC );
66371e7ee59SPeter Avalos if (s->verbosity >= 2)
66471e7ee59SPeter Avalos VPrintf1( " final combined CRC = 0x%08x\n ", s->combinedCRC );
66571e7ee59SPeter Avalos bsFinishWrite ( s );
66671e7ee59SPeter Avalos }
66771e7ee59SPeter Avalos }
66871e7ee59SPeter Avalos
66971e7ee59SPeter Avalos
67071e7ee59SPeter Avalos /*-------------------------------------------------------------*/
67171e7ee59SPeter Avalos /*--- end compress.c ---*/
67271e7ee59SPeter Avalos /*-------------------------------------------------------------*/
673