blob: d6a415b3a17cb266e0c767d295abe47a404b2876 [file] [log] [blame]
Zoltan Szabadka79e99af2013-10-23 13:06:13 +02001// Copyright 2010 Google Inc. All Rights Reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14//
15// A (forgetful) hash table to the data seen by the compressor, to
16// help create backward references to previous data.
17
18#ifndef BROTLI_ENC_HASH_H_
19#define BROTLI_ENC_HASH_H_
20
21#include <stddef.h>
22#include <stdint.h>
23#include <string.h>
24#include <sys/types.h>
25#include <algorithm>
Roderick Sheeter2e5995b2013-12-12 10:43:05 -080026#include <cstdlib>
Zoltan Szabadka2733d6c2014-02-17 14:25:36 +010027#include <string>
Zoltan Szabadka79e99af2013-10-23 13:06:13 +020028
Zoltan Szabadka2733d6c2014-02-17 14:25:36 +010029#include "./transform.h"
Zoltan Szabadka79e99af2013-10-23 13:06:13 +020030#include "./fast_log.h"
31#include "./find_match_length.h"
32#include "./port.h"
33
34namespace brotli {
35
36// kHashMul32 multiplier has these properties:
37// * The multiplier must be odd. Otherwise we may lose the highest bit.
38// * No long streaks of 1s or 0s.
39// * There is no effort to ensure that it is a prime, the oddity is enough
40// for this use.
41// * The number has been tuned heuristically against compression benchmarks.
42static const uint32_t kHashMul32 = 0x1e35a7bd;
43
44inline uint32_t Hash3Bytes(const uint8_t *data, const int bits) {
45 uint32_t h = (BROTLI_UNALIGNED_LOAD32(data) & 0xffffff) * kHashMul32;
46 // The higher bits contain more mixture from the multiplication,
47 // so we take our results from there.
48 return h >> (32 - bits);
49}
50
51// Usually, we always choose the longest backward reference. This function
52// allows for the exception of that rule.
53//
54// If we choose a backward reference that is further away, it will
55// usually be coded with more bits. We approximate this by assuming
56// log2(distance). If the distance can be expressed in terms of the
57// last four distances, we use some heuristic constants to estimate
58// the bits cost. For the first up to four literals we use the bit
59// cost of the literals from the literal cost model, after that we
60// use the average bit cost of the cost model.
61//
62// This function is used to sometimes discard a longer backward reference
63// when it is not much longer and the bit cost for encoding it is more
64// than the saved literals.
65inline double BackwardReferenceScore(double average_cost,
66 double start_cost4,
67 double start_cost3,
68 double start_cost2,
69 int copy_length,
70 int backward_reference_offset,
71 int last_distance1,
72 int last_distance2,
73 int last_distance3,
74 int last_distance4) {
75 double retval = 0;
76 switch (copy_length) {
77 case 2: retval = start_cost2; break;
78 case 3: retval = start_cost3; break;
79 default: retval = start_cost4 + (copy_length - 4) * average_cost; break;
80 }
81 int diff_last1 = abs(backward_reference_offset - last_distance1);
82 int diff_last2 = abs(backward_reference_offset - last_distance2);
83 if (diff_last1 == 0) {
84 retval += 0.6;
85 } else if (diff_last1 < 4) {
86 retval -= 0.9 + 0.03 * diff_last1;
87 } else if (diff_last2 < 4) {
88 retval -= 0.95 + 0.1 * diff_last2;
89 } else if (backward_reference_offset == last_distance3) {
90 retval -= 1.17;
91 } else if (backward_reference_offset == last_distance4) {
92 retval -= 1.27;
93 } else {
94 retval -= 1.20 * Log2Floor(backward_reference_offset);
95 }
96 return retval;
97}
98
99// A (forgetful) hash table to the data seen by the compressor, to
100// help create backward references to previous data.
101//
102// This is a hash map of fixed size (kBucketSize) to a ring buffer of
103// fixed size (kBlockSize). The ring buffer contains the last kBlockSize
104// index positions of the given hash key in the compressed data.
105template <int kBucketBits, int kBlockBits>
106class HashLongestMatch {
107 public:
108 HashLongestMatch()
Zoltan Szabadka1571db32013-11-15 19:02:17 +0100109 : last_distance1_(4),
Zoltan Szabadka79e99af2013-10-23 13:06:13 +0200110 last_distance2_(11),
111 last_distance3_(15),
112 last_distance4_(16),
113 insert_length_(0),
114 average_cost_(5.4) {
115 Reset();
116 }
117 void Reset() {
118 std::fill(&num_[0], &num_[sizeof(num_) / sizeof(num_[0])], 0);
119 }
Zoltan Szabadka79e99af2013-10-23 13:06:13 +0200120
121 // Look at 3 bytes at data.
122 // Compute a hash from these, and store the value of ix at that position.
123 inline void Store(const uint8_t *data, const int ix) {
124 const uint32_t key = Hash3Bytes(data, kBucketBits);
125 const int minor_ix = num_[key] & kBlockMask;
126 buckets_[key][minor_ix] = ix;
127 ++num_[key];
128 }
129
130 // Store hashes for a range of data.
131 void StoreHashes(const uint8_t *data, size_t len, int startix, int mask) {
132 for (int p = 0; p < len; ++p) {
133 Store(&data[p & mask], startix + p);
134 }
135 }
136
137 // Find a longest backward match of &data[cur_ix] up to the length of
138 // max_length.
139 //
140 // Does not look for matches longer than max_length.
141 // Does not look for matches further away than max_backward.
142 // Writes the best found match length into best_len_out.
143 // Writes the index (&data[index]) offset from the start of the best match
144 // into best_distance_out.
145 // Write the score of the best match into best_score_out.
146 bool FindLongestMatch(const uint8_t * __restrict data,
Zoltan Szabadka1571db32013-11-15 19:02:17 +0100147 const float * __restrict literal_cost,
148 const size_t ring_buffer_mask,
Zoltan Szabadka79e99af2013-10-23 13:06:13 +0200149 const uint32_t cur_ix,
150 uint32_t max_length,
151 const uint32_t max_backward,
152 size_t * __restrict best_len_out,
Roderick Sheeter437bbad2013-11-19 14:32:56 -0800153 size_t * __restrict best_len_code_out,
Zoltan Szabadka79e99af2013-10-23 13:06:13 +0200154 size_t * __restrict best_distance_out,
Zoltan Szabadkacbd5cb52014-02-14 15:04:23 +0100155 double * __restrict best_score_out,
156 bool * __restrict in_dictionary) {
157 *in_dictionary = true;
158 *best_len_code_out = 0;
Zoltan Szabadka1571db32013-11-15 19:02:17 +0100159 const size_t cur_ix_masked = cur_ix & ring_buffer_mask;
160 const double start_cost4 = literal_cost == NULL ? 20 :
161 literal_cost[cur_ix_masked] +
162 literal_cost[(cur_ix + 1) & ring_buffer_mask] +
163 literal_cost[(cur_ix + 2) & ring_buffer_mask] +
164 literal_cost[(cur_ix + 3) & ring_buffer_mask];
165 const double start_cost3 = literal_cost == NULL ? 15 :
166 literal_cost[cur_ix_masked] +
167 literal_cost[(cur_ix + 1) & ring_buffer_mask] +
168 literal_cost[(cur_ix + 2) & ring_buffer_mask] + 0.3;
169 double start_cost2 = literal_cost == NULL ? 10 :
170 literal_cost[cur_ix_masked] +
171 literal_cost[(cur_ix + 1) & ring_buffer_mask] + 1.2;
Zoltan Szabadka79e99af2013-10-23 13:06:13 +0200172 bool match_found = false;
173 // Don't accept a short copy from far away.
Zoltan Szabadkacbd5cb52014-02-14 15:04:23 +0100174 double best_score = 8.11;
Zoltan Szabadka79e99af2013-10-23 13:06:13 +0200175 if (insert_length_ < 4) {
Zoltan Szabadkacbd5cb52014-02-14 15:04:23 +0100176 double cost_diff[4] = { 0.10, 0.04, 0.02, 0.01 };
Zoltan Szabadka79e99af2013-10-23 13:06:13 +0200177 best_score += cost_diff[insert_length_];
178 }
179 size_t best_len = *best_len_out;
180 *best_len_out = 0;
181 size_t best_ix = 1;
182 // Try last distance first.
183 for (int i = 0; i < 16; ++i) {
Zoltan Szabadka1571db32013-11-15 19:02:17 +0100184 size_t prev_ix = cur_ix;
Zoltan Szabadka79e99af2013-10-23 13:06:13 +0200185 switch(i) {
186 case 0: prev_ix -= last_distance1_; break;
187 case 1: prev_ix -= last_distance2_; break;
188 case 2: prev_ix -= last_distance3_; break;
189 case 3: prev_ix -= last_distance4_; break;
190
191 case 4: prev_ix -= last_distance1_ - 1; break;
192 case 5: prev_ix -= last_distance1_ + 1; break;
193 case 6: prev_ix -= last_distance1_ - 2; break;
194 case 7: prev_ix -= last_distance1_ + 2; break;
195 case 8: prev_ix -= last_distance1_ - 3; break;
196 case 9: prev_ix -= last_distance1_ + 3; break;
197
198 case 10: prev_ix -= last_distance2_ - 1; break;
199 case 11: prev_ix -= last_distance2_ + 1; break;
200 case 12: prev_ix -= last_distance2_ - 2; break;
201 case 13: prev_ix -= last_distance2_ + 2; break;
202 case 14: prev_ix -= last_distance2_ - 3; break;
203 case 15: prev_ix -= last_distance2_ + 3; break;
204 }
205 if (prev_ix >= cur_ix) {
206 continue;
207 }
208 const size_t backward = cur_ix - prev_ix;
209 if (PREDICT_FALSE(backward > max_backward)) {
210 continue;
211 }
Zoltan Szabadka1571db32013-11-15 19:02:17 +0100212 prev_ix &= ring_buffer_mask;
Zoltan Szabadka40955ce2014-01-06 16:01:57 +0100213 if (cur_ix_masked + best_len > ring_buffer_mask ||
214 prev_ix + best_len > ring_buffer_mask ||
215 data[cur_ix_masked + best_len] != data[prev_ix + best_len]) {
Zoltan Szabadka79e99af2013-10-23 13:06:13 +0200216 continue;
217 }
218 const size_t len =
Zoltan Szabadka1571db32013-11-15 19:02:17 +0100219 FindMatchLengthWithLimit(&data[prev_ix], &data[cur_ix_masked],
220 max_length);
Zoltan Szabadka79e99af2013-10-23 13:06:13 +0200221 if (len >= 3 || (len == 2 && i < 2)) {
222 // Comparing for >= 2 does not change the semantics, but just saves for
223 // a few unnecessary binary logarithms in backward reference score,
224 // since we are not interested in such short matches.
225 const double score = BackwardReferenceScore(average_cost_,
226 start_cost4,
227 start_cost3,
228 start_cost2,
229 len, backward,
230 last_distance1_,
231 last_distance2_,
232 last_distance3_,
233 last_distance4_);
234 if (best_score < score) {
235 best_score = score;
236 best_len = len;
237 best_ix = backward;
238 *best_len_out = best_len;
Roderick Sheeter437bbad2013-11-19 14:32:56 -0800239 *best_len_code_out = best_len;
Zoltan Szabadka79e99af2013-10-23 13:06:13 +0200240 *best_distance_out = best_ix;
241 *best_score_out = best_score;
242 match_found = true;
Zoltan Szabadkacbd5cb52014-02-14 15:04:23 +0100243 *in_dictionary = backward > max_backward;
Zoltan Szabadka79e99af2013-10-23 13:06:13 +0200244 }
245 }
246 }
Zoltan Szabadka1571db32013-11-15 19:02:17 +0100247 const uint32_t key = Hash3Bytes(&data[cur_ix_masked], kBucketBits);
Roderick Sheeter437bbad2013-11-19 14:32:56 -0800248 const int * __restrict const bucket = &buckets_[key][0];
Zoltan Szabadka79e99af2013-10-23 13:06:13 +0200249 const int down = (num_[key] > kBlockSize) ? (num_[key] - kBlockSize) : 0;
250 int stop = int(cur_ix) - 64;
251 if (stop < 0) { stop = 0; }
252
253 start_cost2 -= 1.0;
254 for (int i = cur_ix - 1; i > stop; --i) {
255 size_t prev_ix = i;
256 const size_t backward = cur_ix - prev_ix;
257 if (PREDICT_FALSE(backward > max_backward)) {
258 break;
259 }
Zoltan Szabadka1571db32013-11-15 19:02:17 +0100260 prev_ix &= ring_buffer_mask;
261 if (data[cur_ix_masked] != data[prev_ix] ||
262 data[cur_ix_masked + 1] != data[prev_ix + 1]) {
Zoltan Szabadka79e99af2013-10-23 13:06:13 +0200263 continue;
264 }
265 int len = 2;
Zoltan Szabadkacbd5cb52014-02-14 15:04:23 +0100266 const double score = start_cost2 - 2.3 * Log2Floor(backward);
Zoltan Szabadka79e99af2013-10-23 13:06:13 +0200267
268 if (best_score < score) {
269 best_score = score;
270 best_len = len;
271 best_ix = backward;
272 *best_len_out = best_len;
Roderick Sheeter437bbad2013-11-19 14:32:56 -0800273 *best_len_code_out = best_len;
Zoltan Szabadka79e99af2013-10-23 13:06:13 +0200274 *best_distance_out = best_ix;
275 match_found = true;
276 }
277 }
278 for (int i = num_[key] - 1; i >= down; --i) {
Roderick Sheeter437bbad2013-11-19 14:32:56 -0800279 int prev_ix = bucket[i & kBlockMask];
280 if (prev_ix < 0) {
Zoltan Szabadka2733d6c2014-02-17 14:25:36 +0100281 prev_ix *= -1;
282 prev_ix -= 1;
283 int copy_len_code = prev_ix >> 20;
284 int word_id = prev_ix & 0xfffff;
285 std::string word = GetTransformedDictionaryWord(copy_len_code, word_id);
286 int len = word.size();
287 const size_t backward = max_backward + word_id + 1;
288 bool word_matched = (len >= 3 && len <= max_length);
289 for (int k = 0; k < len && word_matched; ++k) {
290 if ((uint8_t)(word[k]) != data[cur_ix_masked + k]) {
291 word_matched = false;
292 }
293 }
294 if (word_matched) {
295 const double score = BackwardReferenceScore(average_cost_,
296 start_cost4,
297 start_cost3,
298 start_cost2,
299 len, backward,
300 last_distance1_,
301 last_distance2_,
302 last_distance3_,
303 last_distance4_);
304 if (best_score < score) {
305 best_score = score;
306 best_len = len;
307 best_ix = backward;
308 *best_len_out = best_len;
309 *best_len_code_out = copy_len_code;
310 *best_distance_out = best_ix;
311 *best_score_out = best_score;
312 match_found = true;
313 *in_dictionary = true;
314 }
315 }
Roderick Sheeter437bbad2013-11-19 14:32:56 -0800316 } else {
317 const size_t backward = cur_ix - prev_ix;
318 if (PREDICT_FALSE(backward > max_backward)) {
319 break;
320 }
321 prev_ix &= ring_buffer_mask;
Zoltan Szabadka40955ce2014-01-06 16:01:57 +0100322 if (cur_ix_masked + best_len > ring_buffer_mask ||
323 prev_ix + best_len > ring_buffer_mask ||
324 data[cur_ix_masked + best_len] != data[prev_ix + best_len]) {
Roderick Sheeter437bbad2013-11-19 14:32:56 -0800325 continue;
326 }
327 const size_t len =
328 FindMatchLengthWithLimit(&data[prev_ix], &data[cur_ix_masked],
329 max_length);
330 if (len >= 3) {
331 // Comparing for >= 3 does not change the semantics, but just saves
332 // for a few unnecessary binary logarithms in backward reference
333 // score, since we are not interested in such short matches.
334 const double score = BackwardReferenceScore(average_cost_,
335 start_cost4,
336 start_cost3,
337 start_cost2,
338 len, backward,
339 last_distance1_,
340 last_distance2_,
341 last_distance3_,
342 last_distance4_);
343 if (best_score < score) {
344 best_score = score;
345 best_len = len;
346 best_ix = backward;
347 *best_len_out = best_len;
348 *best_len_code_out = best_len;
349 *best_distance_out = best_ix;
350 *best_score_out = best_score;
351 match_found = true;
Zoltan Szabadkacbd5cb52014-02-14 15:04:23 +0100352 *in_dictionary = false;
Roderick Sheeter437bbad2013-11-19 14:32:56 -0800353 }
Zoltan Szabadka79e99af2013-10-23 13:06:13 +0200354 }
355 }
356 }
357 return match_found;
358 }
359
360 void set_last_distance(int v) {
361 if (last_distance1_ != v) {
362 last_distance4_ = last_distance3_;
363 last_distance3_ = last_distance2_;
364 last_distance2_ = last_distance1_;
365 last_distance1_ = v;
366 }
367 }
368
369 int last_distance() const { return last_distance1_; }
370
371 void set_insert_length(int v) { insert_length_ = v; }
372
373 void set_average_cost(double v) { average_cost_ = v; }
374
375 private:
376 // Number of hash buckets.
377 static const uint32_t kBucketSize = 1 << kBucketBits;
378
379 // Only kBlockSize newest backward references are kept,
380 // and the older are forgotten.
381 static const uint32_t kBlockSize = 1 << kBlockBits;
382
383 // Mask for accessing entries in a block (in a ringbuffer manner).
384 static const uint32_t kBlockMask = (1 << kBlockBits) - 1;
385
386 // Number of entries in a particular bucket.
387 uint16_t num_[kBucketSize];
388
389 // Buckets containing kBlockSize of backward references.
Roderick Sheeter437bbad2013-11-19 14:32:56 -0800390 int buckets_[kBucketSize][kBlockSize];
Zoltan Szabadka79e99af2013-10-23 13:06:13 +0200391
Zoltan Szabadka79e99af2013-10-23 13:06:13 +0200392 int last_distance1_;
393 int last_distance2_;
394 int last_distance3_;
395 int last_distance4_;
396
397 // Cost adjustment for how many literals we are planning to insert
398 // anyway.
399 int insert_length_;
400
401 double average_cost_;
402};
403
Zoltan Szabadka1571db32013-11-15 19:02:17 +0100404typedef HashLongestMatch<13, 11> Hasher;
405
Zoltan Szabadka79e99af2013-10-23 13:06:13 +0200406} // namespace brotli
407
408#endif // BROTLI_ENC_HASH_H_