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
*/

/* Function to find backward reference copies. */

func computeDistanceCode( uint,  uint,  []int) uint {
	if  <=  {
		var  uint =  + 3
		var  uint =  - uint([0])
		var  uint =  - uint([1])
		if  == uint([0]) {
			return 0
		} else if  == uint([1]) {
			return 1
		} else if  < 7 {
			return (0x9750468 >> (4 * )) & 0xF
		} else if  < 7 {
			return (0xFDB1ACE >> (4 * )) & 0xF
		} else if  == uint([2]) {
			return 2
		} else if  == uint([3]) {
			return 3
		}
	}

	return  + numDistanceShortCodes - 1
}

var hasherSearchResultPool sync.Pool

func createBackwardReferences( uint,  uint,  []byte,  uint,  *encoderParams,  hasherHandle,  []int,  *uint,  *[]command,  *uint) {
	var  uint = maxBackwardLimit(.lgwin)
	var  uint = *
	var  uint =  + 
	var  uint
	if  >= .StoreLookahead() {
		 =  +  - .StoreLookahead() + 1
	} else {
		 = 
	}
	var  uint = literalSpreeLengthForSparseSearch()
	var  uint =  + 
	var  uint = 0
	/* Set maximum distance, see section 9.1. of the spec. */

	const  uint = scoreBase + 100

	/* For speed up heuristics for random data. */

	/* Minimum score to accept a backward reference. */
	.PrepareDistanceCache()
	,  := hasherSearchResultPool.Get().(*hasherSearchResult)
	if  == nil {
		 = &hasherSearchResult{}
	}
	,  := hasherSearchResultPool.Get().(*hasherSearchResult)
	if  == nil {
		 = &hasherSearchResult{}
	}

	for +.HashTypeLength() <  {
		var  uint =  - 
		var  uint = brotli_min_size_t(, )
		.len = 0
		.len_code_delta = 0
		.distance = 0
		.score = 
		.FindLongestMatch(&.dictionary, , , , , , , , .dist.max_distance, )
		if .score >  {
			/* Found a match. Let's look for something even better ahead. */
			var  int = 0
			--
			for ; ; -- {
				var  uint = 175
				if .quality < minQualityForExtensiveReferenceSearch {
					.len = brotli_min_size_t(.len-1, )
				} else {
					.len = 0
				}
				.len_code_delta = 0
				.distance = 0
				.score = 
				 = brotli_min_size_t(+1, )
				.FindLongestMatch(&.dictionary, , , , +1, , , , .dist.max_distance, )
				if .score >= .score+ {
					/* Ok, let's just write one byte for now and start a match from the
					   next byte. */
					++

					++
					* = *
					++
					if  < 4 && +.HashTypeLength() <  {
						continue
					}
				}

				break
			}

			 =  + 2*.len + 
			 = brotli_min_size_t(, )
			{
				/* The first 16 codes are special short-codes,
				   and the minimum offset is 1. */
				var  uint = computeDistanceCode(.distance, +, )
				if (.distance <= ( + )) &&  > 0 {
					[3] = [2]
					[2] = [1]
					[1] = [0]
					[0] = int(.distance)
					.PrepareDistanceCache()
				}

				* = append(*, makeCommand(&.dist, , .len, .len_code_delta, ))
			}

			* += 
			 = 0
			/* Put the hash keys into the table, if there are enough bytes left.
			   Depending on the hasher implementation, it can push all positions
			   in the given range or only a subset of them.
			   Avoid hash poisoning with RLE data. */
			{
				var  uint =  + 2
				var  uint = brotli_min_size_t(+.len, )
				if .distance < .len>>2 {
					 = brotli_min_size_t(, brotli_max_size_t(, +.len-(.distance<<2)))
				}

				.StoreRange(, , , )
			}

			 += .len
		} else {
			++
			++

			/* If we have not seen matches for a long time, we can skip some
			   match lookups. Unsuccessful match lookups are very very expensive
			   and this kind of a heuristic speeds up compression quite
			   a lot. */
			if  >  {
				/* Going through uncompressible data, jump. */
				if  > +4* {
					var  uint = brotli_max_size_t(.StoreLookahead()-1, 4)
					/* It is quite a long time since we saw a copy, so we assume
					   that this data is not compressible, and store hashes less
					   often. Hashes of non compressible data are less likely to
					   turn out to be useful in the future, too, so we store less of
					   them to not to flood out the hash table of good compressible
					   data. */

					var  uint = brotli_min_size_t(+16, -)
					for ;  < ;  += 4 {
						.Store(, , )
						 += 4
					}
				} else {
					var  uint = brotli_max_size_t(.StoreLookahead()-1, 2)
					var  uint = brotli_min_size_t(+8, -)
					for ;  < ;  += 2 {
						.Store(, , )
						 += 2
					}
				}
			}
		}
	}

	 +=  - 
	* = 

	hasherSearchResultPool.Put()
	hasherSearchResultPool.Put()
}