package brotli

/* Copyright 2013 Google Inc. All Rights Reserved.

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

/* Computes the bit cost reduction by combining out[idx1] and out[idx2] and if
   it is below a threshold, stores the pair (idx1, idx2) in the *pairs queue. */
func compareAndPushToQueueCommand( []histogramCommand,  []uint32,  uint32,  uint32,  uint,  []histogramPair,  *uint) {
	var  bool = false
	var  histogramPair
	.idx2 = 0
	.idx1 = .idx2
	.cost_combo = 0
	.cost_diff = .cost_combo
	if  ==  {
		return
	}

	if  <  {
		var  uint32 = 
		 = 
		 = 
	}

	.idx1 = 
	.idx2 = 
	.cost_diff = 0.5 * clusterCostDiff(uint([]), uint([]))
	.cost_diff -= [].bit_cost_
	.cost_diff -= [].bit_cost_

	if [].total_count_ == 0 {
		.cost_combo = [].bit_cost_
		 = true
	} else if [].total_count_ == 0 {
		.cost_combo = [].bit_cost_
		 = true
	} else {
		var  float64
		if * == 0 {
			 = 1e99
		} else {
			 = brotli_max_double(0.0, [0].cost_diff)
		}
		var  histogramCommand = []
		var  float64
		histogramAddHistogramCommand(&, &[])
		 = populationCostCommand(&)
		if  < -.cost_diff {
			.cost_combo = 
			 = true
		}
	}

	if  {
		.cost_diff += .cost_combo
		if * > 0 && histogramPairIsLess(&[0], &) {
			/* Replace the top of the queue if needed. */
			if * <  {
				[*] = [0]
				(*)++
			}

			[0] = 
		} else if * <  {
			[*] = 
			(*)++
		}
	}
}

func histogramCombineCommand( []histogramCommand,  []uint32,  []uint32,  []uint32,  []histogramPair,  uint,  uint,  uint,  uint) uint {
	var  float64 = 0.0
	var  uint = 1
	var  uint = 0
	{
		/* We maintain a vector of histogram pairs, with the property that the pair
		   with the maximum bit cost reduction is the first. */
		var  uint
		for  = 0;  < ; ++ {
			var  uint
			for  =  + 1;  < ; ++ {
				compareAndPushToQueueCommand(, , [], [], , [0:], &)
			}
		}
	}

	for  >  {
		var  uint32
		var  uint32
		var  uint
		if [0].cost_diff >=  {
			 = 1e99
			 = 
			continue
		}

		/* Take the best pair from the top of heap. */
		 = [0].idx1

		 = [0].idx2
		histogramAddHistogramCommand(&[], &[])
		[].bit_cost_ = [0].cost_combo
		[] += []
		for  = 0;  < ; ++ {
			if [] ==  {
				[] = 
			}
		}

		for  = 0;  < ; ++ {
			if [] ==  {
				copy([:], [+1:][:--1])
				break
			}
		}

		--
		{
			/* Remove pairs intersecting the just combined best pair. */
			var  uint = 0
			for  = 0;  < ; ++ {
				var  *histogramPair = &[]
				if .idx1 ==  || .idx2 ==  || .idx1 ==  || .idx2 ==  {
					/* Remove invalid pair from the queue. */
					continue
				}

				if histogramPairIsLess(&[0], ) {
					/* Replace the top of the queue if needed. */
					var  histogramPair = [0]
					[0] = *
					[] = 
				} else {
					[] = *
				}

				++
			}

			 = 
		}

		/* Push new pairs formed with the combined histogram to the heap. */
		for  = 0;  < ; ++ {
			compareAndPushToQueueCommand(, , , [], , [0:], &)
		}
	}

	return 
}

/* What is the bit cost of moving histogram from cur_symbol to candidate. */
func histogramBitCostDistanceCommand( *histogramCommand,  *histogramCommand) float64 {
	if .total_count_ == 0 {
		return 0.0
	} else {
		var  histogramCommand = *
		histogramAddHistogramCommand(&, )
		return populationCostCommand(&) - .bit_cost_
	}
}