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(&copy_dist_histograms[context], uint(cmd.dist_prefix_)&0x3FF)
   223  			}
   224  		}
   225  	}
   226  }