aboutsummaryrefslogtreecommitdiff
path: root/C/HuffEnc.c
diff options
context:
space:
mode:
authorIgor Pavlov <87184205+ip7z@users.noreply.github.com>2021-12-27 00:00:00 +0000
committerIgor Pavlov <87184205+ip7z@users.noreply.github.com>2022-03-18 15:35:13 +0500
commitf19f813537c7aea1c20749c914e756b54a9c3cf5 (patch)
tree816ba62ca7c0fa19f2eb46d9e9d6f7dd7c3a744d /C/HuffEnc.c
parent98e06a519b63b81986abe76d28887f6984a7732b (diff)
download7zip-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.c148
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
22021-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
17void 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}