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
347#[deprecated(note = "Use decide_over_rle_use instead")]
348pub fn DecideOverRleUse(
349    depth: &[u8],
350    length: usize,
351    use_rle_for_non_zero: &mut i32,
352    use_rle_for_zero: &mut i32,
353) {
354    let (non_zero, zero) = decide_over_rle_use(depth, length);
355    *use_rle_for_non_zero = non_zero.into();
356    *use_rle_for_zero = zero.into();
357}
358
359pub(crate) fn decide_over_rle_use(depth: &[u8], length: usize) -> (bool, bool) {
360    let mut total_reps_zero: usize = 0usize;
361    let mut total_reps_non_zero: usize = 0usize;
362    let mut count_reps_zero: usize = 1;
363    let mut count_reps_non_zero: usize = 1;
364    let mut i: usize;
365    i = 0usize;
366    while i < length {
367        let value: u8 = depth[i];
368        let mut reps: usize = 1;
369        let mut k: usize;
370        k = i.wrapping_add(1);
371        while k < length && (depth[k] as i32 == value as i32) {
372            {
373                reps = reps.wrapping_add(1);
374            }
375            k = k.wrapping_add(1);
376        }
377        if reps >= 3usize && (value as i32 == 0i32) {
378            total_reps_zero = total_reps_zero.wrapping_add(reps);
379            count_reps_zero = count_reps_zero.wrapping_add(1);
380        }
381        if reps >= 4usize && (value as i32 != 0i32) {
382            total_reps_non_zero = total_reps_non_zero.wrapping_add(reps);
383            count_reps_non_zero = count_reps_non_zero.wrapping_add(1);
384        }
385        i = i.wrapping_add(reps);
386    }
387    let use_rle_for_non_zero = total_reps_non_zero > count_reps_non_zero.wrapping_mul(2);
388    let use_rle_for_zero = total_reps_zero > count_reps_zero.wrapping_mul(2);
389
390    (use_rle_for_non_zero, use_rle_for_zero)
391}
392
393fn Reverse(v: &mut [u8], mut start: usize, mut end: usize) {
394    end = end.wrapping_sub(1);
395    while start < end {
396        v.swap(start, end);
397        start = start.wrapping_add(1);
398        end = end.wrapping_sub(1);
399    }
400}
401
402fn BrotliWriteHuffmanTreeRepetitions(
403    previous_value: u8,
404    value: u8,
405    mut repetitions: usize,
406    tree_size: &mut usize,
407    tree: &mut [u8],
408    extra_bits_data: &mut [u8],
409) {
410    if previous_value as i32 != value as i32 {
411        tree[*tree_size] = value;
412        extra_bits_data[*tree_size] = 0u8;
413        *tree_size = tree_size.wrapping_add(1);
414        repetitions = repetitions.wrapping_sub(1);
415    }
416    if repetitions == 7usize {
417        tree[*tree_size] = value;
418        extra_bits_data[*tree_size] = 0u8;
419        *tree_size = tree_size.wrapping_add(1);
420        repetitions = repetitions.wrapping_sub(1);
421    }
422    if repetitions < 3usize {
423        for _i in 0usize..repetitions {
424            tree[*tree_size] = value;
425            extra_bits_data[*tree_size] = 0u8;
426            *tree_size = tree_size.wrapping_add(1);
427        }
428    } else {
429        let start: usize = *tree_size;
430        repetitions = repetitions.wrapping_sub(3);
431        loop {
432            tree[*tree_size] = 16u8;
433            extra_bits_data[*tree_size] = (repetitions & 0x03) as u8;
434            *tree_size = tree_size.wrapping_add(1);
435            repetitions >>= 2i32;
436            if repetitions == 0usize {
437                break;
438            }
439            repetitions = repetitions.wrapping_sub(1);
440        }
441        Reverse(tree, start, *tree_size);
442        Reverse(extra_bits_data, start, *tree_size);
443    }
444}
445
446fn BrotliWriteHuffmanTreeRepetitionsZeros(
447    mut repetitions: usize,
448    tree_size: &mut usize,
449    tree: &mut [u8],
450    extra_bits_data: &mut [u8],
451) {
452    if repetitions == 11 {
453        tree[*tree_size] = 0u8;
454        extra_bits_data[*tree_size] = 0u8;
455        *tree_size = tree_size.wrapping_add(1);
456        repetitions = repetitions.wrapping_sub(1);
457    }
458    if repetitions < 3usize {
459        for _i in 0usize..repetitions {
460            tree[*tree_size] = 0u8;
461            extra_bits_data[*tree_size] = 0u8;
462            *tree_size = tree_size.wrapping_add(1);
463        }
464    } else {
465        let start: usize = *tree_size;
466        repetitions = repetitions.wrapping_sub(3);
467        loop {
468            tree[*tree_size] = 17u8;
469            extra_bits_data[*tree_size] = (repetitions & 0x7usize) as u8;
470            *tree_size = tree_size.wrapping_add(1);
471            repetitions >>= 3i32;
472            if repetitions == 0usize {
473                break;
474            }
475            repetitions = repetitions.wrapping_sub(1);
476        }
477        Reverse(tree, start, *tree_size);
478        Reverse(extra_bits_data, start, *tree_size);
479    }
480}
481
482pub fn BrotliWriteHuffmanTree(
483    depth: &[u8],
484    length: usize,
485    tree_size: &mut usize,
486    tree: &mut [u8],
487    extra_bits_data: &mut [u8],
488) {
489    let mut previous_value: u8 = 8u8;
490    let mut i: usize;
491    let mut use_rle_for_non_zero = false;
492    let mut use_rle_for_zero = false;
493    let mut new_length: usize = length;
494    i = 0usize;
495    'break27: while i < length {
496        {
497            if depth[length.wrapping_sub(i).wrapping_sub(1)] as i32 == 0i32 {
498                new_length = new_length.wrapping_sub(1);
499            } else {
500                break 'break27;
501            }
502        }
503        i = i.wrapping_add(1);
504    }
505    if length > 50 {
506        (use_rle_for_non_zero, use_rle_for_zero) = decide_over_rle_use(depth, new_length);
507    }
508    i = 0usize;
509    while i < new_length {
510        let value: u8 = depth[i];
511        let mut reps: usize = 1;
512        if value != 0 && use_rle_for_non_zero || value == 0 && use_rle_for_zero {
513            let mut k: usize;
514            k = i.wrapping_add(1);
515            while k < new_length && (depth[k] as i32 == value as i32) {
516                {
517                    reps = reps.wrapping_add(1);
518                }
519                k = k.wrapping_add(1);
520            }
521        }
522        if value as i32 == 0i32 {
523            BrotliWriteHuffmanTreeRepetitionsZeros(reps, tree_size, tree, extra_bits_data);
524        } else {
525            BrotliWriteHuffmanTreeRepetitions(
526                previous_value,
527                value,
528                reps,
529                tree_size,
530                tree,
531                extra_bits_data,
532            );
533            previous_value = value;
534        }
535        i = i.wrapping_add(reps);
536    }
537}
538
539fn BrotliReverseBits(num_bits: usize, mut bits: u16) -> u16 {
540    static kLut: [usize; 16] = [
541        0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe, 0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf,
542    ];
543    let mut retval: usize = kLut[(bits as i32 & 0xfi32) as usize];
544    let mut i: usize;
545    i = 4usize;
546    while i < num_bits {
547        {
548            retval <<= 4i32;
549            bits = (bits as i32 >> 4) as u16;
550            retval |= kLut[(bits as i32 & 0xfi32) as usize];
551        }
552        i = i.wrapping_add(4);
553    }
554    retval >>= (0usize.wrapping_sub(num_bits) & 0x3usize);
555    retval as u16
556}
557const MAX_HUFFMAN_BITS: usize = 16;
558pub fn BrotliConvertBitDepthsToSymbols(depth: &[u8], len: usize, bits: &mut [u16]) {
559    /* In Brotli, all bit depths are [1..15]
560    0 bit depth means that the symbol does not exist. */
561
562    let mut bl_count: [u16; MAX_HUFFMAN_BITS] = [0; MAX_HUFFMAN_BITS];
563    let mut next_code: [u16; MAX_HUFFMAN_BITS] = [0; MAX_HUFFMAN_BITS];
564    let mut code: i32 = 0i32;
565    for i in 0usize..len {
566        let _rhs = 1;
567        let _lhs = &mut bl_count[depth[i] as usize];
568        *_lhs = (*_lhs as i32 + _rhs) as u16;
569    }
570    bl_count[0] = 0u16;
571    next_code[0] = 0u16;
572    for i in 1..MAX_HUFFMAN_BITS {
573        code = (code + bl_count[i - 1] as i32) << 1;
574        next_code[i] = code as u16;
575    }
576    for i in 0usize..len {
577        if depth[i] != 0 {
578            bits[i] = BrotliReverseBits(depth[i] as usize, {
579                let _rhs = 1;
580                let _lhs = &mut next_code[depth[i] as usize];
581                let _old = *_lhs;
582                *_lhs = (*_lhs as i32 + _rhs) as u16;
583                _old
584            });
585        }
586    }
587}