xref: /aosp_15_r20/external/brotli/c/enc/hash.h (revision f4ee7fba7774faf2a30f13154332c0a06550dbc4)
1*f4ee7fbaSAndroid Build Coastguard Worker /* Copyright 2010 Google Inc. All Rights Reserved.
2*f4ee7fbaSAndroid Build Coastguard Worker 
3*f4ee7fbaSAndroid Build Coastguard Worker    Distributed under MIT license.
4*f4ee7fbaSAndroid Build Coastguard Worker    See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
5*f4ee7fbaSAndroid Build Coastguard Worker */
6*f4ee7fbaSAndroid Build Coastguard Worker 
7*f4ee7fbaSAndroid Build Coastguard Worker /* A (forgetful) hash table to the data seen by the compressor, to
8*f4ee7fbaSAndroid Build Coastguard Worker    help create backward references to previous data. */
9*f4ee7fbaSAndroid Build Coastguard Worker 
10*f4ee7fbaSAndroid Build Coastguard Worker #ifndef BROTLI_ENC_HASH_H_
11*f4ee7fbaSAndroid Build Coastguard Worker #define BROTLI_ENC_HASH_H_
12*f4ee7fbaSAndroid Build Coastguard Worker 
13*f4ee7fbaSAndroid Build Coastguard Worker #include <string.h>  /* memcmp, memset */
14*f4ee7fbaSAndroid Build Coastguard Worker 
15*f4ee7fbaSAndroid Build Coastguard Worker #include "../common/constants.h"
16*f4ee7fbaSAndroid Build Coastguard Worker #include "../common/dictionary.h"
17*f4ee7fbaSAndroid Build Coastguard Worker #include "../common/platform.h"
18*f4ee7fbaSAndroid Build Coastguard Worker #include <brotli/types.h>
19*f4ee7fbaSAndroid Build Coastguard Worker #include "./encoder_dict.h"
20*f4ee7fbaSAndroid Build Coastguard Worker #include "./fast_log.h"
21*f4ee7fbaSAndroid Build Coastguard Worker #include "./find_match_length.h"
22*f4ee7fbaSAndroid Build Coastguard Worker #include "./memory.h"
23*f4ee7fbaSAndroid Build Coastguard Worker #include "./quality.h"
24*f4ee7fbaSAndroid Build Coastguard Worker #include "./static_dict.h"
25*f4ee7fbaSAndroid Build Coastguard Worker 
26*f4ee7fbaSAndroid Build Coastguard Worker #if defined(__cplusplus) || defined(c_plusplus)
27*f4ee7fbaSAndroid Build Coastguard Worker extern "C" {
28*f4ee7fbaSAndroid Build Coastguard Worker #endif
29*f4ee7fbaSAndroid Build Coastguard Worker 
30*f4ee7fbaSAndroid Build Coastguard Worker typedef struct {
31*f4ee7fbaSAndroid Build Coastguard Worker   /* Dynamically allocated area; first member for quickest access. */
32*f4ee7fbaSAndroid Build Coastguard Worker   void* extra;
33*f4ee7fbaSAndroid Build Coastguard Worker 
34*f4ee7fbaSAndroid Build Coastguard Worker   size_t dict_num_lookups;
35*f4ee7fbaSAndroid Build Coastguard Worker   size_t dict_num_matches;
36*f4ee7fbaSAndroid Build Coastguard Worker 
37*f4ee7fbaSAndroid Build Coastguard Worker   BrotliHasherParams params;
38*f4ee7fbaSAndroid Build Coastguard Worker 
39*f4ee7fbaSAndroid Build Coastguard Worker   /* False if hasher needs to be "prepared" before use. */
40*f4ee7fbaSAndroid Build Coastguard Worker   BROTLI_BOOL is_prepared_;
41*f4ee7fbaSAndroid Build Coastguard Worker } HasherCommon;
42*f4ee7fbaSAndroid Build Coastguard Worker 
43*f4ee7fbaSAndroid Build Coastguard Worker #define score_t size_t
44*f4ee7fbaSAndroid Build Coastguard Worker 
45*f4ee7fbaSAndroid Build Coastguard Worker static const uint32_t kCutoffTransformsCount = 10;
46*f4ee7fbaSAndroid Build Coastguard Worker /*   0,  12,   27,    23,    42,    63,    56,    48,    59,    64 */
47*f4ee7fbaSAndroid Build Coastguard Worker /* 0+0, 4+8, 8+19, 12+11, 16+26, 20+43, 24+32, 28+20, 32+27, 36+28 */
48*f4ee7fbaSAndroid Build Coastguard Worker static const uint64_t kCutoffTransforms =
49*f4ee7fbaSAndroid Build Coastguard Worker     BROTLI_MAKE_UINT64_T(0x071B520A, 0xDA2D3200);
50*f4ee7fbaSAndroid Build Coastguard Worker 
51*f4ee7fbaSAndroid Build Coastguard Worker typedef struct HasherSearchResult {
52*f4ee7fbaSAndroid Build Coastguard Worker   size_t len;
53*f4ee7fbaSAndroid Build Coastguard Worker   size_t distance;
54*f4ee7fbaSAndroid Build Coastguard Worker   score_t score;
55*f4ee7fbaSAndroid Build Coastguard Worker   int len_code_delta; /* == len_code - len */
56*f4ee7fbaSAndroid Build Coastguard Worker } HasherSearchResult;
57*f4ee7fbaSAndroid Build Coastguard Worker 
58*f4ee7fbaSAndroid Build Coastguard Worker /* kHashMul32 multiplier has these properties:
59*f4ee7fbaSAndroid Build Coastguard Worker    * The multiplier must be odd. Otherwise we may lose the highest bit.
60*f4ee7fbaSAndroid Build Coastguard Worker    * No long streaks of ones or zeros.
61*f4ee7fbaSAndroid Build Coastguard Worker    * There is no effort to ensure that it is a prime, the oddity is enough
62*f4ee7fbaSAndroid Build Coastguard Worker      for this use.
63*f4ee7fbaSAndroid Build Coastguard Worker    * The number has been tuned heuristically against compression benchmarks. */
64*f4ee7fbaSAndroid Build Coastguard Worker static const uint32_t kHashMul32 = 0x1E35A7BD;
65*f4ee7fbaSAndroid Build Coastguard Worker static const uint64_t kHashMul64 = BROTLI_MAKE_UINT64_T(0x1E35A7BD, 0x1E35A7BD);
66*f4ee7fbaSAndroid Build Coastguard Worker static const uint64_t kHashMul64Long =
67*f4ee7fbaSAndroid Build Coastguard Worker     BROTLI_MAKE_UINT64_T(0x1FE35A7Bu, 0xD3579BD3u);
68*f4ee7fbaSAndroid Build Coastguard Worker 
Hash14(const uint8_t * data)69*f4ee7fbaSAndroid Build Coastguard Worker static BROTLI_INLINE uint32_t Hash14(const uint8_t* data) {
70*f4ee7fbaSAndroid Build Coastguard Worker   uint32_t h = BROTLI_UNALIGNED_LOAD32LE(data) * kHashMul32;
71*f4ee7fbaSAndroid Build Coastguard Worker   /* The higher bits contain more mixture from the multiplication,
72*f4ee7fbaSAndroid Build Coastguard Worker      so we take our results from there. */
73*f4ee7fbaSAndroid Build Coastguard Worker   return h >> (32 - 14);
74*f4ee7fbaSAndroid Build Coastguard Worker }
75*f4ee7fbaSAndroid Build Coastguard Worker 
PrepareDistanceCache(int * BROTLI_RESTRICT distance_cache,const int num_distances)76*f4ee7fbaSAndroid Build Coastguard Worker static BROTLI_INLINE void PrepareDistanceCache(
77*f4ee7fbaSAndroid Build Coastguard Worker     int* BROTLI_RESTRICT distance_cache, const int num_distances) {
78*f4ee7fbaSAndroid Build Coastguard Worker   if (num_distances > 4) {
79*f4ee7fbaSAndroid Build Coastguard Worker     int last_distance = distance_cache[0];
80*f4ee7fbaSAndroid Build Coastguard Worker     distance_cache[4] = last_distance - 1;
81*f4ee7fbaSAndroid Build Coastguard Worker     distance_cache[5] = last_distance + 1;
82*f4ee7fbaSAndroid Build Coastguard Worker     distance_cache[6] = last_distance - 2;
83*f4ee7fbaSAndroid Build Coastguard Worker     distance_cache[7] = last_distance + 2;
84*f4ee7fbaSAndroid Build Coastguard Worker     distance_cache[8] = last_distance - 3;
85*f4ee7fbaSAndroid Build Coastguard Worker     distance_cache[9] = last_distance + 3;
86*f4ee7fbaSAndroid Build Coastguard Worker     if (num_distances > 10) {
87*f4ee7fbaSAndroid Build Coastguard Worker       int next_last_distance = distance_cache[1];
88*f4ee7fbaSAndroid Build Coastguard Worker       distance_cache[10] = next_last_distance - 1;
89*f4ee7fbaSAndroid Build Coastguard Worker       distance_cache[11] = next_last_distance + 1;
90*f4ee7fbaSAndroid Build Coastguard Worker       distance_cache[12] = next_last_distance - 2;
91*f4ee7fbaSAndroid Build Coastguard Worker       distance_cache[13] = next_last_distance + 2;
92*f4ee7fbaSAndroid Build Coastguard Worker       distance_cache[14] = next_last_distance - 3;
93*f4ee7fbaSAndroid Build Coastguard Worker       distance_cache[15] = next_last_distance + 3;
94*f4ee7fbaSAndroid Build Coastguard Worker     }
95*f4ee7fbaSAndroid Build Coastguard Worker   }
96*f4ee7fbaSAndroid Build Coastguard Worker }
97*f4ee7fbaSAndroid Build Coastguard Worker 
98*f4ee7fbaSAndroid Build Coastguard Worker #define BROTLI_LITERAL_BYTE_SCORE 135
99*f4ee7fbaSAndroid Build Coastguard Worker #define BROTLI_DISTANCE_BIT_PENALTY 30
100*f4ee7fbaSAndroid Build Coastguard Worker /* Score must be positive after applying maximal penalty. */
101*f4ee7fbaSAndroid Build Coastguard Worker #define BROTLI_SCORE_BASE (BROTLI_DISTANCE_BIT_PENALTY * 8 * sizeof(size_t))
102*f4ee7fbaSAndroid Build Coastguard Worker 
103*f4ee7fbaSAndroid Build Coastguard Worker /* Usually, we always choose the longest backward reference. This function
104*f4ee7fbaSAndroid Build Coastguard Worker    allows for the exception of that rule.
105*f4ee7fbaSAndroid Build Coastguard Worker 
106*f4ee7fbaSAndroid Build Coastguard Worker    If we choose a backward reference that is further away, it will
107*f4ee7fbaSAndroid Build Coastguard Worker    usually be coded with more bits. We approximate this by assuming
108*f4ee7fbaSAndroid Build Coastguard Worker    log2(distance). If the distance can be expressed in terms of the
109*f4ee7fbaSAndroid Build Coastguard Worker    last four distances, we use some heuristic constants to estimate
110*f4ee7fbaSAndroid Build Coastguard Worker    the bits cost. For the first up to four literals we use the bit
111*f4ee7fbaSAndroid Build Coastguard Worker    cost of the literals from the literal cost model, after that we
112*f4ee7fbaSAndroid Build Coastguard Worker    use the average bit cost of the cost model.
113*f4ee7fbaSAndroid Build Coastguard Worker 
114*f4ee7fbaSAndroid Build Coastguard Worker    This function is used to sometimes discard a longer backward reference
115*f4ee7fbaSAndroid Build Coastguard Worker    when it is not much longer and the bit cost for encoding it is more
116*f4ee7fbaSAndroid Build Coastguard Worker    than the saved literals.
117*f4ee7fbaSAndroid Build Coastguard Worker 
118*f4ee7fbaSAndroid Build Coastguard Worker    backward_reference_offset MUST be positive. */
BackwardReferenceScore(size_t copy_length,size_t backward_reference_offset)119*f4ee7fbaSAndroid Build Coastguard Worker static BROTLI_INLINE score_t BackwardReferenceScore(
120*f4ee7fbaSAndroid Build Coastguard Worker     size_t copy_length, size_t backward_reference_offset) {
121*f4ee7fbaSAndroid Build Coastguard Worker   return BROTLI_SCORE_BASE + BROTLI_LITERAL_BYTE_SCORE * (score_t)copy_length -
122*f4ee7fbaSAndroid Build Coastguard Worker       BROTLI_DISTANCE_BIT_PENALTY * Log2FloorNonZero(backward_reference_offset);
123*f4ee7fbaSAndroid Build Coastguard Worker }
124*f4ee7fbaSAndroid Build Coastguard Worker 
BackwardReferenceScoreUsingLastDistance(size_t copy_length)125*f4ee7fbaSAndroid Build Coastguard Worker static BROTLI_INLINE score_t BackwardReferenceScoreUsingLastDistance(
126*f4ee7fbaSAndroid Build Coastguard Worker     size_t copy_length) {
127*f4ee7fbaSAndroid Build Coastguard Worker   return BROTLI_LITERAL_BYTE_SCORE * (score_t)copy_length +
128*f4ee7fbaSAndroid Build Coastguard Worker       BROTLI_SCORE_BASE + 15;
129*f4ee7fbaSAndroid Build Coastguard Worker }
130*f4ee7fbaSAndroid Build Coastguard Worker 
BackwardReferencePenaltyUsingLastDistance(size_t distance_short_code)131*f4ee7fbaSAndroid Build Coastguard Worker static BROTLI_INLINE score_t BackwardReferencePenaltyUsingLastDistance(
132*f4ee7fbaSAndroid Build Coastguard Worker     size_t distance_short_code) {
133*f4ee7fbaSAndroid Build Coastguard Worker   return (score_t)39 + ((0x1CA10 >> (distance_short_code & 0xE)) & 0xE);
134*f4ee7fbaSAndroid Build Coastguard Worker }
135*f4ee7fbaSAndroid Build Coastguard Worker 
TestStaticDictionaryItem(const BrotliEncoderDictionary * dictionary,size_t len,size_t word_idx,const uint8_t * data,size_t max_length,size_t max_backward,size_t max_distance,HasherSearchResult * out)136*f4ee7fbaSAndroid Build Coastguard Worker static BROTLI_INLINE BROTLI_BOOL TestStaticDictionaryItem(
137*f4ee7fbaSAndroid Build Coastguard Worker     const BrotliEncoderDictionary* dictionary, size_t len, size_t word_idx,
138*f4ee7fbaSAndroid Build Coastguard Worker     const uint8_t* data, size_t max_length, size_t max_backward,
139*f4ee7fbaSAndroid Build Coastguard Worker     size_t max_distance, HasherSearchResult* out) {
140*f4ee7fbaSAndroid Build Coastguard Worker   size_t offset;
141*f4ee7fbaSAndroid Build Coastguard Worker   size_t matchlen;
142*f4ee7fbaSAndroid Build Coastguard Worker   size_t backward;
143*f4ee7fbaSAndroid Build Coastguard Worker   score_t score;
144*f4ee7fbaSAndroid Build Coastguard Worker   offset = dictionary->words->offsets_by_length[len] + len * word_idx;
145*f4ee7fbaSAndroid Build Coastguard Worker   if (len > max_length) {
146*f4ee7fbaSAndroid Build Coastguard Worker     return BROTLI_FALSE;
147*f4ee7fbaSAndroid Build Coastguard Worker   }
148*f4ee7fbaSAndroid Build Coastguard Worker 
149*f4ee7fbaSAndroid Build Coastguard Worker   matchlen =
150*f4ee7fbaSAndroid Build Coastguard Worker       FindMatchLengthWithLimit(data, &dictionary->words->data[offset], len);
151*f4ee7fbaSAndroid Build Coastguard Worker   if (matchlen + dictionary->cutoffTransformsCount <= len || matchlen == 0) {
152*f4ee7fbaSAndroid Build Coastguard Worker     return BROTLI_FALSE;
153*f4ee7fbaSAndroid Build Coastguard Worker   }
154*f4ee7fbaSAndroid Build Coastguard Worker   {
155*f4ee7fbaSAndroid Build Coastguard Worker     size_t cut = len - matchlen;
156*f4ee7fbaSAndroid Build Coastguard Worker     size_t transform_id = (cut << 2) +
157*f4ee7fbaSAndroid Build Coastguard Worker         (size_t)((dictionary->cutoffTransforms >> (cut * 6)) & 0x3F);
158*f4ee7fbaSAndroid Build Coastguard Worker     backward = max_backward + 1 + word_idx +
159*f4ee7fbaSAndroid Build Coastguard Worker         (transform_id << dictionary->words->size_bits_by_length[len]);
160*f4ee7fbaSAndroid Build Coastguard Worker   }
161*f4ee7fbaSAndroid Build Coastguard Worker   if (backward > max_distance) {
162*f4ee7fbaSAndroid Build Coastguard Worker     return BROTLI_FALSE;
163*f4ee7fbaSAndroid Build Coastguard Worker   }
164*f4ee7fbaSAndroid Build Coastguard Worker   score = BackwardReferenceScore(matchlen, backward);
165*f4ee7fbaSAndroid Build Coastguard Worker   if (score < out->score) {
166*f4ee7fbaSAndroid Build Coastguard Worker     return BROTLI_FALSE;
167*f4ee7fbaSAndroid Build Coastguard Worker   }
168*f4ee7fbaSAndroid Build Coastguard Worker   out->len = matchlen;
169*f4ee7fbaSAndroid Build Coastguard Worker   out->len_code_delta = (int)len - (int)matchlen;
170*f4ee7fbaSAndroid Build Coastguard Worker   out->distance = backward;
171*f4ee7fbaSAndroid Build Coastguard Worker   out->score = score;
172*f4ee7fbaSAndroid Build Coastguard Worker   return BROTLI_TRUE;
173*f4ee7fbaSAndroid Build Coastguard Worker }
174*f4ee7fbaSAndroid Build Coastguard Worker 
SearchInStaticDictionary(const BrotliEncoderDictionary * dictionary,HasherCommon * common,const uint8_t * data,size_t max_length,size_t max_backward,size_t max_distance,HasherSearchResult * out,BROTLI_BOOL shallow)175*f4ee7fbaSAndroid Build Coastguard Worker static BROTLI_INLINE void SearchInStaticDictionary(
176*f4ee7fbaSAndroid Build Coastguard Worker     const BrotliEncoderDictionary* dictionary,
177*f4ee7fbaSAndroid Build Coastguard Worker     HasherCommon* common, const uint8_t* data, size_t max_length,
178*f4ee7fbaSAndroid Build Coastguard Worker     size_t max_backward, size_t max_distance,
179*f4ee7fbaSAndroid Build Coastguard Worker     HasherSearchResult* out, BROTLI_BOOL shallow) {
180*f4ee7fbaSAndroid Build Coastguard Worker   size_t key;
181*f4ee7fbaSAndroid Build Coastguard Worker   size_t i;
182*f4ee7fbaSAndroid Build Coastguard Worker   if (common->dict_num_matches < (common->dict_num_lookups >> 7)) {
183*f4ee7fbaSAndroid Build Coastguard Worker     return;
184*f4ee7fbaSAndroid Build Coastguard Worker   }
185*f4ee7fbaSAndroid Build Coastguard Worker   key = Hash14(data) << 1;
186*f4ee7fbaSAndroid Build Coastguard Worker   for (i = 0; i < (shallow ? 1u : 2u); ++i, ++key) {
187*f4ee7fbaSAndroid Build Coastguard Worker     common->dict_num_lookups++;
188*f4ee7fbaSAndroid Build Coastguard Worker     if (dictionary->hash_table_lengths[key] != 0) {
189*f4ee7fbaSAndroid Build Coastguard Worker       BROTLI_BOOL item_matches = TestStaticDictionaryItem(
190*f4ee7fbaSAndroid Build Coastguard Worker           dictionary, dictionary->hash_table_lengths[key],
191*f4ee7fbaSAndroid Build Coastguard Worker           dictionary->hash_table_words[key], data,
192*f4ee7fbaSAndroid Build Coastguard Worker           max_length, max_backward, max_distance, out);
193*f4ee7fbaSAndroid Build Coastguard Worker       if (item_matches) {
194*f4ee7fbaSAndroid Build Coastguard Worker         common->dict_num_matches++;
195*f4ee7fbaSAndroid Build Coastguard Worker       }
196*f4ee7fbaSAndroid Build Coastguard Worker     }
197*f4ee7fbaSAndroid Build Coastguard Worker   }
198*f4ee7fbaSAndroid Build Coastguard Worker }
199*f4ee7fbaSAndroid Build Coastguard Worker 
200*f4ee7fbaSAndroid Build Coastguard Worker typedef struct BackwardMatch {
201*f4ee7fbaSAndroid Build Coastguard Worker   uint32_t distance;
202*f4ee7fbaSAndroid Build Coastguard Worker   uint32_t length_and_code;
203*f4ee7fbaSAndroid Build Coastguard Worker } BackwardMatch;
204*f4ee7fbaSAndroid Build Coastguard Worker 
InitBackwardMatch(BackwardMatch * self,size_t dist,size_t len)205*f4ee7fbaSAndroid Build Coastguard Worker static BROTLI_INLINE void InitBackwardMatch(BackwardMatch* self,
206*f4ee7fbaSAndroid Build Coastguard Worker     size_t dist, size_t len) {
207*f4ee7fbaSAndroid Build Coastguard Worker   self->distance = (uint32_t)dist;
208*f4ee7fbaSAndroid Build Coastguard Worker   self->length_and_code = (uint32_t)(len << 5);
209*f4ee7fbaSAndroid Build Coastguard Worker }
210*f4ee7fbaSAndroid Build Coastguard Worker 
InitDictionaryBackwardMatch(BackwardMatch * self,size_t dist,size_t len,size_t len_code)211*f4ee7fbaSAndroid Build Coastguard Worker static BROTLI_INLINE void InitDictionaryBackwardMatch(BackwardMatch* self,
212*f4ee7fbaSAndroid Build Coastguard Worker     size_t dist, size_t len, size_t len_code) {
213*f4ee7fbaSAndroid Build Coastguard Worker   self->distance = (uint32_t)dist;
214*f4ee7fbaSAndroid Build Coastguard Worker   self->length_and_code =
215*f4ee7fbaSAndroid Build Coastguard Worker       (uint32_t)((len << 5) | (len == len_code ? 0 : len_code));
216*f4ee7fbaSAndroid Build Coastguard Worker }
217*f4ee7fbaSAndroid Build Coastguard Worker 
BackwardMatchLength(const BackwardMatch * self)218*f4ee7fbaSAndroid Build Coastguard Worker static BROTLI_INLINE size_t BackwardMatchLength(const BackwardMatch* self) {
219*f4ee7fbaSAndroid Build Coastguard Worker   return self->length_and_code >> 5;
220*f4ee7fbaSAndroid Build Coastguard Worker }
221*f4ee7fbaSAndroid Build Coastguard Worker 
BackwardMatchLengthCode(const BackwardMatch * self)222*f4ee7fbaSAndroid Build Coastguard Worker static BROTLI_INLINE size_t BackwardMatchLengthCode(const BackwardMatch* self) {
223*f4ee7fbaSAndroid Build Coastguard Worker   size_t code = self->length_and_code & 31;
224*f4ee7fbaSAndroid Build Coastguard Worker   return code ? code : BackwardMatchLength(self);
225*f4ee7fbaSAndroid Build Coastguard Worker }
226*f4ee7fbaSAndroid Build Coastguard Worker 
227*f4ee7fbaSAndroid Build Coastguard Worker #define EXPAND_CAT(a, b) CAT(a, b)
228*f4ee7fbaSAndroid Build Coastguard Worker #define CAT(a, b) a ## b
229*f4ee7fbaSAndroid Build Coastguard Worker #define FN(X) EXPAND_CAT(X, HASHER())
230*f4ee7fbaSAndroid Build Coastguard Worker 
231*f4ee7fbaSAndroid Build Coastguard Worker #define HASHER() H10
232*f4ee7fbaSAndroid Build Coastguard Worker #define BUCKET_BITS 17
233*f4ee7fbaSAndroid Build Coastguard Worker #define MAX_TREE_SEARCH_DEPTH 64
234*f4ee7fbaSAndroid Build Coastguard Worker #define MAX_TREE_COMP_LENGTH 128
235*f4ee7fbaSAndroid Build Coastguard Worker #include "./hash_to_binary_tree_inc.h"  /* NOLINT(build/include) */
236*f4ee7fbaSAndroid Build Coastguard Worker #undef MAX_TREE_SEARCH_DEPTH
237*f4ee7fbaSAndroid Build Coastguard Worker #undef MAX_TREE_COMP_LENGTH
238*f4ee7fbaSAndroid Build Coastguard Worker #undef BUCKET_BITS
239*f4ee7fbaSAndroid Build Coastguard Worker #undef HASHER
240*f4ee7fbaSAndroid Build Coastguard Worker /* MAX_NUM_MATCHES == 64 + MAX_TREE_SEARCH_DEPTH */
241*f4ee7fbaSAndroid Build Coastguard Worker #define MAX_NUM_MATCHES_H10 128
242*f4ee7fbaSAndroid Build Coastguard Worker 
243*f4ee7fbaSAndroid Build Coastguard Worker /* For BUCKET_SWEEP_BITS == 0, enabling the dictionary lookup makes compression
244*f4ee7fbaSAndroid Build Coastguard Worker    a little faster (0.5% - 1%) and it compresses 0.15% better on small text
245*f4ee7fbaSAndroid Build Coastguard Worker    and HTML inputs. */
246*f4ee7fbaSAndroid Build Coastguard Worker 
247*f4ee7fbaSAndroid Build Coastguard Worker #define HASHER() H2
248*f4ee7fbaSAndroid Build Coastguard Worker #define BUCKET_BITS 16
249*f4ee7fbaSAndroid Build Coastguard Worker #define BUCKET_SWEEP_BITS 0
250*f4ee7fbaSAndroid Build Coastguard Worker #define HASH_LEN 5
251*f4ee7fbaSAndroid Build Coastguard Worker #define USE_DICTIONARY 1
252*f4ee7fbaSAndroid Build Coastguard Worker #include "./hash_longest_match_quickly_inc.h"  /* NOLINT(build/include) */
253*f4ee7fbaSAndroid Build Coastguard Worker #undef BUCKET_SWEEP_BITS
254*f4ee7fbaSAndroid Build Coastguard Worker #undef USE_DICTIONARY
255*f4ee7fbaSAndroid Build Coastguard Worker #undef HASHER
256*f4ee7fbaSAndroid Build Coastguard Worker 
257*f4ee7fbaSAndroid Build Coastguard Worker #define HASHER() H3
258*f4ee7fbaSAndroid Build Coastguard Worker #define BUCKET_SWEEP_BITS 1
259*f4ee7fbaSAndroid Build Coastguard Worker #define USE_DICTIONARY 0
260*f4ee7fbaSAndroid Build Coastguard Worker #include "./hash_longest_match_quickly_inc.h"  /* NOLINT(build/include) */
261*f4ee7fbaSAndroid Build Coastguard Worker #undef USE_DICTIONARY
262*f4ee7fbaSAndroid Build Coastguard Worker #undef BUCKET_SWEEP_BITS
263*f4ee7fbaSAndroid Build Coastguard Worker #undef BUCKET_BITS
264*f4ee7fbaSAndroid Build Coastguard Worker #undef HASHER
265*f4ee7fbaSAndroid Build Coastguard Worker 
266*f4ee7fbaSAndroid Build Coastguard Worker #define HASHER() H4
267*f4ee7fbaSAndroid Build Coastguard Worker #define BUCKET_BITS 17
268*f4ee7fbaSAndroid Build Coastguard Worker #define BUCKET_SWEEP_BITS 2
269*f4ee7fbaSAndroid Build Coastguard Worker #define USE_DICTIONARY 1
270*f4ee7fbaSAndroid Build Coastguard Worker #include "./hash_longest_match_quickly_inc.h"  /* NOLINT(build/include) */
271*f4ee7fbaSAndroid Build Coastguard Worker #undef USE_DICTIONARY
272*f4ee7fbaSAndroid Build Coastguard Worker #undef HASH_LEN
273*f4ee7fbaSAndroid Build Coastguard Worker #undef BUCKET_SWEEP_BITS
274*f4ee7fbaSAndroid Build Coastguard Worker #undef BUCKET_BITS
275*f4ee7fbaSAndroid Build Coastguard Worker #undef HASHER
276*f4ee7fbaSAndroid Build Coastguard Worker 
277*f4ee7fbaSAndroid Build Coastguard Worker #define HASHER() H5
278*f4ee7fbaSAndroid Build Coastguard Worker #include "./hash_longest_match_inc.h"  /* NOLINT(build/include) */
279*f4ee7fbaSAndroid Build Coastguard Worker #undef HASHER
280*f4ee7fbaSAndroid Build Coastguard Worker 
281*f4ee7fbaSAndroid Build Coastguard Worker #define HASHER() H6
282*f4ee7fbaSAndroid Build Coastguard Worker #include "./hash_longest_match64_inc.h"  /* NOLINT(build/include) */
283*f4ee7fbaSAndroid Build Coastguard Worker #undef HASHER
284*f4ee7fbaSAndroid Build Coastguard Worker 
285*f4ee7fbaSAndroid Build Coastguard Worker #define BUCKET_BITS 15
286*f4ee7fbaSAndroid Build Coastguard Worker 
287*f4ee7fbaSAndroid Build Coastguard Worker #define NUM_LAST_DISTANCES_TO_CHECK 4
288*f4ee7fbaSAndroid Build Coastguard Worker #define NUM_BANKS 1
289*f4ee7fbaSAndroid Build Coastguard Worker #define BANK_BITS 16
290*f4ee7fbaSAndroid Build Coastguard Worker #define HASHER() H40
291*f4ee7fbaSAndroid Build Coastguard Worker #include "./hash_forgetful_chain_inc.h"  /* NOLINT(build/include) */
292*f4ee7fbaSAndroid Build Coastguard Worker #undef HASHER
293*f4ee7fbaSAndroid Build Coastguard Worker #undef NUM_LAST_DISTANCES_TO_CHECK
294*f4ee7fbaSAndroid Build Coastguard Worker 
295*f4ee7fbaSAndroid Build Coastguard Worker #define NUM_LAST_DISTANCES_TO_CHECK 10
296*f4ee7fbaSAndroid Build Coastguard Worker #define HASHER() H41
297*f4ee7fbaSAndroid Build Coastguard Worker #include "./hash_forgetful_chain_inc.h"  /* NOLINT(build/include) */
298*f4ee7fbaSAndroid Build Coastguard Worker #undef HASHER
299*f4ee7fbaSAndroid Build Coastguard Worker #undef NUM_LAST_DISTANCES_TO_CHECK
300*f4ee7fbaSAndroid Build Coastguard Worker #undef NUM_BANKS
301*f4ee7fbaSAndroid Build Coastguard Worker #undef BANK_BITS
302*f4ee7fbaSAndroid Build Coastguard Worker 
303*f4ee7fbaSAndroid Build Coastguard Worker #define NUM_LAST_DISTANCES_TO_CHECK 16
304*f4ee7fbaSAndroid Build Coastguard Worker #define NUM_BANKS 512
305*f4ee7fbaSAndroid Build Coastguard Worker #define BANK_BITS 9
306*f4ee7fbaSAndroid Build Coastguard Worker #define HASHER() H42
307*f4ee7fbaSAndroid Build Coastguard Worker #include "./hash_forgetful_chain_inc.h"  /* NOLINT(build/include) */
308*f4ee7fbaSAndroid Build Coastguard Worker #undef HASHER
309*f4ee7fbaSAndroid Build Coastguard Worker #undef NUM_LAST_DISTANCES_TO_CHECK
310*f4ee7fbaSAndroid Build Coastguard Worker #undef NUM_BANKS
311*f4ee7fbaSAndroid Build Coastguard Worker #undef BANK_BITS
312*f4ee7fbaSAndroid Build Coastguard Worker 
313*f4ee7fbaSAndroid Build Coastguard Worker #undef BUCKET_BITS
314*f4ee7fbaSAndroid Build Coastguard Worker 
315*f4ee7fbaSAndroid Build Coastguard Worker #define HASHER() H54
316*f4ee7fbaSAndroid Build Coastguard Worker #define BUCKET_BITS 20
317*f4ee7fbaSAndroid Build Coastguard Worker #define BUCKET_SWEEP_BITS 2
318*f4ee7fbaSAndroid Build Coastguard Worker #define HASH_LEN 7
319*f4ee7fbaSAndroid Build Coastguard Worker #define USE_DICTIONARY 0
320*f4ee7fbaSAndroid Build Coastguard Worker #include "./hash_longest_match_quickly_inc.h"  /* NOLINT(build/include) */
321*f4ee7fbaSAndroid Build Coastguard Worker #undef USE_DICTIONARY
322*f4ee7fbaSAndroid Build Coastguard Worker #undef HASH_LEN
323*f4ee7fbaSAndroid Build Coastguard Worker #undef BUCKET_SWEEP_BITS
324*f4ee7fbaSAndroid Build Coastguard Worker #undef BUCKET_BITS
325*f4ee7fbaSAndroid Build Coastguard Worker #undef HASHER
326*f4ee7fbaSAndroid Build Coastguard Worker 
327*f4ee7fbaSAndroid Build Coastguard Worker /* fast large window hashers */
328*f4ee7fbaSAndroid Build Coastguard Worker 
329*f4ee7fbaSAndroid Build Coastguard Worker #define HASHER() HROLLING_FAST
330*f4ee7fbaSAndroid Build Coastguard Worker #define CHUNKLEN 32
331*f4ee7fbaSAndroid Build Coastguard Worker #define JUMP 4
332*f4ee7fbaSAndroid Build Coastguard Worker #define NUMBUCKETS 16777216
333*f4ee7fbaSAndroid Build Coastguard Worker #define MASK ((NUMBUCKETS * 64) - 1)
334*f4ee7fbaSAndroid Build Coastguard Worker #include "./hash_rolling_inc.h"  /* NOLINT(build/include) */
335*f4ee7fbaSAndroid Build Coastguard Worker #undef JUMP
336*f4ee7fbaSAndroid Build Coastguard Worker #undef HASHER
337*f4ee7fbaSAndroid Build Coastguard Worker 
338*f4ee7fbaSAndroid Build Coastguard Worker 
339*f4ee7fbaSAndroid Build Coastguard Worker #define HASHER() HROLLING
340*f4ee7fbaSAndroid Build Coastguard Worker #define JUMP 1
341*f4ee7fbaSAndroid Build Coastguard Worker #include "./hash_rolling_inc.h"  /* NOLINT(build/include) */
342*f4ee7fbaSAndroid Build Coastguard Worker #undef MASK
343*f4ee7fbaSAndroid Build Coastguard Worker #undef NUMBUCKETS
344*f4ee7fbaSAndroid Build Coastguard Worker #undef JUMP
345*f4ee7fbaSAndroid Build Coastguard Worker #undef CHUNKLEN
346*f4ee7fbaSAndroid Build Coastguard Worker #undef HASHER
347*f4ee7fbaSAndroid Build Coastguard Worker 
348*f4ee7fbaSAndroid Build Coastguard Worker #define HASHER() H35
349*f4ee7fbaSAndroid Build Coastguard Worker #define HASHER_A H3
350*f4ee7fbaSAndroid Build Coastguard Worker #define HASHER_B HROLLING_FAST
351*f4ee7fbaSAndroid Build Coastguard Worker #include "./hash_composite_inc.h"  /* NOLINT(build/include) */
352*f4ee7fbaSAndroid Build Coastguard Worker #undef HASHER_A
353*f4ee7fbaSAndroid Build Coastguard Worker #undef HASHER_B
354*f4ee7fbaSAndroid Build Coastguard Worker #undef HASHER
355*f4ee7fbaSAndroid Build Coastguard Worker 
356*f4ee7fbaSAndroid Build Coastguard Worker #define HASHER() H55
357*f4ee7fbaSAndroid Build Coastguard Worker #define HASHER_A H54
358*f4ee7fbaSAndroid Build Coastguard Worker #define HASHER_B HROLLING_FAST
359*f4ee7fbaSAndroid Build Coastguard Worker #include "./hash_composite_inc.h"  /* NOLINT(build/include) */
360*f4ee7fbaSAndroid Build Coastguard Worker #undef HASHER_A
361*f4ee7fbaSAndroid Build Coastguard Worker #undef HASHER_B
362*f4ee7fbaSAndroid Build Coastguard Worker #undef HASHER
363*f4ee7fbaSAndroid Build Coastguard Worker 
364*f4ee7fbaSAndroid Build Coastguard Worker #define HASHER() H65
365*f4ee7fbaSAndroid Build Coastguard Worker #define HASHER_A H6
366*f4ee7fbaSAndroid Build Coastguard Worker #define HASHER_B HROLLING
367*f4ee7fbaSAndroid Build Coastguard Worker #include "./hash_composite_inc.h"  /* NOLINT(build/include) */
368*f4ee7fbaSAndroid Build Coastguard Worker #undef HASHER_A
369*f4ee7fbaSAndroid Build Coastguard Worker #undef HASHER_B
370*f4ee7fbaSAndroid Build Coastguard Worker #undef HASHER
371*f4ee7fbaSAndroid Build Coastguard Worker 
372*f4ee7fbaSAndroid Build Coastguard Worker #undef FN
373*f4ee7fbaSAndroid Build Coastguard Worker #undef CAT
374*f4ee7fbaSAndroid Build Coastguard Worker #undef EXPAND_CAT
375*f4ee7fbaSAndroid Build Coastguard Worker 
376*f4ee7fbaSAndroid Build Coastguard Worker #define FOR_SIMPLE_HASHERS(H) H(2) H(3) H(4) H(5) H(6) H(40) H(41) H(42) H(54)
377*f4ee7fbaSAndroid Build Coastguard Worker #define FOR_COMPOSITE_HASHERS(H) H(35) H(55) H(65)
378*f4ee7fbaSAndroid Build Coastguard Worker #define FOR_GENERIC_HASHERS(H) FOR_SIMPLE_HASHERS(H) FOR_COMPOSITE_HASHERS(H)
379*f4ee7fbaSAndroid Build Coastguard Worker #define FOR_ALL_HASHERS(H) FOR_GENERIC_HASHERS(H) H(10)
380*f4ee7fbaSAndroid Build Coastguard Worker 
381*f4ee7fbaSAndroid Build Coastguard Worker typedef struct {
382*f4ee7fbaSAndroid Build Coastguard Worker   HasherCommon common;
383*f4ee7fbaSAndroid Build Coastguard Worker 
384*f4ee7fbaSAndroid Build Coastguard Worker   union {
385*f4ee7fbaSAndroid Build Coastguard Worker #define MEMBER_(N) \
386*f4ee7fbaSAndroid Build Coastguard Worker     H ## N _H ## N;
387*f4ee7fbaSAndroid Build Coastguard Worker     FOR_ALL_HASHERS(MEMBER_)
388*f4ee7fbaSAndroid Build Coastguard Worker #undef MEMBER_
389*f4ee7fbaSAndroid Build Coastguard Worker   } privat;
390*f4ee7fbaSAndroid Build Coastguard Worker } Hasher;
391*f4ee7fbaSAndroid Build Coastguard Worker 
392*f4ee7fbaSAndroid Build Coastguard Worker /* MUST be invoked before any other method. */
HasherInit(Hasher * hasher)393*f4ee7fbaSAndroid Build Coastguard Worker static BROTLI_INLINE void HasherInit(Hasher* hasher) {
394*f4ee7fbaSAndroid Build Coastguard Worker   hasher->common.extra = NULL;
395*f4ee7fbaSAndroid Build Coastguard Worker }
396*f4ee7fbaSAndroid Build Coastguard Worker 
DestroyHasher(MemoryManager * m,Hasher * hasher)397*f4ee7fbaSAndroid Build Coastguard Worker static BROTLI_INLINE void DestroyHasher(MemoryManager* m, Hasher* hasher) {
398*f4ee7fbaSAndroid Build Coastguard Worker   if (hasher->common.extra == NULL) return;
399*f4ee7fbaSAndroid Build Coastguard Worker   BROTLI_FREE(m, hasher->common.extra);
400*f4ee7fbaSAndroid Build Coastguard Worker }
401*f4ee7fbaSAndroid Build Coastguard Worker 
HasherReset(Hasher * hasher)402*f4ee7fbaSAndroid Build Coastguard Worker static BROTLI_INLINE void HasherReset(Hasher* hasher) {
403*f4ee7fbaSAndroid Build Coastguard Worker   hasher->common.is_prepared_ = BROTLI_FALSE;
404*f4ee7fbaSAndroid Build Coastguard Worker }
405*f4ee7fbaSAndroid Build Coastguard Worker 
HasherSize(const BrotliEncoderParams * params,BROTLI_BOOL one_shot,const size_t input_size)406*f4ee7fbaSAndroid Build Coastguard Worker static BROTLI_INLINE size_t HasherSize(const BrotliEncoderParams* params,
407*f4ee7fbaSAndroid Build Coastguard Worker     BROTLI_BOOL one_shot, const size_t input_size) {
408*f4ee7fbaSAndroid Build Coastguard Worker   switch (params->hasher.type) {
409*f4ee7fbaSAndroid Build Coastguard Worker #define SIZE_(N)                                                      \
410*f4ee7fbaSAndroid Build Coastguard Worker     case N:                                                           \
411*f4ee7fbaSAndroid Build Coastguard Worker       return HashMemAllocInBytesH ## N(params, one_shot, input_size);
412*f4ee7fbaSAndroid Build Coastguard Worker     FOR_ALL_HASHERS(SIZE_)
413*f4ee7fbaSAndroid Build Coastguard Worker #undef SIZE_
414*f4ee7fbaSAndroid Build Coastguard Worker     default:
415*f4ee7fbaSAndroid Build Coastguard Worker       break;
416*f4ee7fbaSAndroid Build Coastguard Worker   }
417*f4ee7fbaSAndroid Build Coastguard Worker   return 0;  /* Default case. */
418*f4ee7fbaSAndroid Build Coastguard Worker }
419*f4ee7fbaSAndroid Build Coastguard Worker 
HasherSetup(MemoryManager * m,Hasher * hasher,BrotliEncoderParams * params,const uint8_t * data,size_t position,size_t input_size,BROTLI_BOOL is_last)420*f4ee7fbaSAndroid Build Coastguard Worker static BROTLI_INLINE void HasherSetup(MemoryManager* m, Hasher* hasher,
421*f4ee7fbaSAndroid Build Coastguard Worker     BrotliEncoderParams* params, const uint8_t* data, size_t position,
422*f4ee7fbaSAndroid Build Coastguard Worker     size_t input_size, BROTLI_BOOL is_last) {
423*f4ee7fbaSAndroid Build Coastguard Worker   BROTLI_BOOL one_shot = (position == 0 && is_last);
424*f4ee7fbaSAndroid Build Coastguard Worker   if (hasher->common.extra == NULL) {
425*f4ee7fbaSAndroid Build Coastguard Worker     size_t alloc_size;
426*f4ee7fbaSAndroid Build Coastguard Worker     ChooseHasher(params, &params->hasher);
427*f4ee7fbaSAndroid Build Coastguard Worker     alloc_size = HasherSize(params, one_shot, input_size);
428*f4ee7fbaSAndroid Build Coastguard Worker     hasher->common.extra = BROTLI_ALLOC(m, uint8_t, alloc_size);
429*f4ee7fbaSAndroid Build Coastguard Worker     if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(hasher->common.extra)) return;
430*f4ee7fbaSAndroid Build Coastguard Worker     hasher->common.params = params->hasher;
431*f4ee7fbaSAndroid Build Coastguard Worker     switch (hasher->common.params.type) {
432*f4ee7fbaSAndroid Build Coastguard Worker #define INITIALIZE_(N)                        \
433*f4ee7fbaSAndroid Build Coastguard Worker       case N:                                 \
434*f4ee7fbaSAndroid Build Coastguard Worker         InitializeH ## N(&hasher->common,     \
435*f4ee7fbaSAndroid Build Coastguard Worker             &hasher->privat._H ## N, params); \
436*f4ee7fbaSAndroid Build Coastguard Worker         break;
437*f4ee7fbaSAndroid Build Coastguard Worker       FOR_ALL_HASHERS(INITIALIZE_);
438*f4ee7fbaSAndroid Build Coastguard Worker #undef INITIALIZE_
439*f4ee7fbaSAndroid Build Coastguard Worker       default:
440*f4ee7fbaSAndroid Build Coastguard Worker         break;
441*f4ee7fbaSAndroid Build Coastguard Worker     }
442*f4ee7fbaSAndroid Build Coastguard Worker     HasherReset(hasher);
443*f4ee7fbaSAndroid Build Coastguard Worker   }
444*f4ee7fbaSAndroid Build Coastguard Worker 
445*f4ee7fbaSAndroid Build Coastguard Worker   if (!hasher->common.is_prepared_) {
446*f4ee7fbaSAndroid Build Coastguard Worker     switch (hasher->common.params.type) {
447*f4ee7fbaSAndroid Build Coastguard Worker #define PREPARE_(N)                      \
448*f4ee7fbaSAndroid Build Coastguard Worker       case N:                            \
449*f4ee7fbaSAndroid Build Coastguard Worker         PrepareH ## N(                   \
450*f4ee7fbaSAndroid Build Coastguard Worker             &hasher->privat._H ## N,     \
451*f4ee7fbaSAndroid Build Coastguard Worker             one_shot, input_size, data); \
452*f4ee7fbaSAndroid Build Coastguard Worker         break;
453*f4ee7fbaSAndroid Build Coastguard Worker       FOR_ALL_HASHERS(PREPARE_)
454*f4ee7fbaSAndroid Build Coastguard Worker #undef PREPARE_
455*f4ee7fbaSAndroid Build Coastguard Worker       default: break;
456*f4ee7fbaSAndroid Build Coastguard Worker     }
457*f4ee7fbaSAndroid Build Coastguard Worker     if (position == 0) {
458*f4ee7fbaSAndroid Build Coastguard Worker       hasher->common.dict_num_lookups = 0;
459*f4ee7fbaSAndroid Build Coastguard Worker       hasher->common.dict_num_matches = 0;
460*f4ee7fbaSAndroid Build Coastguard Worker     }
461*f4ee7fbaSAndroid Build Coastguard Worker     hasher->common.is_prepared_ = BROTLI_TRUE;
462*f4ee7fbaSAndroid Build Coastguard Worker   }
463*f4ee7fbaSAndroid Build Coastguard Worker }
464*f4ee7fbaSAndroid Build Coastguard Worker 
InitOrStitchToPreviousBlock(MemoryManager * m,Hasher * hasher,const uint8_t * data,size_t mask,BrotliEncoderParams * params,size_t position,size_t input_size,BROTLI_BOOL is_last)465*f4ee7fbaSAndroid Build Coastguard Worker static BROTLI_INLINE void InitOrStitchToPreviousBlock(
466*f4ee7fbaSAndroid Build Coastguard Worker     MemoryManager* m, Hasher* hasher, const uint8_t* data, size_t mask,
467*f4ee7fbaSAndroid Build Coastguard Worker     BrotliEncoderParams* params, size_t position, size_t input_size,
468*f4ee7fbaSAndroid Build Coastguard Worker     BROTLI_BOOL is_last) {
469*f4ee7fbaSAndroid Build Coastguard Worker   HasherSetup(m, hasher, params, data, position, input_size, is_last);
470*f4ee7fbaSAndroid Build Coastguard Worker   if (BROTLI_IS_OOM(m)) return;
471*f4ee7fbaSAndroid Build Coastguard Worker   switch (hasher->common.params.type) {
472*f4ee7fbaSAndroid Build Coastguard Worker #define INIT_(N)                             \
473*f4ee7fbaSAndroid Build Coastguard Worker     case N:                                  \
474*f4ee7fbaSAndroid Build Coastguard Worker       StitchToPreviousBlockH ## N(           \
475*f4ee7fbaSAndroid Build Coastguard Worker           &hasher->privat._H ## N,           \
476*f4ee7fbaSAndroid Build Coastguard Worker           input_size, position, data, mask); \
477*f4ee7fbaSAndroid Build Coastguard Worker     break;
478*f4ee7fbaSAndroid Build Coastguard Worker     FOR_ALL_HASHERS(INIT_)
479*f4ee7fbaSAndroid Build Coastguard Worker #undef INIT_
480*f4ee7fbaSAndroid Build Coastguard Worker     default: break;
481*f4ee7fbaSAndroid Build Coastguard Worker   }
482*f4ee7fbaSAndroid Build Coastguard Worker }
483*f4ee7fbaSAndroid Build Coastguard Worker 
484*f4ee7fbaSAndroid Build Coastguard Worker #if defined(__cplusplus) || defined(c_plusplus)
485*f4ee7fbaSAndroid Build Coastguard Worker }  /* extern "C" */
486*f4ee7fbaSAndroid Build Coastguard Worker #endif
487*f4ee7fbaSAndroid Build Coastguard Worker 
488*f4ee7fbaSAndroid Build Coastguard Worker #endif  /* BROTLI_ENC_HASH_H_ */
489