123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592 |
- package brotli
- import "math"
- /* Copyright 2010 Google Inc. All Rights Reserved.
- Distributed under MIT license.
- See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
- */
- /* Entropy encoding (Huffman) utilities. */
- /* A node of a Huffman tree. */
- type huffmanTree struct {
- total_count_ uint32
- index_left_ int16
- index_right_or_value_ int16
- }
- func initHuffmanTree(self *huffmanTree, count uint32, left int16, right int16) {
- self.total_count_ = count
- self.index_left_ = left
- self.index_right_or_value_ = right
- }
- /* Input size optimized Shell sort. */
- type huffmanTreeComparator func(huffmanTree, huffmanTree) bool
- var sortHuffmanTreeItems_gaps = []uint{132, 57, 23, 10, 4, 1}
- func sortHuffmanTreeItems(items []huffmanTree, n uint, comparator huffmanTreeComparator) {
- if n < 13 {
- /* Insertion sort. */
- var i uint
- for i = 1; i < n; i++ {
- var tmp huffmanTree = items[i]
- var k uint = i
- var j uint = i - 1
- for comparator(tmp, items[j]) {
- items[k] = items[j]
- k = j
- if j == 0 {
- break
- }
- j--
- }
- items[k] = tmp
- }
- return
- } else {
- var g int
- if n < 57 {
- g = 2
- } else {
- g = 0
- }
- for ; g < 6; g++ {
- var gap uint = sortHuffmanTreeItems_gaps[g]
- var i uint
- for i = gap; i < n; i++ {
- var j uint = i
- var tmp huffmanTree = items[i]
- for ; j >= gap && comparator(tmp, items[j-gap]); j -= gap {
- items[j] = items[j-gap]
- }
- items[j] = tmp
- }
- }
- }
- }
- /* Returns 1 if assignment of depths succeeded, otherwise 0. */
- func setDepth(p0 int, pool []huffmanTree, depth []byte, max_depth int) bool {
- var stack [16]int
- var level int = 0
- var p int = p0
- assert(max_depth <= 15)
- stack[0] = -1
- for {
- if pool[p].index_left_ >= 0 {
- level++
- if level > max_depth {
- return false
- }
- stack[level] = int(pool[p].index_right_or_value_)
- p = int(pool[p].index_left_)
- continue
- } else {
- depth[pool[p].index_right_or_value_] = byte(level)
- }
- for level >= 0 && stack[level] == -1 {
- level--
- }
- if level < 0 {
- return true
- }
- p = stack[level]
- stack[level] = -1
- }
- }
- /* Sort the root nodes, least popular first. */
- func sortHuffmanTree(v0 huffmanTree, v1 huffmanTree) bool {
- if v0.total_count_ != v1.total_count_ {
- return v0.total_count_ < v1.total_count_
- }
- return v0.index_right_or_value_ > v1.index_right_or_value_
- }
- /* This function will create a Huffman tree.
- The catch here is that the tree cannot be arbitrarily deep.
- Brotli specifies a maximum depth of 15 bits for "code trees"
- and 7 bits for "code length code trees."
- count_limit is the value that is to be faked as the minimum value
- and this minimum value is raised until the tree matches the
- maximum length requirement.
- This algorithm is not of excellent performance for very long data blocks,
- especially when population counts are longer than 2**tree_limit, but
- we are not planning to use this with extremely long blocks.
- See http://en.wikipedia.org/wiki/Huffman_coding */
- func createHuffmanTree(data []uint32, length uint, tree_limit int, tree []huffmanTree, depth []byte) {
- var count_limit uint32
- var sentinel huffmanTree
- initHuffmanTree(&sentinel, math.MaxUint32, -1, -1)
- /* For block sizes below 64 kB, we never need to do a second iteration
- of this loop. Probably all of our block sizes will be smaller than
- that, so this loop is mostly of academic interest. If we actually
- would need this, we would be better off with the Katajainen algorithm. */
- for count_limit = 1; ; count_limit *= 2 {
- var n uint = 0
- var i uint
- var j uint
- var k uint
- for i = length; i != 0; {
- i--
- if data[i] != 0 {
- var count uint32 = brotli_max_uint32_t(data[i], count_limit)
- initHuffmanTree(&tree[n], count, -1, int16(i))
- n++
- }
- }
- if n == 1 {
- depth[tree[0].index_right_or_value_] = 1 /* Only one element. */
- break
- }
- sortHuffmanTreeItems(tree, n, huffmanTreeComparator(sortHuffmanTree))
- /* The nodes are:
- [0, n): the sorted leaf nodes that we start with.
- [n]: we add a sentinel here.
- [n + 1, 2n): new parent nodes are added here, starting from
- (n+1). These are naturally in ascending order.
- [2n]: we add a sentinel at the end as well.
- There will be (2n+1) elements at the end. */
- tree[n] = sentinel
- tree[n+1] = sentinel
- i = 0 /* Points to the next leaf node. */
- j = n + 1 /* Points to the next non-leaf node. */
- for k = n - 1; k != 0; k-- {
- var left uint
- var right uint
- if tree[i].total_count_ <= tree[j].total_count_ {
- left = i
- i++
- } else {
- left = j
- j++
- }
- if tree[i].total_count_ <= tree[j].total_count_ {
- right = i
- i++
- } else {
- right = j
- j++
- }
- {
- /* The sentinel node becomes the parent node. */
- var j_end uint = 2*n - k
- tree[j_end].total_count_ = tree[left].total_count_ + tree[right].total_count_
- tree[j_end].index_left_ = int16(left)
- tree[j_end].index_right_or_value_ = int16(right)
- /* Add back the last sentinel node. */
- tree[j_end+1] = sentinel
- }
- }
- if setDepth(int(2*n-1), tree[0:], depth, tree_limit) {
- /* We need to pack the Huffman tree in tree_limit bits. If this was not
- successful, add fake entities to the lowest values and retry. */
- break
- }
- }
- }
- func reverse(v []byte, start uint, end uint) {
- end--
- for start < end {
- var tmp byte = v[start]
- v[start] = v[end]
- v[end] = tmp
- start++
- end--
- }
- }
- func writeHuffmanTreeRepetitions(previous_value byte, value byte, repetitions uint, tree_size *uint, tree []byte, extra_bits_data []byte) {
- assert(repetitions > 0)
- if previous_value != value {
- tree[*tree_size] = value
- extra_bits_data[*tree_size] = 0
- (*tree_size)++
- repetitions--
- }
- if repetitions == 7 {
- tree[*tree_size] = value
- extra_bits_data[*tree_size] = 0
- (*tree_size)++
- repetitions--
- }
- if repetitions < 3 {
- var i uint
- for i = 0; i < repetitions; i++ {
- tree[*tree_size] = value
- extra_bits_data[*tree_size] = 0
- (*tree_size)++
- }
- } else {
- var start uint = *tree_size
- repetitions -= 3
- for {
- tree[*tree_size] = repeatPreviousCodeLength
- extra_bits_data[*tree_size] = byte(repetitions & 0x3)
- (*tree_size)++
- repetitions >>= 2
- if repetitions == 0 {
- break
- }
- repetitions--
- }
- reverse(tree, start, *tree_size)
- reverse(extra_bits_data, start, *tree_size)
- }
- }
- func writeHuffmanTreeRepetitionsZeros(repetitions uint, tree_size *uint, tree []byte, extra_bits_data []byte) {
- if repetitions == 11 {
- tree[*tree_size] = 0
- extra_bits_data[*tree_size] = 0
- (*tree_size)++
- repetitions--
- }
- if repetitions < 3 {
- var i uint
- for i = 0; i < repetitions; i++ {
- tree[*tree_size] = 0
- extra_bits_data[*tree_size] = 0
- (*tree_size)++
- }
- } else {
- var start uint = *tree_size
- repetitions -= 3
- for {
- tree[*tree_size] = repeatZeroCodeLength
- extra_bits_data[*tree_size] = byte(repetitions & 0x7)
- (*tree_size)++
- repetitions >>= 3
- if repetitions == 0 {
- break
- }
- repetitions--
- }
- reverse(tree, start, *tree_size)
- reverse(extra_bits_data, start, *tree_size)
- }
- }
- /* Change the population counts in a way that the consequent
- Huffman tree compression, especially its RLE-part will be more
- likely to compress this data more efficiently.
- length contains the size of the histogram.
- counts contains the population counts.
- good_for_rle is a buffer of at least length size */
- func optimizeHuffmanCountsForRLE(length uint, counts []uint32, good_for_rle []byte) {
- var nonzero_count uint = 0
- var stride uint
- var limit uint
- var sum uint
- var streak_limit uint = 1240
- var i uint
- /* Let's make the Huffman code more compatible with RLE encoding. */
- for i = 0; i < length; i++ {
- if counts[i] != 0 {
- nonzero_count++
- }
- }
- if nonzero_count < 16 {
- return
- }
- for length != 0 && counts[length-1] == 0 {
- length--
- }
- if length == 0 {
- return /* All zeros. */
- }
- /* Now counts[0..length - 1] does not have trailing zeros. */
- {
- var nonzeros uint = 0
- var smallest_nonzero uint32 = 1 << 30
- for i = 0; i < length; i++ {
- if counts[i] != 0 {
- nonzeros++
- if smallest_nonzero > counts[i] {
- smallest_nonzero = counts[i]
- }
- }
- }
- if nonzeros < 5 {
- /* Small histogram will model it well. */
- return
- }
- if smallest_nonzero < 4 {
- var zeros uint = length - nonzeros
- if zeros < 6 {
- for i = 1; i < length-1; i++ {
- if counts[i-1] != 0 && counts[i] == 0 && counts[i+1] != 0 {
- counts[i] = 1
- }
- }
- }
- }
- if nonzeros < 28 {
- return
- }
- }
- /* 2) Let's mark all population counts that already can be encoded
- with an RLE code. */
- for i := 0; i < int(length); i++ {
- good_for_rle[i] = 0
- }
- {
- var symbol uint32 = counts[0]
- /* Let's not spoil any of the existing good RLE codes.
- Mark any seq of 0's that is longer as 5 as a good_for_rle.
- Mark any seq of non-0's that is longer as 7 as a good_for_rle. */
- var step uint = 0
- for i = 0; i <= length; i++ {
- if i == length || counts[i] != symbol {
- if (symbol == 0 && step >= 5) || (symbol != 0 && step >= 7) {
- var k uint
- for k = 0; k < step; k++ {
- good_for_rle[i-k-1] = 1
- }
- }
- step = 1
- if i != length {
- symbol = counts[i]
- }
- } else {
- step++
- }
- }
- }
- /* 3) Let's replace those population counts that lead to more RLE codes.
- Math here is in 24.8 fixed point representation. */
- stride = 0
- limit = uint(256*(counts[0]+counts[1]+counts[2])/3 + 420)
- sum = 0
- for i = 0; i <= length; i++ {
- if i == length || good_for_rle[i] != 0 || (i != 0 && good_for_rle[i-1] != 0) || (256*counts[i]-uint32(limit)+uint32(streak_limit)) >= uint32(2*streak_limit) {
- if stride >= 4 || (stride >= 3 && sum == 0) {
- var k uint
- var count uint = (sum + stride/2) / stride
- /* The stride must end, collapse what we have, if we have enough (4). */
- if count == 0 {
- count = 1
- }
- if sum == 0 {
- /* Don't make an all zeros stride to be upgraded to ones. */
- count = 0
- }
- for k = 0; k < stride; k++ {
- /* We don't want to change value at counts[i],
- that is already belonging to the next stride. Thus - 1. */
- counts[i-k-1] = uint32(count)
- }
- }
- stride = 0
- sum = 0
- if i < length-2 {
- /* All interesting strides have a count of at least 4, */
- /* at least when non-zeros. */
- limit = uint(256*(counts[i]+counts[i+1]+counts[i+2])/3 + 420)
- } else if i < length {
- limit = uint(256 * counts[i])
- } else {
- limit = 0
- }
- }
- stride++
- if i != length {
- sum += uint(counts[i])
- if stride >= 4 {
- limit = (256*sum + stride/2) / stride
- }
- if stride == 4 {
- limit += 120
- }
- }
- }
- }
- func decideOverRLEUse(depth []byte, length uint, use_rle_for_non_zero *bool, use_rle_for_zero *bool) {
- var total_reps_zero uint = 0
- var total_reps_non_zero uint = 0
- var count_reps_zero uint = 1
- var count_reps_non_zero uint = 1
- var i uint
- for i = 0; i < length; {
- var value byte = depth[i]
- var reps uint = 1
- var k uint
- for k = i + 1; k < length && depth[k] == value; k++ {
- reps++
- }
- if reps >= 3 && value == 0 {
- total_reps_zero += reps
- count_reps_zero++
- }
- if reps >= 4 && value != 0 {
- total_reps_non_zero += reps
- count_reps_non_zero++
- }
- i += reps
- }
- *use_rle_for_non_zero = total_reps_non_zero > count_reps_non_zero*2
- *use_rle_for_zero = total_reps_zero > count_reps_zero*2
- }
- /* Write a Huffman tree from bit depths into the bit-stream representation
- of a Huffman tree. The generated Huffman tree is to be compressed once
- more using a Huffman tree */
- func writeHuffmanTree(depth []byte, length uint, tree_size *uint, tree []byte, extra_bits_data []byte) {
- var previous_value byte = initialRepeatedCodeLength
- var i uint
- var use_rle_for_non_zero bool = false
- var use_rle_for_zero bool = false
- var new_length uint = length
- /* Throw away trailing zeros. */
- for i = 0; i < length; i++ {
- if depth[length-i-1] == 0 {
- new_length--
- } else {
- break
- }
- }
- /* First gather statistics on if it is a good idea to do RLE. */
- if length > 50 {
- /* Find RLE coding for longer codes.
- Shorter codes seem not to benefit from RLE. */
- decideOverRLEUse(depth, new_length, &use_rle_for_non_zero, &use_rle_for_zero)
- }
- /* Actual RLE coding. */
- for i = 0; i < new_length; {
- var value byte = depth[i]
- var reps uint = 1
- if (value != 0 && use_rle_for_non_zero) || (value == 0 && use_rle_for_zero) {
- var k uint
- for k = i + 1; k < new_length && depth[k] == value; k++ {
- reps++
- }
- }
- if value == 0 {
- writeHuffmanTreeRepetitionsZeros(reps, tree_size, tree, extra_bits_data)
- } else {
- writeHuffmanTreeRepetitions(previous_value, value, reps, tree_size, tree, extra_bits_data)
- previous_value = value
- }
- i += reps
- }
- }
- var reverseBits_kLut = [16]uint{
- 0x00,
- 0x08,
- 0x04,
- 0x0C,
- 0x02,
- 0x0A,
- 0x06,
- 0x0E,
- 0x01,
- 0x09,
- 0x05,
- 0x0D,
- 0x03,
- 0x0B,
- 0x07,
- 0x0F,
- }
- func reverseBits(num_bits uint, bits uint16) uint16 {
- var retval uint = reverseBits_kLut[bits&0x0F]
- var i uint
- for i = 4; i < num_bits; i += 4 {
- retval <<= 4
- bits = uint16(bits >> 4)
- retval |= reverseBits_kLut[bits&0x0F]
- }
- retval >>= ((0 - num_bits) & 0x03)
- return uint16(retval)
- }
- /* 0..15 are values for bits */
- const maxHuffmanBits = 16
- /* Get the actual bit values for a tree of bit depths. */
- func convertBitDepthsToSymbols(depth []byte, len uint, bits []uint16) {
- var bl_count = [maxHuffmanBits]uint16{0}
- var next_code [maxHuffmanBits]uint16
- var i uint
- /* In Brotli, all bit depths are [1..15]
- 0 bit depth means that the symbol does not exist. */
- var code int = 0
- for i = 0; i < len; i++ {
- bl_count[depth[i]]++
- }
- bl_count[0] = 0
- next_code[0] = 0
- for i = 1; i < maxHuffmanBits; i++ {
- code = (code + int(bl_count[i-1])) << 1
- next_code[i] = uint16(code)
- }
- for i = 0; i < len; i++ {
- if depth[i] != 0 {
- bits[i] = reverseBits(uint(depth[i]), next_code[depth[i]])
- next_code[depth[i]]++
- }
- }
- }
|