extlzham 0.0.1.PROTOTYPE3-x86-mingw32
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 +74 -0
- data/Rakefile +152 -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/constants.c +64 -0
- data/ext/decoder.c +313 -0
- data/ext/depend +5 -0
- data/ext/encoder.c +372 -0
- data/ext/error.c +80 -0
- data/ext/extconf.rb +29 -0
- data/ext/extlzham.c +34 -0
- data/ext/extlzham.h +62 -0
- data/gemstub.rb +22 -0
- data/lib/2.0/extlzham.so +0 -0
- data/lib/2.1/extlzham.so +0 -0
- data/lib/2.2/extlzham.so +0 -0
- data/lib/extlzham.rb +158 -0
- data/lib/extlzham/version.rb +5 -0
- data/test/test_extlzham.rb +35 -0
- metadata +156 -0
@@ -0,0 +1,1413 @@
|
|
1
|
+
// File: lzham_lzcomp_state.cpp
|
2
|
+
// See Copyright Notice and license at the end of include/lzham.h
|
3
|
+
#include "lzham_core.h"
|
4
|
+
#include "lzham_lzcomp_internal.h"
|
5
|
+
|
6
|
+
namespace lzham
|
7
|
+
{
|
8
|
+
static uint get_huge_match_code_len(uint len)
|
9
|
+
{
|
10
|
+
LZHAM_ASSERT((len > CLZBase::cMaxMatchLen) && (len <= CLZBase::cMaxHugeMatchLen));
|
11
|
+
len -= (CLZBase::cMaxMatchLen + 1);
|
12
|
+
|
13
|
+
if (len < 256)
|
14
|
+
return 1 + 8;
|
15
|
+
else if (len < (256 + 1024))
|
16
|
+
return 2 + 10;
|
17
|
+
else if (len < (256 + 1024 + 4096))
|
18
|
+
return 3 + 12;
|
19
|
+
else
|
20
|
+
return 3 + 16;
|
21
|
+
}
|
22
|
+
|
23
|
+
static uint get_huge_match_code_bits(uint len)
|
24
|
+
{
|
25
|
+
LZHAM_ASSERT((len > CLZBase::cMaxMatchLen) && (len <= CLZBase::cMaxHugeMatchLen));
|
26
|
+
len -= (CLZBase::cMaxMatchLen + 1);
|
27
|
+
|
28
|
+
uint c;
|
29
|
+
if (len < 256)
|
30
|
+
c = len;
|
31
|
+
else if (len < (256 + 1024))
|
32
|
+
{
|
33
|
+
uint r = (len - 256);
|
34
|
+
LZHAM_ASSERT(r <= 1023);
|
35
|
+
c = r | (2 << 10);
|
36
|
+
}
|
37
|
+
else if (len < (256 + 1024 + 4096))
|
38
|
+
{
|
39
|
+
uint r = (len - (256 + 1024));
|
40
|
+
LZHAM_ASSERT(r <= 4095);
|
41
|
+
c = r | (6 << 12);
|
42
|
+
}
|
43
|
+
else
|
44
|
+
{
|
45
|
+
uint r = (len - (256 + 1024 + 4096));
|
46
|
+
LZHAM_ASSERT(r <= 65535);
|
47
|
+
c = r | (7 << 16);
|
48
|
+
}
|
49
|
+
|
50
|
+
return c;
|
51
|
+
}
|
52
|
+
|
53
|
+
uint lzcompressor::lzdecision::get_match_dist(const state& cur_state) const
|
54
|
+
{
|
55
|
+
if (!is_match())
|
56
|
+
return 0;
|
57
|
+
else if (is_rep())
|
58
|
+
{
|
59
|
+
int index = -m_dist - 1;
|
60
|
+
LZHAM_ASSERT(index < CLZBase::cMatchHistSize);
|
61
|
+
return cur_state.m_match_hist[index];
|
62
|
+
}
|
63
|
+
else
|
64
|
+
return m_dist;
|
65
|
+
}
|
66
|
+
|
67
|
+
lzcompressor::state::state()
|
68
|
+
{
|
69
|
+
m_cur_ofs = 0;
|
70
|
+
m_cur_state = 0;
|
71
|
+
m_block_start_dict_ofs = 0;
|
72
|
+
|
73
|
+
m_match_hist[0] = 1;
|
74
|
+
m_match_hist[1] = 1;
|
75
|
+
m_match_hist[2] = 1;
|
76
|
+
m_match_hist[3] = 1;
|
77
|
+
}
|
78
|
+
|
79
|
+
void lzcompressor::state::clear()
|
80
|
+
{
|
81
|
+
m_cur_ofs = 0;
|
82
|
+
m_cur_state = 0;
|
83
|
+
m_block_start_dict_ofs = 0;
|
84
|
+
|
85
|
+
for (uint i = 0; i < 2; i++)
|
86
|
+
{
|
87
|
+
m_rep_len_table[i].clear();
|
88
|
+
m_large_len_table[i].clear();
|
89
|
+
}
|
90
|
+
m_main_table.clear();
|
91
|
+
m_dist_lsb_table.clear();
|
92
|
+
|
93
|
+
m_lit_table.clear();
|
94
|
+
m_delta_lit_table.clear();
|
95
|
+
|
96
|
+
m_match_hist[0] = 1;
|
97
|
+
m_match_hist[1] = 1;
|
98
|
+
m_match_hist[2] = 1;
|
99
|
+
m_match_hist[3] = 1;
|
100
|
+
}
|
101
|
+
|
102
|
+
void lzcompressor::state::reset()
|
103
|
+
{
|
104
|
+
m_cur_ofs = 0;
|
105
|
+
m_cur_state = 0;
|
106
|
+
m_block_start_dict_ofs = 0;
|
107
|
+
|
108
|
+
for (uint i = 0; i < LZHAM_ARRAY_SIZE(m_is_match_model); i++)
|
109
|
+
m_is_match_model[i].clear();
|
110
|
+
for (uint i = 0; i < LZHAM_ARRAY_SIZE(m_is_rep_model); i++)
|
111
|
+
m_is_rep_model[i].clear();
|
112
|
+
for (uint i = 0; i < LZHAM_ARRAY_SIZE(m_is_rep0_model); i++)
|
113
|
+
m_is_rep0_model[i].clear();
|
114
|
+
for (uint i = 0; i < LZHAM_ARRAY_SIZE(m_is_rep0_single_byte_model); i++)
|
115
|
+
m_is_rep0_single_byte_model[i].clear();
|
116
|
+
for (uint i = 0; i < LZHAM_ARRAY_SIZE(m_is_rep1_model); i++)
|
117
|
+
m_is_rep1_model[i].clear();
|
118
|
+
for (uint i = 0; i < LZHAM_ARRAY_SIZE(m_is_rep2_model); i++)
|
119
|
+
m_is_rep2_model[i].clear();
|
120
|
+
|
121
|
+
for (uint i = 0; i < 2; i++)
|
122
|
+
{
|
123
|
+
m_rep_len_table[i].reset();
|
124
|
+
m_large_len_table[i].reset();
|
125
|
+
}
|
126
|
+
m_main_table.reset();
|
127
|
+
m_dist_lsb_table.reset();
|
128
|
+
|
129
|
+
m_lit_table.reset();
|
130
|
+
m_delta_lit_table.reset();
|
131
|
+
|
132
|
+
m_match_hist[0] = 1;
|
133
|
+
m_match_hist[1] = 1;
|
134
|
+
m_match_hist[2] = 1;
|
135
|
+
m_match_hist[3] = 1;
|
136
|
+
}
|
137
|
+
|
138
|
+
bool lzcompressor::state::init(CLZBase& lzbase, uint table_max_update_interval, uint table_update_interval_slow_rate)
|
139
|
+
{
|
140
|
+
m_cur_ofs = 0;
|
141
|
+
m_cur_state = 0;
|
142
|
+
|
143
|
+
if (!m_rep_len_table[0].init2(true, CLZBase::cNumHugeMatchCodes + (CLZBase::cMaxMatchLen - CLZBase::cMinMatchLen + 1), table_max_update_interval, table_update_interval_slow_rate, NULL))
|
144
|
+
return false;
|
145
|
+
if (!m_rep_len_table[1].assign(m_rep_len_table[0]))
|
146
|
+
return false;
|
147
|
+
|
148
|
+
if (!m_large_len_table[0].init2(true, CLZBase::cNumHugeMatchCodes + CLZBase::cLZXNumSecondaryLengths, table_max_update_interval, table_update_interval_slow_rate, NULL))
|
149
|
+
return false;
|
150
|
+
if (!m_large_len_table[1].assign(m_large_len_table[0]))
|
151
|
+
return false;
|
152
|
+
|
153
|
+
if (!m_main_table.init2(true, CLZBase::cLZXNumSpecialLengths + (lzbase.m_num_lzx_slots - CLZBase::cLZXLowestUsableMatchSlot) * 8, table_max_update_interval, table_update_interval_slow_rate, NULL))
|
154
|
+
return false;
|
155
|
+
if (!m_dist_lsb_table.init2(true, 16, table_max_update_interval, table_update_interval_slow_rate, NULL))
|
156
|
+
return false;
|
157
|
+
|
158
|
+
if (!m_lit_table.init2(true, 256, table_max_update_interval, table_update_interval_slow_rate, NULL))
|
159
|
+
return false;
|
160
|
+
|
161
|
+
if (!m_delta_lit_table.init2(true, 256, table_max_update_interval, table_update_interval_slow_rate, NULL))
|
162
|
+
return false;
|
163
|
+
|
164
|
+
m_match_hist[0] = 1;
|
165
|
+
m_match_hist[1] = 1;
|
166
|
+
m_match_hist[2] = 1;
|
167
|
+
m_match_hist[3] = 1;
|
168
|
+
|
169
|
+
return true;
|
170
|
+
}
|
171
|
+
|
172
|
+
void lzcompressor::state_base::partial_advance(const lzdecision& lzdec)
|
173
|
+
{
|
174
|
+
if (lzdec.m_len == 0)
|
175
|
+
{
|
176
|
+
if (m_cur_state < 4) m_cur_state = 0; else if (m_cur_state < 10) m_cur_state -= 3; else m_cur_state -= 6;
|
177
|
+
}
|
178
|
+
else
|
179
|
+
{
|
180
|
+
if (lzdec.m_dist < 0)
|
181
|
+
{
|
182
|
+
int match_hist_index = -lzdec.m_dist - 1;
|
183
|
+
|
184
|
+
if (!match_hist_index)
|
185
|
+
{
|
186
|
+
if (lzdec.m_len == 1)
|
187
|
+
{
|
188
|
+
m_cur_state = (m_cur_state < CLZBase::cNumLitStates) ? 9 : 11;
|
189
|
+
}
|
190
|
+
else
|
191
|
+
{
|
192
|
+
m_cur_state = (m_cur_state < CLZBase::cNumLitStates) ? 8 : 11;
|
193
|
+
}
|
194
|
+
}
|
195
|
+
else
|
196
|
+
{
|
197
|
+
if (match_hist_index == 1)
|
198
|
+
{
|
199
|
+
std::swap(m_match_hist[0], m_match_hist[1]);
|
200
|
+
}
|
201
|
+
else if (match_hist_index == 2)
|
202
|
+
{
|
203
|
+
int dist = m_match_hist[2];
|
204
|
+
m_match_hist[2] = m_match_hist[1];
|
205
|
+
m_match_hist[1] = m_match_hist[0];
|
206
|
+
m_match_hist[0] = dist;
|
207
|
+
}
|
208
|
+
else
|
209
|
+
{
|
210
|
+
LZHAM_ASSERT(match_hist_index == 3);
|
211
|
+
|
212
|
+
int dist = m_match_hist[3];
|
213
|
+
m_match_hist[3] = m_match_hist[2];
|
214
|
+
m_match_hist[2] = m_match_hist[1];
|
215
|
+
m_match_hist[1] = m_match_hist[0];
|
216
|
+
m_match_hist[0] = dist;
|
217
|
+
}
|
218
|
+
|
219
|
+
m_cur_state = (m_cur_state < CLZBase::cNumLitStates) ? 8 : 11;
|
220
|
+
}
|
221
|
+
}
|
222
|
+
else
|
223
|
+
{
|
224
|
+
// full
|
225
|
+
LZHAM_ASSUME(CLZBase::cMatchHistSize == 4);
|
226
|
+
m_match_hist[3] = m_match_hist[2];
|
227
|
+
m_match_hist[2] = m_match_hist[1];
|
228
|
+
m_match_hist[1] = m_match_hist[0];
|
229
|
+
m_match_hist[0] = lzdec.m_dist;
|
230
|
+
|
231
|
+
m_cur_state = (m_cur_state < CLZBase::cNumLitStates) ? CLZBase::cNumLitStates : CLZBase::cNumLitStates + 3;
|
232
|
+
}
|
233
|
+
}
|
234
|
+
|
235
|
+
m_cur_ofs = lzdec.m_pos + lzdec.get_len();
|
236
|
+
}
|
237
|
+
|
238
|
+
uint lzcompressor::state::get_pred_char(const search_accelerator& dict, int pos, int backward_ofs) const
|
239
|
+
{
|
240
|
+
LZHAM_ASSERT(pos >= (int)m_block_start_dict_ofs);
|
241
|
+
int limit = pos - m_block_start_dict_ofs;
|
242
|
+
if (backward_ofs > limit)
|
243
|
+
return 0;
|
244
|
+
return dict[pos - backward_ofs];
|
245
|
+
}
|
246
|
+
|
247
|
+
bit_cost_t lzcompressor::state::get_cost(CLZBase& lzbase, const search_accelerator& dict, const lzdecision& lzdec) const
|
248
|
+
{
|
249
|
+
//const uint lit_pred0 = get_pred_char(dict, lzdec.m_pos, 1);
|
250
|
+
|
251
|
+
uint is_match_model_index = LZHAM_IS_MATCH_MODEL_INDEX(m_cur_state);
|
252
|
+
LZHAM_ASSERT(is_match_model_index < LZHAM_ARRAY_SIZE(m_is_match_model));
|
253
|
+
bit_cost_t cost = m_is_match_model[is_match_model_index].get_cost(lzdec.is_match());
|
254
|
+
|
255
|
+
if (!lzdec.is_match())
|
256
|
+
{
|
257
|
+
const uint lit = dict[lzdec.m_pos];
|
258
|
+
|
259
|
+
if (m_cur_state < CLZBase::cNumLitStates)
|
260
|
+
{
|
261
|
+
// literal
|
262
|
+
cost += m_lit_table.get_cost(lit);
|
263
|
+
}
|
264
|
+
else
|
265
|
+
{
|
266
|
+
// delta literal
|
267
|
+
const uint rep_lit0 = dict[(lzdec.m_pos - m_match_hist[0]) & dict.m_max_dict_size_mask];
|
268
|
+
|
269
|
+
uint delta_lit = rep_lit0 ^ lit;
|
270
|
+
|
271
|
+
cost += m_delta_lit_table.get_cost(delta_lit);
|
272
|
+
}
|
273
|
+
}
|
274
|
+
else
|
275
|
+
{
|
276
|
+
// match
|
277
|
+
if (lzdec.m_dist < 0)
|
278
|
+
{
|
279
|
+
// rep match
|
280
|
+
cost += m_is_rep_model[m_cur_state].get_cost(1);
|
281
|
+
|
282
|
+
int match_hist_index = -lzdec.m_dist - 1;
|
283
|
+
|
284
|
+
if (!match_hist_index)
|
285
|
+
{
|
286
|
+
// rep0 match
|
287
|
+
cost += m_is_rep0_model[m_cur_state].get_cost(1);
|
288
|
+
|
289
|
+
if (lzdec.m_len == 1)
|
290
|
+
{
|
291
|
+
// single byte rep0
|
292
|
+
cost += m_is_rep0_single_byte_model[m_cur_state].get_cost(1);
|
293
|
+
}
|
294
|
+
else
|
295
|
+
{
|
296
|
+
// normal rep0
|
297
|
+
cost += m_is_rep0_single_byte_model[m_cur_state].get_cost(0);
|
298
|
+
|
299
|
+
if (lzdec.m_len > CLZBase::cMaxMatchLen)
|
300
|
+
{
|
301
|
+
cost += get_huge_match_code_len(lzdec.m_len) + m_rep_len_table[m_cur_state >= CLZBase::cNumLitStates].get_cost((CLZBase::cMaxMatchLen + 1) - CLZBase::cMinMatchLen);
|
302
|
+
}
|
303
|
+
else
|
304
|
+
{
|
305
|
+
cost += m_rep_len_table[m_cur_state >= CLZBase::cNumLitStates].get_cost(lzdec.m_len - CLZBase::cMinMatchLen);
|
306
|
+
}
|
307
|
+
}
|
308
|
+
}
|
309
|
+
else
|
310
|
+
{
|
311
|
+
if (lzdec.m_len > CLZBase::cMaxMatchLen)
|
312
|
+
{
|
313
|
+
cost += get_huge_match_code_len(lzdec.m_len) + m_rep_len_table[m_cur_state >= CLZBase::cNumLitStates].get_cost((CLZBase::cMaxMatchLen + 1) - CLZBase::cMinMatchLen);
|
314
|
+
}
|
315
|
+
else
|
316
|
+
{
|
317
|
+
cost += m_rep_len_table[m_cur_state >= CLZBase::cNumLitStates].get_cost(lzdec.m_len - CLZBase::cMinMatchLen);
|
318
|
+
}
|
319
|
+
|
320
|
+
// rep1-rep3 match
|
321
|
+
cost += m_is_rep0_model[m_cur_state].get_cost(0);
|
322
|
+
|
323
|
+
if (match_hist_index == 1)
|
324
|
+
{
|
325
|
+
// rep1
|
326
|
+
cost += m_is_rep1_model[m_cur_state].get_cost(1);
|
327
|
+
}
|
328
|
+
else
|
329
|
+
{
|
330
|
+
cost += m_is_rep1_model[m_cur_state].get_cost(0);
|
331
|
+
|
332
|
+
if (match_hist_index == 2)
|
333
|
+
{
|
334
|
+
// rep2
|
335
|
+
cost += m_is_rep2_model[m_cur_state].get_cost(1);
|
336
|
+
}
|
337
|
+
else
|
338
|
+
{
|
339
|
+
LZHAM_ASSERT(match_hist_index == 3);
|
340
|
+
// rep3
|
341
|
+
cost += m_is_rep2_model[m_cur_state].get_cost(0);
|
342
|
+
}
|
343
|
+
}
|
344
|
+
}
|
345
|
+
}
|
346
|
+
else
|
347
|
+
{
|
348
|
+
cost += m_is_rep_model[m_cur_state].get_cost(0);
|
349
|
+
|
350
|
+
LZHAM_ASSERT(lzdec.m_len >= CLZBase::cMinMatchLen);
|
351
|
+
|
352
|
+
// full match
|
353
|
+
uint match_slot, match_extra;
|
354
|
+
lzbase.compute_lzx_position_slot(lzdec.m_dist, match_slot, match_extra);
|
355
|
+
|
356
|
+
uint match_low_sym = 0;
|
357
|
+
if (lzdec.m_len >= 9)
|
358
|
+
{
|
359
|
+
match_low_sym = 7;
|
360
|
+
if (lzdec.m_len > CLZBase::cMaxMatchLen)
|
361
|
+
{
|
362
|
+
cost += get_huge_match_code_len(lzdec.m_len) + m_large_len_table[m_cur_state >= CLZBase::cNumLitStates].get_cost((CLZBase::cMaxMatchLen + 1) - 9);
|
363
|
+
}
|
364
|
+
else
|
365
|
+
{
|
366
|
+
cost += m_large_len_table[m_cur_state >= CLZBase::cNumLitStates].get_cost(lzdec.m_len - 9);
|
367
|
+
}
|
368
|
+
}
|
369
|
+
else
|
370
|
+
match_low_sym = lzdec.m_len - 2;
|
371
|
+
|
372
|
+
uint match_high_sym = 0;
|
373
|
+
|
374
|
+
LZHAM_ASSERT(match_slot >= CLZBase::cLZXLowestUsableMatchSlot && (match_slot < lzbase.m_num_lzx_slots));
|
375
|
+
match_high_sym = match_slot - CLZBase::cLZXLowestUsableMatchSlot;
|
376
|
+
|
377
|
+
uint main_sym = match_low_sym | (match_high_sym << 3);
|
378
|
+
|
379
|
+
cost += m_main_table.get_cost(CLZBase::cLZXNumSpecialLengths + main_sym);
|
380
|
+
|
381
|
+
uint num_extra_bits = lzbase.m_lzx_position_extra_bits[match_slot];
|
382
|
+
if (num_extra_bits < 3)
|
383
|
+
cost += convert_to_scaled_bitcost(num_extra_bits);
|
384
|
+
else
|
385
|
+
{
|
386
|
+
if (num_extra_bits > 4)
|
387
|
+
cost += convert_to_scaled_bitcost(num_extra_bits - 4);
|
388
|
+
|
389
|
+
cost += m_dist_lsb_table.get_cost(match_extra & 15);
|
390
|
+
}
|
391
|
+
}
|
392
|
+
}
|
393
|
+
|
394
|
+
return cost;
|
395
|
+
}
|
396
|
+
|
397
|
+
bit_cost_t lzcompressor::state::get_len2_match_cost(CLZBase& lzbase, uint dict_pos, uint len2_match_dist, uint is_match_model_index)
|
398
|
+
{
|
399
|
+
LZHAM_NOTE_UNUSED(dict_pos);
|
400
|
+
|
401
|
+
bit_cost_t cost = m_is_match_model[is_match_model_index].get_cost(1);
|
402
|
+
|
403
|
+
cost += m_is_rep_model[m_cur_state].get_cost(0);
|
404
|
+
|
405
|
+
// full match
|
406
|
+
uint match_slot, match_extra;
|
407
|
+
lzbase.compute_lzx_position_slot(len2_match_dist, match_slot, match_extra);
|
408
|
+
|
409
|
+
const uint match_len = 2;
|
410
|
+
uint match_low_sym = match_len - 2;
|
411
|
+
|
412
|
+
uint match_high_sym = 0;
|
413
|
+
|
414
|
+
LZHAM_ASSERT(match_slot >= CLZBase::cLZXLowestUsableMatchSlot && (match_slot < lzbase.m_num_lzx_slots));
|
415
|
+
match_high_sym = match_slot - CLZBase::cLZXLowestUsableMatchSlot;
|
416
|
+
|
417
|
+
uint main_sym = match_low_sym | (match_high_sym << 3);
|
418
|
+
|
419
|
+
cost += m_main_table.get_cost(CLZBase::cLZXNumSpecialLengths + main_sym);
|
420
|
+
|
421
|
+
uint num_extra_bits = lzbase.m_lzx_position_extra_bits[match_slot];
|
422
|
+
if (num_extra_bits < 3)
|
423
|
+
cost += convert_to_scaled_bitcost(num_extra_bits);
|
424
|
+
else
|
425
|
+
{
|
426
|
+
if (num_extra_bits > 4)
|
427
|
+
cost += convert_to_scaled_bitcost(num_extra_bits - 4);
|
428
|
+
|
429
|
+
cost += m_dist_lsb_table.get_cost(match_extra & 15);
|
430
|
+
}
|
431
|
+
|
432
|
+
return cost;
|
433
|
+
}
|
434
|
+
|
435
|
+
bit_cost_t lzcompressor::state::get_lit_cost(CLZBase& lzbase, const search_accelerator& dict, uint dict_pos, uint lit_pred0, uint is_match_model_index) const
|
436
|
+
{
|
437
|
+
LZHAM_NOTE_UNUSED(lzbase);
|
438
|
+
LZHAM_NOTE_UNUSED(lit_pred0);
|
439
|
+
|
440
|
+
bit_cost_t cost = m_is_match_model[is_match_model_index].get_cost(0);
|
441
|
+
|
442
|
+
const uint lit = dict[dict_pos];
|
443
|
+
|
444
|
+
if (m_cur_state < CLZBase::cNumLitStates)
|
445
|
+
{
|
446
|
+
// literal
|
447
|
+
cost += m_lit_table.get_cost(lit);
|
448
|
+
}
|
449
|
+
else
|
450
|
+
{
|
451
|
+
// delta literal
|
452
|
+
const uint rep_lit0 = dict[(dict_pos - m_match_hist[0]) & dict.m_max_dict_size_mask];
|
453
|
+
|
454
|
+
uint delta_lit = rep_lit0 ^ lit;
|
455
|
+
|
456
|
+
cost += m_delta_lit_table.get_cost(delta_lit);
|
457
|
+
}
|
458
|
+
|
459
|
+
return cost;
|
460
|
+
}
|
461
|
+
|
462
|
+
void lzcompressor::state::get_rep_match_costs(uint dict_pos, bit_cost_t *pBitcosts, uint match_hist_index, int min_len, int max_len, uint is_match_model_index) const
|
463
|
+
{
|
464
|
+
LZHAM_NOTE_UNUSED(dict_pos);
|
465
|
+
// match
|
466
|
+
const quasi_adaptive_huffman_data_model &rep_len_table = m_rep_len_table[m_cur_state >= CLZBase::cNumLitStates];
|
467
|
+
|
468
|
+
bit_cost_t base_cost = m_is_match_model[is_match_model_index].get_cost(1);
|
469
|
+
|
470
|
+
base_cost += m_is_rep_model[m_cur_state].get_cost(1);
|
471
|
+
|
472
|
+
if (!match_hist_index)
|
473
|
+
{
|
474
|
+
// rep0 match
|
475
|
+
base_cost += m_is_rep0_model[m_cur_state].get_cost(1);
|
476
|
+
}
|
477
|
+
else
|
478
|
+
{
|
479
|
+
// rep1-rep3 matches
|
480
|
+
base_cost += m_is_rep0_model[m_cur_state].get_cost(0);
|
481
|
+
|
482
|
+
if (match_hist_index == 1)
|
483
|
+
{
|
484
|
+
// rep1
|
485
|
+
base_cost += m_is_rep1_model[m_cur_state].get_cost(1);
|
486
|
+
}
|
487
|
+
else
|
488
|
+
{
|
489
|
+
base_cost += m_is_rep1_model[m_cur_state].get_cost(0);
|
490
|
+
|
491
|
+
if (match_hist_index == 2)
|
492
|
+
{
|
493
|
+
// rep2
|
494
|
+
base_cost += m_is_rep2_model[m_cur_state].get_cost(1);
|
495
|
+
}
|
496
|
+
else
|
497
|
+
{
|
498
|
+
// rep3
|
499
|
+
base_cost += m_is_rep2_model[m_cur_state].get_cost(0);
|
500
|
+
}
|
501
|
+
}
|
502
|
+
}
|
503
|
+
|
504
|
+
// rep match
|
505
|
+
if (!match_hist_index)
|
506
|
+
{
|
507
|
+
if (min_len == 1)
|
508
|
+
{
|
509
|
+
// single byte rep0
|
510
|
+
pBitcosts[1] = base_cost + m_is_rep0_single_byte_model[m_cur_state].get_cost(1);
|
511
|
+
min_len++;
|
512
|
+
}
|
513
|
+
|
514
|
+
bit_cost_t rep0_match_base_cost = base_cost + m_is_rep0_single_byte_model[m_cur_state].get_cost(0);
|
515
|
+
for (int match_len = min_len; match_len <= max_len; match_len++)
|
516
|
+
{
|
517
|
+
// normal rep0
|
518
|
+
if (match_len > CLZBase::cMaxMatchLen)
|
519
|
+
{
|
520
|
+
pBitcosts[match_len] = get_huge_match_code_len(match_len) + rep0_match_base_cost + rep_len_table.get_cost((CLZBase::cMaxMatchLen + 1) - CLZBase::cMinMatchLen);
|
521
|
+
}
|
522
|
+
else
|
523
|
+
{
|
524
|
+
pBitcosts[match_len] = rep0_match_base_cost + rep_len_table.get_cost(match_len - CLZBase::cMinMatchLen);
|
525
|
+
}
|
526
|
+
}
|
527
|
+
}
|
528
|
+
else
|
529
|
+
{
|
530
|
+
for (int match_len = min_len; match_len <= max_len; match_len++)
|
531
|
+
{
|
532
|
+
if (match_len > CLZBase::cMaxMatchLen)
|
533
|
+
{
|
534
|
+
pBitcosts[match_len] = get_huge_match_code_len(match_len) + base_cost + rep_len_table.get_cost((CLZBase::cMaxMatchLen + 1) - CLZBase::cMinMatchLen);
|
535
|
+
}
|
536
|
+
else
|
537
|
+
{
|
538
|
+
pBitcosts[match_len] = base_cost + rep_len_table.get_cost(match_len - CLZBase::cMinMatchLen);
|
539
|
+
}
|
540
|
+
}
|
541
|
+
}
|
542
|
+
}
|
543
|
+
|
544
|
+
void lzcompressor::state::get_full_match_costs(CLZBase& lzbase, uint dict_pos, bit_cost_t *pBitcosts, uint match_dist, int min_len, int max_len, uint is_match_model_index) const
|
545
|
+
{
|
546
|
+
LZHAM_NOTE_UNUSED(dict_pos);
|
547
|
+
LZHAM_ASSERT(min_len >= CLZBase::cMinMatchLen);
|
548
|
+
|
549
|
+
bit_cost_t cost = m_is_match_model[is_match_model_index].get_cost(1);
|
550
|
+
|
551
|
+
cost += m_is_rep_model[m_cur_state].get_cost(0);
|
552
|
+
|
553
|
+
uint match_slot, match_extra;
|
554
|
+
lzbase.compute_lzx_position_slot(match_dist, match_slot, match_extra);
|
555
|
+
LZHAM_ASSERT(match_slot >= CLZBase::cLZXLowestUsableMatchSlot && (match_slot < lzbase.m_num_lzx_slots));
|
556
|
+
|
557
|
+
uint num_extra_bits = lzbase.m_lzx_position_extra_bits[match_slot];
|
558
|
+
|
559
|
+
if (num_extra_bits < 3)
|
560
|
+
cost += convert_to_scaled_bitcost(num_extra_bits);
|
561
|
+
else
|
562
|
+
{
|
563
|
+
if (num_extra_bits > 4)
|
564
|
+
cost += convert_to_scaled_bitcost(num_extra_bits - 4);
|
565
|
+
|
566
|
+
cost += m_dist_lsb_table.get_cost(match_extra & 15);
|
567
|
+
}
|
568
|
+
|
569
|
+
uint match_high_sym = match_slot - CLZBase::cLZXLowestUsableMatchSlot;
|
570
|
+
|
571
|
+
const quasi_adaptive_huffman_data_model &large_len_table = m_large_len_table[m_cur_state >= CLZBase::cNumLitStates];
|
572
|
+
|
573
|
+
for (int match_len = min_len; match_len <= max_len; match_len++)
|
574
|
+
{
|
575
|
+
bit_cost_t len_cost = cost;
|
576
|
+
|
577
|
+
uint match_low_sym = 0;
|
578
|
+
if (match_len >= 9)
|
579
|
+
{
|
580
|
+
match_low_sym = 7;
|
581
|
+
if (match_len > CLZBase::cMaxMatchLen)
|
582
|
+
{
|
583
|
+
len_cost += get_huge_match_code_len(match_len) + large_len_table.get_cost((CLZBase::cMaxMatchLen + 1) - 9);
|
584
|
+
}
|
585
|
+
else
|
586
|
+
{
|
587
|
+
len_cost += large_len_table.get_cost(match_len - 9);
|
588
|
+
}
|
589
|
+
}
|
590
|
+
else
|
591
|
+
match_low_sym = match_len - 2;
|
592
|
+
|
593
|
+
uint main_sym = match_low_sym | (match_high_sym << 3);
|
594
|
+
|
595
|
+
pBitcosts[match_len] = len_cost + m_main_table.get_cost(CLZBase::cLZXNumSpecialLengths + main_sym);
|
596
|
+
}
|
597
|
+
}
|
598
|
+
|
599
|
+
bool lzcompressor::state::advance(CLZBase& lzbase, const search_accelerator& dict, const lzdecision& lzdec)
|
600
|
+
{
|
601
|
+
//const uint lit_pred0 = get_pred_char(dict, lzdec.m_pos, 1);
|
602
|
+
|
603
|
+
uint is_match_model_index = LZHAM_IS_MATCH_MODEL_INDEX(m_cur_state);
|
604
|
+
m_is_match_model[is_match_model_index].update(lzdec.is_match());
|
605
|
+
|
606
|
+
if (!lzdec.is_match())
|
607
|
+
{
|
608
|
+
const uint lit = dict[lzdec.m_pos];
|
609
|
+
|
610
|
+
if (m_cur_state < CLZBase::cNumLitStates)
|
611
|
+
{
|
612
|
+
// literal
|
613
|
+
if (!m_lit_table.update_sym(lit)) return false;
|
614
|
+
}
|
615
|
+
else
|
616
|
+
{
|
617
|
+
// delta literal
|
618
|
+
const uint rep_lit0 = dict[(lzdec.m_pos - m_match_hist[0]) & dict.m_max_dict_size_mask];
|
619
|
+
|
620
|
+
uint delta_lit = rep_lit0 ^ lit;
|
621
|
+
|
622
|
+
if (!m_delta_lit_table.update_sym(delta_lit)) return false;
|
623
|
+
}
|
624
|
+
|
625
|
+
if (m_cur_state < 4) m_cur_state = 0; else if (m_cur_state < 10) m_cur_state -= 3; else m_cur_state -= 6;
|
626
|
+
}
|
627
|
+
else
|
628
|
+
{
|
629
|
+
// match
|
630
|
+
if (lzdec.m_dist < 0)
|
631
|
+
{
|
632
|
+
// rep match
|
633
|
+
m_is_rep_model[m_cur_state].update(1);
|
634
|
+
|
635
|
+
int match_hist_index = -lzdec.m_dist - 1;
|
636
|
+
|
637
|
+
if (!match_hist_index)
|
638
|
+
{
|
639
|
+
// rep0 match
|
640
|
+
m_is_rep0_model[m_cur_state].update(1);
|
641
|
+
|
642
|
+
if (lzdec.m_len == 1)
|
643
|
+
{
|
644
|
+
// single byte rep0
|
645
|
+
m_is_rep0_single_byte_model[m_cur_state].update(1);
|
646
|
+
|
647
|
+
m_cur_state = (m_cur_state < CLZBase::cNumLitStates) ? 9 : 11;
|
648
|
+
}
|
649
|
+
else
|
650
|
+
{
|
651
|
+
// normal rep0
|
652
|
+
m_is_rep0_single_byte_model[m_cur_state].update(0);
|
653
|
+
|
654
|
+
if (lzdec.m_len > CLZBase::cMaxMatchLen)
|
655
|
+
{
|
656
|
+
if (!m_rep_len_table[m_cur_state >= CLZBase::cNumLitStates].update_sym((CLZBase::cMaxMatchLen + 1) - CLZBase::cMinMatchLen)) return false;
|
657
|
+
}
|
658
|
+
else
|
659
|
+
{
|
660
|
+
if (!m_rep_len_table[m_cur_state >= CLZBase::cNumLitStates].update_sym(lzdec.m_len - CLZBase::cMinMatchLen)) return false;
|
661
|
+
}
|
662
|
+
|
663
|
+
m_cur_state = (m_cur_state < CLZBase::cNumLitStates) ? 8 : 11;
|
664
|
+
}
|
665
|
+
}
|
666
|
+
else
|
667
|
+
{
|
668
|
+
// rep1-rep3 match
|
669
|
+
m_is_rep0_model[m_cur_state].update(0);
|
670
|
+
|
671
|
+
if (lzdec.m_len > CLZBase::cMaxMatchLen)
|
672
|
+
{
|
673
|
+
if (!m_rep_len_table[m_cur_state >= CLZBase::cNumLitStates].update_sym((CLZBase::cMaxMatchLen + 1) - CLZBase::cMinMatchLen)) return false;
|
674
|
+
}
|
675
|
+
else
|
676
|
+
{
|
677
|
+
if (!m_rep_len_table[m_cur_state >= CLZBase::cNumLitStates].update_sym(lzdec.m_len - CLZBase::cMinMatchLen)) return false;
|
678
|
+
}
|
679
|
+
|
680
|
+
if (match_hist_index == 1)
|
681
|
+
{
|
682
|
+
// rep1
|
683
|
+
m_is_rep1_model[m_cur_state].update(1);
|
684
|
+
|
685
|
+
std::swap(m_match_hist[0], m_match_hist[1]);
|
686
|
+
}
|
687
|
+
else
|
688
|
+
{
|
689
|
+
m_is_rep1_model[m_cur_state].update(0);
|
690
|
+
|
691
|
+
if (match_hist_index == 2)
|
692
|
+
{
|
693
|
+
// rep2
|
694
|
+
m_is_rep2_model[m_cur_state].update(1);
|
695
|
+
|
696
|
+
int dist = m_match_hist[2];
|
697
|
+
m_match_hist[2] = m_match_hist[1];
|
698
|
+
m_match_hist[1] = m_match_hist[0];
|
699
|
+
m_match_hist[0] = dist;
|
700
|
+
}
|
701
|
+
else
|
702
|
+
{
|
703
|
+
// rep3
|
704
|
+
m_is_rep2_model[m_cur_state].update(0);
|
705
|
+
|
706
|
+
int dist = m_match_hist[3];
|
707
|
+
m_match_hist[3] = m_match_hist[2];
|
708
|
+
m_match_hist[2] = m_match_hist[1];
|
709
|
+
m_match_hist[1] = m_match_hist[0];
|
710
|
+
m_match_hist[0] = dist;
|
711
|
+
}
|
712
|
+
}
|
713
|
+
|
714
|
+
m_cur_state = (m_cur_state < CLZBase::cNumLitStates) ? 8 : 11;
|
715
|
+
}
|
716
|
+
}
|
717
|
+
else
|
718
|
+
{
|
719
|
+
m_is_rep_model[m_cur_state].update(0);
|
720
|
+
|
721
|
+
LZHAM_ASSERT(lzdec.m_len >= CLZBase::cMinMatchLen);
|
722
|
+
|
723
|
+
// full match
|
724
|
+
uint match_slot, match_extra;
|
725
|
+
lzbase.compute_lzx_position_slot(lzdec.m_dist, match_slot, match_extra);
|
726
|
+
|
727
|
+
uint match_low_sym = 0;
|
728
|
+
int large_len_sym = -1;
|
729
|
+
if (lzdec.m_len >= 9)
|
730
|
+
{
|
731
|
+
match_low_sym = 7;
|
732
|
+
|
733
|
+
large_len_sym = lzdec.m_len - 9;
|
734
|
+
}
|
735
|
+
else
|
736
|
+
match_low_sym = lzdec.m_len - 2;
|
737
|
+
|
738
|
+
uint match_high_sym = 0;
|
739
|
+
|
740
|
+
LZHAM_ASSERT(match_slot >= CLZBase::cLZXLowestUsableMatchSlot && (match_slot < lzbase.m_num_lzx_slots));
|
741
|
+
match_high_sym = match_slot - CLZBase::cLZXLowestUsableMatchSlot;
|
742
|
+
|
743
|
+
uint main_sym = match_low_sym | (match_high_sym << 3);
|
744
|
+
|
745
|
+
if (!m_main_table.update_sym(CLZBase::cLZXNumSpecialLengths + main_sym)) return false;
|
746
|
+
|
747
|
+
if (large_len_sym >= 0)
|
748
|
+
{
|
749
|
+
if (lzdec.m_len > CLZBase::cMaxMatchLen)
|
750
|
+
{
|
751
|
+
if (!m_large_len_table[m_cur_state >= CLZBase::cNumLitStates].update_sym((CLZBase::cMaxMatchLen + 1) - 9)) return false;
|
752
|
+
}
|
753
|
+
else
|
754
|
+
{
|
755
|
+
if (!m_large_len_table[m_cur_state >= CLZBase::cNumLitStates].update_sym(large_len_sym)) return false;
|
756
|
+
}
|
757
|
+
}
|
758
|
+
|
759
|
+
uint num_extra_bits = lzbase.m_lzx_position_extra_bits[match_slot];
|
760
|
+
if (num_extra_bits >= 3)
|
761
|
+
{
|
762
|
+
if (!m_dist_lsb_table.update_sym(match_extra & 15)) return false;
|
763
|
+
}
|
764
|
+
|
765
|
+
update_match_hist(lzdec.m_dist);
|
766
|
+
|
767
|
+
m_cur_state = (m_cur_state < CLZBase::cNumLitStates) ? CLZBase::cNumLitStates : CLZBase::cNumLitStates + 3;
|
768
|
+
}
|
769
|
+
}
|
770
|
+
|
771
|
+
m_cur_ofs = lzdec.m_pos + lzdec.get_len();
|
772
|
+
return true;
|
773
|
+
}
|
774
|
+
|
775
|
+
bool lzcompressor::state::encode(symbol_codec& codec, CLZBase& lzbase, const search_accelerator& dict, const lzdecision& lzdec)
|
776
|
+
{
|
777
|
+
//const uint lit_pred0 = get_pred_char(dict, lzdec.m_pos, 1);
|
778
|
+
|
779
|
+
uint is_match_model_index = LZHAM_IS_MATCH_MODEL_INDEX(m_cur_state);
|
780
|
+
if (!codec.encode(lzdec.is_match(), m_is_match_model[is_match_model_index])) return false;
|
781
|
+
|
782
|
+
if (!lzdec.is_match())
|
783
|
+
{
|
784
|
+
const uint lit = dict[lzdec.m_pos];
|
785
|
+
|
786
|
+
#ifdef LZHAM_LZDEBUG
|
787
|
+
if (!codec.encode_bits(lit, 8)) return false;
|
788
|
+
#endif
|
789
|
+
|
790
|
+
if (m_cur_state < CLZBase::cNumLitStates)
|
791
|
+
{
|
792
|
+
// literal
|
793
|
+
if (!codec.encode(lit, m_lit_table)) return false;
|
794
|
+
}
|
795
|
+
else
|
796
|
+
{
|
797
|
+
// delta literal
|
798
|
+
const uint rep_lit0 = dict[(lzdec.m_pos - m_match_hist[0]) & dict.m_max_dict_size_mask];
|
799
|
+
|
800
|
+
uint delta_lit = rep_lit0 ^ lit;
|
801
|
+
|
802
|
+
#ifdef LZHAM_LZDEBUG
|
803
|
+
if (!codec.encode_bits(rep_lit0, 8)) return false;
|
804
|
+
#endif
|
805
|
+
|
806
|
+
if (!codec.encode(delta_lit, m_delta_lit_table)) return false;
|
807
|
+
}
|
808
|
+
|
809
|
+
if (m_cur_state < 4) m_cur_state = 0; else if (m_cur_state < 10) m_cur_state -= 3; else m_cur_state -= 6;
|
810
|
+
}
|
811
|
+
else
|
812
|
+
{
|
813
|
+
// match
|
814
|
+
if (lzdec.m_dist < 0)
|
815
|
+
{
|
816
|
+
// rep match
|
817
|
+
if (!codec.encode(1, m_is_rep_model[m_cur_state])) return false;
|
818
|
+
|
819
|
+
int match_hist_index = -lzdec.m_dist - 1;
|
820
|
+
|
821
|
+
if (!match_hist_index)
|
822
|
+
{
|
823
|
+
// rep0 match
|
824
|
+
if (!codec.encode(1, m_is_rep0_model[m_cur_state])) return false;
|
825
|
+
|
826
|
+
if (lzdec.m_len == 1)
|
827
|
+
{
|
828
|
+
// single byte rep0
|
829
|
+
if (!codec.encode(1, m_is_rep0_single_byte_model[m_cur_state])) return false;
|
830
|
+
|
831
|
+
m_cur_state = (m_cur_state < CLZBase::cNumLitStates) ? 9 : 11;
|
832
|
+
}
|
833
|
+
else
|
834
|
+
{
|
835
|
+
// normal rep0
|
836
|
+
if (!codec.encode(0, m_is_rep0_single_byte_model[m_cur_state])) return false;
|
837
|
+
|
838
|
+
if (lzdec.m_len > CLZBase::cMaxMatchLen)
|
839
|
+
{
|
840
|
+
if (!codec.encode((CLZBase::cMaxMatchLen + 1) - CLZBase::cMinMatchLen, m_rep_len_table[m_cur_state >= CLZBase::cNumLitStates])) return false;
|
841
|
+
if (!codec.encode_bits(get_huge_match_code_bits(lzdec.m_len), get_huge_match_code_len(lzdec.m_len))) return false;
|
842
|
+
}
|
843
|
+
else
|
844
|
+
{
|
845
|
+
if (!codec.encode(lzdec.m_len - CLZBase::cMinMatchLen, m_rep_len_table[m_cur_state >= CLZBase::cNumLitStates])) return false;
|
846
|
+
}
|
847
|
+
|
848
|
+
m_cur_state = (m_cur_state < CLZBase::cNumLitStates) ? 8 : 11;
|
849
|
+
}
|
850
|
+
}
|
851
|
+
else
|
852
|
+
{
|
853
|
+
// rep1-rep3 match
|
854
|
+
if (!codec.encode(0, m_is_rep0_model[m_cur_state])) return false;
|
855
|
+
|
856
|
+
if (lzdec.m_len > CLZBase::cMaxMatchLen)
|
857
|
+
{
|
858
|
+
if (!codec.encode((CLZBase::cMaxMatchLen + 1) - CLZBase::cMinMatchLen, m_rep_len_table[m_cur_state >= CLZBase::cNumLitStates])) return false;
|
859
|
+
if (!codec.encode_bits(get_huge_match_code_bits(lzdec.m_len), get_huge_match_code_len(lzdec.m_len))) return false;
|
860
|
+
}
|
861
|
+
else
|
862
|
+
{
|
863
|
+
if (!codec.encode(lzdec.m_len - CLZBase::cMinMatchLen, m_rep_len_table[m_cur_state >= CLZBase::cNumLitStates])) return false;
|
864
|
+
}
|
865
|
+
|
866
|
+
if (match_hist_index == 1)
|
867
|
+
{
|
868
|
+
// rep1
|
869
|
+
if (!codec.encode(1, m_is_rep1_model[m_cur_state])) return false;
|
870
|
+
|
871
|
+
std::swap(m_match_hist[0], m_match_hist[1]);
|
872
|
+
}
|
873
|
+
else
|
874
|
+
{
|
875
|
+
if (!codec.encode(0, m_is_rep1_model[m_cur_state])) return false;
|
876
|
+
|
877
|
+
if (match_hist_index == 2)
|
878
|
+
{
|
879
|
+
// rep2
|
880
|
+
if (!codec.encode(1, m_is_rep2_model[m_cur_state])) return false;
|
881
|
+
|
882
|
+
int dist = m_match_hist[2];
|
883
|
+
m_match_hist[2] = m_match_hist[1];
|
884
|
+
m_match_hist[1] = m_match_hist[0];
|
885
|
+
m_match_hist[0] = dist;
|
886
|
+
}
|
887
|
+
else
|
888
|
+
{
|
889
|
+
// rep3
|
890
|
+
if (!codec.encode(0, m_is_rep2_model[m_cur_state])) return false;
|
891
|
+
|
892
|
+
int dist = m_match_hist[3];
|
893
|
+
m_match_hist[3] = m_match_hist[2];
|
894
|
+
m_match_hist[2] = m_match_hist[1];
|
895
|
+
m_match_hist[1] = m_match_hist[0];
|
896
|
+
m_match_hist[0] = dist;
|
897
|
+
}
|
898
|
+
}
|
899
|
+
|
900
|
+
m_cur_state = (m_cur_state < CLZBase::cNumLitStates) ? 8 : 11;
|
901
|
+
}
|
902
|
+
}
|
903
|
+
else
|
904
|
+
{
|
905
|
+
if (!codec.encode(0, m_is_rep_model[m_cur_state])) return false;
|
906
|
+
|
907
|
+
LZHAM_ASSERT(lzdec.m_len >= CLZBase::cMinMatchLen);
|
908
|
+
|
909
|
+
// full match
|
910
|
+
uint match_slot, match_extra;
|
911
|
+
lzbase.compute_lzx_position_slot(lzdec.m_dist, match_slot, match_extra);
|
912
|
+
|
913
|
+
uint match_low_sym = 0;
|
914
|
+
int large_len_sym = -1;
|
915
|
+
if (lzdec.m_len >= 9)
|
916
|
+
{
|
917
|
+
match_low_sym = 7;
|
918
|
+
|
919
|
+
large_len_sym = lzdec.m_len - 9;
|
920
|
+
}
|
921
|
+
else
|
922
|
+
match_low_sym = lzdec.m_len - 2;
|
923
|
+
|
924
|
+
uint match_high_sym = 0;
|
925
|
+
|
926
|
+
LZHAM_ASSERT(match_slot >= CLZBase::cLZXLowestUsableMatchSlot && (match_slot < lzbase.m_num_lzx_slots));
|
927
|
+
match_high_sym = match_slot - CLZBase::cLZXLowestUsableMatchSlot;
|
928
|
+
|
929
|
+
uint main_sym = match_low_sym | (match_high_sym << 3);
|
930
|
+
|
931
|
+
if (!codec.encode(CLZBase::cLZXNumSpecialLengths + main_sym, m_main_table)) return false;
|
932
|
+
|
933
|
+
if (large_len_sym >= 0)
|
934
|
+
{
|
935
|
+
if (lzdec.m_len > CLZBase::cMaxMatchLen)
|
936
|
+
{
|
937
|
+
if (!codec.encode((CLZBase::cMaxMatchLen + 1) - 9, m_large_len_table[m_cur_state >= CLZBase::cNumLitStates])) return false;
|
938
|
+
if (!codec.encode_bits(get_huge_match_code_bits(lzdec.m_len), get_huge_match_code_len(lzdec.m_len))) return false;
|
939
|
+
}
|
940
|
+
else
|
941
|
+
{
|
942
|
+
if (!codec.encode(large_len_sym, m_large_len_table[m_cur_state >= CLZBase::cNumLitStates])) return false;
|
943
|
+
}
|
944
|
+
}
|
945
|
+
|
946
|
+
uint num_extra_bits = lzbase.m_lzx_position_extra_bits[match_slot];
|
947
|
+
if (num_extra_bits < 3)
|
948
|
+
{
|
949
|
+
if (!codec.encode_bits(match_extra, num_extra_bits)) return false;
|
950
|
+
}
|
951
|
+
else
|
952
|
+
{
|
953
|
+
if (num_extra_bits > 4)
|
954
|
+
{
|
955
|
+
if (!codec.encode_bits((match_extra >> 4), num_extra_bits - 4)) return false;
|
956
|
+
}
|
957
|
+
|
958
|
+
if (!codec.encode(match_extra & 15, m_dist_lsb_table)) return false;
|
959
|
+
}
|
960
|
+
|
961
|
+
update_match_hist(lzdec.m_dist);
|
962
|
+
|
963
|
+
m_cur_state = (m_cur_state < CLZBase::cNumLitStates) ? CLZBase::cNumLitStates : CLZBase::cNumLitStates + 3;
|
964
|
+
}
|
965
|
+
|
966
|
+
#ifdef LZHAM_LZDEBUG
|
967
|
+
if (!codec.encode_bits(m_match_hist[0], 29)) return false;
|
968
|
+
#endif
|
969
|
+
}
|
970
|
+
|
971
|
+
m_cur_ofs = lzdec.m_pos + lzdec.get_len();
|
972
|
+
return true;
|
973
|
+
}
|
974
|
+
|
975
|
+
void lzcompressor::state::print(symbol_codec& codec, CLZBase& lzbase, const search_accelerator& dict, const lzdecision& lzdec)
|
976
|
+
{
|
977
|
+
LZHAM_NOTE_UNUSED(codec), LZHAM_NOTE_UNUSED(lzbase), LZHAM_NOTE_UNUSED(dict);
|
978
|
+
|
979
|
+
const uint lit_pred0 = get_pred_char(dict, lzdec.m_pos, 1);
|
980
|
+
|
981
|
+
uint is_match_model_index = LZHAM_IS_MATCH_MODEL_INDEX(m_cur_state);
|
982
|
+
|
983
|
+
printf(" pos: %u, state: %u, match_pred: %u, is_match_model_index: %u, is_match: %u, cost: %f\n",
|
984
|
+
lzdec.m_pos,
|
985
|
+
m_cur_state,
|
986
|
+
lit_pred0, is_match_model_index, lzdec.is_match(), get_cost(lzbase, dict, lzdec) / (float)cBitCostScale);
|
987
|
+
|
988
|
+
if (!lzdec.is_match())
|
989
|
+
{
|
990
|
+
const uint lit = dict[lzdec.m_pos];
|
991
|
+
|
992
|
+
if (m_cur_state < CLZBase::cNumLitStates)
|
993
|
+
{
|
994
|
+
printf("---Regular lit: %u '%c'\n",
|
995
|
+
lit, ((lit >= 32) && (lit <= 127)) ? lit : '.');
|
996
|
+
}
|
997
|
+
else
|
998
|
+
{
|
999
|
+
// delta literal
|
1000
|
+
const uint rep_lit0 = dict[(lzdec.m_pos - m_match_hist[0]) & dict.m_max_dict_size_mask];
|
1001
|
+
|
1002
|
+
uint delta_lit = rep_lit0 ^ lit;
|
1003
|
+
|
1004
|
+
printf("***Delta lit: %u '%c', Mismatch: %u '%c', Delta: 0x%02X\n",
|
1005
|
+
lit, ((lit >= 32) && (lit <= 127)) ? lit : '.',
|
1006
|
+
rep_lit0, ((rep_lit0 >= 32) && (rep_lit0 <= 127)) ? rep_lit0 : '.',
|
1007
|
+
delta_lit);
|
1008
|
+
}
|
1009
|
+
}
|
1010
|
+
else
|
1011
|
+
{
|
1012
|
+
uint actual_match_len = dict.get_match_len(0, lzdec.get_match_dist(*this), CLZBase::cMaxMatchLen);
|
1013
|
+
LZHAM_ASSERT(actual_match_len >= lzdec.get_len());
|
1014
|
+
|
1015
|
+
// match
|
1016
|
+
if (lzdec.m_dist < 0)
|
1017
|
+
{
|
1018
|
+
int match_hist_index = -lzdec.m_dist - 1;
|
1019
|
+
|
1020
|
+
if (!match_hist_index)
|
1021
|
+
{
|
1022
|
+
if (lzdec.m_len == 1)
|
1023
|
+
{
|
1024
|
+
printf("!!!Rep 0 len1\n");
|
1025
|
+
}
|
1026
|
+
else
|
1027
|
+
{
|
1028
|
+
printf("!!!Rep 0 full len %u\n", lzdec.m_len);
|
1029
|
+
}
|
1030
|
+
}
|
1031
|
+
else
|
1032
|
+
{
|
1033
|
+
printf("!!!Rep %u full len %u\n", match_hist_index, lzdec.m_len);
|
1034
|
+
}
|
1035
|
+
}
|
1036
|
+
else
|
1037
|
+
{
|
1038
|
+
LZHAM_ASSERT(lzdec.m_len >= CLZBase::cMinMatchLen);
|
1039
|
+
|
1040
|
+
// full match
|
1041
|
+
uint match_slot, match_extra;
|
1042
|
+
lzbase.compute_lzx_position_slot(lzdec.m_dist, match_slot, match_extra);
|
1043
|
+
|
1044
|
+
uint match_low_sym = 0; LZHAM_NOTE_UNUSED(match_low_sym);
|
1045
|
+
int large_len_sym = -1; LZHAM_NOTE_UNUSED(large_len_sym);
|
1046
|
+
if (lzdec.m_len >= 9)
|
1047
|
+
{
|
1048
|
+
match_low_sym = 7;
|
1049
|
+
|
1050
|
+
large_len_sym = lzdec.m_len - 9;
|
1051
|
+
}
|
1052
|
+
else
|
1053
|
+
match_low_sym = lzdec.m_len - 2;
|
1054
|
+
|
1055
|
+
uint match_high_sym = 0; LZHAM_NOTE_UNUSED(match_high_sym);
|
1056
|
+
|
1057
|
+
LZHAM_ASSERT(match_slot >= CLZBase::cLZXLowestUsableMatchSlot && (match_slot < lzbase.m_num_lzx_slots));
|
1058
|
+
match_high_sym = match_slot - CLZBase::cLZXLowestUsableMatchSlot;
|
1059
|
+
|
1060
|
+
//uint main_sym = match_low_sym | (match_high_sym << 3);
|
1061
|
+
|
1062
|
+
uint num_extra_bits = lzbase.m_lzx_position_extra_bits[match_slot];
|
1063
|
+
printf("^^^Full match Len %u Dist %u, Slot %u, ExtraBits: %u", lzdec.m_len, lzdec.m_dist, match_slot, num_extra_bits);
|
1064
|
+
|
1065
|
+
if (num_extra_bits < 3)
|
1066
|
+
{
|
1067
|
+
}
|
1068
|
+
else
|
1069
|
+
{
|
1070
|
+
printf(" (Low 4 bits: %u vs. %u)", lzdec.m_dist & 15, match_extra & 15);
|
1071
|
+
}
|
1072
|
+
printf("\n");
|
1073
|
+
}
|
1074
|
+
|
1075
|
+
if (actual_match_len > lzdec.get_len())
|
1076
|
+
{
|
1077
|
+
printf(" TRUNCATED match, actual len is %u, shortened by %u\n", actual_match_len, actual_match_len - lzdec.get_len());
|
1078
|
+
}
|
1079
|
+
}
|
1080
|
+
}
|
1081
|
+
|
1082
|
+
bool lzcompressor::state::encode_eob(symbol_codec& codec, const search_accelerator& dict, uint dict_pos)
|
1083
|
+
{
|
1084
|
+
LZHAM_NOTE_UNUSED(dict);
|
1085
|
+
LZHAM_NOTE_UNUSED(dict_pos);
|
1086
|
+
#ifdef LZHAM_LZDEBUG
|
1087
|
+
if (!codec.encode_bits(CLZBase::cLZHAMDebugSyncMarkerValue, CLZBase::cLZHAMDebugSyncMarkerBits)) return false;
|
1088
|
+
if (!codec.encode_bits(1, 1)) return false;
|
1089
|
+
if (!codec.encode_bits(0, 17)) return false;
|
1090
|
+
if (!codec.encode_bits(m_cur_state, 4)) return false;
|
1091
|
+
#endif
|
1092
|
+
|
1093
|
+
//const uint match_pred = get_pred_char(dict, dict_pos, 1);
|
1094
|
+
uint is_match_model_index = LZHAM_IS_MATCH_MODEL_INDEX(m_cur_state);
|
1095
|
+
if (!codec.encode(1, m_is_match_model[is_match_model_index])) return false;
|
1096
|
+
|
1097
|
+
// full match
|
1098
|
+
if (!codec.encode(0, m_is_rep_model[m_cur_state])) return false;
|
1099
|
+
|
1100
|
+
return codec.encode(CLZBase::cLZXSpecialCodeEndOfBlockCode, m_main_table);
|
1101
|
+
}
|
1102
|
+
|
1103
|
+
bool lzcompressor::state::encode_reset_state_partial(symbol_codec& codec, const search_accelerator& dict, uint dict_pos)
|
1104
|
+
{
|
1105
|
+
LZHAM_NOTE_UNUSED(dict);
|
1106
|
+
LZHAM_NOTE_UNUSED(dict_pos);
|
1107
|
+
#ifdef LZHAM_LZDEBUG
|
1108
|
+
if (!codec.encode_bits(CLZBase::cLZHAMDebugSyncMarkerValue, CLZBase::cLZHAMDebugSyncMarkerBits)) return false;
|
1109
|
+
if (!codec.encode_bits(1, 1)) return false;
|
1110
|
+
if (!codec.encode_bits(0, 17)) return false;
|
1111
|
+
if (!codec.encode_bits(m_cur_state, 4)) return false;
|
1112
|
+
#endif
|
1113
|
+
|
1114
|
+
//const uint match_pred = get_pred_char(dict, dict_pos, 1);
|
1115
|
+
uint is_match_model_index = LZHAM_IS_MATCH_MODEL_INDEX(m_cur_state);
|
1116
|
+
if (!codec.encode(1, m_is_match_model[is_match_model_index])) return false;
|
1117
|
+
|
1118
|
+
// full match
|
1119
|
+
if (!codec.encode(0, m_is_rep_model[m_cur_state])) return false;
|
1120
|
+
|
1121
|
+
if (!codec.encode(CLZBase::cLZXSpecialCodePartialStateReset, m_main_table))
|
1122
|
+
return false;
|
1123
|
+
|
1124
|
+
reset_state_partial();
|
1125
|
+
return true;
|
1126
|
+
}
|
1127
|
+
|
1128
|
+
void lzcompressor::state::update_match_hist(uint match_dist)
|
1129
|
+
{
|
1130
|
+
LZHAM_ASSUME(CLZBase::cMatchHistSize == 4);
|
1131
|
+
m_match_hist[3] = m_match_hist[2];
|
1132
|
+
m_match_hist[2] = m_match_hist[1];
|
1133
|
+
m_match_hist[1] = m_match_hist[0];
|
1134
|
+
m_match_hist[0] = match_dist;
|
1135
|
+
}
|
1136
|
+
|
1137
|
+
int lzcompressor::state::find_match_dist(uint match_dist) const
|
1138
|
+
{
|
1139
|
+
for (uint match_hist_index = 0; match_hist_index < CLZBase::cMatchHistSize; match_hist_index++)
|
1140
|
+
if (match_dist == m_match_hist[match_hist_index])
|
1141
|
+
return match_hist_index;
|
1142
|
+
|
1143
|
+
return -1;
|
1144
|
+
}
|
1145
|
+
|
1146
|
+
void lzcompressor::state::reset_state_partial()
|
1147
|
+
{
|
1148
|
+
LZHAM_ASSUME(CLZBase::cMatchHistSize == 4);
|
1149
|
+
m_match_hist[0] = 1;
|
1150
|
+
m_match_hist[1] = 1;
|
1151
|
+
m_match_hist[2] = 1;
|
1152
|
+
m_match_hist[3] = 1;
|
1153
|
+
m_cur_state = 0;
|
1154
|
+
}
|
1155
|
+
|
1156
|
+
void lzcompressor::state::start_of_block(const search_accelerator& dict, uint cur_ofs, uint block_index)
|
1157
|
+
{
|
1158
|
+
LZHAM_NOTE_UNUSED(dict), LZHAM_NOTE_UNUSED(block_index);
|
1159
|
+
|
1160
|
+
reset_state_partial();
|
1161
|
+
|
1162
|
+
m_cur_ofs = cur_ofs;
|
1163
|
+
m_block_start_dict_ofs = cur_ofs;
|
1164
|
+
}
|
1165
|
+
|
1166
|
+
void lzcompressor::state::reset_update_rate()
|
1167
|
+
{
|
1168
|
+
m_lit_table.reset_update_rate();
|
1169
|
+
m_delta_lit_table.reset_update_rate();
|
1170
|
+
|
1171
|
+
m_main_table.reset_update_rate();
|
1172
|
+
|
1173
|
+
for (uint i = 0; i < LZHAM_ARRAY_SIZE(m_rep_len_table); i++)
|
1174
|
+
m_rep_len_table[i].reset_update_rate();
|
1175
|
+
|
1176
|
+
for (uint i = 0; i < LZHAM_ARRAY_SIZE(m_large_len_table); i++)
|
1177
|
+
m_large_len_table[i].reset_update_rate();
|
1178
|
+
|
1179
|
+
m_dist_lsb_table.reset_update_rate();
|
1180
|
+
}
|
1181
|
+
|
1182
|
+
void lzcompressor::coding_stats::clear()
|
1183
|
+
{
|
1184
|
+
m_total_bytes = 0;
|
1185
|
+
m_total_contexts = 0;
|
1186
|
+
m_total_match_bits_cost = 0;
|
1187
|
+
m_worst_match_bits_cost = 0;
|
1188
|
+
m_total_is_match0_bits_cost = 0;
|
1189
|
+
m_total_is_match1_bits_cost = 0;
|
1190
|
+
m_context_stats.clear();
|
1191
|
+
|
1192
|
+
m_total_nonmatches = 0;
|
1193
|
+
m_total_matches = 0;
|
1194
|
+
m_total_cost = 0.0f;
|
1195
|
+
|
1196
|
+
m_lit_stats.clear();
|
1197
|
+
m_delta_lit_stats.clear();
|
1198
|
+
|
1199
|
+
m_rep0_len1_stats.clear();
|
1200
|
+
for (uint i = 0; i < CLZBase::cMatchHistSize; i++)
|
1201
|
+
m_rep_stats[i].clear();
|
1202
|
+
m_rep0_len1_stats.clear();
|
1203
|
+
m_rep0_len2_plus_stats.clear();
|
1204
|
+
|
1205
|
+
for (uint i = 0; i <= CLZBase::cMaxMatchLen; i++)
|
1206
|
+
m_full_match_stats[i].clear();
|
1207
|
+
|
1208
|
+
m_total_far_len2_matches = 0;
|
1209
|
+
m_total_near_len2_matches = 0;
|
1210
|
+
|
1211
|
+
m_total_truncated_matches = 0;
|
1212
|
+
utils::zero_object(m_match_truncation_len_hist);
|
1213
|
+
utils::zero_object(m_match_truncation_hist);
|
1214
|
+
utils::zero_object(m_match_type_truncation_hist);
|
1215
|
+
utils::zero_object(m_match_type_was_not_truncated_hist);
|
1216
|
+
|
1217
|
+
m_total_update_rate_resets = 0;
|
1218
|
+
|
1219
|
+
m_max_len2_dist = 0;
|
1220
|
+
}
|
1221
|
+
|
1222
|
+
void lzcompressor::coding_stats::print()
|
1223
|
+
{
|
1224
|
+
if (!m_total_contexts)
|
1225
|
+
return;
|
1226
|
+
|
1227
|
+
printf("-----------\n");
|
1228
|
+
printf("Coding statistics:\n");
|
1229
|
+
printf("Total update rate resets: %u\n", m_total_update_rate_resets);
|
1230
|
+
printf("Total Bytes: %u, Total Contexts: %u, Total Cost: %f bits (%f bytes)\nContext ave cost: %f StdDev: %f Min: %f Max: %f\n", m_total_bytes, m_total_contexts, m_total_cost, m_total_cost / 8.0f, m_context_stats.get_average(), m_context_stats.get_std_dev(), m_context_stats.get_min_val(), m_context_stats.get_max_val());
|
1231
|
+
printf("Ave bytes per context: %f\n", m_total_bytes / (float)m_total_contexts);
|
1232
|
+
|
1233
|
+
printf("IsMatch:\n");
|
1234
|
+
printf(" Total: %u, Cost: %f (%f bytes), Ave. Cost: %f, Worst Cost: %f\n",
|
1235
|
+
m_total_contexts, m_total_match_bits_cost, m_total_match_bits_cost / 8.0f, m_total_match_bits_cost / math::maximum<uint>(1, m_total_contexts), m_worst_match_bits_cost);
|
1236
|
+
|
1237
|
+
printf(" IsMatch(0): %u, Cost: %f (%f bytes), Ave. Cost: %f\n",
|
1238
|
+
m_total_nonmatches, m_total_is_match0_bits_cost, m_total_is_match0_bits_cost / 8.0f, m_total_is_match0_bits_cost / math::maximum<uint>(1, m_total_nonmatches));
|
1239
|
+
|
1240
|
+
printf(" IsMatch(1): %u, Cost: %f (%f bytes), Ave. Cost: %f\n",
|
1241
|
+
m_total_matches, m_total_is_match1_bits_cost, m_total_is_match1_bits_cost / 8.0f, m_total_is_match1_bits_cost / math::maximum<uint>(1, m_total_matches));
|
1242
|
+
|
1243
|
+
printf("Literal stats:\n");
|
1244
|
+
printf(" Count: %u, Cost: %f (%f bytes), Ave: %f StdDev: %f Min: %f Max: %f\n", m_lit_stats.get_number_of_values32(), m_lit_stats.get_total(), m_lit_stats.get_total() / 8.0f, m_lit_stats.get_average(), m_lit_stats.get_std_dev(), m_lit_stats.get_min_val(), m_lit_stats.get_max_val());
|
1245
|
+
|
1246
|
+
printf("Delta literal stats:\n");
|
1247
|
+
printf(" Count: %u, Cost: %f (%f bytes), Ave: %f StdDev: %f Min: %f Max: %f\n", m_delta_lit_stats.get_number_of_values32(), m_delta_lit_stats.get_total(), m_delta_lit_stats.get_total() / 8.0f, m_delta_lit_stats.get_average(), m_delta_lit_stats.get_std_dev(), m_delta_lit_stats.get_min_val(), m_delta_lit_stats.get_max_val());
|
1248
|
+
|
1249
|
+
printf("Rep0 Len1 stats:\n");
|
1250
|
+
printf(" Count: %u, Cost: %f (%f bytes), Ave. Cost: %f StdDev: %f Min: %f Max: %f\n", m_rep0_len1_stats.get_number_of_values32(), m_rep0_len1_stats.get_total(), m_rep0_len1_stats.get_total() / 8.0f, m_rep0_len1_stats.get_average(), m_rep0_len1_stats.get_std_dev(), m_rep0_len1_stats.get_min_val(), m_rep0_len1_stats.get_max_val());
|
1251
|
+
|
1252
|
+
printf("Rep0 Len2+ stats:\n");
|
1253
|
+
printf(" Count: %u, Cost: %f (%f bytes), Ave. Cost: %f StdDev: %f Min: %f Max: %f\n", m_rep0_len2_plus_stats.get_number_of_values32(), m_rep0_len2_plus_stats.get_total(), m_rep0_len2_plus_stats.get_total() / 8.0f, m_rep0_len2_plus_stats.get_average(), m_rep0_len2_plus_stats.get_std_dev(), m_rep0_len2_plus_stats.get_min_val(), m_rep0_len2_plus_stats.get_max_val());
|
1254
|
+
|
1255
|
+
for (uint i = 0; i < CLZBase::cMatchHistSize; i++)
|
1256
|
+
{
|
1257
|
+
printf("Rep %u stats:\n", i);
|
1258
|
+
printf(" Count: %u, Cost: %f (%f bytes), Ave. Cost: %f StdDev: %f Min: %f Max: %f\n", m_rep_stats[i].get_number_of_values32(), m_rep_stats[i].get_total(), m_rep_stats[i].get_total() / 8.0f, m_rep_stats[i].get_average(), m_rep_stats[i].get_std_dev(), m_rep_stats[i].get_min_val(), m_rep_stats[i].get_max_val());
|
1259
|
+
}
|
1260
|
+
|
1261
|
+
for (uint i = CLZBase::cMinMatchLen; i <= CLZBase::cMaxMatchLen; i++)
|
1262
|
+
{
|
1263
|
+
printf("Match %u: Total: %u, Cost: %f (%f bytes), Ave: %f StdDev: %f Min: %f Max: %f\n", i,
|
1264
|
+
m_full_match_stats[i].get_number_of_values32(), m_full_match_stats[i].get_total(), m_full_match_stats[i].get_total() / 8.0f,
|
1265
|
+
m_full_match_stats[i].get_average(), m_full_match_stats[i].get_std_dev(), m_full_match_stats[i].get_min_val(), m_full_match_stats[i].get_max_val());
|
1266
|
+
}
|
1267
|
+
|
1268
|
+
printf("Total near len2 matches: %u, total far len2 matches: %u\n", m_total_near_len2_matches, m_total_far_len2_matches);
|
1269
|
+
printf("Total matches: %u, truncated matches: %u\n", m_total_matches, m_total_truncated_matches);
|
1270
|
+
printf("Max full match len2 distance: %u\n", m_max_len2_dist);
|
1271
|
+
|
1272
|
+
#if 0
|
1273
|
+
printf("Size of truncation histogram:\n");
|
1274
|
+
for (uint i = 0; i <= CLZBase::cMaxMatchLen; i++)
|
1275
|
+
{
|
1276
|
+
printf("%05u ", m_match_truncation_len_hist[i]);
|
1277
|
+
if ((i & 15) == 15) printf("\n");
|
1278
|
+
}
|
1279
|
+
printf("\n");
|
1280
|
+
|
1281
|
+
printf("Number of truncations per encoded match length histogram:\n");
|
1282
|
+
for (uint i = 0; i <= CLZBase::cMaxMatchLen; i++)
|
1283
|
+
{
|
1284
|
+
printf("%05u ", m_match_truncation_hist[i]);
|
1285
|
+
if ((i & 15) == 15) printf("\n");
|
1286
|
+
}
|
1287
|
+
printf("\n");
|
1288
|
+
|
1289
|
+
for (uint s = 0; s < CLZBase::cNumStates; s++)
|
1290
|
+
{
|
1291
|
+
printf("-- Match type truncation hist for state %u:\n", s);
|
1292
|
+
for (uint i = 0; i < LZHAM_ARRAY_SIZE(m_match_type_truncation_hist[s]); i++)
|
1293
|
+
{
|
1294
|
+
printf("%u truncated (%3.1f%%), %u not truncated\n", m_match_type_truncation_hist[s][i], 100.0f * (float)m_match_type_truncation_hist[s][i] / (m_match_type_truncation_hist[s][i] + m_match_type_was_not_truncated_hist[s][i]), m_match_type_was_not_truncated_hist[s][i]);
|
1295
|
+
}
|
1296
|
+
}
|
1297
|
+
#endif
|
1298
|
+
}
|
1299
|
+
|
1300
|
+
void lzcompressor::coding_stats::update(const lzdecision& lzdec, const state& cur_state, const search_accelerator& dict, bit_cost_t cost)
|
1301
|
+
{
|
1302
|
+
m_total_bytes += lzdec.get_len();
|
1303
|
+
m_total_contexts++;
|
1304
|
+
|
1305
|
+
float cost_in_bits = cost / (float)cBitCostScale;
|
1306
|
+
LZHAM_ASSERT(cost_in_bits > 0.0f);
|
1307
|
+
m_total_cost += cost_in_bits;
|
1308
|
+
|
1309
|
+
m_context_stats.update(cost_in_bits);
|
1310
|
+
|
1311
|
+
//uint match_pred = cur_state.get_pred_char(dict, lzdec.m_pos, 1);
|
1312
|
+
uint is_match_model_index = LZHAM_IS_MATCH_MODEL_INDEX(cur_state.m_cur_state);
|
1313
|
+
|
1314
|
+
if (lzdec.m_len == 0)
|
1315
|
+
{
|
1316
|
+
float match_bit_cost = cur_state.m_is_match_model[is_match_model_index].get_cost(0) / (float)cBitCostScale;
|
1317
|
+
|
1318
|
+
m_total_is_match0_bits_cost += match_bit_cost;
|
1319
|
+
m_total_match_bits_cost += match_bit_cost;
|
1320
|
+
m_worst_match_bits_cost = math::maximum<double>(m_worst_match_bits_cost, static_cast<double>(match_bit_cost));
|
1321
|
+
m_total_nonmatches++;
|
1322
|
+
|
1323
|
+
if (cur_state.m_cur_state < CLZBase::cNumLitStates)
|
1324
|
+
{
|
1325
|
+
m_lit_stats.update(cost_in_bits);
|
1326
|
+
}
|
1327
|
+
else
|
1328
|
+
{
|
1329
|
+
m_delta_lit_stats.update(cost_in_bits);
|
1330
|
+
}
|
1331
|
+
}
|
1332
|
+
else if (lzdec.m_len <= CLZBase::cMaxMatchLen)
|
1333
|
+
{
|
1334
|
+
const uint match_len = lzdec.get_len();
|
1335
|
+
|
1336
|
+
{
|
1337
|
+
uint match_dist = lzdec.get_match_dist(cur_state);
|
1338
|
+
|
1339
|
+
uint cur_lookahead_size = dict.get_lookahead_size();
|
1340
|
+
|
1341
|
+
uint actual_match_len = dict.get_match_len(0, match_dist, LZHAM_MIN(cur_lookahead_size, static_cast<uint>(CLZBase::cMaxMatchLen)));
|
1342
|
+
LZHAM_VERIFY(match_len <= actual_match_len);
|
1343
|
+
|
1344
|
+
m_total_truncated_matches += match_len < actual_match_len;
|
1345
|
+
m_match_truncation_len_hist[math::maximum<int>(0, actual_match_len - match_len)]++;
|
1346
|
+
|
1347
|
+
uint type_index = 4;
|
1348
|
+
if (!lzdec.is_full_match())
|
1349
|
+
{
|
1350
|
+
LZHAM_ASSUME(CLZBase::cMatchHistSize == 4);
|
1351
|
+
type_index = -lzdec.m_dist - 1;
|
1352
|
+
}
|
1353
|
+
|
1354
|
+
if (actual_match_len > match_len)
|
1355
|
+
{
|
1356
|
+
m_match_truncation_hist[match_len]++;
|
1357
|
+
|
1358
|
+
m_match_type_truncation_hist[cur_state.m_cur_state][type_index]++;
|
1359
|
+
}
|
1360
|
+
else
|
1361
|
+
{
|
1362
|
+
m_match_type_was_not_truncated_hist[cur_state.m_cur_state][type_index]++;
|
1363
|
+
}
|
1364
|
+
}
|
1365
|
+
|
1366
|
+
float match_bit_cost = cur_state.m_is_match_model[is_match_model_index].get_cost(1) / (float)cBitCostScale;
|
1367
|
+
m_total_is_match1_bits_cost += match_bit_cost;
|
1368
|
+
m_total_match_bits_cost += match_bit_cost;
|
1369
|
+
m_worst_match_bits_cost = math::maximum<double>(m_worst_match_bits_cost, static_cast<double>(match_bit_cost));
|
1370
|
+
m_total_matches++;
|
1371
|
+
|
1372
|
+
if (lzdec.m_dist < 0)
|
1373
|
+
{
|
1374
|
+
// rep match
|
1375
|
+
int match_hist_index = -lzdec.m_dist - 1;
|
1376
|
+
LZHAM_ASSERT(match_hist_index < CLZBase::cMatchHistSize);
|
1377
|
+
|
1378
|
+
m_rep_stats[match_hist_index].update(cost_in_bits);
|
1379
|
+
|
1380
|
+
if (!match_hist_index)
|
1381
|
+
{
|
1382
|
+
// rep0 match
|
1383
|
+
if (lzdec.m_len == 1)
|
1384
|
+
{
|
1385
|
+
m_rep0_len1_stats.update(cost_in_bits);
|
1386
|
+
}
|
1387
|
+
else
|
1388
|
+
{
|
1389
|
+
m_rep0_len2_plus_stats.update(cost_in_bits);
|
1390
|
+
}
|
1391
|
+
}
|
1392
|
+
}
|
1393
|
+
else
|
1394
|
+
{
|
1395
|
+
m_full_match_stats[math::minimum<int>(cMaxMatchLen, match_len)].update(cost_in_bits);
|
1396
|
+
|
1397
|
+
if (match_len == 2)
|
1398
|
+
{
|
1399
|
+
if (lzdec.m_dist <= 512)
|
1400
|
+
m_total_near_len2_matches++;
|
1401
|
+
else
|
1402
|
+
m_total_far_len2_matches++;
|
1403
|
+
|
1404
|
+
m_max_len2_dist = LZHAM_MAX((int)m_max_len2_dist, lzdec.m_dist);
|
1405
|
+
}
|
1406
|
+
}
|
1407
|
+
}
|
1408
|
+
else
|
1409
|
+
{
|
1410
|
+
// TODO: Handle huge matches.
|
1411
|
+
}
|
1412
|
+
}
|
1413
|
+
} // namespace lzham
|