Blame huffman.c

Packit 71fd91
Packit 71fd91
/*-------------------------------------------------------------*/
Packit 71fd91
/*--- Huffman coding low-level stuff                        ---*/
Packit 71fd91
/*---                                             huffman.c ---*/
Packit 71fd91
/*-------------------------------------------------------------*/
Packit 71fd91
Packit 71fd91
/* ------------------------------------------------------------------
Packit 71fd91
   This file is part of bzip2/libbzip2, a program and library for
Packit 71fd91
   lossless, block-sorting data compression.
Packit 71fd91
Packit 71fd91
   bzip2/libbzip2 version 1.0.6 of 6 September 2010
Packit 71fd91
   Copyright (C) 1996-2010 Julian Seward <jseward@bzip.org>
Packit 71fd91
Packit 71fd91
   Please read the WARNING, DISCLAIMER and PATENTS sections in the 
Packit 71fd91
   README file.
Packit 71fd91
Packit 71fd91
   This program is released under the terms of the license contained
Packit 71fd91
   in the file LICENSE.
Packit 71fd91
   ------------------------------------------------------------------ */
Packit 71fd91
Packit 71fd91
Packit 71fd91
#include "bzlib_private.h"
Packit 71fd91
Packit 71fd91
/*---------------------------------------------------*/
Packit 71fd91
#define WEIGHTOF(zz0)  ((zz0) & 0xffffff00)
Packit 71fd91
#define DEPTHOF(zz1)   ((zz1) & 0x000000ff)
Packit 71fd91
#define MYMAX(zz2,zz3) ((zz2) > (zz3) ? (zz2) : (zz3))
Packit 71fd91
Packit 71fd91
#define ADDWEIGHTS(zw1,zw2)                           \
Packit 71fd91
   (WEIGHTOF(zw1)+WEIGHTOF(zw2)) |                    \
Packit 71fd91
   (1 + MYMAX(DEPTHOF(zw1),DEPTHOF(zw2)))
Packit 71fd91
Packit 71fd91
#define UPHEAP(z)                                     \
Packit 71fd91
{                                                     \
Packit 71fd91
   Int32 zz, tmp;                                     \
Packit 71fd91
   zz = z; tmp = heap[zz];                            \
Packit 71fd91
   while (weight[tmp] < weight[heap[zz >> 1]]) {      \
Packit 71fd91
      heap[zz] = heap[zz >> 1];                       \
Packit 71fd91
      zz >>= 1;                                       \
Packit 71fd91
   }                                                  \
Packit 71fd91
   heap[zz] = tmp;                                    \
Packit 71fd91
}
Packit 71fd91
Packit 71fd91
#define DOWNHEAP(z)                                   \
Packit 71fd91
{                                                     \
Packit 71fd91
   Int32 zz, yy, tmp;                                 \
Packit 71fd91
   zz = z; tmp = heap[zz];                            \
Packit 71fd91
   while (True) {                                     \
Packit 71fd91
      yy = zz << 1;                                   \
Packit 71fd91
      if (yy > nHeap) break;                          \
Packit 71fd91
      if (yy < nHeap &&                               \
Packit 71fd91
          weight[heap[yy+1]] < weight[heap[yy]])      \
Packit 71fd91
         yy++;                                        \
Packit 71fd91
      if (weight[tmp] < weight[heap[yy]]) break;      \
Packit 71fd91
      heap[zz] = heap[yy];                            \
Packit 71fd91
      zz = yy;                                        \
Packit 71fd91
   }                                                  \
Packit 71fd91
   heap[zz] = tmp;                                    \
Packit 71fd91
}
Packit 71fd91
Packit 71fd91
Packit 71fd91
/*---------------------------------------------------*/
Packit 71fd91
void BZ2_hbMakeCodeLengths ( UChar *len, 
Packit 71fd91
                             Int32 *freq,
Packit 71fd91
                             Int32 alphaSize,
Packit 71fd91
                             Int32 maxLen )
Packit 71fd91
{
Packit 71fd91
   /*--
Packit 71fd91
      Nodes and heap entries run from 1.  Entry 0
Packit 71fd91
      for both the heap and nodes is a sentinel.
Packit 71fd91
   --*/
Packit 71fd91
   Int32 nNodes, nHeap, n1, n2, i, j, k;
Packit 71fd91
   Bool  tooLong;
Packit 71fd91
Packit 71fd91
   Int32 heap   [ BZ_MAX_ALPHA_SIZE + 2 ];
Packit 71fd91
   Int32 weight [ BZ_MAX_ALPHA_SIZE * 2 ];
Packit 71fd91
   Int32 parent [ BZ_MAX_ALPHA_SIZE * 2 ]; 
Packit 71fd91
Packit 71fd91
   for (i = 0; i < alphaSize; i++)
Packit 71fd91
      weight[i+1] = (freq[i] == 0 ? 1 : freq[i]) << 8;
Packit 71fd91
Packit 71fd91
   while (True) {
Packit 71fd91
Packit 71fd91
      nNodes = alphaSize;
Packit 71fd91
      nHeap = 0;
Packit 71fd91
Packit 71fd91
      heap[0] = 0;
Packit 71fd91
      weight[0] = 0;
Packit 71fd91
      parent[0] = -2;
Packit 71fd91
Packit 71fd91
      for (i = 1; i <= alphaSize; i++) {
Packit 71fd91
         parent[i] = -1;
Packit 71fd91
         nHeap++;
Packit 71fd91
         heap[nHeap] = i;
Packit 71fd91
         UPHEAP(nHeap);
Packit 71fd91
      }
Packit 71fd91
Packit 71fd91
      AssertH( nHeap < (BZ_MAX_ALPHA_SIZE+2), 2001 );
Packit 71fd91
   
Packit 71fd91
      while (nHeap > 1) {
Packit 71fd91
         n1 = heap[1]; heap[1] = heap[nHeap]; nHeap--; DOWNHEAP(1);
Packit 71fd91
         n2 = heap[1]; heap[1] = heap[nHeap]; nHeap--; DOWNHEAP(1);
Packit 71fd91
         nNodes++;
Packit 71fd91
         parent[n1] = parent[n2] = nNodes;
Packit 71fd91
         weight[nNodes] = ADDWEIGHTS(weight[n1], weight[n2]);
Packit 71fd91
         parent[nNodes] = -1;
Packit 71fd91
         nHeap++;
Packit 71fd91
         heap[nHeap] = nNodes;
Packit 71fd91
         UPHEAP(nHeap);
Packit 71fd91
      }
Packit 71fd91
Packit 71fd91
      AssertH( nNodes < (BZ_MAX_ALPHA_SIZE * 2), 2002 );
Packit 71fd91
Packit 71fd91
      tooLong = False;
Packit 71fd91
      for (i = 1; i <= alphaSize; i++) {
Packit 71fd91
         j = 0;
Packit 71fd91
         k = i;
Packit 71fd91
         while (parent[k] >= 0) { k = parent[k]; j++; }
Packit 71fd91
         len[i-1] = j;
Packit 71fd91
         if (j > maxLen) tooLong = True;
Packit 71fd91
      }
Packit 71fd91
      
Packit 71fd91
      if (! tooLong) break;
Packit 71fd91
Packit 71fd91
      /* 17 Oct 04: keep-going condition for the following loop used
Packit 71fd91
         to be 'i < alphaSize', which missed the last element,
Packit 71fd91
         theoretically leading to the possibility of the compressor
Packit 71fd91
         looping.  However, this count-scaling step is only needed if
Packit 71fd91
         one of the generated Huffman code words is longer than
Packit 71fd91
         maxLen, which up to and including version 1.0.2 was 20 bits,
Packit 71fd91
         which is extremely unlikely.  In version 1.0.3 maxLen was
Packit 71fd91
         changed to 17 bits, which has minimal effect on compression
Packit 71fd91
         ratio, but does mean this scaling step is used from time to
Packit 71fd91
         time, enough to verify that it works.
Packit 71fd91
Packit 71fd91
         This means that bzip2-1.0.3 and later will only produce
Packit 71fd91
         Huffman codes with a maximum length of 17 bits.  However, in
Packit 71fd91
         order to preserve backwards compatibility with bitstreams
Packit 71fd91
         produced by versions pre-1.0.3, the decompressor must still
Packit 71fd91
         handle lengths of up to 20. */
Packit 71fd91
Packit 71fd91
      for (i = 1; i <= alphaSize; i++) {
Packit 71fd91
         j = weight[i] >> 8;
Packit 71fd91
         j = 1 + (j / 2);
Packit 71fd91
         weight[i] = j << 8;
Packit 71fd91
      }
Packit 71fd91
   }
Packit 71fd91
}
Packit 71fd91
Packit 71fd91
Packit 71fd91
/*---------------------------------------------------*/
Packit 71fd91
void BZ2_hbAssignCodes ( Int32 *code,
Packit 71fd91
                         UChar *length,
Packit 71fd91
                         Int32 minLen,
Packit 71fd91
                         Int32 maxLen,
Packit 71fd91
                         Int32 alphaSize )
Packit 71fd91
{
Packit 71fd91
   Int32 n, vec, i;
Packit 71fd91
Packit 71fd91
   vec = 0;
Packit 71fd91
   for (n = minLen; n <= maxLen; n++) {
Packit 71fd91
      for (i = 0; i < alphaSize; i++)
Packit 71fd91
         if (length[i] == n) { code[i] = vec; vec++; };
Packit 71fd91
      vec <<= 1;
Packit 71fd91
   }
Packit 71fd91
}
Packit 71fd91
Packit 71fd91
Packit 71fd91
/*---------------------------------------------------*/
Packit 71fd91
void BZ2_hbCreateDecodeTables ( Int32 *limit,
Packit 71fd91
                                Int32 *base,
Packit 71fd91
                                Int32 *perm,
Packit 71fd91
                                UChar *length,
Packit 71fd91
                                Int32 minLen,
Packit 71fd91
                                Int32 maxLen,
Packit 71fd91
                                Int32 alphaSize )
Packit 71fd91
{
Packit 71fd91
   Int32 pp, i, j, vec;
Packit 71fd91
Packit 71fd91
   pp = 0;
Packit 71fd91
   for (i = minLen; i <= maxLen; i++)
Packit 71fd91
      for (j = 0; j < alphaSize; j++)
Packit 71fd91
         if (length[j] == i) { perm[pp] = j; pp++; };
Packit 71fd91
Packit 71fd91
   for (i = 0; i < BZ_MAX_CODE_LEN; i++) base[i] = 0;
Packit 71fd91
   for (i = 0; i < alphaSize; i++) base[length[i]+1]++;
Packit 71fd91
Packit 71fd91
   for (i = 1; i < BZ_MAX_CODE_LEN; i++) base[i] += base[i-1];
Packit 71fd91
Packit 71fd91
   for (i = 0; i < BZ_MAX_CODE_LEN; i++) limit[i] = 0;
Packit 71fd91
   vec = 0;
Packit 71fd91
Packit 71fd91
   for (i = minLen; i <= maxLen; i++) {
Packit 71fd91
      vec += (base[i+1] - base[i]);
Packit 71fd91
      limit[i] = vec-1;
Packit 71fd91
      vec <<= 1;
Packit 71fd91
   }
Packit 71fd91
   for (i = minLen + 1; i <= maxLen; i++)
Packit 71fd91
      base[i] = ((limit[i-1] + 1) << 1) - base[i];
Packit 71fd91
}
Packit 71fd91
Packit 71fd91
Packit 71fd91
/*-------------------------------------------------------------*/
Packit 71fd91
/*--- end                                         huffman.c ---*/
Packit 71fd91
/*-------------------------------------------------------------*/