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