flate

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

commit 21159561f3409a46a0949d92fc131f18784271b5
parent 6ee26d56c3e3e39af131e339290495825e8951a3
Author: nsz <nszabolcs@gmail.com>
Date:   Mon,  6 Jul 2009 19:13:49 +0200

complexification
Diffstat:
deflate_simple.c | 97++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------------
1 file changed, 66 insertions(+), 31 deletions(-)

diff --git a/deflate_simple.c b/deflate_simple.c @@ -25,11 +25,6 @@ enum { Nclen = 19 /* number of code length codes */ }; -typedef struct { - ushort dist; - ushort len; -} Match; - enum { SymLitlen, SymDist, @@ -44,6 +39,11 @@ typedef struct { } Sym; typedef struct { + ushort dist; + ushort len; +} Match; + +typedef struct { ushort head[HashSize]; /* position of hash chain heads */ ushort chain[WinSize]; /* hash chains */ int pos; /* position in hash chain */ @@ -538,6 +538,7 @@ fprintf(stderr, "tree len: %d bits: %d\n", nsym, dynsize); outbits(s, s->lastblock, 1); if ((long long)fixsize * dynlen > (long long)dynsize * fixlen) { +fprintf(stderr, "dyn "); blocklen = dynlen; outbits(s, 2, 2); outbits(s, nlit - 257, 5); @@ -567,6 +568,7 @@ fprintf(stderr, "tree len: %d bits: %d\n", nsym, dynsize); /* EOB */ outbits(s, lcode[256], llen[256]); } else { +fprintf(stderr, "fix "); blocklen = fixlen; outbits(s, 1, 2); /* block data */ @@ -582,7 +584,7 @@ fprintf(stderr, "tree len: %d bits: %d\n", nsym, dynsize); /* EOB */ outbits(s, fixed_lcode[256], fixed_llen[256]); } -fprintf(stderr, "blocklen: %d symlen: %d dynsize: %d dynlen: %d fixsize: %d fixlen:%d\n", blocklen, s->symlen, dynsize, dynlen, fixsize, fixlen); +fprintf(stderr, "symlen: %d dynsize: %d dynlen: %d fixsize: %d fixlen:%d\n", s->symlen, dynsize, dynlen, fixsize, fixlen); s->symstart = (s->symstart + blocklen) % SymSize; s->symlen -= blocklen; } @@ -615,51 +617,82 @@ static int log2_8(uint n) { return r; } +static int nlog(uint n) { + return n*log2_8(n); +} + static void chooseblock(State *s) { int lfreq[Nlitlen], dfreq[Ndist]; - int i, len, bestlen, longestlen; - int ltotal, dtotal; - int bestvfm; + int ln, dn; + int len; + uint bestrate; + int bestlen, longestlen, besti; + int extra; + int hlen; + int i; Sym sym; + hlen = 600 * 8; /* length of encoded huff tree (usually 400..900 bits) */ + extra = 0; memset(lfreq, 0, sizeof(lfreq)); memset(dfreq, 0, sizeof(dfreq)); - lfreq[256] = 1; /* we're bound to need one EOB */ - ltotal = 1; - dtotal = longestlen = bestvfm = 0; - bestlen = -1; - len = 400 * 8; /* approximate size of the Huffman trees */ + lfreq[256] = 1; /* EOB */ + ln = 1; + dn = 0; +/* + for (i = 0; i < s->symlen; i++) { + sym = getsym(s, i); + if (sym.type == SymLitlen) { + lfreq[sym.n]++; + ln++; + } + if (sym.type == SymDist) { + dfreq[sym.n]++; + dn++; + } + if (sym.type == SymExtra) + extra += 8 * sym.len; + } + len = hlen + nlog(ln) + nlog(dn); + for (i = 0; i < Nlitlen; i++) + len -= nlog(lfreq[i]); + for (i = 0; i < Ndist; i++) + len -= nlog(dfreq[i]); +*/ + len = hlen; + bestlen = longestlen = besti = 0; + bestrate = len << 9; for (i = 0; i < s->symlen; i++) { sym = getsym(s, i); if (sym.type == SymLitlen) { if (sym.n < Nlit) { - int vfm = i * 32768 / len; + uint rate = ((uint)len << 9)/(ln + dn); - if (vfm > bestvfm) { - bestlen = i; - bestvfm = vfm; + if (rate < bestrate) { + besti = i; + bestlen = len; + bestrate = rate; } longestlen = i; } - len += lfreq[sym.n] * log2_8(lfreq[sym.n]); - len -= ltotal * log2_8(ltotal); + len += nlog(lfreq[sym.n]); + len -= nlog(ln); lfreq[sym.n]++; - ltotal++; - len -= lfreq[sym.n] * log2_8(lfreq[sym.n]); - len += ltotal * log2_8(ltotal); + ln++; + len += nlog(ln); + len -= nlog(lfreq[sym.n]); } if (sym.type == SymDist) { - len += dfreq[sym.n] * log2_8(dfreq[sym.n]); - len -= dtotal * log2_8(dtotal); + len += nlog(dfreq[sym.n]); + len -= nlog(dn); dfreq[sym.n]++; - dtotal++; - len -= dfreq[sym.n] * log2_8(dfreq[sym.n]); - len += dtotal * log2_8(dtotal); + dn++; + len += nlog(dn); + len -= nlog(dfreq[sym.n]); } - if (sym.type == SymExtra) - len += 8 * sym.len; } - block(s, bestlen, longestlen); +fprintf(stderr, "i: %u bits: %u rate: %u full: %u\n", besti, bestlen>>3, bestrate>>5, ((uint)len<<9)/(ln+dn) >> 5); + block(s, besti, longestlen); } static int count = 0; @@ -745,6 +778,8 @@ int deflate(uchar *src, int len, uchar *dst) { s.dst = dst; lzcompress(&s, src, len); chooseblock(&s); + if (s.symlen > 4000) + chooseblock(&s); s.lastblock = 1; block(&s, s.symlen, s.symlen); outbits(&s, 0, 7);