Poindexter/stats.go
Claude fa998619dc
Some checks failed
CI / build-test-wasm (pull_request) Has been cancelled
CI / build-test-gonum (pull_request) Has been cancelled
Tests / test (pull_request) Has been cancelled
feat: Add math modules — stats, scale, epsilon, score, signal
Centralizes common math operations used across core/go-ai, core/go,
and core/mining into Poindexter as the math pillar (alongside Borg=data,
Enchantrix=encryption).

New modules:
- stats: Sum, Mean, Variance, StdDev, MinMax, IsUnderrepresented
- scale: Lerp, InverseLerp, Remap, RoundToN, Clamp, MinMaxScale
- epsilon: ApproxEqual, ApproxZero
- score: WeightedScore, Ratio, Delta, DeltaPercent
- signal: RampUp, SineWave, Oscillate, Noise (seeded RNG)

235 LOC implementation, 509 LOC tests, zero external deps, WASM-safe.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 16:16:49 +00:00

63 lines
1.3 KiB
Go

package poindexter
import "math"
// Sum returns the sum of all values. Returns 0 for empty slices.
func Sum(data []float64) float64 {
var s float64
for _, v := range data {
s += v
}
return s
}
// Mean returns the arithmetic mean. Returns 0 for empty slices.
func Mean(data []float64) float64 {
if len(data) == 0 {
return 0
}
return Sum(data) / float64(len(data))
}
// Variance returns the population variance. Returns 0 for empty slices.
func Variance(data []float64) float64 {
if len(data) == 0 {
return 0
}
m := Mean(data)
var ss float64
for _, v := range data {
d := v - m
ss += d * d
}
return ss / float64(len(data))
}
// StdDev returns the population standard deviation.
func StdDev(data []float64) float64 {
return math.Sqrt(Variance(data))
}
// MinMax returns the minimum and maximum values.
// Returns (0, 0) for empty slices.
func MinMax(data []float64) (min, max float64) {
if len(data) == 0 {
return 0, 0
}
min, max = data[0], data[0]
for _, v := range data[1:] {
if v < min {
min = v
}
if v > max {
max = v
}
}
return min, max
}
// IsUnderrepresented returns true if val is below threshold fraction of avg.
// For example, IsUnderrepresented(3, 10, 0.5) returns true because 3 < 10*0.5.
func IsUnderrepresented(val, avg, threshold float64) bool {
return val < avg*threshold
}