extlzham 0.0.1.PROTOTYPE

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.md +27 -0
  3. data/README.md +21 -0
  4. data/Rakefile +143 -0
  5. data/contrib/lzham/LICENSE +22 -0
  6. data/contrib/lzham/README.md +209 -0
  7. data/contrib/lzham/include/lzham.h +781 -0
  8. data/contrib/lzham/lzhamcomp/lzham_comp.h +38 -0
  9. data/contrib/lzham/lzhamcomp/lzham_lzbase.cpp +244 -0
  10. data/contrib/lzham/lzhamcomp/lzham_lzbase.h +45 -0
  11. data/contrib/lzham/lzhamcomp/lzham_lzcomp.cpp +608 -0
  12. data/contrib/lzham/lzhamcomp/lzham_lzcomp_internal.cpp +1966 -0
  13. data/contrib/lzham/lzhamcomp/lzham_lzcomp_internal.h +472 -0
  14. data/contrib/lzham/lzhamcomp/lzham_lzcomp_state.cpp +1413 -0
  15. data/contrib/lzham/lzhamcomp/lzham_match_accel.cpp +562 -0
  16. data/contrib/lzham/lzhamcomp/lzham_match_accel.h +146 -0
  17. data/contrib/lzham/lzhamcomp/lzham_null_threading.h +97 -0
  18. data/contrib/lzham/lzhamcomp/lzham_pthreads_threading.cpp +229 -0
  19. data/contrib/lzham/lzhamcomp/lzham_pthreads_threading.h +520 -0
  20. data/contrib/lzham/lzhamcomp/lzham_threading.h +12 -0
  21. data/contrib/lzham/lzhamcomp/lzham_win32_threading.cpp +220 -0
  22. data/contrib/lzham/lzhamcomp/lzham_win32_threading.h +368 -0
  23. data/contrib/lzham/lzhamdecomp/lzham_assert.cpp +66 -0
  24. data/contrib/lzham/lzhamdecomp/lzham_assert.h +40 -0
  25. data/contrib/lzham/lzhamdecomp/lzham_checksum.cpp +73 -0
  26. data/contrib/lzham/lzhamdecomp/lzham_checksum.h +13 -0
  27. data/contrib/lzham/lzhamdecomp/lzham_config.h +23 -0
  28. data/contrib/lzham/lzhamdecomp/lzham_core.h +264 -0
  29. data/contrib/lzham/lzhamdecomp/lzham_decomp.h +37 -0
  30. data/contrib/lzham/lzhamdecomp/lzham_helpers.h +54 -0
  31. data/contrib/lzham/lzhamdecomp/lzham_huffman_codes.cpp +262 -0
  32. data/contrib/lzham/lzhamdecomp/lzham_huffman_codes.h +14 -0
  33. data/contrib/lzham/lzhamdecomp/lzham_lzdecomp.cpp +1527 -0
  34. data/contrib/lzham/lzhamdecomp/lzham_lzdecompbase.cpp +131 -0
  35. data/contrib/lzham/lzhamdecomp/lzham_lzdecompbase.h +89 -0
  36. data/contrib/lzham/lzhamdecomp/lzham_math.h +142 -0
  37. data/contrib/lzham/lzhamdecomp/lzham_mem.cpp +284 -0
  38. data/contrib/lzham/lzhamdecomp/lzham_mem.h +112 -0
  39. data/contrib/lzham/lzhamdecomp/lzham_platform.cpp +157 -0
  40. data/contrib/lzham/lzhamdecomp/lzham_platform.h +284 -0
  41. data/contrib/lzham/lzhamdecomp/lzham_prefix_coding.cpp +351 -0
  42. data/contrib/lzham/lzhamdecomp/lzham_prefix_coding.h +146 -0
  43. data/contrib/lzham/lzhamdecomp/lzham_symbol_codec.cpp +1484 -0
  44. data/contrib/lzham/lzhamdecomp/lzham_symbol_codec.h +556 -0
  45. data/contrib/lzham/lzhamdecomp/lzham_timer.cpp +147 -0
  46. data/contrib/lzham/lzhamdecomp/lzham_timer.h +99 -0
  47. data/contrib/lzham/lzhamdecomp/lzham_traits.h +141 -0
  48. data/contrib/lzham/lzhamdecomp/lzham_types.h +97 -0
  49. data/contrib/lzham/lzhamdecomp/lzham_utils.h +58 -0
  50. data/contrib/lzham/lzhamdecomp/lzham_vector.cpp +75 -0
  51. data/contrib/lzham/lzhamdecomp/lzham_vector.h +588 -0
  52. data/contrib/lzham/lzhamlib/lzham_lib.cpp +179 -0
  53. data/examples/basic.rb +48 -0
  54. data/ext/extconf.rb +26 -0
  55. data/ext/extlzham.c +741 -0
  56. data/gemstub.rb +22 -0
  57. data/lib/extlzham/version.rb +5 -0
  58. data/lib/extlzham.rb +153 -0
  59. metadata +135 -0
@@ -0,0 +1,472 @@
1
+ // File: lzham_lzcomp_internal.h
2
+ // See Copyright Notice and license at the end of include/lzham.h
3
+ #pragma once
4
+ #include "lzham_match_accel.h"
5
+ #include "lzham_symbol_codec.h"
6
+ #include "lzham_lzbase.h"
7
+
8
+ namespace lzham
9
+ {
10
+ typedef lzham::vector<uint8> byte_vec;
11
+
12
+ const uint cMaxParseGraphNodes = 3072;
13
+ const uint cMaxParseThreads = 8;
14
+
15
+ enum compression_level
16
+ {
17
+ cCompressionLevelFastest,
18
+ cCompressionLevelFaster,
19
+ cCompressionLevelDefault,
20
+ cCompressionLevelBetter,
21
+ cCompressionLevelUber,
22
+
23
+ cCompressionLevelCount
24
+ };
25
+
26
+ struct comp_settings
27
+ {
28
+ uint m_fast_bytes;
29
+ bool m_fast_adaptive_huffman_updating;
30
+ uint m_match_accel_max_matches_per_probe;
31
+ uint m_match_accel_max_probes;
32
+ };
33
+
34
+ class lzcompressor : public CLZBase
35
+ {
36
+ public:
37
+ lzcompressor();
38
+
39
+ struct init_params
40
+ {
41
+ enum
42
+ {
43
+ cMinDictSizeLog2 = CLZBase::cMinDictSizeLog2,
44
+ cMaxDictSizeLog2 = CLZBase::cMaxDictSizeLog2,
45
+ cDefaultBlockSize = 1024U*512U
46
+ };
47
+
48
+ init_params() :
49
+ m_pTask_pool(NULL),
50
+ m_max_helper_threads(0),
51
+ m_compression_level(cCompressionLevelDefault),
52
+ m_dict_size_log2(22),
53
+ m_block_size(cDefaultBlockSize),
54
+ m_lzham_compress_flags(0),
55
+ m_pSeed_bytes(0),
56
+ m_num_seed_bytes(0),
57
+ m_table_max_update_interval(0),
58
+ m_table_update_interval_slow_rate(0)
59
+ {
60
+ }
61
+
62
+ task_pool* m_pTask_pool;
63
+ uint m_max_helper_threads;
64
+
65
+ compression_level m_compression_level;
66
+ uint m_dict_size_log2;
67
+
68
+ uint m_block_size;
69
+
70
+ uint m_lzham_compress_flags;
71
+
72
+ const void *m_pSeed_bytes;
73
+ uint m_num_seed_bytes;
74
+
75
+ uint m_table_max_update_interval;
76
+ uint m_table_update_interval_slow_rate;
77
+ };
78
+
79
+ bool init(const init_params& params);
80
+ void clear();
81
+
82
+ // sync, or sync+dictionary flush
83
+ bool flush(lzham_flush_t flush_type);
84
+
85
+ bool reset();
86
+
87
+ bool put_bytes(const void* pBuf, uint buf_len);
88
+
89
+ const byte_vec& get_compressed_data() const { return m_comp_buf; }
90
+ byte_vec& get_compressed_data() { return m_comp_buf; }
91
+
92
+ uint32 get_src_adler32() const { return m_src_adler32; }
93
+
94
+ private:
95
+ class state;
96
+
97
+ enum
98
+ {
99
+ cLitComplexity = 1,
100
+ cRep0Complexity = 2,
101
+ cRep3Complexity = 5,
102
+
103
+ cLongMatchComplexity = 6,
104
+ cLongMatchComplexityLenThresh = 9,
105
+
106
+ cShortMatchComplexity = 7
107
+ };
108
+
109
+ struct lzdecision
110
+ {
111
+ int m_pos; // dict position where decision was evaluated
112
+ int m_len; // 0 if literal, 1+ if match
113
+ int m_dist; // <0 if match rep, else >=1 is match dist
114
+
115
+ inline lzdecision() { }
116
+ inline lzdecision(int pos, int len, int dist) : m_pos(pos), m_len(len), m_dist(dist) { }
117
+
118
+ inline void init(int pos, int len, int dist) { m_pos = pos; m_len = len; m_dist = dist; }
119
+
120
+ inline bool is_lit() const { return !m_len; }
121
+ inline bool is_match() const { return m_len > 0; } // may be a rep or full match
122
+ inline bool is_full_match() const { return (m_len > 0) && (m_dist >= 1); }
123
+ inline uint get_len() const { return math::maximum<uint>(m_len, 1); }
124
+ inline bool is_rep() const { return m_dist < 0; }
125
+ inline bool is_rep0() const { return m_dist == -1; }
126
+
127
+ uint get_match_dist(const state& s) const;
128
+
129
+ inline uint get_complexity() const
130
+ {
131
+ if (is_lit())
132
+ return cLitComplexity;
133
+ else if (is_rep())
134
+ {
135
+ LZHAM_ASSUME(cRep0Complexity == 2);
136
+ return 1 + -m_dist; // 2, 3, 4, or 5
137
+ }
138
+ else if (get_len() >= cLongMatchComplexityLenThresh)
139
+ return cLongMatchComplexity;
140
+ else
141
+ return cShortMatchComplexity;
142
+ }
143
+
144
+ inline uint get_min_codable_len() const
145
+ {
146
+ if (is_lit() || is_rep0())
147
+ return 1;
148
+ else
149
+ return CLZBase::cMinMatchLen;
150
+ }
151
+ };
152
+
153
+ struct lzpriced_decision : lzdecision
154
+ {
155
+ lzpriced_decision() { }
156
+
157
+ inline lzpriced_decision(int pos, int len, int dist) : lzdecision(pos, len, dist) { }
158
+ inline lzpriced_decision(int pos, int len, int dist, bit_cost_t cost) : lzdecision(pos, len, dist), m_cost(cost) { }
159
+
160
+ inline void init(int pos, int len, int dist, bit_cost_t cost) { lzdecision::init(pos, len, dist); m_cost = cost; }
161
+
162
+ inline bit_cost_t get_cost() const { return m_cost; }
163
+
164
+ bit_cost_t m_cost;
165
+ };
166
+
167
+ struct state_base
168
+ {
169
+ uint m_cur_ofs;
170
+ uint m_cur_state;
171
+ uint m_match_hist[CLZBase::cMatchHistSize];
172
+
173
+ inline bool operator== (const state_base &rhs) const
174
+ {
175
+ if (m_cur_state != rhs.m_cur_state)
176
+ return false;
177
+ for (uint i = 0; i < CLZBase::cMatchHistSize; i++)
178
+ if (m_match_hist[i] != rhs.m_match_hist[i])
179
+ return false;
180
+ return true;
181
+ }
182
+
183
+ void partial_advance(const lzdecision& lzdec);
184
+
185
+ inline void save_partial_state(state_base& dst)
186
+ {
187
+ dst.m_cur_ofs = m_cur_ofs;
188
+ dst.m_cur_state = m_cur_state;
189
+ memcpy(dst.m_match_hist, m_match_hist, sizeof(m_match_hist));
190
+ }
191
+
192
+ inline void restore_partial_state(const state_base& src)
193
+ {
194
+ m_cur_ofs = src.m_cur_ofs;
195
+ m_cur_state = src.m_cur_state;
196
+ memcpy(m_match_hist, src.m_match_hist, sizeof(m_match_hist));
197
+ }
198
+ };
199
+
200
+ class state : public state_base
201
+ {
202
+ public:
203
+ state();
204
+
205
+ void clear();
206
+
207
+ bool init(CLZBase& lzbase, uint table_max_update_interval, uint table_update_interval_slow_rate);
208
+ void reset();
209
+
210
+ bit_cost_t get_cost(CLZBase& lzbase, const search_accelerator& dict, const lzdecision& lzdec) const;
211
+ bit_cost_t get_len2_match_cost(CLZBase& lzbase, uint dict_pos, uint len2_match_dist, uint is_match_model_index);
212
+ bit_cost_t get_lit_cost(CLZBase& lzbase, const search_accelerator& dict, uint dict_pos, uint lit_pred0, uint is_match_model_index) const;
213
+
214
+ // Returns actual cost.
215
+ void 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;
216
+ void 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;
217
+
218
+ bit_cost_t update_stats(CLZBase& lzbase, const search_accelerator& dict, const lzdecision& lzdec);
219
+
220
+ bool advance(CLZBase& lzbase, const search_accelerator& dict, const lzdecision& lzdec);
221
+ bool encode(symbol_codec& codec, CLZBase& lzbase, const search_accelerator& dict, const lzdecision& lzdec);
222
+
223
+ void print(symbol_codec& codec, CLZBase& lzbase, const search_accelerator& dict, const lzdecision& lzdec);
224
+
225
+ bool encode_eob(symbol_codec& codec, const search_accelerator& dict, uint dict_pos);
226
+ bool encode_reset_state_partial(symbol_codec& codec, const search_accelerator& dict, uint dict_pos);
227
+
228
+ void update_match_hist(uint match_dist);
229
+ int find_match_dist(uint match_hist) const;
230
+
231
+ void reset_state_partial();
232
+ void start_of_block(const search_accelerator& dict, uint cur_ofs, uint block_index);
233
+
234
+ void reset_update_rate();
235
+
236
+ uint get_pred_char(const search_accelerator& dict, int pos, int backward_ofs) const;
237
+
238
+ inline bool will_reference_last_match(const lzdecision& lzdec) const
239
+ {
240
+ return (!lzdec.is_match()) && (m_cur_state >= CLZBase::cNumLitStates);
241
+ }
242
+
243
+ uint m_block_start_dict_ofs;
244
+
245
+ adaptive_bit_model m_is_match_model[CLZBase::cNumStates];
246
+
247
+ adaptive_bit_model m_is_rep_model[CLZBase::cNumStates];
248
+ adaptive_bit_model m_is_rep0_model[CLZBase::cNumStates];
249
+ adaptive_bit_model m_is_rep0_single_byte_model[CLZBase::cNumStates];
250
+ adaptive_bit_model m_is_rep1_model[CLZBase::cNumStates];
251
+ adaptive_bit_model m_is_rep2_model[CLZBase::cNumStates];
252
+
253
+ quasi_adaptive_huffman_data_model m_lit_table;
254
+ quasi_adaptive_huffman_data_model m_delta_lit_table;
255
+
256
+ quasi_adaptive_huffman_data_model m_main_table;
257
+ quasi_adaptive_huffman_data_model m_rep_len_table[2];
258
+ quasi_adaptive_huffman_data_model m_large_len_table[2];
259
+ quasi_adaptive_huffman_data_model m_dist_lsb_table;
260
+ };
261
+
262
+ class tracked_stat
263
+ {
264
+ public:
265
+ tracked_stat() { clear(); }
266
+
267
+ void clear() { m_num = 0; m_total = 0.0f; m_total2 = 0.0f; m_min_val = 9e+99; m_max_val = -9e+99; }
268
+
269
+ void update(double val) { m_num++; m_total += val; m_total2 += val * val; m_min_val = LZHAM_MIN(m_min_val, val); m_max_val = LZHAM_MAX(m_max_val, val); }
270
+
271
+ tracked_stat &operator += (double val) { update(val); return *this; }
272
+ operator double() const { return m_total; }
273
+
274
+ uint64 get_number_of_values() { return m_num; }
275
+ uint32 get_number_of_values32() { return static_cast<uint32>(LZHAM_MIN(UINT_MAX, m_num)); }
276
+ double get_total() const { return m_total; }
277
+ double get_average() const { return m_num ? m_total / m_num : 0.0f; };
278
+ double get_std_dev() const { return m_num ? sqrt( m_num * m_total2 - m_total * m_total ) / m_num: 0.0f; }
279
+ double get_min_val() const { return m_num ? m_min_val : 0.0f; }
280
+ double get_max_val() const { return m_num ? m_max_val : 0.0f; }
281
+
282
+ private:
283
+ uint64 m_num;
284
+ double m_total;
285
+ double m_total2;
286
+ double m_min_val;
287
+ double m_max_val;
288
+ };
289
+
290
+ struct coding_stats
291
+ {
292
+ coding_stats() { clear(); }
293
+
294
+ void clear();
295
+
296
+ void update(const lzdecision& lzdec, const state& cur_state, const search_accelerator& dict, bit_cost_t cost);
297
+ void print();
298
+
299
+ uint m_total_bytes;
300
+ uint m_total_contexts;
301
+ double m_total_cost;
302
+
303
+ tracked_stat m_context_stats;
304
+
305
+ double m_total_match_bits_cost;
306
+ double m_worst_match_bits_cost;
307
+ double m_total_is_match0_bits_cost;
308
+ double m_total_is_match1_bits_cost;
309
+
310
+ uint m_total_truncated_matches;
311
+ uint m_match_truncation_len_hist[CLZBase::cMaxMatchLen + 1];
312
+ uint m_match_truncation_hist[CLZBase::cMaxMatchLen + 1];
313
+ uint m_match_type_truncation_hist[CLZBase::cNumStates][5];
314
+ uint m_match_type_was_not_truncated_hist[CLZBase::cNumStates][5];
315
+
316
+ uint m_total_nonmatches;
317
+ uint m_total_matches;
318
+
319
+ tracked_stat m_lit_stats;
320
+ tracked_stat m_delta_lit_stats;
321
+
322
+ tracked_stat m_rep_stats[CLZBase::cMatchHistSize];
323
+ tracked_stat m_rep0_len1_stats;
324
+ tracked_stat m_rep0_len2_plus_stats;
325
+
326
+ tracked_stat m_full_match_stats[cMaxMatchLen + 1];
327
+
328
+ uint m_total_far_len2_matches;
329
+ uint m_total_near_len2_matches;
330
+
331
+ uint m_total_update_rate_resets;
332
+
333
+ uint m_max_len2_dist;
334
+ };
335
+
336
+ init_params m_params;
337
+ comp_settings m_settings;
338
+
339
+ int64 m_src_size;
340
+ uint32 m_src_adler32;
341
+
342
+ search_accelerator m_accel;
343
+
344
+ symbol_codec m_codec;
345
+
346
+ coding_stats m_stats;
347
+
348
+ byte_vec m_block_buf;
349
+ byte_vec m_comp_buf;
350
+
351
+ uint m_step;
352
+
353
+ uint m_block_start_dict_ofs;
354
+
355
+ uint m_block_index;
356
+
357
+ bool m_finished;
358
+ bool m_use_task_pool;
359
+
360
+ struct node_state
361
+ {
362
+ LZHAM_FORCE_INLINE void clear()
363
+ {
364
+ m_total_cost = cBitCostMax; //math::cNearlyInfinite;
365
+ m_total_complexity = UINT_MAX;
366
+ }
367
+
368
+ // the lzdecision that led from parent to this node_state
369
+ lzdecision m_lzdec;
370
+
371
+ // This is either the state of the parent node (optimal parsing), or the state of the child node (extreme parsing).
372
+ state::state_base m_saved_state;
373
+
374
+ // Total cost to arrive at this node state.
375
+ bit_cost_t m_total_cost;
376
+ uint m_total_complexity;
377
+
378
+ // Parent node index.
379
+ int16 m_parent_index;
380
+
381
+ // Parent node state index (only valid when extreme parsing).
382
+ int8 m_parent_state_index;
383
+ };
384
+
385
+ struct node
386
+ {
387
+ LZHAM_FORCE_INLINE void clear()
388
+ {
389
+ m_num_node_states = 0;
390
+ }
391
+
392
+ uint m_num_node_states;
393
+ enum { cMaxNodeStates = 4 };
394
+ node_state m_node_states[cMaxNodeStates];
395
+
396
+ void add_state(int parent_index, int parent_state_index, const lzdecision &lzdec, state &parent_state, bit_cost_t total_cost, uint total_complexity);
397
+ };
398
+
399
+ state m_start_of_block_state; // state at start of block
400
+
401
+ state m_state; // main thread's current coding state
402
+
403
+ struct raw_parse_thread_state
404
+ {
405
+ uint m_start_ofs;
406
+ uint m_bytes_to_match;
407
+
408
+ state m_initial_state;
409
+
410
+ node m_nodes[cMaxParseGraphNodes + 1];
411
+
412
+ lzham::vector<lzdecision> m_best_decisions;
413
+ bool m_emit_decisions_backwards;
414
+
415
+ lzham::vector<lzpriced_decision> m_temp_decisions;
416
+
417
+ uint m_max_greedy_decisions;
418
+ uint m_greedy_parse_total_bytes_coded;
419
+ bool m_greedy_parse_gave_up;
420
+
421
+ bool m_issue_reset_state_partial;
422
+ bool m_failed;
423
+ };
424
+
425
+ struct parse_thread_state : raw_parse_thread_state
426
+ {
427
+ uint8 m_unused_alignment_array[128 - (sizeof(raw_parse_thread_state) & 127)];
428
+ };
429
+
430
+ uint m_num_parse_threads;
431
+ parse_thread_state m_parse_thread_state[cMaxParseThreads + 1]; // +1 extra for the greedy parser thread (only used for delta compression)
432
+
433
+ volatile atomic32_t m_parse_jobs_remaining;
434
+ semaphore m_parse_jobs_complete;
435
+
436
+ enum { cMaxBlockHistorySize = 6, cBlockHistoryCompRatioScale = 1000U };
437
+ struct block_history
438
+ {
439
+ uint m_comp_size;
440
+ uint m_src_size;
441
+ uint m_ratio;
442
+ bool m_raw_block;
443
+ bool m_reset_update_rate;
444
+ };
445
+ block_history m_block_history[cMaxBlockHistorySize];
446
+ uint m_block_history_size;
447
+ uint m_block_history_next;
448
+ void update_block_history(uint comp_size, uint src_size, uint ratio, bool raw_block, bool reset_update_rate);
449
+ uint get_recent_block_ratio();
450
+ uint get_min_block_ratio();
451
+ uint get_max_block_ratio();
452
+ uint get_total_recent_reset_update_rate();
453
+
454
+ bool send_zlib_header();
455
+ bool init_seed_bytes();
456
+ bool send_final_block();
457
+ bool send_configuration();
458
+ bool extreme_parse(parse_thread_state &parse_state);
459
+ bool optimal_parse(parse_thread_state &parse_state);
460
+ int enumerate_lz_decisions(uint ofs, const state& cur_state, lzham::vector<lzpriced_decision>& decisions, uint min_match_len, uint max_match_len);
461
+ bool greedy_parse(parse_thread_state &parse_state);
462
+ void parse_job_callback(uint64 data, void* pData_ptr);
463
+ bool compress_block(const void* pBuf, uint buf_len);
464
+ bool compress_block_internal(const void* pBuf, uint buf_len);
465
+ bool code_decision(lzdecision lzdec, uint& cur_ofs, uint& bytes_to_match);
466
+ bool send_sync_block(lzham_flush_t flush_type);
467
+ };
468
+
469
+ } // namespace lzham
470
+
471
+
472
+