/src/rust-brotli/src/enc/entropy_encode.rs
Line | Count | Source (jump to first uncovered line) |
1 | | /* Copyright 2010 Google Inc. All Rights Reserved. |
2 | | |
3 | | Distributed under MIT license. |
4 | | See file LICENSE for detail or copy at https://opensource.org/licenses/MIT |
5 | | */ |
6 | | |
7 | | /* Entropy encoding (Huffman) utilities. */ |
8 | | use core::cmp::max; |
9 | | |
10 | | #[derive(Clone, Copy, Default)] |
11 | | pub struct HuffmanTree { |
12 | | pub total_count_: u32, |
13 | | pub index_left_: i16, |
14 | | pub index_right_or_value_: i16, |
15 | | } |
16 | | |
17 | | impl HuffmanTree { |
18 | 13.1M | pub fn new(count: u32, left: i16, right: i16) -> Self { |
19 | 13.1M | Self { |
20 | 13.1M | total_count_: count, |
21 | 13.1M | index_left_: left, |
22 | 13.1M | index_right_or_value_: right, |
23 | 13.1M | } |
24 | 13.1M | } |
25 | | } |
26 | | |
27 | 448k | pub fn BrotliSetDepth(p0: i32, pool: &mut [HuffmanTree], depth: &mut [u8], max_depth: i32) -> bool { |
28 | 448k | let mut stack: [i32; 16] = [0; 16]; |
29 | 448k | let mut level: i32 = 0i32; |
30 | 448k | let mut p: i32 = p0; |
31 | 448k | stack[0] = -1i32; |
32 | | loop { |
33 | 24.8M | if (pool[(p as usize)]).index_left_ as i32 >= 0i32 { |
34 | 12.2M | level += 1; |
35 | 12.2M | if level > max_depth { |
36 | 20.7k | return false; |
37 | 12.2M | } |
38 | 12.2M | stack[level as usize] = (pool[(p as usize)]).index_right_or_value_ as i32; |
39 | 12.2M | p = (pool[(p as usize)]).index_left_ as i32; |
40 | 12.2M | { |
41 | 12.2M | continue; |
42 | | } |
43 | 12.6M | } else { |
44 | 12.6M | let pp = pool[(p as usize)]; |
45 | 12.6M | depth[((pp).index_right_or_value_ as usize)] = level as u8; |
46 | 12.6M | } |
47 | 25.1M | while level >= 0i32 && (stack[level as usize] == -1i32) { |
48 | 12.5M | level -= 1; |
49 | 12.5M | } |
50 | 12.6M | if level < 0i32 { |
51 | 428k | return true; |
52 | 12.1M | } |
53 | 12.1M | p = stack[level as usize]; |
54 | 12.1M | stack[level as usize] = -1i32; |
55 | | } |
56 | 448k | } |
57 | | |
58 | | pub trait HuffmanComparator { |
59 | | fn Cmp(&self, a: &HuffmanTree, b: &HuffmanTree) -> bool; |
60 | | } |
61 | | pub struct SortHuffmanTree {} |
62 | | impl HuffmanComparator for SortHuffmanTree { |
63 | 51.3M | fn Cmp(&self, v0: &HuffmanTree, v1: &HuffmanTree) -> bool { |
64 | 51.3M | if v0.total_count_ != v1.total_count_ { |
65 | 18.4M | v0.total_count_ < v1.total_count_ |
66 | | } else { |
67 | 32.9M | v0.index_right_or_value_ > v1.index_right_or_value_ |
68 | | } |
69 | 51.3M | } |
70 | | } |
71 | 448k | pub fn SortHuffmanTreeItems<Comparator: HuffmanComparator>( |
72 | 448k | items: &mut [HuffmanTree], |
73 | 448k | n: usize, |
74 | 448k | comparator: Comparator, |
75 | 448k | ) { |
76 | | static gaps: [usize; 6] = [132, 57, 23, 10, 4, 1]; |
77 | 448k | if n < 13 { |
78 | 1.38M | for i in 1..n { |
79 | 1.38M | let mut tmp: HuffmanTree = items[i]; |
80 | 1.38M | let mut k: usize = i; |
81 | 1.38M | let mut j: usize = i.wrapping_sub(1); |
82 | 3.35M | while comparator.Cmp(&mut tmp, &mut items[j]) { |
83 | 2.37M | items[k] = items[j]; |
84 | 2.37M | k = j; |
85 | 2.37M | if { |
86 | 2.37M | let _old = j; |
87 | 2.37M | j = j.wrapping_sub(1); |
88 | 2.37M | _old |
89 | 2.37M | } == 0 |
90 | | { |
91 | 404k | break; |
92 | 1.97M | } |
93 | | } |
94 | 1.38M | items[k] = tmp; |
95 | | } |
96 | | } else { |
97 | 137k | let mut g: i32 = if n < 57usize { 2i32 } else { 0i32 }; |
98 | 820k | while g < 6i32 { |
99 | | { |
100 | 683k | let gap: usize = gaps[g as usize]; |
101 | 46.4M | for i in gap..n { |
102 | 46.4M | let mut j: usize = i; |
103 | 46.4M | let mut tmp: HuffmanTree = items[i]; |
104 | 68.8M | while j >= gap && (comparator.Cmp(&mut tmp, &mut items[j.wrapping_sub(gap)])) { |
105 | 22.4M | { |
106 | 22.4M | items[j] = items[j.wrapping_sub(gap)]; |
107 | 22.4M | } |
108 | 22.4M | j = j.wrapping_sub(gap); |
109 | 22.4M | } |
110 | 46.4M | items[j] = tmp; |
111 | | } |
112 | | } |
113 | 683k | g += 1; |
114 | | } |
115 | | } |
116 | 448k | } brotli::enc::entropy_encode::SortHuffmanTreeItems::<brotli::enc::brotli_bit_stream::SimpleSortHuffmanTree> Line | Count | Source | 71 | 31.0k | pub fn SortHuffmanTreeItems<Comparator: HuffmanComparator>( | 72 | 31.0k | items: &mut [HuffmanTree], | 73 | 31.0k | n: usize, | 74 | 31.0k | comparator: Comparator, | 75 | 31.0k | ) { | 76 | | static gaps: [usize; 6] = [132, 57, 23, 10, 4, 1]; | 77 | 31.0k | if n < 13 { | 78 | 29.8k | for i in 1..n { | 79 | 29.8k | let mut tmp: HuffmanTree = items[i]; | 80 | 29.8k | let mut k: usize = i; | 81 | 29.8k | let mut j: usize = i.wrapping_sub(1); | 82 | 55.4k | while comparator.Cmp(&mut tmp, &mut items[j]) { | 83 | 30.6k | items[k] = items[j]; | 84 | 30.6k | k = j; | 85 | 30.6k | if { | 86 | 30.6k | let _old = j; | 87 | 30.6k | j = j.wrapping_sub(1); | 88 | 30.6k | _old | 89 | 30.6k | } == 0 | 90 | | { | 91 | 5.05k | break; | 92 | 25.6k | } | 93 | | } | 94 | 29.8k | items[k] = tmp; | 95 | | } | 96 | | } else { | 97 | 22.5k | let mut g: i32 = if n < 57usize { 2i32 } else { 0i32 }; | 98 | 144k | while g < 6i32 { | 99 | | { | 100 | 122k | let gap: usize = gaps[g as usize]; | 101 | 13.7M | for i in gap..n { | 102 | 13.7M | let mut j: usize = i; | 103 | 13.7M | let mut tmp: HuffmanTree = items[i]; | 104 | 19.3M | while j >= gap && (comparator.Cmp(&mut tmp, &mut items[j.wrapping_sub(gap)])) { | 105 | 5.57M | { | 106 | 5.57M | items[j] = items[j.wrapping_sub(gap)]; | 107 | 5.57M | } | 108 | 5.57M | j = j.wrapping_sub(gap); | 109 | 5.57M | } | 110 | 13.7M | items[j] = tmp; | 111 | | } | 112 | | } | 113 | 122k | g += 1; | 114 | | } | 115 | | } | 116 | 31.0k | } |
brotli::enc::entropy_encode::SortHuffmanTreeItems::<brotli::enc::entropy_encode::SortHuffmanTree> Line | Count | Source | 71 | 417k | pub fn SortHuffmanTreeItems<Comparator: HuffmanComparator>( | 72 | 417k | items: &mut [HuffmanTree], | 73 | 417k | n: usize, | 74 | 417k | comparator: Comparator, | 75 | 417k | ) { | 76 | | static gaps: [usize; 6] = [132, 57, 23, 10, 4, 1]; | 77 | 417k | if n < 13 { | 78 | 1.35M | for i in 1..n { | 79 | 1.35M | let mut tmp: HuffmanTree = items[i]; | 80 | 1.35M | let mut k: usize = i; | 81 | 1.35M | let mut j: usize = i.wrapping_sub(1); | 82 | 3.30M | while comparator.Cmp(&mut tmp, &mut items[j]) { | 83 | 2.34M | items[k] = items[j]; | 84 | 2.34M | k = j; | 85 | 2.34M | if { | 86 | 2.34M | let _old = j; | 87 | 2.34M | j = j.wrapping_sub(1); | 88 | 2.34M | _old | 89 | 2.34M | } == 0 | 90 | | { | 91 | 399k | break; | 92 | 1.94M | } | 93 | | } | 94 | 1.35M | items[k] = tmp; | 95 | | } | 96 | | } else { | 97 | 114k | let mut g: i32 = if n < 57usize { 2i32 } else { 0i32 }; | 98 | 676k | while g < 6i32 { | 99 | | { | 100 | 561k | let gap: usize = gaps[g as usize]; | 101 | 32.6M | for i in gap..n { | 102 | 32.6M | let mut j: usize = i; | 103 | 32.6M | let mut tmp: HuffmanTree = items[i]; | 104 | 49.4M | while j >= gap && (comparator.Cmp(&mut tmp, &mut items[j.wrapping_sub(gap)])) { | 105 | 16.8M | { | 106 | 16.8M | items[j] = items[j.wrapping_sub(gap)]; | 107 | 16.8M | } | 108 | 16.8M | j = j.wrapping_sub(gap); | 109 | 16.8M | } | 110 | 32.6M | items[j] = tmp; | 111 | | } | 112 | | } | 113 | 561k | g += 1; | 114 | | } | 115 | | } | 116 | 417k | } |
|
117 | | |
118 | | /* This function will create a Huffman tree. |
119 | | |
120 | | The catch here is that the tree cannot be arbitrarily deep. |
121 | | Brotli specifies a maximum depth of 15 bits for "code trees" |
122 | | and 7 bits for "code length code trees." |
123 | | |
124 | | count_limit is the value that is to be faked as the minimum value |
125 | | and this minimum value is raised until the tree matches the |
126 | | maximum length requirement. |
127 | | |
128 | | This algorithm is not of excellent performance for very long data blocks, |
129 | | especially when population counts are longer than 2**tree_limit, but |
130 | | we are not planning to use this with extremely long blocks. |
131 | | |
132 | | See https://en.wikipedia.org/wiki/Huffman_coding */ |
133 | 397k | pub fn BrotliCreateHuffmanTree( |
134 | 397k | data: &[u32], |
135 | 397k | length: usize, |
136 | 397k | tree_limit: i32, |
137 | 397k | tree: &mut [HuffmanTree], |
138 | 397k | depth: &mut [u8], |
139 | 397k | ) { |
140 | 397k | let sentinel = HuffmanTree::new(u32::MAX, -1, -1); |
141 | 397k | let mut count_limit = 1u32; |
142 | | 'break1: loop { |
143 | | { |
144 | 418k | let mut n: usize = 0usize; |
145 | 418k | let mut i: usize; |
146 | 418k | let mut j: usize; |
147 | 418k | let mut k: usize; |
148 | 418k | i = length; |
149 | 53.2M | while i != 0usize { |
150 | 52.8M | i = i.wrapping_sub(1); |
151 | 52.8M | if data[i] != 0 { |
152 | 9.70M | let count: u32 = max(data[i], count_limit); |
153 | 9.70M | tree[n] = HuffmanTree::new(count, -1, i as i16); |
154 | 9.70M | n = n.wrapping_add(1); |
155 | 43.1M | } |
156 | | } |
157 | 418k | if n == 1 { |
158 | 351 | depth[((tree[0]).index_right_or_value_ as usize)] = 1u8; |
159 | 351 | { |
160 | 351 | break 'break1; |
161 | | } |
162 | 417k | } |
163 | 417k | SortHuffmanTreeItems(tree, n, SortHuffmanTree {}); |
164 | 417k | tree[n] = sentinel; |
165 | 417k | tree[n.wrapping_add(1)] = sentinel; |
166 | 417k | i = 0usize; |
167 | 417k | j = n.wrapping_add(1); |
168 | 417k | k = n.wrapping_sub(1); |
169 | 9.70M | while k != 0usize { |
170 | | { |
171 | | let left: usize; |
172 | | let right: usize; |
173 | 9.28M | if (tree[i]).total_count_ <= (tree[j]).total_count_ { |
174 | 4.92M | left = i; |
175 | 4.92M | i = i.wrapping_add(1); |
176 | 4.92M | } else { |
177 | 4.36M | left = j; |
178 | 4.36M | j = j.wrapping_add(1); |
179 | 4.36M | } |
180 | 9.28M | if (tree[i]).total_count_ <= (tree[j]).total_count_ { |
181 | 4.78M | right = i; |
182 | 4.78M | i = i.wrapping_add(1); |
183 | 4.78M | } else { |
184 | 4.50M | right = j; |
185 | 4.50M | j = j.wrapping_add(1); |
186 | 4.50M | } |
187 | 9.28M | { |
188 | 9.28M | let j_end: usize = (2usize).wrapping_mul(n).wrapping_sub(k); |
189 | 9.28M | (tree[j_end]).total_count_ = (tree[left]) |
190 | 9.28M | .total_count_ |
191 | 9.28M | .wrapping_add((tree[right]).total_count_); |
192 | 9.28M | (tree[j_end]).index_left_ = left as i16; |
193 | 9.28M | (tree[j_end]).index_right_or_value_ = right as i16; |
194 | 9.28M | tree[j_end.wrapping_add(1)] = sentinel; |
195 | 9.28M | } |
196 | 9.28M | } |
197 | 9.28M | k = k.wrapping_sub(1); |
198 | | } |
199 | 417k | if BrotliSetDepth( |
200 | 417k | (2usize).wrapping_mul(n).wrapping_sub(1) as i32, |
201 | 417k | tree, |
202 | 417k | depth, |
203 | 417k | tree_limit, |
204 | 417k | ) { |
205 | 396k | break 'break1; |
206 | 20.7k | } |
207 | 20.7k | } |
208 | 20.7k | count_limit = count_limit.wrapping_mul(2); |
209 | | } |
210 | 397k | } |
211 | 172k | pub fn BrotliOptimizeHuffmanCountsForRle( |
212 | 172k | mut length: usize, |
213 | 172k | counts: &mut [u32], |
214 | 172k | good_for_rle: &mut [u8], |
215 | 172k | ) { |
216 | 172k | let mut nonzero_count: usize = 0usize; |
217 | 172k | let mut stride: usize; |
218 | 172k | let mut limit: usize; |
219 | 172k | let mut sum: usize; |
220 | 172k | let streak_limit: usize = 1240usize; |
221 | 49.8M | for i in 0usize..length { |
222 | 49.8M | if counts[i] != 0 { |
223 | 4.39M | nonzero_count = nonzero_count.wrapping_add(1); |
224 | 45.4M | } |
225 | | } |
226 | 172k | if nonzero_count < 16usize { |
227 | 121k | return; |
228 | 50.4k | } |
229 | 2.86M | while length != 0usize && (counts[length.wrapping_sub(1)] == 0u32) { |
230 | 2.81M | length = length.wrapping_sub(1); |
231 | 2.81M | } |
232 | 50.4k | if length == 0usize { |
233 | 0 | return; |
234 | 50.4k | } |
235 | 50.4k | { |
236 | 50.4k | let mut nonzeros: usize = 0usize; |
237 | 50.4k | let mut smallest_nonzero: u32 = (1i32 << 30) as u32; |
238 | 12.4M | for i in 0usize..length { |
239 | 12.4M | if counts[i] != 0u32 { |
240 | 3.80M | nonzeros = nonzeros.wrapping_add(1); |
241 | 3.80M | if smallest_nonzero > counts[i] { |
242 | 137k | smallest_nonzero = counts[i]; |
243 | 3.66M | } |
244 | 8.67M | } |
245 | | } |
246 | 50.4k | if nonzeros < 5usize { |
247 | 0 | return; |
248 | 50.4k | } |
249 | 50.4k | if smallest_nonzero < 4u32 { |
250 | 47.4k | let zeros: usize = length.wrapping_sub(nonzeros); |
251 | 47.4k | if zeros < 6 { |
252 | 368k | for i in 1..length.wrapping_sub(1) { |
253 | 368k | if counts[i - 1] != 0 && counts[i] == 0 && counts[i + 1] != 0 { |
254 | 3.21k | counts[i] = 1; |
255 | 365k | } |
256 | | } |
257 | 44.9k | } |
258 | 3.01k | } |
259 | 50.4k | if nonzeros < 28usize { |
260 | 15.3k | return; |
261 | 35.1k | } |
262 | | } |
263 | 24.7M | for rle_item in good_for_rle.iter_mut() { |
264 | 24.7M | *rle_item = 0; |
265 | 24.7M | } |
266 | | { |
267 | 35.1k | let mut symbol: u32 = counts[0]; |
268 | 35.1k | let mut step: usize = 0usize; |
269 | 9.19M | for i in 0..=length { |
270 | 9.19M | if i == length || counts[i] != symbol { |
271 | 4.18M | if symbol == 0u32 && (step >= 5usize) || symbol != 0u32 && (step >= 7usize) { |
272 | 4.21M | for k in 0usize..step { |
273 | 4.21M | good_for_rle[i.wrapping_sub(k).wrapping_sub(1)] = 1u8; |
274 | 4.21M | } |
275 | 3.90M | } |
276 | 4.18M | step = 1; |
277 | 4.18M | if i != length { |
278 | 4.15M | symbol = counts[i]; |
279 | 4.15M | } |
280 | 5.00M | } else { |
281 | 5.00M | step = step.wrapping_add(1); |
282 | 5.00M | } |
283 | | } |
284 | | } |
285 | 35.1k | stride = 0usize; |
286 | 35.1k | limit = (256u32) |
287 | 35.1k | .wrapping_mul((counts[0]).wrapping_add(counts[1]).wrapping_add(counts[2])) |
288 | 35.1k | .wrapping_div(3) |
289 | 35.1k | .wrapping_add(420) as usize; |
290 | 35.1k | sum = 0usize; |
291 | 9.19M | for i in 0..=length { |
292 | 9.19M | if i == length |
293 | 9.16M | || good_for_rle[i] != 0 |
294 | 4.94M | || i != 0usize && (good_for_rle[i.wrapping_sub(1)] != 0) |
295 | 4.66M | || ((256u32).wrapping_mul(counts[i]) as usize) |
296 | 4.66M | .wrapping_sub(limit) |
297 | 4.66M | .wrapping_add(streak_limit) |
298 | 4.66M | >= (2usize).wrapping_mul(streak_limit) |
299 | | { |
300 | 5.43M | if stride >= 4usize || stride >= 3usize && (sum == 0usize) { |
301 | 306k | let mut count: usize = sum |
302 | 306k | .wrapping_add(stride.wrapping_div(2)) |
303 | 306k | .wrapping_div(stride); |
304 | 306k | if count == 0usize { |
305 | 32.5k | count = 1; |
306 | 273k | } |
307 | 306k | if sum == 0usize { |
308 | 10.7k | count = 0usize; |
309 | 295k | } |
310 | 3.64M | for k in 0usize..stride { |
311 | 3.64M | counts[i.wrapping_sub(k).wrapping_sub(1)] = count as u32; |
312 | 3.64M | } |
313 | 5.12M | } |
314 | 5.43M | stride = 0usize; |
315 | 5.43M | sum = 0usize; |
316 | 5.43M | if i < length.wrapping_sub(2) { |
317 | 5.36M | limit = (256u32) |
318 | 5.36M | .wrapping_mul( |
319 | 5.36M | (counts[i]) |
320 | 5.36M | .wrapping_add(counts[i.wrapping_add(1)]) |
321 | 5.36M | .wrapping_add(counts[i.wrapping_add(2)]), |
322 | 5.36M | ) |
323 | 5.36M | .wrapping_div(3) |
324 | 5.36M | .wrapping_add(420) as usize; |
325 | 5.36M | } else if i < length { |
326 | 36.5k | limit = (256u32).wrapping_mul(counts[i]) as usize; |
327 | 36.5k | } else { |
328 | 35.1k | limit = 0usize; |
329 | 35.1k | } |
330 | 3.76M | } |
331 | 9.19M | stride = stride.wrapping_add(1); |
332 | 9.19M | if i != length { |
333 | 9.16M | sum = sum.wrapping_add(counts[i] as usize); |
334 | 9.16M | if stride >= 4usize { |
335 | 2.72M | limit = (256usize) |
336 | 2.72M | .wrapping_mul(sum) |
337 | 2.72M | .wrapping_add(stride.wrapping_div(2)) |
338 | 2.72M | .wrapping_div(stride); |
339 | 6.43M | } |
340 | 9.16M | if stride == 4usize { |
341 | 298k | limit = limit.wrapping_add(120); |
342 | 8.86M | } |
343 | 35.1k | } |
344 | | } |
345 | 172k | } |
346 | | |
347 | | |
348 | 156k | pub(crate) fn decide_over_rle_use(depth: &[u8], length: usize) -> (bool, bool) { |
349 | 156k | let mut total_reps_zero: usize = 0usize; |
350 | 156k | let mut total_reps_non_zero: usize = 0usize; |
351 | 156k | let mut count_reps_zero: usize = 1; |
352 | 156k | let mut count_reps_non_zero: usize = 1; |
353 | 156k | let mut i: usize; |
354 | 156k | i = 0usize; |
355 | 4.79M | while i < length { |
356 | 4.63M | let value: u8 = depth[i]; |
357 | 4.63M | let mut reps: usize = 1; |
358 | 4.63M | let mut k: usize; |
359 | 4.63M | k = i.wrapping_add(1); |
360 | 37.9M | while k < length && (depth[k] as i32 == value as i32) { |
361 | 33.3M | { |
362 | 33.3M | reps = reps.wrapping_add(1); |
363 | 33.3M | } |
364 | 33.3M | k = k.wrapping_add(1); |
365 | 33.3M | } |
366 | 4.63M | if reps >= 3usize && (value as i32 == 0i32) { |
367 | 1.43M | total_reps_zero = total_reps_zero.wrapping_add(reps); |
368 | 1.43M | count_reps_zero = count_reps_zero.wrapping_add(1); |
369 | 3.19M | } |
370 | 4.63M | if reps >= 4usize && (value as i32 != 0i32) { |
371 | 447k | total_reps_non_zero = total_reps_non_zero.wrapping_add(reps); |
372 | 447k | count_reps_non_zero = count_reps_non_zero.wrapping_add(1); |
373 | 4.18M | } |
374 | 4.63M | i = i.wrapping_add(reps); |
375 | | } |
376 | 156k | let use_rle_for_non_zero = total_reps_non_zero > count_reps_non_zero.wrapping_mul(2); |
377 | 156k | let use_rle_for_zero = total_reps_zero > count_reps_zero.wrapping_mul(2); |
378 | 156k | |
379 | 156k | (use_rle_for_non_zero, use_rle_for_zero) |
380 | 156k | } |
381 | | |
382 | 3.77M | fn Reverse(v: &mut [u8], mut start: usize, mut end: usize) { |
383 | 3.77M | end = end.wrapping_sub(1); |
384 | 5.25M | while start < end { |
385 | 1.48M | v.swap(start, end); |
386 | 1.48M | start = start.wrapping_add(1); |
387 | 1.48M | end = end.wrapping_sub(1); |
388 | 1.48M | } |
389 | 3.77M | } |
390 | | |
391 | 3.12M | fn BrotliWriteHuffmanTreeRepetitions( |
392 | 3.12M | previous_value: u8, |
393 | 3.12M | value: u8, |
394 | 3.12M | mut repetitions: usize, |
395 | 3.12M | tree_size: &mut usize, |
396 | 3.12M | tree: &mut [u8], |
397 | 3.12M | extra_bits_data: &mut [u8], |
398 | 3.12M | ) { |
399 | 3.12M | if previous_value as i32 != value as i32 { |
400 | 1.96M | tree[*tree_size] = value; |
401 | 1.96M | extra_bits_data[*tree_size] = 0u8; |
402 | 1.96M | *tree_size = tree_size.wrapping_add(1); |
403 | 1.96M | repetitions = repetitions.wrapping_sub(1); |
404 | 1.96M | } |
405 | 3.12M | if repetitions == 7usize { |
406 | 25.2k | tree[*tree_size] = value; |
407 | 25.2k | extra_bits_data[*tree_size] = 0u8; |
408 | 25.2k | *tree_size = tree_size.wrapping_add(1); |
409 | 25.2k | repetitions = repetitions.wrapping_sub(1); |
410 | 3.10M | } |
411 | 3.12M | if repetitions < 3usize { |
412 | 2.67M | for _i in 0usize..repetitions { |
413 | 1.31M | tree[*tree_size] = value; |
414 | 1.31M | extra_bits_data[*tree_size] = 0u8; |
415 | 1.31M | *tree_size = tree_size.wrapping_add(1); |
416 | 1.31M | } |
417 | | } else { |
418 | 449k | let start: usize = *tree_size; |
419 | 449k | repetitions = repetitions.wrapping_sub(3); |
420 | | loop { |
421 | 709k | tree[*tree_size] = 16u8; |
422 | 709k | extra_bits_data[*tree_size] = (repetitions & 0x03) as u8; |
423 | 709k | *tree_size = tree_size.wrapping_add(1); |
424 | 709k | repetitions >>= 2i32; |
425 | 709k | if repetitions == 0usize { |
426 | 449k | break; |
427 | 260k | } |
428 | 260k | repetitions = repetitions.wrapping_sub(1); |
429 | | } |
430 | 449k | Reverse(tree, start, *tree_size); |
431 | 449k | Reverse(extra_bits_data, start, *tree_size); |
432 | | } |
433 | 3.12M | } |
434 | | |
435 | 1.71M | fn BrotliWriteHuffmanTreeRepetitionsZeros( |
436 | 1.71M | mut repetitions: usize, |
437 | 1.71M | tree_size: &mut usize, |
438 | 1.71M | tree: &mut [u8], |
439 | 1.71M | extra_bits_data: &mut [u8], |
440 | 1.71M | ) { |
441 | 1.71M | if repetitions == 11 { |
442 | 21.7k | tree[*tree_size] = 0u8; |
443 | 21.7k | extra_bits_data[*tree_size] = 0u8; |
444 | 21.7k | *tree_size = tree_size.wrapping_add(1); |
445 | 21.7k | repetitions = repetitions.wrapping_sub(1); |
446 | 1.69M | } |
447 | 1.71M | if repetitions < 3usize { |
448 | 334k | for _i in 0usize..repetitions { |
449 | 334k | tree[*tree_size] = 0u8; |
450 | 334k | extra_bits_data[*tree_size] = 0u8; |
451 | 334k | *tree_size = tree_size.wrapping_add(1); |
452 | 334k | } |
453 | | } else { |
454 | 1.43M | let start: usize = *tree_size; |
455 | 1.43M | repetitions = repetitions.wrapping_sub(3); |
456 | | loop { |
457 | 2.01M | tree[*tree_size] = 17u8; |
458 | 2.01M | extra_bits_data[*tree_size] = (repetitions & 0x7usize) as u8; |
459 | 2.01M | *tree_size = tree_size.wrapping_add(1); |
460 | 2.01M | repetitions >>= 3i32; |
461 | 2.01M | if repetitions == 0usize { |
462 | 1.43M | break; |
463 | 581k | } |
464 | 581k | repetitions = repetitions.wrapping_sub(1); |
465 | | } |
466 | 1.43M | Reverse(tree, start, *tree_size); |
467 | 1.43M | Reverse(extra_bits_data, start, *tree_size); |
468 | | } |
469 | 1.71M | } |
470 | | |
471 | 163k | pub fn BrotliWriteHuffmanTree( |
472 | 163k | depth: &[u8], |
473 | 163k | length: usize, |
474 | 163k | tree_size: &mut usize, |
475 | 163k | tree: &mut [u8], |
476 | 163k | extra_bits_data: &mut [u8], |
477 | 163k | ) { |
478 | 163k | let mut previous_value: u8 = 8u8; |
479 | 163k | let mut i: usize; |
480 | 163k | let mut use_rle_for_non_zero = false; |
481 | 163k | let mut use_rle_for_zero = false; |
482 | 163k | let mut new_length: usize = length; |
483 | 163k | i = 0usize; |
484 | 13.5M | 'break27: while i < length { |
485 | | { |
486 | 13.5M | if depth[length.wrapping_sub(i).wrapping_sub(1)] as i32 == 0i32 { |
487 | 13.4M | new_length = new_length.wrapping_sub(1); |
488 | 13.4M | } else { |
489 | 163k | break 'break27; |
490 | | } |
491 | | } |
492 | 13.4M | i = i.wrapping_add(1); |
493 | | } |
494 | 163k | if length > 50 { |
495 | 156k | (use_rle_for_non_zero, use_rle_for_zero) = decide_over_rle_use(depth, new_length); |
496 | 156k | } |
497 | 163k | i = 0usize; |
498 | 5.00M | while i < new_length { |
499 | 4.84M | let value: u8 = depth[i]; |
500 | 4.84M | let mut reps: usize = 1; |
501 | 4.84M | if value != 0 && use_rle_for_non_zero || value == 0 && use_rle_for_zero { |
502 | | let mut k: usize; |
503 | 3.76M | k = i.wrapping_add(1); |
504 | 37.0M | while k < new_length && (depth[k] as i32 == value as i32) { |
505 | 33.2M | { |
506 | 33.2M | reps = reps.wrapping_add(1); |
507 | 33.2M | } |
508 | 33.2M | k = k.wrapping_add(1); |
509 | 33.2M | } |
510 | 1.07M | } |
511 | 4.84M | if value as i32 == 0i32 { |
512 | 1.71M | BrotliWriteHuffmanTreeRepetitionsZeros(reps, tree_size, tree, extra_bits_data); |
513 | 3.12M | } else { |
514 | 3.12M | BrotliWriteHuffmanTreeRepetitions( |
515 | 3.12M | previous_value, |
516 | 3.12M | value, |
517 | 3.12M | reps, |
518 | 3.12M | tree_size, |
519 | 3.12M | tree, |
520 | 3.12M | extra_bits_data, |
521 | 3.12M | ); |
522 | 3.12M | previous_value = value; |
523 | 3.12M | } |
524 | 4.84M | i = i.wrapping_add(reps); |
525 | | } |
526 | 163k | } |
527 | | |
528 | 12.5M | fn BrotliReverseBits(num_bits: usize, mut bits: u16) -> u16 { |
529 | | static kLut: [usize; 16] = [ |
530 | | 0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe, 0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf, |
531 | | ]; |
532 | 12.5M | let mut retval: usize = kLut[(bits as i32 & 0xfi32) as usize]; |
533 | 12.5M | let mut i: usize; |
534 | 12.5M | i = 4usize; |
535 | 25.5M | while i < num_bits { |
536 | 12.9M | { |
537 | 12.9M | retval <<= 4i32; |
538 | 12.9M | bits = (bits as i32 >> 4) as u16; |
539 | 12.9M | retval |= kLut[(bits as i32 & 0xfi32) as usize]; |
540 | 12.9M | } |
541 | 12.9M | i = i.wrapping_add(4); |
542 | 12.9M | } |
543 | 12.5M | retval >>= (0usize.wrapping_sub(num_bits) & 0x3usize); |
544 | 12.5M | retval as u16 |
545 | 12.5M | } |
546 | | const MAX_HUFFMAN_BITS: usize = 16; |
547 | 428k | pub fn BrotliConvertBitDepthsToSymbols(depth: &[u8], len: usize, bits: &mut [u16]) { |
548 | 428k | /* In Brotli, all bit depths are [1..15] |
549 | 428k | 0 bit depth means that the symbol does not exist. */ |
550 | 428k | |
551 | 428k | let mut bl_count: [u16; MAX_HUFFMAN_BITS] = [0; MAX_HUFFMAN_BITS]; |
552 | 428k | let mut next_code: [u16; MAX_HUFFMAN_BITS] = [0; MAX_HUFFMAN_BITS]; |
553 | 428k | let mut code: i32 = 0i32; |
554 | 59.9M | for i in 0usize..len { |
555 | 59.9M | let _rhs = 1; |
556 | 59.9M | let _lhs = &mut bl_count[depth[i] as usize]; |
557 | 59.9M | *_lhs = (*_lhs as i32 + _rhs) as u16; |
558 | 59.9M | } |
559 | 428k | bl_count[0] = 0u16; |
560 | 428k | next_code[0] = 0u16; |
561 | 6.85M | for i in 1..MAX_HUFFMAN_BITS { |
562 | 6.42M | code = (code + bl_count[i - 1] as i32) << 1; |
563 | 6.42M | next_code[i] = code as u16; |
564 | 6.42M | } |
565 | 59.9M | for i in 0usize..len { |
566 | 59.9M | if depth[i] != 0 { |
567 | 12.5M | bits[i] = BrotliReverseBits(depth[i] as usize, { |
568 | 12.5M | let _rhs = 1; |
569 | 12.5M | let _lhs = &mut next_code[depth[i] as usize]; |
570 | 12.5M | let _old = *_lhs; |
571 | 12.5M | *_lhs = (*_lhs as i32 + _rhs) as u16; |
572 | 12.5M | _old |
573 | 12.5M | }); |
574 | 47.4M | } |
575 | | } |
576 | 428k | } |