extlzham 0.0.1.PROTOTYPE
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE.md +27 -0
- data/README.md +21 -0
- data/Rakefile +143 -0
- data/contrib/lzham/LICENSE +22 -0
- data/contrib/lzham/README.md +209 -0
- data/contrib/lzham/include/lzham.h +781 -0
- data/contrib/lzham/lzhamcomp/lzham_comp.h +38 -0
- data/contrib/lzham/lzhamcomp/lzham_lzbase.cpp +244 -0
- data/contrib/lzham/lzhamcomp/lzham_lzbase.h +45 -0
- data/contrib/lzham/lzhamcomp/lzham_lzcomp.cpp +608 -0
- data/contrib/lzham/lzhamcomp/lzham_lzcomp_internal.cpp +1966 -0
- data/contrib/lzham/lzhamcomp/lzham_lzcomp_internal.h +472 -0
- data/contrib/lzham/lzhamcomp/lzham_lzcomp_state.cpp +1413 -0
- data/contrib/lzham/lzhamcomp/lzham_match_accel.cpp +562 -0
- data/contrib/lzham/lzhamcomp/lzham_match_accel.h +146 -0
- data/contrib/lzham/lzhamcomp/lzham_null_threading.h +97 -0
- data/contrib/lzham/lzhamcomp/lzham_pthreads_threading.cpp +229 -0
- data/contrib/lzham/lzhamcomp/lzham_pthreads_threading.h +520 -0
- data/contrib/lzham/lzhamcomp/lzham_threading.h +12 -0
- data/contrib/lzham/lzhamcomp/lzham_win32_threading.cpp +220 -0
- data/contrib/lzham/lzhamcomp/lzham_win32_threading.h +368 -0
- data/contrib/lzham/lzhamdecomp/lzham_assert.cpp +66 -0
- data/contrib/lzham/lzhamdecomp/lzham_assert.h +40 -0
- data/contrib/lzham/lzhamdecomp/lzham_checksum.cpp +73 -0
- data/contrib/lzham/lzhamdecomp/lzham_checksum.h +13 -0
- data/contrib/lzham/lzhamdecomp/lzham_config.h +23 -0
- data/contrib/lzham/lzhamdecomp/lzham_core.h +264 -0
- data/contrib/lzham/lzhamdecomp/lzham_decomp.h +37 -0
- data/contrib/lzham/lzhamdecomp/lzham_helpers.h +54 -0
- data/contrib/lzham/lzhamdecomp/lzham_huffman_codes.cpp +262 -0
- data/contrib/lzham/lzhamdecomp/lzham_huffman_codes.h +14 -0
- data/contrib/lzham/lzhamdecomp/lzham_lzdecomp.cpp +1527 -0
- data/contrib/lzham/lzhamdecomp/lzham_lzdecompbase.cpp +131 -0
- data/contrib/lzham/lzhamdecomp/lzham_lzdecompbase.h +89 -0
- data/contrib/lzham/lzhamdecomp/lzham_math.h +142 -0
- data/contrib/lzham/lzhamdecomp/lzham_mem.cpp +284 -0
- data/contrib/lzham/lzhamdecomp/lzham_mem.h +112 -0
- data/contrib/lzham/lzhamdecomp/lzham_platform.cpp +157 -0
- data/contrib/lzham/lzhamdecomp/lzham_platform.h +284 -0
- data/contrib/lzham/lzhamdecomp/lzham_prefix_coding.cpp +351 -0
- data/contrib/lzham/lzhamdecomp/lzham_prefix_coding.h +146 -0
- data/contrib/lzham/lzhamdecomp/lzham_symbol_codec.cpp +1484 -0
- data/contrib/lzham/lzhamdecomp/lzham_symbol_codec.h +556 -0
- data/contrib/lzham/lzhamdecomp/lzham_timer.cpp +147 -0
- data/contrib/lzham/lzhamdecomp/lzham_timer.h +99 -0
- data/contrib/lzham/lzhamdecomp/lzham_traits.h +141 -0
- data/contrib/lzham/lzhamdecomp/lzham_types.h +97 -0
- data/contrib/lzham/lzhamdecomp/lzham_utils.h +58 -0
- data/contrib/lzham/lzhamdecomp/lzham_vector.cpp +75 -0
- data/contrib/lzham/lzhamdecomp/lzham_vector.h +588 -0
- data/contrib/lzham/lzhamlib/lzham_lib.cpp +179 -0
- data/examples/basic.rb +48 -0
- data/ext/extconf.rb +26 -0
- data/ext/extlzham.c +741 -0
- data/gemstub.rb +22 -0
- data/lib/extlzham/version.rb +5 -0
- data/lib/extlzham.rb +153 -0
- metadata +135 -0
@@ -0,0 +1,262 @@
|
|
1
|
+
// File: huffman_codes.cpp
|
2
|
+
// See Copyright Notice and license at the end of include/lzham.h
|
3
|
+
#include "lzham_core.h"
|
4
|
+
#include "lzham_huffman_codes.h"
|
5
|
+
|
6
|
+
namespace lzham
|
7
|
+
{
|
8
|
+
struct sym_freq
|
9
|
+
{
|
10
|
+
uint m_freq;
|
11
|
+
uint16 m_left;
|
12
|
+
uint16 m_right;
|
13
|
+
|
14
|
+
inline bool operator< (const sym_freq& other) const
|
15
|
+
{
|
16
|
+
return m_freq > other.m_freq;
|
17
|
+
}
|
18
|
+
};
|
19
|
+
|
20
|
+
static inline sym_freq* radix_sort_syms(uint num_syms, sym_freq* syms0, sym_freq* syms1)
|
21
|
+
{
|
22
|
+
const uint cMaxPasses = 2;
|
23
|
+
uint hist[256 * cMaxPasses];
|
24
|
+
|
25
|
+
memset(hist, 0, sizeof(hist[0]) * 256 * cMaxPasses);
|
26
|
+
|
27
|
+
{
|
28
|
+
sym_freq* p = syms0;
|
29
|
+
sym_freq* q = syms0 + (num_syms >> 1) * 2;
|
30
|
+
|
31
|
+
for ( ; p != q; p += 2)
|
32
|
+
{
|
33
|
+
const uint freq0 = p[0].m_freq;
|
34
|
+
const uint freq1 = p[1].m_freq;
|
35
|
+
|
36
|
+
hist[ freq0 & 0xFF]++;
|
37
|
+
hist[256 + ((freq0 >> 8) & 0xFF)]++;
|
38
|
+
|
39
|
+
hist[ freq1 & 0xFF]++;
|
40
|
+
hist[256 + ((freq1 >> 8) & 0xFF)]++;
|
41
|
+
}
|
42
|
+
|
43
|
+
if (num_syms & 1)
|
44
|
+
{
|
45
|
+
const uint freq = p->m_freq;
|
46
|
+
|
47
|
+
hist[ freq & 0xFF]++;
|
48
|
+
hist[256 + ((freq >> 8) & 0xFF)]++;
|
49
|
+
}
|
50
|
+
}
|
51
|
+
|
52
|
+
sym_freq* pCur_syms = syms0;
|
53
|
+
sym_freq* pNew_syms = syms1;
|
54
|
+
|
55
|
+
const uint total_passes = (hist[256] == num_syms) ? 1 : cMaxPasses;
|
56
|
+
|
57
|
+
for (uint pass = 0; pass < total_passes; pass++)
|
58
|
+
{
|
59
|
+
const uint* pHist = &hist[pass << 8];
|
60
|
+
|
61
|
+
uint offsets[256];
|
62
|
+
|
63
|
+
uint cur_ofs = 0;
|
64
|
+
for (uint i = 0; i < 256; i += 2)
|
65
|
+
{
|
66
|
+
offsets[i] = cur_ofs;
|
67
|
+
cur_ofs += pHist[i];
|
68
|
+
|
69
|
+
offsets[i+1] = cur_ofs;
|
70
|
+
cur_ofs += pHist[i+1];
|
71
|
+
}
|
72
|
+
|
73
|
+
const uint pass_shift = pass << 3;
|
74
|
+
|
75
|
+
sym_freq* p = pCur_syms;
|
76
|
+
sym_freq* q = pCur_syms + (num_syms >> 1) * 2;
|
77
|
+
|
78
|
+
for ( ; p != q; p += 2)
|
79
|
+
{
|
80
|
+
uint c0 = p[0].m_freq;
|
81
|
+
uint c1 = p[1].m_freq;
|
82
|
+
|
83
|
+
if (pass)
|
84
|
+
{
|
85
|
+
c0 >>= 8;
|
86
|
+
c1 >>= 8;
|
87
|
+
}
|
88
|
+
|
89
|
+
c0 &= 0xFF;
|
90
|
+
c1 &= 0xFF;
|
91
|
+
|
92
|
+
if (c0 == c1)
|
93
|
+
{
|
94
|
+
uint dst_offset0 = offsets[c0];
|
95
|
+
|
96
|
+
offsets[c0] = dst_offset0 + 2;
|
97
|
+
|
98
|
+
pNew_syms[dst_offset0] = p[0];
|
99
|
+
pNew_syms[dst_offset0 + 1] = p[1];
|
100
|
+
}
|
101
|
+
else
|
102
|
+
{
|
103
|
+
uint dst_offset0 = offsets[c0]++;
|
104
|
+
uint dst_offset1 = offsets[c1]++;
|
105
|
+
|
106
|
+
pNew_syms[dst_offset0] = p[0];
|
107
|
+
pNew_syms[dst_offset1] = p[1];
|
108
|
+
}
|
109
|
+
}
|
110
|
+
|
111
|
+
if (num_syms & 1)
|
112
|
+
{
|
113
|
+
uint c = ((p->m_freq) >> pass_shift) & 0xFF;
|
114
|
+
|
115
|
+
uint dst_offset = offsets[c];
|
116
|
+
offsets[c] = dst_offset + 1;
|
117
|
+
|
118
|
+
pNew_syms[dst_offset] = *p;
|
119
|
+
}
|
120
|
+
|
121
|
+
sym_freq* t = pCur_syms;
|
122
|
+
pCur_syms = pNew_syms;
|
123
|
+
pNew_syms = t;
|
124
|
+
}
|
125
|
+
|
126
|
+
#if LZHAM_ASSERTS_ENABLED
|
127
|
+
uint prev_freq = 0;
|
128
|
+
for (uint i = 0; i < num_syms; i++)
|
129
|
+
{
|
130
|
+
LZHAM_ASSERT(!(pCur_syms[i].m_freq < prev_freq));
|
131
|
+
prev_freq = pCur_syms[i].m_freq;
|
132
|
+
}
|
133
|
+
#endif
|
134
|
+
|
135
|
+
return pCur_syms;
|
136
|
+
}
|
137
|
+
|
138
|
+
struct huffman_work_tables
|
139
|
+
{
|
140
|
+
enum { cMaxInternalNodes = cHuffmanMaxSupportedSyms };
|
141
|
+
|
142
|
+
sym_freq syms0[cHuffmanMaxSupportedSyms + 1 + cMaxInternalNodes];
|
143
|
+
sym_freq syms1[cHuffmanMaxSupportedSyms + 1 + cMaxInternalNodes];
|
144
|
+
|
145
|
+
#if !USE_CALCULATE_MINIMUM_REDUNDANCY
|
146
|
+
uint16 queue[cMaxInternalNodes];
|
147
|
+
#endif
|
148
|
+
};
|
149
|
+
|
150
|
+
uint get_generate_huffman_codes_table_size()
|
151
|
+
{
|
152
|
+
return sizeof(huffman_work_tables);
|
153
|
+
}
|
154
|
+
|
155
|
+
// calculate_minimum_redundancy() written by Alistair Moffat, alistair@cs.mu.oz.au, Jyrki Katajainen, jyrki@diku.dk November 1996.
|
156
|
+
static void calculate_minimum_redundancy(int A[], int n)
|
157
|
+
{
|
158
|
+
int root; /* next root node to be used */
|
159
|
+
int leaf; /* next leaf to be used */
|
160
|
+
int next; /* next value to be assigned */
|
161
|
+
int avbl; /* number of available nodes */
|
162
|
+
int used; /* number of internal nodes */
|
163
|
+
int dpth; /* current depth of leaves */
|
164
|
+
|
165
|
+
/* check for pathological cases */
|
166
|
+
if (n==0) { return; }
|
167
|
+
if (n==1) { A[0] = 0; return; }
|
168
|
+
|
169
|
+
/* first pass, left to right, setting parent pointers */
|
170
|
+
A[0] += A[1]; root = 0; leaf = 2;
|
171
|
+
for (next=1; next < n-1; next++) {
|
172
|
+
/* select first item for a pairing */
|
173
|
+
if (leaf>=n || A[root]<A[leaf]) {
|
174
|
+
A[next] = A[root]; A[root++] = next;
|
175
|
+
} else
|
176
|
+
A[next] = A[leaf++];
|
177
|
+
|
178
|
+
/* add on the second item */
|
179
|
+
if (leaf>=n || (root<next && A[root]<A[leaf])) {
|
180
|
+
A[next] += A[root]; A[root++] = next;
|
181
|
+
} else
|
182
|
+
A[next] += A[leaf++];
|
183
|
+
}
|
184
|
+
|
185
|
+
/* second pass, right to left, setting internal depths */
|
186
|
+
A[n-2] = 0;
|
187
|
+
for (next=n-3; next>=0; next--)
|
188
|
+
A[next] = A[A[next]]+1;
|
189
|
+
|
190
|
+
/* third pass, right to left, setting leaf depths */
|
191
|
+
avbl = 1; used = dpth = 0; root = n-2; next = n-1;
|
192
|
+
while (avbl>0) {
|
193
|
+
while (root>=0 && A[root]==dpth) {
|
194
|
+
used++; root--;
|
195
|
+
}
|
196
|
+
while (avbl>used) {
|
197
|
+
A[next--] = dpth; avbl--;
|
198
|
+
}
|
199
|
+
avbl = 2*used; dpth++; used = 0;
|
200
|
+
}
|
201
|
+
}
|
202
|
+
|
203
|
+
bool generate_huffman_codes(void* pContext, uint num_syms, const uint16* pFreq, uint8* pCodesizes, uint& max_code_size, uint& total_freq_ret)
|
204
|
+
{
|
205
|
+
if ((!num_syms) || (num_syms > cHuffmanMaxSupportedSyms))
|
206
|
+
return false;
|
207
|
+
|
208
|
+
huffman_work_tables& state = *static_cast<huffman_work_tables*>(pContext);;
|
209
|
+
|
210
|
+
uint max_freq = 0;
|
211
|
+
uint total_freq = 0;
|
212
|
+
|
213
|
+
uint num_used_syms = 0;
|
214
|
+
for (uint i = 0; i < num_syms; i++)
|
215
|
+
{
|
216
|
+
uint freq = pFreq[i];
|
217
|
+
|
218
|
+
if (!freq)
|
219
|
+
pCodesizes[i] = 0;
|
220
|
+
else
|
221
|
+
{
|
222
|
+
total_freq += freq;
|
223
|
+
max_freq = math::maximum(max_freq, freq);
|
224
|
+
|
225
|
+
sym_freq& sf = state.syms0[num_used_syms];
|
226
|
+
sf.m_left = (uint16)i;
|
227
|
+
sf.m_right = UINT16_MAX;
|
228
|
+
sf.m_freq = freq;
|
229
|
+
num_used_syms++;
|
230
|
+
}
|
231
|
+
}
|
232
|
+
|
233
|
+
total_freq_ret = total_freq;
|
234
|
+
|
235
|
+
if (num_used_syms == 1)
|
236
|
+
{
|
237
|
+
pCodesizes[state.syms0[0].m_left] = 1;
|
238
|
+
return true;
|
239
|
+
}
|
240
|
+
|
241
|
+
sym_freq* syms = radix_sort_syms(num_used_syms, state.syms0, state.syms1);
|
242
|
+
|
243
|
+
int x[cHuffmanMaxSupportedSyms];
|
244
|
+
for (uint i = 0; i < num_used_syms; i++)
|
245
|
+
x[i] = syms[i].m_freq;
|
246
|
+
|
247
|
+
calculate_minimum_redundancy(x, num_used_syms);
|
248
|
+
|
249
|
+
uint max_len = 0;
|
250
|
+
for (uint i = 0; i < num_used_syms; i++)
|
251
|
+
{
|
252
|
+
uint len = x[i];
|
253
|
+
max_len = math::maximum(len, max_len);
|
254
|
+
pCodesizes[syms[i].m_left] = static_cast<uint8>(len);
|
255
|
+
}
|
256
|
+
max_code_size = max_len;
|
257
|
+
|
258
|
+
return true;
|
259
|
+
}
|
260
|
+
|
261
|
+
} // namespace lzham
|
262
|
+
|
@@ -0,0 +1,14 @@
|
|
1
|
+
// File: lzham_huffman_codes.h
|
2
|
+
// See Copyright Notice and license at the end of include/lzham.h
|
3
|
+
#pragma once
|
4
|
+
|
5
|
+
namespace lzham
|
6
|
+
{
|
7
|
+
//const uint cHuffmanMaxSupportedSyms = 600;
|
8
|
+
const uint cHuffmanMaxSupportedSyms = 1024;
|
9
|
+
|
10
|
+
uint get_generate_huffman_codes_table_size();
|
11
|
+
|
12
|
+
bool generate_huffman_codes(void* pContext, uint num_syms, const uint16* pFreq, uint8* pCodesizes, uint& max_code_size, uint& total_freq_ret);
|
13
|
+
|
14
|
+
} // namespace lzham
|