flate

deflate implementation
git clone git://git.suckless.org/flate
Log | Files | Refs | README

commit 2e11080e70d83bc8d30c95a37c3191db79609a00
parent 73ed0e04029a6e2872d2b4aff478a1b56ebe7528
Author: nsz <nszabolcs@gmail.com>
Date:   Tue, 11 Aug 2009 13:48:57 +0200

deflate: freq/code overlap
Diffstat:
deflate.c | 58++++++++++++++++++++++++++++++++--------------------------
1 file changed, 32 insertions(+), 26 deletions(-)

diff --git a/deflate.c b/deflate.c @@ -5,25 +5,28 @@ /* TODO: - (hufflen: parent+heap only) - match: check backwards - block end guess with lfreq, dfreq - bisect len/distbase -> lookup table - (rolling hash) - bounds on the compressend size - (zlib huffcode trick: if same freq then shorter code goes to the one with smaller subtree) - overlap freq/code, rbuf/dstwin ? - verify dstsize - input from in+nin instead of src+srcend - setting s->state.. - ushort vs int - -spec case tests: - empty block - huff overflow - all zero (rle) - dist = 32K - test with small bufsize (1,2..9 bytes) + space opt: + overlap rbuf/dstwin + hufflen: overlap arrays (parent+heap only) + time opt: + match loop unroll + less branching in deflate_state (check avail > MinMatch once) + bisect len/distbase -> lookup table + rolling hash + better compression: + block split heuristics with lfreq, dfreq + (zlib huffcode trick: if same freq then shorter code goes to the one with smaller subtree) + code cleanups: + bounds on the compressend size + verify dstsize + input from in+nin instead of src+srcend + setting s->state.. + ushort vs int + tests: + empty block + all zero (rle) + uncompressed block + test with small nin/nout (1,2..9 bytes) */ enum { @@ -77,8 +80,8 @@ typedef struct { LzCode lzbuf[LzSize]; /* literal run length, match len, match dist */ LzCode *lz; /* current pos in lzbuf */ int run; /* literal run length */ - int lfreq[Nlitlen]; - int dfreq[Ndist]; + ushort lfreq[Nlitlen]; + ushort dfreq[Ndist]; uchar dstbuf[DstSize]; } State; @@ -192,7 +195,7 @@ static int heappop(int *heap, int len, int *w, int *n) { } /* symbol frequencies -> code lengths (limited to 255) */ -static void hufflens(uchar *lens, int *freqs, int nsym, int limit) { +static void hufflens(uchar *lens, ushort *freqs, int nsym, int limit) { /* 2 <= nsym <= Nlitlen, log(nsym) <= limit <= CodeBits-1 */ int parent[2*Nlitlen-1]; int count[CodeBits]; @@ -334,17 +337,18 @@ static void putblock(State *s, ushort *lcode, uchar *llen, ushort *dcode, uchar } static void deflate_block(State *s) { - int cfreq[Nclen]; uchar codes[Nlitlen + Ndist], extra[Nlitlen + Ndist]; uchar llen[Nlitlen], dlen[Ndist], clen[Nclen]; - ushort lcode[Nlitlen], dcode[Ndist], ccode[Nclen]; + ushort cfreq[Nclen]; + /* freq can be overwritten by code */ + ushort *lcode = s->lfreq, *dcode = s->dfreq, *ccode = cfreq; int i, c, n, ncodes; int nlit, ndist, nclen; LzCode *lz; uchar *pc; int dynsize, fixsize, uncsize; int blocklen = s->pos - s->startpos; -int dyntree; +/*int dyntree;*/ /* calc dynamic codes */ hufflens(llen, s->lfreq, Nlitlen, CodeBits-1); @@ -375,7 +379,7 @@ int dyntree; if (c == 18) dynsize += 7; } -dyntree = dynsize - 3; +/*dyntree = dynsize - 3;*/ for (lz = s->lzbuf, pc = s->win + s->startpos; lz != s->lz; lz++) if (lz->bits & LzLitFlag) for (n = lz->n; n > 0; n--, pc++) { @@ -432,9 +436,11 @@ dyntree = dynsize - 3; memcpy(s->dst, s->win + s->startpos, blocklen); s->dst += blocklen; } +/* fprintf(stderr, "blen: %d [%d,%d] lzlen: %d dynlen: %d (tree: %d, rate: %.3f) fixlen: %d (rate: %.3f) unclen: %d (rate: %.3f) avail %d\n", blocklen, s->startpos, s->pos, s->lz - s->lzbuf, dynsize, dyntree, dynsize/(float)blocklen, fixsize, fixsize/(float)blocklen, uncsize, uncsize/(float)blocklen, s->avail); +*/ } static int bisect(ushort *base, int len, int n) {