github.com/andybalholm/brotli@v1.0.6/histogram.go (about) 1 package brotli 2 3 import "math" 4 5 /* The distance symbols effectively used by "Large Window Brotli" (32-bit). */ 6 const numHistogramDistanceSymbols = 544 7 8 type histogramLiteral struct { 9 data_ [numLiteralSymbols]uint32 10 total_count_ uint 11 bit_cost_ float64 12 } 13 14 func histogramClearLiteral(self *histogramLiteral) { 15 self.data_ = [numLiteralSymbols]uint32{} 16 self.total_count_ = 0 17 self.bit_cost_ = math.MaxFloat64 18 } 19 20 func clearHistogramsLiteral(array []histogramLiteral, length uint) { 21 var i uint 22 for i = 0; i < length; i++ { 23 histogramClearLiteral(&array[i:][0]) 24 } 25 } 26 27 func histogramAddLiteral(self *histogramLiteral, val uint) { 28 self.data_[val]++ 29 self.total_count_++ 30 } 31 32 func histogramAddVectorLiteral(self *histogramLiteral, p []byte, n uint) { 33 self.total_count_ += n 34 n += 1 35 for { 36 n-- 37 if n == 0 { 38 break 39 } 40 self.data_[p[0]]++ 41 p = p[1:] 42 } 43 } 44 45 func histogramAddHistogramLiteral(self *histogramLiteral, v *histogramLiteral) { 46 var i uint 47 self.total_count_ += v.total_count_ 48 for i = 0; i < numLiteralSymbols; i++ { 49 self.data_[i] += v.data_[i] 50 } 51 } 52 53 func histogramDataSizeLiteral() uint { 54 return numLiteralSymbols 55 } 56 57 type histogramCommand struct { 58 data_ [numCommandSymbols]uint32 59 total_count_ uint 60 bit_cost_ float64 61 } 62 63 func histogramClearCommand(self *histogramCommand) { 64 self.data_ = [numCommandSymbols]uint32{} 65 self.total_count_ = 0 66 self.bit_cost_ = math.MaxFloat64 67 } 68 69 func clearHistogramsCommand(array []histogramCommand, length uint) { 70 var i uint 71 for i = 0; i < length; i++ { 72 histogramClearCommand(&array[i:][0]) 73 } 74 } 75 76 func histogramAddCommand(self *histogramCommand, val uint) { 77 self.data_[val]++ 78 self.total_count_++ 79 } 80 81 func histogramAddVectorCommand(self *histogramCommand, p []uint16, n uint) { 82 self.total_count_ += n 83 n += 1 84 for { 85 n-- 86 if n == 0 { 87 break 88 } 89 self.data_[p[0]]++ 90 p = p[1:] 91 } 92 } 93 94 func histogramAddHistogramCommand(self *histogramCommand, v *histogramCommand) { 95 var i uint 96 self.total_count_ += v.total_count_ 97 for i = 0; i < numCommandSymbols; i++ { 98 self.data_[i] += v.data_[i] 99 } 100 } 101 102 func histogramDataSizeCommand() uint { 103 return numCommandSymbols 104 } 105 106 type histogramDistance struct { 107 data_ [numDistanceSymbols]uint32 108 total_count_ uint 109 bit_cost_ float64 110 } 111 112 func histogramClearDistance(self *histogramDistance) { 113 self.data_ = [numDistanceSymbols]uint32{} 114 self.total_count_ = 0 115 self.bit_cost_ = math.MaxFloat64 116 } 117 118 func clearHistogramsDistance(array []histogramDistance, length uint) { 119 var i uint 120 for i = 0; i < length; i++ { 121 histogramClearDistance(&array[i:][0]) 122 } 123 } 124 125 func histogramAddDistance(self *histogramDistance, val uint) { 126 self.data_[val]++ 127 self.total_count_++ 128 } 129 130 func histogramAddVectorDistance(self *histogramDistance, p []uint16, n uint) { 131 self.total_count_ += n 132 n += 1 133 for { 134 n-- 135 if n == 0 { 136 break 137 } 138 self.data_[p[0]]++ 139 p = p[1:] 140 } 141 } 142 143 func histogramAddHistogramDistance(self *histogramDistance, v *histogramDistance) { 144 var i uint 145 self.total_count_ += v.total_count_ 146 for i = 0; i < numDistanceSymbols; i++ { 147 self.data_[i] += v.data_[i] 148 } 149 } 150 151 func histogramDataSizeDistance() uint { 152 return numDistanceSymbols 153 } 154 155 type blockSplitIterator struct { 156 split_ *blockSplit 157 idx_ uint 158 type_ uint 159 length_ uint 160 } 161 162 func initBlockSplitIterator(self *blockSplitIterator, split *blockSplit) { 163 self.split_ = split 164 self.idx_ = 0 165 self.type_ = 0 166 if len(split.lengths) > 0 { 167 self.length_ = uint(split.lengths[0]) 168 } else { 169 self.length_ = 0 170 } 171 } 172 173 func blockSplitIteratorNext(self *blockSplitIterator) { 174 if self.length_ == 0 { 175 self.idx_++ 176 self.type_ = uint(self.split_.types[self.idx_]) 177 self.length_ = uint(self.split_.lengths[self.idx_]) 178 } 179 180 self.length_-- 181 } 182 183 func buildHistogramsWithContext(cmds []command, literal_split *blockSplit, insert_and_copy_split *blockSplit, dist_split *blockSplit, ringbuffer []byte, start_pos uint, mask uint, prev_byte byte, prev_byte2 byte, context_modes []int, literal_histograms []histogramLiteral, insert_and_copy_histograms []histogramCommand, copy_dist_histograms []histogramDistance) { 184 var pos uint = start_pos 185 var literal_it blockSplitIterator 186 var insert_and_copy_it blockSplitIterator 187 var dist_it blockSplitIterator 188 189 initBlockSplitIterator(&literal_it, literal_split) 190 initBlockSplitIterator(&insert_and_copy_it, insert_and_copy_split) 191 initBlockSplitIterator(&dist_it, dist_split) 192 for i := range cmds { 193 var cmd *command = &cmds[i] 194 var j uint 195 blockSplitIteratorNext(&insert_and_copy_it) 196 histogramAddCommand(&insert_and_copy_histograms[insert_and_copy_it.type_], uint(cmd.cmd_prefix_)) 197 198 /* TODO: unwrap iterator blocks. */ 199 for j = uint(cmd.insert_len_); j != 0; j-- { 200 var context uint 201 blockSplitIteratorNext(&literal_it) 202 context = literal_it.type_ 203 if context_modes != nil { 204 var lut contextLUT = getContextLUT(context_modes[context]) 205 context = (context << literalContextBits) + uint(getContext(prev_byte, prev_byte2, lut)) 206 } 207 208 histogramAddLiteral(&literal_histograms[context], uint(ringbuffer[pos&mask])) 209 prev_byte2 = prev_byte 210 prev_byte = ringbuffer[pos&mask] 211 pos++ 212 } 213 214 pos += uint(commandCopyLen(cmd)) 215 if commandCopyLen(cmd) != 0 { 216 prev_byte2 = ringbuffer[(pos-2)&mask] 217 prev_byte = ringbuffer[(pos-1)&mask] 218 if cmd.cmd_prefix_ >= 128 { 219 var context uint 220 blockSplitIteratorNext(&dist_it) 221 context = uint(uint32(dist_it.type_<<distanceContextBits) + commandDistanceContext(cmd)) 222 histogramAddDistance(©_dist_histograms[context], uint(cmd.dist_prefix_)&0x3FF) 223 } 224 } 225 } 226 }