X-Git-Url: http://vcs.maemo.org/git/?a=blobdiff_plain;f=lzma%2FC%2FCompress%2FHuffman%2FHuffmanEncode.c;fp=lzma%2FC%2FCompress%2FHuffman%2FHuffmanEncode.c;h=f27607e67e37d5614d5f5b95c84168a908d23d73;hb=1a2e54b98aaab3669eebd38facb83687c4ac7baf;hp=0000000000000000000000000000000000000000;hpb=0b9bdac28929054558b5d7f315403fe3399a1413;p=physicsfs diff --git a/lzma/C/Compress/Huffman/HuffmanEncode.c b/lzma/C/Compress/Huffman/HuffmanEncode.c new file mode 100644 index 0000000..f27607e --- /dev/null +++ b/lzma/C/Compress/Huffman/HuffmanEncode.c @@ -0,0 +1,146 @@ +/* Compress/HuffmanEncode.c */ + +#include "HuffmanEncode.h" +#include "../../Sort.h" + +#define kMaxLen 16 +#define NUM_BITS 10 +#define MASK ((1 << NUM_BITS) - 1) + +#define NUM_COUNTERS 64 + +/* use BLOCK_SORT_EXTERNAL_FLAGS if blockSize > 1M */ +#define HUFFMAN_SPEED_OPT + +void Huffman_Generate(const UInt32 *freqs, UInt32 *p, Byte *lens, UInt32 numSymbols, UInt32 maxLen) +{ + UInt32 num = 0; + /* if (maxLen > 10) maxLen = 10; */ + { + UInt32 i; + + #ifdef HUFFMAN_SPEED_OPT + + UInt32 counters[NUM_COUNTERS]; + for (i = 0; i < NUM_COUNTERS; i++) + counters[i] = 0; + for (i = 0; i < numSymbols; i++) + { + UInt32 freq = freqs[i]; + counters[(freq < NUM_COUNTERS - 1) ? freq : NUM_COUNTERS - 1]++; + } + + for (i = 1; i < NUM_COUNTERS; i++) + { + UInt32 temp = counters[i]; + counters[i] = num; + num += temp; + } + + for (i = 0; i < numSymbols; i++) + { + UInt32 freq = freqs[i]; + if (freq == 0) + lens[i] = 0; + else + p[counters[((freq < NUM_COUNTERS - 1) ? freq : NUM_COUNTERS - 1)]++] = i | (freq << NUM_BITS); + } + counters[0] = 0; + HeapSort(p + counters[NUM_COUNTERS - 2], counters[NUM_COUNTERS - 1] - counters[NUM_COUNTERS - 2]); + + #else + + for (i = 0; i < numSymbols; i++) + { + UInt32 freq = freqs[i]; + if (freq == 0) + lens[i] = 0; + else + p[num++] = i | (freq << NUM_BITS); + } + HeapSort(p, num); + + #endif + } + + if (num < 2) + { + int minCode = 0; + int maxCode = 1; + if (num == 1) + { + maxCode = p[0] & MASK; + if (maxCode == 0) + maxCode++; + } + p[minCode] = 0; + p[maxCode] = 1; + lens[minCode] = lens[maxCode] = 1; + return; + } + + { + UInt32 b, e, i; + + i = b = e = 0; + do + { + UInt32 n, m, freq; + n = (i != num && (b == e || (p[i] >> NUM_BITS) <= (p[b] >> NUM_BITS))) ? i++ : b++; + freq = (p[n] & ~MASK); + p[n] = (p[n] & MASK) | (e << NUM_BITS); + m = (i != num && (b == e || (p[i] >> NUM_BITS) <= (p[b] >> NUM_BITS))) ? i++ : b++; + freq += (p[m] & ~MASK); + p[m] = (p[m] & MASK) | (e << NUM_BITS); + p[e] = (p[e] & MASK) | freq; + e++; + } + while (num - e > 1); + + { + UInt32 lenCounters[kMaxLen + 1]; + for (i = 0; i <= kMaxLen; i++) + lenCounters[i] = 0; + + p[--e] &= MASK; + lenCounters[1] = 2; + while (e > 0) + { + UInt32 len = (p[p[--e] >> NUM_BITS] >> NUM_BITS) + 1; + p[e] = (p[e] & MASK) | (len << NUM_BITS); + if (len >= maxLen) + for (len = maxLen - 1; lenCounters[len] == 0; len--); + lenCounters[len]--; + lenCounters[len + 1] += 2; + } + + { + UInt32 len; + i = 0; + for (len = maxLen; len != 0; len--) + { + UInt32 num; + for (num = lenCounters[len]; num != 0; num--) + lens[p[i++] & MASK] = (Byte)len; + } + } + + { + UInt32 nextCodes[kMaxLen + 1]; + { + UInt32 code = 0; + UInt32 len; + for (len = 1; len <= kMaxLen; len++) + nextCodes[len] = code = (code + lenCounters[len - 1]) << 1; + } + /* if (code + lenCounters[kMaxLen] - 1 != (1 << kMaxLen) - 1) throw 1; */ + + { + UInt32 i; + for (i = 0; i < numSymbols; i++) + p[i] = nextCodes[lens[i]]++; + } + } + } + } +}