package brotli

import (
	

	
)

func (, ,  float64) float64 {
	return math.Exp(-(-)*(-)/(2**)) / math.Sqrt(2*math.Pi**)
}

// A FastEncoder implements the matchfinder.Encoder interface, writing in Brotli
// format. It uses a simplified encoding (like level 0 in the reference
// implementation) to save time.
type FastEncoder struct {
	wroteHeader   bool
	bw            bitWriter
	commandHisto  [704]uint32
	distanceHisto [64]uint32
}

func ( *FastEncoder) () {
	.wroteHeader = false
	.bw = bitWriter{}
}

func ( *FastEncoder) ( []byte,  []byte,  []matchfinder.Match,  bool) []byte {
	.bw.dst = 
	if !.wroteHeader {
		.bw.writeBits(4, 15)
		.wroteHeader = true

		// Fill the histograms with default statistics.

		// For the command codes we're using for insert lengths (insert + 2-byte copy),
		// fill the histogram with a Zipf-squared distribution.
		for  := range 24 {
			.commandHisto[combineLengthCodes(uint16(), 0, false)] = uint32(2000 / ( + 1) / ( + 1))
		}

		// For the command codes we're using for copy lengths (0 insert + copy
		// (length - 2), with repeat distance),
		// fill the histogram with Zipf distribution starting at code 1 (match length 5),
		// but a smaller frequency for code 0.
		.commandHisto[combineLengthCodes(0, 0, true)] = 50
		for  := 1;  < 24; ++ {
			.commandHisto[combineLengthCodes(0, uint16(),  < 16)] = uint32(800 / )
		}

		// Fill in the combined codes for short insert and copy lengths.
		for  := range 6 {
			 := 2
			.commandHisto[128+<<3+] = uint32(100 / ( + 1) / ( + 1) / )
			for  := 3;  < 8; ++ {
				.commandHisto[128+<<3+] = uint32(343 / ( + 1) / ( + 1) / )
			}
		}

		// Fill e.distanceHisto with a normal distribution.
		.distanceHisto[0] = 100
		for  := 16;  < 64; ++ {
			.distanceHisto[] = max(uint32(gaussianProbability(float64(), 32, 8)*10000), 1)
		}
	}

	if len() == 0 {
		if  {
			.bw.writeBits(2, 3) // islast + isempty
			.bw.jumpToByteBoundary()
			return .bw.dst
		}
		return 
	}

	var  [256]uint32
	for ,  := range  {
		[]++
	}

	storeMetaBlockHeaderBW(uint(len()), false, &.bw)
	.bw.writeBits(13, 0)

	var  [256]byte
	var  [256]uint16
	buildAndStoreHuffmanTreeFastBW([:], uint(len()), 8, [:], [:], &.bw)

	var  [704]byte
	var  [704]uint16
	 := 0
	for ,  := range .commandHisto {
		 += int()
	}
	buildAndStoreHuffmanTreeFastBW(.commandHisto[:], uint(), 10, [:], [:], &.bw)

	var  [64]byte
	var  [64]uint16
	 := 0
	for ,  := range .distanceHisto {
		 += int()
	}
	buildAndStoreHuffmanTreeFastBW(.distanceHisto[:], uint(), 6, [:], [:], &.bw)

	// Reset the statistics, starting with a count of 1 for each symbol we might use.
	for  := range 24 {
		.commandHisto[combineLengthCodes(uint16(), 0, false)] = 1
	}
	for  := range 24 {
		.commandHisto[combineLengthCodes(0, uint16(),  < 16)] = 1
	}
	for  := range 6 {
		for  := 2;  < 8; ++ {
			.commandHisto[128+<<3+] = 1
		}
	}
	.distanceHisto[0] = 1
	for  := 16;  < 64; ++ {
		.distanceHisto[] = 1
	}

	 := 0
	for ,  := range  {
		 := false
		// Write a command with the appropriate insert length, and a copy length of 2.
		if .Unmatched < 6 {
			var  int
			if .Length < 10 && .Length != 0 {
				// We can use a combined insert/copy code with no extra bits.
				 = .Unmatched<<3 + .Length - 2 + 128
				 = true
			} else {
				 = .Unmatched<<3 + 128
			}
			.bw.writeBits(uint([]), uint64([]))
			.commandHisto[]++
		} else {
			 := getInsertLengthCode(uint(.Unmatched))
			 := combineLengthCodes(, 0, false)
			.bw.writeBits(uint([]), uint64([]))
			.bw.writeBits(uint(kInsExtra[]), uint64(.Unmatched)-uint64(kInsBase[]))
			.commandHisto[]++
		}

		// Write the literals, if any.
		if .Unmatched > 0 {
			for ,  := range [ : +.Unmatched] {
				.bw.writeBits(uint([]), uint64([]))
			}
		}

		if .Length != 0 {
			// Write the distance code.
			var  distanceCode
			if  == 0 || .Distance != [-1].Distance {
				 = getDistanceCode(.Distance)
			}
			.bw.writeBits(uint([.code]), uint64([.code]))
			if .nExtra > 0 {
				.bw.writeBits(.nExtra, .extraBits)
			}
			.distanceHisto[.code]++

			// Write a command for the remainder of the match (after the first two bytes
			// from before), using the previous distance.
			switch {
			case :
				// We don't need to finish the length.
			case .Length < 12:
				 := .Length - 4
				.bw.writeBits(uint([]), uint64([]))
				.commandHisto[]++
			case .Length < 72:
				 := getCopyLengthCode(uint(.Length - 2))
				 := combineLengthCodes(0, , true)
				.bw.writeBits(uint([]), uint64([]))
				.bw.writeBits(uint(kCopyExtra[]), uint64(.Length-2)-uint64(kCopyBase[]))
				.commandHisto[]++
			default:
				 := getCopyLengthCode(uint(.Length - 2))
				 := combineLengthCodes(0, , false)
				.bw.writeBits(uint([]), uint64([]))
				.bw.writeBits(uint(kCopyExtra[]), uint64(.Length-2)-uint64(kCopyBase[]))
				.bw.writeBits(uint([0]), uint64([0]))
				.commandHisto[]++
				.distanceHisto[0]++
			}
		}

		 += .Unmatched + .Length
	}

	if  {
		.bw.writeBits(2, 3) // islast + isempty
		.bw.jumpToByteBoundary()
	}
	return .bw.dst
}