enum
{
ZBase = 2, /* base of code to encode 0 runs */
LitBase = ZBase-1, /* base of literal values */
MaxLit = 256,
MaxLeaf = MaxLit+LitBase,
MaxHuffBits = 16, /* limit of bits in a huffman code */
ChainMem = 2 * (MaxHuffBits - 1) * MaxHuffBits,
};
/*
* huffman code table
*/
struct Huff
{
short bits; /* length of the code */
ulong encode; /* the code */
};
struct Chain
{
ulong count; /* occurances of everything in the chain */
ushort leaf; /* leaves to the left of chain, or leaf value */
char col; /* ref count for collecting unused chains */
char gen; /* need to generate chains for next lower level */
Chain *up; /* Chain up in the lists */
};
struct Chains
{
Chain *lists[(MaxHuffBits - 1) * 2];
ulong leafcount[MaxLeaf]; /* sorted list of leaf counts */
ushort leafmap[MaxLeaf]; /* map to actual leaf number */
int nleaf; /* number of leaves */
Chain chains[ChainMem];
Chain *echains;
Chain *free;
char col;
int nlists;
};
static jmp_buf errjmp;
static uchar *bout;
static int bmax;
static int bpos;
/*
* send the data
*/
for(i = 0; i < hbpos; i++){
s = hbuf[i];
b = tab[s].bits;
if(b == 0)
fatal("bad tables %d", i);
databits += b;
bitput(tab[s].encode, b);
}
}
static ulong
sendtab(Huff *tab, int maxleaf, ushort *map)
{
ulong ccount[MaxHuffBits+1], bused[MaxHuffBits+1];
Huff codetab[MaxHuffBits+1];
char tmtf[MaxHuffBits+1];
ulong bits;
int i, b, max, ttb, s, elim;
/*
* make up the table table
* over cleverness: the data is known to be a huffman table
* check for fullness at each bit level, and wipe it out from
* the possibilities; when nothing exists except 0, stop.
*/
for(i = 0; i <= MaxHuffBits; i++){
tmtf[i] = i;
ccount[i] = 0;
bused[i] = 0;
}
tmtf[0] = -1;
tmtf[MaxHuffBits] = 0;
elim = 0;
for(i = 0; i < maxleaf && elim != MaxHuffBits; i++){
b = i;
if(map)
b = map[b];
b = tab[b].bits;
for(s = 0; tmtf[s] != b; s++)
if(s >= MaxHuffBits)
fatal("bitlength not found");
ccount[s]++;
for(; s > 0; s--)
tmtf[s] = tmtf[s-1];
tmtf[0] = b;
static void
elimBit(int b, char *tmtf, int maxbits)
{
int bb;
for(bb = 0; bb < maxbits; bb++)
if(tmtf[bb] == b)
break;
if(tmtf[bb] != b)
fatal("elim bit not found");
while(++bb <= maxbits)
tmtf[bb - 1] = tmtf[bb];
}
/*
* fast?, in-place huffman codes
*
* A. Moffat, J. Katajainen, "In-Place Calculation of Minimum-Redundancy Codes",
*
* counts must be sorted, and may be aliased to bitlens
*/
static int
fmkprecode(ulong *bitcount, ulong *bitlen, ulong *counts, int n, int maxbits)
{
int leaf, tree, treet, depth, nodes, internal;
/*
* form the internal tree structure:
* [0, tree) are parent pointers,
* [tree, treet) are weights of internal nodes,
* [leaf, n) are weights of remaining leaves.
*
* note that at the end, there are n-1 internal nodes
*/
leaf = 0;
tree = 0;
for(treet = 0; treet != n - 1; treet++){
if(leaf >= n || tree < treet && bitlen[tree] < counts[leaf]){
bitlen[treet] = bitlen[tree];
bitlen[tree++] = treet;
}else
bitlen[treet] = counts[leaf++];
if(leaf >= n || tree < treet && bitlen[tree] < counts[leaf]){
bitlen[treet] += bitlen[tree];
bitlen[tree++] = treet;
}else
bitlen[treet] += counts[leaf++];
}
if(tree != treet - 1)
fatal("bad fast mkprecode");
/*
* calculate depth of internal nodes
*/
bitlen[n - 2] = 0;
for(tree = n - 3; tree >= 0; tree--)
bitlen[tree] = bitlen[bitlen[tree]] + 1;
/*
* calculate depth of leaves:
* at each depth, leaves(depth) = nodes(depth) - internal(depth)
* and nodes(depth+1) = 2 * internal(depth)
*/
leaf = n;
tree = n - 2;
depth = 0;
for(nodes = 1; nodes > 0; nodes = 2 * internal){
internal = 0;
while(tree >= 0 && bitlen[tree] == depth){
tree--;
internal++;
}
nodes -= internal;
if(depth < maxbits)
bitcount[depth] = nodes;
while(nodes-- > 0)
bitlen[--leaf] = depth;
depth++;
}
if(leaf != 0 || tree != -1)
fatal("bad leaves in fast mkprecode");
return depth - 1;
}
/*
* fast, low space overhead algorithm for max depth huffman type codes
*
* J. Katajainen, A. Moffat and A. Turpin, "A fast and space-economical
* algorithm for length-limited coding," Proc. Intl. Symp. on Algorithms
* and Computation, Cairns, Australia, Dec. 1995, Lecture Notes in Computer
* Science, Vol 1004, J. Staples, P. Eades, N. Katoh, and A. Moffat, eds.,
* pp 12-21, Springer Verlag, New York, 1995.
*/
static void
mkprecode(Huff *tab, ulong *count, int n, int maxbits)
{
Chains cs;
Chain *c;
ulong bitcount[MaxHuffBits];
int i, m, em, bits;
/*
* set up the sorted list of leaves
*/
m = 0;
for(i = 0; i < n; i++){
tab[i].bits = -1;
tab[i].encode = 0;
if(count[i] != 0){
cs.leafcount[m] = count[i];
cs.leafmap[m] = i;
m++;
}
}
if(m < 2){
if(m != 0){
m = cs.leafmap[0];
tab[m].bits = 0;
tab[m].encode = 0;
}
return;
}
cs.nleaf = m;
leafsort(cs.leafcount, cs.leafmap, 0, m);
/*
* try fast code
*/
bits = fmkprecode(bitcount, cs.leafcount, cs.leafcount, m, maxbits);
if(bits < maxbits){
for(i = 0; i < m; i++)
tab[cs.leafmap[i]].bits = cs.leafcount[i];
bitcount[0] = 0;
}else{
for(i = 0; i < m; i++)
cs.leafcount[i] = count[cs.leafmap[i]];
/*
* set up free list
*/
cs.free = &cs.chains[2];
cs.echains = &cs.chains[ChainMem];
cs.col = 1;
cs.nlists = 2 * (maxbits - 1);
m = 2 * m - 2;
for(i = 2; i < m; i++)
nextchain(&cs, cs.nlists - 2);
bits = 0;
bitcount[0] = cs.nleaf;
for(c = cs.lists[cs.nlists - 1]; c != nil; c = c->up){
m = c->leaf;
bitcount[bits++] -= m;
bitcount[bits] = m;
}
m = 0;
for(i = bits; i >= 0; i--)
for(em = m + bitcount[i]; m < em; m++)
tab[cs.leafmap[m]].bits = i;
}
hufftabinit(tab, n, bitcount, bits);
}
/*
* calculate the next chain on the list
* we can always toss out the old chain
*/
static void
nextchain(Chains *cs, int list)
{
Chain *c, *oc;
int i, nleaf, sumc;
/*
* make sure we have all chains needed to make sumc
* note it is possible to generate only one of these,
* use twice that value for sumc, and then generate
* the second if that preliminary sumc would be chosen.
* however, this appears to be slower on current tests
*/
if(oc->gen){
nextchain(cs, list - 2);
nextchain(cs, list - 2);
oc->gen = 0;
}
/*
* pick up the chain we're going to add;
* collect unused chains no free ones are left
*/
for(c = cs->free; ; c++){
if(c >= cs->echains){
cs->col++;
for(i = 0; i < cs->nlists; i++)
for(c = cs->lists[i]; c != nil; c = c->up)
c->col = cs->col;
c = cs->chains;
}
if(c->col != cs->col)
break;
}
/*
* pick the cheapest of
* 1) the next package from the previous list
* 2) the next leaf
*/
nleaf = oc->leaf;
sumc = 0;
if(list > 0 && cs->lists[list-1] != nil)
sumc = cs->lists[list-2]->count + cs->lists[list-1]->count;
if(sumc != 0 && (nleaf >= cs->nleaf || cs->leafcount[nleaf] > sumc)){
c->count = sumc;
c->leaf = oc->leaf;
c->up = cs->lists[list-1];
c->gen = 1;
}else if(nleaf >= cs->nleaf){
cs->lists[list + 1] = nil;
return;
}else{
c->leaf = nleaf + 1;
c->count = cs->leafcount[nleaf];
c->up = oc->up;
c->gen = 0;
}
cs->free = c + 1;
cs->lists[list + 1] = c;
c->col = cs->col;
}
static void
hufftabinit(Huff *tab, int n, ulong *bitcount, int nbits)
{
ulong code, nc[MaxHuffBits];
int i, bits;