Skip to main content

brotli/enc/
entropy_encode.rs

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