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