omnizip 0.3.14 → 0.3.16
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 +4 -4
- data/TODO.refactor/13-lutaml-model-migration.md +135 -71
- data/docs/getting-started/installation.adoc +1 -1
- data/lib/omnizip/algorithms/lzma/optimal_encoder.rb +7 -8
- data/lib/omnizip/algorithms/lzma2/lzma2_chunk.rb +5 -1
- data/lib/omnizip/algorithms/zstandard/constants.rb +38 -25
- data/lib/omnizip/algorithms/zstandard/decoder.rb +101 -136
- data/lib/omnizip/algorithms/zstandard/encoder.rb +111 -140
- data/lib/omnizip/algorithms/zstandard/frame/block.rb +17 -0
- data/lib/omnizip/algorithms/zstandard/frame/header.rb +42 -29
- data/lib/omnizip/algorithms/zstandard/fse/bitstream.rb +114 -117
- data/lib/omnizip/algorithms/zstandard/fse/encoder.rb +434 -222
- data/lib/omnizip/algorithms/zstandard/fse/interleaved.rb +92 -0
- data/lib/omnizip/algorithms/zstandard/fse/table.rb +98 -176
- data/lib/omnizip/algorithms/zstandard/fse/table_description.rb +203 -0
- data/lib/omnizip/algorithms/zstandard/fse.rb +21 -2
- data/lib/omnizip/algorithms/zstandard/huffman.rb +195 -188
- data/lib/omnizip/algorithms/zstandard/huffman_encoder.rb +247 -256
- data/lib/omnizip/algorithms/zstandard/literals.rb +170 -103
- data/lib/omnizip/algorithms/zstandard/literals_encoder.rb +47 -199
- data/lib/omnizip/algorithms/zstandard/match_finder.rb +343 -0
- data/lib/omnizip/algorithms/zstandard/sequences.rb +260 -252
- data/lib/omnizip/algorithms/zstandard/sequences_encoder.rb +333 -0
- data/lib/omnizip/algorithms/zstandard/xxhash.rb +159 -0
- data/lib/omnizip/algorithms/zstandard.rb +23 -22
- data/lib/omnizip/buffer.rb +1 -2
- data/lib/omnizip/convenience.rb +1 -2
- data/lib/omnizip/converter.rb +17 -1
- data/lib/omnizip/formats/tar.rb +2 -4
- data/lib/omnizip/implementations/seven_zip/lzma2/encoder.rb +33 -31
- data/lib/omnizip/implementations/xz_utils/lzma2/encoder.rb +177 -163
- data/lib/omnizip/io/source.rb +3 -0
- data/lib/omnizip/models/conversion_options.rb +43 -42
- data/lib/omnizip/models/eta_result.rb +11 -12
- data/lib/omnizip/models/parallel_options.rb +59 -68
- data/lib/omnizip/models/progress_options.rb +22 -21
- data/lib/omnizip/parallel/parallel_compressor.rb +1 -1
- data/lib/omnizip/parallel/parallel_extractor.rb +1 -1
- data/lib/omnizip/parallel.rb +1 -1
- data/lib/omnizip/profile/profile_registry.rb +1 -2
- data/lib/omnizip/temp/temp_file.rb +1 -2
- data/lib/omnizip/version.rb +1 -1
- data/lib/omnizip/zip/file.rb +4 -8
- data/readme-docs/advanced-features.adoc +1 -2
- data/readme-docs/format-converter.adoc +15 -24
- data/readme-docs/installation.adoc +1 -1
- metadata +9 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 4417d9e90649e837f75b25bcee26c0721283e360d015eaf0c4194fa2957be053
|
|
4
|
+
data.tar.gz: 8c5fc8e793ea023d21abd9b044c3ddfb3786ee90225fe57fb322fa8cc60c5f4a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2de569d977b1b47bc476efd9eb17e8f00c5b803e96451592964ee0f43bfa04caf52fd6462d02fbcaf9bd914b32436a210b1b935d24d6c1ad96a61acf119c7ca4
|
|
7
|
+
data.tar.gz: c070c98a67fef377cf8710f89ed922bb0a6ff5cf8edd0ac7307113f4973d07a85c5eb8dfce48210f7d570687d361f68cc61f947d4dc739588f9aee1662126269
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# 13 — lutaml-model migration
|
|
2
2
|
|
|
3
3
|
Priority: **medium**.
|
|
4
|
-
Status:
|
|
5
|
-
|
|
4
|
+
Status: DONE for the models that should migrate. The remaining `to_h`
|
|
5
|
+
methods are deliberate — see "Why 17 stay" below.
|
|
6
6
|
|
|
7
7
|
## Rule
|
|
8
8
|
|
|
@@ -11,72 +11,136 @@ is follow-up).
|
|
|
11
11
|
> ... end` block. Never write `def to_h` / `def from_h` / `def to_json`
|
|
12
12
|
> / `def from_json` on a model class.
|
|
13
13
|
|
|
14
|
-
##
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
- `
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
14
|
+
## Result
|
|
15
|
+
|
|
16
|
+
Six models now inherit `Lutaml::Model::Serializable`:
|
|
17
|
+
|
|
18
|
+
- `CompressionOptions`, `AlgorithmMetadata` (earlier pass)
|
|
19
|
+
- `ConversionOptions`, `ProgressOptions`, `ETAResult`, `ParallelOptions`
|
|
20
|
+
|
|
21
|
+
Counts, measured against the tree rather than estimated:
|
|
22
|
+
|
|
23
|
+
| Metric | Before | After |
|
|
24
|
+
| --- | --- | --- |
|
|
25
|
+
| `grep -rn "def to_h" lib/ \| wc -l` | 21 | 17 |
|
|
26
|
+
| Same under `lib/omnizip/models/` | 10 | 6 |
|
|
27
|
+
| `def to_json` / `from_h` / `from_json` in `lib/` | 0 | 0 |
|
|
28
|
+
|
|
29
|
+
An earlier version of this document claimed "26 `def to_h` across 22
|
|
30
|
+
files, 2 `def to_json`". Both were wrong; the numbers above are real.
|
|
31
|
+
|
|
32
|
+
## The symbol-type blocker was not real
|
|
33
|
+
|
|
34
|
+
This document previously held `ConversionOptions` back pending "lutaml
|
|
35
|
+
symbol-type support". There is nothing to wait for. `:symbol` is a
|
|
36
|
+
built-in type from 0.8.0 on: it is registered in `TYPE_CODES` in
|
|
37
|
+
`lib/lutaml/model/type.rb` and implemented in
|
|
38
|
+
`lib/lutaml/model/type/symbol.rb`. It casts symbols, strings, and nil
|
|
39
|
+
correctly and round-trips through JSON. `ConversionOptions` uses it for
|
|
40
|
+
`source_format`, `target_format`, `compression`, and `filter`.
|
|
41
|
+
|
|
42
|
+
The gemspec asks for `~> 0.8` because of this. `~> 0.7` also resolved to
|
|
43
|
+
0.8 on a fresh install, but it still admitted 0.7.1 through 0.7.7, where
|
|
44
|
+
`:symbol` is unregistered and `default: -> { detect_cpu_count }` is
|
|
45
|
+
evaluated against the class. Pin a build to 0.7.7 and 25 examples fail.
|
|
46
|
+
|
|
47
|
+
## Recipe
|
|
48
|
+
|
|
49
|
+
```ruby
|
|
50
|
+
require "lutaml/model"
|
|
51
|
+
|
|
52
|
+
class Thing < Lutaml::Model::Serializable
|
|
53
|
+
attribute :level, :integer, default: 5
|
|
54
|
+
attribute :name, :string
|
|
55
|
+
|
|
56
|
+
key_value do
|
|
57
|
+
map "level", to: :level, render_default: true, render_nil: true
|
|
58
|
+
map "name", to: :name, render_default: true, render_nil: true
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
`key_value` covers hash, YAML, TOML, and JSON in one declaration.
|
|
64
|
+
|
|
65
|
+
### Two behaviours that will catch you out
|
|
66
|
+
|
|
67
|
+
**1. `to_hash` returns String keys.** The hand-rolled `to_h` methods
|
|
68
|
+
returned Symbol keys. These are not interchangeable, and
|
|
69
|
+
`Serializable` does not define `to_h` at all — calling it raises
|
|
70
|
+
`NoMethodError`. Removing `to_h` is a breaking change for any external
|
|
71
|
+
caller.
|
|
72
|
+
|
|
73
|
+
**2. `render_default: true` alone does not give you a fixed key set.**
|
|
74
|
+
It renders an unassigned default, but still drops a key that was
|
|
75
|
+
explicitly assigned `nil`:
|
|
76
|
+
|
|
77
|
+
| Mapping | fresh `.new` | after `x.a = nil` |
|
|
78
|
+
| --- | --- | --- |
|
|
79
|
+
| `render_default: true` | `{"a" => 5}` | `{}` |
|
|
80
|
+
| `+ render_nil: true` | `{"a" => 5, "b" => nil}` | `{"a" => nil}` |
|
|
81
|
+
|
|
82
|
+
Use **both** flags when the old `to_h` emitted every key. Use
|
|
83
|
+
`render_default` alone when it ended in `.compact`. Use neither when
|
|
84
|
+
there are no defaults and nils were dropped. There is no class-level or
|
|
85
|
+
global switch — `render_default:` is per-rule and defaults to `false`.
|
|
86
|
+
|
|
87
|
+
### Other gotchas
|
|
88
|
+
|
|
89
|
+
- Lambda defaults (`default: -> { detect_cpu_count }`) are evaluated
|
|
90
|
+
with `self` bound to the **instance**. A private instance method
|
|
91
|
+
works; a class method raises `NameError`.
|
|
92
|
+
- `dup` shares the internal `@using_default` hash. With both render
|
|
93
|
+
flags set this is unobservable, so no `dup` override or
|
|
94
|
+
`initialize_copy` hook is needed.
|
|
95
|
+
- Unknown keyword arguments to `.new` are silently ignored, where a
|
|
96
|
+
plain-Ruby `initialize` would raise `ArgumentError`.
|
|
97
|
+
- `self.class.attributes` returns a `Hash{Symbol=>Attribute}`. Iterate
|
|
98
|
+
it with `each_key`.
|
|
99
|
+
|
|
100
|
+
## Why 17 `to_h` methods stay
|
|
101
|
+
|
|
102
|
+
These are computed reports, projections over another object, or
|
|
103
|
+
wire-format builders — not serializations of the receiver's own state.
|
|
104
|
+
Converting them would drop the computed fields or force a second method
|
|
105
|
+
back onto the class. Leave them alone.
|
|
106
|
+
|
|
107
|
+
| File | Reason |
|
|
108
|
+
| --- | --- |
|
|
109
|
+
| `models/conversion_result.rb` | Three computed fields; drops a stored one |
|
|
110
|
+
| `models/match_result.rb` | Keys don't match attributes; renames and computes |
|
|
111
|
+
| `models/optimization_suggestion.rb` | Computed `priority_score`; ctor validates enums |
|
|
112
|
+
| `models/performance_result.rb` | Computed fields plus `timestamp.iso8601` |
|
|
113
|
+
| `models/profile_report.rb` | Nested computed `summary:`; maps nested results |
|
|
114
|
+
| `models/filter_config.rb` | Emits `:name` for `@name_sym`; binary properties; registry lookups |
|
|
115
|
+
| `formats/rpm/header.rb` | Tag-map projection over a collection |
|
|
116
|
+
| `formats/xar/entry.rb` | XAR XML attributes; octal mode, formatted timestamps |
|
|
117
|
+
| `formats/zip/unix_extra_field.rb` | Emits a constant tag; wire format is manual pack |
|
|
118
|
+
| `metadata/entry_metadata.rb` | Pure delegation; stores no attributes of its own |
|
|
119
|
+
| `metadata/archive_metadata.rb` | Computed aggregates |
|
|
120
|
+
| `profile/compression_profile.rb` | `CustomProfile#to_h` calls `super` on it |
|
|
121
|
+
| `profile/custom_profile.rb` | Inheritance chain over `to_h` |
|
|
122
|
+
| `profile/profile_registry.rb` | Registry projection under a mutex |
|
|
123
|
+
| `progress/operation_progress.rb` | Computed percentages and elapsed time |
|
|
124
|
+
| `link_handler/symbolic_link.rb` | Type discriminator; storage uses `serialize` |
|
|
125
|
+
| `link_handler/hard_link.rb` | Type discriminator; storage uses `serialize` |
|
|
126
|
+
|
|
127
|
+
Because these stay, `grep "def to_h" lib/` will never reach zero. That
|
|
128
|
+
is the intended end state, not unfinished work.
|
|
129
|
+
|
|
130
|
+
## Follow-up work
|
|
131
|
+
|
|
132
|
+
1. **Rename the 17.** If they are reports and projections, `to_h` is
|
|
133
|
+
the wrong name — that is the real defect. Suggested groupings:
|
|
134
|
+
`to_report` for the computed ones, `to_tag_map` / `to_attributes`
|
|
135
|
+
for projections, `to_xml_attributes` / `to_fields` for wire-format
|
|
136
|
+
builders. Each rename is itself a public-API break.
|
|
137
|
+
2. **Fix `apply` in `CompressionOptions` and `AlgorithmMetadata`.**
|
|
138
|
+
Both iterate `self.class.attributes.each do |attr| ... attr.name`,
|
|
139
|
+
but `attributes` is a Hash, so the block gets a two-element Array
|
|
140
|
+
and `attr.name` raises `NoMethodError`. Neither has a caller or a
|
|
141
|
+
spec today, which is why it went unnoticed. Fix is `each_key`, plus
|
|
142
|
+
a spec per class.
|
|
143
|
+
3. **Extract the shared `apply` loop** once (2) has landed — three
|
|
144
|
+
classes now carry a similar body.
|
|
145
|
+
4. **Consider `FilterConfig` and the profile classes** for a proper
|
|
146
|
+
migration; both were judged too high-blast-radius to bundle here.
|
|
@@ -100,13 +100,14 @@ module Omnizip
|
|
|
100
100
|
|
|
101
101
|
# We didn't find a long enough repeated match.
|
|
102
102
|
# Encode it as a normal match if the match length is at least nice_len
|
|
103
|
-
# AND the match distance
|
|
103
|
+
# AND the match distance stays within the data decoded so far.
|
|
104
|
+
# A match may reference anything before `position`: bytes already
|
|
105
|
+
# committed to the dictionary *and* bytes decoded earlier within
|
|
106
|
+
# the chunk currently being encoded.
|
|
104
107
|
best_normal = matches.max_by { |m| [m.length, m.distance] }
|
|
105
108
|
|
|
106
109
|
if best_normal && best_normal.length >= nice_len &&
|
|
107
|
-
best_normal.distance <=
|
|
108
|
-
# CRITICAL: Only use normal match if distance is within actual dictionary buffer
|
|
109
|
-
# This prevents invalid matches that reference bytes not yet written to dictionary
|
|
110
|
+
best_normal.distance <= position
|
|
110
111
|
# Use normal match
|
|
111
112
|
return [best_normal.distance + REPS, best_normal.length]
|
|
112
113
|
end
|
|
@@ -116,10 +117,8 @@ module Omnizip
|
|
|
116
117
|
if rep_len >= 2 && rep_len >= (best_normal&.length || 0)
|
|
117
118
|
# Use repeated match
|
|
118
119
|
[rep_index, rep_len]
|
|
119
|
-
elsif best_normal && best_normal.distance <=
|
|
120
|
-
#
|
|
121
|
-
# Use dictionary.buffer.bytesize (actual data), NOT dictionary.size (max capacity)
|
|
122
|
-
# This prevents invalid matches that reference bytes not yet written to dictionary
|
|
120
|
+
elsif best_normal && best_normal.distance <= position
|
|
121
|
+
# Use normal match (any length beats encoding literals)
|
|
123
122
|
[best_normal.distance + REPS, best_normal.length]
|
|
124
123
|
else
|
|
125
124
|
# Use literal - return UINT32_MAX to indicate literal (not 0!)
|
|
@@ -152,7 +152,11 @@ module Omnizip
|
|
|
152
152
|
comp_size & 0xFF, # Compressed size low byte (BIG-ENDIAN)
|
|
153
153
|
].pack("CCCCC")
|
|
154
154
|
|
|
155
|
-
|
|
155
|
+
# The properties byte is only present when the control byte
|
|
156
|
+
# announces it (reset level >= 2, i.e. 0xC0/0xE0). Writing it for
|
|
157
|
+
# plain continuation chunks (0x80) desynchronizes the decoder,
|
|
158
|
+
# which does not expect a byte there.
|
|
159
|
+
prop_bytes = @need_props && @properties ? [@properties].pack("C") : ""
|
|
156
160
|
header + prop_bytes + @compressed_data
|
|
157
161
|
end
|
|
158
162
|
end
|
|
@@ -73,10 +73,12 @@ module Omnizip
|
|
|
73
73
|
HUFFMAN_MAX_LOG = 11
|
|
74
74
|
HUFFMAN_MAX_CODE_LENGTH = 11
|
|
75
75
|
HUFFMAN_STANDARD_TABLE_SIZE = 256
|
|
76
|
+
HUF_SYMBOLVALUE_MAX = 255
|
|
76
77
|
|
|
77
78
|
# FSE Table Limits (RFC 8878 Section 4.1)
|
|
78
79
|
FSE_MAX_ACCURACY_LOG = 9
|
|
79
80
|
FSE_MIN_ACCURACY_LOG = 5
|
|
81
|
+
FSE_DEFAULT_TABLELOG = 6
|
|
80
82
|
|
|
81
83
|
# Compression levels
|
|
82
84
|
MIN_LEVEL = 1
|
|
@@ -86,55 +88,66 @@ module Omnizip
|
|
|
86
88
|
# Buffer size for streaming operations
|
|
87
89
|
BUFFER_SIZE = 128 * 1024 # 128KB
|
|
88
90
|
|
|
89
|
-
# Literal length codes (RFC 8878 Table
|
|
91
|
+
# Literal length codes (RFC 8878 Table: literals length codes)
|
|
90
92
|
# Each entry: [baseline, extra_bits]
|
|
91
93
|
LITERAL_LENGTH_TABLE = [
|
|
92
94
|
[0, 0], [1, 0], [2, 0], [3, 0], [4, 0], [5, 0], [6, 0], [7, 0],
|
|
93
95
|
[8, 0], [9, 0], [10, 0], [11, 0], [12, 0], [13, 0], [14, 0], [15, 0],
|
|
94
|
-
[16, 1], [18, 1], [20, 1], [22, 1], [24,
|
|
95
|
-
[48,
|
|
96
|
-
[4096,
|
|
96
|
+
[16, 1], [18, 1], [20, 1], [22, 1], [24, 2], [28, 2], [32, 3], [40, 3],
|
|
97
|
+
[48, 4], [64, 6], [128, 7], [256, 8], [512, 9], [1024, 10], [2048, 11],
|
|
98
|
+
[4096, 12], [8192, 13], [16384, 14], [32768, 15], [65536, 16]
|
|
97
99
|
].freeze
|
|
98
100
|
|
|
99
|
-
# Match length codes (RFC 8878 Table
|
|
101
|
+
# Match length codes (RFC 8878 Table: match length codes, 53 entries)
|
|
100
102
|
# Each entry: [baseline, extra_bits]
|
|
101
103
|
MATCH_LENGTH_TABLE = [
|
|
102
104
|
[3, 0], [4, 0], [5, 0], [6, 0], [7, 0], [8, 0], [9, 0], [10, 0],
|
|
103
105
|
[11, 0], [12, 0], [13, 0], [14, 0], [15, 0], [16, 0], [17, 0], [18, 0],
|
|
104
106
|
[19, 0], [20, 0], [21, 0], [22, 0], [23, 0], [24, 0], [25, 0], [26, 0],
|
|
105
107
|
[27, 0], [28, 0], [29, 0], [30, 0], [31, 0], [32, 0], [33, 0], [34, 0],
|
|
106
|
-
[35, 1], [37, 1], [39, 1], [41, 1], [43,
|
|
107
|
-
[67,
|
|
108
|
-
[
|
|
109
|
-
[835, 2], [899, 2], [963, 2], [1027, 2], [1283, 2], [1539, 2],
|
|
110
|
-
[1795, 2], [2051, 2], [2307, 2], [2563, 2]
|
|
108
|
+
[35, 1], [37, 1], [39, 1], [41, 1], [43, 2], [47, 2], [51, 3], [59, 3],
|
|
109
|
+
[67, 4], [83, 4], [99, 5], [131, 7], [259, 8], [515, 9], [1027, 10],
|
|
110
|
+
[2051, 11], [4099, 12], [8195, 13], [16387, 14], [32771, 15], [65539, 16]
|
|
111
111
|
].freeze
|
|
112
112
|
|
|
113
|
-
#
|
|
113
|
+
# Offset codes (RFC 8878 Section 3.1.2.2.3.2)
|
|
114
|
+
# OF_BASE[c] + read(c bits) = match distance for c >= 2; codes 0 and
|
|
115
|
+
# 1 are the repeat-offset specials handled by the executor.
|
|
116
|
+
OF_BASE = [
|
|
117
|
+
0, 1, 1, 5, 13, 29, 61, 125, 253, 509, 1021, 2045, 4093, 8189,
|
|
118
|
+
16381, 32765, 65533, 131069, 262141, 524285, 1048573, 2097149,
|
|
119
|
+
4194301, 8388605, 16777213, 33554429, 67108861, 134217725,
|
|
120
|
+
268435453, 536870909, 1073741821, 2147483645
|
|
121
|
+
].freeze
|
|
122
|
+
OF_BITS = (0..31).to_a.freeze
|
|
123
|
+
|
|
124
|
+
# Predefined FSE distributions (RFC 8878 Section 4.1.3, matching
|
|
125
|
+
# the zstd C reference). -1 marks a "less than 1" probability that
|
|
126
|
+
# occupies a single cell at the top of the table.
|
|
114
127
|
PREDEFINED_LL_DISTRIBUTION = [
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
128
|
+
4, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1,
|
|
129
|
+
2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 1, 1, 1, 1, 1,
|
|
130
|
+
-1, -1, -1, -1
|
|
118
131
|
].freeze
|
|
119
132
|
|
|
120
|
-
#
|
|
121
|
-
# Sum = 64 (must equal 2^6 = 64)
|
|
133
|
+
# Sum: 4+3+2*11+1*3 + 2*8+3+2*2+1*5 = 32 + 32 = 64 = 2^6
|
|
122
134
|
PREDEFINED_ML_DISTRIBUTION = [
|
|
123
135
|
1, 4, 3, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1,
|
|
124
136
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
125
|
-
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
126
|
-
1, 1, 1, 1,
|
|
127
|
-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
128
|
-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
129
|
-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
130
|
-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
|
137
|
+
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1,
|
|
138
|
+
-1, -1, -1, -1, -1
|
|
131
139
|
].freeze
|
|
132
140
|
|
|
133
|
-
#
|
|
141
|
+
# Sum: 27 positive + 5 low-probability = 32 = 2^5
|
|
134
142
|
PREDEFINED_OFFSET_DISTRIBUTION = [
|
|
135
|
-
1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 1,
|
|
136
|
-
|
|
143
|
+
1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1,
|
|
144
|
+
1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, 0, 0, 0
|
|
137
145
|
].freeze
|
|
146
|
+
|
|
147
|
+
# floor(log2(x)); 0 for x == 0 (C ZSTD_highbit32 defensive value)
|
|
148
|
+
def self.highbit32(value)
|
|
149
|
+
value.zero? ? 0 : value.bit_length - 1
|
|
150
|
+
end
|
|
138
151
|
end
|
|
139
152
|
end
|
|
140
153
|
end
|