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