Class: Omnizip::Algorithms::Zstandard::LdmHashTable
- Inherits:
-
Object
- Object
- Omnizip::Algorithms::Zstandard::LdmHashTable
- Defined in:
- lib/omnizip/algorithms/zstandard/ldm.rb
Overview
Long-Distance Matching sparse hash table (port of the omnizip-rs encoder/ldm.rs).
Hashes every gap-th position into a head/chain table so the
parser can find matches at distances far beyond the normal
match-finder window — up to the full frame size. The table is
pre-populated over the whole input before parsing starts, so
entries may point forward of the current position; find_match
skips those without spending its chain budget.
Constant Summary collapse
- LDM_MAX_CHAIN =
Chain entries walked per find_match (Rust LDM_MAX_CHAIN).
32- MIN_MATCH =
MatchFinder::MIN_MATCH
Instance Method Summary collapse
-
#find_match(src, pos, max_distance, min_match, end_bound) ⇒ Object
Longest match at
poswithinmax_distance, bounded byend_bound(the current block end). -
#initialize(input_len, window_log, gap = 16) ⇒ LdmHashTable
constructor
Hash table and chain sizes are additionally capped by the number of sparse samples so small inputs do not pay for a window-sized table.
-
#insert(src, pos) ⇒ Object
Insert
posinto the table (sparse sampling: every gap-th position only).
Constructor Details
#initialize(input_len, window_log, gap = 16) ⇒ LdmHashTable
Hash table and chain sizes are additionally capped by the number of sparse samples so small inputs do not pay for a window-sized table.
43 44 45 46 47 48 49 50 51 52 |
# File 'lib/omnizip/algorithms/zstandard/ldm.rb', line 43 def initialize(input_len, window_log, gap = 16) samples = (input_len / gap) + 1 hash_log = [[window_log, 21].min, samples.bit_length + 2].min hash_log = 1 if hash_log < 1 @gap = gap @hash_log = hash_log @head = Array.new(1 << hash_log) @chain = Array.new(samples) end |
Instance Method Details
#find_match(src, pos, max_distance, min_match, end_bound) ⇒ Object
Longest match at pos within max_distance, bounded by
end_bound (the current block end). Walks up to MAX_CHAIN
chain entries. Returns [distance, length] or nil.
rubocop:disable Metrics/MethodLength rubocop:disable Metrics/AbcSize rubocop:disable-next Metrics/CyclomaticComplexity
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
# File 'lib/omnizip/algorithms/zstandard/ldm.rb', line 72 def find_match(src, pos, max_distance, min_match, end_bound) return nil if pos + MIN_MATCH > src.bytesize candidate = @head[hash4(src, pos)] best_len = 0 best_dist = 0 chain_count = 0 while candidate && chain_count < LDM_MAX_CHAIN if candidate >= pos candidate = @chain[candidate / @gap] next end dist = pos - candidate break if dist > max_distance len_cap = [end_bound - pos, pos - candidate].min len_cap = 0 if len_cap.negative? len = MatchFinder.count_match(src, pos, src, candidate, len_cap) if len > best_len && len >= min_match best_len = len best_dist = dist end candidate = @chain[candidate / @gap] chain_count += 1 end return nil unless best_len >= min_match && best_dist.positive? [best_dist, best_len] end |
#insert(src, pos) ⇒ Object
Insert pos into the table (sparse sampling: every gap-th
position only).
56 57 58 59 60 61 62 63 |
# File 'lib/omnizip/algorithms/zstandard/ldm.rb', line 56 def insert(src, pos) return unless (pos % @gap).zero? h = hash4(src, pos) idx = pos / @gap @chain[idx] = @head[h] if idx < @chain.length @head[h] = pos end |