/***********************************************************************
* *
* This software is part of the ast package *
* Copyright (c) 2003-2011 AT&T Intellectual Property *
* and is licensed under the *
* Eclipse Public License, Version 1.0 *
* by AT&T Intellectual Property *
* *
* A copy of the License is available at *
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
* *
* Information and Software Systems Research *
* AT&T Research *
* Florham Park NJ *
* *
* Phong Vo <kpv@research.att.com> *
* *
***********************************************************************/
#include "vchhdr.h"
/* Compute the code lengths for symbols based on their frequencies.
** This uses a linear-time algorithm after frequency sorting.
** Frequencies are scaled to be <= VCH_MAXWEIGHT so that max code
** length will be < VCH_MAXLENGTH.
**
** Written by Kiem-Phong Vo
*/
/* node in a kind-of-flattened Huffman tree */
typedef struct _vchtree_s
} Vchtree_t;
/* sort by frequencies */
#if __STD_C
#else
#endif
{
int d;
return d;
else return o < t ? -1 : o == t ? 0 : 1;
}
#if __STD_C
#else
int* runb; /* the run byte if any */
#endif
{
return -1;
/* construct list of elements with non-zero weights */
notz = 0;
{ size[c] = 0;
continue;
}
if(runb)
*runb = -1;
return 0;
}
/* scale to bound max # of bits for a code */
for(k = 0; k < notz; ++k)
/* build linked list sorted by frequencies */
{ f->link = f; /* nodes in each subtree are kept in a circular list */
}
/* linear-time construction of a Huffman tree */
{ /* The invariant (I) needed at this point is this:
** 0. The lists "list" and "head" are sorted by frequency.
** 1. list and list->next are not NULL;
** 2. head == NULL or head->freq >= list->next->freq
** 3. tail == NULL or list->freq+list->next->freq >= tail->freq.
** Then, list and list->next can be merged into a subtree.
*/
/* the difference in depths of s and f will be fixed from now on */
s->next = f; /* final_depth(s) = final_depth(f) + above difference */
/* tree depth for subtree represented by f increases by 1 */
/* merge subtrees, ie, link the two circular lists */
/* move f to the list of merged pairs */
if(list)
continue; /* invariant (I) satisfied, merge them */
/* find the segment in "head" movable to start of list */
break;
/* going back to top of loop, so we need invariant (I).
** I.0, I.1 and I.2 will clearly be true after below move.
** Now observe that tail->freq <= 2*head->freq and
** tail->freq <= 2*list->freq. This gives I.3 in all cases.
*/
if(p)
}
else
}
if(!(head = f) )
}
else
break; /* tree completed */
}
}
/* turn circular list into forward list, then compute final depths */
{ p = f->link;
f->link = s;
s = f;
}
for(c = 0; s; s = s->link)
}
return c;
}