package brotli

import 

/* Copyright 2013 Google Inc. All Rights Reserved.

   Distributed under MIT license.
   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
*/

func initialEntropyCodesCommand( []uint16,  uint,  uint,  uint,  []histogramCommand) {
	var  uint32 = 7
	var  uint =  / 
	var  uint
	clearHistogramsCommand(, )
	for  = 0;  < ; ++ {
		var  uint =  *  / 
		if  != 0 {
			 += uint(myRand(&) % uint32())
		}

		if + >=  {
			 =  -  - 1
		}

		histogramAddVectorCommand(&[], [:], )
	}
}

func randomSampleCommand( *uint32,  []uint16,  uint,  uint,  *histogramCommand) {
	var  uint = 0
	if  >=  {
		 = 
	} else {
		 = uint(myRand() % uint32(-+1))
	}

	histogramAddVectorCommand(, [:], )
}

func refineEntropyCodesCommand( []uint16,  uint,  uint,  uint,  []histogramCommand) {
	var  uint = kIterMulForRefining*/ + kMinItersForRefining
	var  uint32 = 7
	var  uint
	 = (( +  - 1) / ) * 
	for  = 0;  < ; ++ {
		var  histogramCommand
		histogramClearCommand(&)
		randomSampleCommand(&, , , , &)
		histogramAddHistogramCommand(&[%], &)
	}
}

/* Assigns a block id from the range [0, num_histograms) to each data element
   in data[0..length) and fills in block_id[0..length) with the assigned values.
   Returns the number of blocks, i.e. one plus the number of block switches. */
func findBlocksCommand( []uint16,  uint,  float64,  uint,  []histogramCommand,  []float64,  []float64,  []byte,  []byte) uint {
	var  uint = histogramDataSizeCommand()
	var  uint = ( + 7) >> 3
	var  uint = 1
	var  uint
	var  uint
	assert( <= 256)
	if  <= 1 {
		for  = 0;  < ; ++ {
			[] = 0
		}

		return 1
	}

	for  := 0;  < int(*); ++ {
		[] = 0
	}
	for  = 0;  < ; ++ {
		[] = fastLog2(uint(uint32([].total_count_)))
	}

	for  = ;  != 0; {
		--
		for  = 0;  < ; ++ {
			[*+] = [] - bitCost(uint([].data_[]))
		}
	}

	for  := 0;  < int(); ++ {
		[] = 0
	}
	for  := 0;  < int(*); ++ {
		[] = 0
	}

	/* After each iteration of this loop, cost[k] will contain the difference
	   between the minimum cost of arriving at the current byte position using
	   entropy code k, and the minimum cost of arriving at the current byte
	   position. This difference is capped at the block switch cost, and if it
	   reaches block switch cost, it means that when we trace back from the last
	   position, we need to switch here. */
	for  = 0;  < ; ++ {
		var  uint = 
		var  uint =  * 
		var  uint = uint([]) * 
		var  float64 = 1e99
		var  float64 = 
		var  uint
		for  = 0;  < ; ++ {
			/* We are coding the symbol in data[byte_ix] with entropy code k. */
			[] += [+]

			if [] <  {
				 = []
				[] = byte()
			}
		}

		/* More blocks for the beginning. */
		if  < 2000 {
			 *= 0.77 + 0.07*float64()/2000
		}

		for  = 0;  < ; ++ {
			[] -= 
			if [] >=  {
				var  byte = byte(1 << ( & 7))
				[] = 
				assert(>>3 < )
				[+(>>3)] |= 
				/* Trace back from the last position and switch at the marked places. */
			}
		}
	}
	{
		var  uint =  - 1
		var  uint =  * 
		var  byte = []
		for  > 0 {
			var  byte = byte(1 << ( & 7))
			assert(uint()>>3 < )
			--
			 -= 
			if [+uint(>>3)]& != 0 {
				if  != [] {
					 = []
					++
				}
			}

			[] = 
		}
	}

	return 
}

var remapBlockIdsCommand_kInvalidId uint16 = 256

func remapBlockIdsCommand( []byte,  uint,  []uint16,  uint) uint {
	var  uint16 = 0
	var  uint
	for  = 0;  < ; ++ {
		[] = remapBlockIdsCommand_kInvalidId
	}

	for  = 0;  < ; ++ {
		assert(uint([]) < )
		if [[]] == remapBlockIdsCommand_kInvalidId {
			[[]] = 
			++
		}
	}

	for  = 0;  < ; ++ {
		[] = byte([[]])
		assert(uint([]) < )
	}

	assert(uint() <= )
	return uint()
}

func buildBlockHistogramsCommand( []uint16,  uint,  []byte,  uint,  []histogramCommand) {
	var  uint
	clearHistogramsCommand(, )
	for  = 0;  < ; ++ {
		histogramAddCommand(&[[]], uint([]))
	}
}

var clusterBlocksCommand_kInvalidIndex uint32 = math.MaxUint32

func clusterBlocksCommand( []uint16,  uint,  uint,  []byte,  *blockSplit) {
	var  []uint32 = make([]uint32, )
	var  []uint32 = make([]uint32, )
	var  uint = clustersPerBatch * ( + histogramsPerBatch - 1) / histogramsPerBatch
	var  uint = 0
	var  uint = 
	var  []histogramCommand = make([]histogramCommand, )
	var  uint = 0
	var  uint = 
	var  []uint32 = make([]uint32, )
	var  uint = 0
	var  []histogramCommand = make([]histogramCommand, brotli_min_size_t(, histogramsPerBatch))
	var  uint = histogramsPerBatch * histogramsPerBatch / 2
	var  uint =  + 1
	var  []histogramPair = make([]histogramPair, )
	var  uint = 0
	var  []uint32
	var  uint
	var  []uint32
	var  uint
	var  = [histogramsPerBatch]uint32{0}
	var  = [histogramsPerBatch]uint32{0}
	var  = [histogramsPerBatch]uint32{0}
	var  = [histogramsPerBatch]uint32{0}

	for  := 0;  < int(); ++ {
		[] = 0
	}
	{
		var  uint = 0
		for  = 0;  < ; ++ {
			assert( < )
			[]++
			if +1 ==  || [] != [+1] {
				++
			}
		}

		assert( == )
	}

	for  = 0;  < ;  += histogramsPerBatch {
		var  uint = brotli_min_size_t(-, histogramsPerBatch)
		var  uint
		var  uint
		for  = 0;  < ; ++ {
			var  uint
			histogramClearCommand(&[])
			for  = 0; uint32() < [+]; ++ {
				histogramAddCommand(&[], uint([]))
				++
			}

			[].bit_cost_ = populationCostCommand(&[])
			[] = uint32()
			[] = uint32()
			[] = 1
		}

		 = histogramCombineCommand(, [:], [:], [:], []histogramPair(), , , histogramsPerBatch, )
		if  < ( + ) {
			var  uint
			if  == 0 {
				 =  + 
			} else {
				 = 
			}
			var  []histogramCommand
			for  < ( + ) {
				 *= 2
			}
			 = make([]histogramCommand, )
			if  != 0 {
				copy(, [:])
			}

			 = 
			 = 
		}

		brotli_ensure_capacity_uint32_t(&, &, +)
		for  = 0;  < ; ++ {
			[] = [[]]
			++
			[] = [[]]
			++
			[[]] = uint32()
		}

		for  = 0;  < ; ++ {
			[+] = uint32() + [[]]
		}

		 += 
		assert( == )
		assert( == )
	}

	 = nil

	 = brotli_min_size_t(64*, (/2)*)
	if  < +1 {
		 = nil
		 = make([]histogramPair, ( + 1))
	}

	 = make([]uint32, )
	for  = 0;  < ; ++ {
		[] = uint32()
	}

	 = histogramCombineCommand(, , , , , , , maxNumberOfBlockTypes, )
	 = nil
	 = nil

	 = make([]uint32, )
	for  = 0;  < ; ++ {
		[] = clusterBlocksCommand_kInvalidIndex
	}
	 = 0
	{
		var  uint32 = 0
		for  = 0;  < ; ++ {
			var  histogramCommand
			var  uint
			var  uint32
			var  float64
			histogramClearCommand(&)
			for  = 0; uint32() < []; ++ {
				histogramAddCommand(&, uint([]))
				++
			}

			if  == 0 {
				 = [0]
			} else {
				 = [-1]
			}
			 = histogramBitCostDistanceCommand(&, &[])
			for  = 0;  < ; ++ {
				var  float64 = histogramBitCostDistanceCommand(&, &[[]])
				if  <  {
					 = 
					 = []
				}
			}

			[] = 
			if [] == clusterBlocksCommand_kInvalidIndex {
				[] = 
				++
			}
		}
	}

	 = nil
	 = nil
	brotli_ensure_capacity_uint8_t(&.types, &.types_alloc_size, )
	brotli_ensure_capacity_uint32_t(&.lengths, &.lengths_alloc_size, )
	{
		var  uint32 = 0
		var  uint = 0
		var  byte = 0
		for  = 0;  < ; ++ {
			 += []
			if +1 ==  || [] != [+1] {
				var  byte = byte([[]])
				.types[] = 
				.lengths[] = 
				 = brotli_max_uint8_t(, )
				 = 0
				++
			}
		}

		.num_blocks = 
		.num_types = uint() + 1
	}

	 = nil
	 = nil
	 = nil
}

func splitByteVectorCommand( []uint16,  uint,  uint,  uint,  float64,  *encoderParams,  *blockSplit) {
	 := uint(len())
	var  uint = histogramDataSizeCommand()
	var  uint = / + 1
	var  []histogramCommand
	if  >  {
		 = 
	}

	if  == 0 {
		.num_types = 1
		return
	} else if  < kMinLengthForBlockSplitting {
		brotli_ensure_capacity_uint8_t(&.types, &.types_alloc_size, .num_blocks+1)
		brotli_ensure_capacity_uint32_t(&.lengths, &.lengths_alloc_size, .num_blocks+1)
		.num_types = 1
		.types[.num_blocks] = 0
		.lengths[.num_blocks] = uint32()
		.num_blocks++
		return
	}

	 = make([]histogramCommand, )

	/* Find good entropy codes. */
	initialEntropyCodesCommand(, , , , )

	refineEntropyCodesCommand(, , , , )
	{
		var  []byte = make([]byte, )
		var  uint = 0
		var  uint = ( + 7) >> 3
		var  []float64 = make([]float64, ( * ))
		var  []float64 = make([]float64, )
		var  []byte = make([]byte, ( * ))
		var  []uint16 = make([]uint16, )
		var  uint
		if .quality < hqZopflificationQuality {
			 = 3
		} else {
			 = 10
		}
		/* Find a good path through literals with the good entropy codes. */

		var  uint
		for  = 0;  < ; ++ {
			 = findBlocksCommand(, , , , , , , , )
			 = remapBlockIdsCommand(, , , )
			buildBlockHistogramsCommand(, , , , )
		}

		 = nil
		 = nil
		 = nil
		 = nil
		 = nil
		clusterBlocksCommand(, , , , )
		 = nil
	}
}