xref: /aosp_15_r20/external/brotli/c/enc/entropy_encode.c (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 /* Entropy encoding (Huffman) utilities. */
8*f4ee7fbaSAndroid Build Coastguard Worker 
9*f4ee7fbaSAndroid Build Coastguard Worker #include "./entropy_encode.h"
10*f4ee7fbaSAndroid Build Coastguard Worker 
11*f4ee7fbaSAndroid Build Coastguard Worker #include <string.h>  /* memset */
12*f4ee7fbaSAndroid Build Coastguard Worker 
13*f4ee7fbaSAndroid Build Coastguard Worker #include "../common/constants.h"
14*f4ee7fbaSAndroid Build Coastguard Worker #include "../common/platform.h"
15*f4ee7fbaSAndroid Build Coastguard Worker #include <brotli/types.h>
16*f4ee7fbaSAndroid Build Coastguard Worker 
17*f4ee7fbaSAndroid Build Coastguard Worker #if defined(__cplusplus) || defined(c_plusplus)
18*f4ee7fbaSAndroid Build Coastguard Worker extern "C" {
19*f4ee7fbaSAndroid Build Coastguard Worker #endif
20*f4ee7fbaSAndroid Build Coastguard Worker 
21*f4ee7fbaSAndroid Build Coastguard Worker const size_t kBrotliShellGaps[] = {132, 57, 23, 10, 4, 1};
22*f4ee7fbaSAndroid Build Coastguard Worker 
BrotliSetDepth(int p0,HuffmanTree * pool,uint8_t * depth,int max_depth)23*f4ee7fbaSAndroid Build Coastguard Worker BROTLI_BOOL BrotliSetDepth(
24*f4ee7fbaSAndroid Build Coastguard Worker     int p0, HuffmanTree* pool, uint8_t* depth, int max_depth) {
25*f4ee7fbaSAndroid Build Coastguard Worker   int stack[16];
26*f4ee7fbaSAndroid Build Coastguard Worker   int level = 0;
27*f4ee7fbaSAndroid Build Coastguard Worker   int p = p0;
28*f4ee7fbaSAndroid Build Coastguard Worker   BROTLI_DCHECK(max_depth <= 15);
29*f4ee7fbaSAndroid Build Coastguard Worker   stack[0] = -1;
30*f4ee7fbaSAndroid Build Coastguard Worker   while (BROTLI_TRUE) {
31*f4ee7fbaSAndroid Build Coastguard Worker     if (pool[p].index_left_ >= 0) {
32*f4ee7fbaSAndroid Build Coastguard Worker       level++;
33*f4ee7fbaSAndroid Build Coastguard Worker       if (level > max_depth) return BROTLI_FALSE;
34*f4ee7fbaSAndroid Build Coastguard Worker       stack[level] = pool[p].index_right_or_value_;
35*f4ee7fbaSAndroid Build Coastguard Worker       p = pool[p].index_left_;
36*f4ee7fbaSAndroid Build Coastguard Worker       continue;
37*f4ee7fbaSAndroid Build Coastguard Worker     } else {
38*f4ee7fbaSAndroid Build Coastguard Worker       depth[pool[p].index_right_or_value_] = (uint8_t)level;
39*f4ee7fbaSAndroid Build Coastguard Worker     }
40*f4ee7fbaSAndroid Build Coastguard Worker     while (level >= 0 && stack[level] == -1) level--;
41*f4ee7fbaSAndroid Build Coastguard Worker     if (level < 0) return BROTLI_TRUE;
42*f4ee7fbaSAndroid Build Coastguard Worker     p = stack[level];
43*f4ee7fbaSAndroid Build Coastguard Worker     stack[level] = -1;
44*f4ee7fbaSAndroid Build Coastguard Worker   }
45*f4ee7fbaSAndroid Build Coastguard Worker }
46*f4ee7fbaSAndroid Build Coastguard Worker 
47*f4ee7fbaSAndroid Build Coastguard Worker /* Sort the root nodes, least popular first. */
SortHuffmanTree(const HuffmanTree * v0,const HuffmanTree * v1)48*f4ee7fbaSAndroid Build Coastguard Worker static BROTLI_INLINE BROTLI_BOOL SortHuffmanTree(
49*f4ee7fbaSAndroid Build Coastguard Worker     const HuffmanTree* v0, const HuffmanTree* v1) {
50*f4ee7fbaSAndroid Build Coastguard Worker   if (v0->total_count_ != v1->total_count_) {
51*f4ee7fbaSAndroid Build Coastguard Worker     return TO_BROTLI_BOOL(v0->total_count_ < v1->total_count_);
52*f4ee7fbaSAndroid Build Coastguard Worker   }
53*f4ee7fbaSAndroid Build Coastguard Worker   return TO_BROTLI_BOOL(v0->index_right_or_value_ > v1->index_right_or_value_);
54*f4ee7fbaSAndroid Build Coastguard Worker }
55*f4ee7fbaSAndroid Build Coastguard Worker 
56*f4ee7fbaSAndroid Build Coastguard Worker /* This function will create a Huffman tree.
57*f4ee7fbaSAndroid Build Coastguard Worker 
58*f4ee7fbaSAndroid Build Coastguard Worker    The catch here is that the tree cannot be arbitrarily deep.
59*f4ee7fbaSAndroid Build Coastguard Worker    Brotli specifies a maximum depth of 15 bits for "code trees"
60*f4ee7fbaSAndroid Build Coastguard Worker    and 7 bits for "code length code trees."
61*f4ee7fbaSAndroid Build Coastguard Worker 
62*f4ee7fbaSAndroid Build Coastguard Worker    count_limit is the value that is to be faked as the minimum value
63*f4ee7fbaSAndroid Build Coastguard Worker    and this minimum value is raised until the tree matches the
64*f4ee7fbaSAndroid Build Coastguard Worker    maximum length requirement.
65*f4ee7fbaSAndroid Build Coastguard Worker 
66*f4ee7fbaSAndroid Build Coastguard Worker    This algorithm is not of excellent performance for very long data blocks,
67*f4ee7fbaSAndroid Build Coastguard Worker    especially when population counts are longer than 2**tree_limit, but
68*f4ee7fbaSAndroid Build Coastguard Worker    we are not planning to use this with extremely long blocks.
69*f4ee7fbaSAndroid Build Coastguard Worker 
70*f4ee7fbaSAndroid Build Coastguard Worker    See http://en.wikipedia.org/wiki/Huffman_coding */
BrotliCreateHuffmanTree(const uint32_t * data,const size_t length,const int tree_limit,HuffmanTree * tree,uint8_t * depth)71*f4ee7fbaSAndroid Build Coastguard Worker void BrotliCreateHuffmanTree(const uint32_t* data,
72*f4ee7fbaSAndroid Build Coastguard Worker                              const size_t length,
73*f4ee7fbaSAndroid Build Coastguard Worker                              const int tree_limit,
74*f4ee7fbaSAndroid Build Coastguard Worker                              HuffmanTree* tree,
75*f4ee7fbaSAndroid Build Coastguard Worker                              uint8_t* depth) {
76*f4ee7fbaSAndroid Build Coastguard Worker   uint32_t count_limit;
77*f4ee7fbaSAndroid Build Coastguard Worker   HuffmanTree sentinel;
78*f4ee7fbaSAndroid Build Coastguard Worker   InitHuffmanTree(&sentinel, BROTLI_UINT32_MAX, -1, -1);
79*f4ee7fbaSAndroid Build Coastguard Worker   /* For block sizes below 64 kB, we never need to do a second iteration
80*f4ee7fbaSAndroid Build Coastguard Worker      of this loop. Probably all of our block sizes will be smaller than
81*f4ee7fbaSAndroid Build Coastguard Worker      that, so this loop is mostly of academic interest. If we actually
82*f4ee7fbaSAndroid Build Coastguard Worker      would need this, we would be better off with the Katajainen algorithm. */
83*f4ee7fbaSAndroid Build Coastguard Worker   for (count_limit = 1; ; count_limit *= 2) {
84*f4ee7fbaSAndroid Build Coastguard Worker     size_t n = 0;
85*f4ee7fbaSAndroid Build Coastguard Worker     size_t i;
86*f4ee7fbaSAndroid Build Coastguard Worker     size_t j;
87*f4ee7fbaSAndroid Build Coastguard Worker     size_t k;
88*f4ee7fbaSAndroid Build Coastguard Worker     for (i = length; i != 0;) {
89*f4ee7fbaSAndroid Build Coastguard Worker       --i;
90*f4ee7fbaSAndroid Build Coastguard Worker       if (data[i]) {
91*f4ee7fbaSAndroid Build Coastguard Worker         const uint32_t count = BROTLI_MAX(uint32_t, data[i], count_limit);
92*f4ee7fbaSAndroid Build Coastguard Worker         InitHuffmanTree(&tree[n++], count, -1, (int16_t)i);
93*f4ee7fbaSAndroid Build Coastguard Worker       }
94*f4ee7fbaSAndroid Build Coastguard Worker     }
95*f4ee7fbaSAndroid Build Coastguard Worker 
96*f4ee7fbaSAndroid Build Coastguard Worker     if (n == 1) {
97*f4ee7fbaSAndroid Build Coastguard Worker       depth[tree[0].index_right_or_value_] = 1;  /* Only one element. */
98*f4ee7fbaSAndroid Build Coastguard Worker       break;
99*f4ee7fbaSAndroid Build Coastguard Worker     }
100*f4ee7fbaSAndroid Build Coastguard Worker 
101*f4ee7fbaSAndroid Build Coastguard Worker     SortHuffmanTreeItems(tree, n, SortHuffmanTree);
102*f4ee7fbaSAndroid Build Coastguard Worker 
103*f4ee7fbaSAndroid Build Coastguard Worker     /* The nodes are:
104*f4ee7fbaSAndroid Build Coastguard Worker        [0, n): the sorted leaf nodes that we start with.
105*f4ee7fbaSAndroid Build Coastguard Worker        [n]: we add a sentinel here.
106*f4ee7fbaSAndroid Build Coastguard Worker        [n + 1, 2n): new parent nodes are added here, starting from
107*f4ee7fbaSAndroid Build Coastguard Worker                     (n+1). These are naturally in ascending order.
108*f4ee7fbaSAndroid Build Coastguard Worker        [2n]: we add a sentinel at the end as well.
109*f4ee7fbaSAndroid Build Coastguard Worker        There will be (2n+1) elements at the end. */
110*f4ee7fbaSAndroid Build Coastguard Worker     tree[n] = sentinel;
111*f4ee7fbaSAndroid Build Coastguard Worker     tree[n + 1] = sentinel;
112*f4ee7fbaSAndroid Build Coastguard Worker 
113*f4ee7fbaSAndroid Build Coastguard Worker     i = 0;      /* Points to the next leaf node. */
114*f4ee7fbaSAndroid Build Coastguard Worker     j = n + 1;  /* Points to the next non-leaf node. */
115*f4ee7fbaSAndroid Build Coastguard Worker     for (k = n - 1; k != 0; --k) {
116*f4ee7fbaSAndroid Build Coastguard Worker       size_t left, right;
117*f4ee7fbaSAndroid Build Coastguard Worker       if (tree[i].total_count_ <= tree[j].total_count_) {
118*f4ee7fbaSAndroid Build Coastguard Worker         left = i;
119*f4ee7fbaSAndroid Build Coastguard Worker         ++i;
120*f4ee7fbaSAndroid Build Coastguard Worker       } else {
121*f4ee7fbaSAndroid Build Coastguard Worker         left = j;
122*f4ee7fbaSAndroid Build Coastguard Worker         ++j;
123*f4ee7fbaSAndroid Build Coastguard Worker       }
124*f4ee7fbaSAndroid Build Coastguard Worker       if (tree[i].total_count_ <= tree[j].total_count_) {
125*f4ee7fbaSAndroid Build Coastguard Worker         right = i;
126*f4ee7fbaSAndroid Build Coastguard Worker         ++i;
127*f4ee7fbaSAndroid Build Coastguard Worker       } else {
128*f4ee7fbaSAndroid Build Coastguard Worker         right = j;
129*f4ee7fbaSAndroid Build Coastguard Worker         ++j;
130*f4ee7fbaSAndroid Build Coastguard Worker       }
131*f4ee7fbaSAndroid Build Coastguard Worker 
132*f4ee7fbaSAndroid Build Coastguard Worker       {
133*f4ee7fbaSAndroid Build Coastguard Worker         /* The sentinel node becomes the parent node. */
134*f4ee7fbaSAndroid Build Coastguard Worker         size_t j_end = 2 * n - k;
135*f4ee7fbaSAndroid Build Coastguard Worker         tree[j_end].total_count_ =
136*f4ee7fbaSAndroid Build Coastguard Worker             tree[left].total_count_ + tree[right].total_count_;
137*f4ee7fbaSAndroid Build Coastguard Worker         tree[j_end].index_left_ = (int16_t)left;
138*f4ee7fbaSAndroid Build Coastguard Worker         tree[j_end].index_right_or_value_ = (int16_t)right;
139*f4ee7fbaSAndroid Build Coastguard Worker 
140*f4ee7fbaSAndroid Build Coastguard Worker         /* Add back the last sentinel node. */
141*f4ee7fbaSAndroid Build Coastguard Worker         tree[j_end + 1] = sentinel;
142*f4ee7fbaSAndroid Build Coastguard Worker       }
143*f4ee7fbaSAndroid Build Coastguard Worker     }
144*f4ee7fbaSAndroid Build Coastguard Worker     if (BrotliSetDepth((int)(2 * n - 1), &tree[0], depth, tree_limit)) {
145*f4ee7fbaSAndroid Build Coastguard Worker       /* We need to pack the Huffman tree in tree_limit bits. If this was not
146*f4ee7fbaSAndroid Build Coastguard Worker          successful, add fake entities to the lowest values and retry. */
147*f4ee7fbaSAndroid Build Coastguard Worker       break;
148*f4ee7fbaSAndroid Build Coastguard Worker     }
149*f4ee7fbaSAndroid Build Coastguard Worker   }
150*f4ee7fbaSAndroid Build Coastguard Worker }
151*f4ee7fbaSAndroid Build Coastguard Worker 
Reverse(uint8_t * v,size_t start,size_t end)152*f4ee7fbaSAndroid Build Coastguard Worker static void Reverse(uint8_t* v, size_t start, size_t end) {
153*f4ee7fbaSAndroid Build Coastguard Worker   --end;
154*f4ee7fbaSAndroid Build Coastguard Worker   while (start < end) {
155*f4ee7fbaSAndroid Build Coastguard Worker     uint8_t tmp = v[start];
156*f4ee7fbaSAndroid Build Coastguard Worker     v[start] = v[end];
157*f4ee7fbaSAndroid Build Coastguard Worker     v[end] = tmp;
158*f4ee7fbaSAndroid Build Coastguard Worker     ++start;
159*f4ee7fbaSAndroid Build Coastguard Worker     --end;
160*f4ee7fbaSAndroid Build Coastguard Worker   }
161*f4ee7fbaSAndroid Build Coastguard Worker }
162*f4ee7fbaSAndroid Build Coastguard Worker 
BrotliWriteHuffmanTreeRepetitions(const uint8_t previous_value,const uint8_t value,size_t repetitions,size_t * tree_size,uint8_t * tree,uint8_t * extra_bits_data)163*f4ee7fbaSAndroid Build Coastguard Worker static void BrotliWriteHuffmanTreeRepetitions(
164*f4ee7fbaSAndroid Build Coastguard Worker     const uint8_t previous_value,
165*f4ee7fbaSAndroid Build Coastguard Worker     const uint8_t value,
166*f4ee7fbaSAndroid Build Coastguard Worker     size_t repetitions,
167*f4ee7fbaSAndroid Build Coastguard Worker     size_t* tree_size,
168*f4ee7fbaSAndroid Build Coastguard Worker     uint8_t* tree,
169*f4ee7fbaSAndroid Build Coastguard Worker     uint8_t* extra_bits_data) {
170*f4ee7fbaSAndroid Build Coastguard Worker   BROTLI_DCHECK(repetitions > 0);
171*f4ee7fbaSAndroid Build Coastguard Worker   if (previous_value != value) {
172*f4ee7fbaSAndroid Build Coastguard Worker     tree[*tree_size] = value;
173*f4ee7fbaSAndroid Build Coastguard Worker     extra_bits_data[*tree_size] = 0;
174*f4ee7fbaSAndroid Build Coastguard Worker     ++(*tree_size);
175*f4ee7fbaSAndroid Build Coastguard Worker     --repetitions;
176*f4ee7fbaSAndroid Build Coastguard Worker   }
177*f4ee7fbaSAndroid Build Coastguard Worker   if (repetitions == 7) {
178*f4ee7fbaSAndroid Build Coastguard Worker     tree[*tree_size] = value;
179*f4ee7fbaSAndroid Build Coastguard Worker     extra_bits_data[*tree_size] = 0;
180*f4ee7fbaSAndroid Build Coastguard Worker     ++(*tree_size);
181*f4ee7fbaSAndroid Build Coastguard Worker     --repetitions;
182*f4ee7fbaSAndroid Build Coastguard Worker   }
183*f4ee7fbaSAndroid Build Coastguard Worker   if (repetitions < 3) {
184*f4ee7fbaSAndroid Build Coastguard Worker     size_t i;
185*f4ee7fbaSAndroid Build Coastguard Worker     for (i = 0; i < repetitions; ++i) {
186*f4ee7fbaSAndroid Build Coastguard Worker       tree[*tree_size] = value;
187*f4ee7fbaSAndroid Build Coastguard Worker       extra_bits_data[*tree_size] = 0;
188*f4ee7fbaSAndroid Build Coastguard Worker       ++(*tree_size);
189*f4ee7fbaSAndroid Build Coastguard Worker     }
190*f4ee7fbaSAndroid Build Coastguard Worker   } else {
191*f4ee7fbaSAndroid Build Coastguard Worker     size_t start = *tree_size;
192*f4ee7fbaSAndroid Build Coastguard Worker     repetitions -= 3;
193*f4ee7fbaSAndroid Build Coastguard Worker     while (BROTLI_TRUE) {
194*f4ee7fbaSAndroid Build Coastguard Worker       tree[*tree_size] = BROTLI_REPEAT_PREVIOUS_CODE_LENGTH;
195*f4ee7fbaSAndroid Build Coastguard Worker       extra_bits_data[*tree_size] = repetitions & 0x3;
196*f4ee7fbaSAndroid Build Coastguard Worker       ++(*tree_size);
197*f4ee7fbaSAndroid Build Coastguard Worker       repetitions >>= 2;
198*f4ee7fbaSAndroid Build Coastguard Worker       if (repetitions == 0) {
199*f4ee7fbaSAndroid Build Coastguard Worker         break;
200*f4ee7fbaSAndroid Build Coastguard Worker       }
201*f4ee7fbaSAndroid Build Coastguard Worker       --repetitions;
202*f4ee7fbaSAndroid Build Coastguard Worker     }
203*f4ee7fbaSAndroid Build Coastguard Worker     Reverse(tree, start, *tree_size);
204*f4ee7fbaSAndroid Build Coastguard Worker     Reverse(extra_bits_data, start, *tree_size);
205*f4ee7fbaSAndroid Build Coastguard Worker   }
206*f4ee7fbaSAndroid Build Coastguard Worker }
207*f4ee7fbaSAndroid Build Coastguard Worker 
BrotliWriteHuffmanTreeRepetitionsZeros(size_t repetitions,size_t * tree_size,uint8_t * tree,uint8_t * extra_bits_data)208*f4ee7fbaSAndroid Build Coastguard Worker static void BrotliWriteHuffmanTreeRepetitionsZeros(
209*f4ee7fbaSAndroid Build Coastguard Worker     size_t repetitions,
210*f4ee7fbaSAndroid Build Coastguard Worker     size_t* tree_size,
211*f4ee7fbaSAndroid Build Coastguard Worker     uint8_t* tree,
212*f4ee7fbaSAndroid Build Coastguard Worker     uint8_t* extra_bits_data) {
213*f4ee7fbaSAndroid Build Coastguard Worker   if (repetitions == 11) {
214*f4ee7fbaSAndroid Build Coastguard Worker     tree[*tree_size] = 0;
215*f4ee7fbaSAndroid Build Coastguard Worker     extra_bits_data[*tree_size] = 0;
216*f4ee7fbaSAndroid Build Coastguard Worker     ++(*tree_size);
217*f4ee7fbaSAndroid Build Coastguard Worker     --repetitions;
218*f4ee7fbaSAndroid Build Coastguard Worker   }
219*f4ee7fbaSAndroid Build Coastguard Worker   if (repetitions < 3) {
220*f4ee7fbaSAndroid Build Coastguard Worker     size_t i;
221*f4ee7fbaSAndroid Build Coastguard Worker     for (i = 0; i < repetitions; ++i) {
222*f4ee7fbaSAndroid Build Coastguard Worker       tree[*tree_size] = 0;
223*f4ee7fbaSAndroid Build Coastguard Worker       extra_bits_data[*tree_size] = 0;
224*f4ee7fbaSAndroid Build Coastguard Worker       ++(*tree_size);
225*f4ee7fbaSAndroid Build Coastguard Worker     }
226*f4ee7fbaSAndroid Build Coastguard Worker   } else {
227*f4ee7fbaSAndroid Build Coastguard Worker     size_t start = *tree_size;
228*f4ee7fbaSAndroid Build Coastguard Worker     repetitions -= 3;
229*f4ee7fbaSAndroid Build Coastguard Worker     while (BROTLI_TRUE) {
230*f4ee7fbaSAndroid Build Coastguard Worker       tree[*tree_size] = BROTLI_REPEAT_ZERO_CODE_LENGTH;
231*f4ee7fbaSAndroid Build Coastguard Worker       extra_bits_data[*tree_size] = repetitions & 0x7;
232*f4ee7fbaSAndroid Build Coastguard Worker       ++(*tree_size);
233*f4ee7fbaSAndroid Build Coastguard Worker       repetitions >>= 3;
234*f4ee7fbaSAndroid Build Coastguard Worker       if (repetitions == 0) {
235*f4ee7fbaSAndroid Build Coastguard Worker         break;
236*f4ee7fbaSAndroid Build Coastguard Worker       }
237*f4ee7fbaSAndroid Build Coastguard Worker       --repetitions;
238*f4ee7fbaSAndroid Build Coastguard Worker     }
239*f4ee7fbaSAndroid Build Coastguard Worker     Reverse(tree, start, *tree_size);
240*f4ee7fbaSAndroid Build Coastguard Worker     Reverse(extra_bits_data, start, *tree_size);
241*f4ee7fbaSAndroid Build Coastguard Worker   }
242*f4ee7fbaSAndroid Build Coastguard Worker }
243*f4ee7fbaSAndroid Build Coastguard Worker 
BrotliOptimizeHuffmanCountsForRle(size_t length,uint32_t * counts,uint8_t * good_for_rle)244*f4ee7fbaSAndroid Build Coastguard Worker void BrotliOptimizeHuffmanCountsForRle(size_t length, uint32_t* counts,
245*f4ee7fbaSAndroid Build Coastguard Worker                                        uint8_t* good_for_rle) {
246*f4ee7fbaSAndroid Build Coastguard Worker   size_t nonzero_count = 0;
247*f4ee7fbaSAndroid Build Coastguard Worker   size_t stride;
248*f4ee7fbaSAndroid Build Coastguard Worker   size_t limit;
249*f4ee7fbaSAndroid Build Coastguard Worker   size_t sum;
250*f4ee7fbaSAndroid Build Coastguard Worker   const size_t streak_limit = 1240;
251*f4ee7fbaSAndroid Build Coastguard Worker   /* Let's make the Huffman code more compatible with RLE encoding. */
252*f4ee7fbaSAndroid Build Coastguard Worker   size_t i;
253*f4ee7fbaSAndroid Build Coastguard Worker   for (i = 0; i < length; i++) {
254*f4ee7fbaSAndroid Build Coastguard Worker     if (counts[i]) {
255*f4ee7fbaSAndroid Build Coastguard Worker       ++nonzero_count;
256*f4ee7fbaSAndroid Build Coastguard Worker     }
257*f4ee7fbaSAndroid Build Coastguard Worker   }
258*f4ee7fbaSAndroid Build Coastguard Worker   if (nonzero_count < 16) {
259*f4ee7fbaSAndroid Build Coastguard Worker     return;
260*f4ee7fbaSAndroid Build Coastguard Worker   }
261*f4ee7fbaSAndroid Build Coastguard Worker   while (length != 0 && counts[length - 1] == 0) {
262*f4ee7fbaSAndroid Build Coastguard Worker     --length;
263*f4ee7fbaSAndroid Build Coastguard Worker   }
264*f4ee7fbaSAndroid Build Coastguard Worker   if (length == 0) {
265*f4ee7fbaSAndroid Build Coastguard Worker     return;  /* All zeros. */
266*f4ee7fbaSAndroid Build Coastguard Worker   }
267*f4ee7fbaSAndroid Build Coastguard Worker   /* Now counts[0..length - 1] does not have trailing zeros. */
268*f4ee7fbaSAndroid Build Coastguard Worker   {
269*f4ee7fbaSAndroid Build Coastguard Worker     size_t nonzeros = 0;
270*f4ee7fbaSAndroid Build Coastguard Worker     uint32_t smallest_nonzero = 1 << 30;
271*f4ee7fbaSAndroid Build Coastguard Worker     for (i = 0; i < length; ++i) {
272*f4ee7fbaSAndroid Build Coastguard Worker       if (counts[i] != 0) {
273*f4ee7fbaSAndroid Build Coastguard Worker         ++nonzeros;
274*f4ee7fbaSAndroid Build Coastguard Worker         if (smallest_nonzero > counts[i]) {
275*f4ee7fbaSAndroid Build Coastguard Worker           smallest_nonzero = counts[i];
276*f4ee7fbaSAndroid Build Coastguard Worker         }
277*f4ee7fbaSAndroid Build Coastguard Worker       }
278*f4ee7fbaSAndroid Build Coastguard Worker     }
279*f4ee7fbaSAndroid Build Coastguard Worker     if (nonzeros < 5) {
280*f4ee7fbaSAndroid Build Coastguard Worker       /* Small histogram will model it well. */
281*f4ee7fbaSAndroid Build Coastguard Worker       return;
282*f4ee7fbaSAndroid Build Coastguard Worker     }
283*f4ee7fbaSAndroid Build Coastguard Worker     if (smallest_nonzero < 4) {
284*f4ee7fbaSAndroid Build Coastguard Worker       size_t zeros = length - nonzeros;
285*f4ee7fbaSAndroid Build Coastguard Worker       if (zeros < 6) {
286*f4ee7fbaSAndroid Build Coastguard Worker         for (i = 1; i < length - 1; ++i) {
287*f4ee7fbaSAndroid Build Coastguard Worker           if (counts[i - 1] != 0 && counts[i] == 0 && counts[i + 1] != 0) {
288*f4ee7fbaSAndroid Build Coastguard Worker             counts[i] = 1;
289*f4ee7fbaSAndroid Build Coastguard Worker           }
290*f4ee7fbaSAndroid Build Coastguard Worker         }
291*f4ee7fbaSAndroid Build Coastguard Worker       }
292*f4ee7fbaSAndroid Build Coastguard Worker     }
293*f4ee7fbaSAndroid Build Coastguard Worker     if (nonzeros < 28) {
294*f4ee7fbaSAndroid Build Coastguard Worker       return;
295*f4ee7fbaSAndroid Build Coastguard Worker     }
296*f4ee7fbaSAndroid Build Coastguard Worker   }
297*f4ee7fbaSAndroid Build Coastguard Worker   /* 2) Let's mark all population counts that already can be encoded
298*f4ee7fbaSAndroid Build Coastguard Worker      with an RLE code. */
299*f4ee7fbaSAndroid Build Coastguard Worker   memset(good_for_rle, 0, length);
300*f4ee7fbaSAndroid Build Coastguard Worker   {
301*f4ee7fbaSAndroid Build Coastguard Worker     /* Let's not spoil any of the existing good RLE codes.
302*f4ee7fbaSAndroid Build Coastguard Worker        Mark any seq of 0's that is longer as 5 as a good_for_rle.
303*f4ee7fbaSAndroid Build Coastguard Worker        Mark any seq of non-0's that is longer as 7 as a good_for_rle. */
304*f4ee7fbaSAndroid Build Coastguard Worker     uint32_t symbol = counts[0];
305*f4ee7fbaSAndroid Build Coastguard Worker     size_t step = 0;
306*f4ee7fbaSAndroid Build Coastguard Worker     for (i = 0; i <= length; ++i) {
307*f4ee7fbaSAndroid Build Coastguard Worker       if (i == length || counts[i] != symbol) {
308*f4ee7fbaSAndroid Build Coastguard Worker         if ((symbol == 0 && step >= 5) ||
309*f4ee7fbaSAndroid Build Coastguard Worker             (symbol != 0 && step >= 7)) {
310*f4ee7fbaSAndroid Build Coastguard Worker           size_t k;
311*f4ee7fbaSAndroid Build Coastguard Worker           for (k = 0; k < step; ++k) {
312*f4ee7fbaSAndroid Build Coastguard Worker             good_for_rle[i - k - 1] = 1;
313*f4ee7fbaSAndroid Build Coastguard Worker           }
314*f4ee7fbaSAndroid Build Coastguard Worker         }
315*f4ee7fbaSAndroid Build Coastguard Worker         step = 1;
316*f4ee7fbaSAndroid Build Coastguard Worker         if (i != length) {
317*f4ee7fbaSAndroid Build Coastguard Worker           symbol = counts[i];
318*f4ee7fbaSAndroid Build Coastguard Worker         }
319*f4ee7fbaSAndroid Build Coastguard Worker       } else {
320*f4ee7fbaSAndroid Build Coastguard Worker         ++step;
321*f4ee7fbaSAndroid Build Coastguard Worker       }
322*f4ee7fbaSAndroid Build Coastguard Worker     }
323*f4ee7fbaSAndroid Build Coastguard Worker   }
324*f4ee7fbaSAndroid Build Coastguard Worker   /* 3) Let's replace those population counts that lead to more RLE codes.
325*f4ee7fbaSAndroid Build Coastguard Worker      Math here is in 24.8 fixed point representation. */
326*f4ee7fbaSAndroid Build Coastguard Worker   stride = 0;
327*f4ee7fbaSAndroid Build Coastguard Worker   limit = 256 * (counts[0] + counts[1] + counts[2]) / 3 + 420;
328*f4ee7fbaSAndroid Build Coastguard Worker   sum = 0;
329*f4ee7fbaSAndroid Build Coastguard Worker   for (i = 0; i <= length; ++i) {
330*f4ee7fbaSAndroid Build Coastguard Worker     if (i == length || good_for_rle[i] ||
331*f4ee7fbaSAndroid Build Coastguard Worker         (i != 0 && good_for_rle[i - 1]) ||
332*f4ee7fbaSAndroid Build Coastguard Worker         (256 * counts[i] - limit + streak_limit) >= 2 * streak_limit) {
333*f4ee7fbaSAndroid Build Coastguard Worker       if (stride >= 4 || (stride >= 3 && sum == 0)) {
334*f4ee7fbaSAndroid Build Coastguard Worker         size_t k;
335*f4ee7fbaSAndroid Build Coastguard Worker         /* The stride must end, collapse what we have, if we have enough (4). */
336*f4ee7fbaSAndroid Build Coastguard Worker         size_t count = (sum + stride / 2) / stride;
337*f4ee7fbaSAndroid Build Coastguard Worker         if (count == 0) {
338*f4ee7fbaSAndroid Build Coastguard Worker           count = 1;
339*f4ee7fbaSAndroid Build Coastguard Worker         }
340*f4ee7fbaSAndroid Build Coastguard Worker         if (sum == 0) {
341*f4ee7fbaSAndroid Build Coastguard Worker           /* Don't make an all zeros stride to be upgraded to ones. */
342*f4ee7fbaSAndroid Build Coastguard Worker           count = 0;
343*f4ee7fbaSAndroid Build Coastguard Worker         }
344*f4ee7fbaSAndroid Build Coastguard Worker         for (k = 0; k < stride; ++k) {
345*f4ee7fbaSAndroid Build Coastguard Worker           /* We don't want to change value at counts[i],
346*f4ee7fbaSAndroid Build Coastguard Worker              that is already belonging to the next stride. Thus - 1. */
347*f4ee7fbaSAndroid Build Coastguard Worker           counts[i - k - 1] = (uint32_t)count;
348*f4ee7fbaSAndroid Build Coastguard Worker         }
349*f4ee7fbaSAndroid Build Coastguard Worker       }
350*f4ee7fbaSAndroid Build Coastguard Worker       stride = 0;
351*f4ee7fbaSAndroid Build Coastguard Worker       sum = 0;
352*f4ee7fbaSAndroid Build Coastguard Worker       if (i < length - 2) {
353*f4ee7fbaSAndroid Build Coastguard Worker         /* All interesting strides have a count of at least 4, */
354*f4ee7fbaSAndroid Build Coastguard Worker         /* at least when non-zeros. */
355*f4ee7fbaSAndroid Build Coastguard Worker         limit = 256 * (counts[i] + counts[i + 1] + counts[i + 2]) / 3 + 420;
356*f4ee7fbaSAndroid Build Coastguard Worker       } else if (i < length) {
357*f4ee7fbaSAndroid Build Coastguard Worker         limit = 256 * counts[i];
358*f4ee7fbaSAndroid Build Coastguard Worker       } else {
359*f4ee7fbaSAndroid Build Coastguard Worker         limit = 0;
360*f4ee7fbaSAndroid Build Coastguard Worker       }
361*f4ee7fbaSAndroid Build Coastguard Worker     }
362*f4ee7fbaSAndroid Build Coastguard Worker     ++stride;
363*f4ee7fbaSAndroid Build Coastguard Worker     if (i != length) {
364*f4ee7fbaSAndroid Build Coastguard Worker       sum += counts[i];
365*f4ee7fbaSAndroid Build Coastguard Worker       if (stride >= 4) {
366*f4ee7fbaSAndroid Build Coastguard Worker         limit = (256 * sum + stride / 2) / stride;
367*f4ee7fbaSAndroid Build Coastguard Worker       }
368*f4ee7fbaSAndroid Build Coastguard Worker       if (stride == 4) {
369*f4ee7fbaSAndroid Build Coastguard Worker         limit += 120;
370*f4ee7fbaSAndroid Build Coastguard Worker       }
371*f4ee7fbaSAndroid Build Coastguard Worker     }
372*f4ee7fbaSAndroid Build Coastguard Worker   }
373*f4ee7fbaSAndroid Build Coastguard Worker }
374*f4ee7fbaSAndroid Build Coastguard Worker 
DecideOverRleUse(const uint8_t * depth,const size_t length,BROTLI_BOOL * use_rle_for_non_zero,BROTLI_BOOL * use_rle_for_zero)375*f4ee7fbaSAndroid Build Coastguard Worker static void DecideOverRleUse(const uint8_t* depth, const size_t length,
376*f4ee7fbaSAndroid Build Coastguard Worker                              BROTLI_BOOL* use_rle_for_non_zero,
377*f4ee7fbaSAndroid Build Coastguard Worker                              BROTLI_BOOL* use_rle_for_zero) {
378*f4ee7fbaSAndroid Build Coastguard Worker   size_t total_reps_zero = 0;
379*f4ee7fbaSAndroid Build Coastguard Worker   size_t total_reps_non_zero = 0;
380*f4ee7fbaSAndroid Build Coastguard Worker   size_t count_reps_zero = 1;
381*f4ee7fbaSAndroid Build Coastguard Worker   size_t count_reps_non_zero = 1;
382*f4ee7fbaSAndroid Build Coastguard Worker   size_t i;
383*f4ee7fbaSAndroid Build Coastguard Worker   for (i = 0; i < length;) {
384*f4ee7fbaSAndroid Build Coastguard Worker     const uint8_t value = depth[i];
385*f4ee7fbaSAndroid Build Coastguard Worker     size_t reps = 1;
386*f4ee7fbaSAndroid Build Coastguard Worker     size_t k;
387*f4ee7fbaSAndroid Build Coastguard Worker     for (k = i + 1; k < length && depth[k] == value; ++k) {
388*f4ee7fbaSAndroid Build Coastguard Worker       ++reps;
389*f4ee7fbaSAndroid Build Coastguard Worker     }
390*f4ee7fbaSAndroid Build Coastguard Worker     if (reps >= 3 && value == 0) {
391*f4ee7fbaSAndroid Build Coastguard Worker       total_reps_zero += reps;
392*f4ee7fbaSAndroid Build Coastguard Worker       ++count_reps_zero;
393*f4ee7fbaSAndroid Build Coastguard Worker     }
394*f4ee7fbaSAndroid Build Coastguard Worker     if (reps >= 4 && value != 0) {
395*f4ee7fbaSAndroid Build Coastguard Worker       total_reps_non_zero += reps;
396*f4ee7fbaSAndroid Build Coastguard Worker       ++count_reps_non_zero;
397*f4ee7fbaSAndroid Build Coastguard Worker     }
398*f4ee7fbaSAndroid Build Coastguard Worker     i += reps;
399*f4ee7fbaSAndroid Build Coastguard Worker   }
400*f4ee7fbaSAndroid Build Coastguard Worker   *use_rle_for_non_zero =
401*f4ee7fbaSAndroid Build Coastguard Worker       TO_BROTLI_BOOL(total_reps_non_zero > count_reps_non_zero * 2);
402*f4ee7fbaSAndroid Build Coastguard Worker   *use_rle_for_zero = TO_BROTLI_BOOL(total_reps_zero > count_reps_zero * 2);
403*f4ee7fbaSAndroid Build Coastguard Worker }
404*f4ee7fbaSAndroid Build Coastguard Worker 
BrotliWriteHuffmanTree(const uint8_t * depth,size_t length,size_t * tree_size,uint8_t * tree,uint8_t * extra_bits_data)405*f4ee7fbaSAndroid Build Coastguard Worker void BrotliWriteHuffmanTree(const uint8_t* depth,
406*f4ee7fbaSAndroid Build Coastguard Worker                             size_t length,
407*f4ee7fbaSAndroid Build Coastguard Worker                             size_t* tree_size,
408*f4ee7fbaSAndroid Build Coastguard Worker                             uint8_t* tree,
409*f4ee7fbaSAndroid Build Coastguard Worker                             uint8_t* extra_bits_data) {
410*f4ee7fbaSAndroid Build Coastguard Worker   uint8_t previous_value = BROTLI_INITIAL_REPEATED_CODE_LENGTH;
411*f4ee7fbaSAndroid Build Coastguard Worker   size_t i;
412*f4ee7fbaSAndroid Build Coastguard Worker   BROTLI_BOOL use_rle_for_non_zero = BROTLI_FALSE;
413*f4ee7fbaSAndroid Build Coastguard Worker   BROTLI_BOOL use_rle_for_zero = BROTLI_FALSE;
414*f4ee7fbaSAndroid Build Coastguard Worker 
415*f4ee7fbaSAndroid Build Coastguard Worker   /* Throw away trailing zeros. */
416*f4ee7fbaSAndroid Build Coastguard Worker   size_t new_length = length;
417*f4ee7fbaSAndroid Build Coastguard Worker   for (i = 0; i < length; ++i) {
418*f4ee7fbaSAndroid Build Coastguard Worker     if (depth[length - i - 1] == 0) {
419*f4ee7fbaSAndroid Build Coastguard Worker       --new_length;
420*f4ee7fbaSAndroid Build Coastguard Worker     } else {
421*f4ee7fbaSAndroid Build Coastguard Worker       break;
422*f4ee7fbaSAndroid Build Coastguard Worker     }
423*f4ee7fbaSAndroid Build Coastguard Worker   }
424*f4ee7fbaSAndroid Build Coastguard Worker 
425*f4ee7fbaSAndroid Build Coastguard Worker   /* First gather statistics on if it is a good idea to do RLE. */
426*f4ee7fbaSAndroid Build Coastguard Worker   if (length > 50) {
427*f4ee7fbaSAndroid Build Coastguard Worker     /* Find RLE coding for longer codes.
428*f4ee7fbaSAndroid Build Coastguard Worker        Shorter codes seem not to benefit from RLE. */
429*f4ee7fbaSAndroid Build Coastguard Worker     DecideOverRleUse(depth, new_length,
430*f4ee7fbaSAndroid Build Coastguard Worker                      &use_rle_for_non_zero, &use_rle_for_zero);
431*f4ee7fbaSAndroid Build Coastguard Worker   }
432*f4ee7fbaSAndroid Build Coastguard Worker 
433*f4ee7fbaSAndroid Build Coastguard Worker   /* Actual RLE coding. */
434*f4ee7fbaSAndroid Build Coastguard Worker   for (i = 0; i < new_length;) {
435*f4ee7fbaSAndroid Build Coastguard Worker     const uint8_t value = depth[i];
436*f4ee7fbaSAndroid Build Coastguard Worker     size_t reps = 1;
437*f4ee7fbaSAndroid Build Coastguard Worker     if ((value != 0 && use_rle_for_non_zero) ||
438*f4ee7fbaSAndroid Build Coastguard Worker         (value == 0 && use_rle_for_zero)) {
439*f4ee7fbaSAndroid Build Coastguard Worker       size_t k;
440*f4ee7fbaSAndroid Build Coastguard Worker       for (k = i + 1; k < new_length && depth[k] == value; ++k) {
441*f4ee7fbaSAndroid Build Coastguard Worker         ++reps;
442*f4ee7fbaSAndroid Build Coastguard Worker       }
443*f4ee7fbaSAndroid Build Coastguard Worker     }
444*f4ee7fbaSAndroid Build Coastguard Worker     if (value == 0) {
445*f4ee7fbaSAndroid Build Coastguard Worker       BrotliWriteHuffmanTreeRepetitionsZeros(
446*f4ee7fbaSAndroid Build Coastguard Worker           reps, tree_size, tree, extra_bits_data);
447*f4ee7fbaSAndroid Build Coastguard Worker     } else {
448*f4ee7fbaSAndroid Build Coastguard Worker       BrotliWriteHuffmanTreeRepetitions(previous_value,
449*f4ee7fbaSAndroid Build Coastguard Worker                                         value, reps, tree_size,
450*f4ee7fbaSAndroid Build Coastguard Worker                                         tree, extra_bits_data);
451*f4ee7fbaSAndroid Build Coastguard Worker       previous_value = value;
452*f4ee7fbaSAndroid Build Coastguard Worker     }
453*f4ee7fbaSAndroid Build Coastguard Worker     i += reps;
454*f4ee7fbaSAndroid Build Coastguard Worker   }
455*f4ee7fbaSAndroid Build Coastguard Worker }
456*f4ee7fbaSAndroid Build Coastguard Worker 
BrotliReverseBits(size_t num_bits,uint16_t bits)457*f4ee7fbaSAndroid Build Coastguard Worker static uint16_t BrotliReverseBits(size_t num_bits, uint16_t bits) {
458*f4ee7fbaSAndroid Build Coastguard Worker   static const size_t kLut[16] = {  /* Pre-reversed 4-bit values. */
459*f4ee7fbaSAndroid Build Coastguard Worker     0x00, 0x08, 0x04, 0x0C, 0x02, 0x0A, 0x06, 0x0E,
460*f4ee7fbaSAndroid Build Coastguard Worker     0x01, 0x09, 0x05, 0x0D, 0x03, 0x0B, 0x07, 0x0F
461*f4ee7fbaSAndroid Build Coastguard Worker   };
462*f4ee7fbaSAndroid Build Coastguard Worker   size_t retval = kLut[bits & 0x0F];
463*f4ee7fbaSAndroid Build Coastguard Worker   size_t i;
464*f4ee7fbaSAndroid Build Coastguard Worker   for (i = 4; i < num_bits; i += 4) {
465*f4ee7fbaSAndroid Build Coastguard Worker     retval <<= 4;
466*f4ee7fbaSAndroid Build Coastguard Worker     bits = (uint16_t)(bits >> 4);
467*f4ee7fbaSAndroid Build Coastguard Worker     retval |= kLut[bits & 0x0F];
468*f4ee7fbaSAndroid Build Coastguard Worker   }
469*f4ee7fbaSAndroid Build Coastguard Worker   retval >>= ((0 - num_bits) & 0x03);
470*f4ee7fbaSAndroid Build Coastguard Worker   return (uint16_t)retval;
471*f4ee7fbaSAndroid Build Coastguard Worker }
472*f4ee7fbaSAndroid Build Coastguard Worker 
473*f4ee7fbaSAndroid Build Coastguard Worker /* 0..15 are values for bits */
474*f4ee7fbaSAndroid Build Coastguard Worker #define MAX_HUFFMAN_BITS 16
475*f4ee7fbaSAndroid Build Coastguard Worker 
BrotliConvertBitDepthsToSymbols(const uint8_t * depth,size_t len,uint16_t * bits)476*f4ee7fbaSAndroid Build Coastguard Worker void BrotliConvertBitDepthsToSymbols(const uint8_t* depth,
477*f4ee7fbaSAndroid Build Coastguard Worker                                      size_t len,
478*f4ee7fbaSAndroid Build Coastguard Worker                                      uint16_t* bits) {
479*f4ee7fbaSAndroid Build Coastguard Worker   /* In Brotli, all bit depths are [1..15]
480*f4ee7fbaSAndroid Build Coastguard Worker      0 bit depth means that the symbol does not exist. */
481*f4ee7fbaSAndroid Build Coastguard Worker   uint16_t bl_count[MAX_HUFFMAN_BITS] = { 0 };
482*f4ee7fbaSAndroid Build Coastguard Worker   uint16_t next_code[MAX_HUFFMAN_BITS];
483*f4ee7fbaSAndroid Build Coastguard Worker   size_t i;
484*f4ee7fbaSAndroid Build Coastguard Worker   int code = 0;
485*f4ee7fbaSAndroid Build Coastguard Worker   for (i = 0; i < len; ++i) {
486*f4ee7fbaSAndroid Build Coastguard Worker     ++bl_count[depth[i]];
487*f4ee7fbaSAndroid Build Coastguard Worker   }
488*f4ee7fbaSAndroid Build Coastguard Worker   bl_count[0] = 0;
489*f4ee7fbaSAndroid Build Coastguard Worker   next_code[0] = 0;
490*f4ee7fbaSAndroid Build Coastguard Worker   for (i = 1; i < MAX_HUFFMAN_BITS; ++i) {
491*f4ee7fbaSAndroid Build Coastguard Worker     code = (code + bl_count[i - 1]) << 1;
492*f4ee7fbaSAndroid Build Coastguard Worker     next_code[i] = (uint16_t)code;
493*f4ee7fbaSAndroid Build Coastguard Worker   }
494*f4ee7fbaSAndroid Build Coastguard Worker   for (i = 0; i < len; ++i) {
495*f4ee7fbaSAndroid Build Coastguard Worker     if (depth[i]) {
496*f4ee7fbaSAndroid Build Coastguard Worker       bits[i] = BrotliReverseBits(depth[i], next_code[depth[i]]++);
497*f4ee7fbaSAndroid Build Coastguard Worker     }
498*f4ee7fbaSAndroid Build Coastguard Worker   }
499*f4ee7fbaSAndroid Build Coastguard Worker }
500*f4ee7fbaSAndroid Build Coastguard Worker 
501*f4ee7fbaSAndroid Build Coastguard Worker #if defined(__cplusplus) || defined(c_plusplus)
502*f4ee7fbaSAndroid Build Coastguard Worker }  /* extern "C" */
503*f4ee7fbaSAndroid Build Coastguard Worker #endif
504