diff options
Diffstat (limited to 'brotli/enc/hash.h')
-rw-r--r-- | brotli/enc/hash.h | 51 |
1 files changed, 46 insertions, 5 deletions
diff --git a/brotli/enc/hash.h b/brotli/enc/hash.h index cb38e8f..d6a415b 100644 --- a/brotli/enc/hash.h +++ b/brotli/enc/hash.h @@ -24,7 +24,9 @@ #include <sys/types.h> #include <algorithm> #include <cstdlib> +#include <string> +#include "./transform.h" #include "./fast_log.h" #include "./find_match_length.h" #include "./port.h" @@ -150,7 +152,10 @@ class HashLongestMatch { size_t * __restrict best_len_out, size_t * __restrict best_len_code_out, size_t * __restrict best_distance_out, - double * __restrict best_score_out) { + double * __restrict best_score_out, + bool * __restrict in_dictionary) { + *in_dictionary = true; + *best_len_code_out = 0; const size_t cur_ix_masked = cur_ix & ring_buffer_mask; const double start_cost4 = literal_cost == NULL ? 20 : literal_cost[cur_ix_masked] + @@ -166,9 +171,9 @@ class HashLongestMatch { literal_cost[(cur_ix + 1) & ring_buffer_mask] + 1.2; bool match_found = false; // Don't accept a short copy from far away. - double best_score = 8.25; + double best_score = 8.11; if (insert_length_ < 4) { - double cost_diff[4] = { 0.20, 0.09, 0.05, 0.03 }; + double cost_diff[4] = { 0.10, 0.04, 0.02, 0.01 }; best_score += cost_diff[insert_length_]; } size_t best_len = *best_len_out; @@ -235,6 +240,7 @@ class HashLongestMatch { *best_distance_out = best_ix; *best_score_out = best_score; match_found = true; + *in_dictionary = backward > max_backward; } } } @@ -257,7 +263,7 @@ class HashLongestMatch { continue; } int len = 2; - const double score = start_cost2 - 1.70 * Log2Floor(backward); + const double score = start_cost2 - 2.3 * Log2Floor(backward); if (best_score < score) { best_score = score; @@ -272,7 +278,41 @@ class HashLongestMatch { for (int i = num_[key] - 1; i >= down; --i) { int prev_ix = bucket[i & kBlockMask]; if (prev_ix < 0) { - continue; + prev_ix *= -1; + prev_ix -= 1; + int copy_len_code = prev_ix >> 20; + int word_id = prev_ix & 0xfffff; + std::string word = GetTransformedDictionaryWord(copy_len_code, word_id); + int len = word.size(); + const size_t backward = max_backward + word_id + 1; + bool word_matched = (len >= 3 && len <= max_length); + for (int k = 0; k < len && word_matched; ++k) { + if ((uint8_t)(word[k]) != data[cur_ix_masked + k]) { + word_matched = false; + } + } + if (word_matched) { + const double score = BackwardReferenceScore(average_cost_, + start_cost4, + start_cost3, + start_cost2, + len, backward, + last_distance1_, + last_distance2_, + last_distance3_, + last_distance4_); + if (best_score < score) { + best_score = score; + best_len = len; + best_ix = backward; + *best_len_out = best_len; + *best_len_code_out = copy_len_code; + *best_distance_out = best_ix; + *best_score_out = best_score; + match_found = true; + *in_dictionary = true; + } + } } else { const size_t backward = cur_ix - prev_ix; if (PREDICT_FALSE(backward > max_backward)) { @@ -309,6 +349,7 @@ class HashLongestMatch { *best_distance_out = best_ix; *best_score_out = best_score; match_found = true; + *in_dictionary = false; } } } |