diff options
author | Igor Pavlov <87184205+ip7z@users.noreply.github.com> | 2021-12-27 00:00:00 +0000 |
---|---|---|
committer | Igor Pavlov <87184205+ip7z@users.noreply.github.com> | 2022-03-18 15:35:13 +0500 |
commit | f19f813537c7aea1c20749c914e756b54a9c3cf5 (patch) | |
tree | 816ba62ca7c0fa19f2eb46d9e9d6f7dd7c3a744d /C/HuffEnc.c | |
parent | 98e06a519b63b81986abe76d28887f6984a7732b (diff) | |
download | 7zip-21.07.tar.gz 7zip-21.07.tar.bz2 7zip-21.07.zip |
'21.07'21.07
Diffstat (limited to 'C/HuffEnc.c')
-rw-r--r-- | C/HuffEnc.c | 148 |
1 files changed, 148 insertions, 0 deletions
diff --git a/C/HuffEnc.c b/C/HuffEnc.c new file mode 100644 index 0000000..f3c2996 --- /dev/null +++ b/C/HuffEnc.c | |||
@@ -0,0 +1,148 @@ | |||
1 | /* HuffEnc.c -- functions for Huffman encoding | ||
2 | 2021-02-09 : Igor Pavlov : Public domain */ | ||
3 | |||
4 | #include "Precomp.h" | ||
5 | |||
6 | #include "HuffEnc.h" | ||
7 | #include "Sort.h" | ||
8 | |||
9 | #define kMaxLen 16 | ||
10 | #define NUM_BITS 10 | ||
11 | #define MASK (((unsigned)1 << NUM_BITS) - 1) | ||
12 | |||
13 | #define NUM_COUNTERS 64 | ||
14 | |||
15 | #define HUFFMAN_SPEED_OPT | ||
16 | |||
17 | void Huffman_Generate(const UInt32 *freqs, UInt32 *p, Byte *lens, UInt32 numSymbols, UInt32 maxLen) | ||
18 | { | ||
19 | UInt32 num = 0; | ||
20 | /* if (maxLen > 10) maxLen = 10; */ | ||
21 | { | ||
22 | UInt32 i; | ||
23 | |||
24 | #ifdef HUFFMAN_SPEED_OPT | ||
25 | |||
26 | UInt32 counters[NUM_COUNTERS]; | ||
27 | for (i = 0; i < NUM_COUNTERS; i++) | ||
28 | counters[i] = 0; | ||
29 | for (i = 0; i < numSymbols; i++) | ||
30 | { | ||
31 | UInt32 freq = freqs[i]; | ||
32 | counters[(freq < NUM_COUNTERS - 1) ? freq : NUM_COUNTERS - 1]++; | ||
33 | } | ||
34 | |||
35 | for (i = 1; i < NUM_COUNTERS; i++) | ||
36 | { | ||
37 | UInt32 temp = counters[i]; | ||
38 | counters[i] = num; | ||
39 | num += temp; | ||
40 | } | ||
41 | |||
42 | for (i = 0; i < numSymbols; i++) | ||
43 | { | ||
44 | UInt32 freq = freqs[i]; | ||
45 | if (freq == 0) | ||
46 | lens[i] = 0; | ||
47 | else | ||
48 | p[counters[((freq < NUM_COUNTERS - 1) ? freq : NUM_COUNTERS - 1)]++] = i | (freq << NUM_BITS); | ||
49 | } | ||
50 | counters[0] = 0; | ||
51 | HeapSort(p + counters[NUM_COUNTERS - 2], counters[NUM_COUNTERS - 1] - counters[NUM_COUNTERS - 2]); | ||
52 | |||
53 | #else | ||
54 | |||
55 | for (i = 0; i < numSymbols; i++) | ||
56 | { | ||
57 | UInt32 freq = freqs[i]; | ||
58 | if (freq == 0) | ||
59 | lens[i] = 0; | ||
60 | else | ||
61 | p[num++] = i | (freq << NUM_BITS); | ||
62 | } | ||
63 | HeapSort(p, num); | ||
64 | |||
65 | #endif | ||
66 | } | ||
67 | |||
68 | if (num < 2) | ||
69 | { | ||
70 | unsigned minCode = 0; | ||
71 | unsigned maxCode = 1; | ||
72 | if (num == 1) | ||
73 | { | ||
74 | maxCode = (unsigned)p[0] & MASK; | ||
75 | if (maxCode == 0) | ||
76 | maxCode++; | ||
77 | } | ||
78 | p[minCode] = 0; | ||
79 | p[maxCode] = 1; | ||
80 | lens[minCode] = lens[maxCode] = 1; | ||
81 | return; | ||
82 | } | ||
83 | |||
84 | { | ||
85 | UInt32 b, e, i; | ||
86 | |||
87 | i = b = e = 0; | ||
88 | do | ||
89 | { | ||
90 | UInt32 n, m, freq; | ||
91 | n = (i != num && (b == e || (p[i] >> NUM_BITS) <= (p[b] >> NUM_BITS))) ? i++ : b++; | ||
92 | freq = (p[n] & ~MASK); | ||
93 | p[n] = (p[n] & MASK) | (e << NUM_BITS); | ||
94 | m = (i != num && (b == e || (p[i] >> NUM_BITS) <= (p[b] >> NUM_BITS))) ? i++ : b++; | ||
95 | freq += (p[m] & ~MASK); | ||
96 | p[m] = (p[m] & MASK) | (e << NUM_BITS); | ||
97 | p[e] = (p[e] & MASK) | freq; | ||
98 | e++; | ||
99 | } | ||
100 | while (num - e > 1); | ||
101 | |||
102 | { | ||
103 | UInt32 lenCounters[kMaxLen + 1]; | ||
104 | for (i = 0; i <= kMaxLen; i++) | ||
105 | lenCounters[i] = 0; | ||
106 | |||
107 | p[--e] &= MASK; | ||
108 | lenCounters[1] = 2; | ||
109 | while (e > 0) | ||
110 | { | ||
111 | UInt32 len = (p[p[--e] >> NUM_BITS] >> NUM_BITS) + 1; | ||
112 | p[e] = (p[e] & MASK) | (len << NUM_BITS); | ||
113 | if (len >= maxLen) | ||
114 | for (len = maxLen - 1; lenCounters[len] == 0; len--); | ||
115 | lenCounters[len]--; | ||
116 | lenCounters[(size_t)len + 1] += 2; | ||
117 | } | ||
118 | |||
119 | { | ||
120 | UInt32 len; | ||
121 | i = 0; | ||
122 | for (len = maxLen; len != 0; len--) | ||
123 | { | ||
124 | UInt32 k; | ||
125 | for (k = lenCounters[len]; k != 0; k--) | ||
126 | lens[p[i++] & MASK] = (Byte)len; | ||
127 | } | ||
128 | } | ||
129 | |||
130 | { | ||
131 | UInt32 nextCodes[kMaxLen + 1]; | ||
132 | { | ||
133 | UInt32 code = 0; | ||
134 | UInt32 len; | ||
135 | for (len = 1; len <= kMaxLen; len++) | ||
136 | nextCodes[len] = code = (code + lenCounters[(size_t)len - 1]) << 1; | ||
137 | } | ||
138 | /* if (code + lenCounters[kMaxLen] - 1 != (1 << kMaxLen) - 1) throw 1; */ | ||
139 | |||
140 | { | ||
141 | UInt32 k; | ||
142 | for (k = 0; k < numSymbols; k++) | ||
143 | p[k] = nextCodes[lens[k]]++; | ||
144 | } | ||
145 | } | ||
146 | } | ||
147 | } | ||
148 | } | ||