diff --git a/go.mod b/go.mod index 3925508..d04f3b2 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( github.com/alecthomas/kingpin/v2 v2.4.0 github.com/illumos/go-kstat v0.0.0-20210513183136-173c9b0a9973 github.com/kubeservice-stack/common v1.9.1 - github.com/montanaflynn/stats v0.12.2 + github.com/montanaflynn/stats v0.12.3 github.com/prometheus/client_golang v1.24.0 github.com/prometheus/common v0.70.0 github.com/prometheus/exporter-toolkit v0.17.1 diff --git a/go.sum b/go.sum index ed49b98..1d4eafb 100644 --- a/go.sum +++ b/go.sum @@ -41,8 +41,8 @@ github.com/mdlayher/socket v0.6.0 h1:ScZPaAGyO1icQnbFrhPM8mnXyMu9qukC1K4ZoM2IQKU github.com/mdlayher/socket v0.6.0/go.mod h1:q7vozUAnxSqnjHc12Fik5yUKIzfZ8ITCfMkhOtE9z18= github.com/mdlayher/vsock v1.3.0 h1:bqQfZ1OznI03y6YiXp2sze05RVdzLn/zsfjnjd4+ivI= github.com/mdlayher/vsock v1.3.0/go.mod h1:WsuksavOvwCnV5UqGHUkvAvCy+Dqy81y4goKQTzxxNY= -github.com/montanaflynn/stats v0.12.2 h1:qHR+IveGjTbO+lnrz1nKR+xpIcOtovJ5Xu0cst99h80= -github.com/montanaflynn/stats v0.12.2/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= +github.com/montanaflynn/stats v0.12.3 h1:6Wapv3TSE8rWROR0+nYl7Sy6C2jXlnZDcFCb0J554zk= +github.com/montanaflynn/stats v0.12.3/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU= diff --git a/vendor/github.com/montanaflynn/stats/CHANGELOG.md b/vendor/github.com/montanaflynn/stats/CHANGELOG.md index ea3553a..1e407de 100644 --- a/vendor/github.com/montanaflynn/stats/CHANGELOG.md +++ b/vendor/github.com/montanaflynn/stats/CHANGELOG.md @@ -7,16 +7,19 @@ - -## [v0.12.2] - 2026-07-17 + + +## [v0.12.3] - 2026-08-10 ### Fix -- Regression stability and invalid domains ([#124](https://github.com/montanaflynn/stats/issues/124)) +- ProbGeom off-by-one that drops the first interval term ([#127](https://github.com/montanaflynn/stats/issues/127)) +- NormIsf ignores loc, NormPpf uncorrected above the median ([#126](https://github.com/montanaflynn/stats/issues/126)) +- Normal tail collapses to 0/-Inf past ~8 sigma ([#125](https://github.com/montanaflynn/stats/issues/125)) - -## [v0.12.1] - 2026-07-16 + +## [v0.12.2] - 2026-07-17 ### Fix -- Stop Entropy from mutating its input slice ([#123](https://github.com/montanaflynn/stats/issues/123)) +- Regression stability and invalid domains ([#124](https://github.com/montanaflynn/stats/issues/124)) @@ -28,22 +31,6 @@ ## [v0.12.0] - 2026-07-16 - -## [v0.12.0] - 2026-07-16 - - -## [v0.11.0] - 2026-07-13 -### Add -- Add Interp for piecewise-linear interpolation ([#121](https://github.com/montanaflynn/stats/issues/121)) -- Add Histogram with equal-width bins ([#120](https://github.com/montanaflynn/stats/issues/120)) -- Add KendallTau rank correlation coefficient ([#119](https://github.com/montanaflynn/stats/issues/119)) -- Add SEM, RMS, Product, and PercentileOfScore ([#118](https://github.com/montanaflynn/stats/issues/118)) -- Add MovingMedian, MovingMin, MovingMax, MovingSum, and EWMA ([#117](https://github.com/montanaflynn/stats/issues/117)) -- Add TrimmedMean and Winsorize robust statistics ([#116](https://github.com/montanaflynn/stats/issues/116)) -- Add Kurtosis, PopulationKurtosis, and SampleKurtosis ([#115](https://github.com/montanaflynn/stats/issues/115)) -- Add Clip and Rescale elementwise transforms ([#114](https://github.com/montanaflynn/stats/issues/114)) - - ## [v0.11.0] - 2026-07-13 ### Add @@ -77,26 +64,6 @@ - Correct AutoCorrelation lag handling ([#83](https://github.com/montanaflynn/stats/issues/83)) ([#95](https://github.com/montanaflynn/stats/issues/95)) - -## [v0.10.0] - 2026-07-10 -### Add -- Add MovingAverage and MovingStdDev ([#112](https://github.com/montanaflynn/stats/issues/112)) -- Add ZScore and Rank functions ([#111](https://github.com/montanaflynn/stats/issues/111)) -- Add WeightedMean and CoefficientOfVariation ([#110](https://github.com/montanaflynn/stats/issues/110)) -- Add ArgMax, ArgMin and Range functions ([#109](https://github.com/montanaflynn/stats/issues/109)) -- Add CumulativeProduct, CumulativeMax and CumulativeMin ([#108](https://github.com/montanaflynn/stats/issues/108)) -- Add Diff and PercentChange functions ([#107](https://github.com/montanaflynn/stats/issues/107)) -- Add weighted percentile function ([#102](https://github.com/montanaflynn/stats/issues/102)) -- Add NormSample function for normal distribution sampling ([#100](https://github.com/montanaflynn/stats/issues/100)) -- Add Z-test and T-test functions ([#99](https://github.com/montanaflynn/stats/issues/99)) -- Add Spearman rank correlation function ([#98](https://github.com/montanaflynn/stats/issues/98)) - -### Fix -- Stabilize GeometricMean and add input validation -- Use math.Round to avoid ARM64 FMA fusion miscompile ([#97](https://github.com/montanaflynn/stats/issues/97)) -- Correct AutoCorrelation lag handling ([#83](https://github.com/montanaflynn/stats/issues/83)) ([#95](https://github.com/montanaflynn/stats/issues/95)) - - ## [v0.9.0] - 2026-03-24 ### Add @@ -638,16 +605,13 @@ - Merge pull request [#4](https://github.com/montanaflynn/stats/issues/4) from saromanov/sample -[Unreleased]: https://github.com/montanaflynn/stats/compare/v0.12.2...HEAD +[Unreleased]: https://github.com/montanaflynn/stats/compare/v0.12.3...HEAD +[v0.12.3]: https://github.com/montanaflynn/stats/compare/v0.12.2...v0.12.3 [v0.12.2]: https://github.com/montanaflynn/stats/compare/v0.12.1...v0.12.2 [v0.12.1]: https://github.com/montanaflynn/stats/compare/v0.12.0...v0.12.1 -[v0.12.1]: https://github.com/montanaflynn/stats/compare/v0.12.0...v0.12.1 [v0.12.0]: https://github.com/montanaflynn/stats/compare/v0.11.0...v0.12.0 -[v0.12.0]: https://github.com/montanaflynn/stats/compare/v0.11.0...v0.12.0 -[v0.11.0]: https://github.com/montanaflynn/stats/compare/v0.10.0...v0.11.0 [v0.11.0]: https://github.com/montanaflynn/stats/compare/v0.10.0...v0.11.0 [v0.10.0]: https://github.com/montanaflynn/stats/compare/v0.9.0...v0.10.0 -[v0.10.0]: https://github.com/montanaflynn/stats/compare/v0.9.0...v0.10.0 [v0.9.0]: https://github.com/montanaflynn/stats/compare/v0.8.2...v0.9.0 [v0.8.2]: https://github.com/montanaflynn/stats/compare/v0.8.1...v0.8.2 [v0.8.1]: https://github.com/montanaflynn/stats/compare/v0.8.0...v0.8.1 diff --git a/vendor/github.com/montanaflynn/stats/geometric_distribution.go b/vendor/github.com/montanaflynn/stats/geometric_distribution.go index db785dd..f1dfebe 100644 --- a/vendor/github.com/montanaflynn/stats/geometric_distribution.go +++ b/vendor/github.com/montanaflynn/stats/geometric_distribution.go @@ -12,14 +12,15 @@ func ProbGeom(a int, b int, p float64) (prob float64, err error) { return math.NaN(), ErrBounds } - prob = 0 q := 1 - p // probability of failure - for k := a + 1; k <= b; k++ { - prob = prob + p*math.Pow(q, float64(k-1)) + if a == b { + return p * math.Pow(q, float64(a-1)), nil } - return prob, nil + // closed form of the sum p*q^(k-1) over k = a..b; expm1/log1p keep + // 1-q^n accurate where direct subtraction would cancel + return math.Pow(q, float64(a-1)) * -math.Expm1(float64(b-a+1)*math.Log1p(-p)), nil } // ProbGeom generates the expectation or average number of trials diff --git a/vendor/github.com/montanaflynn/stats/norm.go b/vendor/github.com/montanaflynn/stats/norm.go index 620c5ac..0d0fd08 100644 --- a/vendor/github.com/montanaflynn/stats/norm.go +++ b/vendor/github.com/montanaflynn/stats/norm.go @@ -51,27 +51,53 @@ func NormPdf(x float64, loc float64, scale float64) float64 { // NormLogPdf is the log of the probability density function. func NormLogPdf(x float64, loc float64, scale float64) float64 { - return math.Log((math.Pow(math.E, -(math.Pow(x-loc, 2))/(2*math.Pow(scale, 2)))) / (scale * math.Sqrt(2*math.Pi))) + z := (x - loc) / scale + return -0.5*z*z - math.Log(scale) - 0.5*math.Log(2*math.Pi) } // NormCdf is the cumulative distribution function. func NormCdf(x float64, loc float64, scale float64) float64 { - return 0.5 * (1 + math.Erf((x-loc)/(scale*math.Sqrt(2)))) + return 0.5 * math.Erfc(-(x-loc)/(scale*math.Sqrt2)) } // NormLogCdf is the log of the cumulative distribution function. func NormLogCdf(x float64, loc float64, scale float64) float64 { - return math.Log(0.5 * (1 + math.Erf((x-loc)/(scale*math.Sqrt(2))))) + z := (x - loc) / scale + if z > 0 { + return math.Log1p(-0.5 * math.Erfc(z/math.Sqrt2)) + } + return normLogTail(-z) } // NormSf is the survival function (also defined as 1 - cdf, but sf is sometimes more accurate). func NormSf(x float64, loc float64, scale float64) float64 { - return 1 - 0.5*(1+math.Erf((x-loc)/(scale*math.Sqrt(2)))) + return 0.5 * math.Erfc((x-loc)/(scale*math.Sqrt2)) } // NormLogSf is the log of the survival function. func NormLogSf(x float64, loc float64, scale float64) float64 { - return math.Log(1 - 0.5*(1+math.Erf((x-loc)/(scale*math.Sqrt(2))))) + z := (x - loc) / scale + if z < 0 { + return math.Log1p(-0.5 * math.Erfc(-z/math.Sqrt2)) + } + return normLogTail(z) +} + +// normSmallestNormal is the smallest positive normal float64; below it math.Erfc +// keeps only a handful of significant bits. +const normSmallestNormal = 2.2250738585072014e-308 + +// normLogTail returns log(sf(z)) for z >= 0. +func normLogTail(z float64) float64 { + if q := 0.5 * math.Erfc(z/math.Sqrt2); q >= normSmallestNormal { + return math.Log(q) + } + // math.Erfc has decayed into the subnormals, so switch to the Mills ratio + // expansion sf(z) = pdf(z)/z * (1 - 1/z^2 + 3/z^4 - 15/z^6 + 105/z^8 - ...), + // whose first dropped term is below 1e-12 this far out. + r := 1 / (z * z) + return -0.5*z*z - math.Log(z) - 0.5*math.Log(2*math.Pi) + + math.Log1p(r*(-1+r*(3+r*(-15+r*105)))) } // NormPpf is the point percentile function. @@ -132,7 +158,15 @@ func NormPpf(p float64, loc float64, scale float64) (x float64) { (((((b1*r+b2)*r+b3)*r+b4)*r+b5)*r + 1) } - e := 0.5*math.Erfc(-x/math.Sqrt2) - p + // Halley correction on cdf(x)-p. Above the median cdf(x) and p have both + // already rounded to 1, so the difference is taken between the survival + // functions instead; 1-p is exact for p >= 0.5. + var e float64 + if p > 0.5 { + e = (1 - p) - 0.5*math.Erfc(x/math.Sqrt2) + } else { + e = 0.5*math.Erfc(-x/math.Sqrt2) - p + } u := e * math.Sqrt(2*math.Pi) * math.Exp(x*x/2) x = x - u/(1+x*u/2) @@ -140,11 +174,10 @@ func NormPpf(p float64, loc float64, scale float64) (x float64) { } // NormIsf is the inverse survival function (inverse of sf). -func NormIsf(p float64, loc float64, scale float64) (x float64) { - if -NormPpf(p, loc, scale) == 0 { - return 0 - } - return -NormPpf(p, loc, scale) +func NormIsf(p float64, loc float64, scale float64) float64 { + // isf(p) == ppf(1-p), reached by reflecting the standard normal so that + // loc stays out of the negation and 1-p is never formed. + return loc - scale*NormPpf(p, 0, 1) } // NormMoment approximates the non-central (raw) moment of order n. @@ -225,11 +258,10 @@ func NormStd(loc float64, scale float64) float64 { // NormInterval finds endpoints of the range that contains alpha percent of the distribution. func NormInterval(alpha float64, loc float64, scale float64) [2]float64 { - q1 := (1.0 - alpha) / 2 - q2 := (1.0 + alpha) / 2 - a := NormPpf(q1, loc, scale) - b := NormPpf(q2, loc, scale) - return [2]float64{a, b} + // Derive both endpoints from the lower tail: (1+alpha)/2 rounds to 1 once + // alpha is within an ulp of it, which sends the upper endpoint to +Inf. + z := NormPpf((1.0-alpha)/2, 0, 1) + return [2]float64{loc + scale*z, loc - scale*z} } // factorial is the naive factorial algorithm. diff --git a/vendor/github.com/montanaflynn/stats/ttest.go b/vendor/github.com/montanaflynn/stats/ttest.go index f36ea32..728014a 100644 --- a/vendor/github.com/montanaflynn/stats/ttest.go +++ b/vendor/github.com/montanaflynn/stats/ttest.go @@ -76,7 +76,7 @@ func regIncBeta(a, b, x float64) float64 { } lbeta := lgammaBeta(a, b) - front := math.Exp(math.Log(x)*a + math.Log(1-x)*b - lbeta) / a + front := math.Exp(math.Log(x)*a+math.Log(1-x)*b-lbeta) / a // Use Lentz's continued fraction algorithm f := 1.0 diff --git a/vendor/modules.txt b/vendor/modules.txt index 8e72978..2651812 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -55,7 +55,7 @@ github.com/mdlayher/socket # github.com/mdlayher/vsock v1.3.0 ## explicit; go 1.25.0 github.com/mdlayher/vsock -# github.com/montanaflynn/stats v0.12.2 +# github.com/montanaflynn/stats v0.12.3 ## explicit; go 1.13 github.com/montanaflynn/stats # github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822