func computeDistanceCache(pos uint, starting_dist_cache []int, nodes []zopfliNode, dist_cache []int) {
	var idx int = 0
	var p uint = uint(nodes[pos].u.shortcut)
	for idx < 4 && p > 0 {
		var ilen uint = uint(nodes[p].dcode_insert_length & 0x7FFFFFF)
		var clen uint = uint(zopfliNodeCopyLength(&nodes[p]))
		var dist uint = uint(zopfliNodeCopyDistance(&nodes[p]))
		dist_cache[idx] = int(dist)
		idx++
		p = uint(nodes[p-clen-ilen].u.shortcut)
	}
	for ; idx < 4; idx++ {
		dist_cache[idx] = starting_dist_cache[0]
		starting_dist_cache = starting_dist_cache[1:]
	}
}
/* Fills in dist_cache[0..3] with the last four distances (as defined by
Section 4. of the Spec) that would be used at (block_start + pos) if we
used the shortest path of commands from block_start, computed from
nodes[0..pos]. The last four distances at block_start are in
starting_dist_cache[0..3].
REQUIRES: nodes[pos].cost < kInfinity
REQUIRES: nodes[0..pos] satisfies that "ZopfliNode array invariant".
package brotli
import "math"
type zopfliNode struct {
	length              uint32
	distance            uint32
	dcode_insert_length uint32
	u                   struct {
		cost     float32
		next     uint32
		shortcut uint32
	}
}
const maxEffectiveDistanceAlphabetSize = 544
const kInfinity float32 = 1.7e38  
var kDistanceCacheIndex = []uint32{0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1}
var kDistanceCacheOffset = []int{0, 0, 0, 0, -1, 1, -2, 2, -3, 3, -1, 1, -2, 2, -3, 3}
func initZopfliNodes(array []zopfliNode, length uint) {
	var stub zopfliNode
	var i uint
	stub.length = 1
	stub.distance = 0
	stub.dcode_insert_length = 0
	stub.u.cost = kInfinity
	for i = 0; i < length; i++ {
		array[i] = stub
	}
}
func zopfliNodeCopyLength(self *zopfliNode) uint32 {
	return self.length & 0x1FFFFFF
}
func zopfliNodeLengthCode(self *zopfliNode) uint32 {
	var modifier uint32 = self.length >> 25
	return zopfliNodeCopyLength(self) + 9 - modifier
}
func zopfliNodeCopyDistance(self *zopfliNode) uint32 {
	return self.distance
}
func zopfliNodeDistanceCode(self *zopfliNode) uint32 {
	var short_code uint32 = self.dcode_insert_length >> 27
	if short_code == 0 {
		return zopfliNodeCopyDistance(self) + numDistanceShortCodes - 1
	} else {
		return short_code - 1
	}
}
func zopfliNodeCommandLength(self *zopfliNode) uint32 {
	return zopfliNodeCopyLength(self) + (self.dcode_insert_length & 0x7FFFFFF)
}
type zopfliCostModel struct {
	cost_cmd_               [numCommandSymbols]float32
	cost_dist_              []float32
	distance_histogram_size uint32
	literal_costs_          []float32
	min_cost_cmd_           float32
	num_bytes_              uint
}
func initZopfliCostModel(self *zopfliCostModel, dist *distanceParams, num_bytes uint) {
	var distance_histogram_size uint32 = dist.alphabet_size
	if distance_histogram_size > maxEffectiveDistanceAlphabetSize {
		distance_histogram_size = maxEffectiveDistanceAlphabetSize
	}
	self.num_bytes_ = num_bytes
	self.literal_costs_ = make([]float32, (num_bytes + 2))
	self.cost_dist_ = make([]float32, (dist.alphabet_size))
	self.distance_histogram_size = distance_histogram_size
}
func cleanupZopfliCostModel(self *zopfliCostModel) {
	self.literal_costs_ = nil
	self.cost_dist_ = nil
}
func setCost(histogram []uint32, histogram_size uint, literal_histogram bool, cost []float32) {
	var sum uint = 0
	var missing_symbol_sum uint
	var log2sum float32
	var missing_symbol_cost float32
	var i uint
	for i = 0; i < histogram_size; i++ {
		sum += uint(histogram[i])
	}
	log2sum = float32(fastLog2(sum))
	missing_symbol_sum = sum
	if !literal_histogram {
		for i = 0; i < histogram_size; i++ {
			if histogram[i] == 0 {
				missing_symbol_sum++
			}
		}
	}
	missing_symbol_cost = float32(fastLog2(missing_symbol_sum)) + 2
	for i = 0; i < histogram_size; i++ {
		if histogram[i] == 0 {
			cost[i] = missing_symbol_cost
			continue
		}
		cost[i] = log2sum - float32(fastLog2(uint(histogram[i])))
		if cost[i] < 1 {
			cost[i] = 1
		}
	}
}
func zopfliCostModelSetFromCommands(self *zopfliCostModel, position uint, ringbuffer []byte, ringbuffer_mask uint, commands []command, num_commands uint, last_insert_len uint) {
	var histogram_literal [numLiteralSymbols]uint32
	var histogram_cmd [numCommandSymbols]uint32
	var histogram_dist [maxEffectiveDistanceAlphabetSize]uint32
	var cost_literal [numLiteralSymbols]float32
	var pos uint = position - last_insert_len
	var min_cost_cmd float32 = kInfinity
	var i uint
	var cost_cmd []float32 = self.cost_cmd_[:]
	var literal_costs []float32
	histogram_literal = [numLiteralSymbols]uint32{}
	histogram_cmd = [numCommandSymbols]uint32{}
	histogram_dist = [maxEffectiveDistanceAlphabetSize]uint32{}
	for i = 0; i < num_commands; i++ {
		var inslength uint = uint(commands[i].insert_len_)
		var copylength uint = uint(commandCopyLen(&commands[i]))
		var distcode uint = uint(commands[i].dist_prefix_) & 0x3FF
		var cmdcode uint = uint(commands[i].cmd_prefix_)
		var j uint
		histogram_cmd[cmdcode]++
		if cmdcode >= 128 {
			histogram_dist[distcode]++
		}
		for j = 0; j < inslength; j++ {
			histogram_literal[ringbuffer[(pos+j)&ringbuffer_mask]]++
		}
		pos += inslength + copylength
	}
	setCost(histogram_literal[:], numLiteralSymbols, true, cost_literal[:])
	setCost(histogram_cmd[:], numCommandSymbols, false, cost_cmd)
	setCost(histogram_dist[:], uint(self.distance_histogram_size), false, self.cost_dist_)
	for i = 0; i < numCommandSymbols; i++ {
		min_cost_cmd = brotli_min_float(min_cost_cmd, cost_cmd[i])
	}
	self.min_cost_cmd_ = min_cost_cmd
	{
		literal_costs = self.literal_costs_
		var literal_carry float32 = 0.0
		var num_bytes uint = self.num_bytes_
		literal_costs[0] = 0.0
		for i = 0; i < num_bytes; i++ {
			literal_carry += cost_literal[ringbuffer[(position+i)&ringbuffer_mask]]
			literal_costs[i+1] = literal_costs[i] + literal_carry
			literal_carry -= literal_costs[i+1] - literal_costs[i]
		}
	}
}
func zopfliCostModelSetFromLiteralCosts(self *zopfliCostModel, position uint, ringbuffer []byte, ringbuffer_mask uint) {
	var literal_costs []float32 = self.literal_costs_
	var literal_carry float32 = 0.0
	var cost_dist []float32 = self.cost_dist_
	var cost_cmd []float32 = self.cost_cmd_[:]
	var num_bytes uint = self.num_bytes_
	var i uint
	estimateBitCostsForLiterals(position, num_bytes, ringbuffer_mask, ringbuffer, literal_costs[1:])
	literal_costs[0] = 0.0
	for i = 0; i < num_bytes; i++ {
		literal_carry += literal_costs[i+1]
		literal_costs[i+1] = literal_costs[i] + literal_carry
		literal_carry -= literal_costs[i+1] - literal_costs[i]
	}
	for i = 0; i < numCommandSymbols; i++ {
		cost_cmd[i] = float32(fastLog2(uint(11 + uint32(i))))
	}
	for i = 0; uint32(i) < self.distance_histogram_size; i++ {
		cost_dist[i] = float32(fastLog2(uint(20 + uint32(i))))
	}
	self.min_cost_cmd_ = float32(fastLog2(11))
}
func zopfliCostModelGetCommandCost(self *zopfliCostModel, cmdcode uint16) float32 {
	return self.cost_cmd_[cmdcode]
}
func zopfliCostModelGetDistanceCost(self *zopfliCostModel, distcode uint) float32 {
	return self.cost_dist_[distcode]
}
func zopfliCostModelGetLiteralCosts(self *zopfliCostModel, from uint, to uint) float32 {
	return self.literal_costs_[to] - self.literal_costs_[from]
}
func zopfliCostModelGetMinCostCmd(self *zopfliCostModel) float32 {
	return self.min_cost_cmd_
}
func updateZopfliNode(nodes []zopfliNode, pos uint, start_pos uint, len uint, len_code uint, dist uint, short_code uint, cost float32) {
	var next *zopfliNode = &nodes[pos+len]
	next.length = uint32(len | (len+9-len_code)<<25)
	next.distance = uint32(dist)
	next.dcode_insert_length = uint32(short_code<<27 | (pos - start_pos))
	next.u.cost = cost
}
type posData struct {
	pos            uint
	distance_cache [4]int
	costdiff       float32
	cost           float32
}
type startPosQueue struct {
	q_   [8]posData
	idx_ uint
}
func initStartPosQueue(self *startPosQueue) {
	self.idx_ = 0
}
func startPosQueueSize(self *startPosQueue) uint {
	return brotli_min_size_t(self.idx_, 8)
}
func startPosQueuePush(self *startPosQueue, posdata *posData) {
	var offset uint = ^(self.idx_) & 7
	self.idx_++
	var len uint = startPosQueueSize(self)
	var i uint
	var q []posData = self.q_[:]
	q[offset] = *posdata
	for i = 1; i < len; i++ {
		if q[offset&7].costdiff > q[(offset+1)&7].costdiff {
			var tmp posData = q[offset&7]
			q[offset&7] = q[(offset+1)&7]
			q[(offset+1)&7] = tmp
		}
		offset++
	}
}
func startPosQueueAt(self *startPosQueue, k uint) *posData {
	return &self.q_[(k-self.idx_)&7]
}
func computeMinimumCopyLength(start_cost float32, nodes []zopfliNode, num_bytes uint, pos uint) uint {
	var min_cost float32 = start_cost
	var len uint = 2
	var next_len_bucket uint = 4
	var next_len_offset uint = 10
	for pos+len <= num_bytes && nodes[pos+len].u.cost <= min_cost {
		len++
		if len == next_len_offset {
			min_cost += 1.0
			next_len_offset += next_len_bucket
			next_len_bucket *= 2
		}
	}
	return uint(len)
}
func computeDistanceShortcut(block_start uint, pos uint, max_backward_limit uint, gap uint, nodes []zopfliNode) uint32 {
	var clen uint = uint(zopfliNodeCopyLength(&nodes[pos]))
	var ilen uint = uint(nodes[pos].dcode_insert_length & 0x7FFFFFF)
	var dist uint = uint(zopfliNodeCopyDistance(&nodes[pos]))
	if pos == 0 {
		return 0
	} else if dist+clen <= block_start+pos+gap && dist <= max_backward_limit+gap && zopfliNodeDistanceCode(&nodes[pos]) > 0 {
		return uint32(pos)
	} else {
		return nodes[pos-clen-ilen].u.shortcut
	}
}