aboutsummaryrefslogtreecommitdiff
path: root/brotli/enc/hash.h
diff options
context:
space:
mode:
Diffstat (limited to 'brotli/enc/hash.h')
-rw-r--r--brotli/enc/hash.h51
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;
}
}
}