metablock.go 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574
  1. package brotli
  2. import (
  3. "sync"
  4. )
  5. /* Copyright 2014 Google Inc. All Rights Reserved.
  6. Distributed under MIT license.
  7. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
  8. */
  9. /* Algorithms for distributing the literals and commands of a metablock between
  10. block types and contexts. */
  11. type metaBlockSplit struct {
  12. literal_split blockSplit
  13. command_split blockSplit
  14. distance_split blockSplit
  15. literal_context_map []uint32
  16. literal_context_map_size uint
  17. distance_context_map []uint32
  18. distance_context_map_size uint
  19. literal_histograms []histogramLiteral
  20. literal_histograms_size uint
  21. command_histograms []histogramCommand
  22. command_histograms_size uint
  23. distance_histograms []histogramDistance
  24. distance_histograms_size uint
  25. }
  26. var metaBlockPool sync.Pool
  27. func getMetaBlockSplit() *metaBlockSplit {
  28. mb, _ := metaBlockPool.Get().(*metaBlockSplit)
  29. if mb == nil {
  30. mb = &metaBlockSplit{}
  31. } else {
  32. initBlockSplit(&mb.literal_split)
  33. initBlockSplit(&mb.command_split)
  34. initBlockSplit(&mb.distance_split)
  35. mb.literal_context_map = mb.literal_context_map[:0]
  36. mb.literal_context_map_size = 0
  37. mb.distance_context_map = mb.distance_context_map[:0]
  38. mb.distance_context_map_size = 0
  39. mb.literal_histograms = mb.literal_histograms[:0]
  40. mb.command_histograms = mb.command_histograms[:0]
  41. mb.distance_histograms = mb.distance_histograms[:0]
  42. }
  43. return mb
  44. }
  45. func freeMetaBlockSplit(mb *metaBlockSplit) {
  46. metaBlockPool.Put(mb)
  47. }
  48. func initDistanceParams(params *encoderParams, npostfix uint32, ndirect uint32) {
  49. var dist_params *distanceParams = &params.dist
  50. var alphabet_size uint32
  51. var max_distance uint32
  52. dist_params.distance_postfix_bits = npostfix
  53. dist_params.num_direct_distance_codes = ndirect
  54. alphabet_size = uint32(distanceAlphabetSize(uint(npostfix), uint(ndirect), maxDistanceBits))
  55. max_distance = ndirect + (1 << (maxDistanceBits + npostfix + 2)) - (1 << (npostfix + 2))
  56. if params.large_window {
  57. var bound = [maxNpostfix + 1]uint32{0, 4, 12, 28}
  58. var postfix uint32 = 1 << npostfix
  59. alphabet_size = uint32(distanceAlphabetSize(uint(npostfix), uint(ndirect), largeMaxDistanceBits))
  60. /* The maximum distance is set so that no distance symbol used can encode
  61. a distance larger than BROTLI_MAX_ALLOWED_DISTANCE with all
  62. its extra bits set. */
  63. if ndirect < bound[npostfix] {
  64. max_distance = maxAllowedDistance - (bound[npostfix] - ndirect)
  65. } else if ndirect >= bound[npostfix]+postfix {
  66. max_distance = (3 << 29) - 4 + (ndirect - bound[npostfix])
  67. } else {
  68. max_distance = maxAllowedDistance
  69. }
  70. }
  71. dist_params.alphabet_size = alphabet_size
  72. dist_params.max_distance = uint(max_distance)
  73. }
  74. func recomputeDistancePrefixes(cmds []command, orig_params *distanceParams, new_params *distanceParams) {
  75. if orig_params.distance_postfix_bits == new_params.distance_postfix_bits && orig_params.num_direct_distance_codes == new_params.num_direct_distance_codes {
  76. return
  77. }
  78. for i := range cmds {
  79. var cmd *command = &cmds[i]
  80. if commandCopyLen(cmd) != 0 && cmd.cmd_prefix_ >= 128 {
  81. prefixEncodeCopyDistance(uint(commandRestoreDistanceCode(cmd, orig_params)), uint(new_params.num_direct_distance_codes), uint(new_params.distance_postfix_bits), &cmd.dist_prefix_, &cmd.dist_extra_)
  82. }
  83. }
  84. }
  85. func computeDistanceCost(cmds []command, orig_params *distanceParams, new_params *distanceParams, cost *float64) bool {
  86. var equal_params bool = false
  87. var dist_prefix uint16
  88. var dist_extra uint32
  89. var extra_bits float64 = 0.0
  90. var histo histogramDistance
  91. histogramClearDistance(&histo)
  92. if orig_params.distance_postfix_bits == new_params.distance_postfix_bits && orig_params.num_direct_distance_codes == new_params.num_direct_distance_codes {
  93. equal_params = true
  94. }
  95. for i := range cmds {
  96. cmd := &cmds[i]
  97. if commandCopyLen(cmd) != 0 && cmd.cmd_prefix_ >= 128 {
  98. if equal_params {
  99. dist_prefix = cmd.dist_prefix_
  100. } else {
  101. var distance uint32 = commandRestoreDistanceCode(cmd, orig_params)
  102. if distance > uint32(new_params.max_distance) {
  103. return false
  104. }
  105. prefixEncodeCopyDistance(uint(distance), uint(new_params.num_direct_distance_codes), uint(new_params.distance_postfix_bits), &dist_prefix, &dist_extra)
  106. }
  107. histogramAddDistance(&histo, uint(dist_prefix)&0x3FF)
  108. extra_bits += float64(dist_prefix >> 10)
  109. }
  110. }
  111. *cost = populationCostDistance(&histo) + extra_bits
  112. return true
  113. }
  114. var buildMetaBlock_kMaxNumberOfHistograms uint = 256
  115. func buildMetaBlock(ringbuffer []byte, pos uint, mask uint, params *encoderParams, prev_byte byte, prev_byte2 byte, cmds []command, literal_context_mode int, mb *metaBlockSplit) {
  116. var distance_histograms []histogramDistance
  117. var literal_histograms []histogramLiteral
  118. var literal_context_modes []int = nil
  119. var literal_histograms_size uint
  120. var distance_histograms_size uint
  121. var i uint
  122. var literal_context_multiplier uint = 1
  123. var npostfix uint32
  124. var ndirect_msb uint32 = 0
  125. var check_orig bool = true
  126. var best_dist_cost float64 = 1e99
  127. var orig_params encoderParams = *params
  128. /* Histogram ids need to fit in one byte. */
  129. var new_params encoderParams = *params
  130. for npostfix = 0; npostfix <= maxNpostfix; npostfix++ {
  131. for ; ndirect_msb < 16; ndirect_msb++ {
  132. var ndirect uint32 = ndirect_msb << npostfix
  133. var skip bool
  134. var dist_cost float64
  135. initDistanceParams(&new_params, npostfix, ndirect)
  136. if npostfix == orig_params.dist.distance_postfix_bits && ndirect == orig_params.dist.num_direct_distance_codes {
  137. check_orig = false
  138. }
  139. skip = !computeDistanceCost(cmds, &orig_params.dist, &new_params.dist, &dist_cost)
  140. if skip || (dist_cost > best_dist_cost) {
  141. break
  142. }
  143. best_dist_cost = dist_cost
  144. params.dist = new_params.dist
  145. }
  146. if ndirect_msb > 0 {
  147. ndirect_msb--
  148. }
  149. ndirect_msb /= 2
  150. }
  151. if check_orig {
  152. var dist_cost float64
  153. computeDistanceCost(cmds, &orig_params.dist, &orig_params.dist, &dist_cost)
  154. if dist_cost < best_dist_cost {
  155. /* NB: currently unused; uncomment when more param tuning is added. */
  156. /* best_dist_cost = dist_cost; */
  157. params.dist = orig_params.dist
  158. }
  159. }
  160. recomputeDistancePrefixes(cmds, &orig_params.dist, &params.dist)
  161. splitBlock(cmds, ringbuffer, pos, mask, params, &mb.literal_split, &mb.command_split, &mb.distance_split)
  162. if !params.disable_literal_context_modeling {
  163. literal_context_multiplier = 1 << literalContextBits
  164. literal_context_modes = make([]int, (mb.literal_split.num_types))
  165. for i = 0; i < mb.literal_split.num_types; i++ {
  166. literal_context_modes[i] = literal_context_mode
  167. }
  168. }
  169. literal_histograms_size = mb.literal_split.num_types * literal_context_multiplier
  170. literal_histograms = make([]histogramLiteral, literal_histograms_size)
  171. clearHistogramsLiteral(literal_histograms, literal_histograms_size)
  172. distance_histograms_size = mb.distance_split.num_types << distanceContextBits
  173. distance_histograms = make([]histogramDistance, distance_histograms_size)
  174. clearHistogramsDistance(distance_histograms, distance_histograms_size)
  175. mb.command_histograms_size = mb.command_split.num_types
  176. if cap(mb.command_histograms) < int(mb.command_histograms_size) {
  177. mb.command_histograms = make([]histogramCommand, (mb.command_histograms_size))
  178. } else {
  179. mb.command_histograms = mb.command_histograms[:mb.command_histograms_size]
  180. }
  181. clearHistogramsCommand(mb.command_histograms, mb.command_histograms_size)
  182. buildHistogramsWithContext(cmds, &mb.literal_split, &mb.command_split, &mb.distance_split, ringbuffer, pos, mask, prev_byte, prev_byte2, literal_context_modes, literal_histograms, mb.command_histograms, distance_histograms)
  183. literal_context_modes = nil
  184. mb.literal_context_map_size = mb.literal_split.num_types << literalContextBits
  185. if cap(mb.literal_context_map) < int(mb.literal_context_map_size) {
  186. mb.literal_context_map = make([]uint32, (mb.literal_context_map_size))
  187. } else {
  188. mb.literal_context_map = mb.literal_context_map[:mb.literal_context_map_size]
  189. }
  190. mb.literal_histograms_size = mb.literal_context_map_size
  191. if cap(mb.literal_histograms) < int(mb.literal_histograms_size) {
  192. mb.literal_histograms = make([]histogramLiteral, (mb.literal_histograms_size))
  193. } else {
  194. mb.literal_histograms = mb.literal_histograms[:mb.literal_histograms_size]
  195. }
  196. clusterHistogramsLiteral(literal_histograms, literal_histograms_size, buildMetaBlock_kMaxNumberOfHistograms, mb.literal_histograms, &mb.literal_histograms_size, mb.literal_context_map)
  197. literal_histograms = nil
  198. if params.disable_literal_context_modeling {
  199. /* Distribute assignment to all contexts. */
  200. for i = mb.literal_split.num_types; i != 0; {
  201. var j uint = 0
  202. i--
  203. for ; j < 1<<literalContextBits; j++ {
  204. mb.literal_context_map[(i<<literalContextBits)+j] = mb.literal_context_map[i]
  205. }
  206. }
  207. }
  208. mb.distance_context_map_size = mb.distance_split.num_types << distanceContextBits
  209. if cap(mb.distance_context_map) < int(mb.distance_context_map_size) {
  210. mb.distance_context_map = make([]uint32, (mb.distance_context_map_size))
  211. } else {
  212. mb.distance_context_map = mb.distance_context_map[:mb.distance_context_map_size]
  213. }
  214. mb.distance_histograms_size = mb.distance_context_map_size
  215. if cap(mb.distance_histograms) < int(mb.distance_histograms_size) {
  216. mb.distance_histograms = make([]histogramDistance, (mb.distance_histograms_size))
  217. } else {
  218. mb.distance_histograms = mb.distance_histograms[:mb.distance_histograms_size]
  219. }
  220. clusterHistogramsDistance(distance_histograms, mb.distance_context_map_size, buildMetaBlock_kMaxNumberOfHistograms, mb.distance_histograms, &mb.distance_histograms_size, mb.distance_context_map)
  221. distance_histograms = nil
  222. }
  223. const maxStaticContexts = 13
  224. /* Greedy block splitter for one block category (literal, command or distance).
  225. Gathers histograms for all context buckets. */
  226. type contextBlockSplitter struct {
  227. alphabet_size_ uint
  228. num_contexts_ uint
  229. max_block_types_ uint
  230. min_block_size_ uint
  231. split_threshold_ float64
  232. num_blocks_ uint
  233. split_ *blockSplit
  234. histograms_ []histogramLiteral
  235. histograms_size_ *uint
  236. target_block_size_ uint
  237. block_size_ uint
  238. curr_histogram_ix_ uint
  239. last_histogram_ix_ [2]uint
  240. last_entropy_ [2 * maxStaticContexts]float64
  241. merge_last_count_ uint
  242. }
  243. func initContextBlockSplitter(self *contextBlockSplitter, alphabet_size uint, num_contexts uint, min_block_size uint, split_threshold float64, num_symbols uint, split *blockSplit, histograms *[]histogramLiteral, histograms_size *uint) {
  244. var max_num_blocks uint = num_symbols/min_block_size + 1
  245. var max_num_types uint
  246. assert(num_contexts <= maxStaticContexts)
  247. self.alphabet_size_ = alphabet_size
  248. self.num_contexts_ = num_contexts
  249. self.max_block_types_ = maxNumberOfBlockTypes / num_contexts
  250. self.min_block_size_ = min_block_size
  251. self.split_threshold_ = split_threshold
  252. self.num_blocks_ = 0
  253. self.split_ = split
  254. self.histograms_size_ = histograms_size
  255. self.target_block_size_ = min_block_size
  256. self.block_size_ = 0
  257. self.curr_histogram_ix_ = 0
  258. self.merge_last_count_ = 0
  259. /* We have to allocate one more histogram than the maximum number of block
  260. types for the current histogram when the meta-block is too big. */
  261. max_num_types = brotli_min_size_t(max_num_blocks, self.max_block_types_+1)
  262. brotli_ensure_capacity_uint8_t(&split.types, &split.types_alloc_size, max_num_blocks)
  263. brotli_ensure_capacity_uint32_t(&split.lengths, &split.lengths_alloc_size, max_num_blocks)
  264. split.num_blocks = max_num_blocks
  265. *histograms_size = max_num_types * num_contexts
  266. if histograms == nil || cap(*histograms) < int(*histograms_size) {
  267. *histograms = make([]histogramLiteral, (*histograms_size))
  268. } else {
  269. *histograms = (*histograms)[:*histograms_size]
  270. }
  271. self.histograms_ = *histograms
  272. /* Clear only current histogram. */
  273. clearHistogramsLiteral(self.histograms_[0:], num_contexts)
  274. self.last_histogram_ix_[1] = 0
  275. self.last_histogram_ix_[0] = self.last_histogram_ix_[1]
  276. }
  277. /* Does either of three things:
  278. (1) emits the current block with a new block type;
  279. (2) emits the current block with the type of the second last block;
  280. (3) merges the current block with the last block. */
  281. func contextBlockSplitterFinishBlock(self *contextBlockSplitter, is_final bool) {
  282. var split *blockSplit = self.split_
  283. var num_contexts uint = self.num_contexts_
  284. var last_entropy []float64 = self.last_entropy_[:]
  285. var histograms []histogramLiteral = self.histograms_
  286. if self.block_size_ < self.min_block_size_ {
  287. self.block_size_ = self.min_block_size_
  288. }
  289. if self.num_blocks_ == 0 {
  290. var i uint
  291. /* Create first block. */
  292. split.lengths[0] = uint32(self.block_size_)
  293. split.types[0] = 0
  294. for i = 0; i < num_contexts; i++ {
  295. last_entropy[i] = bitsEntropy(histograms[i].data_[:], self.alphabet_size_)
  296. last_entropy[num_contexts+i] = last_entropy[i]
  297. }
  298. self.num_blocks_++
  299. split.num_types++
  300. self.curr_histogram_ix_ += num_contexts
  301. if self.curr_histogram_ix_ < *self.histograms_size_ {
  302. clearHistogramsLiteral(self.histograms_[self.curr_histogram_ix_:], self.num_contexts_)
  303. }
  304. self.block_size_ = 0
  305. } else if self.block_size_ > 0 {
  306. var entropy [maxStaticContexts]float64
  307. var combined_histo []histogramLiteral = make([]histogramLiteral, (2 * num_contexts))
  308. var combined_entropy [2 * maxStaticContexts]float64
  309. var diff = [2]float64{0.0}
  310. /* Try merging the set of histograms for the current block type with the
  311. respective set of histograms for the last and second last block types.
  312. Decide over the split based on the total reduction of entropy across
  313. all contexts. */
  314. var i uint
  315. for i = 0; i < num_contexts; i++ {
  316. var curr_histo_ix uint = self.curr_histogram_ix_ + i
  317. var j uint
  318. entropy[i] = bitsEntropy(histograms[curr_histo_ix].data_[:], self.alphabet_size_)
  319. for j = 0; j < 2; j++ {
  320. var jx uint = j*num_contexts + i
  321. var last_histogram_ix uint = self.last_histogram_ix_[j] + i
  322. combined_histo[jx] = histograms[curr_histo_ix]
  323. histogramAddHistogramLiteral(&combined_histo[jx], &histograms[last_histogram_ix])
  324. combined_entropy[jx] = bitsEntropy(combined_histo[jx].data_[0:], self.alphabet_size_)
  325. diff[j] += combined_entropy[jx] - entropy[i] - last_entropy[jx]
  326. }
  327. }
  328. if split.num_types < self.max_block_types_ && diff[0] > self.split_threshold_ && diff[1] > self.split_threshold_ {
  329. /* Create new block. */
  330. split.lengths[self.num_blocks_] = uint32(self.block_size_)
  331. split.types[self.num_blocks_] = byte(split.num_types)
  332. self.last_histogram_ix_[1] = self.last_histogram_ix_[0]
  333. self.last_histogram_ix_[0] = split.num_types * num_contexts
  334. for i = 0; i < num_contexts; i++ {
  335. last_entropy[num_contexts+i] = last_entropy[i]
  336. last_entropy[i] = entropy[i]
  337. }
  338. self.num_blocks_++
  339. split.num_types++
  340. self.curr_histogram_ix_ += num_contexts
  341. if self.curr_histogram_ix_ < *self.histograms_size_ {
  342. clearHistogramsLiteral(self.histograms_[self.curr_histogram_ix_:], self.num_contexts_)
  343. }
  344. self.block_size_ = 0
  345. self.merge_last_count_ = 0
  346. self.target_block_size_ = self.min_block_size_
  347. } else if diff[1] < diff[0]-20.0 {
  348. split.lengths[self.num_blocks_] = uint32(self.block_size_)
  349. split.types[self.num_blocks_] = split.types[self.num_blocks_-2]
  350. /* Combine this block with second last block. */
  351. var tmp uint = self.last_histogram_ix_[0]
  352. self.last_histogram_ix_[0] = self.last_histogram_ix_[1]
  353. self.last_histogram_ix_[1] = tmp
  354. for i = 0; i < num_contexts; i++ {
  355. histograms[self.last_histogram_ix_[0]+i] = combined_histo[num_contexts+i]
  356. last_entropy[num_contexts+i] = last_entropy[i]
  357. last_entropy[i] = combined_entropy[num_contexts+i]
  358. histogramClearLiteral(&histograms[self.curr_histogram_ix_+i])
  359. }
  360. self.num_blocks_++
  361. self.block_size_ = 0
  362. self.merge_last_count_ = 0
  363. self.target_block_size_ = self.min_block_size_
  364. } else {
  365. /* Combine this block with last block. */
  366. split.lengths[self.num_blocks_-1] += uint32(self.block_size_)
  367. for i = 0; i < num_contexts; i++ {
  368. histograms[self.last_histogram_ix_[0]+i] = combined_histo[i]
  369. last_entropy[i] = combined_entropy[i]
  370. if split.num_types == 1 {
  371. last_entropy[num_contexts+i] = last_entropy[i]
  372. }
  373. histogramClearLiteral(&histograms[self.curr_histogram_ix_+i])
  374. }
  375. self.block_size_ = 0
  376. self.merge_last_count_++
  377. if self.merge_last_count_ > 1 {
  378. self.target_block_size_ += self.min_block_size_
  379. }
  380. }
  381. combined_histo = nil
  382. }
  383. if is_final {
  384. *self.histograms_size_ = split.num_types * num_contexts
  385. split.num_blocks = self.num_blocks_
  386. }
  387. }
  388. /* Adds the next symbol to the current block type and context. When the
  389. current block reaches the target size, decides on merging the block. */
  390. func contextBlockSplitterAddSymbol(self *contextBlockSplitter, symbol uint, context uint) {
  391. histogramAddLiteral(&self.histograms_[self.curr_histogram_ix_+context], symbol)
  392. self.block_size_++
  393. if self.block_size_ == self.target_block_size_ {
  394. contextBlockSplitterFinishBlock(self, false) /* is_final = */
  395. }
  396. }
  397. func mapStaticContexts(num_contexts uint, static_context_map []uint32, mb *metaBlockSplit) {
  398. var i uint
  399. mb.literal_context_map_size = mb.literal_split.num_types << literalContextBits
  400. if cap(mb.literal_context_map) < int(mb.literal_context_map_size) {
  401. mb.literal_context_map = make([]uint32, (mb.literal_context_map_size))
  402. } else {
  403. mb.literal_context_map = mb.literal_context_map[:mb.literal_context_map_size]
  404. }
  405. for i = 0; i < mb.literal_split.num_types; i++ {
  406. var offset uint32 = uint32(i * num_contexts)
  407. var j uint
  408. for j = 0; j < 1<<literalContextBits; j++ {
  409. mb.literal_context_map[(i<<literalContextBits)+j] = offset + static_context_map[j]
  410. }
  411. }
  412. }
  413. func buildMetaBlockGreedyInternal(ringbuffer []byte, pos uint, mask uint, prev_byte byte, prev_byte2 byte, literal_context_lut contextLUT, num_contexts uint, static_context_map []uint32, commands []command, mb *metaBlockSplit) {
  414. var lit_blocks struct {
  415. plain blockSplitterLiteral
  416. ctx contextBlockSplitter
  417. }
  418. var cmd_blocks blockSplitterCommand
  419. var dist_blocks blockSplitterDistance
  420. var num_literals uint = 0
  421. for i := range commands {
  422. num_literals += uint(commands[i].insert_len_)
  423. }
  424. if num_contexts == 1 {
  425. initBlockSplitterLiteral(&lit_blocks.plain, 256, 512, 400.0, num_literals, &mb.literal_split, &mb.literal_histograms, &mb.literal_histograms_size)
  426. } else {
  427. initContextBlockSplitter(&lit_blocks.ctx, 256, num_contexts, 512, 400.0, num_literals, &mb.literal_split, &mb.literal_histograms, &mb.literal_histograms_size)
  428. }
  429. initBlockSplitterCommand(&cmd_blocks, numCommandSymbols, 1024, 500.0, uint(len(commands)), &mb.command_split, &mb.command_histograms, &mb.command_histograms_size)
  430. initBlockSplitterDistance(&dist_blocks, 64, 512, 100.0, uint(len(commands)), &mb.distance_split, &mb.distance_histograms, &mb.distance_histograms_size)
  431. for _, cmd := range commands {
  432. var j uint
  433. blockSplitterAddSymbolCommand(&cmd_blocks, uint(cmd.cmd_prefix_))
  434. for j = uint(cmd.insert_len_); j != 0; j-- {
  435. var literal byte = ringbuffer[pos&mask]
  436. if num_contexts == 1 {
  437. blockSplitterAddSymbolLiteral(&lit_blocks.plain, uint(literal))
  438. } else {
  439. var context uint = uint(getContext(prev_byte, prev_byte2, literal_context_lut))
  440. contextBlockSplitterAddSymbol(&lit_blocks.ctx, uint(literal), uint(static_context_map[context]))
  441. }
  442. prev_byte2 = prev_byte
  443. prev_byte = literal
  444. pos++
  445. }
  446. pos += uint(commandCopyLen(&cmd))
  447. if commandCopyLen(&cmd) != 0 {
  448. prev_byte2 = ringbuffer[(pos-2)&mask]
  449. prev_byte = ringbuffer[(pos-1)&mask]
  450. if cmd.cmd_prefix_ >= 128 {
  451. blockSplitterAddSymbolDistance(&dist_blocks, uint(cmd.dist_prefix_)&0x3FF)
  452. }
  453. }
  454. }
  455. if num_contexts == 1 {
  456. blockSplitterFinishBlockLiteral(&lit_blocks.plain, true) /* is_final = */
  457. } else {
  458. contextBlockSplitterFinishBlock(&lit_blocks.ctx, true) /* is_final = */
  459. }
  460. blockSplitterFinishBlockCommand(&cmd_blocks, true) /* is_final = */
  461. blockSplitterFinishBlockDistance(&dist_blocks, true) /* is_final = */
  462. if num_contexts > 1 {
  463. mapStaticContexts(num_contexts, static_context_map, mb)
  464. }
  465. }
  466. func buildMetaBlockGreedy(ringbuffer []byte, pos uint, mask uint, prev_byte byte, prev_byte2 byte, literal_context_lut contextLUT, num_contexts uint, static_context_map []uint32, commands []command, mb *metaBlockSplit) {
  467. if num_contexts == 1 {
  468. buildMetaBlockGreedyInternal(ringbuffer, pos, mask, prev_byte, prev_byte2, literal_context_lut, 1, nil, commands, mb)
  469. } else {
  470. buildMetaBlockGreedyInternal(ringbuffer, pos, mask, prev_byte, prev_byte2, literal_context_lut, num_contexts, static_context_map, commands, mb)
  471. }
  472. }
  473. func optimizeHistograms(num_distance_codes uint32, mb *metaBlockSplit) {
  474. var good_for_rle [numCommandSymbols]byte
  475. var i uint
  476. for i = 0; i < mb.literal_histograms_size; i++ {
  477. optimizeHuffmanCountsForRLE(256, mb.literal_histograms[i].data_[:], good_for_rle[:])
  478. }
  479. for i = 0; i < mb.command_histograms_size; i++ {
  480. optimizeHuffmanCountsForRLE(numCommandSymbols, mb.command_histograms[i].data_[:], good_for_rle[:])
  481. }
  482. for i = 0; i < mb.distance_histograms_size; i++ {
  483. optimizeHuffmanCountsForRLE(uint(num_distance_codes), mb.distance_histograms[i].data_[:], good_for_rle[:])
  484. }
  485. }